@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,38 +1,100 @@
1
- // import { ActionRegistry, Simplify, WorkflowObserver } from "./types.js";
1
+ // ActionRegistry,
2
+ // import {
3
+ // Executor,
4
+ // Simplify,
5
+ // WorkflowObserver,
6
+ // } from "./types.js";
2
7
  // import { createWorkflow, WorkflowDef } from "./workflow-composer.js";
3
8
  // import { executeWorkflow } from "./workflow-executor.js";
9
+ // type UnionToIntersection<U> = (U extends any ? (x: U) => any : never) extends (
10
+ // x: infer I,
11
+ // ) => any
12
+ // ? I
13
+ // : never;
14
+ // /* ------------------------------------------------ */
15
+ // /* WORKFLOW REGISTRY TYPES */
16
+ // /* ------------------------------------------------ */
17
+ // type EnsureWorkflowRecord<T> =
18
+ // T extends Record<string, WorkflowDef<any, any, any, any, any>>
19
+ // ? T
20
+ // : Record<string, WorkflowDef<any, any, any, any, any>>;
4
21
  //
5
- // type AnyWorkflow = WorkflowDef<any, any, any, any, any>;
6
- //
7
- // type WorkflowFromDeps<Deps extends Record<string, any>> = {
8
- // [K in keyof Deps]: Deps[K] extends Module<any, any, infer Own, infer SubDeps>
9
- // ? Own[keyof Own] | WorkflowFromDeps<SubDeps>
22
+ // type EnsureWorkflowShape<T> = {
23
+ // [K in keyof T]: T[K] extends WorkflowDef<any, any, any, any, any>
24
+ // ? T[K]
10
25
  // : never;
11
- // }[keyof Deps];
26
+ // };
27
+ //
28
+ // type DepWorkflows<Deps extends ModuleMap> = keyof Deps extends never
29
+ // ? {}
30
+ // : Simplify<
31
+ // EnsureWorkflowShape<
32
+ // UnionToIntersection<
33
+ // {
34
+ // [D in keyof Deps & string]: {
35
+ // [K in keyof Deps[D]["workflows"] &
36
+ // string as `${D}.${K}`]: Deps[D]["workflows"][K];
37
+ // };
38
+ // }[keyof Deps & string]
39
+ // >
40
+ // >
41
+ // >;
42
+ //
43
+ // type WorkflowRegistry<Own extends ModuleShape, Deps extends ModuleMap> = Own &
44
+ // DepWorkflows<Deps>;
45
+ //
46
+ // /* ------------------------------------------------ */
47
+ // /* MODULE TYPES */
48
+ // /* ------------------------------------------------ */
49
+ //
50
+ // type AnyWorkflow = WorkflowDef<any, any, any, any, any>;
12
51
  // type ModuleShape = Record<string, AnyWorkflow>;
52
+ // type ModuleMap = Record<string, Module<any, any, any, any>>;
13
53
  //
14
- // type ContextFromDeps<Deps> = [keyof Deps] extends [never]
15
- // ? {} // 👈 THIS is the fix
16
- // : {
17
- // [K in keyof Deps]: Deps[K] extends Module<any, infer Ctx, any, any>
18
- // ? Ctx
19
- // : never;
20
- // }[keyof Deps];
54
+ // // type ContextFromDeps<Deps> = [keyof Deps] extends [never]
55
+ // // ? {}
56
+ // // : {
57
+ // // [K in keyof Deps]: Deps[K] extends Module<any, infer Ctx, any, any>
58
+ // // ? Ctx
59
+ // // : never;
60
+ // // }[keyof Deps];
21
61
  //
22
62
  // type FinalContext<
23
- // Reg extends ActionRegistry,
24
63
  // Context extends Record<string, any>,
25
- // Deps extends ModuleMap<Reg>,
26
- // > = Context & ContextFromDeps<Deps>;
64
+ // Deps extends ModuleMap,
65
+ // > = Context & ContextFromDepsRecursive<Deps>;
66
+ //
67
+ // // type ContextFromDeps<Deps> = [keyof Deps] extends [never]
68
+ // // ? {}
69
+ // // : UnionToIntersection<
70
+ // // {
71
+ // // [K in keyof Deps]: Deps[K] extends Module<any, infer Ctx, any, any>
72
+ // // ? Ctx
73
+ // // : never;
74
+ // // }[keyof Deps]
75
+ // // >;
76
+ //
77
+ // type ContextFromDepsRecursive<Deps extends ModuleMap> = [keyof Deps] extends [
78
+ // never,
79
+ // ]
80
+ // ? {} // no deps
81
+ // : UnionToIntersection<
82
+ // {
83
+ // [K in keyof Deps]: Deps[K] extends Module<
84
+ // any,
85
+ // infer Ctx,
86
+ // any,
87
+ // infer SubDeps
88
+ // >
89
+ // ? Ctx & ContextFromDepsRecursive<SubDeps>
90
+ // : never;
91
+ // }[keyof Deps]
92
+ // >;
27
93
  //
