@nexe/config-manager 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +208 -0
  3. package/dist/config-manager.d.ts +34 -0
  4. package/dist/config-manager.d.ts.map +1 -0
  5. package/dist/config-manager.js +138 -0
  6. package/dist/config-manager.js.map +1 -0
  7. package/dist/debug/consul-debug.d.ts +6 -0
  8. package/dist/debug/consul-debug.d.ts.map +1 -0
  9. package/dist/debug/consul-debug.js +53 -0
  10. package/dist/debug/consul-debug.js.map +1 -0
  11. package/dist/decorators.d.ts +12 -0
  12. package/dist/decorators.d.ts.map +1 -0
  13. package/dist/decorators.js +29 -0
  14. package/dist/decorators.js.map +1 -0
  15. package/dist/examples/annotation-example.d.ts +1 -0
  16. package/dist/examples/annotation-example.d.ts.map +1 -0
  17. package/dist/examples/annotation-example.js +273 -0
  18. package/dist/examples/annotation-example.js.map +1 -0
  19. package/dist/examples/config-example.d.ts +1 -0
  20. package/dist/examples/config-example.d.ts.map +1 -0
  21. package/dist/examples/config-example.js +83 -0
  22. package/dist/examples/config-example.js.map +1 -0
  23. package/dist/examples/consul-config-example.v2.d.ts +1 -0
  24. package/dist/examples/consul-config-example.v2.d.ts.map +1 -0
  25. package/dist/examples/consul-config-example.v2.js +145 -0
  26. package/dist/examples/consul-config-example.v2.js.map +1 -0
  27. package/dist/examples/database-config.d.ts +1 -0
  28. package/dist/examples/database-config.d.ts.map +1 -0
  29. package/dist/examples/database-config.js +23 -0
  30. package/dist/examples/database-config.js.map +1 -0
  31. package/dist/examples/hot-reload-test.d.ts +1 -0
  32. package/dist/examples/hot-reload-test.d.ts.map +1 -0
  33. package/dist/examples/hot-reload-test.js +65 -0
  34. package/dist/examples/hot-reload-test.js.map +1 -0
  35. package/dist/factory.d.ts +45 -0
  36. package/dist/factory.d.ts.map +1 -0
  37. package/dist/factory.js +46 -0
  38. package/dist/factory.js.map +1 -0
  39. package/dist/index.d.ts +5 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +5 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/interfaces.d.ts +100 -0
  44. package/dist/interfaces.d.ts.map +1 -0
  45. package/dist/interfaces.js +6 -0
  46. package/dist/interfaces.js.map +1 -0
  47. package/dist/sources/consul-config-source.d.ts +79 -0
  48. package/dist/sources/consul-config-source.d.ts.map +1 -0
  49. package/dist/sources/consul-config-source.js +332 -0
  50. package/dist/sources/consul-config-source.js.map +1 -0
  51. package/dist/sources/environment-config-source.d.ts +34 -0
  52. package/dist/sources/environment-config-source.d.ts.map +1 -0
  53. package/dist/sources/environment-config-source.js +77 -0
  54. package/dist/sources/environment-config-source.js.map +1 -0
  55. package/dist/sources/index.d.ts +6 -0
  56. package/dist/sources/index.d.ts.map +1 -0
  57. package/dist/sources/index.js +6 -0
  58. package/dist/sources/index.js.map +1 -0
  59. package/dist/sources/json-config-source.d.ts +57 -0
  60. package/dist/sources/json-config-source.d.ts.map +1 -0
  61. package/dist/sources/json-config-source.js +153 -0
  62. package/dist/sources/json-config-source.js.map +1 -0
  63. package/dist/sources/remote-api-config-source.d.ts +62 -0
  64. package/dist/sources/remote-api-config-source.d.ts.map +1 -0
  65. package/dist/sources/remote-api-config-source.js +169 -0
  66. package/dist/sources/remote-api-config-source.js.map +1 -0
  67. package/dist/sources/yaml-config-source.d.ts +57 -0
  68. package/dist/sources/yaml-config-source.d.ts.map +1 -0
  69. package/dist/sources/yaml-config-source.js +163 -0
  70. package/dist/sources/yaml-config-source.js.map +1 -0
  71. package/package.json +66 -0
