接入本地认证启动配置

This commit is contained in:
cat-shark
2026-06-20 10:13:00 +08:00
parent 0fd56f8841
commit 8922a3eef6
3 changed files with 82 additions and 16 deletions
+77 -13
View File
@@ -5,6 +5,7 @@ const { spawn, spawnSync } = require("node:child_process");
const projectRoot = path.resolve(__dirname, "..");
const serverUrl = process.env.VITE_DEV_SERVER_URL || "http://127.0.0.1:3354";
const authServerUrl = process.env.AUTH_SERVER_URL || "http://127.0.0.1:3302";
const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm";
const requiredNodeMajor = 20;
const checkOnly = process.argv.includes("--check");
@@ -18,11 +19,11 @@ function fail(message) {
process.exit(1);
}
function parseServerUrl(url) {
function parseUrl(url, name) {
try {
return new URL(url);
} catch {
fail(`VITE_DEV_SERVER_URL 无效:${url}`);
fail(`${name} 无效:${url}`);
}
}
@@ -57,13 +58,13 @@ function checkDependencies() {
}
}
function assertPortAvailable(host, port) {
function assertPortAvailable(host, port, label) {
return new Promise((resolve, reject) => {
const server = net.createServer();
server.once("error", error => {
if (error.code === "EADDRINUSE") {
reject(new Error(`端口 ${port} 已被占用,请先关闭已有 Vite/Electron 开发进程。`));
reject(new Error(`${label} 端口 ${port} 已被占用,请先关闭已有进程。`));
return;
}
reject(error);
@@ -77,24 +78,75 @@ function assertPortAvailable(host, port) {
});
}
function canConnect(host, port) {
return new Promise(resolve => {
const socket = net.createConnection({ host, port });
const finish = ok => {
socket.destroy();
resolve(ok);
};
socket.setTimeout(500);
socket.once("connect", () => finish(true));
socket.once("timeout", () => finish(false));
socket.once("error", () => finish(false));
});
}
async function startLocalAuth(authUrl) {
const authHost = authUrl.hostname || "127.0.0.1";
const authPort = Number(authUrl.port || 3302);
if (await canConnect(authHost, authPort)) {
log(`本地认证服务已在运行:${authServerUrl}`);
return null;
}
const child = spawn(process.execPath, ["scripts/local-auth-server.cjs"], {
cwd: projectRoot,
stdio: "inherit",
env: {
...process.env,
LOCAL_AUTH_HOST: authHost,
LOCAL_AUTH_PORT: String(authPort),
},
shell: false,
});
child.on("error", error => {
fail(`本地认证服务启动失败:${error.message}`);
});
for (let attempt = 0; attempt < 40; attempt++) {
if (await canConnect(authHost, authPort)) {
return child;
}
await new Promise(resolve => setTimeout(resolve, 250));
}
child.kill();
fail(`本地认证服务未能在 ${authServerUrl} 启动。`);
}
async function main() {
process.chdir(projectRoot);
const parsedUrl = parseServerUrl(serverUrl);
const host = parsedUrl.hostname || "127.0.0.1";
const port = Number(parsedUrl.port || 3344);
const parsedServerUrl = parseUrl(serverUrl, "VITE_DEV_SERVER_URL");
const parsedAuthUrl = parseUrl(authServerUrl, "AUTH_SERVER_URL");
const viteHost = parsedServerUrl.hostname || "127.0.0.1";
const vitePort = Number(parsedServerUrl.port || 3354);
log("========================================");
log(" 本地快速启动:Vite + Electron");
log(" 本地快速启动:Local Auth + Vite + Electron");
log("========================================");
log(`项目目录:${projectRoot}`);
log(`认证服务:${authServerUrl}`);
log(`开发地址:${serverUrl}`);
log("");
checkNodeVersion();
const npmVersion = checkCommand(npmCommand, ["--version"], "npm");
checkDependencies();
await assertPortAvailable(host, port);
await assertPortAvailable(viteHost, vitePort, "Vite");
log(`Node.js${process.version}`);
log(`npm${npmVersion}`);
@@ -105,24 +157,36 @@ async function main() {
return;
}
const authChild = await startLocalAuth(parsedAuthUrl);
log("");
log("正在启动应用,关闭此窗口即可停止开发服务。");
log("默认本地账号:13800138000 / 123456");
log("");
const child = spawn(npmCommand, ["run", "dev:electron"], {
const appChild = spawn(npmCommand, ["run", "dev:electron"], {
cwd: projectRoot,
stdio: "inherit",
env: {
...process.env,
VITE_DEV_SERVER_URL: serverUrl,
AUTH_SERVER_URL: authServerUrl,
},
shell: process.platform === "win32",
});
child.on("exit", code => {
const shutdown = code => {
if (authChild && !authChild.killed) {
authChild.kill();
}
process.exit(code ?? 0);
});
};
child.on("error", error => {
process.on("SIGINT", () => shutdown(0));
process.on("SIGTERM", () => shutdown(0));
appChild.on("exit", shutdown);
appChild.on("error", error => {
fail(`启动失败:${error.message}`);
});
}