nestjs-temporal-core 3.0.4 → 3.0.6

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 (43) hide show
  1. package/README.md +509 -157
  2. package/dist/activity/index.d.ts +2 -0
  3. package/dist/activity/index.js +19 -0
  4. package/dist/activity/index.js.map +1 -0
  5. package/dist/activity/temporal-activity.module.d.ts +11 -0
  6. package/dist/activity/temporal-activity.module.js +52 -0
  7. package/dist/activity/temporal-activity.module.js.map +1 -0
  8. package/dist/activity/temporal-activity.service.d.ts +46 -0
  9. package/dist/activity/temporal-activity.service.js +195 -0
  10. package/dist/activity/temporal-activity.service.js.map +1 -0
  11. package/dist/client/temporal-client.module.d.ts +1 -1
  12. package/dist/client/temporal-client.module.js +22 -14
  13. package/dist/client/temporal-client.module.js.map +1 -1
  14. package/dist/client/temporal-client.service.d.ts +2 -1
  15. package/dist/client/temporal-client.service.js +12 -4
  16. package/dist/client/temporal-client.service.js.map +1 -1
  17. package/dist/constants.d.ts +3 -0
  18. package/dist/constants.js +4 -1
  19. package/dist/constants.js.map +1 -1
  20. package/dist/index.d.ts +2 -0
  21. package/dist/index.js +7 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/interfaces.d.ts +53 -6
  24. package/dist/schedules/index.d.ts +2 -0
  25. package/dist/schedules/index.js +19 -0
  26. package/dist/schedules/index.js.map +1 -0
  27. package/dist/schedules/temporal-schedules.module.d.ts +11 -0
  28. package/dist/schedules/temporal-schedules.module.js +55 -0
  29. package/dist/schedules/temporal-schedules.module.js.map +1 -0
  30. package/dist/schedules/temporal-schedules.service.d.ts +52 -0
  31. package/dist/schedules/temporal-schedules.service.js +220 -0
  32. package/dist/schedules/temporal-schedules.service.js.map +1 -0
  33. package/dist/temporal.service.js +1 -1
  34. package/dist/temporal.service.js.map +1 -1
  35. package/dist/tsconfig.tsbuildinfo +1 -1
  36. package/dist/utils/conditional-logger.d.ts +15 -0
  37. package/dist/utils/conditional-logger.js +58 -0
  38. package/dist/utils/conditional-logger.js.map +1 -0
  39. package/dist/worker/temporal-worker-manager.service.js +15 -11
  40. package/dist/worker/temporal-worker-manager.service.js.map +1 -1
  41. package/dist/worker/temporal-worker.module.js +2 -0
  42. package/dist/worker/temporal-worker.module.js.map +1 -1
  43. package/package.json +1 -4
package/README.md CHANGED
@@ -23,7 +23,9 @@ NestJS Temporal Core brings Temporal's durable execution to NestJS with familiar
23
23
  - **⚙️ Flexible Setup** - Client-only, worker-only, or unified deployments
24
24
  - **🏥 Health Monitoring** - Comprehensive status monitoring and health checks
25
25
  - **🔧 Production Ready** - TLS, connection management, graceful shutdowns
26
- - **📊 Complete Integration** - Full-featured module architecture
26
+ - **📊 Modular Architecture** - Individual modules for specific needs
27
+ - **📝 Configurable Logging** - Fine-grained control over log levels and output
28
+ - **🔐 Enterprise Ready** - Temporal Cloud support with TLS and API keys
27
29
 
28
30
  ## 📦 Installation
29
31
 
@@ -33,7 +35,9 @@ npm install nestjs-temporal-core @temporalio/client @temporalio/worker @temporal
33
35
 
34
36
  ## 🚀 Quick Start
35
37
 
36
- ### 1. Module Setup
38
+ ### 1. Complete Integration (Recommended)
39
+
40
+ For applications that need full Temporal functionality:
37
41
 
