browser-debugger-cli 0.14.0 → 0.15.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.
Files changed (69) hide show
  1. package/.claude/skills/bdg/SKILL.md +1 -1
  2. package/dist/commands/cdp.js +1 -0
  3. package/dist/commands/cleanup.js +3 -0
  4. package/dist/commands/dom/eval.d.ts +2 -1
  5. package/dist/commands/dom/eval.js +6 -21
  6. package/dist/commands/dom/helpers/evalResult.d.ts +36 -0
  7. package/dist/commands/dom/helpers/evalResult.js +59 -0
  8. package/dist/commands/helpJson.d.ts +1 -1
  9. package/dist/commands/helpJson.js +3 -3
  10. package/dist/commands/helpTopic.js +10 -4
  11. package/dist/commands/network/har.js +18 -14
  12. package/dist/commands/optionBehaviors.js +8 -3
  13. package/dist/commands/shared/optionTypes.d.ts +1 -0
  14. package/dist/commands/shared/outputFile.d.ts +2 -1
  15. package/dist/commands/shared/outputFile.js +7 -4
  16. package/dist/commands/status.js +3 -1
  17. package/dist/commands/stop.js +2 -1
  18. package/dist/connection/launcher/flagsBuilder.d.ts +46 -0
  19. package/dist/connection/launcher/flagsBuilder.js +107 -23
  20. package/dist/connection/launcher.d.ts +1 -1
  21. package/dist/connection/launcher.js +1 -2
  22. package/dist/constants.d.ts +2 -4
  23. package/dist/constants.js +2 -4
  24. package/dist/daemon/launcher.d.ts +17 -3
  25. package/dist/daemon/launcher.js +37 -7
  26. package/dist/daemon/session/commandRegistry.js +2 -2
  27. package/dist/daemon.js +8107 -7962
  28. package/dist/errors/messages.d.ts +23 -0
  29. package/dist/errors/messages.js +86 -6
  30. package/dist/index.js +555 -166
  31. package/dist/ipc/client.d.ts +6 -1
  32. package/dist/ipc/client.js +11 -2
  33. package/dist/ipc/protocol/commands.d.ts +4 -0
  34. package/dist/ipc/transport/index.d.ts +6 -0
  35. package/dist/ipc/transport/index.js +16 -1
  36. package/dist/runtime/dom/elementInfo.d.ts +7 -0
  37. package/dist/runtime/dom/elementInfo.js +8 -1
  38. package/dist/runtime/dom/evalHelpers.d.ts +24 -4
  39. package/dist/runtime/dom/evalHelpers.js +40 -12
  40. package/dist/runtime/dom/frames.d.ts +2 -1
  41. package/dist/runtime/dom/frames.js +3 -1
  42. package/dist/runtime/page/emulation.js +6 -5
  43. package/dist/runtime/page/userAgent.d.ts +86 -2
  44. package/dist/runtime/page/userAgent.js +154 -33
  45. package/dist/session/paths.d.ts +38 -3
  46. package/dist/session/paths.js +154 -7
  47. package/dist/session/portClaims.d.ts +0 -8
  48. package/dist/session/portClaims.js +1 -22
  49. package/dist/session/sessionList.d.ts +5 -1
  50. package/dist/session/sessionList.js +5 -1
  51. package/dist/telemetry/har/builder.d.ts +12 -1
  52. package/dist/telemetry/har/builder.js +10 -2
  53. package/dist/telemetry/har/sanitize.d.ts +24 -0
  54. package/dist/telemetry/har/sanitize.js +138 -0
  55. package/dist/telemetry/har/sanitizeBody.d.ts +38 -0
  56. package/dist/telemetry/har/sanitizeBody.js +168 -0
  57. package/dist/ui/formatters/sessions.d.ts +3 -2
  58. package/dist/ui/formatters/sessions.js +10 -3
  59. package/dist/ui/messages/chrome.d.ts +14 -6
  60. package/dist/ui/messages/chrome.js +52 -12
  61. package/dist/ui/messages/networkMessages.d.ts +26 -0
  62. package/dist/ui/messages/networkMessages.js +21 -0
  63. package/dist/ui/messages/session.d.ts +8 -0
  64. package/dist/ui/messages/session.js +10 -0
  65. package/dist/utils/atomicFile.d.ts +2 -1
  66. package/dist/utils/atomicFile.js +5 -2
  67. package/dist/utils/directories.d.ts +41 -0
  68. package/dist/utils/directories.js +48 -0
  69. package/package.json +1 -1
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import type { DomFrame, PendingRequestInfo } from '../ipc/protocol/commands.js';
7
7
  import { type WaitCondition, type WaitSnapshot } from '../runtime/dom/waitCondition.js';
8
+ import { type UntrustedSessionDir } from '../session/paths.js';
8
9
  import type { DocumentRequestState, IndexSource } from '../types.js';
