@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/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
- };
@@ -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";