38
42
  ```typescript
39
43
  // app.module.ts
@@ -48,163 +52,385 @@ import { EmailActivities } from './activities/email.activities';
48
52
  address: 'localhost:7233',
49
53
  namespace: 'default',
50
54
  },
51
- taskQueue: 'my-app',
55
+ taskQueue: 'main-queue',
52
56
  worker: {
53
57
  workflowsPath: './dist/workflows',
54
- activityClasses: [EmailActivities], // Auto-discovered
55
- },
56
- }),
58
+ activityClasses: [EmailActivities],
59
+ autoStart: true
60
+ }
61
+ })
57
62
  ],
58
- providers: [EmailActivities],
63
+ providers: [EmailActivities], // Auto-discovered
59
64
  })
60
65
  export class AppModule {}
61
66
  ```
62
67
 
63
- ### 2. Create Activities
68
+ ### 2. Define Activities
64
69
 
65
70
  ```typescript
66
71
  // activities/email.activities.ts
67
72
  import { Injectable } from '@nestjs/common';
68
73
  import { Activity, ActivityMethod } from 'nestjs-temporal-core';
69
74
 
70
- @Injectable()
71
75
  @Activity()
76
+ @Injectable()
72
77
  export class EmailActivities {
73
- @ActivityMethod()
74
- async sendWelcomeEmail(email: string, name: string): Promise<boolean> {
75
- console.log(`Sending welcome email to ${email}`);
76
- // Your email logic here
77
- return true;
78
+
79
+ @ActivityMethod({
80
+ name: 'sendEmail',
81
+ timeout: '30s',
82
+ maxRetries: 3
83
+ })
84
+ async sendEmail(to: string, subject: string, body: string): Promise<void> {
85
+ console.log(`Sending email to ${to}: ${subject}`);
86
+ // Your email sending logic here
78
87
  }
79
88
 
80
- @ActivityMethod()
81
- async sendNotification(email: string, message: string): Promise<void> {
82
- console.log(`Notification to ${email}: ${message}`);
89
+ @ActivityMethod('sendNotification')
90
+ async sendNotification(userId: string, message: string): Promise<void> {
91
+ console.log(`Notifying user ${userId}: ${message}`);
83
92
  // Your notification logic here
84
93
  }
85
94
  }
86
95
  ```
87
96
 
88
- ### 3. Create Scheduled Workflows
97
+ ### 3. Create Workflows
98
+
99
+ ```typescript
100
+ // workflows/email.workflow.ts
101
+ import { proxyActivities } from '@temporalio/workflow';
102
+ import type { EmailActivities } from '../activities/email.activities';
103
+
104
+ const { sendEmail, sendNotification } = proxyActivities<EmailActivities>({
105
+ startToCloseTimeout: '1 minute',
106
+ });
107
+
108
+ export async function processEmailWorkflow(
109
+ userId: string,
110
+ emailData: { to: string; subject: string; body: string }
111
+ ): Promise<void> {
112
+ // Send email
113
+ await sendEmail(emailData.to, emailData.subject, emailData.body);
114
+
115
+ // Send notification
116
+ await sendNotification(userId, 'Email sent successfully');
117
+ }
118
+ ```
119
+
120
+ ### 4. Schedule Workflows
89
121
 
90
122
  ```typescript
91
123
  // services/scheduled.service.ts
92
124
  import { Injectable } from '@nestjs/common';
93
- import { Cron, Interval } from 'nestjs-temporal-core';
125
+ import { Scheduled, Cron, Interval, CRON_EXPRESSIONS } from 'nestjs-temporal-core';
94
126
 
95
127
  @Injectable()
96
128
  export class ScheduledService {
97
- // Automatic scheduling - runs at 9 AM daily
98
- @Cron('0 9 * * *', {
99
- scheduleId: 'daily-user-report',
100
- description: 'Generate daily user report'
129
+
130
+ @Scheduled({
131
+ scheduleId: 'daily-report',
132
+ cron: CRON_EXPRESSIONS.DAILY_8AM,
133
+ description: 'Generate daily sales report',
134
+ taskQueue: 'reports'
101
135
  })
102
136
  async generateDailyReport(): Promise<void> {
103
- console.log('Generating daily user report...');
104
- // Report generation logic
137
+ console.log('Generating daily report...');
138
+ // Your report generation logic
139
+ }
140
+
141
+ @Cron(CRON_EXPRESSIONS.WEEKLY_MONDAY_9AM, {
142
+ scheduleId: 'weekly-cleanup'
143
+ })
144
+ async performWeeklyCleanup(): Promise<void> {
145
+ console.log('Performing weekly cleanup...');
146
+ // Your cleanup logic
105
147
  }
106
148
 
107
- // Interval-based scheduling - runs every hour
108
- @Interval('1h', {
109
- scheduleId: 'hourly-cleanup',
110
- description: 'Hourly cleanup task'
149
+ @Interval('5m', {
150
+ scheduleId: 'health-check'
111
151
  })
112
- async cleanupTask(): Promise<void> {
113
- console.log('Running cleanup task...');
114
- // Cleanup logic
152
+ async performHealthCheck(): Promise<void> {
153
+ console.log('Performing health check...');
154
+ // Your health check logic
115
155
  }
116
156
  }
117
157
  ```
