import { z } from "zod"; const ENVIRONMENT = Bun.env.NODE_ENV || "development"; const IS_PROD = Bun.env.NODE_ENV === "production"; const CONFIG_PATH = `./data/config.${ENVIRONMENT}.json`; const discordSchema = z.object({ token: z.string(), app_id: z.string(), }); const gameSchema = z .object({ name: z.string(), universeId: z.string(), }) .transform((game) => { const initials = game.name .split(" ") .map((word) => word[0]) .join(""); return { ...game, id: initials.toLowerCase(), }; }); const gamesSchema = z.array(gameSchema); const configSchema = z .object({ discord: discordSchema, games: gamesSchema, }) .transform((config) => { return { ...config, environment: ENVIRONMENT, isProduction: IS_PROD, }; }); // --- types ------------------------------------------------------------------ export type Config = z.infer; export type Game = z.infer; // ---------------------------------------------------------------------------- async function loadConfig(): Promise { const file = Bun.file(CONFIG_PATH); if (!(await file.exists())) { console.error(`[!] couldn't find a config file at ${CONFIG_PATH}`); process.exit(1); } const json = await file.json(); const parsed = configSchema.safeParse(json); if (parsed.success) return parsed.data; console.error("[!] failed to parse config:"); const longestPath = Math.max(...parsed.error.issues.map((err) => err.path.join(".").length)); for (const err of parsed.error.issues) { const path = err.path.join("."); console.error(` * ${path.padEnd(longestPath)} ${err.message} (${err.code})`); } process.exit(1); } // ---------------------------------------------------------------------------- const config = await loadConfig(); export default config;