import { Container, createPipeline, Middleware } from 'farrow-pipeline'; const WORKFLOW_SYMBOL = Symbol('WORKFLOW_SYMBOL'); export type Worker = (I: I) => O; export type Workers = Worker[]; export type RunWorkflowOptions = { container?: Container; }; export type Workflow = { run: (input: I, options?: RunWorkflowOptions) => void; use: (...I: Workers) => Workflow; [WORKFLOW_SYMBOL]: true; }; export type Workflow2Worker> = W extends Workflow< infer I, infer O > ? Worker : never; export type WorkflowRecord = Record>; // eslint-disable-next-line @typescript-eslint/no-invalid-void-type export type Workflows2Workers = { [K in keyof PS]: PS[K] extends Workflow ? Workflow2Worker : // eslint-disable-next-line @typescript-eslint/no-invalid-void-type PS[K] extends void ? // eslint-disable-next-line @typescript-eslint/no-invalid-void-type void : never; }; export type RunnerFromWorkflow> = W extends Workflow ? Workflow['run'] : never; // eslint-disable-next-line @typescript-eslint/no-invalid-void-type export type Workflows2Runners = { [K in keyof PS]: PS[K] extends Workflow ? RunnerFromWorkflow : // eslint-disable-next-line @typescript-eslint/no-invalid-void-type PS[K] extends void ? // eslint-disable-next-line @typescript-eslint/no-invalid-void-type void : never; }; // eslint-disable-next-line @typescript-eslint/no-invalid-void-type export const createWorkflow = (): Workflow => { const pipeline = createPipeline(); const use: Workflow['use'] = (...input) => { pipeline.use(...input.map(mapWorkerToMiddleware)); return workflow; }; const run: Workflow['run'] = async (input, options) => { const result = pipeline.run(input, { ...options, onLast: () => [] }); return result.filter(Boolean); }; const workflow: Workflow = { ...pipeline, use, run, [WORKFLOW_SYMBOL]: true as const, }; return workflow; }; export const isWorkflow = (input: any): input is Workflow => Boolean(input?.[WORKFLOW_SYMBOL]); const mapWorkerToMiddleware = (worker: Worker): Middleware => (input, next) => [worker(input), ...next(input)];