@stacksjs/actions 0.70.87 → 0.70.90

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 (159) hide show
  1. package/dist/action.js +78 -2
  2. package/dist/actions.js +2 -2
  3. package/dist/add.js +20 -2
  4. package/dist/ai/request-model-access.js +10 -2
  5. package/dist/auth/client.js +44 -3
  6. package/dist/auth/prune.js +35 -2
  7. package/dist/auth/setup.js +152 -36
  8. package/dist/auth/token.js +10 -2
  9. package/dist/blog-admin.d.ts +55 -0
  10. package/dist/blog-admin.js +156 -0
  11. package/dist/blog.d.ts +11 -0
  12. package/dist/blog.js +306 -56
  13. package/dist/build/cli.js +6 -2
  14. package/dist/build/component-libs.js +7 -2
  15. package/dist/build/core.js +55 -2
  16. package/dist/build/desktop.js +5 -2
  17. package/dist/build/docs.js +5 -2
  18. package/dist/build/frontend-static.js +123 -8
  19. package/dist/build/server.js +6 -2
  20. package/dist/build/stacks.js +8 -2
  21. package/dist/build/views.js +11 -2
  22. package/dist/build.js +64 -2
  23. package/dist/bump.js +162 -7
  24. package/dist/cdn/invalidate-cache.js +0 -1
  25. package/dist/changelog.js +27 -3
  26. package/dist/check/ports.js +16 -2
  27. package/dist/clean.js +4 -2
  28. package/dist/commit.js +12 -2
  29. package/dist/copy-types.js +10 -3
  30. package/dist/database/seed.js +26 -2
  31. package/dist/deploy/create-receipt-rule.js +36 -2
  32. package/dist/deploy/index.js +1318 -44
  33. package/dist/dev/api.js +94 -6
  34. package/dist/dev/components.js +7 -2
  35. package/dist/dev/dashboard-globals.js +89 -3
  36. package/dist/dev/dashboard-utils.js +380 -2
  37. package/dist/dev/dashboard.js +435 -8
  38. package/dist/dev/desktop.js +5 -2
  39. package/dist/dev/docs.js +24 -2
  40. package/dist/dev/index.js +29 -2
  41. package/dist/dev/migrate-watcher.js +74 -2
  42. package/dist/dev/system-tray.js +5 -2
  43. package/dist/dev/views.js +147 -2
  44. package/dist/discover-packages.js +32 -2
  45. package/dist/domains/add.js +61 -2
  46. package/dist/domains/purchase.js +66 -2
  47. package/dist/domains/remove.js +24 -2
  48. package/dist/examples.js +34 -2
  49. package/dist/find-projects.js +16 -2
  50. package/dist/fresh.js +17 -2
  51. package/dist/generate/action-types.js +9 -4
  52. package/dist/generate/component-meta.js +9 -3
  53. package/dist/generate/custom-cli-file.js +20 -3
  54. package/dist/generate/env-files.js +46 -6
  55. package/dist/generate/ide-helpers.js +8 -3
  56. package/dist/generate/index.js +158 -2
  57. package/dist/generate/lib-entries.js +16 -3
  58. package/dist/generate/pantry-file.js +46 -2
  59. package/dist/generate/symlink-core.js +2 -2
  60. package/dist/generate/types.js +3 -2
  61. package/dist/generate/vscode-custom-data.js +9 -3
  62. package/dist/generate/web-types.js +0 -1
  63. package/dist/helpers/component-meta.js +295 -2
  64. package/dist/helpers/index.js +1 -2
  65. package/dist/helpers/lib-entries.js +73 -2
  66. package/dist/helpers/package-json.js +45 -14
  67. package/dist/helpers/utils.js +105 -2
  68. package/dist/helpers/vscode-custom-data.js +30 -2
  69. package/dist/index.d.ts +13 -0
  70. package/dist/index.js +50 -2
  71. package/dist/key-generate.js +24 -2
  72. package/dist/lint/fix.js +4 -3
  73. package/dist/lint/index.js +4 -3
  74. package/dist/lint/lint.js +34 -2
  75. package/dist/make-command.js +64 -14
  76. package/dist/make-job.js +41 -16
  77. package/dist/make-policy.js +74 -26
  78. package/dist/make-resource.js +50 -21
  79. package/dist/make.js +328 -2
  80. package/dist/migrate/database.js +16 -2
  81. package/dist/migrate/fresh.js +31 -2
  82. package/dist/orm/base.js +0 -2
  83. package/dist/orm/test.js +0 -1
  84. package/dist/prepublish.js +16 -2
  85. package/dist/queue/clear.js +42 -2
  86. package/dist/queue/dlq-purge.js +28 -2
  87. package/dist/queue/dlq-retry.js +35 -2
  88. package/dist/queue/dlq.js +55 -5
  89. package/dist/queue/failed.js +69 -5
  90. package/dist/queue/flush.js +49 -3
  91. package/dist/queue/inspect.js +154 -8
  92. package/dist/queue/list.js +69 -5
  93. package/dist/queue/monitor.js +94 -6
  94. package/dist/queue/pause.js +28 -2
  95. package/dist/queue/quarantine.js +42 -3
  96. package/dist/queue/resume.js +27 -2
  97. package/dist/queue/retry.js +41 -2
  98. package/dist/queue/schedule-list.js +33 -5
  99. package/dist/queue/schedule.js +12 -2
  100. package/dist/queue/status.js +68 -5
  101. package/dist/queue/table.js +10 -2
  102. package/dist/queue/unquarantine.js +27 -2
  103. package/dist/queue/work.js +57 -2
  104. package/dist/release.js +21 -3
  105. package/dist/route/list.js +78 -3
  106. package/dist/run-action.js +1 -2
  107. package/dist/saas/setup.js +9 -2
  108. package/dist/scaffold-crud.js +164 -40
  109. package/dist/schedule/run.js +7 -2
  110. package/dist/search/flush.js +10 -2
  111. package/dist/search/import.js +10 -2
  112. package/dist/search/settings-list.js +10 -2
  113. package/dist/search/settings.js +9 -2
  114. package/dist/serve/api.js +35 -2
  115. package/dist/setup/index.js +1 -2
  116. package/dist/setup/ssl.js +271 -2
  117. package/dist/stacks.js +265 -2
  118. package/dist/templates.js +301 -2
  119. package/dist/test/feature.js +11 -2
  120. package/dist/test/index.js +11 -2
  121. package/dist/test/ui.js +4 -2
  122. package/dist/test/unit.js +11 -2
  123. package/dist/typecheck.js +4 -2
  124. package/dist/types.js +16 -2
  125. package/dist/upgrade/binary.js +29 -2
  126. package/dist/upgrade/bun.js +0 -1
  127. package/dist/upgrade/dependencies.js +0 -2
  128. package/dist/upgrade/framework-utils.js +193 -2
  129. package/dist/upgrade/framework.js +310 -7
  130. package/dist/upgrade/index.js +17 -2
  131. package/dist/upgrade/packages.js +99 -12
  132. package/dist/upgrade/shell.js +40 -4
  133. package/dist/upgrade.js +38 -2
  134. package/package.json +16 -16
  135. package/dist/chunk-0c8sd1t6.js +0 -2
  136. package/dist/chunk-0g2nzhx9.js +0 -240
  137. package/dist/chunk-0gadhvn7.js +0 -3
  138. package/dist/chunk-0h27aa4r.js +0 -93
  139. package/dist/chunk-3peh8kqs.js +0 -851
  140. package/dist/chunk-62gdfav8.js +0 -3
  141. package/dist/chunk-6bk53y02.js +0 -3
  142. package/dist/chunk-78c5n3s2.js +0 -3
  143. package/dist/chunk-c74qv38e.js +0 -17
  144. package/dist/chunk-cdk2r2jd.js +0 -1
  145. package/dist/chunk-dbz9dp2h.js +0 -3
  146. package/dist/chunk-e142dheq.js +0 -3
  147. package/dist/chunk-ec4gky40.js +0 -3
  148. package/dist/chunk-h3d81wrg.js +0 -3
  149. package/dist/chunk-m3q0x4h0.js +0 -688
  150. package/dist/chunk-mqgbyhph.js +0 -5
  151. package/dist/chunk-n24m8prb.js +0 -3
  152. package/dist/chunk-n5eqwhck.js +0 -7
  153. package/dist/chunk-nsvnqv8y.js +0 -5
  154. package/dist/chunk-nty6mmx4.js +0 -283
  155. package/dist/chunk-s735m9mg.js +0 -1
  156. package/dist/chunk-tpb8jgsk.js +0 -7
  157. package/dist/chunk-tsbk5vne.js +0 -3
  158. package/dist/chunk-xg9xscqz.js +0 -1
  159. package/dist/chunk-y6e448he.js +0 -7