118
158
 
119
- ### 4. Use in Services
159
+ ### 5. Use in Services
120
160
 
121
161
  ```typescript
122
- // services/user.service.ts
162
+ // services/order.service.ts
123
163
  import { Injectable } from '@nestjs/common';
124
164
  import { TemporalService } from 'nestjs-temporal-core';
125
165
 
126
166
  @Injectable()
127
- export class UserService {
167
+ export class OrderService {
128
168
  constructor(private readonly temporal: TemporalService) {}
129
169
 
130
- async processUser(email: string, name: string): Promise<string> {
131
- // Start workflow directly with client
170
+ async createOrder(orderData: any) {
132
171
  const { workflowId } = await this.temporal.startWorkflow(
133
- 'processUser',
134
- [email, name],
135
- {
136
- taskQueue: 'user-processing',
137
- workflowId: `user-${email}-${Date.now()}`
172
+ 'processOrder',
173
+ [orderData],
174
+ {
175
+ taskQueue: 'orders',
176
+ workflowId: `order-${orderData.id}`,
177
+ searchAttributes: {
178
+ 'customer-id': orderData.customerId
179
+ }
138
180
  }
139
181
  );
140
182
 
141
- return workflowId;
183
+ return { workflowId };
142
184
  }
143
185
 
144
- async getUserStatus(workflowId: string): Promise<string> {
145
- return await this.temporal.queryWorkflow(workflowId, 'getStatus');
186
+ async cancelOrder(orderId: string) {
187
+ await this.temporal.signalWorkflow(`order-${orderId}`, 'cancel');
188
+ return { cancelled: true };
146
189
  }
147
190
 
148
- async updateUserStatus(workflowId: string, status: string): Promise<void> {
149
- await this.temporal.signalWorkflow(workflowId, 'updateStatus', [status]);
191
+ async getOrderStatus(orderId: string) {
192
+ const status = await this.temporal.queryWorkflow(`order-${orderId}`, 'getStatus');
193
+ return status;
150
194
  }
195
+ }
196
+ ```
151
197
 
152
- // Schedule management
153
- async pauseDailyReport(): Promise<void> {
154
- await this.temporal.pauseSchedule('daily-user-report', 'Maintenance mode');
155
- }
198
+ ## 🏗️ Integration Patterns
156
199
 
157
- async resumeDailyReport(): Promise<void> {
158
- await this.temporal.resumeSchedule('daily-user-report');
159
- }
160
- }
200
+ ### Client-Only Integration
201
+
202
+ For applications that only start workflows (e.g., web APIs):
203
+
204
+ ```typescript
205
+ import { TemporalClientModule } from 'nestjs-temporal-core';
206
+
207
+ @Module({
208
+ imports: [
209
+ TemporalClientModule.forRoot({
210
+ connection: {
211
+ address: 'localhost:7233',
212
+ namespace: 'production'
213
+ }
214
+ })
215
+ ],
216
+ providers: [ApiService],
217
+ })
218
+ export class ClientOnlyModule {}
161
219
  ```
162
220
 
163
- ## ⚙️ Configuration Options
221
+ ### Worker-Only Integration
164
222
 
