UNPKG

review-copilot

Version:

ReviewCopilot - AI-powered code review assistant with customizable prompts

141 lines (140 loc) 4.76 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConfigManager = void 0; const promises_1 = require("fs/promises"); const yaml_1 = require("yaml"); const zod_1 = require("zod"); const providerSchema = zod_1.z .object({ enabled: zod_1.z.boolean(), apiKey: zod_1.z.string(), model: zod_1.z.string(), baseURL: zod_1.z.string(), defaultHeaders: zod_1.z.record(zod_1.z.string()).optional(), timeout: zod_1.z.number().optional(), reviewLanguage: zod_1.z.enum(['en', 'zh', 'ja', 'ko']).optional(), }) .transform((config) => ({ enabled: config.enabled, apiKey: config.apiKey, model: config.model, baseURL: config.baseURL, reviewLanguage: config.reviewLanguage, })); const triggerSchema = zod_1.z.object({ on: zod_1.z.enum(['pull_request', 'merge_request', 'push']), actions: zod_1.z.array(zod_1.z.string()).optional(), }); const configSchema = zod_1.z .object({ providers: zod_1.z.record(zod_1.z.string(), providerSchema).transform((providers) => { const enabledProvider = Object.entries(providers).find(([_, p]) => p.enabled)?.[0] || 'openai'; if (!['openai', 'deepseek'].includes(enabledProvider)) { throw new Error(`Unsupported provider type: ${enabledProvider}`); } return { [enabledProvider]: providers[enabledProvider] }; }), triggers: zod_1.z.array(triggerSchema), rules: zod_1.z.object({ commitMessage: zod_1.z .object({ enabled: zod_1.z.boolean(), pattern: zod_1.z.string().optional(), prompt: zod_1.z.string(), }) .transform((rule) => ({ ...rule, pattern: rule.pattern || '', })), branchName: zod_1.z .object({ enabled: zod_1.z.boolean(), pattern: zod_1.z.string().optional(), prompt: zod_1.z.string(), }) .transform((rule) => ({ ...rule, pattern: rule.pattern || '', })), codeChanges: zod_1.z .object({ enabled: zod_1.z.boolean(), filePatterns: zod_1.z.array(zod_1.z.string()).optional(), prompt: zod_1.z.string(), }) .transform((rule) => ({ ...rule, filePatterns: rule.filePatterns || [], })), }), customReviewPoints: zod_1.z .array(zod_1.z.object({ name: zod_1.z.string(), prompt: zod_1.z.string(), })) .optional() .transform((points) => points || []), }) .transform((config) => ({ providers: config.providers, triggers: config.triggers, rules: config.rules, customReviewPoints: config.customReviewPoints, })); class ConfigManager { constructor() { this.config = null; this.configPromise = null; } static async getInstance(configPath) { if (!ConfigManager.instance) { ConfigManager.instance = new ConfigManager(); await ConfigManager.instance.loadConfig(configPath); } return ConfigManager.instance; } replaceEnvVariables(obj) { if (typeof obj === 'string') { return obj.replace(/\${([^}]+)}/g, (_, key) => process.env[key] || ''); } if (Array.isArray(obj)) { return obj.map((item) => this.replaceEnvVariables(item)); } if (typeof obj === 'object' && obj !== null) { const result = {}; for (const [key, value] of Object.entries(obj)) { result[key] = this.replaceEnvVariables(value); } return result; } return obj; } async loadConfig(path = '.review-copilot.yaml') { if (this.configPromise) { return this.configPromise; } this.configPromise = (async () => { try { const configFile = await (0, promises_1.readFile)(path, 'utf8'); const parsedConfig = (0, yaml_1.parse)(configFile); const configWithEnv = this.replaceEnvVariables(parsedConfig); this.config = configSchema.parse(configWithEnv); return this.config; } catch (error) { // Reset the promise on error this.configPromise = null; this.config = null; throw new Error('Failed to load config'); } })(); return this.configPromise; } getConfig() { if (!this.config) { throw new Error('Config not loaded. Please ensure getInstance() was and awaited.'); } return this.config; } } exports.ConfigManager = ConfigManager;