Files
pi-car-companion/server/src/config.ts
T

84 lines
2.7 KiB
TypeScript

import { resolve } from "node:path";
import { z } from "zod";
import type { AdbConfig } from "./adb.js";
const booleanFromString = z
.enum(["true", "false"])
.default("false")
.transform((value) => value === "true");
const schema = z.object({
NODE_ENV: z.enum(["development", "test", "production"]).default("development"),
HOST: z.string().default("127.0.0.1"),
PORT: z.coerce.number().int().min(1).max(65_535).default(8787),
DATABASE_PATH: z.string().default(resolve("data/companion.db")),
SESSION_TTL_HOURS: z.coerce.number().positive().max(24 * 30).default(24),
COOKIE_SECURE: booleanFromString,
ALLOWED_ORIGINS: z.string().default("http://mg4pi.local:8787"),
UPDATE_STATUS_PATH: z.string().default("/var/lib/pi-car-companion/update-status.json"),
VERSION_FILE: z.string().default(resolve("REVISION")),
NETWORK_MANAGER_ENABLED: booleanFromString,
NETWORK_STATUS_PATH: z.string().default("/var/lib/pi-car-companion/network-status.json"),
NETWORK_COMMAND_PATH: z.string().default("/var/lib/pi-car-companion/network-command.json"),
ADB_ENABLED: booleanFromString,
ADB_PATH: z.string().min(1).default("adb"),
ADB_SERIAL: z.string().max(128).regex(/^[a-zA-Z0-9._:-]*$/).default(""),
ADB_TIMEOUT_MS: z.coerce.number().int().min(500).max(15_000).default(3_000)
});
export type AppConfig = {
nodeEnv: "development" | "test" | "production";
host: string;
port: number;
databasePath: string;
sessionTtlMs: number;
cookieSecure: boolean;
allowedOrigins: ReadonlySet<string>;
updateStatusPath: string;
versionFile: string;
network: {
enabled: boolean;
statusPath: string;
commandPath: string;
};
adb: AdbConfig;
};
export function loadConfig(environment: NodeJS.ProcessEnv = process.env): AppConfig {
const parsed = schema.parse(environment);
const allowedOrigins = new Set(
parsed.ALLOWED_ORIGINS.split(",")
.map((origin) => origin.trim())
.filter(Boolean)
);
if (parsed.NODE_ENV === "development") {
allowedOrigins.add("http://localhost:5173");
allowedOrigins.add("http://127.0.0.1:5173");
}
const adbSerial = parsed.ADB_SERIAL.trim() || null;
return {
nodeEnv: parsed.NODE_ENV,
host: parsed.HOST,
port: parsed.PORT,
databasePath: parsed.DATABASE_PATH,
sessionTtlMs: parsed.SESSION_TTL_HOURS * 60 * 60 * 1000,
cookieSecure: parsed.COOKIE_SECURE,
allowedOrigins,
updateStatusPath: parsed.UPDATE_STATUS_PATH,
versionFile: parsed.VERSION_FILE,
network: {
enabled: parsed.NETWORK_MANAGER_ENABLED,
statusPath: parsed.NETWORK_STATUS_PATH,
commandPath: parsed.NETWORK_COMMAND_PATH
},
adb: {
enabled: parsed.ADB_ENABLED,
executable: parsed.ADB_PATH,
serial: adbSerial,
timeoutMs: parsed.ADB_TIMEOUT_MS
}
};
}