@pogodisco/zephyr 1.5.3 → 1.5.5
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.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +15 -1
- package/dist/workflow-composer-pipe.d.ts +2 -12
- package/dist/workflow-composer.d.ts +9 -7
- package/dist/workflow-composer.js +2 -0
- package/dist/workflow-executor.js +61 -11
- package/dist/workflow-module.d.ts +9 -6
- package/dist/workflow-module.js +305 -5
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from "./registry.js";
|
|
|
3
3
|
export * from "./workflow-executor.js";
|
|
4
4
|
export * from "./workflow-composer.js";
|
|
5
5
|
export * from "./workflow-module.js";
|
|
6
|
+
export { exposeAll, exposeAllAs } from "./utils.js";
|
|
6
7
|
export * from "./types.js";
|
|
7
8
|
export * from "./session.js";
|
|
8
9
|
export { useMetrics, useLog } from "./observer.js";
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export * from "./registry.js";
|
|
|
3
3
|
export * from "./workflow-executor.js";
|
|
4
4
|
export * from "./workflow-composer.js";
|
|
5
5
|
export * from "./workflow-module.js";
|
|
6
|
+
export { exposeAll, exposeAllAs } from "./utils.js";
|
|
6
7
|
export * from "./types.js";
|
|
7
8
|
export * from "./session.js";
|
|
8
9
|
export { useMetrics, useLog } from "./observer.js";
|
package/dist/utils.d.ts
CHANGED
|
@@ -1 +1,4 @@
|
|
|
1
|
+
import { Module } from "./workflow-module.js";
|
|
1
2
|
export declare function generateWorkflowId(name: string): string;
|
|
3
|
+
export declare function exposeAll<Name extends string, M extends Module<any, any, any, any>>(name: Name, mod: M): Record<`${Name}.${keyof M["workflows"] & string}`, `${Name}.${keyof M["workflows"] & string}`>;
|
|
4
|
+
export declare function exposeAllAs<Name extends string, M extends Module<any, any, any, any>>(name: Name, mod: M): Record<keyof M["workflows"] & string, `${Name}.${keyof M["workflows"] & string}`>;
|
package/dist/utils.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
export function generateWorkflowId(name) {
|
|
2
|
-
// Short random + timestamp for practically unique ID
|
|
3
2
|
const random = Math.random().toString(36).slice(2, 10);
|
|
4
3
|
const time = Date.now().toString(36);
|
|
5
4
|
return `${name}-${time}-${random}`;
|
|
6
5
|
}
|
|
6
|
+
export function exposeAll(name, mod) {
|
|
7
|
+
const result = {};
|
|
8
|
+
for (const key in mod.workflows) {
|
|
9
|
+
const full = `${name}.${key}`;
|
|
10
|
+
result[full] = full;
|
|
11
|
+
}
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
export function exposeAllAs(name, mod) {
|
|
15
|
+
const result = {};
|
|
16
|
+
for (const key in mod.workflows) {
|
|
17
|
+
result[key] = `${name}.${key}`;
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
@@ -25,7 +25,7 @@ export declare class PipeBuilder<Current, Reg extends ActionRegistry, Services e
|
|
|
25
25
|
action<A extends keyof Reg & string>(action: A, resolve: (ctx: {
|
|
26
26
|
current: Current;
|
|
27
27
|
results: Results;
|
|
28
|
-
} & CallHelpers<Reg, A>) => NormalizedCall): PipeBuilder<ActionReturn<Reg, A>, Reg, Services, Results, [
|
|
28
|
+
} & Results & CallHelpers<Reg, A>) => NormalizedCall): PipeBuilder<ActionReturn<Reg, A>, Reg, Services, Results, [
|
|
29
29
|
...Steps,
|
|
30
30
|
{
|
|
31
31
|
type: "action";
|
|
@@ -35,7 +35,7 @@ export declare class PipeBuilder<Current, Reg extends ActionRegistry, Services e
|
|
|
35
35
|
service<SK extends keyof Services & string, MK extends keyof Services[SK] & string>(id: string, service: SK, method: MK, resolve: (ctx: {
|
|
36
36
|
current: Current;
|
|
37
37
|
results: Results;
|
|
38
|
-
} & {
|
|
38
|
+
} & Results & {
|
|
39
39
|
args: (...args: ServiceParams<Services, SK, MK>) => {
|
|
40
40
|
kind: "positional";
|
|
41
41
|
args: ServiceParams<Services, SK, MK>;
|
|
@@ -47,16 +47,6 @@ export declare class PipeBuilder<Current, Reg extends ActionRegistry, Services e
|
|
|
47
47
|
none: () => {
|
|
48
48
|
kind: "none";
|
|
49
49
|
};
|
|
50
|
-
loop: (items: {
|
|
51
|
-
kind: "positional";
|
|
52
|
-
args: ServiceParams<Services, SK, MK>;
|
|
53
|
-
}[] | {
|
|
54
|
-
kind: "object";
|
|
55
|
-
args: ServiceParams<Services, SK, MK>[0];
|
|
56
|
-
}[]) => {
|
|
57
|
-
kind: "loop";
|
|
58
|
-
items: typeof items;
|
|
59
|
-
};
|
|
60
50
|
}) => NormalizedCall): PipeBuilder<ServiceReturn<Services, SK, MK>, Reg, Services, Results, [
|
|
61
51
|
...Steps,
|
|
62
52
|
{
|
|
@@ -57,7 +57,7 @@ Input = unknown, Steps extends StepDef<Reg, any, any>[] = [], Results = {}, Outp
|
|
|
57
57
|
step<ID extends string, ActionName extends keyof Reg & string>(id: ID, action: ActionName, resolve?: (ctx: {
|
|
58
58
|
input: Input;
|
|
59
59
|
results: Results;
|
|
60
|
-
} & CallHelpers<Reg, ActionName>) => NormalizedCall, dependsOn?: string[], options?: StepOptions<Input, Results>): WorkflowBuilder<Reg, Services, WFReg, Input, [
|
|
60
|
+
} & Results & CallHelpers<Reg, ActionName>) => NormalizedCall, dependsOn?: string[], options?: StepOptions<Input, Results>): WorkflowBuilder<Reg, Services, WFReg, Input, [
|
|
61
61
|
...Steps,
|
|
62
62
|
StepDef<Reg, ID, ActionName>
|
|
63
63
|
], Simplify<Results & {
|
|
@@ -66,11 +66,11 @@ Input = unknown, Steps extends StepDef<Reg, any, any>[] = [], Results = {}, Outp
|
|
|
66
66
|
seq<ID extends string = string, ActionName extends keyof Reg & string = any>(id: ID, action: ActionName, resolve?: (ctx: {
|
|
67
67
|
input: Input;
|
|
68
68
|
results: Results;
|
|
69
|
-
} & CallHelpers<Reg, ActionName>) => NormalizedCall, options?: StepOptions<Input, Results>): WorkflowBuilder<Reg, Services, WFReg, Input, [...Steps, StepDef<Reg, ID, ActionName>], Results & { [K_1 in ID]: ActionReturn<Reg, ActionName>; } extends infer T ? { [K in keyof T]: T[K]; } : never, undefined>;
|
|
69
|
+
} & Results & CallHelpers<Reg, ActionName>) => NormalizedCall, options?: StepOptions<Input, Results>): WorkflowBuilder<Reg, Services, WFReg, Input, [...Steps, StepDef<Reg, ID, ActionName>], Results & { [K_1 in ID]: ActionReturn<Reg, ActionName>; } extends infer T ? { [K in keyof T]: T[K]; } : never, undefined>;
|
|
70
70
|
service<ID extends string, SK extends keyof Services & string, MK extends keyof Services[SK] & string>(id: ID, service: SK, method: MK, resolve?: (ctx: {
|
|
71
71
|
input: Input;
|
|
72
72
|
results: Results;
|
|
73
|
-
} & {
|
|
73
|
+
} & Results & {
|
|
74
74
|
args: (...args: ServiceParams<Services, SK, MK>) => {
|
|
75
75
|
kind: "positional";
|
|
76
76
|
args: ServiceParams<Services, SK, MK>;
|
|
@@ -91,7 +91,7 @@ Input = unknown, Steps extends StepDef<Reg, any, any>[] = [], Results = {}, Outp
|
|
|
91
91
|
pipe<ID extends string, Arr extends any[], PB extends PipeBuilder<any, Reg, Services, Results, any>>(id: ID, input: (ctx: {
|
|
92
92
|
input: Input;
|
|
93
93
|
results: Results;
|
|
94
|
-
}) => Arr, builder: (p: PipeBuilder<Arr[number], Reg, Services, Results>) => PB, options?: StepOptions<Input, Results>): WorkflowBuilder<Reg, Services, WFReg, Input, [
|
|
94
|
+
} & Results) => Arr, builder: (p: PipeBuilder<Arr[number], Reg, Services, Results>) => PB, options?: StepOptions<Input, Results>): WorkflowBuilder<Reg, Services, WFReg, Input, [
|
|
95
95
|
...Steps,
|
|
96
96
|
StepDef<Reg, ID, any>
|
|
97
97
|
], Simplify<Results & {
|
|
@@ -106,22 +106,24 @@ Input = unknown, Steps extends StepDef<Reg, any, any>[] = [], Results = {}, Outp
|
|
|
106
106
|
join<ID extends string = string, ActionName extends keyof Reg & string = any>(id: ID, action: ActionName, resolve?: (ctx: {
|
|
107
107
|
input: Input;
|
|
108
108
|
results: Results;
|
|
109
|
-
} & CallHelpers<Reg, ActionName>) => NormalizedCall, options?: StepOptions<Input, Results>): WorkflowBuilder<Reg, Services, WFReg, Input, [...Steps, StepDef<Reg, ID, ActionName>], Results & { [K_1 in ID]: ActionReturn<Reg, ActionName>; } extends infer T ? { [K in keyof T]: T[K]; } : never, undefined>;
|
|
109
|
+
} & Results & CallHelpers<Reg, ActionName>) => NormalizedCall, options?: StepOptions<Input, Results>): WorkflowBuilder<Reg, Services, WFReg, Input, [...Steps, StepDef<Reg, ID, ActionName>], Results & { [K_1 in ID]: ActionReturn<Reg, ActionName>; } extends infer T ? { [K in keyof T]: T[K]; } : never, undefined>;
|
|
110
110
|
subflow<Prefix extends string, K extends keyof WFReg & string>(prefix: Prefix, workflowKey: K, resolveInput: (ctx: {
|
|
111
111
|
input: Input;
|
|
112
112
|
results: Results;
|
|
113
113
|
}) => WorkflowInput<WFReg[K]>, options?: StepOptions<Input, Results>): WorkflowBuilder<Reg, Services, WFReg, Input, Steps, Results & {
|
|
114
114
|
[P in Prefix]: WorkflowOutput<WFReg[K]>;
|
|
115
115
|
}>;
|
|
116
|
+
private _subflow;
|
|
117
|
+
sub: this["subflow"];
|
|
116
118
|
when(predicate: (ctx: {
|
|
117
119
|
input: Input;
|
|
118
120
|
results: Results;
|
|
119
|
-
}) => boolean): WorkflowBuilder<Reg, Services, WFReg, Input, Steps, Results, Output>;
|
|
121
|
+
} & Results) => boolean): WorkflowBuilder<Reg, Services, WFReg, Input, Steps, Results, Output>;
|
|
120
122
|
endWhen(): this;
|
|
121
123
|
output<Output>(fn: (ctx: {
|
|
122
124
|
input: Input;
|
|
123
125
|
results: Results;
|
|
124
|
-
}) => Output): WorkflowDef<Reg, Input, Results, Steps, Output>;
|
|
126
|
+
} & Results) => Output): WorkflowDef<Reg, Input, Results, Steps, Output>;
|
|
125
127
|
build(): WorkflowDef<Reg, Input, Results, Steps>;
|
|
126
128
|
private validateDependencies;
|
|
127
129
|
private getEndSteps;
|
|
@@ -11,6 +11,8 @@ export class WorkflowBuilder {
|
|
|
11
11
|
this.name = name;
|
|
12
12
|
this.steps = [];
|
|
13
13
|
this.frontier = [];
|
|
14
|
+
this._subflow = this.subflow.bind(this);
|
|
15
|
+
this.sub = ((...args) => this._subflow(...args));
|
|
14
16
|
}
|
|
15
17
|
step(id, action, resolve, dependsOn, options) {
|
|
16
18
|
const deps = dependsOn ?? [...this.frontier];
|
|
@@ -14,6 +14,24 @@ async function withTimeout(promise, ms) {
|
|
|
14
14
|
new Promise((_, reject) => setTimeout(() => reject(new Error("Timeout")), ms)),
|
|
15
15
|
]);
|
|
16
16
|
}
|
|
17
|
+
function createStepCtx(input, results) {
|
|
18
|
+
const helpers = createCallHelpers();
|
|
19
|
+
return new Proxy({
|
|
20
|
+
input,
|
|
21
|
+
results,
|
|
22
|
+
...helpers,
|
|
23
|
+
}, {
|
|
24
|
+
get(target, prop) {
|
|
25
|
+
// 1. explicit keys first
|
|
26
|
+
if (prop in target)
|
|
27
|
+
return target[prop];
|
|
28
|
+
// 2. fallback to results
|
|
29
|
+
if (prop in results)
|
|
30
|
+
return results[prop];
|
|
31
|
+
return undefined;
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
}
|
|
17
35
|
// Helper to run action with retry support
|
|
18
36
|
async function runWithRetry(actionFn, stepOptions) {
|
|
19
37
|
const maxRetries = stepOptions?.retry ?? 0;
|
|
@@ -100,11 +118,13 @@ export async function executeWorkflow({ workflow, actionRegistry, services, inpu
|
|
|
100
118
|
extras,
|
|
101
119
|
frame,
|
|
102
120
|
};
|
|
103
|
-
const stepCtx =
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
121
|
+
const stepCtx = createStepCtx(input, results);
|
|
122
|
+
// const stepCtx = {
|
|
123
|
+
// input,
|
|
124
|
+
// results,
|
|
125
|
+
//
|
|
126
|
+
// ...createCallHelpers(),
|
|
127
|
+
// };
|
|
108
128
|
const resolvedArgs = step.resolve?.(stepCtx);
|
|
109
129
|
frame.input = resolvedArgs;
|
|
110
130
|
const core = async () => {
|
|
@@ -128,11 +148,43 @@ export async function executeWorkflow({ workflow, actionRegistry, services, inpu
|
|
|
128
148
|
const pipeResults = await Promise.all(items.map(async (item) => {
|
|
129
149
|
let current = item;
|
|
130
150
|
for (const pipeStep of step.pipe.steps) {
|
|
131
|
-
|
|
151
|
+
// return new Proxy(
|
|
152
|
+
// {
|
|
153
|
+
// input,
|
|
154
|
+
// results,
|
|
155
|
+
// ...helpers,
|
|
156
|
+
// },
|
|
157
|
+
// {
|
|
158
|
+
// get(target, prop) {
|
|
159
|
+
// // 1. explicit keys first
|
|
160
|
+
// if (prop in target) return target[prop as keyof typeof target];
|
|
161
|
+
//
|
|
162
|
+
// // 2. fallback to results
|
|
163
|
+
// if (prop in results) return results[prop as keyof typeof target];
|
|
164
|
+
//
|
|
165
|
+
// return undefined;
|
|
166
|
+
// },
|
|
167
|
+
// },
|
|
168
|
+
// );
|
|
169
|
+
// }
|
|
170
|
+
// const pipeCtx = {
|
|
171
|
+
// current,
|
|
172
|
+
// results,
|
|
173
|
+
// ...createCallHelpers(),
|
|
174
|
+
// };
|
|
175
|
+
const pipeCtx = new Proxy({
|
|
132
176
|
current,
|
|
133
177
|
results,
|
|
134
178
|
...createCallHelpers(),
|
|
135
|
-
}
|
|
179
|
+
}, {
|
|
180
|
+
get(target, prop) {
|
|
181
|
+
if (prop in target)
|
|
182
|
+
return target[prop];
|
|
183
|
+
if (prop in results)
|
|
184
|
+
return results[prop];
|
|
185
|
+
return undefined;
|
|
186
|
+
},
|
|
187
|
+
});
|
|
136
188
|
const resolved = pipeStep.resolve(pipeCtx);
|
|
137
189
|
let action;
|
|
138
190
|
if (pipeStep.type === "action") {
|
|
@@ -219,11 +271,9 @@ export async function executeWorkflow({ workflow, actionRegistry, services, inpu
|
|
|
219
271
|
if (completed !== workflow.steps.length) {
|
|
220
272
|
throw new Error("Workflow execution failed (cycle or missing dependency)");
|
|
221
273
|
}
|
|
274
|
+
const outputCtx = createStepCtx(input, results);
|
|
222
275
|
const output = workflow.outputResolver
|
|
223
|
-
? workflow.outputResolver(
|
|
224
|
-
input,
|
|
225
|
-
results,
|
|
226
|
-
})
|
|
276
|
+
? workflow.outputResolver(outputCtx)
|
|
227
277
|
: results;
|
|
228
278
|
return {
|
|
229
279
|
// results: results as WorkflowResults<WR[K]>,
|
|
@@ -9,7 +9,6 @@ type DepWorkflows<Deps extends ModuleMap> = keyof Deps extends never ? {} : Simp
|
|
|
9
9
|
[K in keyof Deps[D]["workflows"] & string as `${D}.${K}`]: Deps[D]["workflows"][K];
|
|
10
10
|
};
|
|
11
11
|
}[keyof Deps & string]>>>;
|
|
12
|
-
type WorkflowRegistry<Own extends ModuleShape, Deps extends ModuleMap> = Own & DepWorkflows<Deps>;
|
|
13
12
|
type AnyWorkflow = WorkflowDef<any, any, any, any, any>;
|
|
14
13
|
type ModuleShape = Record<string, AnyWorkflow>;
|
|
15
14
|
type ModuleMap = Record<string, Module<any, any, any, any>>;
|
|
@@ -22,14 +21,14 @@ type ServicesFromDepsRecursive<Deps extends ModuleMap> = [keyof Deps] extends [
|
|
|
22
21
|
export type WorkflowInput<W> = W extends WorkflowDef<any, infer I, any, any, any> ? I : never;
|
|
23
22
|
export type WorkflowResults<W> = W extends WorkflowDef<any, any, infer R, any, any> ? R : never;
|
|
24
23
|
export type WorkflowOutput<W> = W extends WorkflowDef<any, any, any, any, infer O> ? O : never;
|
|
25
|
-
type Module<Reg extends ActionRegistry, S extends ServiceRegistry, Own extends ModuleShape, Deps extends ModuleMap> = {
|
|
24
|
+
export type Module<Reg extends ActionRegistry, S extends ServiceRegistry, Own extends ModuleShape, Deps extends ModuleMap, Public extends ModuleShape = Own> = {
|
|
26
25
|
workflows: Own;
|
|
27
26
|
__getExecutor: () => Executor;
|
|
28
27
|
createRuntime: (config: {
|
|
29
28
|
services: FinalServices<S, Deps>;
|
|
30
29
|
}) => {
|
|
31
|
-
run: <K extends keyof
|
|
32
|
-
output: WorkflowOutput<
|
|
30
|
+
run: <K extends keyof Public>(workflow: K, input: WorkflowInput<Public[K]>, observers?: WorkflowObserver<Reg>[]) => Promise<{
|
|
31
|
+
output: WorkflowOutput<Public[K]>;
|
|
33
32
|
extras: Record<string, any>;
|
|
34
33
|
}>;
|
|
35
34
|
getServices: () => FinalServices<S, Deps>;
|
|
@@ -39,9 +38,13 @@ type ModuleContext<Reg extends ActionRegistry, WFReg extends Record<string, Work
|
|
|
39
38
|
wf: ReturnType<typeof createWorkflow<Reg, WFReg, S>>;
|
|
40
39
|
services: S;
|
|
41
40
|
};
|
|
42
|
-
|
|
41
|
+
type ExposedWorkflows<Own extends ModuleShape, Use extends ModuleMap, Expose extends Record<string, keyof DepWorkflows<Use>> | undefined> = Own & (Expose extends Record<string, keyof DepWorkflows<Use>> ? {
|
|
42
|
+
[K in keyof Expose]: DepWorkflows<Use>[Expose[K]];
|
|
43
|
+
} : {});
|
|
44
|
+
export declare function createModuleFactory<S extends ServiceRegistry>(): <Reg extends ActionRegistry = Record<string, any>, Use extends ModuleMap = {}, Own extends ModuleShape = {}, Expose extends Record<string, keyof DepWorkflows<Use>> | undefined = undefined>(config: {
|
|
43
45
|
actionRegistry: Reg;
|
|
44
46
|
use?: Use;
|
|
47
|
+
expose?: Expose;
|
|
45
48
|
define: (ctx: ModuleContext<typeof config.actionRegistry, DepWorkflows<Use>, S>) => Own;
|
|
46
|
-
}) => Module<Reg, S, Own, Use
|
|
49
|
+
}) => Module<Reg, S, Own, Use, ExposedWorkflows<Own, Use, Expose>>;
|
|
47
50
|
export {};
|
package/dist/workflow-module.js
CHANGED
|
@@ -1,21 +1,316 @@
|
|
|
1
|
-
import {
|
|
1
|
+
// import {
|
|
2
|
+
// ActionRegistry,
|
|
3
|
+
// ServiceRegistry,
|
|
4
|
+
// Executor,
|
|
5
|
+
// Simplify,
|
|
6
|
+
// WorkflowObserver,
|
|
7
|
+
// } from "./types.js";
|
|
8
|
+
// import { createWorkflow, WorkflowDef } from "./workflow-composer.js";
|
|
9
|
+
// import { executeWorkflow } from "./workflow-executor.js";
|
|
10
|
+
// type UnionToIntersection<U> = (U extends any ? (x: U) => any : never) extends (
|
|
11
|
+
// x: infer I,
|
|
12
|
+
// ) => any
|
|
13
|
+
// ? I
|
|
14
|
+
// : never;
|
|
15
|
+
// /* ------------------------------------------------ */
|
|
16
|
+
// /* WORKFLOW REGISTRY TYPES */
|
|
17
|
+
// /* ------------------------------------------------ */
|
|
18
|
+
// type EnsureWorkflowRecord<T> =
|
|
19
|
+
// T extends Record<string, WorkflowDef<any, any, any, any, any>>
|
|
20
|
+
// ? T
|
|
21
|
+
// : Record<string, WorkflowDef<any, any, any, any, any>>;
|
|
22
|
+
//
|
|
23
|
+
// type EnsureWorkflowShape<T> = {
|
|
24
|
+
// [K in keyof T]: T[K] extends WorkflowDef<any, any, any, any, any>
|
|
25
|
+
// ? T[K]
|
|
26
|
+
// : never;
|
|
27
|
+
// };
|
|
28
|
+
//
|
|
29
|
+
// type DepWorkflows<Deps extends ModuleMap> = keyof Deps extends never
|
|
30
|
+
// ? {}
|
|
31
|
+
// : Simplify<
|
|
32
|
+
// EnsureWorkflowShape<
|
|
33
|
+
// UnionToIntersection<
|
|
34
|
+
// {
|
|
35
|
+
// [D in keyof Deps & string]: {
|
|
36
|
+
// [K in keyof Deps[D]["workflows"] &
|
|
37
|
+
// string as `${D}.${K}`]: Deps[D]["workflows"][K];
|
|
38
|
+
// };
|
|
39
|
+
// }[keyof Deps & string]
|
|
40
|
+
// >
|
|
41
|
+
// >
|
|
42
|
+
// >;
|
|
43
|
+
//
|
|
44
|
+
// type WorkflowRegistry<Own extends ModuleShape, Deps extends ModuleMap> = Own &
|
|
45
|
+
// DepWorkflows<Deps>;
|
|
46
|
+
//
|
|
47
|
+
// /* ------------------------------------------------ */
|
|
48
|
+
// /* MODULE TYPES */
|
|
49
|
+
// /* ------------------------------------------------ */
|
|
50
|
+
//
|
|
51
|
+
// type AnyWorkflow = WorkflowDef<any, any, any, any, any>;
|
|
52
|
+
// type ModuleShape = Record<string, AnyWorkflow>;
|
|
53
|
+
// type ModuleMap = Record<string, Module<any, any, any, any>>;
|
|
54
|
+
//
|
|
55
|
+
// // type ContextFromDeps<Deps> = [keyof Deps] extends [never]
|
|
56
|
+
// // ? {}
|
|
57
|
+
// // : {
|
|
58
|
+
// // [K in keyof Deps]: Deps[K] extends Module<any, infer Ctx, any, any>
|
|
59
|
+
// // ? Ctx
|
|
60
|
+
// // : never;
|
|
61
|
+
// // }[keyof Deps];
|
|
62
|
+
//
|
|
63
|
+
// type FinalServices<S extends ServiceRegistry, Deps extends ModuleMap> = S &
|
|
64
|
+
// ServicesFromDepsRecursive<Deps>;
|
|
65
|
+
//
|
|
66
|
+
// // type ContextFromDeps<Deps> = [keyof Deps] extends [never]
|
|
67
|
+
// // ? {}
|
|
68
|
+
// // : UnionToIntersection<
|
|
69
|
+
// // {
|
|
70
|
+
// // [K in keyof Deps]: Deps[K] extends Module<any, infer Ctx, any, any>
|
|
71
|
+
// // ? Ctx
|
|
72
|
+
// // : never;
|
|
73
|
+
// // }[keyof Deps]
|
|
74
|
+
// // >;
|
|
75
|
+
//
|
|
76
|
+
// type ServicesFromDepsRecursive<Deps extends ModuleMap> = [keyof Deps] extends [
|
|
77
|
+
// never,
|
|
78
|
+
// ]
|
|
79
|
+
// ? {} // no deps
|
|
80
|
+
// : UnionToIntersection<
|
|
81
|
+
// {
|
|
82
|
+
// [K in keyof Deps]: Deps[K] extends Module<
|
|
83
|
+
// any,
|
|
84
|
+
// infer S,
|
|
85
|
+
// any,
|
|
86
|
+
// infer SubDeps
|
|
87
|
+
// >
|
|
88
|
+
// ? S & ServicesFromDepsRecursive<SubDeps>
|
|
89
|
+
// : never;
|
|
90
|
+
// }[keyof Deps]
|
|
91
|
+
// >;
|
|
92
|
+
//
|
|
93
|
+
// /* ------------------------------------------------ */
|
|
94
|
+
// /* WORKFLOW IO TYPES */
|
|
95
|
+
// /* ------------------------------------------------ */
|
|
96
|
+
//
|
|
97
|
+
// export type WorkflowInput<W> =
|
|
98
|
+
// W extends WorkflowDef<any, infer I, any, any, any> ? I : never;
|
|
99
|
+
//
|
|
100
|
+
// export type WorkflowResults<W> =
|
|
101
|
+
// W extends WorkflowDef<any, any, infer R, any, any> ? R : never;
|
|
102
|
+
//
|
|
103
|
+
// export type WorkflowOutput<W> =
|
|
104
|
+
// W extends WorkflowDef<any, any, any, any, infer O> ? O : never;
|
|
105
|
+
//
|
|
106
|
+
// /* ------------------------------------------------ */
|
|
107
|
+
// /* MODULE RUNTIME */
|
|
108
|
+
// /* ------------------------------------------------ */
|
|
109
|
+
//
|
|
110
|
+
// type Module<
|
|
111
|
+
// Reg extends ActionRegistry,
|
|
112
|
+
// S extends ServiceRegistry,
|
|
113
|
+
// Own extends ModuleShape,
|
|
114
|
+
// Deps extends ModuleMap,
|
|
115
|
+
// > = {
|
|
116
|
+
// workflows: Own;
|
|
117
|
+
// __getExecutor: () => Executor;
|
|
118
|
+
//
|
|
119
|
+
// createRuntime: (config: { services: FinalServices<S, Deps> }) => {
|
|
120
|
+
// run: <K extends keyof WorkflowRegistry<Own, Deps>>(
|
|
121
|
+
// workflow: K,
|
|
122
|
+
// input: WorkflowInput<WorkflowRegistry<Own, Deps>[K]>,
|
|
123
|
+
// observers?: WorkflowObserver<Reg>[],
|
|
124
|
+
// ) => Promise<{
|
|
125
|
+
// // results: WorkflowResults<WorkflowRegistry<Own, Deps>[K]>;
|
|
126
|
+
// output: WorkflowOutput<WorkflowRegistry<Own, Deps>[K]>;
|
|
127
|
+
// extras: Record<string, any>;
|
|
128
|
+
// }>;
|
|
129
|
+
//
|
|
130
|
+
// getServices: () => FinalServices<S, Deps>;
|
|
131
|
+
// };
|
|
132
|
+
// };
|
|
133
|
+
//
|
|
134
|
+
// /* ------------------------------------------------ */
|
|
135
|
+
// /* MODULE CONTEXT (FIXED) */
|
|
136
|
+
// /* ------------------------------------------------ */
|
|
137
|
+
//
|
|
138
|
+
// type ModuleContext<
|
|
139
|
+
// Reg extends ActionRegistry,
|
|
140
|
+
// WFReg extends Record<string, WorkflowDef<any, any, any, any, any>>,
|
|
141
|
+
// S extends ServiceRegistry,
|
|
142
|
+
// > = {
|
|
143
|
+
// wf: ReturnType<typeof createWorkflow<Reg, WFReg, S>>;
|
|
144
|
+
// services: S;
|
|
145
|
+
// };
|
|
146
|
+
//
|
|
147
|
+
// function createModule<
|
|
148
|
+
// Reg extends ActionRegistry,
|
|
149
|
+
// S extends ServiceRegistry,
|
|
150
|
+
// Use extends ModuleMap,
|
|
151
|
+
// Own extends ModuleShape,
|
|
152
|
+
// >(config: {
|
|
153
|
+
// actionRegistry: Reg;
|
|
154
|
+
// use?: Use;
|
|
155
|
+
// define: (ctx: ModuleContext<Reg, DepWorkflows<Use>, S>) => Own;
|
|
156
|
+
// }): Module<Reg, S, Own, Use> {
|
|
157
|
+
// const deps = (config.use ?? {}) as Use;
|
|
158
|
+
//
|
|
159
|
+
// const wf = createWorkflow<Reg, DepWorkflows<Use>, S>();
|
|
160
|
+
//
|
|
161
|
+
// const own = config.define({
|
|
162
|
+
// wf,
|
|
163
|
+
// services: {} as S,
|
|
164
|
+
// });
|
|
165
|
+
//
|
|
166
|
+
// function buildWorkflowMap(): WorkflowRegistry<Own, Use> {
|
|
167
|
+
// const depWFs = Object.fromEntries(
|
|
168
|
+
// Object.entries(deps).flatMap(([name, mod]) =>
|
|
169
|
+
// Object.entries(mod.workflows).map(([k, wf]) => [`${name}.${k}`, wf]),
|
|
170
|
+
// ),
|
|
171
|
+
// );
|
|
172
|
+
//
|
|
173
|
+
// return { ...own, ...depWFs } as WorkflowRegistry<Own, Use>;
|
|
174
|
+
// }
|
|
175
|
+
//
|
|
176
|
+
// const workflowMap = buildWorkflowMap();
|
|
177
|
+
//
|
|
178
|
+
// const depsExecutors = Object.fromEntries(
|
|
179
|
+
// Object.entries(deps).map(([name, mod]) => [name, mod.__getExecutor()]),
|
|
180
|
+
// );
|
|
181
|
+
//
|
|
182
|
+
// const executor: Executor = {
|
|
183
|
+
// run(wfId, input, services, observers = []) {
|
|
184
|
+
// const workflow = workflowMap[wfId];
|
|
185
|
+
//
|
|
186
|
+
// if (!workflow) {
|
|
187
|
+
// throw new Error(`Workflow not found: ${String(wfId)}`);
|
|
188
|
+
// }
|
|
189
|
+
//
|
|
190
|
+
// return executeWorkflow({
|
|
191
|
+
// workflow,
|
|
192
|
+
// actionRegistry: config.actionRegistry,
|
|
193
|
+
// depsExecutors,
|
|
194
|
+
// input,
|
|
195
|
+
// services,
|
|
196
|
+
// observers,
|
|
197
|
+
// });
|
|
198
|
+
// },
|
|
199
|
+
// };
|
|
200
|
+
//
|
|
201
|
+
// return {
|
|
202
|
+
// workflows: own,
|
|
203
|
+
// __getExecutor: () => executor,
|
|
204
|
+
//
|
|
205
|
+
// createRuntime({ services }) {
|
|
206
|
+
// let runtimeActions = config.actionRegistry;
|
|
207
|
+
//
|
|
208
|
+
// // const runtimeService = createServiceRegisty(services)
|
|
209
|
+
// return {
|
|
210
|
+
// run: async <K extends keyof WorkflowRegistry<Own, Use>>(
|
|
211
|
+
// workflowId: K,
|
|
212
|
+
// input: WorkflowInput<WorkflowRegistry<Own, Use>[K]>,
|
|
213
|
+
// observers: WorkflowObserver<Reg>[] = [],
|
|
214
|
+
// ) => {
|
|
215
|
+
// return executor.run(workflowId as string, input, services, observers);
|
|
216
|
+
// },
|
|
217
|
+
// // make it same, practically nothing changes but naming, and what context holds
|
|
218
|
+
// getServices: () => ({ ...services }) as FinalServices<S, Use>,
|
|
219
|
+
//
|
|
220
|
+
// setActionRegistry(reg: Reg) {
|
|
221
|
+
// runtimeActions = reg;
|
|
222
|
+
// // ⚠️ optional: if you REALLY want override, you'd need:
|
|
223
|
+
// // executor.actions = reg
|
|
224
|
+
// // but better keep actions immutable
|
|
225
|
+
// },
|
|
226
|
+
// };
|
|
227
|
+
// },
|
|
228
|
+
// };
|
|
229
|
+
// }
|
|
230
|
+
//
|
|
231
|
+
// /* ------------------------------------------------ */
|
|
232
|
+
// /* FACTORY (FIXED) */
|
|
233
|
+
// /* ------------------------------------------------ */
|
|
234
|
+
//
|
|
235
|
+
// export function createModuleFactory<
|
|
236
|
+
// // Reg extends ActionRegistry,
|
|
237
|
+
// S extends ServiceRegistry,
|
|
238
|
+
// >() {
|
|
239
|
+
// return function <
|
|
240
|
+
// Reg extends ActionRegistry = Record<string, any>,
|
|
241
|
+
// Use extends ModuleMap = {},
|
|
242
|
+
// Own extends ModuleShape = {},
|
|
243
|
+
// >(config: {
|
|
244
|
+
// actionRegistry: Reg;
|
|
245
|
+
// use?: Use;
|
|
246
|
+
// define: (
|
|
247
|
+
// ctx: ModuleContext<typeof config.actionRegistry, DepWorkflows<Use>, S>,
|
|
248
|
+
// ) => Own;
|
|
249
|
+
// }): Module<Reg, S, Own, Use> {
|
|
250
|
+
// return createModule<Reg, S, Use, Own>(config);
|
|
251
|
+
// };
|
|
252
|
+
// }
|
|
253
|
+
import { createWorkflow, } from "./workflow-composer.js";
|
|
2
254
|
import { executeWorkflow } from "./workflow-executor.js";
|
|
3
255
|
function createModule(config) {
|
|
4
256
|
const deps = (config.use ?? {});
|
|
5
257
|
const wf = createWorkflow();
|
|
258
|
+
// const macro = createMacro<Reg, S, DepWorkflows<Use>>();
|
|
6
259
|
const own = config.define({
|
|
7
260
|
wf,
|
|
8
261
|
services: {},
|
|
9
262
|
});
|
|
263
|
+
// function buildWorkflowMap(): WorkflowRegistry<Own, Use> {
|
|
264
|
+
// const depWFs = Object.fromEntries(
|
|
265
|
+
// Object.entries(deps).flatMap(([name, mod]) =>
|
|
266
|
+
// Object.entries(mod.workflows).map(([k, wf]) => [`${name}.${k}`, wf]),
|
|
267
|
+
// ),
|
|
268
|
+
// );
|
|
269
|
+
//
|
|
270
|
+
// const internal = { ...own, ...depWFs } as WorkflowRegistry<Own, Use>;
|
|
271
|
+
//
|
|
272
|
+
// const publicMap = own;
|
|
273
|
+
// return { internal, publicMap };
|
|
274
|
+
// }
|
|
10
275
|
function buildWorkflowMap() {
|
|
11
276
|
const depWFs = Object.fromEntries(Object.entries(deps).flatMap(([name, mod]) => Object.entries(mod.workflows).map(([k, wf]) => [`${name}.${k}`, wf])));
|
|
12
|
-
|
|
277
|
+
// const internal = { ...own, ...depWFs } as WorkflowRegistry<Own, Use>;
|
|
278
|
+
// const exposed = Object.fromEntries(
|
|
279
|
+
// Object.entries(config.expose ?? {}).map(([alias, key]) => [
|
|
280
|
+
// alias,
|
|
281
|
+
// internal[key], // reuse already resolved workflow
|
|
282
|
+
// ]),
|
|
283
|
+
// );
|
|
284
|
+
//
|
|
285
|
+
const internalBase = { ...own, ...depWFs };
|
|
286
|
+
const exposed = {};
|
|
287
|
+
if (config.expose) {
|
|
288
|
+
for (const alias in config.expose) {
|
|
289
|
+
const key = config.expose[alias];
|
|
290
|
+
exposed[alias] = internalBase[key];
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
const internal = {
|
|
294
|
+
...internalBase,
|
|
295
|
+
...exposed,
|
|
296
|
+
};
|
|
297
|
+
// if (config.expose) {
|
|
298
|
+
// for (const alias in config.expose) {
|
|
299
|
+
// const key = config.expose[alias];
|
|
300
|
+
// exposed[alias] = internal[key];
|
|
301
|
+
// }
|
|
302
|
+
// }
|
|
303
|
+
const publicMap = { ...own, ...exposed };
|
|
304
|
+
return { internal, publicMap };
|
|
13
305
|
}
|
|
14
|
-
const
|
|
306
|
+
const { internal, publicMap } = buildWorkflowMap();
|
|
15
307
|
const depsExecutors = Object.fromEntries(Object.entries(deps).map(([name, mod]) => [name, mod.__getExecutor()]));
|
|
16
308
|
const executor = {
|
|
17
309
|
run(wfId, input, services, observers = []) {
|
|
18
|
-
|
|
310
|
+
if (!(wfId in publicMap)) {
|
|
311
|
+
throw new Error(`Workflow not in public: ${wfId}`);
|
|
312
|
+
}
|
|
313
|
+
const workflow = internal[wfId];
|
|
19
314
|
if (!workflow) {
|
|
20
315
|
throw new Error(`Workflow not found: ${String(wfId)}`);
|
|
21
316
|
}
|
|
@@ -36,7 +331,12 @@ function createModule(config) {
|
|
|
36
331
|
let runtimeActions = config.actionRegistry;
|
|
37
332
|
// const runtimeService = createServiceRegisty(services)
|
|
38
333
|
return {
|
|
39
|
-
run: async (
|
|
334
|
+
run: async (
|
|
335
|
+
// run: async <K extends keyof WorkflowRegistry<Own, Use>>(
|
|
336
|
+
workflowId, input,
|
|
337
|
+
// input: WorkflowInput<WorkflowRegistry<Own, Use>[K]>,
|
|
338
|
+
// input: WorkflowInput<WorkflowRegistry<Own, Use>[K]>,
|
|
339
|
+
observers = []) => {
|
|
40
340
|
return executor.run(workflowId, input, services, observers);
|
|
41
341
|
},
|
|
42
342
|
// make it same, practically nothing changes but naming, and what context holds
|