9
10
  /**
10
11
  * Generate "session already running" error message (commands carry
@@ -258,6 +259,13 @@ export declare function invalidSelectorFilterError(selector: string, filter: str
258
259
  * @param closest - Most similar existing command path, if any
259
260
  */
260
261
  export declare function unknownHelpTopicError(topic: string, closest?: string): ErrorWithSuggestion;
262
+ /**
263
+ * "Did you mean" for one or more close candidates, joined as a sentence.
264
+ *
265
+ * @param candidates - Close matches, e.g. ["form", "frames"]
266
+ * @returns e.g. "Did you mean: form or frames?" or "Did you mean: a, b or c?"
267
+ */
268
+ export declare function didYouMeanSuggestion(candidates: string[]): string;
261
269
  /**
262
270
  * Suggestion for a command-line usage error (missing argument, invalid value,
263
271
  * unknown option without a close match).
@@ -360,6 +368,21 @@ export declare function sessionDirIsFileError(dir: string): ErrorWithSuggestion;
360
368
  * @param reason - File-system error
361
369
  */
362
370
  export declare function sessionDirNotWritableError(dir: string, reason: string): ErrorWithSuggestion;
371
+ /**
372
+ * The session directory, or one above it, is not safe to use: another user
373
+ * could replace the daemon socket or plant files there.
374
+ *
375
+ * @param untrusted - Untrusted directory and why
376
+ */
377
+ export declare function untrustedSessionDirError(untrusted: UntrustedSessionDir): ErrorWithSuggestion;
378
+ /**
379
+ * The daemon log cannot be opened for writing (a symlink there is refused,
380
+ * not followed).
381
+ *
382
+ * @param logPath - Daemon log path
383
+ * @param code - File-system error code
384
+ */
385
+ export declare function daemonLogNotOpenedError(logPath: string, code: string): ErrorWithSuggestion;
363
386
  /**
364
387
  * The daemon socket path exceeds the OS limit for Unix sockets.
365
388
  *
@@ -3,6 +3,7 @@
3
3
  *
4
4
  * Centralized location for reusable error messages with consistent formatting.
5
5
  */
6
+ import * as os from 'os';
6
7
  import * as path from 'path';
7
8
  import { countedMatches, } from '../runtime/dom/waitCondition.js';
8
9
  import { getSessionBaseDir, getSessionName } from '../session/paths.js';
@@ -370,6 +371,17 @@ export function unknownHelpTopicError(topic, closest) {
370
371
  : `Run "bdg ${parent ? `${parent} ` : ''}--help" for commands`,
371
372
  };
372
373
  }
374
+ /**
375
+ * "Did you mean" for one or more close candidates, joined as a sentence.
376
+ *
377
+ * @param candidates - Close matches, e.g. ["form", "frames"]
378
+ * @returns e.g. "Did you mean: form or frames?" or "Did you mean: a, b or c?"
379
+ */
380
+ export function didYouMeanSuggestion(candidates) {
381
+ const last = candidates.at(-1) ?? '';
382
+ const rest = candidates.slice(0, -1);
383
+ return `Did you mean: ${rest.length > 0 ? `${rest.join(', ')} or ${last}` : last}?`;
384
+ }
373
385
  /**
374
386
  * Suggestion for a command-line usage error (missing argument, invalid value,
375
387
  * unknown option without a close match).
@@ -498,7 +510,7 @@ export function invalidSessionNameError(name, maxLength) {
498
510
  export function sessionNameSocketTooLongError(name, socketPath, max) {
499
511
  return {
500
512
  message: `Session name "${name}" makes the daemon socket path too long (${Buffer.byteLength(socketPath)} bytes, at most ${max}): ${socketPath}`,
501
- suggestion: 'Use a shorter session name, or a shorter BDG_SESSION_DIR (e.g. /tmp/bdg)',
513
+ suggestion: `Use a shorter session name, or a shorter BDG_SESSION_DIR (e.g. ${privateSessionDirExample()})`,
502
514
  };
503
515
  }
504
516
  /**
@@ -524,15 +536,36 @@ export function purgeRefusedError(dir, reason) {
524
536
  suggestion: `End the session first (${sessionCommand('bdg cleanup --force')}), then retry: ${sessionCommand('bdg cleanup --purge')}`,
525
537
  };
526
538
  }
527
- /** Fix for an unusable session directory */
528
- const SESSION_DIR_SUGGESTION = 'Set BDG_SESSION_DIR to a short, writable directory, e.g. BDG_SESSION_DIR=/tmp/bdg';
539
+ /**
540
+ * A short session directory only the user can use, for suggestions: in
541
+ * `$XDG_RUNTIME_DIR` (Linux, private to the user) when set, else a per-user
542
+ * name in the OS temp directory (per-user on macOS). Never the shared
543
+ * `/tmp/bdg`, which another user can create first.
544
+ *
545
+ * @returns Absolute directory path
546
+ */
547
+ function privateSessionDirExample() {
548
+ const runtimeDir = process.env['XDG_RUNTIME_DIR']?.trim();
549
+ if (runtimeDir)
550
+ return path.join(runtimeDir, 'bdg');
551
+ const uid = process.getuid?.();
552
+ return path.join(os.tmpdir(), uid === undefined ? 'bdg' : `bdg-${uid}`);
553
+ }
554
+ /**
555
+ * Fix for an unusable session directory.
556
+ *
557
+ * @returns Suggestion naming a private, short directory
558
+ */
559
+ function sessionDirSuggestion() {
560
+ return `Set BDG_SESSION_DIR to a short directory only you can write to, e.g. BDG_SESSION_DIR=${privateSessionDirExample()}`;
561
+ }
529
562
  /**
530
563
  * The session directory exists but is not a directory.
531
564
  *
532
565
  * @param dir - Session directory
533
566
  */
