@temporal-contract/worker 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,492 @@
1
+ let __temporalio_workflow = require("@temporalio/workflow");
2
+ let zod = require("zod");
3
+
4
+ //#region src/errors.ts
5
+ /**
6
+ * Base error class for worker errors
7
+ */
8
+ var WorkerError = class extends Error {
9
+ constructor(message) {
10
+ super(message);
11
+ this.name = "WorkerError";
12
+ if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
13
+ }
14
+ };
15
+ /**
16
+ * Error thrown when an activity implementation is not found
17
+ */
18
+ var ActivityImplementationNotFoundError = class extends WorkerError {
19
+ constructor(activityName, availableActivities) {
20
+ super(`Activity implementation not found for: "${activityName}". Available activities: ${availableActivities.length > 0 ? availableActivities.join(", ") : "none"}`);
21
+ this.activityName = activityName;
22
+ this.availableActivities = availableActivities;
23
+ this.name = "ActivityImplementationNotFoundError";
24
+ }
25
+ };
26
+ /**
27
+ * Error thrown when an activity definition is not found in the contract
28
+ */
29
+ var ActivityDefinitionNotFoundError = class extends WorkerError {
30
+ constructor(activityName, availableDefinitions) {
31
+ super(`Activity definition not found in contract for: "${activityName}". Available definitions: ${availableDefinitions.length > 0 ? availableDefinitions.join(", ") : "none"}`);
32
+ this.activityName = activityName;
33
+ this.availableDefinitions = availableDefinitions;
34
+ this.name = "ActivityDefinitionNotFoundError";
35
+ }
36
+ };
37
+ /**
38
+ * Error thrown when activity input validation fails
39
+ */
40
+ var ActivityInputValidationError = class extends WorkerError {
41
+ constructor(activityName, zodError) {
42
+ super(`Activity "${activityName}" input validation failed: ${zodError.message}`);
43
+ this.activityName = activityName;
44
+ this.zodError = zodError;
45
+ this.name = "ActivityInputValidationError";
46
+ }
47
+ };
48
+ /**
49
+ * Error thrown when activity output validation fails
50
+ */
51
+ var ActivityOutputValidationError = class extends WorkerError {
52
+ constructor(activityName, zodError) {
53
+ super(`Activity "${activityName}" output validation failed: ${zodError.message}`);
54
+ this.activityName = activityName;
55
+ this.zodError = zodError;
56
+ this.name = "ActivityOutputValidationError";
57
+ }
58
+ };
59
+ /**
60
+ * Error thrown when workflow input validation fails
61
+ */
62
+ var WorkflowInputValidationError = class extends WorkerError {
63
+ constructor(workflowName, zodError) {
64
+ super(`Workflow "${workflowName}" input validation failed: ${zodError.message}`);
65
+ this.workflowName = workflowName;
66
+ this.zodError = zodError;
67
+ this.name = "WorkflowInputValidationError";
68
+ }
69
+ };
70
+ /**
71
+ * Error thrown when workflow output validation fails
72
+ */
73
+ var WorkflowOutputValidationError = class extends WorkerError {
74
+ constructor(workflowName, zodError) {
75
+ super(`Workflow "${workflowName}" output validation failed: ${zodError.message}`);
76
+ this.workflowName = workflowName;
77
+ this.zodError = zodError;
78
+ this.name = "WorkflowOutputValidationError";
79
+ }
80
+ };
81
+ /**
82
+ * Error thrown when signal input validation fails
83
+ */
84
+ var SignalInputValidationError = class extends WorkerError {
85
+ constructor(signalName, zodError) {
86
+ super(`Signal "${signalName}" input validation failed: ${zodError.message}`);
87
+ this.signalName = signalName;
88
+ this.zodError = zodError;
89
+ this.name = "SignalInputValidationError";
90
+ }
91
+ };
92
+ /**
93
+ * Error thrown when query input validation fails
94
+ */
95
+ var QueryInputValidationError = class extends WorkerError {
96
+ constructor(queryName, zodError) {
97
+ super(`Query "${queryName}" input validation failed: ${zodError.message}`);
98
+ this.queryName = queryName;
99
+ this.zodError = zodError;
100
+ this.name = "QueryInputValidationError";
101
+ }
102
+ };
103
+ /**
104
+ * Error thrown when query output validation fails
105
+ */
106
+ var QueryOutputValidationError = class extends WorkerError {
107
+ constructor(queryName, zodError) {
108
+ super(`Query "${queryName}" output validation failed: ${zodError.message}`);
109
+ this.queryName = queryName;
110
+ this.zodError = zodError;
111
+ this.name = "QueryOutputValidationError";
112
+ }
113
+ };
114
+ /**
115
+ * Error thrown when update input validation fails
116
+ */
117
+ var UpdateInputValidationError = class extends WorkerError {
118
+ constructor(updateName, zodError) {
119
+ super(`Update "${updateName}" input validation failed: ${zodError.message}`);
120
+ this.updateName = updateName;
121
+ this.zodError = zodError;
122
+ this.name = "UpdateInputValidationError";
123
+ }
124
+ };
125
+ /**
126
+ * Error thrown when update output validation fails
127
+ */
128
+ var UpdateOutputValidationError = class extends WorkerError {
129
+ constructor(updateName, zodError) {
130
+ super(`Update "${updateName}" output validation failed: ${zodError.message}`);
131
+ this.updateName = updateName;
132
+ this.zodError = zodError;
133
+ this.name = "UpdateOutputValidationError";
134
+ }
135
+ };
136
+
137
+ //#endregion
138
+ //#region src/handler.ts
139
+ /**
140
+ * Create a validated activities proxy that parses inputs and outputs
141
+ *
142
+ * This wrapper ensures data integrity across the network boundary between
143
+ * workflow and activity execution.
144
+ */
145
+ function createValidatedActivities(rawActivities, workflowActivitiesDefinition, contractActivitiesDefinition) {
146
+ const validatedActivities = {};
147
+ const allActivitiesDefinition = {
148
+ ...contractActivitiesDefinition,
149
+ ...workflowActivitiesDefinition
150
+ };
151
+ for (const [activityName, activityDef] of Object.entries(allActivitiesDefinition)) {
152
+ const rawActivity = rawActivities[activityName];
153
+ if (!rawActivity) throw new ActivityImplementationNotFoundError(activityName, Object.keys(rawActivities));
154
+ validatedActivities[activityName] = async (input) => {
155
+ let validatedInput;
156
+ try {
157
+ validatedInput = activityDef.input.parse(input);
158
+ } catch (error) {
159
+ if (error instanceof zod.ZodError) throw new ActivityInputValidationError(activityName, error);
160
+ throw error;
161
+ }
162
+ const result = await rawActivity(validatedInput);
163
+ try {
164
+ return activityDef.output.parse(result);
165
+ } catch (error) {
166
+ if (error instanceof zod.ZodError) throw new ActivityOutputValidationError(activityName, error);
167
+ throw error;
168
+ }
169
+ };
170
+ }
171
+ return validatedActivities;
172
+ }
173
+ /**
174
+ * Create a typed activities handler with automatic validation
175
+ *
176
+ * This wraps all activity implementations with Zod validation at network boundaries.
177
+ * TypeScript ensures ALL activities (global + workflow-specific) are implemented.
178
+ *
179
+ * Use this to create the activities object for the Temporal Worker.
180
+ *
181
+ * @example
182
+ * ```ts
183
+ * import { declareActivitiesHandler } from '@temporal-contract/worker';
184
+ * import myContract from './contract';
185
+ *
186
+ * export const activitiesHandler = declareActivitiesHandler({
187
+ * contract: myContract,
188
+ * activities: {
189
+ * // Global activities
190
+ * sendEmail: async (to, subject, body) => {
191
+ * await emailService.send({ to, subject, body });
192
+ * return { sent: true };
193
+ * },
194
+ * // Workflow-specific activities
195
+ * validateInventory: async (orderId) => {
196
+ * const available = await inventory.check(orderId);
197
+ * return { available };
198
+ * },
199
+ * },
200
+ * });
201
+ *
202
+ * // Use with Temporal Worker
203
+ * import { Worker } from '@temporalio/worker';
204
+ *
205
+ * const worker = await Worker.create({
206
+ * workflowsPath: require.resolve('./workflows'),
207
+ * activities: activitiesHandler.activities,
208
+ * taskQueue: activitiesHandler.contract.taskQueue,
209
+ * });
210
+ * ```
211
+ */
212
+ function declareActivitiesHandler(options) {
213
+ const { contract, activities } = options;
214
+ const wrappedActivities = {};
215
+ const allDefinitions = [];
216
+ if (contract.activities) allDefinitions.push(...Object.keys(contract.activities));
217
+ for (const workflow of Object.values(contract.workflows)) if (workflow.activities) allDefinitions.push(...Object.keys(workflow.activities));
218
+ for (const [activityName, activityImpl] of Object.entries(activities)) {
219
+ let activityDef;
220
+ if (contract.activities?.[activityName]) activityDef = contract.activities[activityName];
221
+ else for (const workflow of Object.values(contract.workflows)) if (workflow.activities?.[activityName]) {
222
+ activityDef = workflow.activities[activityName];
223
+ break;
224
+ }
225
+ if (!activityDef) throw new ActivityDefinitionNotFoundError(activityName, allDefinitions);
226
+ wrappedActivities[activityName] = async (input) => {
227
+ let validatedInput;
228
+ try {
229
+ validatedInput = activityDef.input.parse(input);
230
+ } catch (error) {
231
+ if (error instanceof zod.ZodError) throw new ActivityInputValidationError(activityName, error);
232
+ throw error;
233
+ }
234
+ const result = await activityImpl(validatedInput);
235
+ try {
236
+ return activityDef.output.parse(result);
237
+ } catch (error) {
238
+ if (error instanceof zod.ZodError) throw new ActivityOutputValidationError(activityName, error);
239
+ throw error;
240
+ }
241
+ };
242
+ }
243
+ return {
244
+ contract,
245
+ activities: wrappedActivities
246
+ };
247
+ }
248
+ /**
249
+ * Create a typed workflow implementation with automatic validation
250
+ *
251
+ * This wraps a workflow implementation with:
252
+ * - Input/output validation
253
+ * - Typed workflow context with activities
254
+ * - Workflow info access
255
+ *
256
+ * Workflows must be defined in separate files and imported by the Temporal Worker
257
+ * via workflowsPath.
258
+ *
259
+ * @example
260
+ * ```ts
261
+ * // workflows/processOrder.ts
262
+ * import { declareWorkflow } from '@temporal-contract/worker';
263
+ * import myContract from '../contract';
264
+ *
265
+ * export const processOrder = declareWorkflow({
266
+ * workflowName: 'processOrder',
267
+ * contract: myContract,
268
+ * implementation: async (context, orderId, customerId) => {
269
+ * // context.activities: typed activities (workflow + global)
270
+ * // context.info: WorkflowInfo
271
+ *
272
+ * const inventory = await context.activities.validateInventory(orderId);
273
+ *
274
+ * if (!inventory.available) {
275
+ * throw new Error('Out of stock');
276
+ * }
277
+ *
278
+ * const payment = await context.activities.chargePayment(customerId, 100);
279
+ *
280
+ * // Global activity
281
+ * await context.activities.sendEmail(
282
+ * customerId,
283
+ * 'Order processed',
284
+ * 'Your order has been processed'
285
+ * );
286
+ *
287
+ * return {
288
+ * orderId,
289
+ * status: payment.success ? 'success' : 'failed',
290
+ * transactionId: payment.transactionId,
291
+ * };
292
+ * },
293
+ * activityOptions: {
294
+ * startToCloseTimeout: '1 minute',
295
+ * },
296
+ * });
297
+ * ```
298
+ *
299
+ * Then in your worker setup:
300
+ * ```ts
301
+ * // worker.ts
302
+ * import { Worker } from '@temporalio/worker';
303
+ * import { activitiesHandler } from './activities';
304
+ *
305
+ * const worker = await Worker.create({
306
+ * workflowsPath: require.resolve('./workflows'), // Imports processOrder
307
+ * activities: activitiesHandler.activities,
308
+ * taskQueue: activitiesHandler.contract.taskQueue,
309
+ * });
310
+ * ```
311
+ */
312
+ function declareWorkflow(options) {
313
+ const { workflowName, contract, implementation, activityOptions, signals, queries, updates } = options;
314
+ const definition = contract.workflows[workflowName];
315
+ return async (args) => {
316
+ const singleArg = Array.isArray(args) ? args[0] : args;
317
+ let validatedInput;
318
+ try {
319
+ validatedInput = definition.input.parse(singleArg);
320
+ } catch (error) {
321
+ if (error instanceof zod.ZodError) throw new WorkflowInputValidationError(String(workflowName), error);
322
+ throw error;
323
+ }
324
+ if (definition.signals && signals) {
325
+ const signalDefs = definition.signals;
326
+ const signalHandlers = signals;
327
+ for (const [signalName, signalDef] of Object.entries(signalDefs)) {
328
+ const handler = signalHandlers[signalName];
329
+ if (handler) (0, __temporalio_workflow.setHandler)((0, __temporalio_workflow.defineSignal)(signalName), async (...args$1) => {
330
+ const input = args$1.length === 1 ? args$1[0] : args$1;
331
+ let validatedInput$1;
332
+ try {
333
+ validatedInput$1 = signalDef.input.parse(input);
334
+ } catch (error) {
335
+ if (error instanceof zod.ZodError) throw new SignalInputValidationError(signalName, error);
336
+ throw error;
337
+ }
338
+ await handler(validatedInput$1);
339
+ });
340
+ }
341
+ }
342
+ if (definition.queries && queries) {
343
+ const queryDefs = definition.queries;
344
+ const queryHandlers = queries;
345
+ for (const [queryName, queryDef] of Object.entries(queryDefs)) {
346
+ const handler = queryHandlers[queryName];
347
+ if (handler) (0, __temporalio_workflow.setHandler)((0, __temporalio_workflow.defineQuery)(queryName), (...args$1) => {
348
+ const input = args$1.length === 1 ? args$1[0] : args$1;
349
+ let validatedInput$1;
350
+ try {
351
+ validatedInput$1 = queryDef.input.parse(input);
352
+ } catch (error) {
353
+ if (error instanceof zod.ZodError) throw new QueryInputValidationError(queryName, error);
354
+ throw error;
355
+ }
356
+ const result$1 = handler(validatedInput$1);
357
+ try {
358
+ return queryDef.output.parse(result$1);
359
+ } catch (error) {
360
+ if (error instanceof zod.ZodError) throw new QueryOutputValidationError(queryName, error);
361
+ throw error;
362
+ }
363
+ });
364
+ }
365
+ }
366
+ if (definition.updates && updates) {
367
+ const updateDefs = definition.updates;
368
+ const updateHandlers = updates;
369
+ for (const [updateName, updateDef] of Object.entries(updateDefs)) {
370
+ const handler = updateHandlers[updateName];
371
+ if (handler) (0, __temporalio_workflow.setHandler)((0, __temporalio_workflow.defineUpdate)(updateName), async (...args$1) => {
372
+ const input = args$1.length === 1 ? args$1[0] : args$1;
373
+ let validatedInput$1;
374
+ try {
375
+ validatedInput$1 = updateDef.input.parse(input);
376
+ } catch (error) {
377
+ if (error instanceof zod.ZodError) throw new UpdateInputValidationError(updateName, error);
378
+ throw error;
379
+ }
380
+ const result$1 = await handler(validatedInput$1);
381
+ try {
382
+ return updateDef.output.parse(result$1);
383
+ } catch (error) {
384
+ if (error instanceof zod.ZodError) throw new UpdateOutputValidationError(updateName, error);
385
+ throw error;
386
+ }
387
+ });
388
+ }
389
+ }
390
+ let contextActivities = {};
391
+ if (definition.activities || contract.activities) contextActivities = createValidatedActivities((0, __temporalio_workflow.proxyActivities)({
392
+ startToCloseTimeout: activityOptions?.startToCloseTimeout ?? 6e4,
393
+ ...activityOptions
394
+ }), definition.activities, contract.activities);
395
+ const result = await implementation({
396
+ activities: contextActivities,
397
+ info: (0, __temporalio_workflow.workflowInfo)()
398
+ }, validatedInput);
399
+ try {
400
+ return definition.output.parse(result);
401
+ } catch (error) {
402
+ if (error instanceof zod.ZodError) throw new WorkflowOutputValidationError(String(workflowName), error);
403
+ throw error;
404
+ }
405
+ };
406
+ }
407
+
408
+ //#endregion
409
+ Object.defineProperty(exports, 'ActivityDefinitionNotFoundError', {
410
+ enumerable: true,
411
+ get: function () {
412
+ return ActivityDefinitionNotFoundError;
413
+ }
414
+ });
415
+ Object.defineProperty(exports, 'ActivityImplementationNotFoundError', {
416
+ enumerable: true,
417
+ get: function () {
418
+ return ActivityImplementationNotFoundError;
419
+ }
420
+ });
421
+ Object.defineProperty(exports, 'ActivityInputValidationError', {
422
+ enumerable: true,
423
+ get: function () {
424
+ return ActivityInputValidationError;
425
+ }
426
+ });
427
+ Object.defineProperty(exports, 'ActivityOutputValidationError', {
428
+ enumerable: true,
429
+ get: function () {
430
+ return ActivityOutputValidationError;
431
+ }
432
+ });
433
+ Object.defineProperty(exports, 'QueryInputValidationError', {
434
+ enumerable: true,
435
+ get: function () {
436
+ return QueryInputValidationError;
437
+ }
438
+ });
439
+ Object.defineProperty(exports, 'QueryOutputValidationError', {
440
+ enumerable: true,
441
+ get: function () {
442
+ return QueryOutputValidationError;
443
+ }
444
+ });
445
+ Object.defineProperty(exports, 'SignalInputValidationError', {
446
+ enumerable: true,
447
+ get: function () {
448
+ return SignalInputValidationError;
449
+ }
450
+ });
451
+ Object.defineProperty(exports, 'UpdateInputValidationError', {
452
+ enumerable: true,
453
+ get: function () {
454
+ return UpdateInputValidationError;
455
+ }
456
+ });
457
+ Object.defineProperty(exports, 'UpdateOutputValidationError', {
458
+ enumerable: true,
459
+ get: function () {
460
+ return UpdateOutputValidationError;
461
+ }
462
+ });
463
+ Object.defineProperty(exports, 'WorkerError', {
464
+ enumerable: true,
465
+ get: function () {
466
+ return WorkerError;
467
+ }
468
+ });
469
+ Object.defineProperty(exports, 'WorkflowInputValidationError', {
470
+ enumerable: true,
471
+ get: function () {
472
+ return WorkflowInputValidationError;
473
+ }
474
+ });
475
+ Object.defineProperty(exports, 'WorkflowOutputValidationError', {
476
+ enumerable: true,
477
+ get: function () {
478
+ return WorkflowOutputValidationError;
479
+ }
480
+ });
481
+ Object.defineProperty(exports, 'declareActivitiesHandler', {
482
+ enumerable: true,
483
+ get: function () {
484
+ return declareActivitiesHandler;
485
+ }
486
+ });
487
+ Object.defineProperty(exports, 'declareWorkflow', {
488
+ enumerable: true,
489
+ get: function () {
490
+ return declareWorkflow;
491
+ }
492
+ });