@pogodisco/zephyr 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,354 +1,3 @@
1
- // import {
2
- // ActionParams,
3
- // ActionRegistry,
4
- // ActionReturn,
5
- // Simplify,
6
- // } from "./types.js";
7
- //
8
- // /* ------------------------------------------------ */
9
- // /* STEP INPUT NORMALIZATION TYPES */
10
- // /* ------------------------------------------------ */
11
- //
12
- // type NormalizedCall =
13
- // | { kind: "none" }
14
- // | { kind: "positional"; args: any[] }
15
- // | { kind: "object"; args: any };
16
- //
17
- // export type ResolvedStepInput =
18
- // | NormalizedCall
19
- // | { kind: "loop"; items: NormalizedCall[] };
20
- //
21
- // type CallHelpers<Reg extends ActionRegistry, ActionName extends keyof Reg> = {
22
- // args: (...args: ActionParams<Reg, ActionName>) => {
23
- // kind: "positional";
24
- // args: ActionParams<Reg, ActionName>;
25
- // };
26
- //
27
- // obj: ActionParams<Reg, ActionName> extends [infer A]
28
- // ? (arg: A) => { kind: "object"; args: A }
29
- // : never;
30
- //
31
- // none: () => { kind: "none" };
32
- // loop: (
33
- // items:
34
- // | { kind: "positional"; args: ActionParams<Reg, ActionName> }[]
35
- // | { kind: "object"; args: ActionParams<Reg, ActionName>[0] }[],
36
- // ) => {
37
- // kind: "loop";
38
- // items: typeof items;
39
- // };
40
- // };
41
- //
42
- // /* ------------------------------------------------ */
43
- // /* STEP RESULT TYPES */
44
- // /* ------------------------------------------------ */
45
- //
46
- // type SubflowResult<SubResults, SubOutput> = SubOutput extends undefined
47
- // ? SubResults
48
- // : SubOutput;
49
- //
50
- // type WorkflowInput<T> =
51
- // T extends WorkflowDef<any, infer I, any, any, any> ? I : never;
52
- //
53
- // type WorkflowResults<T> =
54
- // T extends WorkflowDef<any, any, infer R, any, any> ? R : never;
55
- //
56
- // type WorkflowOutput<T> =
57
- // T extends WorkflowDef<any, any, any, any, infer O> ? O : never;
58
- //
59
- // export type StepResultFromResolve<
60
- // Reg extends ActionRegistry,
61
- // ActionName extends keyof Reg,
62
- // R extends ResolvedStepInput,
63
- // > = R extends { kind: "loop" }
64
- // ? ActionReturn<Reg, ActionName>[]
65
- // : ActionReturn<Reg, ActionName>;
66
- //
67
- // /* ------------------------------------------------ */
68
- // /* STEP DEFINITION */
69
- // /* ------------------------------------------------ */
70
- //
71
- // export type StepDef<
72
- // Reg extends ActionRegistry,
73
- // ID extends string = string,
74
- // ActionName extends keyof Reg = any,
75
- // > = {
76
- // id: ID;
77
- // action: ActionName;
78
- // dependsOn: string[];
79
- // resolve: (ctx: any) => ResolvedStepInput;
80
- // when?: (ctx: any) => boolean;
81
- // options?: StepOptions<any, any, any>;
82
- // };
83
- //
84
- // /* ------------------------------------------------ */
85
- // /* WORKFLOW DEFINITION */
86
- // /* ------------------------------------------------ */
87
- //
88
- // export type WorkflowDef<
89
- // Reg extends ActionRegistry,
90
- // Input,
91
- // Results,
92
- // Steps extends StepDef<Reg, any, any>[] = StepDef<Reg, any, any>[],
93
- // Output = undefined,
94
- // > = {
95
- // name: string;
96
- // steps: Steps;
97
- // entrySteps: StepDef<Reg>[];
98
- // endSteps: StepDef<Reg>[];
99
- // input: Input;
100
- // results: Results;
101
- // outputResolver?: (ctx: any) => Output;
102
- // // __context?: any;
103
- // };
104
- // type StepRuntimeCtx<I, R, C> = {
105
- // input: I;
106
- // results: R;
107
- // context: C;
108
- // };
109
- // type StepOptions<Input, Results, Context> = {
110
- // retry?: number;
111
- // retryDelay?: number | ((attempt: number) => number);
112
- // timeout?: number;
113
- //
114
- // continueOnError?: boolean;
115
- //
116
- // onError?: (err: unknown, ctx: StepRuntimeCtx<Input, Results, Context>) => any;
117
- //
118
- // // optional later:
119
- // label?: string;
120
- // meta?: Record<string, any>;
121
- // };
122
- //
123
- // /* ------------------------------------------------ */
124
- // /* HELPER TYPES */
125
- // /* ------------------------------------------------ */
126
- //
127
- // type MergeBranchResults<
128
- // Branches extends readonly any[],
129
- // Acc,
130
- // > = Branches extends readonly [infer Head, ...infer Tail]
131
- // ? MergeBranchResults<
132
- // Tail,
133
- // Acc & (Head extends WorkflowBuilder<any, any, any, any, infer R> ? R : {})
134
- // >
135
- // : Acc;
136
- //
137
- // type MergeBranchSteps<
138
- // Branches extends readonly any[],
139
- // Acc extends any[],
140
- // > = Branches extends readonly [infer Head, ...infer Tail]
141
- // ? MergeBranchSteps<
142
- // Tail,
143
- // [
144
- // ...Acc,
145
- // ...(Head extends WorkflowBuilder<any, any, any, infer S, any> ? S : []),
146
- // ]
147
- // >
148
- // : Acc;
149
- //
150
- // // type UnionToIntersection<U> = (U extends any ? (x: U) => any : never) extends (
151
- // // x: infer I,
152
- // // ) => any
153
- // // ? I
154
- // // : never;
155
- // //
156
- // // type ExtractBranchResults<Branches extends readonly any[]> =
157
- // // Branches[number] extends WorkflowBuilder<any, any, any, any, infer R>
158
- // // ? R
159
- // // : never;
160
- // //
161
- // // type MergeBranchResults<Branches extends readonly any[], Acc> = Simplify<
162
- // // Acc & Partial<ExtractBranchResults<Branches>>
163
- // // >;
164
- //
165
- // /* ------------------------------------------------ */
166
- // /* FLUENT WORKFLOW BUILDER */
167
- // /* ------------------------------------------------ */
168
- //
169
- // export class WorkflowBuilder<
170
- // Reg extends ActionRegistry,
171
- // Input = unknown,
172
- // Context = unknown,
173
- // Steps extends StepDef<Reg, any, any>[] = [],
174
- // Results = {},
175
- // Output = undefined,
176
- // > {
177
- // private steps: StepDef<Reg, any, any>[] = [];
178
- // private frontier: string[] = [];
179
- // private pendingWhen?: (ctx: {
180
- // input: Input;
181
- // results: Results;
182
- // context: Context;
183
- // }) => boolean;
184
- // private outputResolver?: (ctx: any) => any;
185
- // private clearPendingWhen() {
186
- // this.pendingWhen = undefined;
187
- // }
188
- //
189
- // constructor(private name: string) {}
190
- //
191
- // step<
192
- // ID extends string,
193
- // ActionName extends keyof Reg & string,
194
- // ResolveOut extends ResolvedStepInput = ResolvedStepInput,
195
- // >(
196
- // id: ID,
197
- // action: ActionName,
198
- // resolve?: (
199
- // ctx: {
200
- // input: Input;
201
- // results: Results;
202
- // context: Context;
203
- // } & CallHelpers<Reg, ActionName>,
204
- // ) => ResolveOut,
205
- // dependsOn?: string[],
206
- // options?: StepOptions<Input, Results, Context>,
207
- // ): WorkflowBuilder<
208
- // Reg,
209
- // Input,
210
- // Context,
211
- // [...Steps, StepDef<Reg, ID, ActionName>],
212
- // Simplify<
213
- // Results & {
214
- // [K in ID]: StepResultFromResolve<Reg, ActionName, ResolveOut>;
215
- // }
216
- // >
217
- // > {
218
- // const deps = dependsOn ?? [...this.frontier];
219
- //
220
- // this.steps.push({
221
- // id,
222
- // action,
223
- // resolve: resolve ?? (() => ({ kind: "none" })),
224
- // dependsOn: deps,
225
- // when: this.pendingWhen,
226
- // options,
227
- // });
228
- //
229
- // this.frontier = [id];
230
- //
231
- // return this as any;
232
- // }
233
- //
234
- // /* ------------------------------------------------ */
235
- // /* Sequential shortcut */
236
- // /* ------------------------------------------------ */
237
- // seq<
238
- // ID extends string = string,
239
- // ActionName extends keyof Reg & string = any,
240
- // ResolveOut extends ResolvedStepInput = ResolvedStepInput,
241
- // >(
242
- // id: ID,
243
- // action: ActionName,
244
- // resolve?: (
245
- // ctx: {
246
- // input: Input;
247
- // results: Results;
248
- // context: Context;
249
- // } & CallHelpers<Reg, ActionName>,
250
- // ) => ResolveOut,
251
- // options?: StepOptions<Input, Results, Context>,
252
- // ) {
253
- // return this.step<ID, ActionName, ResolveOut>(
254
- // id,
255
- // action,
256
- // resolve,
257
- // undefined,
258
- // options,
259
- // );
260
- // }
261
- //
262
- // /* ------------------------------------------------ */
263
- // /* Override the result of the last step */
264
- // /* ------------------------------------------------ */
265
- // as<NewType>(): WorkflowBuilder<
266
- // Reg,
267
- // Input,
268
- // Context,
269
- // Steps,
270
- // // Override the result of the last step only
271
- // Steps extends [...infer Rest, infer Last]
272
- // ? Last extends StepDef<Reg, infer ID, any>
273
- // ? Simplify<Omit<Results, ID> & { [K in ID]: NewType }>
274
- // : Results
275
- // : Results,
276
- // Output
277
- // > {
278
- // return this as any;
279
- // }
280
- //
281
- // parallel<
282
- // Branches extends readonly WorkflowBuilder<Reg, Input, Context, any, any>[],
283
- // >(
284
- // ...branches: {
285
- // [K in keyof Branches]: (
286
- // builder: WorkflowBuilder<Reg, Input, Context, [], Results>,
287
- // ) => Branches[K];
288
- // }
289
- // ): WorkflowBuilder<
290
- // Reg,
291
- // Input,
292
- // Context,
293
- // MergeBranchSteps<Branches, Steps>,
294
- // // [
295
- // // ...Steps,
296
- // // ...(Branches[number] extends WorkflowBuilder<Reg, any, any, infer S, any>
297
- // // ? S
298
- // // : never),
299
- // // ],
300
- // Simplify<MergeBranchResults<Branches, Results>>
301
- // > {
302
- // const parentFrontier = [...this.frontier];
303
- // const branchEnds: string[] = [];
304
- //
305
- // branches.forEach((branch) => {
306
- // const b = new WorkflowBuilder<Reg, Input, Context, [], Results>(
307
- // this.name,
308
- // );
309
- //
310
- // b.frontier = parentFrontier;
311
- // branch(b);
312
- // branchEnds.push(...b.frontier);
313
- // this.steps.push(...(b as any).steps);
314
- // });
315
- //
316
- // this.frontier = branchEnds;
317
- // this.clearPendingWhen();
318
- // return this as any;
319
- // }
320
- //
321
- // /* ------------------------------------------------ */
322
- // /* Join helper */
323
- // /* ------------------------------------------------ */
324
- // join<
325
- // ID extends string = string,
326
- // ActionName extends keyof Reg & string = any,
327
- // ResolveOut extends ResolvedStepInput = ResolvedStepInput,
328
- // >(
329
- // id: ID,
330
- // action: ActionName,
331
- // resolve?: (
332
- // ctx: {
333
- // input: Input;
334
- // results: Results;
335
- // context: Context;
336
- // } & CallHelpers<Reg, ActionName>,
337
- // ) => ResolveOut,
338
- // options?: StepOptions<Input, Results, Context>,
339
- // ) {
340
- // const result = this.step<ID, ActionName, ResolveOut>(
341
- // id,
342
- // action,
343
- // resolve,
344
- // [...this.frontier],
345
- // options,
346
- // );
347
- //
348
- // this.clearPendingWhen();
349
- // return result;
350
- // }
351
- //
352
1
  // /* ------------------------------------------------ */
