90 lines
3.1 KiB
TypeScript
90 lines
3.1 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"),
|
|
NETWORK_CONFIGURATION_REQUEST_PATH: z.string().default("/var/lib/pi-car-companion/network-configuration-request.json"),
|
|
NETWORK_ACTIVITY_PATH: z.string().default("/var/lib/pi-car-companion/network-activity.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;
|
|
configurationRequestPath: string;
|
|
activityPath: 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,
|
|
configurationRequestPath: parsed.NETWORK_CONFIGURATION_REQUEST_PATH,
|
|
activityPath: parsed.NETWORK_ACTIVITY_PATH
|
|
},
|
|
adb: {
|
|
enabled: parsed.ADB_ENABLED,
|
|
executable: parsed.ADB_PATH,
|
|
serial: adbSerial,
|
|
timeoutMs: parsed.ADB_TIMEOUT_MS
|
|
}
|
|
};
|
|
}
|