@temporal-contract/worker 0.2.0 → 1.0.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.
- package/README.md +7 -8
- package/dist/activity.cjs +44 -119
- package/dist/activity.d.cts +37 -27
- package/dist/activity.d.cts.map +1 -1
- package/dist/activity.d.mts +37 -27
- package/dist/activity.d.mts.map +1 -1
- package/dist/activity.mjs +32 -107
- package/dist/activity.mjs.map +1 -1
- package/dist/{errors-4jH78z8m.d.cts → errors-CG1y7SHO.d.cts} +14 -2
- package/dist/{errors-4jH78z8m.d.cts.map → errors-CG1y7SHO.d.cts.map} +1 -1
- package/dist/{errors-CmTXZ3JW.d.mts → errors-DZhaNhwr.d.mts} +14 -2
- package/dist/{errors-CmTXZ3JW.d.mts.map → errors-DZhaNhwr.d.mts.map} +1 -1
- package/dist/internal-BoNcEtYh.mjs +354 -0
- package/dist/internal-BoNcEtYh.mjs.map +1 -0
- package/dist/internal-Tj4m4f_K.cjs +453 -0
- package/dist/worker.cjs +2 -4
- package/dist/worker.mjs +1 -2
- package/dist/worker.mjs.map +1 -1
- package/dist/workflow.cjs +247 -136
- package/dist/workflow.d.cts +154 -31
- package/dist/workflow.d.cts.map +1 -1
- package/dist/workflow.d.mts +154 -31
- package/dist/workflow.d.mts.map +1 -1
- package/dist/workflow.mjs +231 -120
- package/dist/workflow.mjs.map +1 -1
- package/package.json +23 -24
- package/dist/activity-utils-B3vP03_P.d.mts +0 -68
- package/dist/activity-utils-B3vP03_P.d.mts.map +0 -1
- package/dist/activity-utils-RsXOceIH.d.cts +0 -68
- package/dist/activity-utils-RsXOceIH.d.cts.map +0 -1
- package/dist/errors-Di6Ja4Rt.mjs +0 -156
- package/dist/errors-Di6Ja4Rt.mjs.map +0 -1
- package/dist/errors-DjSZg-93.cjs +0 -227
package/dist/workflow.mjs
CHANGED
|
@@ -1,7 +1,147 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { _ as formatChildWorkflowValidationMessage, a as ActivityInputValidationError, c as ChildWorkflowNotFoundError, d as SignalInputValidationError, f as UpdateInputValidationError, g as WorkflowOutputValidationError, h as WorkflowInputValidationError, l as QueryInputValidationError, m as WorkflowCancelledError, n as createContinueAsNew, o as ActivityOutputValidationError, p as UpdateOutputValidationError, r as extractHandlerInput, s as ChildWorkflowError, t as buildRawActivitiesProxy, u as QueryOutputValidationError } from "./internal-BoNcEtYh.mjs";
|
|
2
|
+
import { CancellationScope, defineQuery, defineSignal, defineUpdate, executeChild, isCancellation, setHandler, startChild, workflowInfo } from "@temporalio/workflow";
|
|
2
3
|
import { Future, Result } from "@temporal-contract/boxed";
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
//#region src/cancellation.ts
|
|
5
|
+
/**
|
|
6
|
+
* Typed wrappers around Temporal's `CancellationScope` so workflows can
|
|
7
|
+
* opt into cancellation control without reaching for
|
|
8
|
+
* `@temporalio/workflow` directly. The wrappers fold cancellation into
|
|
9
|
+
* the same `Future<Result<...>>` shape used elsewhere in the worker
|
|
10
|
+
* context — callers branch on `Result.Error(WorkflowCancelledError)`
|
|
11
|
+
* instead of catching `CancelledFailure`.
|
|
12
|
+
*
|
|
13
|
+
* Non-cancellation errors thrown inside the scope are *not* swallowed:
|
|
14
|
+
* the Future rejects with the original error so user-domain failures
|
|
15
|
+
* keep their identity.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Run `fn` inside a cancellable Temporal scope. If the workflow (or an
|
|
19
|
+
* ancestor scope) is cancelled while the function is in flight, the
|
|
20
|
+
* resulting Future resolves to `Result.Error(WorkflowCancelledError)`,
|
|
21
|
+
* letting callers handle cancellation explicitly — typically to perform
|
|
22
|
+
* a graceful exit from the current step.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const result = await context.cancellableScope(async () => {
|
|
27
|
+
* return await context.activities.processStep(...);
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* result.match({
|
|
31
|
+
* Ok: (output) => { ... },
|
|
32
|
+
* Error: (err) => {
|
|
33
|
+
* // err instanceof WorkflowCancelledError — graceful exit
|
|
34
|
+
* },
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
function cancellableScope(fn) {
|
|
39
|
+
return Future.fromAsync(async () => {
|
|
40
|
+
try {
|
|
41
|
+
const value = await CancellationScope.cancellable(async () => fn());
|
|
42
|
+
return Result.Ok(value);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if (isCancellation(error)) return Result.Error(new WorkflowCancelledError(error));
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Run `fn` inside a non-cancellable Temporal scope. Cancellation requests
|
|
51
|
+
* from outside the scope are ignored for its duration — the idiomatic way
|
|
52
|
+
* to perform cleanup that must not be interrupted (e.g. releasing a
|
|
53
|
+
* resource after a graceful shutdown).
|
|
54
|
+
*
|
|
55
|
+
* Mirrors `cancellableScope`'s `Future<Result<...>>` shape for symmetry;
|
|
56
|
+
* the `Result.Error` branch only triggers when cancellation is raised
|
|
57
|
+
* from inside the scope (rare).
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* await context.nonCancellableScope(async () => {
|
|
62
|
+
* await context.activities.releaseResources(...);
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
function nonCancellableScope(fn) {
|
|
67
|
+
return Future.fromAsync(async () => {
|
|
68
|
+
try {
|
|
69
|
+
const value = await CancellationScope.nonCancellable(async () => fn());
|
|
70
|
+
return Result.Ok(value);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (isCancellation(error)) return Result.Error(new WorkflowCancelledError(error));
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/handlers.ts
|
|
79
|
+
/**
|
|
80
|
+
* Bind a typed signal handler to the running workflow. Validates the
|
|
81
|
+
* signal payload against the contract's input schema before invoking the
|
|
82
|
+
* user-supplied handler.
|
|
83
|
+
*
|
|
84
|
+
* The runtime guard against a missing `signals` block — and an unknown
|
|
85
|
+
* signal name within it — covers the union-typed-`workflowName` case
|
|
86
|
+
* where the type system's keyset constraint collapses; without the
|
|
87
|
+
* check, a caller would see `Cannot read properties of undefined`
|
|
88
|
+
* instead of a controlled error.
|
|
89
|
+
*/
|
|
90
|
+
function bindSignalHandler(workflowDefinition, workflowName, signalName, handler) {
|
|
91
|
+
if (!workflowDefinition.signals) throw new Error(`Signal "${signalName}" cannot be defined: workflow "${workflowName}" has no signals in its contract`);
|
|
92
|
+
const signalDef = workflowDefinition.signals[signalName];
|
|
93
|
+
if (!signalDef) throw new Error(`Signal "${signalName}" not found in workflow "${workflowName}" contract`);
|
|
94
|
+
setHandler(defineSignal(signalName), async (...args) => {
|
|
95
|
+
const input = extractHandlerInput(args);
|
|
96
|
+
const inputResult = await signalDef.input["~standard"].validate(input);
|
|
97
|
+
if (inputResult.issues) throw new SignalInputValidationError(signalName, inputResult.issues);
|
|
98
|
+
await handler(inputResult.value);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Bind a typed query handler to the running workflow. Validates input
|
|
103
|
+
* and output against the contract synchronously.
|
|
104
|
+
*
|
|
105
|
+
* Temporal's query API requires a synchronous handler — async
|
|
106
|
+
* validation breaks replay determinism. The handler trips a clear error
|
|
107
|
+
* if the schema library returns a Promise from `validate(...)`, instead
|
|
108
|
+
* of letting the async path silently corrupt query semantics.
|
|
109
|
+
*/
|
|
110
|
+
function bindQueryHandler(workflowDefinition, workflowName, queryName, handler) {
|
|
111
|
+
if (!workflowDefinition.queries) throw new Error(`Query "${queryName}" cannot be defined: workflow "${workflowName}" has no queries in its contract`);
|
|
112
|
+
const queryDef = workflowDefinition.queries[queryName];
|
|
113
|
+
if (!queryDef) throw new Error(`Query "${queryName}" not found in workflow "${workflowName}" contract`);
|
|
114
|
+
setHandler(defineQuery(queryName), (...args) => {
|
|
115
|
+
const input = extractHandlerInput(args);
|
|
116
|
+
const inputResult = queryDef.input["~standard"].validate(input);
|
|
117
|
+
if (inputResult instanceof Promise) throw new Error(`Query "${queryName}" validation must be synchronous. Use a schema library that supports synchronous validation for queries.`);
|
|
118
|
+
if (inputResult.issues) throw new QueryInputValidationError(queryName, inputResult.issues);
|
|
119
|
+
const result = handler(inputResult.value);
|
|
120
|
+
const outputResult = queryDef.output["~standard"].validate(result);
|
|
121
|
+
if (outputResult instanceof Promise) throw new Error(`Query "${queryName}" output validation must be synchronous. Use a schema library that supports synchronous validation for queries.`);
|
|
122
|
+
if (outputResult.issues) throw new QueryOutputValidationError(queryName, outputResult.issues);
|
|
123
|
+
return outputResult.value;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Bind a typed update handler to the running workflow. Validates both
|
|
128
|
+
* input and output (asynchronously, like signals).
|
|
129
|
+
*/
|
|
130
|
+
function bindUpdateHandler(workflowDefinition, workflowName, updateName, handler) {
|
|
131
|
+
if (!workflowDefinition.updates) throw new Error(`Update "${updateName}" cannot be defined: workflow "${workflowName}" has no updates in its contract`);
|
|
132
|
+
const updateDef = workflowDefinition.updates[updateName];
|
|
133
|
+
if (!updateDef) throw new Error(`Update "${updateName}" not found in workflow "${workflowName}" contract`);
|
|
134
|
+
setHandler(defineUpdate(updateName), async (...args) => {
|
|
135
|
+
const input = extractHandlerInput(args);
|
|
136
|
+
const inputResult = await updateDef.input["~standard"].validate(input);
|
|
137
|
+
if (inputResult.issues) throw new UpdateInputValidationError(updateName, inputResult.issues);
|
|
138
|
+
const result = await handler(inputResult.value);
|
|
139
|
+
const outputResult = await updateDef.output["~standard"].validate(result);
|
|
140
|
+
if (outputResult.issues) throw new UpdateOutputValidationError(updateName, outputResult.issues);
|
|
141
|
+
return outputResult.value;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
//#endregion
|
|
5
145
|
//#region src/workflow.ts
|
|
6
146
|
/**
|
|
7
147
|
* Create a typed workflow implementation with automatic validation
|
|
@@ -26,6 +166,15 @@ import { defineQuery, defineSignal, defineUpdate, executeChild, proxyActivities,
|
|
|
26
166
|
* activityOptions: {
|
|
27
167
|
* startToCloseTimeout: '1 minute',
|
|
28
168
|
* },
|
|
169
|
+
* // Optional: override `activityOptions` for specific activities. Each
|
|
170
|
+
* // entry shallow-merges over the workflow default — the override wins on
|
|
171
|
+
* // every property it specifies, including the whole `retry` block.
|
|
172
|
+
* activityOptionsByName: {
|
|
173
|
+
* chargePayment: {
|
|
174
|
+
* startToCloseTimeout: '5 minutes',
|
|
175
|
+
* retry: { maximumAttempts: 5 },
|
|
176
|
+
* },
|
|
177
|
+
* },
|
|
29
178
|
* implementation: async (context, args) => {
|
|
30
179
|
* // context.activities: typed activities (workflow + global)
|
|
31
180
|
* // context.info: WorkflowInfo
|
|
@@ -67,132 +216,26 @@ import { defineQuery, defineSignal, defineUpdate, executeChild, proxyActivities,
|
|
|
67
216
|
* });
|
|
68
217
|
* ```
|
|
69
218
|
*/
|
|
70
|
-
function declareWorkflow({ workflowName, contract, implementation, activityOptions }) {
|
|
219
|
+
function declareWorkflow({ workflowName, contract, implementation, activityOptions, activityOptionsByName }) {
|
|
71
220
|
const definition = contract.workflows[workflowName];
|
|
72
221
|
return async (...args) => {
|
|
73
|
-
const input = args
|
|
222
|
+
const input = extractHandlerInput(args);
|
|
74
223
|
const inputResult = await definition.input["~standard"].validate(input);
|
|
75
224
|
if (inputResult.issues) throw new WorkflowInputValidationError(String(workflowName), inputResult.issues);
|
|
76
225
|
const validatedInput = inputResult.value;
|
|
77
226
|
let contextActivities = {};
|
|
78
|
-
if (definition.activities || contract.activities) contextActivities = createValidatedActivities(
|
|
79
|
-
async function validateChildWorkflowOutput(childDefinition, result, childWorkflowName) {
|
|
80
|
-
const outputResult = await childDefinition.output["~standard"].validate(result);
|
|
81
|
-
if (outputResult.issues) return Result.Error(new ChildWorkflowError(`Child workflow "${childWorkflowName}" output validation failed: ${outputResult.issues.map((i) => i.message).join("; ")}`));
|
|
82
|
-
return Result.Ok(outputResult.value);
|
|
83
|
-
}
|
|
84
|
-
async function getAndValidateChildWorkflow(childContract, childWorkflowName, args) {
|
|
85
|
-
const childDefinition = childContract.workflows[childWorkflowName];
|
|
86
|
-
if (!childDefinition) return Result.Error(new ChildWorkflowNotFoundError(String(childWorkflowName), Object.keys(childContract.workflows)));
|
|
87
|
-
const inputResult = await childDefinition.input["~standard"].validate(args);
|
|
88
|
-
if (inputResult.issues) return Result.Error(new ChildWorkflowError(`Child workflow "${String(childWorkflowName)}" input validation failed: ${inputResult.issues.map((i) => i.message).join("; ")}`));
|
|
89
|
-
const validatedInput = inputResult.value;
|
|
90
|
-
return Result.Ok({
|
|
91
|
-
definition: childDefinition,
|
|
92
|
-
validatedInput,
|
|
93
|
-
taskQueue: childContract.taskQueue
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
function createTypedChildHandle(handle, childDefinition, childWorkflowName) {
|
|
97
|
-
return {
|
|
98
|
-
workflowId: handle.workflowId,
|
|
99
|
-
result: () => {
|
|
100
|
-
return Future.fromAsync(async () => {
|
|
101
|
-
try {
|
|
102
|
-
return validateChildWorkflowOutput(childDefinition, await handle.result(), childWorkflowName);
|
|
103
|
-
} catch (error) {
|
|
104
|
-
return Result.Error(new ChildWorkflowError(`Child workflow execution failed: ${error instanceof Error ? error.message : String(error)}`, error));
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
function createStartChildWorkflow(childContract, childWorkflowName, options) {
|
|
111
|
-
return Future.fromAsync(async () => {
|
|
112
|
-
const validationResult = await getAndValidateChildWorkflow(childContract, childWorkflowName, options.args);
|
|
113
|
-
if (validationResult.isError()) return Result.Error(validationResult.error);
|
|
114
|
-
const { definition: childDefinition, validatedInput, taskQueue } = validationResult.value;
|
|
115
|
-
try {
|
|
116
|
-
const { args: _args, ...temporalOptions } = options;
|
|
117
|
-
const typedHandle = createTypedChildHandle(await startChild(childWorkflowName, {
|
|
118
|
-
...temporalOptions,
|
|
119
|
-
taskQueue,
|
|
120
|
-
args: [validatedInput]
|
|
121
|
-
}), childDefinition, String(childWorkflowName));
|
|
122
|
-
return Result.Ok(typedHandle);
|
|
123
|
-
} catch (error) {
|
|
124
|
-
return Result.Error(new ChildWorkflowError(`Failed to start child workflow: ${error instanceof Error ? error.message : String(error)}`, error));
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
function createExecuteChildWorkflow(childContract, childWorkflowName, options) {
|
|
129
|
-
return Future.fromAsync(async () => {
|
|
130
|
-
const validationResult = await getAndValidateChildWorkflow(childContract, childWorkflowName, options.args);
|
|
131
|
-
if (validationResult.isError()) return Result.Error(validationResult.error);
|
|
132
|
-
const { definition: childDefinition, validatedInput, taskQueue } = validationResult.value;
|
|
133
|
-
try {
|
|
134
|
-
const { args: _args, ...temporalOptions } = options;
|
|
135
|
-
const outputValidationResult = await validateChildWorkflowOutput(childDefinition, await executeChild(childWorkflowName, {
|
|
136
|
-
...temporalOptions,
|
|
137
|
-
taskQueue,
|
|
138
|
-
args: [validatedInput]
|
|
139
|
-
}), String(childWorkflowName));
|
|
140
|
-
if (outputValidationResult.isError()) return Result.Error(outputValidationResult.error);
|
|
141
|
-
return Result.Ok(outputValidationResult.value);
|
|
142
|
-
} catch (error) {
|
|
143
|
-
return Result.Error(new ChildWorkflowError(`Failed to execute child workflow: ${error instanceof Error ? error.message : String(error)}`, error));
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
function createDefineSignal(signalName, handler) {
|
|
148
|
-
if (!definition.signals) throw new Error(`Signal "${String(signalName)}" cannot be defined: workflow "${String(workflowName)}" has no signals in its contract`);
|
|
149
|
-
const signalDef = definition.signals[signalName];
|
|
150
|
-
if (!signalDef) throw new Error(`Signal "${String(signalName)}" not found in workflow "${String(workflowName)}" contract`);
|
|
151
|
-
setHandler(defineSignal(signalName), async (...args) => {
|
|
152
|
-
const input = args.length === 1 ? args[0] : args;
|
|
153
|
-
const inputResult = await signalDef.input["~standard"].validate(input);
|
|
154
|
-
if (inputResult.issues) throw new SignalInputValidationError(signalName, inputResult.issues);
|
|
155
|
-
await handler(inputResult.value);
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
function createDefineQuery(queryName, handler) {
|
|
159
|
-
if (!definition.queries) throw new Error(`Query "${String(queryName)}" cannot be defined: workflow "${String(workflowName)}" has no queries in its contract`);
|
|
160
|
-
const queryDef = definition.queries[queryName];
|
|
161
|
-
if (!queryDef) throw new Error(`Query "${String(queryName)}" not found in workflow "${String(workflowName)}" contract`);
|
|
162
|
-
setHandler(defineQuery(queryName), (...args) => {
|
|
163
|
-
const input = args.length === 1 ? args[0] : args;
|
|
164
|
-
const inputResult = queryDef.input["~standard"].validate(input);
|
|
165
|
-
if (inputResult instanceof Promise) throw new Error(`Query "${String(queryName)}" validation must be synchronous. Use a schema library that supports synchronous validation for queries.`);
|
|
166
|
-
if (inputResult.issues) throw new QueryInputValidationError(queryName, inputResult.issues);
|
|
167
|
-
const result = handler(inputResult.value);
|
|
168
|
-
const outputResult = queryDef.output["~standard"].validate(result);
|
|
169
|
-
if (outputResult instanceof Promise) throw new Error(`Query "${String(queryName)}" output validation must be synchronous. Use a schema library that supports synchronous validation for queries.`);
|
|
170
|
-
if (outputResult.issues) throw new QueryOutputValidationError(queryName, outputResult.issues);
|
|
171
|
-
return outputResult.value;
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
function createDefineUpdate(updateName, handler) {
|
|
175
|
-
if (!definition.updates) throw new Error(`Update "${String(updateName)}" cannot be defined: workflow "${String(workflowName)}" has no updates in its contract`);
|
|
176
|
-
const updateDef = definition.updates[updateName];
|
|
177
|
-
if (!updateDef) throw new Error(`Update "${String(updateName)}" not found in workflow "${String(workflowName)}" contract`);
|
|
178
|
-
setHandler(defineUpdate(updateName), async (...args) => {
|
|
179
|
-
const input = args.length === 1 ? args[0] : args;
|
|
180
|
-
const inputResult = await updateDef.input["~standard"].validate(input);
|
|
181
|
-
if (inputResult.issues) throw new UpdateInputValidationError(updateName, inputResult.issues);
|
|
182
|
-
const result = await handler(inputResult.value);
|
|
183
|
-
const outputResult = await updateDef.output["~standard"].validate(result);
|
|
184
|
-
if (outputResult.issues) throw new UpdateOutputValidationError(updateName, outputResult.issues);
|
|
185
|
-
return outputResult.value;
|
|
186
|
-
});
|
|
187
|
-
}
|
|
227
|
+
if (definition.activities || contract.activities) contextActivities = createValidatedActivities(buildRawActivitiesProxy(definition.activities, contract.activities, activityOptions, activityOptionsByName), definition.activities, contract.activities);
|
|
188
228
|
const result = await implementation({
|
|
189
229
|
activities: contextActivities,
|
|
190
230
|
info: workflowInfo(),
|
|
191
231
|
startChildWorkflow: createStartChildWorkflow,
|
|
192
232
|
executeChildWorkflow: createExecuteChildWorkflow,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
233
|
+
cancellableScope,
|
|
234
|
+
nonCancellableScope,
|
|
235
|
+
defineSignal: ((signalName, handler) => bindSignalHandler(definition, String(workflowName), signalName, handler)),
|
|
236
|
+
defineQuery: ((queryName, handler) => bindQueryHandler(definition, String(workflowName), queryName, handler)),
|
|
237
|
+
defineUpdate: ((updateName, handler) => bindUpdateHandler(definition, String(workflowName), updateName, handler)),
|
|
238
|
+
continueAsNew: createContinueAsNew(contract, workflowName)
|
|
196
239
|
}, validatedInput);
|
|
197
240
|
const outputResult = await definition.output["~standard"].validate(result);
|
|
198
241
|
if (outputResult.issues) throw new WorkflowOutputValidationError(String(workflowName), outputResult.issues);
|
|
@@ -225,7 +268,75 @@ function createValidatedActivities(rawActivities, workflowActivitiesDefinition,
|
|
|
225
268
|
}
|
|
226
269
|
return validatedActivities;
|
|
227
270
|
}
|
|
228
|
-
|
|
271
|
+
async function validateChildWorkflowOutput(childDefinition, result, childWorkflowName) {
|
|
272
|
+
const outputResult = await childDefinition.output["~standard"].validate(result);
|
|
273
|
+
if (outputResult.issues) return Result.Error(new ChildWorkflowError(formatChildWorkflowValidationMessage(childWorkflowName, "output", outputResult.issues)));
|
|
274
|
+
return Result.Ok(outputResult.value);
|
|
275
|
+
}
|
|
276
|
+
async function getAndValidateChildWorkflow(childContract, childWorkflowName, args) {
|
|
277
|
+
const childDefinition = childContract.workflows[childWorkflowName];
|
|
278
|
+
if (!childDefinition) return Result.Error(new ChildWorkflowNotFoundError(String(childWorkflowName), Object.keys(childContract.workflows)));
|
|
279
|
+
const inputResult = await childDefinition.input["~standard"].validate(args);
|
|
280
|
+
if (inputResult.issues) return Result.Error(new ChildWorkflowError(formatChildWorkflowValidationMessage(String(childWorkflowName), "input", inputResult.issues)));
|
|
281
|
+
const validatedInput = inputResult.value;
|
|
282
|
+
return Result.Ok({
|
|
283
|
+
definition: childDefinition,
|
|
284
|
+
validatedInput,
|
|
285
|
+
taskQueue: childContract.taskQueue
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
function createTypedChildHandle(handle, childDefinition, childWorkflowName) {
|
|
289
|
+
return {
|
|
290
|
+
workflowId: handle.workflowId,
|
|
291
|
+
result: () => {
|
|
292
|
+
return Future.fromAsync(async () => {
|
|
293
|
+
try {
|
|
294
|
+
return validateChildWorkflowOutput(childDefinition, await handle.result(), childWorkflowName);
|
|
295
|
+
} catch (error) {
|
|
296
|
+
return Result.Error(new ChildWorkflowError(`Child workflow execution failed: ${error instanceof Error ? error.message : String(error)}`, error));
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
function createStartChildWorkflow(childContract, childWorkflowName, options) {
|
|
303
|
+
return Future.fromAsync(async () => {
|
|
304
|
+
const validationResult = await getAndValidateChildWorkflow(childContract, childWorkflowName, options.args);
|
|
305
|
+
if (validationResult.isError()) return Result.Error(validationResult.error);
|
|
306
|
+
const { definition: childDefinition, validatedInput, taskQueue } = validationResult.value;
|
|
307
|
+
try {
|
|
308
|
+
const { args: _args, ...temporalOptions } = options;
|
|
309
|
+
const typedHandle = createTypedChildHandle(await startChild(childWorkflowName, {
|
|
310
|
+
...temporalOptions,
|
|
311
|
+
taskQueue,
|
|
312
|
+
args: [validatedInput]
|
|
313
|
+
}), childDefinition, String(childWorkflowName));
|
|
314
|
+
return Result.Ok(typedHandle);
|
|
315
|
+
} catch (error) {
|
|
316
|
+
return Result.Error(new ChildWorkflowError(`Failed to start child workflow: ${error instanceof Error ? error.message : String(error)}`, error));
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
function createExecuteChildWorkflow(childContract, childWorkflowName, options) {
|
|
321
|
+
return Future.fromAsync(async () => {
|
|
322
|
+
const validationResult = await getAndValidateChildWorkflow(childContract, childWorkflowName, options.args);
|
|
323
|
+
if (validationResult.isError()) return Result.Error(validationResult.error);
|
|
324
|
+
const { definition: childDefinition, validatedInput, taskQueue } = validationResult.value;
|
|
325
|
+
try {
|
|
326
|
+
const { args: _args, ...temporalOptions } = options;
|
|
327
|
+
const outputValidationResult = await validateChildWorkflowOutput(childDefinition, await executeChild(childWorkflowName, {
|
|
328
|
+
...temporalOptions,
|
|
329
|
+
taskQueue,
|
|
330
|
+
args: [validatedInput]
|
|
331
|
+
}), String(childWorkflowName));
|
|
332
|
+
if (outputValidationResult.isError()) return Result.Error(outputValidationResult.error);
|
|
333
|
+
return Result.Ok(outputValidationResult.value);
|
|
334
|
+
} catch (error) {
|
|
335
|
+
return Result.Error(new ChildWorkflowError(`Failed to execute child workflow: ${error instanceof Error ? error.message : String(error)}`, error));
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
}
|
|
229
339
|
//#endregion
|
|
230
|
-
export { ActivityInputValidationError, ActivityOutputValidationError, ChildWorkflowError, ChildWorkflowNotFoundError, QueryInputValidationError, QueryOutputValidationError, SignalInputValidationError, UpdateInputValidationError, UpdateOutputValidationError, WorkflowInputValidationError, WorkflowOutputValidationError, declareWorkflow };
|
|
340
|
+
export { ActivityInputValidationError, ActivityOutputValidationError, ChildWorkflowError, ChildWorkflowNotFoundError, QueryInputValidationError, QueryOutputValidationError, SignalInputValidationError, UpdateInputValidationError, UpdateOutputValidationError, WorkflowCancelledError, WorkflowInputValidationError, WorkflowOutputValidationError, declareWorkflow };
|
|
341
|
+
|
|
231
342
|
//# sourceMappingURL=workflow.mjs.map
|
package/dist/workflow.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow.mjs","names":[],"sources":["../src/workflow.ts"],"sourcesContent":["// Entry point for workflows\nimport {\n ActivityDefinition,\n ContractDefinition,\n QueryDefinition,\n SignalDefinition,\n UpdateDefinition,\n WorkflowDefinition,\n} from \"@temporal-contract/contract\";\nimport {\n ActivityInputValidationError,\n ActivityOutputValidationError,\n ChildWorkflowError,\n ChildWorkflowNotFoundError,\n QueryInputValidationError,\n QueryOutputValidationError,\n SignalInputValidationError,\n UpdateInputValidationError,\n UpdateOutputValidationError,\n WorkflowInputValidationError,\n WorkflowOutputValidationError,\n} from \"./errors.js\";\nimport {\n ClientInferInput,\n ClientInferOutput,\n WorkerInferInput,\n WorkerInferOutput,\n} from \"./types.js\";\nimport { Future, Result } from \"@temporal-contract/boxed\";\nimport {\n ActivityOptions,\n ChildWorkflowHandle,\n ChildWorkflowOptions,\n defineQuery,\n defineSignal,\n defineUpdate,\n executeChild,\n proxyActivities,\n setHandler,\n startChild,\n WorkflowInfo,\n workflowInfo,\n} from \"@temporalio/workflow\";\nimport { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nexport {\n ActivityInputValidationError,\n ActivityOutputValidationError,\n ChildWorkflowError,\n ChildWorkflowNotFoundError,\n QueryInputValidationError,\n QueryOutputValidationError,\n SignalInputValidationError,\n UpdateInputValidationError,\n UpdateOutputValidationError,\n WorkflowInputValidationError,\n WorkflowOutputValidationError,\n} from \"./errors.js\";\n\n/**\n * Create a typed workflow implementation with automatic validation\n *\n * This wraps a workflow implementation with:\n * - Input/output validation\n * - Typed workflow context with activities\n * - Workflow info access\n *\n * Workflows must be defined in separate files and imported by the Temporal Worker\n * via workflowsPath.\n *\n * @example\n * ```ts\n * // workflows/processOrder.ts\n * import { declareWorkflow } from '@temporal-contract/worker/workflow';\n * import myContract from '../contract';\n *\n * export const processOrder = declareWorkflow({\n * workflowName: 'processOrder',\n * contract: myContract,\n * activityOptions: {\n * startToCloseTimeout: '1 minute',\n * },\n * implementation: async (context, args) => {\n * // context.activities: typed activities (workflow + global)\n * // context.info: WorkflowInfo\n *\n * const inventory = await context.activities.validateInventory({\n * orderId: args.orderId,\n * });\n *\n * if (!inventory.available) {\n * return { orderId: args.orderId, status: 'out_of_stock' };\n * }\n *\n * const payment = await context.activities.chargePayment({\n * customerId: args.customerId,\n * amount: 100,\n * });\n *\n * return {\n * orderId: args.orderId,\n * status: payment.success ? 'success' : 'failed',\n * transactionId: payment.transactionId,\n * };\n * },\n * });\n * ```\n *\n * Then in your worker setup:\n * ```ts\n * // worker.ts\n * import { createWorker } from '@temporal-contract/worker/worker';\n * import { activities } from './activities';\n * import myContract from './contract';\n *\n * const worker = await createWorker({\n * contract: myContract,\n * connection,\n * workflowsPath: workflowsPathFromURL(import.meta.url, './workflows.js'),\n * activities,\n * });\n * ```\n */\nexport function declareWorkflow<\n TContract extends ContractDefinition,\n TWorkflowName extends keyof TContract[\"workflows\"],\n>({\n workflowName,\n contract,\n implementation,\n activityOptions,\n}: DeclareWorkflowOptions<TContract, TWorkflowName>): (\n ...args: unknown[]\n) => Promise<WorkerInferOutput<TContract[\"workflows\"][TWorkflowName]>> {\n // Get the workflow definition from the contract\n const definition = contract.workflows[\n workflowName as string\n ] as TContract[\"workflows\"][TWorkflowName];\n\n return async (...args: unknown[]) => {\n // Extract single parameter (Temporal passes arguments as array)\n const input = args.length === 1 ? args[0] : args;\n\n // Validate workflow input\n const inputResult = await definition.input[\"~standard\"].validate(input);\n if (inputResult.issues) {\n throw new WorkflowInputValidationError(String(workflowName), inputResult.issues);\n }\n const validatedInput = inputResult.value as WorkerInferInput<\n TContract[\"workflows\"][TWorkflowName]\n >;\n\n // Create activities proxy with validation if activities are defined.\n //\n // Design note — intentional double-validation:\n // Input and output are validated here (workflow side) AND again inside\n // `declareActivitiesHandler` (activity worker side). This is deliberate:\n //\n // 1. Workflow-side validation catches bad data *before* it crosses the\n // task-queue network boundary, giving an early, descriptive error\n // instead of a confusing deserialization failure inside the activity.\n // 2. Activity-side validation is the authoritative guard, since the\n // activity may be called by other callers that do not use this library.\n //\n // The overhead is minimal relative to the network round-trip.\n let contextActivities: unknown = {};\n\n if (definition.activities || contract.activities) {\n const rawActivities =\n proxyActivities<Record<string, (...args: unknown[]) => Promise<unknown>>>(activityOptions);\n\n contextActivities = createValidatedActivities(\n rawActivities,\n definition.activities,\n contract.activities,\n );\n }\n\n // Helper to validate child workflow output\n async function validateChildWorkflowOutput<TChildWorkflow extends WorkflowDefinition>(\n childDefinition: TChildWorkflow,\n result: unknown,\n childWorkflowName: string,\n ): Promise<Result<ClientInferOutput<TChildWorkflow>, ChildWorkflowError>> {\n const outputResult = await childDefinition.output[\"~standard\"].validate(result);\n if (outputResult.issues) {\n return Result.Error(\n new ChildWorkflowError(\n `Child workflow \"${childWorkflowName}\" output validation failed: ${outputResult.issues.map((i: StandardSchemaV1.Issue) => i.message).join(\"; \")}`,\n ),\n );\n }\n return Result.Ok(outputResult.value as WorkerInferOutput<TChildWorkflow>);\n }\n\n // Helper to get and validate child workflow definition and input\n async function getAndValidateChildWorkflow<\n TChildContract extends ContractDefinition,\n TChildWorkflowName extends keyof TChildContract[\"workflows\"],\n >(\n childContract: TChildContract,\n childWorkflowName: TChildWorkflowName,\n args: unknown,\n ): Promise<\n Result<\n {\n definition: TChildContract[\"workflows\"][TChildWorkflowName];\n validatedInput: WorkerInferInput<TChildContract[\"workflows\"][TChildWorkflowName]>;\n taskQueue: string;\n },\n ChildWorkflowError\n >\n > {\n const childDefinition = childContract.workflows[childWorkflowName as string];\n\n if (!childDefinition) {\n return Result.Error(\n new ChildWorkflowNotFoundError(\n String(childWorkflowName),\n Object.keys(childContract.workflows) as string[],\n ),\n );\n }\n\n const inputResult = await childDefinition.input[\"~standard\"].validate(args);\n if (inputResult.issues) {\n return Result.Error(\n new ChildWorkflowError(\n `Child workflow \"${String(childWorkflowName)}\" input validation failed: ${inputResult.issues.map((i: StandardSchemaV1.Issue) => i.message).join(\"; \")}`,\n ),\n );\n }\n\n const validatedInput = inputResult.value as WorkerInferInput<\n TChildContract[\"workflows\"][TChildWorkflowName]\n >;\n\n return Result.Ok({\n definition: childDefinition as TChildContract[\"workflows\"][TChildWorkflowName],\n validatedInput,\n taskQueue: childContract.taskQueue,\n });\n }\n\n // Helper function to create a typed child workflow handle\n function createTypedChildHandle<TChildWorkflow extends WorkflowDefinition>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handle: ChildWorkflowHandle<any>,\n childDefinition: TChildWorkflow,\n childWorkflowName: string,\n ): TypedChildWorkflowHandle<TChildWorkflow> {\n return {\n workflowId: handle.workflowId,\n result: (): Future<Result<ClientInferOutput<TChildWorkflow>, ChildWorkflowError>> => {\n return Future.fromAsync(async () => {\n try {\n const result = await handle.result();\n return validateChildWorkflowOutput(childDefinition, result, childWorkflowName);\n } catch (error) {\n return Result.Error(\n new ChildWorkflowError(\n `Child workflow execution failed: ${error instanceof Error ? error.message : String(error)}`,\n error,\n ),\n );\n }\n });\n },\n };\n }\n\n // Helper function to start a child workflow\n function createStartChildWorkflow<\n TChildContract extends ContractDefinition,\n TChildWorkflowName extends keyof TChildContract[\"workflows\"],\n >(\n childContract: TChildContract,\n childWorkflowName: TChildWorkflowName,\n options: TypedChildWorkflowOptions<TChildContract, TChildWorkflowName>,\n ): Future<\n Result<\n TypedChildWorkflowHandle<TChildContract[\"workflows\"][TChildWorkflowName]>,\n ChildWorkflowError\n >\n > {\n return Future.fromAsync(async () => {\n // Validate input and get definition\n const validationResult = await getAndValidateChildWorkflow(\n childContract,\n childWorkflowName,\n options.args,\n );\n\n if (validationResult.isError()) {\n return Result.Error(validationResult.error);\n }\n\n const { definition: childDefinition, validatedInput, taskQueue } = validationResult.value;\n\n try {\n // Start child workflow (Temporal expects args as array)\n const { args: _args, ...temporalOptions } = options;\n const handle = await startChild(childWorkflowName as string, {\n ...temporalOptions,\n taskQueue,\n args: [validatedInput],\n });\n\n const typedHandle = createTypedChildHandle(\n handle,\n childDefinition,\n String(childWorkflowName),\n ) as TypedChildWorkflowHandle<TChildContract[\"workflows\"][TChildWorkflowName]>;\n\n return Result.Ok(typedHandle);\n } catch (error) {\n return Result.Error(\n new ChildWorkflowError(\n `Failed to start child workflow: ${error instanceof Error ? error.message : String(error)}`,\n error,\n ),\n );\n }\n });\n }\n\n // Helper function to execute a child workflow\n function createExecuteChildWorkflow<\n TChildContract extends ContractDefinition,\n TChildWorkflowName extends keyof TChildContract[\"workflows\"],\n >(\n childContract: TChildContract,\n childWorkflowName: TChildWorkflowName,\n options: TypedChildWorkflowOptions<TChildContract, TChildWorkflowName>,\n ): Future<\n Result<ClientInferOutput<TChildContract[\"workflows\"][TChildWorkflowName]>, ChildWorkflowError>\n > {\n return Future.fromAsync(async () => {\n // Validate input and get definition\n const validationResult = await getAndValidateChildWorkflow(\n childContract,\n childWorkflowName,\n options.args,\n );\n\n if (validationResult.isError()) {\n return Result.Error(validationResult.error);\n }\n\n const { definition: childDefinition, validatedInput, taskQueue } = validationResult.value;\n\n try {\n // Execute child workflow (Temporal expects args as array)\n const { args: _args, ...temporalOptions } = options;\n const result = await executeChild(childWorkflowName as string, {\n ...temporalOptions,\n taskQueue,\n args: [validatedInput],\n });\n\n // Validate output with Standard Schema\n const outputValidationResult = await validateChildWorkflowOutput(\n childDefinition,\n result,\n String(childWorkflowName),\n );\n\n if (outputValidationResult.isError()) {\n return Result.Error(outputValidationResult.error);\n }\n\n return Result.Ok(\n outputValidationResult.value as ClientInferOutput<\n TChildContract[\"workflows\"][TChildWorkflowName]\n >,\n );\n } catch (error) {\n return Result.Error(\n new ChildWorkflowError(\n `Failed to execute child workflow: ${error instanceof Error ? error.message : String(error)}`,\n error,\n ),\n );\n }\n });\n }\n\n // Context methods for defining signals, queries, and updates\n function createDefineSignal<\n TSignalName extends keyof TContract[\"workflows\"][TWorkflowName][\"signals\"],\n >(\n signalName: TSignalName,\n handler: SignalHandlerImplementation<\n TContract[\"workflows\"][TWorkflowName][\"signals\"][TSignalName] extends SignalDefinition\n ? TContract[\"workflows\"][TWorkflowName][\"signals\"][TSignalName]\n : never\n >,\n ): void {\n if (!definition.signals) {\n throw new Error(\n `Signal \"${String(signalName)}\" cannot be defined: workflow \"${String(workflowName)}\" has no signals in its contract`,\n );\n }\n\n const signalDef = (definition.signals as Record<string, SignalDefinition>)[\n signalName as string\n ];\n if (!signalDef) {\n throw new Error(\n `Signal \"${String(signalName)}\" not found in workflow \"${String(workflowName)}\" contract`,\n );\n }\n\n const signal = defineSignal(signalName as string);\n setHandler(signal, async (...args: unknown[]) => {\n // Extract single parameter (Temporal passes as args array)\n const input = args.length === 1 ? args[0] : args;\n const inputResult = await signalDef.input[\"~standard\"].validate(input);\n if (inputResult.issues) {\n throw new SignalInputValidationError(signalName as string, inputResult.issues);\n }\n await (handler as SignalHandlerImplementation<SignalDefinition>)(inputResult.value);\n });\n }\n\n function createDefineQuery<\n TQueryName extends keyof TContract[\"workflows\"][TWorkflowName][\"queries\"],\n >(\n queryName: TQueryName,\n handler: QueryHandlerImplementation<\n TContract[\"workflows\"][TWorkflowName][\"queries\"][TQueryName] extends QueryDefinition\n ? TContract[\"workflows\"][TWorkflowName][\"queries\"][TQueryName]\n : never\n >,\n ): void {\n if (!definition.queries) {\n throw new Error(\n `Query \"${String(queryName)}\" cannot be defined: workflow \"${String(workflowName)}\" has no queries in its contract`,\n );\n }\n\n const queryDef = (definition.queries as Record<string, QueryDefinition>)[queryName as string];\n if (!queryDef) {\n throw new Error(\n `Query \"${String(queryName)}\" not found in workflow \"${String(workflowName)}\" contract`,\n );\n }\n\n const query = defineQuery(queryName as string);\n setHandler(query, (...args: unknown[]) => {\n // Extract single parameter (Temporal passes as args array)\n const input = args.length === 1 ? args[0] : args;\n // Note: Query handlers must be synchronous, so we need to handle validation synchronously\n const inputResult = queryDef.input[\"~standard\"].validate(input);\n\n // Handle both sync and async validation results\n if (inputResult instanceof Promise) {\n throw new Error(\n `Query \"${String(queryName)}\" validation must be synchronous. Use a schema library that supports synchronous validation for queries.`,\n );\n }\n\n if (inputResult.issues) {\n throw new QueryInputValidationError(queryName as string, inputResult.issues);\n }\n\n const result = handler(inputResult.value);\n\n const outputResult = queryDef.output[\"~standard\"].validate(result);\n if (outputResult instanceof Promise) {\n throw new Error(\n `Query \"${String(queryName)}\" output validation must be synchronous. Use a schema library that supports synchronous validation for queries.`,\n );\n }\n\n if (outputResult.issues) {\n throw new QueryOutputValidationError(queryName as string, outputResult.issues);\n }\n\n return outputResult.value;\n });\n }\n\n function createDefineUpdate<\n TUpdateName extends keyof TContract[\"workflows\"][TWorkflowName][\"updates\"],\n >(\n updateName: TUpdateName,\n handler: UpdateHandlerImplementation<\n TContract[\"workflows\"][TWorkflowName][\"updates\"][TUpdateName] extends UpdateDefinition\n ? TContract[\"workflows\"][TWorkflowName][\"updates\"][TUpdateName]\n : never\n >,\n ): void {\n if (!definition.updates) {\n throw new Error(\n `Update \"${String(updateName)}\" cannot be defined: workflow \"${String(workflowName)}\" has no updates in its contract`,\n );\n }\n\n const updateDef = (definition.updates as Record<string, UpdateDefinition>)[\n updateName as string\n ];\n if (!updateDef) {\n throw new Error(\n `Update \"${String(updateName)}\" not found in workflow \"${String(workflowName)}\" contract`,\n );\n }\n\n const update = defineUpdate(updateName as string);\n setHandler(update, async (...args: unknown[]) => {\n // Extract single parameter (Temporal passes as args array)\n const input = args.length === 1 ? args[0] : args;\n const inputResult = await updateDef.input[\"~standard\"].validate(input);\n if (inputResult.issues) {\n throw new UpdateInputValidationError(updateName as string, inputResult.issues);\n }\n\n const result = await handler(inputResult.value);\n\n const outputResult = await updateDef.output[\"~standard\"].validate(result);\n if (outputResult.issues) {\n throw new UpdateOutputValidationError(updateName as string, outputResult.issues);\n }\n\n return outputResult.value;\n });\n }\n\n // Create workflow context\n const context: WorkflowContext<TContract, TWorkflowName> = {\n activities: contextActivities as WorkflowInferWorkflowContextActivities<\n TContract,\n TWorkflowName\n >,\n info: workflowInfo(),\n startChildWorkflow: createStartChildWorkflow,\n executeChildWorkflow: createExecuteChildWorkflow,\n defineSignal: createDefineSignal as WorkflowContext<TContract, TWorkflowName>[\"defineSignal\"],\n defineQuery: createDefineQuery as WorkflowContext<TContract, TWorkflowName>[\"defineQuery\"],\n defineUpdate: createDefineUpdate as WorkflowContext<TContract, TWorkflowName>[\"defineUpdate\"],\n };\n\n // Execute workflow (pass validated input as tuple)\n const result = await implementation(context, validatedInput);\n\n // Validate workflow output\n const outputResult = await definition.output[\"~standard\"].validate(result);\n if (outputResult.issues) {\n throw new WorkflowOutputValidationError(String(workflowName), outputResult.issues);\n }\n\n return outputResult.value as WorkerInferOutput<TContract[\"workflows\"][TWorkflowName]>;\n };\n}\n\n/**\n * Signal handler implementation\n *\n * Processes signal input and can optionally perform asynchronous operations.\n * Should not return a value (signals are fire-and-forget).\n */\ntype SignalHandlerImplementation<TSignal extends SignalDefinition> = (\n args: WorkerInferInput<TSignal>,\n) => void | Promise<void>;\n\n/**\n * Query handler implementation\n *\n * Processes query input and returns a synchronous response.\n * Must be synchronous to satisfy Temporal's query constraints.\n */\ntype QueryHandlerImplementation<TQuery extends QueryDefinition> = (\n args: WorkerInferInput<TQuery>,\n) => WorkerInferOutput<TQuery>;\n\n/**\n * Update handler implementation\n *\n * Processes update input and returns a validated response after modifying workflow state.\n * Can perform asynchronous operations.\n */\ntype UpdateHandlerImplementation<TUpdate extends UpdateDefinition> = (\n args: WorkerInferInput<TUpdate>,\n) => Promise<WorkerInferOutput<TUpdate>>;\n\n/**\n * Options for declaring a workflow implementation\n */\ntype DeclareWorkflowOptions<\n TContract extends ContractDefinition,\n TWorkflowName extends keyof TContract[\"workflows\"],\n> = {\n workflowName: TWorkflowName;\n contract: TContract;\n implementation: WorkflowImplementation<TContract, TWorkflowName>;\n /**\n * Default activity options applied to all activities in this workflow.\n * For more control, you can override specific Temporal ActivityOptions like:\n * - startToCloseTimeout: Maximum time for activity execution\n * - scheduleToCloseTimeout: End-to-end timeout including queuing\n * - scheduleToStartTimeout: Maximum time activity can wait in queue\n * - heartbeatTimeout: Time between heartbeats before considering activity dead\n * - retry: Retry policy for failed activities\n *\n * @example\n * ```ts\n * activityOptions: {\n * startToCloseTimeout: '5m',\n * retry: { maximumAttempts: 3 }\n * }\n * ```\n */\n activityOptions: ActivityOptions;\n};\n\n/**\n * Workflow implementation function\n *\n * Receives a workflow context (with typed activities and utilities) and validated input arguments.\n * Returns the workflow output which will be validated against the contract schema.\n */\ntype WorkflowImplementation<\n TContract extends ContractDefinition,\n TWorkflowName extends keyof TContract[\"workflows\"],\n> = (\n context: WorkflowContext<TContract, TWorkflowName>,\n args: WorkerInferInput<TContract[\"workflows\"][TWorkflowName]>,\n) => Promise<WorkerInferOutput<TContract[\"workflows\"][TWorkflowName]>>;\n\n/**\n * Workflow execution context providing typed activities, workflow info, and interaction handlers\n *\n * Provides access to:\n * - Typed activities (both workflow-specific and global)\n * - Workflow metadata and execution info\n * - Signal, query, and update handler registration\n * - Child workflow execution capabilities\n */\ntype WorkflowContext<\n TContract extends ContractDefinition,\n TWorkflowName extends keyof TContract[\"workflows\"],\n> = {\n activities: WorkflowInferWorkflowContextActivities<TContract, TWorkflowName>;\n info: WorkflowInfo;\n\n /**\n * Define a signal handler within the workflow implementation\n * Allows the signal handler to access workflow state\n *\n * @example\n * ```ts\n * implementation: async (context, args) => {\n * let currentValue = args.initialValue;\n *\n * context.defineSignal('increment', async (signalArgs) => {\n * currentValue += signalArgs.amount;\n * });\n *\n * // ... rest of workflow\n * }\n * ```\n */\n defineSignal: <K extends keyof TContract[\"workflows\"][TWorkflowName][\"signals\"]>(\n signalName: K,\n handler: SignalHandlerImplementation<\n TContract[\"workflows\"][TWorkflowName][\"signals\"][K] extends SignalDefinition\n ? TContract[\"workflows\"][TWorkflowName][\"signals\"][K]\n : never\n >,\n ) => void;\n\n /**\n * Define a query handler within the workflow implementation\n * Allows the query handler to access workflow state\n *\n * @example\n * ```ts\n * implementation: async (context, args) => {\n * let currentValue = args.initialValue;\n *\n * context.defineQuery('getCurrentValue', () => {\n * return { value: currentValue };\n * });\n *\n * // ... rest of workflow\n * }\n * ```\n */\n defineQuery: <K extends keyof TContract[\"workflows\"][TWorkflowName][\"queries\"]>(\n queryName: K,\n handler: QueryHandlerImplementation<\n TContract[\"workflows\"][TWorkflowName][\"queries\"][K] extends QueryDefinition\n ? TContract[\"workflows\"][TWorkflowName][\"queries\"][K]\n : never\n >,\n ) => void;\n\n /**\n * Define an update handler within the workflow implementation\n * Allows the update handler to access and modify workflow state\n *\n * @example\n * ```ts\n * implementation: async (context, args) => {\n * let currentValue = args.initialValue;\n *\n * context.defineUpdate('multiply', async (updateArgs) => {\n * currentValue *= updateArgs.factor;\n * return { newValue: currentValue };\n * });\n *\n * // ... rest of workflow\n * }\n * ```\n */\n defineUpdate: <K extends keyof TContract[\"workflows\"][TWorkflowName][\"updates\"]>(\n updateName: K,\n handler: UpdateHandlerImplementation<\n TContract[\"workflows\"][TWorkflowName][\"updates\"][K] extends UpdateDefinition\n ? TContract[\"workflows\"][TWorkflowName][\"updates\"][K]\n : never\n >,\n ) => void;\n\n /**\n * Start a child workflow and return a typed handle with Future/Result pattern\n *\n * Supports both same-contract and cross-contract child workflows:\n * - Same contract: Pass workflowName from current contract\n * - Cross-contract: Pass contract and workflowName to invoke workflows from other workers\n *\n * @example\n * ```ts\n * // Same contract child workflow\n * const childResult = await context.startChildWorkflow(myContract, 'processPayment', {\n * workflowId: 'payment-123',\n * args: { amount: 100 }\n * });\n *\n * // Cross-contract child workflow (from another worker)\n * const otherResult = await context.startChildWorkflow(otherContract, 'sendNotification', {\n * workflowId: 'notification-123',\n * args: { message: 'Hello' }\n * });\n *\n * childResult.match({\n * Ok: async (handle) => {\n * const result = await handle.result();\n * // ... handle result\n * },\n * Error: (error) => console.error('Failed to start:', error),\n * });\n * ```\n */\n startChildWorkflow: <\n TChildContract extends ContractDefinition,\n TChildWorkflowName extends keyof TChildContract[\"workflows\"],\n >(\n contract: TChildContract,\n workflowName: TChildWorkflowName,\n options: TypedChildWorkflowOptions<TChildContract, TChildWorkflowName>,\n ) => Future<\n Result<\n TypedChildWorkflowHandle<TChildContract[\"workflows\"][TChildWorkflowName]>,\n ChildWorkflowError\n >\n >;\n\n /**\n * Execute a child workflow (start and wait for result) with Future/Result pattern\n *\n * Supports both same-contract and cross-contract child workflows:\n * - Same contract: Pass workflowName from current contract\n * - Cross-contract: Pass contract and workflowName to invoke workflows from other workers\n *\n * @example\n * ```ts\n * // Same contract child workflow\n * const result = await context.executeChildWorkflow(myContract, 'processPayment', {\n * workflowId: 'payment-123',\n * args: { amount: 100 }\n * });\n *\n * // Cross-contract child workflow (from another worker)\n * const otherResult = await context.executeChildWorkflow(otherContract, 'sendNotification', {\n * workflowId: 'notification-123',\n * args: { message: 'Hello' }\n * });\n *\n * result.match({\n * Ok: (output) => console.log('Payment processed:', output),\n * Error: (error) => console.error('Processing failed:', error),\n * });\n * ```\n */\n executeChildWorkflow: <\n TChildContract extends ContractDefinition,\n TChildWorkflowName extends keyof TChildContract[\"workflows\"],\n >(\n contract: TChildContract,\n workflowName: TChildWorkflowName,\n options: TypedChildWorkflowOptions<TChildContract, TChildWorkflowName>,\n ) => Future<\n Result<ClientInferOutput<TChildContract[\"workflows\"][TChildWorkflowName]>, ChildWorkflowError>\n >;\n};\n\n/**\n * Options for starting a child workflow\n */\ntype TypedChildWorkflowOptions<\n TChildContract extends ContractDefinition,\n TChildWorkflowName extends keyof TChildContract[\"workflows\"],\n> = Omit<ChildWorkflowOptions, \"taskQueue\" | \"args\"> & {\n args: ClientInferInput<TChildContract[\"workflows\"][TChildWorkflowName]>;\n};\n\n/**\n * Typed handle for a child workflow with Future/Result pattern\n */\ntype TypedChildWorkflowHandle<TWorkflow extends WorkflowDefinition> = {\n /**\n * Get child workflow result with Result pattern\n */\n result: () => Future<Result<ClientInferOutput<TWorkflow>, ChildWorkflowError>>;\n\n /**\n * Child workflow ID\n */\n workflowId: string;\n};\n\n/**\n * Activity function signature from workflow execution perspective\n *\n * Workflows call activities with validated input (z.input parsed) and receive validated output (z.output)\n */\ntype WorkflowInferActivity<TActivity extends ActivityDefinition> = (\n args: ClientInferInput<TActivity>,\n) => Promise<ClientInferOutput<TActivity>>;\n\n/**\n * All global activities from a contract (workflow execution perspective)\n */\ntype WorkflowInferActivities<TContract extends ContractDefinition> =\n TContract[\"activities\"] extends Record<string, ActivityDefinition>\n ? {\n [K in keyof TContract[\"activities\"]]: WorkflowInferActivity<TContract[\"activities\"][K]>;\n }\n : {};\n\n/**\n * Workflow-specific activities (workflow execution perspective)\n */\ntype WorkflowInferWorkflowActivities<T extends WorkflowDefinition> =\n T[\"activities\"] extends Record<string, ActivityDefinition>\n ? {\n [K in keyof T[\"activities\"]]: WorkflowInferActivity<T[\"activities\"][K]>;\n }\n : {};\n\n/**\n * All activities available in a workflow context (workflow execution perspective)\n *\n * Combines workflow-specific activities with global contract activities\n */\ntype WorkflowInferWorkflowContextActivities<\n TContract extends ContractDefinition,\n TWorkflowName extends keyof TContract[\"workflows\"],\n> = WorkflowInferWorkflowActivities<TContract[\"workflows\"][TWorkflowName]> &\n WorkflowInferActivities<TContract>;\n\n/**\n * Create a validated activities proxy that parses inputs and outputs\n *\n * This wrapper ensures data integrity across the network boundary between\n * workflow and activity execution.\n */\nfunction createValidatedActivities<\n TContract extends ContractDefinition,\n TWorkflowName extends keyof TContract[\"workflows\"],\n>(\n rawActivities: Record<string, (...args: unknown[]) => Promise<unknown>>,\n workflowActivitiesDefinition: Record<string, ActivityDefinition> | undefined,\n contractActivitiesDefinition: Record<string, ActivityDefinition> | undefined,\n): WorkflowInferWorkflowContextActivities<TContract, TWorkflowName> {\n const validatedActivities = {} as WorkflowInferWorkflowContextActivities<\n TContract,\n TWorkflowName\n >;\n\n // Merge workflow-specific and global contract activities\n // Workflow-specific activities take precedence over global ones\n const allActivitiesDefinition = {\n ...contractActivitiesDefinition,\n ...workflowActivitiesDefinition,\n };\n\n for (const [activityName, activityDef] of Object.entries(allActivitiesDefinition)) {\n const rawActivity = rawActivities[activityName];\n\n if (!rawActivity) {\n throw new Error(\n `Activity implementation not found for: \"${activityName}\". ` +\n `Available activities: ${Object.keys(rawActivities).length > 0 ? Object.keys(rawActivities).join(\", \") : \"none\"}`,\n );\n }\n\n // Wrap activity with input/output validation\n // Register the wrapped activity\n (validatedActivities as Record<string, unknown>)[activityName] = async (input: unknown) => {\n // Validate input before sending over the network\n const inputResult = await activityDef.input[\"~standard\"].validate(input);\n if (inputResult.issues) {\n throw new ActivityInputValidationError(activityName, inputResult.issues);\n }\n\n // Call the actual activity with validated input\n const result = await rawActivity(inputResult.value);\n\n // Validate output after receiving from the network\n const outputResult = await activityDef.output[\"~standard\"].validate(result);\n if (outputResult.issues) {\n throw new ActivityOutputValidationError(activityName, outputResult.issues);\n }\n\n return outputResult.value;\n };\n }\n\n return validatedActivities;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"workflow.mjs","names":[],"sources":["../src/cancellation.ts","../src/handlers.ts","../src/workflow.ts"],"sourcesContent":["/**\n * Typed wrappers around Temporal's `CancellationScope` so workflows can\n * opt into cancellation control without reaching for\n * `@temporalio/workflow` directly. The wrappers fold cancellation into\n * the same `Future<Result<...>>` shape used elsewhere in the worker\n * context — callers branch on `Result.Error(WorkflowCancelledError)`\n * instead of catching `CancelledFailure`.\n *\n * Non-cancellation errors thrown inside the scope are *not* swallowed:\n * the Future rejects with the original error so user-domain failures\n * keep their identity.\n */\nimport { CancellationScope, isCancellation } from \"@temporalio/workflow\";\nimport { Future, Result } from \"@temporal-contract/boxed\";\nimport { WorkflowCancelledError } from \"./errors.js\";\n\n/**\n * Run `fn` inside a cancellable Temporal scope. If the workflow (or an\n * ancestor scope) is cancelled while the function is in flight, the\n * resulting Future resolves to `Result.Error(WorkflowCancelledError)`,\n * letting callers handle cancellation explicitly — typically to perform\n * a graceful exit from the current step.\n *\n * @example\n * ```ts\n * const result = await context.cancellableScope(async () => {\n * return await context.activities.processStep(...);\n * });\n *\n * result.match({\n * Ok: (output) => { ... },\n * Error: (err) => {\n * // err instanceof WorkflowCancelledError — graceful exit\n * },\n * });\n * ```\n */\nexport function cancellableScope<T>(\n fn: () => T | Promise<T>,\n): Future<Result<T, WorkflowCancelledError>> {\n return Future.fromAsync(async () => {\n try {\n // Wrap so synchronous returns satisfy CancellationScope.cancellable's\n // `() => Promise<T>` signature without forcing every caller to write\n // `async () => ...` for purely synchronous bodies.\n const value = await CancellationScope.cancellable(async () => fn());\n return Result.Ok(value);\n } catch (error) {\n if (isCancellation(error)) {\n return Result.Error(new WorkflowCancelledError(error));\n }\n throw error;\n }\n });\n}\n\n/**\n * Run `fn` inside a non-cancellable Temporal scope. Cancellation requests\n * from outside the scope are ignored for its duration — the idiomatic way\n * to perform cleanup that must not be interrupted (e.g. releasing a\n * resource after a graceful shutdown).\n *\n * Mirrors `cancellableScope`'s `Future<Result<...>>` shape for symmetry;\n * the `Result.Error` branch only triggers when cancellation is raised\n * from inside the scope (rare).\n *\n * @example\n * ```ts\n * await context.nonCancellableScope(async () => {\n * await context.activities.releaseResources(...);\n * });\n * ```\n */\nexport function nonCancellableScope<T>(\n fn: () => T | Promise<T>,\n): Future<Result<T, WorkflowCancelledError>> {\n return Future.fromAsync(async () => {\n try {\n const value = await CancellationScope.nonCancellable(async () => fn());\n return Result.Ok(value);\n } catch (error) {\n if (isCancellation(error)) {\n return Result.Error(new WorkflowCancelledError(error));\n }\n throw error;\n }\n });\n}\n","// Top-level helpers for binding signal / query / update handlers to a\n// running workflow. Previously nested inside `declareWorkflow`'s closure\n// (#185), they're hoisted here so the bodies aren't reallocated on each\n// workflow invocation. The typed call-site surface is preserved at the\n// context-assignment site in `workflow.ts` (the arrow that forwards into\n// these helpers carries the contract-derived generic constraints).\n//\n// Internally these are loosely typed (string names, broad `*Definition`\n// inputs); the call sites already do the cast against the typed\n// `WorkflowContext` shape, so the typed-vs-runtime split is the same as\n// it was before the hoist.\nimport type {\n QueryDefinition,\n SignalDefinition,\n UpdateDefinition,\n WorkflowDefinition,\n} from \"@temporal-contract/contract\";\nimport { defineQuery, defineSignal, defineUpdate, setHandler } from \"@temporalio/workflow\";\nimport {\n QueryInputValidationError,\n QueryOutputValidationError,\n SignalInputValidationError,\n UpdateInputValidationError,\n UpdateOutputValidationError,\n} from \"./errors.js\";\nimport { extractHandlerInput } from \"./internal.js\";\nimport type { WorkerInferInput, WorkerInferOutput } from \"./types.js\";\n\n/**\n * Signal handler implementation\n *\n * Processes signal input and can optionally perform asynchronous operations.\n * Should not return a value (signals are fire-and-forget).\n */\nexport type SignalHandlerImplementation<TSignal extends SignalDefinition> = (\n args: WorkerInferInput<TSignal>,\n) => void | Promise<void>;\n\n/**\n * Query handler implementation\n *\n * Processes query input and returns a synchronous response.\n * Must be synchronous to satisfy Temporal's query constraints.\n */\nexport type QueryHandlerImplementation<TQuery extends QueryDefinition> = (\n args: WorkerInferInput<TQuery>,\n) => WorkerInferOutput<TQuery>;\n\n/**\n * Update handler implementation\n *\n * Processes update input and returns a validated response after modifying workflow state.\n * Can perform asynchronous operations.\n */\nexport type UpdateHandlerImplementation<TUpdate extends UpdateDefinition> = (\n args: WorkerInferInput<TUpdate>,\n) => Promise<WorkerInferOutput<TUpdate>>;\n\n/**\n * Bind a typed signal handler to the running workflow. Validates the\n * signal payload against the contract's input schema before invoking the\n * user-supplied handler.\n *\n * The runtime guard against a missing `signals` block — and an unknown\n * signal name within it — covers the union-typed-`workflowName` case\n * where the type system's keyset constraint collapses; without the\n * check, a caller would see `Cannot read properties of undefined`\n * instead of a controlled error.\n */\nexport function bindSignalHandler(\n workflowDefinition: WorkflowDefinition,\n workflowName: string,\n signalName: string,\n handler: SignalHandlerImplementation<SignalDefinition>,\n): void {\n if (!workflowDefinition.signals) {\n throw new Error(\n `Signal \"${signalName}\" cannot be defined: workflow \"${workflowName}\" has no signals in its contract`,\n );\n }\n const signalDef = (workflowDefinition.signals as Record<string, SignalDefinition>)[signalName];\n if (!signalDef) {\n throw new Error(`Signal \"${signalName}\" not found in workflow \"${workflowName}\" contract`);\n }\n\n const signal = defineSignal(signalName);\n setHandler(signal, async (...args: unknown[]) => {\n const input = extractHandlerInput(args);\n const inputResult = await signalDef.input[\"~standard\"].validate(input);\n if (inputResult.issues) {\n throw new SignalInputValidationError(signalName, inputResult.issues);\n }\n await handler(inputResult.value);\n });\n}\n\n/**\n * Bind a typed query handler to the running workflow. Validates input\n * and output against the contract synchronously.\n *\n * Temporal's query API requires a synchronous handler — async\n * validation breaks replay determinism. The handler trips a clear error\n * if the schema library returns a Promise from `validate(...)`, instead\n * of letting the async path silently corrupt query semantics.\n */\nexport function bindQueryHandler(\n workflowDefinition: WorkflowDefinition,\n workflowName: string,\n queryName: string,\n handler: QueryHandlerImplementation<QueryDefinition>,\n): void {\n if (!workflowDefinition.queries) {\n throw new Error(\n `Query \"${queryName}\" cannot be defined: workflow \"${workflowName}\" has no queries in its contract`,\n );\n }\n const queryDef = (workflowDefinition.queries as Record<string, QueryDefinition>)[queryName];\n if (!queryDef) {\n throw new Error(`Query \"${queryName}\" not found in workflow \"${workflowName}\" contract`);\n }\n\n const query = defineQuery(queryName);\n setHandler(query, (...args: unknown[]) => {\n const input = extractHandlerInput(args);\n const inputResult = queryDef.input[\"~standard\"].validate(input);\n\n if (inputResult instanceof Promise) {\n throw new Error(\n `Query \"${queryName}\" validation must be synchronous. Use a schema library that supports synchronous validation for queries.`,\n );\n }\n if (inputResult.issues) {\n throw new QueryInputValidationError(queryName, inputResult.issues);\n }\n\n const result = handler(inputResult.value);\n\n const outputResult = queryDef.output[\"~standard\"].validate(result);\n if (outputResult instanceof Promise) {\n throw new Error(\n `Query \"${queryName}\" output validation must be synchronous. Use a schema library that supports synchronous validation for queries.`,\n );\n }\n if (outputResult.issues) {\n throw new QueryOutputValidationError(queryName, outputResult.issues);\n }\n\n return outputResult.value;\n });\n}\n\n/**\n * Bind a typed update handler to the running workflow. Validates both\n * input and output (asynchronously, like signals).\n */\nexport function bindUpdateHandler(\n workflowDefinition: WorkflowDefinition,\n workflowName: string,\n updateName: string,\n handler: UpdateHandlerImplementation<UpdateDefinition>,\n): void {\n if (!workflowDefinition.updates) {\n throw new Error(\n `Update \"${updateName}\" cannot be defined: workflow \"${workflowName}\" has no updates in its contract`,\n );\n }\n const updateDef = (workflowDefinition.updates as Record<string, UpdateDefinition>)[updateName];\n if (!updateDef) {\n throw new Error(`Update \"${updateName}\" not found in workflow \"${workflowName}\" contract`);\n }\n\n const update = defineUpdate(updateName);\n setHandler(update, async (...args: unknown[]) => {\n const input = extractHandlerInput(args);\n const inputResult = await updateDef.input[\"~standard\"].validate(input);\n if (inputResult.issues) {\n throw new UpdateInputValidationError(updateName, inputResult.issues);\n }\n\n const result = await handler(inputResult.value);\n\n const outputResult = await updateDef.output[\"~standard\"].validate(result);\n if (outputResult.issues) {\n throw new UpdateOutputValidationError(updateName, outputResult.issues);\n }\n\n return outputResult.value;\n });\n}\n","// Entry point for workflow implementations.\n//\n// Workflows run inside Temporal's deterministic sandbox, which intercepts\n// timers, randomness, and Promise scheduling for replay. We use the in-house\n// `@temporal-contract/boxed` `Result`/`Future` here because they don't reach\n// for any non-deterministic primitive. Activity code (see activity.ts) is not\n// subject to this constraint and uses `@swan-io/boxed` instead.\nimport {\n ActivityDefinition,\n ContractDefinition,\n QueryDefinition,\n SignalDefinition,\n UpdateDefinition,\n WorkflowDefinition,\n} from \"@temporal-contract/contract\";\nimport {\n ActivityInputValidationError,\n ActivityOutputValidationError,\n ChildWorkflowError,\n ChildWorkflowNotFoundError,\n WorkflowCancelledError,\n WorkflowInputValidationError,\n WorkflowOutputValidationError,\n} from \"./errors.js\";\nimport { cancellableScope, nonCancellableScope } from \"./cancellation.js\";\nimport {\n bindQueryHandler,\n bindSignalHandler,\n bindUpdateHandler,\n type QueryHandlerImplementation,\n type SignalHandlerImplementation,\n type UpdateHandlerImplementation,\n} from \"./handlers.js\";\nimport {\n ClientInferInput,\n ClientInferOutput,\n WorkerInferInput,\n WorkerInferOutput,\n} from \"./types.js\";\nimport { Future, Result } from \"@temporal-contract/boxed\";\nimport {\n buildRawActivitiesProxy,\n createContinueAsNew,\n extractHandlerInput,\n formatChildWorkflowValidationMessage,\n type TypedContinueAsNewOptions,\n} from \"./internal.js\";\nimport {\n ActivityOptions,\n ChildWorkflowHandle,\n ChildWorkflowOptions,\n executeChild,\n startChild,\n WorkflowInfo,\n workflowInfo,\n} from \"@temporalio/workflow\";\n\nexport {\n ActivityInputValidationError,\n ActivityOutputValidationError,\n ChildWorkflowError,\n ChildWorkflowNotFoundError,\n QueryInputValidationError,\n QueryOutputValidationError,\n SignalInputValidationError,\n UpdateInputValidationError,\n UpdateOutputValidationError,\n WorkflowCancelledError,\n WorkflowInputValidationError,\n WorkflowOutputValidationError,\n} from \"./errors.js\";\n\n/**\n * Create a typed workflow implementation with automatic validation\n *\n * This wraps a workflow implementation with:\n * - Input/output validation\n * - Typed workflow context with activities\n * - Workflow info access\n *\n * Workflows must be defined in separate files and imported by the Temporal Worker\n * via workflowsPath.\n *\n * @example\n * ```ts\n * // workflows/processOrder.ts\n * import { declareWorkflow } from '@temporal-contract/worker/workflow';\n * import myContract from '../contract';\n *\n * export const processOrder = declareWorkflow({\n * workflowName: 'processOrder',\n * contract: myContract,\n * activityOptions: {\n * startToCloseTimeout: '1 minute',\n * },\n * // Optional: override `activityOptions` for specific activities. Each\n * // entry shallow-merges over the workflow default — the override wins on\n * // every property it specifies, including the whole `retry` block.\n * activityOptionsByName: {\n * chargePayment: {\n * startToCloseTimeout: '5 minutes',\n * retry: { maximumAttempts: 5 },\n * },\n * },\n * implementation: async (context, args) => {\n * // context.activities: typed activities (workflow + global)\n * // context.info: WorkflowInfo\n *\n * const inventory = await context.activities.validateInventory({\n * orderId: args.orderId,\n * });\n *\n * if (!inventory.available) {\n * return { orderId: args.orderId, status: 'out_of_stock' };\n * }\n *\n * const payment = await context.activities.chargePayment({\n * customerId: args.customerId,\n * amount: 100,\n * });\n *\n * return {\n * orderId: args.orderId,\n * status: payment.success ? 'success' : 'failed',\n * transactionId: payment.transactionId,\n * };\n * },\n * });\n * ```\n *\n * Then in your worker setup:\n * ```ts\n * // worker.ts\n * import { createWorker } from '@temporal-contract/worker/worker';\n * import { activities } from './activities';\n * import myContract from './contract';\n *\n * const worker = await createWorker({\n * contract: myContract,\n * connection,\n * workflowsPath: workflowsPathFromURL(import.meta.url, './workflows.js'),\n * activities,\n * });\n * ```\n */\nexport function declareWorkflow<\n TContract extends ContractDefinition,\n TWorkflowName extends keyof TContract[\"workflows\"],\n>({\n workflowName,\n contract,\n implementation,\n activityOptions,\n activityOptionsByName,\n}: DeclareWorkflowOptions<TContract, TWorkflowName>): (\n ...args: unknown[]\n) => Promise<WorkerInferOutput<TContract[\"workflows\"][TWorkflowName]>> {\n // Get the workflow definition from the contract\n const definition = contract.workflows[\n workflowName as string\n ] as TContract[\"workflows\"][TWorkflowName];\n\n return async (...args: unknown[]) => {\n const input = extractHandlerInput(args);\n\n // Validate workflow input\n const inputResult = await definition.input[\"~standard\"].validate(input);\n if (inputResult.issues) {\n throw new WorkflowInputValidationError(String(workflowName), inputResult.issues);\n }\n const validatedInput = inputResult.value as WorkerInferInput<\n TContract[\"workflows\"][TWorkflowName]\n >;\n\n // Create activities proxy with validation if activities are defined.\n //\n // Design note — intentional double-validation:\n // Input and output are validated here (workflow side) AND again inside\n // `declareActivitiesHandler` (activity worker side). This is deliberate:\n //\n // 1. Workflow-side validation catches bad data *before* it crosses the\n // task-queue network boundary, giving an early, descriptive error\n // instead of a confusing deserialization failure inside the activity.\n // 2. Activity-side validation is the authoritative guard, since the\n // activity may be called by other callers that do not use this library.\n //\n // The overhead is minimal relative to the network round-trip.\n let contextActivities: unknown = {};\n\n if (definition.activities || contract.activities) {\n const rawActivities = buildRawActivitiesProxy(\n definition.activities,\n contract.activities,\n activityOptions,\n activityOptionsByName,\n );\n\n contextActivities = createValidatedActivities(\n rawActivities,\n definition.activities,\n contract.activities,\n );\n }\n\n // Create workflow context.\n //\n // The defineSignal / defineQuery / defineUpdate arrows forward to the\n // hoisted helpers in `./handlers.ts`. The arrows themselves are thin\n // closures that close over `definition` and `workflowName`; the heavy\n // logic — runtime guards, validation, Temporal `defineSignal/Query/\n // Update` + `setHandler` wiring — lives at module scope so it isn't\n // reallocated on each workflow invocation.\n //\n // The cast at each assignment preserves the typed call-site surface\n // (the `K extends keyof ...` constraints declared on\n // `WorkflowContext.defineSignal/Query/Update`), while the helpers\n // themselves take loosely-typed arguments at the runtime boundary.\n const context: WorkflowContext<TContract, TWorkflowName> = {\n activities: contextActivities as WorkflowInferWorkflowContextActivities<\n TContract,\n TWorkflowName\n >,\n info: workflowInfo(),\n startChildWorkflow: createStartChildWorkflow,\n executeChildWorkflow: createExecuteChildWorkflow,\n cancellableScope,\n nonCancellableScope,\n defineSignal: ((signalName, handler) =>\n bindSignalHandler(\n definition,\n String(workflowName),\n signalName as string,\n handler as unknown as SignalHandlerImplementation<SignalDefinition>,\n )) as WorkflowContext<TContract, TWorkflowName>[\"defineSignal\"],\n defineQuery: ((queryName, handler) =>\n bindQueryHandler(\n definition,\n String(workflowName),\n queryName as string,\n handler as unknown as QueryHandlerImplementation<QueryDefinition>,\n )) as WorkflowContext<TContract, TWorkflowName>[\"defineQuery\"],\n defineUpdate: ((updateName, handler) =>\n bindUpdateHandler(\n definition,\n String(workflowName),\n updateName as string,\n handler as unknown as UpdateHandlerImplementation<UpdateDefinition>,\n )) as WorkflowContext<TContract, TWorkflowName>[\"defineUpdate\"],\n continueAsNew: createContinueAsNew(contract, workflowName) as WorkflowContext<\n TContract,\n TWorkflowName\n >[\"continueAsNew\"],\n };\n\n // Execute workflow (pass validated input as tuple)\n const result = await implementation(context, validatedInput);\n\n // Validate workflow output\n const outputResult = await definition.output[\"~standard\"].validate(result);\n if (outputResult.issues) {\n throw new WorkflowOutputValidationError(String(workflowName), outputResult.issues);\n }\n\n return outputResult.value as WorkerInferOutput<TContract[\"workflows\"][TWorkflowName]>;\n };\n}\n\n/**\n * Union of all activity names available to a workflow — the workflow-local\n * activities plus the contract's global activities.\n */\ntype ActivityNamesFor<\n TContract extends ContractDefinition,\n TWorkflowName extends keyof TContract[\"workflows\"],\n> =\n | (TContract[\"workflows\"][TWorkflowName][\"activities\"] extends Record<string, ActivityDefinition>\n ? keyof TContract[\"workflows\"][TWorkflowName][\"activities\"] & string\n : never)\n | (TContract[\"activities\"] extends Record<string, ActivityDefinition>\n ? keyof TContract[\"activities\"] & string\n : never);\n\n/**\n * Options for declaring a workflow implementation\n */\ntype DeclareWorkflowOptions<\n TContract extends ContractDefinition,\n TWorkflowName extends keyof TContract[\"workflows\"],\n> = {\n workflowName: TWorkflowName;\n contract: TContract;\n implementation: WorkflowImplementation<TContract, TWorkflowName>;\n /**\n * Default activity options applied to every activity reachable from this\n * workflow (workflow-local + global) unless overridden in\n * {@link activityOptionsByName}. See Temporal's `ActivityOptions` for the\n * full set of fields:\n * - `startToCloseTimeout`: Maximum time for a single attempt to run\n * - `scheduleToCloseTimeout`: End-to-end timeout including queuing and retries\n * - `scheduleToStartTimeout`: Maximum time the activity can wait in the queue\n * - `heartbeatTimeout`: Time between heartbeats before the activity is considered dead\n * - `retry`: Retry policy for failed activities\n *\n * @example\n * ```ts\n * activityOptions: {\n * startToCloseTimeout: '5m',\n * retry: { maximumAttempts: 3 },\n * }\n * ```\n */\n activityOptions: ActivityOptions;\n /**\n * Per-activity `ActivityOptions` overrides. Each entry shallow-merges over\n * {@link activityOptions} for that activity only — the override wins on\n * every property it specifies, replacing the default value (including the\n * entire nested `retry` block when present, matching Temporal's\n * single-options-per-`proxyActivities`-call semantics).\n *\n * Activity names are typed against the contract; typos surface as TypeScript\n * errors rather than running silently with the default options.\n *\n * @example\n * ```ts\n * activityOptions: { startToCloseTimeout: '1 minute' }, // default\n * activityOptionsByName: {\n * chargePayment: {\n * startToCloseTimeout: '5 minutes',\n * retry: { maximumAttempts: 5 },\n * },\n * fastValidation: { startToCloseTimeout: '5 seconds' },\n * },\n * ```\n */\n activityOptionsByName?: Partial<\n Record<ActivityNamesFor<TContract, TWorkflowName>, ActivityOptions>\n >;\n};\n\n/**\n * Workflow implementation function\n *\n * Receives a workflow context (with typed activities and utilities) and validated input arguments.\n * Returns the workflow output which will be validated against the contract schema.\n */\ntype WorkflowImplementation<\n TContract extends ContractDefinition,\n TWorkflowName extends keyof TContract[\"workflows\"],\n> = (\n context: WorkflowContext<TContract, TWorkflowName>,\n args: WorkerInferInput<TContract[\"workflows\"][TWorkflowName]>,\n) => Promise<WorkerInferOutput<TContract[\"workflows\"][TWorkflowName]>>;\n\n/**\n * Workflow execution context providing typed activities, workflow info, and interaction handlers\n *\n * Provides access to:\n * - Typed activities (both workflow-specific and global)\n * - Workflow metadata and execution info\n * - Signal, query, and update handler registration\n * - Child workflow execution capabilities\n */\ntype WorkflowContext<\n TContract extends ContractDefinition,\n TWorkflowName extends keyof TContract[\"workflows\"],\n> = {\n activities: WorkflowInferWorkflowContextActivities<TContract, TWorkflowName>;\n info: WorkflowInfo;\n\n /**\n * Define a signal handler within the workflow implementation\n * Allows the signal handler to access workflow state\n *\n * @example\n * ```ts\n * implementation: async (context, args) => {\n * let currentValue = args.initialValue;\n *\n * context.defineSignal('increment', async (signalArgs) => {\n * currentValue += signalArgs.amount;\n * });\n *\n * // ... rest of workflow\n * }\n * ```\n */\n defineSignal: <K extends keyof TContract[\"workflows\"][TWorkflowName][\"signals\"]>(\n signalName: K,\n handler: SignalHandlerImplementation<\n TContract[\"workflows\"][TWorkflowName][\"signals\"][K] extends SignalDefinition\n ? TContract[\"workflows\"][TWorkflowName][\"signals\"][K]\n : never\n >,\n ) => void;\n\n /**\n * Define a query handler within the workflow implementation\n * Allows the query handler to access workflow state\n *\n * @example\n * ```ts\n * implementation: async (context, args) => {\n * let currentValue = args.initialValue;\n *\n * context.defineQuery('getCurrentValue', () => {\n * return { value: currentValue };\n * });\n *\n * // ... rest of workflow\n * }\n * ```\n */\n defineQuery: <K extends keyof TContract[\"workflows\"][TWorkflowName][\"queries\"]>(\n queryName: K,\n handler: QueryHandlerImplementation<\n TContract[\"workflows\"][TWorkflowName][\"queries\"][K] extends QueryDefinition\n ? TContract[\"workflows\"][TWorkflowName][\"queries\"][K]\n : never\n >,\n ) => void;\n\n /**\n * Define an update handler within the workflow implementation\n * Allows the update handler to access and modify workflow state\n *\n * @example\n * ```ts\n * implementation: async (context, args) => {\n * let currentValue = args.initialValue;\n *\n * context.defineUpdate('multiply', async (updateArgs) => {\n * currentValue *= updateArgs.factor;\n * return { newValue: currentValue };\n * });\n *\n * // ... rest of workflow\n * }\n * ```\n */\n defineUpdate: <K extends keyof TContract[\"workflows\"][TWorkflowName][\"updates\"]>(\n updateName: K,\n handler: UpdateHandlerImplementation<\n TContract[\"workflows\"][TWorkflowName][\"updates\"][K] extends UpdateDefinition\n ? TContract[\"workflows\"][TWorkflowName][\"updates\"][K]\n : never\n >,\n ) => void;\n\n /**\n * Start a child workflow and return a typed handle with Future/Result pattern\n *\n * Supports both same-contract and cross-contract child workflows:\n * - Same contract: Pass workflowName from current contract\n * - Cross-contract: Pass contract and workflowName to invoke workflows from other workers\n *\n * @example\n * ```ts\n * // Same contract child workflow\n * const childResult = await context.startChildWorkflow(myContract, 'processPayment', {\n * workflowId: 'payment-123',\n * args: { amount: 100 }\n * });\n *\n * // Cross-contract child workflow (from another worker)\n * const otherResult = await context.startChildWorkflow(otherContract, 'sendNotification', {\n * workflowId: 'notification-123',\n * args: { message: 'Hello' }\n * });\n *\n * childResult.match({\n * Ok: async (handle) => {\n * const result = await handle.result();\n * // ... handle result\n * },\n * Error: (error) => console.error('Failed to start:', error),\n * });\n * ```\n */\n startChildWorkflow: <\n TChildContract extends ContractDefinition,\n TChildWorkflowName extends keyof TChildContract[\"workflows\"],\n >(\n contract: TChildContract,\n workflowName: TChildWorkflowName,\n options: TypedChildWorkflowOptions<TChildContract, TChildWorkflowName>,\n ) => Future<\n Result<\n TypedChildWorkflowHandle<TChildContract[\"workflows\"][TChildWorkflowName]>,\n ChildWorkflowError\n >\n >;\n\n /**\n * Execute a child workflow (start and wait for result) with Future/Result pattern\n *\n * Supports both same-contract and cross-contract child workflows:\n * - Same contract: Pass workflowName from current contract\n * - Cross-contract: Pass contract and workflowName to invoke workflows from other workers\n *\n * @example\n * ```ts\n * // Same contract child workflow\n * const result = await context.executeChildWorkflow(myContract, 'processPayment', {\n * workflowId: 'payment-123',\n * args: { amount: 100 }\n * });\n *\n * // Cross-contract child workflow (from another worker)\n * const otherResult = await context.executeChildWorkflow(otherContract, 'sendNotification', {\n * workflowId: 'notification-123',\n * args: { message: 'Hello' }\n * });\n *\n * result.match({\n * Ok: (output) => console.log('Payment processed:', output),\n * Error: (error) => console.error('Processing failed:', error),\n * });\n * ```\n */\n executeChildWorkflow: <\n TChildContract extends ContractDefinition,\n TChildWorkflowName extends keyof TChildContract[\"workflows\"],\n >(\n contract: TChildContract,\n workflowName: TChildWorkflowName,\n options: TypedChildWorkflowOptions<TChildContract, TChildWorkflowName>,\n ) => Future<\n Result<ClientInferOutput<TChildContract[\"workflows\"][TChildWorkflowName]>, ChildWorkflowError>\n >;\n\n /**\n * Run `fn` inside a cancellable Temporal scope. If the workflow (or an\n * ancestor scope) is cancelled while `fn` is in flight, the resulting\n * Future resolves to `Result.Error(WorkflowCancelledError)` instead of\n * rejecting — letting callers handle cancellation explicitly, typically\n * to perform a graceful exit from the current step.\n *\n * Non-cancellation errors thrown by `fn` propagate as Future rejections\n * unchanged, preserving their identity for upstream `try/catch` blocks.\n *\n * @example\n * ```ts\n * implementation: async (context, args) => {\n * const result = await context.cancellableScope(async () => {\n * return context.activities.processStep(args);\n * });\n *\n * if (result.isError()) {\n * // workflow was cancelled — perform cleanup that must not be cancelled:\n * await context.nonCancellableScope(async () => {\n * await context.activities.releaseResources(args);\n * });\n * return { status: \"cancelled\" };\n * }\n *\n * return { status: \"ok\" };\n * }\n * ```\n */\n cancellableScope: <T>(fn: () => T | Promise<T>) => Future<Result<T, WorkflowCancelledError>>;\n\n /**\n * Run `fn` inside a non-cancellable Temporal scope. Cancellation requests\n * from outside the scope are ignored for its duration — the idiomatic way\n * to perform cleanup work that must not be interrupted.\n *\n * Returns the same `Future<Result<...>>` shape as\n * {@link WorkflowContext.cancellableScope} for symmetry; the\n * `Result.Error` branch only triggers when cancellation is raised from\n * *inside* the scope, which is rare.\n */\n nonCancellableScope: <T>(fn: () => T | Promise<T>) => Future<Result<T, WorkflowCancelledError>>;\n\n /**\n * Continue this workflow execution as a new run, optionally with a different\n * workflow type from another contract.\n *\n * Args are validated against the destination workflow's input schema before\n * Temporal's `continueAsNew` is invoked. On validation failure, throws a\n * {@link WorkflowInputValidationError}; on success, Temporal terminates the\n * current execution and starts a fresh one — which is why the function\n * never returns normally (`Promise<never>`).\n *\n * Idiomatic usage:\n *\n * @example\n * ```ts\n * // Same workflow, validated args\n * implementation: async (context, args) => {\n * if (shouldRoll(args)) {\n * return context.continueAsNew({ ...args, retryCount: args.retryCount + 1 });\n * }\n * return ...;\n * }\n *\n * // Cross-contract continueAsNew (less common — taskQueue and workflow type\n * // come from the other contract)\n * return context.continueAsNew(otherContract, \"otherWorkflow\", { ...newArgs });\n * ```\n */\n continueAsNew: {\n /** Same-workflow continuation — args typed against this workflow's input. */\n (\n args: ClientInferInput<TContract[\"workflows\"][TWorkflowName]>,\n options?: TypedContinueAsNewOptions,\n ): Promise<never>;\n /** Cross-contract continuation — args typed against the destination workflow. */\n <\n TOtherContract extends ContractDefinition,\n TOtherWorkflowName extends keyof TOtherContract[\"workflows\"],\n >(\n contract: TOtherContract,\n workflowName: TOtherWorkflowName,\n args: ClientInferInput<TOtherContract[\"workflows\"][TOtherWorkflowName]>,\n options?: TypedContinueAsNewOptions,\n ): Promise<never>;\n };\n};\n\n/**\n * Options for starting a child workflow\n */\ntype TypedChildWorkflowOptions<\n TChildContract extends ContractDefinition,\n TChildWorkflowName extends keyof TChildContract[\"workflows\"],\n> = Omit<ChildWorkflowOptions, \"taskQueue\" | \"args\"> & {\n args: ClientInferInput<TChildContract[\"workflows\"][TChildWorkflowName]>;\n};\n\n/**\n * Typed handle for a child workflow with Future/Result pattern\n */\ntype TypedChildWorkflowHandle<TWorkflow extends WorkflowDefinition> = {\n /**\n * Get child workflow result with Result pattern\n */\n result: () => Future<Result<ClientInferOutput<TWorkflow>, ChildWorkflowError>>;\n\n /**\n * Child workflow ID\n */\n workflowId: string;\n};\n\n/**\n * Activity function signature from workflow execution perspective\n *\n * Workflows call activities with validated input (z.input parsed) and receive validated output (z.output)\n */\ntype WorkflowInferActivity<TActivity extends ActivityDefinition> = (\n args: ClientInferInput<TActivity>,\n) => Promise<ClientInferOutput<TActivity>>;\n\n/**\n * All global activities from a contract (workflow execution perspective)\n */\ntype WorkflowInferActivities<TContract extends ContractDefinition> =\n TContract[\"activities\"] extends Record<string, ActivityDefinition>\n ? {\n [K in keyof TContract[\"activities\"]]: WorkflowInferActivity<TContract[\"activities\"][K]>;\n }\n : {};\n\n/**\n * Workflow-specific activities (workflow execution perspective)\n */\ntype WorkflowInferWorkflowActivities<T extends WorkflowDefinition> =\n T[\"activities\"] extends Record<string, ActivityDefinition>\n ? {\n [K in keyof T[\"activities\"]]: WorkflowInferActivity<T[\"activities\"][K]>;\n }\n : {};\n\n/**\n * All activities available in a workflow context (workflow execution perspective)\n *\n * Combines workflow-specific activities with global contract activities\n */\ntype WorkflowInferWorkflowContextActivities<\n TContract extends ContractDefinition,\n TWorkflowName extends keyof TContract[\"workflows\"],\n> = WorkflowInferWorkflowActivities<TContract[\"workflows\"][TWorkflowName]> &\n WorkflowInferActivities<TContract>;\n\n/**\n * Create a validated activities proxy that parses inputs and outputs\n *\n * This wrapper ensures data integrity across the network boundary between\n * workflow and activity execution.\n */\nfunction createValidatedActivities<\n TContract extends ContractDefinition,\n TWorkflowName extends keyof TContract[\"workflows\"],\n>(\n rawActivities: Record<string, (...args: unknown[]) => Promise<unknown>>,\n workflowActivitiesDefinition: Record<string, ActivityDefinition> | undefined,\n contractActivitiesDefinition: Record<string, ActivityDefinition> | undefined,\n): WorkflowInferWorkflowContextActivities<TContract, TWorkflowName> {\n const validatedActivities = {} as WorkflowInferWorkflowContextActivities<\n TContract,\n TWorkflowName\n >;\n\n // Merge workflow-specific and global contract activities. defineContract\n // guarantees there are no name collisions across scopes, so spread order\n // is just a stable iteration choice (workflow-local last).\n const allActivitiesDefinition = {\n ...contractActivitiesDefinition,\n ...workflowActivitiesDefinition,\n };\n\n for (const [activityName, activityDef] of Object.entries(allActivitiesDefinition)) {\n const rawActivity = rawActivities[activityName];\n\n if (!rawActivity) {\n throw new Error(\n `Activity implementation not found for: \"${activityName}\". ` +\n `Available activities: ${Object.keys(rawActivities).length > 0 ? Object.keys(rawActivities).join(\", \") : \"none\"}`,\n );\n }\n\n // Wrap activity with input/output validation\n // Register the wrapped activity\n (validatedActivities as Record<string, unknown>)[activityName] = async (input: unknown) => {\n // Validate input before sending over the network\n const inputResult = await activityDef.input[\"~standard\"].validate(input);\n if (inputResult.issues) {\n throw new ActivityInputValidationError(activityName, inputResult.issues);\n }\n\n // Call the actual activity with validated input\n const result = await rawActivity(inputResult.value);\n\n // Validate output after receiving from the network\n const outputResult = await activityDef.output[\"~standard\"].validate(result);\n if (outputResult.issues) {\n throw new ActivityOutputValidationError(activityName, outputResult.issues);\n }\n\n return outputResult.value;\n };\n }\n\n return validatedActivities;\n}\n\nasync function validateChildWorkflowOutput<TChildWorkflow extends WorkflowDefinition>(\n childDefinition: TChildWorkflow,\n result: unknown,\n childWorkflowName: string,\n): Promise<Result<ClientInferOutput<TChildWorkflow>, ChildWorkflowError>> {\n const outputResult = await childDefinition.output[\"~standard\"].validate(result);\n if (outputResult.issues) {\n return Result.Error(\n new ChildWorkflowError(\n formatChildWorkflowValidationMessage(childWorkflowName, \"output\", outputResult.issues),\n ),\n );\n }\n return Result.Ok(outputResult.value as ClientInferOutput<TChildWorkflow>);\n}\n\nasync function getAndValidateChildWorkflow<\n TChildContract extends ContractDefinition,\n TChildWorkflowName extends keyof TChildContract[\"workflows\"],\n>(\n childContract: TChildContract,\n childWorkflowName: TChildWorkflowName,\n args: unknown,\n): Promise<\n Result<\n {\n definition: TChildContract[\"workflows\"][TChildWorkflowName];\n validatedInput: WorkerInferInput<TChildContract[\"workflows\"][TChildWorkflowName]>;\n taskQueue: string;\n },\n ChildWorkflowError\n >\n> {\n const childDefinition = childContract.workflows[childWorkflowName as string];\n\n if (!childDefinition) {\n return Result.Error(\n new ChildWorkflowNotFoundError(\n String(childWorkflowName),\n Object.keys(childContract.workflows) as string[],\n ),\n );\n }\n\n const inputResult = await childDefinition.input[\"~standard\"].validate(args);\n if (inputResult.issues) {\n return Result.Error(\n new ChildWorkflowError(\n formatChildWorkflowValidationMessage(\n String(childWorkflowName),\n \"input\",\n inputResult.issues,\n ),\n ),\n );\n }\n\n const validatedInput = inputResult.value as WorkerInferInput<\n TChildContract[\"workflows\"][TChildWorkflowName]\n >;\n\n return Result.Ok({\n definition: childDefinition as TChildContract[\"workflows\"][TChildWorkflowName],\n validatedInput,\n taskQueue: childContract.taskQueue,\n });\n}\n\nfunction createTypedChildHandle<TChildWorkflow extends WorkflowDefinition>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handle: ChildWorkflowHandle<any>,\n childDefinition: TChildWorkflow,\n childWorkflowName: string,\n): TypedChildWorkflowHandle<TChildWorkflow> {\n return {\n workflowId: handle.workflowId,\n result: (): Future<Result<ClientInferOutput<TChildWorkflow>, ChildWorkflowError>> => {\n return Future.fromAsync(async () => {\n try {\n const result = await handle.result();\n return validateChildWorkflowOutput(childDefinition, result, childWorkflowName);\n } catch (error) {\n return Result.Error(\n new ChildWorkflowError(\n `Child workflow execution failed: ${error instanceof Error ? error.message : String(error)}`,\n error,\n ),\n );\n }\n });\n },\n };\n}\n\nfunction createStartChildWorkflow<\n TChildContract extends ContractDefinition,\n TChildWorkflowName extends keyof TChildContract[\"workflows\"],\n>(\n childContract: TChildContract,\n childWorkflowName: TChildWorkflowName,\n options: TypedChildWorkflowOptions<TChildContract, TChildWorkflowName>,\n): Future<\n Result<\n TypedChildWorkflowHandle<TChildContract[\"workflows\"][TChildWorkflowName]>,\n ChildWorkflowError\n >\n> {\n return Future.fromAsync(async () => {\n const validationResult = await getAndValidateChildWorkflow(\n childContract,\n childWorkflowName,\n options.args,\n );\n\n if (validationResult.isError()) {\n return Result.Error(validationResult.error);\n }\n\n const { definition: childDefinition, validatedInput, taskQueue } = validationResult.value;\n\n try {\n const { args: _args, ...temporalOptions } = options;\n const handle = await startChild(childWorkflowName as string, {\n ...temporalOptions,\n taskQueue,\n args: [validatedInput],\n });\n\n const typedHandle = createTypedChildHandle(\n handle,\n childDefinition,\n String(childWorkflowName),\n ) as TypedChildWorkflowHandle<TChildContract[\"workflows\"][TChildWorkflowName]>;\n\n return Result.Ok(typedHandle);\n } catch (error) {\n return Result.Error(\n new ChildWorkflowError(\n `Failed to start child workflow: ${error instanceof Error ? error.message : String(error)}`,\n error,\n ),\n );\n }\n });\n}\n\nfunction createExecuteChildWorkflow<\n TChildContract extends ContractDefinition,\n TChildWorkflowName extends keyof TChildContract[\"workflows\"],\n>(\n childContract: TChildContract,\n childWorkflowName: TChildWorkflowName,\n options: TypedChildWorkflowOptions<TChildContract, TChildWorkflowName>,\n): Future<\n Result<ClientInferOutput<TChildContract[\"workflows\"][TChildWorkflowName]>, ChildWorkflowError>\n> {\n return Future.fromAsync(async () => {\n const validationResult = await getAndValidateChildWorkflow(\n childContract,\n childWorkflowName,\n options.args,\n );\n\n if (validationResult.isError()) {\n return Result.Error(validationResult.error);\n }\n\n const { definition: childDefinition, validatedInput, taskQueue } = validationResult.value;\n\n try {\n const { args: _args, ...temporalOptions } = options;\n const result = await executeChild(childWorkflowName as string, {\n ...temporalOptions,\n taskQueue,\n args: [validatedInput],\n });\n\n const outputValidationResult = await validateChildWorkflowOutput(\n childDefinition,\n result,\n String(childWorkflowName),\n );\n\n if (outputValidationResult.isError()) {\n return Result.Error(outputValidationResult.error);\n }\n\n return Result.Ok(\n outputValidationResult.value as ClientInferOutput<\n TChildContract[\"workflows\"][TChildWorkflowName]\n >,\n );\n } catch (error) {\n return Result.Error(\n new ChildWorkflowError(\n `Failed to execute child workflow: ${error instanceof Error ? error.message : String(error)}`,\n error,\n ),\n );\n }\n });\n}\n"],"mappings":"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"}
|