353
2
  // /* Subflow */
354
3
  // /* ------------------------------------------------ */
@@ -419,90 +68,7 @@
419
68
  // /* Conditional */
420
69
  // /* ------------------------------------------------ */
421
70
  //
422
- // when(
423
- // predicate: (ctx: {
424
- // input: Input;
425
- // results: Results;
426
- // context: Context;
427
- // }) => boolean,
428
- // ): WorkflowBuilder<Reg, Input, Context, Steps, Results, Output> {
429
- // this.pendingWhen = predicate;
430
- // return this;
431
- // }
432
- //
433
- // endWhen(): this {
434
- // this.clearPendingWhen();
435
- //
436
- // return this;
437
- // }
438
- //
439
- // /* ------------------------------------------------ */
440
- // /* Workflow output */
441
- // /* ------------------------------------------------ */
442
- // output<Output>(
443
- // fn: (ctx: { input: Input; results: Results; context: Context }) => Output,
444
- // ): WorkflowDef<Reg, Input, Results, Steps, Output> {
445
- // this.outputResolver = fn;
446
- // return this.build() as WorkflowDef<Reg, Input, Results, Steps, Output>;
447
- // }
448
- //
449
- // build(): WorkflowDef<Reg, Input, Results, Steps> {
450
- // this.validateDependencies();
451
- //
452
- // return {
453
- // name: this.name,
454
- // steps: this.steps as Steps,
455
- // entrySteps: this.steps.filter((s) => s.dependsOn.length === 0),
456
- // endSteps: this.getEndSteps(),
457
- // input: {} as Input,
458
- // results: {} as Results,
459
- // outputResolver: this.outputResolver,
460
- // };
461
- // }
462
- //
463
- // private validateDependencies() {
464
- // const stepIds = new Set(this.steps.map((s) => s.id));
465
- // for (const step of this.steps) {
466
- // for (const dep of step.dependsOn) {
467
- // if (!stepIds.has(dep))
468
- // throw new Error(`Step ${step.id} depends on unknown step ${dep}`);
469
- // }
470
- // }
471
- // }
472
- //
473
- // private getEndSteps() {
474
- // const hasDependents = new Set<string>();
475
- // for (const step of this.steps) {
476
- // for (const dep of step.dependsOn) hasDependents.add(dep);
477
- // }
478
- // return this.steps.filter((s) => !hasDependents.has(s.id));
479
- // }
480
- // }
481
- //
482
- // /* ------------------------------------------------ */
483
- // /* WORKFLOW CREATOR */
484
- // /* ------------------------------------------------ */
485
- // // export function createWorkflow<
486
- // // Reg extends ActionRegistry,
487
- // // Context extends Record<string, any> = {},
488
- // // >(registry: Reg, context?: Context) {
489
- // // return function workflow<Input = unknown>(name: string) {
490
- // // return new WorkflowBuilder<Reg, Input, Context>(name);
491
- // // };
492
- // // }
493
- //
494
- // export function createWorkflow<
495
- // Reg extends ActionRegistry,
496
- // Context extends Record<string, any> = {},
497
- // >() {
498
- // return function workflow<Input = unknown>(name: string) {
499
- // return new WorkflowBuilder<Reg, Input, Context>(name);
500
- // };
501
- // }
502
- //
503
- //
504
- //
505
- //
71
+ import { generateWorkflowId } from "./utils.js";
506
72
  /* ------------------------------------------------ */
