@deaquinodev/querky 0.4.8 → 0.4.9
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/dist/index.js +413 -508
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// src/index.tsx
|
|
4
4
|
import { useState as useState6, useEffect as useEffect5 } from "react";
|
|
5
5
|
import { parseArgs } from "util";
|
|
6
|
-
import { render, Box as
|
|
6
|
+
import { render, Box as Box7, Text as Text7 } from "ink";
|
|
7
7
|
|
|
8
8
|
// src/db/client.ts
|
|
9
9
|
import { Client } from "pg";
|
|
@@ -81,7 +81,7 @@ var SqliteDbClient = class {
|
|
|
81
81
|
const stmt = this.db.prepare(sql);
|
|
82
82
|
if (stmt.reader) {
|
|
83
83
|
const rows = stmt.all();
|
|
84
|
-
const fields = stmt.columns().map((
|
|
84
|
+
const fields = stmt.columns().map((c2) => c2.name);
|
|
85
85
|
return { fields, rows, rowCount: rows.length };
|
|
86
86
|
}
|
|
87
87
|
const info = stmt.run();
|
|
@@ -197,7 +197,7 @@ import { useState as useState4, useEffect as useEffect4, useRef as useRef2 } fro
|
|
|
197
197
|
import { writeFileSync as writeFileSync5 } from "fs";
|
|
198
198
|
import { homedir as homedir4 } from "os";
|
|
199
199
|
import { join as join5 } from "path";
|
|
200
|
-
import { Box as
|
|
200
|
+
import { Box as Box5, Static, Text as Text5, useApp, useInput as useInput2, useStdin as useStdin2 } from "ink";
|
|
201
201
|
|
|
202
202
|
// src/db/query.ts
|
|
203
203
|
async function runQuery(client, sql) {
|
|
@@ -741,10 +741,10 @@ var BUILTIN_COMMAND_LIST = Object.entries(COMMANDS).map(([name, cmd]) => ({
|
|
|
741
741
|
description: cmd.description
|
|
742
742
|
}));
|
|
743
743
|
function getCompletions(partial, aliases = {}) {
|
|
744
|
-
if (partial.length === 0) return BUILTIN_COMMAND_LIST.map((
|
|
744
|
+
if (partial.length === 0) return BUILTIN_COMMAND_LIST.map((c2) => c2.name);
|
|
745
745
|
const tokenLower = partial.toLowerCase();
|
|
746
746
|
const candidates = [
|
|
747
|
-
...BUILTIN_COMMAND_LIST.map((
|
|
747
|
+
...BUILTIN_COMMAND_LIST.map((c2) => c2.name),
|
|
748
748
|
...Object.keys(aliases).filter((n) => !COMMANDS[n])
|
|
749
749
|
];
|
|
750
750
|
return candidates.map((n) => ({ n, score: fuzzyScore(tokenLower, n.toLowerCase()) })).filter(({ score }) => score >= 0).sort((a, b) => b.score - a.score).map(({ n }) => n);
|
|
@@ -831,7 +831,7 @@ async function fetchErd(client, driver) {
|
|
|
831
831
|
if (!tableMap.has(tableName)) tableMap.set(tableName, []);
|
|
832
832
|
const cols = tableMap.get(tableName);
|
|
833
833
|
const colName = String(row["column_name"] ?? "");
|
|
834
|
-
if (cols.some((
|
|
834
|
+
if (cols.some((c2) => c2.name === colName)) continue;
|
|
835
835
|
cols.push({
|
|
836
836
|
name: colName,
|
|
837
837
|
type: String(row["data_type"] ?? ""),
|
|
@@ -1523,7 +1523,7 @@ function SqlLine({ text, bg }) {
|
|
|
1523
1523
|
const tokens = tokenizeSql(text);
|
|
1524
1524
|
return /* @__PURE__ */ jsx(Fragment, { children: tokens.map((tok, i) => /* @__PURE__ */ jsx(Text, { backgroundColor: bg, color: sqlTokenColor(tok.type), children: tok.text }, i)) });
|
|
1525
1525
|
}
|
|
1526
|
-
function SqlHighlightedInput({ text, cursorAt, mode, pad
|
|
1526
|
+
function SqlHighlightedInput({ text, cursorAt, mode, pad }) {
|
|
1527
1527
|
const tokens = tokenizeSql(text);
|
|
1528
1528
|
const parts = [];
|
|
1529
1529
|
let pos = 0;
|
|
@@ -1557,7 +1557,7 @@ function SqlHighlightedInput({ text, cursorAt, mode, pad: pad2 }) {
|
|
|
1557
1557
|
parts.push(/* @__PURE__ */ jsx(Text, { backgroundColor: ACCENT, color: BG, bold: true, children: " " }, "c"));
|
|
1558
1558
|
}
|
|
1559
1559
|
}
|
|
1560
|
-
parts.push(/* @__PURE__ */ jsx(Text, { backgroundColor: BG, children:
|
|
1560
|
+
parts.push(/* @__PURE__ */ jsx(Text, { backgroundColor: BG, children: pad }, "pad"));
|
|
1561
1561
|
return /* @__PURE__ */ jsx(Fragment, { children: parts });
|
|
1562
1562
|
}
|
|
1563
1563
|
var HINTS = {
|
|
@@ -1586,7 +1586,7 @@ var HINTS = {
|
|
|
1586
1586
|
["/toggle-vim-mode", "ENABLE VIM"]
|
|
1587
1587
|
]
|
|
1588
1588
|
};
|
|
1589
|
-
var BUILTIN_DESC_MAP = Object.fromEntries(BUILTIN_COMMAND_LIST.map((
|
|
1589
|
+
var BUILTIN_DESC_MAP = Object.fromEntries(BUILTIN_COMMAND_LIST.map((c2) => [c2.name, c2.description]));
|
|
1590
1590
|
function QueryInput({ onSubmit, isLoading, onModeChange, onShellModeChange, vimEnabled = true, history = [], aliases = {}, schema }) {
|
|
1591
1591
|
function handleTab(current) {
|
|
1592
1592
|
if (!current.startsWith("/")) return null;
|
|
@@ -1752,82 +1752,6 @@ import { Box as Box3, Text as Text3 } from "ink";
|
|
|
1752
1752
|
// src/ui/components/Table.tsx
|
|
1753
1753
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
1754
1754
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1755
|
-
var COL_PAD = 1;
|
|
1756
|
-
var INDIGO = "#818cf8";
|
|
1757
|
-
var BORDER = "white";
|
|
1758
|
-
var NULL_COLOR = "#6366f1";
|
|
1759
|
-
var NULL_MARKER = "\u2205";
|
|
1760
|
-
function isNull(val) {
|
|
1761
|
-
return val === null || val === void 0;
|
|
1762
|
-
}
|
|
1763
|
-
function cellValue(val) {
|
|
1764
|
-
if (isNull(val)) return NULL_MARKER;
|
|
1765
|
-
if (val instanceof Date) return val.toISOString();
|
|
1766
|
-
if (typeof val === "object") return JSON.stringify(val);
|
|
1767
|
-
return String(val);
|
|
1768
|
-
}
|
|
1769
|
-
function colWidths(columns, rows) {
|
|
1770
|
-
return columns.map((col) => {
|
|
1771
|
-
const dataMax = rows.reduce(
|
|
1772
|
-
(max, row) => Math.max(max, cellValue(row[col]).length),
|
|
1773
|
-
0
|
|
1774
|
-
);
|
|
1775
|
-
return Math.max(col.length, dataMax);
|
|
1776
|
-
});
|
|
1777
|
-
}
|
|
1778
|
-
function pad(str, width) {
|
|
1779
|
-
return str.slice(0, width).padEnd(width);
|
|
1780
|
-
}
|
|
1781
|
-
function hline(widths, left, mid, right) {
|
|
1782
|
-
const segments = widths.map((w) => "\u2500".repeat(w + COL_PAD * 2));
|
|
1783
|
-
return left + segments.join(mid) + right;
|
|
1784
|
-
}
|
|
1785
|
-
function ExpandedTable({ columns, rows }) {
|
|
1786
|
-
const keyWidth = columns.reduce((max, col) => Math.max(max, col.length), 0);
|
|
1787
|
-
return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: rows.map((row, i) => /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: i < rows.length - 1 ? 1 : 0, children: [
|
|
1788
|
-
/* @__PURE__ */ jsx2(Text2, { color: BORDER, children: `\u2500[ Record ${i + 1} ]${"\u2500".repeat(Math.max(0, keyWidth + 14 - String(i + 1).length))}` }),
|
|
1789
|
-
columns.map((col) => /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
1790
|
-
/* @__PURE__ */ jsx2(Text2, { color: INDIGO, bold: true, children: col.padEnd(keyWidth) }),
|
|
1791
|
-
/* @__PURE__ */ jsx2(Text2, { color: BORDER, children: " \u2502 " }),
|
|
1792
|
-
isNull(row[col]) ? /* @__PURE__ */ jsx2(Text2, { color: NULL_COLOR, dimColor: true, children: NULL_MARKER }) : /* @__PURE__ */ jsx2(Text2, { children: cellValue(row[col]) })
|
|
1793
|
-
] }, col))
|
|
1794
|
-
] }, i)) });
|
|
1795
|
-
}
|
|
1796
|
-
function Table({ columns, rows, expanded = false }) {
|
|
1797
|
-
if (expanded) return /* @__PURE__ */ jsx2(ExpandedTable, { columns, rows });
|
|
1798
|
-
const widths = colWidths(columns, rows);
|
|
1799
|
-
const topLine = hline(widths, "\u256D", "\u252C", "\u256E");
|
|
1800
|
-
const midLine = hline(widths, "\u251C", "\u253C", "\u2524");
|
|
1801
|
-
const botLine = hline(widths, "\u2570", "\u2534", "\u256F");
|
|
1802
|
-
function renderHeaderRow(cols) {
|
|
1803
|
-
return /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
1804
|
-
/* @__PURE__ */ jsx2(Text2, { color: BORDER, children: "\u2502" }),
|
|
1805
|
-
cols.map((v, i) => /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
1806
|
-
/* @__PURE__ */ jsx2(Text2, { color: INDIGO, bold: true, children: " ".repeat(COL_PAD) + pad(v, widths[i]) + " ".repeat(COL_PAD) }),
|
|
1807
|
-
/* @__PURE__ */ jsx2(Text2, { color: BORDER, children: "\u2502" })
|
|
1808
|
-
] }, i))
|
|
1809
|
-
] });
|
|
1810
|
-
}
|
|
1811
|
-
function renderDataRow(row) {
|
|
1812
|
-
return /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
1813
|
-
/* @__PURE__ */ jsx2(Text2, { color: BORDER, children: "\u2502" }),
|
|
1814
|
-
columns.map((col, i) => /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
1815
|
-
isNull(row[col]) ? /* @__PURE__ */ jsx2(Text2, { color: NULL_COLOR, dimColor: true, children: " ".repeat(COL_PAD) + pad(NULL_MARKER, widths[i]) + " ".repeat(COL_PAD) }) : /* @__PURE__ */ jsx2(Text2, { children: " ".repeat(COL_PAD) + pad(cellValue(row[col]), widths[i]) + " ".repeat(COL_PAD) }),
|
|
1816
|
-
/* @__PURE__ */ jsx2(Text2, { color: BORDER, children: "\u2502" })
|
|
1817
|
-
] }, i))
|
|
1818
|
-
] });
|
|
1819
|
-
}
|
|
1820
|
-
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
1821
|
-
/* @__PURE__ */ jsx2(Text2, { color: BORDER, children: topLine }),
|
|
1822
|
-
renderHeaderRow(columns),
|
|
1823
|
-
/* @__PURE__ */ jsx2(Text2, { color: BORDER, children: midLine }),
|
|
1824
|
-
rows.map((row, i) => /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
1825
|
-
renderDataRow(row),
|
|
1826
|
-
i < rows.length - 1 && /* @__PURE__ */ jsx2(Text2, { color: BORDER, children: midLine })
|
|
1827
|
-
] }, i)),
|
|
1828
|
-
/* @__PURE__ */ jsx2(Text2, { color: BORDER, children: botLine })
|
|
1829
|
-
] });
|
|
1830
|
-
}
|
|
1831
1755
|
|
|
1832
1756
|
// src/ui/components/QueryResult.tsx
|
|
1833
1757
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -1839,82 +1763,11 @@ function ErrorBox({ message }) {
|
|
|
1839
1763
|
line
|
|
1840
1764
|
] }, i)) });
|
|
1841
1765
|
}
|
|
1842
|
-
function formatDuration(ms) {
|
|
1843
|
-
if (ms < 1e3) return `${ms}ms`;
|
|
1844
|
-
return `${(ms / 1e3).toFixed(2)}s`;
|
|
1845
|
-
}
|
|
1846
|
-
function useTerminalWidth() {
|
|
1847
|
-
const [width, setWidth] = useState3(process.stdout.columns ?? 80);
|
|
1848
|
-
useEffect3(() => {
|
|
1849
|
-
const handler = () => setWidth(process.stdout.columns ?? 80);
|
|
1850
|
-
process.stdout.on("resize", handler);
|
|
1851
|
-
return () => {
|
|
1852
|
-
process.stdout.off("resize", handler);
|
|
1853
|
-
};
|
|
1854
|
-
}, []);
|
|
1855
|
-
return width;
|
|
1856
|
-
}
|
|
1857
|
-
function QueryResult({ state, elapsed, page, pageSize }) {
|
|
1858
|
-
const termWidth = useTerminalWidth();
|
|
1859
|
-
if (state.status === "idle" || state.status === "running") return null;
|
|
1860
|
-
const timing = elapsed !== null ? ` \xB7 ${formatDuration(elapsed)}` : "";
|
|
1861
|
-
if (state.status === "error") {
|
|
1862
|
-
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
1863
|
-
/* @__PURE__ */ jsx3(ErrorBox, { message: state.message }),
|
|
1864
|
-
elapsed !== null && /* @__PURE__ */ jsx3(Text3, { color: theme.accent, dimColor: true, children: formatDuration(elapsed) })
|
|
1865
|
-
] });
|
|
1866
|
-
}
|
|
1867
|
-
const { result } = state;
|
|
1868
|
-
const columns = result.fields;
|
|
1869
|
-
if (result.rows.length === 0) {
|
|
1870
|
-
return /* @__PURE__ */ jsx3(Box3, { children: /* @__PURE__ */ jsxs3(Text3, { color: theme.accent, children: [
|
|
1871
|
-
"No rows returned (",
|
|
1872
|
-
result.rowCount ?? 0,
|
|
1873
|
-
" affected)",
|
|
1874
|
-
timing
|
|
1875
|
-
] }) });
|
|
1876
|
-
}
|
|
1877
|
-
const totalRows = result.rows.length;
|
|
1878
|
-
const totalPages = Math.ceil(totalRows / pageSize);
|
|
1879
|
-
const currentPage = Math.min(page, totalPages - 1);
|
|
1880
|
-
const start = currentPage * pageSize;
|
|
1881
|
-
const displayRows = result.rows.slice(start, start + pageSize);
|
|
1882
|
-
const isPaged = totalRows > pageSize;
|
|
1883
|
-
const widths = colWidths(columns, displayRows);
|
|
1884
|
-
const tableWidth = 1 + widths.reduce((sum, w) => sum + w + 3, 0);
|
|
1885
|
-
const expanded = tableWidth > termWidth;
|
|
1886
|
-
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
1887
|
-
/* @__PURE__ */ jsx3(Table, { columns, rows: displayRows, expanded }),
|
|
1888
|
-
/* @__PURE__ */ jsxs3(Box3, { marginTop: 1, flexDirection: "column", children: [
|
|
1889
|
-
isPaged && /* @__PURE__ */ jsxs3(Text3, { color: theme.warning, children: [
|
|
1890
|
-
"Page ",
|
|
1891
|
-
currentPage + 1,
|
|
1892
|
-
" of ",
|
|
1893
|
-
totalPages,
|
|
1894
|
-
" \xB7 showing rows ",
|
|
1895
|
-
start + 1,
|
|
1896
|
-
"\u2013",
|
|
1897
|
-
start + displayRows.length,
|
|
1898
|
-
" of ",
|
|
1899
|
-
totalRows,
|
|
1900
|
-
currentPage > 0 ? " /prev" : "",
|
|
1901
|
-
currentPage < totalPages - 1 ? " /next" : ""
|
|
1902
|
-
] }),
|
|
1903
|
-
/* @__PURE__ */ jsxs3(Text3, { color: theme.accent, children: [
|
|
1904
|
-
displayRows.length,
|
|
1905
|
-
" row",
|
|
1906
|
-
displayRows.length !== 1 ? "s" : "",
|
|
1907
|
-
timing,
|
|
1908
|
-
expanded ? " [expanded]" : ""
|
|
1909
|
-
] })
|
|
1910
|
-
] })
|
|
1911
|
-
] });
|
|
1912
|
-
}
|
|
1913
1766
|
|
|
1914
1767
|
// src/ui/components/Banner.tsx
|
|
1915
1768
|
import { Box as Box4, Text as Text4 } from "ink";
|
|
1916
1769
|
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1917
|
-
var version = true ? "0.4.
|
|
1770
|
+
var version = true ? "0.4.9" : process.env.npm_package_version ?? "unknown";
|
|
1918
1771
|
var LOGO = [
|
|
1919
1772
|
" \u2597\u2584\u2584\u2584\u2584\u2584\u2596",
|
|
1920
1773
|
"\u2590\u2591 \u25CF \u25CF \u2591\u258C",
|
|
@@ -1963,56 +1816,40 @@ function Banner({ connectionState }) {
|
|
|
1963
1816
|
] });
|
|
1964
1817
|
}
|
|
1965
1818
|
|
|
1966
|
-
// src/ui/
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
var
|
|
1970
|
-
function
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
] }, entry.name))
|
|
2001
|
-
] }, group.category)),
|
|
2002
|
-
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
|
|
2003
|
-
"/help ",
|
|
2004
|
-
"<command>",
|
|
2005
|
-
" for more details."
|
|
2006
|
-
] }) })
|
|
2007
|
-
] });
|
|
2008
|
-
}
|
|
2009
|
-
return null;
|
|
2010
|
-
}
|
|
2011
|
-
|
|
2012
|
-
// src/ui/components/ErdView.tsx
|
|
2013
|
-
import { Box as Box6, Text as Text6 } from "ink";
|
|
2014
|
-
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2015
|
-
var TABLE_COLORS = [
|
|
1819
|
+
// src/ui/format.ts
|
|
1820
|
+
var R = "\x1B[0m";
|
|
1821
|
+
var BOLD = "\x1B[1m";
|
|
1822
|
+
var DIM = "\x1B[2m";
|
|
1823
|
+
function fg(hex) {
|
|
1824
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
1825
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
1826
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
1827
|
+
return `\x1B[38;2;${r};${g};${b}m`;
|
|
1828
|
+
}
|
|
1829
|
+
function c(hex, s) {
|
|
1830
|
+
return fg(hex) + s + R;
|
|
1831
|
+
}
|
|
1832
|
+
function bold(s) {
|
|
1833
|
+
return BOLD + s + R;
|
|
1834
|
+
}
|
|
1835
|
+
function dim(s) {
|
|
1836
|
+
return DIM + s + R;
|
|
1837
|
+
}
|
|
1838
|
+
function cbold(hex, s) {
|
|
1839
|
+
return fg(hex) + BOLD + s + R;
|
|
1840
|
+
}
|
|
1841
|
+
function cdim(hex, s) {
|
|
1842
|
+
return fg(hex) + DIM + s + R;
|
|
1843
|
+
}
|
|
1844
|
+
var ACCENT2 = "#818cf8";
|
|
1845
|
+
var HEADER_COL = "#9ca3af";
|
|
1846
|
+
var NULL_COL = "#6366f1";
|
|
1847
|
+
var INDIGO = "#818cf8";
|
|
1848
|
+
var AI_COL = "#a5b4fc";
|
|
1849
|
+
var ERROR_COL = "#ff4444";
|
|
1850
|
+
var WARN_COL = "#f59e0b";
|
|
1851
|
+
var ERD_BORDER = "#4b5563";
|
|
1852
|
+
var ERD_PALETTE = [
|
|
2016
1853
|
"#f472b6",
|
|
2017
1854
|
"#34d399",
|
|
2018
1855
|
"#fb923c",
|
|
@@ -2022,30 +1859,179 @@ var TABLE_COLORS = [
|
|
|
2022
1859
|
"#fbbf24",
|
|
2023
1860
|
"#2dd4bf"
|
|
2024
1861
|
];
|
|
2025
|
-
var
|
|
2026
|
-
var
|
|
2027
|
-
var
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
);
|
|
2040
|
-
|
|
2041
|
-
|
|
1862
|
+
var NULL_MARKER = "\u2205";
|
|
1863
|
+
var COL_PAD = 1;
|
|
1864
|
+
var SP = " ".repeat(COL_PAD);
|
|
1865
|
+
function fmtHeader(label, query) {
|
|
1866
|
+
const dot = cbold(ACCENT2, "\u25CF ");
|
|
1867
|
+
if (query.includes("\n")) {
|
|
1868
|
+
const lines = query.split("\n").map((l) => cbold(HEADER_COL, " " + l));
|
|
1869
|
+
return dot + cbold(HEADER_COL, label + ":") + "\n" + lines.join("\n");
|
|
1870
|
+
}
|
|
1871
|
+
return dot + cbold(HEADER_COL, `${label}(${query})`);
|
|
1872
|
+
}
|
|
1873
|
+
function fmtError(message) {
|
|
1874
|
+
return message.split("\n").map(
|
|
1875
|
+
(line, i) => cbold(ERROR_COL, (i === 0 ? "\u2717 " : " ") + line)
|
|
1876
|
+
).join("\n");
|
|
1877
|
+
}
|
|
1878
|
+
function fmtOk(text) {
|
|
1879
|
+
return c(ACCENT2, "\u2713 ") + text;
|
|
1880
|
+
}
|
|
1881
|
+
function isNull(v) {
|
|
1882
|
+
return v === null || v === void 0;
|
|
1883
|
+
}
|
|
1884
|
+
function cellStr(v) {
|
|
1885
|
+
if (isNull(v)) return NULL_MARKER;
|
|
1886
|
+
if (v instanceof Date) return v.toISOString();
|
|
1887
|
+
if (typeof v === "object") return JSON.stringify(v);
|
|
1888
|
+
return String(v);
|
|
1889
|
+
}
|
|
1890
|
+
function colWidths2(columns, rows) {
|
|
1891
|
+
return columns.map((col) => {
|
|
1892
|
+
const dataMax = rows.reduce((mx, row) => Math.max(mx, cellStr(row[col]).length), 0);
|
|
1893
|
+
return Math.max(col.length, dataMax);
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1896
|
+
function hline(widths, l, m, r) {
|
|
1897
|
+
return l + widths.map((w) => "\u2500".repeat(w + COL_PAD * 2)).join(m) + r;
|
|
1898
|
+
}
|
|
1899
|
+
function fmtTable(columns, rows) {
|
|
1900
|
+
const widths = colWidths2(columns, rows);
|
|
1901
|
+
const top = hline(widths, "\u256D", "\u252C", "\u256E");
|
|
1902
|
+
const mid = hline(widths, "\u251C", "\u253C", "\u2524");
|
|
1903
|
+
const bot = hline(widths, "\u2570", "\u2534", "\u256F");
|
|
1904
|
+
function headerRow() {
|
|
1905
|
+
const cells = columns.map(
|
|
1906
|
+
(col, i) => cbold(INDIGO, SP + col.slice(0, widths[i]).padEnd(widths[i]) + SP)
|
|
1907
|
+
);
|
|
1908
|
+
return "\u2502" + cells.join("\u2502") + "\u2502";
|
|
1909
|
+
}
|
|
1910
|
+
function dataRow(row) {
|
|
1911
|
+
const cells = columns.map((col, i) => {
|
|
1912
|
+
const v = cellStr(row[col]);
|
|
1913
|
+
const cell = SP + v.slice(0, widths[i]).padEnd(widths[i]) + SP;
|
|
1914
|
+
return isNull(row[col]) ? cdim(NULL_COL, cell) : cell;
|
|
1915
|
+
});
|
|
1916
|
+
return "\u2502" + cells.join("\u2502") + "\u2502";
|
|
1917
|
+
}
|
|
1918
|
+
const out = [top, headerRow(), mid];
|
|
1919
|
+
rows.forEach((row, i) => {
|
|
1920
|
+
out.push(dataRow(row));
|
|
1921
|
+
if (i < rows.length - 1) out.push(mid);
|
|
1922
|
+
});
|
|
1923
|
+
out.push(bot);
|
|
1924
|
+
return out.join("\n");
|
|
1925
|
+
}
|
|
1926
|
+
function fmtExpanded(columns, rows) {
|
|
1927
|
+
const kw = columns.reduce((mx, c2) => Math.max(mx, c2.length), 0);
|
|
1928
|
+
const separator = (i) => "\u2500[ Record " + (i + 1) + " ]" + "\u2500".repeat(Math.max(0, kw + 14 - String(i + 1).length));
|
|
1929
|
+
const out = [];
|
|
1930
|
+
rows.forEach((row, i) => {
|
|
1931
|
+
if (i > 0) out.push("");
|
|
1932
|
+
out.push(dim(separator(i)));
|
|
1933
|
+
for (const col of columns) {
|
|
1934
|
+
const val = isNull(row[col]) ? cdim(NULL_COL, NULL_MARKER) : cellStr(row[col]);
|
|
1935
|
+
out.push(cbold(INDIGO, col.padEnd(kw)) + dim(" \u2502 ") + val);
|
|
1936
|
+
}
|
|
1937
|
+
});
|
|
1938
|
+
return out.join("\n");
|
|
1939
|
+
}
|
|
1940
|
+
function fmtDuration(ms) {
|
|
1941
|
+
return ms < 1e3 ? `${ms}ms` : `${(ms / 1e3).toFixed(2)}s`;
|
|
1942
|
+
}
|
|
1943
|
+
function fmtQueryResult(state, elapsed, page, pageSize) {
|
|
1944
|
+
if (state.status === "idle" || state.status === "running") return "";
|
|
1945
|
+
const timing = elapsed !== null ? ` \xB7 ${fmtDuration(elapsed)}` : "";
|
|
1946
|
+
if (state.status === "error") {
|
|
1947
|
+
const t = elapsed !== null ? "\n" + cdim(ACCENT2, fmtDuration(elapsed)) : "";
|
|
1948
|
+
return fmtError(state.message) + t;
|
|
1949
|
+
}
|
|
1950
|
+
const { result } = state;
|
|
1951
|
+
const { fields, rows } = result;
|
|
1952
|
+
if (rows.length === 0) {
|
|
1953
|
+
return c(ACCENT2, `No rows returned (${result.rowCount ?? 0} affected)${timing}`);
|
|
1954
|
+
}
|
|
1955
|
+
const totalRows = rows.length;
|
|
1956
|
+
const totalPages = Math.ceil(totalRows / pageSize);
|
|
1957
|
+
const currentPage = Math.min(page, totalPages - 1);
|
|
1958
|
+
const start = currentPage * pageSize;
|
|
1959
|
+
const displayRows = rows.slice(start, start + pageSize);
|
|
1960
|
+
const isPaged = totalRows > pageSize;
|
|
1961
|
+
const termWidth = process.stdout.columns ?? 80;
|
|
1962
|
+
const widths = colWidths2(fields, displayRows);
|
|
1963
|
+
const tableWidth = 1 + widths.reduce((sum, w) => sum + w + 3, 0);
|
|
1964
|
+
const expanded = tableWidth > termWidth;
|
|
1965
|
+
const table = expanded ? fmtExpanded(fields, displayRows) : fmtTable(fields, displayRows);
|
|
1966
|
+
const lines = [table];
|
|
1967
|
+
if (isPaged) {
|
|
1968
|
+
const nav = (currentPage > 0 ? " /prev" : "") + (currentPage < totalPages - 1 ? " /next" : "");
|
|
1969
|
+
lines.push(c(WARN_COL, `Page ${currentPage + 1} of ${totalPages} \xB7 rows ${start + 1}\u2013${start + displayRows.length} of ${totalRows}${nav}`));
|
|
1970
|
+
}
|
|
1971
|
+
lines.push(c(ACCENT2, `${displayRows.length} row${displayRows.length !== 1 ? "s" : ""}${timing}${expanded ? " [expanded]" : ""}`));
|
|
1972
|
+
return lines.join("\n");
|
|
2042
1973
|
}
|
|
2043
|
-
|
|
1974
|
+
var USAGE_WIDTH = 28;
|
|
1975
|
+
function fmtHelp(data) {
|
|
1976
|
+
if (data.mode === "detail" && data.entry) {
|
|
1977
|
+
const { usage, description, psqlAlias, detail, example, examples } = data.entry;
|
|
1978
|
+
const lines = [];
|
|
1979
|
+
lines.push(bold(usage) + (psqlAlias ? " " + dim(psqlAlias) : ""));
|
|
1980
|
+
lines.push("");
|
|
1981
|
+
lines.push(description);
|
|
1982
|
+
if (detail) {
|
|
1983
|
+
lines.push("");
|
|
1984
|
+
lines.push(dim(detail));
|
|
1985
|
+
}
|
|
1986
|
+
if (examples && examples.length > 0) {
|
|
1987
|
+
lines.push("");
|
|
1988
|
+
lines.push(dim("Examples:"));
|
|
1989
|
+
for (const ex of examples) lines.push(" " + c(ACCENT2, ex));
|
|
1990
|
+
} else if (example) {
|
|
1991
|
+
lines.push("");
|
|
1992
|
+
lines.push(dim("Example: ") + c(ACCENT2, example));
|
|
1993
|
+
}
|
|
1994
|
+
return lines.join("\n");
|
|
1995
|
+
}
|
|
1996
|
+
if (data.mode === "list" && data.groups) {
|
|
1997
|
+
const lines = [];
|
|
1998
|
+
data.groups.forEach((group, gi) => {
|
|
1999
|
+
if (gi > 0) lines.push("");
|
|
2000
|
+
lines.push(cbold(ACCENT2, group.category));
|
|
2001
|
+
for (const entry of group.entries) {
|
|
2002
|
+
const alias = entry.psqlAlias ? dim(" " + entry.psqlAlias) : "";
|
|
2003
|
+
lines.push(" " + entry.usage.padEnd(USAGE_WIDTH) + dim(entry.description) + alias);
|
|
2004
|
+
}
|
|
2005
|
+
});
|
|
2006
|
+
lines.push("");
|
|
2007
|
+
lines.push(dim("/help <command> for more details."));
|
|
2008
|
+
return lines.join("\n");
|
|
2009
|
+
}
|
|
2010
|
+
return "";
|
|
2011
|
+
}
|
|
2012
|
+
function fmtErd(data) {
|
|
2013
|
+
if (data.tables.length === 0) return dim("No tables found in the current schema.");
|
|
2014
|
+
const termW = process.stdout.columns ?? 80;
|
|
2015
|
+
const FK_PREFIX = "FK \u2192 ";
|
|
2016
|
+
const PAD = 1;
|
|
2017
|
+
const GAP = 2;
|
|
2018
|
+
const colorMap = new Map(
|
|
2019
|
+
data.tables.map((t, i) => [t.name, ERD_PALETTE[i % ERD_PALETTE.length]])
|
|
2020
|
+
);
|
|
2021
|
+
function metrics(t) {
|
|
2022
|
+
const nameW = Math.max(2, ...t.columns.map((c2) => c2.name.length));
|
|
2023
|
+
const typeW = Math.max(4, ...t.columns.map((c2) => c2.type.length));
|
|
2024
|
+
const keyW = Math.max(2, ...t.columns.map(
|
|
2025
|
+
(c2) => c2.isPk ? 2 : c2.fkTable ? FK_PREFIX.length + c2.fkTable.length : 0
|
|
2026
|
+
));
|
|
2027
|
+
const totalW = 4 + 3 * PAD * 2 + nameW + typeW + keyW;
|
|
2028
|
+
return { nameW, typeW, keyW, totalW };
|
|
2029
|
+
}
|
|
2030
|
+
const allMetrics = data.tables.map(metrics);
|
|
2044
2031
|
const rows = [];
|
|
2045
|
-
let row = [];
|
|
2046
|
-
let
|
|
2047
|
-
|
|
2048
|
-
const w = metrics[i].totalW;
|
|
2032
|
+
let row = [], usedW = 0;
|
|
2033
|
+
for (let i = 0; i < allMetrics.length; i++) {
|
|
2034
|
+
const w = allMetrics[i].totalW;
|
|
2049
2035
|
if (row.length === 0) {
|
|
2050
2036
|
row.push(i);
|
|
2051
2037
|
usedW = w;
|
|
@@ -2059,120 +2045,113 @@ function groupIntoRows(metrics, termW) {
|
|
|
2059
2045
|
}
|
|
2060
2046
|
}
|
|
2061
2047
|
if (row.length > 0) rows.push(row);
|
|
2062
|
-
|
|
2063
|
-
}
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
sp,
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
p(col.fkTable, keyW - FK_PREFIX.length),
|
|
2109
|
-
sp
|
|
2110
|
-
] })
|
|
2111
|
-
] }) : /* @__PURE__ */ jsxs6(Text6, { children: [
|
|
2112
|
-
sp,
|
|
2113
|
-
" ".repeat(keyW),
|
|
2114
|
-
sp
|
|
2115
|
-
] }),
|
|
2116
|
-
/* @__PURE__ */ jsx6(Text6, { color: BORDER2, children: "\u2502" })
|
|
2117
|
-
] }, i)),
|
|
2118
|
-
/* @__PURE__ */ jsx6(Text6, { color: BORDER2, children: bot })
|
|
2119
|
-
] });
|
|
2048
|
+
function renderTable(t, m, color) {
|
|
2049
|
+
const { nameW, typeW, keyW, totalW } = m;
|
|
2050
|
+
const sp = " ".repeat(PAD);
|
|
2051
|
+
const p = (s, w) => s.slice(0, w).padEnd(w);
|
|
2052
|
+
const bdr = (s) => c(ERD_BORDER, s);
|
|
2053
|
+
const tc = (s) => cbold(color, s);
|
|
2054
|
+
const top = bdr("\u256D" + "\u2500".repeat(totalW - 2) + "\u256E");
|
|
2055
|
+
const headerW = totalW - 4;
|
|
2056
|
+
const headerLine = bdr("\u2502") + tc(sp + p(t.name, headerW) + sp) + bdr("\u2502");
|
|
2057
|
+
const sep = bdr("\u251C" + "\u2500".repeat(nameW + PAD * 2) + "\u252C" + "\u2500".repeat(typeW + PAD * 2) + "\u252C" + "\u2500".repeat(keyW + PAD * 2) + "\u2524");
|
|
2058
|
+
const bot = bdr("\u2570" + "\u2500".repeat(nameW + PAD * 2) + "\u2534" + "\u2500".repeat(typeW + PAD * 2) + "\u2534" + "\u2500".repeat(keyW + PAD * 2) + "\u256F");
|
|
2059
|
+
const out = [top, headerLine, sep];
|
|
2060
|
+
for (const col of t.columns) {
|
|
2061
|
+
let keyPart;
|
|
2062
|
+
if (col.isPk) {
|
|
2063
|
+
keyPart = sp + bold(p("PK", keyW)) + sp;
|
|
2064
|
+
} else if (col.fkTable) {
|
|
2065
|
+
const fkColor = colorMap.get(col.fkTable) ?? color;
|
|
2066
|
+
keyPart = sp + dim(FK_PREFIX) + c(fkColor, p(col.fkTable, keyW - FK_PREFIX.length)) + sp;
|
|
2067
|
+
} else {
|
|
2068
|
+
keyPart = sp + " ".repeat(keyW) + sp;
|
|
2069
|
+
}
|
|
2070
|
+
out.push(
|
|
2071
|
+
bdr("\u2502") + sp + p(col.name, nameW) + sp + bdr("\u2502") + dim(sp + p(col.type, typeW) + sp) + bdr("\u2502") + keyPart + bdr("\u2502")
|
|
2072
|
+
);
|
|
2073
|
+
}
|
|
2074
|
+
out.push(bot);
|
|
2075
|
+
return out;
|
|
2076
|
+
}
|
|
2077
|
+
const output = [];
|
|
2078
|
+
for (const tableRow of rows) {
|
|
2079
|
+
const blocks = tableRow.map((ti) => {
|
|
2080
|
+
const t = data.tables[ti];
|
|
2081
|
+
return renderTable(t, allMetrics[ti], colorMap.get(t.name) ?? ERD_PALETTE[0]);
|
|
2082
|
+
});
|
|
2083
|
+
const height = Math.max(...blocks.map((b) => b.length));
|
|
2084
|
+
for (let line = 0; line < height; line++) {
|
|
2085
|
+
const parts = blocks.map((b, j) => {
|
|
2086
|
+
const l = b[line] ?? " ".repeat(allMetrics[tableRow[j]].totalW);
|
|
2087
|
+
return j < blocks.length - 1 ? l + " ".repeat(GAP) : l;
|
|
2088
|
+
});
|
|
2089
|
+
output.push(parts.join(""));
|
|
2090
|
+
}
|
|
2091
|
+
output.push("");
|
|
2092
|
+
}
|
|
2093
|
+
return output.join("\n").trimEnd();
|
|
2120
2094
|
}
|
|
2121
|
-
function
|
|
2122
|
-
|
|
2123
|
-
|
|
2095
|
+
function fmtAi(text, error) {
|
|
2096
|
+
const lines = [cbold(ACCENT2, "Explanation:"), ""];
|
|
2097
|
+
if (error) {
|
|
2098
|
+
lines.push(fmtError(error));
|
|
2099
|
+
} else {
|
|
2100
|
+
lines.push(c(AI_COL, text));
|
|
2124
2101
|
}
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
);
|
|
2130
|
-
const
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2102
|
+
return lines.join("\n");
|
|
2103
|
+
}
|
|
2104
|
+
function fmtEntry(entry) {
|
|
2105
|
+
const isShell = entry.query.startsWith("!");
|
|
2106
|
+
const isCommand = !isShell && (entry.query.startsWith("/") || entry.query.startsWith("\\"));
|
|
2107
|
+
const label = isShell ? "Shell" : isCommand ? "Command" : "Query";
|
|
2108
|
+
const lines = [" " + fmtHeader(label, entry.query), ""];
|
|
2109
|
+
if (isShell) {
|
|
2110
|
+
if (entry.shellOutput !== null) lines.push(" " + entry.shellOutput.replace(/\n/g, "\n "));
|
|
2111
|
+
} else if (entry.commandMessage) {
|
|
2112
|
+
if (entry.commandMessage.helpData) {
|
|
2113
|
+
lines.push(fmtHelp(entry.commandMessage.helpData).replace(/\n/g, "\n "));
|
|
2114
|
+
} else if (entry.commandMessage.ok) {
|
|
2115
|
+
lines.push(" " + fmtOk(entry.commandMessage.text));
|
|
2116
|
+
} else {
|
|
2117
|
+
lines.push(" " + fmtError(entry.commandMessage.text));
|
|
2138
2118
|
}
|
|
2139
|
-
|
|
2119
|
+
} else if (entry.erdData) {
|
|
2120
|
+
lines.push(" " + fmtErd(entry.erdData).replace(/\n/g, "\n "));
|
|
2121
|
+
} else if (entry.aiResponse || entry.aiError) {
|
|
2122
|
+
lines.push(" " + fmtAi(entry.aiResponse, entry.aiError).replace(/\n/g, "\n "));
|
|
2123
|
+
} else {
|
|
2124
|
+
const result = fmtQueryResult(entry.queryState, entry.elapsed, entry.page, 50);
|
|
2125
|
+
if (result) lines.push(" " + result.replace(/\n/g, "\n "));
|
|
2126
|
+
}
|
|
2127
|
+
lines.push("");
|
|
2128
|
+
return lines.join("\n");
|
|
2140
2129
|
}
|
|
2141
2130
|
|
|
2142
2131
|
// src/ui/components/App.tsx
|
|
2143
|
-
import {
|
|
2144
|
-
var PAGE_SIZE = 50;
|
|
2132
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2145
2133
|
var PLACEHOLDER2 = "#a5b4fc";
|
|
2146
|
-
function activePageSize() {
|
|
2147
|
-
return Math.max(3, (process.stdout.rows ?? 24) - 21);
|
|
2148
|
-
}
|
|
2149
|
-
function limitLines(s, n) {
|
|
2150
|
-
const lines = s.split("\n");
|
|
2151
|
-
if (lines.length <= n) return s;
|
|
2152
|
-
return lines.slice(0, n).join("\n") + `
|
|
2153
|
-
\u2026 +${lines.length - n} more lines (scroll up after next submit)`;
|
|
2154
|
-
}
|
|
2155
2134
|
var QUERY_HEADER_COLOR = "#9ca3af";
|
|
2156
2135
|
function QueryHeader({ label, query }) {
|
|
2157
2136
|
const isMultiLine = query.includes("\n");
|
|
2158
2137
|
if (isMultiLine) {
|
|
2159
|
-
return /* @__PURE__ */
|
|
2160
|
-
/* @__PURE__ */
|
|
2161
|
-
/* @__PURE__ */
|
|
2162
|
-
/* @__PURE__ */
|
|
2138
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
2139
|
+
/* @__PURE__ */ jsxs5(Text5, { children: [
|
|
2140
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accent, bold: true, children: "\u25CF " }),
|
|
2141
|
+
/* @__PURE__ */ jsxs5(Text5, { color: QUERY_HEADER_COLOR, bold: true, children: [
|
|
2163
2142
|
label,
|
|
2164
2143
|
":"
|
|
2165
2144
|
] })
|
|
2166
2145
|
] }),
|
|
2167
|
-
query.split("\n").map((line, i) => /* @__PURE__ */
|
|
2146
|
+
query.split("\n").map((line, i) => /* @__PURE__ */ jsxs5(Text5, { color: QUERY_HEADER_COLOR, bold: true, children: [
|
|
2168
2147
|
" ",
|
|
2169
2148
|
line
|
|
2170
2149
|
] }, i))
|
|
2171
2150
|
] });
|
|
2172
2151
|
}
|
|
2173
|
-
return /* @__PURE__ */
|
|
2174
|
-
/* @__PURE__ */
|
|
2175
|
-
/* @__PURE__ */
|
|
2152
|
+
return /* @__PURE__ */ jsxs5(Text5, { children: [
|
|
2153
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accent, bold: true, children: "\u25CF " }),
|
|
2154
|
+
/* @__PURE__ */ jsxs5(Text5, { color: QUERY_HEADER_COLOR, bold: true, children: [
|
|
2176
2155
|
label,
|
|
2177
2156
|
"(",
|
|
2178
2157
|
query,
|
|
@@ -2180,54 +2159,31 @@ function QueryHeader({ label, query }) {
|
|
|
2180
2159
|
] })
|
|
2181
2160
|
] });
|
|
2182
2161
|
}
|
|
2183
|
-
function EntryView({ entry }) {
|
|
2184
|
-
const showAi = entry.aiResponse !== "" || entry.aiError !== null;
|
|
2185
|
-
const showErd = entry.erdData !== null;
|
|
2186
|
-
const isShell = entry.query.startsWith("!");
|
|
2187
|
-
const isCommand = !isShell && (entry.query.startsWith("/") || entry.query.startsWith("\\"));
|
|
2188
|
-
const label = isShell ? "Shell" : isCommand ? "Command" : "Query";
|
|
2189
|
-
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginBottom: 1, paddingX: 1, children: [
|
|
2190
|
-
/* @__PURE__ */ jsx7(QueryHeader, { label, query: entry.query }),
|
|
2191
|
-
/* @__PURE__ */ jsx7(Box7, { marginTop: 1, flexDirection: "column", children: isShell ? entry.shellOutput !== null && /* @__PURE__ */ jsx7(Text7, { children: entry.shellOutput || "(no output)" }) : /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
2192
|
-
entry.commandMessage && (entry.commandMessage.helpData ? /* @__PURE__ */ jsx7(HelpView, { data: entry.commandMessage.helpData }) : entry.commandMessage.ok ? /* @__PURE__ */ jsxs7(Text7, { color: theme.accent, children: [
|
|
2193
|
-
"\u2713 ",
|
|
2194
|
-
entry.commandMessage.text
|
|
2195
|
-
] }) : /* @__PURE__ */ jsx7(ErrorBox, { message: entry.commandMessage.text })),
|
|
2196
|
-
showErd ? /* @__PURE__ */ jsx7(ErdView, { data: entry.erdData }) : showAi ? /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
2197
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, bold: true, children: "Explanation:" }),
|
|
2198
|
-
/* @__PURE__ */ jsx7(Box7, { flexDirection: "column", marginTop: 1, children: entry.aiError ? /* @__PURE__ */ jsx7(ErrorBox, { message: entry.aiError }) : /* @__PURE__ */ jsx7(Text7, { color: PLACEHOLDER2, children: entry.aiResponse }) })
|
|
2199
|
-
] }) : !entry.commandMessage && /* @__PURE__ */ jsx7(QueryResult, { state: entry.queryState, elapsed: entry.elapsed, page: entry.page, pageSize: PAGE_SIZE })
|
|
2200
|
-
] }) })
|
|
2201
|
-
] });
|
|
2202
|
-
}
|
|
2203
2162
|
function App({ connectionState, aiUrl: aiUrl2, aiModel: aiModel2, aiKey: aiKey2, onChangeDatabase }) {
|
|
2204
2163
|
const { exit } = useApp();
|
|
2205
2164
|
const { isRawModeSupported } = useStdin2();
|
|
2206
|
-
const [
|
|
2207
|
-
const [
|
|
2165
|
+
const [active, setActive] = useState4({ type: "idle" });
|
|
2166
|
+
const [hasHistory, setHasHistory] = useState4(false);
|
|
2167
|
+
const [completedEntries, setCompletedEntries] = useState4([]);
|
|
2168
|
+
const entryIdRef = useRef2(0);
|
|
2208
2169
|
const [lastSqlQuery, setLastSqlQuery] = useState4("");
|
|
2209
2170
|
const [lastResult, setLastResult] = useState4(null);
|
|
2210
|
-
const [
|
|
2171
|
+
const [lastResultPage, setLastResultPage] = useState4(0);
|
|
2211
2172
|
const [vimMode, setVimMode] = useState4("INSERT");
|
|
2212
2173
|
const [inputIsShell, setInputIsShell] = useState4(false);
|
|
2213
|
-
const [elapsed, setElapsed] = useState4(null);
|
|
2214
2174
|
const [vimEnabled, setVimEnabled] = useState4(true);
|
|
2215
|
-
const [commandMessage, setCommandMessage] = useState4(null);
|
|
2216
2175
|
const [history, setHistory] = useState4(() => loadHistory());
|
|
2217
2176
|
const [schema, setSchema] = useState4(null);
|
|
2218
|
-
const [aiResponse, setAiResponse] = useState4("");
|
|
2219
|
-
const [isStreaming, setIsStreaming] = useState4(false);
|
|
2220
|
-
const [aiError, setAiError] = useState4(null);
|
|
2221
|
-
const [shellOutput, setShellOutput] = useState4(null);
|
|
2222
|
-
const [isShellRunning, setIsShellRunning] = useState4(false);
|
|
2223
|
-
const [erdData, setErdData] = useState4(null);
|
|
2224
|
-
const [isErdLoading, setIsErdLoading] = useState4(false);
|
|
2225
|
-
const [completedEntries, setCompletedEntries] = useState4([]);
|
|
2226
|
-
const entryIdRef = useRef2(0);
|
|
2227
2177
|
const aliasScope = connectionState.status === "connected" ? makeScope(connectionState.driver, connectionState.user, connectionState.host, connectionState.database) : "";
|
|
2228
2178
|
const [aliases, setAliases] = useState4(
|
|
2229
2179
|
() => aliasScope ? getAllAliases(aliasScope) : {}
|
|
2230
2180
|
);
|
|
2181
|
+
function writeEntry(entry) {
|
|
2182
|
+
const formatted = fmtEntry(entry);
|
|
2183
|
+
const id = String(++entryIdRef.current);
|
|
2184
|
+
setCompletedEntries((prev) => [...prev, { id, formatted }]);
|
|
2185
|
+
setHasHistory(true);
|
|
2186
|
+
}
|
|
2231
2187
|
function handleSaveAlias(name, query) {
|
|
2232
2188
|
saveAlias(aliasScope, name, query);
|
|
2233
2189
|
setAliases(getAllAliases(aliasScope));
|
|
@@ -2271,65 +2227,55 @@ function App({ connectionState, aiUrl: aiUrl2, aiModel: aiModel2, aiKey: aiKey2,
|
|
|
2271
2227
|
},
|
|
2272
2228
|
{ isActive: isRawModeSupported }
|
|
2273
2229
|
);
|
|
2274
|
-
async function
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
setIsStreaming(false);
|
|
2230
|
+
async function handleQuery(sql) {
|
|
2231
|
+
if (connectionState.status !== "connected") return;
|
|
2232
|
+
setLastSqlQuery(sql);
|
|
2233
|
+
setActive({ type: "loading", label: "Query", query: sql });
|
|
2234
|
+
const updated = addToHistory(history, sql);
|
|
2235
|
+
setHistory(updated);
|
|
2236
|
+
saveHistory(updated);
|
|
2237
|
+
const start = Date.now();
|
|
2238
|
+
const result = await runQuery(connectionState.client, sql);
|
|
2239
|
+
const elapsed = Date.now() - start;
|
|
2240
|
+
if (result.status === "success") {
|
|
2241
|
+
setLastResult(result.result);
|
|
2242
|
+
setLastResultPage(0);
|
|
2288
2243
|
}
|
|
2244
|
+
writeEntry({ query: sql, commandMessage: null, queryState: result, elapsed, page: 0, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2245
|
+
setActive({ type: "idle" });
|
|
2289
2246
|
}
|
|
2290
2247
|
async function handleErd() {
|
|
2291
2248
|
if (connectionState.status !== "connected") {
|
|
2292
|
-
|
|
2249
|
+
writeEntry({ query: "/erd", commandMessage: { ok: false, text: "Not connected." }, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2293
2250
|
return;
|
|
2294
2251
|
}
|
|
2295
|
-
|
|
2296
|
-
setIsErdLoading(true);
|
|
2297
|
-
setCommandMessage(null);
|
|
2298
|
-
setQueryState({ status: "idle" });
|
|
2299
|
-
setAiResponse("");
|
|
2300
|
-
setAiError(null);
|
|
2252
|
+
setActive({ type: "loading", label: "Command", query: "/erd" });
|
|
2301
2253
|
try {
|
|
2302
2254
|
const data = await fetchErd(connectionState.client, connectionState.driver);
|
|
2303
|
-
|
|
2255
|
+
writeEntry({ query: "/erd", commandMessage: null, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: "", aiError: null, shellOutput: null, erdData: data });
|
|
2304
2256
|
} catch (err) {
|
|
2305
|
-
|
|
2306
|
-
} finally {
|
|
2307
|
-
setIsErdLoading(false);
|
|
2257
|
+
writeEntry({ query: "/erd", commandMessage: { ok: false, text: err instanceof Error ? err.message : String(err) }, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2308
2258
|
}
|
|
2259
|
+
setActive({ type: "idle" });
|
|
2309
2260
|
}
|
|
2310
|
-
async function
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
const start = Date.now();
|
|
2325
|
-
const result = await runQuery(connectionState.client, sql);
|
|
2326
|
-
setElapsed(Date.now() - start);
|
|
2327
|
-
setQueryState(result);
|
|
2328
|
-
if (result.status === "success") setLastResult(result.result);
|
|
2261
|
+
async function handleExplain(query) {
|
|
2262
|
+
setActive({ type: "streaming", query, text: "", error: null });
|
|
2263
|
+
let fullText = "";
|
|
2264
|
+
let error = null;
|
|
2265
|
+
try {
|
|
2266
|
+
for await (const chunk of streamExplain(query, aiUrl2, aiModel2, aiKey2 || void 0)) {
|
|
2267
|
+
fullText += chunk;
|
|
2268
|
+
setActive({ type: "streaming", query, text: fullText, error: null });
|
|
2269
|
+
}
|
|
2270
|
+
} catch (err) {
|
|
2271
|
+
error = err instanceof Error ? err.message : String(err);
|
|
2272
|
+
}
|
|
2273
|
+
writeEntry({ query: "/explain", commandMessage: null, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: fullText, aiError: error, shellOutput: null, erdData: null });
|
|
2274
|
+
setActive({ type: "idle" });
|
|
2329
2275
|
}
|
|
2330
2276
|
function handleExport(format) {
|
|
2331
2277
|
if (!lastResult || lastResult.rows.length === 0) {
|
|
2332
|
-
|
|
2278
|
+
writeEntry({ query: `/export ${format}`, commandMessage: { ok: false, text: "No results to export \u2014 run a query first." }, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2333
2279
|
return;
|
|
2334
2280
|
}
|
|
2335
2281
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
@@ -2349,57 +2295,36 @@ function App({ connectionState, aiUrl: aiUrl2, aiModel: aiModel2, aiKey: aiKey2,
|
|
|
2349
2295
|
);
|
|
2350
2296
|
writeFileSync5(filename, [header, ...rows].join("\n"));
|
|
2351
2297
|
}
|
|
2352
|
-
|
|
2298
|
+
writeEntry({ query: `/export ${format}`, commandMessage: { ok: true, text: `Exported to ${filename}` }, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2353
2299
|
} catch (err) {
|
|
2354
|
-
|
|
2355
|
-
}
|
|
2356
|
-
}
|
|
2357
|
-
function snapshotActiveEntry() {
|
|
2358
|
-
if (lastQuery === "") return;
|
|
2359
|
-
setCompletedEntries((prev) => [
|
|
2360
|
-
...prev,
|
|
2361
|
-
{
|
|
2362
|
-
id: entryIdRef.current++,
|
|
2363
|
-
query: lastQuery,
|
|
2364
|
-
commandMessage,
|
|
2365
|
-
queryState,
|
|
2366
|
-
elapsed,
|
|
2367
|
-
page,
|
|
2368
|
-
aiResponse,
|
|
2369
|
-
aiError,
|
|
2370
|
-
shellOutput,
|
|
2371
|
-
erdData
|
|
2372
|
-
}
|
|
2373
|
-
]);
|
|
2300
|
+
writeEntry({ query: `/export ${format}`, commandMessage: { ok: false, text: err instanceof Error ? err.message : String(err) }, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2301
|
+
}
|
|
2374
2302
|
}
|
|
2375
2303
|
async function handleShell(cmd) {
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
setIsShellRunning(true);
|
|
2379
|
-
setCommandMessage(null);
|
|
2380
|
-
setAiResponse("");
|
|
2381
|
-
setAiError(null);
|
|
2382
|
-
setQueryState({ status: "idle" });
|
|
2304
|
+
const q = `!${cmd}`;
|
|
2305
|
+
setActive({ type: "loading", label: "Shell", query: q });
|
|
2383
2306
|
const result = await runShell(cmd);
|
|
2384
2307
|
const combined = [result.stdout, result.stderr].filter(Boolean).join("\n");
|
|
2385
|
-
|
|
2386
|
-
|
|
2308
|
+
writeEntry({ query: q, commandMessage: null, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: "", aiError: null, shellOutput: combined || "(no output)", erdData: null });
|
|
2309
|
+
setActive({ type: "idle" });
|
|
2387
2310
|
}
|
|
2388
2311
|
async function handleSubmit(sql) {
|
|
2389
2312
|
if (sql === "/next") {
|
|
2390
|
-
|
|
2313
|
+
if (!lastResult) return;
|
|
2314
|
+
const p = lastResultPage + 1;
|
|
2315
|
+
setLastResultPage(p);
|
|
2316
|
+
writeEntry({ query: "/next", commandMessage: null, queryState: { status: "success", result: lastResult }, elapsed: null, page: p, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2391
2317
|
return;
|
|
2392
2318
|
}
|
|
2393
2319
|
if (sql === "/prev") {
|
|
2394
|
-
|
|
2320
|
+
if (!lastResult || lastResultPage === 0) return;
|
|
2321
|
+
const p = lastResultPage - 1;
|
|
2322
|
+
setLastResultPage(p);
|
|
2323
|
+
writeEntry({ query: "/prev", commandMessage: null, queryState: { status: "success", result: lastResult }, elapsed: null, page: p, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2395
2324
|
return;
|
|
2396
2325
|
}
|
|
2397
|
-
snapshotActiveEntry();
|
|
2398
2326
|
if (sql.startsWith("!")) {
|
|
2399
|
-
|
|
2400
|
-
setLastQuery(sql);
|
|
2401
|
-
setShellOutput(null);
|
|
2402
|
-
void handleShell(cmd);
|
|
2327
|
+
void handleShell(sql.slice(1).trim());
|
|
2403
2328
|
return;
|
|
2404
2329
|
}
|
|
2405
2330
|
if (sql.startsWith("/") || sql.startsWith("\\")) {
|
|
@@ -2424,62 +2349,45 @@ function App({ connectionState, aiUrl: aiUrl2, aiModel: aiModel2, aiKey: aiKey2,
|
|
|
2424
2349
|
},
|
|
2425
2350
|
onClear: () => {
|
|
2426
2351
|
setCompletedEntries([]);
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
setShellOutput(null);
|
|
2431
|
-
setAiResponse("");
|
|
2432
|
-
setAiError(null);
|
|
2433
|
-
setElapsed(null);
|
|
2434
|
-
setPage(0);
|
|
2435
|
-
process.stdout.write("\x1B[2J\x1B[H");
|
|
2352
|
+
setHasHistory(false);
|
|
2353
|
+
setActive({ type: "idle" });
|
|
2354
|
+
process.stdout.write("\x1B[H\x1B[2J\x1B[3J");
|
|
2436
2355
|
},
|
|
2437
2356
|
aliases,
|
|
2438
2357
|
onSaveAlias: handleSaveAlias,
|
|
2439
2358
|
onDeleteAlias: handleDeleteAlias
|
|
2440
2359
|
});
|
|
2441
2360
|
if (result.cleared) return;
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
setPage(0);
|
|
2448
|
-
setQueryState({ status: "idle" });
|
|
2449
|
-
if (result.helpData) setCommandMessage({ ok: result.ok, text: "", helpData: result.helpData });
|
|
2450
|
-
else if (result.message) setCommandMessage({ ok: result.ok, text: result.message });
|
|
2451
|
-
else setCommandMessage(null);
|
|
2361
|
+
if (result.helpData) {
|
|
2362
|
+
writeEntry({ query: sql, commandMessage: { ok: result.ok, text: "", helpData: result.helpData }, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2363
|
+
} else if (result.message) {
|
|
2364
|
+
writeEntry({ query: sql, commandMessage: { ok: result.ok, text: result.message }, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2365
|
+
}
|
|
2452
2366
|
return;
|
|
2453
2367
|
}
|
|
2454
2368
|
void handleQuery(sql);
|
|
2455
2369
|
}
|
|
2456
|
-
const isLoading =
|
|
2370
|
+
const isLoading = active.type !== "idle";
|
|
2457
2371
|
const isConnected = connectionState.status === "connected";
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
/* @__PURE__ */
|
|
2468
|
-
/* @__PURE__ */
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
/* @__PURE__ */ jsx7(Box7, { flexDirection: "column", marginTop: 1, children: aiError ? /* @__PURE__ */ jsx7(ErrorBox, { message: aiError }) : /* @__PURE__ */ jsxs7(Text7, { color: PLACEHOLDER2, children: [
|
|
2476
|
-
aiResponse,
|
|
2477
|
-
isStreaming && /* @__PURE__ */ jsx7(Text7, { color: PLACEHOLDER2, children: "\u258B" })
|
|
2478
|
-
] }) })
|
|
2479
|
-
] }) : !commandMessage && /* @__PURE__ */ jsx7(QueryResult, { state: queryState, elapsed, page, pageSize: activePageSize() })
|
|
2480
|
-
] }) })
|
|
2372
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
2373
|
+
/* @__PURE__ */ jsx5(Static, { items: completedEntries, children: ({ id, formatted }) => /* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsx5(Text5, { children: formatted }) }, id) }),
|
|
2374
|
+
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingX: 1, children: [
|
|
2375
|
+
!hasHistory && active.type === "idle" && /* @__PURE__ */ jsx5(Banner, { connectionState }),
|
|
2376
|
+
active.type === "loading" && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginBottom: 1, children: [
|
|
2377
|
+
/* @__PURE__ */ jsx5(QueryHeader, { label: active.label, query: active.query }),
|
|
2378
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: " running\u2026" })
|
|
2379
|
+
] }),
|
|
2380
|
+
active.type === "streaming" && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginBottom: 1, children: [
|
|
2381
|
+
/* @__PURE__ */ jsx5(QueryHeader, { label: "Query", query: active.query }),
|
|
2382
|
+
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
|
|
2383
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accent, bold: true, children: "Explanation:" }),
|
|
2384
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: active.error ? /* @__PURE__ */ jsx5(ErrorBox, { message: active.error }) : /* @__PURE__ */ jsxs5(Text5, { color: PLACEHOLDER2, children: [
|
|
2385
|
+
active.text,
|
|
2386
|
+
/* @__PURE__ */ jsx5(Text5, { color: PLACEHOLDER2, children: "\u258B" })
|
|
2387
|
+
] }) })
|
|
2388
|
+
] })
|
|
2481
2389
|
] }),
|
|
2482
|
-
isConnected ? /* @__PURE__ */
|
|
2390
|
+
isConnected ? /* @__PURE__ */ jsx5(
|
|
2483
2391
|
QueryInput,
|
|
2484
2392
|
{
|
|
2485
2393
|
onSubmit: handleSubmit,
|
|
@@ -2491,16 +2399,16 @@ function App({ connectionState, aiUrl: aiUrl2, aiModel: aiModel2, aiKey: aiKey2,
|
|
|
2491
2399
|
aliases,
|
|
2492
2400
|
schema: schema ?? void 0
|
|
2493
2401
|
}
|
|
2494
|
-
) : /* @__PURE__ */
|
|
2495
|
-
(vimEnabled || inputIsShell) && /* @__PURE__ */
|
|
2402
|
+
) : /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Not connected. Press Ctrl+C to exit." }),
|
|
2403
|
+
(vimEnabled || inputIsShell) && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { bold: true, color: inputIsShell ? theme.shellMode : vimMode === "NORMAL" ? theme.normalMode : theme.insertMode, children: isRawModeSupported ? inputIsShell ? "[SHELL]" : `[${vimMode}]` : "" }) })
|
|
2496
2404
|
] })
|
|
2497
2405
|
] });
|
|
2498
2406
|
}
|
|
2499
2407
|
|
|
2500
2408
|
// src/ui/components/ConnectionWizard.tsx
|
|
2501
2409
|
import { useState as useState5 } from "react";
|
|
2502
|
-
import { Box as
|
|
2503
|
-
import { jsx as
|
|
2410
|
+
import { Box as Box6, Text as Text6, useInput as useInput3, useStdin as useStdin3 } from "ink";
|
|
2411
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2504
2412
|
var DRIVERS = ["postgresql", "mysql", "sqlite"];
|
|
2505
2413
|
var LABEL_WIDTH = 10;
|
|
2506
2414
|
function fieldLabels(driver) {
|
|
@@ -2655,36 +2563,36 @@ function ConnectionWizard({ onConnect, initialError }) {
|
|
|
2655
2563
|
{ isActive: isRawModeSupported }
|
|
2656
2564
|
);
|
|
2657
2565
|
const isPassword = (idx) => fields.driver !== "sqlite" && idx === 5;
|
|
2658
|
-
return /* @__PURE__ */
|
|
2659
|
-
/* @__PURE__ */
|
|
2566
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 2, paddingTop: 2, paddingBottom: 1, children: [
|
|
2567
|
+
/* @__PURE__ */ jsx6(Box6, { marginBottom: 1, children: /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.accent, children: "Connect to a database" }) }),
|
|
2660
2568
|
labels.map((label, idx) => {
|
|
2661
2569
|
const isFocused = focus === idx;
|
|
2662
2570
|
const isDriver = idx === 0;
|
|
2663
|
-
return /* @__PURE__ */
|
|
2664
|
-
/* @__PURE__ */
|
|
2665
|
-
isDriver ? /* @__PURE__ */
|
|
2666
|
-
i > 0 && /* @__PURE__ */
|
|
2667
|
-
/* @__PURE__ */
|
|
2571
|
+
return /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
2572
|
+
/* @__PURE__ */ jsx6(Text6, { color: isFocused ? theme.accent : void 0, bold: isFocused, children: label.padEnd(LABEL_WIDTH) }),
|
|
2573
|
+
isDriver ? /* @__PURE__ */ jsx6(Box6, { children: DRIVERS.map((d, i) => /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
2574
|
+
i > 0 && /* @__PURE__ */ jsx6(Text6, { children: " " }),
|
|
2575
|
+
/* @__PURE__ */ jsxs6(Text6, { color: fields.driver === d ? theme.accent : void 0, bold: fields.driver === d, children: [
|
|
2668
2576
|
fields.driver === d ? "\u25CF " : "\u25CB ",
|
|
2669
2577
|
d.charAt(0).toUpperCase() + d.slice(1)
|
|
2670
2578
|
] })
|
|
2671
|
-
] }, d)) }) : /* @__PURE__ */
|
|
2672
|
-
/* @__PURE__ */
|
|
2673
|
-
isFocused && /* @__PURE__ */
|
|
2674
|
-
isFocused && isPassword(idx) && keychainHint && /* @__PURE__ */
|
|
2579
|
+
] }, d)) }) : /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
2580
|
+
/* @__PURE__ */ jsx6(Text6, { children: isPassword(idx) ? "\u2022".repeat(getTextValue(idx).length) : getTextValue(idx) }),
|
|
2581
|
+
isFocused && /* @__PURE__ */ jsx6(Text6, { color: theme.accent, bold: true, children: "\u258C" }),
|
|
2582
|
+
isFocused && isPassword(idx) && keychainHint && /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: " (from keychain)" })
|
|
2675
2583
|
] })
|
|
2676
2584
|
] }, label);
|
|
2677
2585
|
}),
|
|
2678
|
-
/* @__PURE__ */
|
|
2586
|
+
/* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: connecting ? /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Connecting\u2026" }) : error ? /* @__PURE__ */ jsxs6(Text6, { color: theme.error, children: [
|
|
2679
2587
|
"\u2717 ",
|
|
2680
2588
|
error
|
|
2681
2589
|
] }) : null }),
|
|
2682
|
-
/* @__PURE__ */
|
|
2590
|
+
/* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Tab \xB7 \u2191\u2193 navigate Enter connect \u2190\u2192 cycle driver" }) })
|
|
2683
2591
|
] });
|
|
2684
2592
|
}
|
|
2685
2593
|
|
|
2686
2594
|
// src/index.tsx
|
|
2687
|
-
import { jsx as
|
|
2595
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
2688
2596
|
var { values } = parseArgs({
|
|
2689
2597
|
args: process.argv.slice(2).filter((a) => a !== "--"),
|
|
2690
2598
|
options: {
|
|
@@ -2714,10 +2622,10 @@ function Root({ initialDsn: initialDsn2, aiUrl: aiUrl2, aiModel: aiModel2, aiKey
|
|
|
2714
2622
|
}
|
|
2715
2623
|
}, []);
|
|
2716
2624
|
if (initialDsn2 && !connectionState && !dsnError) {
|
|
2717
|
-
return /* @__PURE__ */
|
|
2625
|
+
return /* @__PURE__ */ jsx7(Box7, { paddingX: 2, paddingTop: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Connecting\u2026" }) });
|
|
2718
2626
|
}
|
|
2719
2627
|
if (!connectionState) {
|
|
2720
|
-
return /* @__PURE__ */
|
|
2628
|
+
return /* @__PURE__ */ jsx7(ConnectionWizard, { onConnect: setConnectionState, initialError: dsnError ?? void 0 });
|
|
2721
2629
|
}
|
|
2722
2630
|
async function handleChangeDatabase(database) {
|
|
2723
2631
|
if (connectionState.status !== "connected") return;
|
|
@@ -2727,7 +2635,7 @@ function Root({ initialDsn: initialDsn2, aiUrl: aiUrl2, aiModel: aiModel2, aiKey
|
|
|
2727
2635
|
const next = await connectParams({ ...current.params, database });
|
|
2728
2636
|
setConnectionState(next);
|
|
2729
2637
|
}
|
|
2730
|
-
return /* @__PURE__ */
|
|
2638
|
+
return /* @__PURE__ */ jsx7(
|
|
2731
2639
|
App,
|
|
2732
2640
|
{
|
|
2733
2641
|
connectionState,
|
|
@@ -2740,10 +2648,7 @@ function Root({ initialDsn: initialDsn2, aiUrl: aiUrl2, aiModel: aiModel2, aiKey
|
|
|
2740
2648
|
}
|
|
2741
2649
|
);
|
|
2742
2650
|
}
|
|
2743
|
-
process.stdout.write("\x1B[?1049h\x1B[H");
|
|
2744
|
-
process.on("exit", () => process.stdout.write("\x1B[?1049l"));
|
|
2745
|
-
process.on("SIGTERM", () => process.exit(0));
|
|
2746
2651
|
render(
|
|
2747
|
-
/* @__PURE__ */
|
|
2652
|
+
/* @__PURE__ */ jsx7(Root, { initialDsn, aiUrl, aiModel, aiKey }),
|
|
2748
2653
|
{ exitOnCtrlC: true }
|
|
2749
2654
|
);
|