28
- // type ModuleMap<Reg extends ActionRegistry> = Record<
29
- // string,
30
- // Module<Reg, any, any, any>
31
- // >;
94
+ // /* ------------------------------------------------ */
95
+ // /* WORKFLOW IO TYPES */
96
+ // /* ------------------------------------------------ */
32
97
  //
33
- // // type Module<Own extends ModuleShape = {}, Deps extends ModuleMap = {}> = Own & {
34
- // // deps: Deps;
35
- // // };
36
98
  // export type WorkflowInput<W> =
37
99
  // W extends WorkflowDef<any, infer I, any, any, any> ? I : never;
38
100
  //
@@ -41,134 +103,207 @@
41
103
  //
42
104
  // export type WorkflowOutput<W> =
43
105
  // W extends WorkflowDef<any, any, any, any, infer O> ? O : never;
106
+ //
107
+ // /* ------------------------------------------------ */
108
+ // /* MODULE RUNTIME */
109
+ // /* ------------------------------------------------ */
110
+ //
44
111
  // type Module<
45
112
  // Reg extends ActionRegistry,
46
113
  // Context extends Record<string, any>,
47
- // Own extends ModuleShape = {},
48
- // Deps extends ModuleMap<Reg> = {},
114
+ // Own extends ModuleShape,
115
+ // Deps extends ModuleMap,
49
116
  // > = {
50
- // own: Own;
51
- // deps: Deps;
52
- // createRuntime: (config: {
53
- // registry: Reg;
54
- // context: FinalContext<Reg, Context, Deps>;
55
- // }) => {
56
- // run: <W extends Own[keyof Own] | WorkflowFromDeps<Deps>>(
57
- // workflow: W,
58
- // input: WorkflowInput<W>,
59
- // obververs?: WorkflowObserver<Reg>[],
117
+ // workflows: Own;
118
+ // __getExecutor: () => Executor;
119
+ //
120
+ // createRuntime: (config: { context: FinalContext<Context, Deps> }) => {
121
+ // run: <K extends keyof WorkflowRegistry<Own, Deps>>(
122
+ // workflow: K,
123
+ // input: WorkflowInput<WorkflowRegistry<Own, Deps>[K]>,
124
+ // observers?: WorkflowObserver<Reg>[],
60
125
  // ) => Promise<{
61
- // results: WorkflowResults<W>;
62
- // output: WorkflowOutput<W>;
126
+ // // results: WorkflowResults<WorkflowRegistry<Own, Deps>[K]>;
127
+ // output: WorkflowOutput<WorkflowRegistry<Own, Deps>[K]>;
63
128
  // extras: Record<string, any>;
64
129
  // }>;
65
- // getContext: () => FinalContext<Reg, Context, Deps>;
130
+ //
131
+ // getContext: () => FinalContext<Context, Deps>;
66
132
  // };
67
133
  // };
68
134
  //
69
- // export type ModuleContext<
135
+ // /* ------------------------------------------------ */
136
+ // /* MODULE CONTEXT (FIXED) */
137
+ // /* ------------------------------------------------ */
138
+ //
139
+ // type ModuleContext<
70
140
  // Reg extends ActionRegistry,
141
+ // WFReg extends Record<string, WorkflowDef<any, any, any, any, any>>,
71
142
  // Context extends Record<string, any>,
72
- // Deps extends ModuleMap<Reg>,
73
143
  // > = {
74
- // wf: ReturnType<typeof createWorkflow<Reg, Context>>;
75
- //
76
- // deps: Deps;
144
+ // wf: ReturnType<typeof createWorkflow<Reg, WFReg, Context>>;
77
145
  // context: Context;
78
- //
79
- // tools: <T>(
80
- // factory: (ctx: {
81
- // wf: ModuleContext<Reg, Context, Deps>["wf"];
82
- // deps: Deps;
83
- // context: Context;
84
- // }) => T,
85
- // ) => T;
86
146
  // };
87
147
  //
