@noy-db/in-devtools-tui 0.2.0-pre.9 → 0.3.0-pre.2

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/bin.js CHANGED
@@ -7,22 +7,29 @@ import { createNoydb } from "@noy-db/hub";
7
7
  import { toMeter } from "@noy-db/to-meter";
8
8
 
9
9
  // src/App.tsx
10
- import React, { useState, useEffect } from "react";
10
+ import React2, { useState, useEffect } from "react";
11
11
  import { Box as Box6, Text as Text6, useApp, useInput } from "ink";
12
12
 
13
13
  // src/panes/VaultList.tsx
14
14
  import { Box, Text } from "ink";
15
15
  import { jsx, jsxs } from "react/jsx-runtime";
16
- function VaultList({ vaults, activeName }) {
16
+ function VaultList({
17
+ vaults,
18
+ activeName,
19
+ snapshot
20
+ }) {
17
21
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginRight: 2, children: [
18
22
  /* @__PURE__ */ jsx(Text, { bold: true, underline: true, children: "Vaults" }),
19
- vaults.map((v) => v.id === activeName ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
20
- "\u203A ",
21
- v.id
22
- ] }, v.id) : /* @__PURE__ */ jsxs(Text, { children: [
23
- " ",
24
- v.id
25
- ] }, v.id))
23
+ vaults.map((v) => {
24
+ const vaultLabel = v.id === activeName && snapshot?.meta?.label ? `${snapshot.meta.label} (${v.id})` : v.id;
25
+ return v.id === activeName ? /* @__PURE__ */ jsxs(Text, { color: "green", children: [
26
+ "\u203A ",
27
+ vaultLabel
28
+ ] }, v.id) : /* @__PURE__ */ jsxs(Text, { children: [
29
+ " ",
30
+ v.id
31
+ ] }, v.id);
32
+ })
26
33
  ] });
27
34
  }
28
35
 
@@ -32,34 +39,92 @@ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
32
39
  function CollectionList({ snapshot, selectedIdx }) {
33
40
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginRight: 2, children: [
34
41
  /* @__PURE__ */ jsx2(Text2, { bold: true, underline: true, children: "Collections" }),
35
- snapshot.collections.map((c, i) => i === selectedIdx ? /* @__PURE__ */ jsx2(Text2, { color: "cyan", inverse: true, children: c.name }, c.name) : /* @__PURE__ */ jsx2(Text2, { children: c.name }, c.name))
42
+ snapshot.collections.map((c, i) => {
43
+ const display = c.meta?.label ? `${c.meta.label} (${c.name})` : c.name;
44
+ return i === selectedIdx ? /* @__PURE__ */ jsx2(Text2, { color: "cyan", inverse: true, children: display }, c.name) : /* @__PURE__ */ jsx2(Text2, { children: display }, c.name);
45
+ })
36
46
  ] });
37
47
  }
38
48
 
39
49
  // src/panes/DetailPane.tsx
40
50
  import { Box as Box3, Text as Text3 } from "ink";
41
51
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
52
+ function sensitivityTag(s) {
53
+ if (s === "pii") return "[pii]";
54
+ if (s === "secret") return "[secret]";
55
+ return "";
56
+ }
57
+ function ConfigLine({ config }) {
58
+ const parts = [];
59
+ if (config.textIndexes?.length) parts.push(`idx:${config.textIndexes.length}`);
60
+ if (config.embeddings) parts.push(`emb:${config.embeddings.dim}d`);
61
+ if (config.i18nFields?.length) parts.push(`i18n:${config.i18nFields.length}`);
62
+ if (config.crdt) parts.push(`crdt:${config.crdt}`);
63
+ if (config.provenance) parts.push("provenance");
64
+ if (config.archive) parts.push("archive");
65
+ if (config.tiers?.length) parts.push(`tiers:${config.tiers.join(",")}`);
66
+ if (config.perRecordKeys) parts.push("per-record-cek");
67
+ if (!parts.length) return null;
68
+ return /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
69
+ "config: ",
70
+ parts.join(" ")
71
+ ] });
72
+ }
42
73
  function DetailPane({ collection }) {
43
74
  if (!collection) return /* @__PURE__ */ jsx3(Box3, { flexDirection: "column", children: /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "Select a collection (\u21B5)" }) });
44
- const fieldNames = Object.keys(collection.fields);
75
+ const heading = collection.meta?.label ? `${collection.meta.label} (${collection.name})` : collection.name;
45
76
  return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
46
- /* @__PURE__ */ jsx3(Text3, { bold: true, underline: true, children: collection.name }),
77
+ /* @__PURE__ */ jsx3(Text3, { bold: true, underline: true, children: heading }),
78
+ collection.meta?.description ? /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: collection.meta.description }) : null,
47
79
  /* @__PURE__ */ jsxs3(Text3, { children: [
48
80
  "records: ",
49
81
  collection.stats?.records ?? "\u2014",
50
82
  " bytes: ",
51
83
  collection.stats?.bytes ?? "\u2014"
52
84
  ] }),
