@zintrust/core 0.1.14 → 0.1.16

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 (123) hide show
  1. package/package.json +1 -1
  2. package/src/boot/Application.d.ts.map +1 -1
  3. package/src/boot/Application.js +29 -61
  4. package/src/cli/CLI.d.ts.map +1 -1
  5. package/src/cli/CLI.js +6 -0
  6. package/src/cli/commands/BroadcastWorkCommand.d.ts +10 -0
  7. package/src/cli/commands/BroadcastWorkCommand.d.ts.map +1 -0
  8. package/src/cli/commands/BroadcastWorkCommand.js +16 -0
  9. package/src/cli/commands/NotificationWorkCommand.d.ts +10 -0
  10. package/src/cli/commands/NotificationWorkCommand.d.ts.map +1 -0
  11. package/src/cli/commands/NotificationWorkCommand.js +16 -0
  12. package/src/cli/commands/QueueCommand.d.ts +10 -0
  13. package/src/cli/commands/QueueCommand.d.ts.map +1 -0
  14. package/src/cli/commands/QueueCommand.js +63 -0
  15. package/src/cli/commands/QueueWorkCommandUtils.d.ts +10 -0
  16. package/src/cli/commands/QueueWorkCommandUtils.d.ts.map +1 -0
  17. package/src/cli/commands/QueueWorkCommandUtils.js +43 -0
  18. package/src/cli/commands/createKindWorkCommand.d.ts +9 -0
  19. package/src/cli/commands/createKindWorkCommand.d.ts.map +1 -0
  20. package/src/cli/commands/createKindWorkCommand.js +33 -0
  21. package/src/cli/commands/index.d.ts +3 -0
  22. package/src/cli/commands/index.d.ts.map +1 -1
  23. package/src/cli/commands/index.js +3 -0
  24. package/src/cli/scaffolding/ModelGenerator.d.ts.map +1 -1
  25. package/src/cli/scaffolding/ModelGenerator.js +1 -0
  26. package/src/cli/workers/QueueWorkRunner.d.ts +23 -0
  27. package/src/cli/workers/QueueWorkRunner.d.ts.map +1 -0
  28. package/src/cli/workers/QueueWorkRunner.js +142 -0
  29. package/src/collections/Collection.d.ts +30 -0
  30. package/src/collections/Collection.d.ts.map +1 -0
  31. package/src/collections/Collection.js +146 -0
  32. package/src/collections/index.d.ts +3 -0
  33. package/src/collections/index.d.ts.map +1 -0
  34. package/src/collections/index.js +1 -0
  35. package/src/config/broadcast.d.ts.map +1 -1
  36. package/src/config/broadcast.js +5 -3
  37. package/src/config/cache.d.ts.map +1 -1
  38. package/src/config/cache.js +12 -6
  39. package/src/config/database.d.ts.map +1 -1
  40. package/src/config/database.js +5 -3
  41. package/src/config/mail.d.ts.map +1 -1
  42. package/src/config/mail.js +21 -14
  43. package/src/config/notification.d.ts.map +1 -1
  44. package/src/config/notification.js +10 -5
  45. package/src/config/storage.d.ts.map +1 -1
  46. package/src/config/storage.js +5 -6
  47. package/src/events/EventDispatcher.d.ts +16 -0
  48. package/src/events/EventDispatcher.d.ts.map +1 -0
  49. package/src/events/EventDispatcher.js +90 -0
  50. package/src/events/index.d.ts +3 -0
  51. package/src/events/index.d.ts.map +1 -0
  52. package/src/events/index.js +1 -0
  53. package/src/features/Queue.js +1 -1
  54. package/src/http/Response.d.ts +2 -2
  55. package/src/http/Response.d.ts.map +1 -1
  56. package/src/index.d.ts +11 -0
  57. package/src/index.d.ts.map +1 -1
  58. package/src/index.js +11 -0
  59. package/src/middleware/CsrfMiddleware.d.ts.map +1 -1
  60. package/src/middleware/CsrfMiddleware.js +20 -25
  61. package/src/middleware/SessionMiddleware.d.ts +8 -0
  62. package/src/middleware/SessionMiddleware.d.ts.map +1 -0
  63. package/src/middleware/SessionMiddleware.js +15 -0
  64. package/src/orm/DatabaseRuntimeRegistration.d.ts.map +1 -1
  65. package/src/orm/DatabaseRuntimeRegistration.js +4 -2
  66. package/src/orm/Model.d.ts +15 -0
  67. package/src/orm/Model.d.ts.map +1 -1
  68. package/src/orm/Model.js +57 -8
  69. package/src/orm/QueryBuilder.d.ts +9 -1
  70. package/src/orm/QueryBuilder.d.ts.map +1 -1
  71. package/src/orm/QueryBuilder.js +54 -2
  72. package/src/scripts/TemplateSync.js +23 -1
  73. package/src/security/PasswordResetTokenBroker.d.ts +39 -0
  74. package/src/security/PasswordResetTokenBroker.d.ts.map +1 -0
  75. package/src/security/PasswordResetTokenBroker.js +131 -0
  76. package/src/session/SessionManager.d.ts +39 -0
  77. package/src/session/SessionManager.d.ts.map +1 -0
  78. package/src/session/SessionManager.js +149 -0
  79. package/src/session/index.d.ts +3 -0
  80. package/src/session/index.d.ts.map +1 -0
  81. package/src/session/index.js +1 -0
  82. package/src/templates/features/Queue.ts.tpl +4 -3
  83. package/src/templates/project/basic/config/FileLogWriter.ts.tpl +4 -3
  84. package/src/templates/project/basic/config/SecretsManager.ts.tpl +1 -1
  85. package/src/templates/project/basic/config/broadcast.ts.tpl +6 -4
  86. package/src/templates/project/basic/config/cache.ts.tpl +17 -5
  87. package/src/templates/project/basic/config/database.ts.tpl +6 -4
  88. package/src/templates/project/basic/config/features.ts.tpl +2 -2
  89. package/src/templates/project/basic/config/logger.ts.tpl +0 -2
  90. package/src/templates/project/basic/config/logging/HttpLogger.ts.tpl +1 -1
  91. package/src/templates/project/basic/config/logging/SlackLogger.ts.tpl +1 -1
  92. package/src/templates/project/basic/config/mail.ts.tpl +26 -16
  93. package/src/templates/project/basic/config/microservices.ts.tpl +1 -1
  94. package/src/templates/project/basic/config/middleware.ts.tpl +6 -9
  95. package/src/templates/project/basic/config/notification.ts.tpl +19 -7
  96. package/src/templates/project/basic/config/security.ts.tpl +1 -2
  97. package/src/templates/project/basic/config/storage.ts.tpl +8 -6
  98. package/src/templates/project/basic/config/type.ts.tpl +2 -2
  99. package/src/tools/broadcast/Broadcast.d.ts +8 -0
  100. package/src/tools/broadcast/Broadcast.d.ts.map +1 -1
  101. package/src/tools/broadcast/Broadcast.js +23 -0
  102. package/src/tools/broadcast/BroadcastRuntimeRegistration.d.ts.map +1 -1
  103. package/src/tools/broadcast/BroadcastRuntimeRegistration.js +7 -4
  104. package/src/tools/notification/Notification.d.ts +10 -0
  105. package/src/tools/notification/Notification.d.ts.map +1 -1
  106. package/src/tools/notification/Notification.js +21 -0
  107. package/src/tools/notification/NotificationRuntimeRegistration.d.ts.map +1 -1
  108. package/src/tools/notification/NotificationRuntimeRegistration.js +7 -4
  109. package/src/tools/queue/Queue.d.ts.map +1 -1
  110. package/src/tools/queue/Queue.js +4 -1
  111. package/src/tools/queue/QueueRuntimeRegistration.d.ts.map +1 -1
  112. package/src/tools/queue/QueueRuntimeRegistration.js +5 -8
  113. package/src/tools/storage/StorageRuntimeRegistration.d.ts.map +1 -1
  114. package/src/tools/storage/StorageRuntimeRegistration.js +8 -10
  115. package/src/workers/BroadcastWorker.d.ts +22 -0
  116. package/src/workers/BroadcastWorker.d.ts.map +1 -0
  117. package/src/workers/BroadcastWorker.js +24 -0
  118. package/src/workers/NotificationWorker.d.ts +22 -0
  119. package/src/workers/NotificationWorker.d.ts.map +1 -0
  120. package/src/workers/NotificationWorker.js +23 -0
  121. package/src/workers/createQueueWorker.d.ts +24 -0
  122. package/src/workers/createQueueWorker.d.ts.map +1 -0
  123. package/src/workers/createQueueWorker.js +114 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zintrust/core",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "Production-grade TypeScript backend framework for JavaScript",
