@hoox-sh/hoox-tui 0.2.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.
- package/README.md +247 -0
- package/bin/hoox-tui.js +35 -0
- package/dist/main.js +17594 -0
- package/package.json +72 -0
- package/src/app.tsx +696 -0
- package/src/cli-bridge-test-double.ts +212 -0
- package/src/components/layout/layout.test.tsx +205 -0
- package/src/components/layout/sidebar.tsx +69 -0
- package/src/components/layout/statusbar.test.tsx +423 -0
- package/src/components/layout/statusbar.tsx +348 -0
- package/src/components/shared/animated-border.tsx +58 -0
- package/src/components/shared/chrome.test.tsx +29 -0
- package/src/components/shared/command-palette.tsx +361 -0
- package/src/components/shared/cool-brackets.tsx +75 -0
- package/src/components/shared/crash-screen.tsx +167 -0
- package/src/components/shared/error-boundary.tsx +99 -0
- package/src/components/shared/keybinding-hint.tsx +37 -0
- package/src/components/shared/panel.tsx +61 -0
- package/src/components/shared/quit-modal.tsx +65 -0
- package/src/components/shared/shared.test.tsx +538 -0
- package/src/components/shared/spinner.tsx +85 -0
- package/src/components/shared/status-dot.tsx +54 -0
- package/src/components/shared/view-header.tsx +53 -0
- package/src/components/ui/connection-toasts.test.ts +50 -0
- package/src/components/ui/connection-toasts.ts +215 -0
- package/src/components/ui/dialog.tsx +281 -0
- package/src/components/ui/select.tsx +197 -0
- package/src/components/ui/toast.tsx +185 -0
- package/src/components/views/ai-chat.test.tsx +81 -0
- package/src/components/views/ai-chat.tsx +576 -0
- package/src/components/views/config-editor/action-bar.tsx +102 -0
- package/src/components/views/config-editor/code-editor.tsx +597 -0
- package/src/components/views/config-editor/file-tree.tsx +113 -0
- package/src/components/views/config-editor/types.ts +37 -0
- package/src/components/views/config-editor.test.tsx +465 -0
- package/src/components/views/config-editor.tsx +709 -0
- package/src/components/views/dashboard/alerts-panel.tsx +154 -0
- package/src/components/views/dashboard/auto-repair-panel.tsx +229 -0
- package/src/components/views/dashboard/model-health-section.tsx +276 -0
- package/src/components/views/dashboard/pyne-health-section.tsx +112 -0
- package/src/components/views/dashboard.test.tsx +347 -0
- package/src/components/views/dashboard.tsx +647 -0
- package/src/components/views/db-query.test.tsx +115 -0
- package/src/components/views/db-query.tsx +849 -0
- package/src/components/views/edge-topology.test.tsx +198 -0
- package/src/components/views/edge-topology.tsx +572 -0
- package/src/components/views/kv-viewer.test.tsx +241 -0
- package/src/components/views/kv-viewer.tsx +717 -0
- package/src/components/views/logs-viewer.test.tsx +273 -0
- package/src/components/views/logs-viewer.tsx +616 -0
- package/src/components/views/queue-depth.test.tsx +221 -0
- package/src/components/views/queue-depth.tsx +376 -0
- package/src/components/views/secrets-viewer.test.tsx +65 -0
- package/src/components/views/secrets-viewer.tsx +548 -0
- package/src/components/views/service-manager.test.tsx +358 -0
- package/src/components/views/service-manager.tsx +946 -0
- package/src/components/views/settings.test.tsx +648 -0
- package/src/components/views/settings.tsx +1497 -0
- package/src/components/views/setup-wizard.test.tsx +297 -0
- package/src/components/views/setup-wizard.tsx +1321 -0
- package/src/components/views/trade-monitor.test.tsx +592 -0
- package/src/components/views/trade-monitor.tsx +745 -0
- package/src/components/views/worker-detail.test.tsx +289 -0
- package/src/components/views/worker-detail.tsx +676 -0
- package/src/components/views/worker-settings.test.tsx +43 -0
- package/src/components/views/worker-settings.tsx +563 -0
- package/src/components/views/workers-overview.test.tsx +260 -0
- package/src/components/views/workers-overview.tsx +631 -0
- package/src/hooks/hooks.test.ts +72 -0
- package/src/hooks/index.ts +11 -0
- package/src/hooks/renderer-ref.ts +22 -0
- package/src/hooks/use-keyboard.ts +130 -0
- package/src/hooks/use-polling.ts +73 -0
- package/src/hooks/use-service-data.ts +18 -0
- package/src/main.tsx +117 -0
- package/src/network-test-double.ts +133 -0
- package/src/opentui-augment.d.ts +45 -0
- package/src/opentui-jsx.d.ts +70 -0
- package/src/services/cli-bridge/index.ts +1662 -0
- package/src/services/cli-bridge/standalone.ts +315 -0
- package/src/services/cli-bridge/types.ts +307 -0
- package/src/services/cli-bridge.test.ts +406 -0
- package/src/services/clipboard.test.ts +57 -0
- package/src/services/clipboard.ts +180 -0
- package/src/services/dashboard-settings-loader.ts +31 -0
- package/src/services/dev-log.test.ts +168 -0
- package/src/services/dev-log.ts +194 -0
- package/src/services/hoox-path-service.test.ts +183 -0
- package/src/services/hoox-path-service.ts +185 -0
- package/src/services/tui-connection.test.ts +212 -0
- package/src/services/tui-connection.ts +236 -0
- package/src/services/tui-storage.test.ts +92 -0
- package/src/services/tui-storage.ts +86 -0
- package/src/stores/config-store.test.ts +360 -0
- package/src/stores/service-store.test.ts +1026 -0
- package/src/stores/session-restore.test.ts +134 -0
- package/src/stores/ui-store.test.ts +276 -0
- package/src/test-setup.ts +265 -0
- package/src/test-utils.ts +179 -0
- package/src/types.ts +153 -0
- package/src/utils/colors.test.ts +326 -0
- package/src/utils/formatters.test.ts +236 -0
- package/src/view-registry.test.ts +132 -0
- package/src/view-registry.tsx +368 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 HOOX · HOOX · jango-blockchained (hoox-sh)
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Tests for DbQueryView — registration + source contracts.
|
|
8
|
+
*
|
|
9
|
+
* Isolation strategy:
|
|
10
|
+
* - No OpenTUI renderer (keeps this suite lightweight).
|
|
11
|
+
* - CLI is the process-wide test double from test-setup; real SQL
|
|
12
|
+
* validator coverage lives in services/cli-bridge.test.ts.
|
|
13
|
+
* - Source-level checks against view-registry.tsx / app.tsx / db-query.tsx.
|
|
14
|
+
*/
|
|
15
|
+
import { describe, it, expect } from "bun:test";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import {
|
|
18
|
+
DbQueryView,
|
|
19
|
+
formatCell,
|
|
20
|
+
compareCells,
|
|
21
|
+
sanitizeCellText,
|
|
22
|
+
MAX_VISIBLE_ROWS,
|
|
23
|
+
MAX_HISTORY,
|
|
24
|
+
} from "./db-query";
|
|
25
|
+
import { validateReadOnlySql } from "../../services/cli-bridge";
|
|
26
|
+
|
|
27
|
+
const VIEWS_DIR = import.meta.dir;
|
|
28
|
+
const TUI_SRC = join(VIEWS_DIR, "../..");
|
|
29
|
+
|
|
30
|
+
describe("DbQueryView", () => {
|
|
31
|
+
it("is a function component", () => {
|
|
32
|
+
expect(DbQueryView).toBeInstanceOf(Function);
|
|
33
|
+
expect(DbQueryView.name).toBe("DbQueryView");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("wires client-side validateReadOnlySql before CLI execution", async () => {
|
|
37
|
+
const src = await Bun.file(join(VIEWS_DIR, "db-query.tsx")).text();
|
|
38
|
+
expect(src).toContain("validateReadOnlySql");
|
|
39
|
+
expect(src).toContain("cliBridge.dbQuery");
|
|
40
|
+
// Must surface validation failure as queryError (UI cannot bypass)
|
|
41
|
+
expect(src).toContain("not read-only");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("formats NULL values distinctly in cells (contract)", () => {
|
|
45
|
+
expect(formatCell(null, 20)).toBe("NULL");
|
|
46
|
+
expect(formatCell(undefined, 20)).toBe("NULL");
|
|
47
|
+
expect(formatCell(42, 20)).toBe("42");
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("sanitizes cell text and collapses newlines", () => {
|
|
51
|
+
expect(sanitizeCellText("a\x1bb")).toBe("ab");
|
|
52
|
+
expect(formatCell("line1\nline2", 40)).toBe("line1 line2");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("sorts nulls last and numbers numerically", () => {
|
|
56
|
+
expect(compareCells(null, 1, "asc")).toBe(1);
|
|
57
|
+
expect(compareCells(1, null, "asc")).toBe(-1);
|
|
58
|
+
expect(compareCells(2, 10, "asc")).toBeLessThan(0);
|
|
59
|
+
expect(compareCells(2, 10, "desc")).toBeGreaterThan(0);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("rejects write SQL before any CLI call (defence in depth)", () => {
|
|
63
|
+
expect(validateReadOnlySql("DROP TABLE users").readonly).toBe(false);
|
|
64
|
+
expect(validateReadOnlySql("SELECT 1").readonly).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("caps visible result rows and history size", () => {
|
|
68
|
+
expect(MAX_VISIBLE_ROWS).toBe(200);
|
|
69
|
+
expect(MAX_HISTORY).toBe(20);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("is registered as ViewId db-query in view-registry factory", async () => {
|
|
73
|
+
const registry = await Bun.file(join(TUI_SRC, "view-registry.tsx")).text();
|
|
74
|
+
expect(registry).toContain('id: "db-query"');
|
|
75
|
+
expect(registry).toContain("DbQueryView");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("is registered in the command palette (view-registry)", async () => {
|
|
79
|
+
const registry = await Bun.file(join(TUI_SRC, "view-registry.tsx")).text();
|
|
80
|
+
expect(registry).toContain('id: "db-query"');
|
|
81
|
+
expect(registry).toMatch(/db-query[\s\S]{0,160}paletteShortcut:\s*"\^#q"/);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("has a sidebar nav item via view-registry short labels", async () => {
|
|
85
|
+
const registry = await Bun.file(join(TUI_SRC, "view-registry.tsx")).text();
|
|
86
|
+
expect(registry).toContain('id: "db-query"');
|
|
87
|
+
expect(registry).toContain("DB QUERY");
|
|
88
|
+
// Sidebar consumes SIDEBAR_ITEMS from the registry (single source of truth)
|
|
89
|
+
const sidebar = await Bun.file(
|
|
90
|
+
join(TUI_SRC, "components/layout/sidebar.tsx")
|
|
91
|
+
).text();
|
|
92
|
+
expect(sidebar).toContain("SIDEBAR_ITEMS");
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("uses Ctrl+Alt+Q chord via registry map in app keyboard handler", async () => {
|
|
96
|
+
const registry = await Bun.file(join(TUI_SRC, "view-registry.tsx")).text();
|
|
97
|
+
expect(registry).toContain('id: "db-query"');
|
|
98
|
+
expect(registry).toContain("getCtrlAltViewMap");
|
|
99
|
+
const app = await Bun.file(join(TUI_SRC, "app.tsx")).text();
|
|
100
|
+
expect(app).toContain("getCtrlAltViewMap");
|
|
101
|
+
expect(app).toContain("CTRL_ALT_VIEWS");
|
|
102
|
+
expect(app).toMatch(/key\.ctrl\s*&&\s*key\.alt/);
|
|
103
|
+
expect(app).toContain("CTRL_ALT_VIEWS[name]");
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("persists query history via TuiStateFiles.dbQueryHistory (max 20)", async () => {
|
|
107
|
+
const src = await Bun.file(join(VIEWS_DIR, "db-query.tsx")).text();
|
|
108
|
+
expect(src).toContain("TuiStateFiles.dbQueryHistory");
|
|
109
|
+
expect(src).toMatch(/MAX_HISTORY\s*=\s*20/);
|
|
110
|
+
const storage = await Bun.file(
|
|
111
|
+
join(TUI_SRC, "services/tui-storage.ts")
|
|
112
|
+
).text();
|
|
113
|
+
expect(storage).toContain('dbQueryHistory: "db-query-history.json"');
|
|
114
|
+
});
|
|
115
|
+
});
|