db4ai 0.3.0 → 0.3.1

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 (89) hide show
  1. package/dist/chunk-3DWAMVV5.js +305 -0
  2. package/dist/chunk-3DWAMVV5.js.map +1 -0
  3. package/dist/chunk-COTPYBYM.js +618 -0
  4. package/dist/chunk-COTPYBYM.js.map +1 -0
  5. package/dist/chunk-EERD6CDF.js +735 -0
  6. package/dist/chunk-EERD6CDF.js.map +1 -0
  7. package/dist/chunk-FUF4HJTC.js +758 -0
  8. package/dist/chunk-FUF4HJTC.js.map +1 -0
  9. package/dist/chunk-JLL6FH5L.js +16 -0
  10. package/dist/chunk-JLL6FH5L.js.map +1 -0
  11. package/dist/chunk-JXFW6AIT.js +192 -0
  12. package/dist/chunk-JXFW6AIT.js.map +1 -0
  13. package/dist/chunk-XLSYCQPG.js +854 -0
  14. package/dist/chunk-XLSYCQPG.js.map +1 -0
  15. package/dist/chunk-Y5IXAS7F.js +569 -0
  16. package/dist/chunk-Y5IXAS7F.js.map +1 -0
  17. package/dist/cli/bin.d.ts +13 -12
  18. package/dist/cli/bin.js +277 -307
  19. package/dist/cli/bin.js.map +1 -1
  20. package/dist/cli/dashboard/index.d.ts +295 -14
  21. package/dist/cli/dashboard/index.js +60 -15
  22. package/dist/cli/dashboard/index.js.map +1 -1
  23. package/dist/cli/index.d.ts +10 -16
  24. package/dist/cli/index.js +94 -47
  25. package/dist/cli/index.js.map +1 -1
  26. package/dist/cli/runtime/index.d.ts +52 -23
  27. package/dist/cli/runtime/index.js +10 -704
  28. package/dist/cli/runtime/index.js.map +1 -1
  29. package/dist/cli/scanner/index.d.ts +17 -15
  30. package/dist/cli/scanner/index.js +8 -639
  31. package/dist/cli/scanner/index.js.map +1 -1
  32. package/dist/cli/seed/index.d.ts +16 -12
  33. package/dist/cli/seed/index.js +12 -773
  34. package/dist/cli/seed/index.js.map +1 -1
  35. package/dist/cli/sync/index.d.ts +54 -53
  36. package/dist/cli/sync/index.js +23 -704
  37. package/dist/cli/sync/index.js.map +1 -1
  38. package/dist/cli/terminal.d.ts +9 -8
  39. package/dist/cli/terminal.js +6 -209
  40. package/dist/cli/terminal.js.map +1 -1
  41. package/dist/cli/workflow/index.d.ts +18 -10
  42. package/dist/cli/workflow/index.js +6 -307
  43. package/dist/cli/workflow/index.js.map +1 -1
  44. package/dist/handlers.d.ts +10 -9
  45. package/dist/handlers.js +6 -38
  46. package/dist/handlers.js.map +1 -1
  47. package/dist/index.d.ts +120 -118
  48. package/dist/index.js +1963 -3125
  49. package/dist/index.js.map +1 -1
  50. package/package.json +3 -4
  51. package/dist/cli/bin.d.ts.map +0 -1
  52. package/dist/cli/dashboard/App.d.ts +0 -16
  53. package/dist/cli/dashboard/App.d.ts.map +0 -1
  54. package/dist/cli/dashboard/App.js +0 -116
  55. package/dist/cli/dashboard/App.js.map +0 -1
  56. package/dist/cli/dashboard/components/index.d.ts +0 -70
  57. package/dist/cli/dashboard/components/index.d.ts.map +0 -1
  58. package/dist/cli/dashboard/components/index.js +0 -192
  59. package/dist/cli/dashboard/components/index.js.map +0 -1
  60. package/dist/cli/dashboard/hooks/index.d.ts +0 -76
  61. package/dist/cli/dashboard/hooks/index.d.ts.map +0 -1
  62. package/dist/cli/dashboard/hooks/index.js +0 -201
  63. package/dist/cli/dashboard/hooks/index.js.map +0 -1
  64. package/dist/cli/dashboard/index.d.ts.map +0 -1
  65. package/dist/cli/dashboard/types.d.ts +0 -84
  66. package/dist/cli/dashboard/types.d.ts.map +0 -1
  67. package/dist/cli/dashboard/types.js +0 -5
  68. package/dist/cli/dashboard/types.js.map +0 -1
  69. package/dist/cli/dashboard/views/index.d.ts +0 -51
  70. package/dist/cli/dashboard/views/index.d.ts.map +0 -1
  71. package/dist/cli/dashboard/views/index.js +0 -72
  72. package/dist/cli/dashboard/views/index.js.map +0 -1
  73. package/dist/cli/index.d.ts.map +0 -1
  74. package/dist/cli/runtime/index.d.ts.map +0 -1
  75. package/dist/cli/scanner/index.d.ts.map +0 -1
  76. package/dist/cli/seed/index.d.ts.map +0 -1
  77. package/dist/cli/sync/index.d.ts.map +0 -1
  78. package/dist/cli/terminal.d.ts.map +0 -1
  79. package/dist/cli/workflow/index.d.ts.map +0 -1
  80. package/dist/errors.d.ts +0 -43
  81. package/dist/errors.d.ts.map +0 -1
  82. package/dist/errors.js +0 -47
  83. package/dist/errors.js.map +0 -1
  84. package/dist/handlers.d.ts.map +0 -1
  85. package/dist/index.d.ts.map +0 -1
  86. package/dist/types.d.ts +0 -276
  87. package/dist/types.d.ts.map +0 -1
  88. package/dist/types.js +0 -12
  89. package/dist/types.js.map +0 -1