165
- ### Basic Configuration
223
+ For dedicated worker processes:
166
224
 
167
225
  ```typescript
168
- TemporalModule.register({
226
+ import { TemporalWorkerModule, WORKER_PRESETS } from 'nestjs-temporal-core';
227
+
228
+ @Module({
229
+ imports: [
230
+ TemporalWorkerModule.forRoot({
231
+ connection: {
232
+ address: 'localhost:7233',
233
+ namespace: 'production'
234
+ },
235
+ taskQueue: 'worker-queue',
236
+ workflowsPath: './dist/workflows',
237
+ activityClasses: [ProcessingActivities],
238
+ workerOptions: WORKER_PRESETS.PRODUCTION_HIGH_THROUGHPUT
239
+ })
240
+ ],
241
+ providers: [ProcessingActivities],
242
+ })
243
+ export class WorkerOnlyModule {}
244
+ ```
245
+
246
+ ### Modular Integration
247
+
248
+ Using individual modules for specific needs:
249
+
250
+ ```typescript
251
+ import {
252
+ TemporalClientModule,
253
+ TemporalActivityModule,
254
+ TemporalSchedulesModule
255
+ } from 'nestjs-temporal-core';
256
+
257
+ @Module({
258
+ imports: [
259
+ // Client for workflow operations
260
+ TemporalClientModule.forRoot({
261
+ connection: { address: 'localhost:7233' }
262
+ }),
263
+
264
+ // Activities management
265
+ TemporalActivityModule.forRoot({
266
+ activityClasses: [EmailActivities, PaymentActivities]
267
+ }),
268
+
269
+ // Schedule management
270
+ TemporalSchedulesModule.forRoot({
271
+ autoStart: true,
272
+ defaultTimezone: 'UTC'
273
+ }),
274
+ ],
275
+ providers: [EmailActivities, PaymentActivities, ScheduledService],
276
+ })
277
+ export class ModularIntegrationModule {}
278
+ ```
279
+
280
+ ## ⚙️ Configuration
281
+
282
+ ### Async Configuration
283
+
284
+ ```typescript
285
+ import { ConfigModule, ConfigService } from '@nestjs/config';
286
+
287
+ @Module({
288
+ imports: [
289
+ ConfigModule.forRoot(),
290
+ TemporalModule.registerAsync({
291
+ imports: [ConfigModule],
292
+ useFactory: async (config: ConfigService) => ({
293
+ connection: {
294
+ address: config.get('TEMPORAL_ADDRESS'),
295
+ namespace: config.get('TEMPORAL_NAMESPACE'),
296
+ tls: config.get('TEMPORAL_TLS_ENABLED') === 'true',
297
+ apiKey: config.get('TEMPORAL_API_KEY'),
298
+ },
299
+ taskQueue: config.get('TEMPORAL_TASK_QUEUE'),
300
+ worker: {
301
+ workflowsPath: config.get('WORKFLOWS_PATH'),
302
+ activityClasses: [EmailActivities, PaymentActivities],
303
+ autoStart: config.get('WORKER_AUTO_START') !== 'false',
304
+ }
305
+ }),
306
+ inject: [ConfigService],
307
+ })
308
+ ],
309
+ })
310
+ export class AppModule {}
311
+ ```
312
+
313
+ ### Environment-Specific Configurations
314
+
315
+ ```typescript
316
+ // Development
317
+ const developmentConfig = {
169
318
  connection: {
170
319
  address: 'localhost:7233',
171
- namespace: 'default',
320
+ namespace: 'development'
172
321
  },
173
- taskQueue: 'my-app',
322
+ taskQueue: 'dev-queue',
174
323
  worker: {
175
324
  workflowsPath: './dist/workflows',
176
- activityClasses: [EmailActivities, PaymentActivities],
325
+ workerOptions: WORKER_PRESETS.DEVELOPMENT
326
+ }
327
+ };
328
+
329
+ // Production
330
+ const productionConfig = {
331
+ connection: {
332
+ address: process.env.TEMPORAL_ADDRESS!,
333
+ namespace: process.env.TEMPORAL_NAMESPACE!,
334
+ tls: true,
335
+ apiKey: process.env.TEMPORAL_API_KEY
177
336
  },
178
- });
337
+ taskQueue: process.env.TEMPORAL_TASK_QUEUE!,
338
+ worker: {
339
+ workflowBundle: require('../workflows/bundle'), // Pre-bundled
340
+ workerOptions: WORKER_PRESETS.PRODUCTION_BALANCED
341
+ }
342
+ };
179
343
  ```
