browser-debugger-cli 0.8.0 → 0.10.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 (304) hide show
  1. package/README.md +7 -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 +29 -6
  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 +189 -119
  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/keyAttributes.d.ts +20 -0
  27. package/dist/commands/dom/helpers/keyAttributes.js +54 -0
  28. package/dist/commands/dom/helpers/query.d.ts +44 -17
  29. package/dist/commands/dom/helpers/query.js +300 -106
  30. package/dist/commands/dom/helpers/runElementCommand.d.ts +10 -2
  31. package/dist/commands/dom/helpers/runElementCommand.js +98 -30
  32. package/dist/commands/dom/helpers/screenshot.d.ts +4 -1
  33. package/dist/commands/dom/helpers/screenshot.js +239 -51
  34. package/dist/commands/dom/index.d.ts +4 -1
  35. package/dist/commands/dom/index.js +22 -7
  36. package/dist/commands/dom/inspect.d.ts +15 -0
  37. package/dist/commands/dom/inspect.js +82 -0
  38. package/dist/commands/dom/layout.d.ts +14 -0
  39. package/dist/commands/dom/layout.js +54 -0
  40. package/dist/commands/dom/listeners.d.ts +5 -1
  41. package/dist/commands/dom/listeners.js +15 -5
  42. package/dist/commands/dom/query.js +2 -3
  43. package/dist/commands/dom/screenshot.d.ts +12 -2
  44. package/dist/commands/dom/screenshot.js +27 -3
  45. package/dist/commands/dom/semanticUtils.d.ts +16 -10
  46. package/dist/commands/dom/semanticUtils.js +53 -16
  47. package/dist/commands/dom/wait.d.ts +13 -0
  48. package/dist/commands/dom/wait.js +83 -0
  49. package/dist/commands/helpJson.js +2 -2
  50. package/dist/commands/network/list.js +17 -13
  51. package/dist/commands/optionBehaviors.js +154 -21
  52. package/dist/commands/page.d.ts +3 -2
  53. package/dist/commands/page.js +100 -5
  54. package/dist/commands/peek.js +4 -11
  55. package/dist/commands/sessions.d.ts +8 -0
  56. package/dist/commands/sessions.js +19 -0
  57. package/dist/commands/shared/CommandRunner.js +4 -4
  58. package/dist/commands/shared/commonOptions.d.ts +4 -0
  59. package/dist/commands/shared/commonOptions.js +9 -0
  60. package/dist/commands/shared/dataFetcher.js +2 -2
  61. package/dist/commands/shared/followMode.d.ts +21 -1
  62. package/dist/commands/shared/followMode.js +29 -2
  63. package/dist/commands/shared/handleValidationError.d.ts +2 -2
  64. package/dist/commands/shared/handleValidationError.js +12 -3
  65. package/dist/commands/shared/optionTypes.d.ts +61 -5
  66. package/dist/commands/shared/startHelpers.d.ts +66 -0
  67. package/dist/commands/shared/startHelpers.js +103 -13
  68. package/dist/commands/shared/validation.d.ts +14 -2
  69. package/dist/commands/shared/validation.js +20 -3
  70. package/dist/commands/start.d.ts +63 -0
  71. package/dist/commands/start.js +115 -15
  72. package/dist/commands/status.js +29 -7
  73. package/dist/commands/stop.js +7 -6
  74. package/dist/commands/tail.js +4 -11
  75. package/dist/commands/types.d.ts +2 -0
  76. package/dist/commands.js +2 -0
  77. package/dist/connection/chromeIdentity.d.ts +65 -0
  78. package/dist/connection/chromeIdentity.js +143 -0
  79. package/dist/connection/launcher/profilePreferences.d.ts +47 -0
  80. package/dist/connection/launcher/profilePreferences.js +151 -0
  81. package/dist/connection/launcher.d.ts +21 -2
  82. package/dist/connection/launcher.js +42 -16
  83. package/dist/connection/portReservation.d.ts +14 -4
  84. package/dist/connection/portReservation.js +21 -6
  85. package/dist/connection/startupExit.d.ts +8 -0
  86. package/dist/connection/startupExit.js +15 -6
  87. package/dist/constants.d.ts +6 -2
  88. package/dist/constants.js +9 -2
  89. package/dist/daemon/SessionController.js +23 -7
  90. package/dist/daemon/errors.d.ts +1 -1
  91. package/dist/daemon/errors.js +1 -1
  92. package/dist/daemon/launcher.d.ts +10 -2
  93. package/dist/daemon/launcher.js +8 -7
  94. package/dist/daemon/server/SocketServer.js +1 -2
  95. package/dist/daemon/session/Session.d.ts +20 -0
  96. package/dist/daemon/session/Session.js +80 -9
  97. package/dist/daemon/session/chromeConnection.d.ts +9 -0
  98. package/dist/daemon/session/chromeConnection.js +45 -8
  99. package/dist/daemon/session/commandRegistry.d.ts +14 -1
  100. package/dist/daemon/session/commandRegistry.js +113 -67
  101. package/dist/daemon/session/interactions.d.ts +48 -9
  102. package/dist/daemon/session/interactions.js +46 -9
  103. package/dist/daemon/session/triggeredRequests.d.ts +67 -0
  104. package/dist/daemon/session/triggeredRequests.js +157 -0
  105. package/dist/daemon/session/types.d.ts +5 -1
  106. package/dist/daemon.js +10630 -3601
  107. package/dist/errors/messages.d.ts +456 -24
  108. package/dist/errors/messages.js +862 -67
  109. package/dist/index.js +6915 -3401
  110. package/dist/ipc/client.d.ts +21 -1
  111. package/dist/ipc/client.js +35 -3
  112. package/dist/ipc/protocol/commands.d.ts +145 -5
  113. package/dist/ipc/protocol/commands.js +4 -0
  114. package/dist/ipc/protocol/domTypes.d.ts +291 -7
  115. package/dist/ipc/protocol/inspectTypes.d.ts +388 -0
  116. package/dist/ipc/protocol/inspectTypes.js +10 -0
  117. package/dist/ipc/session/lifecycle.d.ts +8 -1
  118. package/dist/ipc/session/queries.d.ts +5 -1
  119. package/dist/ipc/session/types.d.ts +5 -0
  120. package/dist/ipc/transport/index.d.ts +2 -1
  121. package/dist/ipc/transport/index.js +2 -2
  122. package/dist/runtime/dom/actionEffects.d.ts +185 -0
  123. package/dist/runtime/dom/actionEffects.js +402 -0
  124. package/dist/runtime/dom/actionEffectsScripts.d.ts +90 -0
  125. package/dist/runtime/dom/actionEffectsScripts.js +426 -0
  126. package/dist/runtime/dom/elementGeometry.d.ts +170 -0
  127. package/dist/runtime/dom/elementGeometry.js +553 -0
  128. package/dist/runtime/dom/elementInfo.d.ts +103 -0
  129. package/dist/runtime/dom/elementInfo.js +256 -0
  130. package/dist/runtime/dom/evalHelpers.d.ts +51 -6
  131. package/dist/runtime/dom/evalHelpers.js +136 -26
  132. package/dist/runtime/dom/eventListeners.d.ts +2 -1
  133. package/dist/runtime/dom/eventListeners.js +184 -47
  134. package/dist/runtime/dom/formDiscovery.d.ts +1 -1
  135. package/dist/runtime/dom/formDiscovery.js +116 -16
  136. package/dist/runtime/dom/formFillHelpers/fill.d.ts +9 -0
  137. package/dist/runtime/dom/formFillHelpers/fill.js +178 -14
  138. package/dist/runtime/dom/formFillHelpers/index.d.ts +2 -2
  139. package/dist/runtime/dom/formFillHelpers/index.js +2 -2
  140. package/dist/runtime/dom/formFillHelpers/pressKey.js +14 -3
  141. package/dist/runtime/dom/formFillHelpers/scroll.d.ts +3 -0
  142. package/dist/runtime/dom/formFillHelpers/scroll.js +60 -18
  143. package/dist/runtime/dom/formFillHelpers/shared.d.ts +17 -0
  144. package/dist/runtime/dom/formFillHelpers/shared.js +25 -1
  145. package/dist/runtime/dom/formFillHelpers/stability.d.ts +20 -6
  146. package/dist/runtime/dom/formFillHelpers/stability.js +50 -19
  147. package/dist/runtime/dom/formSubmitHelpers.d.ts +3 -0
  148. package/dist/runtime/dom/formSubmitHelpers.js +89 -15
  149. package/dist/runtime/dom/frameLayout.d.ts +60 -0
  150. package/dist/runtime/dom/frameLayout.js +140 -0
  151. package/dist/runtime/dom/frameOrigin.d.ts +50 -0
  152. package/dist/runtime/dom/frameOrigin.js +62 -0
  153. package/dist/runtime/dom/frameScopedConnection.d.ts +92 -0
  154. package/dist/runtime/dom/frameScopedConnection.js +252 -0
  155. package/dist/runtime/dom/frameSelection.d.ts +12 -1
  156. package/dist/runtime/dom/frameSelection.js +22 -3
  157. package/dist/runtime/dom/frames.d.ts +61 -5
  158. package/dist/runtime/dom/frames.js +329 -75
  159. package/dist/runtime/dom/inspect.d.ts +28 -0
  160. package/dist/runtime/dom/inspect.js +557 -0
  161. package/dist/runtime/dom/inspectAllStyles.d.ts +62 -0
  162. package/dist/runtime/dom/inspectAllStyles.js +385 -0
  163. package/dist/runtime/dom/inspectCascade.d.ts +94 -0
  164. package/dist/runtime/dom/inspectCascade.js +371 -0
  165. package/dist/runtime/dom/inspectCascadeModel.d.ts +39 -0
  166. package/dist/runtime/dom/inspectCascadeModel.js +232 -0
  167. package/dist/runtime/dom/inspectHints.d.ts +62 -0
  168. package/dist/runtime/dom/inspectHints.js +305 -0
  169. package/dist/runtime/dom/inspectLayoutModel.d.ts +87 -0
  170. package/dist/runtime/dom/inspectLayoutModel.js +346 -0
  171. package/dist/runtime/dom/inspectModel.d.ts +74 -0
  172. package/dist/runtime/dom/inspectModel.js +184 -0
  173. package/dist/runtime/dom/inspectPaintModel.d.ts +157 -0
  174. package/dist/runtime/dom/inspectPaintModel.js +461 -0
  175. package/dist/runtime/dom/inspectRules.d.ts +37 -0
  176. package/dist/runtime/dom/inspectRules.js +101 -0
  177. package/dist/runtime/dom/inspectScripts.d.ts +132 -0
  178. package/dist/runtime/dom/inspectScripts.js +263 -0
  179. package/dist/runtime/dom/inspectTree.d.ts +40 -0
  180. package/dist/runtime/dom/inspectTree.js +134 -0
  181. package/dist/runtime/dom/inspectVariables.d.ts +33 -0
  182. package/dist/runtime/dom/inspectVariables.js +94 -0
  183. package/dist/runtime/dom/inspectWhyModel.d.ts +20 -0
  184. package/dist/runtime/dom/inspectWhyModel.js +134 -0
  185. package/dist/runtime/dom/layout.d.ts +71 -0
  186. package/dist/runtime/dom/layout.js +340 -0
  187. package/dist/runtime/dom/listenerPageScripts.d.ts +72 -0
  188. package/dist/runtime/dom/listenerPageScripts.js +365 -0
  189. package/dist/runtime/dom/listenerSummary.d.ts +136 -11
  190. package/dist/runtime/dom/listenerSummary.js +361 -22
  191. package/dist/runtime/dom/pageActivity.d.ts +41 -0
  192. package/dist/runtime/dom/pageActivity.js +123 -0
  193. package/dist/runtime/dom/reactEventHelpers.d.ts +63 -2
  194. package/dist/runtime/dom/reactEventHelpers.js +220 -41
  195. package/dist/runtime/dom/targetNode.d.ts +80 -27
  196. package/dist/runtime/dom/targetNode.js +249 -33
  197. package/dist/runtime/dom/wait.d.ts +25 -0
  198. package/dist/runtime/dom/wait.js +199 -0
  199. package/dist/runtime/dom/waitCondition.d.ts +71 -0
  200. package/dist/runtime/dom/waitCondition.js +75 -0
  201. package/dist/runtime/page/emulation.d.ts +71 -0
  202. package/dist/runtime/page/emulation.js +117 -0
  203. package/dist/runtime/page/loadingState.d.ts +36 -0
  204. package/dist/runtime/page/loadingState.js +86 -0
  205. package/dist/runtime/page/navigation.d.ts +46 -2
  206. package/dist/runtime/page/navigation.js +69 -33
  207. package/dist/session/QueryCacheManager.d.ts +11 -1
  208. package/dist/session/QueryCacheManager.js +25 -3
  209. package/dist/session/chromeOwners.d.ts +34 -0
  210. package/dist/session/chromeOwners.js +51 -0
  211. package/dist/session/cleanup/staleSession.d.ts +11 -1
  212. package/dist/session/cleanup/staleSession.js +17 -6
  213. package/dist/session/cleanup/userCommands.js +2 -4
  214. package/dist/session/metadata.d.ts +5 -1
  215. package/dist/session/metadata.js +2 -1
  216. package/dist/session/paths.d.ts +77 -3
  217. package/dist/session/paths.js +111 -5
  218. package/dist/session/port.d.ts +31 -7
  219. package/dist/session/port.js +50 -43
  220. package/dist/session/portClaims.d.ts +66 -0
  221. package/dist/session/portClaims.js +284 -0
  222. package/dist/session/sessionList.d.ts +58 -0
  223. package/dist/session/sessionList.js +199 -0
  224. package/dist/session/sessionName.d.ts +46 -0
  225. package/dist/session/sessionName.js +97 -0
  226. package/dist/telemetry/a11y.d.ts +18 -3
  227. package/dist/telemetry/a11y.js +170 -29
  228. package/dist/telemetry/console.d.ts +1 -0
  229. package/dist/telemetry/console.js +100 -5
  230. package/dist/telemetry/network.js +3 -1
  231. package/dist/telemetry/requestKinds.d.ts +32 -0
  232. package/dist/telemetry/requestKinds.js +61 -0
  233. package/dist/telemetry/requestState.d.ts +31 -0
  234. package/dist/telemetry/requestState.js +38 -0
  235. package/dist/types.d.ts +112 -3
  236. package/dist/ui/formatters/a11y.js +3 -0
  237. package/dist/ui/formatters/console/chronological.d.ts +8 -0
  238. package/dist/ui/formatters/console/chronological.js +17 -4
  239. package/dist/ui/formatters/console/json.js +3 -4
  240. package/dist/ui/formatters/console/shared.d.ts +12 -0
  241. package/dist/ui/formatters/console.d.ts +2 -2
  242. package/dist/ui/formatters/console.js +1 -1
  243. package/dist/ui/formatters/details.d.ts +8 -0
  244. package/dist/ui/formatters/details.js +61 -4
  245. package/dist/ui/formatters/dom.d.ts +27 -14
  246. package/dist/ui/formatters/dom.js +88 -59
  247. package/dist/ui/formatters/form.js +29 -18
  248. package/dist/ui/formatters/inspect.d.ts +39 -0
  249. package/dist/ui/formatters/inspect.js +596 -0
  250. package/dist/ui/formatters/keyAttributes.d.ts +19 -0
  251. package/dist/ui/formatters/keyAttributes.js +84 -0
  252. package/dist/ui/formatters/layout.d.ts +31 -0
  253. package/dist/ui/formatters/layout.js +53 -0
  254. package/dist/ui/formatters/listeners.d.ts +3 -2
  255. package/dist/ui/formatters/listeners.js +73 -9
  256. package/dist/ui/formatters/networkHeaders.d.ts +13 -0
  257. package/dist/ui/formatters/networkHeaders.js +36 -3
  258. package/dist/ui/formatters/networkList.d.ts +29 -1
  259. package/dist/ui/formatters/networkList.js +86 -20
  260. package/dist/ui/formatters/preview.js +2 -1
  261. package/dist/ui/formatters/requestStatus.d.ts +1 -17
  262. package/dist/ui/formatters/requestStatus.js +2 -30
  263. package/dist/ui/formatters/sessions.d.ts +12 -0
  264. package/dist/ui/formatters/sessions.js +40 -0
  265. package/dist/ui/formatters/status.d.ts +21 -2
  266. package/dist/ui/formatters/status.js +47 -10
  267. package/dist/ui/formatters/triggeredRequests.d.ts +36 -0
  268. package/dist/ui/formatters/triggeredRequests.js +65 -0
  269. package/dist/ui/formatting.d.ts +19 -0
  270. package/dist/ui/formatting.js +31 -36
  271. package/dist/ui/messages/chrome.d.ts +9 -0
  272. package/dist/ui/messages/chrome.js +17 -5
  273. package/dist/ui/messages/commands.d.ts +504 -14
  274. package/dist/ui/messages/commands.js +835 -21
  275. package/dist/ui/messages/consoleMessages.d.ts +10 -0
  276. package/dist/ui/messages/consoleMessages.js +17 -0
  277. package/dist/ui/messages/hints.js +2 -1
  278. package/dist/ui/messages/networkMessages.d.ts +14 -0
  279. package/dist/ui/messages/networkMessages.js +18 -0
  280. package/dist/ui/messages/preview.js +5 -4
  281. package/dist/ui/messages/session.d.ts +30 -21
  282. package/dist/ui/messages/session.js +48 -26
  283. package/dist/ui/messages/sessionCommand.d.ts +43 -0
  284. package/dist/ui/messages/sessionCommand.js +52 -0
  285. package/dist/utils/async.d.ts +17 -0
  286. package/dist/utils/async.js +36 -0
  287. package/dist/utils/color.d.ts +84 -0
  288. package/dist/utils/color.js +376 -0
  289. package/dist/utils/cssValues.d.ts +109 -0
  290. package/dist/utils/cssValues.js +236 -0
  291. package/dist/utils/http.d.ts +22 -1
  292. package/dist/utils/http.js +28 -9
  293. package/dist/utils/selectorFilters.d.ts +48 -8
  294. package/dist/utils/selectorFilters.js +296 -53
  295. package/dist/utils/shellDetection.d.ts +8 -2
  296. package/dist/utils/shellDetection.js +120 -33
  297. package/dist/utils/suggestions.d.ts +26 -0
  298. package/dist/utils/suggestions.js +73 -0
  299. package/dist/utils/taskMappings.js +10 -0
  300. package/dist/utils/url.d.ts +12 -2
  301. package/dist/utils/url.js +69 -7
  302. package/package.json +1 -1
  303. package/dist/ui/formatters/sessionFormatters.d.ts +0 -58
  304. package/dist/ui/formatters/sessionFormatters.js +0 -121
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Human-readable output of `bdg dom layout`.
3
+ */
4
+ import type { ElementLayout, LayoutResult, LayoutSize } from '../../ipc/protocol/domTypes.js';
5
+ import type { IndexSource } from '../../types.js';
6
+ /** `bdg dom layout` data (the `success` flag is implied by the envelope), with the list an index refers to */
7
+ type LayoutOutput = Omit<LayoutResult, 'success'> & {
8
+ indexSource?: IndexSource | undefined;
9
+ };
10
+ /**
11
+ * One element as a compact line: index, description, text, page position
12
+ * and size (not for hidden elements, which have no meaningful box), where it
13
+ * is relative to the viewport, what covers it, an inert or invisible element
14
+ * and the iframe or shadow root it is in (unless the position already names
15
+ * it as the clipping iframe).
16
+ *
17
+ * @param element - Element layout
18
+ * @param viewport - Viewport size, when known (an element larger than it is not centred by the scroll)
19
+ * @returns e.g. `[0] button#save "Save" 420,1180 120×40 below fold (scroll down 500px to centre it)`
20
+ */
21
+ export declare function layoutLine(element: ElementLayout, viewport?: LayoutSize): string;
22
+ /**
23
+ * Format `bdg dom layout` output: the page dimensions, then one line per
24
+ * element (the first {@link LAYOUT_DISPLAY_LIMIT}).
25
+ *
26
+ * @param data - Layout report
27
+ * @returns Formatted output
28
+ */
29
+ export declare function formatLayout(data: LayoutOutput): string;
30
+ export {};
31
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Human-readable output of `bdg dom layout`.
3
+ */
4
+ import { indexSourceText } from '../../errors/messages.js';
5
+ import { OutputFormatter } from '../formatting.js';
6
+ import { coverText, indexLayoutHeadline, layoutHeadline, layoutPositionLabel, moreMatchesNote, pageLayoutLine, } from '../messages/commands.js';
7
+ /** Elements listed in human output (JSON has up to 100) */
8
+ const LAYOUT_DISPLAY_LIMIT = 20;
9
+ /**
10
+ * One element as a compact line: index, description, text, page position
11
+ * and size (not for hidden elements, which have no meaningful box), where it
12
+ * is relative to the viewport, what covers it, an inert or invisible element
13
+ * and the iframe or shadow root it is in (unless the position already names
14
+ * it as the clipping iframe).
15
+ *
16
+ * @param element - Element layout
17
+ * @param viewport - Viewport size, when known (an element larger than it is not centred by the scroll)
18
+ * @returns e.g. `[0] button#save "Save" 420,1180 120×40 below fold (scroll down 500px to centre it)`
19
+ */
20
+ export function layoutLine(element, viewport) {
21
+ const { bounds } = element;
22
+ return [
23
+ `[${element.index}] ${element.element}${element.text ? ` "${element.text}"` : ''}`,
24
+ element.inViewport !== 'hidden' && `${bounds.x},${bounds.y} ${bounds.width}×${bounds.height}`,
25
+ layoutPositionLabel(element, viewport),
26
+ element.coveredBy && coverText(element.coveredBy, element.coverTransparent),
27
+ element.inert && 'inert',
28
+ element.invisible,
29
+ element.context && element.context !== element.clippedBy && `in ${element.context}`,
30
+ ]
31
+ .filter(Boolean)
32
+ .join(' ');
33
+ }
34
+ /**
35
+ * Format `bdg dom layout` output: the page dimensions, then one line per
36
+ * element (the first {@link LAYOUT_DISPLAY_LIMIT}).
37
+ *
38
+ * @param data - Layout report
39
+ * @returns Formatted output
40
+ */
41
+ export function formatLayout(data) {
42
+ const shown = data.elements.slice(0, LAYOUT_DISPLAY_LIMIT);
43
+ const more = data.elements.length - shown.length + (data.omitted ?? 0);
44
+ return new OutputFormatter()
45
+ .text(pageLayoutLine(data.page))
46
+ .text(data.indexSource
47
+ ? indexLayoutHeadline(indexSourceText(data.indexSource))
48
+ : layoutHeadline(data.count, data.elements.length + (data.omitted ?? 0), data.selector))
49
+ .list(shown.map((element) => layoutLine(element, data.page.viewport)))
50
+ .list(more > 0 ? [moreMatchesNote(more, data.omitted ? data.elements.length : undefined)] : [])
51
+ .build();
52
+ }
53
+ //# sourceMappingURL=layout.js.map
@@ -12,8 +12,9 @@ type ListenersOutput = Omit<ListenersResult, 'success'>;
12
12
  */
