@temporal-contract/worker 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,299 @@
1
- import { B as WorkerInferWorkflowQueries, C as SignalInputValidationError, D as WorkflowInputValidationError, E as WorkerError, F as WorkerInferSignal, H as WorkerInferWorkflowUpdates, I as WorkerInferUpdate, L as WorkerInferWorkflow, M as WorkerInferInput, N as WorkerInferOutput, O as WorkflowOutputValidationError, P as WorkerInferQuery, S as QueryOutputValidationError, T as UpdateOutputValidationError, U as WorkerInferWorkflows, V as WorkerInferWorkflowSignals, a as DeclareWorkflowOptions, b as ChildWorkflowNotFoundError, c as TypedChildWorkflowHandle, d as WorkflowContext, f as WorkflowImplementation, l as TypedChildWorkflowOptions, m as declareWorkflow, o as QueryHandlerImplementation, s as SignalHandlerImplementation, u as UpdateHandlerImplementation, w as UpdateInputValidationError, x as QueryInputValidationError, y as ChildWorkflowError } from "./handler-uAeIi9f0.mjs";
2
- export { ChildWorkflowError, ChildWorkflowNotFoundError, type DeclareWorkflowOptions, type QueryHandlerImplementation, QueryInputValidationError, QueryOutputValidationError, type SignalHandlerImplementation, SignalInputValidationError, type TypedChildWorkflowHandle, type TypedChildWorkflowOptions, type UpdateHandlerImplementation, UpdateInputValidationError, UpdateOutputValidationError, WorkerError, type WorkerInferInput, type WorkerInferOutput, type WorkerInferQuery, type WorkerInferSignal, type WorkerInferUpdate, type WorkerInferWorkflow, type WorkerInferWorkflowQueries, type WorkerInferWorkflowSignals, type WorkerInferWorkflowUpdates, type WorkerInferWorkflows, type WorkflowContext, type WorkflowImplementation, WorkflowInputValidationError, WorkflowOutputValidationError, declareWorkflow };
1
+ import { a as ChildWorkflowNotFoundError, c as SignalInputValidationError, d as WorkflowInputValidationError, f as WorkflowOutputValidationError, g as WorkerInferOutput, h as WorkerInferInput, i as ChildWorkflowError, l as UpdateInputValidationError, m as ClientInferOutput, n as ActivityInputValidationError, o as QueryInputValidationError, p as ClientInferInput, r as ActivityOutputValidationError, s as QueryOutputValidationError, u as UpdateOutputValidationError } from "./errors-C1RFkCuD.mjs";
2
+ import { Future, Result } from "@temporal-contract/boxed";
3
+ import { ActivityOptions, ChildWorkflowOptions, WorkflowInfo } from "@temporalio/workflow";
4
+ import { ActivityDefinition, ContractDefinition, QueryDefinition, SignalDefinition, UpdateDefinition, WorkflowDefinition } from "@temporal-contract/contract";
5
+
6
+ //#region src/workflow.d.ts
7
+
8
+ /**
9
+ * Create a typed workflow implementation with automatic validation
10
+ *
11
+ * This wraps a workflow implementation with:
12
+ * - Input/output validation
13
+ * - Typed workflow context with activities
14
+ * - Workflow info access
15
+ *
16
+ * Workflows must be defined in separate files and imported by the Temporal Worker
17
+ * via workflowsPath.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * // workflows/processOrder.ts
22
+ * import { declareWorkflow } from '@temporal-contract/worker';
23
+ * import myContract from '../contract';
24
+ *
25
+ * export const processOrder = declareWorkflow({
26
+ * workflowName: 'processOrder',
27
+ * contract: myContract,
28
+ * implementation: async (context, orderId, customerId) => {
29
+ * // context.activities: typed activities (workflow + global)
30
+ * // context.info: WorkflowInfo
31
+ *
32
+ * const inventory = await context.activities.validateInventory(orderId);
33
+ *
34
+ * if (!inventory.available) {
35
+ * throw new Error('Out of stock');
36
+ * }
37
+ *
38
+ * const payment = await context.activities.chargePayment(customerId, 100);
39
+ *
40
+ * // Global activity
41
+ * await context.activities.sendEmail(
42
+ * customerId,
43
+ * 'Order processed',
44
+ * 'Your order has been processed'
45
+ * );
46
+ *
47
+ * return {
48
+ * orderId,
49
+ * status: payment.success ? 'success' : 'failed',
50
+ * transactionId: payment.transactionId,
51
+ * };
52
+ * },
53
+ * activityOptions: {
54
+ * startToCloseTimeout: '1 minute',
55
+ * },
56
+ * });
57
+ * ```
58
+ *
59
+ * Then in your worker setup:
60
+ * ```ts
61
+ * // worker.ts
62
+ * import { Worker } from '@temporalio/worker';
63
+ * import { activitiesHandler } from './activities';
64
+ *
65
+ * const worker = await Worker.create({
66
+ * workflowsPath: require.resolve('./workflows'), // Imports processOrder
67
+ * activities: activitiesHandler.activities,
68
+ * taskQueue: activitiesHandler.contract.taskQueue,
69
+ * });
70
+ * ```
71
+ */
72
+ declare function declareWorkflow<TContract extends ContractDefinition, TWorkflowName extends keyof TContract["workflows"]>({
73
+ workflowName,
74
+ contract,
75
+ implementation,
76
+ activityOptions
77
+ }: DeclareWorkflowOptions<TContract, TWorkflowName>): (...args: unknown[]) => Promise<WorkerInferOutput<TContract["workflows"][TWorkflowName]>>;
78
+ /**
79
+ * Signal handler implementation
80
+ *
81
+ * Processes signal input and can optionally perform asynchronous operations.
82
+ * Should not return a value (signals are fire-and-forget).
83
+ */
84
+ type SignalHandlerImplementation<TSignal extends SignalDefinition> = (args: WorkerInferInput<TSignal>) => void | Promise<void>;
85
+ /**
86
+ * Query handler implementation
87
+ *
88
+ * Processes query input and returns a synchronous response.
89
+ * Must be synchronous to satisfy Temporal's query constraints.
90
+ */
91
+ type QueryHandlerImplementation<TQuery extends QueryDefinition> = (args: WorkerInferInput<TQuery>) => WorkerInferOutput<TQuery>;
92
+ /**
93
+ * Update handler implementation
94
+ *
95
+ * Processes update input and returns a validated response after modifying workflow state.
96
+ * Can perform asynchronous operations.
97
+ */
98
+ type UpdateHandlerImplementation<TUpdate extends UpdateDefinition> = (args: WorkerInferInput<TUpdate>) => Promise<WorkerInferOutput<TUpdate>>;
99
+ /**
100
+ * Options for declaring a workflow implementation
101
+ */
102
+ interface DeclareWorkflowOptions<TContract extends ContractDefinition, TWorkflowName extends keyof TContract["workflows"]> {
103
+ workflowName: TWorkflowName;
104
+ contract: TContract;
105
+ implementation: WorkflowImplementation<TContract, TWorkflowName>;
106
+ /**
107
+ * Default activity options applied to all activities in this workflow.
108
+ * For more control, you can override specific Temporal ActivityOptions like:
109
+ * - startToCloseTimeout: Maximum time for activity execution
110
+ * - scheduleToCloseTimeout: End-to-end timeout including queuing
111
+ * - scheduleToStartTimeout: Maximum time activity can wait in queue
112
+ * - heartbeatTimeout: Time between heartbeats before considering activity dead
113
+ * - retry: Retry policy for failed activities
114
+ *
115
+ * @example
116
+ * ```ts
117
+ * activityOptions: {
118
+ * startToCloseTimeout: '5m',
119
+ * retry: { maximumAttempts: 3 }
120
+ * }
121
+ * ```
122
+ */
123
+ activityOptions: ActivityOptions;
124
+ }
125
+ /**
126
+ * Workflow implementation function
127
+ *
128
+ * Receives a workflow context (with typed activities and utilities) and validated input arguments.
129
+ * Returns the workflow output which will be validated against the contract schema.
130
+ */
131
+ type WorkflowImplementation<TContract extends ContractDefinition, TWorkflowName extends keyof TContract["workflows"]> = (context: WorkflowContext<TContract, TWorkflowName>, args: WorkerInferInput<TContract["workflows"][TWorkflowName]>) => Promise<WorkerInferOutput<TContract["workflows"][TWorkflowName]>>;
132
+ /**
133
+ * Workflow execution context providing typed activities, workflow info, and interaction handlers
134
+ *
135
+ * Provides access to:
136
+ * - Typed activities (both workflow-specific and global)
137
+ * - Workflow metadata and execution info
138
+ * - Signal, query, and update handler registration
139
+ * - Child workflow execution capabilities
140
+ */
141
+ interface WorkflowContext<TContract extends ContractDefinition, TWorkflowName extends keyof TContract["workflows"]> {
142
+ activities: WorkflowInferWorkflowContextActivities<TContract, TWorkflowName>;
143
+ info: WorkflowInfo;
144
+ /**
145
+ * Define a signal handler within the workflow implementation
146
+ * Allows the signal handler to access workflow state
147
+ *
148
+ * @example
149
+ * ```ts
150
+ * implementation: async (context, args) => {
151
+ * let currentValue = args.initialValue;
152
+ *
153
+ * context.defineSignal('increment', async (signalArgs) => {
154
+ * currentValue += signalArgs.amount;
155
+ * });
156
+ *
157
+ * // ... rest of workflow
158
+ * }
159
+ * ```
160
+ */
161
+ defineSignal: <K$1 extends keyof TContract["workflows"][TWorkflowName]["signals"]>(signalName: K$1, handler: SignalHandlerImplementation<TContract["workflows"][TWorkflowName]["signals"][K$1] extends SignalDefinition ? TContract["workflows"][TWorkflowName]["signals"][K$1] : never>) => void;
162
+ /**
163
+ * Define a query handler within the workflow implementation
164
+ * Allows the query handler to access workflow state
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * implementation: async (context, args) => {
169
+ * let currentValue = args.initialValue;
170
+ *
171
+ * context.defineQuery('getCurrentValue', () => {
172
+ * return { value: currentValue };
173
+ * });
174
+ *
175
+ * // ... rest of workflow
176
+ * }
177
+ * ```
178
+ */
179
+ defineQuery: <K$1 extends keyof TContract["workflows"][TWorkflowName]["queries"]>(queryName: K$1, handler: QueryHandlerImplementation<TContract["workflows"][TWorkflowName]["queries"][K$1] extends QueryDefinition ? TContract["workflows"][TWorkflowName]["queries"][K$1] : never>) => void;
180
+ /**
181
+ * Define an update handler within the workflow implementation
182
+ * Allows the update handler to access and modify workflow state
183
+ *
184
+ * @example
185
+ * ```ts
186
+ * implementation: async (context, args) => {
187
+ * let currentValue = args.initialValue;
188
+ *
189
+ * context.defineUpdate('multiply', async (updateArgs) => {
190
+ * currentValue *= updateArgs.factor;
191
+ * return { newValue: currentValue };
192
+ * });
193
+ *
194
+ * // ... rest of workflow
195
+ * }
196
+ * ```
197
+ */
198
+ defineUpdate: <K$1 extends keyof TContract["workflows"][TWorkflowName]["updates"]>(updateName: K$1, handler: UpdateHandlerImplementation<TContract["workflows"][TWorkflowName]["updates"][K$1] extends UpdateDefinition ? TContract["workflows"][TWorkflowName]["updates"][K$1] : never>) => void;
199
+ /**
200
+ * Start a child workflow and return a typed handle with Future/Result pattern
201
+ *
202
+ * Supports both same-contract and cross-contract child workflows:
203
+ * - Same contract: Pass workflowName from current contract
204
+ * - Cross-contract: Pass contract and workflowName to invoke workflows from other workers
205
+ *
206
+ * @example
207
+ * ```ts
208
+ * // Same contract child workflow
209
+ * const childResult = await context.startChildWorkflow(myContract, 'processPayment', {
210
+ * workflowId: 'payment-123',
211
+ * args: { amount: 100 }
212
+ * });
213
+ *
214
+ * // Cross-contract child workflow (from another worker)
215
+ * const otherResult = await context.startChildWorkflow(otherContract, 'sendNotification', {
216
+ * workflowId: 'notification-123',
217
+ * args: { message: 'Hello' }
218
+ * });
219
+ *
220
+ * childResult.match({
221
+ * Ok: async (handle) => {
222
+ * const result = await handle.result();
223
+ * // ... handle result
224
+ * },
225
+ * Error: (error) => console.error('Failed to start:', error),
226
+ * });
227
+ * ```
228
+ */
229
+ startChildWorkflow: <TChildContract extends ContractDefinition, TChildWorkflowName extends keyof TChildContract["workflows"]>(contract: TChildContract, workflowName: TChildWorkflowName, options: TypedChildWorkflowOptions<TChildContract, TChildWorkflowName>) => Future<Result<TypedChildWorkflowHandle<TChildContract["workflows"][TChildWorkflowName]>, ChildWorkflowError>>;
230
+ /**
231
+ * Execute a child workflow (start and wait for result) with Future/Result pattern
232
+ *
233
+ * Supports both same-contract and cross-contract child workflows:
234
+ * - Same contract: Pass workflowName from current contract
235
+ * - Cross-contract: Pass contract and workflowName to invoke workflows from other workers
236
+ *
237
+ * @example
238
+ * ```ts
239
+ * // Same contract child workflow
240
+ * const result = await context.executeChildWorkflow(myContract, 'processPayment', {
241
+ * workflowId: 'payment-123',
242
+ * args: { amount: 100 }
243
+ * });
244
+ *
245
+ * // Cross-contract child workflow (from another worker)
246
+ * const otherResult = await context.executeChildWorkflow(otherContract, 'sendNotification', {
247
+ * workflowId: 'notification-123',
248
+ * args: { message: 'Hello' }
249
+ * });
250
+ *
251
+ * result.match({
252
+ * Ok: (output) => console.log('Payment processed:', output),
253
+ * Error: (error) => console.error('Processing failed:', error),
254
+ * });
255
+ * ```
256
+ */
257
+ executeChildWorkflow: <TChildContract extends ContractDefinition, TChildWorkflowName extends keyof TChildContract["workflows"]>(contract: TChildContract, workflowName: TChildWorkflowName, options: TypedChildWorkflowOptions<TChildContract, TChildWorkflowName>) => Future<Result<ClientInferOutput<TChildContract["workflows"][TChildWorkflowName]>, ChildWorkflowError>>;
258
+ }
259
+ /**
260
+ * Options for starting a child workflow
261
+ */
262
+ type TypedChildWorkflowOptions<TChildContract extends ContractDefinition, TChildWorkflowName extends keyof TChildContract["workflows"]> = Omit<ChildWorkflowOptions, "taskQueue" | "args"> & {
263
+ args: ClientInferInput<TChildContract["workflows"][TChildWorkflowName]>;
264
+ };
265
+ /**
266
+ * Typed handle for a child workflow with Future/Result pattern
267
+ */
268
+ interface TypedChildWorkflowHandle<TWorkflow extends WorkflowDefinition> {
269
+ /**
270
+ * Get child workflow result with Result pattern
271
+ */
272
+ result: () => Future<Result<ClientInferOutput<TWorkflow>, ChildWorkflowError>>;
273
+ /**
274
+ * Child workflow ID
275
+ */
276
+ workflowId: string;
277
+ }
278
+ /**
279
+ * Activity function signature from workflow execution perspective
280
+ *
281
+ * Workflows call activities with validated input (z.input parsed) and receive validated output (z.output)
282
+ */
283
+ type WorkflowInferActivity<TActivity extends ActivityDefinition> = (args: ClientInferInput<TActivity>) => Promise<ClientInferOutput<TActivity>>;
284
+ /**
285
+ * All global activities from a contract (workflow execution perspective)
286
+ */
287
+ type WorkflowInferActivities<TContract extends ContractDefinition> = TContract["activities"] extends Record<string, ActivityDefinition> ? { [K in keyof TContract["activities"]]: WorkflowInferActivity<TContract["activities"][K]> } : {};
288
+ /**
289
+ * Workflow-specific activities (workflow execution perspective)
290
+ */
291
+ type WorkflowInferWorkflowActivities<T extends WorkflowDefinition> = T["activities"] extends Record<string, ActivityDefinition> ? { [K in keyof T["activities"]]: WorkflowInferActivity<T["activities"][K]> } : {};
292
+ /**
293
+ * All activities available in a workflow context (workflow execution perspective)
294
+ *
295
+ * Combines workflow-specific activities with global contract activities
296
+ */
297
+ type WorkflowInferWorkflowContextActivities<TContract extends ContractDefinition, TWorkflowName extends keyof TContract["workflows"]> = WorkflowInferWorkflowActivities<TContract["workflows"][TWorkflowName]> & WorkflowInferActivities<TContract>;
298
+ //#endregion
299
+ export { ActivityInputValidationError, ActivityOutputValidationError, ChildWorkflowError, ChildWorkflowNotFoundError, QueryInputValidationError, QueryOutputValidationError, SignalInputValidationError, UpdateInputValidationError, UpdateOutputValidationError, WorkflowInputValidationError, WorkflowOutputValidationError, declareWorkflow };
package/dist/workflow.mjs CHANGED
@@ -1,3 +1,245 @@
1
- import { c as ChildWorkflowNotFoundError, d as SignalInputValidationError, f as UpdateInputValidationError, g as WorkflowOutputValidationError, h as WorkflowInputValidationError, l as QueryInputValidationError, m as WorkerError, n as declareWorkflow, p as UpdateOutputValidationError, s as ChildWorkflowError, u as QueryOutputValidationError } from "./handler-DFFpSaGN.mjs";
1
+ import { a as ChildWorkflowNotFoundError, c as SignalInputValidationError, d as WorkflowInputValidationError, f as WorkflowOutputValidationError, i as ChildWorkflowError, l as UpdateInputValidationError, n as ActivityInputValidationError, o as QueryInputValidationError, r as ActivityOutputValidationError, s as QueryOutputValidationError, u as UpdateOutputValidationError } from "./errors-BqVTpfcf.mjs";
2
+ import { Future, Result } from "@temporal-contract/boxed";
3
+ import { defineQuery, defineSignal, defineUpdate, executeChild, proxyActivities, setHandler, startChild, workflowInfo } from "@temporalio/workflow";
2
4
 
