export class WorkflowImportError extends Error { constructor(message: string) { super(message); this.name = 'WorkflowImportError'; } } export type WorkflowEditorNodeType = | 'text' | 'asset' | 'aspectRatio' | 'model' | 'llm' | 'transformText' | 'splitText' | 'ifElse' | 'groupItems' | 'sliceAssets' | 'forEach' | 'forEachEnd' | 'stickyNote' | 'approval' | 'modelInput'; export const VALID_EDITOR_NODE_TYPES: readonly WorkflowEditorNodeType[] = [ 'text', 'asset', 'aspectRatio', 'model', 'llm', 'transformText', 'splitText', 'ifElse', 'groupItems', 'sliceAssets', 'forEach', 'forEachEnd', 'stickyNote', 'approval', 'modelInput', ]; export interface WorkflowExportData { version: '1.0'; name: string; description: string; editorInfo: { nodes: Array<{ type: WorkflowEditorNodeType; [key: string]: unknown }>; edges: Array<{ [key: string]: unknown }>; inputKeys: string[]; }; inputs: unknown[]; tagSet: string[]; uiConfig?: object; exportedAt: string; exportedBy: string; } /** * Validates a workflow export payload (e.g. from a JSON file import). * * Throws a `WorkflowImportError` with a human-readable message on the first * violation found. Returns the validated data cast to `WorkflowExportData`. * * Checks performed: * 1. Data is a non-null object * 2. `version` field is present and equals "1.0" * 3. `editorInfo` has non-empty `nodes` and `edges` arrays * 4. Each node's `type` is a recognized editor node type * 5. `inputs` is an array */ export function validateEditorInfo(data: unknown): WorkflowExportData { if (typeof data !== 'object' || data === null) { throw new WorkflowImportError('Invalid JSON format'); } const workflow = data as Partial; if (!workflow.version) { throw new WorkflowImportError('Missing version field'); } if (workflow.version !== '1.0') { throw new WorkflowImportError(`Unsupported version: ${workflow.version}`); } if (!workflow.editorInfo || !workflow.editorInfo.nodes || !workflow.editorInfo.edges) { throw new WorkflowImportError('Missing editorInfo structure'); } if (!Array.isArray(workflow.editorInfo.nodes)) { throw new WorkflowImportError('Invalid nodes array'); } if (!Array.isArray(workflow.editorInfo.edges)) { throw new WorkflowImportError('Invalid edges array'); } if (!workflow.inputs || !Array.isArray(workflow.inputs)) { throw new WorkflowImportError('Invalid inputs array'); } for (const node of workflow.editorInfo.nodes) { if (!(VALID_EDITOR_NODE_TYPES as readonly string[]).includes(node.type)) { throw new WorkflowImportError(`Invalid node type: ${node.type}`); } } return workflow as WorkflowExportData; }