180
344
 
181
- ### Client-Only Mode
345
+ ## 📝 Logger Configuration
346
+
347
+ Control logging behavior across all Temporal modules with configurable logger settings:
348
+
349
+ ### Basic Logger Setup
182
350
 
183
351
  ```typescript
184
- TemporalModule.forClient({
352
+ // Enable/disable logging and set log levels
353
+ TemporalModule.register({
185
354
  connection: {
186
- address: 'temporal.company.com:7233',
187
- namespace: 'production',
188
- tls: true,
355
+ address: 'localhost:7233',
356
+ namespace: 'default'
189
357
  },
190
- });
358
+ taskQueue: 'main-queue',
359
+ // Logger configuration
360
+ enableLogger: true, // Enable/disable all logging
361
+ logLevel: 'info', // Set log level: 'error' | 'warn' | 'info' | 'debug' | 'verbose'
362
+ worker: {
363
+ workflowsPath: './dist/workflows',
364
+ activityClasses: [EmailActivities]
365
+ }
366
+ })
191
367
  ```
192
368
 
193
- ### Worker-Only Mode
369
+ ### Environment-Based Logger Configuration
194
370
 
195
371
  ```typescript
196
- TemporalModule.forWorker({
197
- connection: {
198
- address: 'localhost:7233',
199
- namespace: 'development',
372
+ // Different log levels for different environments
373
+ const loggerConfig = {
374
+ development: {
375
+ enableLogger: true,
376
+ logLevel: 'debug' as const // Show all logs in development
200
377
  },
201
- taskQueue: 'worker-queue',
202
- workflowsPath: './dist/workflows',
203
- activityClasses: [ProcessingActivities],
204
- });
378
+ production: {
379
+ enableLogger: true,
380
+ logLevel: 'warn' as const // Only warnings and errors in production
381
+ },
382
+ testing: {
383
+ enableLogger: false // Disable logging during tests
384
+ }
385
+ };
386
+
387
+ TemporalModule.register({
388
+ connection: { address: 'localhost:7233' },
389
+ taskQueue: 'main-queue',
390
+ ...loggerConfig[process.env.NODE_ENV || 'development'],
391
+ worker: {
392
+ workflowsPath: './dist/workflows'
393
+ }
394
+ })
205
395
  ```
206
396
 
207
- ### Async Configuration
397
+ ### Individual Module Logger Configuration
398
+
399
+ Configure logging for specific modules:
400
+
401
+ ```typescript
402
+ // Activity Module with custom logging
403
+ TemporalActivityModule.forRoot({
404
+ activityClasses: [EmailActivities],
405
+ enableLogger: true,
406
+ logLevel: 'debug'
407
+ })
408
+
409
+ // Schedules Module with minimal logging
410
+ TemporalSchedulesModule.forRoot({
411
+ autoStart: true,
412
+ enableLogger: true,
413
+ logLevel: 'error' // Only show errors
414
+ })
415
+
416
+ // Client Module with no logging
417
+ TemporalClientModule.forRoot({
418
+ connection: { address: 'localhost:7233' },
419
+ enableLogger: false
420
+ })
421
+ ```
422
+
423
+ ### Log Level Hierarchy
424
+
425
+ The logger follows a hierarchical structure where each level includes all levels above it:
426
+
427
+ - **`error`**: Only critical errors
428
+ - **`warn`**: Errors + warnings
429
+ - **`info`**: Errors + warnings + informational messages (default)
430
+ - **`debug`**: Errors + warnings + info + debug information
431
+ - **`verbose`**: All messages including verbose details
432
+
433
+ ### Async Configuration with Logger
208
434
 
