Refactored the blueprint flow system to use a Step Type Registry Pattern for better maintainability and easier updates to TOML files, CLI flows, and validations.
- Base Step Type (
base-step.ts): Abstract class with shared validation logic - Registry (
registry.ts): Central registry for step type definitions - Individual Step Modules: One file per step type
info-step.ts- Display informationnavigate-step.ts- Direct users to URLsinput-step.ts- Capture user inputchoice-step.ts- Present selection optionsconfirm-step.ts- Ask for confirmationshow-commands-step.ts- Display commandsai-prompt-step.ts- AI prompt integration
Before: 35-line switch statement handling each step type
switch (step.type) {
case "info": return await StepHandlers.executeInfoStep(...);
case "navigate": return await StepHandlers.executeNavigateStep(...);
// ... 7 cases
}After: Single line using registry
return await stepRegistry.execute(step, this.context);Before: 65-line switch statement for validation
switch (step.type) {
case "info":
if (!step.markdown) { errors.push(...) }
// ... 7 cases
}After: Single line delegation
return stepRegistry.validate(step);Each step type now contains ALL its logic in one place:
- Required/optional fields
- Validation rules
- Execution logic
- Create new file in
step-types/(e.g.,webhook-step.ts) - Extend
BaseStepType - Register it in
index.ts - Update JSON schema
- Change validation? Update the step type's
requiredFieldsorcustomValidation() - Change behavior? Update the step type's
execute()method - All logic is colocated
Each step type can be tested independently without complex mocking
To update TOML schema:
- Modify the step type definition (e.g., add new field to
requiredFields) - Update JSON schema in
spec/blueprint-schema.json - No need to touch switch statements
// src/services/step-types/webhook-step.ts
export class WebhookStepType extends BaseStepType {
type = "webhook" as const;
requiredFields = ["url", "method"];
optionalFields = ["headers", "body"];
async execute(step: FlowStep, context: VariableContext): Promise<StepResult> {
// Implementation here
}
}
export const webhookStepType = new WebhookStepType();Then register it:
// src/services/step-types/index.ts
import { webhookStepType } from "./webhook-step.js";
stepRegistry.registerAll([
// ... existing types
webhookStepType,
]);- ✏️
src/services/flow-executor.ts- Simplified to use registry - ✏️
src/services/blueprint-validator.ts- Simplified to use registry
- ✨
src/services/step-types/base-step.ts - ✨
src/services/step-types/registry.ts - ✨
src/services/step-types/info-step.ts - ✨
src/services/step-types/navigate-step.ts - ✨
src/services/step-types/input-step.ts - ✨
src/services/step-types/choice-step.ts - ✨
src/services/step-types/confirm-step.ts - ✨
src/services/step-types/show-commands-step.ts - ✨
src/services/step-types/ai-prompt-step.ts - ✨
src/services/step-types/index.ts
✅ All existing TOML blueprints work without changes ✅ All existing functionality preserved ✅ Build passes successfully
- Generate JSON schema automatically from step type registry
- Add unit tests for each step type
- Create TOML validation CLI command using registry
- Add step type documentation generator