@temporal-contract/client 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.
- package/README.md +4 -4
- package/dist/index.cjs +159 -162
- package/dist/index.d.cts +123 -97
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +123 -97
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +122 -125
- package/dist/index.mjs.map +1 -1
- package/package.json +23 -19
package/README.md
CHANGED
|
@@ -29,11 +29,11 @@ const result = await client.executeWorkflow("processOrder", {
|
|
|
29
29
|
|
|
30
30
|
## Documentation
|
|
31
31
|
|
|
32
|
-
📖 **[Read the full documentation →](https://
|
|
32
|
+
📖 **[Read the full documentation →](https://btravstack.github.io/temporal-contract)**
|
|
33
33
|
|
|
34
|
-
- [API Reference](https://
|
|
35
|
-
- [Getting Started](https://
|
|
36
|
-
- [Examples](https://
|
|
34
|
+
- [API Reference](https://btravstack.github.io/temporal-contract/api/client)
|
|
35
|
+
- [Getting Started](https://btravstack.github.io/temporal-contract/guide/getting-started)
|
|
36
|
+
- [Examples](https://btravstack.github.io/temporal-contract/examples/)
|
|
37
37
|
|
|
38
38
|
## License
|
|
39
39
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,42 +1,32 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
let _temporalio_common = require("@temporalio/common");
|
|
3
|
-
let
|
|
3
|
+
let unthrown = require("unthrown");
|
|
4
4
|
let _temporal_contract_contract = require("@temporal-contract/contract");
|
|
5
5
|
let _temporalio_client = require("@temporalio/client");
|
|
6
6
|
let _temporal_contract_contract_result_async = require("@temporal-contract/contract/result-async");
|
|
7
7
|
//#region src/errors.ts
|
|
8
8
|
/**
|
|
9
|
-
* Base class for all typed client errors.
|
|
10
|
-
*/
|
|
11
|
-
var TypedClientError = class extends Error {
|
|
12
|
-
constructor(message) {
|
|
13
|
-
super(message);
|
|
14
|
-
this.name = this.constructor.name;
|
|
15
|
-
if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
/**
|
|
19
9
|
* Generic runtime failure wrapper when no specific error type applies
|
|
20
10
|
*/
|
|
21
|
-
var RuntimeClientError = class extends
|
|
22
|
-
operation;
|
|
23
|
-
cause;
|
|
11
|
+
var RuntimeClientError = class extends (0, unthrown.TaggedError)("@temporal-contract/RuntimeClientError", { name: "RuntimeClientError" }) {
|
|
24
12
|
constructor(operation, cause) {
|
|
25
|
-
super(
|
|
26
|
-
|
|
27
|
-
|
|
13
|
+
super({
|
|
14
|
+
operation,
|
|
15
|
+
cause,
|
|
16
|
+
message: `Operation "${operation}" failed: ${cause instanceof Error ? cause.message : String(cause ?? "unknown error")}`
|
|
17
|
+
});
|
|
28
18
|
}
|
|
29
19
|
};
|
|
30
20
|
/**
|
|
31
21
|
* Thrown when a workflow is not found in the contract
|
|
32
22
|
*/
|
|
33
|
-
var WorkflowNotFoundError = class extends
|
|
34
|
-
workflowName;
|
|
35
|
-
availableWorkflows;
|
|
23
|
+
var WorkflowNotFoundError = class extends (0, unthrown.TaggedError)("@temporal-contract/WorkflowNotFoundError", { name: "WorkflowNotFoundError" }) {
|
|
36
24
|
constructor(workflowName, availableWorkflows) {
|
|
37
|
-
super(
|
|
38
|
-
|
|
39
|
-
|
|
25
|
+
super({
|
|
26
|
+
workflowName,
|
|
27
|
+
availableWorkflows,
|
|
28
|
+
message: `Workflow "${workflowName}" not found in contract. Available workflows: ${availableWorkflows.join(", ")}`
|
|
29
|
+
});
|
|
40
30
|
}
|
|
41
31
|
};
|
|
42
32
|
/**
|
|
@@ -50,15 +40,14 @@ var WorkflowNotFoundError = class extends TypedClientError {
|
|
|
50
40
|
* branch on it explicitly (e.g. fetch the existing handle and continue)
|
|
51
41
|
* without inspecting `error.cause` against a Temporal SDK class.
|
|
52
42
|
*/
|
|
53
|
-
var WorkflowAlreadyStartedError = class extends
|
|
54
|
-
workflowType;
|
|
55
|
-
workflowId;
|
|
56
|
-
cause;
|
|
43
|
+
var WorkflowAlreadyStartedError = class extends (0, unthrown.TaggedError)("@temporal-contract/WorkflowAlreadyStartedError", { name: "WorkflowAlreadyStartedError" }) {
|
|
57
44
|
constructor(workflowType, workflowId, cause) {
|
|
58
|
-
super(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
45
|
+
super({
|
|
46
|
+
workflowType,
|
|
47
|
+
workflowId,
|
|
48
|
+
cause,
|
|
49
|
+
message: `Workflow "${workflowType}" with ID "${workflowId}" is already started or in retention.`
|
|
50
|
+
});
|
|
62
51
|
}
|
|
63
52
|
};
|
|
64
53
|
/**
|
|
@@ -73,15 +62,14 @@ var WorkflowAlreadyStartedError = class extends TypedClientError {
|
|
|
73
62
|
* - `executeWorkflow` (when the underlying execute call hits a missing
|
|
74
63
|
* execution mid-flight)
|
|
75
64
|
*/
|
|
76
|
-
var WorkflowExecutionNotFoundError = class extends
|
|
77
|
-
workflowId;
|
|
78
|
-
runId;
|
|
79
|
-
cause;
|
|
65
|
+
var WorkflowExecutionNotFoundError = class extends (0, unthrown.TaggedError)("@temporal-contract/WorkflowExecutionNotFoundError", { name: "WorkflowExecutionNotFoundError" }) {
|
|
80
66
|
constructor(workflowId, runId, cause) {
|
|
81
|
-
super(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
67
|
+
super({
|
|
68
|
+
workflowId,
|
|
69
|
+
runId,
|
|
70
|
+
cause,
|
|
71
|
+
message: `Workflow execution "${workflowId}"${runId ? ` (run "${runId}")` : ""} not found in namespace.`
|
|
72
|
+
});
|
|
85
73
|
}
|
|
86
74
|
};
|
|
87
75
|
/**
|
|
@@ -103,68 +91,65 @@ var WorkflowExecutionNotFoundError = class extends TypedClientError {
|
|
|
103
91
|
*
|
|
104
92
|
* Returned from `executeWorkflow` and `handle.result()`.
|
|
105
93
|
*/
|
|
106
|
-
var WorkflowFailedError = class extends
|
|
107
|
-
workflowId;
|
|
108
|
-
cause;
|
|
94
|
+
var WorkflowFailedError = class extends (0, unthrown.TaggedError)("@temporal-contract/WorkflowFailedError", { name: "WorkflowFailedError" }) {
|
|
109
95
|
constructor(workflowId, cause) {
|
|
110
96
|
const causeMessage = cause instanceof Error ? cause.message : String(cause ?? "unknown failure");
|
|
111
|
-
super(
|
|
112
|
-
|
|
113
|
-
|
|
97
|
+
super({
|
|
98
|
+
workflowId,
|
|
99
|
+
cause,
|
|
100
|
+
message: `Workflow "${workflowId}" completed with failure: ${causeMessage}`
|
|
101
|
+
});
|
|
114
102
|
}
|
|
115
103
|
};
|
|
116
104
|
/**
|
|
117
105
|
* Thrown when workflow input or output validation fails
|
|
118
106
|
*/
|
|
119
|
-
var WorkflowValidationError = class extends
|
|
120
|
-
workflowName;
|
|
121
|
-
direction;
|
|
122
|
-
issues;
|
|
107
|
+
var WorkflowValidationError = class extends (0, unthrown.TaggedError)("@temporal-contract/WorkflowValidationError", { name: "WorkflowValidationError" }) {
|
|
123
108
|
constructor(workflowName, direction, issues) {
|
|
124
|
-
super(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
109
|
+
super({
|
|
110
|
+
workflowName,
|
|
111
|
+
direction,
|
|
112
|
+
issues,
|
|
113
|
+
message: `Validation failed for workflow "${workflowName}" ${direction}: ${(0, _temporal_contract_contract.summarizeIssues)(issues)}`
|
|
114
|
+
});
|
|
128
115
|
}
|
|
129
116
|
};
|
|
130
117
|
/**
|
|
131
118
|
* Thrown when query input or output validation fails
|
|
132
119
|
*/
|
|
133
|
-
var QueryValidationError = class extends
|
|
134
|
-
queryName;
|
|
135
|
-
direction;
|
|
136
|
-
issues;
|
|
120
|
+
var QueryValidationError = class extends (0, unthrown.TaggedError)("@temporal-contract/QueryValidationError", { name: "QueryValidationError" }) {
|
|
137
121
|
constructor(queryName, direction, issues) {
|
|
138
|
-
super(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
122
|
+
super({
|
|
123
|
+
queryName,
|
|
124
|
+
direction,
|
|
125
|
+
issues,
|
|
126
|
+
message: `Validation failed for query "${queryName}" ${direction}: ${(0, _temporal_contract_contract.summarizeIssues)(issues)}`
|
|
127
|
+
});
|
|
142
128
|
}
|
|
143
129
|
};
|
|
144
130
|
/**
|
|
145
131
|
* Thrown when signal input validation fails
|
|
146
132
|
*/
|
|
147
|
-
var SignalValidationError = class extends
|
|
148
|
-
signalName;
|
|
149
|
-
issues;
|
|
133
|
+
var SignalValidationError = class extends (0, unthrown.TaggedError)("@temporal-contract/SignalValidationError", { name: "SignalValidationError" }) {
|
|
150
134
|
constructor(signalName, issues) {
|
|
151
|
-
super(
|
|
152
|
-
|
|
153
|
-
|
|
135
|
+
super({
|
|
136
|
+
signalName,
|
|
137
|
+
issues,
|
|
138
|
+
message: `Validation failed for signal "${signalName}": ${(0, _temporal_contract_contract.summarizeIssues)(issues)}`
|
|
139
|
+
});
|
|
154
140
|
}
|
|
155
141
|
};
|
|
156
142
|
/**
|
|
157
143
|
* Thrown when update input or output validation fails
|
|
158
144
|
*/
|
|
159
|
-
var UpdateValidationError = class extends
|
|
160
|
-
updateName;
|
|
161
|
-
direction;
|
|
162
|
-
issues;
|
|
145
|
+
var UpdateValidationError = class extends (0, unthrown.TaggedError)("@temporal-contract/UpdateValidationError", { name: "UpdateValidationError" }) {
|
|
163
146
|
constructor(updateName, direction, issues) {
|
|
164
|
-
super(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
147
|
+
super({
|
|
148
|
+
updateName,
|
|
149
|
+
direction,
|
|
150
|
+
issues,
|
|
151
|
+
message: `Validation failed for update "${updateName}" ${direction}: ${(0, _temporal_contract_contract.summarizeIssues)(issues)}`
|
|
152
|
+
});
|
|
168
153
|
}
|
|
169
154
|
};
|
|
170
155
|
//#endregion
|
|
@@ -192,37 +177,39 @@ var UpdateValidationError = class extends TypedClientError {
|
|
|
192
177
|
* unindexed without any signal to the caller.
|
|
193
178
|
*/
|
|
194
179
|
function toTypedSearchAttributes(workflowDef, workflowName, values) {
|
|
195
|
-
if (!values) return (0,
|
|
180
|
+
if (!values) return (0, unthrown.ok)(void 0);
|
|
196
181
|
const declared = workflowDef.searchAttributes ?? {};
|
|
197
182
|
const pairs = [];
|
|
198
183
|
for (const [name, value] of Object.entries(values)) {
|
|
199
184
|
if (value === void 0) continue;
|
|
200
185
|
const def = declared[name];
|
|
201
|
-
if (!def) return (0,
|
|
186
|
+
if (!def) return (0, unthrown.err)(new RuntimeClientError("searchAttributes", /* @__PURE__ */ new Error(`Search attribute "${name}" is not declared on workflow "${workflowName}". Declared attributes: ${Object.keys(declared).join(", ") || "none"}.`)));
|
|
202
187
|
const key = (0, _temporalio_common.defineSearchAttributeKey)(name, def.kind);
|
|
203
188
|
pairs.push({
|
|
204
189
|
key,
|
|
205
190
|
value
|
|
206
191
|
});
|
|
207
192
|
}
|
|
208
|
-
return (0,
|
|
193
|
+
return (0, unthrown.ok)(pairs.length > 0 ? new _temporalio_common.TypedSearchAttributes(pairs) : void 0);
|
|
209
194
|
}
|
|
210
195
|
/**
|
|
211
|
-
* Wrap an async result-producing function in
|
|
212
|
-
*
|
|
196
|
+
* Wrap an async result-producing function in an `AsyncResult`, routing any
|
|
197
|
+
* unanticipated rejection through unthrown's `defect` channel.
|
|
213
198
|
*
|
|
214
199
|
* The work function is expected to handle its own domain errors and return
|
|
215
|
-
* an `err(...)` for them;
|
|
216
|
-
*
|
|
200
|
+
* an `err(...)` for them; a thrown exception the work didn't anticipate is an
|
|
201
|
+
* *unmodeled* failure and surfaces as a defect (inspectable via
|
|
202
|
+
* `result.isDefect()` / `result.cause`, re-thrown at the edge) rather than a
|
|
203
|
+
* manufactured `RuntimeClientError`.
|
|
217
204
|
*
|
|
218
205
|
* Used by `client.ts` (workflow operations) and `schedule.ts` (schedule
|
|
219
206
|
* operations) so the unexpected-rejection shape is identical across the
|
|
220
|
-
* typed client surface. Delegates to `
|
|
207
|
+
* typed client surface. Delegates to `_internal_makeAsyncResult` from
|
|
221
208
|
* `@temporal-contract/contract` so the same wrapper is shared between the
|
|
222
209
|
* client and worker packages.
|
|
223
210
|
*/
|
|
224
|
-
function
|
|
225
|
-
return (0, _temporal_contract_contract_result_async.
|
|
211
|
+
function makeAsyncResult(work) {
|
|
212
|
+
return (0, _temporal_contract_contract_result_async._internal_makeAsyncResult)(work);
|
|
226
213
|
}
|
|
227
214
|
/**
|
|
228
215
|
* Map a thrown error from `client.workflow.start` / `signalWithStart` into
|
|
@@ -293,11 +280,12 @@ var TypedScheduleClient = class {
|
|
|
293
280
|
create(workflowName, options) {
|
|
294
281
|
const work = async () => {
|
|
295
282
|
const definition = this.contract.workflows[workflowName];
|
|
296
|
-
if (!definition) return (0,
|
|
283
|
+
if (!definition) return (0, unthrown.err)(new WorkflowNotFoundError(workflowName, Object.keys(this.contract.workflows)));
|
|
297
284
|
const inputResult = await definition.input["~standard"].validate(options.args);
|
|
298
|
-
if (inputResult.issues) return (0,
|
|
285
|
+
if (inputResult.issues) return (0, unthrown.err)(new WorkflowValidationError(workflowName, "input", inputResult.issues));
|
|
299
286
|
const searchAttributesResult = toTypedSearchAttributes(definition, workflowName, options.searchAttributes);
|
|
300
|
-
|
|
287
|
+
(0, _temporal_contract_contract_result_async._internal_assertNoDefect)(searchAttributesResult);
|
|
288
|
+
if (searchAttributesResult.isErr()) return (0, unthrown.err)(searchAttributesResult.error);
|
|
301
289
|
const typedSearchAttributes = searchAttributesResult.value;
|
|
302
290
|
try {
|
|
303
291
|
const overrides = options.action ?? {};
|
|
@@ -316,7 +304,7 @@ var TypedScheduleClient = class {
|
|
|
316
304
|
...overrides.staticDetails !== void 0 ? { staticDetails: overrides.staticDetails } : {},
|
|
317
305
|
...overrides.staticSummary !== void 0 ? { staticSummary: overrides.staticSummary } : {}
|
|
318
306
|
};
|
|
319
|
-
return (0,
|
|
307
|
+
return (0, unthrown.ok)(wrapScheduleHandle(await this.scheduleClient.create({
|
|
320
308
|
scheduleId: options.scheduleId,
|
|
321
309
|
spec: options.spec,
|
|
322
310
|
action,
|
|
@@ -325,10 +313,10 @@ var TypedScheduleClient = class {
|
|
|
325
313
|
...options.memo !== void 0 ? { memo: options.memo } : {}
|
|
326
314
|
})));
|
|
327
315
|
} catch (error) {
|
|
328
|
-
return (0,
|
|
316
|
+
return (0, unthrown.err)(new RuntimeClientError("schedule.create", error));
|
|
329
317
|
}
|
|
330
318
|
};
|
|
331
|
-
return
|
|
319
|
+
return makeAsyncResult(work);
|
|
332
320
|
}
|
|
333
321
|
/**
|
|
334
322
|
* Get a typed handle to an existing schedule. Does not validate that the
|
|
@@ -342,11 +330,11 @@ var TypedScheduleClient = class {
|
|
|
342
330
|
function wrapScheduleHandle(handle) {
|
|
343
331
|
return {
|
|
344
332
|
scheduleId: handle.scheduleId,
|
|
345
|
-
pause: (note) =>
|
|
346
|
-
unpause: (note) =>
|
|
347
|
-
trigger: (overlap) =>
|
|
348
|
-
delete: () =>
|
|
349
|
-
describe: () =>
|
|
333
|
+
pause: (note) => (0, unthrown.fromPromise)(handle.pause(note), (error) => new RuntimeClientError("schedule.pause", error)).map(() => void 0),
|
|
334
|
+
unpause: (note) => (0, unthrown.fromPromise)(handle.unpause(note), (error) => new RuntimeClientError("schedule.unpause", error)).map(() => void 0),
|
|
335
|
+
trigger: (overlap) => (0, unthrown.fromPromise)(handle.trigger(overlap), (error) => new RuntimeClientError("schedule.trigger", error)).map(() => void 0),
|
|
336
|
+
delete: () => (0, unthrown.fromPromise)(handle.delete(), (error) => new RuntimeClientError("schedule.delete", error)).map(() => void 0),
|
|
337
|
+
describe: () => (0, unthrown.fromPromise)(handle.describe(), (error) => new RuntimeClientError("schedule.describe", error))
|
|
350
338
|
};
|
|
351
339
|
}
|
|
352
340
|
//#endregion
|
|
@@ -411,20 +399,21 @@ function readTypedSearchAttributes(workflowDef, instance) {
|
|
|
411
399
|
*/
|
|
412
400
|
async function resolveDefinitionAndValidateInput(contract, workflowName, args, searchAttributes) {
|
|
413
401
|
const definition = contract.workflows[workflowName];
|
|
414
|
-
if (!definition) return (0,
|
|
402
|
+
if (!definition) return (0, unthrown.err)(createWorkflowNotFoundError(workflowName, contract));
|
|
415
403
|
const inputResult = await definition.input["~standard"].validate(args);
|
|
416
|
-
if (inputResult.issues) return (0,
|
|
404
|
+
if (inputResult.issues) return (0, unthrown.err)(createWorkflowValidationError(workflowName, "input", inputResult.issues));
|
|
417
405
|
const searchAttributesResult = toTypedSearchAttributes(definition, workflowName, searchAttributes);
|
|
418
|
-
|
|
406
|
+
(0, _temporal_contract_contract_result_async._internal_assertNoDefect)(searchAttributesResult);
|
|
407
|
+
if (searchAttributesResult.isErr()) return (0, unthrown.err)(searchAttributesResult.error);
|
|
419
408
|
const typedSearchAttributes = searchAttributesResult.value;
|
|
420
|
-
return (0,
|
|
409
|
+
return (0, unthrown.ok)({
|
|
421
410
|
definition,
|
|
422
411
|
validatedInput: inputResult.value,
|
|
423
412
|
typedSearchAttributes
|
|
424
413
|
});
|
|
425
414
|
}
|
|
426
415
|
/**
|
|
427
|
-
* Typed Temporal client with
|
|
416
|
+
* Typed Temporal client with unthrown Result/AsyncResult pattern based on a contract
|
|
428
417
|
*
|
|
429
418
|
* Provides type-safe methods to start and execute workflows
|
|
430
419
|
* defined in the contract, with explicit error handling using Result pattern.
|
|
@@ -452,10 +441,11 @@ var TypedClient = class TypedClient {
|
|
|
452
441
|
* args: { orderId: "sweep" },
|
|
453
442
|
* });
|
|
454
443
|
*
|
|
455
|
-
* result.match(
|
|
456
|
-
* async (handle) => { await handle.pause("maintenance"); },
|
|
457
|
-
* (error) => console.error("schedule create failed", error),
|
|
458
|
-
* )
|
|
444
|
+
* await result.match({
|
|
445
|
+
* ok: async (handle) => { await handle.pause("maintenance"); },
|
|
446
|
+
* err: (error) => console.error("schedule create failed", error),
|
|
447
|
+
* defect: (cause) => console.error("unexpected failure", cause),
|
|
448
|
+
* });
|
|
459
449
|
* ```
|
|
460
450
|
*/
|
|
461
451
|
schedule;
|
|
@@ -466,7 +456,7 @@ var TypedClient = class TypedClient {
|
|
|
466
456
|
this.schedule = new TypedScheduleClient(contract, client.schedule);
|
|
467
457
|
}
|
|
468
458
|
/**
|
|
469
|
-
* Create a typed Temporal client with
|
|
459
|
+
* Create a typed Temporal client with unthrown pattern from a contract
|
|
470
460
|
*
|
|
471
461
|
* @example
|
|
472
462
|
* ```ts
|
|
@@ -479,17 +469,18 @@ var TypedClient = class TypedClient {
|
|
|
479
469
|
* args: { ... },
|
|
480
470
|
* });
|
|
481
471
|
*
|
|
482
|
-
* result.match(
|
|
483
|
-
* (output) => console.log('Success:', output),
|
|
484
|
-
* (error) => console.error('Failed:', error),
|
|
485
|
-
* )
|
|
472
|
+
* await result.match({
|
|
473
|
+
* ok: (output) => console.log('Success:', output),
|
|
474
|
+
* err: (error) => console.error('Failed:', error),
|
|
475
|
+
* defect: (cause) => console.error('Unexpected failure:', cause),
|
|
476
|
+
* });
|
|
486
477
|
* ```
|
|
487
478
|
*/
|
|
488
479
|
static create(contract, client) {
|
|
489
480
|
return new TypedClient(contract, client);
|
|
490
481
|
}
|
|
491
482
|
/**
|
|
492
|
-
* Start a workflow and return a typed handle with
|
|
483
|
+
* Start a workflow and return a typed handle with AsyncResult pattern
|
|
493
484
|
*
|
|
494
485
|
* @example
|
|
495
486
|
* ```ts
|
|
@@ -500,19 +491,21 @@ var TypedClient = class TypedClient {
|
|
|
500
491
|
* retry: { maximumAttempts: 3 },
|
|
501
492
|
* });
|
|
502
493
|
*
|
|
503
|
-
* handleResult.match(
|
|
504
|
-
* async (handle) => {
|
|
494
|
+
* await handleResult.match({
|
|
495
|
+
* ok: async (handle) => {
|
|
505
496
|
* const result = await handle.result();
|
|
506
497
|
* // ... handle result
|
|
507
498
|
* },
|
|
508
|
-
* (error) => console.error('Failed to start:', error),
|
|
509
|
-
* )
|
|
499
|
+
* err: (error) => console.error('Failed to start:', error),
|
|
500
|
+
* defect: (cause) => console.error('Unexpected failure:', cause),
|
|
501
|
+
* });
|
|
510
502
|
* ```
|
|
511
503
|
*/
|
|
512
504
|
startWorkflow(workflowName, { args, searchAttributes, ...temporalOptions }) {
|
|
513
505
|
const work = async () => {
|
|
514
506
|
const resolved = await resolveDefinitionAndValidateInput(this.contract, workflowName, args, searchAttributes);
|
|
515
|
-
|
|
507
|
+
(0, _temporal_contract_contract_result_async._internal_assertNoDefect)(resolved);
|
|
508
|
+
if (resolved.isErr()) return (0, unthrown.err)(resolved.error);
|
|
516
509
|
const { definition, validatedInput, typedSearchAttributes } = resolved.value;
|
|
517
510
|
try {
|
|
518
511
|
const handle = await this.client.workflow.start(workflowName, {
|
|
@@ -521,12 +514,12 @@ var TypedClient = class TypedClient {
|
|
|
521
514
|
args: [validatedInput],
|
|
522
515
|
...typedSearchAttributes ? { typedSearchAttributes } : {}
|
|
523
516
|
});
|
|
524
|
-
return (0,
|
|
517
|
+
return (0, unthrown.ok)(this.createTypedHandle(handle, definition));
|
|
525
518
|
} catch (error) {
|
|
526
|
-
return (0,
|
|
519
|
+
return (0, unthrown.err)(classifyStartError("startWorkflow", error));
|
|
527
520
|
}
|
|
528
521
|
};
|
|
529
|
-
return
|
|
522
|
+
return makeAsyncResult(work);
|
|
530
523
|
}
|
|
531
524
|
/**
|
|
532
525
|
* Send a signal to a workflow, starting it first if it doesn't already exist.
|
|
@@ -548,21 +541,23 @@ var TypedClient = class TypedClient {
|
|
|
548
541
|
* signalArgs: { reason: 'duplicate' },
|
|
549
542
|
* });
|
|
550
543
|
*
|
|
551
|
-
* result.match(
|
|
552
|
-
* (handle) => console.log('signaled run', handle.signaledRunId),
|
|
553
|
-
* (error) => console.error('signalWithStart failed', error),
|
|
554
|
-
* )
|
|
544
|
+
* await result.match({
|
|
545
|
+
* ok: (handle) => console.log('signaled run', handle.signaledRunId),
|
|
546
|
+
* err: (error) => console.error('signalWithStart failed', error),
|
|
547
|
+
* defect: (cause) => console.error('unexpected failure', cause),
|
|
548
|
+
* });
|
|
555
549
|
* ```
|
|
556
550
|
*/
|
|
557
551
|
signalWithStart(workflowName, { args, signalName, signalArgs, searchAttributes, ...temporalOptions }) {
|
|
558
552
|
const work = async () => {
|
|
559
553
|
const resolved = await resolveDefinitionAndValidateInput(this.contract, workflowName, args, searchAttributes);
|
|
560
|
-
|
|
554
|
+
(0, _temporal_contract_contract_result_async._internal_assertNoDefect)(resolved);
|
|
555
|
+
if (resolved.isErr()) return (0, unthrown.err)(resolved.error);
|
|
561
556
|
const { definition, validatedInput, typedSearchAttributes } = resolved.value;
|
|
562
557
|
const signalDef = definition.signals?.[signalName];
|
|
563
|
-
if (!signalDef) return (0,
|
|
558
|
+
if (!signalDef) return (0, unthrown.err)(new SignalValidationError(signalName, [{ message: `Signal "${signalName}" is not declared on workflow "${workflowName}".` }]));
|
|
564
559
|
const signalInputResult = await signalDef.input["~standard"].validate(signalArgs);
|
|
565
|
-
if (signalInputResult.issues) return (0,
|
|
560
|
+
if (signalInputResult.issues) return (0, unthrown.err)(new SignalValidationError(signalName, signalInputResult.issues));
|
|
566
561
|
try {
|
|
567
562
|
const handle = await this.client.workflow.signalWithStart(workflowName, {
|
|
568
563
|
...temporalOptions,
|
|
@@ -572,18 +567,18 @@ var TypedClient = class TypedClient {
|
|
|
572
567
|
signalArgs: [signalInputResult.value],
|
|
573
568
|
...typedSearchAttributes ? { typedSearchAttributes } : {}
|
|
574
569
|
});
|
|
575
|
-
return (0,
|
|
570
|
+
return (0, unthrown.ok)({
|
|
576
571
|
...this.createTypedHandle(handle, definition),
|
|
577
572
|
signaledRunId: handle.signaledRunId
|
|
578
573
|
});
|
|
579
574
|
} catch (error) {
|
|
580
|
-
return (0,
|
|
575
|
+
return (0, unthrown.err)(classifyStartError("signalWithStart", error));
|
|
581
576
|
}
|
|
582
577
|
};
|
|
583
|
-
return
|
|
578
|
+
return makeAsyncResult(work);
|
|
584
579
|
}
|
|
585
580
|
/**
|
|
586
|
-
* Execute a workflow (start and wait for result) with
|
|
581
|
+
* Execute a workflow (start and wait for result) with AsyncResult pattern
|
|
587
582
|
*
|
|
588
583
|
* @example
|
|
589
584
|
* ```ts
|
|
@@ -594,16 +589,18 @@ var TypedClient = class TypedClient {
|
|
|
594
589
|
* retry: { maximumAttempts: 3 },
|
|
595
590
|
* });
|
|
596
591
|
*
|
|
597
|
-
* result.match(
|
|
598
|
-
* (output) => console.log('Order processed:', output.status),
|
|
599
|
-
* (error) => console.error('Processing failed:', error),
|
|
600
|
-
* )
|
|
592
|
+
* await result.match({
|
|
593
|
+
* ok: (output) => console.log('Order processed:', output.status),
|
|
594
|
+
* err: (error) => console.error('Processing failed:', error),
|
|
595
|
+
* defect: (cause) => console.error('Unexpected failure:', cause),
|
|
596
|
+
* });
|
|
601
597
|
* ```
|
|
602
598
|
*/
|
|
603
599
|
executeWorkflow(workflowName, { args, searchAttributes, ...temporalOptions }) {
|
|
604
600
|
const work = async () => {
|
|
605
601
|
const resolved = await resolveDefinitionAndValidateInput(this.contract, workflowName, args, searchAttributes);
|
|
606
|
-
|
|
602
|
+
(0, _temporal_contract_contract_result_async._internal_assertNoDefect)(resolved);
|
|
603
|
+
if (resolved.isErr()) return (0, unthrown.err)(resolved.error);
|
|
607
604
|
const { definition, validatedInput, typedSearchAttributes } = resolved.value;
|
|
608
605
|
try {
|
|
609
606
|
const result = await this.client.workflow.execute(workflowName, {
|
|
@@ -613,19 +610,19 @@ var TypedClient = class TypedClient {
|
|
|
613
610
|
...typedSearchAttributes ? { typedSearchAttributes } : {}
|
|
614
611
|
});
|
|
615
612
|
const outputResult = await definition.output["~standard"].validate(result);
|
|
616
|
-
if (outputResult.issues) return (0,
|
|
617
|
-
return (0,
|
|
613
|
+
if (outputResult.issues) return (0, unthrown.err)(createWorkflowValidationError(workflowName, "output", outputResult.issues));
|
|
614
|
+
return (0, unthrown.ok)(outputResult.value);
|
|
618
615
|
} catch (error) {
|
|
619
|
-
if (error instanceof _temporalio_client.WorkflowExecutionAlreadyStartedError) return (0,
|
|
620
|
-
if (error instanceof _temporalio_client.WorkflowFailedError) return (0,
|
|
621
|
-
if (error instanceof _temporalio_common.WorkflowNotFoundError) return (0,
|
|
622
|
-
return (0,
|
|
616
|
+
if (error instanceof _temporalio_client.WorkflowExecutionAlreadyStartedError) return (0, unthrown.err)(new WorkflowAlreadyStartedError(error.workflowType, error.workflowId, error));
|
|
617
|
+
if (error instanceof _temporalio_client.WorkflowFailedError) return (0, unthrown.err)(new WorkflowFailedError(temporalOptions.workflowId, error.cause));
|
|
618
|
+
if (error instanceof _temporalio_common.WorkflowNotFoundError) return (0, unthrown.err)(new WorkflowExecutionNotFoundError(error.workflowId || temporalOptions.workflowId, error.runId, error));
|
|
619
|
+
return (0, unthrown.err)(createRuntimeClientError("executeWorkflow", error));
|
|
623
620
|
}
|
|
624
621
|
};
|
|
625
|
-
return
|
|
622
|
+
return makeAsyncResult(work);
|
|
626
623
|
}
|
|
627
624
|
/**
|
|
628
|
-
* Get a handle to an existing workflow with
|
|
625
|
+
* Get a handle to an existing workflow with AsyncResult pattern
|
|
629
626
|
*
|
|
630
627
|
* @example
|
|
631
628
|
* ```ts
|
|
@@ -642,15 +639,15 @@ var TypedClient = class TypedClient {
|
|
|
642
639
|
getHandle(workflowName, workflowId) {
|
|
643
640
|
const work = async () => {
|
|
644
641
|
const definition = this.contract.workflows[workflowName];
|
|
645
|
-
if (!definition) return (0,
|
|
642
|
+
if (!definition) return (0, unthrown.err)(createWorkflowNotFoundError(workflowName, this.contract));
|
|
646
643
|
try {
|
|
647
644
|
const handle = this.client.workflow.getHandle(workflowId);
|
|
648
|
-
return (0,
|
|
645
|
+
return (0, unthrown.ok)(this.createTypedHandle(handle, definition));
|
|
649
646
|
} catch (error) {
|
|
650
|
-
return (0,
|
|
647
|
+
return (0, unthrown.err)(createRuntimeClientError("getHandle", error));
|
|
651
648
|
}
|
|
652
649
|
};
|
|
653
|
-
return
|
|
650
|
+
return makeAsyncResult(work);
|
|
654
651
|
}
|
|
655
652
|
createTypedHandle(workflowHandle, definition) {
|
|
656
653
|
const queries = buildValidatedProxy({
|
|
@@ -689,18 +686,18 @@ var TypedClient = class TypedClient {
|
|
|
689
686
|
try {
|
|
690
687
|
const result = await workflowHandle.result();
|
|
691
688
|
const outputResult = await definition.output["~standard"].validate(result);
|
|
692
|
-
if (outputResult.issues) return (0,
|
|
693
|
-
return (0,
|
|
689
|
+
if (outputResult.issues) return (0, unthrown.err)(new WorkflowValidationError(workflowHandle.workflowId, "output", outputResult.issues));
|
|
690
|
+
return (0, unthrown.ok)(outputResult.value);
|
|
694
691
|
} catch (error) {
|
|
695
|
-
return (0,
|
|
692
|
+
return (0, unthrown.err)(classifyResultError("result", error, workflowHandle.workflowId));
|
|
696
693
|
}
|
|
697
694
|
};
|
|
698
|
-
return
|
|
695
|
+
return makeAsyncResult(work);
|
|
699
696
|
},
|
|
700
|
-
terminate: (reason) =>
|
|
701
|
-
cancel: () =>
|
|
702
|
-
describe: () =>
|
|
703
|
-
fetchHistory: () =>
|
|
697
|
+
terminate: (reason) => (0, unthrown.fromPromise)(workflowHandle.terminate(reason), (error) => classifyHandleError("terminate", error, workflowHandle.workflowId)).map(() => void 0),
|
|
698
|
+
cancel: () => (0, unthrown.fromPromise)(workflowHandle.cancel(), (error) => classifyHandleError("cancel", error, workflowHandle.workflowId)).map(() => void 0),
|
|
699
|
+
describe: () => (0, unthrown.fromPromise)(workflowHandle.describe(), (error) => classifyHandleError("describe", error, workflowHandle.workflowId)),
|
|
700
|
+
fetchHistory: () => (0, unthrown.fromPromise)(workflowHandle.fetchHistory(), (error) => classifyHandleError("fetchHistory", error, workflowHandle.workflowId))
|
|
704
701
|
};
|
|
705
702
|
}
|
|
706
703
|
};
|
|
@@ -714,7 +711,7 @@ function createWorkflowValidationError(workflowName, direction, issues) {
|
|
|
714
711
|
return new WorkflowValidationError(String(workflowName), direction, issues);
|
|
715
712
|
}
|
|
716
713
|
/**
|
|
717
|
-
* Build a `{ name: (args) =>
|
|
714
|
+
* Build a `{ name: (args) => AsyncResult<...> }` proxy for a contract's
|
|
718
715
|
* queries/signals/updates. The three call sites differ only in how they
|
|
719
716
|
* invoke Temporal and whether they validate output, so the shared
|
|
720
717
|
* input-validate → invoke → output-validate → wrap-Result pipeline lives
|
|
@@ -726,19 +723,19 @@ function buildValidatedProxy({ defs, operation, workflowId, makeValidationError,
|
|
|
726
723
|
for (const [name, def] of Object.entries(defs)) proxy[name] = (args) => {
|
|
727
724
|
const work = async () => {
|
|
728
725
|
const inputResult = await def.input["~standard"].validate(args);
|
|
729
|
-
if (inputResult.issues) return (0,
|
|
726
|
+
if (inputResult.issues) return (0, unthrown.err)(makeValidationError(name, "input", inputResult.issues));
|
|
730
727
|
try {
|
|
731
728
|
const result = await invoke(name, inputResult.value);
|
|
732
729
|
const outputSchema = validateOutput(def);
|
|
733
|
-
if (!outputSchema) return (0,
|
|
730
|
+
if (!outputSchema) return (0, unthrown.ok)(result);
|
|
734
731
|
const outputResult = await outputSchema["~standard"].validate(result);
|
|
735
|
-
if (outputResult.issues) return (0,
|
|
736
|
-
return (0,
|
|
732
|
+
if (outputResult.issues) return (0, unthrown.err)(makeValidationError(name, "output", outputResult.issues));
|
|
733
|
+
return (0, unthrown.ok)(outputResult.value);
|
|
737
734
|
} catch (error) {
|
|
738
|
-
return (0,
|
|
735
|
+
return (0, unthrown.err)(classifyHandleError(operation, error, workflowId));
|
|
739
736
|
}
|
|
740
737
|
};
|
|
741
|
-
return
|
|
738
|
+
return makeAsyncResult(work);
|
|
742
739
|
};
|
|
743
740
|
return proxy;
|
|
744
741
|
}
|