feat: 新增webdav
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
// 统一启动入口:本地运行 Next CLI,Docker 保留 standalone,两者共管 WebDAV 生命周期。
|
||||
import { execFile, spawn } from "node:child_process";
|
||||
import { createRequire } from "node:module";
|
||||
import { getWebdavConfig } from "../src/server/webdav/config.mjs";
|
||||
|
||||
const mode = process.argv[2] || "standalone";
|
||||
if (!["dev", "start", "standalone"].includes(mode))
|
||||
throw new Error("启动模式必须为 dev、start 或 standalone");
|
||||
const local = mode !== "standalone";
|
||||
const load = createRequire(import.meta.url);
|
||||
if (local) {
|
||||
process.env.NODE_ENV = mode === "dev" ? "development" : "production";
|
||||
// 复用当前 Next 安装中的 env loader,与 Next 的 .env* 优先级和变量展开保持一致。
|
||||
const loadNext = createRequire(load.resolve("next/package.json"));
|
||||
loadNext("@next/env").loadEnvConfig(process.cwd(), mode === "dev");
|
||||
process.env.PORT = process.env.PORT?.trim() || "3200";
|
||||
process.env.WEBDAV_PORT = process.env.WEBDAV_PORT?.trim() || "3201";
|
||||
}
|
||||
const config = getWebdavConfig();
|
||||
if (config.enabled && config.port === Number(process.env.PORT))
|
||||
throw new Error("WebDAV 与管理页不能使用相同端口");
|
||||
|
||||
const children = [];
|
||||
let stopping = false;
|
||||
const stop = (code = 0) => {
|
||||
if (stopping) return;
|
||||
stopping = true;
|
||||
process.exitCode = code;
|
||||
for (const child of children) {
|
||||
if (child.exitCode !== null || child.signalCode !== null) continue;
|
||||
// next dev 还会创建服务进程;Windows 必须结束整个子进程树,避免残留监听端口。
|
||||
if (process.platform === "win32")
|
||||
execFile("taskkill", ["/PID", String(child.pid), "/T", "/F"], () => {});
|
||||
else child.kill("SIGTERM");
|
||||
}
|
||||
setTimeout(() => {
|
||||
for (const child of children) child.kill("SIGKILL");
|
||||
}, 6000).unref();
|
||||
};
|
||||
const start = (file, args = [], env = process.env) => {
|
||||
const child = spawn(process.execPath, [file, ...args], {
|
||||
stdio: "inherit",
|
||||
env
|
||||
});
|
||||
children.push(child);
|
||||
child.on("error", () => stop(1));
|
||||
child.on("exit", (code, signal) => {
|
||||
if (!stopping) stop(code || (signal ? 1 : 0));
|
||||
});
|
||||
};
|
||||
|
||||
if (local)
|
||||
start(load.resolve("next/dist/bin/next"), [mode, "-p", process.env.PORT]);
|
||||
else start("server.js");
|
||||
if (config.enabled) {
|
||||
const env = { ...process.env };
|
||||
// 本地无密钥的演示模式沿用网页的 mock 密钥,不改变 Next 进程的演示提示。
|
||||
if (local && !env.TORBOX_API_KEY?.trim() && !env.ACCESS_TOKEN?.trim())
|
||||
env.ACCESS_TOKEN = "mock";
|
||||
start("scripts/webdav.mjs", [], env);
|
||||
}
|
||||
process.once("SIGINT", () => stop());
|
||||
process.once("SIGTERM", () => stop());
|
||||
Reference in New Issue
Block a user