UNPKG

id-scanner-lib

Version:

Browser-based ID card, QR code, and face recognition scanner with liveness detection

170 lines (151 loc) 4.18 kB
/** * @file 配置管理器 + Scanner 配置 * @description 提供全局配置管理功能 + Scanner v2.0 配置接口 * @module core/config */ // ============================================================ // 原有 ConfigManager(保持向后兼容) // ============================================================ export class ConfigManager { private static instance: ConfigManager; private config: Record<string, any> = {}; private changeCallbacks: Map<string, Array<(value: any, oldValue: any) => void>> = new Map(); private initialized = false; private constructor() { this._resetDefaults(); } public static getInstance(): ConfigManager { if (!ConfigManager.instance) { ConfigManager.instance = new ConfigManager(); } return ConfigManager.instance; } public static resetInstance(): void { ConfigManager.instance = undefined as any; } private _resetDefaults(): void { this.config = { debug: false, logLevel: 'info', modelPath: '/models', maxRetries: 3, retryDelay: 1000, detectionInterval: 100, face: { enabled: true, confidenceThreshold: 0.5, maxFaces: 10, }, idCard: { enabled: false, }, qr: { enabled: false, }, }; this.initialized = true; } public get<T = any>(key: string, defaultValue?: T): T { const keys = key.split('.'); let value: any = this.config; for (const k of keys) { value = value?.[k]; } return (value !== undefined ? value : defaultValue) as T; } public set(key: string, value: any): void { const keys = key.split('.'); let target: any = this.config; for (let i = 0; i < keys.length - 1; i++) { if (!target[keys[i]]) target[keys[i]] = {}; target = target[keys[i]]; } const oldValue = target[keys[keys.length - 1]]; target[keys[keys.length - 1]] = value; const callbacks = this.changeCallbacks.get(key); if (callbacks) { callbacks.forEach(cb => cb(value, oldValue)); } } public onChange(key: string, callback: (value: any, oldValue: any) => void): void { if (!this.changeCallbacks.has(key)) { this.changeCallbacks.set(key, []); } this.changeCallbacks.get(key)!.push(callback); } /** @deprecated Use onChange instead */ public onConfigChange<T = any>(key: string, callback: (value: T, oldValue: T) => void): void { this.onChange(key, callback); } public removeChangeCallback(key: string, callback: (value: any, oldValue: any) => void): void { const callbacks = this.changeCallbacks.get(key); if (callbacks) { const index = callbacks.indexOf(callback); if (index > -1) callbacks.splice(index, 1); } } public reset(): void { this.config = {}; this._resetDefaults(); } } // ============================================================ // Scanner v2.0 配置接口 // ============================================================ /** * Scanner configuration interface (v2.0) */ export interface ScannerConfig { debug?: boolean; modules?: { face?: boolean; faceComparator?: boolean; faceLiveness?: boolean; idCard?: boolean; qr?: boolean; }; performance?: { maxCanvasWidth?: number; useWorker?: boolean; lazyLoad?: boolean; }; } /** * Scanner module interface * All modules must implement this interface */ export interface ScannerModule { initialize(): Promise<void>; destroy(): Promise<void>; } /** * Image source types */ export type ImageSource = HTMLVideoElement | HTMLCanvasElement | HTMLImageElement | ImageData | string; /** * Face detection result */ export interface Face { box: { x: number; y: number; width: number; height: number; }; confidence: number; keypoints?: { leftEye?: { x: number; y: number }; rightEye?: { x: number; y: number }; nose?: { x: number; y: number }; leftMouth?: { x: number; y: number }; rightMouth?: { x: number; y: number }; }; embedding?: number[]; } /** * Module configuration */ export interface ModuleConfig { enabled?: boolean; [key: string]: any; }