id-scanner-lib 1.3.3 → 1.6.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 (80) hide show
  1. package/README.md +324 -410
  2. package/dist/id-scanner-lib.esm.js +4826 -0
  3. package/dist/id-scanner-lib.esm.js.map +1 -0
  4. package/dist/id-scanner-lib.js +4858 -0
  5. package/dist/id-scanner-lib.js.map +1 -0
  6. package/dist/types/browser-image-compression.d.ts +19 -0
  7. package/dist/types/tesseract.d.ts +280 -0
  8. package/package.json +89 -78
  9. package/src/core/base-module.ts +78 -0
  10. package/src/core/camera-manager.ts +813 -0
  11. package/src/core/config.ts +305 -0
  12. package/src/core/errors.ts +174 -0
  13. package/src/core/event-emitter.test.ts +42 -0
  14. package/src/core/event-emitter.ts +110 -0
  15. package/src/core/loading-state.test.ts +67 -0
  16. package/src/core/loading-state.ts +156 -0
  17. package/src/core/logger.test.ts +49 -0
  18. package/src/core/logger.ts +549 -0
  19. package/src/core/module-manager.ts +163 -0
  20. package/src/core/plugin-manager.ts +429 -0
  21. package/src/core/resource-manager.ts +762 -0
  22. package/src/core/result.ts +163 -0
  23. package/src/core/scanner-factory.ts +236 -0
  24. package/src/index.ts +117 -939
  25. package/src/interfaces/external-types.ts +200 -0
  26. package/src/interfaces/face-detection.ts +309 -0
  27. package/src/interfaces/scanner-module.ts +384 -0
  28. package/src/modules/face/face-detector.ts +988 -0
  29. package/src/modules/face/index.ts +208 -0
  30. package/src/modules/face/liveness-detector.ts +908 -0
  31. package/src/modules/face/types.ts +133 -0
  32. package/src/{id-recognition → modules/id-card}/anti-fake-detector.ts +274 -240
  33. package/src/modules/id-card/id-card-detector.ts +474 -0
  34. package/src/modules/id-card/index.ts +425 -0
  35. package/src/{id-recognition → modules/id-card}/ocr-processor.ts +149 -92
  36. package/src/modules/id-card/ocr-worker.ts +259 -0
  37. package/src/modules/id-card/types.ts +178 -0
  38. package/src/modules/qrcode/index.ts +175 -0
  39. package/src/modules/qrcode/qr-code-scanner.ts +231 -0
  40. package/src/modules/qrcode/types.ts +169 -0
  41. package/src/types/common.test.ts +99 -0
  42. package/src/types/common.ts +166 -0
  43. package/src/types/tesseract.d.ts +265 -22
  44. package/src/utils/camera.test.ts +30 -0
  45. package/src/utils/camera.ts +4 -1
  46. package/src/utils/error-handler.test.ts +137 -0
  47. package/src/utils/error-handler.ts +110 -0
  48. package/src/utils/image-processing.ts +68 -49
  49. package/src/utils/index.test.ts +186 -0
  50. package/src/utils/index.ts +429 -0
  51. package/src/utils/performance.ts +168 -131
  52. package/src/utils/resource-manager.ts +65 -146
  53. package/src/utils/retry.test.ts +142 -0
  54. package/src/utils/retry.ts +282 -0
  55. package/src/utils/types.ts +90 -2
  56. package/src/utils/utils.test.ts +171 -0
  57. package/src/utils/worker.ts +123 -84
  58. package/src/version.ts +11 -0
  59. package/tools/scaffold.js +543 -0
  60. package/dist/id-scanner-core.esm.js +0 -11349
  61. package/dist/id-scanner-core.js +0 -11361
  62. package/dist/id-scanner-core.min.js +0 -1
  63. package/dist/id-scanner-ocr.esm.js +0 -2319
  64. package/dist/id-scanner-ocr.js +0 -2328
  65. package/dist/id-scanner-ocr.min.js +0 -1
  66. package/dist/id-scanner-qr.esm.js +0 -1296
  67. package/dist/id-scanner-qr.js +0 -1305
  68. package/dist/id-scanner-qr.min.js +0 -1
  69. package/dist/id-scanner.js +0 -4561
  70. package/dist/id-scanner.min.js +0 -1
  71. package/src/core.ts +0 -138
  72. package/src/demo/demo.ts +0 -204
  73. package/src/id-recognition/data-extractor.ts +0 -262
  74. package/src/id-recognition/id-detector.ts +0 -510
  75. package/src/id-recognition/ocr-worker.ts +0 -156
  76. package/src/index-umd.ts +0 -477
  77. package/src/ocr-module.ts +0 -187
  78. package/src/qr-module.ts +0 -179
  79. package/src/scanner/barcode-scanner.ts +0 -251
  80. package/src/scanner/qr-scanner.ts +0 -167
