mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 12:41:09 +02:00
170 lines
3.6 KiB
TypeScript
170 lines
3.6 KiB
TypeScript
/**
|
|
* Environment variable validation utilities
|
|
*/
|
|
|
|
import { z } from 'zod';
|
|
|
|
/**
|
|
* Common environment variable schemas
|
|
*/
|
|
export const envSchemas = {
|
|
/** URL schema */
|
|
url: z.string().url(),
|
|
|
|
/** Non-empty string schema */
|
|
nonEmpty: z.string().min(1),
|
|
|
|
/** Optional string schema */
|
|
optional: z.string().optional(),
|
|
|
|
/** Port number schema */
|
|
port: z.coerce.number().int().min(1).max(65535),
|
|
|
|
/** Boolean schema (accepts various formats) */
|
|
boolean: z.preprocess((val) => {
|
|
if (typeof val === 'boolean') return val;
|
|
if (typeof val === 'string') {
|
|
return ['true', '1', 'yes', 'on'].includes(val.toLowerCase());
|
|
}
|
|
return false;
|
|
}, z.boolean()),
|
|
|
|
/** Number schema */
|
|
number: z.coerce.number(),
|
|
|
|
/** Positive integer schema */
|
|
positiveInt: z.coerce.number().int().positive(),
|
|
|
|
/** Email schema */
|
|
email: z.string().email(),
|
|
|
|
/** Node environment schema */
|
|
nodeEnv: z.enum(['development', 'production', 'test']).default('development'),
|
|
};
|
|
|
|
/**
|
|
* Common Supabase environment schema
|
|
*/
|
|
export const supabaseEnvSchema = z.object({
|
|
SUPABASE_URL: envSchemas.url,
|
|
SUPABASE_ANON_KEY: envSchemas.nonEmpty,
|
|
SUPABASE_SERVICE_ROLE_KEY: envSchemas.nonEmpty.optional(),
|
|
});
|
|
|
|
/**
|
|
* Common app environment schema
|
|
*/
|
|
export const appEnvSchema = z.object({
|
|
NODE_ENV: envSchemas.nodeEnv,
|
|
PORT: envSchemas.port.default(3000),
|
|
});
|
|
|
|
/**
|
|
* Create an environment config from schema
|
|
*/
|
|
export function createEnvConfig<T extends z.ZodTypeAny>(
|
|
schema: T,
|
|
env: NodeJS.ProcessEnv = process.env
|
|
): z.infer<T> {
|
|
const result = schema.safeParse(env);
|
|
|
|
if (!result.success) {
|
|
const errors = result.error.errors
|
|
.map((err) => ` ${err.path.join('.')}: ${err.message}`)
|
|
.join('\n');
|
|
|
|
throw new Error(`Environment validation failed:\n${errors}`);
|
|
}
|
|
|
|
return result.data;
|
|
}
|
|
|
|
/**
|
|
* Validate environment variables with custom schema
|
|
*/
|
|
export function validateEnv<T extends z.ZodRawShape>(
|
|
schema: z.ZodObject<T>,
|
|
env: NodeJS.ProcessEnv = process.env
|
|
): z.infer<z.ZodObject<T>> {
|
|
return createEnvConfig(schema, env);
|
|
}
|
|
|
|
/**
|
|
* Get required environment variable with type safety
|
|
*/
|
|
export function getRequiredEnv(key: string, env: NodeJS.ProcessEnv = process.env): string {
|
|
const value = env[key];
|
|
|
|
if (value === undefined || value === '') {
|
|
throw new Error(`Required environment variable "${key}" is not set`);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Get optional environment variable with default
|
|
*/
|
|
export function getEnv(
|
|
key: string,
|
|
defaultValue: string,
|
|
env: NodeJS.ProcessEnv = process.env
|
|
): string {
|
|
return env[key] ?? defaultValue;
|
|
}
|
|
|
|
/**
|
|
* Get boolean environment variable
|
|
*/
|
|
export function getBoolEnv(
|
|
key: string,
|
|
defaultValue = false,
|
|
env: NodeJS.ProcessEnv = process.env
|
|
): boolean {
|
|
const value = env[key];
|
|
|
|
if (value === undefined) {
|
|
return defaultValue;
|
|
}
|
|
|
|
return ['true', '1', 'yes', 'on'].includes(value.toLowerCase());
|
|
}
|
|
|
|
/**
|
|
* Get number environment variable
|
|
*/
|
|
export function getNumEnv(
|
|
key: string,
|
|
defaultValue: number,
|
|
env: NodeJS.ProcessEnv = process.env
|
|
): number {
|
|
const value = env[key];
|
|
|
|
if (value === undefined) {
|
|
return defaultValue;
|
|
}
|
|
|
|
const parsed = Number(value);
|
|
return isNaN(parsed) ? defaultValue : parsed;
|
|
}
|
|
|
|
/**
|
|
* Check if running in development
|
|
*/
|
|
export function isDevelopment(env: NodeJS.ProcessEnv = process.env): boolean {
|
|
return env.NODE_ENV === 'development';
|
|
}
|
|
|
|
/**
|
|
* Check if running in production
|
|
*/
|
|
export function isProduction(env: NodeJS.ProcessEnv = process.env): boolean {
|
|
return env.NODE_ENV === 'production';
|
|
}
|
|
|
|
/**
|
|
* Check if running in test
|
|
*/
|
|
export function isTest(env: NodeJS.ProcessEnv = process.env): boolean {
|
|
return env.NODE_ENV === 'test';
|
|
}
|