@lotiai/composer 0.2.0 → 0.2.1
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/build-config/index.d.ts +52 -0
- package/dist/build-config/index.d.ts.map +1 -0
- package/dist/build-config/index.js +66 -0
- package/dist/build-config/index.js.map +1 -0
- package/dist/build-config/loader.d.ts +80 -0
- package/dist/build-config/loader.d.ts.map +1 -0
- package/dist/build-config/loader.js +238 -0
- package/dist/build-config/loader.js.map +1 -0
- package/dist/build-config/schema.d.ts +101 -0
- package/dist/build-config/schema.d.ts.map +1 -0
- package/dist/build-config/schema.js +94 -0
- package/dist/build-config/schema.js.map +1 -0
- package/dist/cli/commands/dev-temporal.d.ts +15 -0
- package/dist/cli/commands/dev-temporal.d.ts.map +1 -0
- package/dist/cli/commands/dev-temporal.js +68 -0
- package/dist/cli/commands/dev-temporal.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +21 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +421 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/profiles.d.ts +15 -0
- package/dist/cli/commands/profiles.d.ts.map +1 -0
- package/dist/cli/commands/profiles.js +69 -0
- package/dist/cli/commands/profiles.js.map +1 -0
- package/dist/cli/index.d.ts +21 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +44 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/async/build/workflow-factory.d.ts +212 -0
- package/dist/internal/async/build/workflow-factory.d.ts.map +1 -0
- package/dist/internal/async/build/workflow-factory.js +533 -0
- package/dist/internal/async/build/workflow-factory.js.map +1 -0
- package/dist/internal/async/build-scripts/utils/common.d.ts +28 -0
- package/dist/internal/async/build-scripts/utils/common.d.ts.map +1 -0
- package/dist/internal/async/build-scripts/utils/common.js +50 -0
- package/dist/internal/async/build-scripts/utils/common.js.map +1 -0
- package/dist/internal/async/build-scripts/utils/import-module.d.ts +19 -0
- package/dist/internal/async/build-scripts/utils/import-module.d.ts.map +1 -0
- package/dist/internal/async/build-scripts/utils/import-module.js +80 -0
- package/dist/internal/async/build-scripts/utils/import-module.js.map +1 -0
- package/dist/internal/async/build-scripts/utils/type-guards.d.ts +123 -0
- package/dist/internal/async/build-scripts/utils/type-guards.d.ts.map +1 -0
- package/dist/internal/async/build-scripts/utils/type-guards.js +145 -0
- package/dist/internal/async/build-scripts/utils/type-guards.js.map +1 -0
- package/dist/internal/async/config/cleanup-policy.d.ts +50 -0
- package/dist/internal/async/config/cleanup-policy.d.ts.map +1 -0
- package/dist/internal/async/config/cleanup-policy.js +20 -0
- package/dist/internal/async/config/cleanup-policy.js.map +1 -0
- package/dist/internal/async/config/worker-profiles.d.ts +172 -0
- package/dist/internal/async/config/worker-profiles.d.ts.map +1 -0
- package/dist/internal/async/config/worker-profiles.js +275 -0
- package/dist/internal/async/config/worker-profiles.js.map +1 -0
- package/dist/internal/async/execute/temporal-client.d.ts +182 -0
- package/dist/internal/async/execute/temporal-client.d.ts.map +1 -0
- package/dist/internal/async/execute/temporal-client.js +190 -0
- package/dist/internal/async/execute/temporal-client.js.map +1 -0
- package/dist/internal/async/execute/workflow-execution.d.ts +98 -0
- package/dist/internal/async/execute/workflow-execution.d.ts.map +1 -0
- package/dist/internal/async/execute/workflow-execution.js +191 -0
- package/dist/internal/async/execute/workflow-execution.js.map +1 -0
- package/dist/internal/async/metrics/task-queue-metrics.d.ts +74 -0
- package/dist/internal/async/metrics/task-queue-metrics.d.ts.map +1 -0
- package/dist/internal/async/metrics/task-queue-metrics.js +155 -0
- package/dist/internal/async/metrics/task-queue-metrics.js.map +1 -0
- package/dist/internal/async/register/activity-worker.d.ts +123 -0
- package/dist/internal/async/register/activity-worker.d.ts.map +1 -0
- package/dist/internal/async/register/activity-worker.js +355 -0
- package/dist/internal/async/register/activity-worker.js.map +1 -0
- package/dist/internal/async/register/generate-workflow-source.d.ts +43 -0
- package/dist/internal/async/register/generate-workflow-source.d.ts.map +1 -0
- package/dist/internal/async/register/generate-workflow-source.js +193 -0
- package/dist/internal/async/register/generate-workflow-source.js.map +1 -0
- package/dist/internal/async/register/workflow-worker.d.ts +125 -0
- package/dist/internal/async/register/workflow-worker.d.ts.map +1 -0
- package/dist/internal/async/register/workflow-worker.js +215 -0
- package/dist/internal/async/register/workflow-worker.js.map +1 -0
- package/dist/internal/async/register-scripts/start-activity-worker.d.ts +70 -0
- package/dist/internal/async/register-scripts/start-activity-worker.d.ts.map +1 -0
- package/dist/internal/async/register-scripts/start-activity-worker.js +75 -0
- package/dist/internal/async/register-scripts/start-activity-worker.js.map +1 -0
- package/dist/internal/async/register-scripts/start-all-workers.d.ts +81 -0
- package/dist/internal/async/register-scripts/start-all-workers.d.ts.map +1 -0
- package/dist/internal/async/register-scripts/start-all-workers.js +84 -0
- package/dist/internal/async/register-scripts/start-all-workers.js.map +1 -0
- package/dist/internal/async/register-scripts/start-workflow-worker.d.ts +69 -0
- package/dist/internal/async/register-scripts/start-workflow-worker.d.ts.map +1 -0
- package/dist/internal/async/register-scripts/start-workflow-worker.js +74 -0
- package/dist/internal/async/register-scripts/start-workflow-worker.js.map +1 -0
- package/dist/internal/async/register-scripts/sync-schedules-cli.d.ts +28 -0
- package/dist/internal/async/register-scripts/sync-schedules-cli.d.ts.map +1 -0
- package/dist/internal/async/register-scripts/sync-schedules-cli.js +124 -0
- package/dist/internal/async/register-scripts/sync-schedules-cli.js.map +1 -0
- package/dist/internal/async/register-scripts/sync-schedules-via-lambda.d.ts +55 -0
- package/dist/internal/async/register-scripts/sync-schedules-via-lambda.d.ts.map +1 -0
- package/dist/internal/async/register-scripts/sync-schedules-via-lambda.js +146 -0
- package/dist/internal/async/register-scripts/sync-schedules-via-lambda.js.map +1 -0
- package/dist/internal/async/register-scripts/sync-schedules.d.ts +68 -0
- package/dist/internal/async/register-scripts/sync-schedules.d.ts.map +1 -0
- package/dist/internal/async/register-scripts/sync-schedules.js +83 -0
- package/dist/internal/async/register-scripts/sync-schedules.js.map +1 -0
- package/dist/internal/async/schedule/constants.d.ts +10 -0
- package/dist/internal/async/schedule/constants.d.ts.map +1 -0
- package/dist/internal/async/schedule/constants.js +13 -0
- package/dist/internal/async/schedule/constants.js.map +1 -0
- package/dist/internal/async/schedule/define-schedule.d.ts +192 -0
- package/dist/internal/async/schedule/define-schedule.d.ts.map +1 -0
- package/dist/internal/async/schedule/define-schedule.js +79 -0
- package/dist/internal/async/schedule/define-schedule.js.map +1 -0
- package/dist/internal/async/schedule/index.d.ts +3 -0
- package/dist/internal/async/schedule/index.d.ts.map +1 -0
- package/dist/internal/async/schedule/index.js +9 -0
- package/dist/internal/async/schedule/index.js.map +1 -0
- package/dist/internal/async/schedule/schedule-definition-schema.d.ts +64 -0
- package/dist/internal/async/schedule/schedule-definition-schema.d.ts.map +1 -0
- package/dist/internal/async/schedule/schedule-definition-schema.js +77 -0
- package/dist/internal/async/schedule/schedule-definition-schema.js.map +1 -0
- package/dist/internal/async/schedule/sync-schedules.d.ts +71 -0
- package/dist/internal/async/schedule/sync-schedules.d.ts.map +1 -0
- package/dist/internal/async/schedule/sync-schedules.js +231 -0
- package/dist/internal/async/schedule/sync-schedules.js.map +1 -0
- package/dist/internal/async/utils/ensure-namespace.d.ts +16 -0
- package/dist/internal/async/utils/ensure-namespace.d.ts.map +1 -0
- package/dist/internal/async/utils/ensure-namespace.js +64 -0
- package/dist/internal/async/utils/ensure-namespace.js.map +1 -0
- package/dist/internal/async/utils/find-package-root.d.ts +9 -0
- package/dist/internal/async/utils/find-package-root.d.ts.map +1 -0
- package/dist/internal/async/utils/find-package-root.js +28 -0
- package/dist/internal/async/utils/find-package-root.js.map +1 -0
- package/dist/internal/async/utils/is-composer-error.d.ts +14 -0
- package/dist/internal/async/utils/is-composer-error.d.ts.map +1 -0
- package/dist/internal/async/utils/is-composer-error.js +17 -0
- package/dist/internal/async/utils/is-composer-error.js.map +1 -0
- package/dist/internal/context-provider.d.ts +316 -0
- package/dist/internal/context-provider.d.ts.map +1 -0
- package/dist/internal/context-provider.js +12 -0
- package/dist/internal/context-provider.js.map +1 -0
- package/dist/internal/create-composer.d.ts +57 -0
- package/dist/internal/create-composer.d.ts.map +1 -0
- package/dist/internal/create-composer.js +125 -0
- package/dist/internal/create-composer.js.map +1 -0
- package/dist/internal/dag-sync-fanout.d.ts +79 -0
- package/dist/internal/dag-sync-fanout.d.ts.map +1 -0
- package/dist/internal/dag-sync-fanout.js +59 -0
- package/dist/internal/dag-sync-fanout.js.map +1 -0
- package/dist/internal/dag-sync-step.d.ts +230 -0
- package/dist/internal/dag-sync-step.d.ts.map +1 -0
- package/dist/internal/dag-sync-step.js +159 -0
- package/dist/internal/dag-sync-step.js.map +1 -0
- package/dist/internal/dag-sync-workflow.d.ts +535 -0
- package/dist/internal/dag-sync-workflow.d.ts.map +1 -0
- package/dist/internal/dag-sync-workflow.js +843 -0
- package/dist/internal/dag-sync-workflow.js.map +1 -0
- package/dist/internal/defaults.d.ts +24 -0
- package/dist/internal/defaults.d.ts.map +1 -0
- package/dist/internal/defaults.js +102 -0
- package/dist/internal/defaults.js.map +1 -0
- package/dist/internal/errors.d.ts +109 -0
- package/dist/internal/errors.d.ts.map +1 -0
- package/dist/internal/errors.js +212 -0
- package/dist/internal/errors.js.map +1 -0
- package/dist/internal/index.d.ts +9 -0
- package/dist/internal/index.d.ts.map +1 -0
- package/dist/internal/index.js +22 -0
- package/dist/internal/index.js.map +1 -0
- package/dist/internal/observability.d.ts +63 -0
- package/dist/internal/observability.d.ts.map +1 -0
- package/dist/internal/observability.js +323 -0
- package/dist/internal/observability.js.map +1 -0
- package/dist/internal/types.d.ts +80 -0
- package/dist/internal/types.d.ts.map +1 -0
- package/dist/internal/types.js +9 -0
- package/dist/internal/types.js.map +1 -0
- package/dist/internal/workflow-planning.d.ts +107 -0
- package/dist/internal/workflow-planning.d.ts.map +1 -0
- package/dist/internal/workflow-planning.js +216 -0
- package/dist/internal/workflow-planning.js.map +1 -0
- package/dist/schedule-sync.d.ts +17 -0
- package/dist/schedule-sync.d.ts.map +1 -0
- package/dist/schedule-sync.js +22 -0
- package/dist/schedule-sync.js.map +1 -0
- package/dist/temporal-naming.d.ts +27 -0
- package/dist/temporal-naming.d.ts.map +1 -0
- package/dist/temporal-naming.js +33 -0
- package/dist/temporal-naming.js.map +1 -0
- package/package.json +16 -17
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isFanOutStep = isFanOutStep;
|
|
4
|
+
exports.fanOut = fanOut;
|
|
5
|
+
/**
|
|
6
|
+
* Runtime type guard for detecting FanOut nodes within a step array.
|
|
7
|
+
*/
|
|
8
|
+
function isFanOutStep(value) {
|
|
9
|
+
return "__fanOut" in value && value.__fanOut != null;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Factory function for creating type-safe FanOut nodes.
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* const fo = fanOut<ParentBag>()({
|
|
16
|
+
* name: "startTldIngestions",
|
|
17
|
+
* needs: ["tlds"] as const,
|
|
18
|
+
* childWorkflow: ingestCzdsTld,
|
|
19
|
+
* mapInput: (bag) => bag.tlds.map(tld => ({ tld })),
|
|
20
|
+
* provides: ["tldResults"] as const,
|
|
21
|
+
* aggregateResults: (results) => ({ tldResults: results }),
|
|
22
|
+
* concurrency: 5,
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* The double-call pattern (fanOut<ParentBag>()({...})) matches the step()
|
|
26
|
+
* factory -- ParentBag is explicit, all other generics are inferred from
|
|
27
|
+
* the definition object.
|
|
28
|
+
*
|
|
29
|
+
* Generic parameters:
|
|
30
|
+
* - ParentBag (explicit): The parent workflow's bag type
|
|
31
|
+
* - Name (inferred): Literal string name of this fanOut node
|
|
32
|
+
* - Needs (inferred): Bag keys this fanOut requires as input
|
|
33
|
+
* - Provides (inferred): Bag keys this fanOut produces as output
|
|
34
|
+
* - W (inferred): The child workflow type (carries Bag, RequiredInitial, etc.)
|
|
35
|
+
*/
|
|
36
|
+
function fanOut() {
|
|
37
|
+
return (definition) => {
|
|
38
|
+
if (definition.concurrency != null &&
|
|
39
|
+
(!Number.isFinite(definition.concurrency) || definition.concurrency < 1)) {
|
|
40
|
+
throw new Error(`FanOut "${definition.name}": concurrency must be a positive finite number, got ${definition.concurrency}`);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
name: definition.name,
|
|
44
|
+
needs: definition.needs,
|
|
45
|
+
provides: definition.provides,
|
|
46
|
+
run: async () => {
|
|
47
|
+
throw new Error(`FanOut "${definition.name}" cannot be executed directly. ` +
|
|
48
|
+
`Use the workflow runtime (runSyncWorkflow or Temporal).`);
|
|
49
|
+
},
|
|
50
|
+
__fanOut: {
|
|
51
|
+
childWorkflow: definition.childWorkflow,
|
|
52
|
+
mapInput: definition.mapInput,
|
|
53
|
+
aggregateResults: definition.aggregateResults,
|
|
54
|
+
concurrency: definition.concurrency ?? Infinity,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=dag-sync-fanout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-sync-fanout.js","sourceRoot":"","sources":["../../src/internal/dag-sync-fanout.ts"],"names":[],"mappings":";;AA6DA,oCAIC;AA2BD,wBA+CC;AAjFD;;GAEG;AACH,SAAgB,YAAY,CAC1B,KAAoC;IAEpC,OAAO,UAAU,IAAI,KAAK,IAAK,KAAoC,CAAC,QAAQ,IAAI,IAAI,CAAC;AACvF,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,SAAgB,MAAM;IACpB,OAAO,CAKL,UAYD,EAA4C,EAAE;QAC7C,IACE,UAAU,CAAC,WAAW,IAAI,IAAI;YAC9B,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,UAAU,CAAC,WAAW,GAAG,CAAC,CAAC,EACxE,CAAC;YACD,MAAM,IAAI,KAAK,CACb,WAAW,UAAU,CAAC,IAAI,wDAAwD,UAAU,CAAC,WAAW,EAAE,CAC3G,CAAC;QACJ,CAAC;QAED,OAAO;YACL,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,KAAK,EAAE,UAAU,CAAC,KAAK;YACvB,QAAQ,EAAE,UAAU,CAAC,QAAQ;YAC7B,GAAG,EAAE,KAAK,IAAI,EAAE;gBACd,MAAM,IAAI,KAAK,CACb,WAAW,UAAU,CAAC,IAAI,iCAAiC;oBACzD,yDAAyD,CAC5D,CAAC;YACJ,CAAC;YACD,QAAQ,EAAE;gBACR,aAAa,EAAE,UAAU,CAAC,aAAa;gBACvC,QAAQ,EAAE,UAAU,CAAC,QAAiD;gBACtE,gBAAgB,EACd,UAAU,CAAC,gBAAiE;gBAC9E,WAAW,EAAE,UAAU,CAAC,WAAW,IAAI,QAAQ;aAChD;SACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import type { WorkerProfile } from "./async/config/worker-profiles";
|
|
2
|
+
type LongDurationUnit = "second" | "seconds" | "minute" | "minutes" | "hour" | "hours" | "day" | "days";
|
|
3
|
+
type ShortDurationUnit = "ms" | "s" | "m" | "h" | "d";
|
|
4
|
+
/**
|
|
5
|
+
* Compile-time validated Temporal duration string.
|
|
6
|
+
* Supports long form ("6 hours", "30 minutes") and short form ("6h", "30m").
|
|
7
|
+
*/
|
|
8
|
+
export type DurationString = `${number} ${LongDurationUnit}` | `${number}${ShortDurationUnit}`;
|
|
9
|
+
/**
|
|
10
|
+
* Async (Temporal) runtime utilities injected into the step context.
|
|
11
|
+
* Available on `ctx` via intersection with the application context type.
|
|
12
|
+
*
|
|
13
|
+
* In async execution, these methods delegate to the Temporal activity context.
|
|
14
|
+
* In sync execution and tests, they are no-ops.
|
|
15
|
+
*/
|
|
16
|
+
export interface AsyncStepRuntime {
|
|
17
|
+
/**
|
|
18
|
+
* Report progress to Temporal. Call periodically in long-running activities to:
|
|
19
|
+
* 1. Prove liveness -- Temporal cancels the activity if no heartbeat arrives
|
|
20
|
+
* within `asyncHeartbeatTimeout`.
|
|
21
|
+
* 2. Record progress -- on retry, the new attempt can read the last heartbeat's
|
|
22
|
+
* details via `getHeartbeatDetails()` to resume work.
|
|
23
|
+
*
|
|
24
|
+
* `details` is any JSON-serializable value describing progress, e.g.
|
|
25
|
+
* `{ domainsIngested: 42000 }` or `{ phase: "uploading_to_s3" }`.
|
|
26
|
+
*/
|
|
27
|
+
heartbeat(details?: unknown): void;
|
|
28
|
+
/**
|
|
29
|
+
* Retrieve the most recent heartbeat details from a previous attempt.
|
|
30
|
+
* Returns `undefined` on the first attempt or when no heartbeat was recorded.
|
|
31
|
+
* Use with `heartbeat()` to implement resumable long-running activities.
|
|
32
|
+
*/
|
|
33
|
+
getHeartbeatDetails<T = unknown>(): T | undefined;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Per-step retry policy override. All fields are optional; unset fields
|
|
37
|
+
* fall back to the framework defaults (3 attempts, coefficient 2, 1s initial, 60s max).
|
|
38
|
+
*/
|
|
39
|
+
export interface StepRetryPolicy {
|
|
40
|
+
maximumAttempts?: number;
|
|
41
|
+
backoffCoefficient?: number;
|
|
42
|
+
initialInterval?: DurationString;
|
|
43
|
+
maximumInterval?: DurationString;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A Step represents a single unit of work in the workflow.
|
|
47
|
+
*
|
|
48
|
+
* Generic Parameters:
|
|
49
|
+
* - Bag: The complete data type that flows through the workflow
|
|
50
|
+
* - Needs: Array of field names this step requires as input
|
|
51
|
+
* - Provides: Array of field names this step will output
|
|
52
|
+
* - Context: The execution context available to this step (default: unknown)
|
|
53
|
+
* - Name: The literal string type of the step name (enables compile-time step identity)
|
|
54
|
+
*
|
|
55
|
+
* The type system ensures:
|
|
56
|
+
* - Steps can only access fields they declare in 'needs'
|
|
57
|
+
* - Steps must return exactly the fields they declare in 'provides'
|
|
58
|
+
* - Dependencies are validated at compile-time
|
|
59
|
+
* - Each step has a unique type based on its name (for checkpoint validation)
|
|
60
|
+
*/
|
|
61
|
+
export type Step<Bag extends Record<string, any>, Needs extends readonly (keyof Bag)[], Provides extends readonly (keyof Bag)[], Context = unknown, Name extends string = string> = {
|
|
62
|
+
name: Name;
|
|
63
|
+
needs: Needs;
|
|
64
|
+
provides: Provides;
|
|
65
|
+
run: (context: Context & AsyncStepRuntime, bag: Pick<Bag, Needs[number]>) => Promise<{
|
|
66
|
+
[K in Provides[number]]: Bag[K];
|
|
67
|
+
}> | {
|
|
68
|
+
[K in Provides[number]]: Bag[K];
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Worker profile for Temporal execution - determines which worker pool this step runs on.
|
|
72
|
+
* If not specified, defaults to "standard".
|
|
73
|
+
* Only used for Temporal (async) execution. Sync execution ignores it.
|
|
74
|
+
*/
|
|
75
|
+
workerProfile?: WorkerProfile;
|
|
76
|
+
/**
|
|
77
|
+
* Maximum time the activity may run from start to completion.
|
|
78
|
+
* If not specified, defaults to "5 minutes".
|
|
79
|
+
* Only used for Temporal (async) execution. Sync execution ignores it.
|
|
80
|
+
*/
|
|
81
|
+
asyncStartToCloseTimeout?: DurationString;
|
|
82
|
+
/**
|
|
83
|
+
* Maximum time between heartbeats before Temporal considers the activity dead.
|
|
84
|
+
* When set, the step should call `ctx.heartbeat()` periodically.
|
|
85
|
+
* If not specified, no heartbeat timeout is enforced.
|
|
86
|
+
* Only used for Temporal (async) execution. Sync execution ignores it.
|
|
87
|
+
*/
|
|
88
|
+
asyncHeartbeatTimeout?: DurationString;
|
|
89
|
+
/**
|
|
90
|
+
* Per-step retry policy override. Unset fields fall back to framework defaults.
|
|
91
|
+
* Only used for Temporal (async) execution. Sync execution ignores it.
|
|
92
|
+
*/
|
|
93
|
+
asyncRetry?: StepRetryPolicy;
|
|
94
|
+
/**
|
|
95
|
+
* Workflow path tracks the logical ancestry of this step for observability.
|
|
96
|
+
* Used to create proper span hierarchy even when steps are flattened.
|
|
97
|
+
* Example: ["parentWorkflow", "childWorkflow"] for a step in a composed child workflow
|
|
98
|
+
*/
|
|
99
|
+
workflowPath?: string[];
|
|
100
|
+
/**
|
|
101
|
+
* Original run function before validation wrapper was applied.
|
|
102
|
+
* Used for versioning/hashing to detect actual implementation changes.
|
|
103
|
+
* This is an internal field and should not be called directly - use `run` instead.
|
|
104
|
+
* @internal
|
|
105
|
+
*/
|
|
106
|
+
_originalRun?: (context: Context & AsyncStepRuntime, bag: Pick<Bag, Needs[number]>) => Promise<{
|
|
107
|
+
[K in Provides[number]]: Bag[K];
|
|
108
|
+
}> | {
|
|
109
|
+
[K in Provides[number]]: Bag[K];
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Type that represents valid JSON primitive values
|
|
114
|
+
*/
|
|
115
|
+
type JSONPrimitive = string | number | boolean | null;
|
|
116
|
+
/**
|
|
117
|
+
* Type representing non-serializable types that should be caught at compile time.
|
|
118
|
+
* Must stay in sync with the runtime check in validateSerializable() above.
|
|
119
|
+
*/
|
|
120
|
+
type NonSerializableType = Date | Map<any, any> | Set<any> | ((...args: any[]) => any) | symbol | bigint;
|
|
121
|
+
/**
|
|
122
|
+
* Depth-limited serializability checking using tuple-based recursion.
|
|
123
|
+
*
|
|
124
|
+
* Uses a depth counter pattern to avoid TypeScript's "excessive stack depth" error
|
|
125
|
+
* while still catching nested non-serializable types up to 4 levels deep.
|
|
126
|
+
*
|
|
127
|
+
* This catches patterns like:
|
|
128
|
+
* - { foo: Date } (Level 1)
|
|
129
|
+
* - { foo: { bar: Date } } (Level 2)
|
|
130
|
+
* - { foo: { bar: { baz: Date } } } (Level 3)
|
|
131
|
+
* - Arrays at any level: [{ nested: { date: Date } }]
|
|
132
|
+
*
|
|
133
|
+
* Runtime validateSerializable() provides comprehensive checking for deeper nesting.
|
|
134
|
+
*/
|
|
135
|
+
/** Depth decrement: Decr[D] = D-1, with Decr[0] = never as stop signal. */
|
|
136
|
+
type Decr = [never, 0, 1, 2];
|
|
137
|
+
/** Depth increment for NonSerializableProp search. */
|
|
138
|
+
type Incr = [1, 2, 3, 4];
|
|
139
|
+
/**
|
|
140
|
+
* Checks if a type is JSON-serializable up to D levels deep.
|
|
141
|
+
*
|
|
142
|
+
* Depth behavior:
|
|
143
|
+
* - D=0: Only checks if T itself is a primitive or NonSerializableType
|
|
144
|
+
* - D=1: Checks T and its direct children
|
|
145
|
+
* - D=2: Checks T, children, and grandchildren
|
|
146
|
+
* - D=3: Checks 4 levels deep (default)
|
|
147
|
+
*/
|
|
148
|
+
type IsSerializable<T, D extends number = 3> = T extends JSONPrimitive | undefined ? true : T extends NonSerializableType ? false : D extends 0 ? true : T extends Array<infer U> ? IsSerializable<U, Decr[D]> : T extends object ? false extends IsSerializable<T[keyof T], Decr[D]> ? false : true : true;
|
|
149
|
+
/**
|
|
150
|
+
* Find a top-level property that fails serialization at depth D.
|
|
151
|
+
* D=0 checks for directly non-serializable types; D>0 uses IsSerializable.
|
|
152
|
+
*/
|
|
153
|
+
type FindPropFailingAt<T, D extends number> = T extends object ? D extends 0 ? {
|
|
154
|
+
[K in keyof T]: T[K] extends NonSerializableType ? K : never;
|
|
155
|
+
}[keyof T] : {
|
|
156
|
+
[K in keyof T]: IsSerializable<T[K], Decr[D]> extends false ? K : never;
|
|
157
|
+
}[keyof T] : never;
|
|
158
|
+
/**
|
|
159
|
+
* Find a top-level property containing non-serializable data.
|
|
160
|
+
* Searches from shallowest (D=0) to deepest (D=3) to find the most relevant property.
|
|
161
|
+
*/
|
|
162
|
+
type NonSerializableProp<T, D extends number = 0> = T extends object ? D extends 4 ? never : FindPropFailingAt<T, D> extends never ? NonSerializableProp<T, Incr[D]> : FindPropFailingAt<T, D> : never;
|
|
163
|
+
/**
|
|
164
|
+
* Error type that includes the offending property name in the error message.
|
|
165
|
+
*/
|
|
166
|
+
type SerializationErrorWithProp<PropName> = PropName extends string ? {
|
|
167
|
+
[K in `SERIALIZATION_ERROR: Property '${PropName}' contains non-serializable type (Date/Map/Set/Function/Symbol/BigInt). Use toSerializable()`]: never;
|
|
168
|
+
} : {
|
|
169
|
+
"SERIALIZATION_ERROR: Contains non-serializable type. Use toSerializable()": never;
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Type assertion that produces a compile error if T contains non-serializable types.
|
|
173
|
+
* Returns T unchanged if serializable, otherwise returns an error type with the property name.
|
|
174
|
+
*
|
|
175
|
+
* This provides compile-time feedback with a clear, actionable error message.
|
|
176
|
+
*/
|
|
177
|
+
export type AssertSerializable<T> = IsSerializable<T> extends true ? T : SerializationErrorWithProp<NonSerializableProp<T>>;
|
|
178
|
+
/**
|
|
179
|
+
* COMPILE-TIME vs RUNTIME VALIDATION:
|
|
180
|
+
*
|
|
181
|
+
* What we CAN catch at compile-time:
|
|
182
|
+
* ✅ Properties that exist in the Bag type but are not in the 'provides' array
|
|
183
|
+
* Example: If Bag has 'foo' but provides is ['rules'], returning { rules, foo } will error
|
|
184
|
+
*
|
|
185
|
+
* What we CANNOT catch at compile-time (TypeScript limitation):
|
|
186
|
+
* ❌ Properties that don't exist in the Bag type at all
|
|
187
|
+
* Example: If 'baz' is not in Bag, returning { priceCents, baz } will NOT error at compile time
|
|
188
|
+
* This is due to TypeScript's structural typing allowing extra properties in object literals
|
|
189
|
+
*
|
|
190
|
+
* Solution: We use a hybrid approach:
|
|
191
|
+
* 1. Compile-time checking for properties in Bag (StrictStepReturn type)
|
|
192
|
+
* 2. Runtime validation for ALL excess properties (validateStepReturn function)
|
|
193
|
+
*/
|
|
194
|
+
type PropertyNotInProvidesError<K extends PropertyKey> = `❌ ERROR: Property '${K extends string ? K : string}' is not in the 'provides' array. Either remove it from the return value or add it to 'provides'.`;
|
|
195
|
+
export type StrictStepReturn<Bag, Keys extends keyof Bag> = {
|
|
196
|
+
[K in Keys]: Bag[K];
|
|
197
|
+
} & {
|
|
198
|
+
[K in keyof Bag as K extends Keys ? never : K]?: PropertyNotInProvidesError<K>;
|
|
199
|
+
};
|
|
200
|
+
/**
|
|
201
|
+
* Factory function for creating type-safe steps with validation.
|
|
202
|
+
*
|
|
203
|
+
* This function provides:
|
|
204
|
+
* 1. Clean generic inference - you don't need to specify types manually
|
|
205
|
+
* 2. Compile-time validation via StrictStepReturn type
|
|
206
|
+
* 3. Runtime validation wrapper for additional safety
|
|
207
|
+
*
|
|
208
|
+
* Usage:
|
|
209
|
+
* const myStep = step<Bag, MyContext>()({
|
|
210
|
+
* name: "processData",
|
|
211
|
+
* needs: ["input"],
|
|
212
|
+
* provides: ["output"],
|
|
213
|
+
* run: async (context, bag) => ({ output: processInput(bag.input) })
|
|
214
|
+
* });
|
|
215
|
+
*
|
|
216
|
+
* The double function call pattern allows TypeScript to infer the Bag type
|
|
217
|
+
* from the first call, then infer Needs/Provides from the step definition.
|
|
218
|
+
*/
|
|
219
|
+
export declare function step<Bag extends Record<string, any>, Context = unknown>(): <const Name extends string, const Needs extends readonly (keyof Bag)[], const Provides extends readonly (keyof Bag)[]>(stepDefinition: {
|
|
220
|
+
name: Name;
|
|
221
|
+
needs: Needs;
|
|
222
|
+
provides: Provides;
|
|
223
|
+
workerProfile?: WorkerProfile;
|
|
224
|
+
asyncStartToCloseTimeout?: DurationString;
|
|
225
|
+
asyncHeartbeatTimeout?: DurationString;
|
|
226
|
+
asyncRetry?: StepRetryPolicy;
|
|
227
|
+
run: (context: Context & AsyncStepRuntime, bag: Pick<Bag, Needs[number]>) => Promise<AssertSerializable<StrictStepReturn<Bag, Provides[number]>>> | AssertSerializable<StrictStepReturn<Bag, Provides[number]>>;
|
|
228
|
+
}) => Step<Bag, Needs, Provides, Context, Name>;
|
|
229
|
+
export {};
|
|
230
|
+
//# sourceMappingURL=dag-sync-step.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-sync-step.d.ts","sourceRoot":"","sources":["../../src/internal/dag-sync-step.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.step = step;
|
|
4
|
+
/**
|
|
5
|
+
* Validates that a value is JSON-serializable for Temporal activity boundaries.
|
|
6
|
+
* Returns detailed error information about non-serializable values.
|
|
7
|
+
*/
|
|
8
|
+
function validateSerializable(value, path = "root") {
|
|
9
|
+
// Handle primitives and special cases using a switch statement
|
|
10
|
+
if (value === null || value === undefined) {
|
|
11
|
+
return { valid: true };
|
|
12
|
+
}
|
|
13
|
+
const valueType = typeof value;
|
|
14
|
+
switch (valueType) {
|
|
15
|
+
case "string":
|
|
16
|
+
case "number":
|
|
17
|
+
case "boolean":
|
|
18
|
+
return { valid: true };
|
|
19
|
+
case "object":
|
|
20
|
+
// Check for Date
|
|
21
|
+
if (value instanceof Date) {
|
|
22
|
+
return {
|
|
23
|
+
valid: false,
|
|
24
|
+
path,
|
|
25
|
+
type: "Date",
|
|
26
|
+
value,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
// Check for Map/Set - these serialize to {} and lose all data
|
|
30
|
+
if (value instanceof Map) {
|
|
31
|
+
return {
|
|
32
|
+
valid: false,
|
|
33
|
+
path,
|
|
34
|
+
type: "Map",
|
|
35
|
+
value: `Map with ${value.size} entries`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
if (value instanceof Set) {
|
|
39
|
+
return {
|
|
40
|
+
valid: false,
|
|
41
|
+
path,
|
|
42
|
+
type: "Set",
|
|
43
|
+
value: `Set with ${value.size} entries`,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// Handle arrays
|
|
47
|
+
if (Array.isArray(value)) {
|
|
48
|
+
for (let i = 0; i < value.length; i++) {
|
|
49
|
+
const result = validateSerializable(value[i], `${path}[${i}]`);
|
|
50
|
+
if (!result.valid) {
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return { valid: true };
|
|
55
|
+
}
|
|
56
|
+
// Handle plain objects
|
|
57
|
+
for (const [key, val] of Object.entries(value)) {
|
|
58
|
+
const result = validateSerializable(val, `${path}.${key}`);
|
|
59
|
+
if (!result.valid) {
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return { valid: true };
|
|
64
|
+
default:
|
|
65
|
+
// Unknown type
|
|
66
|
+
return {
|
|
67
|
+
valid: false,
|
|
68
|
+
path,
|
|
69
|
+
type: valueType,
|
|
70
|
+
value: String(value).slice(0, 100),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Runtime validation function that ensures step return objects contain exactly
|
|
76
|
+
* the properties declared in the 'provides' array - no more, no less.
|
|
77
|
+
*
|
|
78
|
+
* This provides a safety net to catch:
|
|
79
|
+
* 1. Excess properties that TypeScript's structural typing might allow through
|
|
80
|
+
* 2. Missing properties when TypeScript is bypassed with 'as any'
|
|
81
|
+
* 3. Non-serializable values that would fail when crossing Temporal boundaries
|
|
82
|
+
*
|
|
83
|
+
* The return type strips compile-time assertion wrappers (AssertSerializable, StrictStepReturn)
|
|
84
|
+
* and returns the clean mapped type. This is safe because:
|
|
85
|
+
* - If the input had non-serializable types, we'd have a compile error at the call site
|
|
86
|
+
* - The runtime validation throws if the actual value doesn't match provides
|
|
87
|
+
*/
|
|
88
|
+
function validateStepReturn(result, provides) {
|
|
89
|
+
const expected = result;
|
|
90
|
+
const returnKeys = Object.keys(expected);
|
|
91
|
+
const providesKeys = provides.map(String);
|
|
92
|
+
// Check for unexpected extra properties
|
|
93
|
+
for (const key of returnKeys) {
|
|
94
|
+
if (!providesKeys.includes(key)) {
|
|
95
|
+
throw new Error(`Step returned unexpected property "${key}". Only properties declared in "provides" are allowed: [${providesKeys.join(", ")}]\n\n` +
|
|
96
|
+
`💡 Fix: Either remove "${key}" from the return object, or add "${key}" to the "provides" array.`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Check for missing required properties
|
|
100
|
+
for (const key of providesKeys) {
|
|
101
|
+
if (!(key in expected)) {
|
|
102
|
+
throw new Error(`Step failed to return required property "${key}". All properties declared in "provides" must be returned: [${providesKeys.join(", ")}]\n\n` +
|
|
103
|
+
`💡 Fix: Make sure your step returns an object containing "${key}".`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Validate serializability (critical for async Temporal workflows)
|
|
107
|
+
const serializationResult = validateSerializable(expected);
|
|
108
|
+
if (!serializationResult.valid) {
|
|
109
|
+
throw new Error(`Step returned non-serializable value at path "${serializationResult.path}".\n` +
|
|
110
|
+
`Type: ${serializationResult.type}\n` +
|
|
111
|
+
`Value: ${JSON.stringify(serializationResult.value, null, 2)}\n\n` +
|
|
112
|
+
`💡 Fix: Use toSerializable() to convert values before returning from steps.\n` +
|
|
113
|
+
` All values must be JSON-serializable because they cross Temporal activity boundaries.\n\n` +
|
|
114
|
+
` - Date objects: toSerializable() converts these to ISO strings automatically\n` +
|
|
115
|
+
` - MikroORM entities: toSerializable() handles Refs, Collections, and getters\n` +
|
|
116
|
+
` - Map/Set: Convert to objects or arrays first (Object.fromEntries() / Array.from())\n` +
|
|
117
|
+
` - Functions: Return their results, not the functions themselves\n` +
|
|
118
|
+
` - BigInt: Convert to number or string first`);
|
|
119
|
+
}
|
|
120
|
+
// Cast is safe: we've validated the object matches the provides array exactly
|
|
121
|
+
return expected;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Factory function for creating type-safe steps with validation.
|
|
125
|
+
*
|
|
126
|
+
* This function provides:
|
|
127
|
+
* 1. Clean generic inference - you don't need to specify types manually
|
|
128
|
+
* 2. Compile-time validation via StrictStepReturn type
|
|
129
|
+
* 3. Runtime validation wrapper for additional safety
|
|
130
|
+
*
|
|
131
|
+
* Usage:
|
|
132
|
+
* const myStep = step<Bag, MyContext>()({
|
|
133
|
+
* name: "processData",
|
|
134
|
+
* needs: ["input"],
|
|
135
|
+
* provides: ["output"],
|
|
136
|
+
* run: async (context, bag) => ({ output: processInput(bag.input) })
|
|
137
|
+
* });
|
|
138
|
+
*
|
|
139
|
+
* The double function call pattern allows TypeScript to infer the Bag type
|
|
140
|
+
* from the first call, then infer Needs/Provides from the step definition.
|
|
141
|
+
*/
|
|
142
|
+
function step() {
|
|
143
|
+
return (stepDefinition) => {
|
|
144
|
+
const originalRun = stepDefinition.run;
|
|
145
|
+
const wrappedRun = async (context, bag) => {
|
|
146
|
+
const result = await originalRun(context, bag);
|
|
147
|
+
return validateStepReturn(result, stepDefinition.provides);
|
|
148
|
+
};
|
|
149
|
+
return {
|
|
150
|
+
...stepDefinition,
|
|
151
|
+
run: wrappedRun,
|
|
152
|
+
// Cast needed: originalRun's return type includes compile-time assertion wrappers
|
|
153
|
+
// (AssertSerializable, StrictStepReturn) but _originalRun expects the clean type.
|
|
154
|
+
// The wrappers only produce errors at compile-time; at runtime it's always the valid type.
|
|
155
|
+
_originalRun: originalRun,
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=dag-sync-step.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-sync-step.js","sourceRoot":"","sources":["../../src/internal/dag-sync-step.ts"],"names":[],"mappings":"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"}
|