brf/server/env.ts
2025-12-18 07:31:37 +01:00

63 lines
1.4 KiB
TypeScript

function read<
const C extends readonly string[],
D extends Partial<Record<C[number], any>> & Record<Exclude<keyof D, C[number]>, never> = {},
>(variables: C, defaults: D): Record<C[number], any> {
const missing: string[] = []
const result: Record<string, any> = {}
for (const variable of variables) {
let value: string | number | boolean | null | undefined = process.env[variable] || defaults[variable as keyof D]
if (value === undefined) {
missing.push(variable)
} else {
if (typeof value === 'string') {
if (/^\d+$/.test(value)) {
value = Number(value)
} else if (['false', 'true', 'null', 'undefined'].includes(value)) {
// oxlint-disable-next-line no-eval
value = eval(value)
}
}
}
result[variable] = value
}
if (missing.length) {
throw new Error(`Missing required env variables: ${missing.join(', ')}`)
}
return result
}
export default read(
[
'DOMAIN',
'PROTOCOL',
'HOSTNAME',
'PORT',
'FASTIFY_PORT',
'FASTIFY_HOST',
'LOG_LEVEL',
'LOG_STREAM',
'MAILGUN_API_KEY',
'NODE_ENV',
'PGDATABASE',
'PGHOST',
'PGPASSWORD',
'PGPORT',
'PGUSER',
'REDIS_HOST',
'SESSION_SECRET',
] as const,
{
MAILGUN_API_KEY: 'this is not a real key',
PGPASSWORD: null,
PGPORT: null,
PGUSER: null,
SESSION_SECRET: 'this is not very secret but it is long enough',
},
)