Files
uptimerunner/ts/config.ts
T
2026-04-29 19:48:14 +00:00

78 lines
2.9 KiB
TypeScript

import type { IUptimeRunnerConfig } from './interfaces.ts';
export const DEFAULT_CONFIG_PATH = '/etc/uptimerunner/config.json';
export async function loadConfig(configPathArg = getConfigPath()): Promise<IUptimeRunnerConfig> {
const fileConfig = await readConfigFile(configPathArg);
const config = applyEnvironmentOverrides(fileConfig);
validateConfig(config);
return config;
}
export async function writeConfig(
configArg: IUptimeRunnerConfig,
configPathArg = getConfigPath(),
): Promise<void> {
validateConfig(configArg);
const configDir = configPathArg.slice(0, configPathArg.lastIndexOf('/')) || '.';
await Deno.mkdir(configDir, { recursive: true });
await Deno.writeTextFile(`${configPathArg}.tmp`, `${JSON.stringify(configArg, null, 2)}\n`);
await Deno.rename(`${configPathArg}.tmp`, configPathArg);
}
export function getConfigPath(): string {
return Deno.env.get('UPTIMERUNNER_CONFIG') || DEFAULT_CONFIG_PATH;
}
export function applyEnvironmentOverrides(configArg: Partial<IUptimeRunnerConfig>) {
const labels = Deno.env.get('UPTIMERUNNER_LABELS');
const pollIntervalMs = Deno.env.get('UPTIMERUNNER_POLL_INTERVAL_MS');
const maxConcurrentChecks = Deno.env.get('UPTIMERUNNER_MAX_CONCURRENT_CHECKS');
return {
...configArg,
instanceUrl: Deno.env.get('UPTIMERUNNER_INSTANCE_URL') || configArg.instanceUrl,
runnerId: Deno.env.get('UPTIMERUNNER_RUNNER_ID') || configArg.runnerId,
token: Deno.env.get('UPTIMERUNNER_TOKEN') || configArg.token,
labels: labels
? labels.split(',').map((labelArg) => labelArg.trim()).filter(Boolean)
: configArg.labels,
pollIntervalMs: pollIntervalMs ? Number(pollIntervalMs) : configArg.pollIntervalMs,
maxConcurrentChecks: maxConcurrentChecks
? Number(maxConcurrentChecks)
: configArg.maxConcurrentChecks,
} satisfies Partial<IUptimeRunnerConfig>;
}
export function validateConfig(
configArg: Partial<IUptimeRunnerConfig>,
): asserts configArg is IUptimeRunnerConfig {
if (!configArg.instanceUrl) {
throw new Error('Missing instanceUrl. Set it in config or UPTIMERUNNER_INSTANCE_URL.');
}
if (!configArg.runnerId) {
throw new Error('Missing runnerId. Set it in config or UPTIMERUNNER_RUNNER_ID.');
}
if (!configArg.token) {
throw new Error('Missing token. Set it in config or UPTIMERUNNER_TOKEN.');
}
if (configArg.pollIntervalMs !== undefined && configArg.pollIntervalMs < 1000) {
throw new Error('pollIntervalMs must be at least 1000ms.');
}
if (configArg.maxConcurrentChecks !== undefined && configArg.maxConcurrentChecks < 1) {
throw new Error('maxConcurrentChecks must be at least 1.');
}
}
async function readConfigFile(configPathArg: string): Promise<Partial<IUptimeRunnerConfig>> {
try {
const configText = await Deno.readTextFile(configPathArg);
return JSON.parse(configText) as Partial<IUptimeRunnerConfig>;
} catch (error) {
if (error instanceof Deno.errors.NotFound) {
return {};
}
throw error;
}
}