Files
devops-platform-api/src/config/env.schema.ts
T

88 lines
2.4 KiB
TypeScript

import { z } from 'zod';
const optionalUrl = z
.string()
.trim()
.url()
.optional()
.or(z.literal('').transform(() => undefined));
const optionalString = z
.string()
.trim()
.min(1)
.optional()
.or(z.literal('').transform(() => undefined));
const booleanFromEnv = z.preprocess((value) => {
if (value === undefined || value === null || value === '') {
return undefined;
}
if (typeof value === 'boolean') {
return value;
}
if (typeof value === 'string') {
return ['1', 'true', 'yes', 'on'].includes(value.toLowerCase());
}
if (typeof value === 'number') {
return value === 1;
}
return false;
}, z.boolean().default(false));
const positiveIntegerFromEnv = (defaultValue: number) =>
z.preprocess((value) => {
if (value === undefined || value === null || value === '') {
return undefined;
}
return value;
}, z.coerce.number().int().positive().default(defaultValue));
export const envSchema = z.object({
NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
PORT: z.coerce.number().int().positive().default(4300),
CORS_ORIGIN: optionalString,
LOG_LEVEL: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info'),
DATABASE_URL: optionalString,
USE_DATABASE_READS: booleanFromEnv,
PRISMA_CONNECT_ON_BOOT: booleanFromEnv,
REDIS_URL: optionalString,
JENKINS_BASE_URL: optionalUrl,
JENKINS_USERNAME: optionalString,
JENKINS_API_TOKEN: optionalString,
JENKINS_AUTO_SYNC_ENABLED: booleanFromEnv,
JENKINS_AUTO_SYNC_INTERVAL_MS: positiveIntegerFromEnv(30000),
GITEA_BASE_URL: optionalUrl,
GITEA_TOKEN: optionalString,
GITEA_WEBHOOK_SECRET: optionalString,
DEVOPS_PUBLIC_URL: optionalUrl,
NOTIFICATION_PROVIDER: optionalString,
NOTIFICATION_WEBHOOK_URL: optionalUrl,
FEISHU_WEBHOOK_URL: optionalUrl,
WECOM_WEBHOOK_URL: optionalUrl,
LLM_BASE_URL: optionalUrl,
LLM_API_KEY: optionalString,
LLM_MODEL: optionalString,
SECRET_ENCRYPTION_KEY: optionalString,
});
export type EnvConfig = z.infer<typeof envSchema>;
export function validateEnv(config: Record<string, unknown>): EnvConfig {
const result = envSchema.safeParse(config);
if (!result.success) {
const details = result.error.issues
.map((issue) => `${issue.path.join('.')}: ${issue.message}`)
.join('; ');
throw new Error(`Invalid environment configuration: ${details}`);
}
return result.data;
}