53
- /* @__PURE__ */ jsxs3(Text3, { children: [
54
- "fields: ",
55
- fieldNames.length ? fieldNames.join(", ") : "(none)"
56
- ] })
85
+ collection.described && collection.described.length > 0 ? /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, children: [
86
+ /* @__PURE__ */ jsx3(Text3, { bold: true, children: "schema" }),
87
+ collection.described.map((f) => {
88
+ const sens = sensitivityTag(f.sensitivity);
89
+ const i18nMark = f.i18n ? "[i18n]" : "";
90
+ const roMark = f.editable === false ? "[ro]" : "";
91
+ const widgetMark = f.widget ? `<${f.widget}>` : "";
92
+ const markers = [sens, i18nMark, roMark, widgetMark].filter(Boolean).join(" ");
93
+ return /* @__PURE__ */ jsxs3(Text3, { children: [
94
+ " ",
95
+ f.label,
96
+ " ",
97
+ /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
98
+ "(",
99
+ f.key,
100
+ ": ",
101
+ f.type,
102
+ ")"
103
+ ] }),
104
+ markers ? /* @__PURE__ */ jsxs3(Text3, { color: "yellow", children: [
105
+ " ",
106
+ markers
107
+ ] }) : null
108
+ ] }, f.key);
109
+ })
110
+ ] }) : /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, children: [
111
+ /* @__PURE__ */ jsx3(Text3, { bold: true, children: "schema" }),
112
+ Object.keys(collection.fields).length ? Object.entries(collection.fields).map(([k, f]) => /* @__PURE__ */ jsxs3(Text3, { children: [
113
+ " ",
114
+ k,
115
+ ": ",
116
+ /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: f.type })
117
+ ] }, k)) : /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: " (no declared fields)" })
118
+ ] }),
119
+ collection.config ? /* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx3(ConfigLine, { config: collection.config }) }) : null
57
120
  ] });
58
121
  }
59
122
 
60
123
  // src/panes/RecordsPane.tsx
124
+ import React from "react";
61
125
  import { Box as Box4, Text as Text4 } from "ink";
62
126
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
127
+ var MASK = "\u2022\u2022\u2022\u2022";
63
128
  function cell(value) {
64
129
  if (value === null || value === void 0) return "\xB7";
65
130
  if (typeof value === "object") return Array.isArray(value) ? `[${value.length}]` : "{\u2026}";
@@ -67,7 +132,15 @@ function cell(value) {
67
132
  if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
68
133
  return "?";
69
134
  }
70
- function RecordsPane({ collection, page, error }) {
135
+ function RecordsPane({ collection, page, error, revealAll }) {
136
+ const sensitiveKeys = React.useMemo(() => {
137
+ if (!collection.described) return /* @__PURE__ */ new Set();
138
+ const keys = /* @__PURE__ */ new Set();
139
+ for (const f of collection.described) {
140
+ if (f.sensitivity !== void 0 && f.sensitivity !== "public") keys.add(f.key);
141
+ }
142
+ return keys;
143
+ }, [collection.described]);
71
144
  const schemaFields = Object.keys(collection.fields);
72
145
  if (error) return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
73
146
  /* @__PURE__ */ jsxs4(Text4, { color: "red", children: [
@@ -81,6 +154,12 @@ function RecordsPane({ collection, page, error }) {
81
154
  const fields = schemaFields.length > 0 ? schemaFields : firstRowKeys;
82
155
  const from = page.total === 0 ? 0 : page.offset + 1;
83
156
  const to = Math.min(page.offset + page.limit, page.total);
157
+ function renderCell(f, row) {
158
+ const raw = cell(row?.[f]);
159
+ if (!revealAll && sensitiveKeys.has(f)) return MASK;
160
+ return raw;
161
+ }
162
+ const revealHint = sensitiveKeys.size > 0 ? " \xB7 r reveal/hide" : "";
84
163
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
85
164
  /* @__PURE__ */ jsxs4(Text4, { bold: true, children: [
86
165
  "rows ",
@@ -90,10 +169,14 @@ function RecordsPane({ collection, page, error }) {
90
169
  " of ",
91
170
  page.total,
92
171
  " ",
93
- /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "(n/p page \xB7 \u21E5 back)" })
172
+ /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
173
+ "(n/p page \xB7 \u21E5 back",
174
+ revealHint,
175
+ ")"
176
+ ] })
94
177
  ] }),
95
178
  /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: fields.join(" ") }),
96
- page.rows.map((row, i) => /* @__PURE__ */ jsx4(Text4, { children: fields.map((f) => cell(row?.[f])).join(" ") }, i))
179
+ page.rows.map((row, i) => /* @__PURE__ */ jsx4(Text4, { children: fields.map((f) => renderCell(f, row)).join(" ") }, i))
97
180
  ] });
98
181
  }
99
182
 
@@ -175,10 +258,14 @@ function App({ inspector, vault, vaultName, initial }) {
175
258
  const [offset, setOffset] = useState(0);
176
259
  const [page, setPage] = useState(null);
177
260
  const [recErr, setRecErr] = useState(void 0);
261
+ const [revealAll, setRevealAll] = useState(false);
178
262
  const current = collections[selectedIdx];
263
+ useEffect(() => {
264
+ setRevealAll(false);
265
+ }, [selectedIdx]);
179
266
  const [view, setView] = useState("structure");
180
267
  const [feed, setFeed] = useState([]);
181
- const conflictKeys = React.useRef(/* @__PURE__ */ new Set());
268
+ const conflictKeys = React2.useRef(/* @__PURE__ */ new Set());
182
269
  const [started, setStarted] = useState(false);
183
270
  const [meter, setMeter] = useState(null);
184
271
  useEffect(() => {
@@ -260,6 +347,7 @@ function App({ inspector, vault, vaultName, initial }) {
260
347
  if (tab === "records") {
261
348
  if (input === "n" && (!page || offset + PAGE < page.total)) setOffset((o) => o + PAGE);
262
349
  if (input === "p" && offset - PAGE >= 0) setOffset((o) => o - PAGE);
350
+ if (input === "r") setRevealAll((v) => !v);
263
351
  }
264
352
  });
265
353
  if (view === "monitor") return /* @__PURE__ */ jsx6(WriteMonitor, { vaultName, rows: feed, meter });
@@ -271,9 +359,9 @@ function App({ inspector, vault, vaultName, initial }) {
271
359
  /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "(\u2191/\u2193 \xB7 \u21B5 drill \xB7 \u21E5 tab \xB7 q quit)" })
272
360
  ] }),
273
361
  /* @__PURE__ */ jsxs6(Box6, { marginTop: 1, children: [
274
- /* @__PURE__ */ jsx6(VaultList, { vaults, activeName: vaultName }),
362
+ /* @__PURE__ */ jsx6(VaultList, { vaults, activeName: vaultName, ...snapshot !== void 0 ? { snapshot } : {} }),
275
363
  /* @__PURE__ */ jsx6(CollectionList, { snapshot: snapshot ?? { vault: vaultName, collections: [] }, selectedIdx }),
276
- drilled && tab === "records" && current ? /* @__PURE__ */ jsx6(RecordsPane, { collection: current, page, ...recErr !== void 0 ? { error: recErr } : {} }) : /* @__PURE__ */ jsx6(DetailPane, { collection: drilled ? current : void 0 })
364
+ drilled && tab === "records" && current ? /* @__PURE__ */ jsx6(RecordsPane, { collection: current, page, revealAll, ...recErr !== void 0 ? { error: recErr } : {} }) : /* @__PURE__ */ jsx6(DetailPane, { collection: drilled ? current : void 0 })
277
365
  ] })
278
366
  ] });
