@rsktash/beads-ui 0.1.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 (68) hide show
  1. package/.github/workflows/publish.yml +28 -0
  2. package/app/protocol.js +216 -0
  3. package/bin/bdui +19 -0
  4. package/client/index.html +12 -0
  5. package/client/postcss.config.js +11 -0
  6. package/client/src/App.tsx +35 -0
  7. package/client/src/components/IssueCard.tsx +73 -0
  8. package/client/src/components/Layout.tsx +175 -0
  9. package/client/src/components/Markdown.tsx +77 -0
  10. package/client/src/components/PriorityBadge.tsx +26 -0
  11. package/client/src/components/SearchDialog.tsx +137 -0
  12. package/client/src/components/SectionEditor.tsx +212 -0
  13. package/client/src/components/StatusBadge.tsx +64 -0
  14. package/client/src/components/TypeBadge.tsx +26 -0
  15. package/client/src/hooks/use-mutation.ts +55 -0
  16. package/client/src/hooks/use-search.ts +19 -0
  17. package/client/src/hooks/use-subscription.ts +187 -0
  18. package/client/src/index.css +133 -0
  19. package/client/src/lib/avatar.ts +17 -0
  20. package/client/src/lib/types.ts +115 -0
  21. package/client/src/lib/ws-client.ts +214 -0
  22. package/client/src/lib/ws-context.tsx +28 -0
  23. package/client/src/main.tsx +10 -0
  24. package/client/src/views/Board.tsx +200 -0
  25. package/client/src/views/Detail.tsx +398 -0
  26. package/client/src/views/List.tsx +461 -0
  27. package/client/tailwind.config.ts +68 -0
  28. package/client/tsconfig.json +16 -0
  29. package/client/vite.config.ts +20 -0
  30. package/package.json +43 -0
  31. package/server/app.js +120 -0
  32. package/server/app.test.js +30 -0
  33. package/server/bd.js +227 -0
  34. package/server/bd.test.js +194 -0
  35. package/server/cli/cli.test.js +207 -0
  36. package/server/cli/commands.integration.test.js +148 -0
  37. package/server/cli/commands.js +285 -0
  38. package/server/cli/commands.unit.test.js +408 -0
  39. package/server/cli/daemon.js +340 -0
  40. package/server/cli/daemon.test.js +31 -0
  41. package/server/cli/index.js +135 -0
  42. package/server/cli/open.js +178 -0
  43. package/server/cli/open.test.js +26 -0
  44. package/server/cli/usage.js +27 -0
  45. package/server/config.js +36 -0
  46. package/server/db.js +154 -0
  47. package/server/db.test.js +169 -0
  48. package/server/dolt-pool.js +257 -0
  49. package/server/dolt-queries.js +646 -0
  50. package/server/index.js +97 -0
  51. package/server/list-adapters.js +395 -0
  52. package/server/list-adapters.test.js +208 -0
  53. package/server/logging.js +23 -0
  54. package/server/registry-watcher.js +200 -0
  55. package/server/subscriptions.js +299 -0
  56. package/server/subscriptions.test.js +128 -0
  57. package/server/validators.js +124 -0
  58. package/server/watcher.js +139 -0
  59. package/server/watcher.test.js +120 -0
  60. package/server/ws.comments.test.js +262 -0
  61. package/server/ws.delete.test.js +119 -0
  62. package/server/ws.js +1309 -0
  63. package/server/ws.labels.test.js +95 -0
  64. package/server/ws.list-refresh.coalesce.test.js +95 -0
  65. package/server/ws.list-subscriptions.test.js +403 -0
  66. package/server/ws.mutation-window.test.js +147 -0
  67. package/server/ws.mutations.test.js +389 -0
  68. package/server/ws.test.js +52 -0
