@temporal-contract/client 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.
- package/.turbo/turbo-build.log +17 -0
- package/LICENSE +21 -0
- package/README.md +98 -0
- package/dist/index.cjs +269 -0
- package/dist/index.d.cts +190 -0
- package/dist/index.d.mts +190 -0
- package/dist/index.mjs +263 -0
- package/package.json +63 -0
- package/src/client.spec.ts +564 -0
- package/src/client.ts +390 -0
- package/src/errors.ts +80 -0
- package/src/index.ts +9 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
> @temporal-contract/client@0.0.1 build /home/runner/work/temporal-contract/temporal-contract/packages/client
|
|
3
|
+
> tsdown src/index.ts --format cjs,esm --dts --clean
|
|
4
|
+
|
|
5
|
+
[34mℹ[39m tsdown [2mv0.17.2[22m powered by rolldown [2mv1.0.0-beta.53[22m
|
|
6
|
+
[34mℹ[39m entry: [34msrc/index.ts[39m
|
|
7
|
+
[34mℹ[39m tsconfig: [34mtsconfig.json[39m
|
|
8
|
+
[34mℹ[39m Build start
|
|
9
|
+
[34mℹ[39m [33m[CJS][39m [2mdist/[22m[1mindex.cjs[22m [2m8.38 kB[22m [2m│ gzip: 1.77 kB[22m
|
|
10
|
+
[34mℹ[39m [33m[CJS][39m 1 files, total: 8.38 kB
|
|
11
|
+
[34mℹ[39m [34m[ESM][39m [2mdist/[22m[1mindex.mjs[22m [2m8.12 kB[22m [2m│ gzip: 1.74 kB[22m
|
|
12
|
+
[34mℹ[39m [34m[ESM][39m [2mdist/[22m[32m[1mindex.d.mts[22m[39m [2m6.70 kB[22m [2m│ gzip: 1.62 kB[22m
|
|
13
|
+
[34mℹ[39m [34m[ESM][39m 2 files, total: 14.81 kB
|
|
14
|
+
[32m✔[39m Build complete in [32m3603ms[39m
|
|
15
|
+
[34mℹ[39m [33m[CJS][39m [2mdist/[22m[32m[1mindex.d.cts[22m[39m [2m6.70 kB[22m [2m│ gzip: 1.62 kB[22m
|
|
16
|
+
[34mℹ[39m [33m[CJS][39m 1 files, total: 6.70 kB
|
|
17
|
+
[32m✔[39m Build complete in [32m3605ms[39m
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Benoit TRAVERS
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# @temporal-contract/client
|
|
2
|
+
|
|
3
|
+
> Type-safe client for consuming Temporal workflows
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @temporal-contract/client @temporal-contract/contract @temporalio/client zod
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { Connection } from '@temporalio/client';
|
|
15
|
+
import { TypedClient } from '@temporal-contract/client';
|
|
16
|
+
import { myContract } from './contract';
|
|
17
|
+
|
|
18
|
+
// Connect to Temporal
|
|
19
|
+
const connection = await Connection.connect({ address: 'localhost:7233' });
|
|
20
|
+
|
|
21
|
+
// Create typed client
|
|
22
|
+
const client = TypedClient.create(myContract, {
|
|
23
|
+
connection,
|
|
24
|
+
namespace: 'default',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Execute workflow (fully typed!)
|
|
28
|
+
const result = await client.executeWorkflow('processOrder', {
|
|
29
|
+
workflowId: 'order-123',
|
|
30
|
+
args: { orderId: 'ORD-123', customerId: 'CUST-456' },
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
console.log(result.status); // 'success' | 'failed' — typed!
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## API
|
|
37
|
+
|
|
38
|
+
### `TypedClient.create(contract, options)`
|
|
39
|
+
|
|
40
|
+
Creates a type-safe Temporal client.
|
|
41
|
+
|
|
42
|
+
**Returns:** Type-safe client with these methods:
|
|
43
|
+
|
|
44
|
+
#### `executeWorkflow(name, options)`
|
|
45
|
+
|
|
46
|
+
Execute and wait for result:
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
const result = await client.executeWorkflow('processOrder', {
|
|
50
|
+
workflowId: 'order-123',
|
|
51
|
+
args: { orderId: 'ORD-123', customerId: 'CUST-456' },
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
#### `startWorkflow(name, options)` / `getHandle(name, workflowId)`
|
|
56
|
+
|
|
57
|
+
Get a typed workflow handle for signals/queries/updates:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
const handle = await client.startWorkflow('processOrder', {
|
|
61
|
+
workflowId: 'order-456',
|
|
62
|
+
args: { orderId: 'ORD-456' },
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Type-safe queries, signals, updates
|
|
66
|
+
await handle.queries.getStatus();
|
|
67
|
+
await handle.signals.cancel({ reason: 'Customer request' });
|
|
68
|
+
await handle.updates.changeAmount({ newAmount: 150 });
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Error Handling
|
|
72
|
+
|
|
73
|
+
Custom error classes with contextual information:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { WorkflowValidationError, WorkflowNotFoundError } from '@temporal-contract/client';
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
await client.executeWorkflow('processOrder', { args: invalidData });
|
|
80
|
+
} catch (error) {
|
|
81
|
+
if (error instanceof WorkflowValidationError) {
|
|
82
|
+
console.error('Validation:', error.zodError.errors);
|
|
83
|
+
} else if (error instanceof WorkflowNotFoundError) {
|
|
84
|
+
console.error('Available:', error.availableWorkflows);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Learn More
|
|
92
|
+
|
|
93
|
+
- [Main README](../../README.md) — Quick start guide
|
|
94
|
+
- [Worker Implementation](../../docs/CONTRACT_HANDLER.md) — Implementing workers
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
let __temporalio_client = require("@temporalio/client");
|
|
2
|
+
let zod = require("zod");
|
|
3
|
+
|
|
4
|
+
//#region src/errors.ts
|
|
5
|
+
/**
|
|
6
|
+
* Base error class for typed client errors
|
|
7
|
+
*/
|
|
8
|
+
var TypedClientError = class extends Error {
|
|
9
|
+
constructor(message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = "TypedClientError";
|
|
12
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Error thrown when a workflow is not found in the contract
|
|
17
|
+
*/
|
|
18
|
+
var WorkflowNotFoundError = class extends TypedClientError {
|
|
19
|
+
constructor(workflowName) {
|
|
20
|
+
super(`Workflow "${workflowName}" not found in contract`);
|
|
21
|
+
this.workflowName = workflowName;
|
|
22
|
+
this.name = "WorkflowNotFoundError";
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Error thrown when workflow input or output validation fails
|
|
27
|
+
*/
|
|
28
|
+
var WorkflowValidationError = class extends TypedClientError {
|
|
29
|
+
constructor(workflowName, phase, zodError) {
|
|
30
|
+
super(`Validation failed for workflow "${workflowName}" ${phase}: ${zodError.message}`);
|
|
31
|
+
this.workflowName = workflowName;
|
|
32
|
+
this.phase = phase;
|
|
33
|
+
this.zodError = zodError;
|
|
34
|
+
this.name = "WorkflowValidationError";
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Error thrown when query input or output validation fails
|
|
39
|
+
*/
|
|
40
|
+
var QueryValidationError = class extends TypedClientError {
|
|
41
|
+
constructor(queryName, phase, zodError) {
|
|
42
|
+
super(`Validation failed for query "${queryName}" ${phase}: ${zodError.message}`);
|
|
43
|
+
this.queryName = queryName;
|
|
44
|
+
this.phase = phase;
|
|
45
|
+
this.zodError = zodError;
|
|
46
|
+
this.name = "QueryValidationError";
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Error thrown when signal input validation fails
|
|
51
|
+
*/
|
|
52
|
+
var SignalValidationError = class extends TypedClientError {
|
|
53
|
+
constructor(signalName, zodError) {
|
|
54
|
+
super(`Validation failed for signal "${signalName}" input: ${zodError.message}`);
|
|
55
|
+
this.signalName = signalName;
|
|
56
|
+
this.zodError = zodError;
|
|
57
|
+
this.name = "SignalValidationError";
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Error thrown when update input or output validation fails
|
|
62
|
+
*/
|
|
63
|
+
var UpdateValidationError = class extends TypedClientError {
|
|
64
|
+
constructor(updateName, phase, zodError) {
|
|
65
|
+
super(`Validation failed for update "${updateName}" ${phase}: ${zodError.message}`);
|
|
66
|
+
this.updateName = updateName;
|
|
67
|
+
this.phase = phase;
|
|
68
|
+
this.zodError = zodError;
|
|
69
|
+
this.name = "UpdateValidationError";
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/client.ts
|
|
75
|
+
/**
|
|
76
|
+
* Typed Temporal client based on a contract
|
|
77
|
+
*
|
|
78
|
+
* Provides type-safe methods to start and execute workflows
|
|
79
|
+
* defined in the contract.
|
|
80
|
+
*/
|
|
81
|
+
var TypedClient = class TypedClient {
|
|
82
|
+
constructor(contract, client) {
|
|
83
|
+
this.contract = contract;
|
|
84
|
+
this.client = client;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Create a typed Temporal client from a contract
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* const connection = await Connection.connect();
|
|
92
|
+
* const client = TypedClient.create(myContract, {
|
|
93
|
+
* connection,
|
|
94
|
+
* namespace: 'default',
|
|
95
|
+
* });
|
|
96
|
+
*
|
|
97
|
+
* const result = await client.executeWorkflow('processOrder', {
|
|
98
|
+
* workflowId: 'order-123',
|
|
99
|
+
* args: [...],
|
|
100
|
+
* });
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
static create(contract, options) {
|
|
104
|
+
return new TypedClient(contract, new __temporalio_client.Client(options));
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Start a workflow and return a typed handle
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```ts
|
|
111
|
+
* const handle = await client.startWorkflow('processOrder', {
|
|
112
|
+
* workflowId: 'order-123',
|
|
113
|
+
* args: ['ORD-123', 'CUST-456', [{ productId: 'PROD-1', quantity: 2 }]],
|
|
114
|
+
* workflowExecutionTimeout: '1 day',
|
|
115
|
+
* retry: { maximumAttempts: 3 },
|
|
116
|
+
* });
|
|
117
|
+
*
|
|
118
|
+
* const result = await handle.result();
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
async startWorkflow(workflowName, { args, ...temporalOptions }) {
|
|
122
|
+
const definition = this.contract.workflows[workflowName];
|
|
123
|
+
if (!definition) throw new WorkflowNotFoundError(String(workflowName));
|
|
124
|
+
let validatedInput;
|
|
125
|
+
try {
|
|
126
|
+
validatedInput = definition.input.parse(args);
|
|
127
|
+
} catch (error) {
|
|
128
|
+
if (error instanceof zod.ZodError) throw new WorkflowValidationError(String(workflowName), "input", error);
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
const handle = await this.client.workflow.start(workflowName, {
|
|
132
|
+
...temporalOptions,
|
|
133
|
+
taskQueue: this.contract.taskQueue,
|
|
134
|
+
args: [validatedInput]
|
|
135
|
+
});
|
|
136
|
+
return this.createTypedHandle(handle, definition);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Execute a workflow (start and wait for result)
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```ts
|
|
143
|
+
* const result = await client.executeWorkflow('processOrder', {
|
|
144
|
+
* workflowId: 'order-123',
|
|
145
|
+
* args: ['ORD-123', 'CUST-456', [{ productId: 'PROD-1', quantity: 2 }]],
|
|
146
|
+
* workflowExecutionTimeout: '1 day',
|
|
147
|
+
* retry: { maximumAttempts: 3 },
|
|
148
|
+
* });
|
|
149
|
+
*
|
|
150
|
+
* console.log(result.status); // fully typed!
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
async executeWorkflow(workflowName, { args, ...temporalOptions }) {
|
|
154
|
+
const definition = this.contract.workflows[workflowName];
|
|
155
|
+
if (!definition) throw new WorkflowNotFoundError(String(workflowName));
|
|
156
|
+
let validatedInput;
|
|
157
|
+
try {
|
|
158
|
+
validatedInput = definition.input.parse(args);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
if (error instanceof zod.ZodError) throw new WorkflowValidationError(String(workflowName), "input", error);
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
const result = await this.client.workflow.execute(workflowName, {
|
|
164
|
+
...temporalOptions,
|
|
165
|
+
taskQueue: this.contract.taskQueue,
|
|
166
|
+
args: [validatedInput]
|
|
167
|
+
});
|
|
168
|
+
try {
|
|
169
|
+
return definition.output.parse(result);
|
|
170
|
+
} catch (error) {
|
|
171
|
+
if (error instanceof zod.ZodError) throw new WorkflowValidationError(String(workflowName), "output", error);
|
|
172
|
+
throw error;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Get a handle to an existing workflow
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* const handle = await client.getHandle('processOrder', 'order-123');
|
|
181
|
+
* const result = await handle.result();
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
async getHandle(workflowName, workflowId) {
|
|
185
|
+
const definition = this.contract.workflows[workflowName];
|
|
186
|
+
if (!definition) throw new WorkflowNotFoundError(String(workflowName));
|
|
187
|
+
const handle = this.client.workflow.getHandle(workflowId);
|
|
188
|
+
return this.createTypedHandle(handle, definition);
|
|
189
|
+
}
|
|
190
|
+
createTypedHandle(handle, definition) {
|
|
191
|
+
const queries = {};
|
|
192
|
+
for (const [queryName, queryDef] of Object.entries(definition.queries ?? {})) queries[queryName] = async (args) => {
|
|
193
|
+
let validatedInput;
|
|
194
|
+
try {
|
|
195
|
+
validatedInput = queryDef.input.parse(args);
|
|
196
|
+
} catch (error) {
|
|
197
|
+
if (error instanceof zod.ZodError) throw new QueryValidationError(queryName, "input", error);
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
const result = await handle.query(queryName, validatedInput);
|
|
201
|
+
try {
|
|
202
|
+
return queryDef.output.parse(result);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
if (error instanceof zod.ZodError) throw new QueryValidationError(queryName, "output", error);
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
const signals = {};
|
|
209
|
+
for (const [signalName, signalDef] of Object.entries(definition.signals ?? {})) signals[signalName] = async (args) => {
|
|
210
|
+
let validatedInput;
|
|
211
|
+
try {
|
|
212
|
+
validatedInput = signalDef.input.parse(args);
|
|
213
|
+
} catch (error) {
|
|
214
|
+
if (error instanceof zod.ZodError) throw new SignalValidationError(signalName, error);
|
|
215
|
+
throw error;
|
|
216
|
+
}
|
|
217
|
+
await handle.signal(signalName, validatedInput);
|
|
218
|
+
};
|
|
219
|
+
const updates = {};
|
|
220
|
+
for (const [updateName, updateDef] of Object.entries(definition.updates ?? {})) updates[updateName] = async (args) => {
|
|
221
|
+
let validatedInput;
|
|
222
|
+
try {
|
|
223
|
+
validatedInput = updateDef.input.parse(args);
|
|
224
|
+
} catch (error) {
|
|
225
|
+
if (error instanceof zod.ZodError) throw new UpdateValidationError(updateName, "input", error);
|
|
226
|
+
throw error;
|
|
227
|
+
}
|
|
228
|
+
const result = await handle.executeUpdate(updateName, { args: [validatedInput] });
|
|
229
|
+
try {
|
|
230
|
+
return updateDef.output.parse(result);
|
|
231
|
+
} catch (error) {
|
|
232
|
+
if (error instanceof zod.ZodError) throw new UpdateValidationError(updateName, "output", error);
|
|
233
|
+
throw error;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
return {
|
|
237
|
+
workflowId: handle.workflowId,
|
|
238
|
+
queries,
|
|
239
|
+
signals,
|
|
240
|
+
updates,
|
|
241
|
+
result: async () => {
|
|
242
|
+
const result = await handle.result();
|
|
243
|
+
try {
|
|
244
|
+
return definition.output.parse(result);
|
|
245
|
+
} catch (error) {
|
|
246
|
+
if (error instanceof zod.ZodError) throw new WorkflowValidationError(handle.workflowId, "output", error);
|
|
247
|
+
throw error;
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
terminate: async (reason) => {
|
|
251
|
+
await handle.terminate(reason);
|
|
252
|
+
},
|
|
253
|
+
cancel: async () => {
|
|
254
|
+
await handle.cancel();
|
|
255
|
+
},
|
|
256
|
+
describe: () => handle.describe(),
|
|
257
|
+
fetchHistory: () => handle.fetchHistory()
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
//#endregion
|
|
263
|
+
exports.QueryValidationError = QueryValidationError;
|
|
264
|
+
exports.SignalValidationError = SignalValidationError;
|
|
265
|
+
exports.TypedClient = TypedClient;
|
|
266
|
+
exports.TypedClientError = TypedClientError;
|
|
267
|
+
exports.UpdateValidationError = UpdateValidationError;
|
|
268
|
+
exports.WorkflowNotFoundError = WorkflowNotFoundError;
|
|
269
|
+
exports.WorkflowValidationError = WorkflowValidationError;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { ClientOptions, WorkflowHandle, WorkflowOptions, WorkflowStartOptions } from "@temporalio/client";
|
|
2
|
+
import { ClientInferInput, ClientInferOutput, ClientInferWorkflowQueries, ClientInferWorkflowSignals, ClientInferWorkflowUpdates, ContractDefinition, WorkflowDefinition } from "@temporal-contract/contract";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
//#region src/client.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Extended options for starting workflows with Temporal-specific features
|
|
9
|
+
* Combines required workflowId with optional Temporal workflow options
|
|
10
|
+
*/
|
|
11
|
+
type TypedWorkflowStartOptions = Pick<WorkflowStartOptions, "workflowId" | "workflowIdReusePolicy" | "workflowExecutionTimeout" | "workflowRunTimeout" | "workflowTaskTimeout" | "retry" | "memo" | "searchAttributes" | "cronSchedule"> & Pick<WorkflowOptions, "workflowId">;
|
|
12
|
+
/**
|
|
13
|
+
* Typed workflow handle with validated results, queries, signals and updates
|
|
14
|
+
*/
|
|
15
|
+
interface TypedWorkflowHandle<TWorkflow extends WorkflowDefinition> {
|
|
16
|
+
workflowId: string;
|
|
17
|
+
/**
|
|
18
|
+
* Type-safe queries based on workflow definition
|
|
19
|
+
*/
|
|
20
|
+
queries: ClientInferWorkflowQueries<TWorkflow>;
|
|
21
|
+
/**
|
|
22
|
+
* Type-safe signals based on workflow definition
|
|
23
|
+
*/
|
|
24
|
+
signals: ClientInferWorkflowSignals<TWorkflow>;
|
|
25
|
+
/**
|
|
26
|
+
* Type-safe updates based on workflow definition
|
|
27
|
+
*/
|
|
28
|
+
updates: ClientInferWorkflowUpdates<TWorkflow>;
|
|
29
|
+
result: () => Promise<ClientInferOutput<TWorkflow>>;
|
|
30
|
+
terminate: (reason?: string) => Promise<void>;
|
|
31
|
+
cancel: () => Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Get workflow execution description including status and metadata
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* const handle = await client.getHandle('processOrder', 'order-123');
|
|
38
|
+
* const description = await handle.describe();
|
|
39
|
+
* console.log(description.workflowExecutionInfo.status); // RUNNING, COMPLETED, etc.
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
describe: () => ReturnType<WorkflowHandle["describe"]>;
|
|
43
|
+
/**
|
|
44
|
+
* Fetch the workflow execution history
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* const handle = await client.getHandle('processOrder', 'order-123');
|
|
49
|
+
* const history = handle.fetchHistory();
|
|
50
|
+
* for await (const event of history) {
|
|
51
|
+
* console.log(event);
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
fetchHistory: () => ReturnType<WorkflowHandle["fetchHistory"]>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Typed Temporal client based on a contract
|
|
59
|
+
*
|
|
60
|
+
* Provides type-safe methods to start and execute workflows
|
|
61
|
+
* defined in the contract.
|
|
62
|
+
*/
|
|
63
|
+
declare class TypedClient<TContract extends ContractDefinition> {
|
|
64
|
+
private readonly contract;
|
|
65
|
+
private readonly client;
|
|
66
|
+
private constructor();
|
|
67
|
+
/**
|
|
68
|
+
* Create a typed Temporal client from a contract
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* const connection = await Connection.connect();
|
|
73
|
+
* const client = TypedClient.create(myContract, {
|
|
74
|
+
* connection,
|
|
75
|
+
* namespace: 'default',
|
|
76
|
+
* });
|
|
77
|
+
*
|
|
78
|
+
* const result = await client.executeWorkflow('processOrder', {
|
|
79
|
+
* workflowId: 'order-123',
|
|
80
|
+
* args: [...],
|
|
81
|
+
* });
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
static create<TContract extends ContractDefinition>(contract: TContract, options: ClientOptions): TypedClient<TContract>;
|
|
85
|
+
/**
|
|
86
|
+
* Start a workflow and return a typed handle
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* const handle = await client.startWorkflow('processOrder', {
|
|
91
|
+
* workflowId: 'order-123',
|
|
92
|
+
* args: ['ORD-123', 'CUST-456', [{ productId: 'PROD-1', quantity: 2 }]],
|
|
93
|
+
* workflowExecutionTimeout: '1 day',
|
|
94
|
+
* retry: { maximumAttempts: 3 },
|
|
95
|
+
* });
|
|
96
|
+
*
|
|
97
|
+
* const result = await handle.result();
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
startWorkflow<TWorkflowName extends keyof TContract["workflows"]>(workflowName: TWorkflowName, {
|
|
101
|
+
args,
|
|
102
|
+
...temporalOptions
|
|
103
|
+
}: TypedWorkflowStartOptions & {
|
|
104
|
+
args: ClientInferInput<TContract["workflows"][TWorkflowName]>;
|
|
105
|
+
}): Promise<TypedWorkflowHandle<TContract["workflows"][TWorkflowName]>>;
|
|
106
|
+
/**
|
|
107
|
+
* Execute a workflow (start and wait for result)
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```ts
|
|
111
|
+
* const result = await client.executeWorkflow('processOrder', {
|
|
112
|
+
* workflowId: 'order-123',
|
|
113
|
+
* args: ['ORD-123', 'CUST-456', [{ productId: 'PROD-1', quantity: 2 }]],
|
|
114
|
+
* workflowExecutionTimeout: '1 day',
|
|
115
|
+
* retry: { maximumAttempts: 3 },
|
|
116
|
+
* });
|
|
117
|
+
*
|
|
118
|
+
* console.log(result.status); // fully typed!
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
executeWorkflow<TWorkflowName extends keyof TContract["workflows"]>(workflowName: TWorkflowName, {
|
|
122
|
+
args,
|
|
123
|
+
...temporalOptions
|
|
124
|
+
}: TypedWorkflowStartOptions & {
|
|
125
|
+
args: ClientInferInput<TContract["workflows"][TWorkflowName]>;
|
|
126
|
+
}): Promise<ClientInferOutput<TContract["workflows"][TWorkflowName]>>;
|
|
127
|
+
/**
|
|
128
|
+
* Get a handle to an existing workflow
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* const handle = await client.getHandle('processOrder', 'order-123');
|
|
133
|
+
* const result = await handle.result();
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
getHandle<TWorkflowName extends keyof TContract["workflows"]>(workflowName: TWorkflowName, workflowId: string): Promise<TypedWorkflowHandle<TContract["workflows"][TWorkflowName]>>;
|
|
137
|
+
private createTypedHandle;
|
|
138
|
+
}
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/errors.d.ts
|
|
141
|
+
/**
|
|
142
|
+
* Base error class for typed client errors
|
|
143
|
+
*/
|
|
144
|
+
declare class TypedClientError extends Error {
|
|
145
|
+
constructor(message: string);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Error thrown when a workflow is not found in the contract
|
|
149
|
+
*/
|
|
150
|
+
declare class WorkflowNotFoundError extends TypedClientError {
|
|
151
|
+
readonly workflowName: string;
|
|
152
|
+
constructor(workflowName: string);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Error thrown when workflow input or output validation fails
|
|
156
|
+
*/
|
|
157
|
+
declare class WorkflowValidationError extends TypedClientError {
|
|
158
|
+
readonly workflowName: string;
|
|
159
|
+
readonly phase: "input" | "output";
|
|
160
|
+
readonly zodError: z.ZodError;
|
|
161
|
+
constructor(workflowName: string, phase: "input" | "output", zodError: z.ZodError);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Error thrown when query input or output validation fails
|
|
165
|
+
*/
|
|
166
|
+
declare class QueryValidationError extends TypedClientError {
|
|
167
|
+
readonly queryName: string;
|
|
168
|
+
readonly phase: "input" | "output";
|
|
169
|
+
readonly zodError: z.ZodError;
|
|
170
|
+
constructor(queryName: string, phase: "input" | "output", zodError: z.ZodError);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Error thrown when signal input validation fails
|
|
174
|
+
*/
|
|
175
|
+
declare class SignalValidationError extends TypedClientError {
|
|
176
|
+
readonly signalName: string;
|
|
177
|
+
readonly zodError: z.ZodError;
|
|
178
|
+
constructor(signalName: string, zodError: z.ZodError);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Error thrown when update input or output validation fails
|
|
182
|
+
*/
|
|
183
|
+
declare class UpdateValidationError extends TypedClientError {
|
|
184
|
+
readonly updateName: string;
|
|
185
|
+
readonly phase: "input" | "output";
|
|
186
|
+
readonly zodError: z.ZodError;
|
|
187
|
+
constructor(updateName: string, phase: "input" | "output", zodError: z.ZodError);
|
|
188
|
+
}
|
|
189
|
+
//#endregion
|
|
190
|
+
export { QueryValidationError, SignalValidationError, TypedClient, TypedClientError, type TypedWorkflowHandle, type TypedWorkflowStartOptions, UpdateValidationError, WorkflowNotFoundError, WorkflowValidationError };
|