@thingd/cli 0.57.0 → 0.58.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAQA,OAAO,EAUL,MAAM,EACN,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AASrB,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAEjD,KAAK,YAAY,GAAG;IAClB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,KAAK,YAAY,GAAG,MAAM,CAAC,cAAc,CAAC;AAE1C,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7B,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAsCF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAwFF,wBAAsB,MAAM,CAC1B,IAAI,WAAwB,EAC5B,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,MAAM,CAAC,CA8EjB;AAk6BD,wBAAsB,MAAM,CAC1B,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAef;AA4BD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,GAAG,iBAAiB,CAqDxE;AAiDD,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/E;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAGlF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnF;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrF;AAyFD,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAEpF;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAElE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAQA,OAAO,EAUL,MAAM,EACN,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AASrB,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAEjD,KAAK,YAAY,GAAG;IAClB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,KAAK,YAAY,GAAG,MAAM,CAAC,cAAc,CAAC;AAE1C,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7B,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAsCF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAwFF,wBAAsB,MAAM,CAC1B,IAAI,WAAwB,EAC5B,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,MAAM,CAAC,CA8EjB;AA08BD,wBAAsB,MAAM,CAC1B,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAef;AA4BD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,GAAG,iBAAiB,CAqDxE;AAiDD,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/E;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAGlF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnF;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrF;AAyFD,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAEpF;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAElE"}
package/dist/index.js CHANGED
@@ -290,6 +290,10 @@ async function runCommand(context) {
290
290
  await runBackup(context);
291
291
  return;
292
292
  }
293
+ if (command === "completions") {
294
+ await runCompletions(context);
295
+ return;
296
+ }
293
297
  if (command === "db") {
294
298
  const sub = context.parsed.tokens[1];
295
299
  if (!sub) {
@@ -381,6 +385,39 @@ async function runDbIntegrity(context) {
381
385
  }
382
386
  });
383
387
  }
388
+ async function runCompletions(context) {
389
+ const shell = optionalToken(context.parsed, 1) ?? "bash";
390
+ const cmds = [
391
+ "status",
392
+ "search",
393
+ "mcp",
394
+ "cloud",
395
+ "objects",
396
+ "events",
397
+ "collections",
398
+ "streams",
399
+ "queues",
400
+ "links",
401
+ "schema",
402
+ "nlq",
403
+ "aggregate",
404
+ "timeseries",
405
+ "metrics",
406
+ "dashboard",
407
+ "export",
408
+ "import",
409
+ "snapshot",
410
+ "backup",
411
+ "db",
412
+ "completions",
413
+ ];
414
+ const script = shell === "zsh"
415
+ ? `#compdef thingd\ncompdef _thingd thingd\n_thingd() {\n _describe 'thingd commands' ${JSON.stringify(cmds.map((c) => `${c}:thingd ${c}`))}\n}\n`
416
+ : shell === "fish"
417
+ ? `complete -c thingd -f\n${cmds.map((c) => `complete -c thingd -n '__fish_use_subcommand' -a ${c}`).join("\n")}\n`
418
+ : `_thingd() {\n local cur=${"${COMP_WORDS[COMP_CWORD]}"}\n if [ $COMP_CWORD -eq 1 ]; then\n COMPREPLY=($(compgen -W "${cmds.join(" ")}" -- "$cur"))\n fi\n}\ncomplete -F _thingd thingd\n`;
419
+ writeText(context.stdout, script);
420
+ }
384
421
  async function runStatus(context) {
385
422
  const connection = resolveConnection(context);
386
423
  if (!connection.cloud) {
@@ -1 +1 @@
1
- {"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../src/interactive.ts"],"names":[],"mappings":"AA8lGA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0FvD"}
1
+ {"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../src/interactive.ts"],"names":[],"mappings":"AAitGA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0FvD"}
@@ -93,6 +93,21 @@ let eventAppendRateHistory = [];
93
93
  let viewerLines = ["Select an item to view details."];
94
94
  let viewerScroll = 0;
95
95
  let showHelp = false;
96
+ const loading = false;
97
+ const toasts = [];
98
+ function addToast(msg) {
99
+ toasts.push(msg);
100
+ if (toasts.length > 3) {
101
+ toasts.shift();
102
+ }
103
+ setTimeout(() => {
104
+ const idx = toasts.indexOf(msg);
105
+ if (idx !== -1) {
106
+ toasts.splice(idx, 1);
107
+ draw();
108
+ }
109
+ }, 3000);
110
+ }
96
111
  let lastNeighborsRef = "";
97
112
  let loadedItemId = "";
98
113
  let loadTimer = null;
