Skip to content

Commit 48e4e2f

Browse files
committed
refactor: remove core
1 parent 4b1302a commit 48e4e2f

36 files changed

Lines changed: 1335 additions & 382 deletions

‎README.md‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66

77
## Packages
88

9-
- **`@temporal-contract/core`** - Core types and utilities
10-
- **`@temporal-contract/contract`** - Contract builder for defining workflows and activities
9+
- **`@temporal-contract/contract`** - Contract builder and type definitions for workflows and activities
1110
- **`@temporal-contract/worker`** - Type-safe worker implementation with automatic validation
11+
- **`@temporal-contract/worker-boxed`** - Worker with Result/Future pattern for explicit error handling
1212
- **`@temporal-contract/client`** - Type-safe client for consuming workflows
1313

1414
## Features
@@ -353,12 +353,13 @@ pnpm lint
353353
```
354354
temporal-contract/
355355
├── packages/
356-
│ ├── core/ # Core types
357-
│ ├── contract/ # Contract builder
356+
│ ├── contract/ # Contract builder and type definitions
358357
│ ├── worker/ # Worker implementation (handler)
358+
│ ├── worker-boxed/ # Worker with Result/Future pattern
359359
│ └── client/ # Typed client
360360
├── samples/ # Sample applications
361-
│ └── basic-order-processing/ # Order processing example
361+
│ ├── basic-order-processing/ # Standard Promise-based example
362+
│ └── boxed-order-processing/ # Result/Future pattern example
362363
├── docs/ # Documentation
363364
├── .github/
364365
│ └── workflows/ # CI/CD

‎docs/ACTIVITY_HANDLERS.md‎

Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
# Activity Handler Utility Types
2+
3+
Cette documentation décrit les types utilitaires disponibles pour simplifier le typage des handlers d'activités.
4+
5+
## Vue d'ensemble
6+
7+
Au lieu de typer explicitement les paramètres et retours avec `WorkerInferInput` et `WorkerInferOutput`, vous pouvez utiliser des types utilitaires qui encapsulent toute la signature de la fonction.
8+
9+
## Types disponibles
10+
11+
### Pour les activités standards
12+
13+
#### `ActivityHandler<TContract, TActivityName>`
14+
15+
Type utilitaire pour typer un handler d'**activité globale** définie au niveau du contrat.
16+
17+
**Exemple :**
18+
19+
```typescript
20+
import type { ActivityHandler } from "@temporal-contract/contract";
21+
import { myContract } from "./contract.js";
22+
23+
// ✅ Avec le type utilitaire
24+
const log: ActivityHandler<typeof myContract, "log"> = async ({ level, message }) => {
25+
logger[level](message);
26+
};
27+
28+
// ❌ Sans le type utilitaire (verbeux)
29+
const log = async ({
30+
level,
31+
message
32+
}: WorkerInferInput<typeof myContract.activities.log>): Promise<WorkerInferOutput<typeof myContract.activities.log>> => {
33+
logger[level](message);
34+
};
35+
```
36+
37+
#### `WorkflowActivityHandler<TContract, TWorkflowName, TActivityName>`
38+
39+
Type utilitaire pour typer un handler d'**activité spécifique à un workflow**.
40+
41+
**Exemple :**
42+
43+
```typescript
44+
import type { WorkflowActivityHandler } from "@temporal-contract/contract";
45+
import { myContract } from "./contract.js";
46+
47+
// ✅ Avec le type utilitaire
48+
const processPayment: WorkflowActivityHandler<
49+
typeof myContract,
50+
"processOrder",
51+
"processPayment"
52+
> = async ({ customerId, amount }) => {
53+
// TypeScript infère automatiquement les types de customerId et amount
54+
return {
55+
transactionId: "txn123",
56+
status: "success" as const,
57+
paidAmount: amount,
58+
};
59+
};
60+
61+
// ❌ Sans le type utilitaire (très verbeux)
62+
const processPayment = async ({
63+
customerId,
64+
amount,
65+
}: WorkerInferInput<typeof myContract.workflows.processOrder.activities.processPayment>): Promise<WorkerInferOutput<typeof myContract.workflows.processOrder.activities.processPayment>> => {
66+
// ...
67+
};
68+
```
69+
70+
### Pour les activités avec pattern Result/Future (@swan-io/boxed)
71+
72+
#### `BoxedActivityHandler<TContract, TActivityName>`
73+
74+
Type utilitaire pour typer un handler d'**activité globale** utilisant le pattern Result/Future.
75+
76+
**Exemple :**
77+
78+
```typescript
79+
import { Future, Result } from "@swan-io/boxed";
80+
import type { BoxedActivityHandler } from "@temporal-contract/worker-boxed";
81+
import { myContract } from "./contract.js";
82+
83+
const log: BoxedActivityHandler<typeof myContract, "log"> = ({
84+
level,
85+
message,
86+
}: {
87+
level: string;
88+
message: string;
89+
}) => {
90+
return Future.make((resolve) => {
91+
logger[level](message);
92+
resolve(Result.Ok(undefined));
93+
});
94+
};
95+
```
96+
97+
**Note :** Pour les activités boxed, vous devez toujours annoter explicitement les paramètres car TypeScript n'infère pas les paramètres des fonctions de rappel.
98+
99+
#### `BoxedWorkflowActivityHandler<TContract, TWorkflowName, TActivityName>`
100+
101+
Type utilitaire pour typer un handler d'**activité spécifique à un workflow** utilisant le pattern Result/Future.
102+
103+
**Exemple :**
104+
105+
```typescript
106+
import { Future, Result } from "@swan-io/boxed";
107+
import type { BoxedWorkflowActivityHandler } from "@temporal-contract/worker-boxed";
108+
import { myContract } from "./contract.js";
109+
110+
const processPayment: BoxedWorkflowActivityHandler<
111+
typeof myContract,
112+
"processOrder",
113+
"processPayment"
114+
> = ({ customerId, amount }: { customerId: string; amount: number }) => {
115+
return Future.make((resolve) => {
116+
// Simulate payment processing
117+
const transactionId = `txn-${Date.now()}`;
118+
119+
resolve(
120+
Result.Ok({
121+
transactionId,
122+
status: "success" as const,
123+
paidAmount: amount,
124+
})
125+
);
126+
});
127+
};
128+
```
129+
130+
## Avantages
131+
132+
✅ **Code plus concis** : Moins de verbosité, plus lisible
133+
134+
✅ **Maintenabilité** : Le type de retour est automatiquement déduit du contrat
135+
136+
✅ **Type safety** : TypeScript vérifie que la signature correspond au contrat
137+
138+
✅ **DX améliorée** : Autocomplétion et IntelliSense fonctionnent parfaitement
139+
140+
## Exemples complets
141+
142+
### Activités standards (basic-order-processing)
143+
144+
```typescript
145+
import { declareActivitiesHandler } from "@temporal-contract/worker";
146+
import type { ActivityHandler, WorkflowActivityHandler } from "@temporal-contract/contract";
147+
import { orderProcessingContract } from "../contract.js";
148+
149+
// Activité globale
150+
const log: ActivityHandler<typeof orderProcessingContract, "log"> = async ({ level, message }) => {
151+
logger[level](message);
152+
};
153+
154+
const sendNotification: ActivityHandler<
155+
typeof orderProcessingContract,
156+
"sendNotification"
157+
> = async ({ customerId, subject, message }) => {
158+
logger.info({ customerId, subject }, `Sending notification to ${customerId}`);
159+
// ...
160+
};
161+
162+
// Activités du workflow
163+
const processPayment: WorkflowActivityHandler<
164+
typeof orderProcessingContract,
165+
"processOrder",
166+
"processPayment"
167+
> = async ({ customerId, amount }) => {
168+
return {
169+
transactionId: `TXN${Date.now()}`,
170+
status: "success" as const,
171+
paidAmount: amount,
172+
};
173+
};
174+
175+
const reserveInventory: WorkflowActivityHandler<
176+
typeof orderProcessingContract,
177+
"processOrder",
178+
"reserveInventory"
179+
> = async (items) => {
180+
return {
181+
reserved: true,
182+
reservationId: `RES${Date.now()}`,
183+
};
184+
};
185+
186+
export const activitiesHandler = declareActivitiesHandler({
187+
contract: orderProcessingContract,
188+
activities: {
189+
log,
190+
sendNotification,
191+
processPayment,
192+
reserveInventory,
193+
},
194+
});
195+
```
196+
197+
### Activités avec Result/Future (boxed-order-processing)
198+
199+
```typescript
200+
import { Future, Result } from "@swan-io/boxed";
201+
import type {
202+
BoxedActivityHandler,
203+
BoxedWorkflowActivityHandler,
204+
} from "@temporal-contract/worker-boxed";
205+
import { boxedOrderContract } from "../contract.js";
206+
207+
// Activité globale
208+
const log: BoxedActivityHandler<typeof boxedOrderContract, "log"> = ({
209+
level,
210+
message,
211+
}: {
212+
level: string;
213+
message: string;
214+
}) => {
215+
return Future.make((resolve) => {
216+
logger[level](message);
217+
resolve(Result.Ok(undefined));
218+
});
219+
};
220+
221+
// Activité du workflow
222+
const processPayment: BoxedWorkflowActivityHandler<
223+
typeof boxedOrderContract,
224+
"processOrder",
225+
"processPayment"
226+
> = ({ customerId, amount }: { customerId: string; amount: number }) => {
227+
return Future.make((resolve) => {
228+
const success = Math.random() > 0.1;
229+
230+
if (success) {
231+
resolve(
232+
Result.Ok({
233+
transactionId: `txn-${Date.now()}`,
234+
status: "success" as const,
235+
paidAmount: amount,
236+
})
237+
);
238+
} else {
239+
resolve(
240+
Result.Error({
241+
code: "PAYMENT_FAILED",
242+
message: "Payment declined",
243+
details: { customerId, amount },
244+
})
245+
);
246+
}
247+
});
248+
};
249+
```
250+
251+
## Cas particuliers
252+
253+
### Activités avec des paramètres scalaires
254+
255+
Pour les activités dont l'input est un type scalaire (string, number, etc.) et non un objet :
256+
257+
```typescript
258+
const releaseInventory: WorkflowActivityHandler<
259+
typeof myContract,
260+
"processOrder",
261+
"releaseInventory"
262+
> = async (reservationId) => {
263+
// reservationId est typé automatiquement comme string
264+
logger.info({ reservationId }, `Releasing inventory`);
265+
};
266+
```
267+
268+
### Activités retournant void
269+
270+
```typescript
271+
const releaseInventory: WorkflowActivityHandler<
272+
typeof myContract,
273+
"processOrder",
274+
"releaseInventory"
275+
> = async (reservationId) => {
276+
logger.info({ reservationId }, `Releasing inventory`);
277+
// Pas besoin de return, le type de retour est automatiquement Promise<void>
278+
};
279+
```
280+
281+
## Tests
282+
283+
Des tests complets sont disponibles dans `/packages/contract/src/types.spec.ts` démontrant l'utilisation de ces types :
284+
285+
```typescript
286+
describe("Activity Handler Utility Types", () => {
287+
it("should correctly type a global activity handler", async () => {
288+
const contract = {
289+
taskQueue: "test",
290+
activities: {
291+
log: {
292+
input: z.object({ level: z.string(), message: z.string() }),
293+
output: z.void(),
294+
},
295+
},
296+
workflows: {},
297+
} satisfies ContractDefinition;
298+
299+
const log: ActivityHandler<typeof contract, "log"> = async ({ level, message }) => {
300+
expect(level).toBe("info");
301+
expect(message).toBe("test");
302+
};
303+
304+
await log({ level: "info", message: "test" });
305+
});
306+
307+
it("should correctly type a workflow-specific activity handler", async () => {
308+
// Voir types.spec.ts pour l'exemple complet
309+
});
310+
});
311+
```
312+
313+
## Références
314+
315+
- [Types contract](/packages/contract/src/types.ts)
316+
- [Tests types](/packages/contract/src/types.spec.ts)
317+
- [Exemple basic-order-processing](/samples/basic-order-processing/src/activities/index.ts)
318+
- [Exemple boxed-order-processing](/samples/boxed-order-processing/src/activities/index.ts)

‎docs/CATALOG.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ catalog:
3434
"@temporalio/worker": 1.13.2
3535
"@temporalio/workflow": 1.13.2
3636

37+
# Logging
38+
pino: 10.1.0
39+
pino-pretty: 13.1.3
40+
3741
# Build tools
3842
tsdown: 0.17.0
3943

‎packages/client/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"typecheck": "tsc --noEmit"
4242
},
4343
"dependencies": {
44-
"@temporal-contract/core": "workspace:*"
44+
"@temporal-contract/contract": "workspace:*"
4545
},
4646
"devDependencies": {
4747
"@temporalio/client": "catalog:",

‎packages/client/src/client.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type {
1111
QueryDefinition,
1212
SignalDefinition,
1313
UpdateDefinition,
14-
} from "@temporal-contract/core";
14+
} from "@temporal-contract/contract";
1515

1616
/**
1717
* Typed workflow handle with validated results, queries, signals and updates

0 commit comments

Comments
 (0)