Files
klz-cables.com/lib/config.ts
Marc Mintel 859d034ed7
Some checks failed
Build & Deploy KLZ Cables / build-and-deploy (push) Failing after 1m17s
env
2026-01-28 15:26:36 +01:00

137 lines
3.4 KiB
TypeScript

/**
* Centralized configuration management for the application.
* This file provides a type-safe way to access environment variables.
*/
import { envSchema, getRawEnv } from './env';
let memoizedConfig: ReturnType<typeof createConfig> | undefined;
/**
* Creates and validates the configuration object.
* Throws if validation fails.
*/
function createConfig() {
const env = envSchema.parse(getRawEnv());
return {
env: env.NODE_ENV,
isProduction: env.NODE_ENV === 'production',
isDevelopment: env.NODE_ENV === 'development',
isTest: env.NODE_ENV === 'test',
baseUrl: env.NEXT_PUBLIC_BASE_URL,
analytics: {
umami: {
websiteId: env.NEXT_PUBLIC_UMAMI_WEBSITE_ID,
scriptUrl: env.NEXT_PUBLIC_UMAMI_SCRIPT_URL,
// The proxied path used in the frontend
proxyPath: '/stats/script.js',
enabled: Boolean(env.NEXT_PUBLIC_UMAMI_WEBSITE_ID),
},
},
errors: {
glitchtip: {
// Use SENTRY_DSN for both server and client (proxied)
dsn: env.SENTRY_DSN,
// The proxied origin used in the frontend
proxyPath: '/errors',
enabled: Boolean(env.SENTRY_DSN),
},
},
cache: {
redis: {
url: env.REDIS_URL,
keyPrefix: env.REDIS_KEY_PREFIX,
enabled: Boolean(env.REDIS_URL),
},
},
logging: {
level: env.LOG_LEVEL,
},
mail: {
host: env.MAIL_HOST,
port: env.MAIL_PORT,
user: env.MAIL_USERNAME,
pass: env.MAIL_PASSWORD,
from: env.MAIL_FROM,
recipients: env.MAIL_RECIPIENTS,
},
} as const;
}
/**
* Returns the validated configuration.
* Memoizes the result after the first call.
*/
export function getConfig() {
if (!memoizedConfig) {
memoizedConfig = createConfig();
}
return memoizedConfig;
}
/**
* Exported config object for convenience.
* Uses getters to ensure it's only initialized when accessed.
*/
export const config = {
get env() { return getConfig().env; },
get isProduction() { return getConfig().isProduction; },
get isDevelopment() { return getConfig().isDevelopment; },
get isTest() { return getConfig().isTest; },
get baseUrl() { return getConfig().baseUrl; },
get analytics() { return getConfig().analytics; },
get errors() { return getConfig().errors; },
get cache() { return getConfig().cache; },
get logging() { return getConfig().logging; },
get mail() { return getConfig().mail; },
};
/**
* Helper to get a masked version of the config for logging.
*/
export function getMaskedConfig() {
const c = getConfig();
const mask = (val: string | undefined) => (val ? `***${val.slice(-4)}` : 'not set');
return {
env: c.env,
baseUrl: c.baseUrl,
analytics: {
umami: {
websiteId: mask(c.analytics.umami.websiteId),
scriptUrl: c.analytics.umami.scriptUrl,
enabled: c.analytics.umami.enabled,
},
},
errors: {
glitchtip: {
dsn: mask(c.errors.glitchtip.dsn),
enabled: c.errors.glitchtip.enabled,
},
},
cache: {
redis: {
url: mask(c.cache.redis.url),
keyPrefix: c.cache.redis.keyPrefix,
enabled: c.cache.redis.enabled,
},
},
logging: {
level: c.logging.level,
},
mail: {
host: c.mail.host,
port: c.mail.port,
user: mask(c.mail.user),
from: c.mail.from,
recipients: c.mail.recipients,
},
};
}