209
435
  ```typescript
210
436
  TemporalModule.registerAsync({
@@ -212,130 +438,256 @@ TemporalModule.registerAsync({
212
438
  useFactory: (config: ConfigService) => ({
213
439
  connection: {
214
440
  address: config.get('TEMPORAL_ADDRESS'),
215
- namespace: config.get('TEMPORAL_NAMESPACE'),
441
+ namespace: config.get('TEMPORAL_NAMESPACE')
216
442
  },
217
443
  taskQueue: config.get('TEMPORAL_TASK_QUEUE'),
444
+ // Dynamic logger configuration
445
+ enableLogger: config.get('TEMPORAL_LOGGING_ENABLED', 'true') === 'true',
446
+ logLevel: config.get('TEMPORAL_LOG_LEVEL', 'info'),
218
447
  worker: {
219
- workflowsPath: './dist/workflows',
220
- activityClasses: [EmailActivities],
221
- },
448
+ workflowsPath: './dist/workflows'
449
+ }
222
450
  }),
223
- inject: [ConfigService],
224
- });
451
+ inject: [ConfigService]
452
+ })
225
453
  ```
226
454
 
227
- ## 📋 Core Concepts
455
+ ### Logger Examples
228
456
 
229
- ### Auto-Discovery
230
- The module automatically discovers and registers:
231
- - **Activity Classes** marked with `@Activity`
232
- - **Scheduled Workflows** marked with `@Cron` or `@Interval`
233
- - **Signals and Queries** within classes
234
-
235
- ### Scheduling Made Simple
236
457
  ```typescript
237
- // Just add the decorator - schedule is created automatically!
238
- @Cron('0 8 * * *', { scheduleId: 'daily-report' })
239
- async generateReport(): Promise<void> {
240
- // This will run every day at 8 AM
458
+ // Silent mode - no logs
459
+ {
460
+ enableLogger: false
461
+ }
462
+
463
+ // Error only - for production monitoring
464
+ {
465
+ enableLogger: true,
466
+ logLevel: 'error'
241
467
  }
242
- ```
243
468
 
244
- ## 🔧 Common Use Cases
469
+ // Development mode - detailed logging
470
+ {
471
+ enableLogger: true,
472
+ logLevel: 'debug'
473
+ }
245
474
 
246
- ### Scheduled Reports
247
- ```typescript
248
- @Injectable()
249
- export class ReportService {
250
- @Cron('0 0 * * 0', { scheduleId: 'weekly-sales-report' })
251
- async generateWeeklySalesReport(): Promise<void> {
252
- // Automatically runs every Sunday at midnight
253
- console.log('Generating weekly sales report...');
254
- }
475
+ // Verbose mode - maximum detail for troubleshooting
476
+ {
477
+ enableLogger: true,
478
+ logLevel: 'verbose'
255
479
  }
256
480
  ```
257
481
 
258
- ### Data Processing
482
+ ## 📊 Health Monitoring
483
+
484
+ Built-in health monitoring for production environments:
485
+
259
486
  ```typescript
260
- @Injectable()
261
- @Activity()
262
- export class DataProcessingActivities {
263
- @ActivityMethod()
264
- async processFile(filePath: string): Promise<string> {
265
- console.log(`Processing file: ${filePath}`);
266
- // File processing logic
267
- return 'processed';
487
+ @Controller('health')
488
+ export class HealthController {
489
+ constructor(private readonly temporal: TemporalService) {}
490
+
491
+ @Get('temporal')
492
+ async getTemporalHealth() {
493
+ const health = await this.temporal.getOverallHealth();
494
+ return {
495
+ status: health.status,
496
+ components: health.components,
497
+ timestamp: new Date().toISOString()
498
+ };
268
499
  }
269
500
 
270
- @ActivityMethod()
271
- async sendNotification(message: string): Promise<void> {
272
- console.log(`Sending notification: ${message}`);
273
- // Notification logic
501
+ @Get('temporal/detailed')
502
+ async getDetailedStatus() {
503
+ const systemStatus = await this.temporal.getSystemStatus();
504
+ const stats = this.temporal.getDiscoveryStats();
505
+
506
+ return {
507
+ system: systemStatus,
508
+ discovery: stats,
509
+ schedules: this.temporal.getScheduleStats()
510
+ };
274
511
  }
275
512
  }
276
513
  ```
