bunqueue-dashboard 1.0.2 → 1.0.3

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 (82) hide show
  1. package/README.md +8 -7
  2. package/agent/manager/config.ts +2 -1
  3. package/agent/server/handler.ts +2 -1
  4. package/agent/server/router.ts +1 -0
  5. package/agent/server/types.ts +1 -1
  6. package/agent/workflow/runtime.ts +25 -7
  7. package/agent/workflow/runtimeRoutes.ts +4 -1
  8. package/dist/.vite/manifest.json +500 -489
  9. package/dist/assets/{AddJob-CiwWycYG.js → AddJob-jq-VZ_YE.js} +1 -1
  10. package/dist/assets/{Alerts-DCKl_C8D.js → Alerts-Bi8zLKXV.js} +1 -1
  11. package/dist/assets/{AreaChart-Db2UVnaK.js → AreaChart-BMYp7z5y.js} +1 -1
  12. package/dist/assets/{Benchmark-DyHvEM8x.js → Benchmark-CWYdqm55.js} +1 -1
  13. package/dist/assets/{BulkAddJobs-GRMVnf0j.js → BulkAddJobs-0cdWqkEF.js} +1 -1
  14. package/dist/assets/{Button-_aSJvRoW.js → Button-BCjgbAhY.js} +1 -1
  15. package/dist/assets/{Card-egIDLwVk.js → Card-DptfvL2O.js} +1 -1
  16. package/dist/assets/{Cron-XL0PdUEc.js → Cron-dPGwJXqY.js} +1 -1
  17. package/dist/assets/{CronManager-Cqtg9Zr8.js → CronManager-C0-Y2QDg.js} +1 -1
  18. package/dist/assets/{Database-BBzyi7f0.js → Database-CseJOrvD.js} +1 -1
  19. package/dist/assets/{Diagnostics-E_icHggb.js → Diagnostics-cZTy4Y2t.js} +1 -1
  20. package/dist/assets/{Dlq-DNs32CzV.js → Dlq-W2xOJiZM.js} +1 -1
  21. package/dist/assets/{DlqControl-DawwIsTI.js → DlqControl-CIV5278D.js} +1 -1
  22. package/dist/assets/DlqPro-BuRxGtGt.js +1 -0
  23. package/dist/assets/{Fleet-Bkbq0dFB.js → Fleet-0zKJSjCw.js} +1 -1
  24. package/dist/assets/{Flows-DKZxI7ta.js → Flows-CEfm102Y.js} +1 -1
  25. package/dist/assets/{JobInspector-BARE52q3.js → JobInspector-BlMj5-Vr.js} +1 -1
  26. package/dist/assets/{Jobs-CKzKpQ7i.js → Jobs-D_TId_Oa.js} +1 -1
  27. package/dist/assets/JobsPro-A06ZG5Xi.js +1 -0
  28. package/dist/assets/{Logs-Bj60G_FP.js → Logs-hbh7XhQU.js} +1 -1
  29. package/dist/assets/{LogsPro-Hv8xwXDK.js → LogsPro-BgEIjgfj.js} +1 -1
  30. package/dist/assets/McpServer-ffXr4nFW.js +22 -0
  31. package/dist/assets/{Metrics-BBLdWOw1.js → Metrics-CIKZGgf0.js} +1 -1
  32. package/dist/assets/{MetricsPro-D470b1aP.js → MetricsPro-CK3WfLCl.js} +1 -1
  33. package/dist/assets/{Overview-B_AOa5kW.js → Overview-BBgwyUn4.js} +1 -1
  34. package/dist/assets/{PageHeader-CQzNsw8r.js → PageHeader-DD4vnVog.js} +1 -1
  35. package/dist/assets/{Pagination-CSkzhNW6.js → Pagination-Cj7GzYNX.js} +1 -1
  36. package/dist/assets/{QueueActions-BBxRt-t0.js → QueueActions-BgdW95rN.js} +1 -1
  37. package/dist/assets/{QueueControl-DaZjeZnw.js → QueueControl-g-9kwrpt.js} +1 -1
  38. package/dist/assets/{QueueDetail-Dgo9Ukmp.js → QueueDetail-Cv3MLDoE.js} +1 -1
  39. package/dist/assets/{QueueDetailPro-D7U8ahp2.js → QueueDetailPro-AhdOAzEF.js} +1 -1
  40. package/dist/assets/{Queues-CS8LeZtJ.js → Queues-Bbvh_OCE.js} +1 -1
  41. package/dist/assets/{QueuesOverview-BySSnCm0.js → QueuesOverview-sPQILfMU.js} +1 -1
  42. package/dist/assets/{S3Backup-Ci4dJPP_.js → S3Backup-Cg6sc2JG.js} +1 -1
  43. package/dist/assets/{S3BackupPro-UwWu0yxr.js → S3BackupPro-BWV_R_Vj.js} +1 -1
  44. package/dist/assets/ServerControl-Dr2gXbaU.js +3 -0
  45. package/dist/assets/{Settings-FOzwrB25.js → Settings-BsDDlu-h.js} +1 -1
  46. package/dist/assets/{StatusBadge-DereLzOj.js → StatusBadge-cYUkK-4P.js} +1 -1
  47. package/dist/assets/{Usage-DR90dCt0.js → Usage-Cxx6pZfb.js} +1 -1
  48. package/dist/assets/{UsagePro-DAlE3oCE.js → UsagePro-CkC8WYcS.js} +1 -1
  49. package/dist/assets/{Webhooks-BonYUgMo.js → Webhooks-BKWnALGC.js} +1 -1
  50. package/dist/assets/{Workers-D1Ead02h.js → Workers-SJ9MApx3.js} +1 -1
  51. package/dist/assets/WorkersPro-BDgHBTpY.js +1 -0
  52. package/dist/assets/Workflows-Cp6jqKeM.js +1 -0
  53. package/dist/assets/{api-D9aT0ND7.js → api-Bbo86MB6.js} +1 -1
  54. package/dist/assets/{bq-DR2BTISO.js → bq-CSX8DSME.js} +1 -1
  55. package/dist/assets/{classicJobsData-Csj4iihY.js → classicJobsData-BimIyQky.js} +1 -1
  56. package/dist/assets/{connectionStore-CVjQyIZv.js → connectionStore-DdLzJyut.js} +1 -1
  57. package/dist/assets/{controlConnectionEpoch-ChAeMMLk.js → controlConnectionEpoch-D4HtriLM.js} +1 -1
  58. package/dist/assets/{feedback-CtGN_kqB.js → feedback-Dxfj-Fy1.js} +1 -1
  59. package/dist/assets/{form-DG3X6cLL.js → form-Dy-an7ew.js} +1 -1
  60. package/dist/assets/{icons-DH9SS1DA.js → icons-C1HVBnFn.js} +1 -1
  61. package/dist/assets/{index-DZFZr0Mi.js → index-CxzFSZj3.js} +3 -3
  62. package/dist/assets/index-DZXf58c2.css +1 -0
  63. package/dist/assets/install-DUkXE5kb.js +3 -0
  64. package/dist/assets/package-C7CtgBEy.js +1 -0
  65. package/dist/assets/react-vendor-DfC0iyIS.js +11 -0
  66. package/dist/assets/{toastStore-XmMX7A5W.js → toastStore-DnqA_aL-.js} +1 -1
  67. package/dist/assets/{useControlActionGuard-1i7aFA7E.js → useControlActionGuard-DImMgJtj.js} +1 -1
  68. package/dist/assets/{usePolledData-CEyyLRYa.js → usePolledData-Dp_ynL9f.js} +1 -1
  69. package/dist/assets/{useServerActionGuard-CUx8TOAC.js → useServerActionGuard-Cr4KUOeZ.js} +1 -1
  70. package/dist/assets/{useThroughputSeries-CeFx-Mwq.js → useThroughputSeries-CrTeR9s3.js} +1 -1
  71. package/dist/index.html +14 -14
  72. package/package.json +21 -24
  73. package/scripts/embedded.gen.ts +156 -154
  74. package/dist/assets/DlqPro-BEdxFiNN.js +0 -1
  75. package/dist/assets/JobsPro-DxDw-akG.js +0 -1
  76. package/dist/assets/McpServer-zxSMjG8K.js +0 -24
  77. package/dist/assets/ServerControl-Ch1wZcKB.js +0 -3
  78. package/dist/assets/WorkersPro-XuLxtU4A.js +0 -1
  79. package/dist/assets/Workflows-CqZZ96EK.js +0 -1
  80. package/dist/assets/index-DaEyLvTR.css +0 -1
  81. package/dist/assets/install-oydLpc1T.js +0 -3
  82. package/dist/assets/react-vendor-CFL9l8LK.js +0 -11
