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.
- package/README.md +7 -1
- package/dist/cdp/schema.d.ts +4 -1
- package/dist/cdp/schema.js +48 -7
- package/dist/commands/cdp.js +3 -2
- package/dist/commands/cleanup.d.ts +11 -0
- package/dist/commands/cleanup.js +161 -57
- package/dist/commands/console.d.ts +20 -1
- package/dist/commands/console.js +57 -17
- package/dist/commands/details.js +3 -2
- package/dist/commands/dom/DomElementResolver.d.ts +10 -3
- package/dist/commands/dom/DomElementResolver.js +35 -17
- package/dist/commands/dom/a11y.d.ts +10 -0
- package/dist/commands/dom/a11y.js +29 -6
- package/dist/commands/dom/eval.d.ts +3 -1
- package/dist/commands/dom/eval.js +29 -4
- package/dist/commands/dom/form.js +16 -62
- package/dist/commands/dom/formInteraction.js +189 -119
- package/dist/commands/dom/formSummary.d.ts +49 -0
- package/dist/commands/dom/formSummary.js +180 -0
- package/dist/commands/dom/frames.d.ts +2 -1
- package/dist/commands/dom/frames.js +17 -2
- package/dist/commands/dom/get.d.ts +6 -5
- package/dist/commands/dom/get.js +92 -82
- package/dist/commands/dom/helpers/index.d.ts +1 -1
- package/dist/commands/dom/helpers/index.js +1 -1
- package/dist/commands/dom/helpers/keyAttributes.d.ts +20 -0
- package/dist/commands/dom/helpers/keyAttributes.js +54 -0
- package/dist/commands/dom/helpers/query.d.ts +44 -17
- package/dist/commands/dom/helpers/query.js +300 -106
- package/dist/commands/dom/helpers/runElementCommand.d.ts +10 -2
- package/dist/commands/dom/helpers/runElementCommand.js +98 -30
- package/dist/commands/dom/helpers/screenshot.d.ts +4 -1
- package/dist/commands/dom/helpers/screenshot.js +239 -51
- package/dist/commands/dom/index.d.ts +4 -1
- package/dist/commands/dom/index.js +22 -7
- package/dist/commands/dom/inspect.d.ts +15 -0
- package/dist/commands/dom/inspect.js +82 -0
- package/dist/commands/dom/layout.d.ts +14 -0
- package/dist/commands/dom/layout.js +54 -0
- package/dist/commands/dom/listeners.d.ts +5 -1
- package/dist/commands/dom/listeners.js +15 -5
- package/dist/commands/dom/query.js +2 -3
- package/dist/commands/dom/screenshot.d.ts +12 -2
- package/dist/commands/dom/screenshot.js +27 -3
- package/dist/commands/dom/semanticUtils.d.ts +16 -10
- package/dist/commands/dom/semanticUtils.js +53 -16
- package/dist/commands/dom/wait.d.ts +13 -0
- package/dist/commands/dom/wait.js +83 -0
- package/dist/commands/helpJson.js +2 -2
- package/dist/commands/network/list.js +17 -13
- package/dist/commands/optionBehaviors.js +154 -21
- package/dist/commands/page.d.ts +3 -2
- package/dist/commands/page.js +100 -5
- package/dist/commands/peek.js +4 -11
- package/dist/commands/sessions.d.ts +8 -0
- package/dist/commands/sessions.js +19 -0
- package/dist/commands/shared/CommandRunner.js +4 -4
- package/dist/commands/shared/commonOptions.d.ts +4 -0
- package/dist/commands/shared/commonOptions.js +9 -0
- package/dist/commands/shared/dataFetcher.js +2 -2
- package/dist/commands/shared/followMode.d.ts +21 -1
- package/dist/commands/shared/followMode.js +29 -2
- package/dist/commands/shared/handleValidationError.d.ts +2 -2
- package/dist/commands/shared/handleValidationError.js +12 -3
- package/dist/commands/shared/optionTypes.d.ts +61 -5
- package/dist/commands/shared/startHelpers.d.ts +66 -0
- package/dist/commands/shared/startHelpers.js +103 -13
- package/dist/commands/shared/validation.d.ts +14 -2
- package/dist/commands/shared/validation.js +20 -3
- package/dist/commands/start.d.ts +63 -0
- package/dist/commands/start.js +115 -15
- package/dist/commands/status.js +29 -7
- package/dist/commands/stop.js +7 -6
- package/dist/commands/tail.js +4 -11
- package/dist/commands/types.d.ts +2 -0
- package/dist/commands.js +2 -0
- package/dist/connection/chromeIdentity.d.ts +65 -0
- package/dist/connection/chromeIdentity.js +143 -0
- package/dist/connection/launcher/profilePreferences.d.ts +47 -0
- package/dist/connection/launcher/profilePreferences.js +151 -0
- package/dist/connection/launcher.d.ts +21 -2
- package/dist/connection/launcher.js +42 -16
- package/dist/connection/portReservation.d.ts +14 -4
- package/dist/connection/portReservation.js +21 -6
- package/dist/connection/startupExit.d.ts +8 -0
- package/dist/connection/startupExit.js +15 -6
- package/dist/constants.d.ts +6 -2
- package/dist/constants.js +9 -2
- package/dist/daemon/SessionController.js +23 -7
- package/dist/daemon/errors.d.ts +1 -1
- package/dist/daemon/errors.js +1 -1
- package/dist/daemon/launcher.d.ts +10 -2
- package/dist/daemon/launcher.js +8 -7
- package/dist/daemon/server/SocketServer.js +1 -2
- package/dist/daemon/session/Session.d.ts +20 -0
- package/dist/daemon/session/Session.js +80 -9
- package/dist/daemon/session/chromeConnection.d.ts +9 -0
- package/dist/daemon/session/chromeConnection.js +45 -8
- package/dist/daemon/session/commandRegistry.d.ts +14 -1
- package/dist/daemon/session/commandRegistry.js +113 -67
- package/dist/daemon/session/interactions.d.ts +48 -9
- package/dist/daemon/session/interactions.js +46 -9
- package/dist/daemon/session/triggeredRequests.d.ts +67 -0
- package/dist/daemon/session/triggeredRequests.js +157 -0
- package/dist/daemon/session/types.d.ts +5 -1
- package/dist/daemon.js +10630 -3601
- package/dist/errors/messages.d.ts +456 -24
- package/dist/errors/messages.js +862 -67
- package/dist/index.js +6915 -3401
- package/dist/ipc/client.d.ts +21 -1
- package/dist/ipc/client.js +35 -3
- package/dist/ipc/protocol/commands.d.ts +145 -5
- package/dist/ipc/protocol/commands.js +4 -0
- package/dist/ipc/protocol/domTypes.d.ts +291 -7
- package/dist/ipc/protocol/inspectTypes.d.ts +388 -0
- package/dist/ipc/protocol/inspectTypes.js +10 -0
- package/dist/ipc/session/lifecycle.d.ts +8 -1
- package/dist/ipc/session/queries.d.ts +5 -1
- package/dist/ipc/session/types.d.ts +5 -0
- package/dist/ipc/transport/index.d.ts +2 -1
- package/dist/ipc/transport/index.js +2 -2
- package/dist/runtime/dom/actionEffects.d.ts +185 -0
- package/dist/runtime/dom/actionEffects.js +402 -0
- package/dist/runtime/dom/actionEffectsScripts.d.ts +90 -0
- package/dist/runtime/dom/actionEffectsScripts.js +426 -0
- package/dist/runtime/dom/elementGeometry.d.ts +170 -0
- package/dist/runtime/dom/elementGeometry.js +553 -0
- package/dist/runtime/dom/elementInfo.d.ts +103 -0
- package/dist/runtime/dom/elementInfo.js +256 -0
- package/dist/runtime/dom/evalHelpers.d.ts +51 -6
- package/dist/runtime/dom/evalHelpers.js +136 -26
- package/dist/runtime/dom/eventListeners.d.ts +2 -1
- package/dist/runtime/dom/eventListeners.js +184 -47
- package/dist/runtime/dom/formDiscovery.d.ts +1 -1
- package/dist/runtime/dom/formDiscovery.js +116 -16
- package/dist/runtime/dom/formFillHelpers/fill.d.ts +9 -0
- package/dist/runtime/dom/formFillHelpers/fill.js +178 -14
- package/dist/runtime/dom/formFillHelpers/index.d.ts +2 -2
- package/dist/runtime/dom/formFillHelpers/index.js +2 -2
- package/dist/runtime/dom/formFillHelpers/pressKey.js +14 -3
- package/dist/runtime/dom/formFillHelpers/scroll.d.ts +3 -0
- package/dist/runtime/dom/formFillHelpers/scroll.js +60 -18
- package/dist/runtime/dom/formFillHelpers/shared.d.ts +17 -0
- package/dist/runtime/dom/formFillHelpers/shared.js +25 -1
- package/dist/runtime/dom/formFillHelpers/stability.d.ts +20 -6
- package/dist/runtime/dom/formFillHelpers/stability.js +50 -19
- package/dist/runtime/dom/formSubmitHelpers.d.ts +3 -0
- package/dist/runtime/dom/formSubmitHelpers.js +89 -15
- package/dist/runtime/dom/frameLayout.d.ts +60 -0
- package/dist/runtime/dom/frameLayout.js +140 -0
- package/dist/runtime/dom/frameOrigin.d.ts +50 -0
- package/dist/runtime/dom/frameOrigin.js +62 -0
- package/dist/runtime/dom/frameScopedConnection.d.ts +92 -0
- package/dist/runtime/dom/frameScopedConnection.js +252 -0
- package/dist/runtime/dom/frameSelection.d.ts +12 -1
- package/dist/runtime/dom/frameSelection.js +22 -3
- package/dist/runtime/dom/frames.d.ts +61 -5
- package/dist/runtime/dom/frames.js +329 -75
- package/dist/runtime/dom/inspect.d.ts +28 -0
- package/dist/runtime/dom/inspect.js +557 -0
- package/dist/runtime/dom/inspectAllStyles.d.ts +62 -0
- package/dist/runtime/dom/inspectAllStyles.js +385 -0
- package/dist/runtime/dom/inspectCascade.d.ts +94 -0
- package/dist/runtime/dom/inspectCascade.js +371 -0
- package/dist/runtime/dom/inspectCascadeModel.d.ts +39 -0
- package/dist/runtime/dom/inspectCascadeModel.js +232 -0
- package/dist/runtime/dom/inspectHints.d.ts +62 -0
- package/dist/runtime/dom/inspectHints.js +305 -0
- package/dist/runtime/dom/inspectLayoutModel.d.ts +87 -0
- package/dist/runtime/dom/inspectLayoutModel.js +346 -0
- package/dist/runtime/dom/inspectModel.d.ts +74 -0
- package/dist/runtime/dom/inspectModel.js +184 -0
- package/dist/runtime/dom/inspectPaintModel.d.ts +157 -0
- package/dist/runtime/dom/inspectPaintModel.js +461 -0
- package/dist/runtime/dom/inspectRules.d.ts +37 -0
- package/dist/runtime/dom/inspectRules.js +101 -0
- package/dist/runtime/dom/inspectScripts.d.ts +132 -0
- package/dist/runtime/dom/inspectScripts.js +263 -0
- package/dist/runtime/dom/inspectTree.d.ts +40 -0
- package/dist/runtime/dom/inspectTree.js +134 -0
- package/dist/runtime/dom/inspectVariables.d.ts +33 -0
- package/dist/runtime/dom/inspectVariables.js +94 -0
- package/dist/runtime/dom/inspectWhyModel.d.ts +20 -0
- package/dist/runtime/dom/inspectWhyModel.js +134 -0
- package/dist/runtime/dom/layout.d.ts +71 -0
- package/dist/runtime/dom/layout.js +340 -0
- package/dist/runtime/dom/listenerPageScripts.d.ts +72 -0
- package/dist/runtime/dom/listenerPageScripts.js +365 -0
- package/dist/runtime/dom/listenerSummary.d.ts +136 -11
- package/dist/runtime/dom/listenerSummary.js +361 -22
- package/dist/runtime/dom/pageActivity.d.ts +41 -0
- package/dist/runtime/dom/pageActivity.js +123 -0
- package/dist/runtime/dom/reactEventHelpers.d.ts +63 -2
- package/dist/runtime/dom/reactEventHelpers.js +220 -41
- package/dist/runtime/dom/targetNode.d.ts +80 -27
- package/dist/runtime/dom/targetNode.js +249 -33
- package/dist/runtime/dom/wait.d.ts +25 -0
- package/dist/runtime/dom/wait.js +199 -0
- package/dist/runtime/dom/waitCondition.d.ts +71 -0
- package/dist/runtime/dom/waitCondition.js +75 -0
- package/dist/runtime/page/emulation.d.ts +71 -0
- package/dist/runtime/page/emulation.js +117 -0
- package/dist/runtime/page/loadingState.d.ts +36 -0
- package/dist/runtime/page/loadingState.js +86 -0
- package/dist/runtime/page/navigation.d.ts +46 -2
- package/dist/runtime/page/navigation.js +69 -33
- package/dist/session/QueryCacheManager.d.ts +11 -1
- package/dist/session/QueryCacheManager.js +25 -3
- package/dist/session/chromeOwners.d.ts +34 -0
- package/dist/session/chromeOwners.js +51 -0
- package/dist/session/cleanup/staleSession.d.ts +11 -1
- package/dist/session/cleanup/staleSession.js +17 -6
- package/dist/session/cleanup/userCommands.js +2 -4
- package/dist/session/metadata.d.ts +5 -1
- package/dist/session/metadata.js +2 -1
- package/dist/session/paths.d.ts +77 -3
- package/dist/session/paths.js +111 -5
- package/dist/session/port.d.ts +31 -7
- package/dist/session/port.js +50 -43
- package/dist/session/portClaims.d.ts +66 -0
- package/dist/session/portClaims.js +284 -0
- package/dist/session/sessionList.d.ts +58 -0
- package/dist/session/sessionList.js +199 -0
- package/dist/session/sessionName.d.ts +46 -0
- package/dist/session/sessionName.js +97 -0
- package/dist/telemetry/a11y.d.ts +18 -3
- package/dist/telemetry/a11y.js +170 -29
- package/dist/telemetry/console.d.ts +1 -0
- package/dist/telemetry/console.js +100 -5
- package/dist/telemetry/network.js +3 -1
- package/dist/telemetry/requestKinds.d.ts +32 -0
- package/dist/telemetry/requestKinds.js +61 -0
- package/dist/telemetry/requestState.d.ts +31 -0
- package/dist/telemetry/requestState.js +38 -0
- package/dist/types.d.ts +112 -3
- package/dist/ui/formatters/a11y.js +3 -0
- package/dist/ui/formatters/console/chronological.d.ts +8 -0
- package/dist/ui/formatters/console/chronological.js +17 -4
- package/dist/ui/formatters/console/json.js +3 -4
- package/dist/ui/formatters/console/shared.d.ts +12 -0
- package/dist/ui/formatters/console.d.ts +2 -2
- package/dist/ui/formatters/console.js +1 -1
- package/dist/ui/formatters/details.d.ts +8 -0
- package/dist/ui/formatters/details.js +61 -4
- package/dist/ui/formatters/dom.d.ts +27 -14
- package/dist/ui/formatters/dom.js +88 -59
- package/dist/ui/formatters/form.js +29 -18
- package/dist/ui/formatters/inspect.d.ts +39 -0
- package/dist/ui/formatters/inspect.js +596 -0
- package/dist/ui/formatters/keyAttributes.d.ts +19 -0
- package/dist/ui/formatters/keyAttributes.js +84 -0
- package/dist/ui/formatters/layout.d.ts +31 -0
- package/dist/ui/formatters/layout.js +53 -0
- package/dist/ui/formatters/listeners.d.ts +3 -2
- package/dist/ui/formatters/listeners.js +73 -9
- package/dist/ui/formatters/networkHeaders.d.ts +13 -0
- package/dist/ui/formatters/networkHeaders.js +36 -3
- package/dist/ui/formatters/networkList.d.ts +29 -1
- package/dist/ui/formatters/networkList.js +86 -20
- package/dist/ui/formatters/preview.js +2 -1
- package/dist/ui/formatters/requestStatus.d.ts +1 -17
- package/dist/ui/formatters/requestStatus.js +2 -30
- package/dist/ui/formatters/sessions.d.ts +12 -0
- package/dist/ui/formatters/sessions.js +40 -0
- package/dist/ui/formatters/status.d.ts +21 -2
- package/dist/ui/formatters/status.js +47 -10
- package/dist/ui/formatters/triggeredRequests.d.ts +36 -0
- package/dist/ui/formatters/triggeredRequests.js +65 -0
- package/dist/ui/formatting.d.ts +19 -0
- package/dist/ui/formatting.js +31 -36
- package/dist/ui/messages/chrome.d.ts +9 -0
- package/dist/ui/messages/chrome.js +17 -5
- package/dist/ui/messages/commands.d.ts +504 -14
- package/dist/ui/messages/commands.js +835 -21
- package/dist/ui/messages/consoleMessages.d.ts +10 -0
- package/dist/ui/messages/consoleMessages.js +17 -0
- package/dist/ui/messages/hints.js +2 -1
- package/dist/ui/messages/networkMessages.d.ts +14 -0
- package/dist/ui/messages/networkMessages.js +18 -0
- package/dist/ui/messages/preview.js +5 -4
- package/dist/ui/messages/session.d.ts +30 -21
- package/dist/ui/messages/session.js +48 -26
- package/dist/ui/messages/sessionCommand.d.ts +43 -0
- package/dist/ui/messages/sessionCommand.js +52 -0
- package/dist/utils/async.d.ts +17 -0
- package/dist/utils/async.js +36 -0
- package/dist/utils/color.d.ts +84 -0
- package/dist/utils/color.js +376 -0
- package/dist/utils/cssValues.d.ts +109 -0
- package/dist/utils/cssValues.js +236 -0
- package/dist/utils/http.d.ts +22 -1
- package/dist/utils/http.js +28 -9
- package/dist/utils/selectorFilters.d.ts +48 -8
- package/dist/utils/selectorFilters.js +296 -53
- package/dist/utils/shellDetection.d.ts +8 -2
- package/dist/utils/shellDetection.js +120 -33
- package/dist/utils/suggestions.d.ts +26 -0
- package/dist/utils/suggestions.js +73 -0
- package/dist/utils/taskMappings.js +10 -0
- package/dist/utils/url.d.ts +12 -2
- package/dist/utils/url.js +69 -7
- package/package.json +1 -1
- package/dist/ui/formatters/sessionFormatters.d.ts +0 -58
- 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,
|
|
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 {
|
|
4
|
+
import { delegationNotes } from '../../runtime/dom/listenerSummary.js';
|
|
5
5
|
import { OutputFormatter } from '../formatting.js';
|
|
6
|
-
import { NO_LISTENERS_HINT,
|
|
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
|
-
*
|
|
59
|
-
*
|
|
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
|
-
|
|
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
|
|
100
|
+
fmt.text(listenersHeadline(result.element, listenerCounts(result.listeners, collapsed), result));
|
|
73
101
|
appendListenerGroups(fmt, result.listeners);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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(
|
|
48
|
-
return `${'[ID]'.padEnd(
|
|
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
|
|
55
|
-
* @param
|
|
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,
|
|
59
|
-
const id = `[${request.requestId}]`.padEnd(
|
|
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(
|
|
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
|
|
66
|
-
|
|
67
|
-
|
|
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
|
|
95
|
-
fmt.text(formatColumnHeader(
|
|
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,
|
|
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
|
|
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(
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|