@db-lyon/flowkit 0.1.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.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/dist/config/deep-merge.d.ts +11 -0
  3. package/dist/config/deep-merge.d.ts.map +1 -0
  4. package/dist/config/deep-merge.js +39 -0
  5. package/dist/config/deep-merge.js.map +1 -0
  6. package/dist/config/index.d.ts +6 -0
  7. package/dist/config/index.d.ts.map +1 -0
  8. package/dist/config/index.js +4 -0
  9. package/dist/config/index.js.map +1 -0
  10. package/dist/config/loader.d.ts +33 -0
  11. package/dist/config/loader.d.ts.map +1 -0
  12. package/dist/config/loader.js +58 -0
  13. package/dist/config/loader.js.map +1 -0
  14. package/dist/config/schema.d.ts +170 -0
  15. package/dist/config/schema.d.ts.map +1 -0
  16. package/dist/config/schema.js +29 -0
  17. package/dist/config/schema.js.map +1 -0
  18. package/dist/dag/index.d.ts +3 -0
  19. package/dist/dag/index.d.ts.map +1 -0
  20. package/dist/dag/index.js +2 -0
  21. package/dist/dag/index.js.map +1 -0
  22. package/dist/dag/resolver.d.ts +17 -0
  23. package/dist/dag/resolver.d.ts.map +1 -0
  24. package/dist/dag/resolver.js +57 -0
  25. package/dist/dag/resolver.js.map +1 -0
  26. package/dist/flow/index.d.ts +3 -0
  27. package/dist/flow/index.d.ts.map +1 -0
  28. package/dist/flow/index.js +2 -0
  29. package/dist/flow/index.js.map +1 -0
  30. package/dist/flow/runner.d.ts +68 -0
  31. package/dist/flow/runner.d.ts.map +1 -0
  32. package/dist/flow/runner.js +184 -0
  33. package/dist/flow/runner.js.map +1 -0
  34. package/dist/index.d.ts +16 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +13 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/logger.d.ts +9 -0
  39. package/dist/logger.d.ts.map +1 -0
  40. package/dist/logger.js +10 -0
  41. package/dist/logger.js.map +1 -0
  42. package/dist/task/base-task.d.ts +27 -0
  43. package/dist/task/base-task.d.ts.map +1 -0
  44. package/dist/task/base-task.js +39 -0
  45. package/dist/task/base-task.js.map +1 -0
  46. package/dist/task/index.d.ts +5 -0
  47. package/dist/task/index.d.ts.map +1 -0
  48. package/dist/task/index.js +3 -0
  49. package/dist/task/index.js.map +1 -0
  50. package/dist/task/registry.d.ts +27 -0
  51. package/dist/task/registry.d.ts.map +1 -0
  52. package/dist/task/registry.js +95 -0
  53. package/dist/task/registry.js.map +1 -0
  54. package/package.json +51 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 David Lyon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Deep-merges two values:
