Spaces:
Running
Running
| import { z } from "zod"; | |
| import * as dotenv from "dotenv"; | |
| dotenv.config(); | |
| const envSchema = z.object({ | |
| // βββ LLM (All on NVIDIA NIM β FREE) ββββββββββββββββββββββββ | |
| NVIDIA_API_KEY: z.string().min(5), | |
| NVIDIA_NIM_BASE_URL: z.string().url().default("https://integrate.api.nvidia.com/v1"), | |
| // βββ Supabase ββββββββββββββββββββββββββββββββββββββββββββββ | |
| SUPABASE_URL: z.string().url(), | |
| SUPABASE_SERVICE_ROLE_KEY: z.string().min(10), | |
| // βββ Trigger.dev βββββββββββββββββββββββββββββββββββββββββββ | |
| TRIGGER_DEV_API_KEY: z.string().min(5), | |
| TRIGGER_DEV_PROJECT_ID: z.string().min(3), | |
| // βββ Web Research ββββββββββββββββββββββββββββββββββββββββββ | |
| SERPER_API_KEY: z.string().min(5), | |
| // βββ Email Finding βββββββββββββββββββββββββββββββββββββββββ | |
| HUNTER_API_KEY: z.string().min(5), | |
| // βββ Email Verification ββββββββββββββββββββββββββββββββββββ | |
| REOON_API_KEY: z.string().min(5), | |
| // βββ Slack βββββββββββββββββββββββββββββββββββββββββββββββββ | |
| SLACK_BOT_TOKEN: z.string().startsWith("xoxb-"), | |
| SLACK_SIGNING_SECRET: z.string().min(5), | |
| SLACK_ALERT_CHANNEL_ID: z.string(), | |
| SLACK_REVIEW_CHANNEL_ID: z.string(), | |
| // βββ Python AI Service βββββββββββββββββββββββββββββββββββββ | |
| PYTHON_AI_SERVICE_URL: z.string().url().default("http://localhost:8000"), | |
| PYTHON_AI_SERVICE_SECRET: z.string().min(10), | |
| // βββ System Config βββββββββββββββββββββββββββββββββββββββββ | |
| NODE_ENV: z.enum(["development", "staging", "production"]).default("development"), | |
| LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("info"), | |
| DAILY_LEAD_QUOTA: z.coerce.number().default(10), | |
| QUALITY_SCORE_THRESHOLD: z.coerce.number().default(70), | |
| HUMAN_REVIEW_ENABLED: z.string().transform((v) => v === "true").default("true"), | |
| DAILY_EMAIL_LIMIT: z.coerce.number().default(50), | |
| DAILY_LINKEDIN_LIMIT: z.coerce.number().default(25), | |
| SCHEDULE_START_HOUR_UTC: z.coerce.number().default(4), | |
| }); | |
| type Env = z.infer<typeof envSchema>; | |
| let _env: Env; | |
| export function getEnv(): Env { | |
| if (!_env) { | |
| const result = envSchema.safeParse(process.env); | |
| if (!result.success) { | |
| console.error("β Invalid environment configuration:"); | |
| result.error.errors.forEach((e) => { | |
| console.error(` ${e.path.join(".")}: ${e.message}`); | |
| }); | |
| process.exit(1); | |
| } | |
| _env = result.data; | |
| } | |
| return _env; | |
| } | |