507
73
  /* FLUENT WORKFLOW BUILDER */
508
74
  /* ------------------------------------------------ */
@@ -534,6 +100,22 @@ export class WorkflowBuilder {
534
100
  seq(id, action, resolve, options) {
535
101
  return this.step(id, action, resolve, undefined, options);
536
102
  }
103
+ service(id, service, method, resolve) {
104
+ const deps = [...this.frontier];
105
+ this.steps.push({
106
+ id,
107
+ action: "__service__",
108
+ serviceCall: {
109
+ service,
110
+ method,
111
+ },
112
+ resolve: resolve ?? (() => ({ kind: "none" })),
113
+ dependsOn: deps,
114
+ when: this.pendingWhen,
115
+ });
116
+ this.frontier = [id];
117
+ return this;
118
+ }
537
119
  /* ------------------------------------------------ */
538
120
  /* Override the result of the last step */
539
121
  /* ------------------------------------------------ */
@@ -546,12 +128,12 @@ export class WorkflowBuilder {
546
128
  branches.forEach((branch) => {
547
129
  const b = new WorkflowBuilder(this.name);
548
130
  b.frontier = parentFrontier;
131
+ b.pendingWhen = this.pendingWhen;
549
132
  branch(b);
550
133
  branchEnds.push(...b.frontier);
551
134
  this.steps.push(...b.steps);
552
135
  });
553
136
  this.frontier = branchEnds;
554
- this.clearPendingWhen();
555
137
  return this;
556
138
  }
557
139
  /* ------------------------------------------------ */
@@ -567,10 +149,8 @@ export class WorkflowBuilder {
567
149
  id: prefix,
568
150
  action: "__subflow__",
569
151
  dependsOn: [...this.frontier],
570
- resolve: (ctx) => ({
571
- kind: "object",
572
- args: resolveInput(ctx),
573
- }),
152
+ when: this.pendingWhen,
153
+ resolve: (ctx) => resolveInput(ctx),
574
154
  options,
575
155
  __subflowId: workflowKey, // 👈 STRING ONLY
576
156
  });
