@monque/tsed 0.1.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.
package/dist/index.cjs ADDED
@@ -0,0 +1,712 @@
1
+ let _tsed_core = require("@tsed/core");
2
+ let _tsed_di = require("@tsed/di");
3
+ let _monque_core = require("@monque/core");
4
+ let mongodb = require("mongodb");
5
+
6
+ //#region src/config/config.ts
7
+ /**
8
+ * Validate that exactly one database resolution strategy is provided.
9
+ *
10
+ * @param config - The configuration to validate.
11
+ * @throws Error if zero or multiple strategies are provided.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * validateDatabaseConfig({ db: mongoDb }); // OK
16
+ * validateDatabaseConfig({}); // throws
17
+ * validateDatabaseConfig({ db: mongoDb, dbFactory: fn }); // throws
18
+ * ```
19
+ */
20
+ function validateDatabaseConfig(config) {
21
+ const strategies = [
22
+ config.db,
23
+ config.dbFactory,
24
+ config.dbToken
25
+ ].filter(Boolean);
26
+ if (strategies.length === 0) throw new Error("MonqueTsedConfig requires exactly one of 'db', 'dbFactory', or 'dbToken' to be set");
27
+ if (strategies.length > 1) throw new Error("MonqueTsedConfig accepts only one of 'db', 'dbFactory', or 'dbToken' - multiple were provided");
28
+ }
29
+
30
+ //#endregion
31
+ //#region src/constants/constants.ts
32
+ /**
33
+ * Symbol used to store decorator metadata on class constructors.
34
+ *
35
+ * Used by @WorkerController, @Worker, and @Cron decorators to attach
36
+ * metadata that is later collected by MonqueModule during initialization.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * Store.from(Class).set(MONQUE, metadata);
41
+ * ```
42
+ */
43
+ const MONQUE = Symbol.for("monque");
44
+
45
+ //#endregion
46
+ //#region src/constants/types.ts
47
+ /**
48
+ * Provider type constants for DI scanning.
49
+ *
50
+ * These constants are used to categorize providers registered with Ts.ED's
51
+ * dependency injection container, enabling MonqueModule to discover and
52
+ * register workers automatically.
53
+ *
54
+ * Note: Using string constants with `as const` instead of enums per
55
+ * Constitution guidelines.
56
+ */
57
+ const ProviderTypes = {
58
+ WORKER_CONTROLLER: "monque:worker-controller",
59
+ CRON: "monque:cron"
60
+ };
61
+
62
+ //#endregion
63
+ //#region src/decorators/cron.ts
64
+ /**
65
+ * Method decorator that registers a method as a scheduled cron job.
66
+ *
67
+ * @param pattern - Cron expression (e.g., "* * * * *", "@daily")
68
+ * @param options - Optional cron configuration (name, timezone, etc.)
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * @WorkerController()
73
+ * class ReportWorkers {
74
+ * @Cron("@daily", { timezone: "UTC" })
75
+ * async generateDailyReport() {
76
+ * // ...
77
+ * }
78
+ * }
79
+ * ```
80
+ */
81
+ function Cron(pattern, options) {
82
+ return (target, propertyKey, _descriptor) => {
83
+ const methodName = String(propertyKey);
84
+ const cronMetadata = {
85
+ pattern,
86
+ name: options?.name || methodName,
87
+ method: methodName,
88
+ opts: options || {}
89
+ };
90
+ const targetConstructor = target.constructor;
91
+ const store = _tsed_core.Store.from(targetConstructor);
92
+ const existing = store.get(MONQUE) || {
93
+ type: "controller",
94
+ workers: [],
95
+ cronJobs: []
96
+ };
97
+ const cronJobs = [...existing.cronJobs || [], cronMetadata];
98
+ store.set(MONQUE, {
99
+ ...existing,
100
+ cronJobs
101
+ });
102
+ };
103
+ }
104
+
105
+ //#endregion
106
+ //#region src/decorators/worker.ts
107
+ /**
108
+ * @Worker method decorator
109
+ *
110
+ * Registers a method as a job handler. The method will be called when a job
111
+ * with the matching name is picked up for processing.
112
+ *
113
+ * @param name - Job name (combined with controller namespace if present).
114
+ * @param options - Worker configuration options.
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * @WorkerController("notifications")
119
+ * export class NotificationWorkers {
120
+ * @Worker("push", { concurrency: 10 })
121
+ * async sendPush(job: Job<PushPayload>) {
122
+ * await pushService.send(job.data);
123
+ * }
124
+ * }
125
+ * ```
126
+ */
127
+ /**
128
+ * Method decorator that registers a method as a job handler.
129
+ *
130
+ * @param name - The job name (will be prefixed with controller namespace if present)
131
+ * @param options - Optional worker configuration (concurrency, replace, etc.)
132
+ */
133
+ function Worker(name, options) {
134
+ return (target, propertyKey, _descriptor) => {
135
+ const workerMetadata = {
136
+ name,
137
+ method: String(propertyKey),
138
+ opts: options || {}
139
+ };
140
+ const targetConstructor = target.constructor;
141
+ const store = _tsed_core.Store.from(targetConstructor);
142
+ const existing = store.get(MONQUE) || {
143
+ type: "controller",
144
+ workers: [],
145
+ cronJobs: []
146
+ };
147
+ const workers = [...existing.workers || [], workerMetadata];
148
+ store.set(MONQUE, {
149
+ ...existing,
150
+ workers
151
+ });
152
+ };
153
+ }
154
+
155
+ //#endregion
156
+ //#region src/decorators/worker-controller.ts
157
+ /**
158
+ * @WorkerController class decorator
159
+ *
160
+ * Marks a class as containing worker methods and registers it with the Ts.ED DI container.
161
+ * Workers in the class will have their job names prefixed with the namespace.
162
+ *
163
+ * @param namespace - Optional prefix for all job names in this controller.
164
+ * When set, job names become "{namespace}.{name}".
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * @WorkerController("email")
169
+ * export class EmailWorkers {
170
+ * @Worker("send") // Registered as "email.send"
171
+ * async send(job: Job<EmailPayload>) { }
172
+ * }
173
+ * ```
174
+ */
175
+ /**
176
+ * Class decorator that registers a class as a worker controller.
177
+ *
178
+ * @param namespace - Optional namespace prefix for job names
179
+ */
180
+ function WorkerController(namespace) {
181
+ return (0, _tsed_core.useDecorators)((0, _tsed_di.Injectable)({ type: ProviderTypes.WORKER_CONTROLLER }), (target) => {
182
+ const store = _tsed_core.Store.from(target);
183
+ const existing = store.get(MONQUE) || {};
184
+ const workerStore = {
185
+ type: "controller",
186
+ ...namespace !== void 0 && { namespace },
187
+ workers: existing.workers || [],
188
+ cronJobs: existing.cronJobs || []
189
+ };
190
+ store.set(MONQUE, workerStore);
191
+ });
192
+ }
193
+
194
+ //#endregion
195
+ //#region \0@oxc-project+runtime@0.110.0/helpers/decorate.js
196
+ function __decorate(decorators, target, key, desc) {
197
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
198
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
199
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
200
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
201
+ }
202
+
203
+ //#endregion
204
+ //#region src/services/monque-service.ts
205
+ let MonqueService = class MonqueService {
206
+ /**
207
+ * Internal Monque instance (set by MonqueModule)
208
+ * @internal
209
+ */
210
+ _monque = null;
211
+ /**
212
+ * Set the internal Monque instance.
213
+ * Called by MonqueModule during initialization.
214
+ * @internal
215
+ */
216
+ _setMonque(monque) {
217
+ this._monque = monque;
218
+ }
219
+ /**
220
+ * Access the underlying Monque instance.
221
+ * @throws Error if MonqueModule is not initialized
222
+ */
223
+ get monque() {
224
+ if (!this._monque) throw new _monque_core.MonqueError("MonqueService is not initialized. Ensure MonqueModule is imported and enabled.");
225
+ return this._monque;
226
+ }
227
+ /**
228
+ * Enqueue a job for processing.
229
+ *
230
+ * @param name - Job type identifier (use full namespaced name, e.g., "email.send")
231
+ * @param data - Job payload
232
+ * @param options - Scheduling and deduplication options
233
+ * @returns The created or existing job document
234
+ */
235
+ async enqueue(name, data, options) {
236
+ return this.monque.enqueue(name, data, options);
237
+ }
238
+ /**
239
+ * Enqueue a job for immediate processing.
240
+ *
241
+ * @param name - Job type identifier
242
+ * @param data - Job payload
243
+ * @returns The created job document
244
+ */
245
+ async now(name, data) {
246
+ return this.monque.now(name, data);
247
+ }
248
+ /**
249
+ * Schedule a recurring job with a cron expression.
250
+ *
251
+ * @param cron - Cron expression (5-field standard or predefined like @daily)
252
+ * @param name - Job type identifier
253
+ * @param data - Job payload
254
+ * @param options - Scheduling options
255
+ * @returns The created job document
256
+ */
257
+ async schedule(cron, name, data, options) {
258
+ return this.monque.schedule(cron, name, data, options);
259
+ }
260
+ /**
261
+ * Cancel a pending or scheduled job.
262
+ *
263
+ * @param jobId - The ID of the job to cancel
264
+ * @returns The cancelled job, or null if not found
265
+ */
266
+ async cancelJob(jobId) {
267
+ return this.monque.cancelJob(jobId);
268
+ }
269
+ /**
270
+ * Retry a failed or cancelled job.
271
+ *
272
+ * @param jobId - The ID of the job to retry
273
+ * @returns The updated job, or null if not found
274
+ */
275
+ async retryJob(jobId) {
276
+ return this.monque.retryJob(jobId);
277
+ }
278
+ /**
279
+ * Reschedule a pending job to run at a different time.
280
+ *
281
+ * @param jobId - The ID of the job to reschedule
282
+ * @param runAt - The new Date when the job should run
283
+ * @returns The updated job, or null if not found
284
+ */
285
+ async rescheduleJob(jobId, runAt) {
286
+ return this.monque.rescheduleJob(jobId, runAt);
287
+ }
288
+ /**
289
+ * Permanently delete a job.
290
+ *
291
+ * @param jobId - The ID of the job to delete
292
+ * @returns true if deleted, false if job not found
293
+ */
294
+ async deleteJob(jobId) {
295
+ return this.monque.deleteJob(jobId);
296
+ }
297
+ /**
298
+ * Cancel multiple jobs matching the given filter.
299
+ *
300
+ * @param filter - Selector for which jobs to cancel
301
+ * @returns Result with count of cancelled jobs
302
+ */
303
+ async cancelJobs(filter) {
304
+ return this.monque.cancelJobs(filter);
305
+ }
306
+ /**
307
+ * Retry multiple jobs matching the given filter.
308
+ *
309
+ * @param filter - Selector for which jobs to retry
310
+ * @returns Result with count of retried jobs
311
+ */
312
+ async retryJobs(filter) {
313
+ return this.monque.retryJobs(filter);
314
+ }
315
+ /**
316
+ * Delete multiple jobs matching the given filter.
317
+ *
318
+ * @param filter - Selector for which jobs to delete
319
+ * @returns Result with count of deleted jobs
320
+ */
321
+ async deleteJobs(filter) {
322
+ return this.monque.deleteJobs(filter);
323
+ }
324
+ /**
325
+ * Get a job by its ID.
326
+ *
327
+ * @param jobId - The job's ObjectId (as string or ObjectId)
328
+ * @returns The job document, or null if not found
329
+ * @throws MonqueError if jobId is an invalid hex string
330
+ */
331
+ async getJob(jobId) {
332
+ let id;
333
+ if (typeof jobId === "string") {
334
+ if (!mongodb.ObjectId.isValid(jobId)) throw new _monque_core.MonqueError(`Invalid job ID format: ${jobId}`);
335
+ id = mongodb.ObjectId.createFromHexString(jobId);
336
+ } else id = jobId;
337
+ return this.monque.getJob(id);
338
+ }
339
+ /**
340
+ * Query jobs from the queue with optional filters.
341
+ *
342
+ * @param filter - Optional filter criteria (name, status, limit, skip)
343
+ * @returns Array of matching jobs
344
+ */
345
+ async getJobs(filter) {
346
+ return this.monque.getJobs(filter);
347
+ }
348
+ /**
349
+ * Get a paginated list of jobs using opaque cursors.
350
+ *
351
+ * @param options - Pagination options (cursor, limit, direction, filter)
352
+ * @returns Page of jobs with next/prev cursors
353
+ */
354
+ async getJobsWithCursor(options) {
355
+ return this.monque.getJobsWithCursor(options);
356
+ }
357
+ /**
358
+ * Get aggregate statistics for the job queue.
359
+ *
360
+ * @param filter - Optional filter to scope statistics by job name
361
+ * @returns Queue statistics
362
+ */
363
+ async getQueueStats(filter) {
364
+ return this.monque.getQueueStats(filter);
365
+ }
366
+ /**
367
+ * Check if the scheduler is healthy and running.
368
+ *
369
+ * @returns true if running and connected
370
+ */
371
+ isHealthy() {
372
+ return this.monque.isHealthy();
373
+ }
374
+ };
375
+ MonqueService = __decorate([(0, _tsed_di.Injectable)()], MonqueService);
376
+
377
+ //#endregion
378
+ //#region src/utils/build-job-name.ts
379
+ /**
380
+ * Build the full job name by combining namespace and name.
381
+ *
382
+ * @param namespace - Optional namespace from @WorkerController
383
+ * @param name - Job name from @Worker or @Cron
384
+ * @returns Full job name (e.g., "email.send" or just "send")
385
+ *
386
+ * @example
387
+ * ```typescript
388
+ * buildJobName("email", "send"); // "email.send"
389
+ * buildJobName(undefined, "send"); // "send"
390
+ * buildJobName("", "send"); // "send"
391
+ * ```
392
+ */
393
+ function buildJobName(namespace, name) {
394
+ return namespace ? `${namespace}.${name}` : name;
395
+ }
396
+
397
+ //#endregion
398
+ //#region src/utils/collect-worker-metadata.ts
399
+ /**
400
+ * Collect worker metadata utility
401
+ *
402
+ * Collects all worker metadata from a class decorated with @WorkerController.
403
+ * Used by MonqueModule to discover and register all workers.
404
+ */
405
+ /**
406
+ * Collect all worker metadata from a class.
407
+ *
408
+ * @param target - The class constructor (decorated with @WorkerController)
409
+ * @returns Array of collected worker metadata ready for registration
410
+ *
411
+ * @example
412
+ * ```typescript
413
+ * const metadata = collectWorkerMetadata(EmailWorkers);
414
+ * // Returns:
415
+ * // [
416
+ * // { fullName: "email.send", method: "sendEmail", opts: {}, isCron: false },
417
+ * // { fullName: "email.daily-digest", method: "sendDailyDigest", opts: {}, isCron: true, cronPattern: "0 9 * * *" }
418
+ * // ]
419
+ * ```
420
+ */
421
+ function collectWorkerMetadata(target) {
422
+ const workerStore = _tsed_core.Store.from(target).get(MONQUE);
423
+ if (!workerStore) return [];
424
+ const results = [];
425
+ const namespace = workerStore.namespace;
426
+ for (const worker of workerStore.workers) results.push({
427
+ fullName: buildJobName(namespace, worker.name),
428
+ method: worker.method,
429
+ opts: worker.opts,
430
+ isCron: false
431
+ });
432
+ for (const cron of workerStore.cronJobs) results.push({
433
+ fullName: buildJobName(namespace, cron.name),
434
+ method: cron.method,
435
+ opts: cron.opts,
436
+ isCron: true,
437
+ cronPattern: cron.pattern
438
+ });
439
+ return results;
440
+ }
441
+
442
+ //#endregion
443
+ //#region src/utils/get-worker-token.ts
444
+ /**
445
+ * Generate a unique token for a worker controller.
446
+ *
447
+ * Used internally by Ts.ED DI to identify worker controller providers.
448
+ * The token is based on the class name for debugging purposes.
449
+ *
450
+ * @param target - The class constructor
451
+ * @returns A Symbol token unique to this worker controller
452
+ *
453
+ * @example
454
+ * ```typescript
455
+ * @WorkerController("email")
456
+ * class EmailWorkers {}
457
+ *
458
+ * const token = getWorkerToken(EmailWorkers);
459
+ * // Symbol("monque:worker:EmailWorkers")
460
+ * ```
461
+ */
462
+ function getWorkerToken(target) {
463
+ const name = target.name?.trim();
464
+ if (!name) throw new Error("Worker class must have a non-empty name");
465
+ return Symbol.for(`monque:worker:${name}`);
466
+ }
467
+
468
+ //#endregion
469
+ //#region src/utils/guards.ts
470
+ /**
471
+ * Type guard to check if an object acts like a Mongoose Service.
472
+ *
473
+ * Checks if the object has a `get` method.
474
+ *
475
+ * @param value The value to check
476
+ */
477
+ function isMongooseService(value) {
478
+ return typeof value === "object" && value !== null && "get" in value && typeof value.get === "function";
479
+ }
480
+ /**
481
+ * Type guard to check if an object acts like a Mongoose Connection.
482
+ *
483
+ * Checks if the object has a `db` property.
484
+ *
485
+ * @param value The value to check
486
+ */
487
+ function isMongooseConnection(value) {
488
+ return typeof value === "object" && value !== null && "db" in value && typeof value.db === "object" && value.db !== null && typeof value.db.collection === "function";
489
+ }
490
+
491
+ //#endregion
492
+ //#region src/utils/resolve-database.ts
493
+ /**
494
+ * Resolve the MongoDB database instance from the configuration.
495
+ *
496
+ * Supports three resolution strategies:
497
+ * 1. **Direct `db`**: Returns the provided Db instance directly
498
+ * 2. **Factory `dbFactory`**: Calls the factory function (supports async)
499
+ * 3. **DI Token `dbToken`**: Resolves the Db from the DI container
500
+ *
501
+ * @param config - The Monque configuration containing database settings
502
+ * @param injectorFn - Optional function to resolve DI tokens (required for dbToken strategy)
503
+ * @returns The resolved MongoDB Db instance
504
+ * @throws Error if no database strategy is provided or if DI resolution fails
505
+ *
506
+ * @example
507
+ * ```typescript
508
+ * // Direct Db instance
509
+ * const db = await resolveDatabase({ db: mongoDb });
510
+ *
511
+ * // Factory function
512
+ * const db = await resolveDatabase({
513
+ * dbFactory: async () => {
514
+ * const client = await MongoClient.connect(uri);
515
+ * return client.db("myapp");
516
+ * }
517
+ * });
518
+ *
519
+ * // DI token
520
+ * const db = await resolveDatabase(
521
+ * { dbToken: "MONGODB_DATABASE" },
522
+ * (token) => injector.get(token)
523
+ * );
524
+ * ```
525
+ */
526
+ async function resolveDatabase(config, injectorFn) {
527
+ if (config.db) return config.db;
528
+ if (config.dbFactory) return config.dbFactory();
529
+ if (config.dbToken) {
530
+ if (!injectorFn) throw new Error("MonqueTsedConfig.dbToken requires an injector function to resolve the database");
531
+ const resolved = injectorFn(config.dbToken);
532
+ if (!resolved) throw new Error(`Could not resolve database from token: ${String(config.dbToken)}. Make sure the provider is registered in the DI container.`);
533
+ if (isMongooseService(resolved)) {
534
+ const connectionId = config.mongooseConnectionId || "default";
535
+ const connection = resolved.get(connectionId);
536
+ if (!connection) throw new Error(`MongooseService resolved from token "${String(config.dbToken)}" returned no connection for ID "${connectionId}". Ensure the connection ID is correct and the connection is established.`);
537
+ if ("db" in connection && connection.db) return connection.db;
538
+ }
539
+ if (isMongooseConnection(resolved)) return resolved.db;
540
+ if (typeof resolved !== "object" || resolved === null || !("collection" in resolved)) throw new Error(`Resolved value from token "${String(config.dbToken)}" does not appear to be a valid MongoDB Db instance.`);
541
+ return resolved;
542
+ }
543
+ throw new Error("MonqueTsedConfig requires 'db', 'dbFactory', or 'dbToken' to be set");
544
+ }
545
+
546
+ //#endregion
547
+ //#region \0@oxc-project+runtime@0.110.0/helpers/decorateMetadata.js
548
+ function __decorateMetadata(k, v) {
549
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
550
+ }
551
+
552
+ //#endregion
553
+ //#region \0@oxc-project+runtime@0.110.0/helpers/decorateParam.js
554
+ function __decorateParam(paramIndex, decorator) {
555
+ return function(target, key) {
556
+ decorator(target, key, paramIndex);
557
+ };
558
+ }
559
+
560
+ //#endregion
561
+ //#region src/monque-module.ts
562
+ /**
563
+ * MonqueModule - Main Integration Module
564
+ *
565
+ * Orchestrates the integration between Monque and Ts.ED.
566
+ * Handles lifecycle hooks, configuration resolution, and worker registration.
567
+ */
568
+ var _ref, _ref2, _ref3, _ref4;
569
+ let MonqueModule = class MonqueModule {
570
+ injector;
571
+ monqueService;
572
+ logger;
573
+ monqueConfig;
574
+ monque = null;
575
+ constructor(injector, monqueService, logger, configuration) {
576
+ this.injector = injector;
577
+ this.monqueService = monqueService;
578
+ this.logger = logger;
579
+ this.monqueConfig = configuration.get("monque") || {};
580
+ }
581
+ async $onInit() {
582
+ const config = this.monqueConfig;
583
+ if (config?.enabled === false) {
584
+ this.logger.info("Monque integration is disabled");
585
+ return;
586
+ }
587
+ validateDatabaseConfig(config);
588
+ try {
589
+ const db = await resolveDatabase(config, (token) => this.injector.get(token));
590
+ const { db: _db, ...restConfig } = config;
591
+ this.monque = new _monque_core.Monque(db, restConfig);
592
+ this.monqueService._setMonque(this.monque);
593
+ this.logger.info("Monque: Connecting to MongoDB...");
594
+ await this.monque.initialize();
595
+ await this.registerWorkers();
596
+ await this.monque.start();
597
+ this.logger.info("Monque: Started successfully");
598
+ } catch (error) {
599
+ this.logger.error({
600
+ event: "MONQUE_INIT_ERROR",
601
+ message: "Failed to initialize Monque",
602
+ error
603
+ });
604
+ throw error;
605
+ }
606
+ }
607
+ async $onDestroy() {
608
+ if (this.monque) {
609
+ this.logger.info("Monque: Stopping...");
610
+ await this.monque.stop();
611
+ this.logger.info("Monque: Stopped");
612
+ }
613
+ }
614
+ /**
615
+ * Discover and register all workers from @WorkerController providers
616
+ */
617
+ async registerWorkers() {
618
+ if (!this.monque) throw new Error("Monque instance not initialized");
619
+ const monque = this.monque;
620
+ const workerControllers = this.injector.getProviders(ProviderTypes.WORKER_CONTROLLER);
621
+ const registeredJobs = /* @__PURE__ */ new Set();
622
+ this.logger.info(`Monque: Found ${workerControllers.length} worker controllers`);
623
+ for (const provider of workerControllers) {
624
+ const useClass = provider.useClass;
625
+ const workers = collectWorkerMetadata(useClass);
626
+ const instance = this.injector.get(provider.token);
627
+ if (!instance && provider.scope !== _tsed_di.ProviderScope.REQUEST) {
628
+ this.logger.warn(`Monque: Could not resolve instance for controller ${provider.name}. Skipping.`);
629
+ continue;
630
+ }
631
+ for (const worker of workers) {
632
+ const { fullName, method, opts, isCron, cronPattern } = worker;
633
+ if (registeredJobs.has(fullName)) throw new Error(`Monque: Duplicate job registration detected. Job "${fullName}" is already registered.`);
634
+ registeredJobs.add(fullName);
635
+ const handler = async (job) => {
636
+ const $ctx = new _tsed_di.DIContext({
637
+ injector: this.injector,
638
+ id: job._id?.toString() || "unknown"
639
+ });
640
+ $ctx.set("MONQUE_JOB", job);
641
+ $ctx.container.set(_tsed_di.DIContext, $ctx);
642
+ await (0, _tsed_di.runInContext)($ctx, async () => {
643
+ try {
644
+ let targetInstance = instance;
645
+ if (provider.scope === _tsed_di.ProviderScope.REQUEST || !targetInstance) targetInstance = await this.injector.invoke(provider.token, { locals: $ctx.container });
646
+ const typedInstance = targetInstance;
647
+ if (typedInstance && typeof typedInstance[method] === "function") await typedInstance[method](job);
648
+ } catch (error) {
649
+ this.logger.error({
650
+ event: "MONQUE_JOB_ERROR",
651
+ jobName: fullName,
652
+ jobId: job._id,
653
+ message: `Error processing job ${fullName}`,
654
+ error
655
+ });
656
+ throw error;
657
+ } finally {
658
+ await $ctx.destroy();
659
+ }
660
+ });
661
+ };
662
+ if (isCron && cronPattern) {
663
+ this.logger.debug(`Monque: Registering cron job "${fullName}" (${cronPattern})`);
664
+ monque.register(fullName, handler, opts);
665
+ await monque.schedule(cronPattern, fullName, {}, opts);
666
+ } else {
667
+ this.logger.debug(`Monque: Registering worker "${fullName}"`);
668
+ monque.register(fullName, handler, opts);
669
+ }
670
+ }
671
+ }
672
+ this.logger.info(`Monque: Registered ${registeredJobs.size} jobs`);
673
+ }
674
+ };
675
+ MonqueModule = __decorate([
676
+ (0, _tsed_di.Module)({ imports: [MonqueService] }),
677
+ __decorateParam(0, (0, _tsed_di.Inject)(_tsed_di.InjectorService)),
678
+ __decorateParam(1, (0, _tsed_di.Inject)(MonqueService)),
679
+ __decorateParam(2, (0, _tsed_di.Inject)(_tsed_di.LOGGER)),
680
+ __decorateParam(3, (0, _tsed_di.Inject)(_tsed_di.Configuration)),
681
+ __decorateMetadata("design:paramtypes", [
682
+ typeof (_ref = typeof _tsed_di.InjectorService !== "undefined" && _tsed_di.InjectorService) === "function" ? _ref : Object,
683
+ typeof (_ref2 = typeof MonqueService !== "undefined" && MonqueService) === "function" ? _ref2 : Object,
684
+ typeof (_ref3 = typeof _tsed_di.LOGGER !== "undefined" && _tsed_di.LOGGER) === "function" ? _ref3 : Object,
685
+ typeof (_ref4 = typeof _tsed_di.Configuration !== "undefined" && _tsed_di.Configuration) === "function" ? _ref4 : Object
686
+ ])
687
+ ], MonqueModule);
688
+
689
+ //#endregion
690
+ exports.Cron = Cron;
691
+ exports.MONQUE = MONQUE;
692
+ Object.defineProperty(exports, 'MonqueModule', {
693
+ enumerable: true,
694
+ get: function () {
695
+ return MonqueModule;
696
+ }
697
+ });
698
+ Object.defineProperty(exports, 'MonqueService', {
699
+ enumerable: true,
700
+ get: function () {
701
+ return MonqueService;
702
+ }
703
+ });
704
+ exports.ProviderTypes = ProviderTypes;
705
+ exports.Worker = Worker;
706
+ exports.WorkerController = WorkerController;
707
+ exports.buildJobName = buildJobName;
708
+ exports.collectWorkerMetadata = collectWorkerMetadata;
709
+ exports.getWorkerToken = getWorkerToken;
710
+ exports.resolveDatabase = resolveDatabase;
711
+ exports.validateDatabaseConfig = validateDatabaseConfig;
712
+ //# sourceMappingURL=index.cjs.map