|
|
/**
|
|
|
* Playwright codegen headed 录制(跨平台,Windows 无需 bash)
|
|
|
* task-121 / GD-15
|
|
|
*/
|
|
|
import { spawn } from "node:child_process";
|
|
|
import fs from "node:fs";
|
|
|
import path from "node:path";
|
|
|
import { isForbiddenQuoteUrl } from "@/lib/rpa/env";
|
|
|
|
|
|
const ROOT = process.cwd();
|
|
|
const OUTPUT_DIR = path.join(ROOT, ".rpa", "recordings");
|
|
|
const STORAGE_PATH =
|
|
|
process.env.RPA_STORAGE_STATE_PATH?.trim() ||
|
|
|
path.join(ROOT, ".rpa", "mothership-storage.json");
|
|
|
|
|
|
function printHelp(): void {
|
|
|
console.log(`
|
|
|
用法: npm run record:mothership [-- 起始URL]
|
|
|
|
|
|
启动 Playwright codegen(headed),录制 Mothership 匿名查价完整路径。
|
|
|
|
|
|
禁止入口(GD-15):
|
|
|
- dashboard.mothership.com
|
|
|
- www.mothership.com/quote
|
|
|
|
|
|
产出:
|
|
|
.rpa/recordings/mothership-<时间戳>.js
|
|
|
.rpa/mothership-storage.json(若会话可持久化)
|
|
|
|
|
|
标准样例: LA 90001 → Dallas 75201,见 docs/rpa-recording-sop.md
|
|
|
`);
|
|
|
}
|
|
|
|
|
|
function formatTimestamp(): string {
|
|
|
const d = new Date();
|
|
|
const pad = (n: number) => String(n).padStart(2, "0");
|
|
|
return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
|
|
|
}
|
|
|
|
|
|
function main(): void {
|
|
|
const startUrl = process.argv[2];
|
|
|
|
|
|
if (startUrl === "-h" || startUrl === "--help") {
|
|
|
printHelp();
|
|
|
process.exit(0);
|
|
|
}
|
|
|
|
|
|
if (startUrl && isForbiddenQuoteUrl(startUrl)) {
|
|
|
console.error("错误:禁止使用入口 URL(GD-15)");
|
|
|
console.error("请使用 headed 录制验证的匿名公开报价 URL,见 docs/rpa-recording-sop.md");
|
|
|
process.exit(1);
|
|
|
}
|
|
|
|
|
|
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
|
|
fs.mkdirSync(path.dirname(STORAGE_PATH), { recursive: true });
|
|
|
|
|
|
const outputFile = path.join(OUTPUT_DIR, `mothership-${formatTimestamp()}.js`);
|
|
|
|
|
|
const args = [
|
|
|
"playwright",
|
|
|
"codegen",
|
|
|
"--target=javascript",
|
|
|
"-o",
|
|
|
outputFile,
|
|
|
`--save-storage=${STORAGE_PATH}`,
|
|
|
];
|
|
|
|
|
|
if (fs.existsSync(STORAGE_PATH)) {
|
|
|
args.push(`--load-storage=${STORAGE_PATH}`);
|
|
|
console.log(`已加载已有 storageState: ${STORAGE_PATH}`);
|
|
|
}
|
|
|
|
|
|
if (startUrl) {
|
|
|
args.push(startUrl);
|
|
|
} else {
|
|
|
console.log("未指定起始 URL:请在 codegen 浏览器中手动导航至匿名报价页");
|
|
|
}
|
|
|
|
|
|
console.log("=== Mothership RPA 录制(headed)===");
|
|
|
console.log("RPA_HEADLESS=false");
|
|
|
console.log("禁止入口: dashboard.mothership.com / www.mothership.com/quote");
|
|
|
console.log(`脚本产出: ${outputFile}`);
|
|
|
console.log(`storageState: ${STORAGE_PATH}`);
|
|
|
console.log("SOP: docs/rpa-recording-sop.md");
|
|
|
console.log("");
|
|
|
|
|
|
const child = spawn("npx", args, {
|
|
|
stdio: "inherit",
|
|
|
shell: true,
|
|
|
cwd: ROOT,
|
|
|
env: { ...process.env, RPA_HEADLESS: "false" },
|
|
|
});
|
|
|
|
|
|
child.on("error", (error) => {
|
|
|
console.error("启动 playwright codegen 失败:", error);
|
|
|
process.exit(1);
|
|
|
});
|
|
|
|
|
|
child.on("exit", (code) => {
|
|
|
process.exit(code ?? 0);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
main();
|