@@ -0,0 +1,273 @@
1
+ "use strict";
2
+ // /**
3
+ // * 配置系统装饰器使用示例
4
+ // *
5
+ // * 这个示例演示了如何使用装饰器定义配置类并使用它们
6
+ // *
7
+ // * 运行方式:
8
+ // * bun src/shared/infrastructure/config/examples/annotation-example.ts
9
+ // */
10
+ // // 必须首先导入reflect-metadata
11
+ // import * as fs from 'fs';
12
+ // import * as path from 'path';
13
+ // import 'reflect-metadata';
14
+ // import { container } from 'tsyringe';
15
+ // import {
16
+ // ConfigManager,
17
+ // ConfigProperty,
18
+ // ConfigSection,
19
+ // EnvironmentConfigSource,
20
+ // JsonConfigSource,
21
+ // YamlConfigSource,
22
+ // } from '..';
23
+ // // 创建测试配置文件 - 使用当前脚本所在目录
24
+ // const SCRIPT_DIR = path.dirname(new URL(import.meta.url).pathname);
25
+ // const CONFIG_DIR = path.join(SCRIPT_DIR, 'config');
26
+ // const JSON_CONFIG_PATH = path.join(CONFIG_DIR, 'config.json');
27
+ // const YAML_CONFIG_PATH = path.join(CONFIG_DIR, 'config.yaml');
28
+ // console.log(`📂 配置目录: ${CONFIG_DIR}`);
29
+ // console.log(`📄 YAML配置文件: ${YAML_CONFIG_PATH}`);
30
+ // // 确保配置目录存在
31
+ // if (!fs.existsSync(CONFIG_DIR)) {
32
+ // fs.mkdirSync(CONFIG_DIR, { recursive: true });
33
+ // }
34
+ // // 创建JSON测试配置文件
35
+ // if (!fs.existsSync(JSON_CONFIG_PATH)) {
36
+ // const jsonConfig = {
37
+ // app: {
38
+ // name: 'Elysia应用',
39
+ // description: '示例配置文件',
40
+ // version: '1.0.0',
41
+ // },
42
+ // server: {
43
+ // port: 3000,
44
+ // host: 'localhost',
45
+ // maxConnections: 100,
46
+ // },
47
+ // database: {
48
+ // host: 'localhost',
49
+ // port: 5432,
50
+ // username: 'postgres',
51
+ // password: 'postgres123',
52
+ // database: 'elysia_db',
53
+ // ssl: false,
54
+ // poolSize: 10,
55
+ // },
56
+ // log: {
57
+ // level: 'info',
58
+ // format: 'json',
59
+ // },
60
+ // };
61
+ // fs.writeFileSync(
62
+ // JSON_CONFIG_PATH,
63
+ // JSON.stringify(jsonConfig, null, 2),
64
+ // 'utf-8',
65
+ // );
66
+ // console.log(`✅ 创建JSON配置文件: ${JSON_CONFIG_PATH}`);
67
+ // }
68
+ // // 创建YAML测试配置文件
69
+ // if (!fs.existsSync(YAML_CONFIG_PATH)) {
70
+ // const yamlConfig = `app:
71
+ // name: Elysia应用(YAML)
72
+ // description: YAML配置文件
73
+ // version: 1.0.0
74
+ // server:
75
+ // port: 3001
76
+ // host: localhost
77
+ // maxConnections: 200
78
+ // database:
79
+ // host: db.example.com
80
+ // port: 5432
81
+ // username: elysia_user
82
+ // password: secure_password
83
+ // database: elysia_db_test
84
+ // ssl: true
85
+ // poolSize: 20
86
+ // log:
87
+ // level: debug
88
+ // format: pretty
89
+ // `;
90
+ // fs.writeFileSync(YAML_CONFIG_PATH, yamlConfig, 'utf-8');
91
+ // console.log(`✅ 创建YAML配置文件: ${YAML_CONFIG_PATH}`);
92
+ // }
93
+ // // 设置环境变量用于测试
94
+ // process.env.APP_DATABASE_HOST = 'env-db-host';
95
+ // process.env.APP_SERVER_PORT = '4000';
96
+ // /**
97
+ // * 服务器配置类示例
98
+ // */
99
+ // @ConfigSection('server')
100
+ // class ServerConfig {
101
+ // @ConfigProperty('port')
102
+ // port = 8080; // 默认值
103
+ // @ConfigProperty('host')
104
+ // host = '127.0.0.1'; // 默认值
105
+ // @ConfigProperty('maxConnections')
106
+ // maxConnections = 50; // 默认值
107
+ // }
108
+ // /**
109
+ // * 数据库配置类示例
110
+ // */
111
+ // @ConfigSection('database')
112
+ // class DatabaseConfig {
113
+ // @ConfigProperty('host')
114
+ // host = 'localhost'; // 默认值
115
+ // @ConfigProperty('port')
116
+ // port = 5432; // 默认值
117
+ // @ConfigProperty('username')
118
+ // username = '';
119
+ // @ConfigProperty('password')
120
+ // password = '';
121
+ // @ConfigProperty('database')
122
+ // database = '';
123
+ // @ConfigProperty('ssl')
124
+ // ssl = false;
125
+ // @ConfigProperty('poolSize')
126
+ // poolSize = 10;
127
+ // }
128
+ // /**
129
+ // * 日志配置类示例
130
+ // * 演示不同的配置路径
131
+ // */
132
+ // @ConfigSection('log')
133
+ // class LogConfig {
134
+ // @ConfigProperty('level')
135
+ // level = 'info';
136
+ // @ConfigProperty('format')
137
+ // format = 'json';
138
+ // // 特定的自定义配置属性
139
+ // @ConfigProperty('custom')
140
+ // customSetting = 'default';
141
+ // }
142
+ // /**
143
+ // * 应用配置类示例
144
+ // */
145
+ // @ConfigSection('app')
146
+ // class AppConfig {
147
+ // @ConfigProperty('name')
148
+ // name = 'Default App';
149
+ // @ConfigProperty('version')
150
+ // version = '0.0.1';
151
+ // @ConfigProperty('description')
152
+ // description = '';
153
+ // }
154
+ // /**
155
+ // * 服务类示例,展示如何在服务中使用配置
156
+ // */
157
+ // class MyService {
158
+ // // 使用非空断言操作符(!)告诉TypeScript这些属性会在init方法中被初始化
159
+ // private dbConfig!: DatabaseConfig;
160
+ // private serverConfig!: ServerConfig;
161
+ // private initialized = false;
162
+ // private initPromise: Promise<void>;
163
+ // constructor(private configManager: ConfigManager) {
164
+ // // 存储初始化Promise以便外部可以等待
165
+ // this.initPromise = this.init();
166
+ // }
167
+ // /**
168
+ // * 初始化服务
169
+ // */
170
+ // private async init(): Promise<void> {
171
+ // try {
172
+ // // 获取强类型配置对象
173
+ // this.dbConfig = await this.configManager.getConfig(DatabaseConfig);
174
+ // this.serverConfig = await this.configManager.getConfig(ServerConfig);
175
+ // console.log('\n🔧 数据库配置:');
176
+ // console.log(` - 主机: ${this.dbConfig.host}`);
177
+ // console.log(` - 端口: ${this.dbConfig.port}`);
178
+ // console.log(` - 数据库: ${this.dbConfig.database}`);
179
+ // console.log(` - SSL: ${this.dbConfig.ssl ? '启用' : '禁用'}`);
180
+ // console.log('\n🖥️ 服务器配置:');
181
+ // console.log(` - 主机: ${this.serverConfig.host}`);
182
+ // console.log(` - 端口: ${this.serverConfig.port}`);
183
+ // console.log(` - 最大连接数: ${this.serverConfig.maxConnections}`);
184
+ // // 设置初始化完成标志
185
+ // this.initialized = true;
186
+ // } catch (error) {
187
+ // console.error('初始化服务失败:', error);
188
+ // throw error;
189
+ // }
190
+ // }
191
+ // /**
192
+ // * 等待初始化完成
193
+ // */
194
+ // async waitForInit(): Promise<void> {
195
+ // return this.initPromise;
196
+ // }
197
+ // /**
198
+ // * 获取数据库连接字符串
199
+ // */
200
+ // getConnectionString(): string {
201
+ // if (!this.initialized) {
202
+ // throw new Error('服务尚未初始化完成');
203
+ // }
204
+ // return `postgresql://${this.dbConfig.username}:${this.dbConfig.password}@${this.dbConfig.host}:${this.dbConfig.port}/${this.dbConfig.database}`;
205
+ // }
206
+ // }
207
+ // /**
208
+ // * 主函数
209
+ // */
210
+ // async function main(): Promise<void> {
211
+ // console.log('🚀 启动配置系统示例...');
212
+ // // 创建配置管理器
213
+ // const configManager = new ConfigManager();
214
+ // // 添加多种配置源(优先级从高到低)
215
+ // console.log('\n⚙️ 添加配置源:');
216
+ // console.log(' - 环境变量 (优先级: 高)');
217
+ // console.log(' - YAML 配置文件 (优先级: 中)');
218
+ // console.log(' - JSON 配置文件 (优先级: 低)');
219
+ // configManager.addSource(new EnvironmentConfigSource('APP_'), 100);
220
+ // configManager.addSource(new YamlConfigSource(YAML_CONFIG_PATH, true), 50);
221
+ // configManager.addSource(new JsonConfigSource(JSON_CONFIG_PATH), 10);
222
+ // // 注册到容器
223
+ // container.registerInstance(ConfigManager, configManager);
224
+ // // 获取并显示各种配置值
225
+ // console.log('\n📊 读取各配置源的值:');
226
+ // // 1. 直接读取原始值
227
+ // const jsonServerPort = await configManager.get<number>('server.port');
228
+ // console.log(`服务器端口 (优先级顺序): ${jsonServerPort}`);
229
+ // // 2. 读取强类型配置对象
230
+ // const serverConfig = await configManager.getConfig(ServerConfig);
231
+ // const dbConfig = await configManager.getConfig(DatabaseConfig);
232
+ // const logConfig = await configManager.getConfig(LogConfig);
233
+ // const appConfig = await configManager.getConfig(AppConfig);
234
+ // console.log('\n📋 强类型配置对象:');
235
+ // console.log(' 📦 应用配置:');
236
+ // console.log(` - 名称: ${appConfig.name}`);
237
+ // console.log(` - 版本: ${appConfig.version}`);
238
+ // console.log(` - 描述: ${appConfig.description}`);
239
+ // console.log(' 🖥️ 服务器配置:');
240
+ // console.log(` - 端口: ${serverConfig.port}`);
241
+ // console.log(` - 主机: ${serverConfig.host}`);
242
+ // console.log(` - 最大连接数: ${serverConfig.maxConnections}`);
243
+ // console.log(' 🔧 数据库配置:');
244
+ // console.log(` - 主机: ${dbConfig.host}`);
245
+ // console.log(` - 端口: ${dbConfig.port}`);
246
+ // console.log(` - 用户名: ${dbConfig.username}`);
247
+ // console.log(` - 数据库: ${dbConfig.database}`);
248
+ // console.log(` - SSL: ${dbConfig.ssl ? '启用' : '禁用'}`);
249
+ // console.log(` - 连接池大小: ${dbConfig.poolSize}`);
250
+ // console.log(' 📝 日志配置:');
251
+ // console.log(` - 级别: ${logConfig.level}`);
252
+ // console.log(` - 格式: ${logConfig.format}`);
253
+ // console.log(` - 自定义设置: ${logConfig.customSetting}`);
254
+ // // 3. 使用注入的方式在服务中使用配置
255
+ // console.log('\n🛠️ 在服务中使用配置:');
256
+ // const myService = new MyService(configManager);
257
+ // // 等待服务初始化完成
258
+ // await myService.waitForInit();
259
+ // console.log(` 连接字符串: ${myService.getConnectionString()}`);
260
+ // // 4. 监听配置变更
261
+ // console.log('\n👀 设置配置变更监听 (请修改配置文件后观察):');
262
+ // configManager.subscribe<number>('server.maxConnections', (newValue) => {
263
+ // console.log(` 配置变更: server.maxConnections 已更新为 ${newValue}`);
264
+ // });
265
+ // console.log('\n✅ 配置系统示例运行完成');
266
+ // console.log('🔍 可以尝试修改 config/config.yaml 文件后观察配置变更');
267
+ // }
268
+ // // 运行主函数
269
+ // main().catch((error) => {
270
+ // console.error('❌ 错误:', error);
271
+ // process.exit(1);
272
+ // });
273
+ //# sourceMappingURL=annotation-example.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotation-example.js","sourceRoot":"","sources":["../../src/examples/annotation-example.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=config-example.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-example.d.ts","sourceRoot":"","sources":["../../src/examples/config-example.ts"],"names":[],"mappings":""}
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ // import { container } from 'tsyringe';
3
+ // import {
4
+ // ConfigManager,
5
+ // EnvironmentConfigSource,
6
+ // JsonConfigSource,
7
+ // RemoteApiConfigSource,
8
+ // YamlConfigSource,
9
+ // } from '..';
10
+ // import { ConsulConfigSource } from '../sources/consul-config-source';
11
+ // import { DatabaseConfig } from './database-config';
12
+ // /**
13
+ // * 配置系统使用示例
14
+ // */
15
+ // // eslint-disable-next-line @typescript-eslint/no-unused-vars
16
+ // async function configExample(): Promise<void> {
17
+ // // 创建配置管理器
18
+ // const configManager = new ConfigManager();
19
+ // // 添加多种配置源,按优先级顺序
20
+ // // 1. 环境变量(最高优先级)
21
+ // configManager.addSource(new EnvironmentConfigSource('APP_'), 100);
22
+ // // 2. Consul配置(高优先级)
23
+ // const consulConfig = new ConsulConfigSource({
24
+ // host: 'localhost',
25
+ // port: 8500,
26
+ // defaultKeyPrefix: 'myapp',
27
+ // });
28
+ // configManager.addSource(consulConfig, 80);
29
+ // // 3. 远程API配置
30
+ // const apiConfig = new RemoteApiConfigSource(
31
+ // 'https://config-api.example.com',
32
+ // { Authorization: 'Bearer your-token' },
33
+ // 60000, // 60秒轮询一次
34
+ // );
35
+ // configManager.addSource(apiConfig, 60);
36
+ // // 4. YAML本地配置(测试环境)
37
+ // const yamlConfig = new YamlConfigSource('./config/test.yaml', true);
38
+ // configManager.addSource(yamlConfig, 40);
39
+ // // 5. JSON本地配置(默认配置,最低优先级)
40
+ // const jsonConfig = new JsonConfigSource('./config/default.json');
41
+ // configManager.addSource(jsonConfig, 20);
42
+ // // 将配置管理器注册到容器
43
+ // container.registerInstance(ConfigManager, configManager);
44
+ // // 1. 获取单个配置值
45
+ // const serverPort = await configManager.get<number>('server.port', 3000);
46
+ // console.log(`服务器端口: ${serverPort}`);
47
+ // // 2. 获取强类型配置对象
48
+ // const dbConfig = await configManager.getConfig(DatabaseConfig);
49
+ // console.log(`数据库配置: ${JSON.stringify(dbConfig, null, 2)}`);
50
+ // // 3. 订阅配置变更
51
+ // configManager.subscribe<number>('server.maxConnections', (newValue) => {
52
+ // console.log(`最大连接数已更新: ${newValue}`);
53
+ // // 这里可以重新配置应用
54
+ // });
55
+ // // 4. 从容器中获取配置
56
+ // class DatabaseService {
57
+ // private dbConfig!: DatabaseConfig; // 使用!断言,因为会在init中初始化
58
+ // constructor() {
59
+ // // 从tsyringe容器获取配置管理器
60
+ // const configManager = container.resolve(ConfigManager);
61
+ // // 异步初始化
62
+ // this.init(configManager).catch(console.error);
63
+ // }
64
+ // private async init(configManager: ConfigManager): Promise<void> {
65
+ // // 获取强类型配置
66
+ // this.dbConfig = await configManager.getConfig(DatabaseConfig);
67
+ // // 使用配置连接数据库
68
+ // console.log(
69
+ // `连接数据库: ${this.dbConfig.host}:${this.dbConfig.port}/${this.dbConfig.database}`,
70
+ // );
71
+ // }
72
+ // }
73
+ // // 使用示例服务
74
+ // new DatabaseService();
75
+ // // 清理资源
76
+ // setTimeout(() => {
77
+ // consulConfig.dispose();
78
+ // apiConfig.dispose();
79
+ // yamlConfig.dispose();
80
+ // jsonConfig.dispose();
81
+ // }, 60000);
82
+ // }
83
+ //# sourceMappingURL=config-example.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-example.js","sourceRoot":"","sources":["../../src/examples/config-example.ts"],"names":[],"mappings":";AAAA,wCAAwC;AACxC,WAAW;AACX,mBAAmB;AACnB,6BAA6B;AAC7B,sBAAsB;AACtB,2BAA2B;AAC3B,sBAAsB;AACtB,eAAe;AACf,wEAAwE;AACxE,sDAAsD;AAEtD,MAAM;AACN,cAAc;AACd,MAAM;AACN,gEAAgE;AAChE,kDAAkD;AAClD,eAAe;AACf,+CAA+C;AAE/C,sBAAsB;AACtB,sBAAsB;AACtB,uEAAuE;AAEvE,yBAAyB;AACzB,kDAAkD;AAClD,yBAAyB;AACzB,kBAAkB;AAClB,iCAAiC;AACjC,QAAQ;AACR,+CAA+C;AAE/C,kBAAkB;AAClB,iDAAiD;AACjD,wCAAwC;AACxC,8CAA8C;AAC9C,wBAAwB;AACxB,OAAO;AACP,4CAA4C;AAE5C,yBAAyB;AACzB,yEAAyE;AACzE,6CAA6C;AAE7C,+BAA+B;AAC/B,sEAAsE;AACtE,6CAA6C;AAE7C,mBAAmB;AACnB,8DAA8D;AAE9D,kBAAkB;AAClB,6EAA6E;AAC7E,yCAAyC;AAEzC,oBAAoB;AACpB,oEAAoE;AACpE,gEAAgE;AAEhE,iBAAiB;AACjB,6EAA6E;AAC7E,4CAA4C;AAC5C,oBAAoB;AACpB,QAAQ;AAER,mBAAmB;AACnB,4BAA4B;AAC5B,+DAA+D;AAE/D,sBAAsB;AACtB,8BAA8B;AAC9B,gEAAgE;AAEhE,iBAAiB;AACjB,uDAAuD;AACvD,QAAQ;AAER,wEAAwE;AACxE,mBAAmB;AACnB,uEAAuE;AAEvE,qBAAqB;AACrB,qBAAqB;AACrB,0FAA0F;AAC1F,WAAW;AACX,QAAQ;AACR,MAAM;AAEN,cAAc;AACd,2BAA2B;AAE3B,YAAY;AACZ,uBAAuB;AACvB,8BAA8B;AAC9B,2BAA2B;AAC3B,4BAA4B;AAC5B,4BAA4B;AAC5B,eAAe;AACf,IAAI"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=consul-config-example.v2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consul-config-example.v2.d.ts","sourceRoot":"","sources":["../../src/examples/consul-config-example.v2.ts"],"names":[],"mappings":""}
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ // import { createLogger } from '@nexe/logger';
3
+ // import { ConsulConfigSource } from '../sources/consul-config-source';
4
+ // const logger = createLogger('ConsulConfigExample');
5
+ // /**
6
+ // * Consul配置源V2使用示例
7
+ // */
8
+ // async function consulConfigExample() {
9
+ // // 创建Consul配置源实例
10
+ // const consulConfig = new ConsulConfigSource({
11
+ // host: '127.0.0.1',
12
+ // port: 8500,
13
+ // secure: false,
14
+ // defaultKeyPrefix: 'app/config',
15
+ // token: process.env.CONSUL_TOKEN, // 可选的访问令牌
16
+ // dc: 'dc1', // 可选的数据中心
17
+ // });
18
+ // try {
19
+ // // 1. 加载所有配置
20
+ // logger.info('加载所有配置...');
21
+ // const allConfig = await consulConfig.load();
22
+ // logger.info('所有配置:', allConfig);
23
+ // // 2. 加载特定配置项
24
+ // logger.info('加载数据库配置...');
25
+ // const dbConfig = await consulConfig.load('database');
26
+ // logger.info('数据库配置:', dbConfig);
27
+ // // 3. 订阅配置变更
28
+ // logger.info('订阅数据库配置变更...');
29
+ // consulConfig.subscribe('database', (newValue: unknown) => {
30
+ // logger.info('数据库配置已更新:', newValue);
31
+ // // 在这里处理配置变更,例如重新连接数据库
32
+ // handleDatabaseConfigChange(newValue);
33
+ // });
34
+ // // 4. 订阅多个配置项
35
+ // consulConfig.subscribe('cache', (newValue: unknown) => {
36
+ // logger.info('缓存配置已更新:', newValue);
37
+ // handleCacheConfigChange(newValue);
38
+ // });
39
+ // consulConfig.subscribe('logging', (newValue: unknown) => {
40
+ // logger.info('日志配置已更新:', newValue);
41
+ // handleLoggingConfigChange(newValue);
42
+ // });
43
+ // // 5. 支持嵌套键访问
44
+ // const redisPort = await consulConfig.load('cache/redis/port');
45
+ // logger.info('Redis端口:', redisPort);
46
+ // logger.info('Consul配置源已初始化并开始监听配置变更');
47
+ // logger.info('配置源名称:', consulConfig.getName());
48
+ // logger.info('支持热更新:', consulConfig.supportsHotReload());
49
+ // // 模拟应用运行,保持监听状态
50
+ // await new Promise<void>(resolve => {
51
+ // setTimeout(() => {
52
+ // logger.info('示例运行完成,清理资源...');
53
+ // resolve();
54
+ // }, 30000); // 运行30秒
55
+ // });
56
+ // } catch (error) {
57
+ // logger.error('Consul配置源使用失败:', error);
58
+ // } finally {
59
+ // // 6. 清理资源
60
+ // consulConfig.dispose();
61
+ // logger.info('已清理Consul配置源资源');
62
+ // }
63
+ // }
64
+ // /**
65
+ // * 处理数据库配置变更
66
+ // */
67
+ // function handleDatabaseConfigChange(_newConfig: unknown): void {
68
+ // logger.info('正在处理数据库配置变更...');
69
+ // // 实际应用中,这里可能需要:
70
+ // // 1. 验证新配置的有效性
71
+ // // 2. 关闭旧的数据库连接
72
+ // // 3. 使用新配置创建数据库连接
73
+ // // 4. 更新应用中的数据库实例
74
+ // }
75
+ // /**
76
+ // * 处理缓存配置变更
77
+ // */
78
+ // function handleCacheConfigChange(_newConfig: unknown): void {
79
+ // logger.info('正在处理缓存配置变更...');
80
+ // // 实际应用中,这里可能需要:
81
+ // // 1. 更新缓存连接参数
82
+ // // 2. 重新连接缓存服务
83
+ // // 3. 清空或迁移现有缓存数据
84
+ // }
85
+ // /**
86
+ // * 处理日志配置变更
87
+ // */
88
+ // function handleLoggingConfigChange(_newConfig: unknown): void {
89
+ // logger.info('正在处理日志配置变更...');
90
+ // // 实际应用中,这里可能需要:
91
+ // // 1. 更新日志级别
92
+ // // 2. 更改日志输出格式
93
+ // // 3. 重新配置日志文件路径
94
+ // }
95
+ // /**
96
+ // * 在Consul中设置示例配置的辅助函数
97
+ // * 注意:这需要Consul客户端写权限
98
+ // */
99
+ // async function setupExampleConfig() {
100
+ // const _consulConfig = new ConsulConfigSource({
101
+ // host: '127.0.0.1',
102
+ // port: 8500,
103
+ // defaultKeyPrefix: 'app/config',
104
+ // });
105
+ // // 注意:这个示例假设有写权限,实际使用时需要相应的权限配置
106
+ // logger.info('设置示例配置到Consul...');
107
+ // const exampleConfig = {
108
+ // database: {
109
+ // host: 'localhost',
110
+ // port: 5432,
111
+ // name: 'myapp',
112
+ // username: 'admin',
113
+ // password: 'secret',
114
+ // pool: {
115
+ // min: 2,
116
+ // max: 10,
117
+ // },
118
+ // },
119
+ // cache: {
120
+ // redis: {
121
+ // host: 'localhost',
122
+ // port: 6379,
123
+ // db: 0,
124
+ // },
125
+ // ttl: 3600,
126
+ // },
127
+ // logging: {
128
+ // level: 'info',
129
+ // format: 'json',
130
+ // file: '/var/log/app.log',
131
+ // },
132
+ // };
133
+ // // 实际使用时,你需要使用Consul的KV存储API来设置这些值
134
+ // logger.info('示例配置结构:', exampleConfig);
135
+ // logger.info('请手动在Consul KV存储中设置这些配置项');
136
+ // }
137
+ // // 如果直接运行此文件,执行示例
138
+ // if (require.main === module) {
139
+ // consulConfigExample().catch(error => {
140
+ // logger.error('示例执行失败:', error);
141
+ // process.exit(1);
142
+ // });
143
+ // }
144
+ // export { consulConfigExample, setupExampleConfig };
145
+ //# sourceMappingURL=consul-config-example.v2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consul-config-example.v2.js","sourceRoot":"","sources":["../../src/examples/consul-config-example.v2.ts"],"names":[],"mappings":";AAAA,+CAA+C;AAC/C,wEAAwE;AAExE,sDAAsD;AAEtD,MAAM;AACN,qBAAqB;AACrB,MAAM;AACN,yCAAyC;AACzC,qBAAqB;AACrB,kDAAkD;AAClD,yBAAyB;AACzB,kBAAkB;AAClB,qBAAqB;AACrB,sCAAsC;AACtC,kDAAkD;AAClD,4BAA4B;AAC5B,QAAQ;AAER,UAAU;AACV,mBAAmB;AACnB,gCAAgC;AAChC,mDAAmD;AACnD,uCAAuC;AAEvC,oBAAoB;AACpB,iCAAiC;AACjC,4DAA4D;AAC5D,uCAAuC;AAEvC,mBAAmB;AACnB,mCAAmC;AACnC,kEAAkE;AAClE,4CAA4C;AAC5C,+BAA+B;AAC/B,8CAA8C;AAC9C,UAAU;AAEV,oBAAoB;AACpB,+DAA+D;AAC/D,2CAA2C;AAC3C,2CAA2C;AAC3C,UAAU;AAEV,iEAAiE;AACjE,2CAA2C;AAC3C,6CAA6C;AAC7C,UAAU;AAEV,oBAAoB;AACpB,qEAAqE;AACrE,0CAA0C;AAE1C,6CAA6C;AAC7C,qDAAqD;AACrD,+DAA+D;AAE/D,uBAAuB;AACvB,2CAA2C;AAC3C,2BAA2B;AAC3B,yCAAyC;AACzC,qBAAqB;AACrB,4BAA4B;AAC5B,UAAU;AACV,sBAAsB;AACtB,6CAA6C;AAC7C,gBAAgB;AAChB,iBAAiB;AACjB,8BAA8B;AAC9B,qCAAqC;AACrC,MAAM;AACN,IAAI;AAEJ,MAAM;AACN,eAAe;AACf,MAAM;AACN,mEAAmE;AACnE,mCAAmC;AACnC,qBAAqB;AACrB,oBAAoB;AACpB,oBAAoB;AACpB,uBAAuB;AACvB,sBAAsB;AACtB,IAAI;AAEJ,MAAM;AACN,cAAc;AACd,MAAM;AACN,gEAAgE;AAChE,kCAAkC;AAClC,qBAAqB;AACrB,mBAAmB;AACnB,mBAAmB;AACnB,sBAAsB;AACtB,IAAI;AAEJ,MAAM;AACN,cAAc;AACd,MAAM;AACN,kEAAkE;AAClE,kCAAkC;AAClC,qBAAqB;AACrB,iBAAiB;AACjB,mBAAmB;AACnB,qBAAqB;AACrB,IAAI;AAEJ,MAAM;AACN,yBAAyB;AACzB,wBAAwB;AACxB,MAAM;AACN,wCAAwC;AACxC,mDAAmD;AACnD,yBAAyB;AACzB,kBAAkB;AAClB,sCAAsC;AACtC,QAAQ;AAER,oCAAoC;AACpC,qCAAqC;AAErC,4BAA4B;AAC5B,kBAAkB;AAClB,2BAA2B;AAC3B,oBAAoB;AACpB,uBAAuB;AACvB,2BAA2B;AAC3B,4BAA4B;AAC5B,gBAAgB;AAChB,kBAAkB;AAClB,mBAAmB;AACnB,WAAW;AACX,SAAS;AACT,eAAe;AACf,iBAAiB;AACjB,6BAA6B;AAC7B,sBAAsB;AACtB,iBAAiB;AACjB,WAAW;AACX,mBAAmB;AACnB,SAAS;AACT,iBAAiB;AACjB,uBAAuB;AACvB,wBAAwB;AACxB,kCAAkC;AAClC,SAAS;AACT,OAAO;AAEP,uCAAuC;AACvC,2CAA2C;AAC3C,4CAA4C;AAC5C,IAAI;AAEJ,oBAAoB;AACpB,iCAAiC;AACjC,2CAA2C;AAC3C,sCAAsC;AACtC,uBAAuB;AACvB,QAAQ;AACR,IAAI;AAEJ,sDAAsD"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=database-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-config.d.ts","sourceRoot":"","sources":["../../src/examples/database-config.ts"],"names":[],"mappings":""}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ // import { ConfigProperty, ConfigSection } from '..';
3
+ // /**
4
+ // * 数据库配置类
5
+ // */
6
+ // @ConfigSection('database')
7
+ // export class DatabaseConfig {
8
+ // @ConfigProperty('host')
9
+ // host = 'localhost';
10
+ // @ConfigProperty('port')
11
+ // port = 5432;
12
+ // @ConfigProperty('username')
13
+ // username = '';
14
+ // @ConfigProperty('password')
15
+ // password = '';
16
+ // @ConfigProperty('database')
17
+ // database = '';
18
+ // @ConfigProperty('ssl')
19
+ // ssl = false;
20
+ // @ConfigProperty('poolSize')
21
+ // poolSize = 10;
22
+ // }
23
+ //# sourceMappingURL=database-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-config.js","sourceRoot":"","sources":["../../src/examples/database-config.ts"],"names":[],"mappings":";AAAA,sDAAsD;AAEtD,MAAM;AACN,YAAY;AACZ,MAAM;AACN,6BAA6B;AAC7B,gCAAgC;AAChC,4BAA4B;AAC5B,wBAAwB;AAExB,4BAA4B;AAC5B,iBAAiB;AAEjB,gCAAgC;AAChC,mBAAmB;AAEnB,gCAAgC;AAChC,mBAAmB;AAEnB,gCAAgC;AAChC,mBAAmB;AAEnB,2BAA2B;AAC3B,iBAAiB;AAEjB,gCAAgC;AAChC,mBAAmB;AACnB,IAAI"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=hot-reload-test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hot-reload-test.d.ts","sourceRoot":"","sources":["../../src/examples/hot-reload-test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ // /**
3
+ // * 配置系统热更新测试
4
+ // *
5
+ // * 这个示例专门测试配置热更新功能
6
+ // *
7
+ // * 运行方式:
8
+ // * bun src/shared/infrastructure/config/examples/hot-reload-test.ts
9
+ // *
10
+ // * 测试步骤:
11
+ // * 1. 运行此脚本
12
+ // * 2. 在另一个终端中修改配置文件
13
+ // * echo "server:\n maxConnections: 500" > src/shared/infrastructure/config/examples/config/test-hot-reload.yaml
14
+ // * 3. 观察控制台输出,应该看到配置变更通知
15
+ // */
16
+ // import * as fs from 'fs';
17
+ // import * as path from 'path';
18
+ // import 'reflect-metadata';
19
+ // import { ConfigManager } from '..';
20
+ // import { YamlConfigSource } from '../sources/yaml-config-source';
21
+ // import { ConfigLogger } from '../utils/config-logger';
22
+ // // 启用日志
23
+ // ConfigLogger.getInstance().setLogEnabled(true);
24
+ // // 获取当前脚本目录
25
+ // const SCRIPT_DIR = path.dirname(new URL(import.meta.url).pathname);
26
+ // const CONFIG_DIR = path.join(SCRIPT_DIR, 'config');
27
+ // const TEST_CONFIG_PATH = path.join(CONFIG_DIR, 'test-hot-reload.yaml');
28
+ // // 确保配置目录存在
29
+ // if (!fs.existsSync(CONFIG_DIR)) {
30
+ // fs.mkdirSync(CONFIG_DIR, { recursive: true });
31
+ // }
32
+ // // 创建测试配置文件
33
+ // const yamlConfig = `server:
34
+ // maxConnections: 100
35
+ // `;
36
+ // fs.writeFileSync(TEST_CONFIG_PATH, yamlConfig, 'utf-8');
37
+ // console.log(`✅ 创建测试配置文件: ${TEST_CONFIG_PATH}`);
38
+ // async function main(): Promise<void> {
39
+ // console.log('🚀 启动热更新测试...');
40
+ // // 创建配置管理器
41
+ // const configManager = new ConfigManager();
42
+ // // 添加YAML配置源并启用监听
43
+ // console.log(`📦 添加YAML配置源: ${TEST_CONFIG_PATH}`);
44
+ // configManager.addSource(new YamlConfigSource(TEST_CONFIG_PATH, true));
45
+ // // 读取初始值
46
+ // const initialValue = await configManager.get<number>('server.maxConnections');
47
+ // console.log(`📊 初始值 server.maxConnections = ${initialValue}`);
48
+ // // 设置变更监听
49
+ // console.log('👀 设置配置变更监听...');
50
+ // configManager.subscribe<number>('server.maxConnections', (newValue) => {
51
+ // console.log(`🔄 配置已更新: server.maxConnections = ${newValue}`);
52
+ // });
53
+ // console.log('\n📝 请在另一个终端中修改配置文件:');
54
+ // console.log(
55
+ // `echo "server:\\n maxConnections: 500" > "${TEST_CONFIG_PATH}"\n`,
56
+ // );
57
+ // // 保持进程运行
58
+ // console.log('⏳ 等待配置变更 (按 Ctrl+C 退出)...\n');
59
+ // }
60
+ // // 运行主函数
61
+ // main().catch((error) => {
62
+ // console.error('❌ 错误:', error);
63
+ // process.exit(1);
64
+ // });
65
+ //# sourceMappingURL=hot-reload-test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hot-reload-test.js","sourceRoot":"","sources":["../../src/examples/hot-reload-test.ts"],"names":[],"mappings":";AAAA,MAAM;AACN,eAAe;AACf,KAAK;AACL,qBAAqB;AACrB,KAAK;AACL,WAAW;AACX,wEAAwE;AACxE,KAAK;AACL,WAAW;AACX,cAAc;AACd,sBAAsB;AACtB,sHAAsH;AACtH,2BAA2B;AAC3B,MAAM;AAEN,4BAA4B;AAC5B,gCAAgC;AAChC,6BAA6B;AAC7B,sCAAsC;AACtC,oEAAoE;AACpE,yDAAyD;AAEzD,UAAU;AACV,kDAAkD;AAElD,cAAc;AACd,sEAAsE;AACtE,sDAAsD;AACtD,0EAA0E;AAE1E,cAAc;AACd,oCAAoC;AACpC,mDAAmD;AACnD,IAAI;AAEJ,cAAc;AACd,8BAA8B;AAC9B,wBAAwB;AACxB,KAAK;AAEL,2DAA2D;AAC3D,kDAAkD;AAElD,yCAAyC;AACzC,kCAAkC;AAElC,eAAe;AACf,+CAA+C;AAE/C,sBAAsB;AACtB,sDAAsD;AACtD,2EAA2E;AAE3E,aAAa;AACb,mFAAmF;AACnF,mEAAmE;AAEnE,cAAc;AACd,mCAAmC;AACnC,6EAA6E;AAC7E,oEAAoE;AACpE,QAAQ;AAER,yCAAyC;AACzC,iBAAiB;AACjB,0EAA0E;AAC1E,OAAO;AAEP,cAAc;AACd,gDAAgD;AAChD,IAAI;AAEJ,WAAW;AACX,4BAA4B;AAC5B,mCAAmC;AACnC,qBAAqB;AACrB,MAAM"}