88 lines
2.4 KiB
TypeScript
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;
|
|
}
|