@deaquinodev/querky 0.4.2 → 0.4.3
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 +198 -63
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// src/index.tsx
|
|
4
4
|
import { useState as useState5, useEffect as useEffect5 } from "react";
|
|
5
5
|
import { parseArgs } from "util";
|
|
6
|
-
import { render, Box as
|
|
6
|
+
import { render, Box as Box8, Text as Text8 } from "ink";
|
|
7
7
|
|
|
8
8
|
// src/db/client.ts
|
|
9
9
|
import { Client } from "pg";
|
|
@@ -196,7 +196,7 @@ import { useState as useState3, useEffect as useEffect4, useRef as useRef2 } fro
|
|
|
196
196
|
import { writeFileSync as writeFileSync5 } from "fs";
|
|
197
197
|
import { homedir as homedir4 } from "os";
|
|
198
198
|
import { join as join6 } from "path";
|
|
199
|
-
import { Box as
|
|
199
|
+
import { Box as Box6, Text as Text6, Static, useApp, useInput as useInput2, useStdin as useStdin2 } from "ink";
|
|
200
200
|
|
|
201
201
|
// src/db/query.ts
|
|
202
202
|
async function runQuery(client, sql) {
|
|
@@ -466,6 +466,9 @@ var PSQL_ALIASES = {
|
|
|
466
466
|
du: "users",
|
|
467
467
|
c: "changeDatabase"
|
|
468
468
|
};
|
|
469
|
+
var PSQL_REVERSE = Object.fromEntries(
|
|
470
|
+
Object.entries(PSQL_ALIASES).filter(([alias, name]) => alias !== name).map(([alias, name]) => [name, `\\${alias}`])
|
|
471
|
+
);
|
|
469
472
|
function describeBasicSql(driver, table) {
|
|
470
473
|
const t = table.replace(/'/g, "''");
|
|
471
474
|
if (driver === "postgresql") {
|
|
@@ -488,7 +491,10 @@ function describeFullSql(driver, table) {
|
|
|
488
491
|
}
|
|
489
492
|
var COMMANDS = {
|
|
490
493
|
"clear": {
|
|
491
|
-
description: "Clear the scrollback
|
|
494
|
+
description: "Clear the terminal scrollback",
|
|
495
|
+
category: "Session",
|
|
496
|
+
usage: "/clear",
|
|
497
|
+
detail: "Erases the visible screen and scrollback buffer. The next query starts fresh from the top.",
|
|
492
498
|
run: (ctx) => {
|
|
493
499
|
ctx.onClear();
|
|
494
500
|
return { ok: true, message: "", cleared: true };
|
|
@@ -496,6 +502,9 @@ var COMMANDS = {
|
|
|
496
502
|
},
|
|
497
503
|
"toggle-vim-mode": {
|
|
498
504
|
description: "Toggle vim keybindings on/off",
|
|
505
|
+
category: "Session",
|
|
506
|
+
usage: "/toggle-vim-mode",
|
|
507
|
+
detail: "Switches the query input between standard editing and vim keybindings. In NORMAL mode use motions like w, b, 0, $, x, dd. Enter INSERT mode with i, a, A, I, o, O.",
|
|
499
508
|
run: (ctx) => {
|
|
500
509
|
const next = !ctx.vimEnabled;
|
|
501
510
|
ctx.setVimEnabled(next);
|
|
@@ -503,7 +512,11 @@ var COMMANDS = {
|
|
|
503
512
|
}
|
|
504
513
|
},
|
|
505
514
|
"d": {
|
|
506
|
-
description: "List tables, or describe a table
|
|
515
|
+
description: "List tables, or describe a table",
|
|
516
|
+
category: "Schema",
|
|
517
|
+
usage: "/d [table]",
|
|
518
|
+
detail: "Without an argument, lists all tables in the current database. With a table name, shows columns, types, nullability, and defaults.",
|
|
519
|
+
example: "/d users",
|
|
507
520
|
run: (ctx) => {
|
|
508
521
|
if (!ctx.args.trim()) {
|
|
509
522
|
ctx.onQuery(DB_QUERIES[ctx.driver].tables);
|
|
@@ -514,7 +527,11 @@ var COMMANDS = {
|
|
|
514
527
|
}
|
|
515
528
|
},
|
|
516
529
|
"describe": {
|
|
517
|
-
description: "Describe a table with
|
|
530
|
+
description: "Describe a table with PK/FK/UQ constraints",
|
|
531
|
+
category: "Schema",
|
|
532
|
+
usage: "/describe <table>",
|
|
533
|
+
detail: "Like /d but includes constraint information \u2014 PK (primary key), FK (foreign key), UQ (unique) \u2014 in an extra key column. SQLite shows PK only.",
|
|
534
|
+
example: "/describe orders",
|
|
518
535
|
run: (ctx) => {
|
|
519
536
|
const table = ctx.args.trim();
|
|
520
537
|
if (!table) return { ok: false, message: "Usage: /describe <table>" };
|
|
@@ -524,6 +541,9 @@ var COMMANDS = {
|
|
|
524
541
|
},
|
|
525
542
|
"databases": {
|
|
526
543
|
description: "List available databases",
|
|
544
|
+
category: "Schema",
|
|
545
|
+
usage: "/databases",
|
|
546
|
+
detail: "Runs a driver-appropriate query to list all databases on the server.",
|
|
527
547
|
run: (ctx) => {
|
|
528
548
|
ctx.onQuery(DB_QUERIES[ctx.driver].databases);
|
|
529
549
|
return { ok: true, message: "" };
|
|
@@ -531,6 +551,9 @@ var COMMANDS = {
|
|
|
531
551
|
},
|
|
532
552
|
"tables": {
|
|
533
553
|
description: "List tables in the current database",
|
|
554
|
+
category: "Schema",
|
|
555
|
+
usage: "/tables",
|
|
556
|
+
detail: "Lists tables in the current database's public schema.",
|
|
534
557
|
run: (ctx) => {
|
|
535
558
|
ctx.onQuery(DB_QUERIES[ctx.driver].tables);
|
|
536
559
|
return { ok: true, message: "" };
|
|
@@ -538,13 +561,20 @@ var COMMANDS = {
|
|
|
538
561
|
},
|
|
539
562
|
"users": {
|
|
540
563
|
description: "List database users",
|
|
564
|
+
category: "Schema",
|
|
565
|
+
usage: "/users",
|
|
566
|
+
detail: "Lists users and their roles. On SQLite, shows a placeholder message since SQLite has no user system.",
|
|
541
567
|
run: (ctx) => {
|
|
542
568
|
ctx.onQuery(DB_QUERIES[ctx.driver].users);
|
|
543
569
|
return { ok: true, message: "" };
|
|
544
570
|
}
|
|
545
571
|
},
|
|
546
572
|
"changeDatabase": {
|
|
547
|
-
description: "Switch to a different database
|
|
573
|
+
description: "Switch to a different database",
|
|
574
|
+
category: "Session",
|
|
575
|
+
usage: "/changeDatabase <dbname>",
|
|
576
|
+
detail: "Switches the active connection to the specified database. Without an argument, shows the current database.",
|
|
577
|
+
example: "/changeDatabase myapp_prod",
|
|
548
578
|
run: (ctx) => {
|
|
549
579
|
if (!ctx.args) return { ok: true, message: `Connected to database: ${ctx.currentDatabase}` };
|
|
550
580
|
ctx.onChangeDatabase(ctx.args.trim());
|
|
@@ -552,7 +582,11 @@ var COMMANDS = {
|
|
|
552
582
|
}
|
|
553
583
|
},
|
|
554
584
|
"export": {
|
|
555
|
-
description: "Export last result to a file
|
|
585
|
+
description: "Export last result to a file",
|
|
586
|
+
category: "Data",
|
|
587
|
+
usage: "/export csv|json",
|
|
588
|
+
detail: "Writes the last query result to a timestamped file in your home directory. CSV files include a header row; JSON files are an array of row objects.",
|
|
589
|
+
example: "/export csv",
|
|
556
590
|
run: (ctx) => {
|
|
557
591
|
const fmt = ctx.args.trim().toLowerCase();
|
|
558
592
|
if (fmt !== "csv" && fmt !== "json") {
|
|
@@ -563,7 +597,11 @@ var COMMANDS = {
|
|
|
563
597
|
}
|
|
564
598
|
},
|
|
565
599
|
"explain": {
|
|
566
|
-
description: "Explain a SQL query using AI
|
|
600
|
+
description: "Explain a SQL query using AI",
|
|
601
|
+
category: "AI",
|
|
602
|
+
usage: "/explain <SQL>",
|
|
603
|
+
detail: "Sends the query to your configured AI endpoint (Ollama by default, or any OpenAI-compatible API) and streams a plain-language explanation.",
|
|
604
|
+
example: "/explain SELECT * FROM orders WHERE status = 'pending'",
|
|
567
605
|
run: (ctx) => {
|
|
568
606
|
if (!ctx.args) return { ok: false, message: "Usage: /explain <SQL query>" };
|
|
569
607
|
ctx.onExplain(ctx.args);
|
|
@@ -572,6 +610,9 @@ var COMMANDS = {
|
|
|
572
610
|
},
|
|
573
611
|
"explain-previous": {
|
|
574
612
|
description: "Explain the last executed query using AI",
|
|
613
|
+
category: "AI",
|
|
614
|
+
usage: "/explain-previous",
|
|
615
|
+
detail: "Like /explain but uses the last SQL query you ran. Useful for quickly understanding a query after seeing its results.",
|
|
575
616
|
run: (ctx) => {
|
|
576
617
|
if (!ctx.lastSqlQuery) {
|
|
577
618
|
return { ok: false, message: "No query to explain \u2014 run a SQL query first." };
|
|
@@ -581,7 +622,11 @@ var COMMANDS = {
|
|
|
581
622
|
}
|
|
582
623
|
},
|
|
583
624
|
"save": {
|
|
584
|
-
description: "Save last query as
|
|
625
|
+
description: "Save last query as a named alias",
|
|
626
|
+
category: "Aliases",
|
|
627
|
+
usage: "/save <name>",
|
|
628
|
+
detail: "Saves the last executed SQL query as a named alias scoped to the current database. Run it later with /<name>. Supports positional ($1, $2) and named (:param) substitution.",
|
|
629
|
+
example: "/save active-orders",
|
|
585
630
|
run: (ctx) => {
|
|
586
631
|
const name = ctx.args.trim();
|
|
587
632
|
if (!name) return { ok: false, message: "Usage: /save <name>" };
|
|
@@ -592,7 +637,11 @@ var COMMANDS = {
|
|
|
592
637
|
}
|
|
593
638
|
},
|
|
594
639
|
"alias": {
|
|
595
|
-
description: "Define an alias inline
|
|
640
|
+
description: "Define an alias inline",
|
|
641
|
+
category: "Aliases",
|
|
642
|
+
usage: "/alias <name> <SQL>",
|
|
643
|
+
detail: "Defines a named alias without running a query first. Equivalent to /save but lets you specify the SQL directly.",
|
|
644
|
+
example: "/alias recent SELECT * FROM events ORDER BY created_at DESC LIMIT 20",
|
|
596
645
|
run: (ctx) => {
|
|
597
646
|
const [name, ...rest] = ctx.args.trim().split(/\s+/);
|
|
598
647
|
if (!name || rest.length === 0) return { ok: false, message: "Usage: /alias <name> <SQL>" };
|
|
@@ -603,6 +652,9 @@ var COMMANDS = {
|
|
|
603
652
|
},
|
|
604
653
|
"aliases": {
|
|
605
654
|
description: "List all saved aliases for this database",
|
|
655
|
+
category: "Aliases",
|
|
656
|
+
usage: "/aliases",
|
|
657
|
+
detail: "Prints all saved aliases for the current database connection, with their SQL template.",
|
|
606
658
|
run: (ctx) => {
|
|
607
659
|
const entries = Object.entries(ctx.aliases);
|
|
608
660
|
if (entries.length === 0) return { ok: true, message: "No aliases saved. Use /save <name> or /alias <name> <SQL>." };
|
|
@@ -614,13 +666,52 @@ var COMMANDS = {
|
|
|
614
666
|
}
|
|
615
667
|
},
|
|
616
668
|
"unalias": {
|
|
617
|
-
description: "Remove a saved alias
|
|
669
|
+
description: "Remove a saved alias",
|
|
670
|
+
category: "Aliases",
|
|
671
|
+
usage: "/unalias <name>",
|
|
672
|
+
detail: "Removes a previously saved alias. Only affects aliases for the current database connection.",
|
|
673
|
+
example: "/unalias active-orders",
|
|
618
674
|
run: (ctx) => {
|
|
619
675
|
const name = ctx.args.trim();
|
|
620
676
|
if (!name) return { ok: false, message: "Usage: /unalias <name>" };
|
|
621
677
|
const removed = ctx.onDeleteAlias(name);
|
|
622
678
|
return removed ? { ok: true, message: `Removed /${name}` } : { ok: false, message: `No alias named /${name}` };
|
|
623
679
|
}
|
|
680
|
+
},
|
|
681
|
+
"help": {
|
|
682
|
+
description: "Show help for all commands or a specific command",
|
|
683
|
+
category: "Session",
|
|
684
|
+
usage: "/help [command]",
|
|
685
|
+
detail: "Without arguments, lists all commands grouped by category. With a command name, shows detailed usage and an example.",
|
|
686
|
+
example: "/help explain",
|
|
687
|
+
run: (ctx) => {
|
|
688
|
+
const arg = ctx.args.trim();
|
|
689
|
+
if (arg) {
|
|
690
|
+
const name = PSQL_ALIASES[arg] ?? arg;
|
|
691
|
+
const cmd = COMMANDS[name];
|
|
692
|
+
if (!cmd) return { ok: false, message: `Unknown command: /${arg}` };
|
|
693
|
+
const entry = {
|
|
694
|
+
name,
|
|
695
|
+
usage: cmd.usage,
|
|
696
|
+
description: cmd.description,
|
|
697
|
+
psqlAlias: PSQL_REVERSE[name],
|
|
698
|
+
detail: cmd.detail,
|
|
699
|
+
example: cmd.example
|
|
700
|
+
};
|
|
701
|
+
return { ok: true, message: "", helpData: { mode: "detail", entry } };
|
|
702
|
+
}
|
|
703
|
+
const categoryOrder = ["AI", "Schema", "Data", "Aliases", "Session"];
|
|
704
|
+
const groups = categoryOrder.map((cat) => ({
|
|
705
|
+
category: cat,
|
|
706
|
+
entries: Object.entries(COMMANDS).filter(([, cmd]) => cmd.category === cat).map(([name, cmd]) => ({
|
|
707
|
+
name,
|
|
708
|
+
usage: cmd.usage,
|
|
709
|
+
description: cmd.description,
|
|
710
|
+
psqlAlias: PSQL_REVERSE[name]
|
|
711
|
+
}))
|
|
712
|
+
})).filter((g) => g.entries.length > 0);
|
|
713
|
+
return { ok: true, message: "", helpData: { mode: "list", groups } };
|
|
714
|
+
}
|
|
624
715
|
}
|
|
625
716
|
};
|
|
626
717
|
var BUILTIN_COMMAND_LIST = Object.entries(COMMANDS).map(([name, cmd]) => ({
|
|
@@ -1760,8 +1851,51 @@ function Banner({ connectionState }) {
|
|
|
1760
1851
|
] });
|
|
1761
1852
|
}
|
|
1762
1853
|
|
|
1854
|
+
// src/ui/components/HelpView.tsx
|
|
1855
|
+
import { Box as Box5, Text as Text5 } from "ink";
|
|
1856
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1857
|
+
var USAGE_WIDTH = 28;
|
|
1858
|
+
function HelpView({ data }) {
|
|
1859
|
+
if (data.mode === "detail" && data.entry) {
|
|
1860
|
+
const { usage, description, psqlAlias, detail, example } = data.entry;
|
|
1861
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
|
|
1862
|
+
/* @__PURE__ */ jsxs5(Text5, { bold: true, color: "white", children: [
|
|
1863
|
+
usage,
|
|
1864
|
+
psqlAlias ? ` ${psqlAlias}` : ""
|
|
1865
|
+
] }),
|
|
1866
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { children: description }) }),
|
|
1867
|
+
detail && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: detail }) }),
|
|
1868
|
+
example && /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, children: [
|
|
1869
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Example: " }),
|
|
1870
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accent, children: example })
|
|
1871
|
+
] })
|
|
1872
|
+
] });
|
|
1873
|
+
}
|
|
1874
|
+
if (data.mode === "list" && data.groups) {
|
|
1875
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
|
|
1876
|
+
data.groups.map((group, gi) => /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginBottom: gi < data.groups.length - 1 ? 1 : 0, children: [
|
|
1877
|
+
/* @__PURE__ */ jsx5(Text5, { bold: true, color: theme.accent, children: group.category }),
|
|
1878
|
+
group.entries.map((entry) => /* @__PURE__ */ jsxs5(Box5, { marginLeft: 2, children: [
|
|
1879
|
+
/* @__PURE__ */ jsx5(Text5, { color: "white", children: entry.usage.padEnd(USAGE_WIDTH) }),
|
|
1880
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: entry.description }),
|
|
1881
|
+
entry.psqlAlias && /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
|
|
1882
|
+
" ",
|
|
1883
|
+
entry.psqlAlias
|
|
1884
|
+
] })
|
|
1885
|
+
] }, entry.name))
|
|
1886
|
+
] }, group.category)),
|
|
1887
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
|
|
1888
|
+
"/help ",
|
|
1889
|
+
"<command>",
|
|
1890
|
+
" for more details."
|
|
1891
|
+
] }) })
|
|
1892
|
+
] });
|
|
1893
|
+
}
|
|
1894
|
+
return null;
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1763
1897
|
// src/ui/components/App.tsx
|
|
1764
|
-
import { Fragment as Fragment3, jsx as
|
|
1898
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1765
1899
|
var PAGE_SIZE = 50;
|
|
1766
1900
|
var PLACEHOLDER2 = "#a5b4fc";
|
|
1767
1901
|
function activePageSize() {
|
|
@@ -1778,23 +1912,23 @@ function EntryView({ entry }) {
|
|
|
1778
1912
|
const isShell = entry.query.startsWith("!");
|
|
1779
1913
|
const isCommand = !isShell && (entry.query.startsWith("/") || entry.query.startsWith("\\"));
|
|
1780
1914
|
const label = isShell ? "Shell:" : isCommand ? "Command:" : "Query:";
|
|
1781
|
-
return /* @__PURE__ */
|
|
1782
|
-
/* @__PURE__ */
|
|
1783
|
-
/* @__PURE__ */
|
|
1915
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginBottom: 1, paddingX: 1, children: [
|
|
1916
|
+
/* @__PURE__ */ jsxs6(Box6, { borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
1917
|
+
/* @__PURE__ */ jsxs6(Text6, { color: theme.accent, bold: true, children: [
|
|
1784
1918
|
label,
|
|
1785
1919
|
" "
|
|
1786
1920
|
] }),
|
|
1787
|
-
/* @__PURE__ */
|
|
1921
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: entry.query })
|
|
1788
1922
|
] }),
|
|
1789
|
-
/* @__PURE__ */
|
|
1790
|
-
entry.commandMessage && (entry.commandMessage.ok ? /* @__PURE__ */
|
|
1923
|
+
/* @__PURE__ */ jsx6(Box6, { marginTop: 1, flexDirection: "column", children: isShell ? entry.shellOutput !== null && /* @__PURE__ */ jsx6(Text6, { children: entry.shellOutput || "(no output)" }) : /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
1924
|
+
entry.commandMessage && (entry.commandMessage.helpData ? /* @__PURE__ */ jsx6(HelpView, { data: entry.commandMessage.helpData }) : entry.commandMessage.ok ? /* @__PURE__ */ jsxs6(Text6, { color: theme.accent, children: [
|
|
1791
1925
|
"\u2713 ",
|
|
1792
1926
|
entry.commandMessage.text
|
|
1793
|
-
] }) : /* @__PURE__ */
|
|
1794
|
-
showAi ? /* @__PURE__ */
|
|
1795
|
-
/* @__PURE__ */
|
|
1796
|
-
/* @__PURE__ */
|
|
1797
|
-
] }) : !entry.commandMessage && /* @__PURE__ */
|
|
1927
|
+
] }) : /* @__PURE__ */ jsx6(ErrorBox, { message: entry.commandMessage.text })),
|
|
1928
|
+
showAi ? /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1929
|
+
/* @__PURE__ */ jsx6(Text6, { color: theme.accent, bold: true, children: "Explanation:" }),
|
|
1930
|
+
/* @__PURE__ */ jsx6(Box6, { flexDirection: "column", marginTop: 1, children: entry.aiError ? /* @__PURE__ */ jsx6(ErrorBox, { message: entry.aiError }) : /* @__PURE__ */ jsx6(Text6, { color: PLACEHOLDER2, children: entry.aiResponse }) })
|
|
1931
|
+
] }) : !entry.commandMessage && /* @__PURE__ */ jsx6(QueryResult, { state: entry.queryState, elapsed: entry.elapsed, page: entry.page, pageSize: PAGE_SIZE })
|
|
1798
1932
|
] }) })
|
|
1799
1933
|
] });
|
|
1800
1934
|
}
|
|
@@ -2015,7 +2149,8 @@ function App({ connectionState, aiUrl: aiUrl2, aiModel: aiModel2, aiKey: aiKey2,
|
|
|
2015
2149
|
setElapsed(null);
|
|
2016
2150
|
setPage(0);
|
|
2017
2151
|
setQueryState({ status: "idle" });
|
|
2018
|
-
if (result.
|
|
2152
|
+
if (result.helpData) setCommandMessage({ ok: result.ok, text: "", helpData: result.helpData });
|
|
2153
|
+
else if (result.message) setCommandMessage({ ok: result.ok, text: result.message });
|
|
2019
2154
|
else setCommandMessage(null);
|
|
2020
2155
|
return;
|
|
2021
2156
|
}
|
|
@@ -2027,33 +2162,33 @@ function App({ connectionState, aiUrl: aiUrl2, aiModel: aiModel2, aiKey: aiKey2,
|
|
|
2027
2162
|
const isShellEntry = lastQuery.startsWith("!");
|
|
2028
2163
|
const isCommand = !isShellEntry && (lastQuery.startsWith("/") || lastQuery.startsWith("\\"));
|
|
2029
2164
|
const activeLabel = isShellEntry ? "Shell:" : isCommand ? "Command:" : "Query:";
|
|
2030
|
-
return /* @__PURE__ */
|
|
2031
|
-
/* @__PURE__ */
|
|
2032
|
-
/* @__PURE__ */
|
|
2033
|
-
lastQuery === "" && /* @__PURE__ */
|
|
2034
|
-
lastQuery !== "" && /* @__PURE__ */
|
|
2035
|
-
/* @__PURE__ */
|
|
2036
|
-
/* @__PURE__ */
|
|
2165
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
2166
|
+
/* @__PURE__ */ jsx6(Static, { items: completedEntries, children: (entry) => /* @__PURE__ */ jsx6(EntryView, { entry }, entry.id) }),
|
|
2167
|
+
/* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 1, children: [
|
|
2168
|
+
lastQuery === "" && /* @__PURE__ */ jsx6(Banner, { connectionState }),
|
|
2169
|
+
lastQuery !== "" && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginBottom: 2, children: [
|
|
2170
|
+
/* @__PURE__ */ jsxs6(Box6, { borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
2171
|
+
/* @__PURE__ */ jsxs6(Text6, { color: theme.accent, bold: true, children: [
|
|
2037
2172
|
activeLabel,
|
|
2038
2173
|
" "
|
|
2039
2174
|
] }),
|
|
2040
|
-
/* @__PURE__ */
|
|
2175
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: lastQuery })
|
|
2041
2176
|
] }),
|
|
2042
|
-
/* @__PURE__ */
|
|
2043
|
-
commandMessage && (commandMessage.ok ? /* @__PURE__ */
|
|
2177
|
+
/* @__PURE__ */ jsx6(Box6, { marginTop: 1, flexDirection: "column", children: isShellEntry ? isShellRunning ? /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "running\u2026" }) : /* @__PURE__ */ jsx6(Text6, { children: limitLines(shellOutput ?? "", activePageSize()) }) : /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
2178
|
+
commandMessage && (commandMessage.helpData ? /* @__PURE__ */ jsx6(HelpView, { data: commandMessage.helpData }) : commandMessage.ok ? /* @__PURE__ */ jsxs6(Text6, { color: theme.accent, children: [
|
|
2044
2179
|
"\u2713 ",
|
|
2045
2180
|
commandMessage.text
|
|
2046
|
-
] }) : /* @__PURE__ */
|
|
2047
|
-
showAi ? /* @__PURE__ */
|
|
2048
|
-
/* @__PURE__ */
|
|
2049
|
-
/* @__PURE__ */
|
|
2181
|
+
] }) : /* @__PURE__ */ jsx6(ErrorBox, { message: commandMessage.text })),
|
|
2182
|
+
showAi ? /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
2183
|
+
/* @__PURE__ */ jsx6(Text6, { color: theme.accent, bold: true, children: "Explanation:" }),
|
|
2184
|
+
/* @__PURE__ */ jsx6(Box6, { flexDirection: "column", marginTop: 1, children: aiError ? /* @__PURE__ */ jsx6(ErrorBox, { message: aiError }) : /* @__PURE__ */ jsxs6(Text6, { color: PLACEHOLDER2, children: [
|
|
2050
2185
|
aiResponse,
|
|
2051
|
-
isStreaming && /* @__PURE__ */
|
|
2186
|
+
isStreaming && /* @__PURE__ */ jsx6(Text6, { color: PLACEHOLDER2, children: "\u258B" })
|
|
2052
2187
|
] }) })
|
|
2053
|
-
] }) : !commandMessage && /* @__PURE__ */
|
|
2188
|
+
] }) : !commandMessage && /* @__PURE__ */ jsx6(QueryResult, { state: queryState, elapsed, page, pageSize: activePageSize() })
|
|
2054
2189
|
] }) })
|
|
2055
2190
|
] }),
|
|
2056
|
-
isConnected ? /* @__PURE__ */
|
|
2191
|
+
isConnected ? /* @__PURE__ */ jsx6(
|
|
2057
2192
|
QueryInput,
|
|
2058
2193
|
{
|
|
2059
2194
|
onSubmit: handleSubmit,
|
|
@@ -2065,16 +2200,16 @@ function App({ connectionState, aiUrl: aiUrl2, aiModel: aiModel2, aiKey: aiKey2,
|
|
|
2065
2200
|
aliases,
|
|
2066
2201
|
schema: schema ?? void 0
|
|
2067
2202
|
}
|
|
2068
|
-
) : /* @__PURE__ */
|
|
2069
|
-
(vimEnabled || inputIsShell) && /* @__PURE__ */
|
|
2203
|
+
) : /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Not connected. Press Ctrl+C to exit." }),
|
|
2204
|
+
(vimEnabled || inputIsShell) && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { bold: true, color: inputIsShell ? theme.shellMode : vimMode === "NORMAL" ? theme.normalMode : theme.insertMode, children: isRawModeSupported ? inputIsShell ? "[SHELL]" : `[${vimMode}]` : "" }) })
|
|
2070
2205
|
] })
|
|
2071
2206
|
] });
|
|
2072
2207
|
}
|
|
2073
2208
|
|
|
2074
2209
|
// src/ui/components/ConnectionWizard.tsx
|
|
2075
2210
|
import { useState as useState4 } from "react";
|
|
2076
|
-
import { Box as
|
|
2077
|
-
import { jsx as
|
|
2211
|
+
import { Box as Box7, Text as Text7, useInput as useInput3, useStdin as useStdin3 } from "ink";
|
|
2212
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2078
2213
|
var DRIVERS = ["postgresql", "mysql", "sqlite"];
|
|
2079
2214
|
var LABEL_WIDTH = 10;
|
|
2080
2215
|
function fieldLabels(driver) {
|
|
@@ -2229,36 +2364,36 @@ function ConnectionWizard({ onConnect, initialError }) {
|
|
|
2229
2364
|
{ isActive: isRawModeSupported }
|
|
2230
2365
|
);
|
|
2231
2366
|
const isPassword = (idx) => fields.driver !== "sqlite" && idx === 5;
|
|
2232
|
-
return /* @__PURE__ */
|
|
2233
|
-
/* @__PURE__ */
|
|
2367
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingX: 2, paddingTop: 2, paddingBottom: 1, children: [
|
|
2368
|
+
/* @__PURE__ */ jsx7(Box7, { marginBottom: 1, children: /* @__PURE__ */ jsx7(Text7, { bold: true, color: theme.accent, children: "Connect to a database" }) }),
|
|
2234
2369
|
labels.map((label, idx) => {
|
|
2235
2370
|
const isFocused = focus === idx;
|
|
2236
2371
|
const isDriver = idx === 0;
|
|
2237
|
-
return /* @__PURE__ */
|
|
2238
|
-
/* @__PURE__ */
|
|
2239
|
-
isDriver ? /* @__PURE__ */
|
|
2240
|
-
i > 0 && /* @__PURE__ */
|
|
2241
|
-
/* @__PURE__ */
|
|
2372
|
+
return /* @__PURE__ */ jsxs7(Box7, { children: [
|
|
2373
|
+
/* @__PURE__ */ jsx7(Text7, { color: isFocused ? theme.accent : void 0, bold: isFocused, children: label.padEnd(LABEL_WIDTH) }),
|
|
2374
|
+
isDriver ? /* @__PURE__ */ jsx7(Box7, { children: DRIVERS.map((d, i) => /* @__PURE__ */ jsxs7(Box7, { children: [
|
|
2375
|
+
i > 0 && /* @__PURE__ */ jsx7(Text7, { children: " " }),
|
|
2376
|
+
/* @__PURE__ */ jsxs7(Text7, { color: fields.driver === d ? theme.accent : void 0, bold: fields.driver === d, children: [
|
|
2242
2377
|
fields.driver === d ? "\u25CF " : "\u25CB ",
|
|
2243
2378
|
d.charAt(0).toUpperCase() + d.slice(1)
|
|
2244
2379
|
] })
|
|
2245
|
-
] }, d)) }) : /* @__PURE__ */
|
|
2246
|
-
/* @__PURE__ */
|
|
2247
|
-
isFocused && /* @__PURE__ */
|
|
2248
|
-
isFocused && isPassword(idx) && keychainHint && /* @__PURE__ */
|
|
2380
|
+
] }, d)) }) : /* @__PURE__ */ jsxs7(Box7, { children: [
|
|
2381
|
+
/* @__PURE__ */ jsx7(Text7, { children: isPassword(idx) ? "\u2022".repeat(getTextValue(idx).length) : getTextValue(idx) }),
|
|
2382
|
+
isFocused && /* @__PURE__ */ jsx7(Text7, { color: theme.accent, bold: true, children: "\u258C" }),
|
|
2383
|
+
isFocused && isPassword(idx) && keychainHint && /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " (from keychain)" })
|
|
2249
2384
|
] })
|
|
2250
2385
|
] }, label);
|
|
2251
2386
|
}),
|
|
2252
|
-
/* @__PURE__ */
|
|
2387
|
+
/* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: connecting ? /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Connecting\u2026" }) : error ? /* @__PURE__ */ jsxs7(Text7, { color: theme.error, children: [
|
|
2253
2388
|
"\u2717 ",
|
|
2254
2389
|
error
|
|
2255
2390
|
] }) : null }),
|
|
2256
|
-
/* @__PURE__ */
|
|
2391
|
+
/* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "Tab \xB7 \u2191\u2193 navigate Enter connect \u2190\u2192 cycle driver" }) })
|
|
2257
2392
|
] });
|
|
2258
2393
|
}
|
|
2259
2394
|
|
|
2260
2395
|
// src/index.tsx
|
|
2261
|
-
import { jsx as
|
|
2396
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
2262
2397
|
var { values } = parseArgs({
|
|
2263
2398
|
args: process.argv.slice(2).filter((a) => a !== "--"),
|
|
2264
2399
|
options: {
|
|
@@ -2288,10 +2423,10 @@ function Root({ initialDsn: initialDsn2, aiUrl: aiUrl2, aiModel: aiModel2, aiKey
|
|
|
2288
2423
|
}
|
|
2289
2424
|
}, []);
|
|
2290
2425
|
if (initialDsn2 && !connectionState && !dsnError) {
|
|
2291
|
-
return /* @__PURE__ */
|
|
2426
|
+
return /* @__PURE__ */ jsx8(Box8, { paddingX: 2, paddingTop: 1, children: /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "Connecting\u2026" }) });
|
|
2292
2427
|
}
|
|
2293
2428
|
if (!connectionState) {
|
|
2294
|
-
return /* @__PURE__ */
|
|
2429
|
+
return /* @__PURE__ */ jsx8(ConnectionWizard, { onConnect: setConnectionState, initialError: dsnError ?? void 0 });
|
|
2295
2430
|
}
|
|
2296
2431
|
async function handleChangeDatabase(database) {
|
|
2297
2432
|
if (connectionState.status !== "connected") return;
|
|
@@ -2301,7 +2436,7 @@ function Root({ initialDsn: initialDsn2, aiUrl: aiUrl2, aiModel: aiModel2, aiKey
|
|
|
2301
2436
|
const next = await connectParams({ ...current.params, database });
|
|
2302
2437
|
setConnectionState(next);
|
|
2303
2438
|
}
|
|
2304
|
-
return /* @__PURE__ */
|
|
2439
|
+
return /* @__PURE__ */ jsx8(
|
|
2305
2440
|
App,
|
|
2306
2441
|
{
|
|
2307
2442
|
connectionState,
|
|
@@ -2315,6 +2450,6 @@ function Root({ initialDsn: initialDsn2, aiUrl: aiUrl2, aiModel: aiModel2, aiKey
|
|
|
2315
2450
|
);
|
|
2316
2451
|
}
|
|
2317
2452
|
render(
|
|
2318
|
-
/* @__PURE__ */
|
|
2453
|
+
/* @__PURE__ */ jsx8(Root, { initialDsn, aiUrl, aiModel, aiKey }),
|
|
2319
2454
|
{ exitOnCtrlC: true }
|
|
2320
2455
|
);
|