13
13
  export declare function handlerLocation(handler: ElementListener['handler']): string;
14
14
  /**
15
- * Format `bdg dom listeners` output: listeners grouped by event type,
16
- * nearest first, with a note for events handled only by delegation.
15
+ * Format `bdg dom listeners` output: listeners grouped by event type, the
16
+ * handlers nearest the element first, then one line per framework root,
17
+ * with notes for events the element has no listener of its own for.
17
18
  *
18
19
  * @param result - Listener report
19
20
  * @param types - Event types asked for with --type, if any
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Human-readable output of `bdg dom listeners`.
3
3
  */
4
- import { delegatedOnlyTypes } from '../../runtime/dom/listenerSummary.js';
4
+ import { delegationNotes } from '../../runtime/dom/listenerSummary.js';
5
5
  import { OutputFormatter } from '../formatting.js';
6
- import { NO_LISTENERS_HINT, delegatedListenersNote, listenersHeadline, noListenersMessage, } from '../messages/commands.js';
6
+ import { COLLAPSED_LISTENERS_HEADING, NO_LISTENERS_HINT, collapsedListenersSummary, delegationNote, eventTypeSuggestion, jqueryHandlersSkippedNote, listenersHeadline, noListenersMessage, reactHandlersSkippedNote, } from '../messages/commands.js';
7
7
  import { truncateByLength } from '../../utils/strings.js';
