browser-debugger-cli 0.15.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.
- package/.claude/skills/bdg/SKILL.md +2 -1
- package/dist/cdp/methodTarget.d.ts +92 -0
- package/dist/cdp/methodTarget.js +159 -0
- package/dist/cdp/protocol.d.ts +16 -1
- package/dist/cdp/protocol.js +21 -0
- package/dist/cdp/schema.d.ts +55 -1
- package/dist/cdp/schema.js +134 -25
- package/dist/cdp/types.d.ts +3 -1
- package/dist/commands/cdp.d.ts +38 -1
- package/dist/commands/cdp.js +200 -133
- package/dist/commands/cleanup.js +18 -4
- package/dist/commands/dom/formInteraction.js +8 -4
- package/dist/commands/dom/helpers/index.d.ts +4 -4
- package/dist/commands/dom/helpers/index.js +3 -3
- package/dist/commands/dom/helpers/query.d.ts +2 -2
- package/dist/commands/dom/helpers/query.js +2 -2
- package/dist/commands/dom/helpers/screenshot.d.ts +21 -26
- package/dist/commands/dom/helpers/screenshot.js +50 -668
- package/dist/commands/dom/screenshot.js +56 -36
- package/dist/commands/optionBehaviors.js +18 -8
- package/dist/commands/shared/CommandRunner.d.ts +5 -0
- package/dist/commands/shared/CommandRunner.js +18 -3
- package/dist/commands/shared/interrupt.d.ts +40 -0
- package/dist/commands/shared/interrupt.js +73 -0
- package/dist/commands/shared/optionTypes.d.ts +2 -0
- package/dist/commands/shared/startHelpers.d.ts +26 -3
- package/dist/commands/shared/startHelpers.js +145 -23
- package/dist/commands/types.d.ts +5 -0
- package/dist/connection/cdp.js +1 -16
- package/dist/connection/chromeIdentity.d.ts +24 -5
- package/dist/connection/chromeIdentity.js +53 -22
- package/dist/connection/launcher.d.ts +34 -1
- package/dist/connection/launcher.js +98 -10
- package/dist/connection/typed-cdp.d.ts +3 -2
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/daemon/SessionController.d.ts +10 -5
- package/dist/daemon/SessionController.js +15 -8
- package/dist/daemon/ipcServer.js +1 -1
- package/dist/daemon/launcher.d.ts +5 -0
- package/dist/daemon/launcher.js +8 -1
- package/dist/daemon/session/Session.d.ts +5 -1
- package/dist/daemon/session/Session.js +9 -8
- package/dist/daemon/session/TelemetryStore.d.ts +5 -0
- package/dist/daemon/session/TelemetryStore.js +4 -0
- package/dist/daemon/session/captureGate.d.ts +59 -0
- package/dist/daemon/session/captureGate.js +96 -0
- package/dist/daemon/session/chromeConnection.d.ts +16 -1
- package/dist/daemon/session/chromeConnection.js +34 -4
- package/dist/daemon/session/collectors.d.ts +15 -0
- package/dist/daemon/session/collectors.js +39 -2
- package/dist/daemon/session/commandRegistry.d.ts +14 -1
- package/dist/daemon/session/commandRegistry.js +46 -11
- package/dist/daemon/session/downloads.d.ts +32 -0
- package/dist/daemon/session/downloads.js +96 -0
- package/dist/daemon/session/interactions.d.ts +3 -2
- package/dist/daemon/session/interactions.js +7 -2
- package/dist/daemon/session/plugins.js +6 -0
- package/dist/daemon.js +12843 -11482
- package/dist/errors/CommandError.d.ts +2 -0
- package/dist/errors/issues.d.ts +1 -1
- package/dist/errors/messages.d.ts +58 -0
- package/dist/errors/messages.js +112 -0
- package/dist/index.js +999 -1020
- package/dist/ipc/client.d.ts +14 -1
- package/dist/ipc/client.js +21 -4
- package/dist/ipc/protocol/commands.d.ts +32 -2
- package/dist/ipc/protocol/commands.js +1 -0
- package/dist/ipc/protocol/domTypes.d.ts +24 -1
- package/dist/ipc/session/queries.d.ts +3 -0
- package/dist/ipc/session/types.d.ts +5 -0
- package/dist/ipc/transport/IPCError.d.ts +9 -0
- package/dist/ipc/transport/IPCError.js +12 -0
- package/dist/ipc/transport/errors.d.ts +2 -1
- package/dist/ipc/transport/errors.js +4 -1
- package/dist/ipc/transport/index.d.ts +4 -2
- package/dist/ipc/transport/index.js +13 -3
- package/dist/runtime/dom/actionEffects.d.ts +48 -9
- package/dist/runtime/dom/actionEffects.js +269 -34
- package/dist/runtime/dom/actionEffectsScripts.d.ts +45 -0
- package/dist/runtime/dom/actionEffectsScripts.js +101 -2
- package/dist/runtime/dom/captureArea.d.ts +35 -0
- package/dist/runtime/dom/captureArea.js +203 -0
- package/dist/runtime/dom/elementInfo.d.ts +10 -8
- package/dist/runtime/dom/elementInfo.js +8 -6
- package/dist/runtime/dom/formDiscovery.d.ts +1 -1
- package/dist/runtime/page/bdgWorld.d.ts +9 -0
- package/dist/runtime/page/bdgWorld.js +11 -0
- package/dist/runtime/page/captureEmulation.d.ts +119 -0
- package/dist/runtime/page/captureEmulation.js +189 -0
- package/dist/runtime/page/captureScroll.d.ts +24 -0
- package/dist/runtime/page/captureScroll.js +124 -0
- package/dist/runtime/page/screenshot.d.ts +41 -0
- package/dist/runtime/page/screenshot.js +394 -0
- package/dist/session/paths.d.ts +14 -0
- package/dist/session/paths.js +25 -0
- package/dist/telemetry/downloads.d.ts +127 -0
- package/dist/telemetry/downloads.js +265 -0
- package/dist/telemetry/har/builder.js +22 -7
- package/dist/telemetry/har/sanitize.d.ts +7 -3
- package/dist/telemetry/har/sanitize.js +52 -6
- package/dist/telemetry/har/sanitizeBody.d.ts +47 -7
- package/dist/telemetry/har/sanitizeBody.js +429 -56
- package/dist/telemetry/har/types.d.ts +2 -0
- package/dist/telemetry/network.d.ts +4 -4
- package/dist/telemetry/network.js +38 -4
- package/dist/telemetry/networkRetention.d.ts +35 -14
- package/dist/telemetry/networkRetention.js +62 -26
- package/dist/types.d.ts +9 -14
- package/dist/ui/OutputBuilder.d.ts +3 -2
- package/dist/ui/OutputBuilder.js +4 -3
- package/dist/ui/formatters/cdp.d.ts +32 -9
- package/dist/ui/formatters/cdp.js +77 -6
- package/dist/ui/formatters/details.js +7 -15
- package/dist/ui/formatters/preview.d.ts +2 -0
- package/dist/ui/formatters/preview.js +7 -1
- package/dist/ui/formatters/status.js +6 -1
- package/dist/ui/formatting.d.ts +7 -0
- package/dist/ui/formatting.js +13 -0
- package/dist/ui/logging/logger.d.ts +1 -1
- package/dist/ui/messages/chrome.d.ts +13 -0
- package/dist/ui/messages/chrome.js +26 -0
- package/dist/ui/messages/commands.d.ts +71 -3
- package/dist/ui/messages/commands.js +98 -3
- package/dist/ui/messages/networkMessages.d.ts +24 -5
- package/dist/ui/messages/networkMessages.js +31 -8
- package/dist/utils/async.d.ts +3 -2
- package/dist/utils/async.js +16 -3
- package/dist/utils/http.d.ts +11 -4
- package/dist/utils/http.js +5 -3
- package/package.json +18 -4
- /package/dist/{commands/dom → runtime/page}/screenshotResize.d.ts +0 -0
- /package/dist/{commands/dom → runtime/page}/screenshotResize.js +0 -0
|
@@ -56,9 +56,10 @@ bdg page info # URL and title
|
|
|
56
56
|
Page: navigated to https://app.test/secure (200) # navigation (or "URL changed ... (same document)")
|
|
57
57
|
New text: "Your password is invalid!" (div#flash) # alert/status/aria-live messages that appeared
|
|
58
58
|
⚠ Element Clicked (no visible effect observed ...) # nothing changed - wrong element or a broken handler
|
|
59
|
+
Download: report.txt → ~/.bdg/downloads/report.txt (completed, 15 B) # files go to <session dir>/downloads
|
|
59
60
|
```
|
|
60
61
|
|
|
61
|
-
- In `--json`: `navigation`, `messages`, `effect: "none"` and pending work (timers, spinners) are fields on `data`.
|
|
62
|
+
- In `--json`: `navigation`, `messages`, `downloads`, `effect: "none"` and pending work (timers, spinners) are fields on `data`.
|
|
62
63
|
- Results the page shows later are not waited for: follow up with `bdg dom wait`.
|
|
63
64
|
|
|
64
65
|
```bash
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `bdg cdp <name>` calls: the bundled protocol follows Chromium's
|
|
3
|
+
* tip of tree, so the user's Chrome can have methods it lacks (and lack
|
|
4
|
+
* methods it has). A well-formed name is sent even when the schema does not
|
|
5
|
+
* know it, unless it is a close typo of a method or domain the schema knows.
|
|
6
|
+
*/
|
|
7
|
+
/** What a `Domain.method` name resolves to */
|
|
8
|
+
export type MethodTarget =
|
|
9
|
+
/** A method in the bundled protocol, with its casing */
|
|
10
|
+
{
|
|
11
|
+
kind: 'known';
|
|
12
|
+
method: string;
|
|
13
|
+
}
|
|
14
|
+
/** A well-formed method the bundled protocol lacks, sent as typed (known domain recased) */
|
|
15
|
+
| {
|
|
16
|
+
kind: 'unlisted';
|
|
17
|
+
method: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A close typo of bundled methods (suggestions may be empty when only the
|
|
21
|
+
* domain is close), with the method to send if the user insists
|
|
22
|
+
*/
|
|
23
|
+
| {
|
|
24
|
+
kind: 'typo';
|
|
25
|
+
method: string;
|
|
26
|
+
suggestions: string[];
|
|
27
|
+
}
|
|
28
|
+
/** A protocol type, not a method */
|
|
29
|
+
| {
|
|
30
|
+
kind: 'type';
|
|
31
|
+
name: string;
|
|
32
|
+
}
|
|
33
|
+
/** Not `Domain.method` */
|
|
34
|
+
| {
|
|
35
|
+
kind: 'malformed';
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Decide what `bdg cdp <name>` calls.
|
|
39
|
+
*
|
|
40
|
+
* @param input - Method name as typed (case-insensitive for bundled methods)
|
|
41
|
+
* @returns Known, unlisted, typo, type or malformed
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* resolveMethodTarget('network.getcookies'); // known Network.getCookies
|
|
46
|
+
* resolveMethodTarget('Storage.getRelatedWebsiteSets'); // unlisted: sent as is
|
|
47
|
+
* resolveMethodTarget('Network.getCookes'); // typo of Network.getCookies
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveMethodTarget(input: string): MethodTarget;
|
|
51
|
+
/**
|
|
52
|
+
* Why Chrome may have answered that it has no method bdg sent (-32601), as
|
|
53
|
+
* far as the bundled protocol tells.
|
|
54
|
+
*/
|
|
55
|
+
export type MissingMethodCause =
|
|
56
|
+
/** A bundled method: this Chrome is older than the bundled protocol (or the method is not for pages) */
|
|
57
|
+
{
|
|
58
|
+
kind: 'older';
|
|
59
|
+
}
|
|
60
|
+
/** A bundled method redirected to a method the protocol lacks, with methods close to that one */
|
|
61
|
+
| {
|
|
62
|
+
kind: 'deadRedirect';
|
|
63
|
+
target: string;
|
|
64
|
+
similar: string[];
|
|
65
|
+
}
|
|
66
|
+
/** A domain the bundled protocol lacks too, with bundled domains close to it */
|
|
67
|
+
| {
|
|
68
|
+
kind: 'unknownDomain';
|
|
69
|
+
domain: string;
|
|
70
|
+
similar: string[];
|
|
71
|
+
}
|
|
72
|
+
/** A method of a bundled domain the bundled protocol lacks; `oneCase` when typed in one case */
|
|
73
|
+
| {
|
|
74
|
+
kind: 'unlisted';
|
|
75
|
+
oneCase: boolean;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Why Chrome has no method bdg sent (it answered -32601): a bundled method
|
|
79
|
+
* this Chrome is older than, one redirected to a method the protocol lacks,
|
|
80
|
+
* a domain neither knows, or a method the bundled protocol lacks.
|
|
81
|
+
*
|
|
82
|
+
* @param method - Method as sent (`Domain.method`, a bundled domain recased)
|
|
83
|
+
* @returns The cause
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* missingMethodCause('Page.deleteCookie'); // deadRedirect to Network.deleteCookie
|
|
88
|
+
* missingMethodCause('Foo.bar'); // unknownDomain Foo
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export declare function missingMethodCause(method: string): MissingMethodCause;
|
|
92
|
+
//# sourceMappingURL=methodTarget.d.ts.map
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `bdg cdp <name>` calls: the bundled protocol follows Chromium's
|
|
3
|
+
* tip of tree, so the user's Chrome can have methods it lacks (and lack
|
|
4
|
+
* methods it has). A well-formed name is sent even when the schema does not
|
|
5
|
+
* know it, unless it is a close typo of a method or domain the schema knows.
|
|
6
|
+
*/
|
|
7
|
+
import { findCommand, findDomain, findType, loadProtocol, normalizeMethod, } from './protocol.js';
|
|
8
|
+
import { levenshteinDistance } from '../utils/levenshtein.js';
|
|
9
|
+
import { findSimilar } from '../utils/suggestions.js';
|
|
10
|
+
/** `Domain.method`: letters and digits, starting with a letter */
|
|
11
|
+
const METHOD_NAME = /^[A-Za-z][A-Za-z0-9]*\.[A-Za-z][A-Za-z0-9]*$/;
|
|
12
|
+
/**
|
|
13
|
+
* Most edits a name can be off a known one and still count as its typo: 1
|
|
14
|
+
* for names of up to 5 letters (so `Foo` is not taken for `Log`), else 2.
|
|
15
|
+
*
|
|
16
|
+
* @param name - Name as typed
|
|
17
|
+
* @returns Edit distance limit
|
|
18
|
+
*/
|
|
19
|
+
function typoLimit(name) {
|
|
20
|
+
return name.length <= 5 ? 1 : 2;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Names close enough to count as typos of the input, closest first.
|
|
24
|
+
*
|
|
25
|
+
* @param input - Name as typed
|
|
26
|
+
* @param candidates - Known names
|
|
27
|
+
* @returns Close candidates
|
|
28
|
+
*/
|
|
29
|
+
function closeNames(input, candidates) {
|
|
30
|
+
const lower = input.toLowerCase();
|
|
31
|
+
return candidates
|
|
32
|
+
.map((name) => ({ name, distance: levenshteinDistance(lower, name.toLowerCase()) }))
|
|
33
|
+
.filter(({ distance }) => distance > 0 && distance <= typoLimit(input))
|
|
34
|
+
.sort((a, b) => a.distance - b.distance)
|
|
35
|
+
.map(({ name }) => name);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Methods of a domain close to the typed method name.
|
|
39
|
+
*
|
|
40
|
+
* @param domainName - Domain with its schema casing
|
|
41
|
+
* @param methodName - Method part as typed
|
|
42
|
+
* @returns Full names of close methods
|
|
43
|
+
*/
|
|
44
|
+
function closeMethods(domainName, methodName) {
|
|
45
|
+
const commands = findDomain(domainName)?.commands ?? [];
|
|
46
|
+
const exact = commands.find((c) => c.name.toLowerCase() === methodName.toLowerCase());
|
|
47
|
+
const names = exact
|
|
48
|
+
? [exact.name]
|
|
49
|
+
: closeNames(methodName, commands.map((c) => c.name));
|
|
50
|
+
return names.map((name) => `${domainName}.${name}`);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Resolve a domain the schema does not know: a typo of a known domain, or a
|
|
54
|
+
* domain to send as is.
|
|
55
|
+
*
|
|
56
|
+
* @param domainName - Domain part as typed
|
|
57
|
+
* @param methodName - Method part as typed
|
|
58
|
+
* @returns Typo with suggested methods, or an unlisted method
|
|
59
|
+
*/
|
|
60
|
+
function resolveUnknownDomain(domainName, methodName) {
|
|
61
|
+
const domains = closeNames(domainName, loadProtocol().domains.map((d) => d.domain));
|
|
62
|
+
const method = `${domainName}.${methodName}`;
|
|
63
|
+
if (domains.length === 0)
|
|
64
|
+
return { kind: 'unlisted', method };
|
|
65
|
+
return { kind: 'typo', method, suggestions: domains.flatMap((d) => closeMethods(d, methodName)) };
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Decide what `bdg cdp <name>` calls.
|
|
69
|
+
*
|
|
70
|
+
* @param input - Method name as typed (case-insensitive for bundled methods)
|
|
71
|
+
* @returns Known, unlisted, typo, type or malformed
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* resolveMethodTarget('network.getcookies'); // known Network.getCookies
|
|
76
|
+
* resolveMethodTarget('Storage.getRelatedWebsiteSets'); // unlisted: sent as is
|
|
77
|
+
* resolveMethodTarget('Network.getCookes'); // typo of Network.getCookies
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export function resolveMethodTarget(input) {
|
|
81
|
+
if (!METHOD_NAME.test(input))
|
|
82
|
+
return { kind: 'malformed' };
|
|
83
|
+
const known = normalizeMethod(input);
|
|
84
|
+
if (known)
|
|
85
|
+
return { kind: 'known', method: known };
|
|
86
|
+
const [domainName = '', methodName = ''] = input.split('.');
|
|
87
|
+
const domain = findDomain(domainName);
|
|
88
|
+
if (!domain)
|
|
89
|
+
return resolveUnknownDomain(domainName, methodName);
|
|
90
|
+
const type = findType(domain.domain, methodName);
|
|
91
|
+
if (type)
|
|
92
|
+
return { kind: 'type', name: `${domain.domain}.${type.id}` };
|
|
93
|
+
const method = `${domain.domain}.${methodName}`;
|
|
94
|
+
const suggestions = closeMethods(domain.domain, methodName);
|
|
95
|
+
return suggestions.length > 0
|
|
96
|
+
? { kind: 'typo', method, suggestions }
|
|
97
|
+
: { kind: 'unlisted', method };
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Names close to a name, for a "Did you mean" after Chrome refused it: up
|
|
101
|
+
* to half its length off (at most 3), so `Foo` is not taken for `Log`.
|
|
102
|
+
*
|
|
103
|
+
* @param name - Name as sent
|
|
104
|
+
* @param candidates - Known names
|
|
105
|
+
* @returns Close names, closest first
|
|
106
|
+
*/
|
|
107
|
+
function similarNames(name, candidates) {
|
|
108
|
+
return findSimilar(name, candidates, {
|
|
109
|
+
maxDistance: Math.min(3, Math.max(1, Math.floor(name.length / 2))),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Whether a method name is all lower or all upper case, which a CDP method
|
|
114
|
+
* of more than one word never is (they are lowerCamelCase).
|
|
115
|
+
*
|
|
116
|
+
* @param methodName - Method part as sent
|
|
117
|
+
* @returns True for e.g. `getrelatedwebsitesets`
|
|
118
|
+
*/
|
|
119
|
+
function isOneCase(methodName) {
|
|
120
|
+
return methodName === methodName.toLowerCase() || methodName === methodName.toUpperCase();
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Why Chrome has no method bdg sent (it answered -32601): a bundled method
|
|
124
|
+
* this Chrome is older than, one redirected to a method the protocol lacks,
|
|
125
|
+
* a domain neither knows, or a method the bundled protocol lacks.
|
|
126
|
+
*
|
|
127
|
+
* @param method - Method as sent (`Domain.method`, a bundled domain recased)
|
|
128
|
+
* @returns The cause
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* missingMethodCause('Page.deleteCookie'); // deadRedirect to Network.deleteCookie
|
|
133
|
+
* missingMethodCause('Foo.bar'); // unknownDomain Foo
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
export function missingMethodCause(method) {
|
|
137
|
+
const [domainName = '', methodName = ''] = method.split('.');
|
|
138
|
+
const domain = findDomain(domainName);
|
|
139
|
+
if (!domain) {
|
|
140
|
+
const domains = loadProtocol().domains.map((d) => d.domain);
|
|
141
|
+
return {
|
|
142
|
+
kind: 'unknownDomain',
|
|
143
|
+
domain: domainName,
|
|
144
|
+
similar: similarNames(domainName, domains),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const command = findCommand(domain.domain, methodName);
|
|
148
|
+
if (!command)
|
|
149
|
+
return { kind: 'unlisted', oneCase: isOneCase(methodName) };
|
|
150
|
+
if (!command.redirect || findCommand(command.redirect, command.name))
|
|
151
|
+
return { kind: 'older' };
|
|
152
|
+
const targetMethods = findDomain(command.redirect)?.commands?.map((c) => c.name) ?? [];
|
|
153
|
+
return {
|
|
154
|
+
kind: 'deadRedirect',
|
|
155
|
+
target: `${command.redirect}.${command.name}`,
|
|
156
|
+
similar: similarNames(command.name, targetMethods).map((name) => `${command.redirect}.${name}`),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=methodTarget.js.map
|
package/dist/cdp/protocol.d.ts
CHANGED
|
@@ -5,7 +5,14 @@
|
|
|
5
5
|
* devtools-protocol package. Provides utilities for domain/method lookup
|
|
6
6
|
* and introspection.
|
|
7
7
|
*/
|
|
8
|
-
import type { ProtocolSchema, Domain, Command } from './types.js';
|
|
8
|
+
import type { ProtocolSchema, Domain, Command, Type } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Version of the bundled devtools-protocol package, which names the Chromium
|
|
11
|
+
* revision its schema comes from.
|
|
12
|
+
*
|
|
13
|
+
* @returns e.g. '0.0.1710668'
|
|
14
|
+
*/
|
|
15
|
+
export declare function getBundledProtocolVersion(): string;
|
|
9
16
|
/**
|
|
10
17
|
* Load the CDP protocol schema.
|
|
11
18
|
*
|
|
@@ -53,6 +60,14 @@ export declare function findDomain(domainName: string): Domain | undefined;
|
|
|
53
60
|
* ```
|
|
54
61
|
*/
|
|
55
62
|
export declare function findCommand(domainName: string, commandName: string): Command | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Find a type within a domain (case-insensitive).
|
|
65
|
+
*
|
|
66
|
+
* @param domainName - Domain name (e.g., 'Network')
|
|
67
|
+
* @param typeName - Type id (e.g., 'CookieSameSite', 'cookiesamesite')
|
|
68
|
+
* @returns Type definition or undefined if not found
|
|
69
|
+
*/
|
|
70
|
+
export declare function findType(domainName: string, typeName: string): Type | undefined;
|
|
56
71
|
/**
|
|
57
72
|
* Normalize a CDP method name to proper casing.
|
|
58
73
|
*
|
package/dist/cdp/protocol.js
CHANGED
|
@@ -10,6 +10,16 @@ import { createRequire } from 'module';
|
|
|
10
10
|
import { dirname, join } from 'path';
|
|
11
11
|
const require = createRequire(import.meta.url);
|
|
12
12
|
let cachedProtocol = null;
|
|
13
|
+
/**
|
|
14
|
+
* Version of the bundled devtools-protocol package, which names the Chromium
|
|
15
|
+
* revision its schema comes from.
|
|
16
|
+
*
|
|
17
|
+
* @returns e.g. '0.0.1710668'
|
|
18
|
+
*/
|
|
19
|
+
export function getBundledProtocolVersion() {
|
|
20
|
+
const packageJson = JSON.parse(readFileSync(require.resolve('devtools-protocol/package.json'), 'utf-8'));
|
|
21
|
+
return packageJson.version;
|
|
22
|
+
}
|
|
13
23
|
/**
|
|
14
24
|
* Load the CDP protocol schema.
|
|
15
25
|
*
|
|
@@ -83,6 +93,17 @@ export function findCommand(domainName, commandName) {
|
|
|
83
93
|
const normalized = commandName.toLowerCase();
|
|
84
94
|
return domain.commands.find((c) => c.name.toLowerCase() === normalized);
|
|
85
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Find a type within a domain (case-insensitive).
|
|
98
|
+
*
|
|
99
|
+
* @param domainName - Domain name (e.g., 'Network')
|
|
100
|
+
* @param typeName - Type id (e.g., 'CookieSameSite', 'cookiesamesite')
|
|
101
|
+
* @returns Type definition or undefined if not found
|
|
102
|
+
*/
|
|
103
|
+
export function findType(domainName, typeName) {
|
|
104
|
+
const normalized = typeName.toLowerCase();
|
|
105
|
+
return findDomain(domainName)?.types?.find((t) => t.id.toLowerCase() === normalized);
|
|
106
|
+
}
|
|
86
107
|
/**
|
|
87
108
|
* Normalize a CDP method name to proper casing.
|
|
88
109
|
*
|
package/dist/cdp/schema.d.ts
CHANGED
|
@@ -27,6 +27,16 @@ export interface MethodSchema {
|
|
|
27
27
|
parameters: ParameterSchema[];
|
|
28
28
|
/** Return value schema */
|
|
29
29
|
returns: ReturnSchema[];
|
|
30
|
+
/**
|
|
31
|
+
* The method implementing this one (the schema's `redirect`) and its
|
|
32
|
+
* parameters; `resolved` is false when the protocol lacks that method
|
|
33
|
+
* (e.g. Page.deleteCookie names Network.deleteCookie)
|
|
34
|
+
*/
|
|
35
|
+
redirect?: {
|
|
36
|
+
method: string;
|
|
37
|
+
resolved: boolean;
|
|
38
|
+
parameters: ParameterSchema[];
|
|
39
|
+
};
|
|
30
40
|
/** Usage example (JSON) */
|
|
31
41
|
example?: {
|
|
32
42
|
command: string;
|
|
@@ -45,12 +55,43 @@ export interface ParameterSchema {
|
|
|
45
55
|
required: boolean;
|
|
46
56
|
/** Human-readable description */
|
|
47
57
|
description?: string;
|
|
48
|
-
/** Enum values (
|
|
58
|
+
/** Enum values (inline, or of the referenced type) */
|
|
49
59
|
enum?: string[];
|
|
60
|
+
/** Referenced protocol type with its domain (e.g. 'Network.CookieSameSite'), for `--describe` */
|
|
61
|
+
ref?: string;
|
|
62
|
+
/** Base type of the referenced type (e.g. 'number' for Network.TimeSinceEpoch, 'object') */
|
|
63
|
+
refType?: string;
|
|
50
64
|
/** Array item type (if type is array) */
|
|
51
65
|
items?: string;
|
|
52
66
|
/** Deprecated flag */
|
|
53
67
|
deprecated?: boolean;
|
|
68
|
+
/** Experimental flag */
|
|
69
|
+
experimental?: boolean;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Protocol type (`Network.CookieSameSite`, `Network.Cookie`) for agent consumption.
|
|
73
|
+
*/
|
|
74
|
+
export interface TypeSchema {
|
|
75
|
+
/** Full type name (Domain.Type) */
|
|
76
|
+
name: string;
|
|
77
|
+
/** Domain name */
|
|
78
|
+
domain: string;
|
|
79
|
+
/** Type id */
|
|
80
|
+
id: string;
|
|
81
|
+
/** Base type (string, object, array, ...) */
|
|
82
|
+
baseType: string;
|
|
83
|
+
/** Human-readable description */
|
|
84
|
+
description?: string;
|
|
85
|
+
/** Whether type is experimental */
|
|
86
|
+
experimental?: boolean;
|
|
87
|
+
/** Whether type is deprecated */
|
|
88
|
+
deprecated?: boolean;
|
|
89
|
+
/** Enum values (string enums) */
|
|
90
|
+
enum?: string[];
|
|
91
|
+
/** Array item type */
|
|
92
|
+
items?: string;
|
|
93
|
+
/** Properties (object types) */
|
|
94
|
+
properties?: ParameterSchema[];
|
|
54
95
|
}
|
|
55
96
|
/**
|
|
56
97
|
* Return value schema for agent consumption.
|
|
@@ -100,6 +141,19 @@ export interface DomainSummary {
|
|
|
100
141
|
* ```
|
|
101
142
|
*/
|
|
102
143
|
export declare function getMethodSchema(domainName: string, methodName: string): MethodSchema | undefined;
|
|
144
|
+
/**
|
|
145
|
+
* Get structured schema for a protocol type.
|
|
146
|
+
*
|
|
147
|
+
* @param domainName - Domain name (case-insensitive)
|
|
148
|
+
* @param typeName - Type id (case-insensitive)
|
|
149
|
+
* @returns Type schema or undefined if not found
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* getTypeSchema('Network', 'CookieSameSite')?.enum; // ['Strict', 'Lax', 'None']
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export declare function getTypeSchema(domainName: string, typeName: string): TypeSchema | undefined;
|
|
103
157
|
/**
|
|
104
158
|
* Get all methods in a domain.
|
|
105
159
|
*
|
package/dist/cdp/schema.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - Self-describing tools
|
|
8
8
|
* - Structured context without verbosity
|
|
9
9
|
*/
|
|
10
|
-
import { loadProtocol, findDomain, findCommand } from './protocol.js';
|
|
10
|
+
import { loadProtocol, findDomain, findCommand, findType } from './protocol.js';
|
|
11
11
|
/**
|
|
12
12
|
* Get structured schema for a specific method.
|
|
13
13
|
*
|
|
@@ -40,31 +40,20 @@ export function getMethodSchema(domainName, methodName) {
|
|
|
40
40
|
* @returns Structured method schema
|
|
41
41
|
*/
|
|
42
42
|
function buildMethodSchema(domainName, command) {
|
|
43
|
-
const parameters = command.parameters?.map(paramToSchema) ?? [];
|
|
43
|
+
const parameters = command.parameters?.map((p) => paramToSchema(domainName, p)) ?? [];
|
|
44
44
|
const returns = command.returns?.map(returnToSchema) ?? [];
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
};
|
|
48
|
-
if (parameters.length > 0) {
|
|
49
|
-
const exampleParams = {};
|
|
50
|
-
parameters.forEach((p) => {
|
|
51
|
-
if (!p.required)
|
|
52
|
-
return; // Skip optional params in example
|
|
53
|
-
exampleParams[p.name] = getExampleValue(p);
|
|
54
|
-
});
|
|
55
|
-
if (Object.keys(exampleParams).length > 0) {
|
|
56
|
-
example.params = exampleParams;
|
|
57
|
-
example.command += ` --params '${JSON.stringify(exampleParams)}'`;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
45
|
+
const redirect = buildRedirect(command);
|
|
46
|
+
const exampleSource = parameters.length > 0 ? parameters : (redirect?.parameters ?? []);
|
|
60
47
|
const schema = {
|
|
61
48
|
name: `${domainName}.${command.name}`,
|
|
62
49
|
domain: domainName,
|
|
63
50
|
method: command.name,
|
|
64
51
|
parameters,
|
|
65
52
|
returns,
|
|
66
|
-
example,
|
|
53
|
+
example: buildExample(`${domainName}.${command.name}`, exampleSource),
|
|
67
54
|
};
|
|
55
|
+
if (redirect)
|
|
56
|
+
schema.redirect = redirect;
|
|
68
57
|
if (command.description)
|
|
69
58
|
schema.description = command.description;
|
|
70
59
|
if (command.experimental)
|
|
@@ -74,24 +63,122 @@ function buildMethodSchema(domainName, command) {
|
|
|
74
63
|
return schema;
|
|
75
64
|
}
|
|
76
65
|
/**
|
|
77
|
-
*
|
|
66
|
+
* The method a redirected command runs (e.g. DOM.highlightNode runs
|
|
67
|
+
* Overlay.highlightNode), with the parameters Chrome checks, and whether the
|
|
68
|
+
* protocol has that method.
|
|
69
|
+
*
|
|
70
|
+
* @param command - Command from protocol
|
|
71
|
+
* @returns Redirect target, or undefined when the command has none
|
|
72
|
+
*/
|
|
73
|
+
function buildRedirect(command) {
|
|
74
|
+
if (!command.redirect)
|
|
75
|
+
return undefined;
|
|
76
|
+
const target = findCommand(command.redirect, command.name);
|
|
77
|
+
return {
|
|
78
|
+
method: `${command.redirect}.${command.name}`,
|
|
79
|
+
resolved: target !== undefined,
|
|
80
|
+
parameters: target?.parameters?.map((p) => paramToSchema(command.redirect ?? '', p)) ?? [],
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Example command with the required parameters.
|
|
85
|
+
*
|
|
86
|
+
* @param methodName - Full method name
|
|
87
|
+
* @param parameters - Parameters to take the required ones from
|
|
88
|
+
* @returns Example command and its parameters
|
|
89
|
+
*/
|
|
90
|
+
function buildExample(methodName, parameters) {
|
|
91
|
+
const example = { command: `bdg cdp ${methodName}` };
|
|
92
|
+
const required = parameters.filter((p) => p.required);
|
|
93
|
+
if (required.length === 0)
|
|
94
|
+
return example;
|
|
95
|
+
const exampleParams = Object.fromEntries(required.map((p) => [p.name, getExampleValue(p)]));
|
|
96
|
+
example.params = exampleParams;
|
|
97
|
+
example.command += ` --params '${JSON.stringify(exampleParams)}'`;
|
|
98
|
+
return example;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* A protocol type a `$ref` names, resolved against the domain it is used in.
|
|
102
|
+
*
|
|
103
|
+
* @param domainName - Domain of the parameter (for refs without a domain)
|
|
104
|
+
* @param ref - `$ref` value, e.g. 'CookieSameSite' or 'Runtime.RemoteObject'
|
|
105
|
+
* @returns Full type name and definition, or undefined when the schema lacks it
|
|
106
|
+
*/
|
|
107
|
+
function lookupRef(domainName, ref) {
|
|
108
|
+
const [refDomain, id] = ref.includes('.') ? ref.split('.') : [domainName, ref];
|
|
109
|
+
const type = refDomain && id ? findType(refDomain, id) : undefined;
|
|
110
|
+
return type && { name: `${refDomain}.${type.id}`, type };
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Convert protocol parameter (or object property) to schema; a `$ref` gets its
|
|
114
|
+
* full type name and, for an enum type, its values.
|
|
115
|
+
*
|
|
116
|
+
* @param domainName - Domain the parameter belongs to
|
|
117
|
+
* @param param - Protocol parameter
|
|
118
|
+
* @returns Parameter schema
|
|
78
119
|
*/
|
|
79
|
-
function paramToSchema(param) {
|
|
120
|
+
function paramToSchema(domainName, param) {
|
|
80
121
|
const schema = {
|
|
81
122
|
name: param.name,
|
|
82
123
|
type: resolveType(param),
|
|
83
124
|
required: !param.optional,
|
|
84
125
|
};
|
|
126
|
+
const referenced = param.$ref ? lookupRef(domainName, param.$ref) : undefined;
|
|
127
|
+
const values = param.enum ?? referenced?.type.enum;
|
|
85
128
|
if (param.description)
|
|
86
129
|
schema.description = param.description;
|
|
87
130
|
if (param.deprecated)
|
|
88
131
|
schema.deprecated = param.deprecated;
|
|
89
|
-
if (param.
|
|
90
|
-
schema.
|
|
132
|
+
if (param.experimental)
|
|
133
|
+
schema.experimental = param.experimental;
|
|
134
|
+
if (values)
|
|
135
|
+
schema.enum = values;
|
|
136
|
+
if (referenced) {
|
|
137
|
+
schema.ref = referenced.name;
|
|
138
|
+
schema.refType = referenced.type.type;
|
|
139
|
+
}
|
|
91
140
|
if (param.items)
|
|
92
141
|
schema.items = resolveType(param.items);
|
|
93
142
|
return schema;
|
|
94
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Get structured schema for a protocol type.
|
|
146
|
+
*
|
|
147
|
+
* @param domainName - Domain name (case-insensitive)
|
|
148
|
+
* @param typeName - Type id (case-insensitive)
|
|
149
|
+
* @returns Type schema or undefined if not found
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* getTypeSchema('Network', 'CookieSameSite')?.enum; // ['Strict', 'Lax', 'None']
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export function getTypeSchema(domainName, typeName) {
|
|
157
|
+
const domain = findDomain(domainName);
|
|
158
|
+
const type = domain && findType(domain.domain, typeName);
|
|
159
|
+
if (!domain || !type)
|
|
160
|
+
return undefined;
|
|
161
|
+
const schema = {
|
|
162
|
+
name: `${domain.domain}.${type.id}`,
|
|
163
|
+
domain: domain.domain,
|
|
164
|
+
id: type.id,
|
|
165
|
+
baseType: type.type,
|
|
166
|
+
};
|
|
167
|
+
if (type.description)
|
|
168
|
+
schema.description = type.description;
|
|
169
|
+
if (type.experimental)
|
|
170
|
+
schema.experimental = type.experimental;
|
|
171
|
+
if (type.deprecated)
|
|
172
|
+
schema.deprecated = type.deprecated;
|
|
173
|
+
if (type.enum)
|
|
174
|
+
schema.enum = type.enum;
|
|
175
|
+
if (type.items)
|
|
176
|
+
schema.items = resolveType(type.items);
|
|
177
|
+
if (type.properties) {
|
|
178
|
+
schema.properties = type.properties.map((p) => paramToSchema(domain.domain, p));
|
|
179
|
+
}
|
|
180
|
+
return schema;
|
|
181
|
+
}
|
|
95
182
|
/**
|
|
96
183
|
* Convert protocol return value to schema.
|
|
97
184
|
*/
|
|
@@ -120,7 +207,24 @@ function resolveType(typeRef) {
|
|
|
120
207
|
return typeRef.type ?? 'any';
|
|
121
208
|
}
|
|
122
209
|
/**
|
|
123
|
-
*
|
|
210
|
+
* Example values for parameters whose name says what a realistic value is,
|
|
211
|
+
* where the type's placeholder would do something else (`width: 0` disables
|
|
212
|
+
* `Emulation.setDeviceMetricsOverride`, `url: "example"` is no URL).
|
|
213
|
+
*/
|
|
214
|
+
const EXAMPLE_VALUES = {
|
|
215
|
+
width: 1280,
|
|
216
|
+
height: 800,
|
|
217
|
+
x: 100,
|
|
218
|
+
y: 100,
|
|
219
|
+
deviceScaleFactor: 1,
|
|
220
|
+
scale: 1,
|
|
221
|
+
timeout: 5000,
|
|
222
|
+
responseCode: 200,
|
|
223
|
+
url: 'https://example.com',
|
|
224
|
+
};
|
|
225
|
+
/**
|
|
226
|
+
* Get example value for a parameter: a realistic value for its name, else
|
|
227
|
+
* one for its type (1 for numbers, so it never means "off").
|
|
124
228
|
*
|
|
125
229
|
* @param param - Parameter schema
|
|
126
230
|
* @returns Example value
|
|
@@ -129,12 +233,17 @@ function getExampleValue(param) {
|
|
|
129
233
|
if (param.enum && param.enum.length > 0) {
|
|
130
234
|
return param.enum[0];
|
|
131
235
|
}
|
|
132
|
-
|
|
236
|
+
const type = param.refType ?? param.type;
|
|
237
|
+
const named = Object.hasOwn(EXAMPLE_VALUES, param.name) ? EXAMPLE_VALUES[param.name] : undefined;
|
|
238
|
+
const namedType = typeof named === 'number' ? ['integer', 'number'] : ['string'];
|
|
239
|
+
if (named !== undefined && namedType.includes(type))
|
|
240
|
+
return named;
|
|
241
|
+
switch (type) {
|
|
133
242
|
case 'string':
|
|
134
243
|
return 'example';
|
|
135
244
|
case 'integer':
|
|
136
245
|
case 'number':
|
|
137
|
-
return
|
|
246
|
+
return 1;
|
|
138
247
|
case 'boolean':
|
|
139
248
|
return true;
|
|
140
249
|
case 'array':
|
package/dist/cdp/types.d.ts
CHANGED
|
@@ -69,7 +69,7 @@ export interface Command {
|
|
|
69
69
|
experimental?: boolean;
|
|
70
70
|
/** Whether command is deprecated */
|
|
71
71
|
deprecated?: boolean;
|
|
72
|
-
/**
|
|
72
|
+
/** Domain whose command of the same name implements this one (e.g. 'Overlay' for DOM.highlightNode) */
|
|
73
73
|
redirect?: string;
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
@@ -105,6 +105,8 @@ export interface Type {
|
|
|
105
105
|
items?: TypeRef;
|
|
106
106
|
/** Whether type is experimental */
|
|
107
107
|
experimental?: boolean;
|
|
108
|
+
/** Whether type is deprecated */
|
|
109
|
+
deprecated?: boolean;
|
|
108
110
|
}
|
|
109
111
|
/**
|
|
110
112
|
* CDP Domain (e.g., Network, Runtime, DOM).
|