sa2kit 1.0.0 → 1.0.2

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 (99) hide show
  1. package/dist/UniversalFileService-CEZRJ87g.d.mts +727 -0
  2. package/dist/UniversalFileService-CEZRJ87g.d.ts +727 -0
  3. package/dist/api/index.d.mts +248 -0
  4. package/dist/api/index.d.ts +248 -0
  5. package/dist/api/index.js +294 -0
  6. package/dist/api/index.js.map +1 -0
  7. package/dist/api/index.mjs +290 -0
  8. package/dist/api/index.mjs.map +1 -0
  9. package/dist/auth/client/index.d.mts +52 -3
  10. package/dist/auth/client/index.d.ts +52 -3
  11. package/dist/auth/components/index.d.mts +149 -4
  12. package/dist/auth/components/index.d.ts +149 -4
  13. package/dist/auth/components/index.js +243 -9
  14. package/dist/auth/components/index.js.map +1 -1
  15. package/dist/auth/components/index.mjs +237 -4
  16. package/dist/auth/components/index.mjs.map +1 -1
  17. package/dist/auth/hooks/index.d.mts +31 -2
  18. package/dist/auth/hooks/index.d.ts +31 -2
  19. package/dist/auth/index.d.mts +5 -5
  20. package/dist/auth/index.d.ts +5 -5
  21. package/dist/auth/index.js +49 -17
  22. package/dist/auth/index.mjs +1 -1
  23. package/dist/auth/routes/index.d.mts +103 -5
  24. package/dist/auth/routes/index.d.ts +103 -5
  25. package/dist/auth/routes/index.js +37 -5
  26. package/dist/auth/routes/index.mjs +1 -1
  27. package/dist/chunk-42IJ7HEI.js +573 -0
  28. package/dist/chunk-42IJ7HEI.js.map +1 -0
  29. package/dist/chunk-7XLFSPDG.mjs +31 -0
  30. package/dist/chunk-7XLFSPDG.mjs.map +1 -0
  31. package/dist/chunk-GCVOKQZP.js +36 -0
  32. package/dist/chunk-GCVOKQZP.js.map +1 -0
  33. package/dist/chunk-IBLB7ARJ.mjs +560 -0
  34. package/dist/chunk-IBLB7ARJ.mjs.map +1 -0
  35. package/dist/{chunk-6FNUWAIV.js → chunk-LX4XX6W7.js} +54 -8
  36. package/dist/chunk-LX4XX6W7.js.map +1 -0
  37. package/dist/{chunk-HXFFYNIF.mjs → chunk-T5OZHYVM.mjs} +54 -8
  38. package/dist/chunk-T5OZHYVM.mjs.map +1 -0
  39. package/dist/config/server/index.d.mts +1533 -0
  40. package/dist/config/server/index.d.ts +1533 -0
  41. package/dist/config/server/index.js +1177 -0
  42. package/dist/config/server/index.js.map +1 -0
  43. package/dist/config/server/index.mjs +1138 -0
  44. package/dist/config/server/index.mjs.map +1 -0
  45. package/dist/i18n/index.d.mts +2 -1
  46. package/dist/i18n/index.d.ts +2 -1
  47. package/dist/i18n/index.js +125 -61
  48. package/dist/i18n/index.js.map +1 -1
  49. package/dist/i18n/index.mjs +126 -62
  50. package/dist/i18n/index.mjs.map +1 -1
  51. package/dist/index.js +6 -6
  52. package/dist/index.mjs +1 -1
  53. package/dist/mmd/index.d.mts +346 -0
  54. package/dist/mmd/index.d.ts +346 -0
  55. package/dist/mmd/index.js +1535 -0
  56. package/dist/mmd/index.js.map +1 -0
  57. package/dist/mmd/index.mjs +1503 -0
  58. package/dist/mmd/index.mjs.map +1 -0
  59. package/dist/storage/index.d.mts +1 -0
  60. package/dist/storage/index.d.ts +1 -0
  61. package/dist/storage/index.js +9 -9
  62. package/dist/storage/index.mjs +1 -1
  63. package/dist/{index-8VoHap_4.d.mts → types-CroexXnI.d.ts} +38 -44
  64. package/dist/{index-8VoHap_4.d.ts → types-DmsXCWvm.d.mts} +38 -44
  65. package/dist/{types-DAxQ1MeY.d.ts → types-Dt0oqeFM.d.mts} +1 -1
  66. package/dist/{types-DT8LVCvE.d.mts → types-zK6kDzDQ.d.ts} +1 -1
  67. package/dist/universalExport/index.js +17 -32
  68. package/dist/universalExport/index.js.map +1 -1
  69. package/dist/universalExport/index.mjs +2 -29
  70. package/dist/universalExport/index.mjs.map +1 -1
  71. package/dist/universalExport/server/index.d.mts +849 -8
  72. package/dist/universalExport/server/index.d.ts +849 -8
  73. package/dist/universalExport/server/index.js +1382 -2
  74. package/dist/universalExport/server/index.js.map +1 -1
  75. package/dist/universalExport/server/index.mjs +1355 -3
  76. package/dist/universalExport/server/index.mjs.map +1 -1
  77. package/dist/universalFile/index.d.mts +54 -3
  78. package/dist/universalFile/index.d.ts +54 -3
  79. package/dist/universalFile/index.js +272 -0
  80. package/dist/universalFile/index.js.map +1 -1
  81. package/dist/universalFile/index.mjs +267 -1
  82. package/dist/universalFile/index.mjs.map +1 -1
  83. package/dist/universalFile/server/index.d.mts +2541 -469
  84. package/dist/universalFile/server/index.d.ts +2541 -469
  85. package/dist/universalFile/server/index.js +830 -64
  86. package/dist/universalFile/server/index.js.map +1 -1
  87. package/dist/universalFile/server/index.mjs +803 -66
  88. package/dist/universalFile/server/index.mjs.map +1 -1
  89. package/package.json +47 -23
  90. package/dist/chunk-6FNUWAIV.js.map +0 -1
  91. package/dist/chunk-APY57REU.js +0 -300
  92. package/dist/chunk-APY57REU.js.map +0 -1
  93. package/dist/chunk-C64RY2OW.mjs +0 -295
  94. package/dist/chunk-C64RY2OW.mjs.map +0 -1
  95. package/dist/chunk-HXFFYNIF.mjs.map +0 -1
  96. package/dist/types-CoGG1rNV.d.mts +0 -258
  97. package/dist/types-CoGG1rNV.d.ts +0 -258
  98. package/dist/types-DW9qar-w.d.mts +0 -52
  99. package/dist/types-DW9qar-w.d.ts +0 -52
