@thingd/cli 0.53.0 → 0.53.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/interactive.d.ts.map +1 -1
- package/dist/interactive.js +75 -77
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../src/interactive.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../src/interactive.ts"],"names":[],"mappings":"AAylEA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0FvD"}
|
package/dist/interactive.js
CHANGED
|
@@ -92,6 +92,7 @@ let viewerScroll = 0;
|
|
|
92
92
|
let loadedItemId = "";
|
|
93
93
|
let loadTimer = null;
|
|
94
94
|
let pollTimer = null;
|
|
95
|
+
let polling = false;
|
|
95
96
|
let keypressHandler = null;
|
|
96
97
|
let formState = null;
|
|
97
98
|
function openForm(title, fields, onSubmit, keepViewer) {
|
|
@@ -198,75 +199,47 @@ function formatUptime(ms) {
|
|
|
198
199
|
}
|
|
199
200
|
async function fetchResourcesFallback() {
|
|
200
201
|
cloudError = null;
|
|
202
|
+
// Collections and streams — parallel fetch
|
|
203
|
+
let nativeCollections;
|
|
204
|
+
let nativeStreams;
|
|
201
205
|
try {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const defaultStrs = new Set();
|
|
207
|
-
for (const c of nativeCollections) {
|
|
208
|
-
defaultCols.add(c);
|
|
209
|
-
}
|
|
210
|
-
for (const s of nativeStreams) {
|
|
211
|
-
defaultStrs.add(s);
|
|
212
|
-
}
|
|
213
|
-
collections = Array.from(defaultCols).sort();
|
|
214
|
-
streams = Array.from(defaultStrs).sort();
|
|
206
|
+
[nativeCollections, nativeStreams] = await Promise.all([
|
|
207
|
+
db.listCollections(),
|
|
208
|
+
db.listStreams(),
|
|
209
|
+
]);
|
|
215
210
|
}
|
|
216
211
|
catch (err) {
|
|
217
212
|
const msg = err instanceof Error ? err.message : String(err);
|
|
218
213
|
cloudError = `Failed to load resources: ${msg}`;
|
|
219
|
-
|
|
220
|
-
|
|
214
|
+
nativeCollections = [];
|
|
215
|
+
nativeStreams = [];
|
|
221
216
|
if (viewerLines.length === 1 && viewerLines[0] === "Select an item to view details.") {
|
|
222
217
|
viewerLines = [pc.yellow(cloudError), pc.dim("Press 'r' to retry or 's' to switch driver.")];
|
|
223
218
|
}
|
|
224
219
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
247
|
-
catch {
|
|
248
|
-
totalDeadJobsCount = 0;
|
|
249
|
-
}
|
|
250
|
-
// Queues
|
|
251
|
-
try {
|
|
252
|
-
const listed = await db.listQueues();
|
|
253
|
-
queues = (listed ?? []).sort();
|
|
254
|
-
}
|
|
255
|
-
catch (err) {
|
|
256
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
257
|
-
cloudError = cloudError ?? `Failed to load queues: ${msg}`;
|
|
258
|
-
queues = [];
|
|
259
|
-
}
|
|
260
|
-
// Link count
|
|
261
|
-
try {
|
|
262
|
-
totalLinksCount = await db.countLinks();
|
|
263
|
-
}
|
|
264
|
-
catch {
|
|
265
|
-
totalLinksCount = 0;
|
|
266
|
-
}
|
|
267
|
-
// Populate objectsByCollection from live data
|
|
220
|
+
collections = [...new Set(nativeCollections)].sort();
|
|
221
|
+
streams = [...new Set(nativeStreams)].sort();
|
|
222
|
+
// Counts, queues, links — all parallel, each with independent error handling
|
|
223
|
+
const [objCount, evtCount, activeCount, deadCount, listedQueues, linkCount] = await Promise.all([
|
|
224
|
+
db.countObjects().catch(() => 0),
|
|
225
|
+
db.countEvents().catch(() => 0),
|
|
226
|
+
db.countActiveJobs().catch(() => 0),
|
|
227
|
+
db.countDeadJobs().catch(() => 0),
|
|
228
|
+
db.listQueues().catch(() => {
|
|
229
|
+
cloudError = cloudError ?? "Failed to load queues";
|
|
230
|
+
return [];
|
|
231
|
+
}),
|
|
232
|
+
db.countLinks().catch(() => 0),
|
|
233
|
+
]);
|
|
234
|
+
totalObjects = objCount;
|
|
235
|
+
totalEventsCount = evtCount;
|
|
236
|
+
totalActiveJobsCount = activeCount;
|
|
237
|
+
totalDeadJobsCount = deadCount;
|
|
238
|
+
queues = [...new Set(listedQueues ?? [])].sort();
|
|
239
|
+
totalLinksCount = linkCount;
|
|
240
|
+
// Objects per collection — parallel
|
|
268
241
|
objectsByCollection.clear();
|
|
269
|
-
|
|
242
|
+
await Promise.all(collections.map(async (col) => {
|
|
270
243
|
try {
|
|
271
244
|
const list = await db.listObjects(col);
|
|
272
245
|
objectsByCollection.set(col, list.map((o) => o.id));
|
|
@@ -274,7 +247,7 @@ async function fetchResourcesFallback() {
|
|
|
274
247
|
catch {
|
|
275
248
|
objectsByCollection.set(col, []);
|
|
276
249
|
}
|
|
277
|
-
}
|
|
250
|
+
}));
|
|
278
251
|
}
|
|
279
252
|
async function fetchResources() {
|
|
280
253
|
if (driver === "native" && dbPath) {
|
|
@@ -327,9 +300,8 @@ async function fetchResources() {
|
|
|
327
300
|
const prevEvents = eventsHistory.length > 0
|
|
328
301
|
? (eventsHistory[eventsHistory.length - 1] ?? totalEventsCount)
|
|
329
302
|
: totalEventsCount;
|
|
330
|
-
|
|
331
|
-
const
|
|
332
|
-
const eventAppendRate = Math.max(0, Math.round((totalEventsCount - prevEvents) / 2));
|
|
303
|
+
const objectWriteRate = Math.max(0, Math.round((totalObjects - prevObjects) / 10));
|
|
304
|
+
const eventAppendRate = Math.max(0, Math.round((totalEventsCount - prevEvents) / 10));
|
|
333
305
|
// Push Histories with Initial Pre-population to prevent misleading growth wiggles
|
|
334
306
|
if (objectsHistory.length === 0) {
|
|
335
307
|
objectsHistory = new Array(60).fill(totalObjects);
|
|
@@ -616,7 +588,12 @@ function scheduleLoad(node) {
|
|
|
616
588
|
? ` Ephemeral in-memory database.\n All data is destroyed on exit.\n\n ${pc.dim("Best for: testing, prototyping")}\n\n ${pc.dim("Press")} ${pc.bold("Enter")} ${pc.dim("to connect.")}`
|
|
617
589
|
: d === "native"
|
|
618
590
|
? ` Persistent SQLite database.\n Data is stored on disk.\n\n ${pc.dim("Best for: local development, single-node")}\n\n ${pc.dim("Press")} ${pc.bold("Enter")} ${pc.dim("to connect.")}`
|
|
619
|
-
:
|
|
591
|
+
: (() => {
|
|
592
|
+
const hasCfg = !!readCloudConfig()?.token;
|
|
593
|
+
return hasCfg
|
|
594
|
+
? ` Connect to a remote thingd instance.\n Requires a URL and optional auth token.\n\n ${pc.dim("Best for: production, multi-node")}\n\n ${pc.dim("Press")} ${pc.bold("Enter")} ${pc.dim("to connect.")}`
|
|
595
|
+
: ` ${pc.yellow("Not logged in to thingd Cloud.")}\n\n Run ${pc.cyan("thingd cloud login")} to authenticate, or\n press ${pc.bold("Enter")} to connect with a URL and token manually.`;
|
|
596
|
+
})(),
|
|
620
597
|
].join("\n");
|
|
621
598
|
viewerLines = info.split("\n");
|
|
622
599
|
loadedItemId = node.id;
|
|
@@ -1986,21 +1963,42 @@ export async function runInteractiveCli() {
|
|
|
1986
1963
|
setupKeypress();
|
|
1987
1964
|
// Background polling loop for real-time updates
|
|
1988
1965
|
pollTimer = setInterval(async () => {
|
|
1989
|
-
if (connected
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
1966
|
+
if (!connected || formState?.active || polling) {
|
|
1967
|
+
return;
|
|
1968
|
+
}
|
|
1969
|
+
polling = true;
|
|
1970
|
+
try {
|
|
1971
|
+
const snapItemId = loadedItemId;
|
|
1972
|
+
const snapshot = JSON.stringify([
|
|
1973
|
+
totalObjects,
|
|
1974
|
+
totalEventsCount,
|
|
1975
|
+
totalActiveJobsCount,
|
|
1976
|
+
totalDeadJobsCount,
|
|
1977
|
+
totalLinksCount,
|
|
1978
|
+
]);
|
|
1979
|
+
await fetchResources();
|
|
1980
|
+
const changed = snapshot !==
|
|
1981
|
+
JSON.stringify([
|
|
1982
|
+
totalObjects,
|
|
1983
|
+
totalEventsCount,
|
|
1984
|
+
totalActiveJobsCount,
|
|
1985
|
+
totalDeadJobsCount,
|
|
1986
|
+
totalLinksCount,
|
|
1987
|
+
]);
|
|
1988
|
+
const tree = buildTree();
|
|
1989
|
+
const n = tree[cursorIndex];
|
|
1990
|
+
if (n && snapItemId === n.id && n.type !== "category") {
|
|
1991
|
+
await loadContent(n).catch(() => { });
|
|
2000
1992
|
}
|
|
2001
|
-
|
|
2002
|
-
|
|
1993
|
+
if (changed) {
|
|
1994
|
+
draw();
|
|
2003
1995
|
}
|
|
2004
1996
|
}
|
|
1997
|
+
catch {
|
|
1998
|
+
// Prevent unhandled rejection from killing the process
|
|
1999
|
+
}
|
|
2000
|
+
finally {
|
|
2001
|
+
polling = false;
|
|
2002
|
+
}
|
|
2005
2003
|
}, 10_000);
|
|
2006
2004
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thingd/cli",
|
|
3
|
-
"version": "0.53.
|
|
3
|
+
"version": "0.53.2",
|
|
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.53.
|
|
48
|
+
"@thingd/sdk": "0.53.2"
|
|
49
49
|
},
|
|
50
50
|
"engines": {
|
|
51
51
|
"node": ">=24.0.0"
|