@temporal-contract/worker 0.0.1 → 0.0.2
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/.turbo/turbo-build.log +12 -12
- package/CHANGELOG.md +9 -0
- package/README.md +14 -93
- package/dist/activity.cjs +1 -1
- package/dist/activity.d.cts +1 -1
- package/dist/activity.d.mts +1 -1
- package/dist/activity.mjs +1 -1
- package/dist/{errors-CqX81ysy.d.cts → errors-B50uht6a.d.cts} +19 -19
- package/dist/{errors-oc-Iiwmu.d.mts → errors-DgUMRes-.d.mts} +19 -19
- package/dist/{handler-aA2RFdV7.mjs → handler-BP9xAycT.mjs} +73 -106
- package/dist/{handler-B3KY0uDx.cjs → handler-Cc951VQp.cjs} +73 -106
- package/dist/workflow.cjs +1 -1
- package/dist/workflow.d.cts +1 -1
- package/dist/workflow.d.mts +1 -1
- package/dist/workflow.mjs +1 -1
- package/package.json +6 -5
- package/src/errors.ts +28 -19
- package/src/handler.spec.ts +38 -64
- package/src/handler.ts +79 -95
- package/vitest.config.ts +12 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@temporal-contract/worker",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Worker utilities for implementing temporal-contract workflows and activities",
|
|
6
6
|
"homepage": "https://github.com/btravers/temporal-contract#readme",
|
|
@@ -47,20 +47,21 @@
|
|
|
47
47
|
"./package.json": "./package.json"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@
|
|
50
|
+
"@standard-schema/spec": "1.0.0",
|
|
51
|
+
"@temporal-contract/contract": "0.0.2"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
53
54
|
"@temporalio/workflow": "1.13.2",
|
|
54
55
|
"@types/node": "24.10.2",
|
|
56
|
+
"@vitest/coverage-v8": "4.0.15",
|
|
55
57
|
"tsdown": "0.17.2",
|
|
56
58
|
"typescript": "5.9.3",
|
|
57
59
|
"vitest": "4.0.15",
|
|
58
60
|
"zod": "4.1.13",
|
|
59
|
-
"@temporal-contract/tsconfig": "0.0.
|
|
61
|
+
"@temporal-contract/tsconfig": "0.0.2"
|
|
60
62
|
},
|
|
61
63
|
"peerDependencies": {
|
|
62
|
-
"@temporalio/workflow": ">=1.13.0 <2.0.0"
|
|
63
|
-
"zod": "^4.0.0"
|
|
64
|
+
"@temporalio/workflow": ">=1.13.0 <2.0.0"
|
|
64
65
|
},
|
|
65
66
|
"scripts": {
|
|
66
67
|
"dev": "tsdown src/activity.ts src/workflow.ts --format cjs,esm --dts --watch",
|
package/src/errors.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Base error class for worker errors
|
|
@@ -52,9 +52,10 @@ export class ActivityDefinitionNotFoundError extends WorkerError {
|
|
|
52
52
|
export class ActivityInputValidationError extends WorkerError {
|
|
53
53
|
constructor(
|
|
54
54
|
public readonly activityName: string,
|
|
55
|
-
public readonly
|
|
55
|
+
public readonly issues: ReadonlyArray<StandardSchemaV1.Issue>,
|
|
56
56
|
) {
|
|
57
|
-
|
|
57
|
+
const message = issues.map((issue) => issue.message).join("; ");
|
|
58
|
+
super(`Activity "${activityName}" input validation failed: ${message}`);
|
|
58
59
|
this.name = "ActivityInputValidationError";
|
|
59
60
|
}
|
|
60
61
|
}
|
|
@@ -65,9 +66,10 @@ export class ActivityInputValidationError extends WorkerError {
|
|
|
65
66
|
export class ActivityOutputValidationError extends WorkerError {
|
|
66
67
|
constructor(
|
|
67
68
|
public readonly activityName: string,
|
|
68
|
-
public readonly
|
|
69
|
+
public readonly issues: ReadonlyArray<StandardSchemaV1.Issue>,
|
|
69
70
|
) {
|
|
70
|
-
|
|
71
|
+
const message = issues.map((issue) => issue.message).join("; ");
|
|
72
|
+
super(`Activity "${activityName}" output validation failed: ${message}`);
|
|
71
73
|
this.name = "ActivityOutputValidationError";
|
|
72
74
|
}
|
|
73
75
|
}
|
|
@@ -78,9 +80,10 @@ export class ActivityOutputValidationError extends WorkerError {
|
|
|
78
80
|
export class WorkflowInputValidationError extends WorkerError {
|
|
79
81
|
constructor(
|
|
80
82
|
public readonly workflowName: string,
|
|
81
|
-
public readonly
|
|
83
|
+
public readonly issues: ReadonlyArray<StandardSchemaV1.Issue>,
|
|
82
84
|
) {
|
|
83
|
-
|
|
85
|
+
const message = issues.map((issue) => issue.message).join("; ");
|
|
86
|
+
super(`Workflow "${workflowName}" input validation failed: ${message}`);
|
|
84
87
|
this.name = "WorkflowInputValidationError";
|
|
85
88
|
}
|
|
86
89
|
}
|
|
@@ -91,9 +94,10 @@ export class WorkflowInputValidationError extends WorkerError {
|
|
|
91
94
|
export class WorkflowOutputValidationError extends WorkerError {
|
|
92
95
|
constructor(
|
|
93
96
|
public readonly workflowName: string,
|
|
94
|
-
public readonly
|
|
97
|
+
public readonly issues: ReadonlyArray<StandardSchemaV1.Issue>,
|
|
95
98
|
) {
|
|
96
|
-
|
|
99
|
+
const message = issues.map((issue) => issue.message).join("; ");
|
|
100
|
+
super(`Workflow "${workflowName}" output validation failed: ${message}`);
|
|
97
101
|
this.name = "WorkflowOutputValidationError";
|
|
98
102
|
}
|
|
99
103
|
}
|
|
@@ -104,9 +108,10 @@ export class WorkflowOutputValidationError extends WorkerError {
|
|
|
104
108
|
export class SignalInputValidationError extends WorkerError {
|
|
105
109
|
constructor(
|
|
106
110
|
public readonly signalName: string,
|
|
107
|
-
public readonly
|
|
111
|
+
public readonly issues: ReadonlyArray<StandardSchemaV1.Issue>,
|
|
108
112
|
) {
|
|
109
|
-
|
|
113
|
+
const message = issues.map((issue) => issue.message).join("; ");
|
|
114
|
+
super(`Signal "${signalName}" input validation failed: ${message}`);
|
|
110
115
|
this.name = "SignalInputValidationError";
|
|
111
116
|
}
|
|
112
117
|
}
|
|
@@ -117,9 +122,10 @@ export class SignalInputValidationError extends WorkerError {
|
|
|
117
122
|
export class QueryInputValidationError extends WorkerError {
|
|
118
123
|
constructor(
|
|
119
124
|
public readonly queryName: string,
|
|
120
|
-
public readonly
|
|
125
|
+
public readonly issues: ReadonlyArray<StandardSchemaV1.Issue>,
|
|
121
126
|
) {
|
|
122
|
-
|
|
127
|
+
const message = issues.map((issue) => issue.message).join("; ");
|
|
128
|
+
super(`Query "${queryName}" input validation failed: ${message}`);
|
|
123
129
|
this.name = "QueryInputValidationError";
|
|
124
130
|
}
|
|
125
131
|
}
|
|
@@ -130,9 +136,10 @@ export class QueryInputValidationError extends WorkerError {
|
|
|
130
136
|
export class QueryOutputValidationError extends WorkerError {
|
|
131
137
|
constructor(
|
|
132
138
|
public readonly queryName: string,
|
|
133
|
-
public readonly
|
|
139
|
+
public readonly issues: ReadonlyArray<StandardSchemaV1.Issue>,
|
|
134
140
|
) {
|
|
135
|
-
|
|
141
|
+
const message = issues.map((issue) => issue.message).join("; ");
|
|
142
|
+
super(`Query "${queryName}" output validation failed: ${message}`);
|
|
136
143
|
this.name = "QueryOutputValidationError";
|
|
137
144
|
}
|
|
138
145
|
}
|
|
@@ -143,9 +150,10 @@ export class QueryOutputValidationError extends WorkerError {
|
|
|
143
150
|
export class UpdateInputValidationError extends WorkerError {
|
|
144
151
|
constructor(
|
|
145
152
|
public readonly updateName: string,
|
|
146
|
-
public readonly
|
|
153
|
+
public readonly issues: ReadonlyArray<StandardSchemaV1.Issue>,
|
|
147
154
|
) {
|
|
148
|
-
|
|
155
|
+
const message = issues.map((issue) => issue.message).join("; ");
|
|
156
|
+
super(`Update "${updateName}" input validation failed: ${message}`);
|
|
149
157
|
this.name = "UpdateInputValidationError";
|
|
150
158
|
}
|
|
151
159
|
}
|
|
@@ -156,9 +164,10 @@ export class UpdateInputValidationError extends WorkerError {
|
|
|
156
164
|
export class UpdateOutputValidationError extends WorkerError {
|
|
157
165
|
constructor(
|
|
158
166
|
public readonly updateName: string,
|
|
159
|
-
public readonly
|
|
167
|
+
public readonly issues: ReadonlyArray<StandardSchemaV1.Issue>,
|
|
160
168
|
) {
|
|
161
|
-
|
|
169
|
+
const message = issues.map((issue) => issue.message).join("; ");
|
|
170
|
+
super(`Update "${updateName}" output validation failed: ${message}`);
|
|
162
171
|
this.name = "UpdateOutputValidationError";
|
|
163
172
|
}
|
|
164
173
|
}
|
package/src/handler.spec.ts
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from "vitest";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { declareActivitiesHandler, declareWorkflow } from "./handler.js";
|
|
4
|
-
import type { ActivityImplementations } from "./handler.js";
|
|
5
4
|
import type { ContractDefinition, WorkflowDefinition } from "@temporal-contract/contract";
|
|
6
|
-
import {
|
|
7
|
-
ActivityDefinitionNotFoundError,
|
|
8
|
-
ActivityInputValidationError,
|
|
9
|
-
ActivityOutputValidationError,
|
|
10
|
-
WorkflowInputValidationError,
|
|
11
|
-
WorkflowOutputValidationError,
|
|
12
|
-
} from "./errors.js";
|
|
13
5
|
|
|
14
6
|
// Mock Temporal workflow functions
|
|
15
7
|
vi.mock("@temporalio/workflow", () => ({
|
|
@@ -363,23 +355,16 @@ describe("Worker Package", () => {
|
|
|
363
355
|
expect(() => {
|
|
364
356
|
declareActivitiesHandler({
|
|
365
357
|
contract,
|
|
366
|
-
|
|
358
|
+
// @ts-expect-error Testing unknown activity
|
|
359
|
+
activities: testActivities,
|
|
367
360
|
});
|
|
368
|
-
}).
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
} catch (error) {
|
|
376
|
-
if (error instanceof ActivityDefinitionNotFoundError) {
|
|
377
|
-
expect(error.activityName).toBe("unknownActivity");
|
|
378
|
-
expect(error.availableDefinitions).toEqual(["sendEmail", "processPayment"]);
|
|
379
|
-
expect(error.message).toContain("unknownActivity");
|
|
380
|
-
expect(error.message).toContain("sendEmail");
|
|
381
|
-
}
|
|
382
|
-
}
|
|
361
|
+
}).toThrowError(
|
|
362
|
+
expect.objectContaining({
|
|
363
|
+
name: "ActivityDefinitionNotFoundError",
|
|
364
|
+
activityName: "unknownActivity",
|
|
365
|
+
availableDefinitions: ["sendEmail", "processPayment"],
|
|
366
|
+
}),
|
|
367
|
+
);
|
|
383
368
|
});
|
|
384
369
|
|
|
385
370
|
it("should throw ActivityInputValidationError with Zod details", async () => {
|
|
@@ -403,19 +388,16 @@ describe("Worker Package", () => {
|
|
|
403
388
|
},
|
|
404
389
|
});
|
|
405
390
|
|
|
406
|
-
|
|
407
|
-
|
|
391
|
+
await expect(
|
|
392
|
+
handler.activities["processPayment"]!({
|
|
408
393
|
amount: -100,
|
|
409
394
|
currency: "USD",
|
|
410
|
-
})
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
expect(error.message).toContain("input validation failed");
|
|
417
|
-
}
|
|
418
|
-
}
|
|
395
|
+
}),
|
|
396
|
+
).rejects.toMatchObject({
|
|
397
|
+
name: "ActivityInputValidationError",
|
|
398
|
+
activityName: "processPayment",
|
|
399
|
+
message: expect.stringContaining("processPayment"),
|
|
400
|
+
});
|
|
419
401
|
});
|
|
420
402
|
|
|
421
403
|
it("should throw ActivityOutputValidationError with Zod details", async () => {
|
|
@@ -439,16 +421,11 @@ describe("Worker Package", () => {
|
|
|
439
421
|
},
|
|
440
422
|
});
|
|
441
423
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
expect(error.zodError).toBeDefined();
|
|
448
|
-
expect(error.message).toContain("fetchData");
|
|
449
|
-
expect(error.message).toContain("output validation failed");
|
|
450
|
-
}
|
|
451
|
-
}
|
|
424
|
+
await expect(handler.activities["fetchData"]!({ id: "123" })).rejects.toMatchObject({
|
|
425
|
+
name: "ActivityOutputValidationError",
|
|
426
|
+
activityName: "fetchData",
|
|
427
|
+
message: expect.stringContaining("fetchData"),
|
|
428
|
+
});
|
|
452
429
|
});
|
|
453
430
|
|
|
454
431
|
it("should throw WorkflowInputValidationError", async () => {
|
|
@@ -472,18 +449,16 @@ describe("Worker Package", () => {
|
|
|
472
449
|
},
|
|
473
450
|
});
|
|
474
451
|
|
|
475
|
-
|
|
476
|
-
|
|
452
|
+
await expect(
|
|
453
|
+
workflow([{ orderId: "not-a-uuid", amount: 100 }] as unknown as {
|
|
477
454
|
orderId: string;
|
|
478
455
|
amount: number;
|
|
479
|
-
})
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
}
|
|
486
|
-
}
|
|
456
|
+
}),
|
|
457
|
+
).rejects.toMatchObject({
|
|
458
|
+
name: "WorkflowInputValidationError",
|
|
459
|
+
workflowName: "processOrder",
|
|
460
|
+
message: expect.stringContaining("input validation failed"),
|
|
461
|
+
});
|
|
487
462
|
});
|
|
488
463
|
|
|
489
464
|
it("should throw WorkflowOutputValidationError", async () => {
|
|
@@ -511,15 +486,14 @@ describe("Worker Package", () => {
|
|
|
511
486
|
},
|
|
512
487
|
});
|
|
513
488
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
}
|
|
489
|
+
await expect(
|
|
490
|
+
// @ts-expect-error Testing invalid output
|
|
491
|
+
workflow([{ orderId: "123" }]),
|
|
492
|
+
).rejects.toMatchObject({
|
|
493
|
+
name: "WorkflowOutputValidationError",
|
|
494
|
+
workflowName: "processOrder",
|
|
495
|
+
message: expect.stringContaining("output validation failed"),
|
|
496
|
+
});
|
|
523
497
|
});
|
|
524
498
|
});
|
|
525
499
|
});
|
package/src/handler.ts
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
setHandler,
|
|
9
9
|
workflowInfo,
|
|
10
10
|
} from "@temporalio/workflow";
|
|
11
|
-
import { ZodError } from "zod";
|
|
12
11
|
import type {
|
|
13
12
|
ActivityDefinition,
|
|
14
13
|
ContractDefinition,
|
|
@@ -236,32 +235,29 @@ function createValidatedActivities<
|
|
|
236
235
|
throw new ActivityImplementationNotFoundError(activityName, Object.keys(rawActivities));
|
|
237
236
|
}
|
|
238
237
|
|
|
239
|
-
//
|
|
240
|
-
|
|
238
|
+
// Create the wrapped activity with validation
|
|
239
|
+
// Type assertion to unknown is safe as we're building the object step by step
|
|
240
|
+
const wrappedActivity = async (input: unknown) => {
|
|
241
241
|
// Validate input before sending over network
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
} catch (error) {
|
|
246
|
-
if (error instanceof ZodError) {
|
|
247
|
-
throw new ActivityInputValidationError(activityName, error);
|
|
248
|
-
}
|
|
249
|
-
throw error;
|
|
242
|
+
const inputResult = await activityDef.input["~standard"].validate(input);
|
|
243
|
+
if (inputResult.issues) {
|
|
244
|
+
throw new ActivityInputValidationError(activityName, inputResult.issues);
|
|
250
245
|
}
|
|
251
246
|
|
|
252
247
|
// Call the actual activity (pass the single parameter directly)
|
|
253
|
-
const result = await rawActivity(
|
|
248
|
+
const result = await rawActivity(inputResult.value);
|
|
254
249
|
|
|
255
250
|
// Validate output after receiving from network
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
if (error instanceof ZodError) {
|
|
260
|
-
throw new ActivityOutputValidationError(activityName, error);
|
|
261
|
-
}
|
|
262
|
-
throw error;
|
|
251
|
+
const outputResult = await activityDef.output["~standard"].validate(result);
|
|
252
|
+
if (outputResult.issues) {
|
|
253
|
+
throw new ActivityOutputValidationError(activityName, outputResult.issues);
|
|
263
254
|
}
|
|
255
|
+
|
|
256
|
+
return outputResult.value;
|
|
264
257
|
};
|
|
258
|
+
|
|
259
|
+
// Assign to validatedActivities with proper type handling
|
|
260
|
+
(validatedActivities as Record<string, unknown>)[activityName] = wrappedActivity;
|
|
265
261
|
}
|
|
266
262
|
|
|
267
263
|
return validatedActivities;
|
|
@@ -348,28 +344,21 @@ export function declareActivitiesHandler<T extends ContractDefinition>(
|
|
|
348
344
|
|
|
349
345
|
wrappedActivities[activityName] = async (input: unknown) => {
|
|
350
346
|
// Validate input
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
} catch (error) {
|
|
355
|
-
if (error instanceof ZodError) {
|
|
356
|
-
throw new ActivityInputValidationError(activityName, error);
|
|
357
|
-
}
|
|
358
|
-
throw error;
|
|
347
|
+
const inputResult = await activityDef.input["~standard"].validate(input);
|
|
348
|
+
if (inputResult.issues) {
|
|
349
|
+
throw new ActivityInputValidationError(activityName, inputResult.issues);
|
|
359
350
|
}
|
|
360
351
|
|
|
361
352
|
// Execute activity
|
|
362
|
-
const result = await activityImpl(
|
|
353
|
+
const result = await activityImpl(inputResult.value);
|
|
363
354
|
|
|
364
355
|
// Validate output
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
if (error instanceof ZodError) {
|
|
369
|
-
throw new ActivityOutputValidationError(activityName, error);
|
|
370
|
-
}
|
|
371
|
-
throw error;
|
|
356
|
+
const outputResult = await activityDef.output["~standard"].validate(result);
|
|
357
|
+
if (outputResult.issues) {
|
|
358
|
+
throw new ActivityOutputValidationError(activityName, outputResult.issues);
|
|
372
359
|
}
|
|
360
|
+
|
|
361
|
+
return outputResult.value;
|
|
373
362
|
};
|
|
374
363
|
}
|
|
375
364
|
|
|
@@ -464,17 +453,13 @@ export function declareWorkflow<
|
|
|
464
453
|
const singleArg = Array.isArray(args) ? args[0] : args;
|
|
465
454
|
|
|
466
455
|
// Validate workflow input
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
TContract["workflows"][TWorkflowName]
|
|
471
|
-
>;
|
|
472
|
-
} catch (error) {
|
|
473
|
-
if (error instanceof ZodError) {
|
|
474
|
-
throw new WorkflowInputValidationError(String(workflowName), error);
|
|
475
|
-
}
|
|
476
|
-
throw error;
|
|
456
|
+
const inputResult = await definition.input["~standard"].validate(singleArg);
|
|
457
|
+
if (inputResult.issues) {
|
|
458
|
+
throw new WorkflowInputValidationError(String(workflowName), inputResult.issues);
|
|
477
459
|
}
|
|
460
|
+
const validatedInput = inputResult.value as WorkerInferInput<
|
|
461
|
+
TContract["workflows"][TWorkflowName]
|
|
462
|
+
>;
|
|
478
463
|
|
|
479
464
|
// Register signal handlers
|
|
480
465
|
if (definition.signals && signals) {
|
|
@@ -488,16 +473,11 @@ export function declareWorkflow<
|
|
|
488
473
|
setHandler(signal, async (...args: unknown[]) => {
|
|
489
474
|
// Extract single parameter (Temporal passes as args array)
|
|
490
475
|
const input = args.length === 1 ? args[0] : args;
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
} catch (error) {
|
|
495
|
-
if (error instanceof ZodError) {
|
|
496
|
-
throw new SignalInputValidationError(signalName, error);
|
|
497
|
-
}
|
|
498
|
-
throw error;
|
|
476
|
+
const inputResult = await signalDef.input["~standard"].validate(input);
|
|
477
|
+
if (inputResult.issues) {
|
|
478
|
+
throw new SignalInputValidationError(signalName, inputResult.issues);
|
|
499
479
|
}
|
|
500
|
-
await (handler as SignalHandlerImplementation<SignalDefinition>)(
|
|
480
|
+
await (handler as SignalHandlerImplementation<SignalDefinition>)(inputResult.value);
|
|
501
481
|
});
|
|
502
482
|
}
|
|
503
483
|
}
|
|
@@ -515,24 +495,37 @@ export function declareWorkflow<
|
|
|
515
495
|
setHandler(query, (...args: unknown[]) => {
|
|
516
496
|
// Extract single parameter (Temporal passes as args array)
|
|
517
497
|
const input = args.length === 1 ? args[0] : args;
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
498
|
+
// Note: Query handlers must be synchronous, so we need to handle validation synchronously
|
|
499
|
+
// Standard Schema validate can return sync or async results
|
|
500
|
+
const inputResult = queryDef.input["~standard"].validate(input);
|
|
501
|
+
|
|
502
|
+
// Handle both sync and async validation results
|
|
503
|
+
if (inputResult instanceof Promise) {
|
|
504
|
+
throw new Error(
|
|
505
|
+
`Query "${queryName}" validation must be synchronous. Use a schema library that supports synchronous validation for queries.`,
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if (inputResult.issues) {
|
|
510
|
+
throw new QueryInputValidationError(queryName, inputResult.issues);
|
|
526
511
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
throw
|
|
512
|
+
|
|
513
|
+
const result = (handler as QueryHandlerImplementation<QueryDefinition>)(
|
|
514
|
+
inputResult.value,
|
|
515
|
+
);
|
|
516
|
+
|
|
517
|
+
const outputResult = queryDef.output["~standard"].validate(result);
|
|
518
|
+
if (outputResult instanceof Promise) {
|
|
519
|
+
throw new Error(
|
|
520
|
+
`Query "${queryName}" output validation must be synchronous. Use a schema library that supports synchronous validation for queries.`,
|
|
521
|
+
);
|
|
535
522
|
}
|
|
523
|
+
|
|
524
|
+
if (outputResult.issues) {
|
|
525
|
+
throw new QueryOutputValidationError(queryName, outputResult.issues);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
return outputResult.value;
|
|
536
529
|
});
|
|
537
530
|
}
|
|
538
531
|
}
|
|
@@ -550,26 +543,21 @@ export function declareWorkflow<
|
|
|
550
543
|
setHandler(update, async (...args: unknown[]) => {
|
|
551
544
|
// Extract single parameter (Temporal passes as args array)
|
|
552
545
|
const input = args.length === 1 ? args[0] : args;
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
} catch (error) {
|
|
557
|
-
if (error instanceof ZodError) {
|
|
558
|
-
throw new UpdateInputValidationError(updateName, error);
|
|
559
|
-
}
|
|
560
|
-
throw error;
|
|
546
|
+
const inputResult = await updateDef.input["~standard"].validate(input);
|
|
547
|
+
if (inputResult.issues) {
|
|
548
|
+
throw new UpdateInputValidationError(updateName, inputResult.issues);
|
|
561
549
|
}
|
|
550
|
+
|
|
562
551
|
const result = await (handler as UpdateHandlerImplementation<UpdateDefinition>)(
|
|
563
|
-
|
|
552
|
+
inputResult.value,
|
|
564
553
|
);
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
throw new UpdateOutputValidationError(updateName, error);
|
|
570
|
-
}
|
|
571
|
-
throw error;
|
|
554
|
+
|
|
555
|
+
const outputResult = await updateDef.output["~standard"].validate(result);
|
|
556
|
+
if (outputResult.issues) {
|
|
557
|
+
throw new UpdateOutputValidationError(updateName, outputResult.issues);
|
|
572
558
|
}
|
|
559
|
+
|
|
560
|
+
return outputResult.value;
|
|
573
561
|
});
|
|
574
562
|
}
|
|
575
563
|
}
|
|
@@ -607,15 +595,11 @@ export function declareWorkflow<
|
|
|
607
595
|
const result = await implementation(context, validatedInput);
|
|
608
596
|
|
|
609
597
|
// Validate workflow output
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
>;
|
|
614
|
-
} catch (error) {
|
|
615
|
-
if (error instanceof ZodError) {
|
|
616
|
-
throw new WorkflowOutputValidationError(String(workflowName), error);
|
|
617
|
-
}
|
|
618
|
-
throw error;
|
|
598
|
+
const outputResult = await definition.output["~standard"].validate(result);
|
|
599
|
+
if (outputResult.issues) {
|
|
600
|
+
throw new WorkflowOutputValidationError(String(workflowName), outputResult.issues);
|
|
619
601
|
}
|
|
602
|
+
|
|
603
|
+
return outputResult.value as WorkerInferOutput<TContract["workflows"][TWorkflowName]>;
|
|
620
604
|
};
|
|
621
605
|
}
|
package/vitest.config.ts
ADDED