UNPKG

@nexe/config-manager

Version:

Nexe Config Manager - A flexible configuration management solution with multiple sources and hot reload support

163 lines 4.96 kB
import { __decorate, __metadata } from "tslib"; import { createLogger } from '@nexe/logger'; import * as fs from 'fs'; import { readFile } from 'fs/promises'; import * as path from 'path'; import { injectable } from 'tsyringe'; import * as YAML from 'yaml'; const logger = createLogger('YamlConfigSource'); /** * YAML配置文件源 */ let YamlConfigSource = class YamlConfigSource { /** * @param filePath 配置文件路径 * @param watchChanges 是否监听文件变化 */ constructor(filePath, watchChanges = false) { this.watchChanges = watchChanges; this.cache = {}; this.watcher = null; this.callbacks = new Map(); this.filePath = path.resolve(filePath); if (this.watchChanges) { this.setupWatcher(); } } /** * 从YAML文件加载配置 */ async load(key, _pathPrefix) { try { if (Object.keys(this.cache).length === 0) { await this.loadFile(); } if (!key) { return this.cache; } return this.getNestedValue(this.cache, key); } catch (error) { logger.error('从YAML加载配置失败', error); return undefined; } } /** * 获取配置源名称 */ getName() { return `YamlConfigSource(${this.filePath})`; } /** * 是否支持热更新 */ supportsHotReload() { return this.watchChanges; } /** * 订阅配置变更 */ subscribe(key, callback) { if (!this.supportsHotReload()) { logger.warn('此配置源未启用热更新,无法订阅变更'); return; } const callbacks = this.callbacks.get(key) ?? []; callbacks.push(callback); this.callbacks.set(key, callbacks); } /** * 取消订阅配置变更 */ unsubscribe(key) { this.callbacks.delete(key); } /** * 设置文件变更监听器 */ setupWatcher() { try { // 先确保文件存在 if (!fs.existsSync(this.filePath)) { logger.warn(`配置文件不存在: ${this.filePath}`); return; } logger.info(`开始监听文件变更: ${this.filePath}`); // 监听文件变更 - 使用更强大的选项 this.watcher = fs.watch(this.filePath, { persistent: true, encoding: 'utf8', recursive: false, }, (eventType, filename) => { logger.info(`检测到文件变更: ${filename ?? this.filePath}, 事件类型: ${eventType}`); // 文件变更后等待一小段时间再读取,确保写入完成 setTimeout(() => { this.handleFileChange().catch(error => { logger.error(`处理文件变更时出错: ${error instanceof Error ? error.message : String(error)}`); }); }, 100); }); } catch (error) { logger.error(`设置文件监听失败: ${error instanceof Error ? error.message : String(error)}`); } } /** * 处理文件变更 */ async handleFileChange() { const oldCache = { ...this.cache }; await this.loadFile(); // 通知所有订阅者 this.callbacks.forEach((callbacks, key) => { const newValue = this.getNestedValue(this.cache, key); const oldValue = this.getNestedValue(oldCache, key); if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) { callbacks.forEach(callback => callback(newValue)); } }); } /** * 加载文件到缓存 */ async loadFile() { try { const content = await readFile(this.filePath, 'utf-8'); this.cache = YAML.parse(content); } catch (error) { throw new Error(`加载YAML文件失败: ${error instanceof Error ? error.message : String(error)}`); } } /** * 获取嵌套对象的属性值 */ getNestedValue(obj, key) { const parts = key.split('.'); let current = obj; for (const part of parts) { if (current === undefined || current === null || typeof current !== 'object') { return undefined; } current = current[part]; } return current; } /** * 关闭资源 */ dispose() { if (this.watcher) { this.watcher.close(); this.watcher = null; } } }; YamlConfigSource = __decorate([ injectable(), __metadata("design:paramtypes", [String, Object]) ], YamlConfigSource); export { YamlConfigSource }; //# sourceMappingURL=yaml-config-source.js.map