117 lines
3.1 KiB
JavaScript
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;
|