@temporal-contract/worker 2.3.1 → 3.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.
@@ -1,170 +1,174 @@
1
1
  let _temporal_contract_contract = require("@temporal-contract/contract");
2
- let _temporalio_workflow = require("@temporalio/workflow");
3
2
  let _temporalio_common = require("@temporalio/common");
3
+ let unthrown = require("unthrown");
4
+ let _temporalio_workflow = require("@temporalio/workflow");
4
5
  require("@temporal-contract/contract/result-async");
5
6
  //#region src/errors.ts
6
7
  /**
7
- * Base error class for worker errors
8
+ * Base class for the contract's runtime validation failures — workflow and
9
+ * activity input/output, plus signal/query/update payloads.
10
+ *
11
+ * These extend Temporal's {@link ApplicationFailure} with `nonRetryable: true`
12
+ * rather than a plain `Error`, and that distinction is load-bearing. The
13
+ * TypeScript SDK classifies a non-`TemporalFailure` thrown from *workflow* code
14
+ * as a Workflow Task failure — presumed to be a transient code bug or
15
+ * non-determinism — and retries the task indefinitely, leaving the execution
16
+ * silently `Running` forever (it looks like the worker "hung"). Only a
17
+ * `TemporalFailure` such as `ApplicationFailure` fails the Workflow Execution
18
+ * terminally. The same logic applies at the activity boundary, where Temporal's
19
+ * default retry policy has unlimited attempts: a plain `Error` would retry
20
+ * forever too.
21
+ *
22
+ * Contract validation failures are deterministic — the schema is static, so bad
23
+ * input/output never becomes valid on replay or retry — so they are surfaced as
24
+ * non-retryable, failing fast with a clear error instead of an infinite retry
25
+ * loop.
26
+ *
27
+ * The concrete subclass name is passed through as the failure `type`, so it
28
+ * stays discriminable after crossing Temporal's serialization boundary (where
29
+ * the JS class identity is lost) via `failure.type`. The failing field path is
30
+ * carried in the human-readable `message` (see {@link summarizeIssues}). The
31
+ * raw `issues` remain available as a property for in-process inspection.
32
+ *
33
+ * See issue #251.
8
34
  */
