56 lines
1.7 KiB
TypeScript
56 lines
1.7 KiB
TypeScript
import { randomBytes } from 'node:crypto';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import dotenv from 'dotenv';
|
|
|
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
const repoRoot = path.resolve(here, '../../..');
|
|
|
|
dotenv.config({ path: path.join(repoRoot, '.env'), quiet: true });
|
|
|
|
function required(name: string, fallback?: string): string {
|
|
const value = process.env[name] ?? fallback;
|
|
if (!value) {
|
|
throw new Error(
|
|
`Variable d'environnement manquante : ${name}. Copie .env.example vers .env et complète-la.`,
|
|
);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function int(name: string, fallback: number): number {
|
|
const raw = process.env[name];
|
|
if (!raw) return fallback;
|
|
const parsed = Number.parseInt(raw, 10);
|
|
return Number.isFinite(parsed) ? parsed : fallback;
|
|
}
|
|
|
|
const isDev = process.env.NODE_ENV !== 'production';
|
|
|
|
export const config = {
|
|
port: int('PORT', 8080),
|
|
host: process.env.HOST ?? '0.0.0.0',
|
|
isDev,
|
|
|
|
adminPassword: required('ADMIN_PASSWORD', isDev ? 'admin' : undefined),
|
|
sessionSecret: required(
|
|
'SESSION_SECRET',
|
|
isDev ? randomBytes(32).toString('hex') : undefined,
|
|
),
|
|
sessionTtlMs: int('SESSION_TTL_MS', 12 * 60 * 60 * 1000),
|
|
|
|
/** Vide = enrôlement automatique désactivé. */
|
|
enrollmentToken: process.env.ENROLLMENT_TOKEN ?? '',
|
|
|
|
dbPath: path.resolve(repoRoot, process.env.DB_PATH ?? './data/stream-control.sqlite'),
|
|
|
|
statusIntervalMs: int('STATUS_INTERVAL_MS', 2000),
|
|
agentTimeoutMs: int('AGENT_TIMEOUT_MS', 15_000),
|
|
commandTimeoutMs: int('COMMAND_TIMEOUT_MS', 15_000),
|
|
|
|
/** Nombre d'entrées de journal conservées en base. */
|
|
logRetention: int('LOG_RETENTION', 2000),
|
|
|
|
webDist: path.resolve(repoRoot, 'packages/web/dist'),
|
|
} as const;
|