"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.env = void 0; const dotenv_1 = __importDefault(require("dotenv")); const zod_1 = require("zod"); dotenv_1.default.config(); const envSchema = zod_1.z.object({ // Server NODE_ENV: zod_1.z.enum(['development', 'production', 'test']).default('development'), PORT: zod_1.z.coerce.number().default(4000), API_URL: zod_1.z.string().default('http://localhost:4000'), ADMIN_URL: zod_1.z.string().default('http://localhost:3000'), DOMAIN: zod_1.z.string().default('cmlite.org'), // Database DATABASE_URL: zod_1.z.string(), // Redis REDIS_URL: zod_1.z.string().default('redis://redis-changemaker:6379'), // JWT JWT_ACCESS_SECRET: zod_1.z.string().min(32), JWT_REFRESH_SECRET: zod_1.z.string().min(32), JWT_ACCESS_EXPIRY: zod_1.z.string().default('15m'), JWT_REFRESH_EXPIRY: zod_1.z.string().default('7d'), // Encryption (for DB-stored secrets like SMTP password; falls back to JWT_ACCESS_SECRET) ENCRYPTION_KEY: zod_1.z.string().optional(), // Initial Super Admin (auto-created during database seeding) INITIAL_ADMIN_EMAIL: zod_1.z.string().email().default('admin@cmlite.org'), INITIAL_ADMIN_PASSWORD: zod_1.z.string().min(12).default('REQUIRED_STRONG_PASSWORD_CHANGE_THIS'), // SMTP SMTP_HOST: zod_1.z.string().default('mailhog-changemaker'), SMTP_PORT: zod_1.z.coerce.number().default(1025), SMTP_USER: zod_1.z.string().default(''), SMTP_PASS: zod_1.z.string().default(''), SMTP_FROM: zod_1.z.string().default('noreply@cmlite.org'), SMTP_FROM_NAME: zod_1.z.string().default('Changemaker Lite'), EMAIL_TEST_MODE: zod_1.z.string().default('true'), TEST_EMAIL_RECIPIENT: zod_1.z.string().default('admin@cmlite.org'), // Listmonk LISTMONK_URL: zod_1.z.string().default('http://listmonk-app:9000'), LISTMONK_ADMIN_USER: zod_1.z.string().default('admin'), LISTMONK_ADMIN_PASSWORD: zod_1.z.string().default(''), LISTMONK_SYNC_ENABLED: zod_1.z.string().default('false'), LISTMONK_PROXY_PORT: zod_1.z.coerce.number().default(9002), // Represent API (Canadian electoral data) REPRESENT_API_URL: zod_1.z.string().default('https://represent.opennorth.ca'), // CORS CORS_ORIGINS: zod_1.z.string().default('http://localhost:3000'), // Rate Limiting RATE_LIMIT_WINDOW_MS: zod_1.z.coerce.number().default(15 * 60 * 1000), RATE_LIMIT_MAX: zod_1.z.coerce.number().default(500), // Geocoding MAPBOX_API_KEY: zod_1.z.string().optional(), GEOCODING_RATE_LIMIT_MS: zod_1.z.coerce.number().default(1100), GEOCODING_CACHE_ENABLED: zod_1.z.string().default('true'), GEOCODING_CACHE_TTL_HOURS: zod_1.z.coerce.number().default(24), // Phase 2: Performance & Accuracy GOOGLE_MAPS_API_KEY: zod_1.z.string().optional(), GOOGLE_MAPS_ENABLED: zod_1.z.string().default('false'), GEOCODING_PARALLEL_ENABLED: zod_1.z.string().default('true'), GEOCODING_BATCH_SIZE: zod_1.z.coerce.number().default(10), // Bulk Re-Geocoding (Phase 3) BULK_GEOCODE_ENABLED: zod_1.z.string().default('true'), BULK_GEOCODE_MAX_BATCH: zod_1.z.coerce.number().default(5000), // Platform Services (NocoDB, n8n, Gitea) NOCODB_URL: zod_1.z.string().default('http://changemaker-v2-nocodb:8080'), NOCODB_PORT: zod_1.z.coerce.number().default(8091), NOCODB_EMBED_PORT: zod_1.z.coerce.number().default(8881), N8N_URL: zod_1.z.string().default('http://n8n-changemaker:5678'), N8N_PORT: zod_1.z.coerce.number().default(5678), N8N_EMBED_PORT: zod_1.z.coerce.number().default(8882), GITEA_URL: zod_1.z.string().default('http://gitea-changemaker:3000'), GITEA_PORT: zod_1.z.coerce.number().default(3030), GITEA_EMBED_PORT: zod_1.z.coerce.number().default(8883), // MailHog (email testing UI) MAILHOG_URL: zod_1.z.string().default('http://mailhog-changemaker:8025'), MAILHOG_EMBED_PORT: zod_1.z.coerce.number().default(8884), // Mini QR (QR code generator) MINI_QR_URL: zod_1.z.string().default('http://mini-qr:8080'), MINI_QR_PORT: zod_1.z.coerce.number().default(8089), MINI_QR_EMBED_PORT: zod_1.z.coerce.number().default(8885), // Excalidraw (collaborative whiteboard) EXCALIDRAW_URL: zod_1.z.string().default('http://excalidraw-changemaker:80'), EXCALIDRAW_PORT: zod_1.z.coerce.number().default(8090), EXCALIDRAW_EMBED_PORT: zod_1.z.coerce.number().default(8886), // Pangolin (tunnel / reverse proxy) PANGOLIN_API_URL: zod_1.z.string() .default('') .refine((url) => !url || url.startsWith('https://'), { message: 'PANGOLIN_API_URL must use HTTPS for secure credential transmission' }), PANGOLIN_API_KEY: zod_1.z.string().default(''), PANGOLIN_ORG_ID: zod_1.z.string().default(''), PANGOLIN_SITE_ID: zod_1.z.string().default(''), PANGOLIN_ENDPOINT: zod_1.z.string().default(''), PANGOLIN_NEWT_ID: zod_1.z.string().default(''), PANGOLIN_NEWT_SECRET: zod_1.z.string().default(''), // NAR (National Address Register) NAR_DATA_DIR: zod_1.z.string().default('/data'), // Media Management ENABLE_MEDIA_FEATURES: zod_1.z.string().default('false'), MEDIA_API_PORT: zod_1.z.coerce.number().default(4100), MEDIA_API_PUBLIC_URL: zod_1.z.string().default('http://media-api:4100'), MEDIA_ROOT: zod_1.z.string().default('/media/library'), MEDIA_UPLOADS: zod_1.z.string().default('/media/uploads'), MAX_UPLOAD_SIZE_GB: zod_1.z.coerce.number().default(10), PUBLIC_MEDIA_PORT: zod_1.z.coerce.number().default(3100), // Docs / Code Server CODE_SERVER_URL: zod_1.z.string().default('http://code-server-changemaker:8080'), CODE_SERVER_PORT: zod_1.z.coerce.number().default(8888), MKDOCS_PREVIEW_URL: zod_1.z.string().default('http://mkdocs-changemaker:8000'), MKDOCS_PORT: zod_1.z.coerce.number().default(4003), MKDOCS_DOCS_PATH: zod_1.z.string().default('/mkdocs/docs'), MKDOCS_CONFIG_PATH: zod_1.z.string().default('/mkdocs/mkdocs.yml'), MKDOCS_CONTAINER_NAME: zod_1.z.string().default('mkdocs-changemaker'), MKDOCS_SITE_SERVER_URL: zod_1.z.string().default('http://mkdocs-site-server-changemaker:80'), MKDOCS_SITE_SERVER_PORT: zod_1.z.coerce.number().default(4004), // Monitoring Services (behind 'monitoring' profile) PROMETHEUS_URL: zod_1.z.string().default('http://prometheus-changemaker:9090'), PROMETHEUS_PORT: zod_1.z.coerce.number().default(9090), GRAFANA_URL: zod_1.z.string().default('http://grafana-changemaker:3000'), GRAFANA_PORT: zod_1.z.coerce.number().default(3005), ALERTMANAGER_URL: zod_1.z.string().default('http://alertmanager-changemaker:9093'), ALERTMANAGER_PORT: zod_1.z.coerce.number().default(9093), CADVISOR_URL: zod_1.z.string().default('http://cadvisor-changemaker:8080'), CADVISOR_PORT: zod_1.z.coerce.number().default(8086), NODE_EXPORTER_URL: zod_1.z.string().default('http://node-exporter-changemaker:9100'), NODE_EXPORTER_PORT: zod_1.z.coerce.number().default(9100), REDIS_EXPORTER_URL: zod_1.z.string().default('http://redis-exporter-changemaker:9121'), REDIS_EXPORTER_PORT: zod_1.z.coerce.number().default(9121), GOTIFY_URL: zod_1.z.string().default('http://gotify-changemaker:80'), GOTIFY_PORT: zod_1.z.coerce.number().default(8889), }); function validateEnv() { const result = envSchema.safeParse(process.env); if (!result.success) { console.error('Invalid environment variables:'); console.error(result.error.flatten().fieldErrors); process.exit(1); } return result.data; } exports.env = validateEnv(); //# sourceMappingURL=env.js.map