@xbrowser/cli 0.14.2 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -1
- package/dist/cli.js +142 -100
- package/dist/daemon-main.js +83 -35
- package/dist/index.js +140 -98
- package/package.json +19 -3
package/dist/daemon-main.js
CHANGED
|
@@ -24,13 +24,13 @@ import {
|
|
|
24
24
|
} from "./chunk-F3ZWFCJJ.js";
|
|
25
25
|
|
|
26
26
|
// src/daemon/daemon-main.ts
|
|
27
|
-
import { writeFileSync as
|
|
27
|
+
import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync6, appendFileSync } from "fs";
|
|
28
28
|
import { join as join6 } from "path";
|
|
29
29
|
import { homedir as homedir6 } from "os";
|
|
30
30
|
import { startHttpServer } from "@dyyz1993/xcli-core";
|
|
31
31
|
|
|
32
32
|
// src/daemon/rpc-handlers.ts
|
|
33
|
-
import { writeFileSync as
|
|
33
|
+
import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync5 } from "fs";
|
|
34
34
|
import { join as join5 } from "path";
|
|
35
35
|
import { homedir as homedir5 } from "os";
|
|
36
36
|
import {
|
|
@@ -129,7 +129,18 @@ function parsePluginParams(args, schema, base = {}) {
|
|
|
129
129
|
if (value === "true") params[key] = true;
|
|
130
130
|
else if (value === "false") params[key] = false;
|
|
131
131
|
else if (/^\d+$/.test(value)) params[key] = parseInt(value, 10);
|
|
132
|
-
else
|
|
132
|
+
else {
|
|
133
|
+
try {
|
|
134
|
+
const parsed = JSON.parse(value);
|
|
135
|
+
if (Array.isArray(parsed) || typeof parsed === "object" && parsed !== null) {
|
|
136
|
+
params[key] = parsed;
|
|
137
|
+
} else {
|
|
138
|
+
params[key] = value;
|
|
139
|
+
}
|
|
140
|
+
} catch {
|
|
141
|
+
params[key] = value;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
133
144
|
i++;
|
|
134
145
|
} else {
|
|
135
146
|
params[key] = true;
|
|
@@ -6206,8 +6217,48 @@ async function loadHooks() {
|
|
|
6206
6217
|
// src/executor.ts
|
|
6207
6218
|
import { homedir as homedir3 } from "os";
|
|
6208
6219
|
import { join as join3 } from "path";
|
|
6220
|
+
import { existsSync as existsSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync5, mkdirSync as mkdirSync3 } from "fs";
|
|
6209
6221
|
var NAVIGATION_COMMANDS = /* @__PURE__ */ new Set(["goto", "back", "forward", "refresh"]);
|
|
6210
6222
|
var snapshotHintShown = /* @__PURE__ */ new WeakSet();
|
|
6223
|
+
var STORAGE_DIR = join3(homedir3(), ".xbrowser", "storage");
|
|
6224
|
+
var storageCache = /* @__PURE__ */ new Map();
|
|
6225
|
+
function getPluginStorage(pluginName) {
|
|
6226
|
+
if (!storageCache.has(pluginName)) {
|
|
6227
|
+
const filePath = join3(STORAGE_DIR, `${pluginName}.json`);
|
|
6228
|
+
let data = {};
|
|
6229
|
+
const load3 = () => {
|
|
6230
|
+
if (existsSync6(filePath)) {
|
|
6231
|
+
try {
|
|
6232
|
+
data = JSON.parse(readFileSync10(filePath, "utf-8"));
|
|
6233
|
+
} catch {
|
|
6234
|
+
data = {};
|
|
6235
|
+
}
|
|
6236
|
+
}
|
|
6237
|
+
};
|
|
6238
|
+
const save = () => {
|
|
6239
|
+
mkdirSync3(STORAGE_DIR, { recursive: true });
|
|
6240
|
+
writeFileSync5(filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
6241
|
+
};
|
|
6242
|
+
load3();
|
|
6243
|
+
storageCache.set(pluginName, {
|
|
6244
|
+
get: async (key) => data[key] ?? null,
|
|
6245
|
+
set: async (key, value) => {
|
|
6246
|
+
data[key] = value;
|
|
6247
|
+
save();
|
|
6248
|
+
},
|
|
6249
|
+
delete: async (key) => {
|
|
6250
|
+
delete data[key];
|
|
6251
|
+
save();
|
|
6252
|
+
},
|
|
6253
|
+
clear: async () => {
|
|
6254
|
+
data = {};
|
|
6255
|
+
save();
|
|
6256
|
+
},
|
|
6257
|
+
keys: async () => Object.keys(data)
|
|
6258
|
+
});
|
|
6259
|
+
}
|
|
6260
|
+
return storageCache.get(pluginName);
|
|
6261
|
+
}
|
|
6211
6262
|
var archiveInitialized = false;
|
|
6212
6263
|
function ensureArchiveInit() {
|
|
6213
6264
|
if (!archiveInitialized) {
|
|
@@ -6315,16 +6366,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
6315
6366
|
args: [],
|
|
6316
6367
|
options: {},
|
|
6317
6368
|
cwd: process.cwd(),
|
|
6318
|
-
storage:
|
|
6319
|
-
get: async () => null,
|
|
6320
|
-
set: async () => {
|
|
6321
|
-
},
|
|
6322
|
-
delete: async () => {
|
|
6323
|
-
},
|
|
6324
|
-
clear: async () => {
|
|
6325
|
-
},
|
|
6326
|
-
keys: async () => []
|
|
6327
|
-
},
|
|
6369
|
+
storage: getPluginStorage(commandName),
|
|
6328
6370
|
output: {
|
|
6329
6371
|
mode: "text",
|
|
6330
6372
|
showTips: false,
|
|
@@ -6547,16 +6589,7 @@ async function executeChain(input, options) {
|
|
|
6547
6589
|
browser: session.context.browser(),
|
|
6548
6590
|
browserContext: session.context,
|
|
6549
6591
|
sessionId: session.id,
|
|
6550
|
-
storage:
|
|
6551
|
-
get: async (_key) => null,
|
|
6552
|
-
set: async (_key, _value) => {
|
|
6553
|
-
},
|
|
6554
|
-
delete: async (_key) => {
|
|
6555
|
-
},
|
|
6556
|
-
clear: async () => {
|
|
6557
|
-
},
|
|
6558
|
-
keys: async () => []
|
|
6559
|
-
},
|
|
6592
|
+
storage: getPluginStorage(cmdName),
|
|
6560
6593
|
output: { mode: "text", showTips: false, color: false, emoji: false },
|
|
6561
6594
|
error: (msg) => {
|
|
6562
6595
|
throw new Error(msg);
|
|
@@ -6567,8 +6600,21 @@ async function executeChain(input, options) {
|
|
|
6567
6600
|
};
|
|
6568
6601
|
const start2 = Date.now();
|
|
6569
6602
|
try {
|
|
6603
|
+
const hooks = await loadHooks();
|
|
6604
|
+
if (hooks.length > 0) {
|
|
6605
|
+
await Promise.all(hooks.map((h) => h.onBeforeCommand?.({ page: session.page, command: `${cmdName} ${subCommand}`, params: pluginParams })));
|
|
6606
|
+
}
|
|
6570
6607
|
const raw = await cmdEntry.handler(pluginParams, pluginCtx);
|
|
6571
6608
|
const duration2 = Date.now() - start2;
|
|
6609
|
+
let hookOutputs;
|
|
6610
|
+
if (hooks.length > 0) {
|
|
6611
|
+
const outputs = [];
|
|
6612
|
+
for (const h of hooks) {
|
|
6613
|
+
const output = await h.onAfterCommand?.({ page: session.page, command: `${cmdName} ${subCommand}`, params: pluginParams, result: raw, duration: duration2 });
|
|
6614
|
+
if (output) outputs.push({ _hook: h.name, ...output });
|
|
6615
|
+
}
|
|
6616
|
+
if (outputs.length > 0) hookOutputs = outputs;
|
|
6617
|
+
}
|
|
6572
6618
|
const data = raw?.data ?? raw;
|
|
6573
6619
|
recordArchive(session.id, sessionName, {
|
|
6574
6620
|
step: results.length,
|
|
@@ -6583,7 +6629,8 @@ async function executeChain(input, options) {
|
|
|
6583
6629
|
command: `${cmdName} ${subCommand}`,
|
|
6584
6630
|
raw: cmdStr,
|
|
6585
6631
|
...ok25(data),
|
|
6586
|
-
duration: duration2
|
|
6632
|
+
duration: duration2,
|
|
6633
|
+
...hookOutputs ? { hookOutputs } : {}
|
|
6587
6634
|
});
|
|
6588
6635
|
if (type === "or") {
|
|
6589
6636
|
return {
|
|
@@ -6647,7 +6694,8 @@ async function executeChain(input, options) {
|
|
|
6647
6694
|
data: result.data,
|
|
6648
6695
|
message: result.message,
|
|
6649
6696
|
duration,
|
|
6650
|
-
tips: result.tips
|
|
6697
|
+
tips: result.tips,
|
|
6698
|
+
...result.hookOutputs ? { hookOutputs: result.hookOutputs } : {}
|
|
6651
6699
|
};
|
|
6652
6700
|
results.push(stepResult);
|
|
6653
6701
|
if (type === "and" && !result.success) {
|
|
@@ -6912,7 +6960,7 @@ async function replayEntry(entry, options = {}) {
|
|
|
6912
6960
|
}
|
|
6913
6961
|
|
|
6914
6962
|
// src/daemon/feedback-store.ts
|
|
6915
|
-
import { readFileSync as
|
|
6963
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync6, mkdirSync as mkdirSync4 } from "fs";
|
|
6916
6964
|
import { join as join4 } from "path";
|
|
6917
6965
|
import { homedir as homedir4 } from "os";
|
|
6918
6966
|
var FEEDBACK_FILE = join4(homedir4(), ".xbrowser", "feedback.json");
|
|
@@ -6923,7 +6971,7 @@ var FeedbackStore = class {
|
|
|
6923
6971
|
}
|
|
6924
6972
|
load() {
|
|
6925
6973
|
try {
|
|
6926
|
-
const data =
|
|
6974
|
+
const data = readFileSync11(FEEDBACK_FILE, "utf8");
|
|
6927
6975
|
this.entries = JSON.parse(data);
|
|
6928
6976
|
} catch {
|
|
6929
6977
|
this.entries = [];
|
|
@@ -6931,8 +6979,8 @@ var FeedbackStore = class {
|
|
|
6931
6979
|
}
|
|
6932
6980
|
save() {
|
|
6933
6981
|
try {
|
|
6934
|
-
|
|
6935
|
-
|
|
6982
|
+
mkdirSync4(join4(homedir4(), ".xbrowser"), { recursive: true });
|
|
6983
|
+
writeFileSync6(FEEDBACK_FILE, JSON.stringify(this.entries, null, 2));
|
|
6936
6984
|
} catch {
|
|
6937
6985
|
}
|
|
6938
6986
|
}
|
|
@@ -7603,9 +7651,9 @@ function createRPCHandler() {
|
|
|
7603
7651
|
try {
|
|
7604
7652
|
const events = await sess.page.evaluate(() => window.__xb_evts || []);
|
|
7605
7653
|
const recordingsDir = join5(CONFIG_DIR, "recordings");
|
|
7606
|
-
|
|
7654
|
+
mkdirSync5(recordingsDir, { recursive: true });
|
|
7607
7655
|
const outPath = params.path || join5(recordingsDir, `recording-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.json`);
|
|
7608
|
-
|
|
7656
|
+
writeFileSync7(outPath, JSON.stringify({
|
|
7609
7657
|
startUrl: sess.page.url(),
|
|
7610
7658
|
recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7611
7659
|
events
|
|
@@ -8658,10 +8706,10 @@ var WSServer = class extends EventEmitter {
|
|
|
8658
8706
|
}
|
|
8659
8707
|
case "file_download": {
|
|
8660
8708
|
try {
|
|
8661
|
-
const { readFileSync:
|
|
8709
|
+
const { readFileSync: readFileSync13 } = await import("fs");
|
|
8662
8710
|
const { resolve: resolve9, basename } = await import("path");
|
|
8663
8711
|
const targetPath = resolve9(msg.path);
|
|
8664
|
-
const data =
|
|
8712
|
+
const data = readFileSync13(targetPath);
|
|
8665
8713
|
const base64 = data.toString("base64");
|
|
8666
8714
|
const ext = targetPath.split(".").pop()?.toLowerCase() || "";
|
|
8667
8715
|
const mimeMap = {
|
|
@@ -9960,8 +10008,8 @@ async function main() {
|
|
|
9960
10008
|
rpcHandler.setPreviewWS(previewWS);
|
|
9961
10009
|
previewWS.on("screencast-started", (sid) => log(`Preview screencast started: ${sid}`));
|
|
9962
10010
|
previewWS.on("screencast-stopped", (sid) => log(`Preview screencast stopped: ${sid}`));
|
|
9963
|
-
|
|
9964
|
-
|
|
10011
|
+
mkdirSync6(CONFIG_DIR2, { recursive: true });
|
|
10012
|
+
writeFileSync8(join6(CONFIG_DIR2, "daemon.json"), JSON.stringify({
|
|
9965
10013
|
port: daemonPort,
|
|
9966
10014
|
pid: process.pid,
|
|
9967
10015
|
startedAt: Date.now()
|