@@ -1,7 +1,95 @@
1
- // @bun
2
- import D from"process";import{log as O}from"@stacksjs/logging";import{Job as P,FailedJob as Q}from"@stacksjs/orm";import{getActiveJobCount as V,isWorkerRunning as X}from"@stacksjs/queue";var U=_(),G=U.queue,Y=Number(U.interval)||2000,H=!0;D.on("SIGINT",()=>{H=!1,console.log(`
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { Job, FailedJob } from "@stacksjs/orm";
4
+ import { getActiveJobCount, isWorkerRunning } from "@stacksjs/queue";
5
+ const options = parseArgs(), queueName = options.queue, refreshInterval = Number(options.interval) || 2000;
6
+ let isRunning = !0;
7
+ process.on("SIGINT", () => {
8
+ isRunning = !1;
9
+ console.log(`
3
10
 
4
- Monitoring stopped.`),D.exit(0)});D.on("SIGTERM",()=>{H=!1,D.exit(0)});async function Z(){let x=G?await P.where("queue",G).get():await P.all(),z=G?await Q.where("queue",G).get():await Q.all(),B=Math.floor(Date.now()/1000),E=0,L=0,M=0;for(let K of x)if(K.reserved_at)L++;else if(K.available_at&&Number(K.available_at)>B)M++;else E++;return{pending:E,processing:L,delayed:M,failed:z.length,total:x.length,workerRunning:X(),activeJobs:V()}}async function T(){let x=await Z(),z=new Date().toLocaleTimeString();if(console.clear(),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 Queue Monitor \u2502"),console.log("\u2502 Press Ctrl+C to exit \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Last Updated: ${z.padEnd(48)} \u2502`),console.log(`\u2502 Queue Filter: ${(G||"All Queues").padEnd(48)} \u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \u2502"),console.log(`\u2502 Pending Jobs: ${String(x.pending).padStart(8)} \u2502`),console.log(`\u2502 Processing Jobs: ${String(x.processing).padStart(8)} \u2502`),console.log(`\u2502 Delayed Jobs: ${String(x.delayed).padStart(8)} \u2502`),console.log(`\u2502 Failed Jobs: ${String(x.failed).padStart(8)} \u2502`),console.log("\u2502 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2502"),console.log(`\u2502 Total Jobs: ${String(x.total).padStart(8)} \u2502`),console.log("\u2502 \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 Worker Status \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Worker Running: ${(x.workerRunning?"Yes":"No").padEnd(8)} \u2502`),console.log(`\u2502 Active Jobs: ${String(x.activeJobs).padStart(8)} \u2502`),console.log("\u2502 \u2502"),console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),x.failed>0)console.log(`
5
- \u26A0\uFE0F Warning: ${x.failed} failed job(s) - run 'buddy queue:failed' for details`);if(!x.workerRunning&&x.pending>0)console.log(`
6
- \u26A0\uFE0F Warning: Worker not running but ${x.pending} job(s) pending - run 'buddy queue:work'`)}try{O.info(`Starting queue monitor...
7
- `),await T();while(H)if(await new Promise((x)=>setTimeout(x,Y)),H)await T()}catch(x){O.error("Monitor error:",x),D.exit(1)}function _(){let x={};return D.argv.forEach((z)=>{if(z.startsWith("--")){let[B,E]=z.slice(2).split("=");if(B&&E)x[B]=E;else if(B)x[B]="true"}}),x}
11
+ Monitoring stopped.`);
12
+ process.exit(0);
13
+ });
14
+ process.on("SIGTERM", () => {
15
+ isRunning = !1;
16
+ process.exit(0);
17
+ });
18
+ async function getStats() {
19
+ const allJobs = queueName ? await Job.where("queue", queueName).get() : await Job.all(), failedJobs = queueName ? await FailedJob.where("queue", queueName).get() : await FailedJob.all(), now = Math.floor(Date.now() / 1000);
20
+ let pending = 0, processing = 0, delayed = 0;
21
+ for (const job of allJobs)
22
+ if (job.reserved_at)
23
+ processing++;
24
+ else if (job.available_at && Number(job.available_at) > now)
25
+ delayed++;
26
+ else
27
+ pending++;
28
+ return {
29
+ pending,
30
+ processing,
31
+ delayed,
32
+ failed: failedJobs.length,
33
+ total: allJobs.length,
34
+ workerRunning: isWorkerRunning(),
35
+ activeJobs: getActiveJobCount()
36
+ };
37
+ }
38
+ async function displayStats() {
39
+ const stats = await getStats(), timestamp = new Date().toLocaleTimeString();
40
+ console.clear();
41
+ console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
42
+ console.log("\u2502 Queue Monitor \u2502");
43
+ console.log("\u2502 Press Ctrl+C to exit \u2502");
44
+ console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
45
+ console.log(`\u2502 Last Updated: ${timestamp.padEnd(48)} \u2502`);
46
+ console.log(`\u2502 Queue Filter: ${(queueName || "All Queues").padEnd(48)} \u2502`);
47
+ console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
48
+ console.log("\u2502 \u2502");
49
+ console.log(`\u2502 Pending Jobs: ${String(stats.pending).padStart(8)} \u2502`);
50
+ console.log(`\u2502 Processing Jobs: ${String(stats.processing).padStart(8)} \u2502`);
51
+ console.log(`\u2502 Delayed Jobs: ${String(stats.delayed).padStart(8)} \u2502`);
52
+ console.log(`\u2502 Failed Jobs: ${String(stats.failed).padStart(8)} \u2502`);
53
+ console.log("\u2502 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2502");
54
+ console.log(`\u2502 Total Jobs: ${String(stats.total).padStart(8)} \u2502`);
55
+ console.log("\u2502 \u2502");
56
+ console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
57
+ console.log("\u2502 Worker Status \u2502");
58
+ console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
59
+ console.log(`\u2502 Worker Running: ${(stats.workerRunning ? "Yes" : "No").padEnd(8)} \u2502`);
60
+ console.log(`\u2502 Active Jobs: ${String(stats.activeJobs).padStart(8)} \u2502`);
61
+ console.log("\u2502 \u2502");
62
+ console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
63
+ if (stats.failed > 0)
64
+ console.log(`
65
+ \u26A0\uFE0F Warning: ${stats.failed} failed job(s) - run 'buddy queue:failed' for details`);
66
+ if (!stats.workerRunning && stats.pending > 0)
67
+ console.log(`
68
+ \u26A0\uFE0F Warning: Worker not running but ${stats.pending} job(s) pending - run 'buddy queue:work'`);
69
+ }
70
+ try {
71
+ log.info(`Starting queue monitor...
72
+ `);
73
+ await displayStats();
74
+ while (isRunning) {
75
+ await new Promise((resolve) => setTimeout(resolve, refreshInterval));
76
+ if (isRunning)
77
+ await displayStats();
78
+ }
79
+ } catch (error) {
80
+ log.error("Monitor error:", error);
81
+ process.exit(1);
82
+ }
83
+ function parseArgs() {
84
+ const args = {};
85
+ process.argv.forEach((arg) => {
86
+ if (arg.startsWith("--")) {
87
+ const [key, value] = arg.slice(2).split("=");
88
+ if (key && value)
89
+ args[key] = value;
90
+ else if (key)
91
+ args[key] = "true";
92
+ }
93
+ });
94
+ return args;
95
+ }
@@ -1,2 +1,28 @@
1
- // @bun
2
- import r from"process";import{log as s}from"@stacksjs/logging";import{pauseQueue as n}from"@stacksjs/queue";var o=f(),t=o.queue;if(!t)s.error("Usage: buddy queue:pause --queue=<name> [--for=300]"),r.exit(1);var c=o.for?Number.parseInt(o.for,10):300;try{await n(t,c),s.success(`Paused queue '${t}' for ${c}s`),r.exit(0)}catch(e){s.error("Failed to pause queue",e),r.exit(1)}function f(){let e={};return r.argv.forEach((u)=>{if(u.startsWith("--")){let[i,a]=u.slice(2).split("=");if(i&&a)e[i]=a}}),e}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { pauseQueue } from "@stacksjs/queue";
4
+ const options = parseArgs(), queue = options.queue;
5
+ if (!queue) {
6
+ log.error("Usage: buddy queue:pause --queue=<name> [--for=300]");
7
+ process.exit(1);
8
+ }
9
+ const pauseSeconds = options.for ? Number.parseInt(options.for, 10) : 300;
10
+ try {
11
+ await pauseQueue(queue, pauseSeconds);
12
+ log.success(`Paused queue '${queue}' for ${pauseSeconds}s`);
13
+ process.exit(0);
14
+ } catch (error) {
15
+ log.error("Failed to pause queue", error);
16
+ process.exit(1);
17
+ }
18
+ function parseArgs() {
19
+ const args = {};
20
+ process.argv.forEach((arg) => {
21
+ if (arg.startsWith("--")) {
22
+ const [key, value] = arg.slice(2).split("=");
23
+ if (key && value)
24
+ args[key] = value;
25
+ }
26
+ });
27
+ return args;
28
+ }
@@ -1,3 +1,42 @@
1
- // @bun
2
- import B from"process";import{log as F}from"@stacksjs/logging";import{listQuarantined as L,quarantineJob as M}from"@stacksjs/queue";var G=O();try{if(G.add){let x=G.add;await M(x),F.success(`Quarantined ${x}`),B.exit(0)}let z=await L();if(z.length===0)console.log("\u2713 No jobs currently quarantined"),B.exit(0);console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 ID \u2502 Job Name \u2502 Payload Hash \u2502 Failures \u2502 Quarantined At \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");for(let x of z){let C=String(x.id).padEnd(3),E=(x.job_name||"?").substring(0,32).padEnd(32),H=(x.payload_hash||"?").substring(0,16).padEnd(16),I=String(x.failure_count??0).padEnd(8),K=(x.quarantined_at||"N/A").substring(0,24).padEnd(24);console.log(`\u2502 ${C} \u2502 ${E} \u2502 ${H} \u2502 ${I} \u2502 ${K} \u2502`)}console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log(`
3
- ${z.length} quarantined entrie(s). Use \`queue:unquarantine <JobName>\` to lift.`),B.exit(0)}catch(z){F.error("Failed to handle queue:quarantine",z),B.exit(1)}function O(){let z={};return B.argv.forEach((x)=>{if(x.startsWith("--")){let[C,E]=x.slice(2).split("=");if(C&&E)z[C]=E}}),z}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { listQuarantined, quarantineJob } from "@stacksjs/queue";
4
+ const options = parseArgs();
5
+ try {
6
+ if (options.add) {
7
+ const jobName = options.add;
8
+ await quarantineJob(jobName);
9
+ log.success(`Quarantined ${jobName}`);
10
+ process.exit(0);
11
+ }
12
+ const rows = await listQuarantined();
13
+ if (rows.length === 0) {
14
+ console.log("\u2713 No jobs currently quarantined");
15
+ process.exit(0);
16
+ }
17
+ console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
18
+ console.log("\u2502 ID \u2502 Job Name \u2502 Payload Hash \u2502 Failures \u2502 Quarantined At \u2502");
19
+ console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
20
+ for (const row of rows) {
21
+ const id = String(row.id).padEnd(3), jn = (row.job_name || "?").substring(0, 32).padEnd(32), ph = (row.payload_hash || "?").substring(0, 16).padEnd(16), fc = String(row.failure_count ?? 0).padEnd(8), qa = (row.quarantined_at || "N/A").substring(0, 24).padEnd(24);
22
+ console.log(`\u2502 ${id} \u2502 ${jn} \u2502 ${ph} \u2502 ${fc} \u2502 ${qa} \u2502`);
23
+ }
24
+ console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
25
+ console.log(`
26
+ ${rows.length} quarantined entrie(s). Use \`queue:unquarantine <JobName>\` to lift.`);
27
+ process.exit(0);
28
+ } catch (error) {
29
+ log.error("Failed to handle queue:quarantine", error);
30
+ process.exit(1);
31
+ }
32
+ function parseArgs() {
33
+ const args = {};
34
+ process.argv.forEach((arg) => {
35
+ if (arg.startsWith("--")) {
36
+ const [key, value] = arg.slice(2).split("=");
37
+ if (key && value)
38
+ args[key] = value;
39
+ }
40
+ });
41
+ return args;
42
+ }
@@ -1,2 +1,27 @@
1
- // @bun
2
- import r from"process";import{log as s}from"@stacksjs/logging";import{resumeQueue as c}from"@stacksjs/queue";var n=a(),t=n.queue;if(!t)s.error("Usage: buddy queue:resume --queue=<name>"),r.exit(1);try{await c(t),s.success(`Resumed queue '${t}'`),r.exit(0)}catch(e){s.error("Failed to resume queue",e),r.exit(1)}function a(){let e={};return r.argv.forEach((u)=>{if(u.startsWith("--")){let[o,i]=u.slice(2).split("=");if(o&&i)e[o]=i}}),e}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { resumeQueue } from "@stacksjs/queue";
4
+ const options = parseArgs(), queue = options.queue;
5
+ if (!queue) {
6
+ log.error("Usage: buddy queue:resume --queue=<name>");
7
+ process.exit(1);
8
+ }
9
+ try {
10
+ await resumeQueue(queue);
11
+ log.success(`Resumed queue '${queue}'`);
12
+ process.exit(0);
13
+ } catch (error) {
14
+ log.error("Failed to resume queue", error);
15
+ process.exit(1);
16
+ }
17
+ function parseArgs() {
18
+ const args = {};
19
+ process.argv.forEach((arg) => {
20
+ if (arg.startsWith("--")) {
21
+ const [key, value] = arg.slice(2).split("=");
22
+ if (key && value)
23
+ args[key] = value;
24
+ }
25
+ });
26
+ return args;
27
+ }
@@ -1,2 +1,41 @@
1
- // @bun
2
- import i from"process";import{log as r}from"@stacksjs/logging";import{executeFailedJobs as n,retryFailedJob as d}from"@stacksjs/queue";var l=f(),a=l.id,u=l.all==="true";try{if(u)r.info("Retrying all failed jobs..."),await n(),r.success("All failed jobs have been queued for retry");else if(a){let e=Number.parseInt(a,10);if(Number.isNaN(e))r.error("Invalid job ID provided"),i.exit(1);r.info(`Retrying failed job ${e}...`),await d(e),r.success(`Failed job ${e} has been queued for retry`)}else r.warn("Please provide a job ID or use --all to retry all failed jobs"),r.info("Usage: buddy queue:retry <id> or buddy queue:retry --all"),i.exit(1);i.exit(0)}catch(e){r.error("Failed to retry job(s)",e),i.exit(1)}function f(){let e={};return i.argv.forEach((t)=>{if(t.startsWith("--")){let[o,s]=t.slice(2).split("=");if(o&&s)e[o]=s;else if(o)e[o]="true"}}),e}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { executeFailedJobs, retryFailedJob } from "@stacksjs/queue";
4
+ const options = parseArgs(), jobId = options.id, all = options.all === "true";
5
+ try {
6
+ if (all) {
7
+ log.info("Retrying all failed jobs...");
8
+ await executeFailedJobs();
9
+ log.success("All failed jobs have been queued for retry");
10
+ } else if (jobId) {
11
+ const id = Number.parseInt(jobId, 10);
12
+ if (Number.isNaN(id)) {
13
+ log.error("Invalid job ID provided");
14
+ process.exit(1);
15
+ }
16
+ log.info(`Retrying failed job ${id}...`);
17
+ await retryFailedJob(id);
18
+ log.success(`Failed job ${id} has been queued for retry`);
19
+ } else {
20
+ log.warn("Please provide a job ID or use --all to retry all failed jobs");
21
+ log.info("Usage: buddy queue:retry <id> or buddy queue:retry --all");
22
+ process.exit(1);
23
+ }
24
+ process.exit(0);
25
+ } catch (error) {
26
+ log.error("Failed to retry job(s)", error);
27
+ process.exit(1);
28
+ }
29
+ function parseArgs() {
30
+ const args = {};
31
+ process.argv.forEach((arg) => {
32
+ if (arg.startsWith("--")) {
33
+ const [key, value] = arg.slice(2).split("=");
34
+ if (key && value)
35
+ args[key] = value;
36
+ else if (key)
37
+ args[key] = "true";
38
+ }
39
+ });
40
+ return args;
41
+ }
@@ -1,5 +1,33 @@
1
- // @bun
2
- import n from"process";import{log as s}from"@stacksjs/logging";import{discoverJobs as d,getScheduledJobs as i}from"@stacksjs/queue";try{s.info(`Discovering scheduled jobs...
3
- `),await d();let o=i();if(o.length===0)s.info("No scheduled jobs found."),s.info('Tip: Add a "rate" or "schedule" property to your job configuration.'),n.exit(0);console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 Job Name \u2502 Schedule \u2502 Queue \u2502 Tries \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");for(let e of o){let l=e.name.substring(0,48).padEnd(48),r=(e.config.rate||e.config.schedule||"N/A").substring(0,21).padEnd(21),t=(e.config.queue||"default").substring(0,9).padEnd(9),c=String(e.config.tries||3).padStart(7);console.log(`\u2502 ${l} \u2502 ${r} \u2502 ${t} \u2502${c} \u2502`)}console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log(`
4
- Total: ${o.length} scheduled job(s)`),console.log(`
5
- Schedule Formats:`),console.log(' \u2022 Cron: "* * * * *" (minute hour day month dayOfWeek)'),console.log(" \u2022 Presets: @hourly, @daily, @weekly, @monthly"),console.log(" \u2022 Every: Every.Minute, Every.Hour, Every.Day"),n.exit(0)}catch(o){s.error("Failed to list scheduled jobs:",o),n.exit(1)}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { discoverJobs, getScheduledJobs } from "@stacksjs/queue";
4
+ try {
5
+ log.info(`Discovering scheduled jobs...
6
+ `);
7
+ await discoverJobs();
8
+ const scheduledJobs = getScheduledJobs();
9
+ if (scheduledJobs.length === 0) {
10
+ log.info("No scheduled jobs found.");
11
+ log.info('Tip: Add a "rate" or "schedule" property to your job configuration.');
12
+ process.exit(0);
13
+ }
14
+ console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
15
+ console.log("\u2502 Job Name \u2502 Schedule \u2502 Queue \u2502 Tries \u2502");
16
+ console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
17
+ for (const job of scheduledJobs) {
18
+ const name = job.name.substring(0, 48).padEnd(48), schedule = (job.config.rate || job.config.schedule || "N/A").substring(0, 21).padEnd(21), queue = (job.config.queue || "default").substring(0, 9).padEnd(9), tries = String(job.config.tries || 3).padStart(7);
19
+ console.log(`\u2502 ${name} \u2502 ${schedule} \u2502 ${queue} \u2502${tries} \u2502`);
20
+ }
21
+ console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
22
+ console.log(`
23
+ Total: ${scheduledJobs.length} scheduled job(s)`);
24
+ console.log(`
25
+ Schedule Formats:`);
26
+ console.log(' \u2022 Cron: "* * * * *" (minute hour day month dayOfWeek)');
27
+ console.log(" \u2022 Presets: @hourly, @daily, @weekly, @monthly");
28
+ console.log(" \u2022 Every: Every.Minute, Every.Hour, Every.Day");
29
+ process.exit(0);
30
+ } catch (error) {
31
+ log.error("Failed to list scheduled jobs:", error);
32
+ process.exit(1);
33
+ }
@@ -1,2 +1,12 @@
1
- // @bun
2
- import e from"process";import{log as r}from"@stacksjs/logging";import{startScheduler as o}from"@stacksjs/queue";r.info("Starting job scheduler...");try{await o(),r.success("Scheduler is running. Press Ctrl+C to stop."),await new Promise(()=>{})}catch(t){r.error("Failed to start scheduler:",t),e.exit(1)}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { startScheduler } from "@stacksjs/queue";
4
+ log.info("Starting job scheduler...");
5
+ try {
6
+ await startScheduler();
7
+ log.success("Scheduler is running. Press Ctrl+C to stop.");
8
+ await new Promise(() => {});
9
+ } catch (error) {
10
+ log.error("Failed to start scheduler:", error);
11
+ process.exit(1);
12
+ }
@@ -1,5 +1,68 @@
1
- // @bun
2
- import H from"process";import{log as V}from"@stacksjs/logging";import{Job as W,FailedJob as X}from"@stacksjs/orm";var h=A(),K=h.queue;try{V.info(`Fetching queue status...
3
- `);let C=K?await W.where("queue",K).get():await W.all(),G=K?await X.where("queue",K).get():await X.all(),B=new Map;for(let x of C){let z=x.queue||"default";if(!B.has(z))B.set(z,{pending:0,processing:0,delayed:0});let I=B.get(z),L=Math.floor(Date.now()/1000);if(x.reserved_at)I.processing++;else if(x.available_at&&Number(x.available_at)>L)I.delayed++;else I.pending++}let E=new Map;for(let x of G){let z=x.queue||"default";E.set(z,(E.get(z)||0)+1)}console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 Queue \u2502 Pending \u2502 Processing \u2502 Delayed \u2502 Failed \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");let M=new Set([...B.keys(),...E.keys()]);if(M.size===0)console.log("\u2502 No queues found \u2502");else for(let x of M){let z=B.get(x)||{pending:0,processing:0,delayed:0},I=E.get(x)||0,L=x.substring(0,48).padEnd(48),Y=String(z.pending).padStart(8),Z=String(z.processing).padStart(10),_=String(z.delayed).padStart(8),$=String(I).padStart(6);console.log(`\u2502 ${L} \u2502${Y} \u2502${Z} \u2502${_} \u2502${$} \u2502`)}console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");let O=Array.from(B.values()).reduce((x,z)=>x+z.pending,0),R=Array.from(B.values()).reduce((x,z)=>x+z.processing,0),T=Array.from(B.values()).reduce((x,z)=>x+z.delayed,0),U=Array.from(E.values()).reduce((x,z)=>x+z,0);console.log(`
4
- Summary:`),console.log(` Pending: ${O}`),console.log(` Processing: ${R}`),console.log(` Delayed: ${T}`),console.log(` Failed: ${U}`),console.log(` Total: ${O+R+T+U}`),H.exit(0)}catch(C){let G=C instanceof Error?C.message:String(C);if(/no such table:\s*(?:jobs|failed_jobs)\b/i.test(G))H.stdout.write(`Queue tables are not set up yet.
5
- `),H.stdout.write("Run `buddy queue:table` to create the migrations, then `buddy migrate` to apply them.\n"),H.exit(0);V.error("Failed to get queue status",C),H.exit(1)}function A(){let C={};return H.argv.forEach((G)=>{if(G.startsWith("--")){let[B,E]=G.slice(2).split("=");if(B&&E)C[B]=E}}),C}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { Job, FailedJob } from "@stacksjs/orm";
4
+ const options = parseArgs(), queueName = options.queue;
5
+ try {
6
+ log.info(`Fetching queue status...
7
+ `);
8
+ const allJobs = queueName ? await Job.where("queue", queueName).get() : await Job.all(), failedJobs = queueName ? await FailedJob.where("queue", queueName).get() : await FailedJob.all(), queueStats = new Map;
9
+ for (const job of allJobs) {
10
+ const queue = job.queue || "default";
11
+ if (!queueStats.has(queue))
12
+ queueStats.set(queue, { pending: 0, processing: 0, delayed: 0 });
13
+ const stats = queueStats.get(queue), now = Math.floor(Date.now() / 1000);
14
+ if (job.reserved_at)
15
+ stats.processing++;
16
+ else if (job.available_at && Number(job.available_at) > now)
17
+ stats.delayed++;
18
+ else
19
+ stats.pending++;
20
+ }
21
+ const failedStats = new Map;
22
+ for (const job of failedJobs) {
23
+ const queue = job.queue || "default";
24
+ failedStats.set(queue, (failedStats.get(queue) || 0) + 1);
25
+ }
26
+ console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
27
+ console.log("\u2502 Queue \u2502 Pending \u2502 Processing \u2502 Delayed \u2502 Failed \u2502");
28
+ console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
29
+ const allQueues = new Set([...queueStats.keys(), ...failedStats.keys()]);
30
+ if (allQueues.size === 0)
31
+ console.log("\u2502 No queues found \u2502");
32
+ else
33
+ for (const queue of allQueues) {
34
+ const stats = queueStats.get(queue) || { pending: 0, processing: 0, delayed: 0 }, failed = failedStats.get(queue) || 0, queueDisplay = queue.substring(0, 48).padEnd(48), pendingDisplay = String(stats.pending).padStart(8), processingDisplay = String(stats.processing).padStart(10), delayedDisplay = String(stats.delayed).padStart(8), failedDisplay = String(failed).padStart(6);
35
+ console.log(`\u2502 ${queueDisplay} \u2502${pendingDisplay} \u2502${processingDisplay} \u2502${delayedDisplay} \u2502${failedDisplay} \u2502`);
36
+ }
37
+ console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
38
+ const totalPending = Array.from(queueStats.values()).reduce((sum, s) => sum + s.pending, 0), totalProcessing = Array.from(queueStats.values()).reduce((sum, s) => sum + s.processing, 0), totalDelayed = Array.from(queueStats.values()).reduce((sum, s) => sum + s.delayed, 0), totalFailed = Array.from(failedStats.values()).reduce((sum, n) => sum + n, 0);
39
+ console.log(`
40
+ Summary:`);
41
+ console.log(` Pending: ${totalPending}`);
42
+ console.log(` Processing: ${totalProcessing}`);
43
+ console.log(` Delayed: ${totalDelayed}`);
44
+ console.log(` Failed: ${totalFailed}`);
45
+ console.log(` Total: ${totalPending + totalProcessing + totalDelayed + totalFailed}`);
46
+ process.exit(0);
47
+ } catch (error) {
48
+ const message = error instanceof Error ? error.message : String(error);
49
+ if (/no such table:\s*(?:jobs|failed_jobs)\b/i.test(message)) {
50
+ process.stdout.write(`Queue tables are not set up yet.
51
+ `);
52
+ process.stdout.write("Run `buddy queue:table` to create the migrations, then `buddy migrate` to apply them.\n");
53
+ process.exit(0);
54
+ }
55
+ log.error("Failed to get queue status", error);
56
+ process.exit(1);
57
+ }
58
+ function parseArgs() {
59
+ const args = {};
60
+ process.argv.forEach((arg) => {
61
+ if (arg.startsWith("--")) {
62
+ const [key, value] = arg.slice(2).split("=");
63
+ if (key && value)
64
+ args[key] = value;
65
+ }
66
+ });
67
+ return args;
68
+ }
@@ -1,2 +1,10 @@
1
- // @bun
2
- import q from"process";import{createJobsMigration as v}from"@stacksjs/database";import{log as w}from"@stacksjs/logging";var m=await v();if(m?.isErr)console.error(m.error),w.error("generateMigrations failed",m.error),q.exit(1);q.exit(0);
1
+ import process from "node:process";
2
+ import { createJobsMigration } from "@stacksjs/database";
3
+ import { log } from "@stacksjs/logging";
4
+ const result = await createJobsMigration();
5
+ if (result?.isErr) {
6
+ console.error(result.error);
7
+ log.error("generateMigrations failed", result.error);
8
+ process.exit(1);
9
+ }
10
+ process.exit(0);
@@ -1,2 +1,27 @@
1
- // @bun
2
- import t from"process";import{log as e}from"@stacksjs/logging";import{unquarantineJob as s}from"@stacksjs/queue";var c=u(),o=c.name;if(!o)e.error("Usage: buddy queue:unquarantine --name=<JobName>"),t.exit(1);try{await s(o),e.success(`Lifted quarantine for ${o}`),t.exit(0)}catch(r){e.error("Failed to unquarantine",r),t.exit(1)}function u(){let r={};return t.argv.forEach((i)=>{if(i.startsWith("--")){let[n,a]=i.slice(2).split("=");if(n&&a)r[n]=a}}),r}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { unquarantineJob } from "@stacksjs/queue";
4
+ const options = parseArgs(), jobName = options.name;
5
+ if (!jobName) {
6
+ log.error("Usage: buddy queue:unquarantine --name=<JobName>");
7
+ process.exit(1);
8
+ }
9
+ try {
10
+ await unquarantineJob(jobName);
11
+ log.success(`Lifted quarantine for ${jobName}`);
12
+ process.exit(0);
13
+ } catch (error) {
14
+ log.error("Failed to unquarantine", error);
15
+ process.exit(1);
16
+ }
17
+ function parseArgs() {
18
+ const args = {};
19
+ process.argv.forEach((arg) => {
20
+ if (arg.startsWith("--")) {
21
+ const [key, value] = arg.slice(2).split("=");
22
+ if (key && value)
23
+ args[key] = value;
24
+ }
25
+ });
26
+ return args;
27
+ }
@@ -1,2 +1,57 @@
1
- // @bun
2
- import m from"process";import{log as x}from"@stacksjs/logging";import{startProcessor as Y,stopProcessor as Z}from"@stacksjs/queue";m.on("unhandledRejection",(b)=>{x.error(`Unhandled Rejection in queue worker: ${b}`)});m.on("uncaughtException",(b)=>{x.error(`Uncaught Exception in queue worker: ${b.message}`)});var F=Number(m.env.STACKS_QUEUE_SHUTDOWN_GRACE_MS)||1e4,J=!1;async function Q(b){if(J)return;J=!0,x.info(`[queue] Worker received ${b}, draining in-flight jobs (max ${F/1000}s)\u2026`),setTimeout(()=>{x.warn("[queue] Drain window exceeded \u2014 forcing worker exit."),m.exit(1)},F+2000).unref();try{await Z({graceMs:F})}catch(z){x.error("[queue] Error while draining worker on shutdown:",z)}m.exit(0)}m.on("SIGTERM",()=>{Q("SIGTERM")});m.on("SIGINT",()=>{Q("SIGINT")});var V=K(),$=V.queue,X=Number(V.concurrency)||1;x.info(`Starting queue worker with ${X} concurrent worker(s)...`);var L=await Y($,{concurrency:X});if(L.isErr)x.error("Failed to start queue worker:",L.error),m.exit(1);x.success("Queue worker started successfully!");await new Promise(()=>{});function K(){let b={};return m.argv.forEach((z)=>{if(z.startsWith("--")){let[B,I]=z.slice(2).split("=");if(B&&I)b[B]=I;else if(B)b[B]="true"}}),b}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { startProcessor, stopProcessor } from "@stacksjs/queue";
4
+ process.on("unhandledRejection", (reason) => {
5
+ log.error(`Unhandled Rejection in queue worker: ${reason}`);
6
+ });
7
+ process.on("uncaughtException", (error) => {
8
+ log.error(`Uncaught Exception in queue worker: ${error.message}`);
9
+ });
10
+ const SHUTDOWN_GRACE_MS = Number(process.env.STACKS_QUEUE_SHUTDOWN_GRACE_MS) || 1e4;
11
+ let shuttingDown = !1;
12
+ async function gracefulShutdown(signal) {
13
+ if (shuttingDown)
14
+ return;
15
+ shuttingDown = !0;
16
+ log.info(`[queue] Worker received ${signal}, draining in-flight jobs (max ${SHUTDOWN_GRACE_MS / 1000}s)\u2026`);
17
+ setTimeout(() => {
18
+ log.warn("[queue] Drain window exceeded \u2014 forcing worker exit.");
19
+ process.exit(1);
20
+ }, SHUTDOWN_GRACE_MS + 2000).unref();
21
+ try {
22
+ await stopProcessor({ graceMs: SHUTDOWN_GRACE_MS });
23
+ } catch (error) {
24
+ log.error("[queue] Error while draining worker on shutdown:", error);
25
+ }
26
+ process.exit(0);
27
+ }
28
+ process.on("SIGTERM", () => {
29
+ gracefulShutdown("SIGTERM");
30
+ });
31
+ process.on("SIGINT", () => {
32
+ gracefulShutdown("SIGINT");
33
+ });
34
+ const options = parseArgs(), queue = options.queue, concurrency = Number(options.concurrency) || 1;
35
+ log.info(`Starting queue worker with ${concurrency} concurrent worker(s)...`);
36
+ const result = await startProcessor(queue, {
37
+ concurrency
38
+ });
39
+ if (result.isErr) {
40
+ log.error("Failed to start queue worker:", result.error);
41
+ process.exit(1);
42
+ }
43
+ log.success("Queue worker started successfully!");
44
+ await new Promise(() => {});
45
+ function parseArgs() {
46
+ const args = {};
47
+ process.argv.forEach((arg) => {
48
+ if (arg.startsWith("--")) {
49
+ const [key, value] = arg.slice(2).split("=");
50
+ if (key && value)
51
+ args[key] = value;
52
+ else if (key)
53
+ args[key] = "true";
54
+ }
55
+ });
56
+ return args;
57
+ }
package/dist/release.js CHANGED
@@ -1,3 +1,21 @@
1
- #!/usr/bin/env bun
2
- // @bun
3
- import"./chunk-0c8sd1t6.js";import"./chunk-cdk2r2jd.js";import"./chunk-n5eqwhck.js";import"./chunk-62gdfav8.js";import"./chunk-78c5n3s2.js";import"./chunk-tpb8jgsk.js";import"./chunk-tsbk5vne.js";import"./chunk-s735m9mg.js";import"./chunk-6bk53y02.js";import{Jb as C}from"./chunk-0gadhvn7.js";import"./chunk-h3d81wrg.js";import{parseOptions as G}from"@stacksjs/cli";import{app as H}from"@stacksjs/config";import{Action as q}from"@stacksjs/enums";import{log as E}from"@stacksjs/logging";import{projectPath as I}from"@stacksjs/path";var J=G()??{},z={};for(let[B,F]of Object.entries(J)){if(B==="--"||B==="_")continue;z[B]=F}var K=z.dryRun===!0||z.dryRun==="true",L=K?[q.GenerateLibraryEntries,q.Bump]:[q.GenerateLibraryEntries,q.LintFix,q.Bump],x=await C(L,{cwd:I(),...z});if(x&&x.isErr)E.error(`Release failed: ${x.error?.message??String(x.error)}`),process.exit(1);E.success(`Successfully released ${H.name}`);
1
+ import { parseOptions } from "@stacksjs/cli";
2
+ import { app } from "@stacksjs/config";
3
+ import { Action } from "@stacksjs/enums";
4
+ import { log } from "@stacksjs/logging";
5
+ import { projectPath } from "@stacksjs/path";
6
+ import { runActions } from ".";
7
+ const raw = parseOptions() ?? {}, passthrough = {};
8
+ for (const [k, v] of Object.entries(raw)) {
9
+ if (k === "--" || k === "_")
10
+ continue;
11
+ passthrough[k] = v;
12
+ }
13
+ const isDryRun = passthrough.dryRun === !0 || passthrough.dryRun === "true", actions = isDryRun ? [Action.GenerateLibraryEntries, Action.Bump] : [Action.GenerateLibraryEntries, Action.LintFix, Action.Bump], result = await runActions(actions, {
14
+ cwd: projectPath(),
15
+ ...passthrough
16
+ });
17
+ if (result && result.isErr) {
18
+ log.error(`Release failed: ${result.error?.message ?? String(result.error)}`);
19
+ process.exit(1);
20
+ }
21
+ log.success(`Successfully released ${app.name}`);