534
567
  export function sessionDirIsFileError(dir) {
535
- return { message: `Session directory ${dir} is a file`, suggestion: SESSION_DIR_SUGGESTION };
568
+ return { message: `Session directory ${dir} is a file`, suggestion: sessionDirSuggestion() };
536
569
  }
537
570
  /**
538
571
  * The session directory cannot be created or written.
@@ -543,7 +576,54 @@ export function sessionDirIsFileError(dir) {
543
576
  export function sessionDirNotWritableError(dir, reason) {
544
577
  return {
545
578
  message: `Session directory ${dir} is not writable (${reason})`,
546
- suggestion: SESSION_DIR_SUGGESTION,
579
+ suggestion: sessionDirSuggestion(),
580
+ };
581
+ }
582
+ /**
583
+ * The session directory, or one above it, is not safe to use: another user
584
+ * could replace the daemon socket or plant files there.
585
+ *
586
+ * @param untrusted - Untrusted directory and why
587
+ */
588
+ export function untrustedSessionDirError(untrusted) {
589
+ return {
590
+ message: `Session directory ${untrusted.dir} is not safe to use: ${untrusted.reason}`,
591
+ suggestion: untrustedSessionDirSuggestion(untrusted),
592
+ };
593
+ }
594
+ /**
595
+ * Fix for an untrusted session directory: remove a symlink, use a
596
+ * subdirectory of a shared sticky directory (`BDG_SESSION_DIR=/tmp`), chmod
597
+ * a directory bdg owns (`~/.bdg`, `sessions/`, `sessions/<name>`), else
598
+ * choose another `BDG_SESSION_DIR`.
599
+ *
600
+ * @param untrusted - Untrusted directory and why
601
+ * @returns Suggestion
602
+ */
603
+ function untrustedSessionDirSuggestion(untrusted) {
604
+ const { dir, kind, bdgOwned } = untrusted;
605
+ const example = `BDG_SESSION_DIR=${privateSessionDirExample()}`;
606
+ if (kind === 'symlink') {
607
+ return `Remove the link (rm ${dir}) or point BDG_SESSION_DIR at the real directory`;
608
+ }
609
+ if (kind === 'shared') {
610
+ return `${dir} is shared by all users; use a subdirectory only you can write to, e.g. ${example}`;
611
+ }
612
+ if (bdgOwned)
613
+ return `Run chmod 700 ${dir} (or remove it if it is not yours), then retry`;
614
+ return `Use a directory you own that others cannot write to, e.g. ${example} (or chmod 700 ${dir} if it is yours)`;
615
+ }
616
+ /**
617
+ * The daemon log cannot be opened for writing (a symlink there is refused,
618
+ * not followed).
619
+ *
620
+ * @param logPath - Daemon log path
621
+ * @param code - File-system error code
622
+ */
623
+ export function daemonLogNotOpenedError(logPath, code) {
624
+ return {
625
+ message: `Cannot open the daemon log ${logPath} (${code === 'ELOOP' ? 'it is a symbolic link' : code})`,
626
+ suggestion: `Remove ${logPath} if you did not create it, then retry`,
547
627
  };
548
628
  }
549
629
  /**
@@ -555,7 +635,7 @@ export function sessionDirNotWritableError(dir, reason) {
555
635
  export function socketPathTooLongError(socketPath, max) {
556
636
  return {
557
637
  message: `Session directory path is too long for the daemon socket (${Buffer.byteLength(socketPath)} bytes, at most ${max}): ${socketPath}`,
558
- suggestion: SESSION_DIR_SUGGESTION,
638
+ suggestion: sessionDirSuggestion(),
559
639
  };
560
640
  }
561
641
  /**