@@ -1130,10 +1145,18 @@ function draw() {
1130
1145
  help = ` ${pc.dim("↑↓")} nav ${pc.dim("enter")} connect ${pc.dim("q")} quit `;
1131
1146
  }
1132
1147
  else {
1133
- help = ` ${pc.dim("↑↓")} nav ${pc.dim("←→")} toggle ${pc.dim("c")} create ${pc.dim("e")} edit ${pc.dim("d")} delete ${pc.dim("/")} search ${pc.dim("n")} neighbors ${pc.dim("N")} nlq ${pc.dim("a")} agg ${pc.dim("t")} ts ${pc.dim("o")} options ${pc.dim("b")} batch ${pc.dim("i")} info ${pc.dim("r")} refresh ${pc.dim("s")} switch ${pc.dim("l")} logout ${pc.dim("q")} quit `;
1148
+ help = ` ${pc.dim("↑↓")} nav ${pc.dim("←→")} toggle ${pc.dim("c")} create ${pc.dim("e")} edit ${pc.dim("d")} delete ${pc.dim("/")} search ${pc.dim("n")} neighbors ${pc.dim("N")} nlq ${pc.dim("a")} agg ${pc.dim("t")} ts ${pc.dim("o")} opts ${pc.dim("b")} batch ${pc.dim("x")} export ${pc.dim("p")} import ${pc.dim("w")} web ${pc.dim("i")} info ${pc.dim("r")} refresh ${pc.dim("s")} switch ${pc.dim("l")} logout ${pc.dim("q")} quit `;
1134
1149
  }
1135
1150
  buf += `${pc.dim("─".repeat(W))}\n`;
1136
1151
  buf += padToWidth(help, W);
1152
+ if (loading) {
1153
+ buf += `\n${pc.cyan("◇")} ${pc.dim("Working...")}`;
1154
+ }
1155
+ if (toasts.length > 0) {
1156
+ for (const t of toasts) {
1157
+ buf += `\n ${pc.green("●")} ${pc.dim(t)}`;
1158
+ }
1159
+ }
1137
1160
  // Clear to end
1138
1161
  buf += "\u001B[J";
1139
1162
  if (showHelp) {
@@ -1447,6 +1470,7 @@ async function handleCreate(selected) {
1447
1470
  await db.put(target, { id, ...data });
1448
1471
  expandedSet.add("cat:collections");
1449
1472
  expandedSet.add(`col:${target}`);
1473
+ addToast(`Created object ${id} in ${target}`);
1450
1474
  }
1451
1475
  else if (kind === "event") {
1452
1476
  if (!vals.payload?.trim()) {
@@ -1454,6 +1478,7 @@ async function handleCreate(selected) {
1454
1478
  }
1455
1479
  await db.events.append(target, { type: vals.payload.trim() });
1456
1480
  expandedSet.add("cat:streams");
1481
+ addToast(`Appended event to ${target}`);
1457
1482
  }
1458
1483
  else if (kind === "queue") {
1459
1484
  if (!vals.payload?.trim()) {
@@ -1462,6 +1487,7 @@ async function handleCreate(selected) {
1462
1487
  const data = parsePayload(vals.payload);
1463
1488
  await db.queue(target).push(data);
1464
1489
  expandedSet.add("cat:queues");
1490
+ addToast(`Pushed job to queue ${target}`);
1465
1491
  }
1466
1492
  else if (kind === "link") {
1467
1493
  const toRef = (vals.objId || "").trim();
@@ -1488,6 +1514,7 @@ async function handleCreate(selected) {
1488
1514
  linkType = (vals.payload || "").trim() || "related";
1489
1515
  }
1490
1516
  await db.links.create(target, linkType, toRef, weight, metadataJson);
1517
+ addToast(`Created link: ${target} ${linkType} ${toRef}`);
1491
1518
  }
1492
1519
  else {
1493
1520
  throw new Error("Kind must be 'object', 'event', 'queue', or 'link'.");
@@ -1593,6 +1620,7 @@ async function handleDelete(selected) {
1593
1620
  if (result && !result.deleted) {
1594
1621
  throw new Error(`Object '${ref.id}' not found in collection '${ref.collection}'`);
1595
1622
  }
1623
+ addToast(`Deleted object ${ref.id}`);
1596
1624
  });
1597
1625
  }
1598
1626
  else if (selected.type === "queue" && selected.ref) {
@@ -1637,6 +1665,7 @@ async function handleDelete(selected) {
1637
1665
  if (!ok) {
1638
1666
  throw new Error(`Link '${linkId}' not found.`);
1639
1667
  }
1668
+ addToast(`Deleted link ${linkId}`);
1640
1669
  });
1641
1670
  }
1642
1671
  else if (selected.type === "job" && selected.ref) {
@@ -2153,6 +2182,71 @@ async function handleBatchOps(selected) {
2153
2182
  }
2154
2183
  });
2155
2184
  }