@@ -0,0 +1,1138 @@
1
+ import '../../chunk-BJTO5JO5.mjs';
2
+ import { pgTable, timestamp, text, jsonb, uniqueIndex, boolean, integer, index } from 'drizzle-orm/pg-core';
3
+ import { sql, eq } from 'drizzle-orm';
4
+ import * as crypto from 'crypto';
5
+ import crypto__default from 'crypto';
6
+
7
+ // src/config/server/types.ts
8
+ var ConfigCategory = /* @__PURE__ */ ((ConfigCategory2) => {
9
+ ConfigCategory2["DATABASE"] = "database";
10
+ ConfigCategory2["STORAGE"] = "storage";
11
+ ConfigCategory2["AI_SERVICE"] = "ai_service";
12
+ ConfigCategory2["EMAIL"] = "email";
13
+ ConfigCategory2["SECURITY"] = "security";
14
+ ConfigCategory2["SYSTEM"] = "system";
15
+ ConfigCategory2["MOBILE"] = "mobile";
16
+ ConfigCategory2["WECHAT"] = "wechat";
17
+ return ConfigCategory2;
18
+ })(ConfigCategory || {});
19
+ var systemConfigs = pgTable(
20
+ "system_configs",
21
+ {
22
+ id: text().primaryKey().notNull(),
23
+ key: text().notNull(),
24
+ value: jsonb().notNull(),
25
+ description: text(),
26
+ createdAt: timestamp({ precision: 3, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
27
+ updatedAt: timestamp({ precision: 3, mode: "string" }).notNull()
28
+ },
29
+ (table) => [
30
+ uniqueIndex("system_configs_key_key").using(
31
+ "btree",
32
+ table.key.asc().nullsLast().op("text_ops")
33
+ )
34
+ ]
35
+ );
36
+ var configMetadata = pgTable("config_metadata", {
37
+ key: text().primaryKey().notNull(),
38
+ category: text().notNull(),
39
+ type: text().default("string").notNull(),
40
+ isSensitive: boolean().default(false).notNull(),
41
+ isRequired: boolean().default(false).notNull(),
42
+ defaultDescription: text(),
43
+ createdAt: timestamp({ precision: 3, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
44
+ updatedAt: timestamp({ precision: 3, mode: "string" }).notNull()
45
+ });
46
+ var configDefinitions = pgTable(
47
+ "config_definitions",
48
+ {
49
+ id: integer().primaryKey().generatedAlwaysAsIdentity(),
50
+ key: text().notNull(),
51
+ category: text().notNull(),
52
+ name: text().notNull(),
53
+ description: text(),
54
+ // 类型和验证
55
+ type: text().notNull(),
56
+ // string, number, boolean, json, enum, url, email
57
+ validationRules: jsonb(),
58
+ // 验证规则 JSON
59
+ // UI 配置
60
+ uiComponent: text().default("input"),
61
+ // input, textarea, select, switch, slider
62
+ uiProps: jsonb(),
63
+ // UI 组件属性
64
+ // 安全和权限
65
+ isSensitive: boolean().default(false).notNull(),
66
+ isRequired: boolean().default(false).notNull(),
67
+ isReadonly: boolean().default(false).notNull(),
68
+ requiredPermission: text(),
69
+ // 默认值和选项
70
+ defaultValue: text(),
71
+ enumOptions: jsonb(),
72
+ // 枚举选项
73
+ // 依赖和条件
74
+ dependsOn: text().array(),
75
+ // 依赖的配置项
76
+ showIf: jsonb(),
77
+ // 显示条件
78
+ // 分组和排序
79
+ groupName: text(),
80
+ sortOrder: integer().default(0).notNull(),
81
+ // 版本和状态
82
+ version: integer().default(1).notNull(),
83
+ status: text().default("active").notNull(),
84
+ // active, deprecated, disabled
85
+ // 标签
86
+ tags: text().array(),
87
+ // 元数据
88
+ createdAt: timestamp({ precision: 3, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
89
+ updatedAt: timestamp({ precision: 3, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
90
+ createdBy: integer()
91
+ },
92
+ (table) => [
93
+ uniqueIndex("config_definitions_key_key").using(
94
+ "btree",
95
+ table.key.asc().nullsLast().op("text_ops")
96
+ ),
97
+ index("config_definitions_category_idx").using(
98
+ "btree",
99
+ table.category.asc().nullsLast().op("text_ops")
100
+ ),
101
+ index("config_definitions_status_idx").using(
102
+ "btree",
103
+ table.status.asc().nullsLast().op("text_ops")
104
+ )
105
+ ]
106
+ );
107
+ var configHistory = pgTable(
108
+ "config_history",
109
+ {
110
+ id: integer().primaryKey().generatedAlwaysAsIdentity(),
111
+ configKey: text().notNull(),
112
+ oldValue: text(),
113
+ newValue: text(),
114
+ changeType: text().notNull(),
115
+ // create, update, delete
116
+ changedBy: integer(),
117
+ changedAt: timestamp({ precision: 3, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull(),
118
+ reason: text(),
119
+ ipAddress: text(),
120
+ userAgent: text()
121
+ },
122
+ (table) => [
123
+ index("config_history_key_idx").using(
124
+ "btree",
125
+ table.configKey.asc().nullsLast().op("text_ops")
126
+ ),
127
+ index("config_history_date_idx").using(
128
+ "btree",
129
+ table.changedAt.asc().nullsLast().op("timestamp_ops")
130
+ )
131
+ ]
132
+ );
133
+ var defaultLogger = {
134
+ info: (message, ...args) => console.log(`[ConfigEngine] ${message}`, ...args),
135
+ warn: (message, ...args) => console.warn(`[ConfigEngine] ${message}`, ...args),
136
+ error: (message, ...args) => console.error(`[ConfigEngine] ${message}`, ...args)
137
+ };
138
+ var ConfigEngine = class {
139
+ constructor(options) {
140
+ this.definitionsCache = /* @__PURE__ */ new Map();
141
+ this.initialized = false;
142
+ this.db = options.db;
143
+ this.tables = options.tables;
144
+ this.logger = options.logger || defaultLogger;
145
+ this.encryptionKey = options.encryptionKey || process.env.CONFIG_ENCRYPTION_KEY || "default-config-key-2024";
146
+ if (this.encryptionKey === "default-config-key-2024") {
147
+ this.logger.warn("\u26A0\uFE0F \u4F7F\u7528\u9ED8\u8BA4\u52A0\u5BC6\u5BC6\u94A5\uFF0C\u751F\u4EA7\u73AF\u5883\u8BF7\u8BBE\u7F6E CONFIG_ENCRYPTION_KEY \u73AF\u5883\u53D8\u91CF");
148
+ }
149
+ }
150
+ /**
151
+ * 初始化配置引擎
152
+ */
153
+ async initialize() {
154
+ if (this.initialized) return;
155
+ try {
156
+ await this.loadDefinitions();
157
+ this.initialized = true;
158
+ this.logger.info("\u2705 ConfigEngine \u521D\u59CB\u5316\u6210\u529F");
159
+ } catch (error) {
160
+ this.logger.error("\u274C ConfigEngine \u521D\u59CB\u5316\u5931\u8D25:", error);
161
+ throw error;
162
+ }
163
+ }
164
+ /**
165
+ * 从数据库加载所有配置定义到缓存
166
+ */
167
+ async loadDefinitions() {
168
+ try {
169
+ const definitions = await this.db.select().from(this.tables.configDefinitions).where(eq(this.tables.configDefinitions.status, "active"));
170
+ this.definitionsCache.clear();
171
+ definitions.forEach((def) => {
172
+ const definition = {
173
+ id: def.id,
174
+ key: def.key,
175
+ category: def.category,
176
+ name: def.name,
177
+ description: def.description || void 0,
178
+ type: def.type,
179
+ validationRules: def.validationRules ? JSON.parse(JSON.stringify(def.validationRules)) : void 0,
180
+ uiComponent: def.uiComponent,
181
+ uiProps: def.uiProps ? JSON.parse(JSON.stringify(def.uiProps)) : void 0,
182
+ isSensitive: def.isSensitive,
183
+ isRequired: def.isRequired,
184
+ isReadonly: def.isReadonly,
185
+ requiredPermission: def.requiredPermission || void 0,
186
+ defaultValue: def.defaultValue || void 0,
187
+ enumOptions: def.enumOptions ? JSON.parse(JSON.stringify(def.enumOptions)) : void 0,
188
+ dependsOn: def.dependsOn || void 0,
189
+ showIf: def.showIf ? JSON.parse(JSON.stringify(def.showIf)) : void 0,
190
+ groupName: def.groupName || void 0,
191
+ sortOrder: def.sortOrder,
192
+ version: def.version,
193
+ status: def.status,
194
+ tags: def.tags || void 0,
195
+ createdAt: def.createdAt,
196
+ updatedAt: def.updatedAt,
197
+ createdBy: def.createdBy || void 0
198
+ };
199
+ this.definitionsCache.set(def.key, definition);
200
+ });
201
+ this.logger.info(`\u2705 \u5DF2\u52A0\u8F7D ${definitions.length} \u4E2A\u914D\u7F6E\u5B9A\u4E49`);
202
+ } catch (error) {
203
+ this.logger.error("\u274C \u52A0\u8F7D\u914D\u7F6E\u5B9A\u4E49\u5931\u8D25:", error);
204
+ throw error;
205
+ }
206
+ }
207
+ /**
208
+ * 获取单个配置定义
209
+ */
210
+ getDefinition(key) {
211
+ return this.definitionsCache.get(key);
212
+ }
213
+ /**
214
+ * 获取所有配置定义
215
+ */
216
+ getAllDefinitions() {
217
+ return Array.from(this.definitionsCache.values());
218
+ }
219
+ /**
220
+ * 获取指定分类的配置定义
221
+ */
222
+ getDefinitionsByCategory(category) {
223
+ return this.getAllDefinitions().filter((def) => def.category === category).sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0));
224
+ }
225
+ /**
226
+ * 验证配置值
227
+ */
228
+ async validate(key, value) {
229
+ const definition = this.getDefinition(key);
230
+ if (!definition) {
231
+ return {
232
+ valid: false,
233
+ errors: ["\u914D\u7F6E\u5B9A\u4E49\u4E0D\u5B58\u5728"]
234
+ };
235
+ }
236
+ const errors = [];
237
+ if (definition.isRequired && (value === null || value === void 0 || value === "")) {
238
+ errors.push("\u6B64\u914D\u7F6E\u9879\u4E3A\u5FC5\u586B");
239
+ return { valid: false, errors };
240
+ }
241
+ if (value === null || value === void 0 || value === "") {
242
+ return { valid: true, errors: [] };
243
+ }
244
+ const typeError = this.validateType(value, definition.type);
245
+ if (typeError) {
246
+ errors.push(typeError);
247
+ }
248
+ if (definition.validationRules && typeError === null) {
249
+ const ruleErrors = this.validateRules(value, definition.validationRules);
250
+ errors.push(...ruleErrors);
251
+ }
252
+ return {
253
+ valid: errors.length === 0,
254
+ errors
255
+ };
256
+ }
257
+ /**
258
+ * 获取配置的完整数据(定义 + 值)
259
+ */
260
+ async getConfigsWithValues(category) {
261
+ if (!this.initialized) {
262
+ await this.initialize();
263
+ }
264
+ const definitions = category ? this.getDefinitionsByCategory(category) : this.getAllDefinitions();
265
+ const configValues = await this.db.select().from(this.tables.systemConfigs);
266
+ const valueMap = new Map(configValues.map((v) => [v.key, v.value]));
267
+ const result = definitions.map((def) => {
268
+ let value = valueMap.get(def.key) ?? def.defaultValue;
269
+ let displayValue = value;
270
+ if (def.isSensitive && value && typeof value === "string") {
271
+ try {
272
+ value = this.decrypt(value);
273
+ displayValue = this.maskValue(value);
274
+ } catch (error) {
275
+ this.logger.warn(`\u89E3\u5BC6\u914D\u7F6E ${def.key} \u5931\u8D25:`, error);
276
+ }
277
+ }
278
+ return {
279
+ ...def,
280
+ value,
281
+ displayValue
282
+ };
283
+ });
284
+ return result;
285
+ }
286
+ /**
287
+ * 获取单个配置值
288
+ */
289
+ async getValue(key) {
290
+ const definition = this.getDefinition(key);
291
+ if (!definition) {
292
+ return void 0;
293
+ }
294
+ const configs = await this.db.select().from(this.tables.systemConfigs).where(eq(this.tables.systemConfigs.key, key)).limit(1);
295
+ if (configs.length === 0) {
296
+ return definition.defaultValue;
297
+ }
298
+ let value = configs[0].value;
299
+ if (definition.isSensitive && value && typeof value === "string") {
300
+ try {
301
+ value = this.decrypt(value);
302
+ } catch (error) {
303
+ this.logger.warn(`\u89E3\u5BC6\u914D\u7F6E ${key} \u5931\u8D25:`, error);
304
+ }
305
+ }
306
+ return value;
307
+ }
308
+ /**
309
+ * 设置配置值
310
+ */
311
+ async setValue(key, value, userId = 0, options) {
312
+ const validation = await this.validate(key, value);
313
+ if (!validation.valid) {
314
+ throw new Error(`\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25: ${validation.errors.join(", ")}`);
315
+ }
316
+ const definition = this.getDefinition(key);
317
+ if (!definition) {
318
+ throw new Error("\u914D\u7F6E\u5B9A\u4E49\u4E0D\u5B58\u5728");
319
+ }
320
+ const oldConfigs = await this.db.select().from(this.tables.systemConfigs).where(eq(this.tables.systemConfigs.key, key)).limit(1);
321
+ const oldValue = oldConfigs.length > 0 ? oldConfigs[0].value : void 0;
322
+ let finalValue = value;
323
+ if (definition.isSensitive && value) {
324
+ finalValue = this.encrypt(String(value));
325
+ }
326
+ if (oldConfigs.length > 0) {
327
+ await this.db.update(this.tables.systemConfigs).set({
328
+ value: finalValue,
329
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
330
+ }).where(eq(this.tables.systemConfigs.key, key));
331
+ } else {
332
+ const id = crypto.randomUUID();
333
+ await this.db.insert(this.tables.systemConfigs).values({
334
+ id,
335
+ key,
336
+ value: finalValue,
337
+ description: definition.description,
338
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
339
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
340
+ });
341
+ }
342
+ await this.recordHistory({
343
+ configKey: key,
344
+ oldValue: oldValue ? JSON.stringify(oldValue) : void 0,
345
+ newValue: JSON.stringify(value),
346
+ changeType: oldValue ? "update" : "create",
347
+ changedBy: userId,
348
+ reason: options?.reason,
349
+ ipAddress: options?.ipAddress,
350
+ userAgent: options?.userAgent
351
+ });
352
+ this.logger.info(`\u2705 \u914D\u7F6E\u5DF2${oldValue ? "\u66F4\u65B0" : "\u521B\u5EFA"}: ${key}`);
353
+ }
354
+ /**
355
+ * 批量设置配置值
356
+ */
357
+ async setValues(values, userId = 0, options) {
358
+ for (const item of values) {
359
+ await this.setValue(item.key, item.value, userId, options);
360
+ }
361
+ }
362
+ /**
363
+ * 注册新配置定义
364
+ */
365
+ async registerDefinition(definition, userId = 0) {
366
+ try {
367
+ await this.db.insert(this.tables.configDefinitions).values({
368
+ key: definition.key,
369
+ category: definition.category,
370
+ name: definition.name,
371
+ description: definition.description,
372
+ type: definition.type,
373
+ validationRules: definition.validationRules ? JSON.stringify(definition.validationRules) : null,
374
+ uiComponent: definition.uiComponent || "input",
375
+ uiProps: definition.uiProps ? JSON.stringify(definition.uiProps) : null,
376
+ isSensitive: definition.isSensitive || false,
377
+ isRequired: definition.isRequired || false,
378
+ isReadonly: definition.isReadonly || false,
379
+ requiredPermission: definition.requiredPermission,
380
+ defaultValue: definition.defaultValue,
381
+ enumOptions: definition.enumOptions ? JSON.stringify(definition.enumOptions) : null,
382
+ dependsOn: definition.dependsOn,
383
+ showIf: definition.showIf ? JSON.stringify(definition.showIf) : null,
384
+ groupName: definition.groupName,
385
+ sortOrder: definition.sortOrder || 0,
386
+ version: definition.version || 1,
387
+ status: definition.status || "active",
388
+ tags: definition.tags,
389
+ createdBy: userId,
390
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
391
+ });
392
+ await this.loadDefinitions();
393
+ this.logger.info(`\u2705 \u6CE8\u518C\u65B0\u914D\u7F6E\u5B9A\u4E49: ${definition.key}`);
394
+ } catch (error) {
395
+ this.logger.error(`\u274C \u6CE8\u518C\u914D\u7F6E\u5B9A\u4E49\u5931\u8D25:`, error);
396
+ throw error;
397
+ }
398
+ }
399
+ /**
400
+ * 批量注册配置定义
401
+ */
402
+ async registerDefinitions(definitions, userId = 0) {
403
+ for (const definition of definitions) {
404
+ await this.registerDefinition(definition, userId);
405
+ }
406
+ }
407
+ /**
408
+ * 记录配置变更历史
409
+ */
410
+ async recordHistory(record) {
411
+ try {
412
+ await this.db.insert(this.tables.configHistory).values({
413
+ ...record,
414
+ changedAt: (/* @__PURE__ */ new Date()).toISOString()
415
+ });
416
+ } catch (error) {
417
+ this.logger.error("\u274C \u8BB0\u5F55\u914D\u7F6E\u5386\u53F2\u5931\u8D25:", error);
418
+ }
419
+ }
420
+ /**
421
+ * 获取配置变更历史
422
+ */
423
+ async getHistory(key, limit = 50) {
424
+ try {
425
+ const history = await this.db.select().from(this.tables.configHistory).where(eq(this.tables.configHistory.configKey, key)).orderBy(this.tables.configHistory.changedAt).limit(limit);
426
+ return history;
427
+ } catch (error) {
428
+ this.logger.error("\u274C \u83B7\u53D6\u914D\u7F6E\u5386\u53F2\u5931\u8D25:", error);
429
+ return [];
430
+ }
431
+ }
432
+ // ==================== 私有辅助方法 ====================
433
+ /**
434
+ * 类型验证
435
+ */
436
+ validateType(value, type) {
437
+ switch (type) {
438
+ case "string":
439
+ return typeof value === "string" ? null : "\u503C\u5FC5\u987B\u662F\u5B57\u7B26\u4E32";
440
+ case "number":
441
+ return typeof value === "number" && !isNaN(value) ? null : "\u503C\u5FC5\u987B\u662F\u6570\u5B57";
442
+ case "boolean":
443
+ return typeof value === "boolean" ? null : "\u503C\u5FC5\u987B\u662F\u5E03\u5C14\u503C";
444
+ case "json":
445
+ try {
446
+ if (typeof value === "string") {
447
+ JSON.parse(value);
448
+ }
449
+ return null;
450
+ } catch {
451
+ return "\u503C\u5FC5\u987B\u662F\u6709\u6548\u7684 JSON";
452
+ }
453
+ case "url":
454
+ try {
455
+ new URL(value);
456
+ return null;
457
+ } catch {
458
+ return "\u503C\u5FC5\u987B\u662F\u6709\u6548\u7684 URL";
459
+ }
460
+ case "email":
461
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) ? null : "\u503C\u5FC5\u987B\u662F\u6709\u6548\u7684\u90AE\u7BB1\u5730\u5740";
462
+ case "enum":
463
+ return null;
464
+ // 枚举验证在规则验证中处理
465
+ default:
466
+ return null;
467
+ }
468
+ }
469
+ /**
470
+ * 规则验证
471
+ */
472
+ validateRules(value, rules) {
473
+ const errors = [];
474
+ if (rules.min !== void 0 && value < rules.min) {
475
+ errors.push(`\u503C\u4E0D\u80FD\u5C0F\u4E8E ${rules.min}`);
476
+ }
477
+ if (rules.max !== void 0 && value > rules.max) {
478
+ errors.push(`\u503C\u4E0D\u80FD\u5927\u4E8E ${rules.max}`);
479
+ }
480
+ if (rules.minLength !== void 0 && String(value).length < rules.minLength) {
481
+ errors.push(`\u957F\u5EA6\u4E0D\u80FD\u5C0F\u4E8E ${rules.minLength}`);
482
+ }
483
+ if (rules.maxLength !== void 0 && String(value).length > rules.maxLength) {
484
+ errors.push(`\u957F\u5EA6\u4E0D\u80FD\u5927\u4E8E ${rules.maxLength}`);
485
+ }
486
+ if (rules.pattern && !new RegExp(rules.pattern).test(String(value))) {
487
+ errors.push("\u503C\u4E0D\u7B26\u5408\u8981\u6C42\u7684\u683C\u5F0F");
488
+ }
489
+ return errors;
490
+ }
491
+ /**
492
+ * 加密
493
+ */
494
+ encrypt(value) {
495
+ const algorithm = "aes-256-cbc";
496
+ const key = crypto.scryptSync(this.encryptionKey, "salt", 32);
497
+ const iv = crypto.randomBytes(16);
498
+ const cipher = crypto.createCipheriv(algorithm, key, iv);
499
+ let encrypted = cipher.update(value, "utf8", "hex");
500
+ encrypted += cipher.final("hex");
501
+ return iv.toString("hex") + ":" + encrypted;
502
+ }
503
+ /**
504
+ * 解密
505
+ */
506
+ decrypt(encrypted) {
507
+ const algorithm = "aes-256-cbc";
508
+ const key = crypto.scryptSync(this.encryptionKey, "salt", 32);
509
+ const parts = encrypted.split(":");
510
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
511
+ throw new Error("\u65E0\u6548\u7684\u52A0\u5BC6\u6570\u636E\u683C\u5F0F");
512
+ }
513
+ const [ivHex, encryptedData] = parts;
514
+ const iv = Buffer.from(ivHex, "hex");
515
+ const decipher = crypto.createDecipheriv(algorithm, key, iv);
516
+ let decrypted = decipher.update(encryptedData, "hex", "utf8");
517
+ decrypted += decipher.final("utf8");
518
+ return decrypted;
519
+ }
520
+ /**
521
+ * 掩码显示敏感值
522
+ */
523
+ maskValue(value) {
524
+ if (!value) return "";
525
+ const len = value.length;
526
+ if (len <= 8) {
527
+ return "*".repeat(len);
528
+ }
529
+ return value.substring(0, 4) + "*".repeat(len - 8) + value.substring(len - 4);
530
+ }
531
+ };
532
+ var defaultLogger2 = {
533
+ info: (message, ...args) => console.log(`[ConfigService] ${message}`, ...args),
534
+ warn: (message, ...args) => console.warn(`[ConfigService] ${message}`, ...args),
535
+ error: (message, ...args) => console.error(`[ConfigService] ${message}`, ...args)
536
+ };
537
+ var ConfigService = class {
538
+ constructor(options) {
539
+ this.configCache = /* @__PURE__ */ new Map();
540
+ this.metadataCache = /* @__PURE__ */ new Map();
541
+ this.db = options.db;
542
+ this.tables = options.tables;
543
+ this.logger = options.logger || defaultLogger2;
544
+ this.templates = options.templates || {};
545
+ this.encryptionKey = options.encryptionKey || process.env.CONFIG_ENCRYPTION_KEY || "default-config-key-2024";
546
+ this.loadConfigsFromDatabase();
547
+ this.loadMetadataFromDatabase();
548
+ }
549
+ // 从数据库加载元数据
550
+ async loadMetadataFromDatabase() {
551
+ if (!this.tables.configMetadata) {
552
+ this.logger.info("\u914D\u7F6E\u5143\u6570\u636E\u8868\u672A\u63D0\u4F9B\uFF0C\u8DF3\u8FC7\u5143\u6570\u636E\u52A0\u8F7D");
553
+ return;
554
+ }
555
+ try {
556
+ const metadata = await this.db.select().from(this.tables.configMetadata);
557
+ metadata.forEach((meta) => {
558
+ this.metadataCache.set(meta.key, {
559
+ category: meta.category,
560
+ type: meta.type,
561
+ isSensitive: meta.isSensitive,
562
+ isRequired: meta.isRequired,
563
+ defaultDescription: meta.defaultDescription || void 0
564
+ });
565
+ });
566
+ this.logger.info(`\u5DF2\u52A0\u8F7D ${metadata.length} \u6761\u914D\u7F6E\u5143\u6570\u636E`);
567
+ } catch (error) {
568
+ this.logger.warn(
569
+ "\u914D\u7F6E\u5143\u6570\u636E\u8868\u4E0D\u5B58\u5728\uFF0C\u4F7F\u7528\u6A21\u677F\u6570\u636E",
570
+ error instanceof Error ? error.message : String(error)
571
+ );
572
+ }
573
+ }
574
+ // 从数据库加载配置到缓存
575
+ async loadConfigsFromDatabase() {
576
+ try {
577
+ const configs = await this.db.select().from(this.tables.systemConfigs);
578
+ configs.forEach((config) => {
579
+ let value = config.value;
580
+ if (this.isSensitiveConfig(config.key)) {
581
+ try {
582
+ value = this.decrypt(config.value);
583
+ this.logger.info(`\u2705 \u6210\u529F\u89E3\u5BC6\u914D\u7F6E: ${config.key}`);
584
+ } catch (error) {
585
+ this.logger.error(`\u274C \u89E3\u5BC6\u914D\u7F6E\u5931\u8D25: ${config.key}`, error);
586
+ return;
587
+ }
588
+ }
589
+ this.configCache.set(config.key, value);
590
+ });
591
+ this.logger.info(`\u5DF2\u52A0\u8F7D ${configs.length} \u4E2A\u914D\u7F6E\u9879`);
592
+ } catch (error) {
593
+ this.logger.error("\u52A0\u8F7D\u914D\u7F6E\u5931\u8D25", error instanceof Error ? error : new Error(String(error)));
594
+ }
595
+ }
596
+ // 获取配置值
597
+ async getConfig(key, defaultValue) {
598
+ if (!key) {
599
+ return defaultValue;
600
+ }
601
+ const envValue = process.env[key.toUpperCase()];
602
+ if (envValue !== void 0) {
603
+ return this.parseValue(envValue, this.getConfigType(key));
604
+ }
605
+ if (this.configCache.has(key)) {
606
+ return this.configCache.get(key);
607
+ }
608
+ try {
609
+ const [config] = await this.db.select().from(this.tables.systemConfigs).where(eq(this.tables.systemConfigs.key, key)).limit(1);
610
+ if (config) {
611
+ let value = config.value;
612
+ if (this.isSensitiveConfig(key)) {
613
+ try {
614
+ value = this.decrypt(config.value);
615
+ this.logger.info(`\u2705 \u6210\u529F\u89E3\u5BC6\u914D\u7F6E: ${key}, \u957F\u5EA6: ${value?.length}`);
616
+ } catch (error) {
617
+ this.logger.error(`\u274C \u89E3\u5BC6\u914D\u7F6E\u5931\u8D25: ${key}`, error);
618
+ throw new Error(`\u914D\u7F6E ${key} \u89E3\u5BC6\u5931\u8D25`);
619
+ }
620
+ }
621
+ this.configCache.set(key, value);
622
+ return value;
623
+ }
624
+ } catch (error) {
625
+ this.logger.error(
626
+ `\u83B7\u53D6\u914D\u7F6E ${key} \u5931\u8D25`,
627
+ error instanceof Error ? error : new Error(String(error))
628
+ );
629
+ }
630
+ return defaultValue;
631
+ }
632
+ // 设置配置值
633
+ async setConfig(key, value, description) {
634
+ try {
635
+ const category = this.getConfigCategory(key);
636
+ const type = this.getConfigType(key);
637
+ const isSensitive = this.isSensitiveConfig(key);
638
+ const validatedValue = this.validateValue(value, type);
639
+ const storageValue = isSensitive ? this.encrypt(validatedValue) : validatedValue;
640
+ const existing = await this.db.select().from(this.tables.systemConfigs).where(eq(this.tables.systemConfigs.key, key)).limit(1);
641
+ if (existing.length > 0) {
642
+ await this.db.update(this.tables.systemConfigs).set({
643
+ value: storageValue,
644
+ description: description || this.getConfigDescription(key),
645
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
646
+ }).where(eq(this.tables.systemConfigs.key, key));
647
+ } else {
648
+ await this.db.insert(this.tables.systemConfigs).values({
649
+ id: crypto__default.randomBytes(16).toString("hex"),
650
+ key,
651
+ value: storageValue,
652
+ description: description || this.getConfigDescription(key),
653
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
654
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
655
+ });
656
+ }
657
+ this.configCache.set(key, validatedValue);
658
+ this.logger.info(`\u914D\u7F6E ${key} \u5DF2\u66F4\u65B0`);
659
+ } catch (error) {
660
+ this.logger.error(
661
+ `\u8BBE\u7F6E\u914D\u7F6E ${key} \u5931\u8D25`,
662
+ error instanceof Error ? error : new Error(String(error))
663
+ );
664
+ throw error;
665
+ }
666
+ }
667
+ // 获取分类下的所有配置
668
+ async getConfigsByCategory(category) {
669
+ const configs = {};
670
+ const template = this.templates[category] || [];
671
+ for (const item of template) {
672
+ configs[item.key] = await this.getConfig(item.key, item.defaultValue);
673
+ }
674
+ return configs;
675
+ }
676
+ // 批量设置配置
677
+ async setConfigs(configs) {
678
+ for (const [key, value] of Object.entries(configs)) {
679
+ await this.setConfig(key, value);
680
+ }
681
+ }
682
+ // 删除配置
683
+ async deleteConfig(key) {
684
+ try {
685
+ await this.db.delete(this.tables.systemConfigs).where(eq(this.tables.systemConfigs.key, key));
686
+ this.configCache.delete(key);
687
+ this.logger.info(`\u914D\u7F6E ${key} \u5DF2\u5220\u9664`);
688
+ } catch (error) {
689
+ this.logger.error(
690
+ `\u5220\u9664\u914D\u7F6E ${key} \u5931\u8D25`,
691
+ error instanceof Error ? error : new Error(String(error))
692
+ );
693
+ throw error;
694
+ }
695
+ }
696
+ // 获取所有配置(用于管理界面)
697
+ async getAllConfigs() {
698
+ const allConfigs = {};
699
+ const dbConfigs = await this.db.select().from(this.tables.systemConfigs);
700
+ const dbConfigKeys = new Set(dbConfigs.map((c) => c.key));
701
+ for (const [category, items] of Object.entries(this.templates)) {
702
+ allConfigs[category] = {};
703
+ for (const item of items) {
704
+ if (dbConfigKeys.has(item.key)) {
705
+ const value = await this.getConfig(item.key, item.defaultValue);
706
+ allConfigs[category][item.key] = {
707
+ ...item,
708
+ value: item.isSensitive ? "" : value,
709
+ // 敏感信息隐藏
710
+ isStored: true
711
+ // 标记为已存储
712
+ };
713
+ }
714
+ }
715
+ }
716
+ return allConfigs;
717
+ }
718
+ // 刷新配置缓存
719
+ async refreshCache() {
720
+ this.configCache.clear();
721
+ await this.loadConfigsFromDatabase();
722
+ }
723
+ // 配置验证
724
+ validateConfig(key, value) {
725
+ const type = this.getConfigType(key);
726
+ const isRequired = this.isRequiredConfig(key);
727
+ if (isRequired && (value === void 0 || value === null || value === "")) {
728
+ throw new Error(`\u914D\u7F6E ${key} \u662F\u5FC5\u9700\u7684`);
729
+ }
730
+ try {
731
+ this.validateValue(value, type);
732
+ return true;
733
+ } catch (error) {
734
+ throw new Error(`\u914D\u7F6E ${key} \u503C\u65E0\u6548: ${error.message}`);
735
+ }
736
+ }
737
+ // 私有方法:加密
738
+ encrypt(text2) {
739
+ const algorithm = "aes-256-cbc";
740
+ const key = crypto__default.scryptSync(this.encryptionKey, "salt", 32);
741
+ const iv = crypto__default.randomBytes(16);
742
+ const cipher = crypto__default.createCipheriv(algorithm, key, iv);
743
+ let encrypted = cipher.update(text2, "utf8", "hex");
744
+ encrypted += cipher.final("hex");
745
+ return iv.toString("hex") + ":" + encrypted;
746
+ }
747
+ // 私有方法:解密
748
+ decrypt(encryptedText) {
749
+ const algorithm = "aes-256-cbc";
750
+ const key = crypto__default.scryptSync(this.encryptionKey, "salt", 32);
751
+ const parts = encryptedText.split(":");
752
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
753
+ throw new Error("\u65E0\u6548\u7684\u52A0\u5BC6\u6570\u636E\u683C\u5F0F");
754
+ }
755
+ const iv = Buffer.from(parts[0], "hex");
756
+ const encrypted = parts[1];
757
+ const decipher = crypto__default.createDecipheriv(algorithm, key, iv);
758
+ let decrypted = decipher.update(encrypted, "hex", "utf8");
759
+ decrypted += decipher.final("utf8");
760
+ return decrypted;
761
+ }
762
+ // 私有方法:解析值类型
763
+ parseValue(value, type) {
764
+ switch (type) {
765
+ case "number":
766
+ return parseInt(value);
767
+ case "boolean":
768
+ return value.toLowerCase() === "true";
769
+ case "json":
770
+ return JSON.parse(value);
771
+ default:
772
+ return value;
773
+ }
774
+ }
775
+ // 私有方法:验证值
776
+ validateValue(value, type) {
777
+ switch (type) {
778
+ case "string":
779
+ return String(value);
780
+ case "number":
781
+ const num = Number(value);
782
+ if (isNaN(num)) throw new Error("\u503C\u5FC5\u987B\u662F\u6570\u5B57");
783
+ return num;
784
+ case "boolean":
785
+ return Boolean(value);
786
+ case "json":
787
+ if (typeof value === "string") {
788
+ return JSON.parse(value);
789
+ }
790
+ return value;
791
+ default:
792
+ return value;
793
+ }
794
+ }
795
+ // 私有方法:获取配置类型
796
+ getConfigType(key) {
797
+ const metadata = this.metadataCache.get(key);
798
+ return metadata?.type || "string";
799
+ }
800
+ // 私有方法:获取配置分类
801
+ getConfigCategory(key) {
802
+ const metadata = this.metadataCache.get(key);
803
+ return metadata?.category || "system" /* SYSTEM */;
804
+ }
805
+ // 私有方法:检查是否为敏感配置
806
+ isSensitiveConfig(key) {
807
+ const metadata = this.metadataCache.get(key);
808
+ return metadata?.isSensitive || false;
809
+ }
810
+ // 私有方法:检查是否为必需配置
811
+ isRequiredConfig(key) {
812
+ const metadata = this.metadataCache.get(key);
813
+ return metadata?.isRequired || false;
814
+ }
815
+ // 私有方法:获取配置描述
816
+ getConfigDescription(key) {
817
+ const metadata = this.metadataCache.get(key);
818
+ return metadata?.defaultDescription || "";
819
+ }
820
+ // 新增方法:创建或更新配置元数据
821
+ async setConfigMetadata(key, category, type = "string", options = {}) {
822
+ if (!this.tables.configMetadata) {
823
+ this.logger.warn("\u914D\u7F6E\u5143\u6570\u636E\u8868\u672A\u63D0\u4F9B\uFF0C\u8DF3\u8FC7\u5143\u6570\u636E\u8BBE\u7F6E");
824
+ return;
825
+ }
826
+ try {
827
+ const now = (/* @__PURE__ */ new Date()).toISOString();
828
+ const existing = await this.db.select().from(this.tables.configMetadata).where(eq(this.tables.configMetadata.key, key)).limit(1);
829
+ if (existing.length > 0) {
830
+ await this.db.update(this.tables.configMetadata).set({
831
+ category,
832
+ type,
833
+ isSensitive: options.isSensitive ?? false,
834
+ isRequired: options.isRequired ?? false,
835
+ defaultDescription: options.defaultDescription,
836
+ updatedAt: now
837
+ }).where(eq(this.tables.configMetadata.key, key));
838
+ } else {
839
+ await this.db.insert(this.tables.configMetadata).values({
840
+ key,
841
+ category,
842
+ type,
843
+ isSensitive: options.isSensitive ?? false,
844
+ isRequired: options.isRequired ?? false,
845
+ defaultDescription: options.defaultDescription,
846
+ createdAt: now,
847
+ updatedAt: now
848
+ });
849
+ }
850
+ this.metadataCache.set(key, {
851
+ category,
852
+ type,
853
+ isSensitive: options.isSensitive ?? false,
854
+ isRequired: options.isRequired ?? false,
855
+ defaultDescription: options.defaultDescription
856
+ });
857
+ this.logger.info(`\u914D\u7F6E\u5143\u6570\u636E ${key} \u5DF2\u66F4\u65B0`);
858
+ } catch (error) {
859
+ this.logger.error(
860
+ `\u8BBE\u7F6E\u914D\u7F6E\u5143\u6570\u636E ${key} \u5931\u8D25`,
861
+ error instanceof Error ? error : new Error(String(error))
862
+ );
863
+ throw error;
864
+ }
865
+ }
866
+ };
867
+ function createConfigService(options) {
868
+ return new ConfigService(options);
869
+ }
870
+
871
+ // src/config/server/templates.ts
872
+ var DEFAULT_CONFIG_TEMPLATES = {
873
+ // 数据库相关的业务配置(非连接配置)
874
+ ["database" /* DATABASE */]: [
875
+ {
876
+ key: "database_pool_size",
877
+ value: 10,
878
+ category: "database" /* DATABASE */,
879
+ type: "number",
880
+ isRequired: false,
881
+ isSensitive: false,
882
+ description: "\u6570\u636E\u5E93\u8FDE\u63A5\u6C60\u5927\u5C0F",
883
+ defaultValue: 10,
884
+ group: "\u8FDE\u63A5\u6C60\u914D\u7F6E"
885
+ },
886
+ {
887
+ key: "database_query_timeout",
888
+ value: 3e4,
889
+ category: "database" /* DATABASE */,
890
+ type: "number",
891
+ isRequired: false,
892
+ isSensitive: false,
893
+ description: "\u6570\u636E\u5E93\u67E5\u8BE2\u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09",
894
+ defaultValue: 3e4,
895
+ group: "\u8FDE\u63A5\u6C60\u914D\u7F6E"
896
+ },
897
+ {
898
+ key: "enable_query_logging",
899
+ value: false,
900
+ category: "database" /* DATABASE */,
901
+ type: "boolean",
902
+ isRequired: false,
903
+ isSensitive: false,
904
+ description: "\u542F\u7528\u6570\u636E\u5E93\u67E5\u8BE2\u65E5\u5FD7",
905
+ defaultValue: false,
906
+ group: "\u8FDE\u63A5\u6C60\u914D\u7F6E"
907
+ }
908
+ ],
909
+ // 存储配置
910
+ ["storage" /* STORAGE */]: [
911
+ {
912
+ key: "storage_type",
913
+ value: "local",
914
+ category: "storage" /* STORAGE */,
915
+ type: "string",
916
+ isRequired: true,
917
+ isSensitive: false,
918
+ description: "\u5B58\u50A8\u7C7B\u578B\uFF08local/aliyun-oss/aws-s3\uFF09",
919
+ defaultValue: "local",
920
+ group: "\u57FA\u7840\u914D\u7F6E"
921
+ },
922
+ {
923
+ key: "upload_max_size",
924
+ value: 10485760,
925
+ category: "storage" /* STORAGE */,
926
+ type: "number",
927
+ isRequired: false,
928
+ isSensitive: false,
929
+ description: "\u6700\u5927\u4E0A\u4F20\u6587\u4EF6\u5927\u5C0F\uFF08\u5B57\u8282\uFF09",
930
+ defaultValue: 10485760,
931
+ group: "\u4E0A\u4F20\u914D\u7F6E"
932
+ }
933
+ ],
934
+ // 安全配置
935
+ ["security" /* SECURITY */]: [
936
+ {
937
+ key: "jwt_secret",
938
+ value: "",
939
+ category: "security" /* SECURITY */,
940
+ type: "string",
941
+ isRequired: true,
942
+ isSensitive: true,
943
+ description: "JWT\u7B7E\u540D\u5BC6\u94A5"
944
+ },
945
+ {
946
+ key: "jwt_expires_in",
947
+ value: "7d",
948
+ category: "security" /* SECURITY */,
949
+ type: "string",
950
+ isRequired: true,
951
+ isSensitive: false,
952
+ description: "JWT\u8FC7\u671F\u65F6\u95F4",
953
+ defaultValue: "7d"
954
+ },
955
+ {
956
+ key: "enable_rate_limiting",
957
+ value: true,
958
+ category: "security" /* SECURITY */,
959
+ type: "boolean",
960
+ isRequired: false,
961
+ isSensitive: false,
962
+ description: "\u542F\u7528API\u901F\u7387\u9650\u5236",
963
+ defaultValue: true
964
+ }
965
+ ],
966
+ // 系统配置
967
+ ["system" /* SYSTEM */]: [
968
+ {
969
+ key: "app_name",
970
+ value: "My App",
971
+ category: "system" /* SYSTEM */,
972
+ type: "string",
973
+ isRequired: true,
974
+ isSensitive: false,
975
+ description: "\u5E94\u7528\u540D\u79F0",
976
+ defaultValue: "My App"
977
+ },
978
+ {
979
+ key: "maintenance_mode",
980
+ value: false,
981
+ category: "system" /* SYSTEM */,
982
+ type: "boolean",
983
+ isRequired: false,
984
+ isSensitive: false,
985
+ description: "\u7EF4\u62A4\u6A21\u5F0F",
986
+ defaultValue: false
987
+ },
988
+ {
989
+ key: "log_level",
990
+ value: "info",
991
+ category: "system" /* SYSTEM */,
992
+ type: "string",
993
+ isRequired: false,
994
+ isSensitive: false,
995
+ description: "\u65E5\u5FD7\u7EA7\u522B",
996
+ defaultValue: "info"
997
+ }
998
+ ]
999
+ };
1000
+ function createConfigTemplates(templates) {
1001
+ const filteredTemplates = { ...DEFAULT_CONFIG_TEMPLATES };
1002
+ Object.keys(templates).forEach((key) => {
1003
+ const value = templates[key];
1004
+ if (value !== void 0) {
1005
+ filteredTemplates[key] = value;
1006
+ }
1007
+ });
1008
+ return filteredTemplates;
1009
+ }
1010
+
1011
+ // src/config/server/factory.ts
1012
+ function createConfigEngine(options) {
1013
+ return new ConfigEngine(options);
1014
+ }
1015
+ function createGlobalConfigService(options) {
1016
+ let instance = null;
1017
+ return () => {
1018
+ if (!instance) {
1019
+ instance = new ConfigService(options);
1020
+ }
1021
+ return instance;
1022
+ };
1023
+ }
1024
+ function createGlobalConfigEngine(options) {
1025
+ let instance = null;
1026
+ let isInitializing = false;
1027
+ return () => {
1028
+ if (!instance) {
1029
+ instance = new ConfigEngine(options);
1030
+ if (!isInitializing) {
1031
+ isInitializing = true;
1032
+ instance.initialize().catch((error) => {
1033
+ console.error("[ConfigEngine] \u521D\u59CB\u5316\u5931\u8D25:", error);
1034
+ });
1035
+ }
1036
+ }
1037
+ return instance;
1038
+ };
1039
+ }
1040
+
1041
+ // src/config/server/database-config.ts
1042
+ function getDatabaseConfig() {
1043
+ const databaseUrl = process.env.DATABASE_URL;
1044
+ if (databaseUrl) {
1045
+ const url = new URL(databaseUrl);
1046
+ return {
1047
+ host: url.hostname,
1048
+ port: parseInt(url.port) || 5432,
1049
+ database: url.pathname.slice(1),
1050
+ // 移除开头的 /
1051
+ username: url.username,
1052
+ password: url.password,
1053
+ ssl: url.searchParams.get("sslmode") === "require",
1054
+ poolSize: parseInt(process.env.DB_POOL_SIZE || "10"),
1055
+ queryTimeout: parseInt(process.env.DB_QUERY_TIMEOUT || "30000")
1056
+ };
1057
+ }
1058
+ return {
1059
+ host: process.env.DB_HOST || process.env.POSTGRES_HOST || "localhost",
1060
+ port: parseInt(process.env.DB_PORT || process.env.POSTGRES_PORT || "5432"),
1061
+ database: process.env.DB_NAME || process.env.POSTGRES_DB || "lyricnote",
1062
+ username: process.env.DB_USER || process.env.POSTGRES_USER || "lyricnote",
1063
+ password: process.env.DB_PASSWORD || process.env.POSTGRES_PASSWORD || "",
1064
+ ssl: process.env.DB_SSL === "true",
1065
+ poolSize: parseInt(process.env.DB_POOL_SIZE || "10"),
1066
+ queryTimeout: parseInt(process.env.DB_QUERY_TIMEOUT || "30000")
1067
+ };
1068
+ }
1069
+ function getRedisConfig() {
1070
+ const redisUrl = process.env.REDIS_URL;
1071
+ if (redisUrl) {
1072
+ const url = new URL(redisUrl);
1073
+ return {
1074
+ host: url.hostname,
1075
+ port: parseInt(url.port) || 6379,
1076
+ password: url.password || void 0,
1077
+ database: parseInt(url.pathname.slice(1)) || 0,
1078
+ keyPrefix: process.env.REDIS_KEY_PREFIX || "lyricnote:"
1079
+ };
1080
+ }
1081
+ return {
1082
+ host: process.env.REDIS_HOST || "localhost",
1083
+ port: parseInt(process.env.REDIS_PORT || "6379"),
1084
+ password: process.env.REDIS_PASSWORD || void 0,
1085
+ database: parseInt(process.env.REDIS_DB || "0"),
1086
+ keyPrefix: process.env.REDIS_KEY_PREFIX || "lyricnote:"
1087
+ };
1088
+ }
1089
+ function buildDatabaseUrl(config) {
1090
+ const { host, port, database, username, password, ssl } = config;
1091
+ let url = `postgresql://${username}:${password}@${host}:${port}/${database}`;
1092
+ if (ssl) {
1093
+ url += "?sslmode=require";
1094
+ }
1095
+ return url;
1096
+ }
1097
+ function buildRedisUrl(config) {
1098
+ const { host, port, password, database } = config;
1099
+ let url = `redis://`;
1100
+ if (password) {
1101
+ url += `:${password}@`;
1102
+ }
1103
+ url += `${host}:${port}`;
1104
+ if (database && database !== 0) {
1105
+ url += `/${database}`;
1106
+ }
1107
+ return url;
1108
+ }
1109
+ function validateDatabaseConfig(config) {
1110
+ const errors = [];
1111
+ if (!config.host) errors.push("\u6570\u636E\u5E93\u4E3B\u673A\u5730\u5740\u4E0D\u80FD\u4E3A\u7A7A");
1112
+ if (!config.port || config.port < 1 || config.port > 65535) errors.push("\u6570\u636E\u5E93\u7AEF\u53E3\u53F7\u65E0\u6548");
1113
+ if (!config.database) errors.push("\u6570\u636E\u5E93\u540D\u4E0D\u80FD\u4E3A\u7A7A");
1114
+ if (!config.username) errors.push("\u6570\u636E\u5E93\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A");
1115
+ if (!config.password) errors.push("\u6570\u636E\u5E93\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A");
1116
+ return errors;
1117
+ }
1118
+ function getDatabaseConfigForDisplay() {
1119
+ const config = getDatabaseConfig();
1120
+ return {
1121
+ // 只显示非敏感信息
1122
+ host: config.host,
1123
+ port: config.port,
1124
+ database: config.database,
1125
+ username: config.username,
1126
+ password: config.password ? "***" : "",
1127
+ ssl: config.ssl || false,
1128
+ poolSize: config.poolSize,
1129
+ queryTimeout: config.queryTimeout,
1130
+ // 连接状态
1131
+ connectionString: `postgresql://${config.username}:***@${config.host}:${config.port}/${config.database}`,
1132
+ source: process.env.DATABASE_URL ? "DATABASE_URL" : "Environment Variables"
1133
+ };
1134
+ }
1135
+
1136
+ export { ConfigCategory, ConfigEngine, ConfigService, DEFAULT_CONFIG_TEMPLATES, buildDatabaseUrl, buildRedisUrl, configDefinitions, configHistory, configMetadata, createConfigEngine, createConfigService, createConfigTemplates, createGlobalConfigEngine, createGlobalConfigService, getDatabaseConfig, getDatabaseConfigForDisplay, getRedisConfig, systemConfigs, validateDatabaseConfig };
1137
+ //# sourceMappingURL=index.mjs.map
1138
+ //# sourceMappingURL=index.mjs.map