3
+ *
4
+ * - Objects: recursive key-by-key merge (override wins per-key)
5
+ * - Arrays: replace by default; `__merge: 'append'` on the override array concatenates
6
+ * - Scalars: override wins
7
+ * - `null` override: explicitly nullifies
8
+ * - `undefined` override: no-op (base preserved)
9
+ */
10
+ export declare function deepMerge(base: unknown, override: unknown): unknown;
11
+ //# sourceMappingURL=deep-merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deep-merge.d.ts","sourceRoot":"","sources":["../../src/config/deep-merge.ts"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CA2BnE"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Deep-merges two values:
3
+ *
4
+ * - Objects: recursive key-by-key merge (override wins per-key)
5
+ * - Arrays: replace by default; `__merge: 'append'` on the override array concatenates
6
+ * - Scalars: override wins
7
+ * - `null` override: explicitly nullifies
8
+ * - `undefined` override: no-op (base preserved)
9
+ */
10
+ export function deepMerge(base, override) {
11
+ if (override === undefined)
12
+ return base;
13
+ if (override === null)
14
+ return null;
15
+ if (Array.isArray(override)) {
16
+ if (Array.isArray(base)) {
17
+ const annotation = override.__merge;
18
+ if (annotation === 'append') {
19
+ const cleaned = override.filter((item) => typeof item !== 'object' || !item.__merge);
20
+ return [...base, ...cleaned];
21
+ }
22
+ }
23
+ return override;
24
+ }
25
+ if (isPlainObject(base) && isPlainObject(override)) {
26
+ const result = { ...base };
27
+ for (const key of Object.keys(override)) {
28
+ if (key === '__merge')
29
+ continue;
30
+ result[key] = deepMerge(result[key], override[key]);
31
+ }
32
+ return result;
33
+ }
34
+ return override;
35
+ }
36
+ function isPlainObject(value) {
37
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
38
+ }
39
+ //# sourceMappingURL=deep-merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deep-merge.js","sourceRoot":"","sources":["../../src/config/deep-merge.ts"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS,CAAC,IAAa,EAAE,QAAiB;IACxD,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEnC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,UAAU,GAAI,QAAsC,CAAC,OAAO,CAAC;YACnE,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;gBAC5B,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAC7B,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAE,IAAuB,CAAC,OAAO,CACxE,CAAC;gBACF,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnD,MAAM,MAAM,GAA4B,EAAE,GAAG,IAAI,EAAE,CAAC;QACpD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxC,IAAI,GAAG,KAAK,SAAS;gBAAE,SAAS;YAChC,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,EAAG,QAAoC,CAAC,GAAG,CAAC,CAAC,CAAC;QACnF,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { deepMerge } from './deep-merge.js';
2
+ export { TaskOptionsSchema, TaskDefinitionSchema, FlowStepSchema, FlowDefinitionSchema, EngineConfigSchema, } from './schema.js';
3
+ export type { TaskOptions, TaskDefinition, FlowStep, FlowDefinition, EngineConfig, } from './schema.js';
4
+ export { loadConfig, loadRawYaml, findConfigFile } from './loader.js';
5
+ export type { LoadConfigOptions, LoadedConfig } from './loader.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,WAAW,EACX,cAAc,EACd,QAAQ,EACR,cAAc,EACd,YAAY,GACb,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACtE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { deepMerge } from './deep-merge.js';
2
+ export { TaskOptionsSchema, TaskDefinitionSchema, FlowStepSchema, FlowDefinitionSchema, EngineConfigSchema, } from './schema.js';
3
+ export { loadConfig, loadRawYaml, findConfigFile } from './loader.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAUrB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { z } from 'zod';
2
+ /**
3
+ * Walk up parent directories looking for `filename`.
4
+ */
5
+ export declare function findConfigFile(filename: string, startDir?: string): string;
6
+ export declare function loadRawYaml(filePath: string): unknown;
7
+ export interface LoadConfigOptions<T extends z.ZodType> {
8
+ /** Primary config filename, e.g. `'myapp.yml'` */
9
+ filename: string;
10
+ /** Zod schema — applied after all layers are merged */
11
+ schema: T;
12
+ /** Builtin defaults merged under the project file */
13
+ defaults?: unknown;
14
+ /** Environment name — loads `{base}.{env}.{ext}` overlay */
15
+ env?: string;
16
+ /** Env var to read environment name from when `env` is not passed */
17
+ envVar?: string;
18
+ /** Directory to search for config files (default: cwd) */
19
+ configDir?: string;
20
+ }
21
+ export interface LoadedConfig<T> {
22
+ config: T;
23
+ configDir: string;
24
+ }
25
+ /**
26
+ * Layered config loader:
27
+ *
28
+ * defaults → {filename} → {base}.{env}.{ext} → {base}.local.{ext}
29
+ *
30
+ * Each layer is deep-merged left-to-right, then validated through the Zod schema.
31
+ */
32
+ export declare function loadConfig<T extends z.ZodType>(options: LoadConfigOptions<T>): LoadedConfig<z.infer<T>>;
33
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAG7B;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAW1E;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGrD;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO;IACpD,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,MAAM,EAAE,CAAC,CAAC;IACV,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,MAAM,EAAE,CAAC,CAAC;IACV,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAC5C,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC5B,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAiC1B"}
@@ -0,0 +1,58 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as yaml from 'js-yaml';
4
+ import { deepMerge } from './deep-merge.js';
5
+ /**
6
+ * Walk up parent directories looking for `filename`.
7
+ */
8
+ export function findConfigFile(filename, startDir) {
9
+ let dir = startDir ?? process.cwd();
10
+ const root = path.parse(dir).root;
11
+ while (dir !== root) {
12
+ const candidate = path.join(dir, filename);
13
+ if (fs.existsSync(candidate))
14
+ return candidate;
15
+ dir = path.dirname(dir);
16
+ }
17
+ throw new Error(`Could not find ${filename} in any parent directory`);
18
+ }
19
+ export function loadRawYaml(filePath) {
20
+ const content = fs.readFileSync(filePath, 'utf8');
21
+ return yaml.load(content);
22
+ }
23
+ /**
24
+ * Layered config loader:
25
+ *
26
+ * defaults → {filename} → {base}.{env}.{ext} → {base}.local.{ext}
27
+ *
28
+ * Each layer is deep-merged left-to-right, then validated through the Zod schema.
29
+ */
30
+ export function loadConfig(options) {
31
+ const configDir = options.configDir ?? process.cwd();
32
+ const ext = path.extname(options.filename);
33
+ const base = path.basename(options.filename, ext);
34
+ const rootPath = path.join(configDir, options.filename);
35
+ if (!fs.existsSync(rootPath)) {
36
+ throw new Error(`Configuration file not found: ${rootPath}`);
37
+ }
38
+ // Layer 1: builtin defaults
39
+ let config = options.defaults ?? {};
40
+ // Layer 2: project file
41
+ const projectConfig = loadRawYaml(rootPath);
42
+ config = deepMerge(config, projectConfig);
43
+ // Layer 3: environment overlay
44
+ const env = options.env ?? (options.envVar ? process.env[options.envVar] : undefined);
45
+ if (env) {
46
+ const envPath = path.join(configDir, `${base}.${env}${ext}`);
47
+ if (fs.existsSync(envPath)) {
48
+ config = deepMerge(config, loadRawYaml(envPath));
49
+ }
50
+ }
51
+ // Layer 4: local overrides (never committed)
52
+ const localPath = path.join(configDir, `${base}.local${ext}`);
53
+ if (fs.existsSync(localPath)) {
54
+ config = deepMerge(config, loadRawYaml(localPath));
55
+ }
56
+ return { config: options.schema.parse(config), configDir };
57
+ }
58
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,170 @@
1
+ import { z } from 'zod';
2
+ export declare const TaskOptionsSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
3
+ export declare const TaskDefinitionSchema: z.ZodObject<{
4
+ class_path: z.ZodString;
5
+ description: z.ZodOptional<z.ZodString>;
6
+ group: z.ZodOptional<z.ZodString>;
7
+ options: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ options: Record<string, unknown>;
10
+ class_path: string;
11
+ description?: string | undefined;
12
+ group?: string | undefined;
13
+ }, {
14
+ class_path: string;
15
+ options?: Record<string, unknown> | undefined;
16
+ description?: string | undefined;
17
+ group?: string | undefined;
18
+ }>;
19
+ export declare const FlowStepSchema: z.ZodEffects<z.ZodObject<{
20
+ task: z.ZodOptional<z.ZodString>;
21
+ flow: z.ZodOptional<z.ZodString>;
22
+ options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
23
+ }, "strip", z.ZodTypeAny, {
24
+ options?: Record<string, unknown> | undefined;
25
+ task?: string | undefined;
26
+ flow?: string | undefined;
27
+ }, {
28
+ options?: Record<string, unknown> | undefined;
29
+ task?: string | undefined;
30
+ flow?: string | undefined;
31
+ }>, {
32
+ options?: Record<string, unknown> | undefined;
33
+ task?: string | undefined;
34
+ flow?: string | undefined;
35
+ }, {
36
+ options?: Record<string, unknown> | undefined;
37
+ task?: string | undefined;
38
+ flow?: string | undefined;
39
+ }>;
40
+ export declare const FlowDefinitionSchema: z.ZodObject<{
41
+ description: z.ZodString;
42
+ steps: z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodObject<{
43
+ task: z.ZodOptional<z.ZodString>;
44
+ flow: z.ZodOptional<z.ZodString>;
45
+ options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
46
+ }, "strip", z.ZodTypeAny, {
47
+ options?: Record<string, unknown> | undefined;
48
+ task?: string | undefined;
49
+ flow?: string | undefined;
50
+ }, {
51
+ options?: Record<string, unknown> | undefined;
52
+ task?: string | undefined;
53
+ flow?: string | undefined;
54
+ }>, {
55
+ options?: Record<string, unknown> | undefined;
56
+ task?: string | undefined;
57
+ flow?: string | undefined;
58
+ }, {
59
+ options?: Record<string, unknown> | undefined;
60
+ task?: string | undefined;
61
+ flow?: string | undefined;
62
+ }>>;
63
+ }, "strip", z.ZodTypeAny, {
64
+ description: string;
65
+ steps: Record<string, {
66
+ options?: Record<string, unknown> | undefined;
67
+ task?: string | undefined;
68
+ flow?: string | undefined;
69
+ }>;
70
+ }, {
71
+ description: string;
72
+ steps: Record<string, {
73
+ options?: Record<string, unknown> | undefined;
74
+ task?: string | undefined;
75
+ flow?: string | undefined;
76
+ }>;
77
+ }>;
78
+ /** Minimal config shape the engine requires. Consumers extend with their own sections. */
79
+ export declare const EngineConfigSchema: z.ZodObject<{
80
+ tasks: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
81
+ class_path: z.ZodString;
82
+ description: z.ZodOptional<z.ZodString>;
83
+ group: z.ZodOptional<z.ZodString>;
84
+ options: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
85
+ }, "strip", z.ZodTypeAny, {
86
+ options: Record<string, unknown>;
87
+ class_path: string;
88
+ description?: string | undefined;
89
+ group?: string | undefined;
90
+ }, {
91
+ class_path: string;
92
+ options?: Record<string, unknown> | undefined;
93
+ description?: string | undefined;
94
+ group?: string | undefined;
95
+ }>>>;
96
+ flows: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
97
+ description: z.ZodString;
98
+ steps: z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodObject<{
99
+ task: z.ZodOptional<z.ZodString>;
100
+ flow: z.ZodOptional<z.ZodString>;
101
+ options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
102
+ }, "strip", z.ZodTypeAny, {
103
+ options?: Record<string, unknown> | undefined;
104
+ task?: string | undefined;
105
+ flow?: string | undefined;
106
+ }, {
107
+ options?: Record<string, unknown> | undefined;
108
+ task?: string | undefined;
109
+ flow?: string | undefined;
110
+ }>, {
111
+ options?: Record<string, unknown> | undefined;
112
+ task?: string | undefined;
113
+ flow?: string | undefined;
114
+ }, {
115
+ options?: Record<string, unknown> | undefined;
116
+ task?: string | undefined;
117
+ flow?: string | undefined;
118
+ }>>;
119
+ }, "strip", z.ZodTypeAny, {
120
+ description: string;
121
+ steps: Record<string, {
122
+ options?: Record<string, unknown> | undefined;
123
+ task?: string | undefined;
124
+ flow?: string | undefined;
125
+ }>;
126
+ }, {
127
+ description: string;
128
+ steps: Record<string, {
129
+ options?: Record<string, unknown> | undefined;
130
+ task?: string | undefined;
131
+ flow?: string | undefined;
132
+ }>;
133
+ }>>>;
134
+ }, "strip", z.ZodTypeAny, {
135
+ tasks: Record<string, {
136
+ options: Record<string, unknown>;
137
+ class_path: string;
138
+ description?: string | undefined;
139
+ group?: string | undefined;
140
+ }>;
141
+ flows: Record<string, {
142
+ description: string;
143
+ steps: Record<string, {
144
+ options?: Record<string, unknown> | undefined;
145
+ task?: string | undefined;
146
+ flow?: string | undefined;
147
+ }>;
148
+ }>;
149
+ }, {
150
+ tasks?: Record<string, {
151
+ class_path: string;
152
+ options?: Record<string, unknown> | undefined;
153
+ description?: string | undefined;
154
+ group?: string | undefined;
155
+ }> | undefined;
156
+ flows?: Record<string, {
157
+ description: string;
158
+ steps: Record<string, {
159
+ options?: Record<string, unknown> | undefined;
160
+ task?: string | undefined;
161
+ flow?: string | undefined;
162
+ }>;
163
+ }> | undefined;
164
+ }>;
165
+ export type TaskOptions = z.infer<typeof TaskOptionsSchema>;
166
+ export type TaskDefinition = z.infer<typeof TaskDefinitionSchema>;
167
+ export type FlowStep = z.infer<typeof FlowStepSchema>;
168
+ export type FlowDefinition = z.infer<typeof FlowDefinitionSchema>;
169
+ export type EngineConfig = z.infer<typeof EngineConfigSchema>;
170
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,iBAAiB,wCAAwB,CAAC;AAEvD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;EAK/B,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;EAYxB,CAAC;AAEJ,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAG/B,CAAC;AAEH,0FAA0F;AAC1F,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAG7B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AACtD,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ export const TaskOptionsSchema = z.record(z.unknown());
3
+ export const TaskDefinitionSchema = z.object({
4
+ class_path: z.string().min(1),
5
+ description: z.string().optional(),
6
+ group: z.string().optional(),
7
+ options: TaskOptionsSchema.optional().default({}),
8
+ });
9
+ export const FlowStepSchema = z
10
+ .object({
11
+ task: z.string().optional(),
12
+ flow: z.string().optional(),
13
+ options: TaskOptionsSchema.optional(),
14
+ })
15
+ .refine((data) => {
16
+ if (data.task === 'None')
17
+ return true;
18
+ return (data.task && !data.flow) || (!data.task && data.flow);
19
+ }, { message: 'Step must have exactly one of task or flow (or task: None to skip)' });
20
+ export const FlowDefinitionSchema = z.object({
21
+ description: z.string(),
22
+ steps: z.record(z.coerce.string(), FlowStepSchema),
23
+ });
24
+ /** Minimal config shape the engine requires. Consumers extend with their own sections. */
25
+ export const EngineConfigSchema = z.object({
26
+ tasks: z.record(TaskDefinitionSchema).default({}),
27
+ flows: z.record(FlowDefinitionSchema).default({}),
28
+ });
29
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AAEvD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,OAAO,EAAE,iBAAiB,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CAClD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC;KAC5B,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,OAAO,EAAE,iBAAiB,CAAC,QAAQ,EAAE;CACtC,CAAC;KACD,MAAM,CACL,CAAC,IAAI,EAAE,EAAE;IACP,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;AAChE,CAAC,EACD,EAAE,OAAO,EAAE,oEAAoE,EAAE,CAClF,CAAC;AAEJ,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC;CACnD,CAAC,CAAC;AAEH,0FAA0F;AAC1F,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACjD,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CAClD,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { topologicalSort, CircularDependencyError, MissingDependencyError, } from './resolver.js';
2
+ export type { DagNode } from './resolver.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dag/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { topologicalSort, CircularDependencyError, MissingDependencyError, } from './resolver.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dag/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface DagNode<T = unknown> {
2
+ id: string;
3
+ dependencies: string[];
4
+ data: T;
5
+ }
6
+ export declare class CircularDependencyError extends Error {
7
+ readonly cycle: string[];
8
+ constructor(cycle: string[]);
9
+ }
10
+ export declare class MissingDependencyError extends Error {
11
+ readonly nodeId: string;
12
+ readonly missingDep: string;
13
+ constructor(nodeId: string, missingDep: string);
14
+ }
15
+ /** Topological sort — returns nodes in dependency order (dependencies first). */
16
+ export declare function topologicalSort<T>(nodes: DagNode<T>[]): DagNode<T>[];
17
+ //# sourceMappingURL=resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/dag/resolver.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO,CAAC,CAAC,GAAG,OAAO;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC;CACT;AAED,qBAAa,uBAAwB,SAAQ,KAAK;aACpB,KAAK,EAAE,MAAM,EAAE;gBAAf,KAAK,EAAE,MAAM,EAAE;CAI5C;AAED,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,MAAM,EAAE,MAAM;aACd,UAAU,EAAE,MAAM;gBADlB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM;CAKrC;AAED,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CA4CpE"}
@@ -0,0 +1,57 @@
1
+ export class CircularDependencyError extends Error {
2
+ cycle;
3
+ constructor(cycle) {
4
+ super(`Circular dependency detected: ${cycle.join(' -> ')}`);
5
+ this.cycle = cycle;
6
+ this.name = 'CircularDependencyError';
7
+ }
8
+ }
9
+ export class MissingDependencyError extends Error {
10
+ nodeId;
11
+ missingDep;
12
+ constructor(nodeId, missingDep) {
13
+ super(`Node "${nodeId}" depends on "${missingDep}" which does not exist`);
14
+ this.nodeId = nodeId;
15
+ this.missingDep = missingDep;
16
+ this.name = 'MissingDependencyError';
17
+ }
18
+ }
19
+ /** Topological sort — returns nodes in dependency order (dependencies first). */
20
+ export function topologicalSort(nodes) {
21
+ const nodeMap = new Map();
22
+ for (const node of nodes) {
23
+ nodeMap.set(node.id, node);
24
+ }
25
+ for (const node of nodes) {
26
+ for (const dep of node.dependencies) {
27
+ if (!nodeMap.has(dep)) {
28
+ throw new MissingDependencyError(node.id, dep);
29
+ }
30
+ }
31
+ }
32
+ const visited = new Set();
33
+ const visiting = new Set();
34
+ const sorted = [];
35
+ function visit(nodeId, path) {
36
+ if (visited.has(nodeId))
37
+ return;
38
+ if (visiting.has(nodeId)) {
39
+ const cycleStart = path.indexOf(nodeId);
40
+ throw new CircularDependencyError([...path.slice(cycleStart), nodeId]);
41
+ }
42
+ visiting.add(nodeId);
43
+ path.push(nodeId);
44
+ const node = nodeMap.get(nodeId);
45
+ for (const dep of node.dependencies) {
46
+ visit(dep, [...path]);
47
+ }
48
+ visiting.delete(nodeId);
49
+ visited.add(nodeId);
50
+ sorted.push(node);
51
+ }
52
+ for (const node of nodes) {
53
+ visit(node.id, []);
54
+ }
55
+ return sorted;
56
+ }
57
+ //# sourceMappingURL=resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/dag/resolver.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACpB;IAA5B,YAA4B,KAAe;QACzC,KAAK,CAAC,iCAAiC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QADnC,UAAK,GAAL,KAAK,CAAU;QAEzC,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAE7B;IACA;IAFlB,YACkB,MAAc,EACd,UAAkB;QAElC,KAAK,CAAC,SAAS,MAAM,iBAAiB,UAAU,wBAAwB,CAAC,CAAC;QAH1D,WAAM,GAAN,MAAM,CAAQ;QACd,eAAU,GAAV,UAAU,CAAQ;QAGlC,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED,iFAAiF;AACjF,MAAM,UAAU,eAAe,CAAI,KAAmB;IACpD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACpC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,IAAI,sBAAsB,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAEhC,SAAS,KAAK,CAAC,MAAc,EAAE,IAAc;QAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO;QAEhC,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACzB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACxC,MAAM,IAAI,uBAAuB,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QACzE,CAAC;QAED,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAElB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC;QAClC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACpC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QACxB,CAAC;QAED,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { FlowRunner } from './runner.js';
2
+ export type { FlowRunOptions, FlowStepResult, FlowRunResult, FlowRunnerHooks, FlowRunnerConfig, PlanStep, } from './runner.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/flow/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,YAAY,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,QAAQ,GACT,MAAM,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { FlowRunner } from './runner.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/flow/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,68 @@
1
+ import type { Logger } from '../logger.js';
2
+ import type { TaskDefinition, FlowDefinition } from '../config/schema.js';
3
+ import type { TaskResult } from '../task/base-task.js';
4
+ import type { TaskContext } from '../task/base-task.js';
5
+ import type { TaskRegistry } from '../task/registry.js';
6
+ export interface FlowRunOptions {
7
+ flowName: string;
8
+ skip?: string[];
9
+ plan?: boolean;
10
+ }
11
+ export interface FlowStepResult {
12
+ stepNumber: number;
13
+ type: 'task' | 'flow';
14
+ name: string;
15
+ result?: TaskResult;
16
+ skipped: boolean;
17
+ duration: number;
18
+ }
19
+ export interface FlowRunResult {
20
+ success: boolean;
21
+ steps: FlowStepResult[];
22
+ duration: number;
23
+ error?: Error;
24
+ }
25
+ export interface PlanStep {
26
+ stepNumber: number;
27
+ type: 'task' | 'flow';
28
+ name: string;
29
+ skipped: boolean;
30
+ options?: Record<string, unknown>;
31
+ }
32
+ export interface FlowRunnerHooks {
33
+ /** Fires once before the top-level flow starts (not for nested flows). */
34
+ beforeRun?(flowName: string, plan: PlanStep[]): Promise<void>;
35
+ /** Fires once after the top-level flow completes (success or failure). */
36
+ afterRun?(result: FlowRunResult): Promise<void>;
37
+ /** Fires before every step (including steps inside nested flows). */
38
+ beforeStep?(step: PlanStep): Promise<void>;
39
+ /** Fires after every step. */
40
+ afterStep?(step: PlanStep, result: FlowStepResult): Promise<void>;
41
+ /** Fires when a step fails — before afterRun. */
42
+ onStepError?(step: PlanStep, error: Error, completed: FlowStepResult[]): Promise<void>;
43
+ }
44
+ export interface FlowRunnerConfig {
45
+ tasks: Record<string, TaskDefinition>;
46
+ flows: Record<string, FlowDefinition>;
47
+ registry: TaskRegistry;
48
+ context: TaskContext;
49
+ hooks?: FlowRunnerHooks;
50
+ logger?: Logger;
51
+ }
52
+ export declare class FlowRunner {
53
+ private logger;
54
+ private tasks;
55
+ private flows;
56
+ private registry;
57
+ private ctx;
58
+ private hooks;
59
+ private runDepth;
60
+ constructor(config: FlowRunnerConfig);
61
+ run(options: FlowRunOptions): Promise<FlowRunResult>;
62
+ /** Flatten a flow definition into an ordered execution plan. */
63
+ resolveExecutionPlan(flow: FlowDefinition, skipSet: Set<string>): PlanStep[];
64
+ private executeFlow;
65
+ private executeTaskStep;
66
+ private resolveTaskDefinition;
67
+ }
68
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/flow/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,184 @@
1
+ import { noopLogger } from '../logger.js';
2
+ // ---------------------------------------------------------------------------
3
+ // FlowRunner
4
+ // ---------------------------------------------------------------------------
5
+ export class FlowRunner {
6
+ logger;
7
+ tasks;
8
+ flows;
9
+ registry;
10
+ ctx;
11
+ hooks;
12
+ runDepth = 0;
13
+ constructor(config) {
14
+ this.logger = (config.logger ?? noopLogger).child({ component: 'flow-runner' });
15
+ this.tasks = config.tasks;
16
+ this.flows = config.flows;
17
+ this.registry = config.registry;
18
+ this.ctx = config.context;
19
+ this.hooks = config.hooks ?? {};
20
+ }
21
+ async run(options) {
22
+ this.runDepth++;
23
+ const isTopLevel = this.runDepth === 1;
24
+ try {
25
+ return await this.executeFlow(options, isTopLevel);
26
+ }
27
+ finally {
28
+ this.runDepth--;
29
+ }
30
+ }
31
+ /** Flatten a flow definition into an ordered execution plan. */
32
+ resolveExecutionPlan(flow, skipSet) {
33
+ const sortedKeys = Object.keys(flow.steps)
34
+ .map(Number)
35
+ .sort((a, b) => a - b);
36
+ return sortedKeys.map((key) => {
37
+ const step = flow.steps[String(key)];
38
+ if (step.task === 'None') {
39
+ return { stepNumber: key, type: 'task', name: 'None', skipped: true };
40
+ }
41
+ const name = (step.task ?? step.flow);
42
+ const type = step.task ? 'task' : 'flow';
43
+ return {
44
+ stepNumber: key,
45
+ type,
46
+ name,
47
+ skipped: skipSet.has(name) || skipSet.has(String(key)),
48
+ options: step.options,
49
+ };
50
+ });
51
+ }
52
+ // ---------------------------------------------------------------------------
53
+ // Internal
54
+ // ---------------------------------------------------------------------------
55
+ async executeFlow(options, isTopLevel) {
56
+ const startTime = Date.now();
57
+ const skipSet = new Set(options.skip ?? []);
58
+ const completedSteps = [];
59
+ const flow = this.flows[options.flowName];
60
+ if (!flow) {
61
+ throw new Error(`Flow "${options.flowName}" not found in configuration`);
62
+ }
63
+ const executionPlan = this.resolveExecutionPlan(flow, skipSet);
64
+ // Plan mode — return the plan without executing anything
65
+ if (options.plan) {
66
+ return {
67
+ success: true,
68
+ steps: executionPlan.map((s) => ({
69
+ stepNumber: s.stepNumber,
70
+ type: s.type,
71
+ name: s.name,
72
+ skipped: s.skipped,
73
+ duration: 0,
74
+ })),
75
+ duration: 0,
76
+ };
77
+ }
78
+ if (isTopLevel) {
79
+ await this.hooks.beforeRun?.(options.flowName, executionPlan);
80
+ }
81
+ let flowError;
82
+ for (const planStep of executionPlan) {
83
+ // ---- Skipped steps ----
84
+ if (planStep.skipped) {
85
+ const sr = {
86
+ stepNumber: planStep.stepNumber,
87
+ type: planStep.type,
88
+ name: planStep.name,
89
+ skipped: true,
90
+ duration: 0,
91
+ };
92
+ completedSteps.push(sr);
93
+ await this.hooks.afterStep?.(planStep, sr);
94
+ continue;
95
+ }
96
+ // ---- Active steps ----
97
+ await this.hooks.beforeStep?.(planStep);
98
+ const stepStart = Date.now();
99
+ try {
100
+ let stepResult;
101
+ if (planStep.type === 'task') {
102
+ const taskResult = await this.executeTaskStep(planStep);
103
+ stepResult = {
104
+ stepNumber: planStep.stepNumber,
105
+ type: 'task',
106
+ name: planStep.name,
107
+ result: taskResult,
108
+ skipped: false,
109
+ duration: Date.now() - stepStart,
110
+ };
111
+ }
112
+ else {
113
+ const nestedResult = await this.run({
114
+ ...options,
115
+ flowName: planStep.name,
116
+ plan: false,
117
+ });
118
+ stepResult = {
119
+ stepNumber: planStep.stepNumber,
120
+ type: 'flow',
121
+ name: planStep.name,
122
+ result: {
123
+ success: nestedResult.success,
124
+ data: { stepCount: nestedResult.steps.length },
125
+ },
126
+ skipped: false,
127
+ duration: Date.now() - stepStart,
128
+ };
129
+ if (!nestedResult.success) {
130
+ flowError = nestedResult.error ?? new Error(`Nested flow ${planStep.name} failed`);
131
+ }
132
+ }
133
+ completedSteps.push(stepResult);
134
+ await this.hooks.afterStep?.(planStep, stepResult);
135
+ if (!stepResult.result?.success) {
136
+ flowError =
137
+ flowError ?? stepResult.result?.error ?? new Error(`Step ${planStep.name} failed`);
138
+ await this.hooks.onStepError?.(planStep, flowError, completedSteps);
139
+ break;
140
+ }
141
+ }
142
+ catch (error) {
143
+ const err = error instanceof Error ? error : new Error(String(error));
144
+ completedSteps.push({
145
+ stepNumber: planStep.stepNumber,
146
+ type: planStep.type,
147
+ name: planStep.name,
148
+ skipped: false,
149
+ duration: Date.now() - stepStart,
150
+ result: { success: false, error: err },
151
+ });
152
+ flowError = err;
153
+ await this.hooks.onStepError?.(planStep, err, completedSteps);
154
+ break;
155
+ }
156
+ }
157
+ const result = {
158
+ success: !flowError,
159
+ steps: completedSteps,
160
+ duration: Date.now() - startTime,
161
+ error: flowError,
162
+ };
163
+ if (isTopLevel) {
164
+ await this.hooks.afterRun?.(result);
165
+ }
166
+ return result;
167
+ }
168
+ async executeTaskStep(step) {
169
+ const taskDef = this.resolveTaskDefinition(step.name);
170
+ const mergedOptions = { ...taskDef.options, ...step.options };
171
+ this.logger.info({ step: step.stepNumber, task: step.name, type: step.type }, `Executing step ${step.stepNumber}: ${step.name}`);
172
+ const task = await this.registry.create(taskDef.class_path, this.ctx, mergedOptions);
173
+ return task.run();
174
+ }
175
+ resolveTaskDefinition(taskName) {
176
+ const taskDef = this.tasks[taskName];
177
+ if (taskDef) {
178
+ return { class_path: taskDef.class_path, options: taskDef.options ?? {} };
179
+ }
180
+ // Allow using a class_path directly as the task reference
181
+ return { class_path: taskName, options: {} };
182
+ }
183
+ }
184
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/flow/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export { deepMerge } from './config/deep-merge.js';
2
+ export { TaskOptionsSchema, TaskDefinitionSchema, FlowStepSchema, FlowDefinitionSchema, EngineConfigSchema, } from './config/schema.js';
3
+ export type { TaskOptions, TaskDefinition, FlowStep, FlowDefinition, EngineConfig, } from './config/schema.js';
4
+ export { loadConfig, loadRawYaml, findConfigFile } from './config/loader.js';
5
+ export type { LoadConfigOptions, LoadedConfig } from './config/loader.js';
6
+ export { BaseTask } from './task/base-task.js';
7
+ export type { TaskContext, TaskResult } from './task/base-task.js';
8
+ export { TaskRegistry } from './task/registry.js';
9
+ export type { TaskConstructor } from './task/registry.js';
10
+ export { FlowRunner } from './flow/runner.js';
11
+ export type { FlowRunOptions, FlowStepResult, FlowRunResult, FlowRunnerHooks, FlowRunnerConfig, PlanStep, } from './flow/runner.js';
12
+ export { topologicalSort, CircularDependencyError, MissingDependencyError, } from './dag/resolver.js';
13
+ export type { DagNode } from './dag/resolver.js';
14
+ export type { Logger } from './logger.js';
15
+ export { noopLogger } from './logger.js';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,WAAW,EACX,cAAc,EACd,QAAQ,EACR,cAAc,EACd,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC7E,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG1E,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,QAAQ,GACT,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAGjD,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ // Config
2
+ export { deepMerge } from './config/deep-merge.js';
3
+ export { TaskOptionsSchema, TaskDefinitionSchema, FlowStepSchema, FlowDefinitionSchema, EngineConfigSchema, } from './config/schema.js';
4
+ export { loadConfig, loadRawYaml, findConfigFile } from './config/loader.js';
5
+ // Task
6
+ export { BaseTask } from './task/base-task.js';
7
+ export { TaskRegistry } from './task/registry.js';
8
+ // Flow
9
+ export { FlowRunner } from './flow/runner.js';
10
+ // DAG
11
+ export { topologicalSort, CircularDependencyError, MissingDependencyError, } from './dag/resolver.js';
12
+ export { noopLogger } from './logger.js';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAQ5B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAG7E,OAAO;AACP,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO;AACP,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAU9C,MAAM;AACN,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface Logger {
2
+ debug(...args: unknown[]): void;
3
+ info(...args: unknown[]): void;
4
+ warn(...args: unknown[]): void;
5
+ error(...args: unknown[]): void;
6
+ child(bindings: Record<string, unknown>): Logger;
7
+ }
8
+ export declare const noopLogger: Logger;
9
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC;CAClD;AAED,eAAO,MAAM,UAAU,EAAE,MAQxB,CAAC"}
package/dist/logger.js ADDED
@@ -0,0 +1,10 @@
1
+ export const noopLogger = {
2
+ debug() { },
3
+ info() { },
4
+ warn() { },
5
+ error() { },
6
+ child() {
7
+ return noopLogger;
8
+ },
9
+ };
10
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,UAAU,GAAW;IAChC,KAAK,KAAI,CAAC;IACV,IAAI,KAAI,CAAC;IACT,IAAI,KAAI,CAAC;IACT,KAAK,KAAI,CAAC;IACV,KAAK;QACH,OAAO,UAAU,CAAC;IACpB,CAAC;CACF,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { Logger } from '../logger.js';
2
+ export interface TaskContext {
3
+ logger?: Logger;
4
+ [key: string]: unknown;
5
+ }
6
+ export interface TaskResult {
7
+ success: boolean;
8
+ data?: Record<string, unknown>;
9
+ error?: Error;
10
+ duration?: number;
11
+ }
12
+ export declare abstract class BaseTask<TOpts = Record<string, unknown>> {
13
+ protected ctx: TaskContext;
14
+ protected options: TOpts;
15
+ protected logger: Logger;
16
+ constructor(ctx: TaskContext, options: TOpts);
17
+ abstract get taskName(): string;
18
+ abstract execute(): Promise<TaskResult>;
19
+ /** Override for option validation — called before execute(). */
20
+ protected validate(): void;
21
+ /**
22
+ * Lifecycle wrapper: validate → execute → return result.
23
+ * Catches exceptions and returns `{ success: false }` instead of throwing.
24
+ */
25
+ run(): Promise<TaskResult>;
26
+ }
27
+ //# sourceMappingURL=base-task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-task.d.ts","sourceRoot":"","sources":["../../src/task/base-task.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,8BAAsB,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAI1D,SAAS,CAAC,GAAG,EAAE,WAAW;IAC1B,SAAS,CAAC,OAAO,EAAE,KAAK;IAJ1B,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;gBAGb,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,KAAK;IAM1B,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC;IAEhC,QAAQ,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;IAEvC,gEAAgE;IAChE,SAAS,CAAC,QAAQ,IAAI,IAAI;IAE1B;;;OAGG;IACG,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC;CA2BjC"}
@@ -0,0 +1,39 @@
1
+ import { noopLogger } from '../logger.js';
2
+ export class BaseTask {
3
+ ctx;
4
+ options;
5
+ logger;
6
+ constructor(ctx, options) {
7
+ this.ctx = ctx;
8
+ this.options = options;
9
+ const parentLogger = ctx.logger ?? noopLogger;
10
+ this.logger = parentLogger.child({ task: this.constructor.name });
11
+ }
12
+ /** Override for option validation — called before execute(). */
13
+ validate() { }
14
+ /**
15
+ * Lifecycle wrapper: validate → execute → return result.
16
+ * Catches exceptions and returns `{ success: false }` instead of throwing.
17
+ */
18
+ async run() {
19
+ const startTime = Date.now();
20
+ this.logger.debug({ options: this.options }, `Starting task: ${this.taskName}`);
21
+ try {
22
+ this.validate();
23
+ const result = await this.execute();
24
+ result.duration = Date.now() - startTime;
25
+ this.logger.debug({ success: result.success, duration: result.duration }, `Completed task: ${this.taskName}`);
26
+ return result;
27
+ }
28
+ catch (error) {
29
+ const duration = Date.now() - startTime;
30
+ this.logger.error({ error, duration }, `Failed task: ${this.taskName}`);
31
+ return {
32
+ success: false,
33
+ error: error instanceof Error ? error : new Error(String(error)),
34
+ duration,
35
+ };
36
+ }
37
+ }
38
+ }
39
+ //# sourceMappingURL=base-task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-task.js","sourceRoot":"","sources":["../../src/task/base-task.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAc1C,MAAM,OAAgB,QAAQ;IAIhB;IACA;IAJF,MAAM,CAAS;IAEzB,YACY,GAAgB,EAChB,OAAc;QADd,QAAG,GAAH,GAAG,CAAa;QAChB,YAAO,GAAP,OAAO,CAAO;QAExB,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,IAAI,UAAU,CAAC;QAC9C,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;IACpE,CAAC;IAMD,gEAAgE;IACtD,QAAQ,KAAU,CAAC;IAE7B;;;OAGG;IACH,KAAK,CAAC,GAAG;QACP,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,kBAAkB,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEhF,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YACpC,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAEzC,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,EACtD,mBAAmB,IAAI,CAAC,QAAQ,EAAE,CACnC,CAAC;YAEF,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YACxC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,gBAAgB,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAExE,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChE,QAAQ;aACT,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ export { BaseTask } from './base-task.js';
2
+ export type { TaskContext, TaskResult } from './base-task.js';
3
+ export { TaskRegistry } from './registry.js';
4
+ export type { TaskConstructor } from './registry.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/task/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { BaseTask } from './base-task.js';
2
+ export { TaskRegistry } from './registry.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/task/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { BaseTask, type TaskContext } from './base-task.js';
2
+ export type TaskConstructor = new (ctx: TaskContext, options: Record<string, unknown>) => BaseTask;
3
+ export declare class TaskRegistry {
4
+ private classPathMap;
5
+ private nameMap;
6
+ private dynamicCache;
7
+ /** Register a task by short name (e.g. `'deploy'`). */
8
+ register(name: string, ctor: TaskConstructor): this;
9
+ /** Register a task by class path (e.g. `'my.tasks.Deploy'`). */
10
+ registerClassPath(classPath: string, ctor: TaskConstructor): this;
11
+ /** Bulk-register by short name. */
12
+ registerAll(entries: Record<string, TaskConstructor>): this;
13
+ /** Bulk-register by class path. */
14
+ registerClassPaths(entries: Record<string, TaskConstructor>): this;
15
+ /**
16
+ * Resolve a task constructor by name or class path.
17
+ * Falls back to dynamic import from the filesystem.
18
+ */
19
+ resolve(classPathOrName: string): Promise<TaskConstructor>;
20
+ /** Resolve + instantiate in one call. */
21
+ create(classPathOrName: string, ctx: TaskContext, options: Record<string, unknown>): Promise<BaseTask>;
22
+ /** Return all registered names and class paths. */
23
+ listRegistered(): string[];
24
+ private loadDynamic;
25
+ private classPathToCandidates;
26
+ }
27
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/task/registry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE5D,MAAM,MAAM,eAAe,GAAG,KAC5B,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,QAAQ,CAAC;AAEd,qBAAa,YAAY;IACvB,OAAO,CAAC,YAAY,CAAsC;IAC1D,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,YAAY,CAAsC;IAE1D,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,IAAI;IAKnD,gEAAgE;IAChE,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,IAAI;IAKjE,mCAAmC;IACnC,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,IAAI;IAO3D,mCAAmC;IACnC,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,IAAI;IAOlE;;;OAGG;IACG,OAAO,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAQhE,yCAAyC;IACnC,MAAM,CACV,eAAe,EAAE,MAAM,EACvB,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,QAAQ,CAAC;IAKpB,mDAAmD;IACnD,cAAc,IAAI,MAAM,EAAE;YAQZ,WAAW;IA0CzB,OAAO,CAAC,qBAAqB;CAW9B"}
@@ -0,0 +1,95 @@
1
+ import * as path from 'node:path';
2
+ import * as fs from 'node:fs';
3
+ import { BaseTask } from './base-task.js';
4
+ export class TaskRegistry {
5
+ classPathMap = new Map();
6
+ nameMap = new Map();
7
+ dynamicCache = new Map();
8
+ /** Register a task by short name (e.g. `'deploy'`). */
9
+ register(name, ctor) {
10
+ this.nameMap.set(name, ctor);
11
+ return this;
12
+ }
13
+ /** Register a task by class path (e.g. `'my.tasks.Deploy'`). */
14
+ registerClassPath(classPath, ctor) {
15
+ this.classPathMap.set(classPath, ctor);
16
+ return this;
17
+ }
18
+ /** Bulk-register by short name. */
19
+ registerAll(entries) {
20
+ for (const [name, ctor] of Object.entries(entries)) {
21
+ this.nameMap.set(name, ctor);
22
+ }
23
+ return this;
24
+ }
25
+ /** Bulk-register by class path. */
26
+ registerClassPaths(entries) {
27
+ for (const [classPath, ctor] of Object.entries(entries)) {
28
+ this.classPathMap.set(classPath, ctor);
29
+ }
30
+ return this;
31
+ }
32
+ /**
33
+ * Resolve a task constructor by name or class path.
34
+ * Falls back to dynamic import from the filesystem.
35
+ */
36
+ async resolve(classPathOrName) {
37
+ const builtin = this.classPathMap.get(classPathOrName) ?? this.nameMap.get(classPathOrName);
38
+ if (builtin)
39
+ return builtin;
40
+ return this.loadDynamic(classPathOrName);
41
+ }
42
+ /** Resolve + instantiate in one call. */
43
+ async create(classPathOrName, ctx, options) {
44
+ const TaskClass = await this.resolve(classPathOrName);
45
+ return new TaskClass(ctx, options);
46
+ }
47
+ /** Return all registered names and class paths. */
48
+ listRegistered() {
49
+ return [...new Set([...this.nameMap.keys(), ...this.classPathMap.keys()])];
50
+ }
51
+ // ---------------------------------------------------------------------------
52
+ // Dynamic loading — class_path treated as a dotted file path
53
+ // ---------------------------------------------------------------------------
54
+ async loadDynamic(classPath) {
55
+ const cached = this.dynamicCache.get(classPath);
56
+ if (cached)
57
+ return cached;
58
+ const candidates = this.classPathToCandidates(classPath);
59
+ let resolvedPath = null;
60
+ for (const candidate of candidates) {
61
+ if (fs.existsSync(candidate)) {
62
+ resolvedPath = candidate;
63
+ break;
64
+ }
65
+ }
66
+ if (!resolvedPath) {
67
+ throw new Error(`Cannot resolve task "${classPath}". Searched:\n` +
68
+ candidates.map((c) => ` - ${c}`).join('\n'));
69
+ }
70
+ const fileUrl = `file://${resolvedPath.replace(/\\/g, '/')}`;
71
+ const mod = await import(fileUrl);
72
+ const baseName = path.basename(classPath.replace(/\./g, '/'));
73
+ const TaskClass = mod.default ?? mod[baseName];
74
+ if (!TaskClass) {
75
+ throw new Error(`Module "${resolvedPath}" does not export a default class or a named export ` +
76
+ `matching "${baseName}"`);
77
+ }
78
+ if (!(TaskClass.prototype instanceof BaseTask)) {
79
+ throw new Error(`Task class from "${resolvedPath}" does not extend BaseTask`);
80
+ }
81
+ this.dynamicCache.set(classPath, TaskClass);
82
+ return TaskClass;
83
+ }
84
+ classPathToCandidates(classPath) {
85
+ const segments = classPath.replace(/\./g, '/');
86
+ const cwd = process.cwd();
87
+ return [
88
+ path.resolve(cwd, `${segments}.ts`),
89
+ path.resolve(cwd, `${segments}.js`),
90
+ path.resolve(cwd, `${segments}/index.ts`),
91
+ path.resolve(cwd, `${segments}/index.js`),
92
+ ];
93
+ }
94
+ }
95
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/task/registry.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@db-lyon/flowkit",
3
+ "version": "0.1.0",
4
+ "description": "YAML-configured task and flow orchestration engine",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": "./dist/index.js",
10
+ "./config": "./dist/config/index.js",
11
+ "./task": "./dist/task/index.js",
12
+ "./flow": "./dist/flow/index.js",
13
+ "./dag": "./dist/dag/index.js"
14
+ },
15
+ "files": [
16
+ "/dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc -b",
20
+ "prepublishOnly": "tsc -b",
21
+ "test": "vitest run",
22
+ "test:watch": "vitest"
23
+ },
24
+ "keywords": [
25
+ "task",
26
+ "flow",
27
+ "orchestration",
28
+ "yaml",
29
+ "pipeline",
30
+ "engine"
31
+ ],
32
+ "author": "David Lyon",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/db-lyon/flowkit.git"
37
+ },
38
+ "dependencies": {
39
+ "js-yaml": "^4",
40
+ "zod": "^3"
41
+ },
42
+ "devDependencies": {
43
+ "@types/js-yaml": "^4",
44
+ "@types/node": "^20",
45
+ "typescript": "^5",
46
+ "vitest": "^2"
47
+ },
48
+ "engines": {
49
+ "node": ">=20"
50
+ }
51
+ }