import fs from 'fs-extra'; import { logInfo, logError } from './logger'; import type { GenerationConfig, TagConfig } from '../types'; import type { SwaggerAnalysis } from '../types'; import type { TagSummary } from '../types'; import type { ApiKeyInfo } from './environment-finder'; /** * Loads and validates a GenerationConfig from a JSON file. */ export function loadConfig(filePath: string): GenerationConfig { if (!fs.existsSync(filePath)) { logError(`Configuration file not found: ${filePath}`); process.exit(1); } const raw = fs.readFileSync(filePath, 'utf8'); let config: GenerationConfig; try { config = JSON.parse(raw) as GenerationConfig; } catch { logError(`Invalid JSON in configuration file: ${filePath}`); process.exit(1); } if (!config.tags || typeof config.tags !== 'object') { logError('Configuration file must contain a "tags" object'); process.exit(1); } for (const [tag, tagConfig] of Object.entries(config.tags)) { if (!tagConfig.baseUrl || typeof tagConfig.baseUrl !== 'string') { logError(`Tag "${tag}" must have a "baseUrl" string`); process.exit(1); } if (!Array.isArray(tagConfig.endpoints) || tagConfig.endpoints.length === 0) { logError(`Tag "${tag}" must have a non-empty "endpoints" array`); process.exit(1); } } return config; } /** * Builds a default GenerationConfig from a swagger analysis, including all tags * and all endpoints. Useful for --init-config to scaffold a config template. */ export function generateDefaultConfig( analysis: SwaggerAnalysis, tagSummaries: TagSummary[], cliOptions: { input: string; output: string; templates?: string; skipLint?: boolean; skipInstall?: boolean; }, apiKeys: ApiKeyInfo[] ): GenerationConfig { const tags: Record = {}; for (const summary of tagSummaries) { const matchingKey = apiKeys.find((k) => k.key.toLowerCase().includes(summary.tag.toLowerCase()) ); tags[summary.tag] = { baseUrl: matchingKey?.key || 'apiUrl', endpoints: summary.operations.map((op) => op.nickname) }; } const config: GenerationConfig = { input: cliOptions.input, output: cliOptions.output, skipLint: cliOptions.skipLint ?? false, skipInstall: cliOptions.skipInstall ?? false, tags }; if (cliOptions.templates) { config.templates = cliOptions.templates; } return config; } /** * Writes a GenerationConfig to a JSON file. */ export function writeConfig(config: GenerationConfig, filePath: string): void { fs.writeFileSync(filePath, JSON.stringify(config, null, 2) + '\n', 'utf8'); logInfo(`Configuration file written to: ${filePath}`); } /** * Derives the selectionFilter (tag → endpoint nicknames) from a GenerationConfig. */ export function deriveSelectionFilter(config: GenerationConfig): Record { const filter: Record = {}; for (const [tag, tagConfig] of Object.entries(config.tags)) { filter[tag] = [...tagConfig.endpoints]; } return filter; } /** * Derives the tagApiKeyMap (tag → baseUrl key) from a GenerationConfig. */ export function deriveTagApiKeyMap(config: GenerationConfig): Record { const map: Record = {}; for (const [tag, tagConfig] of Object.entries(config.tags)) { map[tag] = tagConfig.baseUrl; } return map; }