From 76538369d681ee7417c17bce8e03636439db08b8 Mon Sep 17 00:00:00 2001 From: arsam Date: Fri, 18 Sep 2026 23:17:49 +0330 Subject: [PATCH] Import project configuration: app/backend/src/config.ts Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality. --- app/backend/src/config.ts | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 app/backend/src/config.ts diff --git a/app/backend/src/config.ts b/app/backend/src/config.ts new file mode 100644 index 0000000..faff2a1 --- /dev/null +++ b/app/backend/src/config.ts @@ -0,0 +1,42 @@ +// Centralized env loader with required-value enforcement. +// Loaded once at startup; throws if anything mandatory is missing. +import { z } from 'zod'; + +const envSchema = z.object({ + NODE_ENV: z.enum(['development', 'production', 'test']).default('development'), + PORT: z.coerce.number().int().positive().default(3010), + DATABASE_URL: z.string().url(), + REDIS_URL: z.string().url(), + SESSION_SECRET: z.string().min(32, 'SESSION_SECRET must be at least 32 chars'), + COOKIE_DOMAIN: z.string().default(''), + UPLOAD_DIR: z.string().default('./uploads'), + CORS_ORIGINS: z.string().default('http://localhost:3009'), + LOG_LEVEL: z.enum(['trace', 'debug', 'info', 'warn', 'error', 'fatal']).default('info'), + // OAuth — optional; providers without credentials are simply not offered. + OAUTH_CALLBACK_BASE: z.string().default(''), + GOOGLE_CLIENT_ID: z.string().default(''), + GOOGLE_CLIENT_SECRET: z.string().default(''), + GITHUB_CLIENT_ID: z.string().default(''), + GITHUB_CLIENT_SECRET: z.string().default(''), + SMTP_HOST: z.string().default(''), + SMTP_PORT: z.coerce.number().int().positive().default(587), + SMTP_USER: z.string().default(''), + SMTP_PASS: z.string().default(''), + SMTP_FROM: z.string().default('no-reply@teknav.ir'), + SMS_PROVIDER: z.string().default(''), + SMS_API_KEY: z.string().default(''), + SMS_SENDER: z.string().default(''), +}); + +const parsed = envSchema.safeParse(process.env); +if (!parsed.success) { + console.error('Invalid environment variables:'); + console.error(parsed.error.flatten().fieldErrors); + process.exit(1); +} + +export const config = { + ...parsed.data, + corsOrigins: parsed.data.CORS_ORIGINS.split(',').map((s) => s.trim()).filter(Boolean), + isProd: parsed.data.NODE_ENV === 'production', +};