277
514
 
278
- ### Monitoring Tasks
515
+ ## 🔧 Advanced Features
516
+
517
+ ### Activity Options
518
+
279
519
  ```typescript
520
+ @Activity()
280
521
  @Injectable()
281
- export class MonitoringService {
282
- @Interval('5m', {
283
- scheduleId: 'health-check',
284
- description: 'Health check every 5 minutes'
522
+ export class PaymentActivities {
523
+
524
+ @ActivityMethod({
525
+ name: 'processPayment',
526
+ timeout: '2m',
527
+ maxRetries: 5,
528
+ retryPolicy: {
529
+ maximumAttempts: 5,
530
+ initialInterval: '1s',
531
+ maximumInterval: '60s',
532
+ backoffCoefficient: 2.0
533
+ }
285
534
  })
286
- async healthCheck(): Promise<void> {
287
- console.log('Running health check...');
288
- // Health check logic
535
+ async processPayment(orderId: string, amount: number) {
536
+ // Complex payment processing with retries
289
537
  }
290
538
  }
291
539
  ```
292
540
 
293
- ## 📊 Monitoring & Health Checks
541
+ ### Schedule Management
294
542
 
295
543
  ```typescript
296
544
  @Injectable()
297
- export class MonitoringService {
545
+ export class ScheduleManagementService {
298
546
  constructor(private readonly temporal: TemporalService) {}
299
547
 
300
- async getSystemHealth() {
301
- // Comprehensive health status
302
- const health = await this.temporal.getOverallHealth();
303
- return {
304
- status: health.status, // 'healthy' | 'degraded' | 'unhealthy'
305
- components: health.components,
306
- };
548
+ async pauseSchedule(scheduleId: string) {
549
+ await this.temporal.pauseSchedule(scheduleId, 'Maintenance mode');
307
550
  }
308
551
 
309
- async getDiscoveryInfo() {
310
- // What was discovered
311
- const schedules = this.temporal.getManagedSchedules();
312
- const stats = this.temporal.getDiscoveryStats();
313
-
314
- return { schedules, stats };
552
+ async resumeSchedule(scheduleId: string) {
553
+ await this.temporal.resumeSchedule(scheduleId);
315
554
  }
316
555
 
317
- async manageSchedules() {
318
- // Schedule management
319
- await this.temporal.pauseSchedule('daily-report', 'Maintenance');
320
- await this.temporal.resumeSchedule('daily-report');
321
- await this.temporal.triggerSchedule('daily-report'); // Run now
556
+ async triggerScheduleNow(scheduleId: string) {
557
+ await this.temporal.triggerSchedule(scheduleId);
558
+ }
559
+
560
+ async getScheduleInfo(scheduleId: string) {
561
+ return this.temporal.getScheduleInfo(scheduleId);
322
562
  }
323
563
  }
324
564
  ```
325
565
 
326
- ## 🌟 Why This Package?
566
+ ### Workflow Signals and Queries
567
+
568
+ ```typescript
569
+ // In your workflow
570
+ import { defineSignal, defineQuery, setHandler } from '@temporalio/workflow';
571
+
572
+ export const cancelSignal = defineSignal('cancel');
573
+ export const getStatusQuery = defineQuery<string>('getStatus');
574
+
575
+ export async function orderWorkflow(orderData: any) {
576
+ let status = 'processing';
577
+ let cancelled = false;
578
+
579
+ // Handle cancel signal
580
+ setHandler(cancelSignal, () => {
581
+ cancelled = true;
582
+ status = 'cancelled';
583
+ });
584
+
585
+ // Handle status query
586
+ setHandler(getStatusQuery, () => status);
587
+
588
+ // Workflow logic with cancellation support
589
+ if (cancelled) return;
590
+
591
+ // Process order...
592
+ status = 'completed';
593
+ }
594
+ ```
595
+
596
+ ## 🌐 Temporal Cloud Integration
327
597
 
