exisjs 0.7.12 → 0.7.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/README.md +195 -39
  2. package/dist/cli/commands/run.d.ts.map +1 -1
  3. package/dist/cli/commands/run.js +3 -1
  4. package/dist/cli/commands/run.js.map +1 -1
  5. package/dist/config/types.d.ts +2 -2
  6. package/dist/config/types.d.ts.map +1 -1
  7. package/dist/decorators/params.d.ts +21 -0
  8. package/dist/decorators/params.d.ts.map +1 -1
  9. package/dist/decorators/params.js +21 -1
  10. package/dist/decorators/params.js.map +1 -1
  11. package/dist/di/container.d.ts +15 -6
  12. package/dist/di/container.d.ts.map +1 -1
  13. package/dist/di/container.js +26 -3
  14. package/dist/di/container.js.map +1 -1
  15. package/dist/di/index.d.ts +1 -1
  16. package/dist/di/index.d.ts.map +1 -1
  17. package/dist/di/index.js.map +1 -1
  18. package/dist/di/inject.d.ts +2 -1
  19. package/dist/di/inject.d.ts.map +1 -1
  20. package/dist/di/inject.js +2 -1
  21. package/dist/di/inject.js.map +1 -1
  22. package/dist/docs/ARCHITECTURE.md +130 -78
  23. package/dist/docs/BENCHMARKS.md +4 -4
  24. package/dist/docs/content/README.md +43 -44
  25. package/dist/docs/content/boundaries.mdx +138 -61
  26. package/dist/docs/content/cli/commands.mdx +151 -128
  27. package/dist/docs/content/cli/overview.mdx +61 -47
  28. package/dist/docs/content/cli/usage.mdx +107 -30
  29. package/dist/docs/content/config.mdx +145 -158
  30. package/dist/docs/content/controllers.mdx +193 -464
  31. package/dist/docs/content/cron.mdx +183 -69
  32. package/dist/docs/content/decorators.mdx +449 -154
  33. package/dist/docs/content/errors.mdx +202 -305
  34. package/dist/docs/content/exisjs-mcp.mdx +59 -49
  35. package/dist/docs/content/installation.mdx +243 -157
  36. package/dist/docs/content/introduction.mdx +220 -48
  37. package/dist/docs/content/middleware.mdx +171 -497
  38. package/dist/docs/content/modules.mdx +141 -83
  39. package/dist/docs/content/providers.mdx +216 -180
  40. package/dist/docs/content/requests.mdx +168 -488
  41. package/dist/docs/content/responses.mdx +200 -533
  42. package/dist/docs/content/routing.mdx +235 -598
  43. package/dist/docs/content/security.mdx +233 -57
  44. package/dist/docs/content/structure.mdx +151 -240
  45. package/dist/docs/content/swagger.mdx +192 -91
  46. package/dist/docs/content/testing.mdx +205 -74
  47. package/dist/docs/content/validation.mdx +479 -341
  48. package/dist/docs/reference/README.md +34 -2
  49. package/dist/docs/reference/config.mdx +277 -75
  50. package/dist/docs/reference/context.mdx +197 -106
  51. package/dist/docs/reference/cron.mdx +266 -152
  52. package/dist/docs/reference/database.mdx +135 -53
  53. package/dist/docs/reference/decorators.mdx +234 -116
  54. package/dist/docs/reference/di.mdx +146 -112
  55. package/dist/docs/reference/error.mdx +155 -178
  56. package/dist/docs/reference/exis.mdx +141 -70
  57. package/dist/docs/reference/logger.mdx +110 -126
  58. package/dist/docs/reference/middleware.mdx +235 -158
  59. package/dist/docs/reference/plugin.mdx +136 -64
  60. package/dist/docs/reference/router.mdx +275 -293
  61. package/dist/docs/reference/sanitize.mdx +91 -87
  62. package/dist/docs/reference/swagger.mdx +280 -100
  63. package/dist/docs/reference/testing.mdx +223 -89
  64. package/dist/docs/reference/validator.mdx +194 -206
  65. package/dist/lib/start-server.js +22 -8
  66. package/dist/lib/start-server.js.map +1 -1
  67. package/dist/module/module.d.ts +6 -3
  68. package/dist/module/module.d.ts.map +1 -1
  69. package/dist/module/module.js +17 -3
  70. package/dist/module/module.js.map +1 -1
  71. package/dist/router/controller-registrar.d.ts.map +1 -1
  72. package/dist/router/controller-registrar.js +26 -4
  73. package/dist/router/controller-registrar.js.map +1 -1
  74. package/dist/router/scanner/fs-scanner.d.ts.map +1 -1
  75. package/dist/router/scanner/fs-scanner.js +22 -0
  76. package/dist/router/scanner/fs-scanner.js.map +1 -1
  77. package/dist/router/types.d.ts +6 -4
  78. package/dist/router/types.d.ts.map +1 -1
  79. package/dist/server/app.d.ts +3 -1
  80. package/dist/server/app.d.ts.map +1 -1
  81. package/dist/server/app.js +24 -8
  82. package/dist/server/app.js.map +1 -1
  83. package/dist/server/bootstrapper.d.ts.map +1 -1
  84. package/dist/server/bootstrapper.js +19 -0
  85. package/dist/server/bootstrapper.js.map +1 -1
  86. package/dist/server/request.d.ts +2 -0
  87. package/dist/server/request.d.ts.map +1 -1
  88. package/dist/server/request.js +11 -0
  89. package/dist/server/request.js.map +1 -1
  90. package/dist/server/response.d.ts +10 -5
  91. package/dist/server/response.d.ts.map +1 -1
  92. package/dist/server/response.js +65 -18
  93. package/dist/server/response.js.map +1 -1
  94. package/dist/swagger/generator.d.ts.map +1 -1
  95. package/dist/swagger/generator.js +130 -10
  96. package/dist/swagger/generator.js.map +1 -1
  97. package/dist/telemetry/index.d.ts +12 -0
  98. package/dist/telemetry/index.d.ts.map +1 -0
  99. package/dist/telemetry/index.js +121 -0
  100. package/dist/telemetry/index.js.map +1 -0
  101. package/dist/testing/client.d.ts +1 -0
  102. package/dist/testing/client.d.ts.map +1 -1
  103. package/dist/testing/client.js +4 -1
  104. package/dist/testing/client.js.map +1 -1
  105. package/dist/testing/index.d.ts.map +1 -1
  106. package/dist/testing/index.js +11 -4
  107. package/dist/testing/index.js.map +1 -1
  108. package/dist/validator/builder.d.ts +26 -1
  109. package/dist/validator/builder.d.ts.map +1 -1
  110. package/dist/validator/builder.js +31 -0
  111. package/dist/validator/builder.js.map +1 -1
  112. package/dist/validator/engine.d.ts +23 -0
  113. package/dist/validator/engine.d.ts.map +1 -1
  114. package/dist/validator/engine.js +228 -31
  115. package/dist/validator/engine.js.map +1 -1
  116. package/dist/validator/index.d.ts +8 -4
  117. package/dist/validator/index.d.ts.map +1 -1
  118. package/dist/validator/index.js +4 -1
  119. package/dist/validator/index.js.map +1 -1
  120. package/dist/validator/tex-types.d.ts +19 -4
  121. package/dist/validator/tex-types.d.ts.map +1 -1
  122. package/dist/validator/tex-types.js +102 -0
  123. package/dist/validator/tex-types.js.map +1 -1
  124. package/dist/validator/tex.d.ts +1 -1
  125. package/dist/validator/tex.d.ts.map +1 -1
  126. package/dist/validator/tex.js +3 -1
  127. package/dist/validator/tex.js.map +1 -1
  128. package/dist/validator/types.d.ts +1 -0
  129. package/dist/validator/types.d.ts.map +1 -1
  130. package/package.json +46 -14
  131. package/dist/docs/content/dataloader.mdx +0 -170
  132. package/dist/docs/reference/dataloader.mdx +0 -91
