BaseCommand.ts

Complete command architecture for micro-block pattern with CommandMetadata interface, OutputCommand and InputOnlyCommand base classes, and BaseError class for comprehensive error handling

BaseCommand.tsv1.0.05.1 KB
BaseCommand.ts(typescript)
1/**
2 * Base interfaces for Micro-Block Architecture commands
3 * All commands in the system implement one of these interfaces
4 */
5
6/**
7 * Metadata for command discovery and documentation
8 */
9export interface CommandMetadata {
10  name: string;
11  description: string;
12  category: string;
13  inputType: string;
14  outputType: string;
15  errorType: string;
16  version: string;                 // Command implementation version
17  contractVersion: string;         // Input/output contract version
18  permissions?: string[];
19  timeout?: number;
20  dataFlow?: {
21    inputs: string[];
22    outputs: string[];
23    sideEffects: string[];
24  };
25  performance?: {
26    expectedDuration: string;
27    scaling: string;
28  };
29  /**
30   * Dependencies required by this command
31   */
32  dependencies?: {
33    /** Service dependencies (e.g., IQueueService, IDatabaseService) */
34    services?: string[];
35    /** Command dependencies (e.g., CreateProcessingJobCommand) */
36    commands?: string[];
37    /** External package dependencies (e.g., ytdl-core, openai) */
38    external?: string[];
39  }; 
40}
41
42/**
43 * Base interface that all commands must implement.
44 * Provides metadata access and validation through error throwing.
45 */
46export interface BaseCommand {
47  /** 
48   * Validate that the command can execute with current configuration.
49   * Throws detailed validation errors instead of returning boolean.
50   * Use raiseError() method to throw errors with validation details.
51   */
52  validate(): void;
53  execute(): Promise<any>;
54  /** Get the static metadata for this command */
55  getMetadata(): CommandMetadata;
56}
57
58/**
59 * Commands that return data (queries, transformations, calculations)
60 */
61export abstract class OutputCommand<TInput, TOutput, TError extends Error> implements BaseCommand {
62  protected input?: TInput;
63  private errorHandlers: ((error: TError) => void)[] = [];
64  
65  constructor(input?: TInput) {
66    this.input = input;
67  }
68  
69  setInput(input: TInput): void {
70    this.input = input;
71  }
72  
73  abstract execute(): Promise<TOutput>;
74  
75  validate(): void {
76    // Default implementation does nothing - subclasses should override
77    // to throw detailed validation errors when validation fails
78  }
79  
80  onError(handler: (error: TError) => void): void {
81    this.errorHandlers.push(handler);
82  }
83  
84  /**
85   * Calls all registered error handlers and returns the error.
86   * Usage: throw this.raiseError(error)
87   * This pattern ensures error handlers are called before the error is thrown.
88   */
89  protected raiseError(error: TError): TError {
90    for (const handler of this.errorHandlers) {
91      if (handler) {
92        try {
93          handler(error);
94        } catch (e) {
95          console.error("Error in error handler:", e);
96        }
97      }
98    }
99    return error;
100  }
101  
102  abstract getMetadata(): CommandMetadata;
103}
104
105/**
106 * Commands that perform side effects without returning data
107 */
108export abstract class InputOnlyCommand<TInput, TError extends Error> implements BaseCommand {
109  protected input?: TInput;
110  private errorHandlers: ((error: TError) => void)[] = [];
111  
112  constructor(input?: TInput) {
113    this.input = input;
114  }
115  
116  setInput(input: TInput): void {
117    this.input = input;
118  }
119  
120  abstract execute(): Promise<void>;
121  
122  validate(): void {
123    // Default implementation does nothing - subclasses should override
124    // to throw detailed validation errors when validation fails
125  }
126  
127  onError(handler: (error: TError) => void): void {
128    this.errorHandlers.push(handler);
129  }
130  
131  /**
132   * Calls all registered error handlers and returns the error.
133   * Usage: throw this.raiseError(error)
134   * This pattern ensures error handlers are called before the error is thrown.
135   */
136  protected raiseError(error: TError): TError {
137    for (const handler of this.errorHandlers) {
138      if (handler) {
139        try {
140          handler(error);
141        } catch (e) {
142          console.error("Error in error handler:", e);
143        }
144      }
145    }
146    return error;
147  }
148  
149  abstract getMetadata(): CommandMetadata;
150}
151
152/**
153 * Base error class for all command errors
154 */
155export class BaseError extends Error {
156  public readonly timestamp: Date;
157  public readonly code?: string;
158  public readonly details?: Record<string, any>;
159  
160  // Validation error properties - can be set after construction
161  public invalidInput: boolean = false;
162  public invalidInputName: string = '';
163  public invalidInputPath: string = '';
164
165  constructor(
166    message: string, 
167    code?: string, 
168    details?: Record<string, any>
169  ) {
170    super(message);
171    this.name = this.constructor.name;
172    this.timestamp = new Date();
173    this.code = code;
174    this.details = details;
175    
176    // Maintains proper stack trace for where our error was thrown
177    Object.setPrototypeOf(this, new.target.prototype);
178    
179    // Captures stack trace
180    if (Error.captureStackTrace) {
181      Error.captureStackTrace(this, this.constructor);
182    }
183  }
184  
185  /**
186   * Mark this error as a validation error with specific input details
187   */
188  setValidationError(inputName: string, inputPath: string): this {
189    this.invalidInput = true;
190    this.invalidInputName = inputName;
191    this.invalidInputPath = inputPath;
192    return this;
193  }
194}

Metadata

Path
utaba/main/commands/micro-block/BaseCommand.ts
Namespace
utaba/main/commands/micro-block
Author
utaba
Category
commands
Technology
typescript
Contract Version
1.0.0
MIME Type
application/typescript
Published
18-Jul-2025
Last Updated
18-Jul-2025