3
- export { ChildWorkflowError, ChildWorkflowNotFoundError, QueryInputValidationError, QueryOutputValidationError, SignalInputValidationError, UpdateInputValidationError, UpdateOutputValidationError, WorkerError, WorkflowInputValidationError, WorkflowOutputValidationError, declareWorkflow };
5
+ //#region src/workflow.ts
6
+ /**
7
+ * Create a typed workflow implementation with automatic validation
8
+ *
9
+ * This wraps a workflow implementation with:
10
+ * - Input/output validation
11
+ * - Typed workflow context with activities
12
+ * - Workflow info access
13
+ *
14
+ * Workflows must be defined in separate files and imported by the Temporal Worker
15
+ * via workflowsPath.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * // workflows/processOrder.ts
20
+ * import { declareWorkflow } from '@temporal-contract/worker';
21
+ * import myContract from '../contract';
22
+ *
23
+ * export const processOrder = declareWorkflow({
24
+ * workflowName: 'processOrder',
25
+ * contract: myContract,
26
+ * implementation: async (context, orderId, customerId) => {
27
+ * // context.activities: typed activities (workflow + global)
28
+ * // context.info: WorkflowInfo
29
+ *
30
+ * const inventory = await context.activities.validateInventory(orderId);
31
+ *
32
+ * if (!inventory.available) {
33
+ * throw new Error('Out of stock');
34
+ * }
35
+ *
36
+ * const payment = await context.activities.chargePayment(customerId, 100);
37
+ *
38
+ * // Global activity
39
+ * await context.activities.sendEmail(
40
+ * customerId,
41
+ * 'Order processed',
42
+ * 'Your order has been processed'
43
+ * );
44
+ *
45
+ * return {
46
+ * orderId,
47
+ * status: payment.success ? 'success' : 'failed',
48
+ * transactionId: payment.transactionId,
49
+ * };
50
+ * },
51
+ * activityOptions: {
52
+ * startToCloseTimeout: '1 minute',
53
+ * },
54
+ * });
55
+ * ```
56
+ *
57
+ * Then in your worker setup:
58
+ * ```ts
59
+ * // worker.ts
60
+ * import { Worker } from '@temporalio/worker';
61
+ * import { activitiesHandler } from './activities';
62
+ *
63
+ * const worker = await Worker.create({
64
+ * workflowsPath: require.resolve('./workflows'), // Imports processOrder
65
+ * activities: activitiesHandler.activities,
66
+ * taskQueue: activitiesHandler.contract.taskQueue,
67
+ * });
68
+ * ```
69
+ */
70
+ function declareWorkflow({ workflowName, contract, implementation, activityOptions }) {
71
+ const definition = contract.workflows[workflowName];
72
+ return async (...args) => {
73
+ const input = args.length === 1 ? args[0] : args;
74
+ const inputResult = await definition.input["~standard"].validate(input);
75
+ if (inputResult.issues) throw new WorkflowInputValidationError(String(workflowName), inputResult.issues);
76
+ const validatedInput = inputResult.value;
77
+ let contextActivities = {};
78
+ if (definition.activities || contract.activities) contextActivities = createValidatedActivities(proxyActivities(activityOptions), definition.activities, contract.activities);
79
+ async function validateChildWorkflowOutput(childDefinition, result$1, childWorkflowName) {
80
+ const outputResult$1 = await childDefinition.output["~standard"].validate(result$1);
81
+ if (outputResult$1.issues) return Result.Error(new ChildWorkflowError(`Child workflow "${childWorkflowName}" output validation failed: ${outputResult$1.issues.map((i) => i.message).join("; ")}`));
82
+ return Result.Ok(outputResult$1.value);
83
+ }
84
+ async function getAndValidateChildWorkflow(childContract, childWorkflowName, args$1) {
85
+ const childDefinition = childContract.workflows[childWorkflowName];
86
+ if (!childDefinition) return Result.Error(new ChildWorkflowNotFoundError(String(childWorkflowName), Object.keys(childContract.workflows)));
87
+ const inputResult$1 = await childDefinition.input["~standard"].validate(args$1);
88
+ if (inputResult$1.issues) return Result.Error(new ChildWorkflowError(`Child workflow "${String(childWorkflowName)}" input validation failed: ${inputResult$1.issues.map((i) => i.message).join("; ")}`));
89
+ const validatedInput$1 = inputResult$1.value;
90
+ return Result.Ok({
91
+ definition: childDefinition,
92
+ validatedInput: validatedInput$1,
93
+ taskQueue: childContract.taskQueue
94
+ });
95
+ }
96
+ function createTypedChildHandle(handle, childDefinition, childWorkflowName) {
97
+ return {
98
+ workflowId: handle.workflowId,
99
+ result: () => {
100
+ return Future.make((resolve) => {
101
+ (async () => {
102
+ try {
103
+ resolve(await validateChildWorkflowOutput(childDefinition, await handle.result(), childWorkflowName));
104
+ } catch (error) {
105
+ resolve(Result.Error(new ChildWorkflowError(`Child workflow execution failed: ${error instanceof Error ? error.message : String(error)}`, error)));
106
+ }
107
+ })();
108
+ });
109
+ }
110
+ };
111
+ }
112
+ function createStartChildWorkflow(childContract, childWorkflowName, options) {
113
+ return Future.make((resolve) => {
114
+ (async () => {
115
+ const validationResult = await getAndValidateChildWorkflow(childContract, childWorkflowName, options.args);
116
+ if (validationResult.isError()) {
117
+ resolve(Result.Error(validationResult.error));
118
+ return;
119
+ }
120
+ const { definition: childDefinition, validatedInput: validatedInput$1, taskQueue } = validationResult.value;
121
+ try {
122
+ const { args: _args, ...temporalOptions } = options;
123
+ const typedHandle = createTypedChildHandle(await startChild(childWorkflowName, {
124
+ ...temporalOptions,
125
+ taskQueue,
126
+ args: [validatedInput$1]
127
+ }), childDefinition, String(childWorkflowName));
128
+ resolve(Result.Ok(typedHandle));
129
+ } catch (error) {
130
+ resolve(Result.Error(new ChildWorkflowError(`Failed to start child workflow: ${error instanceof Error ? error.message : String(error)}`, error)));
131
+ }
132
+ })();
133
+ });
134
+ }
135
+ function createExecuteChildWorkflow(childContract, childWorkflowName, options) {
136
+ return Future.make((resolve) => {
137
+ (async () => {
138
+ const validationResult = await getAndValidateChildWorkflow(childContract, childWorkflowName, options.args);
139
+ if (validationResult.isError()) {
140
+ resolve(Result.Error(validationResult.error));
141
+ return;
142
+ }
143
+ const { definition: childDefinition, validatedInput: validatedInput$1, taskQueue } = validationResult.value;
144
+ try {
145
+ const { args: _args, ...temporalOptions } = options;
146
+ const outputValidationResult = await validateChildWorkflowOutput(childDefinition, await executeChild(childWorkflowName, {
147
+ ...temporalOptions,
148
+ taskQueue,
149
+ args: [validatedInput$1]
150
+ }), String(childWorkflowName));
151
+ if (outputValidationResult.isError()) {
152
+ resolve(Result.Error(outputValidationResult.error));
153
+ return;
154
+ }
155
+ resolve(Result.Ok(outputValidationResult.value));
156
+ } catch (error) {
157
+ resolve(Result.Error(new ChildWorkflowError(`Failed to execute child workflow: ${error instanceof Error ? error.message : String(error)}`, error)));
158
+ }
159
+ })();
160
+ });
161
+ }
162
+ function createDefineSignal(signalName, handler) {
163
+ if (!definition.signals) throw new Error(`Signal "${String(signalName)}" cannot be defined: workflow "${String(workflowName)}" has no signals in its contract`);
164
+ const signalDef = definition.signals[signalName];
165
+ if (!signalDef) throw new Error(`Signal "${String(signalName)}" not found in workflow "${String(workflowName)}" contract`);
166
+ setHandler(defineSignal(signalName), async (...args$1) => {
167
+ const input$1 = args$1.length === 1 ? args$1[0] : args$1;
168
+ const inputResult$1 = await signalDef.input["~standard"].validate(input$1);
169
+ if (inputResult$1.issues) throw new SignalInputValidationError(signalName, inputResult$1.issues);
170
+ await handler(inputResult$1.value);
171
+ });
172
+ }
173
+ function createDefineQuery(queryName, handler) {
174
+ if (!definition.queries) throw new Error(`Query "${String(queryName)}" cannot be defined: workflow "${String(workflowName)}" has no queries in its contract`);
175
+ const queryDef = definition.queries[queryName];
176
+ if (!queryDef) throw new Error(`Query "${String(queryName)}" not found in workflow "${String(workflowName)}" contract`);
177
+ setHandler(defineQuery(queryName), (...args$1) => {
178
+ const input$1 = args$1.length === 1 ? args$1[0] : args$1;
179
+ const inputResult$1 = queryDef.input["~standard"].validate(input$1);
180
+ if (inputResult$1 instanceof Promise) throw new Error(`Query "${String(queryName)}" validation must be synchronous. Use a schema library that supports synchronous validation for queries.`);
181
+ if (inputResult$1.issues) throw new QueryInputValidationError(queryName, inputResult$1.issues);
182
+ const result$1 = handler(inputResult$1.value);
183
+ const outputResult$1 = queryDef.output["~standard"].validate(result$1);
184
+ if (outputResult$1 instanceof Promise) throw new Error(`Query "${String(queryName)}" output validation must be synchronous. Use a schema library that supports synchronous validation for queries.`);
185
+ if (outputResult$1.issues) throw new QueryOutputValidationError(queryName, outputResult$1.issues);
186
+ return outputResult$1.value;
187
+ });
188
+ }
189
+ function createDefineUpdate(updateName, handler) {
190
+ if (!definition.updates) throw new Error(`Update "${String(updateName)}" cannot be defined: workflow "${String(workflowName)}" has no updates in its contract`);
191
+ const updateDef = definition.updates[updateName];
192
+ if (!updateDef) throw new Error(`Update "${String(updateName)}" not found in workflow "${String(workflowName)}" contract`);
193
+ setHandler(defineUpdate(updateName), async (...args$1) => {
194
+ const input$1 = args$1.length === 1 ? args$1[0] : args$1;
195
+ const inputResult$1 = await updateDef.input["~standard"].validate(input$1);
196
+ if (inputResult$1.issues) throw new UpdateInputValidationError(updateName, inputResult$1.issues);
197
+ const result$1 = await handler(inputResult$1.value);
198
+ const outputResult$1 = await updateDef.output["~standard"].validate(result$1);
199
+ if (outputResult$1.issues) throw new UpdateOutputValidationError(updateName, outputResult$1.issues);
200
+ return outputResult$1.value;
201
+ });
202
+ }
203
+ const result = await implementation({
204
+ activities: contextActivities,
205
+ info: workflowInfo(),
206
+ startChildWorkflow: createStartChildWorkflow,
207
+ executeChildWorkflow: createExecuteChildWorkflow,
208
+ defineSignal: createDefineSignal,
209
+ defineQuery: createDefineQuery,
210
+ defineUpdate: createDefineUpdate
211
+ }, validatedInput);
212
+ const outputResult = await definition.output["~standard"].validate(result);
213
+ if (outputResult.issues) throw new WorkflowOutputValidationError(String(workflowName), outputResult.issues);
214
+ return outputResult.value;
215
+ };
216
+ }
217
+ /**
218
+ * Create a validated activities proxy that parses inputs and outputs
219
+ *
220
+ * This wrapper ensures data integrity across the network boundary between
221
+ * workflow and activity execution.
222
+ */
223
+ function createValidatedActivities(rawActivities, workflowActivitiesDefinition, contractActivitiesDefinition) {
224
+ const validatedActivities = {};
225
+ const allActivitiesDefinition = {
226
+ ...contractActivitiesDefinition,
227
+ ...workflowActivitiesDefinition
228
+ };
229
+ for (const [activityName, activityDef] of Object.entries(allActivitiesDefinition)) {
230
+ const rawActivity = rawActivities[activityName];
231
+ if (!rawActivity) throw new Error(`Activity implementation not found for: "${activityName}". Available activities: ${Object.keys(rawActivities).length > 0 ? Object.keys(rawActivities).join(", ") : "none"}`);
232
+ validatedActivities[activityName] = async (input) => {
233
+ const inputResult = await activityDef.input["~standard"].validate(input);
234
+ if (inputResult.issues) throw new ActivityInputValidationError(activityName, inputResult.issues);
235
+ const result = await rawActivity(inputResult.value);
236
+ const outputResult = await activityDef.output["~standard"].validate(result);
237
+ if (outputResult.issues) throw new ActivityOutputValidationError(activityName, outputResult.issues);
238
+ return outputResult.value;
239
+ };
240
+ }
241
+ return validatedActivities;
242
+ }
243
+
244
+ //#endregion
245
+ export { ActivityInputValidationError, ActivityOutputValidationError, ChildWorkflowError, ChildWorkflowNotFoundError, QueryInputValidationError, QueryOutputValidationError, SignalInputValidationError, UpdateInputValidationError, UpdateOutputValidationError, WorkflowInputValidationError, WorkflowOutputValidationError, declareWorkflow };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@temporal-contract/worker",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "Worker utilities with Result/Future pattern for implementing temporal-contract workflows and activities",
5
5
  "keywords": [
6
6
  "contract",
@@ -20,7 +20,7 @@
20
20
  "directory": "packages/worker"
21
21
  },
