id-scanner-lib 1.7.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,251 +3,95 @@ import imageCompression from 'browser-image-compression';
3
3
  import jsQR from 'jsqr';
4
4
 
5
5
  /**
6
- * @file 配置管理器
7
- * @description 提供全局配置管理功能
6
+ * @file 配置管理器 + Scanner 配置
7
+ * @description 提供全局配置管理功能 + Scanner v2.0 配置接口
8
8
  * @module core/config
9
9
  */
10
- /**
11
- * 配置管理器
12
- * 负责存储和管理应用程序的配置
13
- */
10
+ // ============================================================
11
+ // 原有 ConfigManager(保持向后兼容)
12
+ // ============================================================
14
13
  class ConfigManager {
15
- /**
16
- * 私有构造函数
17
- */
18
14
  constructor() {
19
- /** 配置存储 */
20
15
  this.config = {};
21
- /** 配置变更回调 */
22
16
  this.changeCallbacks = new Map();
23
- /** 初始化状态 */
24
17
  this.initialized = false;
25
- // 设置默认配置
26
18
  this._resetDefaults();
27
19
  }
28
- /**
29
- * 获取单例实例
30
- */
31
20
  static getInstance() {
32
21
  if (!ConfigManager.instance) {
33
22
  ConfigManager.instance = new ConfigManager();
34
23
  }
35
24
  return ConfigManager.instance;
36
25
  }
37
- /**
38
- * 重置单例实例(主要用于测试)
39
- */
40
26
  static resetInstance() {
41
27
  ConfigManager.instance = undefined;
42
28
  }
43
- /**
44
- * 重置为默认配置
45
- */
46
29
  _resetDefaults() {
47
30
  this.config = {
48
31
  debug: false,
49
32
  logLevel: 'info',
50
- camera: {
51
- resolution: {
52
- width: 1280,
53
- height: 720
54
- },
55
- frameRate: 30,
56
- facingMode: 'environment'
33
+ modelPath: '/models',
34
+ maxRetries: 3,
35
+ retryDelay: 1000,
36
+ detectionInterval: 100,
37
+ face: {
38
+ enabled: true,
39
+ confidenceThreshold: 0.5,
40
+ maxFaces: 10,
41
+ },
42
+ idCard: {
43
+ enabled: false,
44
+ },
45
+ qr: {
46
+ enabled: false,
57
47
  },
58
- performance: {
59
- useCache: true
60
- }
61
48
  };
62
49
  this.initialized = true;
63
50
  }
64
- /**
65
- * 获取配置值
66
- * @param key 配置键,支持点号分隔的路径
67
- * @param defaultValue 默认值
68
- */
69
51
  get(key, defaultValue) {
70
- const value = this.getNestedValue(this.config, key);
71
- return (value !== undefined) ? value : defaultValue;
52
+ const keys = key.split('.');
53
+ let value = this.config;
54
+ for (const k of keys) {
55
+ value = value?.[k];
56
+ }
57
+ return (value !== undefined ? value : defaultValue);
72
58
  }
73
- /**
74
- * 设置配置值
75
- * @param key 配置键,支持点号分隔的路径
76
- * @param value 配置值
77
- */
78
59
  set(key, value) {
79
- const oldValue = this.get(key);
80
- // 如果值相同,不做任何事
81
- if (oldValue === value) {
82
- return;
60
+ const keys = key.split('.');
61
+ let target = this.config;
62
+ for (let i = 0; i < keys.length - 1; i++) {
63
+ if (!target[keys[i]])
64
+ target[keys[i]] = {};
65
+ target = target[keys[i]];
66
+ }
67
+ const oldValue = target[keys[keys.length - 1]];
68
+ target[keys[keys.length - 1]] = value;
69
+ const callbacks = this.changeCallbacks.get(key);
70
+ if (callbacks) {
71
+ callbacks.forEach(cb => cb(value, oldValue));
83
72
  }
84
- this.setNestedValue(this.config, key, value);
85
- // 触发变更回调
86
- this.triggerChangeCallbacks(key, value, oldValue);
87
- }
88
- /**
89
- * 批量更新配置
90
- * @param config 配置对象
91
- */
92
- updateConfig(config) {
93
- Object.entries(config).forEach(([key, value]) => {
94
- this.set(key, value);
95
- });
96
- }
97
- /**
98
- * 重置为默认配置
99
- */
100
- reset() {
101
- const oldConfig = { ...this.config };
102
- // 使用私有 reset 方法重建默认配置
103
- this.config = {
104
- debug: false,
105
- logLevel: 'info',
106
- camera: {
107
- resolution: {
108
- width: 1280,
109
- height: 720
110
- },
111
- frameRate: 30,
112
- facingMode: 'environment'
113
- },
114
- performance: {
115
- useCache: true
116
- }
117
- };
118
- // 触发所有回调
119
- Object.keys(oldConfig).forEach(key => {
120
- this.triggerChangeCallbacks(key, this.get(key), oldConfig[key]);
121
- });
122
73
  }
123
- /**
124
- * 注册配置变更回调
125
- * @param key 配置键
126
- * @param callback 回调函数
127
- */
128
- onConfigChange(key, callback) {
74
+ onChange(key, callback) {
129
75
  if (!this.changeCallbacks.has(key)) {
130
76
  this.changeCallbacks.set(key, []);
131
77
  }
132
78
  this.changeCallbacks.get(key).push(callback);
133
79
  }
134
- /**
135
- * 移除配置变更回调
136
- * @param key 配置键
137
- * @param callback 特定回调函数,如不提供则移除所有
138
- */
139
- offConfigChange(key, callback) {
140
- if (!this.changeCallbacks.has(key)) {
141
- return;
142
- }
143
- if (callback) {
144
- // 移除特定回调
145
- const callbacks = this.changeCallbacks.get(key);
80
+ /** @deprecated Use onChange instead */
81
+ onConfigChange(key, callback) {
82
+ this.onChange(key, callback);
83
+ }
84
+ removeChangeCallback(key, callback) {
85
+ const callbacks = this.changeCallbacks.get(key);
86
+ if (callbacks) {
146
87
  const index = callbacks.indexOf(callback);
147
- if (index !== -1) {
88
+ if (index > -1)
148
89
  callbacks.splice(index, 1);
149
- }
150
- // 如果没有回调,删除键
151
- if (callbacks.length === 0) {
152
- this.changeCallbacks.delete(key);
153
- }
154
- }
155
- else {
156
- // 移除所有回调
157
- this.changeCallbacks.delete(key);
158
90
  }
159
91
  }
160
- /**
161
- * 获取嵌套值
162
- * @param obj 对象
163
- * @param path 路径
164
- */
165
- getNestedValue(obj, path) {
166
- // 处理根路径
167
- if (!path) {
168
- return obj;
169
- }
170
- // 处理嵌套路径
171
- const parts = path.split('.');
172
- let current = obj;
173
- for (const part of parts) {
174
- if (current === undefined || current === null) {
175
- return undefined;
176
- }
177
- current = current[part];
178
- }
179
- return current;
180
- }
181
- /**
182
- * 设置嵌套值
183
- * @param obj 对象
184
- * @param path 路径
185
- * @param value 值
186
- */
187
- setNestedValue(obj, path, value) {
188
- // 处理根路径
189
- if (!path) {
190
- return;
191
- }
192
- // 处理嵌套路径
193
- const parts = path.split('.');
194
- let current = obj;
195
- // 遍历路径,直到倒数第二部分
196
- for (let i = 0; i < parts.length - 1; i++) {
197
- const part = parts[i];
198
- // 如果不存在,创建新对象
199
- if (current[part] === undefined || current[part] === null || typeof current[part] !== 'object') {
200
- current[part] = {};
201
- }
202
- current = current[part];
203
- }
204
- // 设置最终值
205
- current[parts[parts.length - 1]] = value;
206
- }
207
- /**
208
- * 触发变更回调
209
- * @param key 配置键
210
- * @param value 新值
211
- * @param oldValue 旧值
212
- */
213
- triggerChangeCallbacks(key, value, oldValue) {
214
- // 触发特定键的回调
215
- if (this.changeCallbacks.has(key)) {
216
- const callbacks = this.changeCallbacks.get(key);
217
- callbacks.forEach(callback => {
218
- try {
219
- callback(value, oldValue);
220
- }
221
- catch (error) {
222
- console.error(`Error in config change callback for key ${key}:`, error);
223
- }
224
- });
225
- }
226
- // 触发父路径的回调
227
- const parts = key.split('.');
228
- while (parts.length > 1) {
229
- parts.pop();
230
- const parentKey = parts.join('.');
231
- if (this.changeCallbacks.has(parentKey)) {
232
- const parentValue = this.get(parentKey);
233
- this.changeCallbacks.get(parentKey).forEach(callback => {
234
- try {
235
- callback(parentValue, parentValue);
236
- }
237
- catch (error) {
238
- console.error(`Error in config change callback for parent key ${parentKey}:`, error);
239
- }
240
- });
241
- }
242
- }
243
- }
244
- /**
245
- * 检查模块是否启用
246
- * @param moduleName 模块名称
247
- */
248
- isModuleEnabled(moduleName) {
249
- const key = `modules.${moduleName}.enabled`;
250
- return this.get(key) ?? false;
92
+ reset() {
93
+ this.config = {};
94
+ this._resetDefaults();
251
95
  }
252
96
  }
253
97
 
@@ -4774,157 +4618,106 @@ function createLoadingStateManager() {
4774
4618
  }
4775
4619
 
4776
4620
  /**
4777
- * @file 错误处理模块
4778
- * @description 定义ID-Scanner-Lib的错误类层次结构
4621
+ * @file Scanner Errors
4622
+ * @description Error classes for Scanner
4779
4623
  * @module core/errors
4780
4624
  */
4781
4625
  /**
4782
- * ID-Scanner-Lib 基础错误类
4783
- * 所有库特定错误的基类
4626
+ * Scanner specific error
4784
4627
  */
4785
- class IDScannerError extends Error {
4628
+ class ScannerError extends Error {
4786
4629
  /**
4787
- * 构造函数
4788
- * @param message 错误消息
4789
- * @param options 错误选项
4630
+ * Create a ScannerError
4631
+ * @param message Error message
4632
+ * @param code Error code
4633
+ * @param module Module name
4790
4634
  */
4791
- constructor(message, options) {
4635
+ constructor(message, code, module) {
4792
4636
  super(message);
4793
- // 设置错误名称
4794
- this.name = this.constructor.name;
4795
- // 设置错误代码
4796
- this.code = options?.code || 'UNKNOWN_ERROR';
4797
- // 设置错误原因
4798
- this.cause = options?.cause;
4799
- // 捕获堆栈 (Node.js专有,浏览器环境忽略)
4800
- if (typeof Error.captureStackTrace === 'function') {
4801
- Error.captureStackTrace(this, this.constructor);
4802
- }
4637
+ this.name = 'ScannerError';
4638
+ this.code = code;
4639
+ this.module = module;
4803
4640
  }
4804
4641
  }
4805
4642
  /**
4806
- * 初始化错误
4807
- * 当库初始化失败时抛出
4643
+ * Camera access error
4808
4644
  */
4809
- class InitializationError extends IDScannerError {
4810
- constructor(message, details) {
4811
- super(`初始化失败: ${message}${details ? ` (${details})` : ''}`, { code: 'INIT_FAILED' });
4812
- this.name = 'InitializationError';
4645
+ class CameraAccessError extends Error {
4646
+ constructor(message = 'Camera access denied') {
4647
+ super(message);
4648
+ this.name = 'CameraAccessError';
4813
4649
  }
4814
4650
  }
4815
4651
  /**
4816
- * 设备错误
4817
- * 当访问硬件设备(如摄像头)失败时抛出
4652
+ * Device error
4818
4653
  */
4819
- class DeviceError extends IDScannerError {
4820
- constructor(message) {
4821
- super(`设备错误: ${message}`, { code: 'DEVICE_ERROR' });
4654
+ class DeviceError extends Error {
4655
+ constructor(message = 'Device error') {
4656
+ super(message);
4822
4657
  this.name = 'DeviceError';
4823
4658
  }
4824
4659
  }
4825
4660
  /**
4826
- * 摄像头访问错误
4827
- * 当无法访问或启动摄像头时抛出
4661
+ * Resource load error
4828
4662
  */
4829
- class CameraAccessError extends IDScannerError {
4830
- constructor(message, options) {
4831
- super(`摄像头访问失败: ${message}`, {
4832
- code: options?.code || 'CAMERA_ACCESS_FAILED',
4833
- cause: options?.cause
4834
- });
4835
- this.name = 'CameraAccessError';
4663
+ class ResourceLoadError extends Error {
4664
+ constructor(message = 'Failed to load resource', id) {
4665
+ super(message);
4666
+ this.name = 'ResourceLoadError';
4667
+ this.id = id;
4836
4668
  }
4837
4669
  }
4838
4670
  /**
4839
- * 人脸检测错误
4840
- * 当人脸检测过程失败时抛出
4671
+ * Face detection error
4841
4672
  */
4842
- class FaceDetectionError extends IDScannerError {
4843
- constructor(message) {
4844
- super(`人脸检测失败: ${message}`, { code: 'FACE_DETECTION_FAILED' });
4673
+ class FaceDetectionError extends Error {
4674
+ constructor(message = 'Face detection failed') {
4675
+ super(message);
4845
4676
  this.name = 'FaceDetectionError';
4846
4677
  }
4847
4678
  }
4848
4679
  /**
4849
- * 人脸比对错误
4850
- * 当人脸比对过程失败时抛出
4680
+ * Face comparison error
4851
4681
  */
4852
- class FaceComparisonError extends IDScannerError {
4853
- constructor(message) {
4854
- super(`人脸比对失败: ${message}`, { code: 'FACE_COMPARISON_FAILED' });
4682
+ class FaceComparisonError extends Error {
4683
+ constructor(message = 'Face comparison failed') {
4684
+ super(message);
4855
4685
  this.name = 'FaceComparisonError';
4856
4686
  }
4857
4687
  }
4858
4688
  /**
4859
- * 活体检测错误
4860
- * 当活体检测过程失败时抛出
4861
- */
4862
- class LivenessDetectionError extends IDScannerError {
4863
- constructor(message) {
4864
- super(`活体检测失败: ${message}`, { code: 'LIVENESS_DETECTION_FAILED' });
4865
- this.name = 'LivenessDetectionError';
4866
- }
4867
- }
4868
- /**
4869
- * OCR识别错误
4870
- * 当OCR文字识别失败时抛出
4871
- */
4872
- class OCRProcessingError extends IDScannerError {
4873
- constructor(message) {
4874
- super(`OCR处理失败: ${message}`, { code: 'OCR_PROCESSING_FAILED' });
4875
- this.name = 'OCRProcessingError';
4876
- }
4877
- }
4878
- /**
4879
- * 二维码扫描错误
4880
- * 当二维码扫描失败时抛出
4689
+ * Initialization error
4881
4690
  */
4882
- class QRScanError extends IDScannerError {
4883
- constructor(message) {
4884
- super(`二维码扫描失败: ${message}`, { code: 'QR_SCAN_FAILED' });
4885
- this.name = 'QRScanError';
4886
- }
4887
- }
4888
- /**
4889
- * 身份证检测错误
4890
- * 当身份证检测失败时抛出
4891
- */
4892
- class IDCardDetectionError extends IDScannerError {
4893
- constructor(message) {
4894
- super(`身份证检测失败: ${message}`, { code: 'ID_CARD_DETECTION_FAILED' });
4895
- this.name = 'IDCardDetectionError';
4896
- }
4897
- }
4898
- /**
4899
- * 资源加载错误
4900
- * 当无法加载必要资源(如模型)时抛出
4901
- */
4902
- class ResourceLoadError extends IDScannerError {
4903
- constructor(resource, reason) {
4904
- super(`无法加载资源 ${resource}: ${reason}`, { code: 'RESOURCE_LOAD_FAILED' });
4905
- this.name = 'ResourceLoadError';
4691
+ class InitializationError extends Error {
4692
+ constructor(message = 'Initialization failed') {
4693
+ super(message);
4694
+ this.name = 'InitializationError';
4906
4695
  }
4907
4696
  }
4908
4697
  /**
4909
- * 参数错误
4910
- * 当提供的参数无效时抛出
4698
+ * Liveness detection error
4911
4699
  */
4912
- class InvalidArgumentError extends IDScannerError {
4913
- constructor(paramName, reason) {
4914
- super(`无效的参数 ${paramName}: ${reason}`, { code: 'INVALID_ARGUMENT' });
4915
- this.name = 'InvalidArgumentError';
4700
+ class LivenessDetectionError extends Error {
4701
+ constructor(message = 'Liveness detection failed') {
4702
+ super(message);
4703
+ this.name = 'LivenessDetectionError';
4916
4704
  }
4917
4705
  }
4918
4706
  /**
4919
- * 不支持错误
4920
- * 当尝试使用不支持的功能或当前环境无法使用的功能时抛出
4707
+ * Error codes for Scanner
4921
4708
  */
4922
- class NotSupportedError extends IDScannerError {
4923
- constructor(feature) {
4924
- super(`不支持的功能: ${feature}`, { code: 'NOT_SUPPORTED' });
4925
- this.name = 'NotSupportedError';
4926
- }
4927
- }
4709
+ const ErrorCodes = {
4710
+ /** Scanner not initialized */
4711
+ NOT_INITIALIZED: 'SCANNER_001',
4712
+ /** Module not found */
4713
+ MODULE_NOT_FOUND: 'SCANNER_002',
4714
+ /** Detection failed */
4715
+ DETECTION_FAILED: 'SCANNER_003',
4716
+ /** Camera access denied */
4717
+ CAMERA_ACCESS_DENIED: 'CAMERA_001',
4718
+ /** Camera not available */
4719
+ CAMERA_NOT_AVAILABLE: 'CAMERA_002',
4720
+ };
4928
4721
 
4929
4722
  /* eslint-disable */
4930
4723
  /**
@@ -5025,5 +4818,5 @@ IDScanner.VERSION = VERSION;
5025
4818
  /** 构建日期 */
5026
4819
  IDScanner.BUILD_DATE = BUILD_DATE;
5027
4820
 
5028
- export { BarcodeFormat, CameraAccessError, ConsoleLogHandler, DEFAULT_FORMATS, DeviceError, FaceComparisonError, FaceDetectionError, FaceModule, IDCardDetectionError, IDCardModule, IDCardType, IDScanner, IDScannerError, InitializationError, InvalidArgumentError, LivenessDetectionError, LoadingState, LoadingStateManager, LogLevel, Logger, LoggerLevel, MemoryLogHandler, ModuleManager, NotSupportedError, OCRProcessingError, QRCodeModule, QRScanError, RemoteLogHandler, ResourceLoadError, TaggedLogger, createLoadingStateManager, IDScanner as default };
4821
+ export { BarcodeFormat, CameraAccessError, ConsoleLogHandler, DEFAULT_FORMATS, DeviceError, ErrorCodes, FaceComparisonError, FaceDetectionError, FaceModule, IDCardModule, IDCardType, IDScanner, InitializationError, LivenessDetectionError, LoadingState, LoadingStateManager, LogLevel, Logger, LoggerLevel, MemoryLogHandler, ModuleManager, QRCodeModule, RemoteLogHandler, ResourceLoadError, ScannerError, TaggedLogger, createLoadingStateManager, IDScanner as default };
5029
4822
  //# sourceMappingURL=id-scanner-lib.esm.js.map