create-dp-koa 1.1.1 → 1.1.3

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 (84) hide show
  1. package/package.json +1 -1
  2. package/template/scripts/sync-template.mjs +21 -0
  3. package/template/src/app.ts +1 -2
  4. package/template/src/{framework/plugins → plugins}/registry.ts +2 -2
  5. package/template/src/plugins/weboffice/http/routes.ts +2 -2
  6. package/template/src/plugins/weboffice/index.ts +3 -3
  7. package/template/src/plugins/weboffice/services/webofficeCallback.service.ts +3 -4
  8. package/template/src/utils/testDataInitializer.ts +1 -1
  9. package/template/tsconfig.json +6 -0
  10. package/template/src/annotations/decorators/ConfigManagement.ts +0 -9
  11. package/template/src/annotations/decorators/DistributedTracing.ts +0 -9
  12. package/template/src/annotations/decorators/EnterprisePerformance.ts +0 -9
  13. package/template/src/annotations/decorators/PerformanceMonitor.ts +0 -32
  14. package/template/src/annotations/decorators/SecurityAudit.ts +0 -9
  15. package/template/src/annotations/index.ts +0 -50
  16. package/template/src/annotations/processors/ConfigManagementProcessor.ts +0 -369
  17. package/template/src/annotations/processors/DistributedTracingProcessor.ts +0 -288
  18. package/template/src/annotations/processors/EnterprisePerformanceProcessor.ts +0 -189
  19. package/template/src/annotations/processors/PerformanceMonitorProcessor.ts +0 -101
  20. package/template/src/annotations/processors/SecurityAuditProcessor.ts +0 -345
  21. package/template/src/annotations/processors/SwaggerProcessor.ts +0 -612
  22. package/template/src/annotations/processors/index.ts +0 -10
  23. package/template/src/examples/InterceptorExampleRunner.ts +0 -284
  24. package/template/src/examples/ServiceInterceptorExample.ts +0 -214
  25. package/template/src/examples/cacheExamples.ts +0 -155
  26. package/template/src/framework/decorator/controller.ts +0 -311
  27. package/template/src/framework/decorator/processor/AnnotationDecorators.ts +0 -100
  28. package/template/src/framework/decorator/processor/AnnotationProcessor.ts +0 -160
  29. package/template/src/framework/decorator/processor/AnnotationProcessorConfig.ts +0 -45
  30. package/template/src/framework/decorator/processor/AnnotationRegistry.ts +0 -117
  31. package/template/src/framework/decorator/processor/AnnotationSystemInitializer.ts +0 -95
  32. package/template/src/framework/decorator/processor/ProcessorManager.ts +0 -76
  33. package/template/src/framework/decorator/processor/processors/CustomProcessors.ts +0 -126
  34. package/template/src/framework/decorator/processor/processors/DefaultProcessors.ts +0 -207
  35. package/template/src/framework/decorator/refactored/DecoratorFactory.ts +0 -99
  36. package/template/src/framework/decorator/refactored/DecoratorMetadataManager.ts +0 -125
  37. package/template/src/framework/decorator/refactored/DecoratorValidator.ts +0 -128
  38. package/template/src/framework/decorator/refactored/TypeSafeDecorators.ts +0 -139
  39. package/template/src/framework/decorator/refactored/index.ts +0 -98
  40. package/template/src/framework/decorator/swagger.ts +0 -150
  41. package/template/src/framework/interceptors/AdvancedServiceCallInterceptor.ts +0 -375
  42. package/template/src/framework/interceptors/ServiceCallInterceptor.ts +0 -348
  43. package/template/src/framework/interceptors/index.ts +0 -19
  44. package/template/src/framework/plugins/types.ts +0 -15
  45. package/template/src/framework/types/ServiceResult.ts +0 -151
  46. package/template/src/framework/types/index.ts +0 -16
  47. package/template/src/framework/utils/CacheManager.ts +0 -430
  48. package/template/src/framework/utils/CacheService.ts +0 -248
  49. package/template/src/framework/utils/DtoValidator.ts +0 -164
  50. package/template/src/framework/utils/MigrationHelper.ts +0 -179
  51. package/template/src/framework/utils/MigrationManager.ts +0 -256
  52. package/template/src/framework/utils/NewRouter.ts +0 -207
  53. package/template/src/framework/utils/TransactionManager.ts +0 -172
  54. package/template/src/framework/utils/bootstrap.ts +0 -445
  55. package/template/src/framework/utils/cache.ts +0 -269
  56. package/template/src/framework/utils/databaseConfig.ts +0 -148
  57. package/template/src/framework/utils/db.ts +0 -39
  58. package/template/src/framework/utils/dbMonitor.ts +0 -106
  59. package/template/src/framework/utils/function.ts +0 -61
  60. package/template/src/framework/utils/gracefulShutdown.ts +0 -131
  61. package/template/src/framework/utils/logger.ts +0 -388
  62. package/template/src/framework/utils/metrics.ts +0 -182
  63. package/template/src/framework/utils/router.ts +0 -417
  64. package/template/src/framework/utils/swagger.ts +0 -184
  65. package/template/src/framework/utils/testDb.ts +0 -19
  66. package/template/src/framework/utils/token.ts +0 -23
  67. package/template/src/framework/utils/transform.ts +0 -17
  68. package/template/src/libs/aokEmailSender.ts +0 -42
  69. package/template/src/libs/captcha.ts +0 -37
  70. package/template/src/libs/cos.ts +0 -45
  71. package/template/src/libs/mCache.ts +0 -7
  72. package/template/src/libs/serviceValidate.ts +0 -3
  73. package/template/src/libs/tecentSms.ts +0 -51
  74. package/template/src/middlewares/a.middleware.ts +0 -6
  75. package/template/src/middlewares/error.middleware.ts +0 -14
  76. package/template/src/middlewares/logging.middleware.ts +0 -187
  77. package/template/src/middlewares/static.middleware.ts +0 -79
  78. package/template/src/middlewares/swagger.middleware.ts +0 -70
  79. package/template/src/middlewares/token.middleware.ts +0 -32
  80. package/template/src/migrations/1700000000000-InitialDatabaseStructure.ts +0 -172
  81. package/template/src/migrations/index.ts +0 -6
  82. package/template/src/repository/base/BaseRepository.ts +0 -124
  83. package/template/src/repository/interfaces/IBaseRepository.ts +0 -67
  84. package/template/src/service/base.service.ts +0 -116
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-dp-koa",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "Scaffold a DP-Koa framework project from the official template",
5
5
  "type": "module",
