UNPKG

vibe-cli-tool

Version:

VibeCLI v1.9 - 模板商店生态,智能部署生成,多语言支持,交互式学习系统,企业级Web全栈应用CLI工具

124 lines 4.32 kB
import fsExtra from 'fs-extra'; import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; import { z } from 'zod'; import { verifySha256 } from '../../utils/signature.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const DEFAULTS_DIR = path.resolve(__dirname, './defaults'); const PROJECT_OVERRIDE_DIR = path.resolve(process.cwd(), 'vibecli-config'); // ---------------- Schemas ---------------- const enumsSchema = z.object({ userExperience: z.array(z.string()).min(1), developmentPhase: z.array(z.string()).min(1) }); export class ConfigProvider { constructor() { } static getInstance() { if (!ConfigProvider.instance) { ConfigProvider.instance = new ConfigProvider(); } return ConfigProvider.instance; } async load() { const defaults = await this.loadDefaults(); const overrides = await this.loadOverrides(); const merged = this.merge(defaults, overrides); this.validate(merged); this.config = merged; // 开发模式下启用热重载 if (process.env.NODE_ENV !== 'production') { await this.setupWatcher(); } } async loadDefaults() { const enumsPath = path.join(DEFAULTS_DIR, 'enums.json'); const enums = await fsExtra.readJson(enumsPath); return { enums }; } async loadOverrides() { const overrides = {}; const enumsPath = path.join(PROJECT_OVERRIDE_DIR, 'enums.json'); if (await fsExtra.pathExists(enumsPath)) { const sigOk = await verifySha256(enumsPath, enumsPath + '.sha256'); if (!sigOk) { console.warn('[ConfigProvider] enums.json 签名校验失败,已忽略该文件'); } else { overrides.enums = await fsExtra.readJson(enumsPath); } } return overrides; } validate(cfg) { enumsSchema.parse(cfg.enums); } merge(target, source) { if (Array.isArray(target) && Array.isArray(source)) { return Array.from(new Set([...target, ...source])); } else if (this.isPlainObject(target) && this.isPlainObject(source)) { const result = { ...target }; for (const key of Object.keys(source)) { if (key in target) { result[key] = this.merge(target[key], source[key]); } else { result[key] = source[key]; } } return result; } return source; } isPlainObject(item) { return item && typeof item === 'object' && !Array.isArray(item); } // ------------ Public API -------------- getConfig() { if (!this.config) { throw new Error('ConfigProvider 未初始化,请先调用 load()'); } return this.config; } getEnum(key) { return this.getConfig().enums[key]; } isValidEnum(key, value) { return this.getEnum(key).includes(value); } async setupWatcher() { if (this.watcher || !(await this.ensureOverrideDir())) return; this.watcher = fs.watch(PROJECT_OVERRIDE_DIR, { recursive: true }, async () => { try { const defaults = await this.loadDefaults(); const overrides = await this.loadOverrides(); const merged = this.merge(defaults, overrides); this.validate(merged); this.config = merged; // eslint-disable-next-line no-console console.log('[ConfigProvider] 配置已热重载'); } catch (err) { // eslint-disable-next-line no-console console.error('[ConfigProvider] 热重载配置失败:', err); } }); } async ensureOverrideDir() { try { if (!(await fsExtra.pathExists(PROJECT_OVERRIDE_DIR))) { return false; } return true; } catch { return false; } } } // helper for global usage export const GlobalConfig = ConfigProvider.getInstance(); //# sourceMappingURL=config-provider.js.map