9
- var WorkerError = class extends Error {
10
- constructor(message, cause) {
11
- super(message, { cause });
12
- this.name = "WorkerError";
35
+ var ValidationError = class extends _temporalio_common.ApplicationFailure {
36
+ issues;
37
+ constructor(message, type, issues) {
38
+ super(message, type, true);
39
+ this.issues = issues;
40
+ Object.defineProperty(this, "name", {
41
+ value: type,
42
+ writable: true,
43
+ configurable: true,
44
+ enumerable: true
45
+ });
13
46
  if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
14
47
  }
15
48
  };
16
49
  /**
17
50
  * Error thrown when an activity definition is not found in the contract
18
51
  */
19
- var ActivityDefinitionNotFoundError = class extends WorkerError {
20
- activityName;
21
- availableDefinitions;
52
+ var ActivityDefinitionNotFoundError = class extends (0, unthrown.TaggedError)("@temporal-contract/ActivityDefinitionNotFoundError", { name: "ActivityDefinitionNotFoundError" }) {
22
53
  constructor(activityName, availableDefinitions = []) {
23
54
  const available = availableDefinitions.length > 0 ? availableDefinitions.join(", ") : "none";
24
- super(`Activity definition not found for: "${activityName}". Available activities: ${available}`);
25
- this.activityName = activityName;
26
- this.availableDefinitions = availableDefinitions;
27
- this.name = "ActivityDefinitionNotFoundError";
55
+ super({
56
+ activityName,
57
+ availableDefinitions,
58
+ message: `Activity definition not found for: "${activityName}". Available activities: ${available}`
59
+ });
28
60
  }
29
61
  };
30
62
  /**
31
63
  * Error thrown when activity input validation fails
32
64
  */
33
- var ActivityInputValidationError = class extends WorkerError {
65
+ var ActivityInputValidationError = class extends ValidationError {
34
66
  activityName;
35
- issues;
36
67
  constructor(activityName, issues) {
37
68
  const message = (0, _temporal_contract_contract.summarizeIssues)(issues);
38
- super(`Activity "${activityName}" input validation failed: ${message}`);
69
+ super(`Activity "${activityName}" input validation failed: ${message}`, "ActivityInputValidationError", issues);
39
70
  this.activityName = activityName;
40
- this.issues = issues;
41
- this.name = "ActivityInputValidationError";
42
71
  }
43
72
  };
44
73
  /**
45
74
  * Error thrown when activity output validation fails
46
75
  */
47
- var ActivityOutputValidationError = class extends WorkerError {
76
+ var ActivityOutputValidationError = class extends ValidationError {
48
77
  activityName;
49
- issues;
50
78
  constructor(activityName, issues) {
51
79
  const message = (0, _temporal_contract_contract.summarizeIssues)(issues);
52
- super(`Activity "${activityName}" output validation failed: ${message}`);
80
+ super(`Activity "${activityName}" output validation failed: ${message}`, "ActivityOutputValidationError", issues);
53
81
  this.activityName = activityName;
54
- this.issues = issues;
55
- this.name = "ActivityOutputValidationError";
56
82
  }
57
83
  };
58
84
  /**
59
85
  * Error thrown when workflow input validation fails
60
86
  */
61
- var WorkflowInputValidationError = class extends WorkerError {
87
+ var WorkflowInputValidationError = class extends ValidationError {
62
88
  workflowName;
63
- issues;
64
89
  constructor(workflowName, issues) {
65
90
  const message = (0, _temporal_contract_contract.summarizeIssues)(issues);
66
- super(`Workflow "${workflowName}" input validation failed: ${message}`);
91
+ super(`Workflow "${workflowName}" input validation failed: ${message}`, "WorkflowInputValidationError", issues);
67
92
  this.workflowName = workflowName;
68
- this.issues = issues;
69
- this.name = "WorkflowInputValidationError";
70
93
  }
71
94
  };
72
95
  /**
73
96
  * Error thrown when workflow output validation fails
74
97
  */
75
- var WorkflowOutputValidationError = class extends WorkerError {
98
+ var WorkflowOutputValidationError = class extends ValidationError {
76
99
  workflowName;
77
- issues;
78
100
  constructor(workflowName, issues) {
79
101
  const message = (0, _temporal_contract_contract.summarizeIssues)(issues);
80
- super(`Workflow "${workflowName}" output validation failed: ${message}`);
102
+ super(`Workflow "${workflowName}" output validation failed: ${message}`, "WorkflowOutputValidationError", issues);
81
103
  this.workflowName = workflowName;
82
- this.issues = issues;
83
- this.name = "WorkflowOutputValidationError";
84
104
  }
85
105
  };
86
106
  /**
87
107
  * Error thrown when signal input validation fails
88
108
  */
89
- var SignalInputValidationError = class extends WorkerError {
109
+ var SignalInputValidationError = class extends ValidationError {
90
110
  signalName;
91
- issues;
92
111
  constructor(signalName, issues) {
93
112
  const message = (0, _temporal_contract_contract.summarizeIssues)(issues);
94
- super(`Signal "${signalName}" input validation failed: ${message}`);
113
+ super(`Signal "${signalName}" input validation failed: ${message}`, "SignalInputValidationError", issues);
95
114
  this.signalName = signalName;
96
- this.issues = issues;
97
- this.name = "SignalInputValidationError";
98
115
  }
99
116
  };
100
117
  /**
101
118
  * Error thrown when query input validation fails
102
119
  */
103
- var QueryInputValidationError = class extends WorkerError {
120
+ var QueryInputValidationError = class extends ValidationError {
104
121
  queryName;
105
- issues;
106
122
  constructor(queryName, issues) {
107
123
  const message = (0, _temporal_contract_contract.summarizeIssues)(issues);
108
- super(`Query "${queryName}" input validation failed: ${message}`);
124
+ super(`Query "${queryName}" input validation failed: ${message}`, "QueryInputValidationError", issues);
109
125
  this.queryName = queryName;
110
- this.issues = issues;
111
- this.name = "QueryInputValidationError";
112
126
  }
113
127
  };
114
128
  /**
115
129
  * Error thrown when query output validation fails
116
130
  */
117
- var QueryOutputValidationError = class extends WorkerError {
131
+ var QueryOutputValidationError = class extends ValidationError {
118
132
  queryName;
119
- issues;
120
133
  constructor(queryName, issues) {
121
134
  const message = (0, _temporal_contract_contract.summarizeIssues)(issues);
122
- super(`Query "${queryName}" output validation failed: ${message}`);
135
+ super(`Query "${queryName}" output validation failed: ${message}`, "QueryOutputValidationError", issues);
123
136
  this.queryName = queryName;
124
- this.issues = issues;
125
- this.name = "QueryOutputValidationError";
126
137
  }
127
138
  };
128
139
  /**
129
140
  * Error thrown when update input validation fails
130
141
  */
131
- var UpdateInputValidationError = class extends WorkerError {
142
+ var UpdateInputValidationError = class extends ValidationError {
132
143
  updateName;
133
- issues;
134
144
  constructor(updateName, issues) {
135
145
  const message = (0, _temporal_contract_contract.summarizeIssues)(issues);
136
- super(`Update "${updateName}" input validation failed: ${message}`);
146
+ super(`Update "${updateName}" input validation failed: ${message}`, "UpdateInputValidationError", issues);
137
147
  this.updateName = updateName;
138
- this.issues = issues;
139
- this.name = "UpdateInputValidationError";
140
148
  }
141
149
  };
142
150
  /**
143
151
  * Error thrown when update output validation fails
144
152
  */
145
- var UpdateOutputValidationError = class extends WorkerError {
153
+ var UpdateOutputValidationError = class extends ValidationError {
146
154
  updateName;
147
- issues;
148
155
  constructor(updateName, issues) {
149
156
  const message = (0, _temporal_contract_contract.summarizeIssues)(issues);
150
- super(`Update "${updateName}" output validation failed: ${message}`);
157
+ super(`Update "${updateName}" output validation failed: ${message}`, "UpdateOutputValidationError", issues);
151
158
  this.updateName = updateName;
152
- this.issues = issues;
153
- this.name = "UpdateOutputValidationError";
154
159
  }
155
160
  };
156
161
  /**
157
162
  * Error thrown when a child workflow is not found in the contract
158
163
  */
159
- var ChildWorkflowNotFoundError = class extends WorkerError {
160
- workflowName;
161
- availableWorkflows;
164
+ var ChildWorkflowNotFoundError = class extends (0, unthrown.TaggedError)("@temporal-contract/ChildWorkflowNotFoundError", { name: "ChildWorkflowNotFoundError" }) {
162
165
  constructor(workflowName, availableWorkflows = []) {
163
166
  const available = availableWorkflows.length > 0 ? availableWorkflows.join(", ") : "none";
164
- super(`Child workflow not found: "${workflowName}". Available workflows: ${available}`);
165
- this.workflowName = workflowName;
166
- this.availableWorkflows = availableWorkflows;
167
- this.name = "ChildWorkflowNotFoundError";
167
+ super({
168
+ workflowName,
169
+ availableWorkflows,
170
+ message: `Child workflow not found: "${workflowName}". Available workflows: ${available}`
171
+ });
168
172
  }
169
173
  };
170
174
  /**
@@ -176,86 +180,56 @@ var ChildWorkflowNotFoundError = class extends WorkerError {
176
180
  * mirroring the client-side `WorkflowFailedError.cause` behavior, so callers
177
181
  * can branch on the failure category in one step instead of unwrapping twice.
178
182
  */
179
- var ChildWorkflowError = class extends WorkerError {
183
+ var ChildWorkflowError = class extends (0, unthrown.TaggedError)("@temporal-contract/ChildWorkflowError", { name: "ChildWorkflowError" }) {
180
184
  constructor(message, cause) {
181
- super(message, cause);
182
- this.name = "ChildWorkflowError";
185
+ super({
186
+ message,
187
+ cause
188
+ });
183
189
  }
184
190
  };
185
191
  /**
186
- * Discriminated variant of {@link ChildWorkflowError} surfaced when a child
187
- * workflow operation (start, execute, or wait-for-result) was cancelled —
188
- * either because the parent workflow itself was cancelled, the child was
189
- * explicitly cancelled, or its enclosing cancellation scope was. Detected via
190
- * `@temporalio/workflow`'s `isCancellation(...)`, which sees through nested
191
- * `ChildWorkflowFailure` / `CancelledFailure` chains.
192
+ * Discriminated variant surfaced when a child workflow operation (start,
193
+ * execute, or wait-for-result) was cancelled — either because the parent
194
+ * workflow itself was cancelled, the child was explicitly cancelled, or its
195
+ * enclosing cancellation scope was. Detected via `@temporalio/workflow`'s
196
+ * `isCancellation(...)`, which sees through nested `ChildWorkflowFailure` /
197
+ * `CancelledFailure` chains.
192
198
  *
193
- * Extends {@link ChildWorkflowError} so existing `instanceof ChildWorkflowError`
194
- * checks still match cancellation, while `instanceof ChildWorkflowCancelledError`
195
- * lets call sites narrow further when they need to branch on cancellation
196
- * explicitly without inspecting `error.cause` against a Temporal SDK class —
197
- * the worker-side analogue of the client-side cause-forwarding pattern.
199
+ * A sibling of {@link ChildWorkflowError} rather than a subclass: both are
200
+ * distinct {@link TaggedError}s, so call sites discriminate on the `_tag`
201
+ * (or `instanceof ChildWorkflowCancelledError`) instead of relying on an
202
+ * `instanceof ChildWorkflowError` that also matches cancellation. `matchTags`
203
+ * folds the `ChildWorkflowError | ChildWorkflowCancelledError` union
204
+ * exhaustively.
198
205
  */
199
- var ChildWorkflowCancelledError = class extends ChildWorkflowError {
200
- workflowName;
206
+ var ChildWorkflowCancelledError = class extends (0, unthrown.TaggedError)("@temporal-contract/ChildWorkflowCancelledError", { name: "ChildWorkflowCancelledError" }) {
201
207
  constructor(workflowName, cause) {
202
- super(`Child workflow "${workflowName}" was cancelled`, cause);
203
- this.workflowName = workflowName;
204
- this.name = "ChildWorkflowCancelledError";
208
+ super({
209
+ workflowName,
210
+ cause,
211
+ message: `Child workflow "${workflowName}" was cancelled`
212
+ });
205
213
  }
206
214
  };
207
215
  /**
208
- * Error surfaced in the `err(...)` branch of a `ResultAsync` when a typed
216
+ * Error surfaced in the `err(...)` branch of an `AsyncResult` when a typed
209
217
  * cancellation scope is cancelled via Temporal's cancellation propagation.
210
218
  * Returned by both `context.cancellableScope` (when the workflow or an
211
219
  * ancestor scope cancels) and `context.nonCancellableScope` (when
212
220
  * cancellation is raised from inside the scope). Distinct from arbitrary
213
221
  * thrown errors so call sites can branch on cancellation explicitly.
214
222
  *
215
- * Non-cancellation errors thrown inside a scope surface as a sibling
216
- * {@link WorkflowScopeError} on the same `err(...)` channel, so callers can
217
- * use `instanceof` to discriminate without falling back to `try/catch`.
223
+ * Non-cancellation errors thrown inside a scope are *unmodeled* failures: they
224
+ * surface on the scope's `defect` channel (re-thrown at the edge / inspectable
225
+ * via `result.isDefect()` and `result.cause`), not as a typed `err(...)`.
218
226
  */
219
- var WorkflowCancelledError = class extends WorkerError {
227
+ var WorkflowCancelledError = class extends (0, unthrown.TaggedError)("@temporal-contract/WorkflowCancelledError", { name: "WorkflowCancelledError" }) {
220
228
  constructor(cause) {
221
- super("Workflow cancellation scope was cancelled", cause);
222
- this.name = "WorkflowCancelledError";
223
- }
224
- };
225
- /**
226
- * Error surfaced in the `err(...)` branch of a `ResultAsync` when the
227
- * function passed to `cancellableScope` / `nonCancellableScope` throws a
228
- * non-cancellation error.
229
- *
230
- * The original error is preserved on `cause` so call sites can introspect
231
- * it without losing identity:
232
- *
233
- * @example
234
- * ```ts
235
- * const result = await context.cancellableScope(async () => {
236
- * return await context.activities.processStep(args);
237
- * });
238
- *
239
- * if (result.isErr()) {
240
- * if (result.error instanceof WorkflowCancelledError) {
241
- * // graceful cancellation
242
- * } else if (result.error instanceof WorkflowScopeError) {
243
- * // domain error — `result.error.cause` is the original throwable
244
- * }
245
- * }
246
- * ```
247
- *
248
- * Introduced so the scope helpers route every failure through neverthrow's
249
- * railway. Previously, non-cancellation errors were re-thrown out of the
250
- * helper, which became a `ResultAsync` rejection (`new ResultAsync(promise)`
251
- * does not catch) — they leaked as unhandled rejections rather than
252
- * surfacing on the typed error channel callers actually inspect.
253
- */
254
- var WorkflowScopeError = class extends WorkerError {
255
- constructor(cause) {
256
- const message = cause instanceof Error ? `Workflow cancellation scope caught a non-cancellation error: ${cause.message}` : "Workflow cancellation scope caught a non-cancellation error";
257
- super(message, cause);
258
- this.name = "WorkflowScopeError";
229
+ super({
230
+ cause,
231
+ message: "Workflow cancellation scope was cancelled"
232
+ });
259
233
  }
260
234
  };
261
235
  //#endregion
@@ -314,7 +288,7 @@ function buildRawActivitiesProxy(workflowActivities, contractActivities, default
314
288
  const defaultProxy = (0, _temporalio_workflow.proxyActivities)(defaultOptions);
315
289
  const overrideEntries = overrides ? Object.entries(overrides).filter((entry) => entry[1] !== void 0) : [];
316
290
  if (overrideEntries.length === 0) return defaultProxy;
317
- const declared = new Set([...Object.keys(workflowActivities ?? {}), ...Object.keys(contractActivities ?? {})]);
291
+ const declared = /* @__PURE__ */ new Set([...Object.keys(workflowActivities ?? {}), ...Object.keys(contractActivities ?? {})]);
318
292
  for (const [name] of overrideEntries) if (!declared.has(name)) throw new Error(`activityOptionsByName entry "${name}" does not match any declared activity. Available: ${[...declared].join(", ") || "none"}.`);
319
293
  const overriddenFns = {};
320
294
  for (const [name, override] of overrideEntries) {
@@ -516,6 +490,12 @@ Object.defineProperty(exports, "UpdateOutputValidationError", {
516
490
  return UpdateOutputValidationError;
517
491
  }
518
492
  });
493
+ Object.defineProperty(exports, "ValidationError", {
494
+ enumerable: true,
495
+ get: function() {
496
+ return ValidationError;
497
+ }
498
+ });
519
499
  Object.defineProperty(exports, "WorkflowCancelledError", {
520
500
  enumerable: true,
521
501
  get: function() {
@@ -534,12 +514,6 @@ Object.defineProperty(exports, "WorkflowOutputValidationError", {
534
514
  return WorkflowOutputValidationError;
535
515
  }
536
516
  });
537
- Object.defineProperty(exports, "WorkflowScopeError", {
538
- enumerable: true,
539
- get: function() {
540
- return WorkflowScopeError;
541
- }
542
- });
543
517
  Object.defineProperty(exports, "buildRawActivitiesProxy", {
544
518
  enumerable: true,
545
519
  get: function() {