export interface Config { databaseUrl: string; port: number; appUrl: string; production: boolean; telegramBotToken?: string; telegramBotUsername?: string; /** listam | feed | off */ listingSource: string; jinaApiKey?: string; /** Клиентский бот: анкета соискателя. Без токена анкета выключена. */ clientBotToken?: string; clientBotUsername?: string; /** Сколько процентов высоты срезать сверху у фото на странице клиента. */ cropTopPercent: number; /** Куда складывать обработанные фото. */ mediaDir: string; /** Переписывание текста объекта моделью через OpenRouter. Без ключа текст собирается по шаблону. */ openRouterKey?: string; openRouterModel: string; } export function loadConfig(env = process.env): Config { if (!env.DATABASE_URL) throw new Error('DATABASE_URL не задан'); return { databaseUrl: env.DATABASE_URL, port: Number(env.API_PORT ?? 3100), appUrl: (env.APP_URL ?? 'http://localhost:5174').replace(/\/$/, ''), production: env.NODE_ENV === 'production', telegramBotToken: env.TELEGRAM_BOT_TOKEN || undefined, telegramBotUsername: env.TELEGRAM_BOT_USERNAME || undefined, listingSource: env.LISTING_SOURCE || 'listam', jinaApiKey: env.JINA_API_KEY || undefined, clientBotToken: env.CLIENT_BOT_TOKEN || undefined, clientBotUsername: env.CLIENT_BOT_USERNAME || undefined, cropTopPercent: Math.max(0, Math.min(40, Number(env.CROP_TOP_PERCENT ?? 8) || 0)), mediaDir: env.MEDIA_DIR || './data/media', openRouterKey: env.OPENROUTER_API_KEY || undefined, openRouterModel: env.OPENROUTER_MODEL || 'anthropic/claude-haiku-4.5', }; }