22
22
  "license": "MIT",
23
- "author": "Benoit TRAVERS <benoit.travers.frgmail.com>",
23
+ "author": "Benoit TRAVERS <benoit.travers.fr@gmail.com>",
24
24
  "type": "module",
25
25
  "exports": {
26
26
  "./activity": {
@@ -34,6 +34,16 @@
34
34
  }
35
35
  },
36
36
  "./package.json": "./package.json",
37
+ "./worker": {
38
+ "import": {
39
+ "types": "./dist/worker.d.mts",
40
+ "default": "./dist/worker.mjs"
41
+ },
42
+ "require": {
43
+ "types": "./dist/worker.d.cts",
44
+ "default": "./dist/worker.cjs"
45
+ }
46
+ },
37
47
  "./workflow": {
38
48
  "import": {
39
49
  "types": "./dist/workflow.d.mts",
@@ -53,29 +63,31 @@
53
63
  ],
54
64
  "dependencies": {
55
65
  "@standard-schema/spec": "1.1.0",
56
- "@temporal-contract/boxed": "0.0.5",
57
- "@temporal-contract/contract": "0.0.5"
66
+ "@swan-io/boxed": "3.2.1",
67
+ "@temporal-contract/boxed": "0.0.7",
68
+ "@temporal-contract/contract": "0.0.7"
58
69
  },
59
70
  "devDependencies": {
60
- "@temporalio/client": "1.13.2",
61
- "@temporalio/worker": "1.13.2",
62
- "@temporalio/workflow": "1.13.2",
63
- "@types/node": "25.0.2",
71
+ "@temporalio/client": "1.14.0",
72
+ "@temporalio/worker": "1.14.0",
73
+ "@temporalio/workflow": "1.14.0",
74
+ "@types/node": "25.0.3",
64
75
  "@vitest/coverage-v8": "4.0.16",
65
- "tsdown": "0.18.0",
76
+ "tsdown": "0.18.1",
66
77
  "typescript": "5.9.3",
67
78
  "vitest": "4.0.16",
68
79
  "zod": "4.2.1",
69
- "@temporal-contract/client": "0.0.5",
70
- "@temporal-contract/testing": "0.0.5",
71
- "@temporal-contract/tsconfig": "0.0.5"
80
+ "@temporal-contract/client": "0.0.7",
81
+ "@temporal-contract/testing": "0.0.7",
82
+ "@temporal-contract/tsconfig": "0.0.7"
72
83
  },
73
84
  "peerDependencies": {
85
+ "@temporalio/worker": "^1",
74
86
  "@temporalio/workflow": "^1"
75
87
  },
76
88
  "scripts": {
77
- "build": "tsdown src/activity.ts src/workflow.ts --format cjs,esm --dts --clean",
78
- "dev": "tsdown src/activity.ts src/workflow.ts --format cjs,esm --dts --watch",
89
+ "build": "tsdown src/activity.ts src/worker.ts src/workflow.ts --format cjs,esm --dts --clean",
90
+ "dev": "tsdown src/activity.ts src/worker.ts src/workflow.ts --format cjs,esm --dts --watch",
79
91
  "test": "vitest run --project unit",
80
92
  "test:integration": "vitest run --project integration",
81
93
  "test:watch": "vitest --project unit",