@@ -0,0 +1,854 @@
1
+ // cli/dashboard/components/index.tsx
2
+ import { useState, useMemo, memo } from "react";
3
+ import { Box, Text, useInput, useStdout } from "ink";
4
+
5
+ // cli/dashboard/types.ts
6
+ var getLayoutSize = (width) => {
7
+ if (width < 60) return "compact";
8
+ if (width < 100) return "normal";
9
+ return "wide";
10
+ };
11
+
12
+ // cli/dashboard/components/index.tsx
13
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
+ var Layout = memo(function Layout2({
15
+ children,
16
+ header,
17
+ footer,
18
+ responsive = false
19
+ }) {
20
+ const { stdout } = useStdout();
21
+ const width = stdout?.columns ?? 80;
22
+ const layoutSize = useMemo(() => getLayoutSize(width), [width]);
23
+ const padding = useMemo(() => {
24
+ if (!responsive) return 0;
25
+ switch (layoutSize) {
26
+ case "compact":
27
+ return 0;
28
+ case "normal":
29
+ return 1;
30
+ case "wide":
31
+ return 2;
32
+ }
33
+ }, [responsive, layoutSize]);
34
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: padding, children: [
35
+ header,
36
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", children }),
37
+ footer
38
+ ] });
39
+ });
40
+ var Header = memo(function Header2({
41
+ namespace,
42
+ connected,
43
+ view
44
+ }) {
45
+ return /* @__PURE__ */ jsxs(Box, { children: [
46
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "db4.ai" }),
47
+ /* @__PURE__ */ jsx(Text, { children: " - " }),
48
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: namespace }),
49
+ view && /* @__PURE__ */ jsxs(Fragment, { children: [
50
+ /* @__PURE__ */ jsx(Text, { children: " / " }),
51
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: view })
52
+ ] }),
53
+ connected !== void 0 && /* @__PURE__ */ jsxs(Text, { color: connected ? "green" : "red", children: [
54
+ " ",
55
+ connected ? "[connected]" : "[disconnected]"
56
+ ] })
57
+ ] });
58
+ });
59
+ var formatNumber = (n) => {
60
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
61
+ if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
62
+ return n.toString();
63
+ };
64
+ var Stats = memo(function Stats2({ stats }) {
65
+ const formattedRecords = useMemo(() => formatNumber(stats.totalRecords), [stats.totalRecords]);
66
+ return /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
67
+ /* @__PURE__ */ jsxs(Text, { children: [
68
+ "Records: ",
69
+ formattedRecords
70
+ ] }),
71
+ /* @__PURE__ */ jsxs(Text, { children: [
72
+ "Types: ",
73
+ stats.typeCount
74
+ ] }),
75
+ /* @__PURE__ */ jsxs(Text, { children: [
76
+ "Pending: ",
77
+ stats.pendingJobs
78
+ ] }),
79
+ /* @__PURE__ */ jsxs(Text, { children: [
80
+ "Workflows: ",
81
+ stats.activeWorkflows
82
+ ] })
83
+ ] });
84
+ });
85
+ var TypeListItem = memo(function TypeListItem2({
86
+ type,
87
+ isSelected,
88
+ maxWidth
89
+ }) {
90
+ const displayName = useMemo(() => {
91
+ if (maxWidth && type.name.length > maxWidth) {
92
+ return type.name.slice(0, maxWidth - 3) + "...";
93
+ }
94
+ return type.name;
95
+ }, [type.name, maxWidth]);
96
+ return /* @__PURE__ */ jsxs(Text, { inverse: isSelected, children: [
97
+ isSelected ? "> " : " ",
98
+ displayName,
99
+ " (",
100
+ type.count,
101
+ ")"
102
+ ] });
103
+ });
104
+ function TypeList({
105
+ types,
106
+ selectedIndex = 0,
107
+ onSelect,
108
+ maxWidth
109
+ }) {
110
+ const [selected, setSelected] = useState(selectedIndex);
111
+ useInput((input, key) => {
112
+ if (key.downArrow) {
113
+ setSelected((s) => Math.min(s + 1, types.length - 1));
114
+ } else if (key.upArrow) {
115
+ setSelected((s) => Math.max(s - 1, 0));
116
+ } else if (key.return && onSelect) {
117
+ const currentType = types[selected];
118
+ if (currentType) {
119
+ onSelect(currentType);
120
+ }
121
+ }
122
+ });
123
+ if (types.length === 0) {
124
+ return /* @__PURE__ */ jsx(Text, { color: "gray", children: "No types" });
125
+ }
126
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: types.map((type, index) => /* @__PURE__ */ jsx(
127
+ TypeListItem,
128
+ {
129
+ type,
130
+ isSelected: index === selected,
131
+ maxWidth
132
+ },
133
+ type.name
134
+ )) });
135
+ }
136
+ function ActivityFeed({
137
+ events,
138
+ limit,
139
+ autoScroll,
140
+ filter
141
+ }) {
142
+ let filtered = events;
143
+ if (filter) {
144
+ filtered = events.filter((e) => e.type === filter);
145
+ }
146
+ if (limit) {
147
+ filtered = filtered.slice(0, limit);
148
+ }
149
+ if (filtered.length === 0) {
150
+ return /* @__PURE__ */ jsx(Text, { color: "gray", children: "No activity" });
151
+ }
152
+ const formatTime = (date) => {
153
+ return date.toLocaleTimeString("en-US", {
154
+ hour: "2-digit",
155
+ minute: "2-digit",
156
+ hour12: false,
157
+ timeZone: "UTC"
158
+ });
159
+ };
160
+ const getStatusColor2 = (status) => {
161
+ switch (status) {
162
+ case "completed":
163
+ return "green";
164
+ case "running":
165
+ return "yellow";
166
+ case "failed":
167
+ return "red";
168
+ default:
169
+ return "gray";
170
+ }
171
+ };
172
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: filtered.map((event) => /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
173
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: formatTime(event.timestamp) }),
174
+ /* @__PURE__ */ jsx(Text, { color: getStatusColor2(event.status), children: event.status }),
175
+ /* @__PURE__ */ jsx(Text, { children: event.type }),
176
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: event.entity }),
177
+ event.error && /* @__PURE__ */ jsx(Text, { color: "red", children: event.error })
178
+ ] }, event.id)) });
179
+ }
180
+ function ProgressBar({
181
+ current,
182
+ total,
183
+ label,
184
+ showCount,
185
+ width = 30,
186
+ color = "green"
187
+ }) {
188
+ const percentage = total > 0 ? Math.round(current / total * 100) : 0;
189
+ const filled = total > 0 ? Math.round(current / total * width) : 0;
190
+ const empty = width - filled;
191
+ return /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
192
+ label && /* @__PURE__ */ jsx(Text, { children: label }),
193
+ /* @__PURE__ */ jsx(Text, { color, children: "\u2588".repeat(filled) }),
194
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u2591".repeat(empty) }),
195
+ /* @__PURE__ */ jsxs(Text, { children: [
196
+ percentage,
197
+ "%"
198
+ ] }),
199
+ showCount && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
200
+ current,
201
+ "/",
202
+ total
203
+ ] })
204
+ ] });
205
+ }
206
+ function CascadeTree({
207
+ nodes,
208
+ flat,
209
+ onNodeSelect
210
+ }) {
211
+ const [selectedIndex, setSelectedIndex] = useState(0);
212
+ const allNodes = flattenNodes(nodes);
213
+ useInput((input, key) => {
214
+ if (key.downArrow) {
215
+ setSelectedIndex((s) => Math.min(s + 1, allNodes.length - 1));
216
+ } else if (key.upArrow) {
217
+ setSelectedIndex((s) => Math.max(s - 1, 0));
218
+ } else if (key.return && onNodeSelect) {
219
+ const selectedNode = allNodes[selectedIndex];
220
+ if (selectedNode) {
221
+ onNodeSelect(selectedNode);
222
+ }
223
+ }
224
+ });
225
+ if (nodes.length === 0) {
226
+ return /* @__PURE__ */ jsx(Text, { color: "gray", children: "No cascade" });
227
+ }
228
+ const getStatusIcon2 = (status) => {
229
+ switch (status) {
230
+ case "completed":
231
+ return "\u2713";
232
+ case "running":
233
+ return "\u25D0";
234
+ default:
235
+ return "\u25CB";
236
+ }
237
+ };
238
+ const getStatusColor2 = (status) => {
239
+ switch (status) {
240
+ case "completed":
241
+ return "green";
242
+ case "running":
243
+ return "yellow";
244
+ default:
245
+ return "gray";
246
+ }
247
+ };
248
+ const renderNode = (node, depth = 0) => {
249
+ const indent = flat ? "" : " ".repeat(depth);
250
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
251
+ /* @__PURE__ */ jsxs(Box, { children: [
252
+ /* @__PURE__ */ jsx(Text, { children: indent }),
253
+ /* @__PURE__ */ jsxs(Text, { color: getStatusColor2(node.status), children: [
254
+ getStatusIcon2(node.status),
255
+ " "
256
+ ] }),
257
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: node.type }),
258
+ /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
259
+ ":",
260
+ node.id
261
+ ] })
262
+ ] }),
263
+ !flat && node.children.map((child) => renderNode(child, depth + 1))
264
+ ] }, node.id);
265
+ };
266
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: nodes.map((node) => renderNode(node)) });
267
+ }
268
+ function flattenNodes(nodes) {
269
+ const result = [];
270
+ const traverse = (node) => {
271
+ result.push(node);
272
+ node.children.forEach(traverse);
273
+ };
274
+ nodes.forEach(traverse);
275
+ return result;
276
+ }
277
+ function Table({
278
+ data,
279
+ columns,
280
+ headers
281
+ }) {
282
+ if (data.length === 0) {
283
+ return /* @__PURE__ */ jsx(Text, { color: "gray", children: "No data" });
284
+ }
285
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
286
+ /* @__PURE__ */ jsx(Box, { gap: 2, children: columns.map((col) => /* @__PURE__ */ jsx(Text, { bold: true, children: headers?.[col] ?? String(col) }, String(col))) }),
287
+ data.map((row, index) => /* @__PURE__ */ jsx(Box, { gap: 2, children: columns.map((col) => /* @__PURE__ */ jsx(Text, { children: String(row[col] ?? "") }, String(col))) }, index))
288
+ ] });
289
+ }
290
+ function Input({
291
+ placeholder,
292
+ value: initialValue = "",
293
+ onChange,
294
+ onSubmit
295
+ }) {
296
+ const [value, setValue] = useState(initialValue);
297
+ useInput((input, key) => {
298
+ if (key.return) {
299
+ if (onSubmit) {
300
+ onSubmit(value);
301
+ }
302
+ return;
303
+ }
304
+ if (key.backspace || key.delete) {
305
+ const newValue = value.slice(0, -1);
306
+ setValue(newValue);
307
+ onChange(newValue);
308
+ return;
309
+ }
310
+ if (input && !key.ctrl && !key.meta) {
311
+ const newValue = value + input;
312
+ setValue(newValue);
313
+ onChange(newValue);
314
+ }
315
+ });
316
+ return /* @__PURE__ */ jsxs(Box, { children: [
317
+ /* @__PURE__ */ jsx(Text, { children: value || placeholder || "" }),
318
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: "_" })
319
+ ] });
320
+ }
321
+ var shortcuts = [
322
+ { key: "q", action: "quit" },
323
+ { key: "g", action: "generate" },
324
+ { key: "s", action: "seed" },
325
+ { key: "w", action: "workflow" },
326
+ { key: "l", action: "logs" },
327
+ { key: "?", action: "help" },
328
+ { key: "ESC", action: "back" }
329
+ ];
330
+ function HelpOverlay({ visible, context }) {
331
+ if (!visible) {
332
+ return null;
333
+ }
334
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "single", padding: 1, children: [
335
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "Keyboard Shortcuts" }),
336
+ /* @__PURE__ */ jsx(Text, { children: " " }),
337
+ shortcuts.map(({ key, action }) => /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
338
+ /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
339
+ "[",
340
+ key,
341
+ "]"
342
+ ] }),
343
+ /* @__PURE__ */ jsx(Text, { children: action })
344
+ ] }, key)),
345
+ context && /* @__PURE__ */ jsxs(Fragment, { children: [
346
+ /* @__PURE__ */ jsx(Text, { children: " " }),
347
+ /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
348
+ "Context: ",
349
+ context
350
+ ] })
351
+ ] })
352
+ ] });
353
+ }
354
+
355
+ // cli/dashboard/hooks/index.ts
356
+ import { useState as useState2, useEffect, useCallback as useCallback2 } from "react";
357
+ import { useInput as useInput2 } from "ink";
358
+ function useDb(config) {
359
+ const [connected, setConnected] = useState2(false);
360
+ const [error, setError] = useState2(null);
361
+ useEffect(() => {
362
+ const timer = setTimeout(() => {
363
+ if (config.baseUrl.includes("invalid")) {
364
+ setError("Failed to connect");
365
+ setConnected(false);
366
+ } else {
367
+ setConnected(true);
368
+ setError(null);
369
+ }
370
+ }, 100);
371
+ return () => clearTimeout(timer);
372
+ }, [config.baseUrl]);
373
+ const reconnect = useCallback2(() => {
374
+ setConnected(false);
375
+ setError(null);
376
+ setTimeout(() => setConnected(true), 100);
377
+ }, []);
378
+ return { connected, error, reconnect };
379
+ }
380
+ function useStats(config, options = {}) {
381
+ const [stats, setStats] = useState2(null);
382
+ const [loading, setLoading] = useState2(true);
383
+ const [error, setError] = useState2(null);
384
+ const fetchStats = useCallback2(async () => {
385
+ if (config.baseUrl.includes("invalid")) {
386
+ setError("Failed to fetch stats");
387
+ setLoading(false);
388
+ return;
389
+ }
390
+ setLoading(false);
391
+ setStats({
392
+ totalRecords: 150,
393
+ typeCount: 3,
394
+ recentGenerations: 25,
395
+ lastActivity: /* @__PURE__ */ new Date(),
396
+ pendingJobs: 2,
397
+ activeWorkflows: 1
398
+ });
399
+ }, [config.baseUrl]);
400
+ useEffect(() => {
401
+ fetchStats();
402
+ if (options.refreshInterval) {
403
+ const interval = setInterval(fetchStats, options.refreshInterval);
404
+ return () => clearInterval(interval);
405
+ }
406
+ }, [fetchStats, options.refreshInterval]);
407
+ return { stats, loading, error, refresh: fetchStats };
408
+ }
409
+ function useActivity(config, options = {}) {
410
+ const [activity, setActivity] = useState2([]);
411
+ const [loading, setLoading] = useState2(true);
412
+ const [error, setError] = useState2(null);
413
+ useEffect(() => {
414
+ setLoading(false);
415
+ const events = [
416
+ { id: "1", type: "generate", entity: "Company", entityId: "company-1", timestamp: /* @__PURE__ */ new Date(), status: "completed" }
417
+ ];
418
+ setActivity(options.limit ? events.slice(0, options.limit) : events);
419
+ }, [config.baseUrl, options.limit]);
420
+ return { activity, loading, error };
421
+ }
422
+ function useGeneration(config) {
423
+ const [generating, setGenerating] = useState2(false);
424
+ const [progress, setProgress] = useState2(null);
425
+ const [error, setError] = useState2(null);
426
+ const generate = useCallback2(async (type, options) => {
427
+ setGenerating(true);
428
+ setError(null);
429
+ const total = options?.count ?? 1;
430
+ setProgress({ current: 0, total });
431
+ for (let i = 1; i <= total; i++) {
432
+ await new Promise((resolve) => setTimeout(resolve, 10));
433
+ setProgress({ current: i, total });
434
+ }
435
+ setGenerating(false);
436
+ setProgress(null);
437
+ }, []);
438
+ return { generate, generating, progress, error };
439
+ }
440
+ function useKeyboard(handlers, options = {}) {
441
+ const [active, setActive] = useState2(!options.disabled);
442
+ useInput2((input, key) => {
443
+ if (options.disabled) return;
444
+ if (input === "q" && handlers.onQuit) {
445
+ handlers.onQuit();
446
+ } else if (input === "g" && handlers.onGenerate) {
447
+ handlers.onGenerate();
448
+ } else if (input === "s" && handlers.onSeed) {
449
+ handlers.onSeed();
450
+ } else if (input === "w" && handlers.onWorkflow) {
451
+ handlers.onWorkflow();
452
+ } else if (input === "?" && handlers.onHelp) {
453
+ handlers.onHelp();
454
+ } else if (input === "l" && handlers.onLogs) {
455
+ handlers.onLogs();
456
+ } else if (input === "c" && handlers.onCascade) {
457
+ handlers.onCascade();
458
+ } else if (input === "/" && handlers.onQuery) {
459
+ handlers.onQuery();
460
+ } else if (input === "r" && handlers.onRetry) {
461
+ handlers.onRetry();
462
+ } else if (key.escape && handlers.onBack) {
463
+ handlers.onBack();
464
+ } else if (key.upArrow && handlers.onNavigateUp) {
465
+ handlers.onNavigateUp();
466
+ } else if (key.downArrow && handlers.onNavigateDown) {
467
+ handlers.onNavigateDown();
468
+ } else if (key.return && handlers.onSelect) {
469
+ handlers.onSelect();
470
+ }
471
+ });
472
+ return { active };
473
+ }
474
+ function useCascade(config) {
475
+ const [nodes, setNodes] = useState2([]);
476
+ const [loading, setLoading] = useState2(true);
477
+ const [error, setError] = useState2(null);
478
+ useEffect(() => {
479
+ setLoading(false);
480
+ setNodes([]);
481
+ }, [config.baseUrl]);
482
+ const runningCount = nodes.filter((n) => n.status === "running").length;
483
+ return { nodes, loading, error, runningCount };
484
+ }
485
+ function useWorkflow(config) {
486
+ const [workflow, setWorkflow] = useState2(null);
487
+ const [loading, setLoading] = useState2(true);
488
+ const [error, setError] = useState2(null);
489
+ useEffect(() => {
490
+ setLoading(false);
491
+ }, [config.baseUrl]);
492
+ const start = useCallback2(async (name) => {
493
+ setWorkflow({
494
+ id: `wf-${Date.now()}`,
495
+ name,
496
+ status: "running",
497
+ currentStep: 0,
498
+ totalSteps: 1,
499
+ startedAt: /* @__PURE__ */ new Date(),
500
+ steps: [{ name: "Start", status: "running" }]
501
+ });
502
+ }, []);
503
+ const stop = useCallback2(async () => {
504
+ setWorkflow(null);
505
+ }, []);
506
+ const pause = useCallback2(async () => {
507
+ if (workflow) {
508
+ setWorkflow({ ...workflow, status: "pending" });
509
+ }
510
+ }, [workflow]);
511
+ return { workflow, loading, error, start, stop, pause };
512
+ }
513
+ function useLogs(config, options = {}) {
514
+ const [logs, setLogs] = useState2([]);
515
+ const [loading, setLoading] = useState2(true);
516
+ const [error, setError] = useState2(null);
517
+ useEffect(() => {
518
+ setLoading(false);
519
+ const allLogs = [
520
+ { level: "info", message: "Started", timestamp: /* @__PURE__ */ new Date() },
521
+ { level: "error", message: "Failed", timestamp: /* @__PURE__ */ new Date() }
522
+ ];
523
+ if (options.level) {
524
+ setLogs(allLogs.filter((l) => l.level === options.level));
525
+ } else {
526
+ setLogs(allLogs);
527
+ }
528
+ }, [config.baseUrl, options.level]);
529
+ return { logs, loading, error };
530
+ }
531
+
532
+ // cli/dashboard/views/index.tsx
533
+ import { Box as Box2, Text as Text2 } from "ink";
534
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
535
+ function MainView({ stats, types, activity }) {
536
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", gap: 1, children: [
537
+ /* @__PURE__ */ jsx2(Stats, { stats }),
538
+ /* @__PURE__ */ jsxs2(Box2, { gap: 4, children: [
539
+ /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
540
+ /* @__PURE__ */ jsx2(Text2, { bold: true, children: "Types" }),
541
+ types.length > 0 ? /* @__PURE__ */ jsx2(TypeList, { types }) : /* @__PURE__ */ jsx2(Text2, { color: "gray", children: "No types" })
542
+ ] }),
543
+ /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
544
+ /* @__PURE__ */ jsx2(Text2, { bold: true, children: "Activity" }),
545
+ activity.length > 0 ? /* @__PURE__ */ jsx2(ActivityFeed, { events: activity }) : /* @__PURE__ */ jsx2(Text2, { color: "gray", children: "No activity" })
546
+ ] })
547
+ ] })
548
+ ] });
549
+ }
550
+ function GenerateView({
551
+ types,
552
+ onGenerate,
553
+ showCountInput,
554
+ generating
555
+ }) {
556
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", gap: 1, children: [
557
+ /* @__PURE__ */ jsx2(Text2, { bold: true, children: "Generate" }),
558
+ generating ? /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "Generating..." }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
559
+ /* @__PURE__ */ jsx2(TypeList, { types, onSelect: (t) => onGenerate(t.name) }),
560
+ showCountInput && /* @__PURE__ */ jsx2(Text2, { color: "gray", children: "Enter count..." })
561
+ ] })
562
+ ] });
563
+ }
564
+ function CascadeView({ nodes, onNodeSelect }) {
565
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", gap: 1, children: [
566
+ /* @__PURE__ */ jsx2(Text2, { bold: true, children: "Cascade" }),
567
+ /* @__PURE__ */ jsx2(CascadeTree, { nodes, onNodeSelect })
568
+ ] });
569
+ }
570
+ function SeedView({ seedFiles, onSeed, progress }) {
571
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", gap: 1, children: [
572
+ /* @__PURE__ */ jsx2(Text2, { bold: true, children: "Seeds" }),
573
+ progress && /* @__PURE__ */ jsx2(ProgressBar, { current: progress.current, total: progress.total, showCount: true }),
574
+ seedFiles.length > 0 ? /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: seedFiles.map((file) => /* @__PURE__ */ jsx2(Text2, { children: file }, file)) }) : /* @__PURE__ */ jsx2(Text2, { color: "gray", children: "No seed files" })
575
+ ] });
576
+ }
577
+ function WorkflowView({ workflow }) {
578
+ if (!workflow) {
579
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
580
+ /* @__PURE__ */ jsx2(Text2, { bold: true, children: "Workflow" }),
581
+ /* @__PURE__ */ jsx2(Text2, { color: "gray", children: "No active workflow" })
582
+ ] });
583
+ }
584
+ const getStepIcon = (status) => {
585
+ switch (status) {
586
+ case "completed":
587
+ return "\u2713";
588
+ case "running":
589
+ return "\u25D0";
590
+ default:
591
+ return "\u25CB";
592
+ }
593
+ };
594
+ const getStepColor = (status) => {
595
+ switch (status) {
596
+ case "completed":
597
+ return "green";
598
+ case "running":
599
+ return "yellow";
600
+ default:
601
+ return "gray";
602
+ }
603
+ };
604
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", gap: 1, children: [
605
+ /* @__PURE__ */ jsxs2(Text2, { bold: true, children: [
606
+ "Workflow: ",
607
+ workflow.name
608
+ ] }),
609
+ /* @__PURE__ */ jsx2(
610
+ ProgressBar,
611
+ {
612
+ current: workflow.currentStep,
613
+ total: workflow.totalSteps,
614
+ showCount: true
615
+ }
616
+ ),
617
+ /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: workflow.steps.map((step, index) => /* @__PURE__ */ jsxs2(Box2, { gap: 1, children: [
618
+ /* @__PURE__ */ jsx2(Text2, { color: getStepColor(step.status), children: getStepIcon(step.status) }),
619
+ /* @__PURE__ */ jsx2(Text2, { children: step.name })
620
+ ] }, index)) })
621
+ ] });
622
+ }
623
+ function QueryView({ db, results, searching }) {
624
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", gap: 1, children: [
625
+ /* @__PURE__ */ jsx2(Text2, { bold: true, children: "Query" }),
626
+ /* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
627
+ "Search ",
628
+ db.namespace,
629
+ "..."
630
+ ] }),
631
+ searching && /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "Searching..." }),
632
+ results !== void 0 && results.length === 0 && /* @__PURE__ */ jsx2(Text2, { color: "gray", children: "No results found" }),
633
+ results && results.length > 0 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: results.map((result) => /* @__PURE__ */ jsxs2(Box2, { gap: 1, children: [
634
+ /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: result.type }),
635
+ /* @__PURE__ */ jsx2(Text2, { children: result.name })
636
+ ] }, result.id)) })
637
+ ] });
638
+ }
639
+ function LogsView({ logs, filter, autoScroll }) {
640
+ let filtered = logs;
641
+ if (filter) {
642
+ filtered = logs.filter((log) => log.level === filter);
643
+ }
644
+ const getLevelColor = (level) => {
645
+ switch (level) {
646
+ case "error":
647
+ return "red";
648
+ case "warn":
649
+ return "yellow";
650
+ case "info":
651
+ return "blue";
652
+ default:
653
+ return "gray";
654
+ }
655
+ };
656
+ if (filtered.length === 0) {
657
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
658
+ /* @__PURE__ */ jsx2(Text2, { bold: true, children: "Logs" }),
659
+ /* @__PURE__ */ jsx2(Text2, { color: "gray", children: "No logs" })
660
+ ] });
661
+ }
662
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", gap: 1, children: [
663
+ /* @__PURE__ */ jsx2(Text2, { bold: true, children: "Logs" }),
664
+ filtered.map((log, index) => /* @__PURE__ */ jsxs2(Box2, { gap: 1, children: [
665
+ /* @__PURE__ */ jsx2(Text2, { color: "gray", children: log.timestamp.toLocaleTimeString("en-US", {
666
+ hour: "2-digit",
667
+ minute: "2-digit",
668
+ second: "2-digit",
669
+ hour12: false
670
+ }) }),
671
+ /* @__PURE__ */ jsxs2(Text2, { color: getLevelColor(log.level), children: [
672
+ "[",
673
+ log.level.toUpperCase(),
674
+ "]"
675
+ ] }),
676
+ /* @__PURE__ */ jsx2(Text2, { children: log.message })
677
+ ] }, index))
678
+ ] });
679
+ }
680
+
681
+ // cli/dashboard/App.tsx
682
+ import React2, { useState as useState3, useCallback as useCallback3 } from "react";
683
+ import { Box as Box3, Text as Text3, useApp } from "ink";
684
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
685
+ var ErrorBoundary = class extends React2.Component {
686
+ constructor(props) {
687
+ super(props);
688
+ this.state = { hasError: false };
689
+ }
690
+ static getDerivedStateFromError(error) {
691
+ return { hasError: true, error };
692
+ }
693
+ componentDidCatch(error, errorInfo) {
694
+ console.error("Dashboard error:", error, errorInfo);
695
+ }
696
+ render() {
697
+ if (this.state.hasError) {
698
+ return this.props.fallback ?? /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
699
+ /* @__PURE__ */ jsx3(Text3, { color: "red", children: "Something went wrong" }),
700
+ /* @__PURE__ */ jsx3(Text3, { color: "gray", children: this.state.error?.message })
701
+ ] });
702
+ }
703
+ return this.props.children;
704
+ }
705
+ };
706
+ function App({
707
+ db,
708
+ theme,
709
+ onQuit,
710
+ onAnnounce,
711
+ onRetry,
712
+ connectionError,
713
+ children
714
+ }) {
715
+ const { exit } = useApp();
716
+ const [currentView, setCurrentView] = useState3("main");
717
+ const [showHelp, setShowHelp] = useState3(false);
718
+ const { stats, loading: statsLoading } = useStats(db);
719
+ const { activity } = useActivity(db);
720
+ const { nodes: cascadeNodes } = useCascade(db);
721
+ const { workflow } = useWorkflow(db);
722
+ const { generate, generating } = useGeneration(db);
723
+ const [types] = useState3(
724
+ () => Object.keys(db.schema).map((name) => ({
725
+ name,
726
+ count: Math.floor(Math.random() * 100),
727
+ lastGenerated: /* @__PURE__ */ new Date()
728
+ }))
729
+ );
730
+ const handleQuit = useCallback3(() => {
731
+ if (onQuit) {
732
+ onQuit();
733
+ }
734
+ try {
735
+ exit();
736
+ } catch {
737
+ }
738
+ }, [onQuit, exit]);
739
+ const handleBack = useCallback3(() => {
740
+ if (showHelp) {
741
+ setShowHelp(false);
742
+ } else if (currentView !== "main") {
743
+ setCurrentView("main");
744
+ }
745
+ }, [showHelp, currentView]);
746
+ const handleViewChange = useCallback3(
747
+ (view) => {
748
+ setCurrentView(view);
749
+ onAnnounce?.(`${view.charAt(0).toUpperCase() + view.slice(1)} view`);
750
+ },
751
+ [onAnnounce]
752
+ );
753
+ useKeyboard({
754
+ onQuit: handleQuit,
755
+ onGenerate: () => handleViewChange("generate"),
756
+ onSeed: () => handleViewChange("seed"),
757
+ onWorkflow: () => handleViewChange("workflow"),
758
+ onCascade: () => handleViewChange("cascade"),
759
+ onQuery: () => handleViewChange("query"),
760
+ onLogs: () => handleViewChange("logs"),
761
+ onHelp: () => setShowHelp((h) => !h),
762
+ onBack: handleBack,
763
+ onRetry
764
+ });
765
+ const handleGenerate = useCallback3(
766
+ async (type, options) => {
767
+ await generate(type, options);
768
+ },
769
+ [generate]
770
+ );
771
+ const renderView = () => {
772
+ if (connectionError) {
773
+ return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
774
+ /* @__PURE__ */ jsx3(Text3, { color: "red", children: connectionError }),
775
+ /* @__PURE__ */ jsx3(Text3, { color: "gray", children: "Press [r] to retry" })
776
+ ] });
777
+ }
778
+ if (statsLoading) {
779
+ return /* @__PURE__ */ jsx3(Text3, { color: "gray", children: "Loading..." });
780
+ }
781
+ switch (currentView) {
782
+ case "generate":
783
+ return /* @__PURE__ */ jsx3(
784
+ GenerateView,
785
+ {
786
+ types,
787
+ onGenerate: handleGenerate,
788
+ generating
789
+ }
790
+ );
791
+ case "cascade":
792
+ return /* @__PURE__ */ jsx3(CascadeView, { nodes: cascadeNodes });
793
+ case "seed":
794
+ return /* @__PURE__ */ jsx3(SeedView, { seedFiles: [], onSeed: () => {
795
+ } });
796
+ case "workflow":
797
+ return /* @__PURE__ */ jsx3(WorkflowView, { workflow });
798
+ case "query":
799
+ return /* @__PURE__ */ jsx3(QueryView, { db });
800
+ case "logs":
801
+ return /* @__PURE__ */ jsx3(LogsView, { logs: [] });
802
+ default:
803
+ return /* @__PURE__ */ jsx3(
804
+ MainView,
805
+ {
806
+ stats,
807
+ types,
808
+ activity
809
+ }
810
+ );
811
+ }
812
+ };
813
+ return /* @__PURE__ */ jsx3(ErrorBoundary, { children: /* @__PURE__ */ jsxs3(
814
+ Layout,
815
+ {
816
+ header: /* @__PURE__ */ jsx3(Header, { namespace: db.namespace, view: currentView !== "main" ? currentView : void 0 }),
817
+ footer: /* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text3, { color: "gray", children: "[g]enerate [s]eed [w]orkflow [c]ascade [/]query [l]ogs [?]help [q]uit" }) }),
818
+ children: [
819
+ showHelp ? /* @__PURE__ */ jsx3(HelpOverlay, { visible: true, context: currentView }) : renderView(),
820
+ children
821
+ ]
822
+ }
823
+ ) });
824
+ }
825
+
826
+ export {
827
+ Layout,
828
+ Header,
829
+ Stats,
830
+ TypeList,
831
+ ActivityFeed,
832
+ ProgressBar,
833
+ CascadeTree,
834
+ Table,
835
+ Input,
836
+ HelpOverlay,
837
+ useDb,
838
+ useStats,
839
+ useActivity,
840
+ useGeneration,
841
+ useKeyboard,
842
+ useCascade,
843
+ useWorkflow,
844
+ useLogs,
845
+ MainView,
846
+ GenerateView,
847
+ CascadeView,
848
+ SeedView,
849
+ WorkflowView,
850
+ QueryView,
851
+ LogsView,
852
+ App
853
+ };
854
+ //# sourceMappingURL=chunk-XLSYCQPG.js.map