browser-debugger-cli 0.8.0 → 0.9.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 (251) hide show
  1. package/README.md +4 -1
  2. package/dist/cdp/schema.d.ts +4 -1
  3. package/dist/cdp/schema.js +48 -7
  4. package/dist/commands/cdp.js +3 -2
  5. package/dist/commands/cleanup.d.ts +11 -0
  6. package/dist/commands/cleanup.js +161 -57
  7. package/dist/commands/console.d.ts +20 -1
  8. package/dist/commands/console.js +57 -17
  9. package/dist/commands/details.js +3 -2
  10. package/dist/commands/dom/DomElementResolver.d.ts +10 -3
  11. package/dist/commands/dom/DomElementResolver.js +35 -17
  12. package/dist/commands/dom/a11y.d.ts +10 -0
  13. package/dist/commands/dom/a11y.js +27 -5
  14. package/dist/commands/dom/eval.d.ts +3 -1
  15. package/dist/commands/dom/eval.js +29 -4
  16. package/dist/commands/dom/form.js +16 -62
  17. package/dist/commands/dom/formInteraction.js +152 -113
  18. package/dist/commands/dom/formSummary.d.ts +49 -0
  19. package/dist/commands/dom/formSummary.js +180 -0
  20. package/dist/commands/dom/frames.d.ts +2 -1
  21. package/dist/commands/dom/frames.js +17 -2
  22. package/dist/commands/dom/get.d.ts +6 -5
  23. package/dist/commands/dom/get.js +92 -82
  24. package/dist/commands/dom/helpers/index.d.ts +1 -1
  25. package/dist/commands/dom/helpers/index.js +1 -1
  26. package/dist/commands/dom/helpers/query.d.ts +44 -17
  27. package/dist/commands/dom/helpers/query.js +244 -97
  28. package/dist/commands/dom/helpers/runElementCommand.d.ts +10 -2
  29. package/dist/commands/dom/helpers/runElementCommand.js +97 -30
  30. package/dist/commands/dom/helpers/screenshot.d.ts +4 -1
  31. package/dist/commands/dom/helpers/screenshot.js +164 -49
  32. package/dist/commands/dom/index.d.ts +3 -1
  33. package/dist/commands/dom/index.js +16 -6
  34. package/dist/commands/dom/layout.d.ts +14 -0
  35. package/dist/commands/dom/layout.js +54 -0
  36. package/dist/commands/dom/listeners.d.ts +5 -1
  37. package/dist/commands/dom/listeners.js +13 -3
  38. package/dist/commands/dom/query.js +2 -3
  39. package/dist/commands/dom/screenshot.d.ts +12 -2
  40. package/dist/commands/dom/screenshot.js +27 -3
  41. package/dist/commands/dom/semanticUtils.d.ts +6 -13
  42. package/dist/commands/dom/semanticUtils.js +15 -19
  43. package/dist/commands/dom/wait.d.ts +13 -0
  44. package/dist/commands/dom/wait.js +83 -0
  45. package/dist/commands/helpJson.js +2 -2
  46. package/dist/commands/network/list.js +4 -11
  47. package/dist/commands/optionBehaviors.js +112 -21
  48. package/dist/commands/page.d.ts +2 -1
  49. package/dist/commands/page.js +41 -5
  50. package/dist/commands/peek.js +4 -11
  51. package/dist/commands/sessions.d.ts +8 -0
  52. package/dist/commands/sessions.js +19 -0
  53. package/dist/commands/shared/CommandRunner.js +4 -4
  54. package/dist/commands/shared/dataFetcher.js +2 -2
  55. package/dist/commands/shared/followMode.d.ts +21 -1
  56. package/dist/commands/shared/followMode.js +29 -2
  57. package/dist/commands/shared/handleValidationError.d.ts +2 -2
  58. package/dist/commands/shared/handleValidationError.js +12 -3
  59. package/dist/commands/shared/optionTypes.d.ts +40 -5
  60. package/dist/commands/shared/startHelpers.js +12 -3
  61. package/dist/commands/shared/validation.d.ts +3 -2
  62. package/dist/commands/shared/validation.js +4 -3
  63. package/dist/commands/start.d.ts +63 -0
  64. package/dist/commands/start.js +115 -15
  65. package/dist/commands/status.js +29 -7
  66. package/dist/commands/stop.js +7 -6
  67. package/dist/commands/tail.js +4 -11
  68. package/dist/commands/types.d.ts +2 -0
  69. package/dist/commands.js +2 -0
  70. package/dist/connection/chromeIdentity.d.ts +65 -0
  71. package/dist/connection/chromeIdentity.js +143 -0
  72. package/dist/connection/launcher/profilePreferences.d.ts +47 -0
  73. package/dist/connection/launcher/profilePreferences.js +151 -0
  74. package/dist/connection/launcher.d.ts +21 -2
  75. package/dist/connection/launcher.js +42 -16
  76. package/dist/connection/portReservation.d.ts +14 -4
  77. package/dist/connection/portReservation.js +21 -6
  78. package/dist/connection/startupExit.d.ts +8 -0
  79. package/dist/connection/startupExit.js +15 -6
  80. package/dist/constants.d.ts +6 -2
  81. package/dist/constants.js +9 -2
  82. package/dist/daemon/SessionController.js +23 -7
  83. package/dist/daemon/errors.d.ts +1 -1
  84. package/dist/daemon/errors.js +1 -1
  85. package/dist/daemon/launcher.d.ts +2 -1
  86. package/dist/daemon/launcher.js +5 -6
  87. package/dist/daemon/server/SocketServer.js +1 -2
  88. package/dist/daemon/session/Session.d.ts +13 -0
  89. package/dist/daemon/session/Session.js +57 -8
  90. package/dist/daemon/session/chromeConnection.d.ts +9 -0
  91. package/dist/daemon/session/chromeConnection.js +45 -8
  92. package/dist/daemon/session/commandRegistry.js +52 -62
  93. package/dist/daemon/session/interactions.d.ts +35 -9
  94. package/dist/daemon/session/interactions.js +36 -9
  95. package/dist/daemon/session/triggeredRequests.d.ts +67 -0
  96. package/dist/daemon/session/triggeredRequests.js +157 -0
  97. package/dist/daemon/session/types.d.ts +5 -1
  98. package/dist/daemon.js +5393 -1600
  99. package/dist/errors/messages.d.ts +387 -24
  100. package/dist/errors/messages.js +761 -67
  101. package/dist/index.js +3976 -1558
  102. package/dist/ipc/client.d.ts +12 -1
  103. package/dist/ipc/client.js +22 -3
  104. package/dist/ipc/protocol/commands.d.ts +89 -4
  105. package/dist/ipc/protocol/commands.js +2 -0
  106. package/dist/ipc/protocol/domTypes.d.ts +258 -7
  107. package/dist/ipc/session/lifecycle.d.ts +8 -1
  108. package/dist/ipc/session/queries.d.ts +5 -1
  109. package/dist/ipc/session/types.d.ts +5 -0
  110. package/dist/ipc/transport/index.d.ts +2 -1
  111. package/dist/ipc/transport/index.js +2 -2
  112. package/dist/runtime/dom/actionEffects.d.ts +106 -0
  113. package/dist/runtime/dom/actionEffects.js +256 -0
  114. package/dist/runtime/dom/actionEffectsScripts.d.ts +52 -0
  115. package/dist/runtime/dom/actionEffectsScripts.js +234 -0
  116. package/dist/runtime/dom/elementGeometry.d.ts +170 -0
  117. package/dist/runtime/dom/elementGeometry.js +553 -0
  118. package/dist/runtime/dom/elementInfo.d.ts +77 -0
  119. package/dist/runtime/dom/elementInfo.js +191 -0
  120. package/dist/runtime/dom/evalHelpers.d.ts +51 -6
  121. package/dist/runtime/dom/evalHelpers.js +136 -26
  122. package/dist/runtime/dom/eventListeners.d.ts +2 -1
  123. package/dist/runtime/dom/eventListeners.js +174 -47
  124. package/dist/runtime/dom/formDiscovery.d.ts +1 -1
  125. package/dist/runtime/dom/formDiscovery.js +116 -16
  126. package/dist/runtime/dom/formFillHelpers/fill.d.ts +10 -0
  127. package/dist/runtime/dom/formFillHelpers/fill.js +125 -10
  128. package/dist/runtime/dom/formFillHelpers/index.d.ts +2 -2
  129. package/dist/runtime/dom/formFillHelpers/index.js +2 -2
  130. package/dist/runtime/dom/formFillHelpers/pressKey.js +14 -3
  131. package/dist/runtime/dom/formFillHelpers/scroll.d.ts +3 -0
  132. package/dist/runtime/dom/formFillHelpers/scroll.js +60 -18
  133. package/dist/runtime/dom/formFillHelpers/shared.d.ts +17 -0
  134. package/dist/runtime/dom/formFillHelpers/shared.js +25 -1
  135. package/dist/runtime/dom/formFillHelpers/stability.d.ts +20 -6
  136. package/dist/runtime/dom/formFillHelpers/stability.js +50 -19
  137. package/dist/runtime/dom/formSubmitHelpers.d.ts +3 -0
  138. package/dist/runtime/dom/formSubmitHelpers.js +89 -15
  139. package/dist/runtime/dom/frameLayout.d.ts +60 -0
  140. package/dist/runtime/dom/frameLayout.js +140 -0
  141. package/dist/runtime/dom/frameOrigin.d.ts +50 -0
  142. package/dist/runtime/dom/frameOrigin.js +62 -0
  143. package/dist/runtime/dom/frameScopedConnection.d.ts +92 -0
  144. package/dist/runtime/dom/frameScopedConnection.js +252 -0
  145. package/dist/runtime/dom/frameSelection.d.ts +1 -1
  146. package/dist/runtime/dom/frameSelection.js +2 -2
  147. package/dist/runtime/dom/frames.d.ts +25 -2
  148. package/dist/runtime/dom/frames.js +202 -63
  149. package/dist/runtime/dom/layout.d.ts +67 -0
  150. package/dist/runtime/dom/layout.js +333 -0
  151. package/dist/runtime/dom/listenerPageScripts.d.ts +66 -0
  152. package/dist/runtime/dom/listenerPageScripts.js +279 -0
  153. package/dist/runtime/dom/listenerSummary.d.ts +132 -11
  154. package/dist/runtime/dom/listenerSummary.js +344 -22
  155. package/dist/runtime/dom/pageActivity.d.ts +41 -0
  156. package/dist/runtime/dom/pageActivity.js +123 -0
  157. package/dist/runtime/dom/reactEventHelpers.d.ts +58 -2
  158. package/dist/runtime/dom/reactEventHelpers.js +212 -41
  159. package/dist/runtime/dom/targetNode.d.ts +80 -27
  160. package/dist/runtime/dom/targetNode.js +249 -33
  161. package/dist/runtime/dom/wait.d.ts +25 -0
  162. package/dist/runtime/dom/wait.js +199 -0
  163. package/dist/runtime/dom/waitCondition.d.ts +71 -0
  164. package/dist/runtime/dom/waitCondition.js +75 -0
  165. package/dist/runtime/page/emulation.d.ts +51 -0
  166. package/dist/runtime/page/emulation.js +80 -0
  167. package/dist/runtime/page/loadingState.d.ts +36 -0
  168. package/dist/runtime/page/loadingState.js +86 -0
  169. package/dist/runtime/page/navigation.d.ts +46 -2
  170. package/dist/runtime/page/navigation.js +69 -33
  171. package/dist/session/QueryCacheManager.d.ts +11 -1
  172. package/dist/session/QueryCacheManager.js +25 -3
  173. package/dist/session/chromeOwners.d.ts +34 -0
  174. package/dist/session/chromeOwners.js +51 -0
  175. package/dist/session/cleanup/staleSession.d.ts +11 -1
  176. package/dist/session/cleanup/staleSession.js +17 -6
  177. package/dist/session/cleanup/userCommands.js +2 -4
  178. package/dist/session/metadata.d.ts +5 -1
  179. package/dist/session/metadata.js +2 -1
  180. package/dist/session/paths.d.ts +77 -3
  181. package/dist/session/paths.js +111 -5
  182. package/dist/session/port.d.ts +31 -7
  183. package/dist/session/port.js +50 -43
  184. package/dist/session/portClaims.d.ts +66 -0
  185. package/dist/session/portClaims.js +284 -0
  186. package/dist/session/sessionList.d.ts +58 -0
  187. package/dist/session/sessionList.js +199 -0
  188. package/dist/session/sessionName.d.ts +46 -0
  189. package/dist/session/sessionName.js +97 -0
  190. package/dist/telemetry/a11y.d.ts +8 -3
  191. package/dist/telemetry/a11y.js +92 -28
  192. package/dist/telemetry/requestKinds.d.ts +32 -0
  193. package/dist/telemetry/requestKinds.js +61 -0
  194. package/dist/telemetry/requestState.d.ts +31 -0
  195. package/dist/telemetry/requestState.js +38 -0
  196. package/dist/types.d.ts +80 -3
  197. package/dist/ui/formatters/a11y.js +3 -0
  198. package/dist/ui/formatters/console/chronological.d.ts +8 -0
  199. package/dist/ui/formatters/console/chronological.js +17 -4
  200. package/dist/ui/formatters/console/json.js +3 -4
  201. package/dist/ui/formatters/console/shared.d.ts +12 -0
  202. package/dist/ui/formatters/console.d.ts +2 -2
  203. package/dist/ui/formatters/console.js +1 -1
  204. package/dist/ui/formatters/details.js +2 -1
  205. package/dist/ui/formatters/dom.d.ts +26 -14
  206. package/dist/ui/formatters/dom.js +65 -52
  207. package/dist/ui/formatters/form.js +29 -18
  208. package/dist/ui/formatters/layout.d.ts +31 -0
  209. package/dist/ui/formatters/layout.js +53 -0
  210. package/dist/ui/formatters/listeners.d.ts +3 -2
  211. package/dist/ui/formatters/listeners.js +73 -9
  212. package/dist/ui/formatters/networkHeaders.js +13 -0
  213. package/dist/ui/formatters/preview.js +2 -1
  214. package/dist/ui/formatters/requestStatus.d.ts +1 -17
  215. package/dist/ui/formatters/requestStatus.js +2 -30
  216. package/dist/ui/formatters/sessions.d.ts +12 -0
  217. package/dist/ui/formatters/sessions.js +40 -0
  218. package/dist/ui/formatters/status.d.ts +21 -2
  219. package/dist/ui/formatters/status.js +47 -10
  220. package/dist/ui/formatters/triggeredRequests.d.ts +36 -0
  221. package/dist/ui/formatters/triggeredRequests.js +65 -0
  222. package/dist/ui/formatting.d.ts +10 -0
  223. package/dist/ui/formatting.js +28 -36
  224. package/dist/ui/messages/chrome.d.ts +9 -0
  225. package/dist/ui/messages/chrome.js +17 -5
  226. package/dist/ui/messages/commands.d.ts +388 -14
  227. package/dist/ui/messages/commands.js +664 -21
  228. package/dist/ui/messages/consoleMessages.d.ts +10 -0
  229. package/dist/ui/messages/consoleMessages.js +17 -0
  230. package/dist/ui/messages/hints.js +2 -1
  231. package/dist/ui/messages/preview.js +5 -4
  232. package/dist/ui/messages/session.d.ts +16 -21
  233. package/dist/ui/messages/session.js +28 -26
  234. package/dist/ui/messages/sessionCommand.d.ts +43 -0
  235. package/dist/ui/messages/sessionCommand.js +52 -0
  236. package/dist/utils/async.d.ts +8 -0
  237. package/dist/utils/async.js +19 -0
  238. package/dist/utils/http.d.ts +22 -1
  239. package/dist/utils/http.js +28 -9
  240. package/dist/utils/selectorFilters.d.ts +36 -8
  241. package/dist/utils/selectorFilters.js +267 -53
  242. package/dist/utils/shellDetection.d.ts +8 -2
  243. package/dist/utils/shellDetection.js +120 -33
  244. package/dist/utils/suggestions.d.ts +26 -0
  245. package/dist/utils/suggestions.js +73 -0
  246. package/dist/utils/taskMappings.js +10 -0
  247. package/dist/utils/url.d.ts +12 -2
  248. package/dist/utils/url.js +69 -7
  249. package/package.json +1 -1
  250. package/dist/ui/formatters/sessionFormatters.d.ts +0 -58
  251. package/dist/ui/formatters/sessionFormatters.js +0 -121