328
- - **🎯 NestJS First** - Built specifically for NestJS with familiar patterns
329
- - **🔄 Auto-Discovery** - No manual registration, just use decorators
330
- - **📅 Built-in Scheduling** - Cron jobs that integrate with workflows
331
- - **🔧 Production Ready** - Health checks, monitoring, graceful shutdowns
332
- - **📚 Easy to Learn** - Familiar NestJS service patterns
333
- - **🚀 Scalable** - Client-only, worker-only, or unified deployments
598
+ For Temporal Cloud deployments:
599
+
600
+ ```typescript
601
+ TemporalModule.register({
602
+ connection: {
603
+ address: 'your-namespace.account.tmprl.cloud:7233',
604
+ namespace: 'your-namespace.account',
605
+ tls: true,
606
+ apiKey: process.env.TEMPORAL_API_KEY,
607
+ metadata: {
608
+ 'temporal-namespace': 'your-namespace.account'
609
+ }
610
+ },
611
+ taskQueue: 'production-queue',
612
+ worker: {
613
+ workflowBundle: require('../workflows/bundle'),
614
+ workerOptions: WORKER_PRESETS.PRODUCTION_BALANCED
615
+ }
616
+ })
617
+ ```
618
+
619
+ ## 📋 Best Practices
620
+
621
+ ### 1. **Activity Design**
622
+ - Keep activities idempotent
623
+ - Use proper timeouts and retry policies
624
+ - Handle errors gracefully
625
+ - Use dependency injection for testability
626
+
627
+ ### 2. **Workflow Organization**
628
+ - Separate workflow files from activities
629
+ - Use TypeScript for type safety
630
+ - Keep workflows deterministic
631
+ - Bundle workflows for production
632
+
633
+ ### 3. **Configuration Management**
634
+ - Use environment variables for connection settings
635
+ - Separate configs for different environments
636
+ - Use async configuration for dynamic settings
637
+ - Validate configuration at startup
638
+
639
+ ### 4. **Monitoring & Observability**
640
+ - Implement health checks
641
+ - Monitor worker status
642
+ - Track schedule execution
643
+ - Use structured logging
644
+
645
+ ### 5. **Production Deployment**
646
+ - Use pre-bundled workflows
647
+ - Configure appropriate worker limits
648
+ - Enable TLS for security
649
+ - Implement graceful shutdowns
650
+
651
+ ## 📚 API Reference
652
+
653
+ ### Decorators
654
+
655
+ - `@Activity()` - Mark a class as containing activities
656
+ - `@ActivityMethod(options?)` - Define an activity method
657
+ - `@Scheduled(options)` - Schedule a workflow with full options
658
+ - `@Cron(expression, options?)` - Schedule using cron expression
659
+ - `@Interval(interval, options?)` - Schedule using interval
660
+
661
+ ### Services
662
+
663
+ - `TemporalService` - Main service for all operations
664
+ - `TemporalClientService` - Client-only operations
665
+ - `TemporalActivityService` - Activity management
666
+ - `TemporalSchedulesService` - Schedule management
667
+ - `TemporalWorkerManagerService` - Worker lifecycle
668
+
669
+ ### Constants
670
+
671
+ - `CRON_EXPRESSIONS` - Common cron patterns
672
+ - `INTERVAL_EXPRESSIONS` - Common interval patterns
673
+ - `WORKER_PRESETS` - Environment-specific worker configs
674
+ - `RETRY_POLICIES` - Common retry patterns
675
+ - `TIMEOUTS` - Common timeout values
334
676
 
335
677
  ## 🤝 Contributing
336
678
 
337
- Contributions welcome! Please read our [Contributing Guide](./CONTRIBUTING.md) for details.
679
+ Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
338
680
 
339
681
  ## 📄 License
340
682
 
341
- MIT License - see [LICENSE](LICENSE) file for details.
683
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
684
+
685
+ ## 🙏 Acknowledgments
686
+
687
+ - [Temporal.io](https://temporal.io/) for the amazing workflow engine
688
+ - [NestJS](https://nestjs.com/) for the fantastic framework
689
+ - The TypeScript community for excellent tooling
690
+
691
+ ---
692
+
693
+ Built with ❤️ for the NestJS and Temporal communities