PPPAIMT-Crest/backend/src/config/env.js

117 lines
3.1 KiB
JavaScript

import dotenv from 'dotenv';
import { z } from 'zod';
dotenv.config({ quiet: true });
const optionalText = z.preprocess(
(value) => (value === '' || value === undefined ? undefined : value),
z.string().optional(),
);
const optionalUrl = z.preprocess(
(value) => (value === '' || value === undefined ? undefined : value),
z.string().url().optional(),
);
const optionalPort = z.preprocess(
(value) => (value === '' || value === undefined ? undefined : value),
z.coerce.number().int().positive().optional(),
);
const envSchema = z.object({
NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
PORT: z.coerce.number().int().positive().default(4000),
CORS_ORIGIN: z.string().min(1).default('http://localhost:5173'),
DB_HOST: optionalText,
DB_PORT: optionalPort,
DB_USER: optionalText,
DB_PASSWORD: optionalText,
DB_NAME: optionalText,
DB_SSL: z.preprocess(
(value) => (value === '' || value === undefined ? undefined : value),
z.enum(['true', 'false']).optional(),
),
S3_BUCKET: optionalText,
S3_REGION: optionalText,
S3_ACCESS_KEY_ID: optionalText,
S3_SECRET_ACCESS_KEY: optionalText,
SENDGRID_API_KEY: optionalText,
SENDGRID_SANDBOX_MODE: z.preprocess((value) => {
if (value === undefined || value === '') {
return false;
}
if (value === 'true' || value === true) {
return true;
}
if (value === 'false' || value === false) {
return false;
}
return value;
}, z.boolean()),
SENDGRID_WEBHOOK_VERIFICATION_KEY: optionalText,
ADMIN_NOTIFY_EMAILS: optionalText,
MAIL_FROM: optionalText,
APP_BASE_URL: optionalUrl,
JWT_SECRET: optionalText,
TOKEN_PEPPER: optionalText,
RECAPTCHA_SITE_KEY: optionalText,
RECAPTCHA_SECRET_KEY: optionalText,
CAPTCHA_ENABLED: z.preprocess((value) => {
if (value === undefined || value === '') {
return false;
}
if (value === 'true' || value === true) {
return true;
}
if (value === 'false' || value === false) {
return false;
}
return value;
}, z.boolean()),
ADMIN_EMAIL: optionalText,
ADMIN_PASSWORD: optionalText,
DATA_ENCRYPTION_KEY: optionalText,
WEASYPRINT_BIN: optionalText,
PDF_REGENERATE: z.preprocess(
(value) => (value === '' || value === undefined ? undefined : value),
z.enum(['never', 'changed', 'always']).default('never'),
),
TRUST_PROXY: z.preprocess((value) => {
if (value === undefined || value === '') {
return false;
}
if (value === 'true' || value === true) {
return true;
}
if (value === 'false' || value === false) {
return false;
}
return value;
}, z.boolean()),
});
const parsed = envSchema.safeParse(process.env);
if (!parsed.success) {
console.error('Invalid environment variables', parsed.error.flatten().fieldErrors);
process.exit(1);
}
if (parsed.data.NODE_ENV === 'production' && parsed.data.PDF_REGENERATE !== 'never') {
console.error(
`PDF_REGENERATE=${parsed.data.PDF_REGENERATE} is not allowed in production: stored consent and agreement PDFs must not change. Unset it or set PDF_REGENERATE=never.`,
);
process.exit(1);
}
export const env = parsed.data;