@@ -598,6 +178,7 @@ export class WorkflowBuilder {
598
178
  build() {
599
179
  this.validateDependencies();
600
180
  return {
181
+ _id: generateWorkflowId(this.name),
601
182
  name: this.name,
602
183
  steps: this.steps,
603
184
  entrySteps: this.steps.filter((s) => s.dependsOn.length === 0),
@@ -625,17 +206,6 @@ export class WorkflowBuilder {
625
206
  return this.steps.filter((s) => !hasDependents.has(s.id));
626
207
  }
627
208
  }
628
- /* ------------------------------------------------ */
629
- /* WORKFLOW CREATOR */
630
- /* ------------------------------------------------ */
631
- // export function createWorkflow<
632
- // Reg extends ActionRegistry,
633
- // Context extends Record<string, any> = {},
634
- // >(registry: Reg, context?: Context) {
635
- // return function workflow<Input = unknown>(name: string) {
636
- // return new WorkflowBuilder<Reg, Input, Context>(name);
637
- // };
638
- // }
639
209
  export function createWorkflow() {
640
210
  return function workflow(name) {
641
211
  return new WorkflowBuilder(name);
@@ -1,6 +1,5 @@
1
- import { ActionRegistry, WorkflowObserver } from "./types.js";
1
+ import { ActionRegistry, Executor, ServiceRegistry, WorkflowObserver } from "./types.js";
2
2
  import { WorkflowDef } from "./workflow-composer.js";
3
- import { WorkflowInput, WorkflowOutput } from "./workflow-module.js";
4
3
  export declare function createCallHelpers(): {
5
4
  args: (...args: any[]) => {
6
5
  kind: string;
@@ -18,7 +17,14 @@ export declare function createCallHelpers(): {
18
17
  items: any[];
19
18
  };
20
19
  };
21
- export declare function executeWorkflow<Reg extends ActionRegistry, WR extends Record<string, WorkflowDef<any, any, any, any, any>>, K extends keyof WR>(workflowId: K, workflowRegistry: WR, actionRegistry: Reg, input: WorkflowInput<WR[K]>, context: any, observers?: WorkflowObserver<Reg>[]): Promise<{
22
- output: WorkflowOutput<WR[K]>;
20
+ export declare function executeWorkflow<Reg extends ActionRegistry, I, R, O = R>({ workflow, actionRegistry, services, input, depsExecutors, observers, }: {
21
+ workflow: WorkflowDef<Reg, I, any, any, O>;
22
+ actionRegistry: Reg;
23
+ services: ServiceRegistry;
24
+ input: I;
25
+ depsExecutors: Record<string, Executor>;
26
+ observers: WorkflowObserver<Reg>[];
27
+ }): Promise<{
28
+ output: O;
23
29
  extras: Record<string, any>;
24
30
  }>;