browser-debugger-cli 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/.claude/skills/bdg/SKILL.md +3 -2
  2. package/dist/cdp/methodTarget.d.ts +92 -0
  3. package/dist/cdp/methodTarget.js +159 -0
  4. package/dist/cdp/protocol.d.ts +16 -1
  5. package/dist/cdp/protocol.js +21 -0
  6. package/dist/cdp/schema.d.ts +55 -1
  7. package/dist/cdp/schema.js +134 -25
  8. package/dist/cdp/types.d.ts +3 -1
  9. package/dist/commands/cdp.d.ts +38 -1
  10. package/dist/commands/cdp.js +201 -133
  11. package/dist/commands/cleanup.js +21 -4
  12. package/dist/commands/dom/eval.d.ts +2 -1
  13. package/dist/commands/dom/eval.js +6 -21
  14. package/dist/commands/dom/formInteraction.js +8 -4
  15. package/dist/commands/dom/helpers/evalResult.d.ts +36 -0
  16. package/dist/commands/dom/helpers/evalResult.js +59 -0
  17. package/dist/commands/dom/helpers/index.d.ts +4 -4
  18. package/dist/commands/dom/helpers/index.js +3 -3
  19. package/dist/commands/dom/helpers/query.d.ts +2 -2
  20. package/dist/commands/dom/helpers/query.js +2 -2
  21. package/dist/commands/dom/helpers/screenshot.d.ts +21 -26
  22. package/dist/commands/dom/helpers/screenshot.js +50 -668
  23. package/dist/commands/dom/screenshot.js +56 -36
  24. package/dist/commands/helpJson.d.ts +1 -1
  25. package/dist/commands/helpJson.js +3 -3
  26. package/dist/commands/helpTopic.js +10 -4
  27. package/dist/commands/network/har.js +18 -14
  28. package/dist/commands/optionBehaviors.js +24 -9
  29. package/dist/commands/shared/CommandRunner.d.ts +5 -0
  30. package/dist/commands/shared/CommandRunner.js +18 -3
  31. package/dist/commands/shared/interrupt.d.ts +40 -0
  32. package/dist/commands/shared/interrupt.js +73 -0
  33. package/dist/commands/shared/optionTypes.d.ts +3 -0
  34. package/dist/commands/shared/outputFile.d.ts +2 -1
  35. package/dist/commands/shared/outputFile.js +7 -4
  36. package/dist/commands/shared/startHelpers.d.ts +26 -3
  37. package/dist/commands/shared/startHelpers.js +145 -23
  38. package/dist/commands/status.js +3 -1
  39. package/dist/commands/stop.js +2 -1
  40. package/dist/commands/types.d.ts +5 -0
  41. package/dist/connection/cdp.js +1 -16
  42. package/dist/connection/chromeIdentity.d.ts +24 -5
  43. package/dist/connection/chromeIdentity.js +53 -22
  44. package/dist/connection/launcher/flagsBuilder.d.ts +46 -0
  45. package/dist/connection/launcher/flagsBuilder.js +107 -23
  46. package/dist/connection/launcher.d.ts +35 -2
  47. package/dist/connection/launcher.js +99 -12
  48. package/dist/connection/typed-cdp.d.ts +3 -2
  49. package/dist/constants.d.ts +3 -5
  50. package/dist/constants.js +3 -5
  51. package/dist/daemon/SessionController.d.ts +10 -5
  52. package/dist/daemon/SessionController.js +15 -8
  53. package/dist/daemon/ipcServer.js +1 -1
  54. package/dist/daemon/launcher.d.ts +22 -3
  55. package/dist/daemon/launcher.js +45 -8
  56. package/dist/daemon/session/Session.d.ts +5 -1
  57. package/dist/daemon/session/Session.js +9 -8
  58. package/dist/daemon/session/TelemetryStore.d.ts +5 -0
  59. package/dist/daemon/session/TelemetryStore.js +4 -0
  60. package/dist/daemon/session/captureGate.d.ts +59 -0
  61. package/dist/daemon/session/captureGate.js +96 -0
  62. package/dist/daemon/session/chromeConnection.d.ts +16 -1
  63. package/dist/daemon/session/chromeConnection.js +34 -4
  64. package/dist/daemon/session/collectors.d.ts +15 -0
  65. package/dist/daemon/session/collectors.js +39 -2
  66. package/dist/daemon/session/commandRegistry.d.ts +14 -1
  67. package/dist/daemon/session/commandRegistry.js +48 -13
  68. package/dist/daemon/session/downloads.d.ts +32 -0
  69. package/dist/daemon/session/downloads.js +96 -0
  70. package/dist/daemon/session/interactions.d.ts +3 -2
  71. package/dist/daemon/session/interactions.js +7 -2
  72. package/dist/daemon/session/plugins.js +6 -0
  73. package/dist/daemon.js +18520 -17014
  74. package/dist/errors/CommandError.d.ts +2 -0
  75. package/dist/errors/issues.d.ts +1 -1
  76. package/dist/errors/messages.d.ts +81 -0
  77. package/dist/errors/messages.js +198 -6
  78. package/dist/index.js +1446 -1078
  79. package/dist/ipc/client.d.ts +20 -2
  80. package/dist/ipc/client.js +32 -6
  81. package/dist/ipc/protocol/commands.d.ts +36 -2
  82. package/dist/ipc/protocol/commands.js +1 -0
  83. package/dist/ipc/protocol/domTypes.d.ts +24 -1
  84. package/dist/ipc/session/queries.d.ts +3 -0
  85. package/dist/ipc/session/types.d.ts +5 -0
  86. package/dist/ipc/transport/IPCError.d.ts +9 -0
  87. package/dist/ipc/transport/IPCError.js +12 -0
  88. package/dist/ipc/transport/errors.d.ts +2 -1
  89. package/dist/ipc/transport/errors.js +4 -1
  90. package/dist/ipc/transport/index.d.ts +10 -2
  91. package/dist/ipc/transport/index.js +29 -4
  92. package/dist/runtime/dom/actionEffects.d.ts +48 -9
  93. package/dist/runtime/dom/actionEffects.js +269 -34
  94. package/dist/runtime/dom/actionEffectsScripts.d.ts +45 -0
  95. package/dist/runtime/dom/actionEffectsScripts.js +101 -2
  96. package/dist/runtime/dom/captureArea.d.ts +35 -0
  97. package/dist/runtime/dom/captureArea.js +203 -0
  98. package/dist/runtime/dom/elementInfo.d.ts +13 -4
  99. package/dist/runtime/dom/elementInfo.js +12 -3
  100. package/dist/runtime/dom/evalHelpers.d.ts +24 -4
  101. package/dist/runtime/dom/evalHelpers.js +40 -12
  102. package/dist/runtime/dom/formDiscovery.d.ts +1 -1
  103. package/dist/runtime/dom/frames.d.ts +2 -1
  104. package/dist/runtime/dom/frames.js +3 -1
  105. package/dist/runtime/page/bdgWorld.d.ts +9 -0
  106. package/dist/runtime/page/bdgWorld.js +11 -0
  107. package/dist/runtime/page/captureEmulation.d.ts +119 -0
  108. package/dist/runtime/page/captureEmulation.js +189 -0
  109. package/dist/runtime/page/captureScroll.d.ts +24 -0
  110. package/dist/runtime/page/captureScroll.js +124 -0
  111. package/dist/runtime/page/emulation.js +6 -5
  112. package/dist/runtime/page/screenshot.d.ts +41 -0
  113. package/dist/runtime/page/screenshot.js +394 -0
  114. package/dist/runtime/page/userAgent.d.ts +86 -2
  115. package/dist/runtime/page/userAgent.js +154 -33
  116. package/dist/session/paths.d.ts +52 -3
  117. package/dist/session/paths.js +179 -7
  118. package/dist/session/portClaims.d.ts +0 -8
  119. package/dist/session/portClaims.js +1 -22
  120. package/dist/session/sessionList.d.ts +5 -1
  121. package/dist/session/sessionList.js +5 -1
  122. package/dist/telemetry/downloads.d.ts +127 -0
  123. package/dist/telemetry/downloads.js +265 -0
  124. package/dist/telemetry/har/builder.d.ts +12 -1
  125. package/dist/telemetry/har/builder.js +32 -9
  126. package/dist/telemetry/har/sanitize.d.ts +28 -0
  127. package/dist/telemetry/har/sanitize.js +184 -0
  128. package/dist/telemetry/har/sanitizeBody.d.ts +78 -0
  129. package/dist/telemetry/har/sanitizeBody.js +541 -0
  130. package/dist/telemetry/har/types.d.ts +2 -0
  131. package/dist/telemetry/network.d.ts +4 -4
  132. package/dist/telemetry/network.js +38 -4
  133. package/dist/telemetry/networkRetention.d.ts +35 -14
  134. package/dist/telemetry/networkRetention.js +62 -26
  135. package/dist/types.d.ts +9 -14
  136. package/dist/ui/OutputBuilder.d.ts +3 -2
  137. package/dist/ui/OutputBuilder.js +4 -3
  138. package/dist/ui/formatters/cdp.d.ts +32 -9
  139. package/dist/ui/formatters/cdp.js +77 -6
  140. package/dist/ui/formatters/details.js +7 -15
  141. package/dist/ui/formatters/preview.d.ts +2 -0
  142. package/dist/ui/formatters/preview.js +7 -1
  143. package/dist/ui/formatters/sessions.d.ts +3 -2
  144. package/dist/ui/formatters/sessions.js +10 -3
  145. package/dist/ui/formatters/status.js +6 -1
  146. package/dist/ui/formatting.d.ts +7 -0
  147. package/dist/ui/formatting.js +13 -0
  148. package/dist/ui/logging/logger.d.ts +1 -1
  149. package/dist/ui/messages/chrome.d.ts +27 -6
  150. package/dist/ui/messages/chrome.js +78 -12
  151. package/dist/ui/messages/commands.d.ts +71 -3
  152. package/dist/ui/messages/commands.js +98 -3
  153. package/dist/ui/messages/networkMessages.d.ts +50 -5
  154. package/dist/ui/messages/networkMessages.js +50 -6
  155. package/dist/ui/messages/session.d.ts +8 -0
  156. package/dist/ui/messages/session.js +10 -0
  157. package/dist/utils/async.d.ts +3 -2
  158. package/dist/utils/async.js +16 -3
  159. package/dist/utils/atomicFile.d.ts +2 -1
  160. package/dist/utils/atomicFile.js +5 -2
  161. package/dist/utils/directories.d.ts +41 -0
  162. package/dist/utils/directories.js +48 -0
  163. package/dist/utils/http.d.ts +11 -4
  164. package/dist/utils/http.js +5 -3
  165. package/package.json +18 -4
  166. /package/dist/{commands/dom → runtime/page}/screenshotResize.d.ts +0 -0
  167. /package/dist/{commands/dom → runtime/page}/screenshotResize.js +0 -0
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Credential redaction for HAR exports.
3
+ *
4
+ * HAR files are made to be shared (bug reports, tickets), so `bdg network har`
5
+ * redacts credentials by default, as Chrome DevTools does since Chrome 130.
6
+ * Chrome's sanitized export drops the `Cookie`, `Set-Cookie` and
7
+ * `Authorization` headers and empties the `cookies` arrays; bdg instead keeps
8
+ * every header, cookie and parameter name (and cookie attributes such as
9
+ * `httpOnly`) with the value `[redacted]`, so the export still shows that a
10
+ * request was authenticated and which cookies were set. It also covers API
11
+ * key, token and session headers, credential query parameters in URLs
12
+ * (`?code=`, `?access_token=`), and credential fields of request and response
13
+ * bodies and of WebSocket text messages (sanitizeBody.ts), editing only
14
+ * those values. `headersSize`, `bodySize` and `content.size` stay those of the
15
+ * captured request. Base64 bodies are decoded when their type is generic,
16
+ * JSON, form or event-stream, and binary WebSocket messages always; those
17
+ * that are not UTF-8 text, and other binary bodies, are kept. A body or
18
+ * message the sanitizer fails on is replaced whole by {@link REDACTED}.
19
+ */
20
+ import { REDACTED, isSensitiveField, redactBase64Body, redactBody, redactOrReplaceWhole, redactPairs, } from './sanitizeBody.js';
21
+ /** {@link REDACTED} as written in a URL */
22
+ const URL_REDACTED = encodeURIComponent(REDACTED);
23
+ /** Headers whose values are credentials, lowercased (others match by pattern) */
24
+ const SENSITIVE_HEADERS = new Set([
25
+ 'authorization',
26
+ 'proxy-authorization',
27
+ 'authentication',
28
+ 'cookie',
29
+ 'set-cookie',
30
+ ]);
31
+ /** Custom headers carrying keys or tokens (`X-Api-Key`, `X-Auth-Token`, `X-CSRF-Token`) */
32
+ const SENSITIVE_CUSTOM_HEADER = /^x-.*(key|token|secret|auth)/i;
33
+ /**
34
+ * Headers with a credential segment between hyphens (`api-key`,
35
+ * `private-token`, `cf-access-jwt-assertion`, `ocp-apim-subscription-key`,
36
+ * `session-id`); `www-authenticate` and `proxy-authenticate` do not match
37
+ */
38
+ const SENSITIVE_HEADER_SEGMENT = /(^|-)(api-?key|apikey|token|secret|jwt|subscription-key|session(-?id)?)(-|$)/i;
39
+ /** Headers whose values are URLs that may carry credential parameters */
40
+ const URL_HEADERS = new Set(['location', 'referer']);
41
+ /** Query parameter names that hold credentials in URLs only (OAuth codes, signed URLs, API keys) */
42
+ const SENSITIVE_URL_PARAM = /^(code|sig|key)$/i;
43
+ /** {@link REDACTED} as base64, for a binary body or message replaced whole */
44
+ const BASE64_REDACTED = Buffer.from(REDACTED).toString('base64');
45
+ /** WebSocket opcode of a text message */
46
+ const TEXT_OPCODE = 1;
47
+ /** WebSocket opcode of a binary message (base64 in the HAR) */
48
+ const BINARY_OPCODE = 2;
49
+ /**
50
+ * Redact the credentials of a HAR entry.
51
+ *
52
+ * @param entry - Entry built from the captured request
53
+ * @returns Copy of the entry with credential values replaced by {@link REDACTED}
54
+ */
55
+ export function sanitizeEntry(entry) {
56
+ const { request, response, _webSocketMessages: messages } = entry;
57
+ const postData = request.postData;
58
+ return {
59
+ ...entry,
60
+ request: {
61
+ ...request,
62
+ url: redactUrl(request.url),
63
+ cookies: request.cookies.map(redactCookie),
64
+ headers: request.headers.map(redactHeader),
65
+ queryString: request.queryString.map(redactQueryParam),
66
+ ...(postData?.text !== undefined && {
67
+ postData: {
68
+ ...postData,
69
+ text: redactOrReplaceWhole(postData.text, (text) => redactBody(text, postData.mimeType)),
70
+ },
71
+ }),
72
+ },
73
+ response: {
74
+ ...response,
75
+ cookies: response.cookies.map(redactCookie),
76
+ headers: response.headers.map(redactHeader),
77
+ redirectURL: redactUrl(response.redirectURL),
78
+ content: redactContent(response.content),
79
+ },
80
+ ...(messages && { _webSocketMessages: messages.map(redactWebSocketMessage) }),
81
+ };
82
+ }
83
+ /**
84
+ * Redact credential fields of a response body, also of a base64 body whose
85
+ * type is generic or JSON.
86
+ *
87
+ * @param content - HAR response content
88
+ * @returns The content, or a copy with its text redacted; `size` stays as captured
89
+ */
90
+ function redactContent(content) {
91
+ const { text, mimeType } = content;
92
+ if (text === undefined)
93
+ return content;
94
+ const redacted = content.encoding === 'base64'
95
+ ? redactOrReplaceWhole(text, (body) => redactBase64Body(body, mimeType), BASE64_REDACTED)
96
+ : redactOrReplaceWhole(text, (body) => redactBody(body, mimeType));
97
+ return redacted === text ? content : { ...content, text: redacted };
98
+ }
99
+ /**
100
+ * Redact credential fields of a WebSocket message: a text message, or a
101
+ * binary one that decodes as UTF-8 (redacted and encoded again).
102
+ *
103
+ * @param message - HAR WebSocket message
104
+ * @returns The message, or a copy with its data redacted
105
+ */
106
+ function redactWebSocketMessage(message) {
107
+ if (message.opcode !== TEXT_OPCODE && message.opcode !== BINARY_OPCODE)
108
+ return message;
109
+ const data = message.opcode === TEXT_OPCODE
110
+ ? redactOrReplaceWhole(message.data, (text) => redactBody(text, ''))
111
+ : redactOrReplaceWhole(message.data, (text) => redactBase64Body(text, ''), BASE64_REDACTED);
112
+ return data === message.data ? message : { ...message, data };
113
+ }
114
+ /**
115
+ * Whether a header carries a credential.
116
+ *
117
+ * @param name - Header name (any case)
118
+ * @returns True for auth, cookie, API key, token, secret and session headers
119
+ */
120
+ function isSensitiveHeader(name) {
121
+ return (SENSITIVE_HEADERS.has(name.toLowerCase()) ||
122
+ SENSITIVE_CUSTOM_HEADER.test(name) ||
123
+ SENSITIVE_HEADER_SEGMENT.test(name));
124
+ }
125
+ /**
126
+ * Redact a header's value if it carries a credential, or the credential
127
+ * parameters of a `Location` or `Referer` URL.
128
+ *
129
+ * @param header - HAR header
130
+ * @returns The header, or a copy with its value redacted
131
+ */
132
+ function redactHeader(header) {
133
+ if (isSensitiveHeader(header.name))
134
+ return { ...header, value: REDACTED };
135
+ if (!URL_HEADERS.has(header.name.toLowerCase()))
136
+ return header;
137
+ const value = redactUrl(header.value);
138
+ return value === header.value ? header : { ...header, value };
139
+ }
140
+ /**
141
+ * Redact a cookie's value, keeping its name and attributes.
142
+ *
143
+ * @param cookie - HAR cookie
144
+ * @returns Copy with the value redacted
145
+ */
146
+ function redactCookie(cookie) {
147
+ return { ...cookie, value: REDACTED };
148
+ }
149
+ /**
150
+ * Whether a URL query or fragment parameter holds a credential.
151
+ *
152
+ * @param name - Decoded parameter name
153
+ * @returns True for credential field names, `code`, `sig` and `key`
154
+ */
155
+ function isSensitiveParam(name) {
156
+ return isSensitiveField(name) || SENSITIVE_URL_PARAM.test(name);
157
+ }
158
+ /**
159
+ * Redact a parsed query parameter if it holds a credential.
160
+ *
161
+ * @param param - HAR query parameter
162
+ * @returns The parameter, or a copy with its value redacted
163
+ */
164
+ function redactQueryParam(param) {
165
+ return isSensitiveParam(param.name) ? { ...param, value: REDACTED } : param;
166
+ }
167
+ /**
168
+ * Redact credential parameter values in a URL's query and fragment
169
+ * (`#access_token=` of the OAuth implicit flow), leaving the rest byte for byte.
170
+ *
171
+ * @param url - URL (empty for none)
172
+ * @returns URL with credential values replaced by the URL-encoded {@link REDACTED}
173
+ */
174
+ function redactUrl(url) {
175
+ const hash = url.indexOf('#');
176
+ const beforeHash = hash === -1 ? url : url.slice(0, hash);
177
+ const fragment = hash === -1 ? '' : `#${redactPairs(url.slice(hash + 1), isSensitiveParam, URL_REDACTED)}`;
178
+ const question = beforeHash.indexOf('?');
179
+ if (question === -1)
180
+ return beforeHash + fragment;
181
+ const query = redactPairs(beforeHash.slice(question + 1), isSensitiveParam, URL_REDACTED);
182
+ return `${beforeHash.slice(0, question)}?${query}${fragment}`;
183
+ }
184
+ //# sourceMappingURL=sanitize.js.map
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Credential redaction in request and response bodies, WebSocket text
3
+ * messages and `name=value` lists, for sanitized HAR exports (see sanitize.ts).
4
+ *
5
+ * Matching is by field name only, so it over-redacts: any primitive whose
6
+ * name looks like a credential (`tokenCount: 5`) is replaced too.
7
+ *
8
+ * JSON is never parsed and re-serialized: a single linear scan replaces the
9
+ * credential values in place, so everything else (64-bit numbers, formatting,
10
+ * duplicate keys, a BOM or `)]}'` prefix) stays byte for byte, and truncated
11
+ * JSON, socket.io and SockJS packets, server-sent events, NDJSON and JSON
12
+ * encoded in string values are covered too. JWTs are redacted under any name.
13
+ *
14
+ * Only JSON syntax is understood: single-quoted strings, unquoted keys,
15
+ * JSONP and `name:value` header lines (STOMP `passcode:`) are not.
16
+ */
17
+ /** Replaces a credential value */
18
+ export declare const REDACTED = "[redacted]";
19
+ /**
20
+ * Whether a body field, form field or query parameter name looks like it
21
+ * holds a credential.
22
+ *
23
+ * @param name - Field name
24
+ * @returns True for password, token, secret, key, session and signature names
25
+ */
26
+ export declare function isSensitiveField(name: string): boolean;
27
+ /**
28
+ * Run a redaction, replacing the whole text when it fails, so that a body
29
+ * the sanitizer cannot handle is never exported as captured.
30
+ *
31
+ * @param text - Body or message text
32
+ * @param redact - Redaction of the text
33
+ * @param whole - Text written when the redaction throws
34
+ * @returns Redacted text, or `whole`
35
+ */
36
+ export declare function redactOrReplaceWhole(text: string, redact: (text: string) => string, whole?: string): string;
37
+ /**
38
+ * Replace every whole JWT (`eyJ` and three base64url segments, not part of a
39
+ * longer word) in text. Scanned by hand: a regular expression overflows the
40
+ * stack on a word of millions of characters.
41
+ *
42
+ * @param text - Text
43
+ * @param replacement - Text written instead of each JWT
44
+ * @returns Text with JWTs replaced; the text unchanged when it has none
45
+ */
46
+ export declare function redactJwts(text: string, replacement: string): string;
47
+ /**
48
+ * Redact credential values in an `&`-separated `name=value` list (a form body,
49
+ * query string or fragment), leaving the other pairs byte for byte.
50
+ *
51
+ * @param text - List like `user=ann&password=hunter2`
52
+ * @param isSensitive - Whether a decoded name holds a credential
53
+ * @param replacement - Value written instead
54
+ * @returns List with credential values replaced
55
+ */
56
+ export declare function redactPairs(text: string, isSensitive: (name: string) => boolean, replacement: string): string;
57
+ /**
58
+ * Redact credential fields of a body or WebSocket text message: multipart
59
+ * parts, form fields (by Content-Type or shape) and JSON fields at any depth.
60
+ *
61
+ * @param text - Body text
62
+ * @param mimeType - Content-Type of the body (empty for a WebSocket message)
63
+ * @returns Body with credential values replaced; the text unchanged when
64
+ * there were none or it is neither JSON, a form nor multipart
65
+ */
66
+ export declare function redactBody(text: string, mimeType: string): string;
67
+ /**
68
+ * Redact credential fields of a base64 body or binary WebSocket message that
69
+ * may be text: one with no, a generic binary, a JSON, a form or an
70
+ * event-stream Content-Type that decodes as UTF-8.
71
+ *
72
+ * @param base64 - Body as base64
73
+ * @param mimeType - Content-Type of the body
74
+ * @returns The redacted body re-encoded, or the input unchanged when it was
75
+ * not decodable text or held no credentials
76
+ */
77
+ export declare function redactBase64Body(base64: string, mimeType: string): string;
78
+ //# sourceMappingURL=sanitizeBody.d.ts.map