@deaquinodev/querky 0.4.8 → 0.4.10
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 +412 -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.10" : 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,208 @@ 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);
|
|
2042
1889
|
}
|
|
2043
|
-
function
|
|
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");
|
|
1973
|
+
}
|
|
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);
|
|
2031
|
+
function renderTable(t, m, color) {
|
|
2032
|
+
const { nameW, typeW, keyW, totalW } = m;
|
|
2033
|
+
const sp = " ".repeat(PAD);
|
|
2034
|
+
const p = (s, w) => s.slice(0, w).padEnd(w);
|
|
2035
|
+
const bdr = (s) => c(ERD_BORDER, s);
|
|
2036
|
+
const tc = (s) => cbold(color, s);
|
|
2037
|
+
const top = bdr("\u256D" + "\u2500".repeat(totalW - 2) + "\u256E");
|
|
2038
|
+
const headerW = totalW - 4;
|
|
2039
|
+
const headerLine = bdr("\u2502") + tc(sp + p(t.name, headerW) + sp) + bdr("\u2502");
|
|
2040
|
+
const sep = bdr("\u251C" + "\u2500".repeat(nameW + PAD * 2) + "\u252C" + "\u2500".repeat(typeW + PAD * 2) + "\u252C" + "\u2500".repeat(keyW + PAD * 2) + "\u2524");
|
|
2041
|
+
const bot = bdr("\u2570" + "\u2500".repeat(nameW + PAD * 2) + "\u2534" + "\u2500".repeat(typeW + PAD * 2) + "\u2534" + "\u2500".repeat(keyW + PAD * 2) + "\u256F");
|
|
2042
|
+
const out = [top, headerLine, sep];
|
|
2043
|
+
for (const col of t.columns) {
|
|
2044
|
+
let keyPart;
|
|
2045
|
+
if (col.isPk) {
|
|
2046
|
+
keyPart = sp + bold(p("PK", keyW)) + sp;
|
|
2047
|
+
} else if (col.fkTable) {
|
|
2048
|
+
const fkColor = colorMap.get(col.fkTable) ?? color;
|
|
2049
|
+
keyPart = sp + dim(FK_PREFIX) + c(fkColor, p(col.fkTable, keyW - FK_PREFIX.length)) + sp;
|
|
2050
|
+
} else {
|
|
2051
|
+
keyPart = sp + " ".repeat(keyW) + sp;
|
|
2052
|
+
}
|
|
2053
|
+
out.push(
|
|
2054
|
+
bdr("\u2502") + sp + p(col.name, nameW) + sp + bdr("\u2502") + dim(sp + p(col.type, typeW) + sp) + bdr("\u2502") + keyPart + bdr("\u2502")
|
|
2055
|
+
);
|
|
2056
|
+
}
|
|
2057
|
+
out.push(bot);
|
|
2058
|
+
return out;
|
|
2059
|
+
}
|
|
2044
2060
|
const rows = [];
|
|
2045
|
-
let row = [];
|
|
2046
|
-
let
|
|
2047
|
-
|
|
2048
|
-
const w = metrics[i].totalW;
|
|
2061
|
+
let row = [], usedW = 0;
|
|
2062
|
+
for (let i = 0; i < allMetrics.length; i++) {
|
|
2063
|
+
const w = allMetrics[i].totalW;
|
|
2049
2064
|
if (row.length === 0) {
|
|
2050
2065
|
row.push(i);
|
|
2051
2066
|
usedW = w;
|
|
@@ -2059,120 +2074,83 @@ function groupIntoRows(metrics, termW) {
|
|
|
2059
2074
|
}
|
|
2060
2075
|
}
|
|
2061
2076
|
if (row.length > 0) rows.push(row);
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
p(table.name, headerW),
|
|
2079
|
-
sp
|
|
2080
|
-
] }),
|
|
2081
|
-
/* @__PURE__ */ jsx6(Text6, { color: BORDER2, children: "\u2502" })
|
|
2082
|
-
] }),
|
|
2083
|
-
/* @__PURE__ */ jsx6(Text6, { color: BORDER2, children: sep }),
|
|
2084
|
-
table.columns.map((col, i) => /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
2085
|
-
/* @__PURE__ */ jsx6(Text6, { color: BORDER2, children: "\u2502" }),
|
|
2086
|
-
/* @__PURE__ */ jsxs6(Text6, { children: [
|
|
2087
|
-
sp,
|
|
2088
|
-
p(col.name, nameW),
|
|
2089
|
-
sp
|
|
2090
|
-
] }),
|
|
2091
|
-
/* @__PURE__ */ jsx6(Text6, { color: BORDER2, children: "\u2502" }),
|
|
2092
|
-
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
2093
|
-
sp,
|
|
2094
|
-
p(col.type, typeW),
|
|
2095
|
-
sp
|
|
2096
|
-
] }),
|
|
2097
|
-
/* @__PURE__ */ jsx6(Text6, { color: BORDER2, children: "\u2502" }),
|
|
2098
|
-
col.isPk ? /* @__PURE__ */ jsxs6(Text6, { bold: true, children: [
|
|
2099
|
-
sp,
|
|
2100
|
-
p("PK", keyW),
|
|
2101
|
-
sp
|
|
2102
|
-
] }) : col.fkTable ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
2103
|
-
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
2104
|
-
sp,
|
|
2105
|
-
FK_PREFIX
|
|
2106
|
-
] }),
|
|
2107
|
-
/* @__PURE__ */ jsxs6(Text6, { color: colorMap.get(col.fkTable) ?? color, children: [
|
|
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
|
-
] });
|
|
2077
|
+
const output = [];
|
|
2078
|
+
for (const tableRow of rows) {
|
|
2079
|
+
const blocks = tableRow.map(
|
|
2080
|
+
(ti) => renderTable(data.tables[ti], allMetrics[ti], colorMap.get(data.tables[ti].name) ?? ERD_PALETTE[0])
|
|
2081
|
+
);
|
|
2082
|
+
const height = Math.max(...blocks.map((b) => b.length));
|
|
2083
|
+
for (let line = 0; line < height; line++) {
|
|
2084
|
+
const parts = blocks.map((b, j) => {
|
|
2085
|
+
const l = b[line] ?? " ".repeat(allMetrics[tableRow[j]].totalW);
|
|
2086
|
+
return j < blocks.length - 1 ? l + " ".repeat(GAP) : l;
|
|
2087
|
+
});
|
|
2088
|
+
output.push(parts.join(""));
|
|
2089
|
+
}
|
|
2090
|
+
output.push("");
|
|
2091
|
+
}
|
|
2092
|
+
return output.join("\n").trimEnd();
|
|
2120
2093
|
}
|
|
2121
|
-
function
|
|
2122
|
-
|
|
2123
|
-
|
|
2094
|
+
function fmtAi(text, error) {
|
|
2095
|
+
const lines = [cbold(ACCENT2, "Explanation:"), ""];
|
|
2096
|
+
if (error) {
|
|
2097
|
+
lines.push(fmtError(error));
|
|
2098
|
+
} else {
|
|
2099
|
+
lines.push(c(AI_COL, text));
|
|
2124
2100
|
}
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
);
|
|
2130
|
-
const
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2101
|
+
return lines.join("\n");
|
|
2102
|
+
}
|
|
2103
|
+
function fmtEntry(entry) {
|
|
2104
|
+
const isShell = entry.query.startsWith("!");
|
|
2105
|
+
const isCommand = !isShell && (entry.query.startsWith("/") || entry.query.startsWith("\\"));
|
|
2106
|
+
const label = isShell ? "Shell" : isCommand ? "Command" : "Query";
|
|
2107
|
+
const lines = [" " + fmtHeader(label, entry.query), ""];
|
|
2108
|
+
if (isShell) {
|
|
2109
|
+
if (entry.shellOutput !== null) lines.push(" " + entry.shellOutput.replace(/\n/g, "\n "));
|
|
2110
|
+
} else if (entry.commandMessage) {
|
|
2111
|
+
if (entry.commandMessage.helpData) {
|
|
2112
|
+
lines.push(fmtHelp(entry.commandMessage.helpData).replace(/\n/g, "\n "));
|
|
2113
|
+
} else if (entry.commandMessage.ok) {
|
|
2114
|
+
lines.push(" " + fmtOk(entry.commandMessage.text));
|
|
2115
|
+
} else {
|
|
2116
|
+
lines.push(" " + fmtError(entry.commandMessage.text));
|
|
2138
2117
|
}
|
|
2139
|
-
|
|
2118
|
+
} else if (entry.erdData) {
|
|
2119
|
+
lines.push(" " + fmtErd(entry.erdData).replace(/\n/g, "\n "));
|
|
2120
|
+
} else if (entry.aiResponse || entry.aiError) {
|
|
2121
|
+
lines.push(" " + fmtAi(entry.aiResponse, entry.aiError).replace(/\n/g, "\n "));
|
|
2122
|
+
} else {
|
|
2123
|
+
const result = fmtQueryResult(entry.queryState, entry.elapsed, entry.page, 50);
|
|
2124
|
+
if (result) lines.push(" " + result.replace(/\n/g, "\n "));
|
|
2125
|
+
}
|
|
2126
|
+
lines.push("");
|
|
2127
|
+
return lines.join("\n");
|
|
2140
2128
|
}
|
|
2141
2129
|
|
|
2142
2130
|
// src/ui/components/App.tsx
|
|
2143
|
-
import {
|
|
2144
|
-
var PAGE_SIZE = 50;
|
|
2131
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2145
2132
|
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
2133
|
var QUERY_HEADER_COLOR = "#9ca3af";
|
|
2156
2134
|
function QueryHeader({ label, query }) {
|
|
2157
2135
|
const isMultiLine = query.includes("\n");
|
|
2158
2136
|
if (isMultiLine) {
|
|
2159
|
-
return /* @__PURE__ */
|
|
2160
|
-
/* @__PURE__ */
|
|
2161
|
-
/* @__PURE__ */
|
|
2162
|
-
/* @__PURE__ */
|
|
2137
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
2138
|
+
/* @__PURE__ */ jsxs5(Text5, { children: [
|
|
2139
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accent, bold: true, children: "\u25CF " }),
|
|
2140
|
+
/* @__PURE__ */ jsxs5(Text5, { color: QUERY_HEADER_COLOR, bold: true, children: [
|
|
2163
2141
|
label,
|
|
2164
2142
|
":"
|
|
2165
2143
|
] })
|
|
2166
2144
|
] }),
|
|
2167
|
-
query.split("\n").map((line, i) => /* @__PURE__ */
|
|
2145
|
+
query.split("\n").map((line, i) => /* @__PURE__ */ jsxs5(Text5, { color: QUERY_HEADER_COLOR, bold: true, children: [
|
|
2168
2146
|
" ",
|
|
2169
2147
|
line
|
|
2170
2148
|
] }, i))
|
|
2171
2149
|
] });
|
|
2172
2150
|
}
|
|
2173
|
-
return /* @__PURE__ */
|
|
2174
|
-
/* @__PURE__ */
|
|
2175
|
-
/* @__PURE__ */
|
|
2151
|
+
return /* @__PURE__ */ jsxs5(Text5, { children: [
|
|
2152
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accent, bold: true, children: "\u25CF " }),
|
|
2153
|
+
/* @__PURE__ */ jsxs5(Text5, { color: QUERY_HEADER_COLOR, bold: true, children: [
|
|
2176
2154
|
label,
|
|
2177
2155
|
"(",
|
|
2178
2156
|
query,
|
|
@@ -2180,54 +2158,31 @@ function QueryHeader({ label, query }) {
|
|
|
2180
2158
|
] })
|
|
2181
2159
|
] });
|
|
2182
2160
|
}
|
|
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
2161
|
function App({ connectionState, aiUrl: aiUrl2, aiModel: aiModel2, aiKey: aiKey2, onChangeDatabase }) {
|
|
2204
2162
|
const { exit } = useApp();
|
|
2205
2163
|
const { isRawModeSupported } = useStdin2();
|
|
2206
|
-
const [
|
|
2207
|
-
const [
|
|
2164
|
+
const [active, setActive] = useState4({ type: "idle" });
|
|
2165
|
+
const [hasHistory, setHasHistory] = useState4(false);
|
|
2166
|
+
const [completedEntries, setCompletedEntries] = useState4([]);
|
|
2167
|
+
const entryIdRef = useRef2(0);
|
|
2208
2168
|
const [lastSqlQuery, setLastSqlQuery] = useState4("");
|
|
2209
2169
|
const [lastResult, setLastResult] = useState4(null);
|
|
2210
|
-
const [
|
|
2170
|
+
const [lastResultPage, setLastResultPage] = useState4(0);
|
|
2211
2171
|
const [vimMode, setVimMode] = useState4("INSERT");
|
|
2212
2172
|
const [inputIsShell, setInputIsShell] = useState4(false);
|
|
2213
|
-
const [elapsed, setElapsed] = useState4(null);
|
|
2214
2173
|
const [vimEnabled, setVimEnabled] = useState4(true);
|
|
2215
|
-
const [commandMessage, setCommandMessage] = useState4(null);
|
|
2216
2174
|
const [history, setHistory] = useState4(() => loadHistory());
|
|
2217
2175
|
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
2176
|
const aliasScope = connectionState.status === "connected" ? makeScope(connectionState.driver, connectionState.user, connectionState.host, connectionState.database) : "";
|
|
2228
2177
|
const [aliases, setAliases] = useState4(
|
|
2229
2178
|
() => aliasScope ? getAllAliases(aliasScope) : {}
|
|
2230
2179
|
);
|
|
2180
|
+
function writeEntry(entry) {
|
|
2181
|
+
const formatted = fmtEntry(entry);
|
|
2182
|
+
const id = String(++entryIdRef.current);
|
|
2183
|
+
setCompletedEntries((prev) => [...prev, { id, formatted }]);
|
|
2184
|
+
setHasHistory(true);
|
|
2185
|
+
}
|
|
2231
2186
|
function handleSaveAlias(name, query) {
|
|
2232
2187
|
saveAlias(aliasScope, name, query);
|
|
2233
2188
|
setAliases(getAllAliases(aliasScope));
|
|
@@ -2271,65 +2226,55 @@ function App({ connectionState, aiUrl: aiUrl2, aiModel: aiModel2, aiKey: aiKey2,
|
|
|
2271
2226
|
},
|
|
2272
2227
|
{ isActive: isRawModeSupported }
|
|
2273
2228
|
);
|
|
2274
|
-
async function
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
setIsStreaming(false);
|
|
2229
|
+
async function handleQuery(sql) {
|
|
2230
|
+
if (connectionState.status !== "connected") return;
|
|
2231
|
+
setLastSqlQuery(sql);
|
|
2232
|
+
setActive({ type: "loading", label: "Query", query: sql });
|
|
2233
|
+
const updated = addToHistory(history, sql);
|
|
2234
|
+
setHistory(updated);
|
|
2235
|
+
saveHistory(updated);
|
|
2236
|
+
const start = Date.now();
|
|
2237
|
+
const result = await runQuery(connectionState.client, sql);
|
|
2238
|
+
const elapsed = Date.now() - start;
|
|
2239
|
+
if (result.status === "success") {
|
|
2240
|
+
setLastResult(result.result);
|
|
2241
|
+
setLastResultPage(0);
|
|
2288
2242
|
}
|
|
2243
|
+
writeEntry({ query: sql, commandMessage: null, queryState: result, elapsed, page: 0, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2244
|
+
setActive({ type: "idle" });
|
|
2289
2245
|
}
|
|
2290
2246
|
async function handleErd() {
|
|
2291
2247
|
if (connectionState.status !== "connected") {
|
|
2292
|
-
|
|
2248
|
+
writeEntry({ query: "/erd", commandMessage: { ok: false, text: "Not connected." }, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2293
2249
|
return;
|
|
2294
2250
|
}
|
|
2295
|
-
|
|
2296
|
-
setIsErdLoading(true);
|
|
2297
|
-
setCommandMessage(null);
|
|
2298
|
-
setQueryState({ status: "idle" });
|
|
2299
|
-
setAiResponse("");
|
|
2300
|
-
setAiError(null);
|
|
2251
|
+
setActive({ type: "loading", label: "Command", query: "/erd" });
|
|
2301
2252
|
try {
|
|
2302
2253
|
const data = await fetchErd(connectionState.client, connectionState.driver);
|
|
2303
|
-
|
|
2254
|
+
writeEntry({ query: "/erd", commandMessage: null, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: "", aiError: null, shellOutput: null, erdData: data });
|
|
2304
2255
|
} catch (err) {
|
|
2305
|
-
|
|
2306
|
-
} finally {
|
|
2307
|
-
setIsErdLoading(false);
|
|
2256
|
+
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
2257
|
}
|
|
2258
|
+
setActive({ type: "idle" });
|
|
2309
2259
|
}
|
|
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);
|
|
2260
|
+
async function handleExplain(query) {
|
|
2261
|
+
setActive({ type: "streaming", query, text: "", error: null });
|
|
2262
|
+
let fullText = "";
|
|
2263
|
+
let error = null;
|
|
2264
|
+
try {
|
|
2265
|
+
for await (const chunk of streamExplain(query, aiUrl2, aiModel2, aiKey2 || void 0)) {
|
|
2266
|
+
fullText += chunk;
|
|
2267
|
+
setActive({ type: "streaming", query, text: fullText, error: null });
|
|
2268
|
+
}
|
|
2269
|
+
} catch (err) {
|
|
2270
|
+
error = err instanceof Error ? err.message : String(err);
|
|
2271
|
+
}
|
|
2272
|
+
writeEntry({ query: "/explain", commandMessage: null, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: fullText, aiError: error, shellOutput: null, erdData: null });
|
|
2273
|
+
setActive({ type: "idle" });
|
|
2329
2274
|
}
|
|
2330
2275
|
function handleExport(format) {
|
|
2331
2276
|
if (!lastResult || lastResult.rows.length === 0) {
|
|
2332
|
-
|
|
2277
|
+
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
2278
|
return;
|
|
2334
2279
|
}
|
|
2335
2280
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
@@ -2349,57 +2294,36 @@ function App({ connectionState, aiUrl: aiUrl2, aiModel: aiModel2, aiKey: aiKey2,
|
|
|
2349
2294
|
);
|
|
2350
2295
|
writeFileSync5(filename, [header, ...rows].join("\n"));
|
|
2351
2296
|
}
|
|
2352
|
-
|
|
2297
|
+
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
2298
|
} 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
|
-
]);
|
|
2299
|
+
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 });
|
|
2300
|
+
}
|
|
2374
2301
|
}
|
|
2375
2302
|
async function handleShell(cmd) {
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
setIsShellRunning(true);
|
|
2379
|
-
setCommandMessage(null);
|
|
2380
|
-
setAiResponse("");
|
|
2381
|
-
setAiError(null);
|
|
2382
|
-
setQueryState({ status: "idle" });
|
|
2303
|
+
const q = `!${cmd}`;
|
|
2304
|
+
setActive({ type: "loading", label: "Shell", query: q });
|
|
2383
2305
|
const result = await runShell(cmd);
|
|
2384
2306
|
const combined = [result.stdout, result.stderr].filter(Boolean).join("\n");
|
|
2385
|
-
|
|
2386
|
-
|
|
2307
|
+
writeEntry({ query: q, commandMessage: null, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: "", aiError: null, shellOutput: combined || "(no output)", erdData: null });
|
|
2308
|
+
setActive({ type: "idle" });
|
|
2387
2309
|
}
|
|
2388
2310
|
async function handleSubmit(sql) {
|
|
2389
2311
|
if (sql === "/next") {
|
|
2390
|
-
|
|
2312
|
+
if (!lastResult) return;
|
|
2313
|
+
const p = lastResultPage + 1;
|
|
2314
|
+
setLastResultPage(p);
|
|
2315
|
+
writeEntry({ query: "/next", commandMessage: null, queryState: { status: "success", result: lastResult }, elapsed: null, page: p, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2391
2316
|
return;
|
|
2392
2317
|
}
|
|
2393
2318
|
if (sql === "/prev") {
|
|
2394
|
-
|
|
2319
|
+
if (!lastResult || lastResultPage === 0) return;
|
|
2320
|
+
const p = lastResultPage - 1;
|
|
2321
|
+
setLastResultPage(p);
|
|
2322
|
+
writeEntry({ query: "/prev", commandMessage: null, queryState: { status: "success", result: lastResult }, elapsed: null, page: p, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2395
2323
|
return;
|
|
2396
2324
|
}
|
|
2397
|
-
snapshotActiveEntry();
|
|
2398
2325
|
if (sql.startsWith("!")) {
|
|
2399
|
-
|
|
2400
|
-
setLastQuery(sql);
|
|
2401
|
-
setShellOutput(null);
|
|
2402
|
-
void handleShell(cmd);
|
|
2326
|
+
void handleShell(sql.slice(1).trim());
|
|
2403
2327
|
return;
|
|
2404
2328
|
}
|
|
2405
2329
|
if (sql.startsWith("/") || sql.startsWith("\\")) {
|
|
@@ -2424,62 +2348,45 @@ function App({ connectionState, aiUrl: aiUrl2, aiModel: aiModel2, aiKey: aiKey2,
|
|
|
2424
2348
|
},
|
|
2425
2349
|
onClear: () => {
|
|
2426
2350
|
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");
|
|
2351
|
+
setHasHistory(false);
|
|
2352
|
+
setActive({ type: "idle" });
|
|
2353
|
+
process.stdout.write("\x1B[H\x1B[2J\x1B[3J");
|
|
2436
2354
|
},
|
|
2437
2355
|
aliases,
|
|
2438
2356
|
onSaveAlias: handleSaveAlias,
|
|
2439
2357
|
onDeleteAlias: handleDeleteAlias
|
|
2440
2358
|
});
|
|
2441
2359
|
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);
|
|
2360
|
+
if (result.helpData) {
|
|
2361
|
+
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 });
|
|
2362
|
+
} else if (result.message) {
|
|
2363
|
+
writeEntry({ query: sql, commandMessage: { ok: result.ok, text: result.message }, queryState: { status: "idle" }, elapsed: null, page: 0, aiResponse: "", aiError: null, shellOutput: null, erdData: null });
|
|
2364
|
+
}
|
|
2452
2365
|
return;
|
|
2453
2366
|
}
|
|
2454
2367
|
void handleQuery(sql);
|
|
2455
2368
|
}
|
|
2456
|
-
const isLoading =
|
|
2369
|
+
const isLoading = active.type !== "idle";
|
|
2457
2370
|
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
|
-
] }) })
|
|
2371
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
2372
|
+
/* @__PURE__ */ jsx5(Static, { items: completedEntries, children: ({ id, formatted }) => /* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsx5(Text5, { children: formatted }) }, id) }),
|
|
2373
|
+
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingX: 1, children: [
|
|
2374
|
+
!hasHistory && active.type === "idle" && /* @__PURE__ */ jsx5(Banner, { connectionState }),
|
|
2375
|
+
active.type === "loading" && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginBottom: 1, children: [
|
|
2376
|
+
/* @__PURE__ */ jsx5(QueryHeader, { label: active.label, query: active.query }),
|
|
2377
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: " running\u2026" })
|
|
2378
|
+
] }),
|
|
2379
|
+
active.type === "streaming" && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginBottom: 1, children: [
|
|
2380
|
+
/* @__PURE__ */ jsx5(QueryHeader, { label: "Query", query: active.query }),
|
|
2381
|
+
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
|
|
2382
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accent, bold: true, children: "Explanation:" }),
|
|
2383
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: active.error ? /* @__PURE__ */ jsx5(ErrorBox, { message: active.error }) : /* @__PURE__ */ jsxs5(Text5, { color: PLACEHOLDER2, children: [
|
|
2384
|
+
active.text,
|
|
2385
|
+
/* @__PURE__ */ jsx5(Text5, { color: PLACEHOLDER2, children: "\u258B" })
|
|
2386
|
+
] }) })
|
|
2387
|
+
] })
|
|
2481
2388
|
] }),
|
|
2482
|
-
isConnected ? /* @__PURE__ */
|
|
2389
|
+
isConnected ? /* @__PURE__ */ jsx5(
|
|
2483
2390
|
QueryInput,
|
|
2484
2391
|
{
|
|
2485
2392
|
onSubmit: handleSubmit,
|
|
@@ -2491,16 +2398,16 @@ function App({ connectionState, aiUrl: aiUrl2, aiModel: aiModel2, aiKey: aiKey2,
|
|
|
2491
2398
|
aliases,
|
|
2492
2399
|
schema: schema ?? void 0
|
|
2493
2400
|
}
|
|
2494
|
-
) : /* @__PURE__ */
|
|
2495
|
-
(vimEnabled || inputIsShell) && /* @__PURE__ */
|
|
2401
|
+
) : /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Not connected. Press Ctrl+C to exit." }),
|
|
2402
|
+
(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
2403
|
] })
|
|
2497
2404
|
] });
|
|
2498
2405
|
}
|
|
2499
2406
|
|
|
2500
2407
|
// src/ui/components/ConnectionWizard.tsx
|
|
2501
2408
|
import { useState as useState5 } from "react";
|
|
2502
|
-
import { Box as
|
|
2503
|
-
import { jsx as
|
|
2409
|
+
import { Box as Box6, Text as Text6, useInput as useInput3, useStdin as useStdin3 } from "ink";
|
|
2410
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2504
2411
|
var DRIVERS = ["postgresql", "mysql", "sqlite"];
|
|
2505
2412
|
var LABEL_WIDTH = 10;
|
|
2506
2413
|
function fieldLabels(driver) {
|
|
@@ -2655,36 +2562,36 @@ function ConnectionWizard({ onConnect, initialError }) {
|
|
|
2655
2562
|
{ isActive: isRawModeSupported }
|
|
2656
2563
|
);
|
|
2657
2564
|
const isPassword = (idx) => fields.driver !== "sqlite" && idx === 5;
|
|
2658
|
-
return /* @__PURE__ */
|
|
2659
|
-
/* @__PURE__ */
|
|
2565
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 2, paddingTop: 2, paddingBottom: 1, children: [
|
|
2566
|
+
/* @__PURE__ */ jsx6(Box6, { marginBottom: 1, children: /* @__PURE__ */ jsx6(Text6, { bold: true, color: theme.accent, children: "Connect to a database" }) }),
|
|
2660
2567
|
labels.map((label, idx) => {
|
|
2661
2568
|
const isFocused = focus === idx;
|
|
2662
2569
|
const isDriver = idx === 0;
|
|
2663
|
-
return /* @__PURE__ */
|
|
2664
|
-
/* @__PURE__ */
|
|
2665
|
-
isDriver ? /* @__PURE__ */
|
|
2666
|
-
i > 0 && /* @__PURE__ */
|
|
2667
|
-
/* @__PURE__ */
|
|
2570
|
+
return /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
2571
|
+
/* @__PURE__ */ jsx6(Text6, { color: isFocused ? theme.accent : void 0, bold: isFocused, children: label.padEnd(LABEL_WIDTH) }),
|
|
2572
|
+
isDriver ? /* @__PURE__ */ jsx6(Box6, { children: DRIVERS.map((d, i) => /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
2573
|
+
i > 0 && /* @__PURE__ */ jsx6(Text6, { children: " " }),
|
|
2574
|
+
/* @__PURE__ */ jsxs6(Text6, { color: fields.driver === d ? theme.accent : void 0, bold: fields.driver === d, children: [
|
|
2668
2575
|
fields.driver === d ? "\u25CF " : "\u25CB ",
|
|
2669
2576
|
d.charAt(0).toUpperCase() + d.slice(1)
|
|
2670
2577
|
] })
|
|
2671
|
-
] }, d)) }) : /* @__PURE__ */
|
|
2672
|
-
/* @__PURE__ */
|
|
2673
|
-
isFocused && /* @__PURE__ */
|
|
2674
|
-
isFocused && isPassword(idx) && keychainHint && /* @__PURE__ */
|
|
2578
|
+
] }, d)) }) : /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
2579
|
+
/* @__PURE__ */ jsx6(Text6, { children: isPassword(idx) ? "\u2022".repeat(getTextValue(idx).length) : getTextValue(idx) }),
|
|
2580
|
+
isFocused && /* @__PURE__ */ jsx6(Text6, { color: theme.accent, bold: true, children: "\u258C" }),
|
|
2581
|
+
isFocused && isPassword(idx) && keychainHint && /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: " (from keychain)" })
|
|
2675
2582
|
] })
|
|
2676
2583
|
] }, label);
|
|
2677
2584
|
}),
|
|
2678
|
-
/* @__PURE__ */
|
|
2585
|
+
/* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: connecting ? /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Connecting\u2026" }) : error ? /* @__PURE__ */ jsxs6(Text6, { color: theme.error, children: [
|
|
2679
2586
|
"\u2717 ",
|
|
2680
2587
|
error
|
|
2681
2588
|
] }) : null }),
|
|
2682
|
-
/* @__PURE__ */
|
|
2589
|
+
/* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Tab \xB7 \u2191\u2193 navigate Enter connect \u2190\u2192 cycle driver" }) })
|
|
2683
2590
|
] });
|
|
2684
2591
|
}
|
|
2685
2592
|
|
|
2686
2593
|
// src/index.tsx
|
|
2687
|
-
import { jsx as
|
|
2594
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
2688
2595
|
var { values } = parseArgs({
|
|
2689
2596
|
args: process.argv.slice(2).filter((a) => a !== "--"),
|
|
2690
2597
|
options: {
|
|
@@ -2714,10 +2621,10 @@ function Root({ initialDsn: initialDsn2, aiUrl: aiUrl2, aiModel: aiModel2, aiKey
|
|
|
2714
2621
|
}
|
|
2715
2622
|
}, []);
|
|
2716
2623
|
if (initialDsn2 && !connectionState && !dsnError) {
|
|
2717
|
-
return /* @__PURE__ */
|
|
2624
|
+
return /* @__PURE__ */ jsx7(Box7, { paddingX: 2, paddingTop: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Connecting\u2026" }) });
|
|
2718
2625
|
}
|
|
2719
2626
|
if (!connectionState) {
|
|
2720
|
-
return /* @__PURE__ */
|
|
2627
|
+
return /* @__PURE__ */ jsx7(ConnectionWizard, { onConnect: setConnectionState, initialError: dsnError ?? void 0 });
|
|
2721
2628
|
}
|
|
2722
2629
|
async function handleChangeDatabase(database) {
|
|
2723
2630
|
if (connectionState.status !== "connected") return;
|
|
@@ -2727,7 +2634,7 @@ function Root({ initialDsn: initialDsn2, aiUrl: aiUrl2, aiModel: aiModel2, aiKey
|
|
|
2727
2634
|
const next = await connectParams({ ...current.params, database });
|
|
2728
2635
|
setConnectionState(next);
|
|
2729
2636
|
}
|
|
2730
|
-
return /* @__PURE__ */
|
|
2637
|
+
return /* @__PURE__ */ jsx7(
|
|
2731
2638
|
App,
|
|
2732
2639
|
{
|
|
2733
2640
|
connectionState,
|
|
@@ -2740,10 +2647,7 @@ function Root({ initialDsn: initialDsn2, aiUrl: aiUrl2, aiModel: aiModel2, aiKey
|
|
|
2740
2647
|
}
|
|
2741
2648
|
);
|
|
2742
2649
|
}
|
|
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
2650
|
render(
|
|
2747
|
-
/* @__PURE__ */
|
|
2651
|
+
/* @__PURE__ */ jsx7(Root, { initialDsn, aiUrl, aiModel, aiKey }),
|
|
2748
2652
|
{ exitOnCtrlC: true }
|
|
2749
2653
|
);
|