@thingd/cli 0.42.1 → 0.44.0

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":"interactive.d.ts","sourceRoot":"","sources":["../src/interactive.ts"],"names":[],"mappings":"AA6wDA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkCvD"}
1
+ {"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../src/interactive.ts"],"names":[],"mappings":"AAyyDA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA4CvD"}
@@ -100,6 +100,7 @@ function openForm(title, fields, onSubmit) {
100
100
  value: f.value || (f.options?.[0] ?? ""),
101
101
  placeholder: f.placeholder,
102
102
  isSecret: f.isSecret,
103
+ dirty: false,
103
104
  options: f.options,
104
105
  allowCustom: f.allowCustom,
105
106
  })),
@@ -341,6 +342,30 @@ async function fetchResources() {
341
342
  }
342
343
  }
343
344
  }
345
+ // ── Connection helpers ───────────────────────────────────────────────
346
+ async function connectToDriver(selectedDriver, resolvedPath, url, token) {
347
+ db = await ThingD.open({
348
+ path: resolvedPath,
349
+ url,
350
+ driver: selectedDriver,
351
+ authToken: token,
352
+ });
353
+ driver = selectedDriver;
354
+ dbPath = resolvedPath;
355
+ authToken = typeof token === "string" ? token : "";
356
+ connected = true;
357
+ startedAt = Date.now();
358
+ cursorIndex = 0;
359
+ scrollOffset = 0;
360
+ loadedItemId = "";
361
+ await fetchResources();
362
+ draw();
363
+ const t = buildTree();
364
+ const first = t[cursorIndex];
365
+ if (first) {
366
+ scheduleLoad(first);
367
+ }
368
+ }
344
369
  function buildTree() {
345
370
  if (!connected) {
346
371
  return [
@@ -1369,7 +1394,13 @@ function setupKeypress() {
1369
1394
  // biome-ignore lint/suspicious/noControlCharactersInRegex: we need to filter control characters
1370
1395
  const clean = str.replace(/[\x00-\x1F\x7F]/g, "");
1371
1396
  if (clean) {
1372
- f.value += clean;
1397
+ if (f.isSecret && !f.dirty && f.value) {
1398
+ f.value = clean;
1399
+ f.dirty = true;
1400
+ }
1401
+ else {
1402
+ f.value += clean;
1403
+ }
1373
1404
  formState.error = undefined;
1374
1405
  draw();
1375
1406
  }
@@ -1531,6 +1562,21 @@ async function handleConnect(node) {
1531
1562
  return;
1532
1563
  }
1533
1564
  const selectedDriver = node.ref.driver;
1565
+ // Cloud with saved credentials — skip form
1566
+ if (selectedDriver === "cloud") {
1567
+ const cloudCfg = readCloudConfig();
1568
+ if (cloudCfg?.token && cloudCfg?.url) {
1569
+ try {
1570
+ await connectToDriver("cloud", cloudCfg.url, cloudCfg.url, cloudCfg.token);
1571
+ }
1572
+ catch (err) {
1573
+ const errMsg = err instanceof Error ? err.message : String(err);
1574
+ viewerLines = [pc.red(`Failed to connect: ${errMsg}`)];
1575
+ draw();
1576
+ }
1577
+ return;
1578
+ }
1579
+ }
1534
1580
  if (selectedDriver === "native" || selectedDriver === "cloud") {
1535
1581
  const cloudCfg = selectedDriver === "cloud" ? readCloudConfig() : null;
1536
1582
  openForm(`Connect to ${selectedDriver}`, [
@@ -1557,35 +1603,7 @@ async function handleConnect(node) {
1557
1603
  ]),
1558
1604
  ], async (vals) => {
1559
1605
  const resolvedPath = selectedDriver === "cloud" ? vals.url || "" : vals.path || "";
1560
- // Allow the underlying SDK/SQLite driver to automatically create the file
1561
- // if it does not exist, rather than throwing an error here.
1562
- db = await ThingD.open({
1563
- path: resolvedPath,
1564
- url: selectedDriver === "cloud" ? resolvedPath : undefined,
1565
- driver: selectedDriver,
1566
- authToken: vals.token,
1567
- });
1568
- driver = selectedDriver;
1569
- dbPath = resolvedPath;
1570
- // Update global authToken safely
1571
- if (typeof vals.token === "string") {
1572
- authToken = vals.token;
1573
- }
1574
- else {
1575
- authToken = "";
1576
- }
1577
- connected = true;
1578
- startedAt = Date.now();
1579
- cursorIndex = 0;
1580
- scrollOffset = 0;
1581
- loadedItemId = "";
1582
- await fetchResources();
1583
- draw();
1584
- const tree = buildTree();
1585
- const first = tree[cursorIndex];
1586
- if (first) {
1587
- scheduleLoad(first);
1588
- }
1606
+ await connectToDriver(selectedDriver, resolvedPath, selectedDriver === "cloud" ? resolvedPath : undefined, vals.token);
1589
1607
  });
1590
1608
  }
1591
1609
  else {
@@ -1666,6 +1684,16 @@ export async function runInteractiveCli() {
1666
1684
  if (first) {
1667
1685
  scheduleLoad(first);
1668
1686
  }
1687
+ // Auto-connect to cloud if credentials exist
1688
+ const cloudCfg = readCloudConfig();
1689
+ if (cloudCfg?.token && cloudCfg?.url) {
1690
+ try {
1691
+ await connectToDriver("cloud", cloudCfg.url, cloudCfg.url, cloudCfg.token);
1692
+ }
1693
+ catch {
1694
+ // Auto-connect failed — fall through to environment selection
1695
+ }
1696
+ }
1669
1697
  setupKeypress();
1670
1698
  // Background polling loop for real-time updates
1671
1699
  pollTimer = setInterval(async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thingd/cli",
3
- "version": "0.42.1",
3
+ "version": "0.44.0",
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.42.1"
48
+ "@thingd/sdk": "0.44.0"
49
49
  },
50
50
  "engines": {
51
51
  "node": ">=24.0.0"