34 lines
1.6 KiB
TypeScript
34 lines
1.6 KiB
TypeScript
import { readFileSync } from 'node:fs';
|
|
|
|
export type ServerConfig = {
|
|
host: string;
|
|
port: number;
|
|
mongoUri: string;
|
|
mongoDatabase: string;
|
|
visitStore: 'mongo' | 'memory';
|
|
allowedOrigins: string[];
|
|
};
|
|
|
|
export function loadServerConfig(path: string | URL = new URL('../.config.json', import.meta.url)): ServerConfig {
|
|
let contents: string;
|
|
try { contents = readFileSync(path, 'utf8'); }
|
|
catch { throw new Error('Cannot read .config.json; copy .config.example.json to .config.json and configure the server.'); }
|
|
let value: unknown;
|
|
try { value = JSON.parse(contents); }
|
|
catch { throw new Error('Invalid JSON in .config.json'); }
|
|
if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Invalid .config.json: expected an object');
|
|
const config = value as Record<string, unknown>;
|
|
const nonempty = (value: unknown): value is string => typeof value === 'string' && value.trim().length > 0;
|
|
for (const field of ['host', 'mongoUri', 'mongoDatabase']) {
|
|
if (!nonempty(config[field])) throw new Error(`Invalid .config.json field: ${field}`);
|
|
}
|
|
if (typeof config.port !== 'number' || !Number.isInteger(config.port) || config.port < 0 || config.port > 65535) {
|
|
throw new Error('Invalid .config.json field: port');
|
|
}
|
|
if (config.visitStore !== 'mongo' && config.visitStore !== 'memory') throw new Error('Invalid .config.json field: visitStore');
|
|
if (!Array.isArray(config.allowedOrigins) || !config.allowedOrigins.length || !config.allowedOrigins.every(nonempty)) {
|
|
throw new Error('Invalid .config.json field: allowedOrigins');
|
|
}
|
|
return config as ServerConfig;
|
|
}
|