164 lines
4.8 KiB
JavaScript
164 lines
4.8 KiB
JavaScript
const path = require("node:path");
|
|
const { spawnSync } = require("node:child_process");
|
|
|
|
const projectRoot = path.resolve(__dirname, "..");
|
|
const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
const electronBuilder = path.join(
|
|
projectRoot,
|
|
"node_modules",
|
|
".bin",
|
|
process.platform === "win32" ? "electron-builder.cmd" : "electron-builder",
|
|
);
|
|
|
|
function usage() {
|
|
console.log(`
|
|
客户端打包脚本(不包含认证服务/管理后台)
|
|
|
|
用法:
|
|
npm.cmd run build:client:win -- --auth-url=https://auth.example.com
|
|
npm.cmd run build:client:win -- --auth-url=http://127.0.0.1:3302 --dry-run
|
|
|
|
参数:
|
|
--auth-url <url> 认证服务地址,可带或不带 /api
|
|
--dir 只打包目录,不生成安装包
|
|
--dry-run 只打印将执行的命令,不真正打包
|
|
--help 显示帮助
|
|
`);
|
|
}
|
|
|
|
function readArg(name) {
|
|
const prefix = `${name}=`;
|
|
const inline = process.argv.find(arg => arg.startsWith(prefix));
|
|
if (inline) return inline.slice(prefix.length);
|
|
|
|
const index = process.argv.indexOf(name);
|
|
if (index >= 0) return process.argv[index + 1];
|
|
|
|
return "";
|
|
}
|
|
|
|
function hasArg(name) {
|
|
return process.argv.includes(name);
|
|
}
|
|
|
|
function normalizeAuthUrl(value) {
|
|
const raw = String(value || "").trim();
|
|
if (!raw) return "";
|
|
if (/^https?\/\//i.test(raw)) {
|
|
throw new Error(`认证服务地址无效,协议后缺少冒号:${raw}`);
|
|
}
|
|
|
|
let parsed;
|
|
try {
|
|
parsed = new URL(raw);
|
|
} catch {
|
|
throw new Error(`认证服务地址无效:${raw}`);
|
|
}
|
|
|
|
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
throw new Error(`认证服务地址只支持 http 或 https:${raw}`);
|
|
}
|
|
if (["http", "https"].includes(parsed.hostname) && parsed.pathname.startsWith("//")) {
|
|
throw new Error(`认证服务地址疑似多写了协议,请检查:${raw}`);
|
|
}
|
|
if (!parsed.hostname || parsed.hostname.includes("/")) {
|
|
throw new Error(`认证服务地址主机名无效:${raw}`);
|
|
}
|
|
|
|
parsed.pathname = parsed.pathname.replace(/\/api\/?$/i, "").replace(/\/+$/, "");
|
|
parsed.search = "";
|
|
parsed.hash = "";
|
|
return parsed.toString().replace(/\/+$/, "");
|
|
}
|
|
|
|
function quoteDisplay(value) {
|
|
const text = String(value);
|
|
return /\s/.test(text) ? `"${text}"` : text;
|
|
}
|
|
|
|
function quoteCmdArg(value) {
|
|
const text = String(value);
|
|
if (!/[ \t"&|<>^]/.test(text)) return text;
|
|
return `"${text.replace(/"/g, '""')}"`;
|
|
}
|
|
|
|
function isWindowsCmd(command) {
|
|
return process.platform === "win32" && /\.(cmd|bat)$/i.test(command);
|
|
}
|
|
|
|
function run(command, args, env, dryRun) {
|
|
const display = [command, ...args].map(quoteDisplay).join(" ");
|
|
console.log(`[package-client] ${display}`);
|
|
if (dryRun) return;
|
|
|
|
const spawnCommand = isWindowsCmd(command)
|
|
? (process.env.ComSpec || "cmd.exe")
|
|
: command;
|
|
const spawnArgs = isWindowsCmd(command)
|
|
? ["/d", "/s", "/c", [quoteCmdArg(command), ...args.map(quoteCmdArg)].join(" ")]
|
|
: args;
|
|
|
|
const result = spawnSync(spawnCommand, spawnArgs, {
|
|
cwd: projectRoot,
|
|
stdio: "inherit",
|
|
env,
|
|
shell: false,
|
|
});
|
|
|
|
if (result.error) {
|
|
throw result.error;
|
|
}
|
|
|
|
if (result.status !== 0) {
|
|
throw new Error(`命令执行失败:${display}`);
|
|
}
|
|
}
|
|
|
|
function main() {
|
|
if (hasArg("--help") || hasArg("-h")) {
|
|
usage();
|
|
return;
|
|
}
|
|
|
|
const authUrl = normalizeAuthUrl(
|
|
readArg("--auth-url") ||
|
|
process.env.PACKAGE_AUTH_SERVER_URL ||
|
|
process.env.AUTH_SERVER_URL ||
|
|
process.env.VITE_AUTH_SERVER_URL,
|
|
);
|
|
const dryRun = hasArg("--dry-run");
|
|
const dirOnly = hasArg("--dir");
|
|
|
|
if (!authUrl) {
|
|
usage();
|
|
throw new Error("打包客户端必须指定认证服务地址:--auth-url=https://auth.example.com");
|
|
}
|
|
|
|
const env = {
|
|
...process.env,
|
|
AUTH_SERVER_URL: authUrl,
|
|
VITE_AUTH_SERVER_URL: authUrl,
|
|
PACKAGE_CLIENT_ONLY: "1",
|
|
};
|
|
|
|
console.log(`[package-client] 认证服务地址:${authUrl}`);
|
|
console.log("[package-client] 本脚本只打包客户端,不会启动或打包本地认证服务。");
|
|
|
|
run(npmCommand, ["run", "prepare-package"], env, dryRun);
|
|
run(npmCommand, ["run", "build"], env, dryRun);
|
|
run(process.execPath, ["scripts/build-resource-artifacts.cjs"], env, dryRun);
|
|
run(electronBuilder, ["--win", "--x64", ...(dirOnly ? ["--dir"] : [])], env, dryRun);
|
|
|
|
if (!dirOnly) {
|
|
run(process.execPath, ["scripts/fix-latest-yml.cjs"], env, dryRun);
|
|
run(process.execPath, ["scripts/assemble-release-artifacts.cjs"], env, dryRun);
|
|
}
|
|
}
|
|
|
|
try {
|
|
main();
|
|
} catch (error) {
|
|
console.error(`[package-client] ${error.message}`);
|
|
process.exit(1);
|
|
}
|