@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
package/dist/orm/base.js CHANGED
@@ -1,2 +0,0 @@
1
- // @bun
2
- import"../chunk-h3d81wrg.js";var c=void 0;export{c as default};
package/dist/orm/test.js CHANGED
@@ -1 +0,0 @@
1
- // @bun
@@ -1,2 +1,16 @@
1
- // @bun
2
- import z from"process";import{NpmScript as A}from"@stacksjs/enums";import{log as q}from"@stacksjs/logging";import{runtimePath as B}from"@stacksjs/path";import{ExitCode as D}from"@stacksjs/types";import{runNpmScript as F}from"@stacksjs/utils";q.info("Running prepublish command...");var v=await F(A.BuildStacks,{verbose:!0,cwd:B()});if(v.isErr)q.error(Error("There was an error while prepublishing your stack"),v.error),z.exit(D.FatalError);q.success("Prepublishing completed");
1
+ import process from "node:process";
2
+ import { NpmScript } from "@stacksjs/enums";
3
+ import { log } from "@stacksjs/logging";
4
+ import { runtimePath } from "@stacksjs/path";
5
+ import { ExitCode } from "@stacksjs/types";
6
+ import { runNpmScript } from "@stacksjs/utils";
7
+ log.info("Running prepublish command...");
8
+ const result = await runNpmScript(NpmScript.BuildStacks, {
9
+ verbose: !0,
10
+ cwd: runtimePath()
11
+ });
12
+ if (result.isErr) {
13
+ log.error(Error("There was an error while prepublishing your stack"), result.error);
14
+ process.exit(ExitCode.FatalError);
15
+ }
16
+ log.success("Prepublishing completed");
@@ -1,2 +1,42 @@
1
- // @bun
2
- import s from"process";import{log as r}from"@stacksjs/logging";import{Job as a}from"@stacksjs/orm";var n=c(),i=n.queue,f=n.force==="true";try{if(!f)r.warn("This will delete all jobs from the queue. Use --force to confirm."),s.exit(1);let e=0;if(i){r.info(`Clearing all jobs from queue "${i}"...`);let o=await a.where("queue",i).get();e=o.length;for(let t of o)await t.delete()}else{r.info("Clearing all jobs from all queues...");let o=await a.all();e=o.length;for(let t of o)await t.delete()}r.success(`Cleared ${e} job(s)`),s.exit(0)}catch(e){r.error("Failed to clear jobs",e),s.exit(1)}function c(){let e={};return s.argv.forEach((o)=>{if(o.startsWith("--")){let[t,l]=o.slice(2).split("=");if(t&&l)e[t]=l;else if(t)e[t]="true"}}),e}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { Job } from "@stacksjs/orm";
4
+ const options = parseArgs(), queueName = options.queue, force = options.force === "true";
5
+ try {
6
+ if (!force) {
7
+ log.warn("This will delete all jobs from the queue. Use --force to confirm.");
8
+ process.exit(1);
9
+ }
10
+ let deletedCount = 0;
11
+ if (queueName) {
12
+ log.info(`Clearing all jobs from queue "${queueName}"...`);
13
+ const jobs = await Job.where("queue", queueName).get();
14
+ deletedCount = jobs.length;
15
+ for (const job of jobs)
16
+ await job.delete();
17
+ } else {
18
+ log.info("Clearing all jobs from all queues...");
19
+ const jobs = await Job.all();
20
+ deletedCount = jobs.length;
21
+ for (const job of jobs)
22
+ await job.delete();
23
+ }
24
+ log.success(`Cleared ${deletedCount} job(s)`);
25
+ process.exit(0);
26
+ } catch (error) {
27
+ log.error("Failed to clear jobs", error);
28
+ process.exit(1);
29
+ }
30
+ function parseArgs() {
31
+ const args = {};
32
+ process.argv.forEach((arg) => {
33
+ if (arg.startsWith("--")) {
34
+ const [key, value] = arg.slice(2).split("=");
35
+ if (key && value)
36
+ args[key] = value;
37
+ else if (key)
38
+ args[key] = "true";
39
+ }
40
+ });
41
+ return args;
42
+ }
@@ -1,2 +1,28 @@
1
- // @bun
2
- import s from"process";import{log as t}from"@stacksjs/logging";import{purgeDeadLetterJobs as i}from"@stacksjs/queue";var e=l(),o=e.olderThanDays?Number.parseInt(e.olderThanDays,10):e["older-than-days"]?Number.parseInt(e["older-than-days"],10):30;if(!Number.isFinite(o)||o<1)t.error(`Invalid --older-than-days value '${e.olderThanDays??e["older-than-days"]}'`),s.exit(1);try{t.info(`Pruning dead-letter rows older than ${o} day(s)...`);let r=await i(o);t.success(`Deleted ${r} dead-letter row(s)`),s.exit(0)}catch(r){t.error("Failed to purge dead-letter jobs",r),s.exit(1)}function l(){let r={};return s.argv.forEach((a)=>{if(a.startsWith("--")){let[d,n]=a.slice(2).split("=");if(d&&n)r[d]=n}}),r}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { purgeDeadLetterJobs } from "@stacksjs/queue";
4
+ const options = parseArgs(), days = options.olderThanDays ? Number.parseInt(options.olderThanDays, 10) : options["older-than-days"] ? Number.parseInt(options["older-than-days"], 10) : 30;
5
+ if (!Number.isFinite(days) || days < 1) {
6
+ log.error(`Invalid --older-than-days value '${options.olderThanDays ?? options["older-than-days"]}'`);
7
+ process.exit(1);
8
+ }
9
+ try {
10
+ log.info(`Pruning dead-letter rows older than ${days} day(s)...`);
11
+ const deleted = await purgeDeadLetterJobs(days);
12
+ log.success(`Deleted ${deleted} dead-letter row(s)`);
13
+ process.exit(0);
14
+ } catch (error) {
15
+ log.error("Failed to purge dead-letter jobs", 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,2 +1,35 @@
1
- // @bun
2
- import r from"process";import{log as t}from"@stacksjs/logging";import{retryDeadLetterJob as a}from"@stacksjs/queue";var c=u(),n=c.id;if(!n)t.error("Usage: buddy queue:dlq:retry --id=<id>"),r.exit(1);var o=Number.parseInt(n,10);if(Number.isNaN(o))t.error("Invalid id provided"),r.exit(1);try{if(!await a(o))t.error(`Dead-letter job ${o} not found (or DLQ table missing)`),r.exit(1);t.success(`Re-enqueued dead-letter job ${o}`),r.exit(0)}catch(e){t.error("Failed to re-enqueue dead-letter job",e),r.exit(1)}function u(){let e={};return r.argv.forEach((i)=>{if(i.startsWith("--")){let[s,d]=i.slice(2).split("=");if(s&&d)e[s]=d}}),e}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { retryDeadLetterJob } from "@stacksjs/queue";
4
+ const options = parseArgs(), idArg = options.id;
5
+ if (!idArg) {
6
+ log.error("Usage: buddy queue:dlq:retry --id=<id>");
7
+ process.exit(1);
8
+ }
9
+ const id = Number.parseInt(idArg, 10);
10
+ if (Number.isNaN(id)) {
11
+ log.error("Invalid id provided");
12
+ process.exit(1);
13
+ }
14
+ try {
15
+ if (!await retryDeadLetterJob(id)) {
16
+ log.error(`Dead-letter job ${id} not found (or DLQ table missing)`);
17
+ process.exit(1);
18
+ }
19
+ log.success(`Re-enqueued dead-letter job ${id}`);
20
+ process.exit(0);
21
+ } catch (error) {
22
+ log.error("Failed to re-enqueue dead-letter job", error);
23
+ process.exit(1);
24
+ }
25
+ function parseArgs() {
26
+ const args = {};
27
+ process.argv.forEach((arg) => {
28
+ if (arg.startsWith("--")) {
29
+ const [key, value] = arg.slice(2).split("=");
30
+ if (key && value)
31
+ args[key] = value;
32
+ }
33
+ });
34
+ return args;
35
+ }
package/dist/queue/dlq.js CHANGED
@@ -1,5 +1,55 @@
1
- // @bun
2
- import E from"process";import{log as H}from"@stacksjs/logging";import{listDeadLetterJobs as R}from"@stacksjs/queue";var G=W(),T=G.queue||void 0,U=G.reason||void 0,I=G.since,V=G.limit?Number.parseInt(G.limit,10):100;try{H.info(`Fetching dead-letter jobs...
3
- `);let B=I?X(I)??void 0:void 0,x=await R({queue:T,reason:U,sinceCutoffMs:B,limit:V});if(x.length===0)console.log("\u2713 No dead-letter jobs found"),E.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 Queue \u2502 Reason \u2502 Failures \u2502 Dead-Lettered 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 z of x){let F=String(z.id).padEnd(3),K=(z.queue||"default").substring(0,32).padEnd(32),O=(z.reason||"unknown").substring(0,16).padEnd(16),P=String(z.total_failures??1).padEnd(8),Q=(z.dead_lettered_at||"N/A").substring(0,24).padEnd(24);console.log(`\u2502 ${F} \u2502 ${K} \u2502 ${O} \u2502 ${P} \u2502 ${Q} \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(`
4
- Showing ${x.length} dead-letter job(s)`),E.exit(0)}catch(B){let x=B instanceof Error?B.message:String(B);if(/no such table:\s*dead_letter_jobs\b/i.test(x))E.stdout.write(`Dead-letter queue table is not set up yet.
5
- `),E.stdout.write("Run `buddy queue:table` to create the migrations, then `buddy migrate` to apply them.\n"),E.exit(0);H.error("Failed to fetch dead-letter jobs",B),E.exit(1)}function W(){let B={};return E.argv.forEach((x)=>{if(x.startsWith("--")){let[z,F]=x.slice(2).split("=");if(z&&F)B[z]=F}}),B}function X(B){let x=/^(\d+)([smhd])$/.exec(B.trim());if(!x)return null;let z=Number(x[1]);if(!Number.isFinite(z)||z<=0)return null;let F=x[2]==="s"?1000:x[2]==="m"?60000:x[2]==="h"?3600000:86400000;return Date.now()-z*F}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { listDeadLetterJobs } from "@stacksjs/queue";
4
+ const options = parseArgs(), queueName = options.queue || void 0, reason = options.reason || void 0, sinceArg = options.since, limit = options.limit ? Number.parseInt(options.limit, 10) : 100;
5
+ try {
6
+ log.info(`Fetching dead-letter jobs...
7
+ `);
8
+ const sinceCutoffMs = sinceArg ? parseSinceDuration(sinceArg) ?? void 0 : void 0, rows = await listDeadLetterJobs({ queue: queueName, reason, sinceCutoffMs, limit });
9
+ if (rows.length === 0) {
10
+ console.log("\u2713 No dead-letter jobs found");
11
+ process.exit(0);
12
+ }
13
+ 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");
14
+ console.log("\u2502 ID \u2502 Queue \u2502 Reason \u2502 Failures \u2502 Dead-Lettered At \u2502");
15
+ 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");
16
+ for (const row of rows) {
17
+ const id = String(row.id).padEnd(3), q = (row.queue || "default").substring(0, 32).padEnd(32), r = (row.reason || "unknown").substring(0, 16).padEnd(16), f = String(row.total_failures ?? 1).padEnd(8), dt = (row.dead_lettered_at || "N/A").substring(0, 24).padEnd(24);
18
+ console.log(`\u2502 ${id} \u2502 ${q} \u2502 ${r} \u2502 ${f} \u2502 ${dt} \u2502`);
19
+ }
20
+ 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");
21
+ console.log(`
22
+ Showing ${rows.length} dead-letter job(s)`);
23
+ process.exit(0);
24
+ } catch (error) {
25
+ const message = error instanceof Error ? error.message : String(error);
26
+ if (/no such table:\s*dead_letter_jobs\b/i.test(message)) {
27
+ process.stdout.write(`Dead-letter queue table is not set up yet.
28
+ `);
29
+ process.stdout.write("Run `buddy queue:table` to create the migrations, then `buddy migrate` to apply them.\n");
30
+ process.exit(0);
31
+ }
32
+ log.error("Failed to fetch dead-letter jobs", error);
33
+ process.exit(1);
34
+ }
35
+ function parseArgs() {
36
+ const args = {};
37
+ process.argv.forEach((arg) => {
38
+ if (arg.startsWith("--")) {
39
+ const [key, value] = arg.slice(2).split("=");
40
+ if (key && value)
41
+ args[key] = value;
42
+ }
43
+ });
44
+ return args;
45
+ }
46
+ function parseSinceDuration(input) {
47
+ const m = /^(\d+)([smhd])$/.exec(input.trim());
48
+ if (!m)
49
+ return null;
50
+ const n = Number(m[1]);
51
+ if (!Number.isFinite(n) || n <= 0)
52
+ return null;
53
+ const mult = m[2] === "s" ? 1000 : m[2] === "m" ? 60000 : m[2] === "h" ? 3600000 : 86400000;
54
+ return Date.now() - n * mult;
55
+ }
@@ -1,5 +1,69 @@
1
- // @bun
2
- import G from"process";import{log as L}from"@stacksjs/logging";import{FailedJob as M}from"@stacksjs/orm";var T=W(),O=T.queue,K=T.since,I=K?X(K):null;try{L.info(`Fetching failed jobs...
3
- `);let B;if(O)B=await M.where("queue",O).get();else B=await M.all();if(I)B=B.filter((z)=>{if(!z.failed_at)return!1;let E=Date.parse(z.failed_at);return Number.isFinite(E)&&E>=I});if(B.length===0){if(I)console.log(`\u2713 No failed jobs found since ${K}`);else console.log("\u2713 No failed jobs found");G.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\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\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 Queue \u2502 Failed At \u2502 Exception \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\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\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 z of B){let E=String(z.id).padEnd(3),H=(z.queue||"default").substring(0,48).padEnd(48),U=(z.failed_at||"N/A").substring(0,21).padEnd(21),V=(z.exception||"Unknown error").substring(0,31).padEnd(31);console.log(`\u2502 ${E} \u2502 ${H} \u2502 ${U} \u2502 ${V} \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\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\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(`
4
- Total: ${B.length} failed job(s)`),G.exit(0)}catch(B){let z=B instanceof Error?B.message:String(B);if(/no such table:\s*(?:jobs|failed_jobs)\b/i.test(z))G.stdout.write(`Queue tables are not set up yet.
5
- `),G.stdout.write("Run `buddy queue:table` to create the migrations, then `buddy migrate` to apply them.\n"),G.exit(0);L.error("Failed to fetch failed jobs",B),G.exit(1)}function W(){let B={};return G.argv.forEach((z)=>{if(z.startsWith("--")){let[E,H]=z.slice(2).split("=");if(E&&H)B[E]=H}}),B}function X(B){let z=/^(\d+)([smhd])$/.exec(B.trim());if(!z)return null;let E=Number(z[1]);if(!Number.isFinite(E)||E<=0)return null;let H=z[2]==="s"?1000:z[2]==="m"?60000:z[2]==="h"?3600000:86400000;return Date.now()-E*H}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { FailedJob } from "@stacksjs/orm";
4
+ const options = parseArgs(), queueName = options.queue, sinceArg = options.since, sinceCutoff = sinceArg ? parseSinceDuration(sinceArg) : null;
5
+ try {
6
+ log.info(`Fetching failed jobs...
7
+ `);
8
+ let failedJobs;
9
+ if (queueName)
10
+ failedJobs = await FailedJob.where("queue", queueName).get();
11
+ else
12
+ failedJobs = await FailedJob.all();
13
+ if (sinceCutoff)
14
+ failedJobs = failedJobs.filter((j) => {
15
+ if (!j.failed_at)
16
+ return !1;
17
+ const ts = Date.parse(j.failed_at);
18
+ return Number.isFinite(ts) && ts >= sinceCutoff;
19
+ });
20
+ if (failedJobs.length === 0) {
21
+ if (sinceCutoff)
22
+ console.log(`\u2713 No failed jobs found since ${sinceArg}`);
23
+ else
24
+ console.log("\u2713 No failed jobs found");
25
+ process.exit(0);
26
+ }
27
+ 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\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
28
+ console.log("\u2502 ID \u2502 Queue \u2502 Failed At \u2502 Exception \u2502");
29
+ 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\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
30
+ for (const job of failedJobs) {
31
+ const id = String(job.id).padEnd(3), queue = (job.queue || "default").substring(0, 48).padEnd(48), failedAt = (job.failed_at || "N/A").substring(0, 21).padEnd(21), exception = (job.exception || "Unknown error").substring(0, 31).padEnd(31);
32
+ console.log(`\u2502 ${id} \u2502 ${queue} \u2502 ${failedAt} \u2502 ${exception} \u2502`);
33
+ }
34
+ 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\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
35
+ console.log(`
36
+ Total: ${failedJobs.length} failed job(s)`);
37
+ process.exit(0);
38
+ } catch (error) {
39
+ const message = error instanceof Error ? error.message : String(error);
40
+ if (/no such table:\s*(?:jobs|failed_jobs)\b/i.test(message)) {
41
+ process.stdout.write(`Queue tables are not set up yet.
42
+ `);
43
+ process.stdout.write("Run `buddy queue:table` to create the migrations, then `buddy migrate` to apply them.\n");
44
+ process.exit(0);
45
+ }
46
+ log.error("Failed to fetch failed jobs", error);
47
+ process.exit(1);
48
+ }
49
+ function parseArgs() {
50
+ const args = {};
51
+ process.argv.forEach((arg) => {
52
+ if (arg.startsWith("--")) {
53
+ const [key, value] = arg.slice(2).split("=");
54
+ if (key && value)
55
+ args[key] = value;
56
+ }
57
+ });
58
+ return args;
59
+ }
60
+ function parseSinceDuration(input) {
61
+ const m = /^(\d+)([smhd])$/.exec(input.trim());
62
+ if (!m)
63
+ return null;
64
+ const n = Number(m[1]);
65
+ if (!Number.isFinite(n) || n <= 0)
66
+ return null;
67
+ const mult = m[2] === "s" ? 1000 : m[2] === "m" ? 60000 : m[2] === "h" ? 3600000 : 86400000;
68
+ return Date.now() - n * mult;
69
+ }
@@ -1,3 +1,49 @@
1
- // @bun
2
- import s from"process";import{log as i}from"@stacksjs/logging";import{FailedJob as l}from"@stacksjs/orm";var n=f(),r=n.queue,u=n.force==="true";try{if(!u)i.warn("This will permanently delete all failed jobs. Use --force to confirm."),s.exit(1);let e=0;if(r){i.info(`Flushing all failed jobs from queue "${r}"...`);let t=await l.where("queue",r).get();e=t.length;for(let o of t)await o.delete()}else{i.info("Flushing all failed jobs from all queues...");let t=await l.all();e=t.length;for(let o of t)await o.delete()}i.success(`Flushed ${e} failed job(s)`),s.exit(0)}catch(e){let t=e instanceof Error?e.message:String(e);if(/no such table:\s*(?:jobs|failed_jobs)\b/i.test(t))s.stdout.write(`Queue tables are not set up yet.
3
- `),s.stdout.write("Run `buddy queue:table` to create the migrations, then `buddy migrate` to apply them.\n"),s.exit(0);i.error("Failed to flush failed jobs",e),s.exit(1)}function f(){let e={};return s.argv.forEach((t)=>{if(t.startsWith("--")){let[o,a]=t.slice(2).split("=");if(o&&a)e[o]=a;else if(o)e[o]="true"}}),e}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { FailedJob } from "@stacksjs/orm";
4
+ const options = parseArgs(), queueName = options.queue, force = options.force === "true";
5
+ try {
6
+ if (!force) {
7
+ log.warn("This will permanently delete all failed jobs. Use --force to confirm.");
8
+ process.exit(1);
9
+ }
10
+ let deletedCount = 0;
11
+ if (queueName) {
12
+ log.info(`Flushing all failed jobs from queue "${queueName}"...`);
13
+ const failedJobs = await FailedJob.where("queue", queueName).get();
14
+ deletedCount = failedJobs.length;
15
+ for (const job of failedJobs)
16
+ await job.delete();
17
+ } else {
18
+ log.info("Flushing all failed jobs from all queues...");
19
+ const failedJobs = await FailedJob.all();
20
+ deletedCount = failedJobs.length;
21
+ for (const job of failedJobs)
22
+ await job.delete();
23
+ }
24
+ log.success(`Flushed ${deletedCount} failed job(s)`);
25
+ process.exit(0);
26
+ } catch (error) {
27
+ const message = error instanceof Error ? error.message : String(error);
28
+ if (/no such table:\s*(?:jobs|failed_jobs)\b/i.test(message)) {
29
+ process.stdout.write(`Queue tables are not set up yet.
30
+ `);
31
+ process.stdout.write("Run `buddy queue:table` to create the migrations, then `buddy migrate` to apply them.\n");
32
+ process.exit(0);
33
+ }
34
+ log.error("Failed to flush failed jobs", error);
35
+ process.exit(1);
36
+ }
37
+ function parseArgs() {
38
+ const args = {};
39
+ process.argv.forEach((arg) => {
40
+ if (arg.startsWith("--")) {
41
+ const [key, value] = arg.slice(2).split("=");
42
+ if (key && value)
43
+ args[key] = value;
44
+ else if (key)
45
+ args[key] = "true";
46
+ }
47
+ });
48
+ return args;
49
+ }
@@ -1,8 +1,154 @@
1
- // @bun
2
- import N from"process";import{log as M}from"@stacksjs/logging";import{Job as S,FailedJob as U}from"@stacksjs/orm";var P=W(),O=P.id,V=P.failed==="true";try{if(!O)M.error("Please provide a job ID"),M.info("Usage: buddy queue:inspect --id=<jobId> [--failed]"),N.exit(1);let z=Number.parseInt(O,10);if(Number.isNaN(z))M.error("Invalid job ID provided"),N.exit(1);if(V){let B=await U.find(z);if(!B)M.error(`Failed job with ID ${z} not found`),N.exit(1);let h=B;console.log(`
3
- \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 Failed Job Details \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 ID: ${String(h.id).padEnd(52)} \u2502`),console.log(`\u2502 Queue: ${(h.queue||"default").padEnd(52)} \u2502`),console.log(`\u2502 Connection: ${(h.connection||"database").padEnd(52)} \u2502`),console.log(`\u2502 Failed At: ${(h.failed_at||"N/A").padEnd(52)} \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 Exception: \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");let E=h.exception||"Unknown error",G=E.match(/.{1,62}/g)||[E];for(let q of G.slice(0,20))console.log(`\u2502 ${q.padEnd(62)} \u2502`);if(G.length>20)console.log(`\u2502 ... (${G.length-20} more lines)`.padEnd(64)+" \u2502");if(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 Payload: \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"),h.payload)try{let q=JSON.parse(h.payload);console.log(`\u2502 Name: ${q.name.padEnd(52)} \u2502`),console.log(`\u2502 Path: ${q.path.padEnd(52)} \u2502`),console.log(`\u2502 Max Tries: ${String(q.maxTries).padEnd(52)} \u2502`),console.log("\u2502 Parameters: \u2502");let K=JSON.stringify(q.params,null,2).split(`
4
- `);for(let H of K.slice(0,15))console.log(`\u2502 ${H.substring(0,60).padEnd(60)} \u2502`);if(K.length>15)console.log(`\u2502 ... (${K.length-15} more lines)`.padEnd(64)+" \u2502")}catch{console.log(`\u2502 Raw: ${h.payload.substring(0,58).padEnd(58)} \u2502`)}else console.log("\u2502 (No payload) \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"),console.log(`
5
- Actions:`),console.log(` Retry this job: buddy queue:retry --id=${z}`),console.log(` Delete this job: buddy queue:flush --id=${z}`)}else{let B=await S.find(z);if(!B)M.error(`Job with ID ${z} not found`),M.info("Tip: Use --failed flag to inspect failed jobs"),N.exit(1);let h=B,E=Math.floor(Date.now()/1000),G="Pending";if(h.reserved_at)G="Processing";else if(h.available_at&&h.available_at>E)G="Delayed";if(console.log(`
6
- \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 Job Details \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 ID: ${String(h.id).padEnd(50)} \u2502`),console.log(`\u2502 Queue: ${(h.queue||"default").padEnd(50)} \u2502`),console.log(`\u2502 Status: ${G.padEnd(50)} \u2502`),console.log(`\u2502 Attempts: ${String(h.attempts||0).padEnd(50)} \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"),h.available_at){let q=new Date(h.available_at*1000);console.log(`\u2502 Available At: ${q.toISOString().padEnd(50)} \u2502`)}if(h.reserved_at){let q=new Date(h.reserved_at*1000);console.log(`\u2502 Reserved At: ${q.toISOString().padEnd(50)} \u2502`)}if(h.created_at)console.log(`\u2502 Created At: ${String(h.created_at).padEnd(50)} \u2502`);if(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 Payload: \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"),h.payload)try{let q=JSON.parse(h.payload);console.log(`\u2502 Name: ${q.name.padEnd(52)} \u2502`),console.log(`\u2502 Path: ${q.path.padEnd(52)} \u2502`),console.log(`\u2502 Max Tries: ${String(q.maxTries).padEnd(52)} \u2502`),console.log(`\u2502 Timeout: ${String(q.timeOut||"N/A").padEnd(52)} \u2502`),console.log("\u2502 Parameters: \u2502");let K=JSON.stringify(q.params,null,2).split(`
7
- `);for(let H of K.slice(0,15))console.log(`\u2502 ${H.substring(0,60).padEnd(60)} \u2502`);if(K.length>15)console.log(`\u2502 ... (${K.length-15} more lines)`.padEnd(64)+" \u2502");if(q.classPayload)try{let H=JSON.parse(q.classPayload);if(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 Job Configuration: \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 Tries: ${String(H.tries||3).padEnd(52)} \u2502`),console.log(`\u2502 Timeout: ${String(H.timeout||60).padEnd(52)} \u2502`),H.backoff)console.log(`\u2502 Backoff: ${String(JSON.stringify(H.backoff)).substring(0,52).padEnd(52)} \u2502`)}catch{}}catch{console.log(`\u2502 Raw: ${h.payload.substring(0,58).padEnd(58)} \u2502`)}else console.log("\u2502 (No payload) \u2502");if(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"),G==="Delayed"&&h.available_at){let q=h.available_at-E;console.log(`
8
- This job will be available in ${q} second(s)`)}}N.exit(0)}catch(z){M.error("Failed to inspect job",z),N.exit(1)}function W(){let z={};return N.argv.forEach((B)=>{if(B.startsWith("--")){let[h,E]=B.slice(2).split("=");if(h&&E)z[h]=E;else if(h)z[h]="true"}}),z}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { Job, FailedJob } from "@stacksjs/orm";
4
+ const options = parseArgs(), jobId = options.id, failedFlag = options.failed === "true";
5
+ try {
6
+ if (!jobId) {
7
+ log.error("Please provide a job ID");
8
+ log.info("Usage: buddy queue:inspect --id=<jobId> [--failed]");
9
+ process.exit(1);
10
+ }
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
+ if (failedFlag) {
17
+ const failedResult = await FailedJob.find(id);
18
+ if (!failedResult) {
19
+ log.error(`Failed job with ID ${id} not found`);
20
+ process.exit(1);
21
+ }
22
+ const job = failedResult;
23
+ console.log(`
24
+ \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`);
25
+ console.log("\u2502 Failed Job Details \u2502");
26
+ 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");
27
+ console.log(`\u2502 ID: ${String(job.id).padEnd(52)} \u2502`);
28
+ console.log(`\u2502 Queue: ${(job.queue || "default").padEnd(52)} \u2502`);
29
+ console.log(`\u2502 Connection: ${(job.connection || "database").padEnd(52)} \u2502`);
30
+ console.log(`\u2502 Failed At: ${(job.failed_at || "N/A").padEnd(52)} \u2502`);
31
+ 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");
32
+ console.log("\u2502 Exception: \u2502");
33
+ 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");
34
+ const exception = job.exception || "Unknown error", lines = exception.match(/.{1,62}/g) || [exception];
35
+ for (const line of lines.slice(0, 20))
36
+ console.log(`\u2502 ${line.padEnd(62)} \u2502`);
37
+ if (lines.length > 20)
38
+ console.log(`\u2502 ... (${lines.length - 20} more lines)`.padEnd(64) + " \u2502");
39
+ 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");
40
+ console.log("\u2502 Payload: \u2502");
41
+ 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");
42
+ if (job.payload)
43
+ try {
44
+ const payload = JSON.parse(job.payload);
45
+ console.log(`\u2502 Name: ${payload.name.padEnd(52)} \u2502`);
46
+ console.log(`\u2502 Path: ${payload.path.padEnd(52)} \u2502`);
47
+ console.log(`\u2502 Max Tries: ${String(payload.maxTries).padEnd(52)} \u2502`);
48
+ console.log("\u2502 Parameters: \u2502");
49
+ const paramLines = JSON.stringify(payload.params, null, 2).split(`
50
+ `);
51
+ for (const line of paramLines.slice(0, 15))
52
+ console.log(`\u2502 ${line.substring(0, 60).padEnd(60)} \u2502`);
53
+ if (paramLines.length > 15)
54
+ console.log(`\u2502 ... (${paramLines.length - 15} more lines)`.padEnd(64) + " \u2502");
55
+ } catch {
56
+ console.log(`\u2502 Raw: ${job.payload.substring(0, 58).padEnd(58)} \u2502`);
57
+ }
58
+ else
59
+ console.log("\u2502 (No payload) \u2502");
60
+ 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");
61
+ console.log(`
62
+ Actions:`);
63
+ console.log(` Retry this job: buddy queue:retry --id=${id}`);
64
+ console.log(` Delete this job: buddy queue:flush --id=${id}`);
65
+ } else {
66
+ const jobResult = await Job.find(id);
67
+ if (!jobResult) {
68
+ log.error(`Job with ID ${id} not found`);
69
+ log.info("Tip: Use --failed flag to inspect failed jobs");
70
+ process.exit(1);
71
+ }
72
+ const job = jobResult, now = Math.floor(Date.now() / 1000);
73
+ let status = "Pending";
74
+ if (job.reserved_at)
75
+ status = "Processing";
76
+ else if (job.available_at && job.available_at > now)
77
+ status = "Delayed";
78
+ console.log(`
79
+ \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`);
80
+ console.log("\u2502 Job Details \u2502");
81
+ 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");
82
+ console.log(`\u2502 ID: ${String(job.id).padEnd(50)} \u2502`);
83
+ console.log(`\u2502 Queue: ${(job.queue || "default").padEnd(50)} \u2502`);
84
+ console.log(`\u2502 Status: ${status.padEnd(50)} \u2502`);
85
+ console.log(`\u2502 Attempts: ${String(job.attempts || 0).padEnd(50)} \u2502`);
86
+ 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");
87
+ if (job.available_at) {
88
+ const availableDate = new Date(job.available_at * 1000);
89
+ console.log(`\u2502 Available At: ${availableDate.toISOString().padEnd(50)} \u2502`);
90
+ }
91
+ if (job.reserved_at) {
92
+ const reservedDate = new Date(job.reserved_at * 1000);
93
+ console.log(`\u2502 Reserved At: ${reservedDate.toISOString().padEnd(50)} \u2502`);
94
+ }
95
+ if (job.created_at)
96
+ console.log(`\u2502 Created At: ${String(job.created_at).padEnd(50)} \u2502`);
97
+ 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");
98
+ console.log("\u2502 Payload: \u2502");
99
+ 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");
100
+ if (job.payload)
101
+ try {
102
+ const payload = JSON.parse(job.payload);
103
+ console.log(`\u2502 Name: ${payload.name.padEnd(52)} \u2502`);
104
+ console.log(`\u2502 Path: ${payload.path.padEnd(52)} \u2502`);
105
+ console.log(`\u2502 Max Tries: ${String(payload.maxTries).padEnd(52)} \u2502`);
106
+ console.log(`\u2502 Timeout: ${String(payload.timeOut || "N/A").padEnd(52)} \u2502`);
107
+ console.log("\u2502 Parameters: \u2502");
108
+ const paramLines = JSON.stringify(payload.params, null, 2).split(`
109
+ `);
110
+ for (const line of paramLines.slice(0, 15))
111
+ console.log(`\u2502 ${line.substring(0, 60).padEnd(60)} \u2502`);
112
+ if (paramLines.length > 15)
113
+ console.log(`\u2502 ... (${paramLines.length - 15} more lines)`.padEnd(64) + " \u2502");
114
+ if (payload.classPayload)
115
+ try {
116
+ const classConfig = JSON.parse(payload.classPayload);
117
+ 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");
118
+ console.log("\u2502 Job Configuration: \u2502");
119
+ 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");
120
+ console.log(`\u2502 Tries: ${String(classConfig.tries || 3).padEnd(52)} \u2502`);
121
+ console.log(`\u2502 Timeout: ${String(classConfig.timeout || 60).padEnd(52)} \u2502`);
122
+ if (classConfig.backoff)
123
+ console.log(`\u2502 Backoff: ${String(JSON.stringify(classConfig.backoff)).substring(0, 52).padEnd(52)} \u2502`);
124
+ } catch {}
125
+ } catch {
126
+ console.log(`\u2502 Raw: ${job.payload.substring(0, 58).padEnd(58)} \u2502`);
127
+ }
128
+ else
129
+ console.log("\u2502 (No payload) \u2502");
130
+ 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");
131
+ if (status === "Delayed" && job.available_at) {
132
+ const waitTime = job.available_at - now;
133
+ console.log(`
134
+ This job will be available in ${waitTime} second(s)`);
135
+ }
136
+ }
137
+ process.exit(0);
138
+ } catch (error) {
139
+ log.error("Failed to inspect job", error);
140
+ process.exit(1);
141
+ }
142
+ function parseArgs() {
143
+ const args = {};
144
+ process.argv.forEach((arg) => {
145
+ if (arg.startsWith("--")) {
146
+ const [key, value] = arg.slice(2).split("=");
147
+ if (key && value)
148
+ args[key] = value;
149
+ else if (key)
150
+ args[key] = "true";
151
+ }
152
+ });
153
+ return args;
154
+ }
@@ -1,5 +1,69 @@
1
- // @bun
2
- import E from"process";import{log as L}from"@stacksjs/logging";import{Job as M}from"@stacksjs/orm";var I=Z(),H=I.queue,G=I.status,K=I.limit?Number.parseInt(I.limit,10):50;try{L.info(`Fetching queued jobs...
3
- `);let z=H?await M.where("queue",H).get():await M.all(),C=Math.floor(Date.now()/1000);if(G==="pending")z=z.filter((B)=>!B.reserved_at&&(B.available_at??0)<=C);else if(G==="reserved")z=z.filter((B)=>Boolean(B.reserved_at));else if(G==="delayed")z=z.filter((B)=>!B.reserved_at&&(B.available_at??0)>C);if(Number.isFinite(K)&&K>0)z=z.slice(0,K);if(z.length===0)console.log("\u2713 No queued jobs found"),E.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\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\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\u2510"),console.log("\u2502 ID \u2502 Queue \u2502 Job \u2502 Attempts \u2502 Status \u2502 Available 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\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\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\u2524");for(let B of z){let D=B,O=String(D.id??"").padEnd(3),P=String(D.queue??"default").substring(0,18).padEnd(18),Q=X(D.payload).substring(0,32).padEnd(32),R=String(D.attempts??0).padEnd(8),V=(D.reserved_at?"reserved":(D.available_at??0)>C?"delayed":"pending").padEnd(8),W=Y(D.available_at).padEnd(19);console.log(`\u2502 ${O} \u2502 ${P} \u2502 ${Q} \u2502 ${R} \u2502 ${V} \u2502 ${W} \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\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\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\u2518"),console.log(`
4
- Showing ${z.length} job(s)${H?` on queue '${H}'`:""}${G?` (status=${G})`:""}`),E.exit(0)}catch(z){let C=z instanceof Error?z.message:String(z);if(/no such table:\s*jobs\b/i.test(C))E.stdout.write(`Queue tables are not set up yet.
5
- `),E.stdout.write("Run `buddy queue:table` to create the migrations, then `buddy migrate` to apply them.\n"),E.exit(0);L.error("Failed to list queued jobs",z),E.exit(1)}function X(z){if(typeof z!=="string")return"unknown";try{let C=JSON.parse(z);return C.jobName??C.name??"unknown"}catch{return"unknown"}}function Y(z){if(typeof z!=="number"||!Number.isFinite(z))return"N/A";return new Date(z*1000).toISOString().slice(0,19).replace("T"," ")}function Z(){let z={};return E.argv.forEach((C)=>{if(C.startsWith("--")){let[B,D]=C.slice(2).split("=");if(B&&D)z[B]=D}}),z}
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { Job } from "@stacksjs/orm";
4
+ const options = parseArgs(), queueName = options.queue, statusFilter = options.status, limit = options.limit ? Number.parseInt(options.limit, 10) : 50;
5
+ try {
6
+ log.info(`Fetching queued jobs...
7
+ `);
8
+ let jobs = queueName ? await Job.where("queue", queueName).get() : await Job.all();
9
+ const nowSec = Math.floor(Date.now() / 1000);
10
+ if (statusFilter === "pending")
11
+ jobs = jobs.filter((j) => !j.reserved_at && (j.available_at ?? 0) <= nowSec);
12
+ else if (statusFilter === "reserved")
13
+ jobs = jobs.filter((j) => Boolean(j.reserved_at));
14
+ else if (statusFilter === "delayed")
15
+ jobs = jobs.filter((j) => !j.reserved_at && (j.available_at ?? 0) > nowSec);
16
+ if (Number.isFinite(limit) && limit > 0)
17
+ jobs = jobs.slice(0, limit);
18
+ if (jobs.length === 0) {
19
+ console.log("\u2713 No queued jobs found");
20
+ process.exit(0);
21
+ }
22
+ 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\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\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\u2510");
23
+ console.log("\u2502 ID \u2502 Queue \u2502 Job \u2502 Attempts \u2502 Status \u2502 Available At \u2502");
24
+ 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\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\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\u2524");
25
+ for (const j of jobs) {
26
+ const jobAny = j, id = String(jobAny.id ?? "").padEnd(3), queue = String(jobAny.queue ?? "default").substring(0, 18).padEnd(18), jobName = extractJobName(jobAny.payload).substring(0, 32).padEnd(32), attempts = String(jobAny.attempts ?? 0).padEnd(8), status = (jobAny.reserved_at ? "reserved" : (jobAny.available_at ?? 0) > nowSec ? "delayed" : "pending").padEnd(8), avail = formatUnixTime(jobAny.available_at).padEnd(19);
27
+ console.log(`\u2502 ${id} \u2502 ${queue} \u2502 ${jobName} \u2502 ${attempts} \u2502 ${status} \u2502 ${avail} \u2502`);
28
+ }
29
+ 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\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\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\u2518");
30
+ console.log(`
31
+ Showing ${jobs.length} job(s)${queueName ? ` on queue '${queueName}'` : ""}${statusFilter ? ` (status=${statusFilter})` : ""}`);
32
+ process.exit(0);
33
+ } catch (error) {
34
+ const message = error instanceof Error ? error.message : String(error);
35
+ if (/no such table:\s*jobs\b/i.test(message)) {
36
+ process.stdout.write(`Queue tables are not set up yet.
37
+ `);
38
+ process.stdout.write("Run `buddy queue:table` to create the migrations, then `buddy migrate` to apply them.\n");
39
+ process.exit(0);
40
+ }
41
+ log.error("Failed to list queued jobs", error);
42
+ process.exit(1);
43
+ }
44
+ function extractJobName(payload) {
45
+ if (typeof payload !== "string")
46
+ return "unknown";
47
+ try {
48
+ const parsed = JSON.parse(payload);
49
+ return parsed.jobName ?? parsed.name ?? "unknown";
50
+ } catch {
51
+ return "unknown";
52
+ }
53
+ }
54
+ function formatUnixTime(seconds) {
55
+ if (typeof seconds !== "number" || !Number.isFinite(seconds))
56
+ return "N/A";
57
+ return new Date(seconds * 1000).toISOString().slice(0, 19).replace("T", " ");
58
+ }
59
+ function parseArgs() {
60
+ const args = {};
61
+ process.argv.forEach((arg) => {
62
+ if (arg.startsWith("--")) {
63
+ const [key, value] = arg.slice(2).split("=");
64
+ if (key && value)
65
+ args[key] = value;
66
+ }
67
+ });
68
+ return args;
69
+ }