splitwise / src /lib /server /config.ts
assafvayner's picture
assafvayner HF Staff
fix(app): 503 on storage failures, validated currency, lock release on shutdown, per-IP login limit, unit-only npm test
e830ad4
Raw
History Blame Contribute Delete
1.99 kB
import { env } from '$env/dynamic/private';
import { dev } from '$app/environment';
export interface Config {
storage: 'local' | 'hf';
hfToken: string;
hfBucket: `buckets/${string}`;
/** Directory inside the bucket that this deployment owns; '' means the bucket root. */
hfPrefix: string;
localDataDir: string;
sessionSecret: string;
currency: string;
compactionIntervalMs: number;
}
function required(name: string, value: string | undefined): string {
if (!value) throw new Error(`Missing required environment variable ${name}`);
return value;
}
export function loadConfig(): Config {
const storage = (env.STORAGE ?? (dev ? 'local' : 'hf')) as Config['storage'];
if (storage !== 'local' && storage !== 'hf') throw new Error(`STORAGE must be 'local' or 'hf', got '${storage}'`);
const sessionSecret = env.SESSION_SECRET ?? (dev ? 'dev-only-session-secret-do-not-use-in-prod' : undefined);
const hfBucket = storage === 'hf' ? required('HF_BUCKET', env.HF_BUCKET) : '';
if (storage === 'hf' && !hfBucket.startsWith('buckets/')) throw new Error('HF_BUCKET must look like buckets/<namespace>/<name>');
const secret = required('SESSION_SECRET', sessionSecret);
if (!dev && secret.length < 32) throw new Error('SESSION_SECRET must be at least 32 characters in production');
const compactionIntervalMs = Number(env.COMPACTION_INTERVAL_MS ?? 3_600_000);
if (!Number.isFinite(compactionIntervalMs) || compactionIntervalMs < 60_000)
throw new Error('COMPACTION_INTERVAL_MS must be a number of milliseconds ≥ 60000');
const currency = env.CURRENCY ?? 'USD';
if (!/^[A-Z]{3}$/.test(currency)) throw new Error('CURRENCY must be a 3-letter uppercase ISO 4217 code');
return {
storage,
hfToken: storage === 'hf' ? required('HF_TOKEN', env.HF_TOKEN) : '',
hfBucket: hfBucket as `buckets/${string}`,
hfPrefix: (env.HF_PREFIX ?? '').replace(/^\/+|\/+$/g, ''),
localDataDir: env.LOCAL_DATA_DIR ?? '.data',
sessionSecret: secret,
currency,
compactionIntervalMs
};
}