@nexusts/schedule 0.7.2 → 0.7.4

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/README.md CHANGED
@@ -4,37 +4,64 @@
4
4
 
5
5
  ## Description
6
6
 
7
- Cron scheduling (@Cron / @Interval / @Timeout).
7
+ Cron scheduling (`@Cron` / `@Interval` / `@Timeout`).
8
8
 
9
- In-tree cron parser (no `cron` / `node-cron` peer dep). Decorator-based.
9
+ In-tree cron parser (no `cron` / `node-cron` peer dep). Decorator-based
10
+ with auto-scanning — no manual registration needed.
10
11
 
11
12
  ## Install
12
13
 
13
- This module is part of the NexusTS monorepo. Each module is published as its own npm package under the `@nexusts/` scope.
14
-
15
- Most apps start with just the core:
16
-
17
14
  ```bash
18
- bun add @nexusts/core
15
+ bun add @nexusts/schedule
19
16
  ```
20
17
 
21
- Then add this module only if you need it:
18
+ ## Quick start
22
19
 
23
- ```bash
24
- bun add @nexusts/schedule
20
+ ```ts
21
+ // app.module.ts
22
+ import { Module } from '@nexusts/core';
23
+ import { ScheduleModule } from '@nexusts/schedule';
24
+
25
+ @Module({
26
+ imports: [ScheduleModule.forRoot({ backend: 'memory' })],
27
+ })
28
+ export class AppModule {}
25
29
  ```
26
30
 
27
- ## Peer dependencies
31
+ ```ts
32
+ // app/tasks/cleanup.task.ts
33
+ import { Injectable } from '@nexusts/core';
34
+ import { Cron } from '@nexusts/schedule';
35
+
36
+ @Injectable()
37
+ export class CleanupTask {
38
+ @Cron('0 * * * *') // every hour — auto-detected at boot
39
+ async hourly() {
40
+ // cleanup logic
41
+ }
42
+ }
43
+ ```
28
44
 
29
- **None.** No external dependencies. In-tree cron parser; no `cron` or `node-cron` needed.
45
+ No manual `scanForSchedulers()` or `start()` call needed.
46
+ `ScheduleModule` auto-scans every resolved provider during
47
+ `Application.bootstrap()`.
30
48
 
31
- ## Usage
49
+ ## API
32
50
 
33
- ```typescript
34
- import { /* public API */ } from "@nexusts/schedule";
35
- ```
51
+ | Export | Purpose |
52
+ |--------|---------|
53
+ | `ScheduleModule` | `forRoot(config)` — configure and import |
54
+ | `ScheduleService` | Programmatic `addCron` / `addInterval` / `addTimeout` |
55
+ | `@Cron(expr, opts?)` | Schedule a method on a cron expression |
56
+ | `@Interval(ms, name?)` | Run a method every N ms |
57
+ | `@Timeout(ms, name?)` | Run a method once after N ms |
58
+ | `CronExpr` | Parse and test cron expressions |
59
+ | `MemorySchedulesBackend` | In-process backend (Bun / Node) |
60
+ | `CloudflareSchedulesBackend` | Workers Cron Triggers backend |
61
+
62
+ ## Peer dependencies
36
63
 
37
- See the [user guide](../../docs/user-guide/schedule.md) and the [example app](../../examples/) for a working demo.
64
+ None. In-tree cron parser; no `cron` or `node-cron` needed.
38
65
 
39
66
  ## License
40
67
 
package/dist/index.js CHANGED
@@ -1,4 +1,31 @@
1
1
  // @bun
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
7
+ var __toCommonJS = (from) => {
8
+ var entry = __moduleCache.get(from), desc;
9
+ if (entry)
10
+ return entry;
11
+ entry = __defProp({}, "__esModule", { value: true });
12
+ if (from && typeof from === "object" || typeof from === "function")
13
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
14
+ get: () => from[key],
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ }));
17
+ __moduleCache.set(from, entry);
18
+ return entry;
19
+ };
20
+ var __export = (target, all) => {
21
+ for (var name in all)
22
+ __defProp(target, name, {
23
+ get: all[name],
24
+ enumerable: true,
25
+ configurable: true,
26
+ set: (newValue) => all[name] = () => newValue
27
+ });
28
+ };
2
29
  var __legacyDecorateClassTS = function(decorators, target, key, desc) {
3
30
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
31
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
@@ -14,6 +41,120 @@ var __legacyMetadataTS = (k, v) => {
14
41
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
15
42
  return Reflect.metadata(k, v);
16
43
  };
44
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
45
+
46
+ // packages/schedule/src/scanner.ts
47
+ var exports_scanner = {};
48
+ __export(exports_scanner, {
49
+ scanProviderForSchedules: () => scanProviderForSchedules,
50
+ __setScheduleService: () => __setScheduleService
51
+ });
52
+ function __setScheduleService(svc) {
53
+ _scheduleService = svc;
54
+ }
55
+ function scanProviderForSchedules(instance) {
56
+ const svc = _scheduleService;
57
+ if (!svc)
58
+ return;
59
+ const ctor = instance?.constructor;
60
+ if (!ctor)
61
+ return;
62
+ const hasCron = Reflect.getMetadata("nexus:schedule:cron", ctor);
63
+ const hasInterval = Reflect.getMetadata("nexus:schedule:interval", ctor);
64
+ const hasTimeout = Reflect.getMetadata("nexus:schedule:timeout", ctor);
65
+ if (hasCron || hasInterval || hasTimeout) {
66
+ svc.scanInstance(instance);
67
+ }
68
+ }
69
+ var _scheduleService = null;
70
+
71
+ // packages/schedule/src/decorators/cron.ts
72
+ var exports_cron = {};
73
+ __export(exports_cron, {
74
+ scanForSchedulers: () => scanForSchedulers,
75
+ getTimeoutHooks: () => getTimeoutHooks,
76
+ getIntervalHooks: () => getIntervalHooks,
77
+ getCronHooks: () => getCronHooks,
78
+ Timeout: () => Timeout,
79
+ Interval: () => Interval,
80
+ Cron: () => Cron
81
+ });
82
+ import"reflect-metadata";
83
+ function Cron(expression, options = {}) {
84
+ return (target, propertyKey, descriptor) => {
85
+ if (!descriptor || typeof descriptor.value !== "function") {
86
+ throw new Error("@Cron can only decorate methods.");
87
+ }
88
+ const ctor = target.constructor;
89
+ const hooks = Reflect.getMetadata(CRON_META, ctor) ?? [];
90
+ hooks.push({ method: String(propertyKey), expression, options });
91
+ Reflect.defineMetadata(CRON_META, hooks, ctor);
92
+ };
93
+ }
94
+ function Interval(milliseconds, name) {
95
+ return (target, propertyKey, descriptor) => {
96
+ if (!descriptor || typeof descriptor.value !== "function") {
97
+ throw new Error("@Interval can only decorate methods.");
98
+ }
99
+ const ctor = target.constructor;
100
+ const hooks = Reflect.getMetadata(INTERVAL_META, ctor) ?? [];
101
+ hooks.push({ method: String(propertyKey), milliseconds, name });
102
+ Reflect.defineMetadata(INTERVAL_META, hooks, ctor);
103
+ };
104
+ }
105
+ function Timeout(milliseconds, name) {
106
+ return (target, propertyKey, descriptor) => {
107
+ if (!descriptor || typeof descriptor.value !== "function") {
108
+ throw new Error("@Timeout can only decorate methods.");
109
+ }
110
+ const ctor = target.constructor;
111
+ const hooks = Reflect.getMetadata(TIMEOUT_META, ctor) ?? [];
112
+ hooks.push({ method: String(propertyKey), milliseconds, name });
113
+ Reflect.defineMetadata(TIMEOUT_META, hooks, ctor);
114
+ };
115
+ }
116
+ function getCronHooks(target) {
117
+ const ctor = target.constructor ?? target;
118
+ return Reflect.getMetadata(CRON_META, ctor) ?? [];
119
+ }
120
+ function getIntervalHooks(target) {
121
+ const ctor = target.constructor ?? target;
122
+ return Reflect.getMetadata(INTERVAL_META, ctor) ?? [];
123
+ }
124
+ function getTimeoutHooks(target) {
125
+ const ctor = target.constructor ?? target;
126
+ return Reflect.getMetadata(TIMEOUT_META, ctor) ?? [];
127
+ }
128
+ async function scanForSchedulers(instance, service) {
129
+ const ids = [];
130
+ for (const h of getCronHooks(instance)) {
131
+ const fn = instance[h.method];
132
+ if (typeof fn !== "function")
133
+ continue;
134
+ const id = service.addCron(h.expression, fn.bind(instance), {
135
+ ...h.options,
136
+ name: h.options.name ?? `${instance.constructor.name}.${h.method}`
137
+ });
138
+ ids.push(id);
139
+ }
140
+ for (const h of getIntervalHooks(instance)) {
141
+ const fn = instance[h.method];
142
+ if (typeof fn !== "function")
143
+ continue;
144
+ const id = service.addInterval(h.milliseconds, fn.bind(instance), h.name ?? `${instance.constructor.name}.${h.method}`);
145
+ ids.push(id);
146
+ }
147
+ for (const h of getTimeoutHooks(instance)) {
148
+ const fn = instance[h.method];
149
+ if (typeof fn !== "function")
150
+ continue;
151
+ const id = service.addTimeout(h.milliseconds, fn.bind(instance), h.name ?? `${instance.constructor.name}.${h.method}`);
152
+ ids.push(id);
153
+ }
154
+ return ids;
155
+ }
156
+ var CRON_META = "nexus:schedule:cron", INTERVAL_META = "nexus:schedule:interval", TIMEOUT_META = "nexus:schedule:timeout";
157
+ var init_cron = () => {};
17
158
  // packages/schedule/src/cron-parser.ts
18
159
  var FIELD_RANGES = [
19
160
  [0, 59],
@@ -91,8 +232,11 @@ class CronExpression {
91
232
  }
92
233
  next(from, maxYears = 5) {
93
234
  const cap = new Date(from.getTime() + maxYears * 365 * 24 * 60 * 60 * 1000);
94
- let cur = new Date(from.getTime() + 1000);
235
+ const offsetMs = this.hasSeconds ? 1000 : 60000;
236
+ let cur = new Date(from.getTime() + offsetMs);
95
237
  cur.setMilliseconds(0);
238
+ if (!this.hasSeconds)
239
+ cur.setSeconds(0);
96
240
  let safety = 0;
97
241
  while (cur <= cap) {
98
242
  if (this.matches(cur)) {
@@ -649,15 +793,50 @@ class CloudflareSchedulesBackend {
649
793
  // packages/schedule/src/schedule.service.ts
650
794
  import { Inject, Injectable } from "@nexusts/core";
651
795
  class ScheduleService {
652
- config;
796
+ _config;
653
797
  static TOKEN = Symbol.for("nexus:ScheduleService");
654
798
  registry;
655
799
  #listeners = new Set;
656
800
  #started = false;
657
801
  #memoryBackend = null;
658
- constructor(config = {}) {
659
- this.config = config;
660
- this.registry = this.#createBackend(config);
802
+ constructor(_config = {}) {
803
+ this._config = _config;
804
+ this.registry = this.#createBackend(this._config);
805
+ __setScheduleService(this);
806
+ if (typeof module_schedule_service !== "undefined" && module_schedule_service.hot) {
807
+ module_schedule_service.hot?.dispose?.(() => {
808
+ this.stop();
809
+ });
810
+ }
811
+ }
812
+ scanInstance(instance) {
813
+ const { getCronHooks: getCronHooks2, getIntervalHooks: getIntervalHooks2, getTimeoutHooks: getTimeoutHooks2 } = (init_cron(), __toCommonJS(exports_cron));
814
+ for (const h of getCronHooks2(instance)) {
815
+ const fn = instance[h.method];
816
+ if (typeof fn !== "function")
817
+ continue;
818
+ this.addCron(h.expression, fn.bind(instance), {
819
+ ...h.options,
820
+ name: h.options.name ?? `${instance.constructor.name}.${h.method}`
821
+ });
822
+ }
823
+ for (const h of getIntervalHooks2(instance)) {
824
+ const fn = instance[h.method];
825
+ if (typeof fn !== "function")
826
+ continue;
827
+ this.addInterval(h.milliseconds, fn.bind(instance), h.name ?? `${instance.constructor.name}.${h.method}`);
828
+ }
829
+ for (const h of getTimeoutHooks2(instance)) {
830
+ const fn = instance[h.method];
831
+ if (typeof fn !== "function")
832
+ continue;
833
+ this.addTimeout(h.milliseconds, fn.bind(instance), h.name ?? `${instance.constructor.name}.${h.method}`);
834
+ }
835
+ }
836
+ async onApplicationInit() {
837
+ const { __setScheduleService: __setScheduleService2 } = await Promise.resolve().then(() => exports_scanner);
838
+ __setScheduleService2(this);
839
+ this.start();
661
840
  }
662
841
  addCron(expression, handler, options = {}) {
663
842
  const name = options.name ?? `cron-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
