nest-scheduler-engine 1.0.0

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 (85) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +374 -0
  3. package/dist/decorators/event-handler.decorator.d.ts +2 -0
  4. package/dist/decorators/event-handler.decorator.js +12 -0
  5. package/dist/decorators/event-handler.decorator.js.map +1 -0
  6. package/dist/index.d.ts +16 -0
  7. package/dist/index.js +25 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/interfaces/cache-adapter.interface.d.ts +7 -0
  10. package/dist/interfaces/cache-adapter.interface.js +3 -0
  11. package/dist/interfaces/cache-adapter.interface.js.map +1 -0
  12. package/dist/interfaces/config.interface.d.ts +43 -0
  13. package/dist/interfaces/config.interface.js +3 -0
  14. package/dist/interfaces/config.interface.js.map +1 -0
  15. package/dist/interfaces/database-adapter.interface.d.ts +8 -0
  16. package/dist/interfaces/database-adapter.interface.js +3 -0
  17. package/dist/interfaces/database-adapter.interface.js.map +1 -0
  18. package/dist/interfaces/event-handler.interface.d.ts +15 -0
  19. package/dist/interfaces/event-handler.interface.js +3 -0
  20. package/dist/interfaces/event-handler.interface.js.map +1 -0
  21. package/dist/interfaces/index.d.ts +6 -0
  22. package/dist/interfaces/index.js +23 -0
  23. package/dist/interfaces/index.js.map +1 -0
  24. package/dist/interfaces/logger-adapter.interface.d.ts +6 -0
  25. package/dist/interfaces/logger-adapter.interface.js +3 -0
  26. package/dist/interfaces/logger-adapter.interface.js.map +1 -0
  27. package/dist/interfaces/queue-adapter.interface.d.ts +14 -0
  28. package/dist/interfaces/queue-adapter.interface.js +3 -0
  29. package/dist/interfaces/queue-adapter.interface.js.map +1 -0
  30. package/dist/migrations/index.d.ts +9 -0
  31. package/dist/migrations/index.js +142 -0
  32. package/dist/migrations/index.js.map +1 -0
  33. package/dist/models/dead-letter.model.d.ts +8 -0
  34. package/dist/models/dead-letter.model.js +10 -0
  35. package/dist/models/dead-letter.model.js.map +1 -0
  36. package/dist/models/event-execution.model.d.ts +13 -0
  37. package/dist/models/event-execution.model.js +19 -0
  38. package/dist/models/event-execution.model.js.map +1 -0
  39. package/dist/models/event-instance.model.d.ts +22 -0
  40. package/dist/models/event-instance.model.js +22 -0
  41. package/dist/models/event-instance.model.js.map +1 -0
  42. package/dist/models/event-type.model.d.ts +14 -0
  43. package/dist/models/event-type.model.js +17 -0
  44. package/dist/models/event-type.model.js.map +1 -0
  45. package/dist/models/index.d.ts +4 -0
  46. package/dist/models/index.js +21 -0
  47. package/dist/models/index.js.map +1 -0
  48. package/dist/registry/handler.registry.d.ts +18 -0
  49. package/dist/registry/handler.registry.js +69 -0
  50. package/dist/registry/handler.registry.js.map +1 -0
  51. package/dist/scheduler.module.d.ts +10 -0
  52. package/dist/scheduler.module.js +183 -0
  53. package/dist/scheduler.module.js.map +1 -0
  54. package/dist/services/dispatcher.service.d.ts +26 -0
  55. package/dist/services/dispatcher.service.js +250 -0
  56. package/dist/services/dispatcher.service.js.map +1 -0
  57. package/dist/services/event-manager.service.d.ts +31 -0
  58. package/dist/services/event-manager.service.js +319 -0
  59. package/dist/services/event-manager.service.js.map +1 -0
  60. package/dist/services/polling-engine.service.d.ts +23 -0
  61. package/dist/services/polling-engine.service.js +162 -0
  62. package/dist/services/polling-engine.service.js.map +1 -0
  63. package/dist/services/scheduler.service.d.ts +24 -0
  64. package/dist/services/scheduler.service.js +67 -0
  65. package/dist/services/scheduler.service.js.map +1 -0
  66. package/dist/tsconfig.tsbuildinfo +1 -0
  67. package/dist/types/enums.d.ts +21 -0
  68. package/dist/types/enums.js +29 -0
  69. package/dist/types/enums.js.map +1 -0
  70. package/dist/types/index.d.ts +2 -0
  71. package/dist/types/index.js +19 -0
  72. package/dist/types/index.js.map +1 -0
  73. package/dist/types/inputs.d.ts +33 -0
  74. package/dist/types/inputs.js +3 -0
  75. package/dist/types/inputs.js.map +1 -0
  76. package/dist/utils/console-logger.d.ts +7 -0
  77. package/dist/utils/console-logger.js +19 -0
  78. package/dist/utils/console-logger.js.map +1 -0
  79. package/dist/utils/retry-helper.d.ts +3 -0
  80. package/dist/utils/retry-helper.js +16 -0
  81. package/dist/utils/retry-helper.js.map +1 -0
  82. package/dist/utils/rrule-helper.d.ts +2 -0
  83. package/dist/utils/rrule-helper.js +24 -0
  84. package/dist/utils/rrule-helper.js.map +1 -0
  85. package/package.json +50 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Your Organization
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,374 @@
1
+ # @your-org/scheduler-engine
2
+
3
+ A generic, event-type-driven scheduling engine for NestJS applications. This package provides a flexible and scalable solution for scheduling and executing recurring and one-time events with built-in retry logic, dead-letter handling, and RRULE support (RFC 5545).
4
+
5
+ ## Features
6
+
7
+ - **Zero Infrastructure Ownership** - Package never creates DB connections, queues, or caches. All are injected via adapters.
8
+ - **Adapter Pattern** - Works with any PostgreSQL client (pg, TypeORM, Knex, Prisma) and queue system (SQS, BullMQ, RabbitMQ).
9
+ - **Ships Database Migrations** - Includes migration files that consumers run against their own database.
10
+ - **Data-Driven Scheduling** - All scheduling decisions from DB, no hardcoded schedules.
11
+ - **RRULE Support** - RFC 5545 compliant recurrence rules for complex recurring schedules.
12
+ - **Built-in Retry & Dead-Letter** - Configurable retry policies with exponential backoff and dead-letter queue.
13
+ - **Framework-Agnostic Core** - Core logic is framework-agnostic with a NestJS wrapper module.
14
+ - **Horizontal Scalability** - Multiple instances can run concurrently with database-level locking.
15
+ - **Observability Hooks** - Lifecycle hooks for monitoring, alerting, and audit logging.
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install @your-org/scheduler-engine
21
+
22
+ # Peer dependencies (consumer must install)
23
+ npm install @nestjs/core @nestjs/common rxjs
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ### 1. Run Migrations
29
+
30
+ First, export and run the migrations against your database:
31
+
32
+ ```typescript
33
+ import { getMigrations } from '@your-org/scheduler-engine';
34
+
35
+ const migrations = getMigrations({ tablePrefix: 'scheduler_' });
36
+
37
+ // Use your migration tool (Knex, TypeORM, Flyway, etc.)
38
+ // migrations is an array of { version, up, down }
39
+ ```
40
+
41
+ Or use the CLI helper:
42
+
43
+ ```bash
44
+ npx scheduler-engine migrations:export --output ./migrations/
45
+ ```
46
+
47
+ ### 2. Implement Adapters
48
+
49
+ Create adapter implementations for your infrastructure:
50
+
51
+ ```typescript
52
+ // adapters/pg-database.adapter.ts
53
+ import { Injectable } from '@nestjs/common';
54
+ import { Pool } from 'pg';
55
+ import { IDatabaseAdapter, ITransactionClient } from '@your-org/scheduler-engine';
56
+
57
+ @Injectable()
58
+ export class PgDatabaseAdapter implements IDatabaseAdapter {
59
+ constructor(private readonly pool: Pool) {}
60
+
61
+ async query<T = any>(sql: string, params?: any[]): Promise<T[]> {
62
+ const result = await this.pool.query(sql, params);
63
+ return result.rows;
64
+ }
65
+
66
+ async transaction<T>(fn: (trx: ITransactionClient) => Promise<T>): Promise<T> {
67
+ const client = await this.pool.connect();
68
+ try {
69
+ await client.query('BEGIN');
70
+ const trx = {
71
+ query: async <T = any>(sql: string, params?: any[]) => {
72
+ const result = await client.query(sql, params);
73
+ return result.rows;
74
+ },
75
+ };
76
+ const result = await fn(trx);
77
+ await client.query('COMMIT');
78
+ return result;
79
+ } catch (error) {
80
+ await client.query('ROLLBACK');
81
+ throw error;
82
+ } finally {
83
+ client.release();
84
+ }
85
+ }
86
+
87
+ async ping(): Promise<boolean> {
88
+ try {
89
+ await this.pool.query('SELECT 1');
90
+ return true;
91
+ } catch {
92
+ return false;
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ ```typescript
99
+ // adapters/sqs-queue.adapter.ts
100
+ import { Injectable } from '@nestjs/common';
101
+ import { SQSClient, SendMessageCommand } from '@aws-sdk/client-sqs';
102
+ import { IQueueAdapter, QueueMessage } from '@your-org/scheduler-engine';
103
+
104
+ @Injectable()
105
+ export class SqsQueueAdapter implements IQueueAdapter {
106
+ constructor(
107
+ private readonly sqs: SQSClient,
108
+ private readonly queueUrl: string,
109
+ ) {}
110
+
111
+ async publish(message: QueueMessage): Promise<void> {
112
+ await this.sqs.send(new SendMessageCommand({
113
+ QueueUrl: this.queueUrl,
114
+ MessageBody: JSON.stringify(message),
115
+ }));
116
+ }
117
+
118
+ async subscribe(handler: (msg: QueueMessage) => Promise<void>): Promise<void> {
119
+ // Implement SQS polling and handler invocation
120
+ // This is typically done in a separate worker process
121
+ }
122
+
123
+ async ack(messageId: string): Promise<void> {
124
+ // Delete message from SQS
125
+ }
126
+
127
+ async nack(messageId: string): Promise<void> {
128
+ // Change message visibility or move to DLQ
129
+ }
130
+ }
131
+ ```
132
+
133
+ ### 3. Register the Module
134
+
135
+ ```typescript
136
+ // app.module.ts
137
+ import { Module } from '@nestjs/common';
138
+ import { SchedulerModule } from '@your-org/scheduler-engine';
139
+ import { PgDatabaseAdapter } from './adapters/pg-database.adapter';
140
+ import { SqsQueueAdapter } from './adapters/sqs-queue.adapter';
141
+ import { Pool } from 'pg';
142
+
143
+ @Module({
144
+ imports: [
145
+ SchedulerModule.forRoot({
146
+ // Required adapters
147
+ database: {
148
+ useFactory: (pool: Pool) => new PgDatabaseAdapter(pool),
149
+ inject: [Pool],
150
+ },
151
+ queue: {
152
+ useFactory: (sqs: SQSClient) => new SqsQueueAdapter(sqs, process.env.QUEUE_URL),
153
+ inject: [SQSClient],
154
+ },
155
+
156
+ // Optional configuration
157
+ config: {
158
+ pollingIntervalMs: 5000,
159
+ lockDurationMs: 30000,
160
+ batchSize: 50,
161
+ concurrency: 10,
162
+ deadLetterEnabled: true,
163
+ tablePrefix: 'scheduler_',
164
+ },
165
+
166
+ // Optional hooks
167
+ hooks: {
168
+ onEventScheduled: async (event) => {
169
+ console.log('Event scheduled:', event.id);
170
+ },
171
+ onEventFailed: async (event, error, retryCount) => {
172
+ console.error('Event failed:', event.id, error);
173
+ },
174
+ onEventDeadLettered: async (event) => {
175
+ // Send alert to oncall
176
+ },
177
+ },
178
+ }),
179
+ ],
180
+ providers: [
181
+ // Your event handlers
182
+ ReminderHandler,
183
+ DataSyncHandler,
184
+ ReportHandler,
185
+ ],
186
+ })
187
+ export class AppModule {}
188
+ ```
189
+
190
+ ### 4. Create Event Handlers
191
+
192
+ ```typescript
193
+ // handlers/reminder.handler.ts
194
+ import { Injectable } from '@nestjs/common';
195
+ import { EventHandler, IEventHandler, ExecutionContext, HandlerResult } from '@your-org/scheduler-engine';
196
+
197
+ @Injectable()
198
+ @EventHandler('REMINDER_NOTIFICATION')
199
+ export class ReminderHandler implements IEventHandler {
200
+ readonly eventType = 'REMINDER_NOTIFICATION';
201
+
202
+ constructor(
203
+ private readonly notificationService: NotificationService,
204
+ ) {}
205
+
206
+ async handle(payload: Record<string, any>, ctx: ExecutionContext): Promise<HandlerResult> {
207
+ try {
208
+ await this.notificationService.send(payload.userId, payload.message);
209
+ return { success: true };
210
+ } catch (error) {
211
+ return {
212
+ success: false,
213
+ error: error instanceof Error ? error.message : String(error),
214
+ };
215
+ }
216
+ }
217
+ }
218
+ ```
219
+
220
+ ### 5. Schedule Events
221
+
222
+ ```typescript
223
+ // some.service.ts
224
+ import { Injectable } from '@nestjs/common';
225
+ import { SchedulerService, ScheduleType } from '@your-org/scheduler-engine';
226
+
227
+ @Injectable()
228
+ export class NotificationService {
229
+ constructor(private readonly scheduler: SchedulerService) {}
230
+
231
+ async scheduleReminder(userId: string, message: string, sendAt: Date) {
232
+ // First, create the event type (usually done once on app startup)
233
+ await this.scheduler.createEventType({
234
+ name: 'REMINDER_NOTIFICATION',
235
+ description: 'Send reminder notifications to users',
236
+ retryPolicy: {
237
+ maxRetries: 3,
238
+ delayMs: 5000,
239
+ backoff: 'exponential',
240
+ },
241
+ });
242
+
243
+ // Schedule a one-time event
244
+ const event = await this.scheduler.scheduleEvent({
245
+ eventTypeName: 'REMINDER_NOTIFICATION',
246
+ payload: { userId, message },
247
+ scheduleType: ScheduleType.ONE_TIME,
248
+ scheduledAt: sendAt,
249
+ });
250
+
251
+ return event;
252
+ }
253
+
254
+ async scheduleRecurringReport() {
255
+ // Schedule a recurring event using RRULE
256
+ const event = await this.scheduler.scheduleEvent({
257
+ eventTypeName: 'WEEKLY_REPORT',
258
+ payload: { reportType: 'sales' },
259
+ scheduleType: ScheduleType.RECURRING,
260
+ rrule: 'FREQ=WEEKLY;BYDAY=MO;BYHOUR=9;BYMINUTE=0', // Every Monday at 9:00 AM
261
+ });
262
+
263
+ return event;
264
+ }
265
+ }
266
+ ```
267
+
268
+ ## API Reference
269
+
270
+ ### SchedulerService
271
+
272
+ Main service for interacting with the scheduler.
273
+
274
+ #### Event Type Management
275
+
276
+ - `createEventType(input: CreateEventTypeInput): Promise<EventType>`
277
+ - `getEventType(id: string): Promise<EventType | null>`
278
+ - `getEventTypeByName(name: string): Promise<EventType | null>`
279
+ - `listEventTypes(): Promise<EventType[]>`
280
+ - `deleteEventType(id: string): Promise<void>`
281
+
282
+ #### Event Instance Management
283
+
284
+ - `scheduleEvent(input: ScheduleEventInput): Promise<EventInstance>`
285
+ - `getEvent(id: string): Promise<EventInstance | null>`
286
+ - `listEvents(filters?: EventFilters): Promise<PaginatedResult<EventInstance>>`
287
+ - `pauseEvent(id: string): Promise<EventInstance>`
288
+ - `resumeEvent(id: string): Promise<EventInstance>`
289
+ - `cancelEvent(id: string): Promise<void>`
290
+
291
+ #### Execution History
292
+
293
+ - `getExecutions(eventId: string): Promise<EventExecution[]>`
294
+
295
+ #### Dead Letters
296
+
297
+ - `listDeadLetters(): Promise<DeadLetter[]>`
298
+ - `retryDeadLetter(id: string): Promise<EventInstance>`
299
+
300
+ ## Deployment Modes
301
+
302
+ The package supports three deployment modes:
303
+
304
+ ### Combined Mode (Default)
305
+
306
+ Polls + dispatches + consumes in one process.
307
+
308
+ ```typescript
309
+ config: {
310
+ workerMode: true, // default
311
+ }
312
+ ```
313
+
314
+ ### Poller Only
315
+
316
+ Only polls and dispatches to queue. Separate workers consume.
317
+
318
+ ```typescript
319
+ config: {
320
+ pollerOnly: true,
321
+ }
322
+ ```
323
+
324
+ ### Worker Only
325
+
326
+ Only consumes from queue. Separate poller dispatches.
327
+
328
+ ```typescript
329
+ config: {
330
+ workerMode: true,
331
+ pollerOnly: false,
332
+ }
333
+ ```
334
+
335
+ ## RRULE Examples
336
+
337
+ ```typescript
338
+ // Every day at 10:00 AM
339
+ rrule: 'FREQ=DAILY;BYHOUR=10;BYMINUTE=0'
340
+
341
+ // Every Monday and Friday at 9:00 AM
342
+ rrule: 'FREQ=WEEKLY;BYDAY=MO,FR;BYHOUR=9;BYMINUTE=0'
343
+
344
+ // Last day of every month at 11:59 PM
345
+ rrule: 'FREQ=MONTHLY;BYMONTHDAY=-1;BYHOUR=23;BYMINUTE=59'
346
+
347
+ // Every 2 hours
348
+ rrule: 'FREQ=HOURLY;INTERVAL=2'
349
+ ```
350
+
351
+ See [RFC 5545](https://tools.ietf.org/html/rfc5545) for full RRULE specification.
352
+
353
+ ## Database Schema
354
+
355
+ The package creates the following tables:
356
+
357
+ - `event_types` - Event type definitions with retry policies
358
+ - `event_instances` - Scheduled event instances
359
+ - `event_executions` - Execution history for audit and debugging
360
+ - `dead_letters` - Failed events that exhausted retries
361
+
362
+ All tables support an optional prefix via `tablePrefix` config option.
363
+
364
+ ## License
365
+
366
+ MIT
367
+
368
+ ## Contributing
369
+
370
+ Contributions are welcome! Please see CONTRIBUTING.md for details.
371
+
372
+ ## Support
373
+
374
+ For issues and feature requests, please use the GitHub issue tracker.
@@ -0,0 +1,2 @@
1
+ export declare const EVENT_HANDLER_METADATA = "scheduler:event_handler";
2
+ export declare function EventHandler(eventType: string): ClassDecorator;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EVENT_HANDLER_METADATA = void 0;
4
+ exports.EventHandler = EventHandler;
5
+ const common_1 = require("@nestjs/common");
6
+ exports.EVENT_HANDLER_METADATA = "scheduler:event_handler";
7
+ function EventHandler(eventType) {
8
+ return (target) => {
9
+ (0, common_1.SetMetadata)(exports.EVENT_HANDLER_METADATA, eventType)(target);
10
+ };
11
+ }
12
+ //# sourceMappingURL=event-handler.decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-handler.decorator.js","sourceRoot":"","sources":["../../src/decorators/event-handler.decorator.ts"],"names":[],"mappings":";;;AAWA,oCAIC;AAfD,2CAA6C;AAKhC,QAAA,sBAAsB,GAAG,yBAAyB,CAAC;AAMhE,SAAgB,YAAY,CAAC,SAAiB;IAC5C,OAAO,CAAC,MAAW,EAAE,EAAE;QACrB,IAAA,oBAAW,EAAC,8BAAsB,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;IACzD,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ export { SchedulerModule } from './scheduler.module';
2
+ export { SchedulerService } from './services/scheduler.service';
3
+ export { EventHandler } from './decorators/event-handler.decorator';
4
+ export type { IDatabaseAdapter, ITransactionClient, } from './interfaces/database-adapter.interface';
5
+ export type { IQueueAdapter, QueueMessage, } from './interfaces/queue-adapter.interface';
6
+ export type { ILoggerAdapter } from './interfaces/logger-adapter.interface';
7
+ export type { ICacheAdapter } from './interfaces/cache-adapter.interface';
8
+ export type { IEventHandler, HandlerResult, ExecutionContext, } from './interfaces/event-handler.interface';
9
+ export type { SchedulerConfig, SchedulerHooks, SchedulerModuleOptions, SchedulerModuleAsyncOptions, AdapterProvider, } from './interfaces/config.interface';
10
+ export { EventStatus, ScheduleType, RetryBackoff, ExecutionStatus, } from './types/enums';
11
+ export type { RetryPolicy, CreateEventTypeInput, ScheduleEventInput, EventFilters, PaginatedResult, } from './types/inputs';
12
+ export { EventType } from './models/event-type.model';
13
+ export { EventInstance } from './models/event-instance.model';
14
+ export { EventExecution } from './models/event-execution.model';
15
+ export { DeadLetter } from './models/dead-letter.model';
16
+ export { getMigrations, Migration, MigrationOptions } from './migrations';
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getMigrations = exports.DeadLetter = exports.EventExecution = exports.EventInstance = exports.EventType = exports.ExecutionStatus = exports.RetryBackoff = exports.ScheduleType = exports.EventStatus = exports.EventHandler = exports.SchedulerService = exports.SchedulerModule = void 0;
4
+ var scheduler_module_1 = require("./scheduler.module");
5
+ Object.defineProperty(exports, "SchedulerModule", { enumerable: true, get: function () { return scheduler_module_1.SchedulerModule; } });
6
+ var scheduler_service_1 = require("./services/scheduler.service");
7
+ Object.defineProperty(exports, "SchedulerService", { enumerable: true, get: function () { return scheduler_service_1.SchedulerService; } });
8
+ var event_handler_decorator_1 = require("./decorators/event-handler.decorator");
9
+ Object.defineProperty(exports, "EventHandler", { enumerable: true, get: function () { return event_handler_decorator_1.EventHandler; } });
10
+ var enums_1 = require("./types/enums");
11
+ Object.defineProperty(exports, "EventStatus", { enumerable: true, get: function () { return enums_1.EventStatus; } });
12
+ Object.defineProperty(exports, "ScheduleType", { enumerable: true, get: function () { return enums_1.ScheduleType; } });
13
+ Object.defineProperty(exports, "RetryBackoff", { enumerable: true, get: function () { return enums_1.RetryBackoff; } });
14
+ Object.defineProperty(exports, "ExecutionStatus", { enumerable: true, get: function () { return enums_1.ExecutionStatus; } });
15
+ var event_type_model_1 = require("./models/event-type.model");
16
+ Object.defineProperty(exports, "EventType", { enumerable: true, get: function () { return event_type_model_1.EventType; } });
17
+ var event_instance_model_1 = require("./models/event-instance.model");
18
+ Object.defineProperty(exports, "EventInstance", { enumerable: true, get: function () { return event_instance_model_1.EventInstance; } });
19
+ var event_execution_model_1 = require("./models/event-execution.model");
20
+ Object.defineProperty(exports, "EventExecution", { enumerable: true, get: function () { return event_execution_model_1.EventExecution; } });
21
+ var dead_letter_model_1 = require("./models/dead-letter.model");
22
+ Object.defineProperty(exports, "DeadLetter", { enumerable: true, get: function () { return dead_letter_model_1.DeadLetter; } });
23
+ var migrations_1 = require("./migrations");
24
+ Object.defineProperty(exports, "getMigrations", { enumerable: true, get: function () { return migrations_1.getMigrations; } });
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,uDAAqD;AAA5C,mHAAA,eAAe,OAAA;AAGxB,kEAAgE;AAAvD,qHAAA,gBAAgB,OAAA;AAGzB,gFAAoE;AAA3D,uHAAA,YAAY,OAAA;AAgCrB,uCAKuB;AAJrB,oGAAA,WAAW,OAAA;AACX,qGAAA,YAAY,OAAA;AACZ,qGAAA,YAAY,OAAA;AACZ,wGAAA,eAAe,OAAA;AAYjB,8DAAsD;AAA7C,6GAAA,SAAS,OAAA;AAClB,sEAA8D;AAArD,qHAAA,aAAa,OAAA;AACtB,wEAAgE;AAAvD,uHAAA,cAAc,OAAA;AACvB,gEAAwD;AAA/C,+GAAA,UAAU,OAAA;AAGnB,2CAA0E;AAAjE,2GAAA,aAAa,OAAA"}
@@ -0,0 +1,7 @@
1
+ export interface ICacheAdapter {
2
+ get(key: string): Promise<any | null>;
3
+ set(key: string, value: any, ttlMs?: number): Promise<void>;
4
+ del(key: string): Promise<void>;
5
+ acquireLock(key: string, ttlMs: number): Promise<boolean>;
6
+ releaseLock(key: string): Promise<void>;
7
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=cache-adapter.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-adapter.interface.js","sourceRoot":"","sources":["../../src/interfaces/cache-adapter.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,43 @@
1
+ import { ModuleMetadata, Type } from "@nestjs/common";
2
+ import { IDatabaseAdapter } from "./database-adapter.interface";
3
+ import { IQueueAdapter } from "./queue-adapter.interface";
4
+ import { ILoggerAdapter } from "./logger-adapter.interface";
5
+ import { ICacheAdapter } from "./cache-adapter.interface";
6
+ import { HandlerResult, ExecutionContext } from "./event-handler.interface";
7
+ export interface SchedulerConfig {
8
+ pollingIntervalMs?: number;
9
+ lockDurationMs?: number;
10
+ batchSize?: number;
11
+ concurrency?: number;
12
+ deadLetterEnabled?: boolean;
13
+ tablePrefix?: string;
14
+ workerMode?: boolean;
15
+ pollerOnly?: boolean;
16
+ }
17
+ export interface SchedulerHooks {
18
+ onEventScheduled?: (event: any) => Promise<void>;
19
+ onEventExecuting?: (event: any, ctx: ExecutionContext) => Promise<void>;
20
+ onEventCompleted?: (event: any, result: HandlerResult) => Promise<void>;
21
+ onEventFailed?: (event: any, error: any, retryCount: number) => Promise<void>;
22
+ onEventDeadLettered?: (event: any) => Promise<void>;
23
+ onEventPaused?: (event: any) => Promise<void>;
24
+ onEventResumed?: (event: any) => Promise<void>;
25
+ }
26
+ export interface AdapterProvider<T = any> {
27
+ useClass?: Type<T>;
28
+ useFactory?: (...args: any[]) => T | Promise<T>;
29
+ useExisting?: Type<T>;
30
+ inject?: any[];
31
+ }
32
+ export interface SchedulerModuleOptions {
33
+ database: AdapterProvider<IDatabaseAdapter>;
34
+ queue: AdapterProvider<IQueueAdapter>;
35
+ logger?: AdapterProvider<ILoggerAdapter>;
36
+ cache?: AdapterProvider<ICacheAdapter>;
37
+ config?: SchedulerConfig;
38
+ hooks?: SchedulerHooks;
39
+ }
40
+ export interface SchedulerModuleAsyncOptions extends Pick<ModuleMetadata, "imports"> {
41
+ useFactory?: (...args: any[]) => Promise<SchedulerModuleOptions> | SchedulerModuleOptions;
42
+ inject?: any[];
43
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=config.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.interface.js","sourceRoot":"","sources":["../../src/interfaces/config.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ export interface ITransactionClient {
2
+ query<T = any>(sql: string, params?: any[]): Promise<T[]>;
3
+ }
4
+ export interface IDatabaseAdapter {
5
+ query<T = any>(sql: string, params?: any[]): Promise<T[]>;
6
+ transaction<T>(fn: (trx: ITransactionClient) => Promise<T>): Promise<T>;
7
+ ping(): Promise<boolean>;
8
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=database-adapter.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-adapter.interface.js","sourceRoot":"","sources":["../../src/interfaces/database-adapter.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ export interface ExecutionContext {
2
+ executionId: string;
3
+ eventInstanceId: string;
4
+ attempt: number;
5
+ scheduledAt: Date;
6
+ }
7
+ export interface HandlerResult {
8
+ success: boolean;
9
+ data?: any;
10
+ error?: string;
11
+ }
12
+ export interface IEventHandler {
13
+ readonly eventType: string;
14
+ handle(payload: Record<string, any>, ctx: ExecutionContext): Promise<HandlerResult>;
15
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=event-handler.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-handler.interface.js","sourceRoot":"","sources":["../../src/interfaces/event-handler.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ export * from './database-adapter.interface';
2
+ export * from './queue-adapter.interface';
3
+ export * from './logger-adapter.interface';
4
+ export * from './cache-adapter.interface';
5
+ export * from './event-handler.interface';
6
+ export * from './config.interface';
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./database-adapter.interface"), exports);
18
+ __exportStar(require("./queue-adapter.interface"), exports);
19
+ __exportStar(require("./logger-adapter.interface"), exports);
20
+ __exportStar(require("./cache-adapter.interface"), exports);
21
+ __exportStar(require("./event-handler.interface"), exports);
22
+ __exportStar(require("./config.interface"), exports);
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/interfaces/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+DAA6C;AAC7C,4DAA0C;AAC1C,6DAA2C;AAC3C,4DAA0C;AAC1C,4DAA0C;AAC1C,qDAAmC"}
@@ -0,0 +1,6 @@
1
+ export interface ILoggerAdapter {
2
+ info(message: string, meta?: Record<string, any>): void;
3
+ warn(message: string, meta?: Record<string, any>): void;
4
+ error(message: string, meta?: Record<string, any>): void;
5
+ debug(message: string, meta?: Record<string, any>): void;
6
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=logger-adapter.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger-adapter.interface.js","sourceRoot":"","sources":["../../src/interfaces/logger-adapter.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ export interface QueueMessage {
2
+ id: string;
3
+ eventInstanceId: string;
4
+ eventType: string;
5
+ payload: Record<string, any>;
6
+ attempt: number;
7
+ scheduledAt: Date;
8
+ }
9
+ export interface IQueueAdapter {
10
+ publish(message: QueueMessage): Promise<void>;
11
+ subscribe(handler: (msg: QueueMessage) => Promise<void>): Promise<void>;
12
+ ack(messageId: string): Promise<void>;
13
+ nack(messageId: string): Promise<void>;
14
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=queue-adapter.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-adapter.interface.js","sourceRoot":"","sources":["../../src/interfaces/queue-adapter.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ export interface Migration {
2
+ version: string;
3
+ up: string;
4
+ down: string;
5
+ }
6
+ export interface MigrationOptions {
7
+ tablePrefix?: string;
8
+ }
9
+ export declare function getMigrations(options?: MigrationOptions): Migration[];