@xbrowser/cli 1.0.7 → 1.0.9
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 +4 -2
- package/dist/{browser-X7OVRKJH.js → browser-6QN42A4K.js} +2 -2
- package/dist/{browser-U4VWPTS2.js → browser-AN6MKGOD.js} +1 -1
- package/dist/{browser-AXCKBSWS.js → browser-MUPES4UY.js} +2 -2
- package/dist/{cdp-driver-CWNZVWHX.js → cdp-driver-E4I3AEJK.js} +4 -0
- package/dist/{cdp-driver-ZAVN7GRB.js → cdp-driver-LKNM6OQI.js} +1 -1
- package/dist/{chunk-5QAYN5EZ.js → chunk-EUHVZVVL.js} +1 -1
- package/dist/{chunk-7POCCXIB.js → chunk-HRTXMFW4.js} +4 -0
- package/dist/{chunk-SEFIJY2M.js → chunk-IX4JY6OO.js} +4 -0
- package/dist/{chunk-MXG2H3HJ.js → chunk-JUNEBEGF.js} +1 -1
- package/dist/{chunk-WJRE55TN.js → chunk-O3FLVCUU.js} +37 -0
- package/dist/{chunk-6WOSXSCQ.js → chunk-XYXCS7JW.js} +37 -0
- package/dist/cli.js +19 -7
- package/dist/{daemon-client-DIEHGP5B.js → daemon-client-R4QWHD7V.js} +1 -1
- package/dist/{daemon-client-3JOKX2L2.js → daemon-client-ZHO6NG36.js} +1 -1
- package/dist/daemon-main.js +19 -7
- package/dist/index.js +20 -8
- package/dist/{session-replayer-GCGY6KFK.js → session-replayer-YWMSSZWC.js} +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,8 +50,10 @@ xbrowser "goto https://example.com && wait .content && text --selector .content"
|
|
|
50
50
|
|
|
51
51
|
**SEO & Backlink Automation**
|
|
52
52
|
```bash
|
|
53
|
-
#
|
|
54
|
-
xbrowser publish --
|
|
53
|
+
# Publish articles to SEO platforms via site plugins
|
|
54
|
+
xbrowser devto publish --file article.md
|
|
55
|
+
xbrowser juejin publish --file article.md
|
|
56
|
+
# (Each platform has its own plugin — run `xbrowser plugin list` to see available)
|
|
55
57
|
```
|
|
56
58
|
|
|
57
59
|
## 快速开始
|
|
@@ -20,8 +20,8 @@ import {
|
|
|
20
20
|
saveSessionDiskMeta,
|
|
21
21
|
setActivePage,
|
|
22
22
|
touchSession
|
|
23
|
-
} from "./chunk-
|
|
24
|
-
import "./chunk-
|
|
23
|
+
} from "./chunk-EUHVZVVL.js";
|
|
24
|
+
import "./chunk-IX4JY6OO.js";
|
|
25
25
|
import "./chunk-TNEN6VQ2.js";
|
|
26
26
|
import "./chunk-GDKLH7ZY.js";
|
|
27
27
|
import "./chunk-ABXMBNQ6.js";
|
|
@@ -20,8 +20,8 @@ import {
|
|
|
20
20
|
saveSessionDiskMeta,
|
|
21
21
|
setActivePage,
|
|
22
22
|
touchSession
|
|
23
|
-
} from "./chunk-
|
|
24
|
-
import "./chunk-
|
|
23
|
+
} from "./chunk-JUNEBEGF.js";
|
|
24
|
+
import "./chunk-IX4JY6OO.js";
|
|
25
25
|
import "./chunk-TNEN6VQ2.js";
|
|
26
26
|
import "./chunk-GDKLH7ZY.js";
|
|
27
27
|
import "./chunk-KFQGP6VL.js";
|
|
@@ -1669,6 +1669,10 @@ Last error: ${lastError.message}` : "";
|
|
|
1669
1669
|
}
|
|
1670
1670
|
};
|
|
1671
1671
|
this._emit("dialog", dialog);
|
|
1672
|
+
setTimeout(() => {
|
|
1673
|
+
this.conn.send("Page.handleJavaScriptDialog", { accept: false }, this.sessionId).catch(() => {
|
|
1674
|
+
});
|
|
1675
|
+
}, 100);
|
|
1672
1676
|
})
|
|
1673
1677
|
);
|
|
1674
1678
|
this._subscriptions.push(
|
|
@@ -1674,6 +1674,10 @@ Last error: ${lastError.message}` : "";
|
|
|
1674
1674
|
}
|
|
1675
1675
|
};
|
|
1676
1676
|
this._emit("dialog", dialog);
|
|
1677
|
+
setTimeout(() => {
|
|
1678
|
+
this.conn.send("Page.handleJavaScriptDialog", { accept: false }, this.sessionId).catch(() => {
|
|
1679
|
+
});
|
|
1680
|
+
}, 100);
|
|
1677
1681
|
})
|
|
1678
1682
|
);
|
|
1679
1683
|
this._subscriptions.push(
|
|
@@ -1668,6 +1668,10 @@ Last error: ${lastError.message}` : "";
|
|
|
1668
1668
|
}
|
|
1669
1669
|
};
|
|
1670
1670
|
this._emit("dialog", dialog);
|
|
1671
|
+
setTimeout(() => {
|
|
1672
|
+
this.conn.send("Page.handleJavaScriptDialog", { accept: false }, this.sessionId).catch(() => {
|
|
1673
|
+
});
|
|
1674
|
+
}, 100);
|
|
1671
1675
|
})
|
|
1672
1676
|
);
|
|
1673
1677
|
this._subscriptions.push(
|
|
@@ -3,6 +3,7 @@ import { spawn } from "child_process";
|
|
|
3
3
|
import { join, dirname } from "path";
|
|
4
4
|
import { homedir } from "os";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
|
+
import { writeFileSync, unlinkSync, mkdirSync } from "fs";
|
|
6
7
|
import { stopDaemon as xcliStopDaemon, isDaemonRunning, getDaemonStatus, killAllDaemon } from "@dyyz1993/xcli-core";
|
|
7
8
|
var CONFIG_DIR = join(homedir(), ".xbrowser");
|
|
8
9
|
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -23,6 +24,30 @@ async function startDaemonProcess(port = 9224) {
|
|
|
23
24
|
}
|
|
24
25
|
await xcliStopDaemon(config);
|
|
25
26
|
}
|
|
27
|
+
const lockFile = join(CONFIG_DIR, "daemon.lock");
|
|
28
|
+
try {
|
|
29
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
30
|
+
writeFileSync(lockFile, String(process.pid), { flag: "wx" });
|
|
31
|
+
} catch {
|
|
32
|
+
console.error("Another process is starting the daemon, waiting...");
|
|
33
|
+
for (let i = 0; i < 50; i++) {
|
|
34
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
35
|
+
if (isDaemonRunning(config)) {
|
|
36
|
+
const s = getDaemonStatus(config);
|
|
37
|
+
if (s.port === port && s.pid) {
|
|
38
|
+
return { pid: s.pid, port: s.port, startedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
unlinkSync(lockFile);
|
|
44
|
+
} catch {
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
writeFileSync(lockFile, String(process.pid), { flag: "wx" });
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
}
|
|
26
51
|
const child = spawn("node", [WORKER_PATH], {
|
|
27
52
|
detached: true,
|
|
28
53
|
stdio: "ignore",
|
|
@@ -37,6 +62,10 @@ async function startDaemonProcess(port = 9224) {
|
|
|
37
62
|
const timeout = setTimeout(() => {
|
|
38
63
|
if (!resolved) {
|
|
39
64
|
resolved = true;
|
|
65
|
+
try {
|
|
66
|
+
unlinkSync(lockFile);
|
|
67
|
+
} catch {
|
|
68
|
+
}
|
|
40
69
|
reject(new Error("Daemon start timeout after 15s"));
|
|
41
70
|
}
|
|
42
71
|
}, 15e3);
|
|
@@ -47,6 +76,10 @@ async function startDaemonProcess(port = 9224) {
|
|
|
47
76
|
resolved = true;
|
|
48
77
|
clearTimeout(timeout);
|
|
49
78
|
clearInterval(checkInterval);
|
|
79
|
+
try {
|
|
80
|
+
unlinkSync(lockFile);
|
|
81
|
+
} catch {
|
|
82
|
+
}
|
|
50
83
|
resolve({ pid: s.pid, port: s.port, startedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
51
84
|
}
|
|
52
85
|
}
|
|
@@ -56,6 +89,10 @@ async function startDaemonProcess(port = 9224) {
|
|
|
56
89
|
resolved = true;
|
|
57
90
|
clearTimeout(timeout);
|
|
58
91
|
clearInterval(checkInterval);
|
|
92
|
+
try {
|
|
93
|
+
unlinkSync(lockFile);
|
|
94
|
+
} catch {
|
|
95
|
+
}
|
|
59
96
|
reject(err);
|
|
60
97
|
}
|
|
61
98
|
});
|
|
@@ -7,6 +7,7 @@ import { spawn } from "child_process";
|
|
|
7
7
|
import { join, dirname } from "path";
|
|
8
8
|
import { homedir } from "os";
|
|
9
9
|
import { fileURLToPath } from "url";
|
|
10
|
+
import { writeFileSync, unlinkSync, mkdirSync } from "fs";
|
|
10
11
|
import { stopDaemon as xcliStopDaemon, isDaemonRunning, getDaemonStatus, killAllDaemon } from "@dyyz1993/xcli-core";
|
|
11
12
|
var CONFIG_DIR = join(homedir(), ".xbrowser");
|
|
12
13
|
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -27,6 +28,30 @@ async function startDaemonProcess(port = 9224) {
|
|
|
27
28
|
}
|
|
28
29
|
await xcliStopDaemon(config);
|
|
29
30
|
}
|
|
31
|
+
const lockFile = join(CONFIG_DIR, "daemon.lock");
|
|
32
|
+
try {
|
|
33
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
34
|
+
writeFileSync(lockFile, String(process.pid), { flag: "wx" });
|
|
35
|
+
} catch {
|
|
36
|
+
console.error("Another process is starting the daemon, waiting...");
|
|
37
|
+
for (let i = 0; i < 50; i++) {
|
|
38
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
39
|
+
if (isDaemonRunning(config)) {
|
|
40
|
+
const s = getDaemonStatus(config);
|
|
41
|
+
if (s.port === port && s.pid) {
|
|
42
|
+
return { pid: s.pid, port: s.port, startedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
unlinkSync(lockFile);
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
writeFileSync(lockFile, String(process.pid), { flag: "wx" });
|
|
52
|
+
} catch {
|
|
53
|
+
}
|
|
54
|
+
}
|
|
30
55
|
const child = spawn("node", [WORKER_PATH], {
|
|
31
56
|
detached: true,
|
|
32
57
|
stdio: "ignore",
|
|
@@ -41,6 +66,10 @@ async function startDaemonProcess(port = 9224) {
|
|
|
41
66
|
const timeout = setTimeout(() => {
|
|
42
67
|
if (!resolved) {
|
|
43
68
|
resolved = true;
|
|
69
|
+
try {
|
|
70
|
+
unlinkSync(lockFile);
|
|
71
|
+
} catch {
|
|
72
|
+
}
|
|
44
73
|
reject(new Error("Daemon start timeout after 15s"));
|
|
45
74
|
}
|
|
46
75
|
}, 15e3);
|
|
@@ -51,6 +80,10 @@ async function startDaemonProcess(port = 9224) {
|
|
|
51
80
|
resolved = true;
|
|
52
81
|
clearTimeout(timeout);
|
|
53
82
|
clearInterval(checkInterval);
|
|
83
|
+
try {
|
|
84
|
+
unlinkSync(lockFile);
|
|
85
|
+
} catch {
|
|
86
|
+
}
|
|
54
87
|
resolve({ pid: s.pid, port: s.port, startedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
55
88
|
}
|
|
56
89
|
}
|
|
@@ -60,6 +93,10 @@ async function startDaemonProcess(port = 9224) {
|
|
|
60
93
|
resolved = true;
|
|
61
94
|
clearTimeout(timeout);
|
|
62
95
|
clearInterval(checkInterval);
|
|
96
|
+
try {
|
|
97
|
+
unlinkSync(lockFile);
|
|
98
|
+
} catch {
|
|
99
|
+
}
|
|
63
100
|
reject(err);
|
|
64
101
|
}
|
|
65
102
|
});
|
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-HRTXMFW4.js";
|
|
29
29
|
import "./chunk-TNEN6VQ2.js";
|
|
30
30
|
import {
|
|
31
31
|
forwardCommandLog,
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
killAllDaemonProcesses,
|
|
55
55
|
startDaemonProcess,
|
|
56
56
|
stopDaemonProcess
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-XYXCS7JW.js";
|
|
58
58
|
import {
|
|
59
59
|
errMsg
|
|
60
60
|
} from "./chunk-GDKLH7ZY.js";
|
|
@@ -6967,7 +6967,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
6967
6967
|
}
|
|
6968
6968
|
let targetPageOverride = null;
|
|
6969
6969
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
6970
|
-
const { findTargetPage } = await import("./browser-
|
|
6970
|
+
const { findTargetPage } = await import("./browser-AN6MKGOD.js");
|
|
6971
6971
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
6972
6972
|
if (!targetPageOverride) {
|
|
6973
6973
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -6984,7 +6984,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
6984
6984
|
params = result.data;
|
|
6985
6985
|
}
|
|
6986
6986
|
if (command.scope !== "cli" && !process.env.XBROWSER_DAEMON_WORKER) {
|
|
6987
|
-
const { forwardExec } = await import("./daemon-client-
|
|
6987
|
+
const { forwardExec } = await import("./daemon-client-ZHO6NG36.js");
|
|
6988
6988
|
const result = await forwardExec(commandName, params, sessionName, extraOpts?.cdpEndpoint);
|
|
6989
6989
|
if (result) return result;
|
|
6990
6990
|
}
|
|
@@ -9648,6 +9648,18 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
|
|
|
9648
9648
|
params = { width, height };
|
|
9649
9649
|
break;
|
|
9650
9650
|
}
|
|
9651
|
+
case "mouse": {
|
|
9652
|
+
const action = options.action || args.find((a) => ["move", "click", "dblclick", "down", "up"].includes(a));
|
|
9653
|
+
const actionIdx = action ? args.indexOf(action) : -1;
|
|
9654
|
+
const x = options.x !== void 0 ? Number(options.x) : actionIdx >= 0 && args[actionIdx + 1] ? Number(args[actionIdx + 1]) : void 0;
|
|
9655
|
+
const y = options.y !== void 0 ? Number(options.y) : actionIdx >= 0 && args[actionIdx + 2] ? Number(args[actionIdx + 2]) : void 0;
|
|
9656
|
+
if (!action || x === void 0 || y === void 0) {
|
|
9657
|
+
outputError("Usage: xbrowser mouse <move|click|dblclick> <x> <y>\n xbrowser mouse --action <action> --x <x> --y <y>");
|
|
9658
|
+
}
|
|
9659
|
+
cmdName = "mouse";
|
|
9660
|
+
params = { action, x, y, ...options.button ? { button: options.button } : {} };
|
|
9661
|
+
break;
|
|
9662
|
+
}
|
|
9651
9663
|
case "html":
|
|
9652
9664
|
cmdName = "html";
|
|
9653
9665
|
params = { selector: options.selector || options.s };
|
|
@@ -12409,7 +12421,7 @@ Run "xbrowser ${command} ${subCommand} --help" to see available parameters.`
|
|
|
12409
12421
|
}
|
|
12410
12422
|
const needsBrowser = cmdEntry.scope === "page" || cmdEntry.scope === "browser";
|
|
12411
12423
|
if (needsBrowser && !process.env.XBROWSER_DAEMON_WORKER) {
|
|
12412
|
-
const { forwardExec } = await import("./daemon-client-
|
|
12424
|
+
const { forwardExec } = await import("./daemon-client-ZHO6NG36.js");
|
|
12413
12425
|
const userTimeout = typeof params.timeout === "number" && params.timeout > 0 ? params.timeout * 1e3 + 3e4 : void 0;
|
|
12414
12426
|
const result = await forwardExec(`${command}.${subCommand}`, params, sessionName, cdpEndpoint, userTimeout);
|
|
12415
12427
|
const resultData = result && typeof result === "object" && "data" in result ? result.data : void 0;
|
|
@@ -12595,7 +12607,7 @@ async function handleServe(_args, options, mode) {
|
|
|
12595
12607
|
\u{1F310} xbrowser HTTP Server`);
|
|
12596
12608
|
console.log(`
|
|
12597
12609
|
URL: ${output.url}`);
|
|
12598
|
-
console.log(` Auth: ${output.authRequired ? "Enabled (Bearer token)" : "Disabled (dev mode)"}
|
|
12610
|
+
console.log(` Auth: ${output.authRequired ? "Enabled (Bearer token, except /health)" : "Disabled (dev mode)"}
|
|
12599
12611
|
`);
|
|
12600
12612
|
console.log(` Endpoints:`);
|
|
12601
12613
|
for (const [, value] of Object.entries(output.endpoints)) {
|
|
@@ -12715,7 +12727,7 @@ async function main() {
|
|
|
12715
12727
|
const command = process.argv[2];
|
|
12716
12728
|
const isLongRunning = command === "preview" || command === "serve";
|
|
12717
12729
|
if (!isLongRunning) {
|
|
12718
|
-
const { ensureProcessCanExit } = await import("./browser-
|
|
12730
|
+
const { ensureProcessCanExit } = await import("./browser-AN6MKGOD.js");
|
|
12719
12731
|
await ensureProcessCanExit().catch(() => {
|
|
12720
12732
|
});
|
|
12721
12733
|
process.exit(exitCode);
|
package/dist/daemon-main.js
CHANGED
|
@@ -21,20 +21,20 @@ import {
|
|
|
21
21
|
resolveLaunchOpts,
|
|
22
22
|
saveSessionDiskMeta,
|
|
23
23
|
setActivePage
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
24
|
+
} from "./chunk-JUNEBEGF.js";
|
|
25
|
+
import "./chunk-IX4JY6OO.js";
|
|
26
26
|
import "./chunk-TNEN6VQ2.js";
|
|
27
27
|
import {
|
|
28
28
|
getDaemonConfig,
|
|
29
29
|
getDaemonProcessStatus
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-O3FLVCUU.js";
|
|
31
31
|
import {
|
|
32
32
|
errMsg
|
|
33
33
|
} from "./chunk-GDKLH7ZY.js";
|
|
34
34
|
import "./chunk-KFQGP6VL.js";
|
|
35
35
|
|
|
36
36
|
// src/daemon/daemon-main.ts
|
|
37
|
-
import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, appendFileSync } from "fs";
|
|
37
|
+
import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, appendFileSync, unlinkSync } from "fs";
|
|
38
38
|
import { join as join9 } from "path";
|
|
39
39
|
import { homedir as homedir9 } from "os";
|
|
40
40
|
import { startHttpServer } from "@dyyz1993/xcli-core";
|
|
@@ -6925,7 +6925,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
6925
6925
|
}
|
|
6926
6926
|
let targetPageOverride = null;
|
|
6927
6927
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
6928
|
-
const { findTargetPage } = await import("./browser-
|
|
6928
|
+
const { findTargetPage } = await import("./browser-MUPES4UY.js");
|
|
6929
6929
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
6930
6930
|
if (!targetPageOverride) {
|
|
6931
6931
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -6942,7 +6942,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
6942
6942
|
params = result.data;
|
|
6943
6943
|
}
|
|
6944
6944
|
if (command.scope !== "cli" && !process.env.XBROWSER_DAEMON_WORKER) {
|
|
6945
|
-
const { forwardExec } = await import("./daemon-client-
|
|
6945
|
+
const { forwardExec } = await import("./daemon-client-R4QWHD7V.js");
|
|
6946
6946
|
const result = await forwardExec(commandName, params, sessionName, extraOpts?.cdpEndpoint);
|
|
6947
6947
|
if (result) return result;
|
|
6948
6948
|
}
|
|
@@ -8609,7 +8609,7 @@ function createRPCHandler() {
|
|
|
8609
8609
|
const isNewFormat = Array.isArray(parsed.actions);
|
|
8610
8610
|
if (isNewFormat) {
|
|
8611
8611
|
try {
|
|
8612
|
-
const { SessionReplayer } = await import("./session-replayer-
|
|
8612
|
+
const { SessionReplayer } = await import("./session-replayer-YWMSSZWC.js");
|
|
8613
8613
|
const replayer = new SessionReplayer({
|
|
8614
8614
|
page: session.page,
|
|
8615
8615
|
stepDelay: slowMo * 500,
|
|
@@ -11406,6 +11406,18 @@ async function main() {
|
|
|
11406
11406
|
}
|
|
11407
11407
|
]
|
|
11408
11408
|
});
|
|
11409
|
+
server.on("error", (err) => {
|
|
11410
|
+
if (err.code === "EADDRINUSE") {
|
|
11411
|
+
log(`Port ${daemonPort} already in use \u2014 another daemon instance likely won the startup race. Exiting gracefully.`);
|
|
11412
|
+
try {
|
|
11413
|
+
unlinkSync(join9(CONFIG_DIR4, "daemon.json"));
|
|
11414
|
+
} catch {
|
|
11415
|
+
}
|
|
11416
|
+
process.exit(0);
|
|
11417
|
+
}
|
|
11418
|
+
log(`Server error: ${err.message}`);
|
|
11419
|
+
process.exit(1);
|
|
11420
|
+
});
|
|
11409
11421
|
const originalListeners = server.listeners("request").slice();
|
|
11410
11422
|
server.removeAllListeners("request");
|
|
11411
11423
|
server.on("request", (req, res) => {
|
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
killAllDaemonProcesses,
|
|
26
26
|
startDaemonProcess,
|
|
27
27
|
stopDaemonProcess
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-XYXCS7JW.js";
|
|
29
29
|
import {
|
|
30
30
|
CaptchaDetector,
|
|
31
31
|
HumanInteractionManager,
|
|
@@ -81,8 +81,8 @@ import {
|
|
|
81
81
|
resolveLaunchOpts,
|
|
82
82
|
saveSessionDiskMeta,
|
|
83
83
|
setActivePage
|
|
84
|
-
} from "./chunk-
|
|
85
|
-
import "./chunk-
|
|
84
|
+
} from "./chunk-EUHVZVVL.js";
|
|
85
|
+
import "./chunk-IX4JY6OO.js";
|
|
86
86
|
import "./chunk-TNEN6VQ2.js";
|
|
87
87
|
import {
|
|
88
88
|
errMsg
|
|
@@ -7287,7 +7287,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7287
7287
|
}
|
|
7288
7288
|
let targetPageOverride = null;
|
|
7289
7289
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
7290
|
-
const { findTargetPage } = await import("./browser-
|
|
7290
|
+
const { findTargetPage } = await import("./browser-6QN42A4K.js");
|
|
7291
7291
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
7292
7292
|
if (!targetPageOverride) {
|
|
7293
7293
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -7304,7 +7304,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7304
7304
|
params = result.data;
|
|
7305
7305
|
}
|
|
7306
7306
|
if (command.scope !== "cli" && !process.env.XBROWSER_DAEMON_WORKER) {
|
|
7307
|
-
const { forwardExec } = await import("./daemon-client-
|
|
7307
|
+
const { forwardExec } = await import("./daemon-client-ZHO6NG36.js");
|
|
7308
7308
|
const result = await forwardExec(commandName, params, sessionName, extraOpts?.cdpEndpoint);
|
|
7309
7309
|
if (result) return result;
|
|
7310
7310
|
}
|
|
@@ -9988,6 +9988,18 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
|
|
|
9988
9988
|
params = { width, height };
|
|
9989
9989
|
break;
|
|
9990
9990
|
}
|
|
9991
|
+
case "mouse": {
|
|
9992
|
+
const action = options.action || args.find((a) => ["move", "click", "dblclick", "down", "up"].includes(a));
|
|
9993
|
+
const actionIdx = action ? args.indexOf(action) : -1;
|
|
9994
|
+
const x = options.x !== void 0 ? Number(options.x) : actionIdx >= 0 && args[actionIdx + 1] ? Number(args[actionIdx + 1]) : void 0;
|
|
9995
|
+
const y = options.y !== void 0 ? Number(options.y) : actionIdx >= 0 && args[actionIdx + 2] ? Number(args[actionIdx + 2]) : void 0;
|
|
9996
|
+
if (!action || x === void 0 || y === void 0) {
|
|
9997
|
+
outputError("Usage: xbrowser mouse <move|click|dblclick> <x> <y>\n xbrowser mouse --action <action> --x <x> --y <y>");
|
|
9998
|
+
}
|
|
9999
|
+
cmdName = "mouse";
|
|
10000
|
+
params = { action, x, y, ...options.button ? { button: options.button } : {} };
|
|
10001
|
+
break;
|
|
10002
|
+
}
|
|
9991
10003
|
case "html":
|
|
9992
10004
|
cmdName = "html";
|
|
9993
10005
|
params = { selector: options.selector || options.s };
|
|
@@ -12749,7 +12761,7 @@ Run "xbrowser ${command} ${subCommand} --help" to see available parameters.`
|
|
|
12749
12761
|
}
|
|
12750
12762
|
const needsBrowser = cmdEntry.scope === "page" || cmdEntry.scope === "browser";
|
|
12751
12763
|
if (needsBrowser && !process.env.XBROWSER_DAEMON_WORKER) {
|
|
12752
|
-
const { forwardExec } = await import("./daemon-client-
|
|
12764
|
+
const { forwardExec } = await import("./daemon-client-ZHO6NG36.js");
|
|
12753
12765
|
const userTimeout = typeof params.timeout === "number" && params.timeout > 0 ? params.timeout * 1e3 + 3e4 : void 0;
|
|
12754
12766
|
const result = await forwardExec(`${command}.${subCommand}`, params, sessionName, cdpEndpoint, userTimeout);
|
|
12755
12767
|
const resultData = result && typeof result === "object" && "data" in result ? result.data : void 0;
|
|
@@ -12935,7 +12947,7 @@ async function handleServe(_args, options, mode) {
|
|
|
12935
12947
|
\u{1F310} xbrowser HTTP Server`);
|
|
12936
12948
|
console.log(`
|
|
12937
12949
|
URL: ${output.url}`);
|
|
12938
|
-
console.log(` Auth: ${output.authRequired ? "Enabled (Bearer token)" : "Disabled (dev mode)"}
|
|
12950
|
+
console.log(` Auth: ${output.authRequired ? "Enabled (Bearer token, except /health)" : "Disabled (dev mode)"}
|
|
12939
12951
|
`);
|
|
12940
12952
|
console.log(` Endpoints:`);
|
|
12941
12953
|
for (const [, value] of Object.entries(output.endpoints)) {
|
|
@@ -15842,7 +15854,7 @@ var DataCollector = class {
|
|
|
15842
15854
|
return results;
|
|
15843
15855
|
}
|
|
15844
15856
|
async createBrowserContext() {
|
|
15845
|
-
const { launch } = await import("./cdp-driver-
|
|
15857
|
+
const { launch } = await import("./cdp-driver-LKNM6OQI.js");
|
|
15846
15858
|
const { browser } = await launch({
|
|
15847
15859
|
headless: true,
|
|
15848
15860
|
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-LKNM6OQI.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.9",
|
|
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": {
|