8
8
  /** Longest handler name shown (JSON has the full name) */
9
9
  const NAME_MAX_LENGTH = 30;
@@ -29,6 +29,9 @@ export function handlerLocation(handler) {
29
29
  */
30
30
  function listenerCells(listener) {
31
31
  const flags = [
32
+ listener.reactProp ? `React ${listener.reactProp}` : listener.framework,
33
+ listener.delegateSelector && `delegate ${listener.delegateSelector}`,
34
+ listener.noop && 'no-op',
32
35
  listener.useCapture && 'capture',
33
36
  listener.passive && 'passive',
34
37
  listener.once && 'once',
@@ -54,9 +57,31 @@ function alignColumns(rows) {
54
57
  .map((cell, column) => (column === row.length - 1 ? cell : cell.padEnd(widths[column] ?? 0)))
55
58
  .join(' '));
56
59
  }
60
+ /** Dispatcher names listed per collapsed framework root */
61
+ const COLLAPSED_HANDLERS_SHOWN = 3;
57
62
  /**
58
- * Format `bdg dom listeners` output: listeners grouped by event type,
59
- * nearest first, with a note for events handled only by delegation.
63
+ * Listeners by where they are attached, collapsed framework roots included.
64
+ *
65
+ * @param listeners - Listed listeners
66
+ * @param collapsed - Collapsed framework roots
67
+ * @returns Counts on the element, its ancestors, and document or window
68
+ */
69
+ function listenerCounts(listeners, collapsed) {
70
+ const counts = { target: 0, ancestor: 0, global: 0 };
71
+ const add = (on, count) => {
72
+ if (on === 'target' || on === 'ancestor')
73
+ counts[on] += count;
74
+ else
75
+ counts.global += count;
76
+ };
77
+ listeners.forEach((listener) => add(listener.on, 1));
78
+ collapsed.forEach((root) => add(root.on, root.count));
79
+ return counts;
80
+ }
81
+ /**
82
+ * Format `bdg dom listeners` output: listeners grouped by event type, the
83
+ * handlers nearest the element first, then one line per framework root,
84
+ * with notes for events the element has no listener of its own for.
60
85
  *
61
86
  * @param result - Listener report
62
87
  * @param types - Event types asked for with --type, if any
@@ -64,21 +89,60 @@ function alignColumns(rows) {
64
89
  */
65
90
  export function formatListeners(result, types) {
66
91
  const fmt = new OutputFormatter();
67
- if (result.listeners.length === 0) {
92
+ const collapsed = result.collapsed ?? [];
93
+ if (result.listeners.length === 0 && collapsed.length === 0) {
68
94
  fmt.text(noListenersMessage(result.element, types));
95
+ if (result.typeSuggestions?.length)
96
+ fmt.text(eventTypeSuggestion(result.typeSuggestions));
69
97
  fmt.tip(NO_LISTENERS_HINT);
70
98
  }
71
99
  else {
72
- fmt.text(listenersHeadline(result.element, result.listeners.length));
100
+ fmt.text(listenersHeadline(result.element, listenerCounts(result.listeners, collapsed), result));
73
101
  appendListenerGroups(fmt, result.listeners);
74
- const delegated = delegatedOnlyTypes(result.listeners);
75
- if (delegated.length > 0)
76
- fmt.blank().text(delegatedListenersNote(delegated));
102
+ appendCollapsed(fmt, collapsed);
103
+ appendDelegationNotes(fmt, result.listeners, collapsed);
104
+ }
105
+ if (result.jqueryHandlersSkipped) {
106
+ fmt.blank().text(jqueryHandlersSkippedNote(result.jqueryHandlersSkipped));
107
+ }
108
+ if (result.reactHandlersSkipped) {
109
+ fmt.blank().text(reactHandlersSkippedNote(result.reactHandlersSkipped));
77
110
  }
78
111
  if (result.warning)
79
112
  fmt.blank().text(`⚠ Warning: ${result.warning}`);
80
113
  return fmt.build();
81
114
  }
115
+ /**
116
+ * Add a note per way events reach their handlers without a listener on the
117
+ * element itself (React props, React root, jQuery, plain delegation).
118
+ *
119
+ * @param fmt - Output being built
120
+ * @param listeners - Listeners
121
+ * @param collapsed - Collapsed roots
122
+ */
123
+ function appendDelegationNotes(fmt, listeners, collapsed) {
124
+ const notes = delegationNotes(listeners, collapsed).flatMap((note) => delegationNote(note) ?? []);
125
+ if (notes.length > 0)
126
+ fmt.blank();
127
+ notes.forEach((note) => fmt.text(note));
128
+ }
129
+ /**
130
+ * Add the collapsed framework roots, one line per node.
131
+ *
132
+ * @param fmt - Output being built
133
+ * @param collapsed - Collapsed roots
134
+ */
135
+ function appendCollapsed(fmt, collapsed) {
136
+ if (collapsed.length === 0)
137
+ return;
138
+ fmt.blank().text(COLLAPSED_LISTENERS_HEADING);
139
+ const rows = collapsed.map((root) => {
140
+ const names = root.handlers.map((handler) => truncateByLength(handler.name || ANONYMOUS, NAME_MAX_LENGTH));
141
+ const shown = [...new Set(names)].slice(0, COLLAPSED_HANDLERS_SHOWN);
142
+ return [root.on, root.node, collapsedListenersSummary({ ...root, handlers: shown })];
143
+ });
144
+ alignColumns(rows).forEach((line) => fmt.text(` ${line}`));
145
+ }
82
146
  /**
83
147
  * Add one block per event type: the type, then its listeners.
84
148
  *
@@ -11,4 +11,17 @@ import type { SessionNetworkHeadersData } from '../../ipc/protocol/commands.js';
11
11
  * @returns Formatted string for console output
12
12
  */
13
13
  export declare function formatNetworkHeaders(data: SessionNetworkHeadersData): string;
14
+ /**
15
+ * The values of a header, one per line. A header sent several times reaches
16
+ * CDP as one value with the values joined by newlines (`Set-Cookie`, or a
17
+ * server repeating `Strict-Transport-Security`); a value sent more than once
18
+ * is listed once, saying how often it was sent. `Set-Cookie` lines are all
19
+ * kept: each one sets a cookie, and repeating one is not the same as sending
20
+ * it once.
21
+ *
22
+ * @param name - Header name
23
+ * @param value - Header value as CDP reports it
24
+ * @returns e.g. `['max-age=63072000 (sent 2 times)']`
25
+ */
26
+ export declare function headerValueLines(name: string, value: string): string[];
14
27
  //# sourceMappingURL=networkHeaders.d.ts.map
@@ -3,7 +3,9 @@
3
3
  *
4
4
  * Formats network request and response headers for human-readable display.
5
5
  */
6
+ import { formatRequestStatus } from './requestStatus.js';
6
7
  import { OutputFormatter } from '../formatting.js';
8
+ import { headerRepeatedNote } from '../messages/networkMessages.js';
7
9
  /**
8
10
  * Format network request headers for display.
9
11
  *
@@ -14,6 +16,7 @@ export function formatNetworkHeaders(data) {
14
16
  const fmt = new OutputFormatter();
15
17
  fmt.text('Network Request Headers').separator('━', 60).blank();
16
18
  fmt.text('URL:').text(` ${data.url}`).blank();
19
+ fmt.text(`Status: ${requestStatusLine(data)}`).blank();
17
20
  if (Object.keys(data.responseHeaders).length > 0) {
18
21
  fmt.text('Response Headers:');
19
22
  formatHeaderSection(fmt, data.responseHeaders);
@@ -31,11 +34,30 @@ export function formatNetworkHeaders(data) {
31
34
  fmt.text(`Request ID: ${data.requestId}`);
32
35
  return fmt.build();
33
36
  }
37
+ /**
38
+ * The values of a header, one per line. A header sent several times reaches
39
+ * CDP as one value with the values joined by newlines (`Set-Cookie`, or a
40
+ * server repeating `Strict-Transport-Security`); a value sent more than once
41
+ * is listed once, saying how often it was sent. `Set-Cookie` lines are all
42
+ * kept: each one sets a cookie, and repeating one is not the same as sending
43
+ * it once.
44
+ *
45
+ * @param name - Header name
46
+ * @param value - Header value as CDP reports it
47
+ * @returns e.g. `['max-age=63072000 (sent 2 times)']`
48
+ */
49
+ export function headerValueLines(name, value) {
50
+ if (name.toLowerCase() === 'set-cookie')
51
+ return value.split('\n');
52
+ const counts = new Map();
53
+ for (const line of value.split('\n'))
54
+ counts.set(line, (counts.get(line) ?? 0) + 1);
55
+ return [...counts].map(([line, count]) => count > 1 ? `${line} ${headerRepeatedNote(count)}` : line);
56
+ }
34
57
  /**
35
58
  * Format a section of headers with consistent formatting.
36
59
  *
37
- * Repeated headers (CDP joins e.g. multiple `Set-Cookie` values with newlines)
38
- * are printed one per line.
60
+ * Repeated headers are printed one value per line ({@link headerValueLines}).
39
61
  *
40
62
  * @param fmt - Output formatter instance
41
63
  * @param headers - Headers to format
@@ -44,7 +66,18 @@ function formatHeaderSection(fmt, headers) {
44
66
  const entries = Object.entries(headers).sort(([a], [b]) => a.localeCompare(b));
45
67
  const keyWidth = Math.max(...entries.map(([k]) => k.length)) + 4;
46
68
  entries.forEach(([key, value]) => {
47
- value.split('\n').forEach((line) => fmt.keyValue(` ${key}`, line, keyWidth));
69
+ headerValueLines(key, value).forEach((line) => fmt.keyValue(` ${key}`, line, keyWidth));
48
70
  });
49
71
  }
72
+ /**
73
+ * Status line of a request: method, HTTP status and status text, or how it failed.
74
+ *
75
+ * @param data - Network headers data
76
+ * @returns e.g. `GET 404 Not Found`, `GET FAILED (net::ERR_NAME_NOT_RESOLVED)`, `GET pending`
77
+ */
78
+ function requestStatusLine(data) {
79
+ const status = formatRequestStatus(data);
80
+ const text = data.statusText && /^\d+$/.test(status) ? ` ${data.statusText}` : '';
81
+ return [data.method, `${status}${text}`].filter(Boolean).join(' ');
82
+ }
50
83
  //# sourceMappingURL=networkHeaders.js.map
@@ -7,22 +7,50 @@
7
7
  import type { NetworkRequest } from '../../types.js';
8
8
  export interface NetworkListOptions {
9
9
  verbose?: boolean;
10
+ /** Start of the current page, which the START column counts from ({@link pageStartOf}) */
11
+ pageStart?: PageStart;
10
12
  last?: number;
11
13
  totalCount?: number;
12
14
  /** Requests matching the filters, before --last (defaults to totalCount) */
13
15
  filteredCount?: number;
14
16
  }
17
+ /**
18
+ * When the current page started loading: the request of its document, in
19
+ * Chrome's monotonic time (`sentTime`, seconds) and wall-clock time
20
+ * (`timestamp`, epoch ms).
21
+ */
22
+ export type PageStart = Pick<NetworkRequest, 'sentTime' | 'timestamp'>;
23
+ /**
24
+ * The start of the current page: the earliest document request of the
25
+ * latest navigation among the requests (its earliest request when its
26
+ * document was not captured).
27
+ *
28
+ * @param requests - All captured requests (before filters, so the document is among them)
29
+ * @returns Its times, or undefined when there are no requests
30
+ */
31
+ export declare function pageStartOf(requests: NetworkRequest[]): PageStart | undefined;
32
+ /**
33
+ * Format a request's start for the START column, relative to the current
34
+ * page's start: tenths of a second up to 100 s, then whole seconds, then
35
+ * minutes.
36
+ *
37
+ * @param request - Request
38
+ * @param pageStart - Start of the current page (none: `-`)
39
+ * @returns e.g. "+0.0s", "+1.2s", "+250s", "+17m", "-35.2s" (earlier page)
40
+ */
41
+ export declare function formatStartOffset(request: NetworkRequest, pageStart: PageStart | undefined): string;
15
42
  /**
16
43
  * Rows of the network stream: requests that finished since the last poll,
17
44
  * with the column header the first time.
18
45
  *
19
46
  * @param requests - Newly finished requests
20
- * @param options - `header` the first time; `verbose` for full URLs
47
+ * @param options - `header` the first time; `verbose` for full URLs; the page start for START
21
48
  * @returns Text to print (empty when there is nothing new)
22
49
  */
23
50
  export declare function formatNetworkFollowRows(requests: NetworkRequest[], options?: {
24
51
  header?: boolean;
25
52
  verbose?: boolean;
53
+ pageStart?: PageStart;
26
54
  }): string;
27
55
  /**
28
56
  * Format network requests for display.
@@ -39,32 +39,99 @@ function formatDuration(ms) {
39
39
  return ms < 1000 ? `${Math.round(ms)}ms` : `${(ms / 1000).toFixed(1)}s`;
40
40
  }
41
41
  /**
42
- * Column header aligned to the widest request id in the list.
42
+ * The start of the current page: the earliest document request of the
43
+ * latest navigation among the requests (its earliest request when its
44
+ * document was not captured).
43
45
  *
44
- * @param idWidth - Width of the bracketed id column
46
+ * @param requests - All captured requests (before filters, so the document is among them)
47
+ * @returns Its times, or undefined when there are no requests
48
+ */
49
+ export function pageStartOf(requests) {
50
+ const navigationIds = requests.flatMap((r) => r.navigationId === undefined ? [] : [r.navigationId]);
51
+ const current = navigationIds.length > 0 ? Math.max(...navigationIds) : undefined;
52
+ const page = requests.filter((r) => r.navigationId === current);
53
+ const documents = page.filter((r) => r.resourceType === 'Document');
54
+ const first = (documents.length > 0 ? documents : page).reduce((earliest, r) => (earliest === undefined || r.timestamp < earliest.timestamp ? r : earliest), undefined);
55
+ return (first && {
56
+ timestamp: first.timestamp,
57
+ ...(first.sentTime !== undefined && { sentTime: first.sentTime }),
58
+ });
59
+ }
60
+ /**
61
+ * Milliseconds from the page start to a request's start, in Chrome's time
62
+ * when both have it (precise), else in wall-clock time.
63
+ *
64
+ * @param request - Request
65
+ * @param pageStart - Start of the current page
66
+ * @returns Offset (negative for requests of earlier pages)
67
+ */
68
+ function startOffsetMs(request, pageStart) {
69
+ if (request.sentTime !== undefined && pageStart.sentTime !== undefined) {
70
+ return (request.sentTime - pageStart.sentTime) * 1000;
71
+ }
72
+ return request.timestamp - pageStart.timestamp;
73
+ }
74
+ /**
75
+ * Format a request's start for the START column, relative to the current
76
+ * page's start: tenths of a second up to 100 s, then whole seconds, then
77
+ * minutes.
78
+ *
79
+ * @param request - Request
80
+ * @param pageStart - Start of the current page (none: `-`)
81
+ * @returns e.g. "+0.0s", "+1.2s", "+250s", "+17m", "-35.2s" (earlier page)
82
+ */
83
+ export function formatStartOffset(request, pageStart) {
84
+ if (!pageStart)
85
+ return '-';
86
+ const ms = startOffsetMs(request, pageStart);
87
+ const seconds = Math.abs(ms) / 1000;
88
+ const sign = ms < -50 ? '-' : '+';
89
+ if (seconds < 99.95)
90
+ return `${sign}${seconds.toFixed(1)}s`;
91
+ if (seconds < 999.5)
92
+ return `${sign}${Math.round(seconds)}s`;
93
+ return `${sign}${Math.floor(seconds / 60)}m`;
94
+ }
95
+ /**
96
+ * Column header aligned to the widest request id and method in the list.
97
+ *
98
+ * @param widths - Column widths
45
99
  * @returns Header line
46
100
  */
47
- function formatColumnHeader(idWidth) {
48
- return `${'[ID]'.padEnd(idWidth)} STS METH TYP ${'SIZE'.padStart(8)} ${'TIME'.padStart(6)} URL`;
101
+ function formatColumnHeader(widths) {
102
+ return `${'[ID]'.padEnd(widths.id)} ${'START'.padStart(6)} STS ${'METH'.padEnd(widths.method)} TYP ${'SIZE'.padStart(8)} ${'TIME'.padStart(6)} URL`;
49
103
  }
50
104
  /**
51
105
  * Format one request as a table row.
52
106
  *
53
107
  * @param request - Network request
54
- * @param verbose - Show full URLs
55
- * @param idWidth - Width of the bracketed id column (ids vary in length)
108
+ * @param options - Show full URLs (`verbose`), the page start for START
109
+ * @param widths - Column widths (ids and methods vary in length)
56
110
  * @returns Row text
57
111
  */
58
- function formatRequestLine(request, verbose, idWidth) {
59
- const id = `[${request.requestId}]`.padEnd(idWidth);
112
+ function formatRequestLine(request, options, widths) {
113
+ const id = `[${request.requestId}]`.padEnd(widths.id);
114
+ const start = formatStartOffset(request, options.pageStart).padStart(6);
60
115
  const status = formatStatus(request).padEnd(3);
61
- const method = request.method.padEnd(4);
116
+ const method = request.method.padEnd(widths.method);
62
117
  const type = getResourceTypeAbbr(request.resourceType, request.mimeType).padEnd(3);
63
118
  const size = formatSize(request.encodedDataLength).padStart(8);
64
119
  const time = formatDuration(request.duration).padStart(6);
65
- const urlMaxLength = verbose ? 120 : 50;
66
- const url = verbose ? request.url : truncateUrl(request.url, urlMaxLength);
67
- return `${id} ${status} ${method} ${type} ${size} ${time} ${url}`;
120
+ const url = options.verbose ? request.url : truncateUrl(request.url, 50);
121
+ return `${id} ${start} ${status} ${method} ${type} ${size} ${time} ${url}`;
122
+ }
123
+ /**
124
+ * Column widths fitting the rows.
125
+ *
126
+ * @param requests - Rows
127
+ * @param minIdWidth - Narrowest id column
128
+ * @returns Widths
129
+ */
130
+ function columnWidths(requests, minIdWidth) {
131
+ return {
132
+ id: Math.max(minIdWidth, ...requests.map((r) => r.requestId.length + 2)),
133
+ method: Math.max('METH'.length, ...requests.map((r) => r.method.length)),
134
+ };
68
135
  }
69
136
  /**
70
137
  * Header line with how many requests are shown.
@@ -91,12 +158,11 @@ function formatNetworkListHuman(requests, options) {
91
158
  fmt.text('No matching requests found.');
92
159
  return fmt.build();
93
160
  }
94
- const idWidth = Math.max('[ID]'.length, ...requests.map((r) => r.requestId.length + 2));
95
- fmt.text(formatColumnHeader(idWidth));
161
+ const widths = columnWidths(requests, '[ID]'.length);
162
+ fmt.text(formatColumnHeader(widths));
96
163
  fmt.separator('─', SEPARATOR_WIDTH);
97
- const verbose = options.verbose ?? false;
98
164
  for (const request of requests) {
99
- fmt.text(formatRequestLine(request, verbose, idWidth));
165
+ fmt.text(formatRequestLine(request, options, widths));
100
166
  }
101
167
  return fmt.build();
102
168
  }
@@ -107,19 +173,19 @@ const FOLLOW_ID_WIDTH = 14;
107
173
  * with the column header the first time.
108
174
  *
109
175
  * @param requests - Newly finished requests
110
- * @param options - `header` the first time; `verbose` for full URLs
176
+ * @param options - `header` the first time; `verbose` for full URLs; the page start for START
111
177
  * @returns Text to print (empty when there is nothing new)
112
178
  */
113
179
  export function formatNetworkFollowRows(requests, options = {}) {
114
180
  const fmt = new OutputFormatter();
115
- const idWidth = Math.max(FOLLOW_ID_WIDTH, ...requests.map((r) => r.requestId.length + 2));
181
+ const widths = columnWidths(requests, FOLLOW_ID_WIDTH);
116
182
  if (options.header) {
117
183
  fmt.text('Streaming network requests... (Ctrl+C to stop)');
118
- fmt.text(formatColumnHeader(idWidth));
184
+ fmt.text(formatColumnHeader(widths));
119
185
  fmt.separator('─', SEPARATOR_WIDTH);
120
186
  }
121
187
  for (const request of requests)
122
- fmt.text(formatRequestLine(request, options.verbose ?? false, idWidth));
188
+ fmt.text(formatRequestLine(request, options, widths));
123
189
  return fmt.build();
124
190
  }
125
191
  /**
@@ -4,6 +4,7 @@ import { formatTimestamp } from './console/shared.js';
4
4
  import { failureReason, formatRequestStatus, getRequestState, } from './requestStatus.js';
5
5
  import { OutputFormatter, truncateUrl, truncateText } from '../formatting.js';
6
6
  import { PREVIEW_EMPTY_STATES, PREVIEW_HEADERS, compactTipsMessage, verboseCommandsMessage, } from '../messages/preview.js';
7
+ import { sessionCommand } from '../messages/sessionCommand.js';
7
8
  /**
8
9
  * Infer resource type from MIME type when CDP doesn't provide it.
9
10
  *
@@ -218,7 +219,7 @@ function formatPreviewVerbose(output, options) {
218
219
  if (req.mimeType) {
219
220
  fmt.text(` MIME: ${req.mimeType}`);
220
221
  }
221
- fmt.text(` ID: ${req.requestId} (use 'bdg details network ${req.requestId}' for full details)`);
222
+ fmt.text(` ID: ${req.requestId} (use '${sessionCommand(`bdg details network ${req.requestId}`)}' for full details)`);
222
223
  });
223
224
  }
224
225
  fmt.blank();
@@ -6,23 +6,7 @@
6
6
  * response keeps its HTTP status even if loading failed afterwards.
7
7
  */
8
8
  import type { NetworkRequest } from '../../types.js';
9
- /** Lifecycle state of a captured request. */
10
- export type RequestState = 'pending' | 'failed' | 'complete';
11
- /**
12
- * Classify a request.
13
- *
14
- * @param request - Captured request
15
- * @returns Its lifecycle state
16
- */
17
- export declare function getRequestState(request: Pick<NetworkRequest, 'status'>): RequestState;
18
- /**
19
- * Why a request failed, leaving out Chrome stopping an unneeded body after a
20
- * complete response (204/304 report `net::ERR_ABORTED` that way).
21
- *
22
- * @param request - Captured request
23
- * @returns Reason, or undefined when there is none worth showing
24
- */
25
- export declare function failureReason(request: Pick<NetworkRequest, 'status' | 'errorText'>): string | undefined;
9
+ export { failureReason, getRequestState, type RequestState } from '../../telemetry/requestState.js';
26
10
  /**
27
11
  * Human-readable status: the HTTP status (with the failure reason if loading
28
12
  * failed after the response), `FAILED (<reason>)`, or `pending`.
@@ -5,31 +5,8 @@
5
5
  * without any response (DNS, refused, aborted, blocked); a request that got a
6
6
  * response keeps its HTTP status even if loading failed afterwards.
7
7
  */
8
- /**
9
- * Classify a request.
10
- *
11
- * @param request - Captured request
12
- * @returns Its lifecycle state
13
- */
14
- export function getRequestState(request) {
15
- if (request.status === undefined)
16
- return 'pending';
17
- return request.status === 0 ? 'failed' : 'complete';
18
- }
19
- /**
20
- * Why a request failed, leaving out Chrome stopping an unneeded body after a
21
- * complete response (204/304 report `net::ERR_ABORTED` that way).
22
- *
23
- * @param request - Captured request
24
- * @returns Reason, or undefined when there is none worth showing
25
- */
26
- export function failureReason(request) {
27
- if (!request.errorText)
28
- return undefined;
29
- return getRequestState(request) === 'complete' && request.errorText === BODY_ABORTED
30
- ? undefined
31
- : request.errorText;
32
- }
8
+ import { BODY_ABORTED, getRequestState } from '../../telemetry/requestState.js';
9
+ export { failureReason, getRequestState } from '../../telemetry/requestState.js';
33
10
  /**
34
11
  * Human-readable status: the HTTP status (with the failure reason if loading
35
12
  * failed after the response), `FAILED (<reason>)`, or `pending`.
@@ -47,9 +24,4 @@ export function formatRequestStatus(request) {
47
24
  ? `${request.status} (${request.errorText})`
48
25
  : String(request.status);
49
26
  }
50
- /**
51
- * Error Chrome reports when it stops reading a response body nobody needs
52
- * (the response itself arrived; not a failure of the request).
53
- */
54
- const BODY_ABORTED = 'net::ERR_ABORTED';
55
27
  //# sourceMappingURL=requestStatus.js.map
@@ -0,0 +1,12 @@
1
+ import type { RunningSessionInfo } from '../../session/sessionList.js';
2
+ /**
3
+ * Format the sessions as a table, followed by the cleanup commands of
4
+ * crashed and stale sessions.
5
+ *
6
+ * @param data - Sessions
7
+ * @returns Human-readable list
8
+ */
9
+ export declare function formatSessionList(data: {
10
+ sessions: RunningSessionInfo[];
11
+ }): string;
12
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1,40 @@
1
+ import { OutputFormatter } from '../formatting.js';
2
+ /** Label of the default session in the list */
3
+ const DEFAULT_SESSION_LABEL = '(default)';
4
+ /**
5
+ * Format the sessions as a table, followed by the cleanup commands of
6
+ * crashed and stale sessions.
7
+ *
8
+ * @param data - Sessions
9
+ * @returns Human-readable list
10
+ */
11
+ export function formatSessionList(data) {
12
+ const fmt = new OutputFormatter();
13
+ if (data.sessions.length === 0) {
14
+ return fmt
15
+ .text('No running sessions')
16
+ .hints('Suggestions:', ['Start one: bdg <url> [--session <name>]'])
17
+ .build();
18
+ }
19
+ const rows = data.sessions.map((session) => [
20
+ session.name ?? DEFAULT_SESSION_LABEL,
21
+ session.state,
22
+ session.port?.toString() ?? '-',
23
+ session.daemonPid?.toString() ?? '-',
24
+ session.url ?? '-',
25
+ ]);
26
+ const header = ['SESSION', 'STATE', 'PORT', 'PID', 'URL'];
27
+ const widths = header.map((title, column) => Math.max(title.length, ...rows.map((row) => row[column]?.length ?? 0)));
28
+ for (const row of [header, ...rows]) {
29
+ fmt.text(row
30
+ .map((cell, column) => cell.padEnd(widths[column] ?? 0))
31
+ .join(' ')
32
+ .trimEnd());
33
+ }
34
+ const cleanups = data.sessions.flatMap((session) => (session.cleanup ? [session.cleanup] : []));
35
+ if (cleanups.length > 0) {
36
+ fmt.hints('Crashed or stale sessions; clean up with:', cleanups);
37
+ }
38
+ return fmt.build();
39
+ }
40
+ //# sourceMappingURL=sessions.js.map