package/README.md CHANGED
@@ -32,7 +32,7 @@ The live demo uses sample data. The docs explain how to connect and operate a re
32
32
  ![Vite 8](https://img.shields.io/badge/Vite-8-646CFF?logo=vite&logoColor=white)
33
33
  ![Bun](https://img.shields.io/badge/Bun-1.4-000?logo=bun&logoColor=white)
34
34
  ![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6?logo=typescript&logoColor=white)
35
- ![Oxlint + Oxfmt](https://img.shields.io/badge/Oxc-Oxlint%20%2B%20Oxfmt-7C3AED)
35
+ ![Oxlint + Bun fmt](https://img.shields.io/badge/Tooling-Oxlint%20%2B%20Bun%20fmt-7C3AED)
36
36
 
37
37
  <br />
38
38
 
@@ -263,20 +263,21 @@ target-pinned Flow, Workflow, Queue and Backup agent operations.
263
263
  | `bun start` | **Agent + dashboard together** (one-command dev) |
264
264
  | `bun dev` | Dashboard only (Vite dev server) |
265
265
  | `bun run agent` | Control agent only |
266
- | `bun run build` | Typecheck (`tsc --noEmit`) + production build → `dist/` |
266
+ | `bun run build` | Native Bun typecheck + production build → `dist/` |
267
+ | `bun run typecheck` | Native `bun check` for the frontend, agent/scripts, examples and browser tests |
267
268
  | `bun run preview` | Preview the production build |
268
269
  | `bun run lint` | Lint with Oxlint, including type-aware rules and the implicit-`any` parity guard |
269
- | `bun run format:check` | Check formatting with Oxfmt |
270
- | `bun run check` | Oxlint + Oxfmt validation (the CI gate) |
271
- | `bun run check:fix` | Apply safe Oxlint fixes, then format with Oxfmt |
270
+ | `bun run format:check` | Check formatting with native `bun fmt --check` |
271
+ | `bun run check` | Native typechecking, Oxlint and native formatting validation |
272
+ | `bun run check:fix` | Apply safe Oxlint fixes, then format with native `bun fmt` |
272
273
  | `bun test` | Unit + agent-lifecycle tests |
273
274
  | `bun run test:e2e:tls` | Queue, Flow and Workflow over verified native TLS, including untrusted-certificate rejection |
274
- | `bun run test:e2e:upgrade` | Real npm Bunqueue 2.9.2 SQLite schema-35 → 2.9.4 schema-37 migration and retention semantics |
275
+ | `bun run test:e2e:upgrade` | Real npm Bunqueue 2.9.2 SQLite schema-35 → 2.9.20 schema-37 migration and retention semantics |
275
276
  | `bun run test:e2e` | Real TLS, SQLite upgrade, Flow, Workflow, Queue SDK, and three-broker PostgreSQL runtime tests |
276
277
  | `bun run test:e2e:browser` | Production UI tests on Chromium, Firefox and WebKit |
277
278
  | `bun run test:e2e:browser:postgres-fleet` | Real UI operations across three PostgreSQL brokers (requires Docker and Chromium) |
278
279
  | `bun run quality` | Complete static, build, docs, coverage, runtime, package and dependency gate |
279
- | `bun run test:e2e:postgres-fleet` | Three authenticated Bunqueue 2.9.4 brokers + three agents sharing disposable PostgreSQL 18.6 |
280
+ | `bun run test:e2e:postgres-fleet` | Three authenticated Bunqueue 2.9.20 brokers + three agents sharing disposable PostgreSQL 18.6 |
280
281
 
281
282
  ## Docker
282
283
 
@@ -1,3 +1,4 @@
1
+ import manifest from '../../package.json';
1
2
  import type { ServerConfig } from './types';
2
3
 
3
4
  const CONFIG_KEYS = new Set<keyof ServerConfig>([
@@ -10,7 +11,7 @@ const CONFIG_KEYS = new Set<keyof ServerConfig>([
10
11
 
11
12
  export function defaultConfig(): ServerConfig {
12
13
  return {
13
- command: process.env.BUNQUEUE_START_CMD || 'bunx bunqueue@2.9.4 start',
14
+ command: process.env.BUNQUEUE_START_CMD || `bunx bunqueue@${manifest.dependencies.bunqueue} start`,
14
15
  httpPort: Number(process.env.HTTP_PORT) || 6790,
15
16
  tcpPort: Number(process.env.TCP_PORT) || 6789,
16
17
  dataPath: process.env.BUNQUEUE_DATA_PATH || './data/bunq.db',
@@ -65,7 +65,8 @@ export function createFetchHandler(
65
65
  return new Response(null, { status: 204, headers: corsHeaders(origin, allowedOrigins) });
66
66
  }
67
67
  const mutating = method === 'POST' || method === 'PUT';
68
- const authRequired = requireTokenForAll || (mutating && Boolean(token));
68
+ const configurationRead = pathname === '/control/config' || pathname === '/control/status';
69
+ const authRequired = requireTokenForAll || ((mutating || configurationRead) && Boolean(token));
69
70
  if (authRequired && !tokenOk(request, token)) {
70
71
  return json({ ok: false, error: 'Unauthorized' }, 401, origin);
71
72
  }
@@ -201,6 +201,7 @@ function isWorkflowRuntimeRoute(pathname: string, method: string): boolean {
201
201
  if (method !== 'POST') return false;
202
202
  return (
203
203
  [
204
+ '/workflows/runtime/initialize',
204
205
  '/workflows/runtime/reload',
205
206
  '/workflows/start',
206
207
  '/workflows/recover',
@@ -5,7 +5,7 @@ export interface AgentOptions {
5
5
  allowedOrigins: string[];
6
6
  /** DNS-rebinding defense; compared by hostname only. */
7
7
  allowedHosts?: string[];
8
- /** On loopback, when set, changing requests must present this token. */
8
+ /** On loopback, when set, mutations and complete configuration reads require this token. */
9
9
  token?: string;
10
10
  /** Network exposure: require token on every non-OPTIONS request. */
11
11
  requireTokenForAll?: boolean;
@@ -29,10 +29,12 @@ export interface WorkflowRuntimeStatus {
29
29
  queueName?: string;
30
30
  concurrency?: number;
31
31
  error?: string;
32
+ needsInitialization?: boolean;
32
33
  }
33
34
 
34
35
  export interface WorkflowRuntimePort {
35
- status(config: ServerConfig, activate?: boolean): Promise<WorkflowRuntimeStatus>;
36
+ status(config: ServerConfig, serverRunning?: boolean): Promise<WorkflowRuntimeStatus>;
37
+ initialize(config: ServerConfig): Promise<WorkflowRuntimeStatus>;
36
38
  reload(config: ServerConfig): Promise<WorkflowRuntimeStatus>;
37
39
  start(config: ServerConfig, workflowName: string, input?: unknown): Promise<unknown>;
38
40
  signal(config: ServerConfig, id: string, event: string, payload?: unknown): Promise<void>;
@@ -72,20 +74,32 @@ export class WorkflowRuntime implements WorkflowRuntimePort {
72
74
  private readonly createEngine: WorkflowEngineFactory = (options) => new Engine(options)
73
75
  ) {}
74
76
 
75
- status(config: ServerConfig, activate = true): Promise<WorkflowRuntimeStatus> {
77
+ status(config: ServerConfig, serverRunning = true): Promise<WorkflowRuntimeStatus> {
76
78
  return this.serial(async () => {
77
79
  const modulePath = configuredWorkflowModule(config);
78
80
  try {
79
81
  if (!modulePath) {
80
- await this.closeActive();
81
82
  return { configured: false, ready: false, workflowNames: [] };
82
83
  }
83
- if (!activate) {
84
- await this.closeActive();
84
+ if (!serverRunning) {
85
85
  return stoppedRuntimeStatus(config, modulePath);
86
86
  }
87
- const active = await this.ensure(config);
88
- return readyRuntimeStatus(active);
87
+ const active = this.active;
88
+ if (active?.closeFailure !== undefined) throw quarantinedRuntimeError(active);
89
+ const path = await realpath(modulePath);
90
+ const modified = (await stat(path)).mtimeMs;
91
+ const options = workflowRuntimeOptions(config);
92
+ if (active?.signature === workflowRuntimeSignature(config, path, modified, options)) {
93
+ return readyRuntimeStatus(active);
94
+ }
95
+ return {
96
+ configured: true,
97
+ ready: false,
98
+ needsInitialization: true,
99
+ moduleName: basename(modulePath),
100
+ workflowNames: [],
101
+ ...options,
102
+ };
89
103
  } catch (error) {
90
104
  const active = this.active;
91
105
  return {
@@ -101,6 +115,10 @@ export class WorkflowRuntime implements WorkflowRuntimePort {
101
115
  });
102
116
  }
103
117
 
118
+ initialize(config: ServerConfig): Promise<WorkflowRuntimeStatus> {
119
+ return this.serial(async () => readyRuntimeStatus(await this.ensure(config)));
120
+ }
121
+
104
122
  reload(config: ServerConfig): Promise<WorkflowRuntimeStatus> {
105
123
  return this.serial(async () => {
106
124
  await this.closeActive();
@@ -49,6 +49,9 @@ export async function routeWorkflowRuntimeRequest(
49
49
  );
50
50
  }
51
51
  if (!serverRunning) throw new Error('Start the managed Bunqueue server before workflow control.');
52
+ if (pathname === '/workflows/runtime/initialize') {
53
+ return success(await admitted(true, ({ config: current }) => runtime.initialize(current)));
54
+ }
52
55
  if (pathname === '/workflows/runtime/reload') {
53
56
  return success(await admitted(true, ({ config: current }) => runtime.reload(current)));
54
57
  }
@@ -98,7 +101,7 @@ function isRuntimePath(pathname: string, method: string): boolean {
98
101
  if (method === 'GET') return pathname === '/workflows/runtime';
99
102
  if (method !== 'POST') return false;
100
103
  return (
101
- ['/workflows/runtime/reload', '/workflows/start', '/workflows/recover', '/workflows/archive', '/workflows/cleanup'].includes(pathname) ||
104
+ ['/workflows/runtime/initialize', '/workflows/runtime/reload', '/workflows/start', '/workflows/recover', '/workflows/archive', '/workflows/cleanup'].includes(pathname) ||
102
105
  /^\/workflows\/[^/]+\/(signal|resume-compensation|abandon-compensation)$/.test(pathname)
103
106
  );
104
107
  }