@citadel-labs/beads-ui 2.4.0 → 2.5.0

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 (97) hide show
  1. package/README.md +6 -3
  2. package/bin/beads-board.js +173 -183
  3. package/package.json +2 -2
  4. package/server/__tests__/api.test.js +241 -2
  5. package/server/__tests__/pidfile.test.js +99 -0
  6. package/server/__tests__/terminal.test.js +339 -0
  7. package/server/dist/assets/index-Dm1YZe0A.css +1 -0
  8. package/server/dist/assets/index-G6bcoKqz.js +232 -0
  9. package/server/dist/index.html +2 -2
  10. package/server/handlers.js +167 -57
  11. package/server/index.js +5 -26
  12. package/server/pidfile.js +71 -0
  13. package/server/terminal-sessions.js +149 -0
  14. package/server/terminal.js +132 -31
  15. package/terminal-session-01-initial.png +0 -0
  16. package/terminal-session-02-before-refresh.png +0 -0
  17. package/terminal-session-03-after-refresh.png +0 -0
  18. package/.claude/worktrees/agent-a7b97047/LICENSE +0 -21
  19. package/.claude/worktrees/agent-a7b97047/README.md +0 -63
  20. package/.claude/worktrees/agent-a7b97047/bin/beads-board.js +0 -183
  21. package/.claude/worktrees/agent-a7b97047/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  22. package/.claude/worktrees/agent-a7b97047/package-lock.json +0 -1752
  23. package/.claude/worktrees/agent-a7b97047/package.json +0 -43
  24. package/.claude/worktrees/agent-a7b97047/server/__tests__/api.test.js +0 -206
  25. package/.claude/worktrees/agent-a7b97047/server/dist/assets/angular-html-DA-rfuFy.js +0 -1
  26. package/.claude/worktrees/agent-a7b97047/server/dist/assets/angular-ts-BrjP3tb8.js +0 -1
  27. package/.claude/worktrees/agent-a7b97047/server/dist/assets/c-BIGW1oBm.js +0 -1
  28. package/.claude/worktrees/agent-a7b97047/server/dist/assets/cpp-BRuaLJcg.js +0 -1
  29. package/.claude/worktrees/agent-a7b97047/server/dist/assets/csharp-COcwbKMJ.js +0 -1
  30. package/.claude/worktrees/agent-a7b97047/server/dist/assets/css-CLj8gQPS.js +0 -1
  31. package/.claude/worktrees/agent-a7b97047/server/dist/assets/dockerfile-BcOcwvcX.js +0 -1
  32. package/.claude/worktrees/agent-a7b97047/server/dist/assets/dotenv-Da5cRb03.js +0 -1
  33. package/.claude/worktrees/agent-a7b97047/server/dist/assets/github-dark-DHJKELXO.js +0 -1
  34. package/.claude/worktrees/agent-a7b97047/server/dist/assets/go-C27-OAKa.js +0 -1
  35. package/.claude/worktrees/agent-a7b97047/server/dist/assets/graphql-ChdNCCLP.js +0 -1
  36. package/.claude/worktrees/agent-a7b97047/server/dist/assets/html-derivative-C6UeqQa8.js +0 -1
  37. package/.claude/worktrees/agent-a7b97047/server/dist/assets/html-pp8916En.js +0 -1
  38. package/.claude/worktrees/agent-a7b97047/server/dist/assets/http-l_GQhCeT.js +0 -1
  39. package/.claude/worktrees/agent-a7b97047/server/dist/assets/index-BBBYE21N.css +0 -1
  40. package/.claude/worktrees/agent-a7b97047/server/dist/assets/index-cZFE6wf9.js +0 -231
  41. package/.claude/worktrees/agent-a7b97047/server/dist/assets/ini-BEwlwnbL.js +0 -1
  42. package/.claude/worktrees/agent-a7b97047/server/dist/assets/java-CylS5w8V.js +0 -1
  43. package/.claude/worktrees/agent-a7b97047/server/dist/assets/javascript-wDzz0qaB.js +0 -1
  44. package/.claude/worktrees/agent-a7b97047/server/dist/assets/json-Cp-IABpG.js +0 -1
  45. package/.claude/worktrees/agent-a7b97047/server/dist/assets/jsonc-Des-eS-w.js +0 -1
  46. package/.claude/worktrees/agent-a7b97047/server/dist/assets/jsonl-DcaNXYhu.js +0 -1
  47. package/.claude/worktrees/agent-a7b97047/server/dist/assets/jsx-g9-lgVsj.js +0 -1
  48. package/.claude/worktrees/agent-a7b97047/server/dist/assets/kotlin-BdnUsdx6.js +0 -1
  49. package/.claude/worktrees/agent-a7b97047/server/dist/assets/kusto-wEQ09or8.js +0 -1
  50. package/.claude/worktrees/agent-a7b97047/server/dist/assets/latex-DdMFrP5M.js +0 -1
  51. package/.claude/worktrees/agent-a7b97047/server/dist/assets/markdown-Cvjx9yec.js +0 -1
  52. package/.claude/worktrees/agent-a7b97047/server/dist/assets/mdc-Dz5ISc6g.js +0 -1
  53. package/.claude/worktrees/agent-a7b97047/server/dist/assets/mdx-Cmh6b_Ma.js +0 -1
  54. package/.claude/worktrees/agent-a7b97047/server/dist/assets/mermaid-mWjccvbQ.js +0 -1
  55. package/.claude/worktrees/agent-a7b97047/server/dist/assets/php-R6g_5hLQ.js +0 -1
  56. package/.claude/worktrees/agent-a7b97047/server/dist/assets/powershell-Dpen1YoG.js +0 -1
  57. package/.claude/worktrees/agent-a7b97047/server/dist/assets/python-B6aJPvgy.js +0 -1
  58. package/.claude/worktrees/agent-a7b97047/server/dist/assets/ruby-AcS3PBV-.js +0 -1
  59. package/.claude/worktrees/agent-a7b97047/server/dist/assets/rust-B1yitclQ.js +0 -1
  60. package/.claude/worktrees/agent-a7b97047/server/dist/assets/sass-Cj5Yp3dK.js +0 -1
  61. package/.claude/worktrees/agent-a7b97047/server/dist/assets/scss-D5BDwBP9.js +0 -1
  62. package/.claude/worktrees/agent-a7b97047/server/dist/assets/shellscript-DfDnw5Jg.js +0 -1
  63. package/.claude/worktrees/agent-a7b97047/server/dist/assets/sql-BLtJtn59.js +0 -1
  64. package/.claude/worktrees/agent-a7b97047/server/dist/assets/svelte-DR4MIrkg.js +0 -1
  65. package/.claude/worktrees/agent-a7b97047/server/dist/assets/swift-D82vCrfD.js +0 -1
  66. package/.claude/worktrees/agent-a7b97047/server/dist/assets/toml-vGWfd6FD.js +0 -1
  67. package/.claude/worktrees/agent-a7b97047/server/dist/assets/tsx-COt5Ahok.js +0 -1
  68. package/.claude/worktrees/agent-a7b97047/server/dist/assets/typescript-BPQ3VLAy.js +0 -1
  69. package/.claude/worktrees/agent-a7b97047/server/dist/assets/vue-CJgBXYWu.js +0 -1
  70. package/.claude/worktrees/agent-a7b97047/server/dist/assets/xml-sdJ4AIDG.js +0 -1
  71. package/.claude/worktrees/agent-a7b97047/server/dist/assets/yaml-Buea-lGh.js +0 -1
  72. package/.claude/worktrees/agent-a7b97047/server/dist/assets/zig-VOosw3JB.js +0 -1
  73. package/.claude/worktrees/agent-a7b97047/server/dist/favicon.svg +0 -103
  74. package/.claude/worktrees/agent-a7b97047/server/dist/index.html +0 -14
  75. package/.claude/worktrees/agent-a7b97047/server/dist/vite.svg +0 -1
  76. package/.claude/worktrees/agent-a7b97047/server/handlers.js +0 -357
  77. package/.claude/worktrees/agent-a7b97047/server/index.js +0 -88
  78. package/.claude/worktrees/agent-a7b97047/server/terminal.js +0 -103
  79. package/.claude/worktrees/agent-a7b97047/vitest.config.mjs +0 -8
  80. package/.claude/worktrees/agent-a952bde8/LICENSE +0 -21
  81. package/.claude/worktrees/agent-a952bde8/README.md +0 -63
  82. package/.claude/worktrees/agent-a952bde8/bin/beads-board.js +0 -183
  83. package/.claude/worktrees/agent-a952bde8/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  84. package/.claude/worktrees/agent-a952bde8/package-lock.json +0 -1752
  85. package/.claude/worktrees/agent-a952bde8/package.json +0 -43
  86. package/.claude/worktrees/agent-a952bde8/server/__tests__/api.test.js +0 -122
  87. package/.claude/worktrees/agent-a952bde8/server/dist/assets/index-BsWRmNbj.js +0 -79
  88. package/.claude/worktrees/agent-a952bde8/server/dist/assets/index-C7JKZkTD.css +0 -1
  89. package/.claude/worktrees/agent-a952bde8/server/dist/favicon.svg +0 -103
  90. package/.claude/worktrees/agent-a952bde8/server/dist/index.html +0 -14
  91. package/.claude/worktrees/agent-a952bde8/server/dist/vite.svg +0 -1
  92. package/.claude/worktrees/agent-a952bde8/server/handlers.js +0 -269
  93. package/.claude/worktrees/agent-a952bde8/server/index.js +0 -88
  94. package/.claude/worktrees/agent-a952bde8/server/terminal.js +0 -103
  95. package/.claude/worktrees/agent-a952bde8/vitest.config.mjs +0 -8
  96. package/server/dist/assets/index-DOFQi_E1.js +0 -231
  97. package/server/dist/assets/index-DeppoR8O.css +0 -1
