nestjs-temporal-core 2.0.8 → 3.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.
Files changed (101) hide show
  1. package/README.md +114 -563
  2. package/dist/client/temporal-client.module.d.ts +4 -2
  3. package/dist/client/temporal-client.module.js +59 -78
  4. package/dist/client/temporal-client.module.js.map +1 -1
  5. package/dist/client/temporal-client.service.d.ts +4 -3
  6. package/dist/client/temporal-client.service.js +43 -27
  7. package/dist/client/temporal-client.service.js.map +1 -1
  8. package/dist/client/temporal-schedule.service.d.ts +8 -2
  9. package/dist/client/temporal-schedule.service.js +86 -65
  10. package/dist/client/temporal-schedule.service.js.map +1 -1
  11. package/dist/constants.d.ts +171 -32
  12. package/dist/constants.js +164 -19
  13. package/dist/constants.js.map +1 -1
  14. package/dist/decorators/communication.decorators.d.ts +5 -0
  15. package/dist/decorators/communication.decorators.js +66 -0
  16. package/dist/decorators/communication.decorators.js.map +1 -0
  17. package/dist/decorators/core.decorators.d.ts +6 -0
  18. package/dist/decorators/core.decorators.js +87 -0
  19. package/dist/decorators/core.decorators.js.map +1 -0
  20. package/dist/decorators/index.d.ts +5 -6
  21. package/dist/decorators/index.js +5 -6
  22. package/dist/decorators/index.js.map +1 -1
  23. package/dist/decorators/parameter.decorators.d.ts +2 -0
  24. package/dist/decorators/parameter.decorators.js +29 -0
  25. package/dist/decorators/parameter.decorators.js.map +1 -0
  26. package/dist/decorators/scheduling.decorators.d.ts +4 -0
  27. package/dist/decorators/scheduling.decorators.js +37 -0
  28. package/dist/decorators/scheduling.decorators.js.map +1 -0
  29. package/dist/decorators/workflow-starter.decorator.d.ts +2 -0
  30. package/dist/decorators/workflow-starter.decorator.js +14 -0
  31. package/dist/decorators/workflow-starter.decorator.js.map +1 -0
  32. package/dist/discovery/index.d.ts +2 -0
  33. package/dist/discovery/index.js +19 -0
  34. package/dist/discovery/index.js.map +1 -0
  35. package/dist/discovery/schedule-manager.service.d.ts +36 -0
  36. package/dist/discovery/schedule-manager.service.js +215 -0
  37. package/dist/discovery/schedule-manager.service.js.map +1 -0
  38. package/dist/discovery/workflow-discovery.service.d.ts +36 -0
  39. package/dist/discovery/workflow-discovery.service.js +216 -0
  40. package/dist/discovery/workflow-discovery.service.js.map +1 -0
  41. package/dist/index.d.ts +15 -8
  42. package/dist/index.js +27 -11
  43. package/dist/index.js.map +1 -1
  44. package/dist/interfaces/core.interface.d.ts +112 -0
  45. package/dist/interfaces/{base.interface.js → core.interface.js} +1 -1
  46. package/dist/interfaces/core.interface.js.map +1 -0
  47. package/dist/interfaces/discovery.interface.d.ts +61 -0
  48. package/dist/interfaces/{client.interface.js → discovery.interface.js} +1 -1
  49. package/dist/interfaces/discovery.interface.js.map +1 -0
  50. package/dist/interfaces/index.d.ts +4 -4
  51. package/dist/interfaces/index.js +4 -4
  52. package/dist/interfaces/index.js.map +1 -1
  53. package/dist/interfaces/scheduling.interface.d.ts +17 -0
  54. package/dist/interfaces/{temporal.interface.js → scheduling.interface.js} +1 -1
  55. package/dist/interfaces/scheduling.interface.js.map +1 -0
  56. package/dist/interfaces/worker.interface.d.ts +20 -17
  57. package/dist/interfaces/workflow.interface.d.ts +41 -1
  58. package/dist/temporal.module.d.ts +17 -1
  59. package/dist/temporal.module.js +120 -53
  60. package/dist/temporal.module.js.map +1 -1
  61. package/dist/temporal.service.d.ts +50 -8
  62. package/dist/temporal.service.js +166 -18
  63. package/dist/temporal.service.js.map +1 -1
  64. package/dist/tsconfig.tsbuildinfo +1 -1
  65. package/dist/worker/index.d.ts +1 -1
  66. package/dist/worker/index.js +1 -1
  67. package/dist/worker/index.js.map +1 -1
  68. package/dist/worker/temporal-metadata.accessor.d.ts +21 -6
  69. package/dist/worker/temporal-metadata.accessor.js +153 -22
  70. package/dist/worker/temporal-metadata.accessor.js.map +1 -1
  71. package/dist/worker/temporal-worker.module.d.ts +1 -1
  72. package/dist/worker/temporal-worker.module.js +6 -7
  73. package/dist/worker/temporal-worker.module.js.map +1 -1
  74. package/dist/worker/worker-manager.service.d.ts +24 -7
  75. package/dist/worker/worker-manager.service.js +218 -85
  76. package/dist/worker/worker-manager.service.js.map +1 -1
  77. package/package.json +50 -18
  78. package/dist/decorators/activity-method.decorator.d.ts +0 -2
  79. package/dist/decorators/activity-method.decorator.js +0 -35
  80. package/dist/decorators/activity-method.decorator.js.map +0 -1
  81. package/dist/decorators/activity.decorator.d.ts +0 -2
  82. package/dist/decorators/activity.decorator.js +0 -14
  83. package/dist/decorators/activity.decorator.js.map +0 -1
  84. package/dist/decorators/query-method.decorator.d.ts +0 -1
  85. package/dist/decorators/query-method.decorator.js +0 -17
  86. package/dist/decorators/query-method.decorator.js.map +0 -1
  87. package/dist/decorators/signal-method.decorator.d.ts +0 -1
  88. package/dist/decorators/signal-method.decorator.js +0 -17
  89. package/dist/decorators/signal-method.decorator.js.map +0 -1
  90. package/dist/decorators/workflow-method.decorator.d.ts +0 -2
  91. package/dist/decorators/workflow-method.decorator.js +0 -26
  92. package/dist/decorators/workflow-method.decorator.js.map +0 -1
  93. package/dist/decorators/workflow.decorator.d.ts +0 -2
  94. package/dist/decorators/workflow.decorator.js +0 -16
  95. package/dist/decorators/workflow.decorator.js.map +0 -1
  96. package/dist/interfaces/base.interface.d.ts +0 -13
  97. package/dist/interfaces/base.interface.js.map +0 -1
  98. package/dist/interfaces/client.interface.d.ts +0 -30
  99. package/dist/interfaces/client.interface.js.map +0 -1
  100. package/dist/interfaces/temporal.interface.d.ts +0 -33
  101. package/dist/interfaces/temporal.interface.js.map +0 -1