@@ -1,11 +1,51 @@
1
1
  ---
2
- title: "Cron & Scheduling"
3
- description: "API Reference for ExisJS Task Scheduling, Cron Expressions, and Job Management."
2
+ title: "exisjs/cron"
3
+ description: "API Reference for ExisJS task scheduling, cron expressions, interval timers, CronManager, and @Cron decorators."
4
+ nextUrl: "/docs/reference/sanitize"
5
+ nextTitle: "Sanitize Reference"
4
6
  ---
5
7
 
6
- # Cron & Scheduling (`exisjs/cron`, `exisjs/decorators`)
8
+ # `exisjs/cron`
7
9
 
8
- The `exisjs/cron` module provides task scheduling, cron expression parsing, interval timers, and runtime job management.
10
+ The `exisjs/cron` module provides background task scheduling, 5/6-field cron expression parsing, drift-corrected interval timers, retry backoff, and runtime job management.
11
+
12
+ ---
13
+
14
+ ## Module Exports
15
+
16
+ ```typescript
17
+ import {
18
+ cron,
19
+ defineCron,
20
+ CronManager,
21
+ CronJob,
22
+ CronExpression,
23
+ every,
24
+ } from 'exisjs/cron'
25
+
26
+ import type {
27
+ CronSchedule,
28
+ CronJobOptions,
29
+ CronContext,
30
+ CronJobStats,
31
+ CronJobStatus,
32
+ OverlapPolicy,
33
+ IntervalOptions,
34
+ TimeoutOptions,
35
+ } from 'exisjs/cron'
36
+ ```
37
+
38
+ Decorators for class-based jobs are imported from `exisjs/decorators`:
39
+
40
+ ```typescript
41
+ import {
42
+ Cron,
43
+ Interval,
44
+ TimeoutTask,
45
+ Scheduled,
46
+ ScheduledTimeout,
47
+ } from 'exisjs/decorators'
48
+ ```
9
49
 
