@unbound-app/debugger 0.6.0 → 0.7.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/index.mjs +42 -34
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import { cli } from "cleye";
|
|
|
8
8
|
const HISTORY_PATH = join(__dirname, "..", "..", ".history.json");
|
|
9
9
|
const HISTORY_FILE = Bun.file(HISTORY_PATH);
|
|
10
10
|
let history = [];
|
|
11
|
+
/** @description Loads the persisted REPL history from disk, if present. */
|
|
11
12
|
async function loadHistory() {
|
|
12
13
|
try {
|
|
13
14
|
if (await HISTORY_FILE.exists()) history = await HISTORY_FILE.json();
|
|
@@ -15,10 +16,12 @@ async function loadHistory() {
|
|
|
15
16
|
terminal.red.bold(`Failed to load history.\n`);
|
|
16
17
|
}
|
|
17
18
|
}
|
|
19
|
+
/** @description Appends an entry to the REPL history and persists it. */
|
|
18
20
|
function addHistoryItem(item) {
|
|
19
21
|
history.push(item);
|
|
20
22
|
persistHistory();
|
|
21
23
|
}
|
|
24
|
+
/** @description Writes the REPL history to disk. */
|
|
22
25
|
function persistHistory() {
|
|
23
26
|
HISTORY_FILE.write(JSON.stringify(history, null, 2));
|
|
24
27
|
}
|
|
@@ -218,29 +221,41 @@ function handleDeviceMessage$1(message) {
|
|
|
218
221
|
entry.deliver(message);
|
|
219
222
|
return;
|
|
220
223
|
}
|
|
221
|
-
if (message.type
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
224
|
+
if (message.type !== "log") return;
|
|
225
|
+
for (const socket of state$2.controllers) socket.send(JSON.stringify(message));
|
|
226
|
+
for (const listener of logListeners) listener(message);
|
|
225
227
|
}
|
|
226
|
-
/**
|
|
228
|
+
/**
|
|
229
|
+
* @description Subscribes to device log lines.
|
|
230
|
+
* @param listener Called with each log line.
|
|
231
|
+
* @returns An unsubscribe function.
|
|
232
|
+
*/
|
|
227
233
|
function onLog(listener) {
|
|
228
234
|
logListeners.add(listener);
|
|
229
235
|
return () => void logListeners.delete(listener);
|
|
230
236
|
}
|
|
231
|
-
/**
|
|
237
|
+
/**
|
|
238
|
+
* @description Subscribes to code a controller (e.g. the MCP) sends to evaluate.
|
|
239
|
+
* @param listener Called with each controller's code.
|
|
240
|
+
* @returns An unsubscribe function.
|
|
241
|
+
*/
|
|
232
242
|
function onControllerEval(listener) {
|
|
233
243
|
evalListeners.add(listener);
|
|
234
244
|
return () => void evalListeners.delete(listener);
|
|
235
245
|
}
|
|
236
|
-
/**
|
|
246
|
+
/**
|
|
247
|
+
* @description Subscribes to the results of controller evals.
|
|
248
|
+
* @param listener Called with each controller eval's result.
|
|
249
|
+
* @returns An unsubscribe function.
|
|
250
|
+
*/
|
|
237
251
|
function onControllerResult(listener) {
|
|
238
252
|
resultListeners.add(listener);
|
|
239
253
|
return () => void resultListeners.delete(listener);
|
|
240
254
|
}
|
|
241
255
|
/**
|
|
242
|
-
* @description Subscribes to controller (MCP) connect/disconnect transitions
|
|
243
|
-
*
|
|
256
|
+
* @description Subscribes to controller (MCP) connect/disconnect transitions.
|
|
257
|
+
* @param listener Called with the transition and the resulting controller count.
|
|
258
|
+
* @returns An unsubscribe function.
|
|
244
259
|
*/
|
|
245
260
|
function onController(listener) {
|
|
246
261
|
controllerListeners.add(listener);
|
|
@@ -270,12 +285,14 @@ const state$1 = {
|
|
|
270
285
|
repl: null,
|
|
271
286
|
currentInput: ""
|
|
272
287
|
};
|
|
288
|
+
/** @description Exits the debugger on Ctrl+C. */
|
|
273
289
|
function setupReplListeners() {
|
|
274
|
-
terminal.on("key", (name
|
|
290
|
+
terminal.on("key", (name) => {
|
|
275
291
|
if (name !== "CTRL_C") return;
|
|
276
292
|
process.exit(0);
|
|
277
293
|
});
|
|
278
294
|
}
|
|
295
|
+
/** @description Draws a fresh prompt and evaluates the submitted line on the device. */
|
|
279
296
|
async function takeReplInput() {
|
|
280
297
|
abortCurrentReplInput();
|
|
281
298
|
terminal.bold.cyan("» ");
|
|
@@ -297,27 +314,17 @@ async function takeReplInput() {
|
|
|
297
314
|
});
|
|
298
315
|
await state$1.repl.promise;
|
|
299
316
|
}
|
|
317
|
+
/** @description Cancels the active prompt, optionally erasing it and the pending input. */
|
|
300
318
|
function abortCurrentReplInput({ deletePrompt = false, deleteCurrentInput = false } = {}) {
|
|
301
|
-
if (state$1.repl)
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}
|
|
319
|
+
if (!state$1.repl) return;
|
|
320
|
+
state$1.repl.abort();
|
|
321
|
+
state$1.repl = null;
|
|
322
|
+
if (deletePrompt) terminal.deleteLine(-1);
|
|
323
|
+
if (deleteCurrentInput) state$1.currentInput = "";
|
|
307
324
|
}
|
|
308
325
|
//#endregion
|
|
309
326
|
//#region src/lib/format-log.ts
|
|
310
327
|
/**
|
|
311
|
-
* Reformats a log line as Hermes hands it to `nativeLoggingHook`. Hermes inspects each `console.*`
|
|
312
|
-
* argument and joins them with `, ` — quoting string args (`'a', 'b', { x: 1 }`). That reads badly
|
|
313
|
-
* in the debugger terminal, so we split on the top-level commas Hermes inserted, unquote the plain
|
|
314
|
-
* string segments, and rejoin with spaces — leaving inspected objects/arrays untouched.
|
|
315
|
-
*
|
|
316
|
-
* This is best-effort: it only rewrites what parses cleanly as Hermes's join format. A segment it
|
|
317
|
-
* can't confidently classify is left exactly as received, so worst case a line is unchanged, never
|
|
318
|
-
* mangled.
|
|
319
|
-
*/
|
|
320
|
-
/**
|
|
321
328
|
* @description Cleans a Hermes-joined console line into space-separated, unquoted output.
|
|
322
329
|
* @param message The raw `nativeLoggingHook` message string.
|
|
323
330
|
* @returns The reformatted line, or the original if it doesn't look like a Hermes join.
|
|
@@ -380,9 +387,8 @@ function unquoteSegment(segment) {
|
|
|
380
387
|
//#endregion
|
|
381
388
|
//#region src/lib/banner.ts
|
|
382
389
|
/**
|
|
383
|
-
* Renders the debugger's startup banner: a rounded box
|
|
384
|
-
*
|
|
385
|
-
* on wide ones; when the terminal is too narrow for a box, it falls back to plain starred lines.
|
|
390
|
+
* Renders the debugger's startup banner: a pink rounded box sized to the terminal, capped on wide
|
|
391
|
+
* ones, falling back to plain starred lines when the terminal is too narrow for a box.
|
|
386
392
|
*/
|
|
387
393
|
/** Brand pink used for the banner frame and title. */
|
|
388
394
|
const PINK = "#ff5fbf";
|
|
@@ -450,7 +456,7 @@ function printFallback(title, lines) {
|
|
|
450
456
|
/** The usable terminal width: terminal-kit's when it's a real TTY, else stdout's, else a default. */
|
|
451
457
|
function terminalWidth() {
|
|
452
458
|
const fromKit = terminal.width;
|
|
453
|
-
if (
|
|
459
|
+
if (Number.isFinite(fromKit)) return fromKit;
|
|
454
460
|
const fromStdout = process.stdout.columns;
|
|
455
461
|
if (typeof fromStdout === "number" && fromStdout > 0) return fromStdout;
|
|
456
462
|
return 80;
|
|
@@ -494,9 +500,7 @@ const SYSTEM_COLORS = {
|
|
|
494
500
|
gray: "#9ca3af"
|
|
495
501
|
};
|
|
496
502
|
/**
|
|
497
|
-
* @description Prints a bold, glyph-prefixed banner line for a bridge lifecycle event
|
|
498
|
-
* the given hex colour. Uses terminal-kit's runtime `colorRgbHex`, which `@types/terminal-kit`
|
|
499
|
-
* doesn't declare, so the chain is reached through a narrow cast.
|
|
503
|
+
* @description Prints a bold, glyph-prefixed banner line for a bridge lifecycle event.
|
|
500
504
|
* @param color The banner colour, keyed into {@link SYSTEM_COLORS}.
|
|
501
505
|
* @param text The line to print (the glyph is prepended and a trailing newline added).
|
|
502
506
|
*/
|
|
@@ -595,6 +599,10 @@ function handleControllerMessage(ws, raw) {
|
|
|
595
599
|
}
|
|
596
600
|
if (message?.type === "plugin-push") pushPluginForController(ws, message);
|
|
597
601
|
}
|
|
602
|
+
/**
|
|
603
|
+
* @description Finds the machine's first external IPv4 address, for devices on the LAN to dial.
|
|
604
|
+
* @returns The address, or `undefined` if the machine has none.
|
|
605
|
+
*/
|
|
598
606
|
function getLocalAddress() {
|
|
599
607
|
const interfaces = os.networkInterfaces();
|
|
600
608
|
for (const ifaces of Object.values(interfaces)) {
|
|
@@ -605,6 +613,6 @@ function getLocalAddress() {
|
|
|
605
613
|
//#endregion
|
|
606
614
|
//#region src/index.ts
|
|
607
615
|
await loadHistory();
|
|
608
|
-
|
|
616
|
+
setupWebSocket();
|
|
609
617
|
//#endregion
|
|
610
618
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unbound-app/debugger",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "A REPL debugger for @unbound-app/client runtime instances.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Mario P.",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"build": "tsdown"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@unbound-app/debugger-protocol": "0.
|
|
27
|
+
"@unbound-app/debugger-protocol": "0.7.2",
|
|
28
28
|
"cleye": "^1.3.4",
|
|
29
29
|
"terminal-kit": "^3.1.2"
|
|
30
30
|
},
|