package/README.md CHANGED
@@ -1,49 +1,50 @@
1
1
  # NestJS Temporal Core
2
2
 
3
- A simplified NestJS integration for [Temporal.io](https://temporal.io/) that provides seamless worker and client support for building reliable distributed applications.
3
+ A comprehensive NestJS integration for [Temporal.io](https://temporal.io/) that provides seamless worker and client support with auto-discovery, declarative scheduling, and enterprise-ready features for building reliable distributed applications.
4
+
5
+ [![npm version](https://badge.fury.io/js/nestjs-temporal-core.svg)](https://badge.fury.io/js/nestjs-temporal-core)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/)
8
+
9
+ ## 📚 Documentation
10
+
11
+ ### Quick Links
12
+ - **[🚀 Getting Started](./docs/getting-started.md)** - Installation, basic setup, and first workflow
13
+ - **[⚙️ Configuration](./docs/configuration.md)** - Complete configuration reference and examples
14
+ - **[📖 API Reference](./docs/api-reference.md)** - Detailed API documentation for all services and decorators
15
+ - **[🍳 Examples & Recipes](./docs/examples.md)** - Practical examples and common patterns
4
16
 
5
17
  ## Overview
6
18
 
7
- NestJS Temporal Core makes it easy to integrate Temporal.io with your NestJS applications. Temporal is a durable execution system for reliable microservices and workflow orchestration.
19
+ NestJS Temporal Core makes it easy to integrate Temporal.io with your NestJS applications using familiar decorator patterns. Temporal is a durable execution system for reliable microservices and workflow orchestration.
8
20
 
9
- ## Features
21
+ ## Features
10
22
 
11
23
  - 🚀 **Easy NestJS Integration** - Simple module registration with unified configuration
24
+ - 🎯 **Auto-Discovery** - Automatic discovery of workflow controllers and scheduled workflows
12
25
  - 🔄 **Complete Lifecycle Management** - Automatic worker initialization and graceful shutdown
13
- - 🎯 **Declarative Decorators** - Type-safe `@Activity()`, `@ActivityMethod()`, `@Workflow()`, and more
14
- - 🔌 **Connection Management** - Simplified connection handling with TLS support
26
+ - 📋 **Declarative Decorators** - NestJS-style `@WorkflowController`, `@Cron`, `@Interval`, and more
27
+ - 🕐 **Smart Scheduling** - Built-in cron and interval-based workflow scheduling with management
28
+ - 🔌 **Connection Management** - Simplified connection handling with TLS and Temporal Cloud support
15
29
  - 🔒 **Type Safety** - Clean, strongly typed interfaces for all Temporal concepts
16
- - 📡 **Client Utilities** - Methods for starting, signaling, and querying workflows
17
- - 📊 **Worker Management** - Simple worker lifecycle control and monitoring
18
- - 📅 **Scheduling** - Support for cron and interval-based workflow scheduling
30
+ - 📡 **Enhanced Client** - Methods for starting, signaling, and querying workflows with auto-discovery
31
+ - 📊 **Worker Management** - Advanced worker lifecycle control, monitoring, and health checks
32
+ - 🏭 **Production Ready** - Environment-aware configuration, health monitoring, and graceful degradation
19
33
 
20
- ## Installation
34
+ ## 🚀 Quick Start
35
+
36
+ ### Installation
21
37
 
22
38
  ```bash
23
39
  npm install nestjs-temporal-core @temporalio/client @temporalio/worker @temporalio/workflow
24
40
  ```
25
41
 
26
- ## Quick Start
27
-
28
- ### 1. Enable Shutdown Hooks
29
-
30
- First, make sure to enable shutdown hooks in your `main.ts` file:
31
-
32
- ```typescript
33
- async function bootstrap() {
34
- const app = await NestFactory.create(AppModule);
35
- app.enableShutdownHooks();
36
- await app.listen(3000);
37
- }
38
- bootstrap();
39
- ```
40
-
41
- ### 2. Register the Module
42
+ ### Basic Setup
42
43
 
43
44
  ```typescript
45
+ // app.module.ts
44
46
  import { Module } from '@nestjs/common';
45
47
  import { TemporalModule } from 'nestjs-temporal-core';
46
- import { EmailActivities } from './activities/email.activities';
47
48
 
48
49
  @Module({
49
50
  imports: [
@@ -65,591 +66,141 @@ import { EmailActivities } from './activities/email.activities';
65
66
  export class AppModule {}
66
67
  ```
67
68
 
68
- ### 3. Define Activities
69
-
70
- ```typescript
71
- import { Activity, ActivityMethod } from 'nestjs-temporal-core';
72
-
73
- @Activity()
74
- export class EmailActivities {
75
- @ActivityMethod()
76
- async sendWelcomeEmail(to: string): Promise<boolean> {
77
- // Implementation
78
- console.log(`Sending welcome email to ${to}`);
79
- return true;
80
- }
81
-
82
- @ActivityMethod('sendPromoEmail')
83
- async sendPromotion(to: string, promoCode: string): Promise<boolean> {
84
- // Implementation
85
- console.log(`Sending promo ${promoCode} to ${to}`);
86
- return true;
87
- }
88
- }
89
- ```
90
-
91
- ### 4. Define Workflows
92
-
93
- Create a workflow file in your workflows directory:
94
-
95
- ```typescript
96
- // workflows/email-workflow.ts
97
- import { proxyActivities } from '@temporalio/workflow';
98
-
99
- // Activities interface
100
- interface EmailActivities {
101
- sendWelcomeEmail(to: string): Promise<boolean>;
102
- sendPromoEmail(to: string, promoCode: string): Promise<boolean>;
103
- }
104
-
105
- const activities = proxyActivities<EmailActivities>({
106
- startToCloseTimeout: '30s',
107
- });
108
-
109
- export async function sendWelcomeWorkflow(email: string): Promise<boolean> {
110
- return await activities.sendWelcomeEmail(email);
111
- }
112
-
113
- export async function sendPromoWorkflow(email: string, promoCode: string): Promise<boolean> {
114
- return await activities.sendPromoEmail(email, promoCode);
115
- }
116
- ```
117
-
118
- ### 5. Use the Temporal Service
69
+ ### Create a Workflow Controller
119
70
 
120
71
  ```typescript
121
- import { Injectable } from '@nestjs/common';
122
- import { TemporalService } from 'nestjs-temporal-core';
72
+ import { WorkflowController, WorkflowMethod, Cron, Signal, Query } from 'nestjs-temporal-core';
123
73
 
124
- @Injectable()
125
- export class EmailService {
126
- constructor(private readonly temporalService: TemporalService) {}
127
-
128
- async sendWelcomeEmail(email: string): Promise<string> {
129
- // Use the simplified API to start a workflow
130
- const { workflowId } = await this.temporalService.startWorkflow(
131
- 'sendWelcomeWorkflow',
132
- [email],
133
- 'my-task-queue',
134
- {
135
- workflowId: `welcome-${email}-${Date.now()}`,
136
- },
137
- );
138
-
139
- return workflowId;
74
+ @WorkflowController({ taskQueue: 'orders' })
75
+ export class OrderWorkflowController {
76
+ private status = 'pending';
77
+
78
+ @WorkflowMethod()
79
+ async processOrder(orderId: string, customerId: string): Promise<string> {
80
+ this.status = 'processing';
81
+ // Workflow logic here
82
+ this.status = 'completed';
83
+ return this.status;
140
84
  }
141
85
 
142
- async sendPromoEmail(email: string, promoCode: string): Promise<string> {
143
- // Use the client service directly for more options
144
- const { workflowId } = await this.temporalService
145
- .getClient()
146
- .startWorkflow('sendPromoWorkflow', [email, promoCode], {
147
- taskQueue: 'my-task-queue',
148
- workflowId: `promo-${email}-${Date.now()}`,
149
- retry: {
150
- maximumAttempts: 3,
151
- },
152
- });
153
-
154
- return workflowId;
86
+ @Cron('0 8 * * *', {
87
+ scheduleId: 'daily-order-report',
88
+ description: 'Generate daily order report'
89
+ })
90
+ @WorkflowMethod()
91
+ async generateDailyReport(): Promise<void> {
92
+ console.log('Generating daily order report...');
155
93
  }
156
- }
157
- ```
158
-
159
- ## Advanced Features
160
94
 
161
- ### Using Signals and Queries
162
-
163
- ```typescript
164
- import { Injectable } from '@nestjs/common';
165
- import { TemporalService } from 'nestjs-temporal-core';
166
-
167
- @Injectable()
168
- export class OrderService {
169
- constructor(private readonly temporalService: TemporalService) {}
170
-
171
- async addItemToOrder(orderId: string, item: string): Promise<void> {
172
- // Signal a running workflow
173
- await this.temporalService.getClient().signalWorkflow(orderId, 'addItem', [item]);
95
+ @Signal('addItem')
96
+ async addItemToOrder(item: any): Promise<void> {
97
+ console.log('Item added to order:', item);
174
98
  }
175
99
 
176
- async getOrderStatus(orderId: string): Promise<string> {
177
- // Query a running workflow
178
- return await this.temporalService.getClient().queryWorkflow(orderId, 'getStatus');
100
+ @Query('getStatus')
101
+ getOrderStatus(): string {
102
+ return this.status;
179
103
  }
180
104
  }
181
105
  ```
182
106
 
183
- ### Schedule Management
107
+ ### Use the Service
184
108
 
185
109
  ```typescript
186
110
  import { Injectable } from '@nestjs/common';
187
111
  import { TemporalService } from 'nestjs-temporal-core';
188
112
 
189
113
  @Injectable()
190
- export class ReportingService {
114
+ export class OrderService {
191
115
  constructor(private readonly temporalService: TemporalService) {}
192
116
 
193
- async scheduleDailyReport(): Promise<string> {
194
- const handle = await this.temporalService.getScheduleService().createCronWorkflow(
195
- 'daily-report',
196
- 'generateReportWorkflow',
197
- '0 0 * * *', // Daily at midnight
198
- 'reports-queue',
199
- ['daily-summary'],
117
+ async processOrder(orderId: string, customerId: string): Promise<string> {
118
+ const { workflowId } = await this.temporalService.startWorkflow(
119
+ 'processOrder',
120
+ [orderId, customerId],
121
+ { workflowId: `order-${orderId}` }
200
122
  );
201
123
 
202
- return handle.scheduleId;
203
- }
204
-
205
- async pauseReporting(): Promise<void> {
206
- await this.temporalService
207
- .getScheduleService()
208
- .pauseSchedule('daily-report', 'Paused for maintenance');
209
- }
210
-
211
- async resumeReporting(): Promise<void> {
212
- await this.temporalService.getScheduleService().resumeSchedule('daily-report');
213
- }
214
- }
215
- ```
216
-
217
- ## Configuration Options
218
-
219
- ### Async Configuration
220
-
221
- ```typescript
222
- import { Module } from '@nestjs/common';
223
- import { ConfigModule, ConfigService } from '@nestjs/config';
224
- import { TemporalModule } from 'nestjs-temporal-core';
225
- import { EmailActivities } from './activities/email.activities';
226
-
227
- @Module({
228
- imports: [
229
- ConfigModule.forRoot(),
230
- TemporalModule.registerAsync({
231
- imports: [ConfigModule],
232
- inject: [ConfigService],
233
- useFactory: (configService: ConfigService) => ({
234
- connection: {
235
- address: configService.get('TEMPORAL_ADDRESS'),
236
- namespace: configService.get('TEMPORAL_NAMESPACE'),
237
- apiKey: configService.get('TEMPORAL_API_KEY'),
238
- },
239
- taskQueue: configService.get('TEMPORAL_TASK_QUEUE'),
240
- worker: {
241
- workflowsPath: './dist/workflows',
242
- activityClasses: [EmailActivities],
243
- },
244
-
245
- isGlobal: true,
246
- }),
247
- }),
248
- ],
249
- })
250
- export class AppModule {}
251
- ```
252
-
253
- ### Secure Connection with TLS
254
-
255
- ```typescript
256
- TemporalModule.register({
257
- connection: {
258
- address: 'temporal.example.com:7233',
259
- namespace: 'production',
260
- tls: {
261
- // Simple boolean for default TLS
262
- // tls: true,
263
-
264
- // Or detailed configuration
265
- serverName: 'temporal.example.com',
266
- clientCertPair: {
267
- crt: fs.readFileSync('./certs/client.crt'),
268
- key: fs.readFileSync('./certs/client.key'),
269
- ca: fs.readFileSync('./certs/ca.crt'),
270
- },
271
- },
272
- // For Temporal Cloud
273
- apiKey: process.env.TEMPORAL_API_KEY,
274
- },
275
- // ...other options
276
- });
277
- ```
278
-
279
- ```
280
-
281
- ## API Reference
282
-
283
- ### Core Modules
284
-
285
- - `TemporalModule` - Unified module for both client and worker functionality
286
- - `TemporalClientModule` - Client-only module for workflow operations
287
- - `TemporalWorkerModule` - Worker-only module for running activities
288
-
289
- ### Decorators
290
-
291
- - `@Activity(options?)` - Marks a class as a Temporal activity
292
- - `@ActivityMethod(options?)` - Marks a method as an activity implementation
293
- - `@Workflow(options)` - Marks a class as a Temporal workflow
294
- - `@WorkflowMethod(options?)` - Marks the primary workflow execution method
295
- - `@SignalMethod(name?)` - Marks a method as a signal handler
296
- - `@QueryMethod(name?)` - Marks a method as a query handler
297
-
298
- ### Services
299
-
300
- #### TemporalService
301
-
302
- - `getClient()` - Get the client service
303
- - `getScheduleService()` - Get the schedule service
304
- - `getWorkerManager()` - Get the worker manager (if available)
305
- - `startWorkflow()` - Simplified method to start a workflow
306
- - `hasWorker()` - Check if worker functionality is available
307
-
308
-
309
- #### TemporalClientService
310
-
311
- - `startWorkflow()` - Start a new workflow execution
312
- - `signalWorkflow()` - Send a signal to a running workflow
313
- - `queryWorkflow()` - Query a running workflow
314
- - `terminateWorkflow()` - Terminate a running workflow
315
- - `cancelWorkflow()` - Request cancellation of a workflow
316
- - `getWorkflowHandle()` - Get a handle to manage a workflow
317
- - `describeWorkflow()` - Get workflow execution details
318
- - `listWorkflows()` - List workflows matching a query
319
-
320
- #### TemporalScheduleService
321
-
322
- - `createCronWorkflow()` - Create a workflow scheduled by cron expression
323
- - `createIntervalWorkflow()` - Create a workflow scheduled by time interval
324
- - `pauseSchedule()` - Pause a schedule
325
- - `resumeSchedule()` - Resume a paused schedule
326
- - `deleteSchedule()` - Delete a schedule
327
- - `triggerNow()` - Trigger an immediate execution
328
- - `listSchedules()` - List all schedules
329
-
330
- #### WorkerManager
331
-
332
- - `startWorker()` - Manually start the worker
333
- - `shutdown()` - Gracefully shutdown the worker
334
- - `getWorker()` - Get the underlying worker instance
335
-
336
- ## Project Structure
337
-
338
- When integrating Temporal with your NestJS application, organizing your code properly helps maintain separation of concerns and follows NestJS conventions. Here's a recommended project structure:
339
-
340
- ```
341
-
342
- ```
343
- src/
344
- ├── temporal/
345
- │ ├── activities/
346
- │ │ ├── email.activities.ts
347
- │ │ ├── payment.activities.ts
348
- │ │ └── index.ts
349
- │ ├── workflows/
350
- │ │ ├── email-workflows.ts
351
- │ │ ├── payment-workflows.ts
352
- │ │ └── index.ts
353
- │ ├── interfaces/
354
- │ │ ├── email.interfaces.ts
355
- │ │ └── payment.interfaces.ts
356
- │ └── temporal.module.ts
357
- ├── modules/
358
- │ ├── email/
359
- │ │ ├── email.service.ts
360
- │ │ ├── email.controller.ts
361
- │ │ └── email.module.ts
362
- │ └── payment/
363
- │ ├── payment.service.ts
364
- │ ├── payment.controller.ts
365
- │ └── payment.module.ts
366
- └── app.module.ts
367
-
368
- ```
369
-
370
- ### Key Files and Their Purpose
371
-
372
- 1. **Activities (src/temporal/activities/)**:
373
-
374
- - Contains activity classes decorated with `@Activity()`
375
- - Each activity class should group related functionality
376
-
377
- 2. **Workflows (src/temporal/workflows/)**:
378
-
379
- - Contains workflow definitions that orchestrate activities
380
- - Workflows should be in separate files based on domain
381
-
382
- 3. **Interfaces (src/temporal/interfaces/)**:
383
-
384
- - TypeScript interfaces that define activity and workflow parameters/returns
385
- - Helps maintain type safety between activities and workflows
386
-
387
- 4. **Temporal Module (src/temporal/temporal.module.ts)**:
388
-
389
- - Centralizes Temporal configuration
390
- - Imports and registers all activities
391
-
392
- 5. **Business Services (src/modules/\*/)**:
393
- - Inject the TemporalService
394
- - Use it to start workflows and interact with Temporal
395
-
396
- ## Integration Examples
397
-
398
- ### Activity Definition
399
-
400
- ```typescript
401
- // src/temporal/activities/email.activities.ts
402
- import { Activity, ActivityMethod } from 'nestjs-temporal-core';
403
- import { Injectable } from '@nestjs/common';
404
- import { EmailService } from '../../modules/email/email.service';
405
-
406
- @Injectable()
407
- @Activity()
408
- export class EmailActivities {
409
- constructor(private readonly emailService: EmailService) {}
410
-
411
- @ActivityMethod()
412
- async sendWelcomeEmail(to: string, name: string): Promise<boolean> {
413
- await this.emailService.sendEmail({
414
- to,
415
- subject: 'Welcome!',
416
- body: `Hello ${name}, welcome to our platform!`,
417
- });
418
- return true;
419
- }
420
-
421
- @ActivityMethod()
422
- async sendPasswordReset(to: string, resetToken: string): Promise<boolean> {
423
- await this.emailService.sendEmail({
424
- to,
425
- subject: 'Password Reset',
426
- body: `Please use this token to reset your password: ${resetToken}`,
427
- });
428
- return true;
429
- }
430
- }
431
- ```
432
-
433
- ```typescript
434
- // src/temporal/activities/index.ts
435
- export * from './email.activities';
436
- export * from './payment.activities';
437
- // Export all other activity classes
438
- ```
439
-
440
- ### Workflow Definition
441
-
442
- ```typescript
443
- // src/temporal/workflows/email-workflows.ts
444
- import { proxyActivities } from '@temporalio/workflow';
445
-
446
- // Define the interface of activities this workflow will use
447
- export interface EmailActivities {
448
- sendWelcomeEmail(to: string, name: string): Promise<boolean>;
449
- sendPasswordReset(to: string, resetToken: string): Promise<boolean>;
450
- }
451
-
452
- // Create a proxy to the activities
453
- const activities = proxyActivities<EmailActivities>({
454
- startToCloseTimeout: '30 seconds',
455
- });
456
-
457
- // Welcome workflow with retry logic
458
- export async function welcomeUserWorkflow(email: string, name: string): Promise<boolean> {
459
- let attempts = 0;
460
- const maxAttempts = 3;
461
-
462
- while (attempts < maxAttempts) {
463
- try {
464
- return await activities.sendWelcomeEmail(email, name);
465
- } catch (error) {
466
- attempts++;
467
- if (attempts >= maxAttempts) {
468
- throw error;
469
- }
470
- // Wait before retrying
471
- await new Promise((resolve) => setTimeout(resolve, 5000));
472
- }
124
+ return workflowId;
473
125
  }
474
-
475
- return false;
476
- }
477
-
478
- // Password reset workflow
479
- export async function passwordResetWorkflow(email: string, resetToken: string): Promise<boolean> {
480
- return await activities.sendPasswordReset(email, resetToken);
481
126
  }
482
127
  ```
483
128
 
484
- ### Scheduled Workflow Example
129
+ ## 📖 Core Concepts
485
130
 
486
- ```typescript
487
- // src/temporal/workflows/scheduled-workflows.ts
488
- import { proxyActivities } from '@temporalio/workflow';
131
+ ### Workflow Controllers
132
+ New NestJS-style controllers for defining workflows with auto-discovery and declarative scheduling.
489
133
 
490
- interface ReportActivities {
491
- generateDailyReport(): Promise<string>;
492
- emailReportToAdmins(reportUrl: string): Promise<boolean>;
493
- }
134
+ ### Activities
135
+ Reusable business logic components that can be called from workflows.
494
136
 
495
- const activities = proxyActivities<ReportActivities>({
496
- startToCloseTimeout: '10 minutes',
497
- });
137
+ ### Scheduling
138
+ Built-in support for cron and interval-based workflow scheduling using decorators.
498
139
 
499
- // This workflow will be scheduled to run daily
500
- export async function dailyReportWorkflow(): Promise<void> {
501
- const reportUrl = await activities.generateDailyReport();
502
- await activities.emailReportToAdmins(reportUrl);
503
- }
504
- ```
140
+ ### Auto-Discovery
141
+ Automatic detection and registration of workflow controllers and scheduled workflows.
505
142
 
506
- ### Setting Up the Temporal Module
143
+ ## 🏗️ Architecture
507
144
 
508
- ```typescript
509
- // src/temporal/temporal.module.ts
510
- import { Module } from '@nestjs/common';
511
- import { TemporalModule } from 'nestjs-temporal-core';
512
- import { ConfigModule, ConfigService } from '@nestjs/config';
513
- import * as path from 'path';
514
- import { EmailActivities, PaymentActivities } from './activities';
515
- import { EmailModule } from '../modules/email/email.module';
516
- import { PaymentModule } from '../modules/payment/payment.module';
517
-
518
- @Module({
519
- imports: [
520
- EmailModule,
521
- PaymentModule,
522
- TemporalModule.registerAsync({
523
- imports: [ConfigModule],
524
- inject: [ConfigService],
525
- useFactory: (configService: ConfigService) => ({
526
- connection: {
527
- address: configService.get('TEMPORAL_ADDRESS', 'localhost:7233'),
528
- namespace: configService.get('TEMPORAL_NAMESPACE', 'default'),
529
- },
530
- taskQueue: configService.get('TEMPORAL_TASK_QUEUE', 'my-app-queue'),
531
- worker: {
532
- workflowsPath: path.resolve(__dirname, 'workflows'),
533
- activityClasses: [EmailActivities, PaymentActivities],
534
- autoStart: true,
535
- },
536
- isGlobal: true,
537
- }),
538
- }),
539
- ],
540
- providers: [EmailActivities, PaymentActivities],
541
- exports: [TemporalModule],
542
- })
543
- export class TemporalAppModule {}
544
145
  ```
545
-
546
- ### Using Temporal in Business Services
547
-
548
- ```typescript
549
- // src/modules/email/email.service.ts
550
- import { Injectable } from '@nestjs/common';
551
- import { TemporalService } from 'nestjs-temporal-core';
552
-
553
- @Injectable()
554
- export class EmailService {
555
- constructor(private readonly temporalService: TemporalService) {}
556
-
557
- // Your actual email sending functionality
558
- async sendEmail(options: { to: string; subject: string; body: string }): Promise<void> {
559
- // Implementation...
560
- }
561
-
562
- // Triggering a Temporal workflow
563
- async sendWelcomeEmail(email: string, name: string): Promise<string> {
564
- const { workflowId } = await this.temporalService.startWorkflow(
565
- 'welcomeUserWorkflow',
566
- [email, name],
567
- 'my-app-queue',
568
- { workflowId: `welcome-${email}-${Date.now()}` },
569
- );
570
-
571
- return workflowId;
572
- }
573
- }
146
+ ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
147
+ │ NestJS App │ │ Temporal Server │ │ Worker Process
148
+ │ │ │ │ │ │
149
+ │ ┌─────────────┐ │ │ ┌──────────────┐ │ │ ┌─────────────┐ │
150
+ │ Controllers │ │───▶│ │ Workflows │ │───▶│ │ Activities │ │
151
+ │ Services │ │ │ │ Schedules │ │ │ │ Workers │ │
152
+ └─────────────┘ │ │ └──────────────┘ │ │ └─────────────┘ │
153
+ └─────────────────┘ └──────────────────┘ └─────────────────┘
574
154
  ```
575
155
 
576
- ### Setting Up Scheduled Workflows
156
+ ## 🎯 Use Cases
577
157
 
578
- ```typescript
579
- // src/modules/reports/report.service.ts
580
- import { Injectable, OnModuleInit } from '@nestjs/common';
581
- import { TemporalService } from 'nestjs-temporal-core';
582
-
583
- @Injectable()
584
- export class ReportService implements OnModuleInit {
585
- constructor(private readonly temporalService: TemporalService) {}
586
-
587
- async onModuleInit() {
588
- // Set up scheduled workflows when the module initializes
589
- await this.setupDailyReport();
590
- }
591
-
592
- private async setupDailyReport() {
593
- try {
594
- // Check if the schedule already exists
595
- const schedules = await this.temporalService.getScheduleService().listSchedules();
596
-
597
- if (!schedules.some((s) => s.scheduleId === 'daily-report')) {
598
- // Create a new schedule
599
- await this.temporalService.getScheduleService().createCronWorkflow(
600
- 'daily-report',
601
- 'dailyReportWorkflow',
602
- '0 8 * * *', // Run every day at 8 AM
603
- 'my-app-queue',
604
- [], // No arguments needed for this workflow
605
- 'Daily business report generation',
606
- );
607
-
608
- console.log('Daily report schedule created');
609
- }
610
- } catch (error) {
611
- console.error('Failed to set up daily report schedule:', error);
612
- }
613
- }
614
- }
615
- ```
158
+ - **Order Processing** - Reliable order fulfillment with compensation
159
+ - **Payment Processing** - Multi-step payment flows with retries
160
+ - **Data Pipelines** - Long-running data processing workflows
161
+ - **Scheduled Jobs** - Cron-based and interval-based background tasks
162
+ - **Saga Patterns** - Distributed transaction management
163
+ - **Human Tasks** - Workflows requiring human intervention
164
+ - **Microservice Orchestration** - Coordinating multiple services
616
165
 
617
- ## Best Practices
166
+ ## 🌟 What's New in v3.0
618
167
 
619
- 1. **Activity Design**
168
+ - **🎮 Workflow Controllers** - NestJS-style workflow definition
169
+ - **📅 Declarative Scheduling** - `@Cron` and `@Interval` decorators
170
+ - **🔍 Auto-Discovery** - Automatic workflow and schedule detection
171
+ - **📊 Enhanced Monitoring** - Built-in health checks and metrics
172
+ - **🏭 Production Features** - Worker presets, graceful shutdown, error handling
173
+ - **🔧 Better Developer Experience** - Improved APIs and TypeScript support
620
174
 
621
- - Keep activities focused on single responsibilities
622
- - Set appropriate timeouts for expected durations
623
- - Use dependency injection within activity classes
175
+ ## 📦 Packages
624
176
 
625
- 2. **Workflow Design**
177
+ | Package | Version | Description |
178
+ | ---------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------ |
179
+ | `nestjs-temporal-core` | [![npm](https://img.shields.io/npm/v/nestjs-temporal-core.svg)](https://www.npmjs.com/package/nestjs-temporal-core) | Main integration package |
180
+ | `@temporalio/client` | [![npm](https://img.shields.io/npm/v/@temporalio/client.svg)](https://www.npmjs.com/package/@temporalio/client) | Temporal client library |
181
+ | `@temporalio/worker` | [![npm](https://img.shields.io/npm/v/@temporalio/worker.svg)](https://www.npmjs.com/package/@temporalio/worker) | Temporal worker library |
182
+ | `@temporalio/workflow` | [![npm](https://img.shields.io/npm/v/@temporalio/workflow.svg)](https://www.npmjs.com/package/@temporalio/workflow) | Workflow runtime library |
626
183
 
627
- - Make workflows deterministic
628
- - Use signals for external events
629
- - Use queries for retrieving workflow state
630
- - Separate workflows by domain/function
184
+ ## 🤝 Community
631
185
 
632
- 3. **Configuration**
186
+ - **GitHub Discussions** - Ask questions and share ideas
187
+ - **Issues** - Report bugs and request features
188
+ - **Pull Requests** - Contribute to the project
633
189
 
634
- - Use meaningful workflow IDs for tracking
635
- - Configure appropriate timeouts for activities and workflows
636
- - Implement proper error handling
190
+ ## 📄 License
637
191
 
638
- 4. **Lifecycle Management**
192
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
639
193
 
640
- - Enable NestJS shutdown hooks
641
- - Configure proper worker shutdown grace periods
642
- - Consider using OnModuleInit to set up schedules
194
+ ## 👨‍💻 Author
643
195
 
644
- 5. **Security**
645
- - Implement proper TLS security for production environments
646
- - Use namespaces to isolate different environments
647
- - Use API keys for Temporal Cloud authentication
196
+ **Harsh M** - [GitHub](https://github.com/harsh-simform)
648
197
 
649
- ## License
198
+ ## 🙏 Acknowledgments
650
199
 
651
- MIT
200
+ - [Temporal.io](https://temporal.io/) - For the amazing workflow engine
201
+ - [NestJS](https://nestjs.com/) - For the incredible framework
202
+ - [TypeScript](https://www.typescriptlang.org/) - For making JavaScript enjoyable
652
203
 
653
- ## Author
204
+ ---
654
205
 
655
- Harsh M
206
+ **[📚 Continue to Getting Started →](./docs/getting-started.md)**