10
50
  ---
11
51
 
@@ -13,65 +53,115 @@ The `exisjs/cron` module provides task scheduling, cron expression parsing, inte
13
53
 
14
54
  ### `cron(scheduleOrOptions, handler?)`
15
55
 
16
- Defines a functional cron job.
56
+ Defines a functional cron job for auto-discovery or dynamic registration.
17
57
 
18
58
  ```typescript
19
- import { cron, CronExpression } from 'exisjs/cron'
59
+ function cron(
60
+ scheduleOrOptions: string | CronJobOptions,
61
+ handler?: (ctx: CronContext) => any
62
+ ): FunctionalCronDefinition
63
+ ```
20
64
 
21
- // Signature 1: Options object with inline run handler
22
- export default cron({
23
- name: 'sync-users',
24
- schedule: CronExpression.EVERY_10_MINUTES,
25
- timezone: 'UTC',
26
- preventOverlap: true,
27
- retries: 2,
28
- retryDelayMs: 1000,
29
- async run({ app, log }) {
30
- // ...
31
- }
32
- })
65
+ #### Overloads
66
+
67
+ 1. **Option Object**:
68
+ ```typescript filename="src/cron/sync.ts"
69
+ import { cron, CronExpression } from 'exisjs/cron'
70
+
71
+ export default cron({
72
+ name: 'sync-users',
73
+ schedule: CronExpression.EVERY_10_MINUTES,
74
+ timezone: 'UTC',
75
+ preventOverlap: true,
76
+ retries: 2,
77
+ retryDelayMs: 1000,
78
+ async run({ app, log, iteration }) {
79
+ log.info({ iteration }, 'Running user synchronization')
80
+ },
81
+ })
82
+ ```
83
+
84
+ 2. **Schedule Pattern & Handler**:
85
+ ```typescript filename="src/cron/cleanup.ts"
86
+ import { cron } from 'exisjs/cron'
87
+
88
+ export default cron('0 0 * * *', async ({ log }) => {
89
+ log.info('Running nightly purge')
90
+ })
91
+ ```
33
92
 
34
- // Signature 2: Schedule string with handler
35
- export const purgeJob = cron('0 0 * * *', async ({ log }) => {
36
- // ...
37
- })
38
- ```
93
+ ---
39
94
 
40
95
  ### `cron.every(duration, handler, options?)`
41
96
 
42
- Shorthand helper accepting human-readable duration strings (e.g., `'10 seconds'`, `'5 minutes'`, `'2 hours'`).
97
+ Shorthand helper accepting natural language English duration strings (e.g., `'10 seconds'`, `'5 minutes'`, `'2 hours'`, `'1 day'`).
43
98
 
44
99
  ```typescript
100
+ cron.every(
101
+ duration: string,
102
+ handler: (ctx: CronContext) => any,
103
+ options?: Omit<CronJobOptions, 'schedule' | 'run' | 'handle'>
104
+ ): FunctionalCronDefinition
105
+ ```
106
+
107
+ #### Example
108
+
109
+ ```typescript filename="src/cron/heartbeat.ts"
45
110
  import { cron } from 'exisjs/cron'
46
111
 
