@well-prado/blok-workflow-analyzer
v1.1.1
Published
Automatic workflow analysis and type inference for Blok Framework
Maintainers
Readme
@blok-framework/workflow-analyzer
Automatic workflow analysis and type inference for Blok Framework
Eliminates manual type definitions by automatically inferring types from workflow nodes. Inspired by Laravel + Inertia.js, powered by TypeScript AST parsing.
✨ Features
- 🔍 Automatic Workflow Discovery - Scans and analyzes all workflows
- 🎯 Smart Type Inference - Extracts types from node JSON schemas
- 🚀 Zero Manual Work - No type definitions needed!
- ⚡ Fast & Cached - Analysis results are cached for performance
- 👀 Watch Mode - Auto-regenerate on file changes
- 🎨 Perfect TypeScript - Generates production-ready types
- 🔐 Security Analysis - Detects auth requirements automatically
📦 Installation
npm install @blok-framework/workflow-analyzer
# or
pnpm add @blok-framework/workflow-analyzer🚀 Quick Start
import { WorkflowAnalyzer } from "@blok-framework/workflow-analyzer";
// Create analyzer
const analyzer = new WorkflowAnalyzer({
projectRoot: process.cwd(),
});
// Analyze single workflow
const analysis = await analyzer.analyzeWorkflow("admin-logs");
console.log(analysis.inputType); // Perfect TypeScript types!
console.log(analysis.outputType);
// Analyze all workflows
const allAnalyses = await analyzer.analyzeAllWorkflows();
console.log(`Analyzed ${allAnalyses.size} workflows`);
// Watch for changes
analyzer.watch((event) => {
console.log(`Workflow ${event.type}:`, event.workflowKey);
});📖 API Reference
WorkflowAnalyzer
Main class for analyzing workflows.
Constructor
new WorkflowAnalyzer(config: AnalyzerConfig)Config Options:
projectRoot(required): Project root directoryworkflowsDir(optional): Workflows directory (default:src/workflows)nodesDir(optional): Nodes directory (default:src/nodes)cache(optional): Enable caching (default:true)middlewarePatterns(optional): Custom middleware patterns to skip
Methods
analyzeWorkflow(workflowKey: string): Promise<WorkflowAnalysis>
Analyzes a single workflow and returns complete type information.
const analysis = await analyzer.analyzeWorkflow("admin-logs");
// analysis contains:
// - workflowKey: string
// - name, version, description
// - endpoint, method, path
// - inputType, outputType (TypeScript types!)
// - requiresAuth, requiredRole
// - dataNodes: string[]
// - structure: WorkflowStructureanalyzeAllWorkflows(): Promise<Map<string, WorkflowAnalysis>>
Analyzes all workflows in the project.
const analyses = await analyzer.analyzeAllWorkflows();
for (const [key, analysis] of analyses) {
console.log(`${key}: ${analysis.dataNodes.join(", ")}`);
}watch(callback: WorkflowChangeCallback): void
Watches for workflow file changes and triggers callback.
analyzer.watch(async (event) => {
if (event.type === "changed") {
const analysis = await analyzer.analyzeWorkflow(event.workflowKey);
// Regenerate types...
}
});clearCache(): void
Clears the analysis cache.
analyzer.clearCache();🎯 How It Works
1. Workflow Discovery
The analyzer scans your workflows directory and discovers all workflow files:
// Automatically finds:
src/workflows/
├── admin/admin-logs.ts
├── auth/register.ts
├── profile/profile-update.ts
└── ...2. Workflow Parsing
Each workflow is parsed using TypeScript AST to extract:
- Workflow metadata (name, version, description)
- HTTP trigger information
- Node references
- Conditional branches
- Exported types
3. Node Schema Loading
For each node referenced in a workflow:
- Locate the node file (supports multiple patterns)
- Extract
inputSchemaandoutputSchema(JSON Schema format) - Parse schema properties and types
4. Type Inference
Smart type inference engine:
- Analyzes HTTP trigger parameters
- Examines first step's input requirements
- Checks last step's output shape
- Detects authentication requirements
- Identifies admin-only workflows
5. Type Generation
Generates perfect TypeScript types:
// Input: Workflow with system-action-logger node
// Output: Perfect TypeScript types!
export interface AdminLogsInput {
action: "log" | "query" | "getStats" | "cleanup" | "export";
phase?: "start" | "complete";
userId?: string;
// ... 14 more fields
}
export interface AdminLogsOutput {
success?: boolean;
message?: string;
data?: Record<string, any>;
}🔧 Integration with Codegen
Perfect integration with @blok-framework/codegen:
import { WorkflowAnalyzer } from "@blok-framework/workflow-analyzer";
import { TypeGenerator } from "@blok-framework/codegen";
// Analyze workflows
const analyzer = new WorkflowAnalyzer({ projectRoot });
const analyses = await analyzer.analyzeAllWorkflows();
// Generate types
const generator = new TypeGenerator();
const types = generator.generateFromAnalysis(analyses);
// Write to files
await writeFile("generated-types.ts", types);📊 Supported Patterns
Node Patterns
✅ Folder with index.ts: src/nodes/auth/user-register/index.ts
✅ Direct TypeScript file: src/nodes/notifications/get-user-notifications.ts
✅ Nested categories: src/nodes/security/system-action-logger/index.ts
Workflow Patterns
✅ Simple workflows (single node)
✅ Multi-step workflows (multiple nodes)
✅ Conditional workflows (if-else branches)
✅ Middleware workflows (auth, interceptors)
✅ Any HTTP method (GET, POST, PUT, PATCH, DELETE)
Middleware Detection
Automatically skips common middleware nodes:
authentication-checkerrequest-interceptorerror@nanoservice-ts/*(framework nodes)
Custom patterns can be added via config:
const analyzer = new WorkflowAnalyzer({
projectRoot,
middlewarePatterns: [
"authentication-checker",
"request-interceptor",
"my-custom-middleware",
],
});🎯 Best Practices
1. Node Schema Quality
Ensure your nodes have comprehensive JSON schemas:
export default class MyNode extends NanoService<MyInput> {
constructor() {
super();
// ✅ Good: Comprehensive schema
this.inputSchema = {
type: "object",
properties: {
action: {
type: "string",
enum: ["create", "update", "delete"],
description: "Operation to perform", // ← Descriptions help!
},
data: {
type: "object",
description: "Operation data",
},
},
required: ["action"],
};
this.outputSchema = {
type: "object",
properties: {
success: { type: "boolean" },
data: { type: "object" },
},
};
}
}2. Workflow Organization
Organize workflows by category:
src/workflows/
├── admin/ # Admin-only workflows
├── auth/ # Authentication workflows
├── profile/ # User profile workflows
├── notifications/ # Notification workflows
└── api/ # Public API workflows3. Cache Management
Use caching for better performance:
// Enable caching (default: true)
const analyzer = new WorkflowAnalyzer({
projectRoot,
cache: true,
});
// Clear cache when needed
analyzer.clearCache();🐛 Troubleshooting
Issue: Node not found
Solution: Check that node file follows supported patterns:
src/nodes/category/node-name/index.ts✅src/nodes/category/node-name.ts✅
Issue: Types not accurate
Solution: Ensure node has proper inputSchema and outputSchema:
this.inputSchema = { ... }; // Must be valid JSON Schema
this.outputSchema = { ... }; // Must be valid JSON SchemaIssue: Middleware node detected as main node
Solution: Add to middleware patterns:
const analyzer = new WorkflowAnalyzer({
projectRoot,
middlewarePatterns: ["your-middleware-node"],
});📚 Examples
Example 1: Analyze Specific Workflow
import { WorkflowAnalyzer } from "@blok-framework/workflow-analyzer";
const analyzer = new WorkflowAnalyzer({ projectRoot: __dirname });
const analysis = await analyzer.analyzeWorkflow("admin-logs");
console.log(`Workflow: ${analysis.name}`);
console.log(`Endpoint: ${analysis.method} ${analysis.endpoint}`);
console.log(`Auth Required: ${analysis.requiresAuth}`);
console.log(`Data Nodes: ${analysis.dataNodes.join(", ")}`);Example 2: Generate Report
const analyses = await analyzer.analyzeAllWorkflows();
const report = {
total: analyses.size,
requireAuth: Array.from(analyses.values()).filter((a) => a.requiresAuth)
.length,
adminOnly: Array.from(analyses.values()).filter(
(a) => a.requiredRole === "ADMIN"
).length,
byMethod: {},
};
console.log("Workflow Analysis Report:", report);Example 3: Watch Mode Integration
import { WorkflowAnalyzer } from "@blok-framework/workflow-analyzer";
import { TypeGenerator } from "@blok-framework/codegen";
const analyzer = new WorkflowAnalyzer({ projectRoot });
const generator = new TypeGenerator();
// Watch for changes and regenerate types
analyzer.watch(async (event) => {
console.log(`\n📝 Workflow ${event.type}: ${event.workflowKey}`);
if (event.type !== "removed") {
const analysis = await analyzer.analyzeWorkflow(event.workflowKey);
const types = generator.generateFromAnalysis(
new Map([[event.workflowKey, analysis]])
);
await writeFile("generated-types.ts", types);
console.log("✅ Types regenerated!");
}
});
console.log("👀 Watching for workflow changes...");🤝 Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
📄 License
MIT © Blok Framework Team
🔗 Related Packages
- @blok-framework/codegen - Type generation from analysis
- @blok-framework/typed-sdk - Type-safe frontend SDK
- @well-prado/blok-react-sdk - React hooks for Blok
📖 Documentation
Built with ❤️ by the Blok Framework Team
From 150 lines of manual types to ZERO with perfect type safety!
