Files
illusory-mapp/packages/settings/index.ts

121 lines
3.3 KiB
TypeScript

import * as v from "valibot";
import "dotenv/config";
/**
* Settings schema using Valibot for validation
*/
export const settingsSchema = v.object({
appName: v.string(),
nodeEnv: v.string(),
logLevel: v.string(),
isDevelopment: v.optional(v.boolean()),
redisUrl: v.string(),
databaseUrl: v.string(),
internalApiKey: v.string(),
debugKey: v.string(),
processorApiUrl: v.string(),
betterAuthUrl: v.string(),
betterAuthSecret: v.string(),
twoFaSecret: v.string(),
twofaSessionExpiryMinutes: v.optional(v.number()),
twofaRequiredHours: v.optional(v.number()),
defaultAdminEmail: v.string(),
defaultAdminPassword: v.string(),
otelServiceName: v.string(),
otelExporterOtlpHttpEndpoint: v.string(),
});
export type Settings = v.InferOutput<typeof settingsSchema>;
/**
* Helper to get environment variable with default value
*/
function getEnv(key: string, defaultValue: string = ""): string {
return process.env[key] ?? defaultValue;
}
/**
* Helper to get environment variable as number with default value
*/
function getEnvNumber(key: string, defaultValue: number): number {
const value = process.env[key];
if (!value) return defaultValue;
const parsed = Number(value);
return Number.isNaN(parsed) ? defaultValue : parsed;
}
/**
* Load and validate settings from environment variables
*/
function loadSettings(): Settings {
const nodeEnv = getEnv("NODE_ENV", "development");
const rawSettings = {
appName: getEnv("APP_NAME", "App"),
nodeEnv,
logLevel: getEnv("LOG_LEVEL", "info"),
isDevelopment: nodeEnv === "development",
redisUrl: getEnv("REDIS_URL", "redis://localhost:6379"),
databaseUrl: getEnv("DATABASE_URL"),
internalApiKey: getEnv("INTERNAL_API_KEY"),
processorApiUrl: getEnv("PROCESSOR_API_URL", "http://localhost:3000"),
betterAuthUrl: getEnv("BETTER_AUTH_URL"),
betterAuthSecret: getEnv("BETTER_AUTH_SECRET"),
twoFaSecret: getEnv("TWOFA_SECRET"),
twofaSessionExpiryMinutes: getEnvNumber(
"TWOFA_SESSION_EXPIRY_MINUTES",
10,
),
twofaRequiredHours: getEnvNumber("TWOFA_REQUIRED_HOURS", 24),
defaultAdminEmail: getEnv("DEFAULT_ADMIN_EMAIL"),
defaultAdminPassword: getEnv("DEFAULT_ADMIN_PASSWORD"),
otelServiceName: getEnv("OTEL_SERVICE_NAME"),
otelExporterOtlpHttpEndpoint: getEnv(
"OTEL_EXPORTER_OTLP_HTTP_ENDPOINT",
),
};
try {
return v.parse(settingsSchema, rawSettings);
} catch (error) {
console.error("❌ Settings validation failed:");
if (error instanceof v.ValiError) {
for (const issue of error.issues) {
console.error(
` - ${issue.path?.map((p: any) => p.key).join(".")}: ${issue.message}`,
);
}
} else {
console.error(error);
}
throw new Error(
"Failed to load settings. Check environment variables.",
);
}
}
export const settings = loadSettings();
export const getSetting = <K extends keyof Settings>(key: K): Settings[K] => {
return settings[key];
};
console.log(`✅ Settings loaded | ${settings.appName} (${settings.nodeEnv})`);