@xbrowser/cli 1.0.5 → 1.0.6
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/dist/{browser-ITLZZDHJ.js → browser-AXCKBSWS.js} +2 -2
- package/dist/{browser-5CTOA2WS.js → browser-U4VWPTS2.js} +1 -1
- package/dist/{browser-IUJXXNBT.js → browser-X7OVRKJH.js} +2 -2
- package/dist/{cdp-driver-4X3DK6PS.js → cdp-driver-CWNZVWHX.js} +18 -4
- package/dist/{cdp-driver-D6WMSMWX.js → cdp-driver-ZAVN7GRB.js} +1 -1
- package/dist/{chunk-TWWOIJM7.js → chunk-5QAYN5EZ.js} +10 -1
- package/dist/{chunk-DKWR54XQ.js → chunk-7POCCXIB.js} +27 -4
- package/dist/{chunk-LRBSUKUZ.js → chunk-MXG2H3HJ.js} +10 -1
- package/dist/{chunk-N2JFPWMI.js → chunk-SEFIJY2M.js} +18 -4
- package/dist/cli.js +38 -15
- package/dist/daemon-main.js +15 -9
- package/dist/index.js +39 -16
- package/dist/{session-replayer-MY27H4DX.js → session-replayer-GCGY6KFK.js} +1 -1
- package/package.json +1 -1
|
@@ -20,8 +20,8 @@ import {
|
|
|
20
20
|
saveSessionDiskMeta,
|
|
21
21
|
setActivePage,
|
|
22
22
|
touchSession
|
|
23
|
-
} from "./chunk-
|
|
24
|
-
import "./chunk-
|
|
23
|
+
} from "./chunk-MXG2H3HJ.js";
|
|
24
|
+
import "./chunk-SEFIJY2M.js";
|
|
25
25
|
import "./chunk-TNEN6VQ2.js";
|
|
26
26
|
import "./chunk-GDKLH7ZY.js";
|
|
27
27
|
import "./chunk-KFQGP6VL.js";
|
|
@@ -20,8 +20,8 @@ import {
|
|
|
20
20
|
saveSessionDiskMeta,
|
|
21
21
|
setActivePage,
|
|
22
22
|
touchSession
|
|
23
|
-
} from "./chunk-
|
|
24
|
-
import "./chunk-
|
|
23
|
+
} from "./chunk-5QAYN5EZ.js";
|
|
24
|
+
import "./chunk-SEFIJY2M.js";
|
|
25
25
|
import "./chunk-TNEN6VQ2.js";
|
|
26
26
|
import "./chunk-GDKLH7ZY.js";
|
|
27
27
|
import "./chunk-ABXMBNQ6.js";
|
|
@@ -2179,8 +2179,14 @@ var XBContextImpl = class {
|
|
|
2179
2179
|
// ── Cookies ─────────────────────────────────────────────────
|
|
2180
2180
|
async cookies(urls) {
|
|
2181
2181
|
const urlList = typeof urls === "string" ? [urls] : urls;
|
|
2182
|
-
const
|
|
2183
|
-
|
|
2182
|
+
const params = urlList ? { urls: urlList } : void 0;
|
|
2183
|
+
try {
|
|
2184
|
+
const result = await this.conn.send("Storage.getCookies", params);
|
|
2185
|
+
return result.cookies;
|
|
2186
|
+
} catch {
|
|
2187
|
+
const result = await this.conn.send("Network.getCookies", params);
|
|
2188
|
+
return result.cookies;
|
|
2189
|
+
}
|
|
2184
2190
|
}
|
|
2185
2191
|
async addCookies(cookies) {
|
|
2186
2192
|
const cdpCookies = cookies.map((c) => ({
|
|
@@ -2193,10 +2199,18 @@ var XBContextImpl = class {
|
|
|
2193
2199
|
secure: c.secure,
|
|
2194
2200
|
sameSite: c.sameSite
|
|
2195
2201
|
}));
|
|
2196
|
-
|
|
2202
|
+
try {
|
|
2203
|
+
await this.conn.send("Storage.setCookies", { cookies: cdpCookies });
|
|
2204
|
+
} catch {
|
|
2205
|
+
await this.conn.send("Network.setCookies", { cookies: cdpCookies });
|
|
2206
|
+
}
|
|
2197
2207
|
}
|
|
2198
2208
|
async clearCookies() {
|
|
2199
|
-
|
|
2209
|
+
try {
|
|
2210
|
+
await this.conn.send("Storage.clearCookies");
|
|
2211
|
+
} catch {
|
|
2212
|
+
await this.conn.send("Network.clearBrowserCookies");
|
|
2213
|
+
}
|
|
2200
2214
|
}
|
|
2201
2215
|
on(event, handler) {
|
|
2202
2216
|
this._emitter.on(event, handler);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
launch
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SEFIJY2M.js";
|
|
4
4
|
import {
|
|
5
5
|
errMsg
|
|
6
6
|
} from "./chunk-GDKLH7ZY.js";
|
|
@@ -36,6 +36,15 @@ async function fetchNoProxy(url) {
|
|
|
36
36
|
async function resolveCDPEndpoint(raw) {
|
|
37
37
|
if (raw === "auto") {
|
|
38
38
|
const httpResp = await fetchNoProxy("http://localhost:9222/json/version");
|
|
39
|
+
if (!httpResp.ok) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`CDP port 9222 responded with ${httpResp.status} ${httpResp.statusText}. \u53EF\u80FD\u539F\u56E0\uFF1A9222 \u88AB\u50F5\u6B7B\u7684 Chrome \u5360\u7528\uFF0C\u6216\u6CA1\u6709 Chrome \u4EE5 --remote-debugging-port \u542F\u52A8\u3002
|
|
42
|
+
\u89E3\u51B3\u65B9\u6CD5\uFF1A
|
|
43
|
+
1. \u6740\u6389\u6B8B\u7559 Chrome: pkill -f "remote-debugging-port"
|
|
44
|
+
2. \u91CD\u542F Chrome: npx cdp-tunnel setup
|
|
45
|
+
3. \u6216\u6307\u5B9A\u7AEF\u53E3: --cdp <port>`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
39
48
|
const data = await httpResp.json();
|
|
40
49
|
if (!data.webSocketDebuggerUrl) {
|
|
41
50
|
throw new Error("Could not auto-discover CDP endpoint from localhost:9222");
|
|
@@ -2184,8 +2184,14 @@ var XBContextImpl = class {
|
|
|
2184
2184
|
// ── Cookies ─────────────────────────────────────────────────
|
|
2185
2185
|
async cookies(urls) {
|
|
2186
2186
|
const urlList = typeof urls === "string" ? [urls] : urls;
|
|
2187
|
-
const
|
|
2188
|
-
|
|
2187
|
+
const params = urlList ? { urls: urlList } : void 0;
|
|
2188
|
+
try {
|
|
2189
|
+
const result = await this.conn.send("Storage.getCookies", params);
|
|
2190
|
+
return result.cookies;
|
|
2191
|
+
} catch {
|
|
2192
|
+
const result = await this.conn.send("Network.getCookies", params);
|
|
2193
|
+
return result.cookies;
|
|
2194
|
+
}
|
|
2189
2195
|
}
|
|
2190
2196
|
async addCookies(cookies) {
|
|
2191
2197
|
const cdpCookies = cookies.map((c) => ({
|
|
@@ -2198,10 +2204,18 @@ var XBContextImpl = class {
|
|
|
2198
2204
|
secure: c.secure,
|
|
2199
2205
|
sameSite: c.sameSite
|
|
2200
2206
|
}));
|
|
2201
|
-
|
|
2207
|
+
try {
|
|
2208
|
+
await this.conn.send("Storage.setCookies", { cookies: cdpCookies });
|
|
2209
|
+
} catch {
|
|
2210
|
+
await this.conn.send("Network.setCookies", { cookies: cdpCookies });
|
|
2211
|
+
}
|
|
2202
2212
|
}
|
|
2203
2213
|
async clearCookies() {
|
|
2204
|
-
|
|
2214
|
+
try {
|
|
2215
|
+
await this.conn.send("Storage.clearCookies");
|
|
2216
|
+
} catch {
|
|
2217
|
+
await this.conn.send("Network.clearBrowserCookies");
|
|
2218
|
+
}
|
|
2205
2219
|
}
|
|
2206
2220
|
on(event, handler) {
|
|
2207
2221
|
this._emitter.on(event, handler);
|
|
@@ -4129,6 +4143,15 @@ async function fetchNoProxy(url) {
|
|
|
4129
4143
|
async function resolveCDPEndpoint(raw) {
|
|
4130
4144
|
if (raw === "auto") {
|
|
4131
4145
|
const httpResp = await fetchNoProxy("http://localhost:9222/json/version");
|
|
4146
|
+
if (!httpResp.ok) {
|
|
4147
|
+
throw new Error(
|
|
4148
|
+
`CDP port 9222 responded with ${httpResp.status} ${httpResp.statusText}. \u53EF\u80FD\u539F\u56E0\uFF1A9222 \u88AB\u50F5\u6B7B\u7684 Chrome \u5360\u7528\uFF0C\u6216\u6CA1\u6709 Chrome \u4EE5 --remote-debugging-port \u542F\u52A8\u3002
|
|
4149
|
+
\u89E3\u51B3\u65B9\u6CD5\uFF1A
|
|
4150
|
+
1. \u6740\u6389\u6B8B\u7559 Chrome: pkill -f "remote-debugging-port"
|
|
4151
|
+
2. \u91CD\u542F Chrome: npx cdp-tunnel setup
|
|
4152
|
+
3. \u6216\u6307\u5B9A\u7AEF\u53E3: --cdp <port>`
|
|
4153
|
+
);
|
|
4154
|
+
}
|
|
4132
4155
|
const data = await httpResp.json();
|
|
4133
4156
|
if (!data.webSocketDebuggerUrl) {
|
|
4134
4157
|
throw new Error("Could not auto-discover CDP endpoint from localhost:9222");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
launch
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SEFIJY2M.js";
|
|
4
4
|
import {
|
|
5
5
|
errMsg
|
|
6
6
|
} from "./chunk-GDKLH7ZY.js";
|
|
@@ -1401,6 +1401,15 @@ async function fetchNoProxy(url) {
|
|
|
1401
1401
|
async function resolveCDPEndpoint(raw) {
|
|
1402
1402
|
if (raw === "auto") {
|
|
1403
1403
|
const httpResp = await fetchNoProxy("http://localhost:9222/json/version");
|
|
1404
|
+
if (!httpResp.ok) {
|
|
1405
|
+
throw new Error(
|
|
1406
|
+
`CDP port 9222 responded with ${httpResp.status} ${httpResp.statusText}. \u53EF\u80FD\u539F\u56E0\uFF1A9222 \u88AB\u50F5\u6B7B\u7684 Chrome \u5360\u7528\uFF0C\u6216\u6CA1\u6709 Chrome \u4EE5 --remote-debugging-port \u542F\u52A8\u3002
|
|
1407
|
+
\u89E3\u51B3\u65B9\u6CD5\uFF1A
|
|
1408
|
+
1. \u6740\u6389\u6B8B\u7559 Chrome: pkill -f "remote-debugging-port"
|
|
1409
|
+
2. \u91CD\u542F Chrome: npx cdp-tunnel setup
|
|
1410
|
+
3. \u6216\u6307\u5B9A\u7AEF\u53E3: --cdp <port>`
|
|
1411
|
+
);
|
|
1412
|
+
}
|
|
1404
1413
|
const data = await httpResp.json();
|
|
1405
1414
|
if (!data.webSocketDebuggerUrl) {
|
|
1406
1415
|
throw new Error("Could not auto-discover CDP endpoint from localhost:9222");
|
|
@@ -2178,8 +2178,14 @@ var XBContextImpl = class {
|
|
|
2178
2178
|
// ── Cookies ─────────────────────────────────────────────────
|
|
2179
2179
|
async cookies(urls) {
|
|
2180
2180
|
const urlList = typeof urls === "string" ? [urls] : urls;
|
|
2181
|
-
const
|
|
2182
|
-
|
|
2181
|
+
const params = urlList ? { urls: urlList } : void 0;
|
|
2182
|
+
try {
|
|
2183
|
+
const result = await this.conn.send("Storage.getCookies", params);
|
|
2184
|
+
return result.cookies;
|
|
2185
|
+
} catch {
|
|
2186
|
+
const result = await this.conn.send("Network.getCookies", params);
|
|
2187
|
+
return result.cookies;
|
|
2188
|
+
}
|
|
2183
2189
|
}
|
|
2184
2190
|
async addCookies(cookies) {
|
|
2185
2191
|
const cdpCookies = cookies.map((c) => ({
|
|
@@ -2192,10 +2198,18 @@ var XBContextImpl = class {
|
|
|
2192
2198
|
secure: c.secure,
|
|
2193
2199
|
sameSite: c.sameSite
|
|
2194
2200
|
}));
|
|
2195
|
-
|
|
2201
|
+
try {
|
|
2202
|
+
await this.conn.send("Storage.setCookies", { cookies: cdpCookies });
|
|
2203
|
+
} catch {
|
|
2204
|
+
await this.conn.send("Network.setCookies", { cookies: cdpCookies });
|
|
2205
|
+
}
|
|
2196
2206
|
}
|
|
2197
2207
|
async clearCookies() {
|
|
2198
|
-
|
|
2208
|
+
try {
|
|
2209
|
+
await this.conn.send("Storage.clearCookies");
|
|
2210
|
+
} catch {
|
|
2211
|
+
await this.conn.send("Network.clearBrowserCookies");
|
|
2212
|
+
}
|
|
2199
2213
|
}
|
|
2200
2214
|
on(event, handler) {
|
|
2201
2215
|
this._emitter.on(event, handler);
|
package/dist/cli.js
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
resolveLaunchOpts,
|
|
26
26
|
saveSessionDiskMeta,
|
|
27
27
|
setActivePage
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-7POCCXIB.js";
|
|
29
29
|
import "./chunk-TNEN6VQ2.js";
|
|
30
30
|
import {
|
|
31
31
|
forwardCommandLog,
|
|
@@ -346,8 +346,13 @@ var gotoCommand = registerCommand({
|
|
|
346
346
|
}),
|
|
347
347
|
handler: async (p, ctx) => {
|
|
348
348
|
let url = p.url;
|
|
349
|
-
|
|
350
|
-
|
|
349
|
+
const hasScheme = /^(https?|wss?|file|about|data|chrome|blob):/i.test(url);
|
|
350
|
+
if (!hasScheme) {
|
|
351
|
+
if (/^[\w-]+(\.[\w-]+)+/.test(url) || url.startsWith("localhost")) {
|
|
352
|
+
url = "https://" + url;
|
|
353
|
+
} else {
|
|
354
|
+
throw new Error(`Invalid URL: "${url}". Expected http(s)://, file://, about:, data:, or a domain name.`);
|
|
355
|
+
}
|
|
351
356
|
}
|
|
352
357
|
const response = await ctx.page.goto(url, {
|
|
353
358
|
waitUntil: p.waitUntil || "domcontentloaded"
|
|
@@ -402,7 +407,7 @@ var urlCommand = registerCommand({
|
|
|
402
407
|
scope: "page",
|
|
403
408
|
result: z.object({ url: z.string() }),
|
|
404
409
|
handler: async (_p, ctx) => {
|
|
405
|
-
return ok({ url: ctx.page.url() });
|
|
410
|
+
return ok({ url: ctx.page.url() || "about:blank" });
|
|
406
411
|
}
|
|
407
412
|
});
|
|
408
413
|
registerCommand({
|
|
@@ -565,7 +570,8 @@ var fillCommand = registerCommand({
|
|
|
565
570
|
}),
|
|
566
571
|
handler: async (p, ctx) => {
|
|
567
572
|
const page = ctx.page;
|
|
568
|
-
|
|
573
|
+
const shouldClear = p.clear !== false;
|
|
574
|
+
if (shouldClear) {
|
|
569
575
|
await page.fill(p.selector, "", { force: true, timeout: 1e4 });
|
|
570
576
|
}
|
|
571
577
|
const isReact = await page.evaluate(() => {
|
|
@@ -591,7 +597,7 @@ var fillCommand = registerCommand({
|
|
|
591
597
|
} else {
|
|
592
598
|
await page.fill(p.selector, p.value, { force: true, timeout: 1e4 });
|
|
593
599
|
}
|
|
594
|
-
return ok2({ selector: p.selector, value: p.value, cleared:
|
|
600
|
+
return ok2({ selector: p.selector, value: p.value, cleared: shouldClear, reactMode: !!isReact });
|
|
595
601
|
}
|
|
596
602
|
});
|
|
597
603
|
var typeCommand = registerCommand({
|
|
@@ -6960,7 +6966,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
6960
6966
|
}
|
|
6961
6967
|
let targetPageOverride = null;
|
|
6962
6968
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
6963
|
-
const { findTargetPage } = await import("./browser-
|
|
6969
|
+
const { findTargetPage } = await import("./browser-U4VWPTS2.js");
|
|
6964
6970
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
6965
6971
|
if (!targetPageOverride) {
|
|
6966
6972
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -9497,10 +9503,10 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
|
|
|
9497
9503
|
break;
|
|
9498
9504
|
}
|
|
9499
9505
|
case "press": {
|
|
9500
|
-
const key = parsed.value || parsed.remaining[1];
|
|
9501
|
-
if (!
|
|
9506
|
+
const key = parsed.value || (sel ? parsed.remaining[1] : parsed.remaining[0]);
|
|
9507
|
+
if (!key) outputError("Usage: xbrowser press [selector] <key>");
|
|
9502
9508
|
cmdName = "press";
|
|
9503
|
-
params = { ...sel ? { selector: sel } : {}, key
|
|
9509
|
+
params = { ...sel ? { selector: sel } : {}, key };
|
|
9504
9510
|
break;
|
|
9505
9511
|
}
|
|
9506
9512
|
case "select": {
|
|
@@ -9569,13 +9575,22 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
|
|
|
9569
9575
|
params = { expression: args.join(" ") };
|
|
9570
9576
|
break;
|
|
9571
9577
|
case "scroll": {
|
|
9572
|
-
|
|
9573
|
-
|
|
9574
|
-
|
|
9578
|
+
let direction = "down";
|
|
9579
|
+
let distance;
|
|
9580
|
+
const firstArg = args[0];
|
|
9581
|
+
if (firstArg && ["up", "down", "left", "right"].includes(firstArg)) {
|
|
9582
|
+
direction = firstArg;
|
|
9583
|
+
if (args[1] && /^\d+$/.test(args[1])) distance = Number(args[1]);
|
|
9584
|
+
} else if (firstArg && /^\d+$/.test(firstArg)) {
|
|
9585
|
+
distance = Number(firstArg);
|
|
9586
|
+
} else if (firstArg) {
|
|
9587
|
+
outputError(`Invalid scroll argument: "${firstArg}". Use up/down/left/right or a pixel number.`);
|
|
9588
|
+
}
|
|
9589
|
+
distance = distance ?? (options.distance ? Number(options.distance) : options.amount ? Number(options.amount) : void 0);
|
|
9575
9590
|
cmdName = "scroll";
|
|
9576
9591
|
params = {
|
|
9577
9592
|
direction,
|
|
9578
|
-
distance
|
|
9593
|
+
distance,
|
|
9579
9594
|
selector: options.selector || options.s
|
|
9580
9595
|
};
|
|
9581
9596
|
break;
|
|
@@ -9588,6 +9603,14 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
|
|
|
9588
9603
|
cmdName = "url";
|
|
9589
9604
|
params = {};
|
|
9590
9605
|
break;
|
|
9606
|
+
case "set-viewport": {
|
|
9607
|
+
const width = options.width ? Number(options.width) : args[0] ? Number(args[0]) : void 0;
|
|
9608
|
+
const height = options.height ? Number(options.height) : args[1] ? Number(args[1]) : void 0;
|
|
9609
|
+
if (!width || !height) outputError("Usage: xbrowser set-viewport <width> <height>");
|
|
9610
|
+
cmdName = "set-viewport";
|
|
9611
|
+
params = { width, height };
|
|
9612
|
+
break;
|
|
9613
|
+
}
|
|
9591
9614
|
case "html":
|
|
9592
9615
|
cmdName = "html";
|
|
9593
9616
|
params = { selector: options.selector || options.s };
|
|
@@ -12650,7 +12673,7 @@ async function main() {
|
|
|
12650
12673
|
const command = process.argv[2];
|
|
12651
12674
|
const isLongRunning = command === "preview" || command === "serve";
|
|
12652
12675
|
if (!isLongRunning) {
|
|
12653
|
-
const { ensureProcessCanExit } = await import("./browser-
|
|
12676
|
+
const { ensureProcessCanExit } = await import("./browser-U4VWPTS2.js");
|
|
12654
12677
|
await ensureProcessCanExit().catch(() => {
|
|
12655
12678
|
});
|
|
12656
12679
|
process.exit(exitCode);
|
package/dist/daemon-main.js
CHANGED
|
@@ -21,8 +21,8 @@ import {
|
|
|
21
21
|
resolveLaunchOpts,
|
|
22
22
|
saveSessionDiskMeta,
|
|
23
23
|
setActivePage
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
24
|
+
} from "./chunk-MXG2H3HJ.js";
|
|
25
|
+
import "./chunk-SEFIJY2M.js";
|
|
26
26
|
import "./chunk-TNEN6VQ2.js";
|
|
27
27
|
import {
|
|
28
28
|
getDaemonConfig,
|
|
@@ -304,8 +304,13 @@ var gotoCommand = registerCommand({
|
|
|
304
304
|
}),
|
|
305
305
|
handler: async (p, ctx) => {
|
|
306
306
|
let url = p.url;
|
|
307
|
-
|
|
308
|
-
|
|
307
|
+
const hasScheme = /^(https?|wss?|file|about|data|chrome|blob):/i.test(url);
|
|
308
|
+
if (!hasScheme) {
|
|
309
|
+
if (/^[\w-]+(\.[\w-]+)+/.test(url) || url.startsWith("localhost")) {
|
|
310
|
+
url = "https://" + url;
|
|
311
|
+
} else {
|
|
312
|
+
throw new Error(`Invalid URL: "${url}". Expected http(s)://, file://, about:, data:, or a domain name.`);
|
|
313
|
+
}
|
|
309
314
|
}
|
|
310
315
|
const response = await ctx.page.goto(url, {
|
|
311
316
|
waitUntil: p.waitUntil || "domcontentloaded"
|
|
@@ -360,7 +365,7 @@ var urlCommand = registerCommand({
|
|
|
360
365
|
scope: "page",
|
|
361
366
|
result: z.object({ url: z.string() }),
|
|
362
367
|
handler: async (_p, ctx) => {
|
|
363
|
-
return ok({ url: ctx.page.url() });
|
|
368
|
+
return ok({ url: ctx.page.url() || "about:blank" });
|
|
364
369
|
}
|
|
365
370
|
});
|
|
366
371
|
registerCommand({
|
|
@@ -523,7 +528,8 @@ var fillCommand = registerCommand({
|
|
|
523
528
|
}),
|
|
524
529
|
handler: async (p, ctx) => {
|
|
525
530
|
const page = ctx.page;
|
|
526
|
-
|
|
531
|
+
const shouldClear = p.clear !== false;
|
|
532
|
+
if (shouldClear) {
|
|
527
533
|
await page.fill(p.selector, "", { force: true, timeout: 1e4 });
|
|
528
534
|
}
|
|
529
535
|
const isReact = await page.evaluate(() => {
|
|
@@ -549,7 +555,7 @@ var fillCommand = registerCommand({
|
|
|
549
555
|
} else {
|
|
550
556
|
await page.fill(p.selector, p.value, { force: true, timeout: 1e4 });
|
|
551
557
|
}
|
|
552
|
-
return ok2({ selector: p.selector, value: p.value, cleared:
|
|
558
|
+
return ok2({ selector: p.selector, value: p.value, cleared: shouldClear, reactMode: !!isReact });
|
|
553
559
|
}
|
|
554
560
|
});
|
|
555
561
|
var typeCommand = registerCommand({
|
|
@@ -6918,7 +6924,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
6918
6924
|
}
|
|
6919
6925
|
let targetPageOverride = null;
|
|
6920
6926
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
6921
|
-
const { findTargetPage } = await import("./browser-
|
|
6927
|
+
const { findTargetPage } = await import("./browser-AXCKBSWS.js");
|
|
6922
6928
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
6923
6929
|
if (!targetPageOverride) {
|
|
6924
6930
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -8602,7 +8608,7 @@ function createRPCHandler() {
|
|
|
8602
8608
|
const isNewFormat = Array.isArray(parsed.actions);
|
|
8603
8609
|
if (isNewFormat) {
|
|
8604
8610
|
try {
|
|
8605
|
-
const { SessionReplayer } = await import("./session-replayer-
|
|
8611
|
+
const { SessionReplayer } = await import("./session-replayer-GCGY6KFK.js");
|
|
8606
8612
|
const replayer = new SessionReplayer({
|
|
8607
8613
|
page: session.page,
|
|
8608
8614
|
stepDelay: slowMo * 500,
|
package/dist/index.js
CHANGED
|
@@ -81,8 +81,8 @@ import {
|
|
|
81
81
|
resolveLaunchOpts,
|
|
82
82
|
saveSessionDiskMeta,
|
|
83
83
|
setActivePage
|
|
84
|
-
} from "./chunk-
|
|
85
|
-
import "./chunk-
|
|
84
|
+
} from "./chunk-5QAYN5EZ.js";
|
|
85
|
+
import "./chunk-SEFIJY2M.js";
|
|
86
86
|
import "./chunk-TNEN6VQ2.js";
|
|
87
87
|
import {
|
|
88
88
|
errMsg
|
|
@@ -386,8 +386,13 @@ var gotoCommand = registerCommand({
|
|
|
386
386
|
}),
|
|
387
387
|
handler: async (p, ctx) => {
|
|
388
388
|
let url = p.url;
|
|
389
|
-
|
|
390
|
-
|
|
389
|
+
const hasScheme = /^(https?|wss?|file|about|data|chrome|blob):/i.test(url);
|
|
390
|
+
if (!hasScheme) {
|
|
391
|
+
if (/^[\w-]+(\.[\w-]+)+/.test(url) || url.startsWith("localhost")) {
|
|
392
|
+
url = "https://" + url;
|
|
393
|
+
} else {
|
|
394
|
+
throw new Error(`Invalid URL: "${url}". Expected http(s)://, file://, about:, data:, or a domain name.`);
|
|
395
|
+
}
|
|
391
396
|
}
|
|
392
397
|
const response = await ctx.page.goto(url, {
|
|
393
398
|
waitUntil: p.waitUntil || "domcontentloaded"
|
|
@@ -442,7 +447,7 @@ var urlCommand = registerCommand({
|
|
|
442
447
|
scope: "page",
|
|
443
448
|
result: z.object({ url: z.string() }),
|
|
444
449
|
handler: async (_p, ctx) => {
|
|
445
|
-
return ok({ url: ctx.page.url() });
|
|
450
|
+
return ok({ url: ctx.page.url() || "about:blank" });
|
|
446
451
|
}
|
|
447
452
|
});
|
|
448
453
|
registerCommand({
|
|
@@ -605,7 +610,8 @@ var fillCommand = registerCommand({
|
|
|
605
610
|
}),
|
|
606
611
|
handler: async (p, ctx) => {
|
|
607
612
|
const page = ctx.page;
|
|
608
|
-
|
|
613
|
+
const shouldClear = p.clear !== false;
|
|
614
|
+
if (shouldClear) {
|
|
609
615
|
await page.fill(p.selector, "", { force: true, timeout: 1e4 });
|
|
610
616
|
}
|
|
611
617
|
const isReact = await page.evaluate(() => {
|
|
@@ -631,7 +637,7 @@ var fillCommand = registerCommand({
|
|
|
631
637
|
} else {
|
|
632
638
|
await page.fill(p.selector, p.value, { force: true, timeout: 1e4 });
|
|
633
639
|
}
|
|
634
|
-
return ok2({ selector: p.selector, value: p.value, cleared:
|
|
640
|
+
return ok2({ selector: p.selector, value: p.value, cleared: shouldClear, reactMode: !!isReact });
|
|
635
641
|
}
|
|
636
642
|
});
|
|
637
643
|
var typeCommand = registerCommand({
|
|
@@ -7280,7 +7286,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7280
7286
|
}
|
|
7281
7287
|
let targetPageOverride = null;
|
|
7282
7288
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
7283
|
-
const { findTargetPage } = await import("./browser-
|
|
7289
|
+
const { findTargetPage } = await import("./browser-X7OVRKJH.js");
|
|
7284
7290
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
7285
7291
|
if (!targetPageOverride) {
|
|
7286
7292
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -9837,10 +9843,10 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
|
|
|
9837
9843
|
break;
|
|
9838
9844
|
}
|
|
9839
9845
|
case "press": {
|
|
9840
|
-
const key = parsed.value || parsed.remaining[1];
|
|
9841
|
-
if (!
|
|
9846
|
+
const key = parsed.value || (sel ? parsed.remaining[1] : parsed.remaining[0]);
|
|
9847
|
+
if (!key) outputError("Usage: xbrowser press [selector] <key>");
|
|
9842
9848
|
cmdName = "press";
|
|
9843
|
-
params = { ...sel ? { selector: sel } : {}, key
|
|
9849
|
+
params = { ...sel ? { selector: sel } : {}, key };
|
|
9844
9850
|
break;
|
|
9845
9851
|
}
|
|
9846
9852
|
case "select": {
|
|
@@ -9909,13 +9915,22 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
|
|
|
9909
9915
|
params = { expression: args.join(" ") };
|
|
9910
9916
|
break;
|
|
9911
9917
|
case "scroll": {
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9918
|
+
let direction = "down";
|
|
9919
|
+
let distance;
|
|
9920
|
+
const firstArg = args[0];
|
|
9921
|
+
if (firstArg && ["up", "down", "left", "right"].includes(firstArg)) {
|
|
9922
|
+
direction = firstArg;
|
|
9923
|
+
if (args[1] && /^\d+$/.test(args[1])) distance = Number(args[1]);
|
|
9924
|
+
} else if (firstArg && /^\d+$/.test(firstArg)) {
|
|
9925
|
+
distance = Number(firstArg);
|
|
9926
|
+
} else if (firstArg) {
|
|
9927
|
+
outputError(`Invalid scroll argument: "${firstArg}". Use up/down/left/right or a pixel number.`);
|
|
9928
|
+
}
|
|
9929
|
+
distance = distance ?? (options.distance ? Number(options.distance) : options.amount ? Number(options.amount) : void 0);
|
|
9915
9930
|
cmdName = "scroll";
|
|
9916
9931
|
params = {
|
|
9917
9932
|
direction,
|
|
9918
|
-
distance
|
|
9933
|
+
distance,
|
|
9919
9934
|
selector: options.selector || options.s
|
|
9920
9935
|
};
|
|
9921
9936
|
break;
|
|
@@ -9928,6 +9943,14 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
|
|
|
9928
9943
|
cmdName = "url";
|
|
9929
9944
|
params = {};
|
|
9930
9945
|
break;
|
|
9946
|
+
case "set-viewport": {
|
|
9947
|
+
const width = options.width ? Number(options.width) : args[0] ? Number(args[0]) : void 0;
|
|
9948
|
+
const height = options.height ? Number(options.height) : args[1] ? Number(args[1]) : void 0;
|
|
9949
|
+
if (!width || !height) outputError("Usage: xbrowser set-viewport <width> <height>");
|
|
9950
|
+
cmdName = "set-viewport";
|
|
9951
|
+
params = { width, height };
|
|
9952
|
+
break;
|
|
9953
|
+
}
|
|
9931
9954
|
case "html":
|
|
9932
9955
|
cmdName = "html";
|
|
9933
9956
|
params = { selector: options.selector || options.s };
|
|
@@ -15777,7 +15800,7 @@ var DataCollector = class {
|
|
|
15777
15800
|
return results;
|
|
15778
15801
|
}
|
|
15779
15802
|
async createBrowserContext() {
|
|
15780
|
-
const { launch } = await import("./cdp-driver-
|
|
15803
|
+
const { launch } = await import("./cdp-driver-ZAVN7GRB.js");
|
|
15781
15804
|
const { browser } = await launch({
|
|
15782
15805
|
headless: true,
|
|
15783
15806
|
args: ["--no-sandbox", "--disable-setuid-sandbox"]
|
|
@@ -31,7 +31,7 @@ var SessionReplayer = class {
|
|
|
31
31
|
if (this.opts.page) {
|
|
32
32
|
this.page = this.opts.page;
|
|
33
33
|
} else if (this.opts.cdpUrl) {
|
|
34
|
-
const { launch } = await import("./cdp-driver-
|
|
34
|
+
const { launch } = await import("./cdp-driver-ZAVN7GRB.js");
|
|
35
35
|
const { browser } = await launch({ cdpEndpoint: this.opts.cdpUrl });
|
|
36
36
|
let contexts = browser.contexts();
|
|
37
37
|
for (let i = 0; i < 10 && contexts.length === 0; i++) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xbrowser/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Browser automation CLI for web scraping, headless browsing, SEO analysis, and AI agent workflows. A command-line alternative to Playwright, Puppeteer, and Selenium.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|