@@ -0,0 +1,549 @@
1
+ /**
2
+ * @file 日志系统
3
+ * @description 提供统一的日志记录与管理功能
4
+ * @module core/logger
5
+ */
6
+
7
+ import { ConfigManager } from './config';
8
+
9
+ /**
10
+ * 日志级别枚举
11
+ */
12
+ export enum LogLevel {
13
+ DEBUG = 'debug',
14
+ INFO = 'info',
15
+ WARN = 'warn',
16
+ ERROR = 'error'
17
+ }
18
+
19
+ /**
20
+ * 日志条目接口
21
+ */
22
+ export interface LogEntry {
23
+ /** 日志级别 */
24
+ level: LogLevel;
25
+ /** 日志标签 */
26
+ tag: string;
27
+ /** 日志消息 */
28
+ message: string;
29
+ /** 时间戳 */
30
+ timestamp: number;
31
+ /** 额外数据 */
32
+ data?: any;
33
+ /** 错误 */
34
+ error?: Error;
35
+ }
36
+
37
+ /**
38
+ * 日志处理器接口
39
+ */
40
+ export interface LogHandler {
41
+ /**
42
+ * 处理日志条目
43
+ * @param entry 日志条目
44
+ */
45
+ handle(entry: LogEntry): void;
46
+ }
47
+
48
+ /**
49
+ * 控制台日志处理器
50
+ * 将日志输出到浏览器控制台
51
+ */
52
+ export class ConsoleLogHandler implements LogHandler {
53
+ /**
54
+ * 处理日志条目
55
+ * @param entry 日志条目
56
+ */
57
+ handle(entry: LogEntry): void {
58
+ const timestamp = new Date(entry.timestamp).toISOString();
59
+ const prefix = `[${timestamp}] [${entry.level.toUpperCase()}] [${entry.tag}]`;
60
+
61
+ switch (entry.level) {
62
+ case LogLevel.DEBUG:
63
+ console.debug(prefix, entry.message, entry.error || '');
64
+ break;
65
+ case LogLevel.INFO:
66
+ console.info(prefix, entry.message, entry.error || '');
67
+ break;
68
+ case LogLevel.WARN:
69
+ console.warn(prefix, entry.message, entry.error || '');
70
+ break;
71
+ case LogLevel.ERROR:
72
+ console.error(prefix, entry.message, entry.error || '');
73
+ break;
74
+ default:
75
+ // 输出什么也不做
76
+ }
77
+ }
78
+ }
79
+
80
+ /**
81
+ * 内存日志处理器
82
+ * 将日志保存在内存中,用于后续分析或显示
83
+ */
84
+ export class MemoryLogHandler implements LogHandler {
85
+ /** 日志条目数组 */
86
+ private entries: LogEntry[] = [];
87
+ /** 最大日志条目数 */
88
+ private maxEntries: number;
89
+
90
+ /**
91
+ * 构造函数
92
+ * @param maxEntries 最大日志条目数,默认为1000
93
+ */
94
+ constructor(maxEntries: number = 1000) {
95
+ this.maxEntries = maxEntries;
96
+ }
97
+
98
+ /**
99
+ * 处理日志条目
100
+ * @param entry 日志条目
101
+ */
102
+ handle(entry: LogEntry): void {
103
+ this.entries.push(entry);
104
+
105
+ // 如果超过最大条目数,移除最老的
106
+ if (this.entries.length > this.maxEntries) {
107
+ this.entries.shift();
108
+ }
109
+ }
110
+
111
+ /**
112
+ * 获取所有日志条目
113
+ */
114
+ getEntries(): LogEntry[] {
115
+ return [...this.entries];
116
+ }
117
+
118
+ /**
119
+ * 根据级别过滤日志条目
120
+ * @param level 日志级别
121
+ */
122
+ getEntriesByLevel(level: LogLevel): LogEntry[] {
123
+ return this.entries.filter(entry => entry.level === level);
124
+ }
125
+
126
+ /**
127
+ * 根据标签过滤日志条目
128
+ * @param tag 日志标签
129
+ */
130
+ getEntriesByTag(tag: string): LogEntry[] {
131
+ return this.entries.filter(entry => entry.tag === tag);
132
+ }
133
+
134
+ /**
135
+ * 清空日志
136
+ */
137
+ clear(): void {
138
+ this.entries = [];
139
+ }
140
+ }
141
+
142
+ /**
143
+ * 远程日志处理器
144
+ * 将日志发送到远程服务器
145
+ */
146
+ export class RemoteLogHandler implements LogHandler {
147
+ /** 远程服务器URL */
148
+ private endpoint: string;
149
+ /** 批量发送的队列 */
150
+ private queue: LogEntry[] = [];
151
+ /** 最大队列长度 */
152
+ private maxQueueSize: number;
153
+ /** 发送间隔(毫秒) */
154
+ private flushInterval: number;
155
+ /** 定时发送的计时器ID */
156
+ private timerId: number | null = null;
157
+
158
+ /**
159
+ * 构造函数
160
+ * @param endpoint 远程服务器URL
161
+ * @param maxQueueSize 最大队列长度,默认为100
162
+ * @param flushInterval 发送间隔(毫秒),默认为5000
163
+ */
164
+ constructor(endpoint: string, maxQueueSize: number = 100, flushInterval: number = 5000) {
165
+ this.endpoint = endpoint;
166
+ this.maxQueueSize = maxQueueSize;
167
+ this.flushInterval = flushInterval;
168
+
169
+ // 设置定时发送
170
+ this.startTimer();
171
+
172
+ // 页面卸载前尝试发送剩余日志
173
+ window.addEventListener('beforeunload', () => {
174
+ this.flush();
175
+ });
176
+ }
177
+
178
+ /**
179
+ * 处理日志条目
180
+ * @param entry 日志条目
181
+ */
182
+ handle(entry: LogEntry): void {
183
+ // 只处理INFO以上级别的日志
184
+ if (entry.level >= LogLevel.INFO) {
185
+ this.queue.push(entry);
186
+
187
+ // 如果队列满了,立即发送
188
+ if (this.queue.length >= this.maxQueueSize) {
189
+ this.flush();
190
+ }
191
+ }
192
+ }
193
+
194
+ /**
195
+ * 发送队列中的日志
196
+ */
197
+ flush(): void {
198
+ if (this.queue.length === 0) return;
199
+
200
+ const entriesToSend = [...this.queue];
201
+ this.queue = [];
202
+
203
+ try {
204
+ fetch(this.endpoint, {
205
+ method: 'POST',
206
+ headers: {
207
+ 'Content-Type': 'application/json'
208
+ },
209
+ body: JSON.stringify(entriesToSend),
210
+ // 不等待响应,避免阻塞
211
+ keepalive: true
212
+ }).catch(err => {
213
+ console.error('Failed to send logs to remote server:', err);
214
+ // 失败时把日志放回队列,但防止无限增长
215
+ if (this.queue.length < this.maxQueueSize) {
216
+ this.queue = [...entriesToSend.slice(0, this.maxQueueSize - this.queue.length), ...this.queue];
217
+ }
218
+ });
219
+ } catch (error) {
220
+ console.error('Error sending logs:', error);
221
+ }
222
+ }
223
+
224
+ /**
225
+ * 开始定时发送
226
+ */
227
+ startTimer(): void {
228
+ if (this.timerId !== null) return;
229
+
230
+ this.timerId = window.setInterval(() => {
231
+ this.flush();
232
+ }, this.flushInterval);
233
+ }
234
+
235
+ /**
236
+ * 停止定时发送
237
+ */
238
+ stopTimer(): void {
239
+ if (this.timerId !== null) {
240
+ window.clearInterval(this.timerId);
241
+ this.timerId = null;
242
+ }
243
+ }
244
+ }
245
+
246
+ /**
247
+ * 日志管理类
248
+ * 中央日志管理器,提供统一的日志记录接口
249
+ */
250
+ export class Logger {
251
+ /** 单例实例 */
252
+ private static instance: Logger;
253
+ /** 配置管理器 */
254
+ private config: ConfigManager;
255
+ /** 日志处理器 */
256
+ private handlers: LogHandler[] = [];
257
+ /** 默认标签 */
258
+ private defaultTag: string = 'IDScanner';
259
+ /** 日志级别 */
260
+ private logLevel: LogLevel = LogLevel.INFO;
261
+
262
+ /**
263
+ * 私有构造函数,防止直接实例化
264
+ */
265
+ private constructor() {
266
+ this.config = ConfigManager.getInstance();
267
+
268
+ // 默认添加控制台处理器
269
+ this.addHandler(new ConsoleLogHandler());
270
+
271
+ // 监听配置变化
272
+ this.config.onConfigChange('logLevel', (level: LogLevel) => {
273
+ this.debug('Logger', `Log level changed to ${level}`);
274
+ });
275
+ }
276
+
277
+ /**
278
+ * 获取单例实例
279
+ */
280
+ public static getInstance(): Logger {
281
+ if (!Logger.instance) {
282
+ Logger.instance = new Logger();
283
+ }
284
+ return Logger.instance;
285
+ }
286
+
287
+ /**
288
+ * 添加日志处理器
289
+ * @param handler 日志处理器
290
+ */
291
+ addHandler(handler: LogHandler): void {
292
+ this.handlers.push(handler);
293
+ }
294
+
295
+ /**
296
+ * 移除日志处理器
297
+ * @param handler 要移除的处理器
298
+ */
299
+ removeHandler(handler: LogHandler): void {
300
+ const index = this.handlers.indexOf(handler);
301
+ if (index !== -1) {
302
+ this.handlers.splice(index, 1);
303
+ }
304
+ }
305
+
306
+ /**
307
+ * 移除所有处理器
308
+ */
309
+ clearHandlers(): void {
310
+ this.handlers = [];
311
+ }
312
+
313
+ /**
314
+ * 设置默认标签
315
+ * @param tag 默认标签
316
+ */
317
+ setDefaultTag(tag: string): void {
318
+ this.defaultTag = tag;
319
+ }
320
+
321
+ /**
322
+ * 记录调试级别日志
323
+ * @param tag 标签
324
+ * @param message 消息
325
+ * @param error 错误
326
+ */
327
+ debug(tag: string, message: string, error?: Error): void {
328
+ this.log(LogLevel.DEBUG, tag, message, error);
329
+ }
330
+
331
+ /**
332
+ * 记录信息级别日志
333
+ * @param tag 标签
334
+ * @param message 消息
335
+ * @param error 错误
336
+ */
337
+ info(tag: string, message: string, error?: Error): void {
338
+ this.log(LogLevel.INFO, tag, message, error);
339
+ }
340
+
341
+ /**
342
+ * 记录警告级别日志
343
+ * @param tag 标签
344
+ * @param message 消息
345
+ * @param error 错误
346
+ */
347
+ warn(tag: string, message: string, error?: Error): void {
348
+ this.log(LogLevel.WARN, tag, message, error);
349
+ }
350
+
351
+ /**
352
+ * 记录错误级别日志
353
+ * @param tag 标签
354
+ * @param message 消息
355
+ * @param error 错误
356
+ */
357
+ error(tag: string, message: string, error?: Error): void {
358
+ this.log(LogLevel.ERROR, tag, message, error);
359
+ }
360
+
361
+ /**
362
+ * 创建标记了特定标签的日志记录器
363
+ * @param tag 标签
364
+ */
365
+ getTaggedLogger(tag: string): TaggedLogger {
366
+ return new TaggedLogger(this, tag);
367
+ }
368
+
369
+ /**
370
+ * 记录日志
371
+ * @param level 日志级别
372
+ * @param tag 标签
373
+ * @param message 消息
374
+ * @param error 错误
375
+ */
376
+ private log(level: LogLevel, tag: string, message: string, error?: Error): void {
377
+ // 检查日志级别
378
+ const levelValue = this.getLevelValue(level);
379
+ const currentLevelValue = this.getLevelValue(this.logLevel);
380
+
381
+ if (levelValue < currentLevelValue) {
382
+ return;
383
+ }
384
+
385
+ // 创建日志条目
386
+ const entry: LogEntry = {
387
+ timestamp: Date.now(),
388
+ level: level,
389
+ tag: tag || this.defaultTag,
390
+ message,
391
+ error
392
+ };
393
+
394
+ // 分发到所有处理程序
395
+ for (const handler of this.handlers) {
396
+ try {
397
+ handler.handle(entry);
398
+ } catch (handlerError) {
399
+ console.error(`[Logger] 处理程序错误:`, handlerError);
400
+ }
401
+ }
402
+
403
+ // 如果没有处理程序,使用控制台
404
+ if (this.handlers.length === 0) {
405
+ this.consoleOutput(entry);
406
+ }
407
+ }
408
+
409
+ /**
410
+ * 控制台输出
411
+ * @param entry 日志条目
412
+ */
413
+ private consoleOutput(entry: LogEntry): void {
414
+ const timestamp = new Date(entry.timestamp).toISOString();
415
+ const prefix = `[${timestamp}] [${entry.level.toUpperCase()}] [${entry.tag}]`;
416
+
417
+ switch (entry.level) {
418
+ case LogLevel.DEBUG:
419
+ console.debug(`${prefix} ${entry.message}`, entry.error || '');
420
+ break;
421
+ case LogLevel.INFO:
422
+ console.info(`${prefix} ${entry.message}`, entry.error || '');
423
+ break;
424
+ case LogLevel.WARN:
425
+ console.warn(`${prefix} ${entry.message}`, entry.error || '');
426
+ break;
427
+ case LogLevel.ERROR:
428
+ console.error(`${prefix} ${entry.message}`, entry.error || '');
429
+ break;
430
+ }
431
+ }
432
+
433
+ /**
434
+ * 获取日志级别值
435
+ * @param level 日志级别
436
+ */
437
+ private getLevelValue(level: LogLevel): number {
438
+ switch (level) {
439
+ case LogLevel.DEBUG:
440
+ return 0;
441
+ case LogLevel.INFO:
442
+ return 1;
443
+ case LogLevel.WARN:
444
+ return 2;
445
+ case LogLevel.ERROR:
446
+ return 3;
447
+ default:
448
+ return 1; // 默认INFO级别
449
+ }
450
+ }
451
+
452
+ /**
453
+ * 设置日志级别
454
+ * @param level 日志级别
455
+ */
456
+ public setLevel(level: LogLevel | string): void {
457
+ if (typeof level === 'string') {
458
+ switch (level) {
459
+ case 'debug':
460
+ this.logLevel = LogLevel.DEBUG;
461
+ break;
462
+ case 'info':
463
+ this.logLevel = LogLevel.INFO;
464
+ break;
465
+ case 'warn':
466
+ this.logLevel = LogLevel.WARN;
467
+ break;
468
+ case 'error':
469
+ this.logLevel = LogLevel.ERROR;
470
+ break;
471
+ default:
472
+ this.logLevel = LogLevel.INFO;
473
+ }
474
+ } else {
475
+ this.logLevel = level;
476
+ }
477
+
478
+ this.debug('Logger', `日志级别已设置为 ${this.logLevel}`);
479
+ }
480
+
481
+ /**
482
+ * 获取当前日志级别
483
+ * @returns 当前日志级别
484
+ */
485
+ public getLevel(): LogLevel {
486
+ return this.logLevel;
487
+ }
488
+ }
489
+
490
+ /**
491
+ * 带标签的日志记录器
492
+ * 提供特定标签的简易日志接口
493
+ */
494
+ export class TaggedLogger {
495
+ /** 所属的主日志记录器 */
496
+ private logger: Logger;
497
+ /** 标签 */
498
+ private tag: string;
499
+
500
+ /**
501
+ * 构造函数
502
+ * @param logger 所属的主日志记录器
503
+ * @param tag 标签
504
+ */
505
+ constructor(logger: Logger, tag: string) {
506
+ this.logger = logger;
507
+ this.tag = tag;
508
+ }
509
+
510
+ /**
511
+ * 记录调试级别日志
512
+ * @param message 消息
513
+ * @param error 错误
514
+ */
515
+ debug(message: string, error?: Error): void {
516
+ this.logger.debug(this.tag, message, error);
517
+ }
518
+
519
+ /**
520
+ * 记录信息级别日志
521
+ * @param message 消息
522
+ * @param error 错误
523
+ */
524
+ info(message: string, error?: Error): void {
525
+ this.logger.info(this.tag, message, error);
526
+ }
527
+
528
+ /**
529
+ * 记录警告级别日志
530
+ * @param message 消息
531
+ * @param error 错误
532
+ */
533
+ warn(message: string, error?: Error): void {
534
+ this.logger.warn(this.tag, message, error);
535
+ }
536
+
537
+ /**
538
+ * 记录错误级别日志
539
+ * @param message 消息
540
+ * @param error 错误
541
+ */
542
+ error(message: string, error?: Error): void {
543
+ this.logger.error(this.tag, message, error);
544
+ }
545
+ }
546
+
547
+ /**
548
+ * 日志级别枚举
549
+ */
@@ -0,0 +1,163 @@
1
+ /**
2
+ * @file 模块管理器
3
+ * @description 统一管理库的各功能模块,提供模块的注册、初始化和卸载功能
4
+ * @module core/module-manager
5
+ */
6
+
7
+ import { Logger } from './logger';
8
+ import { EventEmitter } from './event-emitter';
9
+ import { VERSION } from '../version';
10
+
11
+ /**
12
+ * 模块接口
13
+ * 所有功能模块必须实现此接口
14
+ */
15
+ export interface Module {
16
+ /** 模块名称 */
17
+ name: string;
18
+
19
+ /** 模块版本 */
20
+ version: string;
21
+
22
+ /** 模块是否已初始化 */
23
+ isInitialized: boolean;
24
+
25
+ /** 初始化模块 */
26
+ initialize(): Promise<void>;
27
+
28
+ /** 释放模块资源 */
29
+ dispose(): Promise<void>;
30
+ }
31
+
32
+ /**
33
+ * 模块配置接口
34
+ */
35
+ export interface ModuleOptions {
36
+ /** 是否启用该模块 */
37
+ enabled?: boolean;
38
+
39
+ /** 模块特定配置 */
40
+ [key: string]: any;
41
+ }
42
+
43
+ /**
44
+ * 模块管理器类
45
+ * 负责管理所有功能模块的生命周期
46
+ */
47
+ export class ModuleManager extends EventEmitter {
48
+ private static instance: ModuleManager;
49
+ private modules: Map<string, Module> = new Map();
50
+ private logger: Logger;
51
+ private initialized = false;
52
+
53
+ /**
54
+ * 获取模块管理器单例
55
+ */
56
+ public static getInstance(): ModuleManager {
57
+ if (!ModuleManager.instance) {
58
+ ModuleManager.instance = new ModuleManager();
59
+ }
60
+ return ModuleManager.instance;
61
+ }
62
+
63
+ /**
64
+ * 私有构造函数,确保单例模式
65
+ */
66
+ private constructor() {
67
+ super();
68
+ this.logger = Logger.getInstance();
69
+ this.logger.debug('ModuleManager', `初始化模块管理器 v${VERSION}`);
70
+ }
71
+
72
+ /**
73
+ * 注册模块
74
+ * @param module 要注册的模块
75
+ * @returns 模块管理器实例,支持链式调用
76
+ */
77
+ public register(module: Module): ModuleManager {
78
+ if (this.modules.has(module.name)) {
79
+ this.logger.warn('ModuleManager', `模块 "${module.name}" 已经注册,将被覆盖`);
80
+ }
81
+
82
+ this.modules.set(module.name, module);
83
+ this.logger.debug('ModuleManager', `注册模块: ${module.name} v${module.version}`);
84
+ this.emit('module:registered', { name: module.name });
85
+
86
+ return this;
87
+ }
88
+
89
+ /**
90
+ * 获取模块
91
+ * @param name 模块名称
92
+ * @returns 模块实例
93
+ */
94
+ public getModule<T extends Module>(name: string): T | undefined {
95
+ return this.modules.get(name) as T | undefined;
96
+ }
97
+
98
+ /**
99
+ * 初始化所有注册的模块
100
+ */
101
+ public async initialize(): Promise<void> {
102
+ if (this.initialized) {
103
+ return;
104
+ }
105
+
106
+ this.logger.debug('ModuleManager', '开始初始化所有模块...');
107
+
108
+ for (const [name, module] of this.modules.entries()) {
109
+ try {
110
+ this.logger.debug('ModuleManager', `初始化模块: ${name}`);
111
+ await module.initialize();
112
+ this.emit('module:initialized', { name });
113
+ this.logger.debug('ModuleManager', `模块 ${name} 初始化完成`);
114
+ } catch (error) {
115
+ this.logger.error('ModuleManager', `模块 ${name} 初始化失败`, error instanceof Error ? error : undefined);
116
+ this.emit('module:error', { name, error });
117
+ throw new Error(`模块 ${name} 初始化失败: ${error instanceof Error ? error.message : String(error)}`);
118
+ }
119
+ }
120
+
121
+ this.initialized = true;
122
+ this.logger.debug('ModuleManager', '所有模块初始化完成');
123
+ this.emit('modules:initialized');
124
+ }
125
+
126
+ /**
127
+ * 卸载所有模块并释放资源
128
+ */
129
+ public async dispose(): Promise<void> {
130
+ this.logger.debug('ModuleManager', '开始释放所有模块资源...');
131
+
132
+ for (const [name, module] of this.modules.entries()) {
133
+ try {
134
+ this.logger.debug('ModuleManager', `释放模块资源: ${name}`);
135
+ await module.dispose();
136
+ this.emit('module:disposed', { name });
137
+ } catch (error) {
138
+ this.logger.error('ModuleManager', `模块 ${name} 资源释放失败`, error instanceof Error ? error : undefined);
139
+ this.emit('module:error', { name, error });
140
+ }
141
+ }
142
+
143
+ this.modules.clear();
144
+ this.initialized = false;
145
+ this.logger.debug('ModuleManager', '所有模块资源已释放');
146
+ this.emit('modules:disposed');
147
+ }
148
+
149
+ /**
150
+ * 获取所有已注册的模块名称
151
+ */
152
+ public getRegisteredModules(): string[] {
153
+ return Array.from(this.modules.keys());
154
+ }
155
+
156
+ /**
157
+ * 检查模块是否已注册
158
+ * @param name 模块名称
159
+ */
160
+ public hasModule(name: string): boolean {
161
+ return this.modules.has(name);
162
+ }
163
+ }