@temporal-contract/contract 0.0.1 → 0.0.3
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 +14 -80
- package/dist/index.cjs +18 -10
- package/dist/index.d.cts +23 -22
- package/dist/index.d.mts +23 -22
- package/dist/index.mjs +18 -10
- package/package.json +12 -6
- package/.turbo/turbo-build.log +0 -17
- package/src/builder.spec.ts +0 -625
- package/src/builder.ts +0 -262
- package/src/helpers.spec.ts +0 -122
- package/src/index.ts +0 -55
- package/src/types.spec.ts +0 -637
- package/src/types.ts +0 -420
- package/tsconfig.json +0 -9
package/src/builder.ts
DELETED
|
@@ -1,262 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import type {
|
|
3
|
-
ActivityDefinition,
|
|
4
|
-
ContractDefinition,
|
|
5
|
-
QueryDefinition,
|
|
6
|
-
SignalDefinition,
|
|
7
|
-
UpdateDefinition,
|
|
8
|
-
WorkflowDefinition,
|
|
9
|
-
} from "./types.js";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Schema for validating JavaScript identifiers (workflow names, activity names, etc.)
|
|
13
|
-
* Allows: letters, digits, underscore, dollar sign
|
|
14
|
-
* Must start with: letter, underscore, or dollar sign
|
|
15
|
-
*/
|
|
16
|
-
const identifierSchema = z
|
|
17
|
-
.string()
|
|
18
|
-
.min(1)
|
|
19
|
-
.regex(/^[a-zA-Z_$][a-zA-Z0-9_$]*$/, "must be a valid JavaScript identifier");
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Extract clean error message from Zod validation error
|
|
23
|
-
*/
|
|
24
|
-
const getCleanErrorMessage = (error: z.ZodError): string => {
|
|
25
|
-
try {
|
|
26
|
-
const parsed = JSON.parse(error.message);
|
|
27
|
-
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
28
|
-
const firstError = parsed[0];
|
|
29
|
-
|
|
30
|
-
// For record key validation errors, dive into nested issues
|
|
31
|
-
if (
|
|
32
|
-
firstError?.code === "invalid_key" &&
|
|
33
|
-
firstError?.issues &&
|
|
34
|
-
firstError.issues.length > 0
|
|
35
|
-
) {
|
|
36
|
-
const nestedError = firstError.issues[0];
|
|
37
|
-
if (nestedError?.message) {
|
|
38
|
-
return nestedError.message;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// For direct validation errors
|
|
43
|
-
if (firstError?.message) {
|
|
44
|
-
return firstError.message;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
} catch {
|
|
48
|
-
// If parsing fails, return the raw message
|
|
49
|
-
}
|
|
50
|
-
return error.message;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Schema for validating activity definitions
|
|
55
|
-
* Checks that input and output are Zod schemas
|
|
56
|
-
*/
|
|
57
|
-
const activityDefinitionSchema = z.object({
|
|
58
|
-
input: z.instanceof(z.ZodType, {
|
|
59
|
-
message: "input must be a Zod schema",
|
|
60
|
-
}),
|
|
61
|
-
output: z.instanceof(z.ZodType, {
|
|
62
|
-
message: "output must be a Zod schema",
|
|
63
|
-
}),
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Schema for validating signal definitions
|
|
68
|
-
*/
|
|
69
|
-
const signalDefinitionSchema = z.object({
|
|
70
|
-
input: z.instanceof(z.ZodType, {
|
|
71
|
-
message: "input must be a Zod schema",
|
|
72
|
-
}),
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Schema for validating query definitions
|
|
77
|
-
*/
|
|
78
|
-
const queryDefinitionSchema = z.object({
|
|
79
|
-
input: z.instanceof(z.ZodType, {
|
|
80
|
-
message: "input must be a Zod schema",
|
|
81
|
-
}),
|
|
82
|
-
output: z.instanceof(z.ZodType, {
|
|
83
|
-
message: "output must be a Zod schema",
|
|
84
|
-
}),
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Schema for validating update definitions
|
|
89
|
-
*/
|
|
90
|
-
const updateDefinitionSchema = z.object({
|
|
91
|
-
input: z.instanceof(z.ZodType, {
|
|
92
|
-
message: "input must be a Zod schema",
|
|
93
|
-
}),
|
|
94
|
-
output: z.instanceof(z.ZodType, {
|
|
95
|
-
message: "output must be a Zod schema",
|
|
96
|
-
}),
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Schema for validating workflow definitions
|
|
101
|
-
*/
|
|
102
|
-
const workflowDefinitionSchema = z.object({
|
|
103
|
-
input: z.instanceof(z.ZodType, {
|
|
104
|
-
message: "input must be a Zod schema",
|
|
105
|
-
}),
|
|
106
|
-
output: z.instanceof(z.ZodType, {
|
|
107
|
-
message: "output must be a Zod schema",
|
|
108
|
-
}),
|
|
109
|
-
activities: z.record(identifierSchema, activityDefinitionSchema).optional(),
|
|
110
|
-
signals: z.record(identifierSchema, signalDefinitionSchema).optional(),
|
|
111
|
-
queries: z.record(identifierSchema, queryDefinitionSchema).optional(),
|
|
112
|
-
updates: z.record(identifierSchema, updateDefinitionSchema).optional(),
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Schema for validating a contract definition structure
|
|
117
|
-
*/
|
|
118
|
-
const contractValidationSchema = z
|
|
119
|
-
.object({
|
|
120
|
-
taskQueue: z.string().trim().min(1, "taskQueue cannot be empty"),
|
|
121
|
-
workflows: z
|
|
122
|
-
.record(identifierSchema, workflowDefinitionSchema)
|
|
123
|
-
.refine((workflows) => Object.keys(workflows).length > 0, {
|
|
124
|
-
message: "at least one workflow is required",
|
|
125
|
-
}),
|
|
126
|
-
activities: z.record(identifierSchema, activityDefinitionSchema).optional(),
|
|
127
|
-
})
|
|
128
|
-
.superRefine((contract, ctx) => {
|
|
129
|
-
// Check for conflicts between global and workflow-specific activities
|
|
130
|
-
if (!contract.activities) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
for (const [workflowName, workflow] of Object.entries(contract.workflows)) {
|
|
135
|
-
if (workflow.activities) {
|
|
136
|
-
for (const activityName of Object.keys(workflow.activities)) {
|
|
137
|
-
if (activityName in contract.activities) {
|
|
138
|
-
ctx.addIssue({
|
|
139
|
-
code: z.ZodIssueCode.custom,
|
|
140
|
-
message: `workflow "${workflowName}" has activity "${activityName}" that conflicts with a global activity. Consider renaming the workflow-specific activity or removing the global activity "${activityName}".`,
|
|
141
|
-
});
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Builder for creating activity definitions
|
|
151
|
-
*
|
|
152
|
-
* @example
|
|
153
|
-
* ```ts
|
|
154
|
-
* const myActivity = defineActivity({
|
|
155
|
-
* input: z.tuple([z.object({ name: z.string() })]),
|
|
156
|
-
* output: z.object({ greeting: z.string() }),
|
|
157
|
-
* });
|
|
158
|
-
* ```
|
|
159
|
-
*/
|
|
160
|
-
export const defineActivity = <TActivity extends ActivityDefinition>(
|
|
161
|
-
definition: TActivity,
|
|
162
|
-
): TActivity => {
|
|
163
|
-
return definition;
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Builder for creating signal definitions
|
|
168
|
-
*
|
|
169
|
-
* @example
|
|
170
|
-
* ```ts
|
|
171
|
-
* const mySignal = defineSignal({
|
|
172
|
-
* input: z.object({ message: z.string() }),
|
|
173
|
-
* });
|
|
174
|
-
* ```
|
|
175
|
-
*/
|
|
176
|
-
export const defineSignal = <TSignal extends SignalDefinition>(definition: TSignal): TSignal => {
|
|
177
|
-
return definition;
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Builder for creating query definitions
|
|
182
|
-
*
|
|
183
|
-
* @example
|
|
184
|
-
* ```ts
|
|
185
|
-
* const myQuery = defineQuery({
|
|
186
|
-
* input: z.object({ id: z.string() }),
|
|
187
|
-
* output: z.object({ status: z.string() }),
|
|
188
|
-
* });
|
|
189
|
-
* ```
|
|
190
|
-
*/
|
|
191
|
-
export const defineQuery = <TQuery extends QueryDefinition>(definition: TQuery): TQuery => {
|
|
192
|
-
return definition;
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Builder for creating update definitions
|
|
197
|
-
*
|
|
198
|
-
* @example
|
|
199
|
-
* ```ts
|
|
200
|
-
* const myUpdate = defineUpdate({
|
|
201
|
-
* input: z.object({ value: z.number() }),
|
|
202
|
-
* output: z.object({ newValue: z.number() }),
|
|
203
|
-
* });
|
|
204
|
-
* ```
|
|
205
|
-
*/
|
|
206
|
-
export const defineUpdate = <TUpdate extends UpdateDefinition>(definition: TUpdate): TUpdate => {
|
|
207
|
-
return definition;
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Builder for creating workflow definitions
|
|
212
|
-
*
|
|
213
|
-
* @example
|
|
214
|
-
* ```ts
|
|
215
|
-
* const myWorkflow = defineWorkflow({
|
|
216
|
-
* input: z.tuple([z.object({ orderId: z.string() })]),
|
|
217
|
-
* output: z.object({ status: z.string() }),
|
|
218
|
-
* activities: {
|
|
219
|
-
* processPayment: defineActivity({
|
|
220
|
-
* input: z.tuple([z.object({ amount: z.number() })]),
|
|
221
|
-
* output: z.object({ success: z.boolean() }),
|
|
222
|
-
* }),
|
|
223
|
-
* },
|
|
224
|
-
* });
|
|
225
|
-
* ```
|
|
226
|
-
*/
|
|
227
|
-
export const defineWorkflow = <TWorkflow extends WorkflowDefinition>(
|
|
228
|
-
definition: TWorkflow,
|
|
229
|
-
): TWorkflow => {
|
|
230
|
-
return definition;
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Builder for creating a complete contract
|
|
235
|
-
*
|
|
236
|
-
* @example
|
|
237
|
-
* ```ts
|
|
238
|
-
* const myContract = defineContract({
|
|
239
|
-
* taskQueue: 'my-service',
|
|
240
|
-
* workflows: {
|
|
241
|
-
* processOrder: defineWorkflow({ ... }),
|
|
242
|
-
* sendNotification: defineWorkflow({ ... }),
|
|
243
|
-
* },
|
|
244
|
-
* activities: {
|
|
245
|
-
* sendEmail: defineActivity({ ... }),
|
|
246
|
-
* },
|
|
247
|
-
* });
|
|
248
|
-
* ```
|
|
249
|
-
*/
|
|
250
|
-
export const defineContract = <TContract extends ContractDefinition>(
|
|
251
|
-
definition: TContract,
|
|
252
|
-
): TContract => {
|
|
253
|
-
// Validate entire contract structure with Zod (including activity conflicts)
|
|
254
|
-
const validationResult = contractValidationSchema.safeParse(definition);
|
|
255
|
-
|
|
256
|
-
if (!validationResult.success) {
|
|
257
|
-
const cleanMessage = getCleanErrorMessage(validationResult.error);
|
|
258
|
-
throw new Error(`Contract error: ${cleanMessage}`);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
return definition;
|
|
262
|
-
};
|
package/src/helpers.spec.ts
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
defineActivity,
|
|
4
|
-
defineQuery,
|
|
5
|
-
defineSignal,
|
|
6
|
-
defineUpdate,
|
|
7
|
-
defineWorkflow,
|
|
8
|
-
} from "./builder.js";
|
|
9
|
-
import { z } from "zod";
|
|
10
|
-
|
|
11
|
-
describe("Helper Functions", () => {
|
|
12
|
-
describe("defineActivity", () => {
|
|
13
|
-
it("should create an activity definition", () => {
|
|
14
|
-
const activity = defineActivity({
|
|
15
|
-
input: z.object({ value: z.string() }),
|
|
16
|
-
output: z.object({ result: z.string() }),
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
expect(activity.input).toBeDefined();
|
|
20
|
-
expect(activity.output).toBeDefined();
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
describe("defineSignal", () => {
|
|
25
|
-
it("should create a signal definition", () => {
|
|
26
|
-
const signal = defineSignal({
|
|
27
|
-
input: z.object({ message: z.string() }),
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
expect(signal.input).toBeDefined();
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("should work with primitive types", () => {
|
|
34
|
-
const signal = defineSignal({
|
|
35
|
-
input: z.string(),
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
expect(signal.input).toBeDefined();
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
describe("defineQuery", () => {
|
|
43
|
-
it("should create a query definition", () => {
|
|
44
|
-
const query = defineQuery({
|
|
45
|
-
input: z.object({ id: z.string() }),
|
|
46
|
-
output: z.object({ status: z.string() }),
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
expect(query.input).toBeDefined();
|
|
50
|
-
expect(query.output).toBeDefined();
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("should work with void input", () => {
|
|
54
|
-
const query = defineQuery({
|
|
55
|
-
input: z.void(),
|
|
56
|
-
output: z.object({ count: z.number() }),
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
expect(query.input).toBeDefined();
|
|
60
|
-
expect(query.output).toBeDefined();
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
describe("defineUpdate", () => {
|
|
65
|
-
it("should create an update definition", () => {
|
|
66
|
-
const update = defineUpdate({
|
|
67
|
-
input: z.object({ value: z.number() }),
|
|
68
|
-
output: z.object({ newValue: z.number() }),
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
expect(update.input).toBeDefined();
|
|
72
|
-
expect(update.output).toBeDefined();
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
describe("defineWorkflow", () => {
|
|
77
|
-
it("should create a workflow definition", () => {
|
|
78
|
-
const workflow = defineWorkflow({
|
|
79
|
-
input: z.object({ orderId: z.string() }),
|
|
80
|
-
output: z.object({ status: z.string() }),
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
expect(workflow.input).toBeDefined();
|
|
84
|
-
expect(workflow.output).toBeDefined();
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it("should support all interaction types", () => {
|
|
88
|
-
const workflow = defineWorkflow({
|
|
89
|
-
input: z.object({ orderId: z.string() }),
|
|
90
|
-
output: z.object({ status: z.string() }),
|
|
91
|
-
activities: {
|
|
92
|
-
processPayment: {
|
|
93
|
-
input: z.object({ amount: z.number() }),
|
|
94
|
-
output: z.object({ success: z.boolean() }),
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
signals: {
|
|
98
|
-
cancelOrder: {
|
|
99
|
-
input: z.object({ reason: z.string() }),
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
queries: {
|
|
103
|
-
getStatus: {
|
|
104
|
-
input: z.void(),
|
|
105
|
-
output: z.object({ status: z.string() }),
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
updates: {
|
|
109
|
-
updateAmount: {
|
|
110
|
-
input: z.object({ newAmount: z.number() }),
|
|
111
|
-
output: z.object({ updated: z.boolean() }),
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
expect(workflow.activities).toBeDefined();
|
|
117
|
-
expect(workflow.signals).toBeDefined();
|
|
118
|
-
expect(workflow.queries).toBeDefined();
|
|
119
|
-
expect(workflow.updates).toBeDefined();
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
});
|
package/src/index.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
export {
|
|
2
|
-
defineActivity,
|
|
3
|
-
defineContract,
|
|
4
|
-
defineQuery,
|
|
5
|
-
defineSignal,
|
|
6
|
-
defineUpdate,
|
|
7
|
-
defineWorkflow,
|
|
8
|
-
} from "./builder.js";
|
|
9
|
-
|
|
10
|
-
export type {
|
|
11
|
-
AnyZodSchema,
|
|
12
|
-
ActivityDefinition,
|
|
13
|
-
SignalDefinition,
|
|
14
|
-
QueryDefinition,
|
|
15
|
-
UpdateDefinition,
|
|
16
|
-
WorkflowDefinition,
|
|
17
|
-
ContractDefinition,
|
|
18
|
-
// Worker perspective types
|
|
19
|
-
WorkerInferInput,
|
|
20
|
-
WorkerInferOutput,
|
|
21
|
-
WorkerInferWorkflow,
|
|
22
|
-
WorkerInferActivity,
|
|
23
|
-
WorkerInferSignal,
|
|
24
|
-
WorkerInferQuery,
|
|
25
|
-
WorkerInferUpdate,
|
|
26
|
-
WorkerInferWorkflows,
|
|
27
|
-
WorkerInferActivities,
|
|
28
|
-
WorkerInferWorkflowActivities,
|
|
29
|
-
WorkerInferWorkflowSignals,
|
|
30
|
-
WorkerInferWorkflowQueries,
|
|
31
|
-
WorkerInferWorkflowUpdates,
|
|
32
|
-
WorkerInferWorkflowContextActivities,
|
|
33
|
-
// Client perspective types
|
|
34
|
-
ClientInferInput,
|
|
35
|
-
ClientInferOutput,
|
|
36
|
-
ClientInferWorkflow,
|
|
37
|
-
ClientInferActivity,
|
|
38
|
-
ClientInferSignal,
|
|
39
|
-
ClientInferQuery,
|
|
40
|
-
ClientInferUpdate,
|
|
41
|
-
ClientInferWorkflows,
|
|
42
|
-
ClientInferActivities,
|
|
43
|
-
ClientInferWorkflowActivities,
|
|
44
|
-
ClientInferWorkflowSignals,
|
|
45
|
-
ClientInferWorkflowQueries,
|
|
46
|
-
ClientInferWorkflowUpdates,
|
|
47
|
-
ClientInferWorkflowContextActivities,
|
|
48
|
-
// Activity handler utility types
|
|
49
|
-
ActivityHandler,
|
|
50
|
-
WorkflowActivityHandler,
|
|
51
|
-
// Contract utility types
|
|
52
|
-
InferWorkflowNames,
|
|
53
|
-
InferActivityNames,
|
|
54
|
-
InferContractWorkflows,
|
|
55
|
-
} from "./types.js";
|