88
148
  // function createModule<
89
149
  // Reg extends ActionRegistry,
90
150
  // Context extends Record<string, any>,
91
- // Use extends ModuleMap<Reg>,
151
+ // Use extends ModuleMap,
92
152
  // Own extends ModuleShape,
93
153
  // >(config: {
154
+ // actionRegistry: Reg;
94
155
  // use?: Use;
95
- // define: (ctx: ModuleContext<Reg, Context, Use>) => Own;
156
+ // define: (ctx: ModuleContext<Reg, DepWorkflows<Use>, Context>) => Own;
96
157
  // }): Module<Reg, Context, Own, Use> {
97
- // const wf = createWorkflow<Reg, Context>();
98
- //
99
158
  // const deps = (config.use ?? {}) as Use;
100
159
  //
101
- // const moduleCtx: ModuleContext<Reg, Context, Use> = {
160
+ // const wf = createWorkflow<Reg, DepWorkflows<Use>, Context>();
161
+ //
162
+ // const own = config.define({
102
163
  // wf,
103
- // deps,
104
164
  // context: {} as Context,
165
+ // });
105
166
  //
106
- // tools: (factory) =>
107
- // factory({
108
- // wf,
109
- // deps,
110
- // context: {} as Context,
111
- // }),
112
- // };
167
+ // function buildWorkflowMap(): WorkflowRegistry<Own, Use> {
168
+ // const depWFs = Object.fromEntries(
169
+ // Object.entries(deps).flatMap(([name, mod]) =>
170
+ // Object.entries(mod.workflows).map(([k, wf]) => [`${name}.${k}`, wf]),
171
+ // ),
172
+ // );
173
+ //
174
+ // return { ...own, ...depWFs } as WorkflowRegistry<Own, Use>;
175
+ // }
176
+ //
177
+ // const workflowMap = buildWorkflowMap();
178
+ //
179
+ // const depsExecutors = Object.fromEntries(
180
+ // Object.entries(deps).map(([name, mod]) => [name, mod.__getExecutor()]),
181
+ // );
182
+ //
183
+ // const executor: Executor = {
184
+ // run(wfId, input, context, observers = []) {
185
+ // const workflow = workflowMap[wfId];
113
186
  //
114
- // const own = config.define(moduleCtx);
187
+ // if (!workflow) {
188
+ // throw new Error(`Workflow not found: ${String(wfId)}`);
189
+ // }
190
+ //
191
+ // return executeWorkflow({
192
+ // workflow,
193
+ // actionRegistry: config.actionRegistry,
194
+ // depsExecutors,
195
+ // input,
196
+ // context,
197
+ // observers,
198
+ // });
199
+ // },
200
+ // };
115
201
  //
116
202
  // return {
117
- // own,
118
- // deps,
119
- // createRuntime({ registry, context }) {
120
- // const runtimeCtx = { ...context } as FinalContext<Reg, Context, Use>;
203
+ // workflows: own,
204
+ // __getExecutor: () => executor,
205
+ //
206
+ // createRuntime({ services }) {
207
+ // let runtimeActions = config.actionRegistry;
208
+ //
209
+ // // const runtimeService = createServiceRegisty(services)
121
210
  // return {
122
- // run: async (workflow, input, observers = []) => {
123
- // return executeWorkflow(workflow, registry, input, context, observers);
211
+ // run: async <K extends keyof WorkflowRegistry<Own, Use>>(
212
+ // workflowId: K,
213
+ // input: WorkflowInput<WorkflowRegistry<Own, Use>[K]>,
214
+ // observers: WorkflowObserver<Reg>[] = [],
215
+ // ) => {
216
+ // return executor.run(workflowId as string, input, context, observers);
217
+ // },
218
+ // // make it same, practically nothing changes but naming, and what context holds
219
+ // getContext: () => ({ ...context }) as FinalContext<Context, Use>,
220
+ //
221
+ // setActionRegistry(reg: Reg) {
222
+ // runtimeActions = reg;
223
+ // // ⚠️ optional: if you REALLY want override, you'd need:
224
+ // // executor.actions = reg
225
+ // // but better keep actions immutable
124
226
  // },
125
- // getContext: () => ({ ...runtimeCtx }),
126
227
  // };
127
228
  // },
128
229
  // };
129
230
  // }
130
231
  //
232
+ // /* ------------------------------------------------ */
233
+ // /* FACTORY (FIXED) */
234
+ // /* ------------------------------------------------ */
235
+ //
131
236
  // export function createModuleFactory<