279
367
  }
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin.tsx","../src/App.tsx","../src/panes/VaultList.tsx","../src/panes/CollectionList.tsx","../src/panes/DetailPane.tsx","../src/panes/RecordsPane.tsx","../src/panes/WriteMonitor.tsx","../src/load-options.ts","../src/prompt-passphrase.ts"],"sourcesContent":["import React from 'react'\nimport { render } from 'ink'\nimport { createInspector } from '@noy-db/in-devtools'\nimport { createNoydb } from '@noy-db/hub'\nimport type { NoydbOptions } from '@noy-db/hub'\nimport { toMeter } from '@noy-db/to-meter'\nimport { App } from './App.js'\nimport { loadOptionsFromFile, resolvePassphrase } from './load-options.js'\nimport { promptMasked } from './prompt-passphrase.js'\n\nfunction fail(msg: string): never {\n process.stderr.write(`noydb-inspect: ${msg}\\n`)\n process.exit(2)\n}\n\nasync function main(): Promise<void> {\n const argv = process.argv.slice(2)\n const configPath = argv.find((a) => !a.startsWith('--'))\n if (!configPath) fail('usage: noydb-inspect <config.js|mjs> --vault=<name> [--passphrase=…]')\n const vaultFlag = argv.find((a) => a.startsWith('--vault='))\n if (!vaultFlag) fail('missing --vault=<name>')\n const vaultName = vaultFlag.slice('--vault='.length)\n\n let passphrase = resolvePassphrase(argv, process.env)\n if (passphrase === undefined) {\n if (!process.stdin.isTTY) fail('no passphrase — pass --passphrase=… or set NOYDB_PASSPHRASE')\n passphrase = await promptMasked('Passphrase: ')\n }\n\n let baseOptions: NoydbOptions\n try {\n baseOptions = (await loadOptionsFromFile(configPath)) as NoydbOptions\n } catch (err) {\n fail(`failed to load config \"${configPath}\": ${err instanceof Error ? err.message : String(err)}`)\n }\n\n let meter\n if (argv.includes('--meter') && baseOptions.store) {\n const metered = toMeter(baseOptions.store)\n baseOptions = { ...baseOptions, store: metered.store }\n meter = metered.meter\n }\n\n // Passphrase lives in NoydbOptions.secret — openVault(name) picks it up internally.\n const options: NoydbOptions = { ...baseOptions, secret: passphrase }\n const db = await createNoydb(options)\n\n let vault\n try {\n vault = await db.openVault(vaultName)\n } catch (err) {\n fail(`failed to open vault \"${vaultName}\": ${err instanceof Error ? err.message : String(err)}`)\n }\n\n const inspector = createInspector(db, meter ? { meter } : undefined)\n const initial = { vaults: await inspector.listVaults(), snapshot: await inspector.snapshot(vault) }\n const { waitUntilExit } = render(\n <App inspector={inspector} vault={vault} vaultName={vaultName} initial={initial} />,\n )\n await waitUntilExit()\n}\n\nmain().catch((err) => fail(err instanceof Error ? err.message : String(err)))\n","import React, { useState, useEffect } from 'react'\nimport { Box, Text, useApp, useInput } from 'ink'\nimport type { AppProps, DetailTab, View, FeedRow } from './types.js'\nimport type { RecordPage } from '@noy-db/in-devtools'\nimport type { InspectorWriteEvent } from '@noy-db/in-devtools'\nimport type { MeterSnapshot } from '@noy-db/to-meter'\nimport { VaultList } from './panes/VaultList.js'\nimport { CollectionList } from './panes/CollectionList.js'\nimport { DetailPane } from './panes/DetailPane.js'\nimport { RecordsPane } from './panes/RecordsPane.js'\nimport { WriteMonitor } from './panes/WriteMonitor.js'\n\nconst PAGE = 20\nconst BUFFER = 200\n\nfunction fmtTime(ts: number): string { return new Date(ts).toTimeString().slice(0, 8) }\n\nfunction rowOf(e: InspectorWriteEvent): FeedRow {\n const op = e.op === 'delete' ? 'del' : 'put'\n const versions = e.op === 'delete' ? `${e.baseVersion}→·` : `${e.baseVersion}→${e.version}`\n return { time: fmtTime(e.timestamp), user: e.userId, op, target: `${e.collection}/${e.docId}`, versions, baseKey: `${e.collection}/${e.docId}@${e.baseVersion}`, conflict: false }\n}\n\nexport function App({ inspector, vault, vaultName, initial }: AppProps) {\n const { exit } = useApp()\n const vaults = initial?.vaults ?? []\n const snapshot = initial?.snapshot\n const collections = snapshot?.collections ?? []\n const [selectedIdx, setSelectedIdx] = useState(0)\n const [drilled, setDrilled] = useState(false)\n const [tab, setTab] = useState<DetailTab>('schema')\n const [offset, setOffset] = useState(0)\n const [page, setPage] = useState<RecordPage | null>(null)\n const [recErr, setRecErr] = useState<string | undefined>(undefined)\n const current = collections[selectedIdx]\n\n const [view, setView] = useState<View>('structure')\n const [feed, setFeed] = useState<ReadonlyArray<FeedRow>>([])\n const conflictKeys = React.useRef<Set<string>>(new Set())\n const [started, setStarted] = useState(false)\n const [meter, setMeter] = useState<MeterSnapshot | null>(null)\n useEffect(() => {\n if (view !== 'monitor') return\n const tick = () => setMeter(inspector.meterSnapshot())\n tick()\n const id = setInterval(tick, 1000)\n return () => clearInterval(id)\n }, [view, inspector])\n\n useEffect(() => {\n if (!drilled || tab !== 'records' || !current) return\n let live = true\n setPage(null); setRecErr(undefined)\n inspector.records(vault, current.name, { limit: PAGE, offset })\n .then((p) => { if (live) setPage(p) })\n .catch((e) => { if (live) setRecErr(e instanceof Error ? e.message : String(e)) })\n return () => { live = false }\n }, [drilled, tab, current, offset, inspector, vault])\n\n useEffect(() => {\n if (!started) return\n const offW = inspector.subscribe((e) => {\n setFeed((prev) => {\n const row = rowOf(e)\n if (conflictKeys.current.has(row.baseKey)) row.conflict = true\n const overlap = prev.some((r) => r.baseKey === row.baseKey && r.user !== row.user)\n if (overlap) row.conflict = true\n const next = [row, ...prev.map((r) => (r.baseKey === row.baseKey && r.user !== row.user ? { ...r, conflict: true } : r))]\n return next.slice(0, BUFFER)\n })\n })\n const offC = inspector.subscribeConflicts((c) => {\n const key = `${c.collection}/${c.docId}@${c.baseVersion}`\n conflictKeys.current.add(key)\n setFeed((prev) => prev.map((r) => (r.baseKey === key ? { ...r, conflict: true } : r)))\n })\n return () => { offW(); offC() }\n }, [started, inspector])\n\n useInput((input, key) => {\n if (input === 'q' || (key.ctrl && input === 'c')) { exit(); return }\n if (view === 'monitor') {\n if (key.escape) setView('structure')\n if (input === 'c') setFeed([])\n return\n }\n if (input === 'w') { setView('monitor'); setStarted(true); return }\n if (!drilled) {\n if (key.downArrow) setSelectedIdx((i) => Math.min(collections.length - 1, i + 1))\n if (key.upArrow) setSelectedIdx((i) => Math.max(0, i - 1))\n if (key.return) { setDrilled(true); setTab('schema') }\n return\n }\n if (key.escape) { setDrilled(false); setTab('schema'); setOffset(0) }\n if (key.tab) { setTab((t) => (t === 'schema' ? 'records' : 'schema')); setOffset(0) }\n if (tab === 'records') {\n if (input === 'n' && (!page || offset + PAGE < page.total)) setOffset((o) => o + PAGE)\n if (input === 'p' && offset - PAGE >= 0) setOffset((o) => o - PAGE)\n }\n })\n\n if (view === 'monitor') return <WriteMonitor vaultName={vaultName} rows={feed} meter={meter} />\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>noy-db inspector — {vaultName} <Text dimColor>(↑/↓ · ↵ drill · ⇥ tab · q quit)</Text></Text>\n <Box marginTop={1}>\n <VaultList vaults={vaults} activeName={vaultName} />\n <CollectionList snapshot={snapshot ?? { vault: vaultName, collections: [] }} selectedIdx={selectedIdx} />\n {drilled && tab === 'records' && current\n ? <RecordsPane collection={current} page={page} {...(recErr !== undefined ? { error: recErr } : {})} />\n : <DetailPane collection={drilled ? current : undefined} />}\n </Box>\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { VaultInfo } from '@noy-db/in-devtools'\n\nexport function VaultList({ vaults, activeName }: { vaults: ReadonlyArray<VaultInfo>; activeName: string }) {\n return (\n <Box flexDirection=\"column\" marginRight={2}>\n <Text bold underline>Vaults</Text>\n {vaults.map((v) => (\n v.id === activeName\n ? <Text key={v.id} color=\"green\">{'› '}{v.id}</Text>\n : <Text key={v.id}>{' '}{v.id}</Text>\n ))}\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { InspectorSnapshot } from '@noy-db/in-devtools'\n\nexport function CollectionList({ snapshot, selectedIdx }: { snapshot: InspectorSnapshot; selectedIdx: number }) {\n return (\n <Box flexDirection=\"column\" marginRight={2}>\n <Text bold underline>Collections</Text>\n {snapshot.collections.map((c, i) => (\n i === selectedIdx\n ? <Text key={c.name} color=\"cyan\" inverse>{c.name}</Text>\n : <Text key={c.name}>{c.name}</Text>\n ))}\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { InspectorCollection } from '@noy-db/in-devtools'\n\nexport function DetailPane({ collection }: { collection: InspectorCollection | undefined }) {\n if (!collection) return (\n <Box flexDirection=\"column\"><Text dimColor>Select a collection (↵)</Text></Box>\n )\n const fieldNames = Object.keys(collection.fields)\n return (\n <Box flexDirection=\"column\">\n <Text bold underline>{collection.name}</Text>\n <Text>records: {collection.stats?.records ?? '—'} bytes: {collection.stats?.bytes ?? '—'}</Text>\n <Text>fields: {fieldNames.length ? fieldNames.join(', ') : '(none)'}</Text>\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { RecordPage, InspectorCollection } from '@noy-db/in-devtools'\n\nfunction cell(value: unknown): string {\n if (value === null || value === undefined) return '·'\n if (typeof value === 'object') return Array.isArray(value) ? `[${(value as unknown[]).length}]` : '{…}'\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value)\n return '?'\n}\n\nexport function RecordsPane({ collection, page, error }: {\n collection: InspectorCollection\n page: RecordPage | null\n error?: string\n}) {\n const schemaFields = Object.keys(collection.fields)\n if (error) return <Box flexDirection=\"column\"><Text color=\"red\">records error: {error}</Text><Text dimColor>n/p retry · ⇥ back</Text></Box>\n if (!page) return <Box flexDirection=\"column\"><Text dimColor>loading records…</Text></Box>\n // Fall back to first-row keys when schema has no declared fields\n const firstRowKeys = page.rows.length > 0 && typeof page.rows[0] === 'object' && page.rows[0] !== null\n ? Object.keys(page.rows[0] as Record<string, unknown>)\n : []\n const fields = schemaFields.length > 0 ? schemaFields : firstRowKeys\n const from = page.total === 0 ? 0 : page.offset + 1\n const to = Math.min(page.offset + page.limit, page.total)\n return (\n <Box flexDirection=\"column\">\n <Text bold>rows {from}–{to} of {page.total} <Text dimColor>(n/p page · ⇥ back)</Text></Text>\n <Text dimColor>{fields.join(' ')}</Text>\n {page.rows.map((row, i) => (\n <Text key={i}>{fields.map((f) => cell((row as Record<string, unknown>)?.[f])).join(' ')}</Text>\n ))}\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { FeedRow } from '../types.js'\nimport type { MeterSnapshot } from '@noy-db/to-meter'\n\nexport function WriteMonitor({ vaultName, rows, meter }: { vaultName: string; rows: ReadonlyArray<FeedRow>; meter: MeterSnapshot | null }) {\n const m = meter?.byMethod\n return (\n <Box flexDirection=\"column\">\n <Text bold>Write Monitor — {vaultName} <Text dimColor>(w/esc · c clear · q quit)</Text></Text>\n {meter && m && (\n <Text>\n store put p50 {m.put?.p50 ?? '—'}ms p99 {m.put?.p99 ?? '—'}ms{meter.status === 'degraded' ? ' ⚠degraded' : ''} · del p50 {m.delete?.p50 ?? '—'} p99 {m.delete?.p99 ?? '—'} · get p50 {m.get?.p50 ?? '—'} p99 {m.get?.p99 ?? '—'}\n </Text>\n )}\n <Text dimColor>time user op collection/docId v</Text>\n {rows.length === 0 && <Text dimColor>(waiting for writes…)</Text>}\n {rows.map((r, i) => (\n r.conflict\n ? <Text key={i} color=\"yellow\">{r.time} {r.user.padEnd(6)} {r.op} {r.target.padEnd(18)} {r.versions} ⚠ CONFLICT</Text>\n : <Text key={i}>{r.time} {r.user.padEnd(6)} {r.op} {r.target.padEnd(18)} {r.versions}</Text>\n ))}\n </Box>\n )\n}\n","import { resolve as resolvePath } from 'node:path'\nimport { pathToFileURL } from 'node:url'\n\n/**\n * Load a NoydbOptions object from a `.js`/`.mjs` config (default export, or a\n * factory function). Mirrors @noy-db/cli's loader; reimplemented here to avoid\n * coupling the TUI bin to the whole cli package. `.ts` is unsupported (Node has\n * no native loader) — compile first or use a `.mjs` config.\n */\nexport async function loadOptionsFromFile(filePath: string): Promise<unknown> {\n const abs = resolvePath(filePath)\n if (/\\.[mc]?ts$/.test(abs)) {\n throw new Error(\n `TypeScript config files are not directly loadable. Compile it first, or use a .mjs/.js config.`,\n )\n }\n const mod = (await import(pathToFileURL(abs).href)) as { default?: unknown }\n const value = mod.default ?? mod\n return typeof value === 'function' ? await (value as () => Promise<unknown>)() : value\n}\n\n/** Resolve the passphrase from `--passphrase=…` or `NOYDB_PASSPHRASE`; undefined → caller prompts. */\nexport function resolvePassphrase(argv: readonly string[], env: NodeJS.ProcessEnv): string | undefined {\n const flag = argv.find((a) => a.startsWith('--passphrase='))\n if (flag) return flag.slice('--passphrase='.length)\n if (env.NOYDB_PASSPHRASE) return env.NOYDB_PASSPHRASE\n return undefined\n}\n","import type { Readable, Writable } from 'node:stream'\n\nexport interface PromptStreams {\n input?: Readable & { setRawMode?: (mode: boolean) => void }\n output?: Writable\n}\n\n/**\n * Read a line from `input` without echoing the plaintext; emit one `•` per\n * character to `output`. Returns the typed string (Enter terminates).\n * Never logs/persists the value.\n */\nexport function promptMasked(question: string, streams: PromptStreams = {}): Promise<string> {\n const input = (streams.input ?? process.stdin) as Readable & { setRawMode?: (m: boolean) => void }\n const output = streams.output ?? process.stdout\n return new Promise<string>((resolve, reject) => {\n output.write(question)\n input.setRawMode?.(true)\n let buf = ''\n const onData = (chunk: Buffer | string) => {\n const s = chunk.toString()\n for (const ch of s) {\n if (ch === '\\r' || ch === '\\n') {\n output.write('\\n')\n input.setRawMode?.(false)\n input.removeListener('data', onData)\n resolve(buf)\n return\n }\n if (ch === '\\x03') { // Ctrl-C — abort\n output.write('\\n')\n input.setRawMode?.(false)\n input.removeListener('data', onData)\n reject(new Error('aborted'))\n return\n }\n if (ch === '\\x7f' || ch === '\\x08') { // DEL / Backspace\n if (buf.length > 0) { buf = buf.slice(0, -1); output.write('\\b \\b') }\n continue\n }\n buf += ch\n output.write('•')\n }\n }\n input.on('data', onData)\n })\n}\n"],"mappings":"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","names":["Box","Text","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","jsx","jsxs","Box","Text","jsx"]}
1
+ {"version":3,"sources":["../src/bin.tsx","../src/App.tsx","../src/panes/VaultList.tsx","../src/panes/CollectionList.tsx","../src/panes/DetailPane.tsx","../src/panes/RecordsPane.tsx","../src/panes/WriteMonitor.tsx","../src/load-options.ts","../src/prompt-passphrase.ts"],"sourcesContent":["import React from 'react'\nimport { render } from 'ink'\nimport { createInspector } from '@noy-db/in-devtools'\nimport { createNoydb } from '@noy-db/hub'\nimport type { NoydbOptions } from '@noy-db/hub'\nimport { toMeter } from '@noy-db/to-meter'\nimport { App } from './App.js'\nimport { loadOptionsFromFile, resolvePassphrase } from './load-options.js'\nimport { promptMasked } from './prompt-passphrase.js'\n\nfunction fail(msg: string): never {\n process.stderr.write(`noydb-inspect: ${msg}\\n`)\n process.exit(2)\n}\n\nasync function main(): Promise<void> {\n const argv = process.argv.slice(2)\n const configPath = argv.find((a) => !a.startsWith('--'))\n if (!configPath) fail('usage: noydb-inspect <config.js|mjs> --vault=<name> [--passphrase=…]')\n const vaultFlag = argv.find((a) => a.startsWith('--vault='))\n if (!vaultFlag) fail('missing --vault=<name>')\n const vaultName = vaultFlag.slice('--vault='.length)\n\n let passphrase = resolvePassphrase(argv, process.env)\n if (passphrase === undefined) {\n if (!process.stdin.isTTY) fail('no passphrase — pass --passphrase=… or set NOYDB_PASSPHRASE')\n passphrase = await promptMasked('Passphrase: ')\n }\n\n let baseOptions: NoydbOptions\n try {\n baseOptions = (await loadOptionsFromFile(configPath)) as NoydbOptions\n } catch (err) {\n fail(`failed to load config \"${configPath}\": ${err instanceof Error ? err.message : String(err)}`)\n }\n\n let meter\n if (argv.includes('--meter') && baseOptions.store) {\n const metered = toMeter(baseOptions.store)\n baseOptions = { ...baseOptions, store: metered.store }\n meter = metered.meter\n }\n\n // Passphrase lives in NoydbOptions.secret — openVault(name) picks it up internally.\n const options: NoydbOptions = { ...baseOptions, secret: passphrase }\n const db = await createNoydb(options)\n\n let vault\n try {\n vault = await db.openVault(vaultName)\n } catch (err) {\n fail(`failed to open vault \"${vaultName}\": ${err instanceof Error ? err.message : String(err)}`)\n }\n\n const inspector = createInspector(db, meter ? { meter } : undefined)\n const initial = { vaults: await inspector.listVaults(), snapshot: await inspector.snapshot(vault) }\n const { waitUntilExit } = render(\n <App inspector={inspector} vault={vault} vaultName={vaultName} initial={initial} />,\n )\n await waitUntilExit()\n}\n\nmain().catch((err) => fail(err instanceof Error ? err.message : String(err)))\n","import React, { useState, useEffect } from 'react'\nimport { Box, Text, useApp, useInput } from 'ink'\nimport type { AppProps, DetailTab, View, FeedRow } from './types.js'\nimport type { RecordPage } from '@noy-db/in-devtools'\nimport type { InspectorWriteEvent } from '@noy-db/in-devtools'\nimport type { MeterSnapshot } from '@noy-db/to-meter'\nimport { VaultList } from './panes/VaultList.js'\nimport { CollectionList } from './panes/CollectionList.js'\nimport { DetailPane } from './panes/DetailPane.js'\nimport { RecordsPane } from './panes/RecordsPane.js'\nimport { WriteMonitor } from './panes/WriteMonitor.js'\n\nconst PAGE = 20\nconst BUFFER = 200\n\nfunction fmtTime(ts: number): string { return new Date(ts).toTimeString().slice(0, 8) }\n\nfunction rowOf(e: InspectorWriteEvent): FeedRow {\n const op = e.op === 'delete' ? 'del' : 'put'\n const versions = e.op === 'delete' ? `${e.baseVersion}→·` : `${e.baseVersion}→${e.version}`\n return { time: fmtTime(e.timestamp), user: e.userId, op, target: `${e.collection}/${e.docId}`, versions, baseKey: `${e.collection}/${e.docId}@${e.baseVersion}`, conflict: false }\n}\n\nexport function App({ inspector, vault, vaultName, initial }: AppProps) {\n const { exit } = useApp()\n const vaults = initial?.vaults ?? []\n const snapshot = initial?.snapshot\n const collections = snapshot?.collections ?? []\n const [selectedIdx, setSelectedIdx] = useState(0)\n const [drilled, setDrilled] = useState(false)\n const [tab, setTab] = useState<DetailTab>('schema')\n const [offset, setOffset] = useState(0)\n const [page, setPage] = useState<RecordPage | null>(null)\n const [recErr, setRecErr] = useState<string | undefined>(undefined)\n const [revealAll, setRevealAll] = useState(false)\n const current = collections[selectedIdx]\n\n // Reset reveal-all when the viewed collection changes so PII doesn't linger.\n useEffect(() => {\n setRevealAll(false)\n }, [selectedIdx])\n\n const [view, setView] = useState<View>('structure')\n const [feed, setFeed] = useState<ReadonlyArray<FeedRow>>([])\n const conflictKeys = React.useRef<Set<string>>(new Set())\n const [started, setStarted] = useState(false)\n const [meter, setMeter] = useState<MeterSnapshot | null>(null)\n useEffect(() => {\n if (view !== 'monitor') return\n const tick = () => setMeter(inspector.meterSnapshot())\n tick()\n const id = setInterval(tick, 1000)\n return () => clearInterval(id)\n }, [view, inspector])\n\n useEffect(() => {\n if (!drilled || tab !== 'records' || !current) return\n let live = true\n setPage(null); setRecErr(undefined)\n inspector.records(vault, current.name, { limit: PAGE, offset })\n .then((p) => { if (live) setPage(p) })\n .catch((e) => { if (live) setRecErr(e instanceof Error ? e.message : String(e)) })\n return () => { live = false }\n }, [drilled, tab, current, offset, inspector, vault])\n\n useEffect(() => {\n if (!started) return\n const offW = inspector.subscribe((e) => {\n setFeed((prev) => {\n const row = rowOf(e)\n if (conflictKeys.current.has(row.baseKey)) row.conflict = true\n const overlap = prev.some((r) => r.baseKey === row.baseKey && r.user !== row.user)\n if (overlap) row.conflict = true\n const next = [row, ...prev.map((r) => (r.baseKey === row.baseKey && r.user !== row.user ? { ...r, conflict: true } : r))]\n return next.slice(0, BUFFER)\n })\n })\n const offC = inspector.subscribeConflicts((c) => {\n const key = `${c.collection}/${c.docId}@${c.baseVersion}`\n conflictKeys.current.add(key)\n setFeed((prev) => prev.map((r) => (r.baseKey === key ? { ...r, conflict: true } : r)))\n })\n return () => { offW(); offC() }\n }, [started, inspector])\n\n useInput((input, key) => {\n if (input === 'q' || (key.ctrl && input === 'c')) { exit(); return }\n if (view === 'monitor') {\n if (key.escape) setView('structure')\n if (input === 'c') setFeed([])\n return\n }\n if (input === 'w') { setView('monitor'); setStarted(true); return }\n if (!drilled) {\n if (key.downArrow) setSelectedIdx((i) => Math.min(collections.length - 1, i + 1))\n if (key.upArrow) setSelectedIdx((i) => Math.max(0, i - 1))\n if (key.return) { setDrilled(true); setTab('schema') }\n return\n }\n if (key.escape) { setDrilled(false); setTab('schema'); setOffset(0) }\n if (key.tab) { setTab((t) => (t === 'schema' ? 'records' : 'schema')); setOffset(0) }\n if (tab === 'records') {\n if (input === 'n' && (!page || offset + PAGE < page.total)) setOffset((o) => o + PAGE)\n if (input === 'p' && offset - PAGE >= 0) setOffset((o) => o - PAGE)\n if (input === 'r') setRevealAll((v) => !v)\n }\n })\n\n if (view === 'monitor') return <WriteMonitor vaultName={vaultName} rows={feed} meter={meter} />\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>noy-db inspector — {vaultName} <Text dimColor>(↑/↓ · ↵ drill · ⇥ tab · q quit)</Text></Text>\n <Box marginTop={1}>\n <VaultList vaults={vaults} activeName={vaultName} {...(snapshot !== undefined ? { snapshot } : {})} />\n <CollectionList snapshot={snapshot ?? { vault: vaultName, collections: [] }} selectedIdx={selectedIdx} />\n {drilled && tab === 'records' && current\n ? <RecordsPane collection={current} page={page} revealAll={revealAll} {...(recErr !== undefined ? { error: recErr } : {})} />\n : <DetailPane collection={drilled ? current : undefined} />}\n </Box>\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { VaultInfo, InspectorSnapshot } from '@noy-db/in-devtools'\n\nexport function VaultList({\n vaults,\n activeName,\n snapshot,\n}: {\n vaults: ReadonlyArray<VaultInfo>\n activeName: string\n /** Active vault snapshot; used to read vault meta.label when available. */\n snapshot?: InspectorSnapshot\n}) {\n return (\n <Box flexDirection=\"column\" marginRight={2}>\n <Text bold underline>Vaults</Text>\n {vaults.map((v) => {\n // Show meta.label for the active vault when available\n const vaultLabel = v.id === activeName && snapshot?.meta?.label\n ? `${snapshot.meta.label} (${v.id})`\n : v.id\n return v.id === activeName\n ? <Text key={v.id} color=\"green\">{'› '}{vaultLabel}</Text>\n : <Text key={v.id}>{' '}{v.id}</Text>\n })}\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { InspectorSnapshot } from '@noy-db/in-devtools'\n\nexport function CollectionList({ snapshot, selectedIdx }: { snapshot: InspectorSnapshot; selectedIdx: number }) {\n return (\n <Box flexDirection=\"column\" marginRight={2}>\n <Text bold underline>Collections</Text>\n {snapshot.collections.map((c, i) => {\n // Show meta.label when present; append the collection key in dimmed parens\n const display = c.meta?.label ? `${c.meta.label} (${c.name})` : c.name\n return i === selectedIdx\n ? <Text key={c.name} color=\"cyan\" inverse>{display}</Text>\n : <Text key={c.name}>{display}</Text>\n })}\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { InspectorCollection } from '@noy-db/in-devtools'\nimport type { CollectionConfig } from '@noy-db/hub'\n\n/** Compact sensitivity marker for terminal rendering. */\nfunction sensitivityTag(s: 'public' | 'pii' | 'secret' | undefined): string {\n if (s === 'pii') return '[pii]'\n if (s === 'secret') return '[secret]'\n return ''\n}\n\n/** Render a compact config line from CollectionConfig fields that are set. */\nfunction ConfigLine({ config }: { config: CollectionConfig }) {\n const parts: string[] = []\n if (config.textIndexes?.length) parts.push(`idx:${config.textIndexes.length}`)\n if (config.embeddings) parts.push(`emb:${config.embeddings.dim}d`)\n if (config.i18nFields?.length) parts.push(`i18n:${config.i18nFields.length}`)\n if (config.crdt) parts.push(`crdt:${config.crdt}`)\n if (config.provenance) parts.push('provenance')\n if (config.archive) parts.push('archive')\n if (config.tiers?.length) parts.push(`tiers:${config.tiers.join(',')}`)\n if (config.perRecordKeys) parts.push('per-record-cek')\n if (!parts.length) return null\n return <Text dimColor>config: {parts.join(' ')}</Text>\n}\n\nexport function DetailPane({ collection }: { collection: InspectorCollection | undefined }) {\n if (!collection) return (\n <Box flexDirection=\"column\"><Text dimColor>Select a collection (↵)</Text></Box>\n )\n\n const heading = collection.meta?.label\n ? `${collection.meta.label} (${collection.name})`\n : collection.name\n\n return (\n <Box flexDirection=\"column\">\n <Text bold underline>{heading}</Text>\n {collection.meta?.description\n ? <Text dimColor>{collection.meta.description}</Text>\n : null}\n <Text>records: {collection.stats?.records ?? '—'} bytes: {collection.stats?.bytes ?? '—'}</Text>\n\n {/* Rich field list from describe() when available */}\n {collection.described && collection.described.length > 0\n ? (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold>schema</Text>\n {collection.described.map((f) => {\n const sens = sensitivityTag(f.sensitivity)\n const i18nMark = f.i18n ? '[i18n]' : ''\n const roMark = f.editable === false ? '[ro]' : ''\n const widgetMark = f.widget ? `<${f.widget}>` : ''\n const markers = [sens, i18nMark, roMark, widgetMark].filter(Boolean).join(' ')\n return (\n <Text key={f.key}>\n {' '}{f.label} <Text dimColor>({f.key}: {f.type})</Text>\n {markers ? <Text color=\"yellow\"> {markers}</Text> : null}\n </Text>\n )\n })}\n </Box>\n )\n : (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold>schema</Text>\n {Object.keys(collection.fields).length\n ? Object.entries(collection.fields).map(([k, f]) => (\n <Text key={k}>{' '}{k}: <Text dimColor>{f.type}</Text></Text>\n ))\n : <Text dimColor> (no declared fields)</Text>}\n </Box>\n )}\n\n {/* Collection config strip */}\n {collection.config\n ? <Box marginTop={1}><ConfigLine config={collection.config} /></Box>\n : null}\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { RecordPage, InspectorCollection } from '@noy-db/in-devtools'\n\nconst MASK = '••••'\n\nfunction cell(value: unknown): string {\n if (value === null || value === undefined) return '·'\n if (typeof value === 'object') return Array.isArray(value) ? `[${(value as unknown[]).length}]` : '{…}'\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value)\n return '?'\n}\n\nexport function RecordsPane({ collection, page, error, revealAll }: {\n collection: InspectorCollection\n page: RecordPage | null\n error?: string\n revealAll?: boolean\n}) {\n // Build the set of sensitive field keys from described[] (pii + secret); empty if no described.\n const sensitiveKeys: ReadonlySet<string> = React.useMemo(() => {\n if (!collection.described) return new Set<string>()\n const keys = new Set<string>()\n for (const f of collection.described) {\n if (f.sensitivity !== undefined && f.sensitivity !== 'public') keys.add(f.key)\n }\n return keys\n }, [collection.described])\n\n const schemaFields = Object.keys(collection.fields)\n if (error) return <Box flexDirection=\"column\"><Text color=\"red\">records error: {error}</Text><Text dimColor>n/p retry · ⇥ back</Text></Box>\n if (!page) return <Box flexDirection=\"column\"><Text dimColor>loading records…</Text></Box>\n // Fall back to first-row keys when schema has no declared fields\n const firstRowKeys = page.rows.length > 0 && typeof page.rows[0] === 'object' && page.rows[0] !== null\n ? Object.keys(page.rows[0] as Record<string, unknown>)\n : []\n const fields = schemaFields.length > 0 ? schemaFields : firstRowKeys\n const from = page.total === 0 ? 0 : page.offset + 1\n const to = Math.min(page.offset + page.limit, page.total)\n\n function renderCell(f: string, row: unknown): string {\n const raw = cell((row as Record<string, unknown>)?.[f])\n if (!revealAll && sensitiveKeys.has(f)) return MASK\n return raw\n }\n\n const revealHint = sensitiveKeys.size > 0 ? ' · r reveal/hide' : ''\n return (\n <Box flexDirection=\"column\">\n <Text bold>rows {from}–{to} of {page.total} <Text dimColor>(n/p page · ⇥ back{revealHint})</Text></Text>\n <Text dimColor>{fields.join(' ')}</Text>\n {page.rows.map((row, i) => (\n <Text key={i}>{fields.map((f) => renderCell(f, row)).join(' ')}</Text>\n ))}\n </Box>\n )\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport type { FeedRow } from '../types.js'\nimport type { MeterSnapshot } from '@noy-db/to-meter'\n\nexport function WriteMonitor({ vaultName, rows, meter }: { vaultName: string; rows: ReadonlyArray<FeedRow>; meter: MeterSnapshot | null }) {\n const m = meter?.byMethod\n return (\n <Box flexDirection=\"column\">\n <Text bold>Write Monitor — {vaultName} <Text dimColor>(w/esc · c clear · q quit)</Text></Text>\n {meter && m && (\n <Text>\n store put p50 {m.put?.p50 ?? '—'}ms p99 {m.put?.p99 ?? '—'}ms{meter.status === 'degraded' ? ' ⚠degraded' : ''} · del p50 {m.delete?.p50 ?? '—'} p99 {m.delete?.p99 ?? '—'} · get p50 {m.get?.p50 ?? '—'} p99 {m.get?.p99 ?? '—'}\n </Text>\n )}\n <Text dimColor>time user op collection/docId v</Text>\n {rows.length === 0 && <Text dimColor>(waiting for writes…)</Text>}\n {rows.map((r, i) => (\n r.conflict\n ? <Text key={i} color=\"yellow\">{r.time} {r.user.padEnd(6)} {r.op} {r.target.padEnd(18)} {r.versions} ⚠ CONFLICT</Text>\n : <Text key={i}>{r.time} {r.user.padEnd(6)} {r.op} {r.target.padEnd(18)} {r.versions}</Text>\n ))}\n </Box>\n )\n}\n","import { resolve as resolvePath } from 'node:path'\nimport { pathToFileURL } from 'node:url'\n\n/**\n * Load a NoydbOptions object from a `.js`/`.mjs` config (default export, or a\n * factory function). Mirrors @noy-db/cli's loader; reimplemented here to avoid\n * coupling the TUI bin to the whole cli package. `.ts` is unsupported (Node has\n * no native loader) — compile first or use a `.mjs` config.\n */\nexport async function loadOptionsFromFile(filePath: string): Promise<unknown> {\n const abs = resolvePath(filePath)\n if (/\\.[mc]?ts$/.test(abs)) {\n throw new Error(\n `TypeScript config files are not directly loadable. Compile it first, or use a .mjs/.js config.`,\n )\n }\n const mod = (await import(pathToFileURL(abs).href)) as { default?: unknown }\n const value = mod.default ?? mod\n return typeof value === 'function' ? await (value as () => Promise<unknown>)() : value\n}\n\n/** Resolve the passphrase from `--passphrase=…` or `NOYDB_PASSPHRASE`; undefined → caller prompts. */\nexport function resolvePassphrase(argv: readonly string[], env: NodeJS.ProcessEnv): string | undefined {\n const flag = argv.find((a) => a.startsWith('--passphrase='))\n if (flag) return flag.slice('--passphrase='.length)\n if (env.NOYDB_PASSPHRASE) return env.NOYDB_PASSPHRASE\n return undefined\n}\n","import type { Readable, Writable } from 'node:stream'\n\nexport interface PromptStreams {\n input?: Readable & { setRawMode?: (mode: boolean) => void }\n output?: Writable\n}\n\n/**\n * Read a line from `input` without echoing the plaintext; emit one `•` per\n * character to `output`. Returns the typed string (Enter terminates).\n * Never logs/persists the value.\n */\nexport function promptMasked(question: string, streams: PromptStreams = {}): Promise<string> {\n const input = (streams.input ?? process.stdin) as Readable & { setRawMode?: (m: boolean) => void }\n const output = streams.output ?? process.stdout\n return new Promise<string>((resolve, reject) => {\n output.write(question)\n input.setRawMode?.(true)\n let buf = ''\n const onData = (chunk: Buffer | string) => {\n const s = chunk.toString()\n for (const ch of s) {\n if (ch === '\\r' || ch === '\\n') {\n output.write('\\n')\n input.setRawMode?.(false)\n input.removeListener('data', onData)\n resolve(buf)\n return\n }\n if (ch === '\\x03') { // Ctrl-C — abort\n output.write('\\n')\n input.setRawMode?.(false)\n input.removeListener('data', onData)\n reject(new Error('aborted'))\n return\n }\n if (ch === '\\x7f' || ch === '\\x08') { // DEL / Backspace\n if (buf.length > 0) { buf = buf.slice(0, -1); output.write('\\b \\b') }\n continue\n }\n buf += ch\n output.write('•')\n }\n }\n input.on('data', onData)\n })\n}\n"],"mappings":"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","names":["React","Box","Text","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","jsx","jsxs","React","Box","Text","jsx"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noy-db/in-devtools-tui",
3
- "version": "0.2.0-pre.9",
3
+ "version": "0.3.0-pre.2",
4
4
  "description": "Interactive terminal inspector for a live noy-db (ink TUI over @noy-db/in-devtools).",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -14,18 +14,21 @@
14
14
  "dependencies": {
15
15
  "ink": "^5.0.1",
16
16
  "react": "^18.3.1",
17
- "@noy-db/to-meter": "0.2.0-pre.9"
17
+ "@noy-db/to-meter": "0.3.0-pre.2"
18
18
  },
19
19
  "peerDependencies": {
20
- "@noy-db/hub": "0.2.0-pre.9",
21
- "@noy-db/in-devtools": "0.2.0-pre.9"
20
+ "@noy-db/hub": "0.3.0-pre.2",
21
+ "@noy-db/in-devtools": "0.3.0-pre.2"
22
22
  },
23
23
  "devDependencies": {
24
24
  "ink-testing-library": "^4.0.0",
25
25
  "@types/node": "^22.0.0",
26
26
  "@types/react": "^18.3.12",
27
- "@noy-db/in-devtools": "0.2.0-pre.9",
28
- "@noy-db/hub": "0.2.0-pre.9"
27
+ "@noy-db/in-devtools": "0.3.0-pre.2",
28
+ "@noy-db/hub": "0.3.0-pre.2"
29
+ },
30
+ "engines": {
31
+ "node": ">=22.0.0"
29
32
  },
30
33
  "scripts": {
31
34
  "build": "tsup",