@@ -31,4 +31,77 @@ export function formatSuggestions(suggestions, options = {}) {
31
31
  export function getSuggestion(input, candidates, options = {}) {
32
32
  return formatSuggestions(findSimilar(input, candidates, options), options);
33
33
  }
34
+ /** Most similar ids or classes suggested for a selector that matched nothing */
35
+ const MAX_SIMILAR_NAMES = 3;
36
+ /**
37
+ * Length of the common start of two strings.
38
+ *
39
+ * @param a - First string
40
+ * @param b - Second string
41
+ * @returns Characters they share from the start
42
+ */
43
+ function commonPrefixLength(a, b) {
44
+ let length = 0;
45
+ while (length < a.length && length < b.length && a[length] === b[length])
46
+ length++;
47
+ return length;
48
+ }
49
+ /**
50
+ * Length of the common end of two strings.
51
+ *
52
+ * @param a - First string
53
+ * @param b - Second string
54
+ * @returns Characters they share from the end
55
+ */
56
+ function commonSuffixLength(a, b) {
57
+ let length = 0;
58
+ while (length < a.length &&
59
+ length < b.length &&
60
+ a[a.length - 1 - length] === b[b.length - 1 - length]) {
61
+ length++;
62
+ }
63
+ return length;
64
+ }
65
+ /**
66
+ * Names (ids or classes) similar to one that matched nothing, best first, at
67
+ * most three: near-typos first (Levenshtein distance up to a fifth of the
68
+ * length, at least 2), then names sharing a long end, then names sharing a
69
+ * long start (at least a third of the name, at least 4 characters). The end
70
+ * ranks before the start because ids tend to name an action before the item
71
+ * (`add-to-cart-backpack` becomes `remove-backpack` once clicked).
72
+ *
73
+ * @param name - Id or class that matched nothing
74
+ * @param candidates - Ids or classes on the page
75
+ * @returns Up to three similar names
76
+ */
77
+ export function findSimilarNames(name, candidates) {
78
+ const others = [...new Set(candidates)].filter((candidate) => candidate !== name);
79
+ const maxDistance = Math.max(2, Math.floor(name.length / 5));
80
+ const minAffix = Math.max(4, Math.ceil(name.length / 3));
81
+ const typos = findMatches(name, others, maxDistance, false).map((match) => match.value);
82
+ const byAffix = (length) => others
83
+ .map((candidate) => ({ candidate, length: length(candidate) }))
84
+ .filter((entry) => entry.length >= minAffix)
85
+ .sort((a, b) => b.length - a.length)
86
+ .map((entry) => entry.candidate);
87
+ const ranked = [
88
+ ...typos,
89
+ ...byAffix((candidate) => commonSuffixLength(name, candidate)),
90
+ ...byAffix((candidate) => commonPrefixLength(name, candidate)),
91
+ ];
92
+ return [...new Set(ranked)].slice(0, MAX_SIMILAR_NAMES);
93
+ }
94
+ /**
95
+ * Whether a selector is a single id or class (the kind "did you mean" can
96
+ * suggest for).
97
+ *
98
+ * @param selector - CSS selector
99
+ * @returns The id or class, or null for any other selector
100
+ */
101
+ export function parseSingleNameSelector(selector) {
102
+ const match = /^([#.])(-?[_a-zA-Z][\w-]*)$/.exec(selector.trim());
103
+ if (!match)
104
+ return null;
105
+ return { kind: match[1] === '#' ? 'id' : 'class', name: match[2] };
106
+ }
34
107
  //# sourceMappingURL=suggestions.js.map
@@ -35,6 +35,11 @@ export const TASK_MAPPINGS = {
35
35
  description: 'Fill form input field by selector',
36
36
  cdpAlternative: 'Runtime.evaluate with value assignment',
37
37
  },
38
+ wait_for_element: {
39
+ commands: ['dom wait'],
40
+ description: 'Wait until an element appears, becomes visible, contains a text or is gone (or the page loads)',
41
+ cdpAlternative: 'Runtime.evaluate polling with querySelector (awaitPromise)',
42
+ },
38
43
  click_element: {
39
44
  commands: ['dom click'],
40
45
  description: 'Click element by selector',
@@ -55,6 +60,11 @@ export const TASK_MAPPINGS = {
55
60
  description: 'List event listeners for an element, incl. delegated ones on ancestors/document/window',
56
61
  cdpAlternative: 'DOMDebugger.getEventListeners on the element and each ancestor',
57
62
  },
63
+ element_layout: {
64
+ commands: ['dom layout'],
65
+ description: 'Where elements are (page/viewport coordinates, size), whether they are in view, hidden or covered',
66
+ cdpAlternative: 'Runtime.evaluate with getBoundingClientRect, getComputedStyle and elementFromPoint',
67
+ },
58
68
  accessibility_tree: {
59
69
  commands: ['dom a11y'],
60
70
  description: 'Get accessibility tree for page or element',
@@ -68,11 +68,21 @@ export declare function validateUrl(url: string): ValidationResult;
68
68
  * ```
69
69
  */
70
70
  export declare function safeParseUrl(input: string): URL | null;
71
+ /**
72
+ * The HTTP DevTools endpoint a `--chrome-ws-url` value names instead of a
73
+ * WebSocket URL: a port (`9222`), `host:port` (nothing after it), or an
74
+ * `http(s)://` URL of the endpoint (any path is ignored).
75
+ *
76
+ * @param value - Option value
77
+ * @returns Endpoint origin, e.g. `http://127.0.0.1:9222`, or null for anything else
78
+ */
79
+ export declare function devToolsHttpEndpoint(value: string): string | null;
71
80
  /**
72
81
  * Validate a `--chrome-ws-url` value.
73
82
  *
74
- * Accepted schemes: `ws://` and `wss://`. Rejects other schemes, malformed
75
- * URLs, and empty input so users hear about the problem at the CLI boundary
83
+ * Accepted: `ws://` and `wss://` DevTools URLs, or the HTTP endpoint they come
84
+ * from ({@link devToolsHttpEndpoint}). Rejects other schemes, malformed URLs,
85
+ * and empty input so users hear about the problem at the CLI boundary
76
86
  * instead of after a daemon round-trip.
77
87
  *
78
88
  * @param url - ws URL to validate
package/dist/utils/url.js CHANGED
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * URL normalization, validation, and parsing utilities.
3
3
  */
4
+ import { sessionCommand } from '../ui/messages/sessionCommand.js';
4
5
  import { invalid, valid } from './validation.js';
5
6
  /**
6
7
  * Dangerous URL protocols that must be explicitly blocked.
@@ -119,7 +120,7 @@ export function validateUrl(url) {
119
120
  const normalized = normalizeUrl(url);
120
121
  const urlLower = url.toLowerCase();
121
122
  if (urlLower.startsWith('javascript:')) {
122
- return invalid(`Cannot start a session on a javascript: URL`, `Open a page first, then run the script: bdg about:blank && bdg dom eval '...'`);
123
+ return invalid(`Cannot start a session on a javascript: URL`, `Open a page first, then run the script: ${sessionCommand('bdg about:blank')} && ${sessionCommand("bdg dom eval '...'")}`);
123
124
  }
124
125
  if (urlLower.startsWith('vbscript:')) {
125
126
  return invalid(`Dangerous protocol: 'vbscript:' is not allowed`, 'Use http://, https://, or other safe protocols');
@@ -181,11 +182,67 @@ export function safeParseUrl(input) {
181
182
  }
182
183
  }
183
184
  }
185
+ /**
186
+ * The HTTP DevTools endpoint a `--chrome-ws-url` value names instead of a
187
+ * WebSocket URL: a port (`9222`), `host:port` (nothing after it), or an
188
+ * `http(s)://` URL of the endpoint (any path is ignored).
189
+ *
190
+ * @param value - Option value
191
+ * @returns Endpoint origin, e.g. `http://127.0.0.1:9222`, or null for anything else
192
+ */
193
+ export function devToolsHttpEndpoint(value) {
194
+ const trimmed = value.trim();
195
+ if (/^\d{1,5}$/.test(trimmed)) {
196
+ return isValidPort(Number(trimmed)) ? `http://127.0.0.1:${trimmed}` : null;
197
+ }
198
+ const candidate = /^https?:\/\//i.test(trimmed)
199
+ ? trimmed
200
+ : /^[^/\s]+:\d{1,5}\/?$/.test(trimmed)
201
+ ? `http://${trimmed}`
202
+ : null;
203
+ if (candidate === null)
204
+ return null;
205
+ try {
206
+ const url = new URL(candidate);
207
+ return url.port === '' || isValidPort(Number(url.port)) ? url.origin : null;
208
+ }
209
+ catch {
210
+ return null;
211
+ }
212
+ }
213
+ /**
214
+ * Whether a number is a usable TCP port (1-65535).
215
+ *
216
+ * @param port - Port number
217
+ * @returns True if in range
218
+ */
219
+ function isValidPort(port) {
220
+ return Number.isInteger(port) && port >= 1 && port <= 65535;
221
+ }
222
+ /** A `--chrome-ws-url` value shaped like a port or `host:port` (port possibly missing) */
223
+ const PORT_SHAPED_VALUE = /^(?:[^/\s]+:)?(\d*)\/?$/;
224
+ /**
225
+ * Why a port-shaped `--chrome-ws-url` value (`99999`, `0`, `localhost:`) has
226
+ * no usable port.
227
+ *
228
+ * @param value - Trimmed option value that is not a valid endpoint
229
+ * @returns Error and suggestion, or null when the value is not port-shaped
230
+ */
231
+ function portShapedValueError(value) {
232
+ const match = PORT_SHAPED_VALUE.exec(value);
233
+ if (!match || /^[a-z][a-z0-9+.-]*:\/\//i.test(value))
234
+ return null;
235
+ const digits = match[1] ?? '';
236
+ return invalid(digits === ''
237
+ ? `--chrome-ws-url is missing the port: '${value}'`
238
+ : `--chrome-ws-url port ${digits} is out of range (1-65535)`, 'Expected: the DevTools port (9222), host:port, or ws://host:port/devtools/browser/<uuid>');
239
+ }
184
240
  /**
185
241
  * Validate a `--chrome-ws-url` value.
186
242
  *
187
- * Accepted schemes: `ws://` and `wss://`. Rejects other schemes, malformed
188
- * URLs, and empty input so users hear about the problem at the CLI boundary
243
+ * Accepted: `ws://` and `wss://` DevTools URLs, or the HTTP endpoint they come
244
+ * from ({@link devToolsHttpEndpoint}). Rejects other schemes, malformed URLs,
245
+ * and empty input so users hear about the problem at the CLI boundary
189
246
  * instead of after a daemon round-trip.
190
247
  *
191
248
  * @param url - ws URL to validate
@@ -194,20 +251,25 @@ export function safeParseUrl(input) {
194
251
  export function validateChromeWsUrl(url) {
195
252
  const trimmed = url.trim();
196
253
  if (!trimmed) {
197
- return invalid('--chrome-ws-url cannot be empty', 'Expected: ws://host:port/devtools/browser/<uuid>');
254
+ return invalid('--chrome-ws-url cannot be empty', 'Expected: the DevTools port (9222), host:port, or ws://host:port/devtools/browser/<uuid>');
198
255
  }
256
+ if (devToolsHttpEndpoint(trimmed) !== null)
257
+ return valid();
258
+ const portError = portShapedValueError(trimmed);
259
+ if (portError)
260
+ return portError;
199
261
  let parsed;
200
262
  try {
201
263
  parsed = new URL(trimmed);
202
264
  }
203
265
  catch {
204
- return invalid(`--chrome-ws-url is not a valid URL: '${url}'`, 'Expected: ws://host:port/devtools/browser/<uuid>');
266
+ return invalid(`--chrome-ws-url is not a valid URL: '${url}'`, 'Expected: the DevTools port (9222), host:port, or ws://host:port/devtools/browser/<uuid>');
205
267
  }
206
268
  if (parsed.protocol !== 'ws:' && parsed.protocol !== 'wss:') {
207
- return invalid(`--chrome-ws-url must use ws:// or wss://, got '${parsed.protocol}'`, `Find it with: curl -s http://${parsed.host || '127.0.0.1:9222'}/json/version | jq -r .webSocketDebuggerUrl`);
269
+ return invalid(`--chrome-ws-url must use ws:// or wss://, got '${parsed.protocol}'`, `Give the DevTools port instead, e.g. --chrome-ws-url ${parsed.hostname || '127.0.0.1'}:9222`);
208
270
  }
209
271
  if (!parsed.hostname) {
210
- return invalid(`--chrome-ws-url is missing a hostname: '${url}'`, 'Expected: ws://host:port/devtools/browser/<uuid>');
272
+ return invalid(`--chrome-ws-url is missing a hostname: '${url}'`, 'Expected: the DevTools port (9222), host:port, or ws://host:port/devtools/browser/<uuid>');
211
273
  }
212
274
  if (!/^\/devtools\/(browser|page)\/[^/]+$/.test(parsed.pathname)) {
213
275
  return invalid(`--chrome-ws-url must point to /devtools/browser/<id> or /devtools/page/<id>, got '${parsed.pathname}'`, `Find it with: curl -s http://${parsed.host}/json/version | jq -r .webSocketDebuggerUrl`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-debugger-cli",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "DevTools telemetry in your terminal. For humans and agents. Direct WebSocket to Chrome's debugging port.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,58 +0,0 @@
1
- /**
2
- * Session-related formatting helpers for landing page sections.
3
- *
4
- * Provides well-structured, TSDoc'd helpers for building each section
5
- * of the landing page, organized by priority (high-level commands first).
6
- */
7
- /**
8
- * Builds the common tasks section showing task-to-command mappings.
9
- *
10
- * Provides agents with clear intent-to-command examples.
11
- *
12
- * @returns Formatted common tasks section
13
- */
14
- export declare function buildCommonTasksSection(): string;
15
- /**
16
- * Builds the domain commands section with expanded command coverage.
17
- *
18
- * Shows all 12+ high-level commands organized by domain (DOM, Network, Console).
19
- * Previously showed only 2 commands, now provides comprehensive coverage.
20
- *
21
- * @returns Formatted domain commands section
22
- */
23
- export declare function buildDomainCommandsSection(): string;
24
- /**
25
- * Builds the live monitoring section.
26
- *
27
- * Shows commands for real-time data inspection during active sessions.
28
- *
29
- * @returns Formatted live monitoring section
30
- */
31
- export declare function buildLiveMonitoringSection(): string;
32
- /**
33
- * Builds the session management section.
34
- *
35
- * Shows commands for controlling the daemon and session lifecycle.
36
- *
37
- * @returns Formatted session management section
38
- */
39
- export declare function buildSessionManagementSection(): string;
40
- /**
41
- * Builds the CDP access section positioned as advanced fallback.
42
- *
43
- * Provides raw CDP protocol access for advanced use cases not covered
44
- * by high-level commands. Intentionally positioned after domain commands
45
- * to guide agents toward wrapper commands first.
46
- *
47
- * @returns Formatted CDP section
48
- */
49
- export declare function buildCdpSection(): string;
50
- /**
51
- * Builds the discovery section for AI agents.
52
- *
53
- * Points agents to machine-readable schemas and documentation resources.
54
- *
55
- * @returns Formatted discovery section
56
- */
57
- export declare function buildDiscoverySection(): string;
58
- //# sourceMappingURL=sessionFormatters.d.ts.map
@@ -1,121 +0,0 @@
1
- /**
2
- * Session-related formatting helpers for landing page sections.
3
- *
4
- * Provides well-structured, TSDoc'd helpers for building each section
5
- * of the landing page, organized by priority (high-level commands first).
6
- */
7
- import { getProtocolCounts } from '../../cdp/schema.js';
8
- import { section } from '../formatting.js';
9
- /**
10
- * Builds the common tasks section showing task-to-command mappings.
11
- *
12
- * Provides agents with clear intent-to-command examples.
13
- *
14
- * @returns Formatted common tasks section
15
- */
16
- export function buildCommonTasksSection() {
17
- return section('Common Tasks:', [
18
- 'Screenshot bdg dom screenshot output.png',
19
- 'Fill forms bdg dom fill "#email" "test@test.com"',
20
- 'Click button bdg dom click "button.submit"',
21
- 'Press Enter bdg dom pressKey "input" Enter',
22
- 'Query DOM bdg dom query "article h2"',
23
- 'Get cookies bdg network getCookies',
24
- 'Export HAR bdg network har output.har',
25
- ]);
26
- }
27
- /**
28
- * Builds the domain commands section with expanded command coverage.
29
- *
30
- * Shows all 12+ high-level commands organized by domain (DOM, Network, Console).
31
- * Previously showed only 2 commands, now provides comprehensive coverage.
32
- *
33
- * @returns Formatted domain commands section
34
- */
35
- export function buildDomainCommandsSection() {
36
- return section('Domain Commands:', [
37
- 'DOM:',
38
- ' bdg dom query <selector> Query elements (returns JSON)',
39
- ' bdg dom get <selector|index> Get element details',
40
- ' bdg dom eval <javascript> Execute JavaScript in page context',
41
- ' bdg dom screenshot <path> Capture full page screenshot',
42
- ' bdg dom fill <selector> <value> Fill form input',
43
- ' bdg dom click <selector> Click element',
44
- ' bdg dom pressKey <selector> <key> Press key (Enter, Tab, Escape, etc.)',
45
- ' bdg dom a11y [search] Accessibility search (tree, query, describe)',
46
- ' bdg dom listeners <selector> Event listeners (incl. delegated)',
47
- '',
48
- 'Network:',
49
- ' bdg network har [path] Export HTTP Archive (HAR)',
50
- ' bdg network getCookies List all cookies',
51
- ' bdg network headers [id] HTTP headers (default: main document)',
52
- '',
53
- 'Console:',
54
- ' bdg console [options] Query console logs',
55
- ]);
56
- }
57
- /**
58
- * Builds the live monitoring section.
59
- *
60
- * Shows commands for real-time data inspection during active sessions.
61
- *
62
- * @returns Formatted live monitoring section
63
- */
64
- export function buildLiveMonitoringSection() {
65
- return section('Live Monitoring:', [
66
- 'bdg peek Preview collected data (last 10 items)',
67
- 'bdg peek --follow Live updates every second',
68
- 'bdg tail Continuous monitoring (like tail -f)',
69
- 'bdg details network <id> Full request/response details',
70
- 'bdg details console <id> Full console message details',
71
- ]);
72
- }
73
- /**
74
- * Builds the session management section.
75
- *
76
- * Shows commands for controlling the daemon and session lifecycle.
77
- *
78
- * @returns Formatted session management section
79
- */
80
- export function buildSessionManagementSection() {
81
- return section('Session Management:', [
82
- 'bdg status Check session state',
83
- 'bdg status --verbose Include Chrome diagnostics',
84
- 'bdg stop End session',
85
- 'bdg cleanup Clean stale sessions',
86
- ]);
87
- }
88
- /**
89
- * Builds the CDP access section positioned as advanced fallback.
90
- *
91
- * Provides raw CDP protocol access for advanced use cases not covered
92
- * by high-level commands. Intentionally positioned after domain commands
93
- * to guide agents toward wrapper commands first.
94
- *
95
- * @returns Formatted CDP section
96
- */
97
- export function buildCdpSection() {
98
- const counts = getProtocolCounts();
99
- return section(`Advanced: Raw CDP Access (${counts.domains} domains, ${counts.methods} methods):`, [
100
- 'bdg cdp --list List all domains',
101
- `bdg cdp Network --list List Network methods (${counts.methodsIn('Network')} methods)`,
102
- 'bdg cdp --search cookie Search methods by keyword',
103
- 'bdg cdp Runtime.evaluate --params \'{"expression":"document.title"}\'',
104
- '',
105
- 'Use high-level commands above when possible for better efficiency.',
106
- ]);
107
- }
108
- /**
109
- * Builds the discovery section for AI agents.
110
- *
111
- * Points agents to machine-readable schemas and documentation resources.
112
- *
113
- * @returns Formatted discovery section
114
- */
115
- export function buildDiscoverySection() {
116
- return section('Discovery (for AI agents):', [
117
- 'bdg --help --json Machine-readable schema (commands, options, exit codes)',
118
- 'bdg cdp --search <term> Find CDP methods by keyword',
119
- ]);
120
- }
121
- //# sourceMappingURL=sessionFormatters.js.map