@@ -692,9 +871,8 @@ class ScheduleService {
692
871
  if (this.#started)
693
872
  return;
694
873
  this.#started = true;
695
- if (this.#memoryBackend) {
874
+ if (this.#memoryBackend)
696
875
  this.#memoryBackend.start();
697
- }
698
876
  this.registry.on((event) => this.#broadcast(event));
699
877
  }
700
878
  async stop() {
@@ -739,9 +917,12 @@ ScheduleService = __legacyDecorateClassTS([
739
917
  ], ScheduleService);
740
918
  // packages/schedule/src/schedule.module.ts
741
919
  import"reflect-metadata";
742
- import { Module } from "@nexusts/core";
920
+ import { Module, setScheduleScanner } from "@nexusts/core";
921
+ setScheduleScanner(scanProviderForSchedules);
922
+
743
923
  class ScheduleModule {
744
924
  static forRoot(config = {}) {
925
+
745
926
  class ConfiguredScheduleModule {
746
927
  }
747
928
  ConfiguredScheduleModule = __legacyDecorateClassTS([
@@ -769,84 +950,9 @@ ScheduleModule = __legacyDecorateClassTS([
769
950
  exports: [ScheduleService, ScheduleService.TOKEN]
770
951
  })
771
952
  ], ScheduleModule);
772
- // packages/schedule/src/decorators/cron.ts
773
- import"reflect-metadata";
774
- var CRON_META = "nexus:schedule:cron";
775
- var INTERVAL_META = "nexus:schedule:interval";
776
- var TIMEOUT_META = "nexus:schedule:timeout";
777
- function Cron(expression, options = {}) {
778
- return (target, propertyKey, descriptor) => {
779
- if (!descriptor || typeof descriptor.value !== "function") {
780
- throw new Error("@Cron can only decorate methods.");
781
- }
782
- const ctor = target.constructor;
783
- const hooks = Reflect.getMetadata(CRON_META, ctor) ?? [];
784
- hooks.push({ method: String(propertyKey), expression, options });
785
- Reflect.defineMetadata(CRON_META, hooks, ctor);
786
- };
787
- }
788
- function Interval(milliseconds, name) {
789
- return (target, propertyKey, descriptor) => {
790
- if (!descriptor || typeof descriptor.value !== "function") {
791
- throw new Error("@Interval can only decorate methods.");
792
- }
793
- const ctor = target.constructor;
794
- const hooks = Reflect.getMetadata(INTERVAL_META, ctor) ?? [];
795
- hooks.push({ method: String(propertyKey), milliseconds, name });
796
- Reflect.defineMetadata(INTERVAL_META, hooks, ctor);
797
- };
798
- }
799
- function Timeout(milliseconds, name) {
800
- return (target, propertyKey, descriptor) => {
801
- if (!descriptor || typeof descriptor.value !== "function") {
802
- throw new Error("@Timeout can only decorate methods.");
803
- }
804
- const ctor = target.constructor;
805
- const hooks = Reflect.getMetadata(TIMEOUT_META, ctor) ?? [];
806
- hooks.push({ method: String(propertyKey), milliseconds, name });
807
- Reflect.defineMetadata(TIMEOUT_META, hooks, ctor);
808
- };
809
- }
810
- function getCronHooks(target) {
811
- const ctor = target.constructor ?? target;
812
- return Reflect.getMetadata(CRON_META, ctor) ?? [];
813
- }
814
- function getIntervalHooks(target) {
815
- const ctor = target.constructor ?? target;
816
- return Reflect.getMetadata(INTERVAL_META, ctor) ?? [];
817
- }
818
- function getTimeoutHooks(target) {
819
- const ctor = target.constructor ?? target;
820
- return Reflect.getMetadata(TIMEOUT_META, ctor) ?? [];
821
- }
822
- async function scanForSchedulers(instance, service) {
823
- const ids = [];
824
- for (const h of getCronHooks(instance)) {
825
- const fn = instance[h.method];
826
- if (typeof fn !== "function")
827
- continue;
828
- const id = service.addCron(h.expression, fn.bind(instance), {
829
- ...h.options,
830
- name: h.options.name ?? `${instance.constructor.name}.${h.method}`
831
- });
832
- ids.push(id);
833
- }
834
- for (const h of getIntervalHooks(instance)) {
835
- const fn = instance[h.method];
836
- if (typeof fn !== "function")
837
- continue;
838
- const id = service.addInterval(h.milliseconds, fn.bind(instance), h.name ?? `${instance.constructor.name}.${h.method}`);
839
- ids.push(id);
840
- }
841
- for (const h of getTimeoutHooks(instance)) {
842
- const fn = instance[h.method];
843
- if (typeof fn !== "function")
844
- continue;
845
- const id = service.addTimeout(h.milliseconds, fn.bind(instance), h.name ?? `${instance.constructor.name}.${h.method}`);
846
- ids.push(id);
847
- }
848
- return ids;
849
- }
953
+
954
+ // packages/schedule/src/index.ts
955
+ init_cron();
850
956
  export {
851
957
  scanForSchedulers,
852
958
  parseCron,
@@ -866,5 +972,5 @@ export {
866
972
  CloudflareSchedulesBackend
867
973
  };
868
974
 
869
- //# debugId=BE7269D6BACECC6B64756E2164756E21
975
+ //# debugId=DBB1B65D1B69D17764756E2164756E21
870
976
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/cron-parser.ts", "../src/backends/memory.ts", "../src/backends/cloudflare.ts", "../src/schedule.service.ts", "../src/schedule.module.ts", "../src/decorators/cron.ts"],
3
+ "sources": ["../src/scanner.ts", "../src/decorators/cron.ts", "../src/cron-parser.ts", "../src/backends/memory.ts", "../src/backends/cloudflare.ts", "../src/schedule.service.ts", "../src/schedule.module.ts", "../src/index.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * Cron expression parser + next-run calculator.\n *\n * Supports the standard 5-field crontab syntax, an optional 6-field\n * variant (with seconds), common aliases, and \"@every <duration>\".\n *\n * * * * * * every minute\n * 0 * * * * every hour\n * star-slash-15 every 15m\n * 0 9 * * 1-5 9am on weekdays\n * 0 0 1 * * first of the month\n * 30 14 1 4 * Apr 1st at 14:30\n * @yearly @annually 0 0 1 1 *\n * @monthly 0 0 1 * *\n * @weekly 0 0 * * 0\n * @daily @midnight 0 0 * * *\n * @hourly 0 * * * *\n * @every 1h30m every 90 minutes\n *\n * Field names (JAN, FEB, SUN, MON, ...) are accepted case-insensitively.\n */\n\nconst FIELD_RANGES: Array<[number, number]> = [\n\t[0, 59], // minute\n\t[0, 23], // hour\n\t[1, 31], // day of month\n\t[1, 12], // month\n\t[0, 7], // day of week (0 or 7 = Sunday)\n];\n\nconst FIELD_NAMES: Record<string, number> = {\n\tJAN: 1,\n\tFEB: 2,\n\tMAR: 3,\n\tAPR: 4,\n\tMAY: 5,\n\tJUN: 6,\n\tJUL: 7,\n\tAUG: 8,\n\tSEP: 9,\n\tOCT: 10,\n\tNOV: 11,\n\tDEC: 12,\n\tSUN: 0,\n\tMON: 1,\n\tTUE: 2,\n\tWED: 3,\n\tTHU: 4,\n\tFRI: 5,\n\tSAT: 6,\n};\n\nconst ALIASES: Record<string, string> = {\n\t\"@yearly\": \"0 0 1 1 *\",\n\t\"@annually\": \"0 0 1 1 *\",\n\t\"@monthly\": \"0 0 1 * *\",\n\t\"@weekly\": \"0 0 * * 0\",\n\t\"@daily\": \"0 0 * * *\",\n\t\"@midnight\": \"0 0 * * *\",\n\t\"@hourly\": \"0 * * * *\",\n};\n\n/** A single field expanded into a set of allowed numeric values. */\nexport class CronField {\n\treadonly values: Set<number>;\n\n\tconstructor(field: string, range: [number, number]) {\n\t\tthis.values = parseField(field, range);\n\t}\n\n\tcontains(n: number): boolean {\n\t\treturn this.values.has(n);\n\t}\n}\n\n/** A fully-parsed cron expression. */\nexport class CronExpression {\n\treadonly fields: CronField[]; // 5 or 6 entries\n\treadonly hasSeconds: boolean;\n\n\tconstructor(raw: string) {\n\t\tconst expanded = expandAlias(raw);\n\t\tconst every = expandEvery(expanded);\n\n\t\tif (every) {\n\t\t\t// \"@every Nd|Nh|Nm|Ns\" → uniform interval\n\t\t\tthis.hasSeconds = true;\n\t\t\tthis.fields = everyToFields(every);\n\t\t\treturn;\n\t\t}\n\n\t\tconst parts = expanded.trim().split(/\\s+/);\n\t\tif (parts.length === 5) {\n\t\t\tthis.hasSeconds = false;\n\t\t\tthis.fields = parts.map((p, i) => new CronField(p, FIELD_RANGES[i]!));\n\t\t} else if (parts.length === 6) {\n\t\t\tthis.hasSeconds = true;\n\t\t\tconst sec: [number, number] = [0, 59];\n\t\t\tthis.fields = [\n\t\t\t\tnew CronField(parts[0]!, sec),\n\t\t\t\t...parts.slice(1).map((p, i) => new CronField(p, FIELD_RANGES[i]!)),\n\t\t\t];\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid cron expression: \"${raw}\" (expected 5 or 6 fields, got ${parts.length})`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Return the next Date at or after `from` that matches this\n\t * expression. Returns null if no match is found within `maxYears`\n\t * (default 5) — which would indicate a misconfigured expression.\n\t */\n\tnext(from: Date, maxYears = 5): Date | null {\n\t\tconst cap = new Date(from.getTime() + maxYears * 365 * 24 * 60 * 60 * 1000);\n\t\tlet cur = new Date(from.getTime() + 1000);\n\t\tcur.setMilliseconds(0);\n\n\t\t// Brute-force: step minute-by-minute, but skip ahead when a\n\t\t// higher-order field doesn't match. For most crons this is\n\t\t// fast enough; for very sparse crons we use a forwarder.\n\t\tlet safety = 0;\n\t\twhile (cur <= cap) {\n\t\t\tif (this.matches(cur)) {\n\t\t\t\treturn cur;\n\t\t\t}\n\t\t\t// Fast-forward: if the month doesn't match, jump to next month.\n\t\t\tif (!this.fields[this.hasSeconds ? 4 : 3]!.contains(cur.getMonth() + 1)) {\n\t\t\t\tcur = new Date(cur.getFullYear(), cur.getMonth() + 1, 1, 0, 0, 0, 0);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// If day-of-month is restricted and current day doesn't match,\n\t\t\t// jump to next month at the first allowed day.\n\t\t\tconst domIdx = this.hasSeconds ? 3 : 2;\n\t\t\tconst domField = this.fields[domIdx]!;\n\t\t\tif (!domField.contains(cur.getDate())) {\n\t\t\t\t// Find the first allowed day in the set, or jump to next month.\n\t\t\t\tconst sortedDays = [...domField.values].sort((a, b) => a - b);\n\t\t\t\tconst nextDay = sortedDays.find((d) => d >= cur.getDate());\n\t\t\t\tif (nextDay !== undefined) {\n\t\t\t\t\tcur = new Date(\n\t\t\t\t\t\tcur.getFullYear(),\n\t\t\t\t\t\tcur.getMonth(),\n\t\t\t\t\t\tnextDay,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tcur = new Date(\n\t\t\t\t\t\tcur.getFullYear(),\n\t\t\t\t\t\tcur.getMonth() + 1,\n\t\t\t\t\t\tsortedDays[0]!,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// If the hour doesn't match, jump to next hour.\n\t\t\tif (!this.fields[this.hasSeconds ? 2 : 1]!.contains(cur.getHours())) {\n\t\t\t\tcur = new Date(\n\t\t\t\t\tcur.getFullYear(),\n\t\t\t\t\tcur.getMonth(),\n\t\t\t\t\tcur.getDate(),\n\t\t\t\t\tcur.getHours() + 1,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// If the minute doesn't match, jump to next minute.\n\t\t\tif (!this.fields[this.hasSeconds ? 1 : 0]!.contains(cur.getMinutes())) {\n\t\t\t\tcur = new Date(\n\t\t\t\t\tcur.getFullYear(),\n\t\t\t\t\tcur.getMonth(),\n\t\t\t\t\tcur.getDate(),\n\t\t\t\t\tcur.getHours(),\n\t\t\t\t\tcur.getMinutes() + 1,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// If seconds field exists and doesn't match, jump to next second.\n\t\t\tif (this.hasSeconds && !this.fields[0]!.contains(cur.getSeconds())) {\n\t\t\t\tcur = new Date(cur.getTime() + 1000);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Fallback: step 1 second (shouldn't normally hit).\n\t\t\tcur = new Date(cur.getTime() + 1000);\n\t\t\tif (++safety > 1_000_000) return null;\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate matches(d: Date): boolean {\n\t\tconst fields = this.hasSeconds\n\t\t\t? [\n\t\t\t\t\td.getSeconds(),\n\t\t\t\t\td.getMinutes(),\n\t\t\t\t\td.getHours(),\n\t\t\t\t\td.getDate(),\n\t\t\t\t\td.getMonth() + 1,\n\t\t\t\t\td.getDay(),\n\t\t\t\t]\n\t\t\t: [\n\t\t\t\t\td.getMinutes(),\n\t\t\t\t\td.getHours(),\n\t\t\t\t\td.getDate(),\n\t\t\t\t\td.getMonth() + 1,\n\t\t\t\t\td.getDay(),\n\t\t\t\t];\n\t\t// Day-of-week in crontab: 0 = Sunday. Day-of-month is OR'd with\n\t\t// day-of-week when both are restricted (standard crontab behavior).\n\t\tconst domField = this.fields[this.hasSeconds ? 3 : 2]!;\n\t\tconst dowField = this.fields[this.hasSeconds ? 4 : 3]!;\n\t\tconst isWildDom = domField.values.size === FIELD_RANGES[2]![1]!;\n\t\tconst isWildDow = dowField.values.size === FIELD_RANGES[4]![1]! + 1;\n\t\tconst dayMatch =\n\t\t\tisWildDom || isWildDow\n\t\t\t\t? domField.contains(d.getDate()) || dowField.contains(d.getDay())\n\t\t\t\t: domField.contains(d.getDate()) || dowField.contains(d.getDay());\n\n\t\tfor (let i = 0; i < this.fields.length; i++) {\n\t\t\tif (i === (this.hasSeconds ? 3 : 2)) continue;\n\t\t\tif (!this.fields[i]!.contains(fields[i]!)) return false;\n\t\t}\n\t\treturn dayMatch;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction expandAlias(raw: string): string {\n\tconst trimmed = raw.trim();\n\tconst alias = ALIASES[trimmed.toLowerCase()];\n\treturn alias ?? trimmed;\n}\n\nfunction expandEvery(raw: string): number | null {\n\tconst m = /^@every\\s+(\\d+)\\s*(s|m|h|d)?$/i.exec(raw.trim());\n\tif (!m) return null;\n\tconst n = Number(m[1]);\n\tconst unit = (m[2] ?? \"s\").toLowerCase();\n\tswitch (unit) {\n\t\tcase \"s\":\n\t\t\treturn n * 1000;\n\t\tcase \"m\":\n\t\t\treturn n * 60 * 1000;\n\t\tcase \"h\":\n\t\t\treturn n * 60 * 60 * 1000;\n\t\tcase \"d\":\n\t\t\treturn n * 24 * 60 * 60 * 1000;\n\t}\n\treturn null;\n}\n\nfunction everyToFields(intervalMs: number): CronField[] {\n\t// Generate a 6-field expression that fires every `intervalMs`\n\t// starting from the next round minute.\n\tconst seconds = Math.floor(intervalMs / 1000);\n\tif (seconds < 60) {\n\t\t// fire every N seconds (only if it divides 60)\n\t\tif (60 % seconds === 0) {\n\t\t\treturn [\n\t\t\t\tnew CronField(`*/${seconds}`, [0, 59]),\n\t\t\t\tnew CronField(\"*\", [0, 59]),\n\t\t\t\tnew CronField(\"*\", [0, 23]),\n\t\t\t\tnew CronField(\"*\", [1, 31]),\n\t\t\t\tnew CronField(\"*\", [1, 12]),\n\t\t\t\tnew CronField(\"*\", [0, 7]),\n\t\t\t];\n\t\t}\n\t}\n\t// Otherwise just allow every minute; the registry layer handles\n\t// throttling via setInterval.\n\treturn [\n\t\tnew CronField(\"0\", [0, 59]),\n\t\tnew CronField(\"*\", [0, 59]),\n\t\tnew CronField(\"*\", [0, 23]),\n\t\tnew CronField(\"*\", [1, 31]),\n\t\tnew CronField(\"*\", [1, 12]),\n\t\tnew CronField(\"*\", [0, 7]),\n\t];\n}\n\nfunction parseField(field: string, range: [number, number]): Set<number> {\n\tconst out = new Set<number>();\n\tconst [lo, hi] = range;\n\tconst parts = field.split(\",\");\n\tfor (const partRaw of parts) {\n\t\tconst part = partRaw.trim();\n\t\t// step: e.g. \"*/2\" or \"0-30/2\"\n\t\tconst stepMatch = /^(.+?)\\/(\\d+)$/.exec(part);\n\t\tlet base = part;\n\t\tlet step = 1;\n\t\tif (stepMatch) {\n\t\t\tbase = stepMatch[1]!;\n\t\t\tstep = Number(stepMatch[2]);\n\t\t}\n\t\tlet start: number;\n\t\tlet end: number;\n\t\tif (base === \"*\") {\n\t\t\tstart = lo;\n\t\t\tend = hi;\n\t\t} else if (base.includes(\"-\")) {\n\t\t\tconst [a, b] = base.split(\"-\").map((s) => resolveValue(s, lo, hi));\n\t\t\tstart = a;\n\t\t\tend = b;\n\t\t} else {\n\t\t\tconst v = resolveValue(base, lo, hi);\n\t\t\tstart = v;\n\t\t\tend = stepMatch ? hi : v;\n\t\t}\n\t\tif (start > end) {\n\t\t\tthrow new Error(`Invalid range in cron field: \"${part}\"`);\n\t\t}\n\t\tfor (let i = start; i <= end; i += step) {\n\t\t\tout.add(i);\n\t\t}\n\t}\n\treturn out;\n}\n\nfunction resolveValue(token: string, lo: number, hi: number): number {\n\tconst t = token.trim();\n\tif (t === \"*\") return lo;\n\tconst named = FIELD_NAMES[t.toUpperCase()];\n\tif (named !== undefined) return named;\n\tconst n = Number(t);\n\tif (Number.isNaN(n)) {\n\t\tthrow new Error(`Invalid cron field value: \"${token}\"`);\n\t}\n\tif (n < lo || n > hi) {\n\t\tthrow new Error(`Cron value ${n} out of range [${lo}, ${hi}]`);\n\t}\n\treturn n;\n}\n\n/**\n * Parse a cron expression. Throws on invalid syntax. The returned\n * object can be queried for the next match (`expr.next(new Date())`).\n */\nexport function parseCron(expression: string): CronExpression {\n\treturn new CronExpression(expression);\n}\n\n/** Convenience: return the next Date matching `expression` after `from`. */\nexport function nextCron(\n\texpression: string,\n\tfrom: Date = new Date(),\n): Date | null {\n\treturn parseCron(expression).next(from);\n}\n",
5
+ "/**\n * Scanner bridge — connects the Application's provider scanner with the\n * ScheduleService. Lives in its own file to avoid circular imports\n * between schedule.module.ts and schedule.service.ts.\n */\nimport type { ScheduleService } from \"./schedule.service.js\";\n\nlet _scheduleService: ScheduleService | null = null;\n\n/** @internal Set by ScheduleService constructor. */\nexport function __setScheduleService(svc: ScheduleService | null): void {\n\t_scheduleService = svc;\n}\n\n/** @internal Called by Application.bootstrap() for each resolved provider. */\nexport function scanProviderForSchedules(instance: unknown): void {\n\tconst svc = _scheduleService;\n\tif (!svc) return;\n\tconst ctor = (instance as any)?.constructor;\n\tif (!ctor) return;\n\tconst hasCron = Reflect.getMetadata(\"nexus:schedule:cron\", ctor);\n\tconst hasInterval = Reflect.getMetadata(\"nexus:schedule:interval\", ctor);\n\tconst hasTimeout = Reflect.getMetadata(\"nexus:schedule:timeout\", ctor);\n\tif (hasCron || hasInterval || hasTimeout) {\n\t\tsvc.scanInstance(instance as object);\n\t}\n}\n",
6
+ "/**\n * `@Cron(expression)` — schedule a method as a cron task.\n *\n * Mirrors `@nestjs/schedule`'s decorator. The decorated method runs\n * on the cron schedule; pair it with `ScheduleModule.scanForSchedulers`\n * to register at boot.\n *\n * Usage:\n * @Injectable()\n * class CleanupWorker {\n * constructor(@Inject(ScheduleService.TOKEN) private schedule: ScheduleService) {}\n *\n * @Cron('0 * * * *') // every hour\n * async hourly() {\n * // ...\n * }\n *\n * @Cron('@daily', { timezone: 'UTC' })\n * async dailyDigest() {\n * // ...\n * }\n * }\n *\n * // src/app/main.ts\n * const app = new Application(AppModule);\n * const schedule = app.container.resolve(ScheduleService);\n * for (const instance of getInjectables(app)) {\n * await schedule.scanForSchedulers(instance);\n * }\n * schedule.start();\n */\n\nimport \"reflect-metadata\";\nimport type { ScheduleService } from \"../schedule.service.js\";\nimport type { CronExpression, CronOptions, ScheduleHandler } from \"../types.js\";\n\nconst CRON_META = \"nexus:schedule:cron\";\nconst INTERVAL_META = \"nexus:schedule:interval\";\nconst TIMEOUT_META = \"nexus:schedule:timeout\";\n\n/**\n * Schedule the decorated method as a cron task.\n */\nexport function Cron(\n\texpression: CronExpression,\n\toptions: CronOptions = {},\n): MethodDecorator {\n\treturn (target, propertyKey, descriptor) => {\n\t\tif (!descriptor || typeof descriptor.value !== \"function\") {\n\t\t\tthrow new Error(\"@Cron can only decorate methods.\");\n\t\t}\n\t\tconst ctor = target.constructor as object;\n\t\tconst hooks: Array<{\n\t\t\tmethod: string;\n\t\t\texpression: CronExpression;\n\t\t\toptions: CronOptions;\n\t\t}> =\n\t\t\t(Reflect.getMetadata(CRON_META, ctor) as\n\t\t\t\t| Array<{\n\t\t\t\t\t\tmethod: string;\n\t\t\t\t\t\texpression: CronExpression;\n\t\t\t\t\t\toptions: CronOptions;\n\t\t\t\t }>\n\t\t\t\t| undefined) ?? [];\n\t\thooks.push({ method: String(propertyKey), expression, options });\n\t\tReflect.defineMetadata(CRON_META, hooks, ctor);\n\t};\n}\n\n/**\n * Schedule the decorated method to run every `milliseconds`.\n */\nexport function Interval(milliseconds: number, name?: string): MethodDecorator {\n\treturn (target, propertyKey, descriptor) => {\n\t\tif (!descriptor || typeof descriptor.value !== \"function\") {\n\t\t\tthrow new Error(\"@Interval can only decorate methods.\");\n\t\t}\n\t\tconst ctor = target.constructor as object;\n\t\tconst hooks: Array<{\n\t\t\tmethod: string;\n\t\t\tmilliseconds: number;\n\t\t\tname?: string;\n\t\t}> =\n\t\t\t(Reflect.getMetadata(INTERVAL_META, ctor) as\n\t\t\t\t| Array<{ method: string; milliseconds: number; name?: string }>\n\t\t\t\t| undefined) ?? [];\n\t\thooks.push({ method: String(propertyKey), milliseconds, name });\n\t\tReflect.defineMetadata(INTERVAL_META, hooks, ctor);\n\t};\n}\n\n/**\n * Schedule the decorated method to run once after `milliseconds`.\n */\nexport function Timeout(milliseconds: number, name?: string): MethodDecorator {\n\treturn (target, propertyKey, descriptor) => {\n\t\tif (!descriptor || typeof descriptor.value !== \"function\") {\n\t\t\tthrow new Error(\"@Timeout can only decorate methods.\");\n\t\t}\n\t\tconst ctor = target.constructor as object;\n\t\tconst hooks: Array<{\n\t\t\tmethod: string;\n\t\t\tmilliseconds: number;\n\t\t\tname?: string;\n\t\t}> =\n\t\t\t(Reflect.getMetadata(TIMEOUT_META, ctor) as\n\t\t\t\t| Array<{ method: string; milliseconds: number; name?: string }>\n\t\t\t\t| undefined) ?? [];\n\t\thooks.push({ method: String(propertyKey), milliseconds, name });\n\t\tReflect.defineMetadata(TIMEOUT_META, hooks, ctor);\n\t};\n}\n\n/**\n * Get the cron hooks declared on a class.\n */\nexport function getCronHooks(\n\ttarget: unknown,\n): Array<{ method: string; expression: CronExpression; options: CronOptions }> {\n\tconst ctor =\n\t\t(target as { constructor?: object }).constructor ?? (target as object);\n\treturn (\n\t\t(Reflect.getMetadata(CRON_META, ctor) as\n\t\t\t| Array<{\n\t\t\t\t\tmethod: string;\n\t\t\t\t\texpression: CronExpression;\n\t\t\t\t\toptions: CronOptions;\n\t\t\t }>\n\t\t\t| undefined) ?? []\n\t);\n}\n\nexport function getIntervalHooks(\n\ttarget: unknown,\n): Array<{ method: string; milliseconds: number; name?: string }> {\n\tconst ctor =\n\t\t(target as { constructor?: object }).constructor ?? (target as object);\n\treturn (\n\t\t(Reflect.getMetadata(INTERVAL_META, ctor) as\n\t\t\t| Array<{ method: string; milliseconds: number; name?: string }>\n\t\t\t| undefined) ?? []\n\t);\n}\n\nexport function getTimeoutHooks(\n\ttarget: unknown,\n): Array<{ method: string; milliseconds: number; name?: string }> {\n\tconst ctor =\n\t\t(target as { constructor?: object }).constructor ?? (target as object);\n\treturn (\n\t\t(Reflect.getMetadata(TIMEOUT_META, ctor) as\n\t\t\t| Array<{ method: string; milliseconds: number; name?: string }>\n\t\t\t| undefined) ?? []\n\t);\n}\n\n/**\n * Scan an instance for `@Cron` / `@Interval` / `@Timeout` hooks and\n * register them with the `ScheduleService`.\n */\nexport async function scanForSchedulers(\n\tinstance: object,\n\tservice: ScheduleService,\n): Promise<string[]> {\n\tconst ids: string[] = [];\n\n\tfor (const h of getCronHooks(instance)) {\n\t\tconst fn = (instance as Record<string, unknown>)[h.method] as\n\t\t\t| ScheduleHandler\n\t\t\t| undefined;\n\t\tif (typeof fn !== \"function\") continue;\n\t\tconst id = service.addCron(h.expression, fn.bind(instance), {\n\t\t\t...h.options,\n\t\t\tname: h.options.name ?? `${instance.constructor.name}.${h.method}`,\n\t\t});\n\t\tids.push(id);\n\t}\n\n\tfor (const h of getIntervalHooks(instance)) {\n\t\tconst fn = (instance as Record<string, unknown>)[h.method] as\n\t\t\t| ScheduleHandler\n\t\t\t| undefined;\n\t\tif (typeof fn !== \"function\") continue;\n\t\tconst id = service.addInterval(\n\t\t\th.milliseconds,\n\t\t\tfn.bind(instance),\n\t\t\th.name ?? `${instance.constructor.name}.${h.method}`,\n\t\t);\n\t\tids.push(id);\n\t}\n\n\tfor (const h of getTimeoutHooks(instance)) {\n\t\tconst fn = (instance as Record<string, unknown>)[h.method] as\n\t\t\t| ScheduleHandler\n\t\t\t| undefined;\n\t\tif (typeof fn !== \"function\") continue;\n\t\tconst id = service.addTimeout(\n\t\t\th.milliseconds,\n\t\t\tfn.bind(instance),\n\t\t\th.name ?? `${instance.constructor.name}.${h.method}`,\n\t\t);\n\t\tids.push(id);\n\t}\n\n\treturn ids;\n}\n\n// Re-export for convenience.\nexport type { ScheduleService };\n",
7
+ "/**\n * Cron expression parser + next-run calculator.\n *\n * Supports the standard 5-field crontab syntax, an optional 6-field\n * variant (with seconds), common aliases, and \"@every <duration>\".\n *\n * * * * * * every minute\n * 0 * * * * every hour\n * star-slash-15 every 15m\n * 0 9 * * 1-5 9am on weekdays\n * 0 0 1 * * first of the month\n * 30 14 1 4 * Apr 1st at 14:30\n * @yearly @annually 0 0 1 1 *\n * @monthly 0 0 1 * *\n * @weekly 0 0 * * 0\n * @daily @midnight 0 0 * * *\n * @hourly 0 * * * *\n * @every 1h30m every 90 minutes\n *\n * Field names (JAN, FEB, SUN, MON, ...) are accepted case-insensitively.\n */\n\nconst FIELD_RANGES: Array<[number, number]> = [\n\t[0, 59], // minute\n\t[0, 23], // hour\n\t[1, 31], // day of month\n\t[1, 12], // month\n\t[0, 7], // day of week (0 or 7 = Sunday)\n];\n\nconst FIELD_NAMES: Record<string, number> = {\n\tJAN: 1,\n\tFEB: 2,\n\tMAR: 3,\n\tAPR: 4,\n\tMAY: 5,\n\tJUN: 6,\n\tJUL: 7,\n\tAUG: 8,\n\tSEP: 9,\n\tOCT: 10,\n\tNOV: 11,\n\tDEC: 12,\n\tSUN: 0,\n\tMON: 1,\n\tTUE: 2,\n\tWED: 3,\n\tTHU: 4,\n\tFRI: 5,\n\tSAT: 6,\n};\n\nconst ALIASES: Record<string, string> = {\n\t\"@yearly\": \"0 0 1 1 *\",\n\t\"@annually\": \"0 0 1 1 *\",\n\t\"@monthly\": \"0 0 1 * *\",\n\t\"@weekly\": \"0 0 * * 0\",\n\t\"@daily\": \"0 0 * * *\",\n\t\"@midnight\": \"0 0 * * *\",\n\t\"@hourly\": \"0 * * * *\",\n};\n\n/** A single field expanded into a set of allowed numeric values. */\nexport class CronField {\n\treadonly values: Set<number>;\n\n\tconstructor(field: string, range: [number, number]) {\n\t\tthis.values = parseField(field, range);\n\t}\n\n\tcontains(n: number): boolean {\n\t\treturn this.values.has(n);\n\t}\n}\n\n/** A fully-parsed cron expression. */\nexport class CronExpression {\n\treadonly fields: CronField[]; // 5 or 6 entries\n\treadonly hasSeconds: boolean;\n\n\tconstructor(raw: string) {\n\t\tconst expanded = expandAlias(raw);\n\t\tconst every = expandEvery(expanded);\n\n\t\tif (every) {\n\t\t\t// \"@every Nd|Nh|Nm|Ns\" → uniform interval\n\t\t\tthis.hasSeconds = true;\n\t\t\tthis.fields = everyToFields(every);\n\t\t\treturn;\n\t\t}\n\n\t\tconst parts = expanded.trim().split(/\\s+/);\n\t\tif (parts.length === 5) {\n\t\t\tthis.hasSeconds = false;\n\t\t\tthis.fields = parts.map((p, i) => new CronField(p, FIELD_RANGES[i]!));\n\t\t} else if (parts.length === 6) {\n\t\t\tthis.hasSeconds = true;\n\t\t\tconst sec: [number, number] = [0, 59];\n\t\t\tthis.fields = [\n\t\t\t\tnew CronField(parts[0]!, sec),\n\t\t\t\t...parts.slice(1).map((p, i) => new CronField(p, FIELD_RANGES[i]!)),\n\t\t\t];\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid cron expression: \"${raw}\" (expected 5 or 6 fields, got ${parts.length})`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Return the next Date at or after `from` that matches this\n\t * expression. Returns null if no match is found within `maxYears`\n\t * (default 5) — which would indicate a misconfigured expression.\n\t */\n\tnext(from: Date, maxYears = 5): Date | null {\n\t\tconst cap = new Date(from.getTime() + maxYears * 365 * 24 * 60 * 60 * 1000);\n\t\t// For 5-field expressions (no seconds), start from the next minute boundary.\n\t\t// For 6-field expressions (with seconds), start from +1 second.\n\t\tconst offsetMs = this.hasSeconds ? 1000 : 60_000;\n\t\tlet cur = new Date(from.getTime() + offsetMs);\n\t\tcur.setMilliseconds(0);\n\t\t// For 5-field, also zero out seconds so we start at :00 of the next minute.\n\t\tif (!this.hasSeconds) cur.setSeconds(0);\n\n\t\t// Brute-force: step minute-by-minute, but skip ahead when a\n\t\t// higher-order field doesn't match. For most crons this is\n\t\t// fast enough; for very sparse crons we use a forwarder.\n\t\tlet safety = 0;\n\t\twhile (cur <= cap) {\n\t\t\tif (this.matches(cur)) {\n\t\t\t\treturn cur;\n\t\t\t}\n\t\t\t// Fast-forward: if the month doesn't match, jump to next month.\n\t\t\tif (!this.fields[this.hasSeconds ? 4 : 3]!.contains(cur.getMonth() + 1)) {\n\t\t\t\tcur = new Date(cur.getFullYear(), cur.getMonth() + 1, 1, 0, 0, 0, 0);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// If day-of-month is restricted and current day doesn't match,\n\t\t\t// jump to next month at the first allowed day.\n\t\t\tconst domIdx = this.hasSeconds ? 3 : 2;\n\t\t\tconst domField = this.fields[domIdx]!;\n\t\t\tif (!domField.contains(cur.getDate())) {\n\t\t\t\t// Find the first allowed day in the set, or jump to next month.\n\t\t\t\tconst sortedDays = [...domField.values].sort((a, b) => a - b);\n\t\t\t\tconst nextDay = sortedDays.find((d) => d >= cur.getDate());\n\t\t\t\tif (nextDay !== undefined) {\n\t\t\t\t\tcur = new Date(\n\t\t\t\t\t\tcur.getFullYear(),\n\t\t\t\t\t\tcur.getMonth(),\n\t\t\t\t\t\tnextDay,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tcur = new Date(\n\t\t\t\t\t\tcur.getFullYear(),\n\t\t\t\t\t\tcur.getMonth() + 1,\n\t\t\t\t\t\tsortedDays[0]!,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t0,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// If the hour doesn't match, jump to next hour.\n\t\t\tif (!this.fields[this.hasSeconds ? 2 : 1]!.contains(cur.getHours())) {\n\t\t\t\tcur = new Date(\n\t\t\t\t\tcur.getFullYear(),\n\t\t\t\t\tcur.getMonth(),\n\t\t\t\t\tcur.getDate(),\n\t\t\t\t\tcur.getHours() + 1,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// If the minute doesn't match, jump to next minute.\n\t\t\tif (!this.fields[this.hasSeconds ? 1 : 0]!.contains(cur.getMinutes())) {\n\t\t\t\tcur = new Date(\n\t\t\t\t\tcur.getFullYear(),\n\t\t\t\t\tcur.getMonth(),\n\t\t\t\t\tcur.getDate(),\n\t\t\t\t\tcur.getHours(),\n\t\t\t\t\tcur.getMinutes() + 1,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// If seconds field exists and doesn't match, jump to next second.\n\t\t\tif (this.hasSeconds && !this.fields[0]!.contains(cur.getSeconds())) {\n\t\t\t\tcur = new Date(cur.getTime() + 1000);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Fallback: step 1 second (shouldn't normally hit).\n\t\t\tcur = new Date(cur.getTime() + 1000);\n\t\t\tif (++safety > 1_000_000) return null;\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate matches(d: Date): boolean {\n\t\tconst fields = this.hasSeconds\n\t\t\t? [\n\t\t\t\t\td.getSeconds(),\n\t\t\t\t\td.getMinutes(),\n\t\t\t\t\td.getHours(),\n\t\t\t\t\td.getDate(),\n\t\t\t\t\td.getMonth() + 1,\n\t\t\t\t\td.getDay(),\n\t\t\t\t]\n\t\t\t: [\n\t\t\t\t\td.getMinutes(),\n\t\t\t\t\td.getHours(),\n\t\t\t\t\td.getDate(),\n\t\t\t\t\td.getMonth() + 1,\n\t\t\t\t\td.getDay(),\n\t\t\t\t];\n\t\t// Day-of-week in crontab: 0 = Sunday. Day-of-month is OR'd with\n\t\t// day-of-week when both are restricted (standard crontab behavior).\n\t\tconst domField = this.fields[this.hasSeconds ? 3 : 2]!;\n\t\tconst dowField = this.fields[this.hasSeconds ? 4 : 3]!;\n\t\tconst isWildDom = domField.values.size === FIELD_RANGES[2]![1]!;\n\t\tconst isWildDow = dowField.values.size === FIELD_RANGES[4]![1]! + 1;\n\t\tconst dayMatch =\n\t\t\tisWildDom || isWildDow\n\t\t\t\t? domField.contains(d.getDate()) || dowField.contains(d.getDay())\n\t\t\t\t: domField.contains(d.getDate()) || dowField.contains(d.getDay());\n\n\t\tfor (let i = 0; i < this.fields.length; i++) {\n\t\t\tif (i === (this.hasSeconds ? 3 : 2)) continue;\n\t\t\tif (!this.fields[i]!.contains(fields[i]!)) return false;\n\t\t}\n\t\treturn dayMatch;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction expandAlias(raw: string): string {\n\tconst trimmed = raw.trim();\n\tconst alias = ALIASES[trimmed.toLowerCase()];\n\treturn alias ?? trimmed;\n}\n\nfunction expandEvery(raw: string): number | null {\n\tconst m = /^@every\\s+(\\d+)\\s*(s|m|h|d)?$/i.exec(raw.trim());\n\tif (!m) return null;\n\tconst n = Number(m[1]);\n\tconst unit = (m[2] ?? \"s\").toLowerCase();\n\tswitch (unit) {\n\t\tcase \"s\":\n\t\t\treturn n * 1000;\n\t\tcase \"m\":\n\t\t\treturn n * 60 * 1000;\n\t\tcase \"h\":\n\t\t\treturn n * 60 * 60 * 1000;\n\t\tcase \"d\":\n\t\t\treturn n * 24 * 60 * 60 * 1000;\n\t}\n\treturn null;\n}\n\nfunction everyToFields(intervalMs: number): CronField[] {\n\t// Generate a 6-field expression that fires every `intervalMs`\n\t// starting from the next round minute.\n\tconst seconds = Math.floor(intervalMs / 1000);\n\tif (seconds < 60) {\n\t\t// fire every N seconds (only if it divides 60)\n\t\tif (60 % seconds === 0) {\n\t\t\treturn [\n\t\t\t\tnew CronField(`*/${seconds}`, [0, 59]),\n\t\t\t\tnew CronField(\"*\", [0, 59]),\n\t\t\t\tnew CronField(\"*\", [0, 23]),\n\t\t\t\tnew CronField(\"*\", [1, 31]),\n\t\t\t\tnew CronField(\"*\", [1, 12]),\n\t\t\t\tnew CronField(\"*\", [0, 7]),\n\t\t\t];\n\t\t}\n\t}\n\t// Otherwise just allow every minute; the registry layer handles\n\t// throttling via setInterval.\n\treturn [\n\t\tnew CronField(\"0\", [0, 59]),\n\t\tnew CronField(\"*\", [0, 59]),\n\t\tnew CronField(\"*\", [0, 23]),\n\t\tnew CronField(\"*\", [1, 31]),\n\t\tnew CronField(\"*\", [1, 12]),\n\t\tnew CronField(\"*\", [0, 7]),\n\t];\n}\n\nfunction parseField(field: string, range: [number, number]): Set<number> {\n\tconst out = new Set<number>();\n\tconst [lo, hi] = range;\n\tconst parts = field.split(\",\");\n\tfor (const partRaw of parts) {\n\t\tconst part = partRaw.trim();\n\t\t// step: e.g. \"*/2\" or \"0-30/2\"\n\t\tconst stepMatch = /^(.+?)\\/(\\d+)$/.exec(part);\n\t\tlet base = part;\n\t\tlet step = 1;\n\t\tif (stepMatch) {\n\t\t\tbase = stepMatch[1]!;\n\t\t\tstep = Number(stepMatch[2]);\n\t\t}\n\t\tlet start: number;\n\t\tlet end: number;\n\t\tif (base === \"*\") {\n\t\t\tstart = lo;\n\t\t\tend = hi;\n\t\t} else if (base.includes(\"-\")) {\n\t\t\tconst [a, b] = base.split(\"-\").map((s) => resolveValue(s, lo, hi));\n\t\t\tstart = a;\n\t\t\tend = b;\n\t\t} else {\n\t\t\tconst v = resolveValue(base, lo, hi);\n\t\t\tstart = v;\n\t\t\tend = stepMatch ? hi : v;\n\t\t}\n\t\tif (start > end) {\n\t\t\tthrow new Error(`Invalid range in cron field: \"${part}\"`);\n\t\t}\n\t\tfor (let i = start; i <= end; i += step) {\n\t\t\tout.add(i);\n\t\t}\n\t}\n\treturn out;\n}\n\nfunction resolveValue(token: string, lo: number, hi: number): number {\n\tconst t = token.trim();\n\tif (t === \"*\") return lo;\n\tconst named = FIELD_NAMES[t.toUpperCase()];\n\tif (named !== undefined) return named;\n\tconst n = Number(t);\n\tif (Number.isNaN(n)) {\n\t\tthrow new Error(`Invalid cron field value: \"${token}\"`);\n\t}\n\tif (n < lo || n > hi) {\n\t\tthrow new Error(`Cron value ${n} out of range [${lo}, ${hi}]`);\n\t}\n\treturn n;\n}\n\n/**\n * Parse a cron expression. Throws on invalid syntax. The returned\n * object can be queried for the next match (`expr.next(new Date())`).\n */\nexport function parseCron(expression: string): CronExpression {\n\treturn new CronExpression(expression);\n}\n\n/** Convenience: return the next Date matching `expression` after `from`. */\nexport function nextCron(\n\texpression: string,\n\tfrom: Date = new Date(),\n): Date | null {\n\treturn parseCron(expression).next(from);\n}\n",
6
8
  "/**\n * In-process scheduler backend.\n *\n * Runs on a single setInterval tick (default 1s) and dispatches due\n * tasks. Honors cron expressions via `CronExpression.next()`, fixed\n * intervals via `setInterval`, and one-shot delays via `setTimeout`.\n *\n * Use for Bun / Node long-running servers. For Cloudflare Workers,\n * use the dedicated `CloudflareSchedulesBackend` which integrates\n * with Cron Triggers.\n */\n\nimport type {\n\tScheduleRegistry,\n\tScheduleHandler,\n\tScheduledTask,\n\tCronExpression,\n\tCronOptions,\n\tScheduleEvent,\n\tScheduleEventListener,\n\tTaskKind,\n} from \"../types.js\";\nimport { CronExpression as CronExpr, nextCron } from \"../cron-parser.js\";\n\ninterface InternalTask {\n\tid: string;\n\tname: string;\n\tkind: TaskKind;\n\texpression: string;\n\t/** Next run time (epoch ms). */\n\tnextRunAt: number;\n\t/** Last run time (epoch ms). */\n\tlastRunAt?: number;\n\tinvocations: number;\n\tlastError?: string;\n\tstatus: \"running\" | \"stopped\" | \"paused\";\n\thandler: ScheduleHandler;\n\t/** Interval handle for `interval` / `timeout` tasks. */\n\ttimer?: ReturnType<typeof setInterval> | ReturnType<typeof setTimeout>;\n}\n\nexport interface MemoryBackendOptions {\n\t/** Tick interval in ms. Default: 1000. */\n\ttickMs?: number;\n\t/** Default cron timezone. */\n\tdefaultTimezone?: string;\n\t/** Skip tasks that fall behind by more than this many ms. Default: 60_000. */\n\tmaxDriftMs?: number;\n}\n\nexport class MemorySchedulesBackend implements ScheduleRegistry {\n\t#tasks = new Map<string, InternalTask>();\n\t#byName = new Map<string, string>(); // name → id\n\t#listeners = new Set<ScheduleEventListener>();\n\t#tickHandle: ReturnType<typeof setInterval> | null = null;\n\t#tickMs: number;\n\t#maxDriftMs: number;\n\t#defaultTimezone: string | undefined = undefined;\n\t#nextId = 1;\n\n\tconstructor(options: MemoryBackendOptions = {}) {\n\t\tthis.#tickMs = options.tickMs ?? 1000;\n\t\tthis.#maxDriftMs = options.maxDriftMs ?? 60_000;\n\t\tthis.#defaultTimezone = options.defaultTimezone;\n\t}\n\n\t// ===========================================================================\n\t// Public API\n\t// ===========================================================================\n\n\taddCron(\n\t\tname: string,\n\t\texpression: CronExpression,\n\t\thandler: ScheduleHandler,\n\t\toptions: CronOptions = {},\n\t): string {\n\t\tconst id = this.#allocateId();\n\t\tconst next = nextCron(\n\t\t\texpression,\n\t\t\toptions.runOnInit ? new Date(Date.now() - 1000) : new Date(),\n\t\t);\n\t\tconst task: InternalTask = {\n\t\t\tid,\n\t\t\tname,\n\t\t\tkind: \"cron\",\n\t\t\texpression,\n\t\t\tnextRunAt: next?.getTime() ?? Date.now() + 60_000,\n\t\t\tinvocations: 0,\n\t\t\tstatus: \"running\",\n\t\t\thandler,\n\t\t};\n\t\tthis.#tasks.set(id, task);\n\t\tthis.#byName.set(name, id);\n\t\tthis.#emit({\n\t\t\tkind: \"task:registered\",\n\t\t\tid,\n\t\t\tname,\n\t\t\ttaskKind: \"cron\",\n\t\t\texpression,\n\t\t});\n\t\treturn id;\n\t}\n\n\taddInterval(name: string, ms: number, handler: ScheduleHandler): string {\n\t\tconst id = this.#allocateId();\n\t\tconst task: InternalTask = {\n\t\t\tid,\n\t\t\tname,\n\t\t\tkind: \"interval\",\n\t\t\texpression: `${ms}ms`,\n\t\t\tnextRunAt: Date.now() + ms,\n\t\t\tinvocations: 0,\n\t\t\tstatus: \"running\",\n\t\t\thandler,\n\t\t};\n\t\ttask.timer = setInterval(() => this.#runTask(id), ms);\n\t\tthis.#tasks.set(id, task);\n\t\tthis.#byName.set(name, id);\n\t\tthis.#emit({\n\t\t\tkind: \"task:registered\",\n\t\t\tid,\n\t\t\tname,\n\t\t\ttaskKind: \"interval\",\n\t\t\texpression: `${ms}ms`,\n\t\t});\n\t\treturn id;\n\t}\n\n\taddTimeout(name: string, ms: number, handler: ScheduleHandler): string {\n\t\tconst id = this.#allocateId();\n\t\tconst task: InternalTask = {\n\t\t\tid,\n\t\t\tname,\n\t\t\tkind: \"timeout\",\n\t\t\texpression: `${ms}ms`,\n\t\t\tnextRunAt: Date.now() + ms,\n\t\t\tinvocations: 0,\n\t\t\tstatus: \"running\",\n\t\t\thandler,\n\t\t};\n\t\ttask.timer = setTimeout(() => this.#runOnceAndRemove(id), ms);\n\t\tthis.#tasks.set(id, task);\n\t\tthis.#byName.set(name, id);\n\t\tthis.#emit({\n\t\t\tkind: \"task:registered\",\n\t\t\tid,\n\t\t\tname,\n\t\t\ttaskKind: \"timeout\",\n\t\t\texpression: `${ms}ms`,\n\t\t});\n\t\treturn id;\n\t}\n\n\tdelete(idOrName: string): boolean {\n\t\tconst id = this.#resolveId(idOrName);\n\t\tif (!id) return false;\n\t\tconst task = this.#tasks.get(id);\n\t\tif (!task) return false;\n\t\tthis.#clearTimer(task);\n\t\tthis.#tasks.delete(id);\n\t\tthis.#byName.delete(task.name);\n\t\tthis.#emit({ kind: \"task:deleted\", id });\n\t\treturn true;\n\t}\n\n\tlist(): ScheduledTask[] {\n\t\treturn [...this.#tasks.values()].map((t) => this.#toPublic(t));\n\t}\n\n\tget(idOrName: string): ScheduledTask | undefined {\n\t\tconst id = this.#resolveId(idOrName);\n\t\tif (!id) return undefined;\n\t\tconst task = this.#tasks.get(id);\n\t\treturn task ? this.#toPublic(task) : undefined;\n\t}\n\n\tpause(idOrName: string): boolean {\n\t\tconst id = this.#resolveId(idOrName);\n\t\tif (!id) return false;\n\t\tconst task = this.#tasks.get(id);\n\t\tif (!task) return false;\n\t\tthis.#clearTimer(task);\n\t\ttask.status = \"paused\";\n\t\tthis.#emit({ kind: \"task:paused\", id });\n\t\treturn true;\n\t}\n\n\tresume(idOrName: string): boolean {\n\t\tconst id = this.#resolveId(idOrName);\n\t\tif (!id) return false;\n\t\tconst task = this.#tasks.get(id);\n\t\tif (!task) return false;\n\t\tif (task.kind === \"interval\" && !task.timer) {\n\t\t\ttask.timer = setInterval(\n\t\t\t\t() => this.#runTask(id),\n\t\t\t\tNumber(task.expression.replace(\"ms\", \"\")),\n\t\t\t);\n\t\t}\n\t\ttask.status = \"running\";\n\t\tthis.#emit({ kind: \"task:resumed\", id });\n\t\treturn true;\n\t}\n\n\tasync stop(): Promise<void> {\n\t\tfor (const task of this.#tasks.values()) {\n\t\t\tthis.#clearTimer(task);\n\t\t}\n\t\tthis.#tasks.clear();\n\t\tthis.#byName.clear();\n\t\tif (this.#tickHandle) clearInterval(this.#tickHandle);\n\t\tthis.#tickHandle = null;\n\t}\n\n\t// ===========================================================================\n\t// Events\n\t// ===========================================================================\n\n\ton(listener: ScheduleEventListener): () => void {\n\t\tthis.#listeners.add(listener);\n\t\treturn () => this.#listeners.delete(listener);\n\t}\n\n\t// ===========================================================================\n\t// Lifecycle\n\t// ===========================================================================\n\n\t/** Start the tick loop. Idempotent. */\n\tstart(): void {\n\t\tif (this.#tickHandle) return;\n\t\tthis.#tickHandle = setInterval(() => this.#tick(), this.#tickMs);\n\t\t// Don't keep Node alive just for the tick.\n\t\tconst handle = this.#tickHandle as unknown as { unref?: () => void };\n\t\tif (typeof handle.unref === \"function\") handle.unref();\n\t}\n\n\t// ===========================================================================\n\t// Internal\n\t// ===========================================================================\n\n\t#allocateId(): string {\n\t\treturn `sched-${this.#nextId++}`;\n\t}\n\n\t#resolveId(idOrName: string): string | null {\n\t\tif (this.#tasks.has(idOrName)) return idOrName;\n\t\treturn this.#byName.get(idOrName) ?? null;\n\t}\n\n\t#toPublic(t: InternalTask): ScheduledTask {\n\t\tconst public_: ScheduledTask = {\n\t\t\tid: t.id,\n\t\t\tname: t.name,\n\t\t\tkind: t.kind,\n\t\t\texpression: t.expression,\n\t\t\tstatus: t.status,\n\t\t\tinvocations: t.invocations,\n\t\t};\n\t\tif (t.lastRunAt !== undefined) {\n\t\t\tpublic_.lastRunAt = new Date(t.lastRunAt).toISOString();\n\t\t}\n\t\tpublic_.nextRunAt = new Date(t.nextRunAt).toISOString();\n\t\tif (t.lastError !== undefined) public_.lastError = t.lastError;\n\t\treturn public_;\n\t}\n\n\t#clearTimer(task: InternalTask): void {\n\t\tif (task.timer) {\n\t\t\tclearInterval(task.timer as ReturnType<typeof setInterval>);\n\t\t\tclearTimeout(task.timer as ReturnType<typeof setTimeout>);\n\t\t\ttask.timer = undefined;\n\t\t}\n\t}\n\n\t#tick(): void {\n\t\tconst now = Date.now();\n\t\tfor (const [id, task] of this.#tasks) {\n\t\t\tif (task.status !== \"running\") continue;\n\t\t\tif (task.kind !== \"cron\") continue; // intervals/timeouts fire via their own timer\n\t\t\tif (task.nextRunAt > now) continue;\n\t\t\tvoid this.#runTask(id);\n\t\t}\n\t}\n\n\tasync #runTask(id: string): Promise<void> {\n\t\tconst task = this.#tasks.get(id);\n\t\tif (!task) return;\n\t\tconst startedAt = new Date();\n\t\tthis.#emit({\n\t\t\tkind: \"task:invoked\",\n\t\t\tid,\n\t\t\tname: task.name,\n\t\t\tstartedAt: startedAt.toISOString(),\n\t\t});\n\t\tconst start = Date.now();\n\t\ttry {\n\t\t\tconst result = await task.handler();\n\t\t\ttask.invocations++;\n\t\t\ttask.lastRunAt = start;\n\t\t\ttask.lastError = undefined;\n\t\t\tthis.#emit({\n\t\t\t\tkind: \"task:completed\",\n\t\t\t\tid,\n\t\t\t\tname: task.name,\n\t\t\t\tdurationMs: Date.now() - start,\n\t\t\t\treturnvalue: result,\n\t\t\t});\n\t\t} catch (err) {\n\t\t\ttask.invocations++;\n\t\t\ttask.lastRunAt = start;\n\t\t\tconst error = err instanceof Error ? err : new Error(String(err));\n\t\t\ttask.lastError = error.message;\n\t\t\tthis.#emit({ kind: \"task:failed\", id, name: task.name, error });\n\t\t} finally {\n\t\t\t// Schedule the next cron run.\n\t\t\tif (task.kind === \"cron\" && task.status === \"running\") {\n\t\t\t\tconst next = nextCron(task.expression, new Date());\n\t\t\t\tif (next) {\n\t\t\t\t\tconst drift = next.getTime() - Date.now();\n\t\t\t\t\ttask.nextRunAt =\n\t\t\t\t\t\tdrift > this.#maxDriftMs ? Date.now() + 60_000 : next.getTime();\n\t\t\t\t} else {\n\t\t\t\t\ttask.nextRunAt = Date.now() + 60_000;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t#runOnceAndRemove(id: string): void {\n\t\tvoid this.#runTask(id);\n\t\tconst task = this.#tasks.get(id);\n\t\tif (task) {\n\t\t\tthis.#tasks.delete(id);\n\t\t\tthis.#byName.delete(task.name);\n\t\t\tthis.#emit({ kind: \"task:deleted\", id });\n\t\t}\n\t}\n\n\t#emit(event: ScheduleEvent): void {\n\t\tfor (const l of this.#listeners) {\n\t\t\tvoid Promise.resolve(l(event));\n\t\t}\n\t}\n}\n\n// Re-export the parser's CronExpression class for users who want to\n// parse expressions manually.\nexport { CronExpr };\n",
7
9
  "/**\n * Cloudflare Cron Triggers backend.\n *\n * Cloudflare Cron Triggers are configured in `wrangler.toml`:\n *\n * [[triggers.crons]]\n * cron = \"every 15m (your expression)\"\n *\n * The trigger fires a Worker's `scheduled(event, env, ctx)` handler.\n * We dispatch that to the registered task by name.\n *\n * This backend is a **registration-only facade**: tasks are stored\n * locally (so `nx route:list`-style introspection works), but the\n * actual scheduling is at the platform level. The worker's `scheduled`\n * export calls `dispatch(event)` to run the matching task.\n */\n\nimport type {\n\tScheduleRegistry,\n\tScheduleHandler,\n\tScheduledTask,\n\tCronExpression,\n\tCronOptions,\n\tScheduleEvent,\n\tScheduleEventListener,\n} from \"../types.js\";\n\ninterface InternalTask {\n\tid: string;\n\tname: string;\n\texpression: string;\n\thandler: ScheduleHandler;\n\toptions: CronOptions;\n}\n\n/** Shape of the Worker's `scheduled` event. Mirrors `cloudflare-types`. */\nexport interface CloudflareScheduledEvent {\n\tcron: string;\n\t/** ISO timestamp of when the trigger fired. */\n\tscheduledTime: Date | number;\n}\n\nexport interface CloudflareSchedulesOptions {\n\t/** Validate that registered expressions match the wrangler.toml trigger. Default: true. */\n\tvalidateAgainstTrigger?: boolean;\n}\n\nexport class CloudflareSchedulesBackend implements ScheduleRegistry {\n\t#tasks = new Map<string, InternalTask>();\n\t#byName = new Map<string, string>();\n\t#listeners = new Set<ScheduleEventListener>();\n\t#nextId = 1;\n\t#validate: boolean;\n\n\tconstructor(options: CloudflareSchedulesOptions = {}) {\n\t\tthis.#validate = options.validateAgainstTrigger ?? true;\n\t}\n\n\taddCron(\n\t\tname: string,\n\t\texpression: CronExpression,\n\t\thandler: ScheduleHandler,\n\t\toptions: CronOptions = {},\n\t): string {\n\t\tconst id = `sched-${this.#nextId++}`;\n\t\tthis.#tasks.set(id, { id, name, expression, handler, options });\n\t\tthis.#byName.set(name, id);\n\t\tthis.#emit({\n\t\t\tkind: \"task:registered\",\n\t\t\tid,\n\t\t\tname,\n\t\t\ttaskKind: \"cron\",\n\t\t\texpression,\n\t\t});\n\t\treturn id;\n\t}\n\n\taddInterval(): string {\n\t\tthrow new Error(\n\t\t\t\"[schedule/cloudflare] setInterval is not supported on Workers. \" +\n\t\t\t\t\"Use @Cron with a short interval or use the memory backend for in-process scheduling.\",\n\t\t);\n\t}\n\n\taddTimeout(): string {\n\t\tthrow new Error(\n\t\t\t\"[schedule/cloudflare] setTimeout is not supported on Workers. \" +\n\t\t\t\t'Use @Cron with a delay (e.g. \"@every 30s\") or run the work from a request handler.',\n\t\t);\n\t}\n\n\tdelete(idOrName: string): boolean {\n\t\tconst id = this.#resolveId(idOrName);\n\t\tif (!id) return false;\n\t\tconst task = this.#tasks.get(id);\n\t\tif (!task) return false;\n\t\tthis.#tasks.delete(id);\n\t\tthis.#byName.delete(task.name);\n\t\tthis.#emit({ kind: \"task:deleted\", id });\n\t\treturn true;\n\t}\n\n\tlist(): ScheduledTask[] {\n\t\treturn [...this.#tasks.values()].map((t) => ({\n\t\t\tid: t.id,\n\t\t\tname: t.name,\n\t\t\tkind: \"cron\",\n\t\t\texpression: t.expression,\n\t\t\tstatus: \"running\",\n\t\t\tinvocations: 0,\n\t\t}));\n\t}\n\n\tget(idOrName: string): ScheduledTask | undefined {\n\t\tconst id = this.#resolveId(idOrName);\n\t\tif (!id) return undefined;\n\t\tconst t = this.#tasks.get(id);\n\t\treturn t\n\t\t\t? {\n\t\t\t\t\tid: t.id,\n\t\t\t\t\tname: t.name,\n\t\t\t\t\tkind: \"cron\",\n\t\t\t\t\texpression: t.expression,\n\t\t\t\t\tstatus: \"running\",\n\t\t\t\t\tinvocations: 0,\n\t\t\t\t}\n\t\t\t: undefined;\n\t}\n\n\tpause(): boolean {\n\t\t// No-op — Cloudflare controls the trigger. Edit wrangler.toml to disable.\n\t\treturn false;\n\t}\n\n\tresume(): boolean {\n\t\treturn false;\n\t}\n\n\tasync stop(): Promise<void> {\n\t\tthis.#tasks.clear();\n\t\tthis.#byName.clear();\n\t}\n\n\t// ===========================================================================\n\t// Events\n\t// ===========================================================================\n\n\ton(listener: ScheduleEventListener): () => void {\n\t\tthis.#listeners.add(listener);\n\t\treturn () => this.#listeners.delete(listener);\n\t}\n\n\t// ===========================================================================\n\t// Worker integration\n\t// ===========================================================================\n\n\t/**\n\t * Return the Worker's `scheduled()` handler. Mount it in the\n\t * default export:\n\t *\n\t * export default {\n\t * fetch: app.fetch,\n\t * scheduled: backend.scheduledHandler(),\n\t * };\n\t *\n\t * The handler dispatches based on the trigger's cron expression\n\t * (or, when validation is disabled, by event ordering).\n\t */\n\tscheduledHandler(): (event: CloudflareScheduledEvent) => Promise<void> {\n\t\treturn async (event) => {\n\t\t\tfor (const task of this.#tasks.values()) {\n\t\t\t\tif (this.#validate && task.expression !== event.cron) continue;\n\t\t\t\tawait this.#dispatch(task, event);\n\t\t\t}\n\t\t};\n\t}\n\n\tasync #dispatch(\n\t\ttask: InternalTask,\n\t\tevent: CloudflareScheduledEvent,\n\t): Promise<void> {\n\t\tconst startedAt = new Date();\n\t\tthis.#emit({\n\t\t\tkind: \"task:invoked\",\n\t\t\tid: task.id,\n\t\t\tname: task.name,\n\t\t\tstartedAt: startedAt.toISOString(),\n\t\t});\n\t\ttry {\n\t\t\tconst result = await task.handler();\n\t\t\tthis.#emit({\n\t\t\t\tkind: \"task:completed\",\n\t\t\t\tid: task.id,\n\t\t\t\tname: task.name,\n\t\t\t\tdurationMs: Date.now() - startedAt.getTime(),\n\t\t\t\treturnvalue: result,\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tconst error = err instanceof Error ? err : new Error(String(err));\n\t\t\tthis.#emit({ kind: \"task:failed\", id: task.id, name: task.name, error });\n\t\t}\n\t\tvoid event; // (kept for future event-based logic)\n\t}\n\n\t// ===========================================================================\n\t// Internal\n\t// ===========================================================================\n\n\t#resolveId(idOrName: string): string | null {\n\t\tif (this.#tasks.has(idOrName)) return idOrName;\n\t\treturn this.#byName.get(idOrName) ?? null;\n\t}\n\n\t#emit(event: ScheduleEvent): void {\n\t\tfor (const l of this.#listeners) {\n\t\t\tvoid Promise.resolve(l(event));\n\t\t}\n\t}\n}\n",
8
- "/**\n * `ScheduleService` — DI-friendly facade over a `ScheduleRegistry`.\n *\n * Mirrors the `@nestjs/schedule` API for familiarity. Controllers and\n * services can:\n * - Inject this and call `addCron / addInterval / addTimeout` to\n * schedule dynamically.\n * - Inject this and call `list / get / pause / resume / delete` to\n * introspect or mutate registered tasks.\n *\n * For static registration, use the `@Cron`, `@Interval`, `@Timeout`\n * decorators plus `ScheduleModule.scanForSchedulers(instance)`.\n */\n\nimport { Inject, Injectable } from '@nexusts/core';\nimport type {\n\tScheduleRegistry,\n\tScheduleConfig,\n\tCronExpression,\n\tCronOptions,\n\tScheduledTask,\n\tScheduleHandler,\n\tScheduleEvent,\n\tScheduleEventListener,\n} from './types.js';\nimport {\n\tMemorySchedulesBackend,\n\tCloudflareSchedulesBackend,\n} from './backends/index.js';\n\n@Injectable()\nexport class ScheduleService {\n\t/** DI token — use with `@Inject(ScheduleService.TOKEN)`. */\n\tstatic readonly TOKEN = Symbol.for('nexus:ScheduleService');\n\n\treadonly registry: ScheduleRegistry;\n\t#listeners = new Set<ScheduleEventListener>();\n\t#started = false;\n\t#memoryBackend: MemorySchedulesBackend | null = null;\n\n\tconstructor(@Inject('SCHEDULE_CONFIG') private readonly config: ScheduleConfig = {}) {\n\t\tthis.registry = this.#createBackend(config);\n\t}\n\n\t// ===========================================================================\n\t// Static-style API (used by @Cron / @Interval / @Timeout decorators)\n\t// ===========================================================================\n\n\t/**\n\t * Schedule a cron task. Returns the assigned task id.\n\t */\n\taddCron(\n\t\texpression: CronExpression,\n\t\thandler: ScheduleHandler,\n\t\toptions: CronOptions & { name?: string } = {},\n\t): string {\n\t\tconst name = options.name ?? `cron-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\t\treturn this.registry.addCron(name, expression, handler, options);\n\t}\n\n\taddInterval(milliseconds: number, handler: ScheduleHandler, name?: string): string {\n\t\treturn this.registry.addInterval(name ?? `interval-${Date.now()}`, milliseconds, handler);\n\t}\n\n\taddTimeout(milliseconds: number, handler: ScheduleHandler, name?: string): string {\n\t\treturn this.registry.addTimeout(name ?? `timeout-${Date.now()}`, milliseconds, handler);\n\t}\n\n\t// ===========================================================================\n\t// Introspection / mutation\n\t// ===========================================================================\n\n\tlist(): ScheduledTask[] {\n\t\treturn this.registry.list();\n\t}\n\n\tget(idOrName: string): ScheduledTask | undefined {\n\t\treturn this.registry.get(idOrName);\n\t}\n\n\tpause(idOrName: string): boolean {\n\t\treturn this.registry.pause(idOrName);\n\t}\n\n\tresume(idOrName: string): boolean {\n\t\treturn this.registry.resume(idOrName);\n\t}\n\n\tdelete(idOrName: string): boolean {\n\t\treturn this.registry.delete(idOrName);\n\t}\n\n\t// ===========================================================================\n\t// Events\n\t// ===========================================================================\n\n\ton(listener: ScheduleEventListener): () => void {\n\t\tthis.#listeners.add(listener);\n\t\treturn () => this.#listeners.delete(listener);\n\t}\n\n\t// ===========================================================================\n\t// Lifecycle\n\t// ===========================================================================\n\n\t/** Start the in-process scheduler tick. Idempotent. */\n\tstart(): void {\n\t\tif (this.#started) return;\n\t\tthis.#started = true;\n\t\tif (this.#memoryBackend) {\n\t\t\tthis.#memoryBackend.start();\n\t\t}\n\t\t// Bridge backend events.\n\t\tthis.registry.on((event) => this.#broadcast(event));\n\t}\n\n\tasync stop(): Promise<void> {\n\t\tif (!this.#started) return;\n\t\tthis.#started = false;\n\t\tawait this.registry.stop();\n\t}\n\n\t/**\n\t * Get the underlying in-process backend (for tests / `nx dev`).\n\t * Returns null when the configured backend isn't memory.\n\t */\n\tgetMemoryBackend(): MemorySchedulesBackend | null {\n\t\treturn this.#memoryBackend;\n\t}\n\n\t/**\n\t * Get the underlying Cloudflare backend (for Workers). Returns\n\t * null when the configured backend isn't Cloudflare.\n\t */\n\tgetCloudflareBackend(): CloudflareSchedulesBackend | null {\n\t\treturn this.registry instanceof CloudflareSchedulesBackend ? this.registry : null;\n\t}\n\n\t// ===========================================================================\n\t// Internal\n\t// ===========================================================================\n\n\t#createBackend(config: ScheduleConfig): ScheduleRegistry {\n\t\tswitch (config.backend ?? 'memory') {\n\t\t\tcase 'memory': {\n\t\t\t\tconst backend = new MemorySchedulesBackend({\n\t\t\t\t\ttickMs: config.memory?.tickMs ?? 1000,\n\t\t\t\t\tmaxDriftMs: config.memory?.maxDriftMs,\n\t\t\t\t\tdefaultTimezone: config.defaultTimezone,\n\t\t\t\t});\n\t\t\t\tthis.#memoryBackend = backend;\n\t\t\t\treturn backend;\n\t\t\t}\n\t\t\tcase 'cloudflare':\n\t\t\t\treturn new CloudflareSchedulesBackend();\n\t\t}\n\t}\n\n\t#broadcast(event: ScheduleEvent): void {\n\t\tfor (const l of this.#listeners) {\n\t\t\tvoid Promise.resolve(l(event));\n\t\t}\n\t}\n}",
9
- "/**\n * `ScheduleModule` — drop-in module for adding scheduled tasks to a\n * NexusTS app.\n *\n * Usage:\n * // src/app/app.module.ts\n * @Module({\n * imports: [\n * ScheduleModule.forRoot({\n * backend: 'memory', // or 'cloudflare'\n * defaultTimezone: 'UTC',\n * }),\n * ],\n * })\n * export class AppModule {}\n *\n * // any service\n * @Injectable()\n * class CleanupWorker {\n * constructor(@Inject(ScheduleService.TOKEN) private schedule: ScheduleService) {}\n *\n * @Cron('0 * * * *') // every hour\n * async hourly() {\n * // ...\n * }\n * }\n *\n * // bootstrap\n * const app = new Application(AppModule);\n * const schedule = app.container.resolve(ScheduleService);\n * await scanForSchedulers(worker, schedule);\n * schedule.start();\n */\n\nimport \"reflect-metadata\";\nimport { Module } from \"@nexusts/core\";\nimport { ScheduleService } from \"./schedule.service.js\";\nimport type { ScheduleConfig } from \"./types.js\";\n\n@Module({\n\tproviders: [\n\t\tScheduleService,\n\t\t{ provide: ScheduleService.TOKEN, useExisting: ScheduleService },\n\t],\n\texports: [ScheduleService, ScheduleService.TOKEN],\n})\nexport class ScheduleModule {\n\t/**\n\t * Build a configured `ScheduleModule` class.\n\t */\n\tstatic forRoot(config: ScheduleConfig = {}) {\n\t\t@Module({\n\t\t\tproviders: [\n\t\t\t\tScheduleService,\n\t\t\t\t{ provide: ScheduleService.TOKEN, useExisting: ScheduleService },\n\t\t\t\t{ provide: \"SCHEDULE_CONFIG\", useValue: config },\n\t\t\t],\n\t\t\texports: [ScheduleService, ScheduleService.TOKEN],\n\t\t})\n\t\tclass ConfiguredScheduleModule {}\n\n\t\tObject.defineProperty(ConfiguredScheduleModule, \"name\", {\n\t\t\tvalue: \"ConfiguredScheduleModule\",\n\t\t});\n\n\t\treturn ConfiguredScheduleModule;\n\t}\n}\n",
10
- "/**\n * `@Cron(expression)` schedule a method as a cron task.\n *\n * Mirrors `@nestjs/schedule`'s decorator. The decorated method runs\n * on the cron schedule; pair it with `ScheduleModule.scanForSchedulers`\n * to register at boot.\n *\n * Usage:\n * @Injectable()\n * class CleanupWorker {\n * constructor(@Inject(ScheduleService.TOKEN) private schedule: ScheduleService) {}\n *\n * @Cron('0 * * * *') // every hour\n * async hourly() {\n * // ...\n * }\n *\n * @Cron('@daily', { timezone: 'UTC' })\n * async dailyDigest() {\n * // ...\n * }\n * }\n *\n * // src/app/main.ts\n * const app = new Application(AppModule);\n * const schedule = app.container.resolve(ScheduleService);\n * for (const instance of getInjectables(app)) {\n * await schedule.scanForSchedulers(instance);\n * }\n * schedule.start();\n */\n\nimport \"reflect-metadata\";\nimport type { ScheduleService } from \"../schedule.service.js\";\nimport type { CronExpression, CronOptions, ScheduleHandler } from \"../types.js\";\n\nconst CRON_META = \"nexus:schedule:cron\";\nconst INTERVAL_META = \"nexus:schedule:interval\";\nconst TIMEOUT_META = \"nexus:schedule:timeout\";\n\n/**\n * Schedule the decorated method as a cron task.\n */\nexport function Cron(\n\texpression: CronExpression,\n\toptions: CronOptions = {},\n): MethodDecorator {\n\treturn (target, propertyKey, descriptor) => {\n\t\tif (!descriptor || typeof descriptor.value !== \"function\") {\n\t\t\tthrow new Error(\"@Cron can only decorate methods.\");\n\t\t}\n\t\tconst ctor = target.constructor as object;\n\t\tconst hooks: Array<{\n\t\t\tmethod: string;\n\t\t\texpression: CronExpression;\n\t\t\toptions: CronOptions;\n\t\t}> =\n\t\t\t(Reflect.getMetadata(CRON_META, ctor) as\n\t\t\t\t| Array<{\n\t\t\t\t\t\tmethod: string;\n\t\t\t\t\t\texpression: CronExpression;\n\t\t\t\t\t\toptions: CronOptions;\n\t\t\t\t }>\n\t\t\t\t| undefined) ?? [];\n\t\thooks.push({ method: String(propertyKey), expression, options });\n\t\tReflect.defineMetadata(CRON_META, hooks, ctor);\n\t};\n}\n\n/**\n * Schedule the decorated method to run every `milliseconds`.\n */\nexport function Interval(milliseconds: number, name?: string): MethodDecorator {\n\treturn (target, propertyKey, descriptor) => {\n\t\tif (!descriptor || typeof descriptor.value !== \"function\") {\n\t\t\tthrow new Error(\"@Interval can only decorate methods.\");\n\t\t}\n\t\tconst ctor = target.constructor as object;\n\t\tconst hooks: Array<{\n\t\t\tmethod: string;\n\t\t\tmilliseconds: number;\n\t\t\tname?: string;\n\t\t}> =\n\t\t\t(Reflect.getMetadata(INTERVAL_META, ctor) as\n\t\t\t\t| Array<{ method: string; milliseconds: number; name?: string }>\n\t\t\t\t| undefined) ?? [];\n\t\thooks.push({ method: String(propertyKey), milliseconds, name });\n\t\tReflect.defineMetadata(INTERVAL_META, hooks, ctor);\n\t};\n}\n\n/**\n * Schedule the decorated method to run once after `milliseconds`.\n */\nexport function Timeout(milliseconds: number, name?: string): MethodDecorator {\n\treturn (target, propertyKey, descriptor) => {\n\t\tif (!descriptor || typeof descriptor.value !== \"function\") {\n\t\t\tthrow new Error(\"@Timeout can only decorate methods.\");\n\t\t}\n\t\tconst ctor = target.constructor as object;\n\t\tconst hooks: Array<{\n\t\t\tmethod: string;\n\t\t\tmilliseconds: number;\n\t\t\tname?: string;\n\t\t}> =\n\t\t\t(Reflect.getMetadata(TIMEOUT_META, ctor) as\n\t\t\t\t| Array<{ method: string; milliseconds: number; name?: string }>\n\t\t\t\t| undefined) ?? [];\n\t\thooks.push({ method: String(propertyKey), milliseconds, name });\n\t\tReflect.defineMetadata(TIMEOUT_META, hooks, ctor);\n\t};\n}\n\n/**\n * Get the cron hooks declared on a class.\n */\nexport function getCronHooks(\n\ttarget: unknown,\n): Array<{ method: string; expression: CronExpression; options: CronOptions }> {\n\tconst ctor =\n\t\t(target as { constructor?: object }).constructor ?? (target as object);\n\treturn (\n\t\t(Reflect.getMetadata(CRON_META, ctor) as\n\t\t\t| Array<{\n\t\t\t\t\tmethod: string;\n\t\t\t\t\texpression: CronExpression;\n\t\t\t\t\toptions: CronOptions;\n\t\t\t }>\n\t\t\t| undefined) ?? []\n\t);\n}\n\nexport function getIntervalHooks(\n\ttarget: unknown,\n): Array<{ method: string; milliseconds: number; name?: string }> {\n\tconst ctor =\n\t\t(target as { constructor?: object }).constructor ?? (target as object);\n\treturn (\n\t\t(Reflect.getMetadata(INTERVAL_META, ctor) as\n\t\t\t| Array<{ method: string; milliseconds: number; name?: string }>\n\t\t\t| undefined) ?? []\n\t);\n}\n\nexport function getTimeoutHooks(\n\ttarget: unknown,\n): Array<{ method: string; milliseconds: number; name?: string }> {\n\tconst ctor =\n\t\t(target as { constructor?: object }).constructor ?? (target as object);\n\treturn (\n\t\t(Reflect.getMetadata(TIMEOUT_META, ctor) as\n\t\t\t| Array<{ method: string; milliseconds: number; name?: string }>\n\t\t\t| undefined) ?? []\n\t);\n}\n\n/**\n * Scan an instance for `@Cron` / `@Interval` / `@Timeout` hooks and\n * register them with the `ScheduleService`.\n */\nexport async function scanForSchedulers(\n\tinstance: object,\n\tservice: ScheduleService,\n): Promise<string[]> {\n\tconst ids: string[] = [];\n\n\tfor (const h of getCronHooks(instance)) {\n\t\tconst fn = (instance as Record<string, unknown>)[h.method] as\n\t\t\t| ScheduleHandler\n\t\t\t| undefined;\n\t\tif (typeof fn !== \"function\") continue;\n\t\tconst id = service.addCron(h.expression, fn.bind(instance), {\n\t\t\t...h.options,\n\t\t\tname: h.options.name ?? `${instance.constructor.name}.${h.method}`,\n\t\t});\n\t\tids.push(id);\n\t}\n\n\tfor (const h of getIntervalHooks(instance)) {\n\t\tconst fn = (instance as Record<string, unknown>)[h.method] as\n\t\t\t| ScheduleHandler\n\t\t\t| undefined;\n\t\tif (typeof fn !== \"function\") continue;\n\t\tconst id = service.addInterval(\n\t\t\th.milliseconds,\n\t\t\tfn.bind(instance),\n\t\t\th.name ?? `${instance.constructor.name}.${h.method}`,\n\t\t);\n\t\tids.push(id);\n\t}\n\n\tfor (const h of getTimeoutHooks(instance)) {\n\t\tconst fn = (instance as Record<string, unknown>)[h.method] as\n\t\t\t| ScheduleHandler\n\t\t\t| undefined;\n\t\tif (typeof fn !== \"function\") continue;\n\t\tconst id = service.addTimeout(\n\t\t\th.milliseconds,\n\t\t\tfn.bind(instance),\n\t\t\th.name ?? `${instance.constructor.name}.${h.method}`,\n\t\t);\n\t\tids.push(id);\n\t}\n\n\treturn ids;\n}\n\n// Re-export for convenience.\nexport type { ScheduleService };\n"
10
+ "import { Inject, Injectable, OnApplicationInit } from '@nexusts/core';\nimport { __setScheduleService } from './scanner.js';\nimport type {\n\tScheduleRegistry,\n\tScheduleConfig,\n\tCronExpression,\n\tCronOptions,\n\tScheduledTask,\n\tScheduleHandler,\n\tScheduleEvent,\n\tScheduleEventListener,\n} from './types.js';\nimport {\n\tMemorySchedulesBackend,\n\tCloudflareSchedulesBackend,\n} from './backends/index.js';\n\n\n\n@Injectable()\nexport class ScheduleService implements OnApplicationInit {\n\t/** DI token — use with `@Inject(ScheduleService.TOKEN)`. */\n\tstatic readonly TOKEN = Symbol.for('nexus:ScheduleService');\n\n\treadonly registry: ScheduleRegistry;\n\t#listeners = new Set<ScheduleEventListener>();\n\t#started = false;\n\t#memoryBackend: MemorySchedulesBackend | null = null;\n\n\tconstructor(@Inject('SCHEDULE_CONFIG') private _config: ScheduleConfig = {}) {\n\t\tthis.registry = this.#createBackend(this._config);\n\t\t// Register this instance immediately so the Application's scanner\n\t\t// callback can use it for subsequent providers resolved after this one.\n\t\t__setScheduleService(this);\n\t\t// Bun hot-reload support: when the module is about to be disposed,\n\t\t// stop all timers so stale intervals from the previous version don't\n\t\t// keep running alongside the new version.\n\t\tif (typeof module !== 'undefined' && (module as any).hot) {\n\t\t\t(module as any).hot?.dispose?.(() => {\n\t\t\t\tvoid this.stop();\n\t\t\t});\n\t\t}\n\t}\n\n\t/** @internal called by Application.bootstrap() for each resolved instance. */\n\tscanInstance(instance: object): void {\n\t\tconst { getCronHooks, getIntervalHooks, getTimeoutHooks } =\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports\n\t\t\trequire('./decorators/cron.js');\n\t\tfor (const h of getCronHooks(instance)) {\n\t\t\tconst fn = (instance as Record<string, unknown>)[h.method] as\n\t\t\t\t| ScheduleHandler\n\t\t\t\t| undefined;\n\t\t\tif (typeof fn !== 'function') continue;\n\t\t\tthis.addCron(h.expression, fn.bind(instance), {\n\t\t\t\t...h.options,\n\t\t\t\tname: h.options.name ?? `${instance.constructor.name}.${h.method}`,\n\t\t\t});\n\t\t}\n\t\tfor (const h of getIntervalHooks(instance)) {\n\t\t\tconst fn = (instance as Record<string, unknown>)[h.method] as\n\t\t\t\t| ScheduleHandler\n\t\t\t\t| undefined;\n\t\t\tif (typeof fn !== 'function') continue;\n\t\t\tthis.addInterval(h.milliseconds, fn.bind(instance), h.name ?? `${instance.constructor.name}.${h.method}`);\n\t\t}\n\t\tfor (const h of getTimeoutHooks(instance)) {\n\t\t\tconst fn = (instance as Record<string, unknown>)[h.method] as\n\t\t\t\t| ScheduleHandler\n\t\t\t\t| undefined;\n\t\t\tif (typeof fn !== 'function') continue;\n\t\t\tthis.addTimeout(h.milliseconds, fn.bind(instance), h.name ?? `${instance.constructor.name}.${h.method}`);\n\t\t}\n\t}\n\n\tasync onApplicationInit(): Promise<void> {\n\t\t// Register this instance so the scanner callback can use it.\n\t\tconst { __setScheduleService } = await import('./scanner.js');\n\t\t__setScheduleService(this);\n\t\t// Auto-start the scheduler\n\t\tthis.start();\n\t}\n\n\t// ===========================================================================\n\t// Static-style API (used by @Cron / @Interval / @Timeout decorators)\n\t// ===========================================================================\n\n\taddCron(\n\t\texpression: CronExpression,\n\t\thandler: ScheduleHandler,\n\t\toptions: CronOptions & { name?: string } = {},\n\t): string {\n\t\tconst name = options.name ?? `cron-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\t\treturn this.registry.addCron(name, expression, handler, options);\n\t}\n\n\taddInterval(milliseconds: number, handler: ScheduleHandler, name?: string): string {\n\t\treturn this.registry.addInterval(name ?? `interval-${Date.now()}`, milliseconds, handler);\n\t}\n\n\taddTimeout(milliseconds: number, handler: ScheduleHandler, name?: string): string {\n\t\treturn this.registry.addTimeout(name ?? `timeout-${Date.now()}`, milliseconds, handler);\n\t}\n\n\tlist(): ScheduledTask[] {\n\t\treturn this.registry.list();\n\t}\n\n\tget(idOrName: string): ScheduledTask | undefined {\n\t\treturn this.registry.get(idOrName);\n\t}\n\n\tpause(idOrName: string): boolean {\n\t\treturn this.registry.pause(idOrName);\n\t}\n\n\tresume(idOrName: string): boolean {\n\t\treturn this.registry.resume(idOrName);\n\t}\n\n\tdelete(idOrName: string): boolean {\n\t\treturn this.registry.delete(idOrName);\n\t}\n\n\ton(listener: ScheduleEventListener): () => void {\n\t\tthis.#listeners.add(listener);\n\t\treturn () => this.#listeners.delete(listener);\n\t}\n\n\tstart(): void {\n\t\tif (this.#started) return;\n\t\tthis.#started = true;\n\t\tif (this.#memoryBackend) this.#memoryBackend.start();\n\t\tthis.registry.on((event) => this.#broadcast(event));\n\t}\n\n\tasync stop(): Promise<void> {\n\t\tif (!this.#started) return;\n\t\tthis.#started = false;\n\t\tawait this.registry.stop();\n\t}\n\n\tgetMemoryBackend(): MemorySchedulesBackend | null {\n\t\treturn this.#memoryBackend;\n\t}\n\n\tgetCloudflareBackend(): CloudflareSchedulesBackend | null {\n\t\treturn this.registry instanceof CloudflareSchedulesBackend ? this.registry : null;\n\t}\n\n\t#createBackend(config: ScheduleConfig): ScheduleRegistry {\n\t\tswitch (config.backend ?? 'memory') {\n\t\t\tcase 'memory': {\n\t\t\t\tconst backend = new MemorySchedulesBackend({\n\t\t\t\t\ttickMs: config.memory?.tickMs ?? 1000,\n\t\t\t\t\tmaxDriftMs: config.memory?.maxDriftMs,\n\t\t\t\t\tdefaultTimezone: config.defaultTimezone,\n\t\t\t\t});\n\t\t\t\tthis.#memoryBackend = backend;\n\t\t\t\treturn backend;\n\t\t\t}\n\t\t\tcase 'cloudflare':\n\t\t\t\treturn new CloudflareSchedulesBackend();\n\t\t}\n\t}\n\n\t#broadcast(event: ScheduleEvent): void {\n\t\tfor (const l of this.#listeners) {\n\t\t\tvoid Promise.resolve(l(event));\n\t\t}\n\t}\n}\n",
11
+ "/**\n * `ScheduleModule` — drop-in module for adding scheduled tasks.\n *\n * Usage:\n * @Module({\n * imports: [ScheduleModule.forRoot({ backend: 'memory' })],\n * })\n * export class AppModule {}\n *\n * @Injectable()\n * class Worker {\n * @Cron('0 * * * *')\n * async hourly() { ... }\n * }\n *\n * No manual scanForSchedulers or start() call needed the module\n * auto-scans every resolved provider during bootstrap.\n */\n\nimport \"reflect-metadata\";\nimport { Module, setScheduleScanner } from \"@nexusts/core\";\nimport { ScheduleService } from \"./schedule.service.js\";\nimport { scanProviderForSchedules } from \"./scanner.js\";\nimport type { ScheduleConfig } from \"./types.js\";\n\n// Register the scanner hook once at module load time.\nsetScheduleScanner(scanProviderForSchedules);\n\n@Module({\n\tproviders: [\n\t\tScheduleService,\n\t\t{ provide: ScheduleService.TOKEN, useExisting: ScheduleService },\n\t],\n\texports: [ScheduleService, ScheduleService.TOKEN],\n})\nexport class ScheduleModule {\n\tstatic forRoot(config: ScheduleConfig = {}) {\n\t\t@Module({\n\t\t\tproviders: [\n\t\t\t\tScheduleService,\n\t\t\t\t{ provide: ScheduleService.TOKEN, useExisting: ScheduleService },\n\t\t\t\t{ provide: \"SCHEDULE_CONFIG\", useValue: config },\n\t\t\t],\n\t\t\texports: [ScheduleService, ScheduleService.TOKEN],\n\t\t})\n\t\tclass ConfiguredScheduleModule {}\n\n\t\tObject.defineProperty(ConfiguredScheduleModule, \"name\", {\n\t\t\tvalue: \"ConfiguredScheduleModule\",\n\t\t});\n\n\t\treturn ConfiguredScheduleModule;\n\t}\n}\n",
12
+ "/**\n * Public API for the NexusTS schedule module.\n *\n * Two backends out of the box:\n * - In-process runs on Bun / Node via setInterval + cron tick.\n * - Cloudflare Cron Triggers Workers-native, fires from wrangler.toml.\n *\n * Mirrors `@nestjs/schedule`'s decorator API: `@Cron`, `@Interval`,\n * `@Timeout`. Plus a programmatic `ScheduleService` for dynamic\n * registration.\n *\n * Quick start:\n *\n * // src/app/app.module.ts\n * import { Module } from 'nexusjs';\n * import { ScheduleModule } from 'nexusjs/schedule';\n *\n * @Module({\n * imports: [ScheduleModule.forRoot({ backend: 'memory' })],\n * })\n * export class AppModule {}\n *\n * // any service\n * import { ScheduleService, Cron, Interval, scanForSchedulers } from 'nexusjs/schedule';\n *\n * @Injectable()\n * class CleanupWorker {\n * constructor(@Inject(ScheduleService.TOKEN) private schedule: ScheduleService) {}\n *\n * @Cron('0 * * * *') // every hour\n * async hourly() { /* ... *\\/ }\n *\n * @Interval(60_000) // every minute\n * async tick() { /* ... *\\/ }\n * }\n *\n * // bootstrap\n * const app = new Application(AppModule);\n * const schedule = app.container.resolve(ScheduleService);\n * await scanForSchedulers(worker, schedule);\n * schedule.start();\n */\n\nexport * from \"./types.js\";\nexport {\n\tMemorySchedulesBackend,\n\tCloudflareSchedulesBackend,\n\tCronExpr,\n} from \"./backends/index.js\";\nexport type { MemoryBackendOptions } from \"./backends/memory.js\";\nexport type {\n\tCloudflareScheduledEvent,\n\tCloudflareSchedulesOptions,\n} from \"./backends/cloudflare.js\";\nexport { ScheduleService } from \"./schedule.service.js\";\nexport { ScheduleModule } from \"./schedule.module.js\";\nexport {\n\tCron,\n\tInterval,\n\tTimeout,\n\tscanForSchedulers,\n\tgetCronHooks,\n\tgetIntervalHooks,\n\tgetTimeoutHooks,\n} from \"./decorators/cron.js\";\nexport {\n\tparseCron,\n\tnextCron,\n\tCronExpression as CronExpressionClass,\n\tCronField,\n} from \"./cron-parser.js\";\n"
11
13
  ],
12
- "mappings": "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",
13
- "debugId": "BE7269D6BACECC6B64756E2164756E21",
14
+ "mappings": "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",
15
+ "debugId": "DBB1B65D1B69D17764756E2164756E21",
14
16
  "names": []
15
17
  }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Scanner bridge — connects the Application's provider scanner with the
3
+ * ScheduleService. Lives in its own file to avoid circular imports
4
+ * between schedule.module.ts and schedule.service.ts.
5
+ */
6
+ import type { ScheduleService } from "./schedule.service.js";
7
+ /** @internal Set by ScheduleService constructor. */
8
+ export declare function __setScheduleService(svc: ScheduleService | null): void;
9
+ /** @internal Called by Application.bootstrap() for each resolved provider. */
10
+ export declare function scanProviderForSchedules(instance: unknown): void;
@@ -1,42 +1,24 @@
1
1
  /**
2
- * `ScheduleModule` — drop-in module for adding scheduled tasks to a
3
- * NexusTS app.
2
+ * `ScheduleModule` — drop-in module for adding scheduled tasks.
4
3
  *
5
4
  * Usage:
6
- * // src/app/app.module.ts
7
5
  * @Module({
8
- * imports: [
9
- * ScheduleModule.forRoot({
10
- * backend: 'memory', // or 'cloudflare'
11
- * defaultTimezone: 'UTC',
12
- * }),
13
- * ],
6
+ * imports: [ScheduleModule.forRoot({ backend: 'memory' })],
14
7
  * })
15
8
  * export class AppModule {}
16
9
  *
17
- * // any service
18
10
  * @Injectable()
19
- * class CleanupWorker {
20
- * constructor(@Inject(ScheduleService.TOKEN) private schedule: ScheduleService) {}
21
- *
22
- * @Cron('0 * * * *') // every hour
23
- * async hourly() {
24
- * // ...
25
- * }
11
+ * class Worker {
12
+ * @Cron('0 * * * *')
13
+ * async hourly() { ... }
26
14
  * }
27
15
  *
28
- * // bootstrap
29
- * const app = new Application(AppModule);
30
- * const schedule = app.container.resolve(ScheduleService);
31
- * await scanForSchedulers(worker, schedule);
32
- * schedule.start();
16
+ * No manual scanForSchedulers or start() call needed — the module
17
+ * auto-scans every resolved provider during bootstrap.
33
18
  */
34
19
  import "reflect-metadata";
35
20
  import type { ScheduleConfig } from "./types.js";
36
21
  export declare class ScheduleModule {
37
- /**
38
- * Build a configured `ScheduleModule` class.
39
- */
40
22
  static forRoot(config?: ScheduleConfig): {
41
23
  new (): {};
42
24
  };
@@ -1,28 +1,16 @@
1
- /**
2
- * `ScheduleService` — DI-friendly facade over a `ScheduleRegistry`.
3
- *
4
- * Mirrors the `@nestjs/schedule` API for familiarity. Controllers and
5
- * services can:
6
- * - Inject this and call `addCron / addInterval / addTimeout` to
7
- * schedule dynamically.
8
- * - Inject this and call `list / get / pause / resume / delete` to
9
- * introspect or mutate registered tasks.
10
- *
11
- * For static registration, use the `@Cron`, `@Interval`, `@Timeout`
12
- * decorators plus `ScheduleModule.scanForSchedulers(instance)`.
13
- */
1
+ import { OnApplicationInit } from '@nexusts/core';
14
2
  import type { ScheduleRegistry, ScheduleConfig, CronExpression, CronOptions, ScheduledTask, ScheduleHandler, ScheduleEventListener } from './types.js';
15
3
  import { MemorySchedulesBackend, CloudflareSchedulesBackend } from './backends/index.js';
16
- export declare class ScheduleService {
4
+ export declare class ScheduleService implements OnApplicationInit {
17
5
  #private;
18
- private readonly config;
6
+ private _config;
19
7
  /** DI token — use with `@Inject(ScheduleService.TOKEN)`. */
20
8
  static readonly TOKEN: unique symbol;
21
9
  readonly registry: ScheduleRegistry;
22
- constructor(config?: ScheduleConfig);
23
- /**
24
- * Schedule a cron task. Returns the assigned task id.
25
- */
10
+ constructor(_config?: ScheduleConfig);
11
+ /** @internal called by Application.bootstrap() for each resolved instance. */
12
+ scanInstance(instance: object): void;
13
+ onApplicationInit(): Promise<void>;
26
14
  addCron(expression: CronExpression, handler: ScheduleHandler, options?: CronOptions & {
27
15
  name?: string;
28
16
  }): string;
@@ -34,17 +22,8 @@ export declare class ScheduleService {
34
22
  resume(idOrName: string): boolean;
35
23
  delete(idOrName: string): boolean;
36
24
  on(listener: ScheduleEventListener): () => void;
37
- /** Start the in-process scheduler tick. Idempotent. */
38
25
  start(): void;
39
26
  stop(): Promise<void>;
40
- /**
41
- * Get the underlying in-process backend (for tests / `nx dev`).
42
- * Returns null when the configured backend isn't memory.
43
- */
44
27
  getMemoryBackend(): MemorySchedulesBackend | null;
45
- /**
46
- * Get the underlying Cloudflare backend (for Workers). Returns
47
- * null when the configured backend isn't Cloudflare.
48
- */
49
28
  getCloudflareBackend(): CloudflareSchedulesBackend | null;
50
29
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexusts/schedule",
3
- "version": "0.7.2",
3
+ "version": "0.7.4",
4
4
  "description": "Cron scheduling (@Cron / @Interval / @Timeout)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -12,15 +12,20 @@
12
12
  "import": "./dist/index.js"
13
13
  }
14
14
  },
15
- "files": ["dist", "README.md"],
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
16
19
  "scripts": {
17
20
  "build": "bun run ../../build.ts"
18
21
  },
19
- "keywords": ["nexusts", "framework", "bun"],
22
+ "keywords": [
23
+ "nexusts",
24
+ "framework",
25
+ "bun"
26
+ ],
20
27
  "license": "MIT",
21
-
22
-
23
28
  "dependencies": {
24
- "@nexusts/core": "file:../core"
29
+ "@nexusts/core": "^0.7.4"
25
30
  }
26
31
  }