132
- // Reg extends ActionRegistry,
237
+ // // Reg extends ActionRegistry,
133
238
  // Context extends Record<string, any>,
134
239
  // >() {
135
240
  // return function <
136
- // Use extends ModuleMap<Reg> = {},
241
+ // Reg extends ActionRegistry = Record<string, any>,
242
+ // Use extends ModuleMap = {},
137
243
  // Own extends ModuleShape = {},
138
244
  // >(config: {
245
+ // actionRegistry: Reg;
139
246
  // use?: Use;
140
- // define: (ctx: ModuleContext<Reg, Context, Use>) => Own;
247
+ // define: (
248
+ // ctx: ModuleContext<
249
+ // typeof config.actionRegistry,
250
+ // DepWorkflows<Use>,
251
+ // Context
252
+ // >, // ✅ FIXED HERE
253
+ // ) => Own;
141
254
  // }): Module<Reg, Context, Own, Use> {
142
255
  // return createModule<Reg, Context, Use, Own>(config);
143
256
  // };
144
257
  // }
145
- //
146
258
  import { createWorkflow } from "./workflow-composer.js";
147
259
  import { executeWorkflow } from "./workflow-executor.js";
148
- /* ------------------------------------------------ */
149
- /* CREATE MODULE (FIXED) */
150
- /* ------------------------------------------------ */
151
260
  function createModule(config) {
152
261
  const deps = (config.use ?? {});
153
- // ✅ CRITICAL: wf only sees DEP workflows
154
262
  const wf = createWorkflow();
155
263
  const own = config.define({
156
264
  wf,
157
- context: {},
265
+ services: {},
158
266
  });
159
- function buildRegistry() {
267
+ function buildWorkflowMap() {
160
268
  const depWFs = Object.fromEntries(Object.entries(deps).flatMap(([name, mod]) => Object.entries(mod.workflows).map(([k, wf]) => [`${name}.${k}`, wf])));
161
269
  return { ...own, ...depWFs };
162
270
  }
271
+ const workflowMap = buildWorkflowMap();
272
+ const depsExecutors = Object.fromEntries(Object.entries(deps).map(([name, mod]) => [name, mod.__getExecutor()]));
273
+ const executor = {
274
+ run(wfId, input, services, observers = []) {
275
+ const workflow = workflowMap[wfId];
276
+ if (!workflow) {
277
+ throw new Error(`Workflow not found: ${String(wfId)}`);
278
+ }
279
+ return executeWorkflow({
280
+ workflow,
281
+ actionRegistry: config.actionRegistry,
282
+ depsExecutors,
283
+ input,
284
+ services,
285
+ observers,
286
+ });
287
+ },
288
+ };
163
289
  return {
164
290
  workflows: own,
165
- createRuntime({ registry, context }) {
166
- const workflowRegistry = buildRegistry();
291
+ __getExecutor: () => executor,
292
+ createRuntime({ services }) {
293
+ let runtimeActions = config.actionRegistry;
294
+ // const runtimeService = createServiceRegisty(services)
167
295
  return {
168
296
  run: async (workflowId, input, observers = []) => {
169
- return executeWorkflow(workflowId, workflowRegistry, registry, input, context, observers);
297
+ return executor.run(workflowId, input, services, observers);
298
+ },
299
+ // make it same, practically nothing changes but naming, and what context holds
300
+ getServices: () => ({ ...services }),
301
+ setActionRegistry(reg) {
302
+ runtimeActions = reg;
303
+ // ⚠️ optional: if you REALLY want override, you'd need:
304
+ // executor.actions = reg
305
+ // but better keep actions immutable
170
306
  },
171
- getContext: () => ({ ...context }),
172
307
  };
173
308
  },
174
309
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pogodisco/zephyr",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -33,6 +33,8 @@
33
33
  "prepublishOnly": "npm run build",
34
34
  "build": "tsc -p tsconfig.build.json",
35
35
  "dev": "tsc -w -p tsconfig.json",
36
+ "test": "vitest",
37
+ "test:run": "vitest run",
36
38
  "test:types": "tsd"
37
39
  },
38
40
  "tsd": {
@@ -45,6 +47,7 @@
45
47
  "@types/node": "^25.2.3",
46
48
  "chalk": "^5.6.2",
47
49
  "pretty-format": "^30.2.0",
48
- "tsd": "^0.33.0"
50
+ "tsd": "^0.33.0",
51
+ "vitest": "^4.1.2"
49
52
  }
50
53
  }