47
- export const healthCheck = cron.every('30 seconds', async ({ log }) => {
48
- log.info('Checking external dependencies...')
112
+ export default cron.every('15 minutes', async ({ log }) => {
113
+ log.info('Heartbeat tick')
49
114
  }, {
50
- name: 'ext-health-check'
115
+ name: 'health-heartbeat',
116
+ timezone: 'UTC',
51
117
  })
52
118
  ```
53
119
 
120
+ ---
121
+
54
122
  ### `cron.interval(ms, handler, options?)`
55
123
 
56
- Shorthand helper for millisecond recurring intervals.
124
+ Shorthand helper for millisecond recurring intervals with timer unref and drift management.
57
125
 
58
126
  ```typescript
127
+ cron.interval(
128
+ ms: number,
129
+ handler: (ctx: CronContext) => any,
130
+ options?: Omit<CronJobOptions, 'interval' | 'run' | 'handle'>
131
+ ): FunctionalCronDefinition
132
+ ```
133
+
134
+ #### Example
135
+
136
+ ```typescript filename="src/cron/queue-poll.ts"
59
137
  import { cron } from 'exisjs/cron'
60
138
 
61
- export const heartbeat = cron.interval(60_000, async ({ log }) => {
62
- log.info('Server heartbeat tick')
139
+ export default cron.interval(30_000, async ({ log }) => {
140
+ log.info('Polling background job queue')
63
141
  })
64
142
  ```
65
143
 
144
+ ---
145
+
66
146
  ### `cron.timeout(ms, handler, options?)`
67
147
 
68
- Shorthand helper for one-time delayed startup tasks (executes once after application boot).
148
+ Shorthand helper for one-time delayed startup tasks executed once after the server initializes.
69
149
 
70
150
  ```typescript
151
+ cron.timeout(
152
+ ms: number,
153
+ handler: (ctx: CronContext) => any,
154
+ options?: Omit<CronJobOptions, 'timeout' | 'run' | 'handle'>
155
+ ): FunctionalCronDefinition
156
+ ```
157
+
158
+ #### Example
159
+
160
+ ```typescript filename="src/cron/warmup.ts"
71
161
  import { cron } from 'exisjs/cron'
72
162
 
73
- export const cacheWarmup = cron.timeout(5_000, async ({ app, log }) => {
74
- log.info('Warming up Redis cache after boot')
163
+ export default cron.timeout(5_000, async ({ app, log }) => {
164
+ log.info('Warming up memory cache after application startup')
75
165
  })
76
166
  ```
77
167
 
@@ -81,102 +171,153 @@ export const cacheWarmup = cron.timeout(5_000, async ({ app, log }) => {
81
171
 
82
172
  ### `@Cron(schedule, options?)`
83
173
 
84
- Method decorator that marks a class method as a scheduled cron job. Can be used on any `@Injectable()` service.
174
+ Method decorator that marks a class method on an `@Injectable()` service as a scheduled cron job.
175
+
176
+ ```typescript
177
+ function Cron(
178
+ schedule: string,
179
+ options?: Omit<CronJobOptions, 'schedule' | 'run' | 'handle'>
180
+ ): MethodDecorator
181
+ ```
85
182
 
86
183
  | Parameter | Type | Description |
87
184
  | :--- | :--- | :--- |
88
185
  | `schedule` | `string` | Standard 5 or 6 field cron expression or `CronExpression` constant. |
89
- | `options` | `CronJobOptions` | Optional job configuration (name, timezone, preventOverlap, retries, etc.). |
186
+ | `options` | `CronJobOptions` | Optional job configuration (`name`, `timezone`, `preventOverlap`, `retries`, `retryDelayMs`). |
90
187
 
91
- ```typescript
92
- import { Injectable, Cron, CronExpression } from 'exisjs/decorators'
188
+ ```typescript filename="src/services/report.service.ts"
189
+ import { Injectable } from 'exisjs/di'
190
+ import { Cron, CronExpression } from 'exisjs/decorators'
93
191
 
94
192
  @Injectable()
95
- export default class ReportService {
193
+ export class ReportService {
96
194
  @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT, {
97
195
  name: 'nightly-report',
98
196
  timezone: 'UTC',
99
197
  preventOverlap: true,
100
198
  })
101
199
  async generateDailyReport() {
102
- // ...
200
+ // Executes every day at 00:00 UTC
103
201
  }
104
202
  }
105
203
  ```
106
204
 
205
+ ---
206
+
107
207
  ### `@Interval(ms, options?)`
108
208
 
109
- Method decorator for recurring millisecond tasks.
209
+ Method decorator that schedules a method to run at recurring millisecond intervals.
110
210
 
111
211
  ```typescript
112
- import { Injectable, Interval } from 'exisjs/decorators'
212
+ function Interval(
213
+ ms: number,
214
+ options?: Omit<CronJobOptions, 'interval' | 'run' | 'handle'>
215
+ ): MethodDecorator
216
+ ```
217
+
218
+ ```typescript filename="src/services/monitor.service.ts"
219
+ import { Injectable } from 'exisjs/di'
220
+ import { Interval } from 'exisjs/decorators'
113
221
 
114
222
  @Injectable()
115
- export default class QueueMonitor {
116
- @Interval(15_000, { name: 'queue-poll' })
117
- async pollQueue() {
118
- // ...
223
+ export class MonitorService {
224
+ @Interval(60_000, { name: 'health-monitor' })
225
+ async pingExternalServices() {
226
+ // Runs every 60 seconds
119
227
  }
120
228
  }
121
229
  ```
122
230
 
123
- ### `@TimeoutTask(ms, options?)` (alias `@ScheduledTimeout`)
231
+ ---
124
232
 
125
- Method decorator for one-time startup tasks executed after the specified millisecond delay.
233
+ ### `@TimeoutTask(ms, options?)`
234
+
235
+ Method decorator for one-time startup tasks executed after the specified millisecond delay. Also aliased as `@ScheduledTimeout`.
126
236
 
127
237
  ```typescript
128
- import { Injectable, TimeoutTask } from 'exisjs/decorators'
238
+ function TimeoutTask(
239
+ ms: number,
240
+ options?: Omit<CronJobOptions, 'timeout' | 'run' | 'handle'>
241
+ ): MethodDecorator
242
+ ```
243
+
244
+ ```typescript filename="src/services/bootstrap.service.ts"
245
+ import { Injectable } from 'exisjs/di'
246
+ import { TimeoutTask } from 'exisjs/decorators'
129
247
 
130
248
  @Injectable()
131
- export default class CacheBootstrap {
249
+ export class BootstrapService {
132
250
  @TimeoutTask(3_000, { name: 'seed-cache' })
133
251
  async seedCache() {
134
- // ...
252
+ // Runs once 3s after server boot
135
253
  }
136
254
  }
137
255
  ```
138
256
 
139
257
  ---
140
258
 
141
- ## 3. Configuration & Options
259
+ ## 3. Configuration Interfaces
142
260
 
143
261
  ### `CronJobOptions`
144
262
 
145
- Configuration object passed to `cron()` or decorator options:
263
+ Configuration object accepted by `cron()`, `app.cron.schedule()`, and cron decorators:
146
264
 
147
- | Property | Type | Default | Description |
265
+ | Option | Type | Default | Description |
148
266
  | :--- | :--- | :--- | :--- |
149
- | `name` | `string` | `auto-generated` | Unique identifier for the job. Used in logs and runtime APIs. |
267
+ | `name` | `string` | `job_<random>` | Unique identifier for the job. Used in logging, statistics, and runtime triggers. |
150
268
  | `schedule` | `string` | `undefined` | 5 or 6 field cron expression (e.g. `'0 0 * * *'`). |
151
- | `interval` | `number` | `undefined` | Millisecond interval for recurring execution. |
152
- | `timeout` | `number` | `undefined` | Millisecond delay for one-time execution. |
153
- | `timezone` | `string` | `'UTC'` | Valid IANA timezone string (e.g. `'America/New_York'`, `'Asia/Kolkata'`). |
154
- | `preventOverlap` | `boolean` | `true` | Skips execution if the previous tick is still running. |
155
- | `overlapPolicy` | `'skip' \| 'queue'` | `'skip'` | Action taken when execution overlap occurs. |
156
- | `retries` | `number` | `0` | Number of retry attempts upon failure. |
157
- | `retryDelayMs` | `number` | `1000` | Milliseconds to wait before executing a retry. |
158
- | `autoStart` | `boolean` | `true` | Whether the job automatically starts on application bootstrap. |
159
- | `run` / `handle` | `(ctx: CronContext) => Promise<any> \| any` | `undefined` | The execution callback function. |
160
- | `onError` | `(err: Error, ctx: CronContext) => void` | `undefined` | Hook called when the job fails after all retries. |
269
+ | `interval` | `number` | `undefined` | Interval in milliseconds for recurring execution. |
270
+ | `timeout` | `number` | `undefined` | Delay in milliseconds for one-time execution. |
271
+ | `timezone` | `string` | `'UTC'` | IANA timezone string (e.g. `'America/New_York'`, `'Asia/Kolkata'`). |
272
+ | `preventOverlap` | `boolean` | `true` | When `true`, skips execution if the previous execution is still running. |
273
+ | `onOverlap` | `'skip' \| 'queue'` | `'skip'` | Overlap policy when a job is triggered while already running. |
274
+ | `autoStart` | `boolean` | `true` | Whether the job begins scheduling automatically upon registration. |
275
+ | `retries` | `number` | `0` | Number of retry attempts if the handler throws an unhandled error. |
276
+ | `retryDelayMs` | `number` | `1000` | Delay between retry attempts in milliseconds. |
277
+ | `run` / `handle` | `(ctx: CronContext) => any` | `undefined` | Main execution callback function. |
278
+ | `onError` | `(err: Error, ctx: CronContext) => void` | `undefined` | Error hook executed if the handler fails all retry attempts. |
279
+
280
+ ---
161
281
 
162
282
  ### `CronContext`
163
283
 
164
- The context object provided as the first argument to job execution handlers:
284
+ Context object passed to cron execution handlers:
165
285
 
166
286
  | Property | Type | Description |
167
287
  | :--- | :--- | :--- |
168
- | `name` | `string` | The unique name of the active job. |
169
- | `scheduledTime` | `Date` | The theoretical timestamp the job was scheduled to run. |
170
- | `executionTime` | `Date` | The actual timestamp execution began. |
171
- | `iteration` | `number` | Total number of executions completed by this job instance. |
172
- | `app` | `App` | Reference to the current ExisJS application instance. |
173
- | `log` | `Logger` | Scoped logger instance with `job: name` context. |
288
+ | `app` | `App` | The active ExisJS application instance. |
289
+ | `log` | `Logger` | Structured application logger instance. |
290
+ | `jobName` | `string` | The unique name of the currently executing job. |
291
+ | `startedAt` | `Date` | Timestamp when the current execution began. |
292
+ | `iteration` | `number` | Monotonically increasing execution counter for this job instance. |
293
+ | `signal` | `AbortSignal` | AbortSignal triggered during application graceful shutdown. |
294
+
295
+ ---
296
+
297
+ ### `CronJobStats`
298
+
299
+ Statistics descriptor returned by `job.getStats()` and `app.cron.getStats()`:
300
+
301
+ | Field | Type | Description |
302
+ | :--- | :--- | :--- |
303
+ | `name` | `string` | Unique job identifier. |
304
+ | `status` | `'idle' \| 'running' \| 'paused' \| 'stopped'` | Current job execution status. |
305
+ | `schedule` | `string \| undefined` | Configured cron schedule expression. |
306
+ | `intervalMs` | `number \| undefined` | Configured interval in milliseconds. |
307
+ | `timezone` | `string \| undefined` | Configured IANA timezone. |
308
+ | `preventOverlap` | `boolean` | Overlap prevention status. |
309
+ | `lastRun` | `Date \| undefined` | Timestamp of the most recent execution. |
310
+ | `nextRun` | `Date \| undefined` | Calculated timestamp for the upcoming scheduled run. |
311
+ | `executionCount` | `number` | Total number of executions attempted. |
312
+ | `failureCount` | `number` | Total number of failed executions. |
313
+ | `lastDurationMs` | `number \| undefined` | Duration in milliseconds of the last execution. |
314
+ | `lastError` | `string \| undefined` | Last error message if execution failed. |
174
315
 
175
316
  ---
176
317
 
177
- ## 4. `CronExpression` Presets
318
+ ## 4. `CronExpression` Constants
178
319
 
179
- ExisJS exports pre-validated standard cron expression constants:
320
+ ExisJS exports pre-compiled cron patterns:
180
321
 
181
322
  | Constant | Value | Description |
182
323
  | :--- | :--- | :--- |
@@ -185,116 +326,89 @@ ExisJS exports pre-validated standard cron expression constants:
185
326
  | `CronExpression.EVERY_10_SECONDS` | `*/10 * * * * *` | Every 10 seconds (6-field) |
186
327
  | `CronExpression.EVERY_30_SECONDS` | `*/30 * * * * *` | Every 30 seconds (6-field) |
187
328
  | `CronExpression.EVERY_MINUTE` | `* * * * *` | Every minute |
329
+ | `CronExpression.EVERY_2_MINUTES` | `*/2 * * * *` | Every 2 minutes |
330
+ | `CronExpression.EVERY_3_MINUTES` | `*/3 * * * *` | Every 3 minutes |
188
331
  | `CronExpression.EVERY_5_MINUTES` | `*/5 * * * *` | Every 5 minutes |
189
332
  | `CronExpression.EVERY_10_MINUTES` | `*/10 * * * *` | Every 10 minutes |
190
333
  | `CronExpression.EVERY_15_MINUTES` | `*/15 * * * *` | Every 15 minutes |
191
334
  | `CronExpression.EVERY_30_MINUTES` | `*/30 * * * *` | Every 30 minutes |
192
- | `CronExpression.EVERY_HOUR` | `0 * * * *` | Top of every hour |
335
+ | `CronExpression.EVERY_HOUR` | `0 * * * *` | At minute 0 of every hour |
193
336
  | `CronExpression.EVERY_2_HOURS` | `0 */2 * * *` | Every 2 hours |
337
+ | `CronExpression.EVERY_3_HOURS` | `0 */3 * * *` | Every 3 hours |
194
338
  | `CronExpression.EVERY_6_HOURS` | `0 */6 * * *` | Every 6 hours |
195
339
  | `CronExpression.EVERY_12_HOURS` | `0 */12 * * *` | Every 12 hours |
196
340
  | `CronExpression.EVERY_DAY_AT_MIDNIGHT` | `0 0 * * *` | Daily at 00:00 (Midnight) |
197
341
  | `CronExpression.EVERY_DAY_AT_1AM` | `0 1 * * *` | Daily at 01:00 AM |
198
342
  | `CronExpression.EVERY_DAY_AT_2AM` | `0 2 * * *` | Daily at 02:00 AM |
199
343
  | `CronExpression.EVERY_DAY_AT_NOON` | `0 12 * * *` | Daily at 12:00 PM |
200
- | `CronExpression.EVERY_WEEK` | `0 0 * * 0` | Every Sunday at midnight |
201
- | `CronExpression.EVERY_MONTH` | `0 0 1 * *` | First day of every month at midnight |
202
- | `CronExpression.EVERY_YEAR` | `0 0 1 1 *` | January 1st at midnight |
344
+ | `CronExpression.EVERY_WEEK` | `0 0 * * 0` | Every Sunday at 00:00 |
345
+ | `CronExpression.EVERY_WEEKDAY` | `0 0 * * 1-5` | Monday through Friday at 00:00 |
346
+ | `CronExpression.EVERY_WEEKEND` | `0 0 * * 6,0` | Saturday and Sunday at 00:00 |
347
+ | `CronExpression.EVERY_MONTH` | `0 0 1 * *` | First day of every month at 00:00 |
348
+ | `CronExpression.EVERY_QUARTER` | `0 0 1 1,4,7,10 *` | First day of every quarter at 00:00 |
349
+ | `CronExpression.EVERY_YEAR` | `0 0 1 1 *` | January 1st at 00:00 |
203
350
 
204
351
  ---
205
352
 
206
- ## 5. Runtime Management API (`app.cron`)
207
-
208
- Access the cron manager via `app.cron`:
209
-
210
- ### `app.cron.schedule(options)`
211
- Registers and schedules a new cron job dynamically.
212
-
213
- ```typescript
214
- const job = app.cron.schedule({
215
- name: 'dynamic-sync',
216
- schedule: '0 */3 * * *',
217
- run: async ({ log }) => {
218
- log.info('Dynamic sync executed')
219
- }
220
- })
221
- ```
353
+ ## 5. `every(duration)` Helper
222
354
 
223
- ### `app.cron.get(name)`
224
- Returns the `CronJob` instance by name, or `undefined` if not found.
355
+ Converts human-readable duration strings into standard 5 or 6 field cron patterns.
225
356
 
226
357
  ```typescript
227
- const job = app.cron.get('nightly-sync')
358
+ function every(duration: string): string
228
359
  ```
229
360
 
230
- ### `app.cron.has(name)`
231
- Returns `true` if a job with the specified name exists.
361
+ | Input Example | Generated Cron Pattern |
362
+ | :--- | :--- |
363
+ | `every('10 seconds')` | `*/10 * * * * *` |
364
+ | `every('5 minutes')` | `*/5 * * * *` |
365
+ | `every('2 hours')` | `0 */2 * * *` |
366
+ | `every('1 day')` | `0 0 * * *` |
367
+ | `every('1 week')` | `0 0 * * 0` |
368
+ | `every('1 month')` | `0 0 1 * *` |
232
369
 
233
- ```typescript
234
- if (app.cron.has('nightly-sync')) {
235
- // ...
236
- }
237
- ```
238
-
239
- ### `app.cron.list()`
240
- Returns an array of all registered `CronJob` instances.
241
-
242
- ```typescript
243
- const allJobs = app.cron.list()
244
- ```
245
-
246
- ### `app.cron.status()`
247
- Returns an array of status and metric descriptors for all registered jobs.
248
-
249
- ```typescript
250
- const stats = app.cron.status()
251
- // [
252
- // {
253
- // name: 'nightly-sync',
254
- // status: 'running',
255
- // running: false,
256
- // totalExecutions: 14,
257
- // successCount: 14,
258
- // failureCount: 0,
259
- // lastExecution: '2026-09-22T00:00:00.000Z',
260
- // nextExecution: '2026-09-23T00:00:00.000Z',
261
- // lastDurationMs: 142
262
- // }
263
- // ]
264
- ```
265
-
266
- ### `app.cron.trigger(name)`
267
- Manually triggers an immediate execution of the specified job, returning the handler result.
370
+ ---
268
371
 
269
- ```typescript
270
- const result = await app.cron.trigger('nightly-sync')
271
- ```
372
+ ## 6. Runtime Management (`CronManager`)
272
373
 
273
- ### `app.cron.pause(name)` / `app.cron.resume(name)`
274
- Pauses or resumes a job's automatic scheduling without unregistering it.
374
+ Access the application cron manager instance via `app.cron`:
275
375
 
276
376
  ```typescript
277
- app.cron.pause('nightly-sync')
278
- app.cron.resume('nightly-sync')
377
+ export class CronManager {
378
+ has(name: string): boolean
379
+ schedule(nameOrOptions: string | CronJobOptions, schedule?: string, handler?: (ctx: CronContext) => any, options?: Partial<CronJobOptions>): CronJob
380
+ interval(name: string, ms: number, handler: (ctx: CronContext) => any, options?: Partial<CronJobOptions>): CronJob
381
+ timeout(name: string, ms: number, handler: (ctx: CronContext) => any, options?: Partial<CronJobOptions>): CronJob
382
+ getJob(name: string): CronJob | undefined
383
+ getJobs(): Map<string, CronJob>
384
+ getStats(): CronJobStats[]
385
+ startAll(): void
386
+ pauseAll(): void
387
+ stopAll(): void
388
+ trigger(name: string): Promise<any>
389
+ drain(timeoutMs?: number): Promise<void>
390
+ }
279
391
  ```
280
392
 
281
- ### `app.cron.remove(name)`
282
- Stops and unregisters a job by name.
393
+ ### Examples
283
394
 
284
395
  ```typescript
285
- app.cron.remove('nightly-sync')
286
- ```
396
+ // Check if a job exists
397
+ if (app.cron.has('sync-users')) {
398
+ // Retrieve execution metrics
399
+ const job = app.cron.getJob('sync-users')
400
+ console.log(job?.getStats())
401
+ }
287
402
 
288
- ### `app.cron.stopAll()`
289
- Stops all scheduled timers across all registered jobs.
403
+ // Manually trigger immediate execution
404
+ await app.cron.trigger('sync-users')
290
405
 
291
- ```typescript
292
- app.cron.stopAll()
293
- ```
406
+ // Pause all jobs during maintenance
407
+ app.cron.pauseAll()
294
408
 
295
- ### `app.cron.drain(timeoutMs?)`
296
- Stops new ticks and awaits any currently running job executions to complete. Called automatically during graceful server shutdown.
409
+ // Resume scheduling
410
+ app.cron.startAll()
297
411
 
298
- ```typescript
412
+ // Gracefully drain in-flight jobs during shutdown
299
413
  await app.cron.drain(5000)
300
414
  ```