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
|
@@ -4,7 +4,7 @@ import { daemonNotRunningError, unknownError, genericError, commandTimedOutError
|
|
|
4
4
|
import { IPCEarlyCloseError, IPCTimeoutError } from '../../ipc/transport/IPCError.js';
|
|
5
5
|
import { OutputBuilder, buildSuccessResponse } from '../../ui/OutputBuilder.js';
|
|
6
6
|
import { escapeControlChars } from '../../ui/formatting.js';
|
|
7
|
-
import {
|
|
7
|
+
import { noActiveSessionMessage, startSessionSuggestion } from '../../ui/messages/sessionCommand.js';
|
|
8
8
|
import { getErrorExitCode, getErrorMessage } from '../../utils/errors.js';
|
|
9
9
|
import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
10
10
|
/**
|
|
@@ -13,7 +13,7 @@ import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
|
13
13
|
* @returns Command error (exit 83) with how to start one
|
|
14
14
|
*/
|
|
15
15
|
export function noActiveSessionError() {
|
|
16
|
-
return new CommandError(
|
|
16
|
+
return new CommandError(noActiveSessionMessage(), { suggestion: startSessionSuggestion() }, EXIT_CODES.RESOURCE_NOT_FOUND);
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Execute an async function and output JSON result with proper error handling.
|
|
@@ -168,8 +168,8 @@ export async function runCommand(handler, options, formatter) {
|
|
|
168
168
|
const errorMessage = getErrorMessage(error);
|
|
169
169
|
if (isDaemonConnectionError(error)) {
|
|
170
170
|
if (options.json) {
|
|
171
|
-
console.log(JSON.stringify(OutputBuilder.buildJsonError(
|
|
172
|
-
suggestion:
|
|
171
|
+
console.log(JSON.stringify(OutputBuilder.buildJsonError(noActiveSessionMessage(), {
|
|
172
|
+
suggestion: startSessionSuggestion(),
|
|
173
173
|
exitCode: EXIT_CODES.RESOURCE_NOT_FOUND,
|
|
174
174
|
}), null, 2));
|
|
175
175
|
}
|
|
@@ -30,4 +30,8 @@ export declare function showBothSectionsWhenBothRequested(options: {
|
|
|
30
30
|
network?: boolean;
|
|
31
31
|
console?: boolean;
|
|
32
32
|
}): void;
|
|
33
|
+
/** Help of a `<selectorOrIndex>` argument */
|
|
34
|
+
export declare const SELECTOR_OR_INDEX_ARGUMENT = "CSS selector (searches open shadow roots and same-origin iframes) or numeric index from query results (0-based)";
|
|
35
|
+
/** Help text after `dom query`'s options: what selectors search and what they cannot */
|
|
36
|
+
export declare const SELECTOR_SCOPE_HELP = "\nSelectors search the page, open shadow roots and same-origin iframes (nested ones\nincluded). They cannot reach into closed shadow roots or cross-origin iframes:\nuse bdg dom eval --frame <frame> for those (see bdg dom frames).";
|
|
33
37
|
//# sourceMappingURL=commonOptions.d.ts.map
|
|
@@ -34,4 +34,13 @@ export function showBothSectionsWhenBothRequested(options) {
|
|
|
34
34
|
options.console = false;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
/** Where selectors search, for the help of commands that take one */
|
|
38
|
+
const SELECTOR_SCOPE = 'searches open shadow roots and same-origin iframes';
|
|
39
|
+
/** Help of a `<selectorOrIndex>` argument */
|
|
40
|
+
export const SELECTOR_OR_INDEX_ARGUMENT = `CSS selector (${SELECTOR_SCOPE}) or numeric index from query results (0-based)`;
|
|
41
|
+
/** Help text after `dom query`'s options: what selectors search and what they cannot */
|
|
42
|
+
export const SELECTOR_SCOPE_HELP = `
|
|
43
|
+
Selectors search the page, open shadow roots and same-origin iframes (nested ones
|
|
44
|
+
included). They cannot reach into closed shadow roots or cross-origin iframes:
|
|
45
|
+
use bdg dom eval --frame <frame> for those (see bdg dom frames).`;
|
|
37
46
|
//# sourceMappingURL=commonOptions.js.map
|
|
@@ -7,7 +7,7 @@ import { validateIPCResponse } from '../../ipc/index.js';
|
|
|
7
7
|
import { IPCConnectionError, IPCEarlyCloseError, IPCTimeoutError, } from '../../ipc/transport/IPCError.js';
|
|
8
8
|
import { isConnectionError } from '../../ipc/utils/errors.js';
|
|
9
9
|
import { createLogger } from '../../ui/logging/index.js';
|
|
10
|
-
import {
|
|
10
|
+
import { noActiveSessionMessage } from '../../ui/messages/sessionCommand.js';
|
|
11
11
|
import { getExitCodeForConnectionError } from '../../utils/errorMapping.js';
|
|
12
12
|
import { getErrorMessage } from '../../utils/errors.js';
|
|
13
13
|
import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
@@ -42,7 +42,7 @@ export async function fetchPreviewOutput(query = {}) {
|
|
|
42
42
|
log.debug(`Daemon unreachable: ${getErrorMessage(error)}`);
|
|
43
43
|
return {
|
|
44
44
|
success: false,
|
|
45
|
-
error:
|
|
45
|
+
error: noActiveSessionMessage(),
|
|
46
46
|
exitCode: EXIT_CODES.RESOURCE_NOT_FOUND,
|
|
47
47
|
};
|
|
48
48
|
}
|
|
@@ -4,6 +4,25 @@
|
|
|
4
4
|
* Provides a unified pattern for commands that continuously poll
|
|
5
5
|
* and display updates (like tail -f behavior).
|
|
6
6
|
*/
|
|
7
|
+
/** What a refresh asks for: nothing to keep following, or the exit code to stop with */
|
|
8
|
+
export type FollowPoll = {
|
|
9
|
+
exitCode: number;
|
|
10
|
+
} | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Report a failed fetch in follow mode: a lost connection is reported and
|
|
13
|
+
* retried while the session was seen before, otherwise follow mode stops.
|
|
14
|
+
*
|
|
15
|
+
* @param failure - The fetch's error and exit code
|
|
16
|
+
* @param options - JSON output and the retry interval shown
|
|
17
|
+
* @returns The exit code to stop with, or undefined to keep following
|
|
18
|
+
*/
|
|
19
|
+
export declare function followFetchFailure(failure: {
|
|
20
|
+
error: string;
|
|
21
|
+
exitCode?: number | undefined;
|
|
22
|
+
}, options: {
|
|
23
|
+
json?: boolean | undefined;
|
|
24
|
+
retryIntervalMs: number;
|
|
25
|
+
}): FollowPoll;
|
|
7
26
|
/**
|
|
8
27
|
* Options for configuring follow mode behavior.
|
|
9
28
|
*/
|
|
@@ -24,6 +43,7 @@ export interface FollowModeOptions {
|
|
|
24
43
|
* - First refresh call (awaited)
|
|
25
44
|
* - Periodic interval-based refresh
|
|
26
45
|
* - SIGINT handler for graceful shutdown
|
|
46
|
+
* - Stopping with the exit code a refresh returns (e.g. the session is gone)
|
|
27
47
|
*
|
|
28
48
|
* @param refreshFn - Async function to call on each refresh cycle
|
|
29
49
|
* @param options - Configuration options for follow mode
|
|
@@ -43,5 +63,5 @@ export interface FollowModeOptions {
|
|
|
43
63
|
* );
|
|
44
64
|
* ```
|
|
45
65
|
*/
|
|
46
|
-
export declare function setupFollowMode(refreshFn: () => Promise<
|
|
66
|
+
export declare function setupFollowMode(refreshFn: () => Promise<FollowPoll>, options: FollowModeOptions): Promise<void>;
|
|
47
67
|
//# sourceMappingURL=followMode.d.ts.map
|
|
@@ -4,9 +4,29 @@
|
|
|
4
4
|
* Provides a unified pattern for commands that continuously poll
|
|
5
5
|
* and display updates (like tail -f behavior).
|
|
6
6
|
*/
|
|
7
|
+
import { handleDaemonConnectionError } from './daemonErrorHandler.js';
|
|
7
8
|
import { genericError } from '../../errors/messages.js';
|
|
8
9
|
import { getErrorMessage } from '../../utils/errors.js';
|
|
9
10
|
import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
11
|
+
/**
|
|
12
|
+
* Report a failed fetch in follow mode: a lost connection is reported and
|
|
13
|
+
* retried while the session was seen before, otherwise follow mode stops.
|
|
14
|
+
*
|
|
15
|
+
* @param failure - The fetch's error and exit code
|
|
16
|
+
* @param options - JSON output and the retry interval shown
|
|
17
|
+
* @returns The exit code to stop with, or undefined to keep following
|
|
18
|
+
*/
|
|
19
|
+
export function followFetchFailure(failure, options) {
|
|
20
|
+
const result = handleDaemonConnectionError(failure.error, {
|
|
21
|
+
json: options.json,
|
|
22
|
+
follow: true,
|
|
23
|
+
retryIntervalMs: options.retryIntervalMs,
|
|
24
|
+
exitCode: failure.exitCode,
|
|
25
|
+
});
|
|
26
|
+
return result.shouldExit
|
|
27
|
+
? { exitCode: result.exitCode ?? EXIT_CODES.RESOURCE_NOT_FOUND }
|
|
28
|
+
: undefined;
|
|
29
|
+
}
|
|
10
30
|
/**
|
|
11
31
|
* Sets up follow mode with periodic refresh and graceful shutdown.
|
|
12
32
|
*
|
|
@@ -16,6 +36,7 @@ import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
|
16
36
|
* - First refresh call (awaited)
|
|
17
37
|
* - Periodic interval-based refresh
|
|
18
38
|
* - SIGINT handler for graceful shutdown
|
|
39
|
+
* - Stopping with the exit code a refresh returns (e.g. the session is gone)
|
|
19
40
|
*
|
|
20
41
|
* @param refreshFn - Async function to call on each refresh cycle
|
|
21
42
|
* @param options - Configuration options for follow mode
|
|
@@ -37,10 +58,16 @@ import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
|
37
58
|
*/
|
|
38
59
|
export async function setupFollowMode(refreshFn, options) {
|
|
39
60
|
const { startMessage, stopMessage, intervalMs = 1000 } = options;
|
|
61
|
+
const stopIfAsked = (poll) => {
|
|
62
|
+
if (poll)
|
|
63
|
+
process.exit(poll.exitCode);
|
|
64
|
+
};
|
|
40
65
|
console.error(startMessage());
|
|
41
|
-
await refreshFn();
|
|
66
|
+
stopIfAsked(await refreshFn());
|
|
42
67
|
const intervalId = setInterval(() => {
|
|
43
|
-
refreshFn()
|
|
68
|
+
refreshFn()
|
|
69
|
+
.then(stopIfAsked)
|
|
70
|
+
.catch((error) => {
|
|
44
71
|
console.error(genericError(getErrorMessage(error)));
|
|
45
72
|
});
|
|
46
73
|
}, intervalMs);
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*
|
|
5
5
|
* For `CommandError`, emits either a JSON envelope (when `json=true`) or
|
|
6
6
|
* a human-readable message + suggestion, then exits with the error's own
|
|
7
|
-
* exit code. For anything else, prints the message
|
|
8
|
-
* `INVALID_ARGUMENTS`.
|
|
7
|
+
* exit code. For anything else, prints the message (as an envelope with
|
|
8
|
+
* `--json`) and exits with `INVALID_ARGUMENTS`.
|
|
9
9
|
*
|
|
10
10
|
* @param error - Error thrown from validation code
|
|
11
11
|
* @param json - Whether the caller is in `--json` output mode
|
|
@@ -9,8 +9,8 @@ import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
|
9
9
|
*
|
|
10
10
|
* For `CommandError`, emits either a JSON envelope (when `json=true`) or
|
|
11
11
|
* a human-readable message + suggestion, then exits with the error's own
|
|
12
|
-
* exit code. For anything else, prints the message
|
|
13
|
-
* `INVALID_ARGUMENTS`.
|
|
12
|
+
* exit code. For anything else, prints the message (as an envelope with
|
|
13
|
+
* `--json`) and exits with `INVALID_ARGUMENTS`.
|
|
14
14
|
*
|
|
15
15
|
* @param error - Error thrown from validation code
|
|
16
16
|
* @param json - Whether the caller is in `--json` output mode
|
|
@@ -33,7 +33,16 @@ export function handleValidationError(error, json) {
|
|
|
33
33
|
}
|
|
34
34
|
process.exit(error.exitCode);
|
|
35
35
|
}
|
|
36
|
-
|
|
36
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
37
|
+
if (json) {
|
|
38
|
+
const envelope = OutputBuilder.buildJsonError(message, {
|
|
39
|
+
exitCode: EXIT_CODES.INVALID_ARGUMENTS,
|
|
40
|
+
});
|
|
41
|
+
console.log(JSON.stringify(envelope, null, 2));
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
console.error(genericError(message));
|
|
45
|
+
}
|
|
37
46
|
process.exit(EXIT_CODES.INVALID_ARGUMENTS);
|
|
38
47
|
}
|
|
39
48
|
//# sourceMappingURL=handleValidationError.js.map
|
|
@@ -25,6 +25,8 @@ export interface BaseOptions {
|
|
|
25
25
|
json?: boolean;
|
|
26
26
|
/** Hide tips and hints (`-q`, accepted by every command) */
|
|
27
27
|
quiet?: boolean;
|
|
28
|
+
/** Named session to act on (`--session`, accepted by every command) */
|
|
29
|
+
session?: string;
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
30
32
|
* Options for commands with verbose output.
|
|
@@ -58,6 +60,8 @@ export interface CleanupOptions {
|
|
|
58
60
|
removeOutput?: boolean;
|
|
59
61
|
/** Aggressive cleanup - kill all Chrome processes */
|
|
60
62
|
aggressive?: boolean;
|
|
63
|
+
/** Also delete the named session's directory (profile, logs, port) */
|
|
64
|
+
purge?: boolean;
|
|
61
65
|
}
|
|
62
66
|
/**
|
|
63
67
|
* Options for commands with raw output mode.
|
|
@@ -138,12 +142,17 @@ export type DetailsCommandOptions = BaseOptions & {
|
|
|
138
142
|
/** Options for DOM query command */
|
|
139
143
|
export type DomQueryCommandOptions = BaseOptions;
|
|
140
144
|
/** Options for DOM get command */
|
|
141
|
-
export type DomGetCommandOptions = BaseOptions & RawOptions & SelectionOptions
|
|
145
|
+
export type DomGetCommandOptions = BaseOptions & RawOptions & SelectionOptions & {
|
|
146
|
+
/** All of the element's text instead of its first 500 characters (semantic output) */
|
|
147
|
+
full?: boolean;
|
|
148
|
+
/** Which match of the selector (0-based); `--nth` is its alias */
|
|
149
|
+
index?: number;
|
|
150
|
+
};
|
|
142
151
|
/** Options for DOM screenshot command */
|
|
143
152
|
export type DomScreenshotCommandOptions = BaseOptions & ScreenshotOptions;
|
|
144
153
|
/** Options for DOM eval command */
|
|
145
154
|
export interface DomEvalCommandOptions extends BaseOptions {
|
|
146
|
-
/** Iframe to evaluate in: index, name/id attribute, or part of the URL */
|
|
155
|
+
/** Iframe to evaluate in: index, name/id attribute, or part of the name, id or URL */
|
|
147
156
|
frame?: string;
|
|
148
157
|
}
|
|
149
158
|
/** Options for DOM frames command */
|
|
@@ -174,6 +183,8 @@ export interface ClickCommandOptions extends BaseOptions, IndexOptions {
|
|
|
174
183
|
double?: boolean;
|
|
175
184
|
/** Right-click */
|
|
176
185
|
right?: boolean;
|
|
186
|
+
/** Refuse instead of falling back to DOM events when the mouse can't reach the element */
|
|
187
|
+
strict?: boolean;
|
|
177
188
|
}
|
|
178
189
|
/**
|
|
179
190
|
* Options for submit command.
|
|
@@ -218,13 +229,54 @@ export interface ScrollCommandOptions extends BaseOptions, IndexOptions {
|
|
|
218
229
|
* Options for `dom listeners`.
|
|
219
230
|
*/
|
|
220
231
|
export interface ListenersCommandOptions extends BaseOptions, IndexOptions {
|
|
221
|
-
/** Only these event types (from --type, comma-separated) */
|
|
232
|
+
/** Only these event types (from --type, comma-separated, repeatable) */
|
|
222
233
|
type?: string[];
|
|
234
|
+
/** List every listener of framework roots */
|
|
235
|
+
all?: boolean;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Options for `dom layout`.
|
|
239
|
+
*/
|
|
240
|
+
export type LayoutCommandOptions = BaseOptions & IndexOptions;
|
|
241
|
+
/**
|
|
242
|
+
* Options for `dom inspect`.
|
|
243
|
+
*/
|
|
244
|
+
export interface InspectCommandOptions extends BaseOptions, IndexOptions {
|
|
245
|
+
/** Child tree depth (0 for none) */
|
|
246
|
+
tree?: number;
|
|
247
|
+
/** Child tree rows at most */
|
|
248
|
+
treeLimit?: number;
|
|
249
|
+
/** Every non-default property instead of the groups */
|
|
250
|
+
all?: boolean;
|
|
251
|
+
/** Only these properties */
|
|
252
|
+
props?: string[];
|
|
253
|
+
/** Which declaration sets each shown property */
|
|
254
|
+
rules?: boolean;
|
|
255
|
+
/** Every declaration of this property */
|
|
256
|
+
why?: string;
|
|
257
|
+
/** `--no-hints` sets false */
|
|
258
|
+
hints?: boolean;
|
|
259
|
+
}
|
|
260
|
+
/** Options for `bdg dom wait` */
|
|
261
|
+
export interface WaitCommandOptions extends BaseOptions {
|
|
262
|
+
/** Text a match must contain */
|
|
263
|
+
text?: string;
|
|
264
|
+
/** Wait for the matches to be gone */
|
|
265
|
+
gone?: boolean;
|
|
266
|
+
/** Only count visible matches */
|
|
267
|
+
visible?: boolean;
|
|
268
|
+
/** Wait for document.readyState to be complete */
|
|
269
|
+
load?: boolean;
|
|
270
|
+
/** Give up after this many milliseconds */
|
|
271
|
+
timeout: number;
|
|
223
272
|
}
|
|
224
273
|
/** Options for A11y tree command */
|
|
225
274
|
export type A11yTreeCommandOptions = BaseOptions;
|
|
226
275
|
/** Options for A11y query command */
|
|
227
|
-
export
|
|
276
|
+
export interface A11yQueryCommandOptions extends BaseOptions {
|
|
277
|
+
/** Matches to list (0 = all) */
|
|
278
|
+
limit?: number;
|
|
279
|
+
}
|
|
228
280
|
/** Options for A11y describe command */
|
|
229
281
|
export type A11yDescribeCommandOptions = BaseOptions;
|
|
230
282
|
/** Options for CDP command */
|
|
@@ -274,9 +326,13 @@ export interface SessionStartOptions {
|
|
|
274
326
|
json?: boolean | undefined;
|
|
275
327
|
/** Custom Chrome flags (e.g., ['--ignore-certificate-errors']) */
|
|
276
328
|
chromeFlags: string[] | undefined;
|
|
329
|
+
/** Viewport size to emulate (`--viewport`) */
|
|
330
|
+
viewport?: ViewportSize | undefined;
|
|
331
|
+
/** `prefers-color-scheme` to emulate (`--color-scheme`) */
|
|
332
|
+
colorScheme?: ColorScheme | undefined;
|
|
277
333
|
}
|
|
278
334
|
export type { ConsoleLevel } from '../../types.js';
|
|
279
|
-
import type { ConsoleLevel } from '../../types.js';
|
|
335
|
+
import type { ColorScheme, ConsoleLevel, ViewportSize } from '../../types.js';
|
|
280
336
|
/**
|
|
281
337
|
* Options for console command.
|
|
282
338
|
* Supports smart summary (default), list view (--list), and streaming (--follow).
|
|
@@ -5,7 +5,48 @@
|
|
|
5
5
|
* Handles IPC communication with daemon to start browser sessions.
|
|
6
6
|
*/
|
|
7
7
|
import type { SessionStartOptions } from './optionTypes.js';
|
|
8
|
+
import { type SpawnedDaemon } from '../../daemon/launcher.js';
|
|
9
|
+
import { startSession as sendStartSessionRequest } from '../../ipc/client.js';
|
|
10
|
+
import { IPCErrorCode, type StartSessionResponseData } from '../../ipc/index.js';
|
|
8
11
|
import type { TelemetryType } from '../../types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Outcome of a start attempt, printed by {@link reportStartOutcome}.
|
|
14
|
+
*/
|
|
15
|
+
export type StartOutcome = {
|
|
16
|
+
ok: true;
|
|
17
|
+
data: StartSessionResponseData;
|
|
18
|
+
} | {
|
|
19
|
+
ok: false;
|
|
20
|
+
/** Message for `--json` (no "Error:" prefix) */
|
|
21
|
+
error: string;
|
|
22
|
+
/** Full human-readable message */
|
|
23
|
+
human: string;
|
|
24
|
+
exitCode: number;
|
|
25
|
+
/** Daemon's error code (internal: not printed) */
|
|
26
|
+
errorCode?: IPCErrorCode | undefined;
|
|
27
|
+
/** Extra fields of the JSON error envelope */
|
|
28
|
+
details?: Record<string, unknown>;
|
|
29
|
+
/** The daemon went away mid-request (e.g. the previous session was ending) */
|
|
30
|
+
retryable?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The daemon reported the failure or dropped the connection, so it is
|
|
33
|
+
* exiting (a daemon this start spawned is then waited for)
|
|
34
|
+
*/
|
|
35
|
+
daemonExiting?: boolean;
|
|
36
|
+
/** The daemon this attempt spawned, when it is exiting */
|
|
37
|
+
spawned?: SpawnedDaemon;
|
|
38
|
+
};
|
|
39
|
+
/** How long a failed start waits for the daemons it spawned to exit */
|
|
40
|
+
export declare const SPAWNED_DAEMON_EXIT_WAIT_MS = 3000;
|
|
41
|
+
/** What a start uses to reach the daemon (replaced in tests) */
|
|
42
|
+
export interface StartDeps {
|
|
43
|
+
/** Spawns the daemon if none runs ({@link launchDaemon}) */
|
|
44
|
+
launch: () => Promise<SpawnedDaemon | undefined>;
|
|
45
|
+
/** Sends `start_session_request` */
|
|
46
|
+
send: typeof sendStartSessionRequest;
|
|
47
|
+
/** How long a failed start waits for the daemons it spawned to exit */
|
|
48
|
+
exitWaitMs: number;
|
|
49
|
+
}
|
|
9
50
|
/**
|
|
10
51
|
* Start a session via the daemon and report the result.
|
|
11
52
|
*
|
|
@@ -17,4 +58,29 @@ import type { TelemetryType } from '../../types.js';
|
|
|
17
58
|
* @param telemetry - Array of telemetry types to enable
|
|
18
59
|
*/
|
|
19
60
|
export declare function startSessionViaDaemon(url: string, options: SessionStartOptions, telemetry: TelemetryType[]): Promise<never>;
|
|
61
|
+
/**
|
|
62
|
+
* Start a session, retrying while the previous session shuts down. After a
|
|
63
|
+
* failure the daemon reported (or a dropped connection), it waits for every
|
|
64
|
+
* daemon the attempts spawned to exit ({@link afterSpawnedDaemonExit}).
|
|
65
|
+
*
|
|
66
|
+
* @param url - Target URL
|
|
67
|
+
* @param options - Session options
|
|
68
|
+
* @param telemetry - Telemetry types
|
|
69
|
+
* @param deps - How to reach the daemon (tests replace it)
|
|
70
|
+
* @returns Start outcome, ready to report
|
|
71
|
+
*/
|
|
72
|
+
export declare function attemptStart(url: string, options: SessionStartOptions, telemetry: TelemetryType[], deps?: StartDeps): Promise<StartOutcome>;
|
|
73
|
+
/**
|
|
74
|
+
* Let the daemons a failed start spawned finish exiting before the error is
|
|
75
|
+
* reported: a daemon removes its session files on the way out, and a command
|
|
76
|
+
* run right after (`bdg sessions`, another start) would otherwise still see
|
|
77
|
+
* the session as starting. The wait is bounded; a daemon still running after
|
|
78
|
+
* it is reported (`details.daemonStillRunning`, `daemonPid`, a suggestion).
|
|
79
|
+
*
|
|
80
|
+
* @param outcome - Start outcome
|
|
81
|
+
* @param spawned - Exiting daemons the attempts spawned
|
|
82
|
+
* @param waitMs - Milliseconds to wait at most for all of them
|
|
83
|
+
* @returns The failure (without internal fields), with a hint when a daemon did not exit in time
|
|
84
|
+
*/
|
|
85
|
+
export declare function afterSpawnedDaemonExit(outcome: StartOutcome, spawned: SpawnedDaemon[], waitMs: number): Promise<StartOutcome>;
|
|
20
86
|
//# sourceMappingURL=startHelpers.d.ts.map
|
|
@@ -8,21 +8,30 @@ import { timeoutError } from './CommandRunner.js';
|
|
|
8
8
|
import { landingPage } from './landingPage.js';
|
|
9
9
|
import { DaemonError, SessionDirError } from '../../daemon/errors.js';
|
|
10
10
|
import { launchDaemon } from '../../daemon/launcher.js';
|
|
11
|
-
import { LAUNCHED_CHROME_DESCRIPTION, sessionAlreadyRunningError,
|
|
11
|
+
import { LAUNCHED_CHROME_DESCRIPTION, sessionAlreadyRunningError, alreadyRunningSuggestion, sessionTargetMismatchError, daemonNotRunningError, invalidResponseError, genericError, } from '../../errors/messages.js';
|
|
12
12
|
import { startSession as sendStartSessionRequest } from '../../ipc/client.js';
|
|
13
13
|
import { IPCErrorCode, } from '../../ipc/index.js';
|
|
14
14
|
import { IPCTimeoutError } from '../../ipc/transport/index.js';
|
|
15
15
|
import { isConnectionError } from '../../ipc/utils/errors.js';
|
|
16
|
+
import { getSessionName } from '../../session/paths.js';
|
|
16
17
|
import { OutputBuilder, buildSuccessResponse } from '../../ui/OutputBuilder.js';
|
|
17
18
|
import { escapeControlChars, joinLines } from '../../ui/formatting.js';
|
|
18
19
|
import { createLogger } from '../../ui/logging/index.js';
|
|
19
|
-
import { startNotices } from '../../ui/messages/session.js';
|
|
20
|
-
import {
|
|
20
|
+
import { daemonStillExitingHint, daemonStillExitingSuggestion, startNotices, } from '../../ui/messages/session.js';
|
|
21
|
+
import { noActiveSessionMessage } from '../../ui/messages/sessionCommand.js';
|
|
22
|
+
import { delay, waitUntil } from '../../utils/async.js';
|
|
21
23
|
import { getExitCodeForIPCError } from '../../utils/errorMapping.js';
|
|
22
24
|
import { getErrorMessage } from '../../utils/errors.js';
|
|
23
25
|
import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
24
26
|
import { filterDefined } from '../../utils/objects.js';
|
|
25
27
|
const log = createLogger('bdg');
|
|
28
|
+
/** How long a failed start waits for the daemons it spawned to exit */
|
|
29
|
+
export const SPAWNED_DAEMON_EXIT_WAIT_MS = 3000;
|
|
30
|
+
const DEFAULT_START_DEPS = {
|
|
31
|
+
launch: launchDaemon,
|
|
32
|
+
send: sendStartSessionRequest,
|
|
33
|
+
exitWaitMs: SPAWNED_DAEMON_EXIT_WAIT_MS,
|
|
34
|
+
};
|
|
26
35
|
/**
|
|
27
36
|
* Start a session via the daemon and report the result.
|
|
28
37
|
*
|
|
@@ -36,13 +45,69 @@ const log = createLogger('bdg');
|
|
|
36
45
|
export async function startSessionViaDaemon(url, options, telemetry) {
|
|
37
46
|
process.once('SIGINT', () => reportStartOutcome(interruptedOutcome('SIGINT'), options));
|
|
38
47
|
process.once('SIGTERM', () => reportStartOutcome(interruptedOutcome('SIGTERM'), options));
|
|
39
|
-
|
|
48
|
+
reportStartOutcome(await attemptStart(url, options, telemetry), options);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Start a session, retrying while the previous session shuts down. After a
|
|
52
|
+
* failure the daemon reported (or a dropped connection), it waits for every
|
|
53
|
+
* daemon the attempts spawned to exit ({@link afterSpawnedDaemonExit}).
|
|
54
|
+
*
|
|
55
|
+
* @param url - Target URL
|
|
56
|
+
* @param options - Session options
|
|
57
|
+
* @param telemetry - Telemetry types
|
|
58
|
+
* @param deps - How to reach the daemon (tests replace it)
|
|
59
|
+
* @returns Start outcome, ready to report
|
|
60
|
+
*/
|
|
61
|
+
export async function attemptStart(url, options, telemetry, deps = DEFAULT_START_DEPS) {
|
|
62
|
+
const spawned = [];
|
|
63
|
+
const attempt = async () => {
|
|
64
|
+
const outcome = await requestSession(url, options, telemetry, deps);
|
|
65
|
+
if (!outcome.ok && outcome.spawned)
|
|
66
|
+
spawned.push(outcome.spawned);
|
|
67
|
+
return outcome;
|
|
68
|
+
};
|
|
69
|
+
let outcome = await attempt();
|
|
40
70
|
const deadline = Date.now() + SHUTDOWN_WAIT_MS;
|
|
41
71
|
while (isShuttingDown(outcome) && Date.now() < deadline) {
|
|
42
72
|
await delay(SHUTDOWN_POLL_MS);
|
|
43
|
-
outcome = await
|
|
73
|
+
outcome = await attempt();
|
|
74
|
+
}
|
|
75
|
+
return afterSpawnedDaemonExit(outcome, spawned, deps.exitWaitMs);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Let the daemons a failed start spawned finish exiting before the error is
|
|
79
|
+
* reported: a daemon removes its session files on the way out, and a command
|
|
80
|
+
* run right after (`bdg sessions`, another start) would otherwise still see
|
|
81
|
+
* the session as starting. The wait is bounded; a daemon still running after
|
|
82
|
+
* it is reported (`details.daemonStillRunning`, `daemonPid`, a suggestion).
|
|
83
|
+
*
|
|
84
|
+
* @param outcome - Start outcome
|
|
85
|
+
* @param spawned - Exiting daemons the attempts spawned
|
|
86
|
+
* @param waitMs - Milliseconds to wait at most for all of them
|
|
87
|
+
* @returns The failure (without internal fields), with a hint when a daemon did not exit in time
|
|
88
|
+
*/
|
|
89
|
+
export async function afterSpawnedDaemonExit(outcome, spawned, waitMs) {
|
|
90
|
+
if (outcome.ok)
|
|
91
|
+
return outcome;
|
|
92
|
+
const { spawned: _spawned, daemonExiting: _exiting, ...failure } = outcome;
|
|
93
|
+
if (spawned.length === 0)
|
|
94
|
+
return failure;
|
|
95
|
+
if (await waitUntil(() => spawned.every((daemon) => daemon.hasExited()), waitMs)) {
|
|
96
|
+
return failure;
|
|
44
97
|
}
|
|
45
|
-
|
|
98
|
+
const running = spawned.filter((daemon) => !daemon.hasExited()).pop();
|
|
99
|
+
const suggestion = daemonStillExitingSuggestion();
|
|
100
|
+
const previous = failure.details?.['suggestion'];
|
|
101
|
+
return {
|
|
102
|
+
...failure,
|
|
103
|
+
human: joinLines(failure.human, `${daemonStillExitingHint(running?.pid, waitMs)}; ${suggestion}`),
|
|
104
|
+
details: {
|
|
105
|
+
...failure.details,
|
|
106
|
+
daemonStillRunning: true,
|
|
107
|
+
...(running?.pid !== undefined && { daemonPid: running.pid }),
|
|
108
|
+
suggestion: typeof previous === 'string' && previous ? `${previous}; ${suggestion}` : suggestion,
|
|
109
|
+
},
|
|
110
|
+
};
|
|
46
111
|
}
|
|
47
112
|
/**
|
|
48
113
|
* The outcome of a start interrupted with Ctrl-C (the daemon notices the
|
|
@@ -81,9 +146,10 @@ function isShuttingDown(outcome) {
|
|
|
81
146
|
* @param telemetry - Telemetry types
|
|
82
147
|
* @returns Start outcome
|
|
83
148
|
*/
|
|
84
|
-
async function requestSession(url, options, telemetry) {
|
|
149
|
+
async function requestSession(url, options, telemetry, deps) {
|
|
150
|
+
let spawned;
|
|
85
151
|
try {
|
|
86
|
-
await
|
|
152
|
+
spawned = await deps.launch();
|
|
87
153
|
}
|
|
88
154
|
catch (error) {
|
|
89
155
|
if (error instanceof SessionDirError) {
|
|
@@ -99,9 +165,24 @@ async function requestSession(url, options, telemetry) {
|
|
|
99
165
|
const exitCode = error instanceof DaemonError ? error.exitCode : EXIT_CODES.SOFTWARE_ERROR;
|
|
100
166
|
return { ok: false, error: message, human: genericError(message), exitCode };
|
|
101
167
|
}
|
|
168
|
+
const outcome = await sendStart(url, options, telemetry, deps.send);
|
|
169
|
+
return !outcome.ok && outcome.daemonExiting && spawned ? { ...outcome, spawned } : outcome;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Ask the running daemon to start a session.
|
|
173
|
+
*
|
|
174
|
+
* @param url - Target URL
|
|
175
|
+
* @param options - Session options
|
|
176
|
+
* @param telemetry - Telemetry types
|
|
177
|
+
* @param send - Sends the request
|
|
178
|
+
* @returns Start outcome; `daemonExiting` for a failure the daemon reported
|
|
179
|
+
* or a dropped connection, not for a timeout or an unexpected error (the
|
|
180
|
+
* daemon may still be starting the session then)
|
|
181
|
+
*/
|
|
182
|
+
async function sendStart(url, options, telemetry, send) {
|
|
102
183
|
try {
|
|
103
184
|
log.debug('Connecting to daemon...');
|
|
104
|
-
const response = await
|
|
185
|
+
const response = await send(url, filterDefined({
|
|
105
186
|
port: options.port,
|
|
106
187
|
timeout: options.timeout,
|
|
107
188
|
telemetry: telemetry.length > 0 ? telemetry : undefined,
|
|
@@ -111,9 +192,12 @@ async function requestSession(url, options, telemetry) {
|
|
|
111
192
|
headless: options.headless,
|
|
112
193
|
chromeWsUrl: options.chromeWsUrl,
|
|
113
194
|
chromeFlags: options.chromeFlags,
|
|
195
|
+
viewport: options.viewport,
|
|
196
|
+
colorScheme: options.colorScheme,
|
|
114
197
|
}));
|
|
115
|
-
if (response.status === 'error')
|
|
116
|
-
return describeStartFailure(response, options);
|
|
198
|
+
if (response.status === 'error') {
|
|
199
|
+
return { ...describeStartFailure(response, options), daemonExiting: true };
|
|
200
|
+
}
|
|
117
201
|
if (!response.data) {
|
|
118
202
|
const message = 'Invalid response from daemon: missing data';
|
|
119
203
|
return {
|
|
@@ -139,10 +223,11 @@ async function requestSession(url, options, telemetry) {
|
|
|
139
223
|
if (isConnectionError(error)) {
|
|
140
224
|
return {
|
|
141
225
|
ok: false,
|
|
142
|
-
error:
|
|
226
|
+
error: `${noActiveSessionMessage()} (daemon not running)`,
|
|
143
227
|
human: daemonNotRunningError({ suggestStatus: true, suggestRetry: true }),
|
|
144
228
|
exitCode: EXIT_CODES.RESOURCE_NOT_FOUND,
|
|
145
229
|
retryable: true,
|
|
230
|
+
daemonExiting: true,
|
|
146
231
|
};
|
|
147
232
|
}
|
|
148
233
|
const message = getErrorMessage(error);
|
|
@@ -189,7 +274,7 @@ function describeStartFailure(response, options) {
|
|
|
189
274
|
human: sessionAlreadyRunningError(pid, duration ? duration * 1000 : 0, targetUrl),
|
|
190
275
|
exitCode,
|
|
191
276
|
errorCode: response.errorCode,
|
|
192
|
-
details: { ...details, suggestion:
|
|
277
|
+
details: { ...details, suggestion: alreadyRunningSuggestion() },
|
|
193
278
|
};
|
|
194
279
|
}
|
|
195
280
|
if (response.errorCode === IPCErrorCode.SESSION_TARGET_MISMATCH) {
|
|
@@ -242,11 +327,14 @@ function reportStartOutcome(outcome, options) {
|
|
|
242
327
|
}
|
|
243
328
|
const { data } = outcome;
|
|
244
329
|
const autoStopAt = options.timeout !== undefined ? new Date(Date.now() + options.timeout * 1000) : undefined;
|
|
330
|
+
const session = getSessionName() ?? undefined;
|
|
245
331
|
if (options.json) {
|
|
246
332
|
const result = {
|
|
333
|
+
...(session && { session }),
|
|
247
334
|
targetUrl: data.targetUrl,
|
|
248
335
|
...(data.targetTitle !== undefined && { targetTitle: data.targetTitle }),
|
|
249
336
|
...(data.documentStatus !== undefined && { documentStatus: data.documentStatus }),
|
|
337
|
+
...(data.loading && { loading: data.loading }),
|
|
250
338
|
port: data.port,
|
|
251
339
|
...(data.chromePid > 0 ? { chromePid: data.chromePid } : { externalChrome: true }),
|
|
252
340
|
daemonPid: data.daemonPid,
|
|
@@ -258,7 +346,9 @@ function reportStartOutcome(outcome, options) {
|
|
|
258
346
|
const page = {
|
|
259
347
|
url: data.targetUrl,
|
|
260
348
|
...(data.documentStatus !== undefined && { documentStatus: data.documentStatus }),
|
|
349
|
+
...(data.loading && { loading: data.loading }),
|
|
261
350
|
...(autoStopAt && { autoStopAt }),
|
|
351
|
+
...(session && { session }),
|
|
262
352
|
};
|
|
263
353
|
const text = options.quiet
|
|
264
354
|
? [`Session started: ${data.targetUrl}`, ...startNotices(page)].join('\n')
|
|
@@ -49,12 +49,24 @@ export declare function screenshotFormatOption(value: string): 'png' | 'jpeg';
|
|
|
49
49
|
export declare function consoleLevelOption(value: string): ConsoleLevel;
|
|
50
50
|
/**
|
|
51
51
|
* Commander parser for `dom listeners --type`: comma-separated event types
|
|
52
|
-
* (case-sensitive, like `addEventListener`).
|
|
52
|
+
* (case-sensitive, like `addEventListener`); repeated options add up.
|
|
53
53
|
*
|
|
54
54
|
* @param value - Raw option value, e.g. "click,keydown"
|
|
55
|
+
* @param previous - Types from earlier `--type` options
|
|
55
56
|
* @returns Event types
|
|
56
57
|
* @throws InvalidArgumentError (exit 81) when no type is given
|
|
57
58
|
*/
|
|
58
|
-
export declare function eventTypesOption(value: string): string[];
|
|
59
|
+
export declare function eventTypesOption(value: string, previous?: string[]): string[];
|
|
60
|
+
/**
|
|
61
|
+
* Commander parser for `dom inspect --props`: comma-separated CSS property
|
|
62
|
+
* names, lowercased except custom properties (`--brand`), which are
|
|
63
|
+
* case-sensitive; repeated options add up.
|
|
64
|
+
*
|
|
65
|
+
* @param value - Raw option value, e.g. "padding-top,color"
|
|
66
|
+
* @param previous - Names from earlier `--props` options
|
|
67
|
+
* @returns Property names
|
|
68
|
+
* @throws InvalidArgumentError (exit 81) when no name is given
|
|
69
|
+
*/
|
|
70
|
+
export declare function cssPropertiesOption(value: string, previous?: string[]): string[];
|
|
59
71
|
export declare function resourceTypeRule(): ValidationRule<Protocol.Network.ResourceType[]>;
|
|
60
72
|
//# sourceMappingURL=validation.d.ts.map
|