import { Arr, Type } from '@ephox/katamari'; import type { DieFn, NextFn } from '../pipe/Pipe'; import type { Step } from './Step'; import { TestLogs } from './TestLogs'; const assertSteps = (steps: Step[]) => { Arr.each(steps, (s: Step, i: number) => { let msg: string; if (s === undefined) { msg = 'step ' + i + ' was undefined. All steps: ' + JSON.stringify(steps) + '\n'; } else if (Type.isArray(s)) { msg = 'step ' + i + ' was an array'; } if (msg !== undefined) { // eslint-disable-next-line no-console console.trace(msg, steps); throw new Error(msg); } }); }; /** * Execute a Step, supplying default logs. * * If you need to run a sequence of steps, compose them using the functions in StepSequence */ const runStep = (initial: T, step: Step, onSuccess: NextFn, onFailure: DieFn, initLogs?: TestLogs): void => { step.runStep(initial, onSuccess, onFailure, TestLogs.getOrInit(initLogs)); }; const async = (initial: any, steps: Step[], onSuccess: NextFn, onFailure: DieFn, initLogs?: TestLogs): void => { assertSteps(steps); const chain = (lastLink: any, logs: TestLogs, index: number) => { if (index < steps.length) { const asyncOperation = steps[index]; // FIX: Make this test elsewhere without creating a circular dependency on Chain if ('runChain' in asyncOperation) { return onFailure('You cannot create a pipeline out of chains. Use Chain.asStep to turns chains into steps', logs); } try { const nextStep = (result, newLogs) => { chain(result, newLogs, index + 1); }; asyncOperation.runStep(lastLink, (x, newLogs) => { nextStep(x, newLogs); }, onFailure, logs); } catch (error) { onFailure(error, logs); } } else { const finalLogs = logs; onSuccess(lastLink, finalLogs); } }; const startLogs = TestLogs.getOrInit(initLogs); chain(initial, startLogs, 0); }; export const Pipeline = { async, runStep };