@@ -1,43 +0,0 @@
1
- {
2
- "name": "@citadel-labs/beads-ui",
3
- "version": "2.3.0",
4
- "description": "Kanban dashboard and git log viewer for Beads",
5
- "bin": {
6
- "bdui": "bin/beads-board.js"
7
- },
8
- "scripts": {
9
- "build": "cd ui && npm run build",
10
- "start": "node server/index.js",
11
- "test": "vitest run && npm --prefix ui test",
12
- "test:server": "vitest run",
13
- "test:ui": "npm --prefix ui test",
14
- "test:watch": "vitest",
15
- "test:coverage": "vitest run --coverage",
16
- "publish:patch": "npm version patch && git push && git push --tags && npm publish --access public",
17
- "publish:minor": "npm version minor && git push && git push --tags && npm publish --access public",
18
- "publish:major": "npm version major && git push && git push --tags && npm publish --access public"
19
- },
20
- "keywords": [
21
- "beads",
22
- "kanban",
23
- "dashboard",
24
- "git",
25
- "cli",
26
- "bdui"
27
- ],
28
- "repository": {
29
- "type": "git",
30
- "url": "https://github.com/srimel/beads-board.git"
31
- },
32
- "homepage": "https://github.com/srimel/beads-board",
33
- "author": "Stuart Rimel <stuart.rimel@gmail.com>",
34
- "license": "MIT",
35
- "dependencies": {
36
- "node-pty": "^1.1.0",
37
- "ws": "^8.19.0"
38
- },
39
- "devDependencies": {
40
- "@vitest/coverage-v8": "^4.0.18",
41
- "vitest": "^4.0.18"
42
- }
43
- }
@@ -1,122 +0,0 @@
1
- import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from 'vitest';
2
- import http from 'node:http';
3
- import path from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
-
6
- import { createRequestHandler, setExecFile } from '../handlers.js';
7
-
8
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
- const DIST_DIR = path.join(__dirname, '..', 'dist');
10
- const PROJECT_DIR = path.join(__dirname, '..', '..');
11
-
12
- let server;
13
- let baseUrl;
14
- const mockFn = vi.fn();
15
-
16
- // Helper: mock execFile to return specific output for bd/git commands
17
- function mockExecFile(fn) {
18
- mockFn.mockImplementation((cmd, args, opts, cb) => {
19
- const result = fn(cmd, args);
20
- if (result instanceof Error) {
21
- cb(result, '', result.message);
22
- } else {
23
- cb(null, result, '');
24
- }
25
- });
26
- }
27
-
28
- beforeAll(async () => {
29
- // Replace the real execFile with our mock
30
- setExecFile(mockFn);
31
- const handler = createRequestHandler(PROJECT_DIR, DIST_DIR);
32
- server = http.createServer(handler);
33
- await new Promise((resolve) => {
34
- server.listen(0, () => {
35
- const addr = server.address();
36
- baseUrl = `http://localhost:${addr.port}`;
37
- resolve();
38
- });
39
- });
40
- });
41
-
42
- afterAll(async () => {
43
- await new Promise((resolve) => server.close(resolve));
44
- });
45
-
46
- afterEach(() => {
47
- mockFn.mockReset();
48
- });
49
-
50
- async function get(urlPath) {
51
- const r = await fetch(`${baseUrl}${urlPath}`);
52
- const text = await r.text();
53
- let data = null;
54
- try { data = JSON.parse(text); } catch {}
55
- return { status: r.status, data, text };
56
- }
57
-
58
- describe('API endpoints', () => {
59
- it('GET /api/issues returns JSON array', async () => {
60
- mockExecFile((cmd, args) => {
61
- return JSON.stringify([{ id: 'test-1', title: 'Test', issue_type: 'task' }]);
62
- });
63
- const res = await get('/api/issues');
64
- expect(res.status).toBe(200);
65
- expect(Array.isArray(res.data)).toBe(true);
66
- expect(res.data[0]).toHaveProperty('id', 'test-1');
67
- expect(res.data[0]).toHaveProperty('type', 'task'); // normalizeIssue applied
68
- });
69
-
70
- it('GET /api/issue/:id returns issue data for valid ID', async () => {
71
- mockExecFile((cmd, args) => {
72
- if (cmd === 'bd') return JSON.stringify({ id: 'beads-board-abc', title: 'Test Issue' });
73
- return '';
74
- });
75
- const res = await get('/api/issue/beads-board-abc');
76
- expect(res.status).toBe(200);
77
- expect(res.data).toHaveProperty('title', 'Test Issue');
78
- });
79
-
80
- it('GET /api/issue/:id accepts dotted IDs', async () => {
81
- mockExecFile((cmd, args) => {
82
- if (cmd === 'bd') return JSON.stringify({ id: 'beads-board-abc.1', title: 'Sub-task' });
83
- return '';
84
- });
85
- const res = await get('/api/issue/beads-board-abc.1');
86
- expect(res.status).toBe(200);
87
- expect(res.data).toHaveProperty('id', 'beads-board-abc.1');
88
- });
89
-
90
- it('GET /api/issue/:id returns 400 for invalid ID', async () => {
91
- const res = await get('/api/issue/invalid;id');
92
- expect(res.status).toBe(400);
93
- expect(res.data).toHaveProperty('error', 'Invalid issue ID');
94
- });
95
-
96
- it('GET /api/ready returns JSON array', async () => {
97
- mockExecFile((cmd, args) => {
98
- if (cmd === 'bd') return JSON.stringify([{ id: 'test-2', title: 'Ready', issue_type: 'bug' }]);
99
- return '';
100
- });
101
- const res = await get('/api/ready');
102
- expect(res.status).toBe(200);
103
- expect(Array.isArray(res.data)).toBe(true);
104
- });
105
-
106
- it('GET /api/blocked returns JSON array', async () => {
107
- mockExecFile((cmd, args) => {
108
- if (cmd === 'bd') return JSON.stringify([]);
109
- return '';
110
- });
111
- const res = await get('/api/blocked');
112
- expect(res.status).toBe(200);
113
- expect(Array.isArray(res.data)).toBe(true);
114
- });
115
-
116
- it('GET / serves index.html', async () => {
117
- // No mock needed — this reads from dist/
118
- const res = await fetch(`${baseUrl}/`);
119
- expect(res.status).toBe(200);
120
- expect(res.headers.get('content-type')).toContain('text/html');
121
- });
122
- });