2185
+ async function handleExport(selected) {
2186
+ const colName = selected?.type === "collection"
2187
+ ? (selected.ref?.name ?? "")
2188
+ : selected?.type === "object"
2189
+ ? (selected.ref?.collection ?? "")
2190
+ : "";
2191
+ if (!colName) {
2192
+ viewerLines = [pc.yellow("Select a collection first, then press [x] to export.")];
2193
+ loadedItemId = "export_info";
2194
+ draw();
2195
+ return;
2196
+ }
2197
+ openForm(`Export: ${colName}`, [{ id: "path", label: "Output File Path", placeholder: "/tmp/export.jsonl" }], async (vals) => {
2198
+ const filePath = (vals.path || "").trim();
2199
+ if (!filePath) {
2200
+ throw new Error("File path is required.");
2201
+ }
2202
+ const objs = await db.listObjects(colName);
2203
+ const lines = objs.map((o) => JSON.stringify(o)).join("\n");
2204
+ await fs.promises.writeFile(filePath, lines, "utf-8");
2205
+ addToast(`Exported ${objs.length} objects to ${filePath}`);
2206
+ });
2207
+ }
2208
+ async function handleImport(selected) {
2209
+ const colName = selected?.type === "collection"
2210
+ ? (selected.ref?.name ?? "")
2211
+ : selected?.type === "object"
2212
+ ? (selected.ref?.collection ?? "")
2213
+ : "";
2214
+ if (!colName) {
2215
+ viewerLines = [pc.yellow("Select a collection first, then press [p] to import.")];
2216
+ loadedItemId = "import_info";
2217
+ draw();
2218
+ return;
2219
+ }
2220
+ openForm(`Import: ${colName}`, [{ id: "path", label: "Input File Path (JSONL)", placeholder: "/tmp/export.jsonl" }], async (vals) => {
2221
+ const filePath = (vals.path || "").trim();
2222
+ if (!filePath) {
2223
+ throw new Error("File path is required.");
2224
+ }
2225
+ const text = await fs.promises.readFile(filePath, "utf-8");
2226
+ const objects = text
2227
+ .split("\n")
2228
+ .filter(Boolean)
2229
+ .map((line) => JSON.parse(line));
2230
+ const result = await db.putBatch(colName, objects);
2231
+ addToast(`Imported ${result.length} objects into ${colName}`);
2232
+ });
2233
+ }
2234
+ async function handleDashboard() {
2235
+ const bin = process.argv[1] || "thingd";
2236
+ const args = ["dashboard", "--driver", driver];
2237
+ if (dbPath) {
2238
+ args.push("--path", dbPath);
2239
+ }
2240
+ if (authToken) {
2241
+ args.push("--auth-token", authToken);
2242
+ }
2243
+ const child = spawn(bin, args, {
2244
+ stdio: "inherit",
2245
+ detached: true,
2246
+ });
2247
+ child.unref();
2248
+ addToast(`Launching dashboard: ${bin} dashboard`);
2249
+ }
2156
2250
  async function handleMaintenance() {
2157
2251
  // Cycle through maintenance operations with each press of 'm'
2158
2252
  const operations = ["health", "checkpoint", "backup"];
@@ -2480,6 +2574,15 @@ function setupKeypress() {
2480
2574
  else if (str === "b" || str === "B") {
2481
2575
  await handleBatchOps(tree[cursorIndex]);
2482
2576
  }
2577
+ else if (str === "x" || str === "X") {
2578
+ await handleExport(tree[cursorIndex]);
2579
+ }
2580
+ else if (str === "p" || str === "P") {
2581
+ await handleImport(tree[cursorIndex]);
2582
+ }
2583
+ else if (str === "w" || str === "W") {
2584
+ await handleDashboard();
2585
+ }
2483
2586
  else if (str === "m" || str === "M") {
2484
2587
  await handleMaintenance();
2485
2588
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thingd/cli",
3
- "version": "0.57.0",
3
+ "version": "0.58.1",
4
4
  "description": "CLI, Interactive TUI Dashboard, and MCP server for thingd — a fast object-first data engine for applications and AI agents.",
5
5
  "type": "module",
6
6
  "homepage": "https://engine.thingd.cloud",
@@ -45,7 +45,7 @@
45
45
  "cli-table3": "^0.6.5",
46
46
  "picocolors": "^1.1.1",
47
47
  "zod": "^4.4.3",
48
- "@thingd/sdk": "0.57.0"
48
+ "@thingd/sdk": "0.58.1"
49
49
  },
50
50
  "engines": {
51
51
  "node": ">=24.0.0"