6
6
  "bin": {
@@ -28,6 +28,21 @@ const EXCLUDED_SEGMENTS = new Set([
28
28
  /** 仓库根下整目录排除 */
29
29
  const EXCLUDED_TOP_LEVEL = new Set(['packages']);
30
30
 
31
+ /**
32
+ * 不同步到模板的相对路径前缀(相对仓库根)
33
+ * 目标:让脚手架模板不再携带框架实现快照(framework/libs 等),改为依赖 npm 包。
34
+ */
35
+ const EXCLUDED_RELATIVE_PREFIXES = [
36
+ 'src/framework/',
37
+ 'src/libs/',
38
+ 'src/annotations/',
39
+ 'src/middlewares/',
40
+ 'src/examples/',
41
+ 'src/repository/',
42
+ 'src/migrations/',
43
+ 'src/service/',
44
+ ];
45
+
31
46
  // template 内部“必须保留”的文件(防止后续 sync-template 直接覆盖回旧实现)
32
47
  // 相对路径以 DEST 为基准。
33
48
  const PRESERVE_RELATIVE_PATHS = [
@@ -38,11 +53,17 @@ const PRESERVE_RELATIVE_PATHS = [
38
53
  'src/controllers/demo/AnnotationDemoController.ts',
39
54
  'src/controllers/example/ExampleController.ts',
40
55
  'src/controllers/example/EnterpriseExampleController.ts',
56
+ 'src/plugins/weboffice/http/routes.ts',
57
+ 'src/plugins/registry.ts',
41
58
  ];
42
59
 
43
60
  function shouldCopySource(absSrc, baseRoot) {
44
61
  const rel = relative(baseRoot, absSrc);
45
62
  if (!rel || rel === '.') return true;
63
+ const normalized = rel.replace(/\\/g, '/');
64
+ for (const prefix of EXCLUDED_RELATIVE_PREFIXES) {
65
+ if (normalized === prefix.slice(0, -1) || normalized.startsWith(prefix)) return false;
66
+ }
46
67
  const parts = rel.split(/[/\\]/);
47
68
  for (const p of parts) {
48
69
  if (EXCLUDED_SEGMENTS.has(p)) return false;
@@ -1,4 +1,3 @@
1
- import { DataSourceOptions } from "typeorm";
2
1
  import {
3
2
  bootstrap,
4
3
  setAfterBootstrap,
@@ -30,7 +29,7 @@ import {
30
29
  registerPluginRoutes,
31
30
  runAfterBootstrapHooks,
32
31
  runBeforeBootstrapHooks,
33
- } from "@src/framework/plugins/registry";
32
+ } from "@src/plugins/registry";
34
33
  import Koa from "koa";
35
34
  import path from "path";
36
35
 
@@ -1,7 +1,7 @@
1
1
  import type Koa from "koa";
2
2
  import type Router from "koa-router";
3
- import type { PluginDescriptor } from "@src/framework/plugins/types";
4
- import { logger } from "@src/framework/utils/logger";
3
+ import type { PluginDescriptor } from "dp-koa-framework-core";
4
+ import { logger } from "dp-koa-framework-core";
5
5
 
6
6
  // 示例插件(可按需添加/移除)
7
7
  import { plugin as webofficePlugin } from "@src/plugins/weboffice";
@@ -3,7 +3,7 @@ import { Provider } from "dp-ioc2";
3
3
  import { WebofficeCallbackService } from "../services/webofficeCallback.service";
4
4
  import { parseWebOfficeContext } from "../core/context";
5
5
  import { OK, WebOfficeError, ErrInvalidArguments } from "../core/errors";
6
- import { logger } from "@src/framework/utils/logger";
6
+ import { logger } from "dp-koa-framework-core";
7
7
  import path from "path";
8
8
  import fs from "fs";
9
9
 
@@ -33,7 +33,7 @@ function registerUnderPrefix(router: Router, basePath: string): void {
33
33
  router.post(`${base}/files`, async (ctx) => {
34
34
  try {
35
35
  const woCtx = parseWebOfficeContext(ctx);
36
- const body = (ctx.request.body as any) || {};
36
+ const body = ((ctx.request as any).body as any) || {};
37
37
  const name = body.name || "未命名文档";
38
38
  const projectId = body.project_id != null ? Number(body.project_id) : undefined;
39
39
  const data = await service.createDocument(woCtx, name, projectId);
@@ -1,14 +1,14 @@
1
1
  import type Router from "koa-router";
2
2
  import type Koa from "koa";
3
- import type { PluginDescriptor } from "@src/framework/plugins/types";
3
+ import type { PluginDescriptor } from "dp-koa-framework-core";
4
4
  import { registerWebOfficeRoutes } from "./http/routes";
5
5
  import { WebofficeFileEntity, WebofficeFileVersionEntity } from "./entities";
6
- import { logger } from "@src/framework/utils/logger";
6
+ import { logger } from "dp-koa-framework-core";
7
7
 
8
8
  export const plugin: PluginDescriptor = {
9
9
  id: "weboffice",
10
10
  displayName: "WPS WebOffice 示例插件",
11
- enabled: (env) => env.WEBOFFICE_ENABLED !== "0",
11
+ enabled: (env: NodeJS.ProcessEnv) => env.WEBOFFICE_ENABLED !== "0",
12
12
 
13
13
  onBeforeBootstrap(_app: Koa) {
14
14
  logger.info('Plugin "weboffice" before bootstrap');
@@ -1,5 +1,5 @@
1
1
  import { Injectable } from "dp-ioc2";
2
- import { BaseService } from "@src/service/base.service";
2
+ import { BaseService, logger } from "dp-koa-framework-core";
3
3
  import { WebofficeFileEntity } from "../entities/webofficeFile.entity";
4
4
  import { WebofficeFileVersionEntity } from "../entities/webofficeFileVersion.entity";
5
5
  import {
@@ -18,8 +18,7 @@ import {
18
18
  ErrInternalError,
19
19
  } from "../core/errors";
20
20
  import { normalizeWpsUserId } from "../core/utils";
21
- import { getFilePublicUrl, isCosConfigured, uploadToCos, webofficeCosKey } from "@src/libs/cos";
22
- import { logger } from "@src/framework/utils/logger";
21
+ import { getFilePublicUrl, isCosConfigured, uploadToCos, webofficeCosKey } from "dp-koa-framework-libs";
23
22
  import fs from "fs";
24
23
  import { v4 as uuidv4 } from "uuid";
25
24
 
@@ -229,7 +228,7 @@ export class WebofficeCallbackService extends BaseService {
229
228
  skip: offset,
230
229
  take: limit,
231
230
  });
232
- return versions.map((v) => this.toGetFileReply(pair.file, v));
231
+ return versions.map((v: WebofficeFileVersionEntity) => this.toGetFileReply(pair.file, v));
233
232
  }
234
233
 
235
234
  async getFileVersion(
@@ -1,4 +1,4 @@
1
- import { logger } from "@src/framework/utils/logger";
1
+ import { logger } from "dp-koa-framework-core";
2
2
 
3
3
  /**
4
4
  * 测试数据初始化工具
@@ -15,6 +15,12 @@
15
15
  "@src/*": [
16
16
  "./src/*"
17
17
  ],
18
+ "dp-koa-framework-core": [
19
+ "../../dp-koa-framework-core/dist/index.d.ts"
20
+ ],
21
+ "dp-koa-framework-libs": [
22
+ "../../dp-koa-framework-libs/dist/index.d.ts"
23
+ ]
18
24
  },
19
25
  "strictPropertyInitialization": false
20
26
  },
@@ -1,9 +0,0 @@
1
- /**
2
- * 企业级配置管理装饰器
3
- */
4
- import { createAnnotationDecorator } from '@src/framework/decorator/processor/AnnotationDecorators';
5
- import { ConfigManagementConfig } from '@src/annotations/processors/ConfigManagementProcessor';
6
-
7
- export function ConfigManagement(config?: ConfigManagementConfig) {
8
- return createAnnotationDecorator('ConfigManagement')(config);
9
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * 企业级分布式追踪装饰器
3
- */
4
- import { createAnnotationDecorator } from '@src/framework/decorator/processor/AnnotationDecorators';
5
- import { TracingConfig } from '@src/annotations/processors/DistributedTracingProcessor';
6
-
7
- export function DistributedTracing(config?: TracingConfig) {
8
- return createAnnotationDecorator('DistributedTracing')(config);
9
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * 企业级性能监控装饰器
3
- */
4
- import { createAnnotationDecorator } from '@src/framework/decorator/processor/AnnotationDecorators';
5
- import { PerformanceConfig } from '@src/annotations/processors/EnterprisePerformanceProcessor';
6
-
7
- export function EnterprisePerformance(config?: PerformanceConfig) {
8
- return createAnnotationDecorator('EnterprisePerformance')(config);
9
- }
@@ -1,32 +0,0 @@
1
- import { createAnnotationDecorator } from '@src/framework/decorator/processor/AnnotationDecorators';
2
-
3
- /**
4
- * 性能监控注解配置接口
5
- */
6
- export interface PerformanceMonitorConfig {
7
- /** 最大执行时间(毫秒) */
8
- maxExecutionTime?: number;
9
- /** 最大内存使用变化(MB) */
10
- maxMemoryUsage?: number;
11
- /** 是否启用详细日志 */
12
- verbose?: boolean;
13
- }
14
-
15
- /**
16
- * 性能监控注解
17
- * 用于监控方法执行性能,包括执行时间和内存使用
18
- *
19
- * @example
20
- * ```typescript
21
- * @PerformanceMonitor()
22
- * async getData() {
23
- * return { data: 'example' };
24
- * }
25
- *
26
- * @PerformanceMonitor({ maxExecutionTime: 1000, maxMemoryUsage: 10 })
27
- * async heavyOperation() {
28
- * // 执行耗时操作
29
- * }
30
- * ```
31
- */
32
- export const PerformanceMonitor = createAnnotationDecorator('PerformanceMonitor');
@@ -1,9 +0,0 @@
1
- /**
2
- * 企业级安全审计装饰器
3
- */
4
- import { createAnnotationDecorator } from '@src/framework/decorator/processor/AnnotationDecorators';
5
- import { SecurityAuditConfig } from '@src/annotations/processors/SecurityAuditProcessor';
6
-
7
- export function SecurityAudit(config?: SecurityAuditConfig) {
8
- return createAnnotationDecorator('SecurityAudit')(config);
9
- }
@@ -1,50 +0,0 @@
1
- /**
2
- * 企业级业务层注解导出文件
3
- * 统一导出所有自定义注解处理器和装饰器
4
- */
5
-
6
- // 导出基础注解处理器
7
- export { PerformanceMonitorProcessor } from './processors/PerformanceMonitorProcessor';
8
-
9
- // 导出企业级注解处理器
10
- export { EnterprisePerformanceProcessor } from './processors/EnterprisePerformanceProcessor';
11
- export { SecurityAuditProcessor } from './processors/SecurityAuditProcessor';
12
- export { DistributedTracingProcessor } from './processors/DistributedTracingProcessor';
13
- export { ConfigManagementProcessor } from './processors/ConfigManagementProcessor';
14
-
15
- // 导出基础注解装饰器
16
- export { PerformanceMonitor, type PerformanceMonitorConfig } from './decorators/PerformanceMonitor';
17
-
18
- // 导出企业级注解装饰器
19
- export { EnterprisePerformance } from './decorators/EnterprisePerformance';
20
- export { SecurityAudit } from './decorators/SecurityAudit';
21
- export { DistributedTracing } from './decorators/DistributedTracing';
22
- export { ConfigManagement } from './decorators/ConfigManagement';
23
-
24
- // 导出类型定义
25
- export type { PerformanceConfig } from './processors/EnterprisePerformanceProcessor';
26
- export type { SecurityAuditConfig } from './processors/SecurityAuditProcessor';
27
- export type { TracingConfig } from './processors/DistributedTracingProcessor';
28
- export type { ConfigManagementConfig } from './processors/ConfigManagementProcessor';
29
-
30
- /**
31
- * 获取所有业务层注解处理器
32
- * 用于在注解系统初始化时注册
33
- */
34
- export function getBusinessAnnotationProcessors() {
35
- const {
36
- PerformanceMonitorProcessor,
37
- EnterprisePerformanceProcessor,
38
- SecurityAuditProcessor,
39
- DistributedTracingProcessor,
40
- ConfigManagementProcessor
41
- } = require('@src/annotations/processors');
42
-
43
- return [
44
- new PerformanceMonitorProcessor(),
45
- new EnterprisePerformanceProcessor(),
46
- new SecurityAuditProcessor(),
47
- new DistributedTracingProcessor(),
48
- new ConfigManagementProcessor()
49
- ];
50
- }
@@ -1,369 +0,0 @@
1
- /**
2
- * 企业级配置管理注解处理器
3
- * 提供动态配置、环境变量管理和配置验证
4
- */
5
-
6
- import { Context } from 'koa';
7
- import { AnnotationProcessor } from '@src/framework/decorator/processor/AnnotationProcessor';
8
- import { logger } from '@src/framework/utils/logger';
9
- import { getRuntimeEnvironmentLabel } from '@src/framework/utils/function';
10
-
11
- export interface ConfigManagementConfig {
12
- configKey?: string;
13
- defaultValue?: any;
14
- required?: boolean;
15
- validationRules?: ValidationRule[];
16
- refreshInterval?: number;
17
- environment?: 'development' | 'staging' | 'production';
18
- fallbackConfig?: Record<string, any>;
19
- }
20
-
21
- export interface ValidationRule {
22
- type: 'string' | 'number' | 'boolean' | 'array' | 'object' | 'email' | 'url';
23
- min?: number;
24
- max?: number;
25
- pattern?: RegExp;
26
- custom?: (value: any) => boolean;
27
- message?: string;
28
- }
29
-
30
- export interface ConfigValue {
31
- key: string;
32
- value: any;
33
- source: 'environment' | 'database' | 'file' | 'default';
34
- lastUpdated: Date;
35
- environment: string;
36
- validated: boolean;
37
- }
38
-
39
- export class ConfigManagementProcessor implements AnnotationProcessor {
40
- readonly name = 'ConfigManagement';
41
- readonly priority = 4;
42
-
43
- private configCache: Map<string, ConfigValue> = new Map();
44
- private validationRules: Map<string, ValidationRule[]> = new Map();
45
- private refreshTimers: Map<string, NodeJS.Timeout> = new Map();
46
- private configRefreshInterval: NodeJS.Timeout | null = null; // 存储定时器引用
47
-
48
- constructor() {
49
- this.loadEnvironmentConfigs();
50
- this.startConfigRefresh();
51
- }
52
-
53
- async process(
54
- ctx: Context,
55
- controller: any,
56
- methodName: string,
57
- annotationData: ConfigManagementConfig,
58
- callParams: any[]
59
- ): Promise<boolean> {
60
- const config = annotationData || {};
61
-
62
- if (!config.configKey) return true;
63
-
64
- try {
65
- // 获取配置值
66
- const configValue = await this.getConfigValue(config.configKey, config);
67
-
68
- // 验证配置
69
- if (config.validationRules) {
70
- const isValid = this.validateConfig(config.configKey, configValue.value, config.validationRules);
71
- if (!isValid) {
72
- logger.error(`[${this.name}] 配置验证失败: ${config.configKey}`);
73
- ctx.status = 500;
74
- ctx.body = { error: 'Configuration validation failed' };
75
- return false;
76
- }
77
- }
78
-
79
- // 将配置注入到上下文
80
- ctx.state.config = ctx.state.config || {};
81
- ctx.state.config[config.configKey] = configValue.value;
82
-
83
- logger.debug(`[${this.name}] 配置加载成功: ${config.configKey}`, {
84
- value: this.sanitizeValue(configValue.value),
85
- source: configValue.source
86
- });
87
-
88
- } catch (error) {
89
- logger.error(`[${this.name}] 配置加载失败: ${config.configKey}`, error as Error);
90
-
91
- if (config.required) {
92
- ctx.status = 500;
93
- ctx.body = { error: 'Required configuration missing' };
94
- return false;
95
- }
96
- }
97
-
98
- return true;
99
- }
100
-
101
- private async getConfigValue(key: string, config: ConfigManagementConfig): Promise<ConfigValue> {
102
- // 检查缓存
103
- const cached = this.configCache.get(key);
104
- if (cached && this.isCacheValid(cached)) {
105
- return cached;
106
- }
107
-
108
- let value: any;
109
- let source: ConfigValue['source'] = 'default';
110
-
111
- // 1. 尝试从环境变量获取
112
- const envValue = process.env[key.toUpperCase()];
113
- if (envValue !== undefined) {
114
- value = this.parseValue(envValue);
115
- source = 'environment';
116
- }
117
- // 2. 尝试从数据库获取
118
- else if (await this.hasDatabaseConfig(key)) {
119
- value = await this.getDatabaseConfig(key);
120
- source = 'database';
121
- }
122
- // 3. 尝试从配置文件获取
123
- else if (await this.hasFileConfig(key)) {
124
- value = await this.getFileConfig(key);
125
- source = 'file';
126
- }
127
- // 4. 使用默认值
128
- else {
129
- value = config.defaultValue;
130
- source = 'default';
131
- }
132
-
133
- const configValue: ConfigValue = {
134
- key,
135
- value,
136
- source,
137
- lastUpdated: new Date(),
138
- environment: config.environment || getRuntimeEnvironmentLabel(),
139
- validated: false
140
- };
141
-
142
- // 缓存配置
143
- this.configCache.set(key, configValue);
144
-
145
- return configValue;
146
- }
147
-
148
- private parseValue(value: string): any {
149
- // 尝试解析 JSON
150
- try {
151
- return JSON.parse(value);
152
- } catch {
153
- // 尝试解析布尔值
154
- if (value.toLowerCase() === 'true') return true;
155
- if (value.toLowerCase() === 'false') return false;
156
-
157
- // 尝试解析数字
158
- const num = Number(value);
159
- if (!isNaN(num)) return num;
160
-
161
- // 返回字符串
162
- return value;
163
- }
164
- }
165
-
166
- private validateConfig(key: string, value: any, rules: ValidationRule[]): boolean {
167
- for (const rule of rules) {
168
- if (!this.validateRule(value, rule)) {
169
- logger.warn(`[${this.name}] 配置验证失败: ${key}`, {
170
- value: this.sanitizeValue(value),
171
- rule: rule.type,
172
- message: rule.message
173
- });
174
- return false;
175
- }
176
- }
177
- return true;
178
- }
179
-
180
- private validateRule(value: any, rule: ValidationRule): boolean {
181
- switch (rule.type) {
182
- case 'string':
183
- if (typeof value !== 'string') return false;
184
- if (rule.min && value.length < rule.min) return false;
185
- if (rule.max && value.length > rule.max) return false;
186
- if (rule.pattern && !rule.pattern.test(value)) return false;
187
- break;
188
-
189
- case 'number':
190
- if (typeof value !== 'number') return false;
191
- if (rule.min && value < rule.min) return false;
192
- if (rule.max && value > rule.max) return false;
193
- break;
194
-
195
- case 'boolean':
196
- if (typeof value !== 'boolean') return false;
197
- break;
198
-
199
- case 'array':
200
- if (!Array.isArray(value)) return false;
201
- if (rule.min && value.length < rule.min) return false;
202
- if (rule.max && value.length > rule.max) return false;
203
- break;
204
-
205
- case 'object':
206
- if (typeof value !== 'object' || value === null) return false;
207
- break;
208
-
209
- case 'email':
210
- if (typeof value !== 'string' || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return false;
211
- break;
212
-
213
- case 'url':
214
- if (typeof value !== 'string' || !/^https?:\/\/.+/.test(value)) return false;
215
- break;
216
- }
217
-
218
- // 自定义验证
219
- if (rule.custom && !rule.custom(value)) return false;
220
-
221
- return true;
222
- }
223
-
224
- private async hasDatabaseConfig(key: string): Promise<boolean> {
225
- // 这里应该实现数据库配置检查
226
- return false;
227
- }
228
-
229
- private async getDatabaseConfig(key: string): Promise<any> {
230
- // 这里应该实现数据库配置获取
231
- return null;
232
- }
233
-
234
- private async hasFileConfig(key: string): Promise<boolean> {
235
- // 这里应该实现文件配置检查
236
- return false;
237
- }
238
-
239
- private async getFileConfig(key: string): Promise<any> {
240
- // 这里应该实现文件配置获取
241
- return null;
242
- }
243
-
244
- private isCacheValid(configValue: ConfigValue): boolean {
245
- const maxAge = 5 * 60 * 1000; // 5分钟
246
- return Date.now() - configValue.lastUpdated.getTime() < maxAge;
247
- }
248
-
249
- private sanitizeValue(value: any): any {
250
- if (typeof value === 'string' && value.length > 100) {
251
- return value.substring(0, 100) + '...';
252
- }
253
- return value;
254
- }
255
-
256
- private loadEnvironmentConfigs(): void {
257
- // 加载环境变量配置
258
- Object.keys(process.env).forEach(key => {
259
- if (key.startsWith('CONFIG_')) {
260
- const configKey = key.substring(7).toLowerCase();
261
- const value = this.parseValue(process.env[key]!);
262
-
263
- this.configCache.set(configKey, {
264
- key: configKey,
265
- value,
266
- source: 'environment',
267
- lastUpdated: new Date(),
268
- environment: getRuntimeEnvironmentLabel(),
269
- validated: false
270
- });
271
- }
272
- });
273
- }
274
-
275
- private startConfigRefresh(): void {
276
- // 如果已有定时器,先清除
277
- if (this.configRefreshInterval) {
278
- clearInterval(this.configRefreshInterval);
279
- }
280
-
281
- // 定期刷新配置
282
- this.configRefreshInterval = setInterval(() => {
283
- this.refreshConfigs();
284
- }, 60000); // 每分钟刷新一次
285
- }
286
-
287
- /**
288
- * 停止配置刷新定时器
289
- * 防止内存泄露
290
- */
291
- stopConfigRefresh(): void {
292
- if (this.configRefreshInterval) {
293
- clearInterval(this.configRefreshInterval);
294
- this.configRefreshInterval = null;
295
- logger.info(`[${this.name}] 配置刷新定时器已停止`);
296
- }
297
- }
298
-
299
- /**
300
- * 清理所有定时器
301
- */
302
- cleanup(): void {
303
- // 清理主刷新定时器
304
- this.stopConfigRefresh();
305
-
306
- // 清理所有独立的刷新定时器
307
- this.refreshTimers.forEach((timer) => {
308
- clearInterval(timer);
309
- });
310
- this.refreshTimers.clear();
311
-
312
- // 清理缓存
313
- this.configCache.clear();
314
- this.validationRules.clear();
315
-
316
- logger.info(`[${this.name}] 所有资源已清理`);
317
- }
318
-
319
- private async refreshConfigs(): Promise<void> {
320
- const keys = Array.from(this.configCache.keys());
321
-
322
- for (const key of keys) {
323
- try {
324
- const cached = this.configCache.get(key)!;
325
- if (cached.source === 'environment') {
326
- // 环境变量配置不需要刷新
327
- continue;
328
- }
329
-
330
- // 重新加载配置
331
- const newValue = await this.getConfigValue(key, {});
332
- if (JSON.stringify(newValue.value) !== JSON.stringify(cached.value)) {
333
- logger.info(`[${this.name}] 配置已更新: ${key}`);
334
- }
335
- } catch (error) {
336
- logger.error(`[${this.name}] 配置刷新失败: ${key}`, error as Error);
337
- }
338
- }
339
- }
340
-
341
- /**
342
- * 获取所有配置
343
- */
344
- getAllConfigs(): ConfigValue[] {
345
- return Array.from(this.configCache.values());
346
- }
347
-
348
- /**
349
- * 获取指定配置
350
- */
351
- getConfig(key: string): ConfigValue | undefined {
352
- return this.configCache.get(key);
353
- }
354
-
355
- /**
356
- * 设置配置验证规则
357
- */
358
- setValidationRules(key: string, rules: ValidationRule[]): void {
359
- this.validationRules.set(key, rules);
360
- }
361
-
362
- /**
363
- * 清理配置缓存
364
- */
365
- clearCache(): void {
366
- this.configCache.clear();
367
- logger.info(`[${this.name}] 配置缓存已清理`);
368
- }
369
- }