/** * 运行所需的配置项,全部来自环境变量(Bun 会自动读取 .env)。 * * 这里刻意在启动时就把缺失项报出来,而不是等到某个请求进来才失败—— * 配置类工具最糟糕的失败方式是「界面能打开、点保存才发现连不上内核」。 */ import { resolve } from 'node:path' function required(name: string): string { const value = Bun.env[name] if (!value) { throw new Error( `缺少环境变量 ${name}。把 .env.example 复制成 .env 再填,或者在启动命令里带上它。`, ) } return value } function optional(name: string, fallback: string): string { return Bun.env[name] || fallback } /** * 路径一律转成绝对路径。 * * 不只是为了整洁:内核的 `PUT /configs` 接口拒绝相对路径,会直接回 * `path is not a absolute path`。在这里统一处理,别让 .env 里怎么写决定后面能不能跑。 */ function absolute(name: string): string { return resolve(required(name)) } export interface Env { /** mihomo 管理接口的地址,例如 http://127.0.0.1:9090 */ mihomoApi: string /** 管理接口的访问密钥,即配置文件里 secret: 那一行 */ mihomoSecret: string /** 要编辑的配置文件路径 */ configPath: string /** mihomo 可执行文件路径,用于运行 `mihomo -t` 校验 */ mihomoBin: string /** 传给 `mihomo -t -d` 的工作目录 */ mihomoHome: string /** Patchbay 自己监听的地址 */ host: string /** Patchbay 自己监听的端口 */ port: number } export function readEnv(): Env { const port = Number(optional('PATCHBAY_PORT', '7580')) if (!Number.isInteger(port) || port < 1 || port > 65535) { throw new Error(`PATCHBAY_PORT 不是合法端口号:${String(Bun.env.PATCHBAY_PORT)}`) } return { mihomoApi: required('MIHOMO_API').replace(/\/+$/, ''), mihomoSecret: required('MIHOMO_SECRET'), configPath: absolute('PATCHBAY_CONFIG'), mihomoBin: absolute('PATCHBAY_MIHOMO_BIN'), mihomoHome: absolute('PATCHBAY_MIHOMO_HOME'), host: optional('PATCHBAY_HOST', '127.0.0.1'), port, } }