5
5
  "homepage": "https://zintrust.com",
6
6
  "repository": {
@@ -1 +1 @@
1
- {"version":3,"file":"Application.d.ts","sourceRoot":"","sources":["../../../src/boot/Application.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAoB,MAAM,8BAA8B,CAAC;AAEnF,OAAO,EAAE,gBAAgB,EAAmB,MAAM,8BAA8B,CAAC;AACjF,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,kBAAkB,CAAC;AASxD,MAAM,WAAW,YAAY;IAC3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,QAAQ,IAAI,OAAO,CAAC;IACpB,aAAa,IAAI,OAAO,CAAC;IACzB,YAAY,IAAI,OAAO,CAAC;IACxB,SAAS,IAAI,OAAO,CAAC;IACrB,cAAc,IAAI,MAAM,CAAC;IACzB,SAAS,IAAI,OAAO,CAAC;IACrB,YAAY,IAAI,iBAAiB,CAAC;IAClC,kBAAkB,IAAI,gBAAgB,CAAC;IACvC,WAAW,IAAI,MAAM,CAAC;CACvB;AAkVD;;GAEG;AACH,eAAO,MAAM,WAAW;IACtB;;OAEG;sBACe,MAAM,GAAG,YAAY;EA0CvC,CAAC;AAEH,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"Application.d.ts","sourceRoot":"","sources":["../../../src/boot/Application.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAoB,MAAM,8BAA8B,CAAC;AAEnF,OAAO,EAAE,gBAAgB,EAAmB,MAAM,8BAA8B,CAAC;AACjF,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,kBAAkB,CAAC;AASxD,MAAM,WAAW,YAAY;IAC3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,QAAQ,IAAI,OAAO,CAAC;IACpB,aAAa,IAAI,OAAO,CAAC;IACzB,YAAY,IAAI,OAAO,CAAC;IACxB,SAAS,IAAI,OAAO,CAAC;IACrB,cAAc,IAAI,MAAM,CAAC;IACzB,SAAS,IAAI,OAAO,CAAC;IACrB,YAAY,IAAI,iBAAiB,CAAC;IAClC,kBAAkB,IAAI,gBAAgB,CAAC;IACvC,WAAW,IAAI,MAAM,CAAC;CACvB;AAsUD;;GAEG;AACH,eAAO,MAAM,WAAW;IACtB;;OAEG;sBACe,MAAM,GAAG,YAAY;EA0CvC,CAAC;AAEH,eAAe,WAAW,CAAC"}
@@ -197,6 +197,34 @@ const initializeArtifactDirectories = async (resolvedBasePath) => {
197
197
  }
198
198
  }
199
199
  };
200
+ const tryImportOptional = async (modulePath) => {
201
+ try {
202
+ return (await import(modulePath));
203
+ }
204
+ catch {
205
+ return undefined;
206
+ }
207
+ };
208
+ const registerFromRuntimeConfig = async () => {
209
+ const db = await tryImportOptional('@orm/DatabaseRuntimeRegistration');
210
+ db?.registerDatabasesFromRuntimeConfig?.(databaseConfig);
211
+ const queues = await tryImportOptional('@tools/queue/QueueRuntimeRegistration');
212
+ queues?.registerQueuesFromRuntimeConfig?.(queueConfig);
213
+ const caches = await tryImportOptional('@cache/CacheRuntimeRegistration');
214
+ caches?.registerCachesFromRuntimeConfig?.(cacheConfig);
215
+ const broadcasters = await tryImportOptional('@broadcast/BroadcastRuntimeRegistration');
216
+ broadcasters?.registerBroadcastersFromRuntimeConfig?.({
217
+ default: broadcastConfig.default,
218
+ drivers: broadcastConfig.drivers,
219
+ });
220
+ const disks = await tryImportOptional('@storage/StorageRuntimeRegistration');
221
+ disks?.registerDisksFromRuntimeConfig?.(storageConfig);
222
+ const notifications = await tryImportOptional('@notification/NotificationRuntimeRegistration');
223
+ notifications?.registerNotificationChannelsFromRuntimeConfig?.({
224
+ default: notificationConfig.default,
225
+ drivers: notificationConfig.drivers,
226
+ });
227
+ };
200
228
  const createLifecycle = (params) => {
201
229
  const boot = async () => {
202
230
  if (params.getBooted())
@@ -205,67 +233,7 @@ const createLifecycle = (params) => {
205
233
  StartupConfigValidator.assertValid();
206
234
  FeatureFlags.initialize();
207
235
  await StartupHealthChecks.assertHealthy();
208
- // Register ORM database connections from runtime config.
209
- // This makes every `databaseConfig.connections[name]` available via `useDatabase(undefined, name)`.
210
- // The configured default is also registered as 'default'.
211
- try {
212
- const { registerDatabasesFromRuntimeConfig } = await import('../orm/DatabaseRuntimeRegistration.js');
213
- registerDatabasesFromRuntimeConfig(databaseConfig);
214
- }
215
- catch {
216
- // best-effort: ignore in restrictive runtimes
217
- }
218
- // Register queue drivers from runtime config.
219
- // Ensures default drivers like `sync` are available without manual registration.
220
- try {
221
- const { registerQueuesFromRuntimeConfig } = await import('../tools/queue/QueueRuntimeRegistration.js');
222
- registerQueuesFromRuntimeConfig(queueConfig);
223
- }
224
- catch {
225
- // best-effort: ignore in restrictive runtimes
226
- }
227
- // Register cache driver factories from runtime config.
228
- // Ensures built-in drivers are available via the driver registry.
229
- try {
230
- const { registerCachesFromRuntimeConfig } = await import('../cache/CacheRuntimeRegistration.js');
231
- registerCachesFromRuntimeConfig(cacheConfig);
232
- }
233
- catch {
234
- // best-effort: ignore in restrictive runtimes
235
- }
236
- // Register broadcasters from runtime config.
237
- // Ensures named broadcasters are available and unknown names throw when selected.
238
- try {
239
- const { registerBroadcastersFromRuntimeConfig } = await import('../tools/broadcast/BroadcastRuntimeRegistration.js');
240
- registerBroadcastersFromRuntimeConfig({
241
- default: broadcastConfig.default,
242
- drivers: broadcastConfig.drivers,
243
- });
244
- }
245
- catch {
246
- // best-effort: ignore in restrictive runtimes
247
- }
248
- // Register storage disks from runtime config.
249
- // Ensures named disks are available and 'default' is a reserved alias.
250
- try {
251
- const { registerDisksFromRuntimeConfig } = await import('../tools/storage/StorageRuntimeRegistration.js');
252
- registerDisksFromRuntimeConfig(storageConfig);
253
- }
254
- catch {
255
- // best-effort: ignore in restrictive runtimes
256
- }
257
- // Register notification channels from runtime config.
258
- // Enables selecting named channels and reserves the `default` alias.
259
- try {
260
- const { registerNotificationChannelsFromRuntimeConfig } = await import('../tools/notification/NotificationRuntimeRegistration.js');
261
- registerNotificationChannelsFromRuntimeConfig({
262
- default: notificationConfig.default,
263
- drivers: notificationConfig.drivers,
264
- });
265
- }
266
- catch {
267
- // best-effort: ignore in restrictive runtimes
268
- }
236
+ await registerFromRuntimeConfig();
269
237
  await initializeArtifactDirectories(params.resolvedBasePath);
270
238
  await registerRoutes(params.resolvedBasePath, params.router);
271
239
  // Register service providers
@@ -1 +1 @@
1
- {"version":3,"file":"CLI.d.ts","sourceRoot":"","sources":["../../../src/cli/CLI.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAyBH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,MAAM,WAAW,IAAI;IACnB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,UAAU,IAAI,OAAO,CAAC;CACvB;AAsLD;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG;cACJ,IAAI;EAed,CAAC"}
1
+ {"version":3,"file":"CLI.d.ts","sourceRoot":"","sources":["../../../src/cli/CLI.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA4BH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,MAAM,WAAW,IAAI;IACnB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,UAAU,IAAI,OAAO,CAAC;CACvB;AAyLD;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG;cACJ,IAAI;EAed,CAAC"}
package/src/cli/CLI.js CHANGED
@@ -3,6 +3,7 @@
3
3
  * Orchestrates all CLI commands using Commander
4
4
  */
5
5
  import { AddCommand } from './commands/AddCommand.js';
6
+ import { BroadcastWorkCommand } from './commands/BroadcastWorkCommand.js';
6
7
  import { ConfigCommand } from './commands/ConfigCommand.js';
7
8
  import { D1MigrateCommand } from './commands/D1MigrateCommand.js';
8
9
  import { DebugCommand } from './commands/DebugCommand.js';
@@ -12,9 +13,11 @@ import { MakeMailTemplateCommand } from './commands/MakeMailTemplateCommand.js';
12
13
  import { MakeNotificationTemplateCommand } from './commands/MakeNotificationTemplateCommand.js';
13
14
  import { MigrateCommand } from './commands/MigrateCommand.js';
14
15
  import { NewCommand } from './commands/NewCommand.js';
16
+ import { NotificationWorkCommand } from './commands/NotificationWorkCommand.js';
15
17
  import { PluginCommand } from './commands/PluginCommand.js';
16
18
  import { PrepareCommand } from './commands/PrepareCommand.js';
17
19
  import { QACommand } from './commands/QACommand.js';
20
+ import { QueueCommand } from './commands/QueueCommand.js';
18
21
  import { SecretsCommand } from './commands/SecretsCommand.js';
19
22
  import { SimulateCommand } from './commands/SimulateCommand.js';
20
23
  import { StartCommand } from './commands/StartCommand.js';
@@ -68,6 +71,9 @@ const registerCommands = (program) => {
68
71
  PrepareCommand,
69
72
  AddCommand.create(),
70
73
  StartCommand.create(),
74
+ QueueCommand.create(),
75
+ BroadcastWorkCommand.create(),
76
+ NotificationWorkCommand.create(),
71
77
  MigrateCommand.create(),
72
78
  D1MigrateCommand.create(),
73
79
  DebugCommand.create(),
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Broadcast Work Command
3
+ * Alias to work a broadcast queue.
4
+ */
5
+ import { type IBaseCommand } from '../BaseCommand';
6
+ export declare const BroadcastWorkCommand: Readonly<{
7
+ create(): IBaseCommand;
8
+ }>;
9
+ export default BroadcastWorkCommand;
10
+ //# sourceMappingURL=BroadcastWorkCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BroadcastWorkCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/BroadcastWorkCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,eAAO,MAAM,oBAAoB;cACrB,YAAY;EAQtB,CAAC;AAEH,eAAe,oBAAoB,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Broadcast Work Command
3
+ * Alias to work a broadcast queue.
4
+ */
5
+ import { createKindWorkCommand } from '../commands/createKindWorkCommand.js';
6
+ export const BroadcastWorkCommand = Object.freeze({
7
+ create() {
8
+ return createKindWorkCommand({
9
+ name: 'broadcast:work',
10
+ description: 'Work queued broadcasts',
11
+ kind: 'broadcast',
12
+ helpHint: 'zin broadcast:work --help',
13
+ });
14
+ },
15
+ });
16
+ export default BroadcastWorkCommand;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Notification Work Command
3
+ * Alias to work a notification queue.
4
+ */
5
+ import { type IBaseCommand } from '../BaseCommand';
6
+ export declare const NotificationWorkCommand: Readonly<{
7
+ create(): IBaseCommand;
8
+ }>;
9
+ export default NotificationWorkCommand;
10
+ //# sourceMappingURL=NotificationWorkCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotificationWorkCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/NotificationWorkCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,eAAO,MAAM,uBAAuB;cACxB,YAAY;EAQtB,CAAC;AAEH,eAAe,uBAAuB,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Notification Work Command
3
+ * Alias to work a notification queue.
4
+ */
5
+ import { createKindWorkCommand } from '../commands/createKindWorkCommand.js';
6
+ export const NotificationWorkCommand = Object.freeze({
7
+ create() {
8
+ return createKindWorkCommand({
9
+ name: 'notification:work',
10
+ description: 'Work queued notifications',
11
+ kind: 'notification',
12
+ helpHint: 'zin notification:work --help',
13
+ });
14
+ },
15
+ });
16
+ export default NotificationWorkCommand;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Queue Command
3
+ * Run queued jobs via the framework CLI.
4
+ */
5
+ import { type IBaseCommand } from '../BaseCommand';
6
+ export declare const QueueCommand: Readonly<{
7
+ create(): IBaseCommand;
8
+ }>;
9
+ export default QueueCommand;
10
+ //# sourceMappingURL=QueueCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueueCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/QueueCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAYvF,eAAO,MAAM,YAAY;cACb,YAAY;EA0EtB,CAAC;AAEH,eAAe,YAAY,CAAC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Queue Command
3
+ * Run queued jobs via the framework CLI.
4
+ */
5
+ import { BaseCommand } from '../BaseCommand.js';
6
+ import { QueueWorkCommandUtils } from '../commands/QueueWorkCommandUtils.js';
7
+ import { QueueWorkRunner } from '../workers/QueueWorkRunner.js';
8
+ export const QueueCommand = Object.freeze({
9
+ create() {
10
+ return BaseCommand.create({
11
+ name: 'queue',
12
+ description: 'Work queued jobs (broadcast/notification)',
13
+ addOptions: (command) => {
14
+ command
15
+ .argument('<queueName>', 'Queue name to work')
16
+ .option('--timeout <seconds>', 'Stop after this many seconds (default: 10)')
17
+ .option('--retry <count>', 'Retries after first attempt (default: 3)')
18
+ .option('--max-items <count>', 'Max items to process in one run (default: 1000)')
19
+ .option('--driver <name>', 'Queue driver name (default: from QUEUE_DRIVER)');
20
+ command
21
+ .command('work <kind> <queueName>')
22
+ .alias('w')
23
+ .description('Work a queue with explicit kind (broadcast|notification)')
24
+ .option('--timeout <seconds>', 'Stop after this many seconds (default: 10)')
25
+ .option('--retry <count>', 'Retries after first attempt (default: 3)')
26
+ .option('--max-items <count>', 'Max items to process in one run (default: 1000)')
27
+ .option('--driver <name>', 'Queue driver name (default: from QUEUE_DRIVER)')
28
+ .action(async (kindRaw, queueName, subOptions) => {
29
+ const kind = QueueWorkRunner.parseKind(kindRaw);
30
+ const timeoutSeconds = QueueWorkCommandUtils.parsePositiveInt(subOptions['timeout'], '--timeout');
31
+ const retry = QueueWorkCommandUtils.parseNonNegativeInt(subOptions['retry'], '--retry');
32
+ const maxItems = QueueWorkCommandUtils.parsePositiveInt(subOptions['maxItems'], '--max-items');
33
+ const driverName = QueueWorkCommandUtils.normalizeDriverName(subOptions['driver']);
34
+ const result = await QueueWorkRunner.run({
35
+ kind,
36
+ queueName,
37
+ timeoutSeconds,
38
+ retry,
39
+ maxItems,
40
+ driverName,
41
+ });
42
+ QueueWorkCommandUtils.logSummary(queueName, kind, result);
43
+ });
44
+ },
45
+ execute: async (options) => {
46
+ const queueName = QueueWorkCommandUtils.requireQueueNameFromArgs(options.args, 'zin queue --help');
47
+ const timeoutSeconds = QueueWorkCommandUtils.parsePositiveInt(options.timeout, '--timeout');
48
+ const retry = QueueWorkCommandUtils.parseNonNegativeInt(options.retry, '--retry');
49
+ const maxItems = QueueWorkCommandUtils.parsePositiveInt(options.maxItems, '--max-items');
50
+ const driverName = QueueWorkCommandUtils.normalizeDriverName(options.driver);
51
+ const result = await QueueWorkRunner.run({
52
+ queueName,
53
+ timeoutSeconds,
54
+ retry,
55
+ maxItems,
56
+ driverName,
57
+ });
58
+ QueueWorkCommandUtils.logSummary(queueName, 'auto', result);
59
+ },
60
+ });
61
+ },
62
+ });
63
+ export default QueueCommand;
@@ -0,0 +1,10 @@
1
+ import { type QueueWorkRunnerResult } from '../workers/QueueWorkRunner';
2
+ export declare const QueueWorkCommandUtils: Readonly<{
3
+ parsePositiveInt: (value: unknown, flag: string) => number | undefined;
4
+ parseNonNegativeInt: (value: unknown, flag: string) => number | undefined;
5
+ normalizeDriverName: (value: unknown) => string | undefined;
6
+ requireQueueNameFromArgs: (args: unknown[] | undefined, helpHint: string) => string;
7
+ logSummary: (queueName: string, kindLabel: string, result: QueueWorkRunnerResult) => void;
8
+ }>;
9
+ export default QueueWorkCommandUtils;
10
+ //# sourceMappingURL=QueueWorkCommandUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueueWorkCommandUtils.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/QueueWorkCommandUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAI1E,eAAO,MAAM,qBAAqB;8BACN,OAAO,QAAQ,MAAM,KAAG,MAAM,GAAG,SAAS;iCAcvC,OAAO,QAAQ,MAAM,KAAG,MAAM,GAAG,SAAS;iCAc1C,OAAO,KAAG,MAAM,GAAG,SAAS;qCAKxB,OAAO,EAAE,GAAG,SAAS,YAAY,MAAM,KAAG,MAAM;4BAQzD,MAAM,aAAa,MAAM,UAAU,qBAAqB,KAAG,IAAI;EAKvF,CAAC;AAEH,eAAe,qBAAqB,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { Logger } from '../../config/logger.js';
2
+ import { ErrorFactory } from '../../exceptions/ZintrustError.js';
3
+ export const QueueWorkCommandUtils = Object.freeze({
4
+ parsePositiveInt: (value, flag) => {
5
+ if (value === undefined)
6
+ return undefined;
7
+ const raw = String(value).trim();
8
+ if (raw === '')
9
+ return undefined;
10
+ const n = Number.parseInt(raw, 10);
11
+ if (!Number.isFinite(n) || n <= 0) {
12
+ throw ErrorFactory.createCliError(`Error: Invalid ${flag} '${raw}'. Expected a positive integer.`);
13
+ }
14
+ return n;
15
+ },
16
+ parseNonNegativeInt: (value, flag) => {
17
+ if (value === undefined)
18
+ return undefined;
19
+ const raw = String(value).trim();
20
+ if (raw === '')
21
+ return undefined;
22
+ const n = Number.parseInt(raw, 10);
23
+ if (!Number.isFinite(n) || n < 0) {
24
+ throw ErrorFactory.createCliError(`Error: Invalid ${flag} '${raw}'. Expected a non-negative integer.`);
25
+ }
26
+ return n;
27
+ },
28
+ normalizeDriverName: (value) => {
29
+ const raw = typeof value === 'string' ? value.trim() : '';
30
+ return raw === '' ? undefined : raw;
31
+ },
32
+ requireQueueNameFromArgs: (args, helpHint) => {
33
+ const queueName = typeof args?.[0] === 'string' ? String(args[0]) : '';
34
+ if (queueName.trim() === '') {
35
+ throw ErrorFactory.createCliError(`Error: Missing <queueName>. Try '${helpHint}'.`);
36
+ }
37
+ return queueName;
38
+ },
39
+ logSummary: (queueName, kindLabel, result) => {
40
+ Logger.info(`Queue work complete (${kindLabel}) for '${queueName}': processed=${result.processed} retried=${result.retried} dropped=${result.dropped} notDueRequeued=${result.notDueRequeued} unknown=${result.unknown}`);
41
+ },
42
+ });
43
+ export default QueueWorkCommandUtils;
@@ -0,0 +1,9 @@
1
+ import { type IBaseCommand } from '../BaseCommand';
2
+ import { type QueueWorkKind } from '../workers/QueueWorkRunner';
3
+ export declare function createKindWorkCommand(options: {
4
+ name: string;
5
+ description: string;
6
+ kind: QueueWorkKind;
7
+ helpHint: string;
8
+ }): IBaseCommand;
9
+ //# sourceMappingURL=createKindWorkCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createKindWorkCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/createKindWorkCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEvF,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAUnF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,aAAa,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,YAAY,CAsCf"}
@@ -0,0 +1,33 @@
1
+ import { BaseCommand } from '../BaseCommand.js';
2
+ import { QueueWorkCommandUtils } from '../commands/QueueWorkCommandUtils.js';
3
+ import { QueueWorkRunner } from '../workers/QueueWorkRunner.js';
4
+ export function createKindWorkCommand(options) {
5
+ return BaseCommand.create({
6
+ name: options.name,
7
+ description: options.description,
8
+ addOptions: (command) => {
9
+ command
10
+ .argument('<queueName>', 'Queue name to work')
11
+ .option('--timeout <seconds>', 'Stop after this many seconds (default: 10)')
12
+ .option('--retry <count>', 'Retries after first attempt (default: 3)')
13
+ .option('--max-items <count>', 'Max items to process in one run (default: 1000)')
14
+ .option('--driver <name>', 'Queue driver name (default: from QUEUE_DRIVER)');
15
+ },
16
+ execute: async (cmdOptions) => {
17
+ const queueName = QueueWorkCommandUtils.requireQueueNameFromArgs(cmdOptions.args, options.helpHint);
18
+ const timeoutSeconds = QueueWorkCommandUtils.parsePositiveInt(cmdOptions.timeout, '--timeout');
19
+ const retry = QueueWorkCommandUtils.parseNonNegativeInt(cmdOptions.retry, '--retry');
20
+ const maxItems = QueueWorkCommandUtils.parsePositiveInt(cmdOptions.maxItems, '--max-items');
21
+ const driverName = QueueWorkCommandUtils.normalizeDriverName(cmdOptions.driver);
22
+ const result = await QueueWorkRunner.run({
23
+ kind: options.kind,
24
+ queueName,
25
+ timeoutSeconds,
26
+ retry,
27
+ maxItems,
28
+ driverName,
29
+ });
30
+ QueueWorkCommandUtils.logSummary(queueName, options.kind, result);
31
+ },
32
+ });
33
+ }
@@ -2,6 +2,7 @@
2
2
  * CLI Commands Module Index
3
3
  */
4
4
  export { AddCommand } from '../commands/AddCommand';
5
+ export { BroadcastWorkCommand } from '../commands/BroadcastWorkCommand';
5
6
  export { ConfigCommand } from '../commands/ConfigCommand';
6
7
  export { DebugCommand } from '../commands/DebugCommand';
7
8
  export { LogsCleanupCommand } from '../commands/LogsCleanupCommand';
@@ -9,7 +10,9 @@ export { MakeMailTemplateCommand } from '../commands/MakeMailTemplateCommand';
9
10
  export { MakeNotificationTemplateCommand } from '../commands/MakeNotificationTemplateCommand';
10
11
  export { MigrateCommand } from '../commands/MigrateCommand';
11
12
  export { NewCommand } from '../commands/NewCommand';
13
+ export { NotificationWorkCommand } from '../commands/NotificationWorkCommand';
12
14
  export { PrepareCommand } from '../commands/PrepareCommand';
15
+ export { QueueCommand } from '../commands/QueueCommand';
13
16
  export { SecretsCommand } from '../commands/SecretsCommand';
14
17
  export { StartCommand } from '../commands/StartCommand';
15
18
  export { TemplatesCommand } from '../commands/TemplatesCommand';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,EAAE,+BAA+B,EAAE,MAAM,+CAA+C,CAAC;AAChG,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,EAAE,+BAA+B,EAAE,MAAM,+CAA+C,CAAC;AAChG,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC"}
@@ -2,6 +2,7 @@
2
2
  * CLI Commands Module Index
3
3
  */
4
4
  export { AddCommand } from '../commands/AddCommand.js';
5
+ export { BroadcastWorkCommand } from '../commands/BroadcastWorkCommand.js';
5
6
  export { ConfigCommand } from '../commands/ConfigCommand.js';
6
7
  export { DebugCommand } from '../commands/DebugCommand.js';
7
8
  export { LogsCleanupCommand } from '../commands/LogsCleanupCommand.js';
@@ -9,7 +10,9 @@ export { MakeMailTemplateCommand } from '../commands/MakeMailTemplateCommand.js'
9
10
  export { MakeNotificationTemplateCommand } from '../commands/MakeNotificationTemplateCommand.js';
10
11
  export { MigrateCommand } from '../commands/MigrateCommand.js';
11
12
  export { NewCommand } from '../commands/NewCommand.js';
13
+ export { NotificationWorkCommand } from '../commands/NotificationWorkCommand.js';
12
14
  export { PrepareCommand } from '../commands/PrepareCommand.js';
15
+ export { QueueCommand } from '../commands/QueueCommand.js';
13
16
  export { SecretsCommand } from '../commands/SecretsCommand.js';
14
17
  export { StartCommand } from '../commands/StartCommand.js';
15
18
  export { TemplatesCommand } from '../commands/TemplatesCommand.js';
@@ -1 +1 @@
1
- {"version":3,"file":"ModelGenerator.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/ModelGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,SAAS,GACT,OAAO,GACP,SAAS,GACT,MAAM,GACN,UAAU,GACV,MAAM,GACN,EAAE,CAAC;AAEP,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAsB3F;AAED;;GAEG;AAEH,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA0ClF;AA+HD;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,SAAS,EAAE,CAEjD;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,UAAU,EAAE,CAW5C;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,UAAU,EAAE,CAU5C;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,UAAU,EAAE,CAU7C;AAED;;GAEG;AACH,eAAO,MAAM,cAAc;;;;;;;EAOzB,CAAC"}
1
+ {"version":3,"file":"ModelGenerator.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/ModelGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,SAAS,GACT,OAAO,GACP,SAAS,GACT,MAAM,GACN,UAAU,GACV,MAAM,GACN,EAAE,CAAC;AAEP,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAsB3F;AAED;;GAEG;AAEH,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA0ClF;AAgID;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,SAAS,EAAE,CAEjD;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,UAAU,EAAE,CAW5C;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,UAAU,EAAE,CAU5C;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,UAAU,EAAE,CAU7C;AAED;;GAEG;AACH,eAAO,MAAM,cAAc;;;;;;;EAOzB,CAAC"}
@@ -92,6 +92,7 @@ export const ${options.name} = Object.freeze(
92
92
  fillable: [${fillable.map((f) => `'${f}'`).join(', ')}],
93
93
  hidden: [${hidden.map((f) => `'${f}'`).join(', ')}],
94
94
  timestamps: ${options.timestamps !== false},
95
+ softDeletes: ${options.softDelete === true},
95
96
  casts: {
96
97
  `;
97
98
  // Add field casts
@@ -0,0 +1,23 @@
1
+ export type QueueWorkKind = 'broadcast' | 'notification';
2
+ export type QueueWorkRunnerOptions = {
3
+ queueName: string;
4
+ kind?: QueueWorkKind;
5
+ driverName?: string;
6
+ timeoutSeconds?: number;
7
+ maxItems?: number;
8
+ /** Max retries after the first attempt (so total attempts = retry + 1) */
9
+ retry?: number;
10
+ };
11
+ export type QueueWorkRunnerResult = {
12
+ processed: number;
13
+ retried: number;
14
+ dropped: number;
15
+ notDueRequeued: number;
16
+ unknown: number;
17
+ };
18
+ export declare const QueueWorkRunner: Readonly<{
19
+ run(options: QueueWorkRunnerOptions): Promise<QueueWorkRunnerResult>;
20
+ parseKind(value: unknown): QueueWorkKind;
21
+ }>;
22
+ export default QueueWorkRunner;
23
+ //# sourceMappingURL=QueueWorkRunner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueueWorkRunner.d.ts","sourceRoot":"","sources":["../../../../src/cli/workers/QueueWorkRunner.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,cAAc,CAAC;AAoBzD,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAyHF,eAAO,MAAM,eAAe;iBACP,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC;qBAuCzD,OAAO,GAAG,aAAa;EAUxC,CAAC;AAEH,eAAe,eAAe,CAAC"}
@@ -0,0 +1,142 @@
1
+ import { Broadcast } from '../../tools/broadcast/Broadcast.js';
2
+ import { Logger } from '../../config/logger.js';
3
+ import { queueConfig } from '../../config/queue.js';
4
+ import { ErrorFactory } from '../../exceptions/ZintrustError.js';
5
+ import { Notification } from '../../tools/notification/Notification.js';
6
+ import { Queue } from '../../tools/queue/Queue.js';
7
+ import { registerQueuesFromRuntimeConfig } from '../../tools/queue/QueueRuntimeRegistration.js';
8
+ const isKind = (value) => value === 'broadcast' || value === 'notification';
9
+ const detectKindFromPayload = (payload) => {
10
+ if (payload !== null && typeof payload === 'object') {
11
+ const p = payload;
12
+ if (isKind(p['type']))
13
+ return p['type'];
14
+ if (typeof p['channel'] === 'string' && typeof p['event'] === 'string')
15
+ return 'broadcast';
16
+ if (typeof p['recipient'] === 'string' && typeof p['message'] === 'string')
17
+ return 'notification';
18
+ }
19
+ return undefined;
20
+ };
21
+ const normalizeNumber = (value) => {
22
+ if (typeof value === 'number' && Number.isFinite(value))
23
+ return value;
24
+ if (typeof value === 'string' && value.trim() !== '') {
25
+ const n = Number(value);
26
+ if (Number.isFinite(n))
27
+ return n;
28
+ }
29
+ return undefined;
30
+ };
31
+ const getTimestamp = (payload) => {
32
+ return normalizeNumber(payload['timestamp']);
33
+ };
34
+ const getAttempts = (payload) => {
35
+ const n = normalizeNumber(payload['attempts']);
36
+ return typeof n === 'number' && n >= 0 ? Math.floor(n) : 0;
37
+ };
38
+ const withAttempts = (payload, attempts) => {
39
+ return { ...payload, attempts };
40
+ };
41
+ const shouldStop = (startedAtMs, timeoutSeconds) => {
42
+ if (timeoutSeconds === undefined)
43
+ return false;
44
+ const elapsedMs = Date.now() - startedAtMs;
45
+ return elapsedMs >= timeoutSeconds * 1000;
46
+ };
47
+ const processMessage = async (options, msg, maxAttempts, result) => {
48
+ const payload = msg.payload ?? {};
49
+ const kind = options.kind ?? detectKindFromPayload(payload);
50
+ if (kind === undefined) {
51
+ Logger.warn('Queue worker: unknown job payload; dropping', {
52
+ queue: options.queueName,
53
+ messageId: msg.id,
54
+ payloadKeys: Object.keys(payload),
55
+ });
56
+ result.unknown++;
57
+ await Queue.ack(options.queueName, msg.id, options.driverName);
58
+ return 'continue';
59
+ }
60
+ const timestamp = getTimestamp(payload);
61
+ if (typeof timestamp === 'number' && timestamp > Date.now()) {
62
+ // Not due yet: re-enqueue and stop after rotating the head once.
63
+ await Queue.enqueue(options.queueName, payload, options.driverName);
64
+ await Queue.ack(options.queueName, msg.id, options.driverName);
65
+ result.notDueRequeued++;
66
+ return 'break';
67
+ }
68
+ const attempts = getAttempts(payload);
69
+ try {
70
+ if (kind === 'broadcast') {
71
+ const job = payload;
72
+ await Broadcast.send(job.channel, job.event, job.data);
73
+ }
74
+ else {
75
+ const job = payload;
76
+ await Notification.send(job.recipient, job.message, job.options ?? {});
77
+ }
78
+ await Queue.ack(options.queueName, msg.id, options.driverName);
79
+ result.processed++;
80
+ return 'continue';
81
+ }
82
+ catch (error) {
83
+ const nextAttempts = attempts + 1;
84
+ const canRetry = nextAttempts < maxAttempts;
85
+ Logger.error('Queue worker: job failed', {
86
+ queue: options.queueName,
87
+ kind,
88
+ messageId: msg.id,
89
+ attempts: nextAttempts,
90
+ maxAttempts,
91
+ error,
92
+ });
93
+ if (canRetry) {
94
+ await Queue.enqueue(options.queueName, withAttempts(payload, nextAttempts), options.driverName);
95
+ result.retried++;
96
+ }
97
+ else {
98
+ result.dropped++;
99
+ }
100
+ await Queue.ack(options.queueName, msg.id, options.driverName);
101
+ return 'continue';
102
+ }
103
+ };
104
+ export const QueueWorkRunner = Object.freeze({
105
+ async run(options) {
106
+ registerQueuesFromRuntimeConfig(queueConfig);
107
+ const startedAtMs = Date.now();
108
+ const maxItems = typeof options.maxItems === 'number' ? options.maxItems : 1000;
109
+ const timeoutSeconds = typeof options.timeoutSeconds === 'number' ? options.timeoutSeconds : 10;
110
+ const maxRetries = typeof options.retry === 'number' ? options.retry : 3;
111
+ const maxAttempts = Math.max(0, Math.floor(maxRetries)) + 1;
112
+ const result = {
113
+ processed: 0,
114
+ retried: 0,
115
+ dropped: 0,
116
+ notDueRequeued: 0,
117
+ unknown: 0,
118
+ };
119
+ /* eslint-disable no-await-in-loop */
120
+ while (result.processed < maxItems && !shouldStop(startedAtMs, timeoutSeconds)) {
121
+ const msg = await Queue.dequeue(options.queueName, options.driverName);
122
+ if (msg === undefined)
123
+ break;
124
+ const outcome = await processMessage(options, { id: msg.id, payload: msg.payload ?? {} }, maxAttempts, result);
125
+ if (outcome === 'break')
126
+ break;
127
+ }
128
+ /* eslint-enable no-await-in-loop */
129
+ return result;
130
+ },
131
+ parseKind(value) {
132
+ const v = String(value ?? '')
133
+ .trim()
134
+ .toLowerCase();
135
+ if (v === 'broadcast' || v === 'broad')
136
+ return 'broadcast';
137
+ if (v === 'notification' || v === 'notify')
138
+ return 'notification';
139
+ throw ErrorFactory.createCliError(`Invalid kind '${String(value)}'. Expected 'broadcast' or 'notification'.`);
140
+ },
141
+ });
142
+ export default QueueWorkRunner;