@@ -0,0 +1,119 @@
1
+ import { beforeEach, describe, expect, test, vi } from 'vitest';
2
+ import { runBd } from './bd.js';
3
+ import { handleMessage } from './ws.js';
4
+
5
+ vi.mock('./bd.js', () => ({
6
+ runBd: vi.fn(),
7
+ runBdJson: vi.fn(),
8
+ getGitUserName: vi.fn()
9
+ }));
10
+
11
+ function makeStubSocket() {
12
+ return {
13
+ sent: /** @type {string[]} */ ([]),
14
+ readyState: 1,
15
+ OPEN: 1,
16
+ /** @param {string} msg */
17
+ send(msg) {
18
+ this.sent.push(String(msg));
19
+ }
20
+ };
21
+ }
22
+
23
+ describe('delete-issue handler', () => {
24
+ beforeEach(() => {
25
+ vi.clearAllMocks();
26
+ });
27
+
28
+ test('sends delete-issue and receives success', async () => {
29
+ const rb = /** @type {import('vitest').Mock} */ (runBd);
30
+ rb.mockResolvedValueOnce({ code: 0, stdout: '', stderr: '' });
31
+
32
+ const ws = makeStubSocket();
33
+ await handleMessage(
34
+ /** @type {any} */ (ws),
35
+ Buffer.from(
36
+ JSON.stringify({
37
+ id: 'req-1',
38
+ type: /** @type {any} */ ('delete-issue'),
39
+ payload: { id: 'beads-abc123' }
40
+ })
41
+ )
42
+ );
43
+
44
+ // Check bd delete was called with --force
45
+ expect(rb).toHaveBeenCalledWith(['delete', 'beads-abc123', '--force']);
46
+
47
+ // Check response
48
+ expect(ws.sent.length).toBe(1);
49
+ const reply = JSON.parse(ws.sent[0]);
50
+ expect(reply.ok).toBe(true);
51
+ expect(reply.payload.deleted).toBe(true);
52
+ expect(reply.payload.id).toBe('beads-abc123');
53
+ });
54
+
55
+ test('returns error when bd delete fails', async () => {
56
+ const rb = /** @type {import('vitest').Mock} */ (runBd);
57
+ rb.mockResolvedValueOnce({
58
+ code: 1,
59
+ stdout: '',
60
+ stderr: 'Issue not found'
61
+ });
62
+
63
+ const ws = makeStubSocket();
64
+ await handleMessage(
65
+ /** @type {any} */ (ws),
66
+ Buffer.from(
67
+ JSON.stringify({
68
+ id: 'req-2',
69
+ type: /** @type {any} */ ('delete-issue'),
70
+ payload: { id: 'beads-notfound' }
71
+ })
72
+ )
73
+ );
74
+
75
+ expect(ws.sent.length).toBe(1);
76
+ const reply = JSON.parse(ws.sent[0]);
77
+ expect(reply.ok).toBe(false);
78
+ expect(reply.error.code).toBe('bd_error');
79
+ expect(reply.error.message).toBe('Issue not found');
80
+ });
81
+
82
+ test('returns error when id is missing', async () => {
83
+ const ws = makeStubSocket();
84
+ await handleMessage(
85
+ /** @type {any} */ (ws),
86
+ Buffer.from(
87
+ JSON.stringify({
88
+ id: 'req-3',
89
+ type: /** @type {any} */ ('delete-issue'),
90
+ payload: {}
91
+ })
92
+ )
93
+ );
94
+
95
+ expect(ws.sent.length).toBe(1);
96
+ const reply = JSON.parse(ws.sent[0]);
97
+ expect(reply.ok).toBe(false);
98
+ expect(reply.error.code).toBe('bad_request');
99
+ });
100
+
101
+ test('returns error when id is empty string', async () => {
102
+ const ws = makeStubSocket();
103
+ await handleMessage(
104
+ /** @type {any} */ (ws),
105
+ Buffer.from(
106
+ JSON.stringify({
107
+ id: 'req-4',
108
+ type: /** @type {any} */ ('delete-issue'),
109
+ payload: { id: '' }
110
+ })
111
+ )
112
+ );
113
+
114
+ expect(ws.sent.length).toBe(1);
115
+ const reply = JSON.parse(ws.sent[0]);
116
+ expect(reply.ok).toBe(false);
117
+ expect(reply.error.code).toBe('bad_request');
118
+ });
119
+ });