@lee-zg/melange 1.0.0 → 1.2.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.
- package/README.md +14 -14
- package/dist/chunk-3RM45M64.js +1637 -0
- package/dist/chunk-3RM45M64.js.map +1 -0
- package/dist/{chunk-Q7XG6YN6.cjs → chunk-BEY4UAYF.cjs} +3 -5
- package/dist/chunk-BEY4UAYF.cjs.map +1 -0
- package/dist/{chunk-ALBD5XC5.js → chunk-GXFWPL5M.js} +4 -8
- package/dist/chunk-GXFWPL5M.js.map +1 -0
- package/dist/{chunk-352XNR3C.js → chunk-GZBY4BUP.js} +7 -24
- package/dist/chunk-GZBY4BUP.js.map +1 -0
- package/dist/{chunk-2PXWQDZC.js → chunk-ILNGTDQ4.js} +3 -5
- package/dist/chunk-ILNGTDQ4.js.map +1 -0
- package/dist/{chunk-Q73NOVWX.cjs → chunk-JLBTZPBY.cjs} +7 -24
- package/dist/chunk-JLBTZPBY.cjs.map +1 -0
- package/dist/{chunk-ZT6HVG4G.cjs → chunk-UYJUSNDI.cjs} +4 -8
- package/dist/chunk-UYJUSNDI.cjs.map +1 -0
- package/dist/chunk-YZVCK6VZ.cjs +1646 -0
- package/dist/chunk-YZVCK6VZ.cjs.map +1 -0
- package/dist/core/index.cjs +23 -23
- package/dist/core/index.js +1 -1
- package/dist/fp/index.cjs +45 -45
- package/dist/fp/index.js +1 -1
- package/dist/index.cjs +147 -147
- package/dist/index.js +4 -4
- package/dist/plugins/index.cjs +9 -9
- package/dist/plugins/index.d.cts +287 -133
- package/dist/plugins/index.d.ts +287 -133
- package/dist/plugins/index.js +1 -1
- package/dist/utils/index.cjs +73 -73
- package/dist/utils/index.js +1 -1
- package/package.json +5 -2
- package/dist/chunk-2PXWQDZC.js.map +0 -1
- package/dist/chunk-352XNR3C.js.map +0 -1
- package/dist/chunk-ALBD5XC5.js.map +0 -1
- package/dist/chunk-O7K662J5.cjs +0 -842
- package/dist/chunk-O7K662J5.cjs.map +0 -1
- package/dist/chunk-Q73NOVWX.cjs.map +0 -1
- package/dist/chunk-Q7XG6YN6.cjs.map +0 -1
- package/dist/chunk-YGMBCZJQ.js +0 -833
- package/dist/chunk-YGMBCZJQ.js.map +0 -1
- package/dist/chunk-ZT6HVG4G.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugins/speech/synthesis.ts","../src/plugins/speech/recognition.ts"],"names":[],"mappings":"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","file":"chunk-3RM45M64.js","sourcesContent":["/**\n * @fileoverview 语音合成 (TTS) 实现 - 商业级版本 v2.0\n * @module melange/plugins/speech/synthesis\n * @description 生产级 Web 语音合成插件\n *\n * 架构:\n * [UI层] -> [SpeechSynthesizerImpl] -> [NativeStrategy / CloudStrategy]\n * |\n * +-> [音频核心]: AudioContext, 流式播放\n * +-> [适配器]: AzureAdapter, GoogleAdapter, TencentAdapter...\n *\n * 功能特性:\n * 1. 多模式: 支持原生 Web Speech API & 云端 TTS 服务\n * 2. 状态机: IDLE -> LOADING -> SPEAKING -> PAUSED\n * 3. 插件化: 内置 Azure/Google/AWS/讯飞/腾讯/百度/阿里 适配器\n * 4. 核心: AudioContext 流式播放 + 音频队列管理\n * 5. 兼容性: 多浏览器支持 + 自动降级处理\n */\n\nimport type {\n SpeechProviderType,\n SpeechServiceStatus,\n VoiceInfo,\n SynthesisConfig,\n SynthesisEventType,\n SynthesisEvent,\n SynthesisEventHandler,\n SynthesisProvider,\n SpeechSynthesizer,\n} from './types';\n\n// ============================================================================\n// 1. 类型定义 & 枚举\n// ============================================================================\n\n/**\n * 合成器状态枚举\n */\nexport enum SynthesisStatus {\n /** 空闲状态 */\n IDLE = 'IDLE',\n /** 加载中(获取语音/准备中) */\n LOADING = 'LOADING',\n /** 正在播放 */\n SPEAKING = 'SPEAKING',\n /** 已暂停 */\n PAUSED = 'PAUSED',\n}\n\n/**\n * 合成引擎模式\n */\nexport type SynthesisEngineMode = 'native' | 'cloud' | 'auto';\n\n/**\n * 云端 TTS 音频格式\n */\nexport type CloudAudioFormat = 'mp3' | 'wav' | 'ogg' | 'pcm';\n\n/**\n * 云端合成结果接口\n */\nexport interface ISynthesisResult {\n /** 音频数据 */\n audioData: ArrayBuffer;\n /** 音频格式 */\n format: CloudAudioFormat;\n /** 音频时长 (ms) */\n duration?: number;\n /** 原始响应数据 */\n original?: unknown;\n}\n\n/**\n * 合成错误接口\n */\nexport interface ISynthesisError {\n /** 错误代码 */\n code:\n | 'NETWORK'\n | 'NOT_SUPPORTED'\n | 'INVALID_TEXT'\n | 'ADAPTER_ERROR'\n | 'PLAYBACK_ERROR'\n | 'UNKNOWN';\n /** 错误信息 */\n message: string;\n /** 原始错误 */\n originalError?: unknown;\n}\n\n/**\n * 云端语音信息\n */\nexport interface ICloudVoice {\n /** 语音 ID */\n id: string;\n /** 语音名称 */\n name: string;\n /** 语言代码 */\n lang: string;\n /** 性别 */\n gender?: 'male' | 'female' | 'neutral';\n /** 提供商名称 */\n provider: string;\n}\n\n/**\n * 高级合成配置\n */\nexport interface IAdvancedSynthesisConfig extends SynthesisConfig {\n /** 合成引擎模式 */\n mode?: SynthesisEngineMode;\n /** 云端适配器 */\n cloudAdapter?: ICloudSynthesisAdapter;\n /** 音频格式偏好 */\n audioFormat?: CloudAudioFormat;\n /** 是否启用 SSML */\n enableSSML?: boolean;\n /** 是否预加载音频 */\n preload?: boolean;\n /** 音频缓存大小 */\n cacheSize?: number;\n}\n\n// ============================================================================\n// 2. 云端合成适配器接口\n// ============================================================================\n\n/**\n * 云端合成适配器接口\n * 提供统一的第三方语音合成服务集成接口\n */\nexport interface ICloudSynthesisAdapter {\n /** 适配器名称 */\n readonly name: string;\n\n /**\n * 合成语音\n * @param text 要合成的文本\n * @param config 合成配置\n * @returns 合成结果(音频数据)\n */\n synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult>;\n\n /**\n * 获取可用语音列表\n * @returns 语音列表\n */\n getVoices?(): Promise<ICloudVoice[]>;\n\n /**\n * 检查适配器是否可用\n * @returns 是否可用\n */\n isAvailable?(): boolean;\n}\n\n// ============================================================================\n// 3. 音频播放工具类\n// ============================================================================\n\n/**\n * 音频播放工具集\n */\nexport const SynthesisAudioUtils = {\n /**\n * 创建 AudioContext\n */\n createAudioContext(): AudioContext {\n const AudioCtor =\n typeof window !== 'undefined'\n ? window.AudioContext ||\n (window as Window & { webkitAudioContext?: typeof AudioContext }).webkitAudioContext\n : null;\n if (!AudioCtor) {\n throw new Error('浏览器不支持 AudioContext');\n }\n return new AudioCtor();\n },\n\n /**\n * ArrayBuffer 转 Base64\n */\n arrayBufferToBase64(buffer: ArrayBuffer): string {\n let binary = '';\n const bytes = new Uint8Array(buffer);\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i] ?? 0);\n }\n return typeof btoa !== 'undefined' ? btoa(binary) : Buffer.from(binary).toString('base64');\n },\n\n /**\n * Base64 转 ArrayBuffer\n */\n base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binary =\n typeof atob !== 'undefined' ? atob(base64) : Buffer.from(base64, 'base64').toString('binary');\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes.buffer;\n },\n\n /**\n * 计算音频时长(粗略估算)\n */\n estimateDuration(byteLength: number, format: CloudAudioFormat): number {\n const bitRates: Record<CloudAudioFormat, number> = {\n mp3: 128000, // 128 kbps\n wav: 256000, // 16bit 16kHz mono\n ogg: 96000, // 96 kbps\n pcm: 256000, // 16bit 16kHz mono\n };\n return Math.ceil(((byteLength * 8) / bitRates[format]) * 1000);\n },\n};\n\n// ============================================================================\n// 4. 内置云端适配器实现\n// ============================================================================\n\n/**\n * 通用适配器 (BFF 模式 - 推荐)\n * 适用于自建后端代理场景\n */\nexport class GenericSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'Generic/BFF';\n\n constructor(private baseUrl: string) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n const response = await fetch(`${this.baseUrl}/synthesize`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n text,\n lang: config?.lang ?? 'zh-CN',\n voice: typeof config?.voice === 'string' ? config.voice : config?.voice?.id,\n rate: config?.rate ?? 1.0,\n pitch: config?.pitch ?? 1.0,\n volume: config?.volume ?? 1.0,\n format: config?.audioFormat ?? 'mp3',\n }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const audioData = await response.arrayBuffer();\n return {\n audioData,\n format: config?.audioFormat ?? 'mp3',\n duration: SynthesisAudioUtils.estimateDuration(\n audioData.byteLength,\n config?.audioFormat ?? 'mp3'\n ),\n };\n }\n\n async getVoices(): Promise<ICloudVoice[]> {\n try {\n const response = await fetch(`${this.baseUrl}/voices`);\n if (!response.ok) return [];\n const data = (await response.json()) as { voices?: ICloudVoice[] };\n return data.voices ?? [];\n } catch {\n return [];\n }\n }\n}\n\n/**\n * Azure 语音服务适配器\n */\nexport class AzureSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'Azure';\n\n constructor(\n private subscriptionKey: string,\n private region: string,\n private defaultVoice: string = 'zh-CN-XiaoxiaoNeural'\n ) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n const voice =\n typeof config?.voice === 'string' ? config.voice : (config?.voice?.id ?? this.defaultVoice);\n const rate = config?.rate ?? 1.0;\n const pitch = config?.pitch ?? 1.0;\n\n // 构建 SSML\n const ssml = `\n<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xml:lang=\"${config?.lang ?? 'zh-CN'}\">\n <voice name=\"${voice}\">\n <prosody rate=\"${rate}\" pitch=\"${(pitch - 1) * 50}%\">\n ${this.escapeXml(text)}\n </prosody>\n </voice>\n</speak>`;\n\n const response = await fetch(\n `https://${this.region}.tts.speech.microsoft.com/cognitiveservices/v1`,\n {\n method: 'POST',\n headers: {\n 'Ocp-Apim-Subscription-Key': this.subscriptionKey,\n 'Content-Type': 'application/ssml+xml',\n 'X-Microsoft-OutputFormat': 'audio-16khz-128kbitrate-mono-mp3',\n },\n body: ssml,\n }\n );\n\n if (!response.ok) {\n throw new Error(`Azure TTS Error: ${response.status}`);\n }\n\n const audioData = await response.arrayBuffer();\n return { audioData, format: 'mp3' };\n }\n\n async getVoices(): Promise<ICloudVoice[]> {\n const response = await fetch(\n `https://${this.region}.tts.speech.microsoft.com/cognitiveservices/voices/list`,\n {\n headers: { 'Ocp-Apim-Subscription-Key': this.subscriptionKey },\n }\n );\n\n if (!response.ok) return [];\n\n const voices = (await response.json()) as Array<{\n ShortName: string;\n DisplayName: string;\n Locale: string;\n Gender: string;\n }>;\n\n return voices.map(v => ({\n id: v.ShortName,\n name: v.DisplayName,\n lang: v.Locale,\n gender: v.Gender.toLowerCase() as 'male' | 'female' | 'neutral',\n provider: 'Azure',\n }));\n }\n\n private escapeXml(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n }\n}\n\n/**\n * Google Cloud TTS 适配器\n */\nexport class GoogleSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'Google';\n\n constructor(\n private apiKey: string,\n private defaultVoice: string = 'zh-CN-Wavenet-A'\n ) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n const voice =\n typeof config?.voice === 'string' ? config.voice : (config?.voice?.id ?? this.defaultVoice);\n const lang = config?.lang ?? 'zh-CN';\n\n const payload = {\n input: config?.enableSSML ? { ssml: text } : { text },\n voice: {\n languageCode: lang,\n name: voice,\n },\n audioConfig: {\n audioEncoding: 'MP3',\n speakingRate: config?.rate ?? 1.0,\n pitch: config?.pitch ?? 0,\n volumeGainDb: ((config?.volume ?? 1.0) - 1) * 10,\n },\n };\n\n const response = await fetch(\n `https://texttospeech.googleapis.com/v1/text:synthesize?key=${this.apiKey}`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n }\n );\n\n if (!response.ok) {\n const error = (await response.json()) as { error?: { message?: string } };\n throw new Error(error.error?.message ?? 'Google TTS Error');\n }\n\n const data = (await response.json()) as { audioContent: string };\n const audioData = SynthesisAudioUtils.base64ToArrayBuffer(data.audioContent);\n return { audioData, format: 'mp3' };\n }\n\n async getVoices(): Promise<ICloudVoice[]> {\n const response = await fetch(\n `https://texttospeech.googleapis.com/v1/voices?key=${this.apiKey}`\n );\n\n if (!response.ok) return [];\n\n const data = (await response.json()) as {\n voices: Array<{\n name: string;\n languageCodes: string[];\n ssmlGender: string;\n }>;\n };\n\n return data.voices.map(v => ({\n id: v.name,\n name: v.name,\n lang: v.languageCodes[0] ?? 'en-US',\n gender: v.ssmlGender.toLowerCase() as 'male' | 'female' | 'neutral',\n provider: 'Google',\n }));\n }\n}\n\n/**\n * AWS Polly 适配器\n */\nexport class AWSSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'AWS';\n\n constructor(\n private accessKeyId: string,\n private secretAccessKey: string,\n private region: string,\n private defaultVoice: string = 'Zhiyu'\n ) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n // AWS Polly 需要签名,建议通过 BFF 代理\n const voice =\n typeof config?.voice === 'string' ? config.voice : (config?.voice?.id ?? this.defaultVoice);\n\n // 简化示例,生产环境建议通过后端代理\n const response = await fetch('/api/aws-polly/synthesize', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n text,\n voiceId: voice,\n languageCode: config?.lang ?? 'cmn-CN',\n outputFormat: 'mp3',\n accessKeyId: this.accessKeyId,\n secretAccessKey: this.secretAccessKey,\n region: this.region,\n }),\n });\n\n if (!response.ok) {\n throw new Error(`AWS Polly Error: ${response.status}`);\n }\n\n const audioData = await response.arrayBuffer();\n return { audioData, format: 'mp3' };\n }\n\n getVoices(): Promise<ICloudVoice[]> {\n // 返回部分常用中文语音\n return Promise.resolve([\n { id: 'Zhiyu', name: '智瑜', lang: 'cmn-CN', gender: 'female', provider: 'AWS' },\n ]);\n }\n}\n\n/**\n * 讯飞云适配器\n */\nexport class XunfeiSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'Xunfei';\n\n // Note: apiKey and apiSecret are reserved for future direct API authentication\n // Currently using BFF proxy mode which handles auth server-side\n constructor(\n private appId: string,\n _apiKey?: string,\n _apiSecret?: string,\n private defaultVoice: string = 'xiaoyan'\n ) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n const voice =\n typeof config?.voice === 'string' ? config.voice : (config?.voice?.id ?? this.defaultVoice);\n\n // 讯飞 WebAPI 需要鉴权,建议通过 BFF 代理\n const response = await fetch('/api/xunfei-tts/synthesize', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n text,\n appId: this.appId,\n vcn: voice,\n speed: Math.round((config?.rate ?? 1.0) * 50),\n pitch: Math.round((config?.pitch ?? 1.0) * 50),\n volume: Math.round((config?.volume ?? 1.0) * 100),\n aue: 'lame', // mp3\n }),\n });\n\n if (!response.ok) {\n throw new Error(`讯飞 TTS Error: ${response.status}`);\n }\n\n const audioData = await response.arrayBuffer();\n return { audioData, format: 'mp3' };\n }\n\n getVoices(): Promise<ICloudVoice[]> {\n return Promise.resolve([\n { id: 'xiaoyan', name: '小燕', lang: 'zh-CN', gender: 'female', provider: 'Xunfei' },\n { id: 'aisjiuxu', name: '许久', lang: 'zh-CN', gender: 'male', provider: 'Xunfei' },\n { id: 'aisxping', name: '小萍', lang: 'zh-CN', gender: 'female', provider: 'Xunfei' },\n { id: 'aisjinger', name: '小婧', lang: 'zh-CN', gender: 'female', provider: 'Xunfei' },\n ]);\n }\n}\n\n/**\n * 腾讯云适配器\n */\nexport class TencentSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'Tencent';\n\n constructor(\n private secretId: string,\n private secretKey: string,\n private defaultVoice: string = '101001'\n ) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n const voice =\n typeof config?.voice === 'string' ? config.voice : (config?.voice?.id ?? this.defaultVoice);\n\n // TC3-HMAC-SHA256 签名应在后端完成\n const response = await fetch('/api/tencent-tts/synthesize', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n text,\n secretId: this.secretId,\n secretKey: this.secretKey,\n voiceType: Number(voice),\n speed: config?.rate ?? 1.0,\n volume: config?.volume ?? 0,\n codec: 'mp3',\n }),\n });\n\n if (!response.ok) {\n throw new Error(`腾讯云 TTS Error: ${response.status}`);\n }\n\n const audioData = await response.arrayBuffer();\n return { audioData, format: 'mp3' };\n }\n\n getVoices(): Promise<ICloudVoice[]> {\n return Promise.resolve([\n { id: '101001', name: '智瑜', lang: 'zh-CN', gender: 'female', provider: 'Tencent' },\n { id: '101002', name: '智聆', lang: 'zh-CN', gender: 'male', provider: 'Tencent' },\n { id: '101003', name: '智美', lang: 'zh-CN', gender: 'female', provider: 'Tencent' },\n ]);\n }\n}\n\n/**\n * 百度云适配器\n */\nexport class BaiduSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'Baidu';\n\n constructor(\n private accessToken: string,\n private defaultVoice: string = '0'\n ) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n const voice =\n typeof config?.voice === 'string' ? config.voice : (config?.voice?.id ?? this.defaultVoice);\n\n const params = new URLSearchParams({\n tex: encodeURIComponent(text),\n tok: this.accessToken,\n cuid: `sdk-user-${Date.now()}`,\n ctp: '1',\n lan: config?.lang === 'en-US' ? 'en' : 'zh',\n spd: String(Math.round((config?.rate ?? 1.0) * 5)),\n pit: String(Math.round((config?.pitch ?? 1.0) * 5)),\n vol: String(Math.round((config?.volume ?? 1.0) * 15)),\n per: voice,\n aue: '3', // mp3\n });\n\n // 建议通过 BFF 代理调用,避免 CORS 问题\n const response = await fetch('/api/baidu-tts/synthesize', {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: params.toString(),\n });\n\n const contentType = response.headers.get('Content-Type') ?? '';\n if (contentType.includes('audio')) {\n const audioData = await response.arrayBuffer();\n return { audioData, format: 'mp3' };\n }\n\n // 错误响应是 JSON\n const error = (await response.json()) as { err_msg?: string };\n throw new Error(error.err_msg ?? '百度 TTS Error');\n }\n\n getVoices(): Promise<ICloudVoice[]> {\n return Promise.resolve([\n { id: '0', name: '度小美', lang: 'zh-CN', gender: 'female', provider: 'Baidu' },\n { id: '1', name: '度小宇', lang: 'zh-CN', gender: 'male', provider: 'Baidu' },\n { id: '3', name: '度逍遥', lang: 'zh-CN', gender: 'male', provider: 'Baidu' },\n { id: '4', name: '度丫丫', lang: 'zh-CN', gender: 'female', provider: 'Baidu' },\n ]);\n }\n}\n\n/**\n * 阿里云适配器\n */\nexport class AlibabaSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'Alibaba';\n\n // Note: accessKeySecret is reserved for future direct API authentication\n // Currently using BFF proxy mode which handles auth server-side\n constructor(\n private accessKeyId: string,\n _accessKeySecret: string,\n private appKey: string,\n private defaultVoice: string = 'xiaoyun'\n ) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n const voice =\n typeof config?.voice === 'string' ? config.voice : (config?.voice?.id ?? this.defaultVoice);\n\n // 建议通过 BFF 代理调用\n const response = await fetch('/api/alibaba-tts/synthesize', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-NLS-Token': this.accessKeyId,\n },\n body: JSON.stringify({\n appkey: this.appKey,\n text,\n format: 'mp3',\n voice,\n sample_rate: 16000,\n speech_rate: Math.round((config?.rate ?? 1.0 - 1) * 500),\n pitch_rate: Math.round((config?.pitch ?? 1.0 - 1) * 500),\n volume: Math.round((config?.volume ?? 1.0) * 100),\n }),\n });\n\n if (!response.ok) {\n throw new Error(`阿里云 TTS Error: ${response.status}`);\n }\n\n const audioData = await response.arrayBuffer();\n return { audioData, format: 'mp3' };\n }\n\n getVoices(): Promise<ICloudVoice[]> {\n return Promise.resolve([\n { id: 'xiaoyun', name: '小云', lang: 'zh-CN', gender: 'female', provider: 'Alibaba' },\n { id: 'xiaogang', name: '小刚', lang: 'zh-CN', gender: 'male', provider: 'Alibaba' },\n { id: 'ruoxi', name: '若兮', lang: 'zh-CN', gender: 'female', provider: 'Alibaba' },\n { id: 'siqi', name: '思琪', lang: 'zh-CN', gender: 'female', provider: 'Alibaba' },\n ]);\n }\n}\n\n// ============================================================================\n// 5. 抽象策略基类\n// ============================================================================\n\n/**\n * 事件监听器类型定义\n */\ntype SynthesisEventListeners = {\n start: Array<() => void>;\n end: Array<() => void>;\n pause: Array<() => void>;\n resume: Array<() => void>;\n boundary: Array<\n (data: { charIndex?: number; charLength?: number; elapsedTime?: number; name?: string }) => void\n >;\n mark: Array<(data: { name?: string }) => void>;\n error: Array<(err: ISynthesisError) => void>;\n state: Array<(status: SynthesisStatus) => void>;\n};\n\n/**\n * 合成策略基类\n */\nabstract class BaseSynthesisStrategy {\n protected listeners: SynthesisEventListeners = {\n start: [],\n end: [],\n pause: [],\n resume: [],\n boundary: [],\n mark: [],\n error: [],\n state: [],\n };\n\n protected _status: SynthesisStatus = SynthesisStatus.IDLE;\n\n constructor(protected config: IAdvancedSynthesisConfig) {}\n\n /**\n * 获取当前状态\n */\n get status(): SynthesisStatus {\n return this._status;\n }\n\n /**\n * 朗读文本\n */\n abstract speak(text: string, config?: SynthesisConfig): Promise<void>;\n\n /**\n * 暂停\n */\n abstract pause(): void;\n\n /**\n * 继续\n */\n abstract resume(): void;\n\n /**\n * 取消\n */\n abstract cancel(): void;\n\n /**\n * 是否正在朗读\n */\n abstract isSpeaking(): boolean;\n\n /**\n * 是否已暂停\n */\n abstract isPaused(): boolean;\n\n /**\n * 获取可用语音\n */\n abstract getVoices(): Promise<VoiceInfo[]>;\n\n /**\n * 检查是否可用\n */\n abstract isAvailable(): boolean;\n\n /**\n * 设置状态\n */\n protected setStatus(status: SynthesisStatus): void {\n if (this._status !== status) {\n this._status = status;\n this.emit('state', status);\n }\n }\n\n /**\n * 添加事件监听\n */\n on<K extends keyof SynthesisEventListeners>(\n event: K,\n fn: SynthesisEventListeners[K][number]\n ): void {\n (this.listeners[event] as Array<typeof fn>).push(fn);\n }\n\n /**\n * 移除事件监听\n */\n off<K extends keyof SynthesisEventListeners>(\n event: K,\n fn: SynthesisEventListeners[K][number]\n ): void {\n const listeners = this.listeners[event] as Array<typeof fn>;\n const index = listeners.indexOf(fn);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n }\n\n /**\n * 触发事件\n */\n protected emit<K extends keyof SynthesisEventListeners>(\n event: K,\n data?: Parameters<SynthesisEventListeners[K][number]>[0]\n ): void {\n const listeners = this.listeners[event] as Array<(arg?: typeof data) => void>;\n listeners.forEach(fn => {\n try {\n fn(data);\n } catch (e) {\n console.error(`[Synthesis] 事件处理器错误 (${event}):`, e);\n }\n });\n }\n\n /**\n * 销毁资源\n */\n dispose(): void {\n this.cancel();\n Object.keys(this.listeners).forEach(key => {\n (this.listeners as Record<string, unknown[]>)[key] = [];\n });\n }\n}\n\n// ============================================================================\n// 6. 原生合成策略\n// ============================================================================\n\n/**\n * 浏览器原生语音合成策略\n * 使用 Web Speech API SpeechSynthesis\n */\nclass NativeSynthesisStrategy extends BaseSynthesisStrategy {\n private synthesis: SpeechSynthesis | null = null;\n // Internal state tracking for current utterance (write-only, used for GC reference)\n private currentUtterance: SpeechSynthesisUtterance | null = null;\n private voicesLoaded: boolean = false;\n private voicesPromise: Promise<VoiceInfo[]> | null = null;\n\n constructor(config: IAdvancedSynthesisConfig) {\n super(config);\n if (this.isAvailable()) {\n this.synthesis = window.speechSynthesis;\n }\n }\n\n isAvailable(): boolean {\n return typeof window !== 'undefined' && 'speechSynthesis' in window;\n }\n\n async getVoices(): Promise<VoiceInfo[]> {\n if (!this.synthesis) return [];\n\n if (this.voicesPromise) {\n return this.voicesPromise;\n }\n\n this.voicesPromise = new Promise(resolve => {\n const loadVoices = () => {\n const voices = this.synthesis!.getVoices();\n if (voices.length > 0) {\n this.voicesLoaded = true;\n resolve(\n voices.map(voice => ({\n id: voice.voiceURI,\n name: voice.name,\n lang: voice.lang,\n localService: voice.localService,\n default: voice.default,\n provider: 'browser' as SpeechProviderType,\n }))\n );\n }\n };\n\n loadVoices();\n\n if (!this.voicesLoaded) {\n this.synthesis!.addEventListener('voiceschanged', loadVoices, { once: true });\n setTimeout(() => {\n if (!this.voicesLoaded) {\n resolve([]);\n }\n }, 3000);\n }\n });\n\n return this.voicesPromise;\n }\n\n async speak(text: string, config?: SynthesisConfig): Promise<void> {\n if (!this.synthesis) {\n throw { code: 'NOT_SUPPORTED', message: '浏览器不支持语音合成' };\n }\n\n // 取消当前朗读\n this.cancel();\n\n this.setStatus(SynthesisStatus.LOADING);\n\n return new Promise((resolve, reject) => {\n const mergedConfig = { ...this.config, ...config };\n const utterance = new SpeechSynthesisUtterance(text);\n this.currentUtterance = utterance;\n\n // 应用配置\n if (mergedConfig.lang) utterance.lang = mergedConfig.lang;\n if (mergedConfig.volume !== undefined) utterance.volume = mergedConfig.volume;\n if (mergedConfig.rate !== undefined) utterance.rate = mergedConfig.rate;\n if (mergedConfig.pitch !== undefined) utterance.pitch = mergedConfig.pitch;\n\n // 设置语音\n if (mergedConfig.voice) {\n const voices = this.synthesis!.getVoices();\n const voiceConfig = mergedConfig.voice;\n const targetVoice =\n typeof voiceConfig === 'string'\n ? voices.find(v => v.name === voiceConfig || v.voiceURI === voiceConfig)\n : voices.find(v => v.voiceURI === voiceConfig.id);\n if (targetVoice) {\n utterance.voice = targetVoice;\n }\n }\n\n // 事件处理\n utterance.onstart = () => {\n this.setStatus(SynthesisStatus.SPEAKING);\n this.emit('start');\n };\n\n utterance.onend = () => {\n this.setStatus(SynthesisStatus.IDLE);\n this.currentUtterance = null;\n this.emit('end');\n resolve();\n };\n\n utterance.onpause = () => {\n this.setStatus(SynthesisStatus.PAUSED);\n this.emit('pause');\n };\n\n utterance.onresume = () => {\n this.setStatus(SynthesisStatus.SPEAKING);\n this.emit('resume');\n };\n\n utterance.onboundary = event => {\n this.emit('boundary', {\n charIndex: event.charIndex,\n charLength: event.charLength,\n elapsedTime: event.elapsedTime,\n name: event.name,\n });\n };\n\n utterance.onmark = event => {\n this.emit('mark', { name: event.name });\n };\n\n utterance.onerror = event => {\n this.setStatus(SynthesisStatus.IDLE);\n this.currentUtterance = null;\n const error: ISynthesisError = {\n code: 'UNKNOWN',\n message: `语音合成错误: ${event.error}`,\n originalError: event,\n };\n this.emit('error', error);\n reject(error);\n };\n\n this.synthesis!.speak(utterance);\n });\n }\n\n pause(): void {\n if (this.synthesis && this.isSpeaking()) {\n this.synthesis.pause();\n }\n }\n\n resume(): void {\n if (this.synthesis && this.isPaused()) {\n this.synthesis.resume();\n }\n }\n\n cancel(): void {\n if (this.synthesis) {\n this.synthesis.cancel();\n this.currentUtterance = null;\n this.setStatus(SynthesisStatus.IDLE);\n }\n }\n\n isSpeaking(): boolean {\n return this.currentUtterance !== null && (this.synthesis?.speaking ?? false);\n }\n\n isPaused(): boolean {\n return this.synthesis?.paused ?? false;\n }\n}\n\n// ============================================================================\n// 7. 云端合成策略\n// ============================================================================\n\n/**\n * 云端语音合成策略\n * 支持多种第三方 TTS 服务\n */\nclass CloudSynthesisStrategy extends BaseSynthesisStrategy {\n private adapter: ICloudSynthesisAdapter;\n private audioContext: AudioContext | null = null;\n private sourceNode: AudioBufferSourceNode | null = null;\n private gainNode: GainNode | null = null;\n private startTime: number = 0;\n private pauseTime: number = 0;\n private audioBuffer: AudioBuffer | null = null;\n\n constructor(config: IAdvancedSynthesisConfig) {\n super(config);\n if (!config.cloudAdapter) {\n throw new Error('[CloudStrategy] 需要提供 cloudAdapter');\n }\n this.adapter = config.cloudAdapter;\n }\n\n isAvailable(): boolean {\n return typeof window !== 'undefined' && 'AudioContext' in window;\n }\n\n async getVoices(): Promise<VoiceInfo[]> {\n if (!this.adapter.getVoices) return [];\n\n try {\n const cloudVoices = await this.adapter.getVoices();\n return cloudVoices.map(v => ({\n id: v.id,\n name: v.name,\n lang: v.lang,\n localService: false,\n default: false,\n provider: 'custom' as SpeechProviderType,\n }));\n } catch {\n return [];\n }\n }\n\n async speak(text: string, config?: SynthesisConfig): Promise<void> {\n if (!text.trim()) {\n throw { code: 'INVALID_TEXT', message: '文本内容为空' } as ISynthesisError;\n }\n\n // 取消当前播放\n this.cancel();\n\n const mergedConfig = { ...this.config, ...config } as IAdvancedSynthesisConfig;\n this.setStatus(SynthesisStatus.LOADING);\n\n try {\n // 1. 调用适配器合成音频\n this.emit('start');\n const result = await this.adapter.synthesize(text, mergedConfig);\n\n // 2. 初始化音频上下文\n if (!this.audioContext) {\n this.audioContext = SynthesisAudioUtils.createAudioContext();\n }\n\n if (this.audioContext.state === 'suspended') {\n await this.audioContext.resume();\n }\n\n // 3. 解码音频\n this.audioBuffer = await this.audioContext.decodeAudioData(result.audioData.slice(0));\n\n // 4. 播放\n await this.playBuffer();\n } catch (e: unknown) {\n const error = e as Error;\n this.setStatus(SynthesisStatus.IDLE);\n const synthError: ISynthesisError = {\n code: 'ADAPTER_ERROR',\n message: error.message || '合成失败',\n originalError: e,\n };\n this.emit('error', synthError);\n throw synthError;\n }\n }\n\n private async playBuffer(): Promise<void> {\n if (!this.audioContext || !this.audioBuffer) return;\n\n return new Promise((resolve, reject) => {\n try {\n // 创建节点\n this.sourceNode = this.audioContext!.createBufferSource();\n this.sourceNode.buffer = this.audioBuffer;\n\n this.gainNode = this.audioContext!.createGain();\n this.gainNode.gain.value = this.config.volume ?? 1.0;\n\n // 连接节点\n this.sourceNode.connect(this.gainNode);\n this.gainNode.connect(this.audioContext!.destination);\n\n // 播放结束处理\n this.sourceNode.onended = () => {\n if (this._status === SynthesisStatus.SPEAKING) {\n this.setStatus(SynthesisStatus.IDLE);\n this.emit('end');\n resolve();\n }\n };\n\n // 开始播放\n const offset = this.pauseTime > 0 ? this.pauseTime : 0;\n this.sourceNode.start(0, offset);\n this.startTime = this.audioContext!.currentTime - offset;\n this.pauseTime = 0;\n this.setStatus(SynthesisStatus.SPEAKING);\n } catch (e) {\n reject(e);\n }\n });\n }\n\n pause(): void {\n if (this._status === SynthesisStatus.SPEAKING && this.audioContext && this.sourceNode) {\n this.pauseTime = this.audioContext.currentTime - this.startTime;\n this.sourceNode.stop();\n this.sourceNode.disconnect();\n this.sourceNode = null;\n this.setStatus(SynthesisStatus.PAUSED);\n this.emit('pause');\n }\n }\n\n resume(): void {\n if (this._status === SynthesisStatus.PAUSED && this.audioBuffer) {\n this.emit('resume');\n void this.playBuffer();\n }\n }\n\n cancel(): void {\n if (this.sourceNode) {\n try {\n this.sourceNode.stop();\n this.sourceNode.disconnect();\n } catch {\n // ignore\n }\n this.sourceNode = null;\n }\n\n this.audioBuffer = null;\n this.pauseTime = 0;\n this.startTime = 0;\n this.setStatus(SynthesisStatus.IDLE);\n }\n\n isSpeaking(): boolean {\n return this._status === SynthesisStatus.SPEAKING;\n }\n\n isPaused(): boolean {\n return this._status === SynthesisStatus.PAUSED;\n }\n\n override dispose(): void {\n super.dispose();\n this.cancel();\n if (this.audioContext) {\n void this.audioContext.close();\n this.audioContext = null;\n }\n }\n}\n\n// ============================================================================\n// 8. 主入口类 (Facade)\n// ============================================================================\n\n/**\n * 语音合成器实现\n * 统一封装原生合成和云端合成\n */\nexport class SpeechSynthesizerImpl implements SpeechSynthesizer {\n private strategy: BaseSynthesisStrategy | null = null;\n private config: IAdvancedSynthesisConfig = {};\n private _currentProvider: SpeechProviderType = 'browser';\n private _status: SpeechServiceStatus = 'idle';\n private eventHandlers: Map<SynthesisEventType, Set<SynthesisEventHandler>> = new Map();\n private customProviders: Map<SpeechProviderType, SynthesisProvider> = new Map();\n\n get currentProvider(): SpeechProviderType {\n return this._currentProvider;\n }\n\n get status(): SpeechServiceStatus {\n return this._status;\n }\n\n /**\n * 获取当前合成状态\n */\n get synthesisStatus(): SynthesisStatus {\n return this.strategy?.status ?? SynthesisStatus.IDLE;\n }\n\n /**\n * 初始化语音合成器\n */\n initialize(config?: SynthesisConfig): Promise<void> {\n this._status = 'loading';\n\n // 合并配置\n this.config = {\n lang: 'zh-CN',\n volume: 1.0,\n rate: 1.0,\n pitch: 1.0,\n preferredProvider: 'browser',\n autoFallback: true,\n fallbackProviders: ['azure', 'google', 'aws'],\n mode: 'auto',\n audioFormat: 'mp3',\n ...config,\n } as IAdvancedSynthesisConfig;\n\n try {\n this.initializeStrategy();\n this._status = 'ready';\n return Promise.resolve();\n } catch (error) {\n this._status = 'error';\n return Promise.reject(error);\n }\n }\n\n /**\n * 初始化合成策略\n */\n private initializeStrategy(): void {\n const advConfig = this.config;\n const mode = advConfig.mode ?? 'auto';\n const hasNative = typeof window !== 'undefined' && 'speechSynthesis' in window;\n\n // 选择策略\n if (mode === 'native' || (mode === 'auto' && hasNative && !advConfig.cloudAdapter)) {\n const nativeStrategy = new NativeSynthesisStrategy(advConfig);\n if (!nativeStrategy.isAvailable()) {\n throw new Error('浏览器不支持原生语音合成');\n }\n this.strategy = nativeStrategy;\n this._currentProvider = 'browser';\n } else if (mode === 'cloud' || (mode === 'auto' && advConfig.cloudAdapter)) {\n if (!advConfig.cloudAdapter) {\n throw new Error('云端模式需要提供 cloudAdapter');\n }\n this.strategy = new CloudSynthesisStrategy(advConfig);\n this._currentProvider = 'custom';\n } else {\n throw new Error('没有可用的合成策略');\n }\n\n // 转发事件\n this.forwardStrategyEvents();\n }\n\n /**\n * 转发策略事件\n */\n private forwardStrategyEvents(): void {\n if (!this.strategy) return;\n\n this.strategy.on('start', () => this.emit('start', { type: 'start' }));\n this.strategy.on('end', () => this.emit('end', { type: 'end' }));\n this.strategy.on('pause', () => this.emit('pause', { type: 'pause' }));\n this.strategy.on('resume', () => this.emit('resume', { type: 'resume' }));\n\n this.strategy.on('boundary', data => {\n const event: SynthesisEvent = { type: 'boundary' };\n if (data.charIndex !== undefined) event.charIndex = data.charIndex;\n if (data.charLength !== undefined) event.charLength = data.charLength;\n if (data.elapsedTime !== undefined) event.elapsedTime = data.elapsedTime;\n if (data.name !== undefined) event.name = data.name;\n this.emit('boundary', event);\n });\n\n this.strategy.on('mark', data => {\n const event: SynthesisEvent = { type: 'mark' };\n if (data.name !== undefined) event.name = data.name;\n this.emit('mark', event);\n });\n\n this.strategy.on('error', err => {\n const errorEvent: SynthesisEvent = {\n type: 'error',\n error: {\n code: err.code,\n message: err.message,\n },\n };\n if (err.originalError) {\n errorEvent.error!.originalError = err.originalError as Error;\n }\n this.emit('error', errorEvent);\n });\n }\n\n /**\n * 获取可用语音列表\n */\n async getVoices(): Promise<VoiceInfo[]> {\n if (!this.strategy) {\n throw new Error('语音合成器未初始化');\n }\n return this.strategy.getVoices();\n }\n\n /**\n * 朗读文本\n */\n async speak(text: string, config?: SynthesisConfig): Promise<void> {\n if (this._status !== 'ready') {\n throw new Error('语音合成器未就绪');\n }\n\n return this.strategy?.speak(text, config);\n }\n\n /**\n * 暂停朗读\n */\n pause(): void {\n this.strategy?.pause();\n }\n\n /**\n * 继续朗读\n */\n resume(): void {\n this.strategy?.resume();\n }\n\n /**\n * 取消朗读\n */\n cancel(): void {\n this.strategy?.cancel();\n }\n\n /**\n * 是否正在朗读\n */\n isSpeaking(): boolean {\n return this.strategy?.isSpeaking() ?? false;\n }\n\n /**\n * 是否已暂停\n */\n isPaused(): boolean {\n return this.strategy?.isPaused() ?? false;\n }\n\n /**\n * 添加事件监听\n */\n on(event: SynthesisEventType, handler: SynthesisEventHandler): void {\n if (!this.eventHandlers.has(event)) {\n this.eventHandlers.set(event, new Set());\n }\n this.eventHandlers.get(event)!.add(handler);\n }\n\n /**\n * 移除事件监听\n */\n off(event: SynthesisEventType, handler: SynthesisEventHandler): void {\n this.eventHandlers.get(event)?.delete(handler);\n }\n\n /**\n * 触发事件\n */\n private emit(type: SynthesisEventType, event: SynthesisEvent): void {\n this.eventHandlers.get(type)?.forEach(handler => {\n try {\n handler(event);\n } catch (e) {\n console.error('[SpeechSynthesizer] 事件处理器错误:', e);\n }\n });\n }\n\n /**\n * 销毁实例\n */\n dispose(): void {\n this.strategy?.dispose();\n this.strategy = null;\n this.eventHandlers.clear();\n this._status = 'idle';\n }\n\n /**\n * 注册自定义提供商\n */\n registerProvider(type: SpeechProviderType, provider: SynthesisProvider): void {\n this.customProviders.set(type, provider);\n }\n\n /**\n * 使用云端适配器\n */\n useCloudAdapter(adapter: ICloudSynthesisAdapter): void {\n this.config.cloudAdapter = adapter;\n this.config.mode = 'cloud';\n }\n}\n\n// ============================================================================\n// 9. 工厂函数和工具函数\n// ============================================================================\n\n/**\n * 创建语音合成器实例\n * @param config - 可选的合成配置\n * @returns 语音合成器实例\n *\n * @example\n * ```typescript\n * // 使用原生合成\n * const synthesizer = await createSpeechSynthesizer({\n * lang: 'zh-CN',\n * rate: 1.0,\n * });\n *\n * // 使用云端合成 (Azure)\n * const azureAdapter = new AzureSynthesisAdapter('key', 'eastasia');\n * const cloudSynthesizer = await createSpeechSynthesizer({\n * mode: 'cloud',\n * cloudAdapter: azureAdapter,\n * });\n *\n * await synthesizer.speak('你好,世界!');\n * ```\n */\nexport async function createSpeechSynthesizer(\n config?: SynthesisConfig | IAdvancedSynthesisConfig\n): Promise<SpeechSynthesizer> {\n const synthesizer = new SpeechSynthesizerImpl();\n await synthesizer.initialize(config);\n return synthesizer;\n}\n\n/**\n * 检查当前环境是否支持语音合成\n * @returns 是否支持语音合成\n */\nexport function isSpeechSynthesisSupported(): boolean {\n return typeof window !== 'undefined' && 'speechSynthesis' in window;\n}\n\n/**\n * 快速朗读文本(一次性使用)\n * @param text - 要朗读的文本\n * @param config - 可选的合成配置\n *\n * @example\n * ```typescript\n * // 快速朗读\n * await speak('你好,世界!');\n *\n * // 带配置的朗读\n * await speak('Hello World', { lang: 'en-US', rate: 0.8 });\n * ```\n */\nexport async function speak(\n text: string,\n config?: SynthesisConfig | IAdvancedSynthesisConfig\n): Promise<void> {\n const synthesizer = await createSpeechSynthesizer(config);\n try {\n await synthesizer.speak(text, config);\n } finally {\n synthesizer.dispose();\n }\n}\n\n/**\n * 快速朗读文本(云端模式)\n * @param text - 要朗读的文本\n * @param adapter - 云端适配器\n * @param config - 可选配置\n */\nexport async function speakWithCloud(\n text: string,\n adapter: ICloudSynthesisAdapter,\n config?: SynthesisConfig\n): Promise<void> {\n const synthesizer = await createSpeechSynthesizer({\n ...config,\n mode: 'cloud',\n cloudAdapter: adapter,\n } as IAdvancedSynthesisConfig);\n\n try {\n await synthesizer.speak(text, config);\n } finally {\n synthesizer.dispose();\n }\n}\n","/**\n * @fileoverview 语音识别 (STT) 实现 - 商业级版本 v2.0\n * @module melange/plugins/speech/recognition\n * @description 生产级 Web 语音识别插件\n *\n * 架构:\n * [UI层] -> [SpeechRecognizerImpl] -> [NativeStrategy / CloudStrategy]\n * |\n * +-> [音频核心]: Worklet, VAD, Resample\n * +-> [适配器]: BaiduAdapter, XunfeiAdapter, TencentAdapter...\n *\n * 功能特性:\n * 1. 多模式: 支持 WebSocket 流式识别 & HTTP 短语音识别\n * 2. 状态机: IDLE -> CONNECTING -> RECORDING -> PROCESSING\n * 3. 插件化: 内置 讯飞/腾讯/百度/阿里/Google/Azure 适配器\n * 4. 核心: AudioWorklet + VAD + 自动重采样 + WAV编码\n * 5. 兼容性: 自动降级处理 (ScriptProcessor) + 断网缓冲队列\n */\n\nimport type {\n SpeechProviderType,\n SpeechServiceStatus,\n RecognitionConfig,\n RecognitionEventType,\n RecognitionEvent,\n RecognitionEventHandler,\n RecognitionProvider,\n SpeechRecognizer,\n RecognitionResult,\n} from './types';\n\n// ============================================================================\n// 1. 类型定义 & 枚举\n// ============================================================================\n\n// Window 接口扩展 - 支持浏览器语音 API 和 AudioContext\n// 使用 unknown 避免循环引用,实际类型在下方 BrowserSpeechRecognition 中定义\ndeclare global {\n interface Window {\n SpeechRecognition?: unknown;\n webkitSpeechRecognition?: unknown;\n webkitAudioContext?: typeof AudioContext;\n }\n}\n\n/**\n * 识别器状态枚举\n */\nexport enum RecognitionStatus {\n /** 空闲状态 */\n IDLE = 'IDLE',\n /** 连接中 */\n CONNECTING = 'CONNECTING',\n /** 录音中 */\n RECORDING = 'RECORDING',\n /** 处理中/上传中 */\n PROCESSING = 'PROCESSING',\n}\n\n/**\n * 识别引擎模式\n */\nexport type RecognitionEngineMode = 'native' | 'cloud' | 'auto';\n\n/**\n * 云端传输协议类型\n */\nexport type CloudTransportType = 'websocket' | 'http';\n\n/**\n * 识别结果接口\n */\nexport interface IRecognitionResult {\n /** 识别文本 */\n transcript: string;\n /** 是否为最终结果 */\n isFinal: boolean;\n /** 置信度 (0-1) */\n confidence: number;\n /** 原始响应数据 */\n original?: unknown;\n}\n\n/**\n * 识别错误接口\n */\nexport interface IRecognitionError {\n /** 错误代码 */\n code:\n | 'NETWORK'\n | 'NOT_ALLOWED'\n | 'NO_SPEECH'\n | 'NOT_SUPPORTED'\n | 'VAD_TIMEOUT'\n | 'ADAPTER_ERROR'\n | 'UNKNOWN';\n /** 错误信息 */\n message: string;\n /** 原始错误 */\n originalError?: unknown;\n}\n\n/**\n * 音频配置接口\n */\nexport interface IAudioConfig {\n /** 目标采样率 (默认 16000) */\n sampleRate?: number;\n /** VAD 阈值 (0.01 ~ 0.5) */\n vadThreshold?: number;\n /** VAD 静音超时 (ms) */\n vadDuration?: number;\n /** 是否启用回声消除 */\n echoCancellation?: boolean;\n /** 是否启用噪声抑制 */\n noiseSuppression?: boolean;\n /** 是否启用自动增益控制 */\n autoGainControl?: boolean;\n}\n\n/**\n * 高级识别配置\n */\nexport interface IAdvancedRecognitionConfig extends RecognitionConfig {\n /** 识别引擎模式 */\n mode?: RecognitionEngineMode;\n /** 云端适配器 */\n cloudAdapter?: ICloudRecognitionAdapter;\n /** 传输协议 */\n transport?: CloudTransportType;\n /** 音频配置 */\n audioConfig?: IAudioConfig;\n /** 是否启用自动重连 */\n autoReconnect?: boolean;\n /** 最大重连次数 */\n maxReconnectAttempts?: number;\n /** 重连间隔 (ms) */\n reconnectInterval?: number;\n}\n\n// ============================================================================\n// 2. 云端适配器接口\n// ============================================================================\n\n/**\n * 云端识别适配器接口\n * 提供统一的第三方语音识别服务集成接口\n */\nexport interface ICloudRecognitionAdapter {\n /** 适配器名称 */\n readonly name: string;\n\n /**\n * 获取 WebSocket 连接地址\n * @returns WebSocket URL\n */\n getConnectUrl?(): Promise<string> | string;\n\n /**\n * 获取握手参数\n * @returns 握手消息\n */\n getHandshakeParams?(): unknown;\n\n /**\n * HTTP 短语音识别\n * @param audioData WAV/PCM 二进制数据\n * @returns 识别结果\n */\n recognizeShortAudio?(audioData: ArrayBuffer): Promise<IRecognitionResult>;\n\n /**\n * 转换音频数据格式\n * @param pcmData PCM 原始数据\n * @returns 转换后的数据\n */\n transformAudioData?(pcmData: ArrayBuffer): ArrayBuffer | string;\n\n /**\n * 解析识别结果\n * @param data 原始响应数据\n * @returns 识别结果\n */\n parseResult(data: unknown): IRecognitionResult | null;\n\n /**\n * 检查适配器是否可用\n * @returns 是否可用\n */\n isAvailable?(): boolean;\n}\n\n// ============================================================================\n// 3. 音频工具类 (含 WAV 编码器)\n// ============================================================================\n\n/**\n * 音频处理工具集\n */\nexport const AudioUtils = {\n /**\n * 重采样音频数据\n * @param data 原始音频数据\n * @param inputRate 输入采样率\n * @param outputRate 输出采样率\n * @returns 重采样后的数据\n */\n resample(data: Float32Array, inputRate: number, outputRate: number): Float32Array {\n if (inputRate === outputRate) return data;\n const compression = inputRate / outputRate;\n const length = Math.ceil(data.length / compression);\n const result = new Float32Array(length);\n for (let i = 0; i < length; i++) {\n result[i] = data[Math.floor(i * compression)] ?? 0;\n }\n return result;\n },\n\n /**\n * Float32 转 Int16 PCM\n * @param input Float32 数据\n * @returns Int16 PCM 数据\n */\n floatTo16BitPCM(input: Float32Array): Int16Array {\n const output = new Int16Array(input.length);\n for (let i = 0; i < input.length; i++) {\n const s = Math.max(-1, Math.min(1, input[i] ?? 0));\n output[i] = s < 0 ? s * 0x8000 : s * 0x7fff;\n }\n return output;\n },\n\n /**\n * 计算音量 RMS\n * @param data 音频数据\n * @returns RMS 值\n */\n calculateRMS(data: Float32Array): number {\n let sum = 0;\n for (let i = 0; i < data.length; i++) {\n const sample = data[i] ?? 0;\n sum += sample * sample;\n }\n return Math.sqrt(sum / data.length);\n },\n\n /**\n * 合并 PCM 片段\n * @param buffers PCM 缓冲区数组\n * @param totalLength 总采样数\n * @returns 合并后的 Int16 数组\n */\n mergeBuffers(buffers: ArrayBuffer[], totalLength: number): Int16Array {\n const result = new Int16Array(totalLength);\n let offset = 0;\n for (const buffer of buffers) {\n const view = new Int16Array(buffer);\n result.set(view, offset);\n offset += view.length;\n }\n return result;\n },\n\n /**\n * PCM 转 WAV 封装\n * @param samples PCM 采样数据\n * @param sampleRate 采样率\n * @param channels 声道数\n * @returns WAV 格式 ArrayBuffer\n */\n encodeWAV(samples: Int16Array, sampleRate: number = 16000, channels: number = 1): ArrayBuffer {\n const buffer = new ArrayBuffer(44 + samples.length * 2);\n const view = new DataView(buffer);\n\n const writeString = (offset: number, str: string): void => {\n for (let i = 0; i < str.length; i++) {\n view.setUint8(offset + i, str.charCodeAt(i));\n }\n };\n\n // RIFF Header\n writeString(0, 'RIFF');\n view.setUint32(4, 36 + samples.length * 2, true);\n writeString(8, 'WAVE');\n\n // fmt chunk\n writeString(12, 'fmt ');\n view.setUint32(16, 16, true); // chunk size\n view.setUint16(20, 1, true); // PCM format\n view.setUint16(22, channels, true); // channels\n view.setUint32(24, sampleRate, true); // sample rate\n view.setUint32(28, sampleRate * channels * 2, true); // byte rate\n view.setUint16(32, channels * 2, true); // block align\n view.setUint16(34, 16, true); // bits per sample\n\n // data chunk\n writeString(36, 'data');\n view.setUint32(40, samples.length * 2, true);\n\n // 写入采样数据\n const dataOffset = 44;\n for (let i = 0; i < samples.length; i++) {\n view.setInt16(dataOffset + i * 2, samples[i] ?? 0, true);\n }\n\n return buffer;\n },\n\n /**\n * ArrayBuffer 转 Base64\n * @param buffer ArrayBuffer\n * @returns Base64 字符串\n */\n arrayBufferToBase64(buffer: ArrayBuffer): string {\n let binary = '';\n const bytes = new Uint8Array(buffer);\n const len = bytes.byteLength;\n for (let i = 0; i < len; i++) {\n binary += String.fromCharCode(bytes[i] ?? 0);\n }\n return typeof btoa !== 'undefined' ? btoa(binary) : Buffer.from(binary).toString('base64');\n },\n};\n\n// ============================================================================\n// 4. AudioWorklet 核心代码\n// ============================================================================\n\n/**\n * AudioWorklet 处理器代码\n * 在音频线程中运行,实现实时音频处理\n */\nconst WORKLET_CODE = `\nclass SpeechProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this.buffer = [];\n this.targetRate = 16000;\n this.currentRate = 44100;\n this.silenceFrames = 0;\n this.maxSilenceFrames = 0;\n this.vadThreshold = 0.02;\n this.isRecording = false;\n this.port.onmessage = this.handleMessage.bind(this);\n }\n\n static get parameterDescriptors() {\n return [];\n }\n\n process(inputs) {\n const input = inputs[0];\n if (!input || !input.length || !this.isRecording) return true;\n const channelData = input[0];\n\n // VAD 检测\n let sum = 0;\n for (let i = 0; i < channelData.length; i++) {\n sum += channelData[i] * channelData[i];\n }\n const rms = Math.sqrt(sum / channelData.length);\n\n if (rms < this.vadThreshold) {\n this.silenceFrames++;\n if (this.maxSilenceFrames > 0 && this.silenceFrames > this.maxSilenceFrames) {\n this.port.postMessage({ type: 'VAD_TIMEOUT' });\n this.silenceFrames = 0;\n }\n } else {\n this.silenceFrames = 0;\n }\n\n // 重采样\n if (this.targetRate < this.currentRate) {\n const compression = this.currentRate / this.targetRate;\n for (let i = 0; i < channelData.length; i += compression) {\n this.buffer.push(channelData[Math.floor(i)]);\n }\n } else {\n this.buffer.push(...channelData);\n }\n\n // 定期刷新 (~128ms)\n if (this.buffer.length >= 2048) {\n this.flush();\n }\n return true;\n }\n\n flush() {\n if (this.buffer.length === 0) return;\n const pcmData = new Int16Array(this.buffer.length);\n for (let i = 0; i < this.buffer.length; i++) {\n let s = Math.max(-1, Math.min(1, this.buffer[i]));\n s = s < 0 ? s * 0x8000 : s * 0x7FFF;\n pcmData[i] = s;\n }\n this.port.postMessage({ type: 'AUDIO_DATA', payload: pcmData.buffer }, [pcmData.buffer]);\n this.buffer = [];\n }\n\n handleMessage(event) {\n const { type, payload } = event.data;\n if (type === 'CONFIG') {\n this.targetRate = payload.targetRate || 16000;\n this.currentRate = payload.currentRate || 44100;\n this.vadThreshold = payload.vadThreshold || 0.02;\n const secondsPerBlock = 128 / this.currentRate;\n this.maxSilenceFrames = (payload.vadDuration / 1000) / secondsPerBlock;\n }\n if (type === 'SET_RECORDING') {\n this.isRecording = payload;\n if (!payload) this.flush();\n }\n }\n}\nregisterProcessor('speech-processor', SpeechProcessor);\n`;\n\n// ============================================================================\n// 5. 浏览器 Speech Recognition API 类型声明\n// ============================================================================\n\ninterface BrowserSpeechRecognitionResultList {\n readonly length: number;\n item(index: number): BrowserSpeechRecognitionResult | null;\n [index: number]: BrowserSpeechRecognitionResult;\n}\n\ninterface BrowserSpeechRecognitionResult {\n readonly length: number;\n readonly isFinal: boolean;\n item(index: number): BrowserSpeechRecognitionAlternative | null;\n [index: number]: BrowserSpeechRecognitionAlternative;\n}\n\ninterface BrowserSpeechRecognitionAlternative {\n readonly transcript: string;\n readonly confidence: number;\n}\n\ninterface BrowserSpeechRecognitionEvent {\n readonly results: BrowserSpeechRecognitionResultList;\n readonly resultIndex: number;\n}\n\ninterface BrowserSpeechRecognitionErrorEvent {\n readonly error: string;\n readonly message: string;\n}\n\ninterface BrowserSpeechRecognition extends EventTarget {\n lang: string;\n continuous: boolean;\n interimResults: boolean;\n maxAlternatives: number;\n start(): void;\n stop(): void;\n abort(): void;\n onstart: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onend: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onresult: ((this: BrowserSpeechRecognition, ev: BrowserSpeechRecognitionEvent) => void) | null;\n onerror:\n | ((this: BrowserSpeechRecognition, ev: BrowserSpeechRecognitionErrorEvent) => void)\n | null;\n onsoundstart: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onsoundend: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onspeechstart: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onspeechend: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onaudiostart: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onaudioend: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onnomatch: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n}\n\ninterface BrowserSpeechRecognitionConstructor {\n new (): BrowserSpeechRecognition;\n}\n\n// ============================================================================\n// 6. 内置云端适配器实现\n// ============================================================================\n\n/**\n * 通用适配器 (BFF 模式 - 推荐)\n * 适用于自建后端代理场景\n */\nexport class GenericAdapter implements ICloudRecognitionAdapter {\n readonly name = 'Generic/BFF';\n\n constructor(private baseUrl: string) {}\n\n getConnectUrl(): string {\n return this.baseUrl.replace(/^http/, 'ws');\n }\n\n async recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult> {\n const formData = new FormData();\n formData.append('file', new Blob([audioData], { type: 'audio/wav' }));\n\n const res = await fetch(`${this.baseUrl}/recognize`, {\n method: 'POST',\n body: formData,\n });\n\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}: ${res.statusText}`);\n }\n\n const json = (await res.json()) as Record<string, unknown>;\n const result = this.parseResult(json);\n if (!result) throw new Error('解析结果失败');\n return result;\n }\n\n parseResult(data: Record<string, unknown>): IRecognitionResult | null {\n return {\n transcript: (data['text'] as string) || (data['transcript'] as string) || '',\n isFinal: true,\n confidence: (data['score'] as number) || (data['confidence'] as number) || 0.9,\n original: data,\n };\n }\n}\n\n/**\n * 讯飞云适配器\n * 支持讯飞语音听写 WebAPI\n */\nexport class XunfeiAdapter implements ICloudRecognitionAdapter {\n readonly name = 'Xunfei';\n /** API Key - 生产环境应在后端使用 */\n readonly apiKey: string | undefined;\n /** API Secret - 生产环境应在后端使用 */\n readonly apiSecret: string | undefined;\n\n constructor(\n private appId: string,\n apiKey?: string,\n apiSecret?: string\n ) {\n this.apiKey = apiKey;\n this.apiSecret = apiSecret;\n }\n\n getConnectUrl(): string {\n // 生产环境应在后端生成鉴权 URL\n // 参见: https://www.xfyun.cn/doc/asr/voicedictation/API.html\n const host = 'iat-api.xfyun.cn';\n const path = '/v2/iat';\n // 简化演示,实际需要计算 authorization\n return `wss://${host}${path}?authorization=...&date=...&host=${host}`;\n }\n\n getHandshakeParams(): Record<string, unknown> {\n return {\n common: { app_id: this.appId },\n business: {\n language: 'zh_cn',\n domain: 'iat',\n accent: 'mandarin',\n vad_eos: 3000,\n },\n data: {\n status: 0,\n format: 'audio/L16;rate=16000',\n encoding: 'raw',\n },\n };\n }\n\n async recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult> {\n const blob = new Blob([audioData], { type: 'audio/wav' });\n const formData = new FormData();\n formData.append('audio', blob);\n formData.append('engine_type', 'sms16k');\n\n const response = await fetch('https://api.xfyun.cn/v1/service/v1/iat', {\n method: 'POST',\n headers: {\n 'X-Appid': this.appId,\n // 生产环境需添加: 'X-CurTime', 'X-Param', 'X-CheckSum'\n },\n body: formData,\n });\n\n const data = (await response.json()) as Record<string, unknown>;\n const result = this.parseResult(data);\n if (!result) throw new Error('讯飞识别失败');\n return result;\n }\n\n parseResult(data: Record<string, unknown>): IRecognitionResult | null {\n // WebSocket 响应格式\n if (data['code'] !== undefined && data['code'] !== 0) {\n return null;\n }\n\n let text = '';\n\n // WebSocket 格式\n const wsData = data['data'] as Record<string, unknown> | undefined;\n if (wsData?.['result']) {\n const result = wsData['result'] as { ws?: Array<{ cw: Array<{ w: string }> }> };\n text = result.ws?.map(w => w.cw[0]?.w ?? '').join('') ?? '';\n }\n\n // HTTP 格式\n if (data['desc'] === 'success' && typeof data['data'] === 'string') {\n text = data['data'];\n }\n\n if (!text) return null;\n\n return {\n transcript: text,\n isFinal: wsData?.['status'] === 2 || !!data['desc'],\n confidence: 0.9,\n original: data,\n };\n }\n}\n\n/**\n * 腾讯云适配器\n * 支持腾讯云一句话识别\n */\nexport class TencentAdapter implements ICloudRecognitionAdapter {\n readonly name = 'Tencent';\n /** Secret ID - 生产环境应在后端使用 */\n readonly secretId: string;\n /** Secret Key - 生产环境应在后端使用 */\n readonly secretKey: string;\n\n constructor(secretId: string, secretKey: string) {\n this.secretId = secretId;\n this.secretKey = secretKey;\n }\n\n async recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult> {\n // TC3-HMAC-SHA256 签名应在后端完成\n const base64Audio = AudioUtils.arrayBufferToBase64(audioData);\n\n const payload = {\n ProjectId: 0,\n SubServiceType: 2,\n EngSerViceType: '16k_zh',\n SourceType: 1,\n VoiceFormat: 'wav',\n UsrAudioKey: `session-${Date.now()}`,\n Data: base64Audio,\n DataLen: audioData.byteLength,\n };\n\n const res = await fetch('https://asr.tencentcloudapi.com', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-TC-Action': 'SentenceRecognition',\n // 生产环境需添加: 'Authorization', 'X-TC-Timestamp' 等\n },\n body: JSON.stringify(payload),\n });\n\n const json = (await res.json()) as Record<string, unknown>;\n const result = this.parseResult(json);\n if (!result) throw new Error('腾讯云识别失败');\n return result;\n }\n\n parseResult(data: Record<string, unknown>): IRecognitionResult | null {\n const resp = data['Response'] as Record<string, unknown> | undefined;\n if (resp?.['Error']) {\n const error = resp['Error'] as { Message?: string };\n throw new Error(error.Message ?? '腾讯云 API 错误');\n }\n if (resp?.['Result']) {\n return {\n transcript: resp['Result'] as string,\n isFinal: true,\n confidence: 0.9,\n original: data,\n };\n }\n return null;\n }\n}\n\n/**\n * 百度云适配器\n * 支持百度语音识别 REST API 和 WebSocket API\n */\nexport class BaiduAdapter implements ICloudRecognitionAdapter {\n readonly name = 'Baidu';\n\n constructor(\n private accessToken: string,\n private appId?: string,\n private appKey?: string,\n private devPid: number = 1537\n ) {}\n\n getConnectUrl(): string {\n const sn = Math.random().toString(36).substring(2) + Date.now();\n return `wss://vop.baidu.com/realtime_asr?sn=${sn}`;\n }\n\n getHandshakeParams(): Record<string, unknown> {\n if (!this.appId || !this.appKey) {\n console.warn('[BaiduAdapter] WebSocket 模式需要 appId 和 appKey');\n }\n return {\n type: 'START',\n data: {\n appid: Number(this.appId),\n appkey: this.appKey,\n dev_pid: this.devPid,\n cuid: `sdk-user-${Date.now()}`,\n format: 'pcm',\n sample: 16000,\n },\n };\n }\n\n async recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult> {\n const base64Audio = AudioUtils.arrayBufferToBase64(audioData);\n\n const payload = {\n format: 'wav',\n rate: 16000,\n channel: 1,\n cuid: `sdk-user-${Date.now()}`,\n token: this.accessToken,\n dev_pid: this.devPid,\n speech: base64Audio,\n len: audioData.byteLength,\n };\n\n // 建议通过 BFF 代理调用,避免 CORS 问题\n const response = await fetch('/api/baidu-speech/pro_api', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n\n const data = (await response.json()) as Record<string, unknown>;\n const result = this.parseResult(data);\n if (!result) throw new Error('百度识别失败');\n return result;\n }\n\n parseResult(data: Record<string, unknown>): IRecognitionResult | null {\n // HTTP 响应\n if (data['err_no'] !== undefined) {\n if (data['err_no'] !== 0) {\n throw new Error(`Baidu API Error [${String(data['err_no'])}]: ${String(data['err_msg'])}`);\n }\n const result = data['result'] as string[] | undefined;\n if (result && result.length > 0) {\n return {\n transcript: result[0] ?? '',\n isFinal: true,\n confidence: 0.9,\n original: data,\n };\n }\n }\n\n // WebSocket 响应\n if (data['type']) {\n if (data['type'] === 'HEARTBEAT') return null;\n if (data['type'] === 'ERROR') {\n throw new Error(`Baidu WS Error: ${String(data['err_msg'])}`);\n }\n if (data['type'] === 'MID_TEXT' || data['type'] === 'FIN_TEXT') {\n return {\n transcript: data['result'] as string,\n isFinal: data['type'] === 'FIN_TEXT',\n confidence: 0.9,\n original: data,\n };\n }\n }\n\n return null;\n }\n}\n\n/**\n * 阿里云适配器\n * 支持阿里云智能语音交互\n */\nexport class AlibabaAdapter implements ICloudRecognitionAdapter {\n readonly name = 'Alibaba';\n /** Access Key Secret - 生产环境应在后端使用 */\n readonly accessKeySecret: string;\n\n constructor(\n private accessKeyId: string,\n accessKeySecret: string,\n private appKey: string\n ) {\n this.accessKeySecret = accessKeySecret;\n }\n\n getConnectUrl(): string {\n // 阿里云实时语音识别 WebSocket 地址\n return `wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1`;\n }\n\n getHandshakeParams(): Record<string, unknown> {\n return {\n header: {\n message_id: this.generateUUID(),\n task_id: this.generateUUID(),\n namespace: 'SpeechRecognizer',\n name: 'StartRecognition',\n appkey: this.appKey,\n },\n payload: {\n format: 'pcm',\n sample_rate: 16000,\n enable_intermediate_result: true,\n enable_punctuation_prediction: true,\n enable_inverse_text_normalization: true,\n },\n };\n }\n\n async recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult> {\n const base64Audio = AudioUtils.arrayBufferToBase64(audioData);\n\n // 建议通过 BFF 代理调用\n const response = await fetch('/api/alibaba-speech/recognize', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-NLS-Token': this.accessKeyId,\n },\n body: JSON.stringify({\n appkey: this.appKey,\n format: 'wav',\n sample_rate: 16000,\n audio: base64Audio,\n }),\n });\n\n const data = (await response.json()) as Record<string, unknown>;\n const result = this.parseResult(data);\n if (!result) throw new Error('阿里云识别失败');\n return result;\n }\n\n parseResult(data: Record<string, unknown>): IRecognitionResult | null {\n // WebSocket 响应\n const header = data['header'] as Record<string, unknown> | undefined;\n if (header) {\n const status = header['status'] as number;\n if (status !== 20000000) {\n throw new Error(`Alibaba Error [${status}]: ${String(header['status_text'])}`);\n }\n\n const payload = data['payload'] as Record<string, unknown> | undefined;\n if (payload?.['result']) {\n return {\n transcript: payload['result'] as string,\n isFinal: header['name'] === 'RecognitionCompleted',\n confidence: 0.9,\n original: data,\n };\n }\n }\n\n // HTTP 响应\n if (data['result']) {\n return {\n transcript: data['result'] as string,\n isFinal: true,\n confidence: (data['confidence'] as number) || 0.9,\n original: data,\n };\n }\n\n return null;\n }\n\n private generateUUID(): string {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n}\n\n/**\n * Google Cloud Speech 适配器\n */\nexport class GoogleAdapter implements ICloudRecognitionAdapter {\n readonly name = 'Google';\n\n constructor(\n private apiKey: string,\n private languageCode: string = 'zh-CN'\n ) {}\n\n async recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult> {\n const base64Audio = AudioUtils.arrayBufferToBase64(audioData);\n\n const payload = {\n config: {\n encoding: 'LINEAR16',\n sampleRateHertz: 16000,\n languageCode: this.languageCode,\n enableAutomaticPunctuation: true,\n },\n audio: {\n content: base64Audio,\n },\n };\n\n const response = await fetch(\n `https://speech.googleapis.com/v1/speech:recognize?key=${this.apiKey}`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n }\n );\n\n const data = (await response.json()) as Record<string, unknown>;\n const result = this.parseResult(data);\n if (!result) throw new Error('Google 识别失败');\n return result;\n }\n\n parseResult(data: Record<string, unknown>): IRecognitionResult | null {\n if (data['error']) {\n const error = data['error'] as { message?: string };\n throw new Error(error.message ?? 'Google API Error');\n }\n\n const results = data['results'] as Array<{\n alternatives?: Array<{ transcript?: string; confidence?: number }>;\n }>;\n\n if (results && results.length > 0) {\n const alternatives = results[0]?.alternatives;\n if (alternatives && alternatives.length > 0) {\n return {\n transcript: alternatives[0]?.transcript ?? '',\n isFinal: true,\n confidence: alternatives[0]?.confidence ?? 0.9,\n original: data,\n };\n }\n }\n\n return null;\n }\n}\n\n/**\n * Azure Speech 适配器\n */\nexport class AzureAdapter implements ICloudRecognitionAdapter {\n readonly name = 'Azure';\n\n constructor(\n private subscriptionKey: string,\n private region: string,\n private language: string = 'zh-CN'\n ) {}\n\n getConnectUrl(): string {\n return `wss://${this.region}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?language=${this.language}`;\n }\n\n getHandshakeParams(): Record<string, unknown> {\n return {\n 'Ocp-Apim-Subscription-Key': this.subscriptionKey,\n };\n }\n\n async recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult> {\n const response = await fetch(\n `https://${this.region}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?language=${this.language}`,\n {\n method: 'POST',\n headers: {\n 'Ocp-Apim-Subscription-Key': this.subscriptionKey,\n 'Content-Type': 'audio/wav; codecs=audio/pcm; samplerate=16000',\n },\n body: audioData,\n }\n );\n\n const data = (await response.json()) as Record<string, unknown>;\n const result = this.parseResult(data);\n if (!result) throw new Error('Azure 识别失败');\n return result;\n }\n\n parseResult(data: Record<string, unknown>): IRecognitionResult | null {\n if (data['RecognitionStatus'] === 'Success') {\n return {\n transcript: (data['DisplayText'] as string) || (data['Text'] as string) || '',\n isFinal: true,\n confidence: (data['Confidence'] as number) || 0.9,\n original: data,\n };\n }\n\n // WebSocket 分片响应\n if (data['Text']) {\n return {\n transcript: data['Text'] as string,\n isFinal: data['RecognitionStatus'] === 'Success',\n confidence: 0.9,\n original: data,\n };\n }\n\n return null;\n }\n}\n\n// ============================================================================\n// 7. 抽象策略基类\n// ============================================================================\n\n/**\n * 事件监听器类型定义\n */\ntype EventListeners = {\n result: Array<(res: IRecognitionResult) => void>;\n error: Array<(err: IRecognitionError) => void>;\n state: Array<(status: RecognitionStatus) => void>;\n start: Array<() => void>;\n end: Array<() => void>;\n soundstart: Array<() => void>;\n soundend: Array<() => void>;\n speechstart: Array<() => void>;\n speechend: Array<() => void>;\n audiostart: Array<() => void>;\n audioend: Array<() => void>;\n};\n\n/**\n * 识别策略基类\n */\nabstract class BaseRecognitionStrategy {\n protected listeners: EventListeners = {\n result: [],\n error: [],\n state: [],\n start: [],\n end: [],\n soundstart: [],\n soundend: [],\n speechstart: [],\n speechend: [],\n audiostart: [],\n audioend: [],\n };\n\n protected _status: RecognitionStatus = RecognitionStatus.IDLE;\n\n constructor(protected config: IAdvancedRecognitionConfig) {}\n\n /**\n * 获取当前状态\n */\n get status(): RecognitionStatus {\n return this._status;\n }\n\n /**\n * 开始识别\n */\n abstract start(): Promise<void>;\n\n /**\n * 停止识别\n */\n abstract stop(): void;\n\n /**\n * 中止识别\n */\n abstract abort(): void;\n\n /**\n * 是否正在录音\n */\n abstract isListening(): boolean;\n\n /**\n * 设置状态\n */\n protected setStatus(status: RecognitionStatus): void {\n if (this._status !== status) {\n this._status = status;\n this.emit('state', status);\n }\n }\n\n /**\n * 添加事件监听\n */\n on<K extends keyof EventListeners>(event: K, fn: EventListeners[K][number]): void {\n (this.listeners[event] as Array<typeof fn>).push(fn);\n }\n\n /**\n * 移除事件监听\n */\n off<K extends keyof EventListeners>(event: K, fn: EventListeners[K][number]): void {\n const listeners = this.listeners[event] as Array<typeof fn>;\n const index = listeners.indexOf(fn);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n }\n\n /**\n * 触发事件\n */\n protected emit<K extends keyof EventListeners>(\n event: K,\n data?: Parameters<EventListeners[K][number]>[0]\n ): void {\n const listeners = this.listeners[event] as Array<(arg?: typeof data) => void>;\n listeners.forEach(fn => {\n try {\n fn(data);\n } catch (e) {\n console.error(`[Recognition] 事件处理器错误 (${event}):`, e);\n }\n });\n }\n\n /**\n * 销毁资源\n */\n dispose(): void {\n this.abort();\n Object.keys(this.listeners).forEach(key => {\n (this.listeners as Record<string, unknown[]>)[key] = [];\n });\n }\n}\n\n// ============================================================================\n// 8. 原生识别策略\n// ============================================================================\n\n/**\n * 浏览器原生语音识别策略\n * 使用 Web Speech API\n */\nclass NativeRecognitionStrategy extends BaseRecognitionStrategy {\n private recognition: BrowserSpeechRecognition | null = null;\n private SpeechRecognitionClass: BrowserSpeechRecognitionConstructor | null = null;\n\n constructor(config: IAdvancedRecognitionConfig) {\n super(config);\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const srClass =\n typeof window !== 'undefined'\n ? ((window.SpeechRecognition as BrowserSpeechRecognitionConstructor | undefined) ??\n (window.webkitSpeechRecognition as BrowserSpeechRecognitionConstructor | undefined))\n : undefined;\n this.SpeechRecognitionClass = srClass ?? null;\n }\n\n /**\n * 检查是否可用\n */\n isAvailable(): boolean {\n return this.SpeechRecognitionClass !== null;\n }\n\n async start(): Promise<void> {\n if (!this.SpeechRecognitionClass) {\n throw { code: 'NOT_SUPPORTED', message: '浏览器不支持语音识别' };\n }\n\n if (this._status !== RecognitionStatus.IDLE) {\n return;\n }\n\n this.setStatus(RecognitionStatus.CONNECTING);\n\n return new Promise((resolve, reject) => {\n this.recognition = new this.SpeechRecognitionClass!();\n\n // 配置\n this.recognition.lang = this.config.lang ?? 'zh-CN';\n this.recognition.continuous = this.config.continuous ?? false;\n this.recognition.interimResults = this.config.interimResults ?? true;\n this.recognition.maxAlternatives = this.config.maxAlternatives ?? 1;\n\n // 事件处理\n this.recognition.onstart = () => {\n this.setStatus(RecognitionStatus.RECORDING);\n this.emit('start');\n this.emit('audiostart');\n resolve();\n };\n\n this.recognition.onend = () => {\n this.setStatus(RecognitionStatus.IDLE);\n this.emit('audioend');\n this.emit('end');\n };\n\n this.recognition.onresult = e => {\n const results = e.results[e.resultIndex];\n if (results?.[0]) {\n this.emit('result', {\n transcript: results[0].transcript,\n isFinal: results.isFinal,\n confidence: results[0].confidence,\n original: e,\n });\n }\n };\n\n this.recognition.onerror = e => {\n const errorMap: Record<string, IRecognitionError['code']> = {\n 'not-allowed': 'NOT_ALLOWED',\n 'no-speech': 'NO_SPEECH',\n network: 'NETWORK',\n };\n\n const error: IRecognitionError = {\n code: errorMap[e.error] ?? 'UNKNOWN',\n message: this.getErrorMessage(e.error),\n originalError: e,\n };\n\n this.setStatus(RecognitionStatus.IDLE);\n this.emit('error', error);\n\n if (e.error === 'not-allowed' || e.error === 'audio-capture') {\n reject(error);\n }\n };\n\n this.recognition.onsoundstart = () => this.emit('soundstart');\n this.recognition.onsoundend = () => this.emit('soundend');\n this.recognition.onspeechstart = () => this.emit('speechstart');\n this.recognition.onspeechend = () => this.emit('speechend');\n\n try {\n this.recognition.start();\n } catch (e) {\n this.setStatus(RecognitionStatus.IDLE);\n reject({ code: 'UNKNOWN', message: '启动识别失败', originalError: e });\n }\n });\n }\n\n stop(): void {\n if (this.recognition && this._status === RecognitionStatus.RECORDING) {\n this.recognition.stop();\n }\n }\n\n abort(): void {\n if (this.recognition) {\n this.recognition.abort();\n this.setStatus(RecognitionStatus.IDLE);\n }\n }\n\n isListening(): boolean {\n return this._status === RecognitionStatus.RECORDING;\n }\n\n private getErrorMessage(errorCode: string): string {\n const messages: Record<string, string> = {\n 'no-speech': '未检测到语音输入',\n 'audio-capture': '无法访问麦克风',\n 'not-allowed': '麦克风权限被拒绝',\n network: '网络错误',\n aborted: '识别被中止',\n 'language-not-supported': '不支持的语言',\n 'service-not-allowed': '语音服务不可用',\n };\n return messages[errorCode] ?? `语音识别错误: ${errorCode}`;\n }\n}\n\n// ============================================================================\n// 9. 云端识别策略\n// ============================================================================\n\n/**\n * 云端语音识别策略\n * 支持 WebSocket 流式识别和 HTTP 短语音识别\n */\nclass CloudRecognitionStrategy extends BaseRecognitionStrategy {\n private audioContext: AudioContext | null = null;\n private mediaStream: MediaStream | null = null;\n private workletNode: AudioWorkletNode | null = null;\n private scriptProcessor: ScriptProcessorNode | null = null;\n private socket: WebSocket | null = null;\n private adapter: ICloudRecognitionAdapter;\n private transport: CloudTransportType;\n\n // HTTP 模式缓冲\n private pcmChunks: ArrayBuffer[] = [];\n private totalPCMLength = 0;\n\n // 页面可见性监听器\n private visibilityHandler: (() => void) | null = null;\n\n // 弱网消息队列\n private msgQueue: ArrayBuffer[] = [];\n private readonly MSG_QUEUE_MAX = 50;\n\n // ScriptProcessor 降级参数\n private spSilenceCount = 0;\n private spMaxSilence = 0;\n private isRecordingFlag = false;\n\n // 重连参数\n private reconnectAttempts = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Worklet 加载标记\n private workletLoaded = false;\n\n constructor(config: IAdvancedRecognitionConfig) {\n super(config);\n if (!config.cloudAdapter) {\n throw new Error('[CloudStrategy] 需要提供 cloudAdapter');\n }\n this.adapter = config.cloudAdapter;\n this.transport = config.transport ?? 'websocket';\n }\n\n async start(): Promise<void> {\n if (this._status !== RecognitionStatus.IDLE) {\n return;\n }\n\n this.setStatus(RecognitionStatus.CONNECTING);\n this.pcmChunks = [];\n this.totalPCMLength = 0;\n this.reconnectAttempts = 0;\n\n try {\n // 1. WebSocket 模式预连接\n if (this.transport === 'websocket') {\n if (!this.adapter.getConnectUrl) {\n throw new Error('适配器缺少 getConnectUrl 方法');\n }\n const url = await Promise.resolve(this.adapter.getConnectUrl());\n await this.initWebSocket(url);\n }\n\n // 2. 获取麦克风权限\n const audioConfig = this.config.audioConfig ?? {};\n this.mediaStream = await navigator.mediaDevices.getUserMedia({\n audio: {\n echoCancellation: audioConfig.echoCancellation ?? true,\n noiseSuppression: audioConfig.noiseSuppression ?? true,\n autoGainControl: audioConfig.autoGainControl ?? true,\n },\n });\n\n // 3. 初始化音频上下文\n await this.initAudioContext();\n\n // 4. HTTP 模式直接进入录音状态\n if (this.transport === 'http') {\n this.setStatus(RecognitionStatus.RECORDING);\n }\n\n // 5. 监听页面可见性\n this.setupVisibilityListener();\n\n this.emit('start');\n this.emit('audiostart');\n } catch (err: unknown) {\n const error = err as Error;\n this.emit('error', {\n code: 'NOT_ALLOWED',\n message: error.message || '启动失败',\n originalError: err,\n });\n this.cleanup();\n throw err;\n }\n }\n\n /**\n * 初始化 WebSocket 连接\n */\n private initWebSocket(url: string): Promise<void> {\n return new Promise((resolve, reject) => {\n this.socket = new WebSocket(url);\n this.socket.binaryType = 'arraybuffer';\n\n const timeout = setTimeout(() => {\n reject(new Error('WebSocket 连接超时'));\n }, 10000);\n\n this.socket.onopen = () => {\n clearTimeout(timeout);\n this.setStatus(RecognitionStatus.RECORDING);\n this.reconnectAttempts = 0;\n\n // 发送握手消息\n if (this.adapter.getHandshakeParams) {\n const params = this.adapter.getHandshakeParams();\n if (params) {\n const msg = typeof params === 'string' ? params : JSON.stringify(params);\n this.socket?.send(msg);\n }\n }\n resolve();\n };\n\n this.socket.onerror = e => {\n clearTimeout(timeout);\n reject(e);\n };\n\n this.socket.onmessage = e => {\n try {\n const data = e.data as string | ArrayBuffer;\n const raw = typeof data === 'string' ? data : new TextDecoder().decode(data);\n const res = this.adapter.parseResult(JSON.parse(raw));\n if (res) {\n this.emit('result', res);\n }\n } catch {\n // 忽略解析错误\n }\n };\n\n this.socket.onclose = () => {\n if (this._status === RecognitionStatus.RECORDING) {\n this.handleReconnect();\n }\n };\n });\n }\n\n /**\n * 处理重连逻辑\n */\n private handleReconnect(): void {\n const maxAttempts = this.config.maxReconnectAttempts ?? 3;\n const interval = this.config.reconnectInterval ?? 2000;\n\n if (this.config.autoReconnect && this.reconnectAttempts < maxAttempts) {\n this.reconnectAttempts++;\n // eslint-disable-next-line no-console\n console.log(`[CloudStrategy] 尝试重连 (${this.reconnectAttempts}/${maxAttempts})`);\n\n this.reconnectTimer = setTimeout(() => {\n void (async () => {\n try {\n if (this.adapter.getConnectUrl) {\n const url = await Promise.resolve(this.adapter.getConnectUrl());\n await this.initWebSocket(url);\n }\n } catch {\n this.handleReconnect();\n }\n })();\n }, interval);\n } else {\n this.emit('error', {\n code: 'NETWORK',\n message: '连接已断开',\n });\n void this.stop();\n }\n }\n\n /**\n * 初始化音频上下文\n */\n private async initAudioContext(): Promise<void> {\n const AudioCtor =\n typeof window !== 'undefined' && (window.AudioContext || window.webkitAudioContext);\n if (!AudioCtor) {\n throw new Error('浏览器不支持 AudioContext');\n }\n\n this.audioContext = new AudioCtor();\n if (this.audioContext.state === 'suspended') {\n await this.audioContext.resume();\n }\n\n const source = this.audioContext.createMediaStreamSource(this.mediaStream!);\n\n // 优先使用 AudioWorklet\n if (this.audioContext.audioWorklet && !this.workletLoaded) {\n try {\n const blob = new Blob([WORKLET_CODE], { type: 'application/javascript' });\n await this.audioContext.audioWorklet.addModule(URL.createObjectURL(blob));\n this.workletLoaded = true;\n this.setupWorklet(source);\n console.log('[CloudStrategy] 使用 AudioWorklet 模式');\n return;\n } catch (e) {\n console.warn('[CloudStrategy] AudioWorklet 加载失败,降级到 ScriptProcessor:', e);\n }\n }\n\n // 降级到 ScriptProcessor\n this.setupScriptProcessor(source);\n console.log('[CloudStrategy] 使用 ScriptProcessor 降级模式');\n }\n\n /**\n * 设置 AudioWorklet\n */\n private setupWorklet(source: MediaStreamAudioSourceNode): void {\n this.workletNode = new AudioWorkletNode(this.audioContext!, 'speech-processor');\n\n const audioConfig = this.config.audioConfig ?? {};\n this.workletNode.port.postMessage({\n type: 'CONFIG',\n payload: {\n currentRate: this.audioContext!.sampleRate,\n targetRate: audioConfig.sampleRate ?? 16000,\n vadThreshold: audioConfig.vadThreshold ?? 0.02,\n vadDuration: audioConfig.vadDuration ?? 3000,\n },\n });\n\n this.workletNode.port.onmessage = (\n e: MessageEvent<{ type: string; payload?: ArrayBuffer }>\n ) => {\n const { type, payload } = e.data;\n if (type === 'AUDIO_DATA' && payload) {\n this.handlePCM(payload);\n }\n if (type === 'VAD_TIMEOUT') {\n this.emit('speechend');\n void this.stop();\n }\n };\n\n this.workletNode.port.postMessage({ type: 'SET_RECORDING', payload: true });\n source.connect(this.workletNode);\n this.workletNode.connect(this.audioContext!.destination);\n\n this.emit('speechstart');\n }\n\n /**\n * 设置 ScriptProcessor (降级方案)\n */\n private setupScriptProcessor(source: MediaStreamAudioSourceNode): void {\n const bufferSize = 4096;\n this.scriptProcessor = this.audioContext!.createScriptProcessor(bufferSize, 1, 1);\n\n const audioConfig = this.config.audioConfig ?? {};\n const targetRate = audioConfig.sampleRate ?? 16000;\n const currentRate = this.audioContext!.sampleRate;\n\n // VAD 参数\n const secondsPerBuf = bufferSize / currentRate;\n this.spMaxSilence = (audioConfig.vadDuration ?? 3000) / 1000 / secondsPerBuf;\n this.spSilenceCount = 0;\n this.isRecordingFlag = true;\n\n this.scriptProcessor.onaudioprocess = e => {\n if (!this.isRecordingFlag) return;\n\n const input = e.inputBuffer.getChannelData(0);\n\n // VAD 检测\n const rms = AudioUtils.calculateRMS(input);\n if (rms < (audioConfig.vadThreshold ?? 0.02)) {\n this.spSilenceCount++;\n if (this.spSilenceCount > this.spMaxSilence) {\n this.emit('speechend');\n void this.stop();\n return;\n }\n } else {\n this.spSilenceCount = 0;\n }\n\n // 重采样 + 转换\n const resampled = AudioUtils.resample(input, currentRate, targetRate);\n const pcm = AudioUtils.floatTo16BitPCM(resampled);\n this.handlePCM(pcm.buffer.slice(0));\n };\n\n source.connect(this.scriptProcessor);\n this.scriptProcessor.connect(this.audioContext!.destination);\n\n this.emit('speechstart');\n }\n\n /**\n * 处理 PCM 数据\n */\n private handlePCM(buffer: ArrayBuffer): void {\n if (this.transport === 'websocket') {\n // WebSocket 流式发送\n let payload: ArrayBuffer | string = buffer;\n if (this.adapter.transformAudioData) {\n payload = this.adapter.transformAudioData(buffer);\n }\n\n if (this.socket && this.socket.readyState === WebSocket.OPEN) {\n // 先发送缓存队列\n this.flushMsgQueue();\n this.socket.send(payload);\n } else if (this.socket && this.socket.readyState === WebSocket.CONNECTING) {\n // 缓存到队列\n if (payload instanceof ArrayBuffer && this.msgQueue.length < this.MSG_QUEUE_MAX) {\n this.msgQueue.push(payload);\n }\n }\n } else {\n // HTTP 模式:堆积数据\n const chunk = buffer.slice(0);\n this.pcmChunks.push(chunk);\n this.totalPCMLength += chunk.byteLength / 2;\n }\n }\n\n /**\n * 刷新消息队列\n */\n private flushMsgQueue(): void {\n while (this.msgQueue.length > 0 && this.socket?.readyState === WebSocket.OPEN) {\n const data = this.msgQueue.shift();\n if (data) {\n this.socket.send(data);\n }\n }\n }\n\n /**\n * 设置页面可见性监听\n */\n private setupVisibilityListener(): void {\n if (typeof document === 'undefined') return;\n\n this.visibilityHandler = () => {\n if (document.hidden && this._status === RecognitionStatus.RECORDING) {\n this.emit('error', {\n code: 'NOT_ALLOWED',\n message: '页面已进入后台,录音已暂停',\n });\n void this.stop();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityHandler);\n }\n\n async stop(): Promise<void> {\n if (this._status === RecognitionStatus.IDLE) {\n return;\n }\n\n // 1. 停止录音\n this.isRecordingFlag = false;\n this.workletNode?.port.postMessage({ type: 'SET_RECORDING', payload: false });\n\n // 2. 停止媒体轨道\n this.mediaStream?.getTracks().forEach(t => t.stop());\n\n // 3. HTTP 模式提交音频\n if (\n this.transport === 'http' &&\n this.pcmChunks.length > 0 &&\n this.adapter.recognizeShortAudio\n ) {\n try {\n this.setStatus(RecognitionStatus.PROCESSING);\n\n // 合并 & 编码 WAV\n const mergedPCM = AudioUtils.mergeBuffers(this.pcmChunks, this.totalPCMLength);\n const sampleRate = this.config.audioConfig?.sampleRate ?? 16000;\n const wavBuffer = AudioUtils.encodeWAV(mergedPCM, sampleRate);\n\n // 调用适配器识别\n const result = await this.adapter.recognizeShortAudio(wavBuffer);\n this.emit('result', result);\n } catch (e: unknown) {\n const error = e as Error;\n this.emit('error', {\n code: 'ADAPTER_ERROR',\n message: error.message || '识别失败',\n originalError: e,\n });\n }\n }\n\n // 4. 清理资源\n this.cleanup();\n this.emit('audioend');\n this.emit('end');\n }\n\n abort(): void {\n this.isRecordingFlag = false;\n this.cleanup();\n this.emit('end');\n }\n\n isListening(): boolean {\n return this._status === RecognitionStatus.RECORDING;\n }\n\n /**\n * 清理资源\n */\n private cleanup(): void {\n // 清理重连定时器\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n // 关闭 WebSocket\n if (this.socket) {\n this.socket.close();\n this.socket = null;\n }\n\n // 断开音频节点\n this.workletNode?.disconnect();\n this.scriptProcessor?.disconnect();\n void this.audioContext?.close();\n\n // 移除可见性监听\n if (this.visibilityHandler && typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', this.visibilityHandler);\n this.visibilityHandler = null;\n }\n\n // 清理引用\n this.workletNode = null;\n this.scriptProcessor = null;\n this.audioContext = null;\n this.mediaStream = null;\n this.pcmChunks = [];\n this.totalPCMLength = 0;\n this.msgQueue = [];\n\n this.setStatus(RecognitionStatus.IDLE);\n }\n}\n\n// ============================================================================\n// 10. 主入口类 (Facade)\n// ============================================================================\n\n/**\n * 语音识别器实现\n * 统一封装原生识别和云端识别\n */\nexport class SpeechRecognizerImpl implements SpeechRecognizer {\n private strategy: BaseRecognitionStrategy | null = null;\n private config: IAdvancedRecognitionConfig = {};\n private _currentProvider: SpeechProviderType = 'browser';\n private _status: SpeechServiceStatus = 'idle';\n private eventHandlers: Map<RecognitionEventType, Set<RecognitionEventHandler>> = new Map();\n private customProviders: Map<SpeechProviderType, RecognitionProvider> = new Map();\n\n get currentProvider(): SpeechProviderType {\n return this._currentProvider;\n }\n\n get status(): SpeechServiceStatus {\n return this._status;\n }\n\n /**\n * 获取当前识别状态\n */\n get recognitionStatus(): RecognitionStatus {\n return this.strategy?.status ?? RecognitionStatus.IDLE;\n }\n\n /**\n * 初始化语音识别器\n */\n initialize(config?: RecognitionConfig): Promise<void> {\n this._status = 'loading';\n\n // 合并配置\n this.config = {\n lang: 'zh-CN',\n continuous: false,\n interimResults: true,\n maxAlternatives: 1,\n mode: 'auto',\n autoReconnect: true,\n maxReconnectAttempts: 3,\n reconnectInterval: 2000,\n audioConfig: {\n sampleRate: 16000,\n vadThreshold: 0.02,\n vadDuration: 3000,\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n },\n ...config,\n } as IAdvancedRecognitionConfig;\n\n try {\n this.initializeStrategy();\n this._status = 'ready';\n return Promise.resolve();\n } catch (error) {\n this._status = 'error';\n return Promise.reject(error);\n }\n }\n\n /**\n * 初始化识别策略\n */\n private initializeStrategy(): void {\n const advConfig = this.config;\n const mode = advConfig.mode ?? 'auto';\n const hasNative =\n typeof window !== 'undefined' &&\n ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window);\n\n // 选择策略\n if (mode === 'native' || (mode === 'auto' && hasNative && !advConfig.cloudAdapter)) {\n const nativeStrategy = new NativeRecognitionStrategy(advConfig);\n if (!nativeStrategy.isAvailable()) {\n throw new Error('浏览器不支持原生语音识别');\n }\n this.strategy = nativeStrategy;\n this._currentProvider = 'browser';\n } else if (mode === 'cloud' || (mode === 'auto' && advConfig.cloudAdapter)) {\n if (!advConfig.cloudAdapter) {\n throw new Error('云端模式需要提供 cloudAdapter');\n }\n this.strategy = new CloudRecognitionStrategy(advConfig);\n this._currentProvider = 'custom';\n } else {\n throw new Error('没有可用的识别策略');\n }\n\n // 转发事件\n this.forwardStrategyEvents();\n }\n\n /**\n * 转发策略事件\n */\n private forwardStrategyEvents(): void {\n if (!this.strategy) return;\n\n this.strategy.on('result', res => {\n this.emit('result', {\n type: 'result',\n result: this.convertResult(res),\n });\n });\n\n this.strategy.on('error', err => {\n const errorEvent: RecognitionEvent = {\n type: 'error',\n error: {\n code: err.code,\n message: err.message,\n },\n };\n if (err.originalError) {\n errorEvent.error!.originalError = err.originalError as Error;\n }\n this.emit('error', errorEvent);\n });\n\n this.strategy.on('start', () => this.emit('start', { type: 'start' }));\n this.strategy.on('end', () => this.emit('end', { type: 'end' }));\n this.strategy.on('soundstart', () => this.emit('soundstart', { type: 'soundstart' }));\n this.strategy.on('soundend', () => this.emit('soundend', { type: 'soundend' }));\n this.strategy.on('speechstart', () => this.emit('speechstart', { type: 'speechstart' }));\n this.strategy.on('speechend', () => this.emit('speechend', { type: 'speechend' }));\n this.strategy.on('audiostart', () => this.emit('audiostart', { type: 'audiostart' }));\n this.strategy.on('audioend', () => this.emit('audioend', { type: 'audioend' }));\n }\n\n /**\n * 转换识别结果格式\n */\n private convertResult(res: IRecognitionResult): RecognitionResult {\n return {\n results: [\n {\n transcript: res.transcript,\n confidence: res.confidence,\n isFinal: res.isFinal,\n },\n ],\n bestTranscript: res.transcript,\n bestConfidence: res.confidence,\n isFinal: res.isFinal,\n };\n }\n\n /**\n * 开始识别\n */\n async start(config?: RecognitionConfig): Promise<void> {\n if (this._status !== 'ready') {\n throw new Error('识别器未就绪');\n }\n\n if (config) {\n // 更新配置并重新初始化\n this.config = { ...this.config, ...config } as IAdvancedRecognitionConfig;\n this.initializeStrategy();\n }\n\n return this.strategy?.start();\n }\n\n /**\n * 停止识别\n */\n stop(): void {\n this.strategy?.stop();\n }\n\n /**\n * 中止识别\n */\n abort(): void {\n this.strategy?.abort();\n }\n\n /**\n * 是否正在识别\n */\n isListening(): boolean {\n return this.strategy?.isListening() ?? false;\n }\n\n /**\n * 添加事件监听\n */\n on(event: RecognitionEventType, handler: RecognitionEventHandler): void {\n if (!this.eventHandlers.has(event)) {\n this.eventHandlers.set(event, new Set());\n }\n this.eventHandlers.get(event)!.add(handler);\n }\n\n /**\n * 移除事件监听\n */\n off(event: RecognitionEventType, handler: RecognitionEventHandler): void {\n this.eventHandlers.get(event)?.delete(handler);\n }\n\n /**\n * 触发事件\n */\n private emit(type: RecognitionEventType, event: RecognitionEvent): void {\n this.eventHandlers.get(type)?.forEach(handler => {\n try {\n handler(event);\n } catch (e) {\n console.error('[SpeechRecognizer] 事件处理器错误:', e);\n }\n });\n }\n\n /**\n * 销毁实例\n */\n dispose(): void {\n this.strategy?.dispose();\n this.strategy = null;\n this.eventHandlers.clear();\n this._status = 'idle';\n }\n\n /**\n * 注册自定义提供商\n */\n registerProvider(type: SpeechProviderType, provider: RecognitionProvider): void {\n this.customProviders.set(type, provider);\n }\n\n /**\n * 使用云端适配器\n */\n useCloudAdapter(adapter: ICloudRecognitionAdapter): void {\n this.config.cloudAdapter = adapter;\n this.config.mode = 'cloud';\n }\n}\n\n// ============================================================================\n// 11. 工厂函数和工具函数\n// ============================================================================\n\n/**\n * 获取浏览器的 SpeechRecognition 构造函数\n */\nfunction getSpeechRecognitionConstructor(): BrowserSpeechRecognitionConstructor | null {\n if (typeof window === 'undefined') {\n return null;\n }\n return (\n (window.SpeechRecognition as BrowserSpeechRecognitionConstructor | undefined) ??\n (window.webkitSpeechRecognition as BrowserSpeechRecognitionConstructor | undefined) ??\n null\n );\n}\n\n/**\n * 创建语音识别器实例\n * @param config 识别配置\n * @returns 语音识别器实例\n *\n * @example\n * ```typescript\n * // 使用原生识别\n * const recognizer = await createSpeechRecognizer({\n * lang: 'zh-CN',\n * continuous: true,\n * });\n *\n * // 使用云端识别 (百度)\n * const baiduAdapter = new BaiduAdapter('your-access-token');\n * const cloudRecognizer = await createSpeechRecognizer({\n * mode: 'cloud',\n * cloudAdapter: baiduAdapter,\n * transport: 'http',\n * });\n *\n * recognizer.on('result', (event) => {\n * console.log('识别结果:', event.result?.bestTranscript);\n * });\n *\n * await recognizer.start();\n * ```\n */\nexport async function createSpeechRecognizer(\n config?: RecognitionConfig | IAdvancedRecognitionConfig\n): Promise<SpeechRecognizer> {\n const recognizer = new SpeechRecognizerImpl();\n await recognizer.initialize(config);\n return recognizer;\n}\n\n/**\n * 检查当前环境是否支持语音识别\n * @returns 是否支持\n */\nexport function isSpeechRecognitionSupported(): boolean {\n return getSpeechRecognitionConstructor() !== null;\n}\n\n/**\n * 快速进行一次语音识别\n * @param config 识别配置\n * @returns 识别结果\n *\n * @example\n * ```typescript\n * const result = await listen({ lang: 'zh-CN' });\n * console.log('识别结果:', result.bestTranscript);\n * ```\n */\nexport async function listen(\n config?: RecognitionConfig | IAdvancedRecognitionConfig\n): Promise<RecognitionResult> {\n const recognizer = await createSpeechRecognizer({\n ...config,\n continuous: false,\n });\n\n return new Promise((resolve, reject) => {\n let hasResult = false;\n\n recognizer.on('result', event => {\n if (event.result && event.result.isFinal) {\n hasResult = true;\n recognizer.dispose();\n resolve(event.result);\n }\n });\n\n recognizer.on('error', event => {\n recognizer.dispose();\n reject(event.error);\n });\n\n recognizer.on('end', () => {\n if (!hasResult) {\n recognizer.dispose();\n resolve({\n results: [],\n bestTranscript: '',\n bestConfidence: 0,\n isFinal: true,\n });\n }\n });\n\n recognizer.start().catch(reject);\n });\n}\n\n/**\n * 创建带超时的语音识别\n * @param config 识别配置\n * @param timeout 超时时间 (ms)\n * @returns 识别结果\n */\nexport async function listenWithTimeout(\n config?: RecognitionConfig | IAdvancedRecognitionConfig,\n timeout: number = 10000\n): Promise<RecognitionResult> {\n return Promise.race([\n listen(config),\n new Promise<RecognitionResult>((_, reject) => {\n setTimeout(() => reject(new Error('识别超时')), timeout);\n }),\n ]);\n}\n\n/**\n * [使用示例 - 原生识别]\n *\n * const recognizer = await createSpeechRecognizer({\n * lang: 'zh-CN',\n * continuous: true,\n * interimResults: true,\n * });\n *\n * recognizer.on('result', (event) => {\n * console.log(event.result?.bestTranscript);\n * });\n *\n * recognizer.on('error', (event) => {\n * console.error(event.error?.message);\n * });\n *\n * await recognizer.start();\n */\n\n/**\n * [使用示例 - 云端识别 (百度)]\n *\n * const adapter = new BaiduAdapter('your-access-token', 'appId', 'appKey');\n * const recognizer = await createSpeechRecognizer({\n * mode: 'cloud',\n * transport: 'websocket', // 或 'http'\n * cloudAdapter: adapter,\n * audioConfig: {\n * vadDuration: 2000,\n * vadThreshold: 0.03,\n * },\n * autoReconnect: true,\n * });\n *\n * recognizer.on('result', (event) => {\n * if (event.result?.isFinal) {\n * console.log('最终结果:', event.result.bestTranscript);\n * }\n * });\n *\n * await recognizer.start();\n */\n\n/**\n * [使用示例 - 自定义 BFF 适配器]\n *\n * const adapter = new GenericAdapter('https://api.yoursite.com/speech');\n * const recognizer = await createSpeechRecognizer({\n * mode: 'cloud',\n * transport: 'http',\n * cloudAdapter: adapter,\n * });\n */\n"]}
|
|
@@ -474,9 +474,7 @@ function Timeout(timeoutMs, errorMessage) {
|
|
|
474
474
|
descriptor.value = async function(...args) {
|
|
475
475
|
const timeoutPromise = new Promise((_, reject) => {
|
|
476
476
|
setTimeout(() => {
|
|
477
|
-
reject(
|
|
478
|
-
new Error(errorMessage ?? `${methodName} timed out after ${timeoutMs}ms`)
|
|
479
|
-
);
|
|
477
|
+
reject(new Error(errorMessage ?? `${methodName} timed out after ${timeoutMs}ms`));
|
|
480
478
|
}, timeoutMs);
|
|
481
479
|
});
|
|
482
480
|
return Promise.race([originalMethod.apply(this, args), timeoutPromise]);
|
|
@@ -678,5 +676,5 @@ exports.Validate = Validate;
|
|
|
678
676
|
exports.combineDisposables = combineDisposables;
|
|
679
677
|
exports.globalContainer = globalContainer;
|
|
680
678
|
exports.toDisposable = toDisposable;
|
|
681
|
-
//# sourceMappingURL=chunk-
|
|
682
|
-
//# sourceMappingURL=chunk-
|
|
679
|
+
//# sourceMappingURL=chunk-BEY4UAYF.cjs.map
|
|
680
|
+
//# sourceMappingURL=chunk-BEY4UAYF.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/events.ts","../src/core/container.ts","../src/core/decorators.ts","../src/core/disposable.ts"],"names":["__name","Lifecycle"],"mappings":"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","file":"chunk-BEY4UAYF.cjs","sourcesContent":["/**\n * @fileoverview 用于发布/订阅模式的事件发射器类\n * @module melange/core/events\n * @description 提供一个类型安全的事件发射器实现\n * 遵循观察者模式。\n */\n\nimport type { EventHandler, Subscription } from '../types';\n\n/**\n * 类型安全的事件映射接口。\n * 扩展此接口以定义您的事件类型。\n *\n * @example\n * ```typescript\n * interface MyEvents {\n * userLogin: { userId: string; timestamp: Date };\n * userLogout: { userId: string };\n * error: Error;\n * }\n *\n * const emitter = new EventEmitter<MyEvents>();\n * emitter.on('userLogin', event => console.log(event.userId));\n * ```\n */\nexport interface EventMap {\n [event: string]: unknown;\n}\n\n/**\n * 带有元数据的内部监听器条目。\n */\ninterface ListenerEntry<T> {\n handler: EventHandler<T>;\n once: boolean;\n}\n\n/**\n * 类型安全的事件发射器类。\n * 实现观察者模式以进行解耦的事件驱动编程。\n *\n * @description\n * EventEmitter 提供了一种订阅和发射事件的方式,具有完整的\n * TypeScript 类型安全性。它支持一次性监听器、监听器移除\n * 和适当的清理。\n *\n * @template Events - 定义事件名称和载荷类型的事件映射类型\n *\n * @example\n * ```typescript\n * interface AppEvents {\n * 'user:created': { id: string; name: string };\n * 'user:deleted': { id: string };\n * 'error': Error;\n * }\n *\n * const events = new EventEmitter<AppEvents>();\n *\n * // 订阅事件\n * events.on('user:created', user => {\n * console.log(`创建用户: ${user.name}`);\n * });\n *\n * // 发射事件\n * events.emit('user:created', { id: '1', name: 'John' });\n *\n * // 一次性监听器\n * events.once('error', err => console.error(err));\n *\n * // 取消订阅\n * const subscription = events.on('user:deleted', handleDelete);\n * subscription.unsubscribe();\n * ```\n */\nexport class EventEmitter<Events extends EventMap = EventMap> {\n /**\n * 事件名称到其监听器的映射\n */\n private listeners: Map<keyof Events, ListenerEntry<unknown>[]> = new Map();\n\n /**\n * 订阅事件。\n *\n * @param event - 要订阅的事件名称\n * @param handler - 事件发射时要调用的处理函数\n * @returns 带有取消订阅方法的订阅对象\n */\n public on<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): Subscription {\n return this.addListener(event, handler, false);\n }\n\n /**\n * 仅订阅事件的一次发射。\n * 监听器在被调用一次后自动移除。\n *\n * @param event - 要订阅的事件名称\n * @param handler - 事件发射时要调用的处理函数\n * @returns 带有取消订阅方法的订阅对象\n */\n public once<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): Subscription {\n return this.addListener(event, handler, true);\n }\n\n /**\n * 从事件中移除特定监听器。\n *\n * @param event - 事件名称\n * @param handler - 要移除的处理函数\n */\n public off<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): void {\n const eventListeners = this.listeners.get(event);\n if (eventListeners) {\n const index = eventListeners.findIndex(entry => entry.handler === handler);\n if (index !== -1) {\n eventListeners.splice(index, 1);\n }\n }\n }\n\n /**\n * 发射带有给定载荷的事件。\n * 所有订阅的监听器将同步调用。\n *\n * @param event - 要发射的事件名称\n * @param payload - 事件载荷\n */\n public emit<K extends keyof Events>(event: K, payload: Events[K]): void {\n const eventListeners = this.listeners.get(event);\n if (!eventListeners) return;\n\n // 创建副本以避免监听器修改数组时出现问题\n const listenersCopy = [...eventListeners];\n\n for (const entry of listenersCopy) {\n entry.handler(payload);\n\n if (entry.once) {\n this.off(event, entry.handler as EventHandler<Events[K]>);\n }\n }\n }\n\n /**\n * 移除特定事件的所有监听器,或如果不指定事件则移除所有监听器。\n *\n * @param event - 可选的事件名称,用于清除监听器\n */\n public removeAllListeners<K extends keyof Events>(event?: K): void {\n if (event) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n\n /**\n * 返回特定事件的监听器数量。\n *\n * @param event - 事件名称\n * @returns 监听器数量\n */\n public listenerCount<K extends keyof Events>(event: K): number {\n const eventListeners = this.listeners.get(event);\n return eventListeners?.length ?? 0;\n }\n\n /**\n * 返回所有具有监听器的事件名称。\n *\n * @returns 事件名称数组\n */\n public eventNames(): Array<keyof Events> {\n return Array.from(this.listeners.keys());\n }\n\n /**\n * 添加监听器的内部方法。\n */\n private addListener<K extends keyof Events>(\n event: K,\n handler: EventHandler<Events[K]>,\n once: boolean\n ): Subscription {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, []);\n }\n\n const entry: ListenerEntry<Events[K]> = { handler, once };\n this.listeners.get(event)!.push(entry as ListenerEntry<unknown>);\n\n return {\n unsubscribe: () => this.off(event, handler),\n };\n }\n}\n","/**\n * @fileoverview 依赖注入容器\n * @module melange/core/container\n * @description 提供一个简单而强大的依赖注入容器\n * 支持单例、工厂函数和自动解析。\n */\n\nimport type { Constructor } from '../types';\n\n/**\n * 用于标识依赖项的令牌类型。\n * 可以是字符串、符号或类构造函数。\n */\nexport type Token<T = unknown> = string | symbol | Constructor<T>;\n\n/**\n * 创建实例的工厂函数类型。\n */\nexport type Factory<T> = (container: Container) => T;\n\n/**\n * 依赖注册的生命周期选项。\n */\nexport enum Lifecycle {\n /** 每次都创建新实例 */\n Transient = 'transient',\n /** 创建单个实例并重复使用 */\n Singleton = 'singleton',\n}\n\n/**\n * 容器中的注册条目。\n */\ninterface Registration<T> {\n factory: Factory<T>;\n lifecycle: Lifecycle;\n instance?: T;\n}\n\n/**\n * 可注入类的元数据键。\n */\nconst INJECTABLE_METADATA = Symbol('melange:injectable');\nconst INJECT_METADATA = Symbol('melange:inject');\n\n/**\n * 依赖注入容器。\n * 管理依赖项的生命周期和解析。\n *\n * @description\n * Container 类提供控制反转 (IoC) 功能,\n * 允许您通过在运行时注册和解析依赖项来解耦代码。\n *\n * @example\n * ```typescript\n * // 创建容器\n * const container = new Container();\n *\n * // 注册类\n * container.register('logger', () => new ConsoleLogger());\n *\n * // 注册单例\n * container.registerSingleton('config', () => loadConfig());\n *\n * // 解析依赖项\n * const logger = container.resolve<Logger>('logger');\n *\n * // 使用装饰器\n * @Injectable()\n * class UserService {\n * constructor(@Inject('logger') private logger: Logger) {}\n * }\n * container.registerClass(UserService);\n * ```\n */\nexport class Container {\n /**\n * 已注册依赖项的映射\n */\n private registrations: Map<Token, Registration<unknown>> = new Map();\n\n /**\n * 用于分层解析的父容器\n */\n private parent: Container | undefined;\n\n /**\n * 创建新的容器实例。\n *\n * @param parent - 用于分层解析的可选父容器\n */\n constructor(parent?: Container) {\n this.parent = parent;\n }\n\n /**\n * 使用工厂函数注册依赖项。\n *\n * @template T - 依赖项类型\n * @param token - 用于标识依赖项的令牌\n * @param factory - 创建依赖项的工厂函数\n * @param lifecycle - 依赖项的生命周期(默认:Transient)\n * @returns 容器实例,用于链式调用\n */\n public register<T>(\n token: Token<T>,\n factory: Factory<T>,\n lifecycle: Lifecycle = Lifecycle.Transient\n ): this {\n this.registrations.set(token, {\n factory: factory as Factory<unknown>,\n lifecycle,\n });\n return this;\n }\n\n /**\n * 注册单例依赖项。\n * 工厂函数只会被调用一次,之后返回相同的实例。\n *\n * @template T - 依赖项类型\n * @param token - 用于标识依赖项的令牌\n * @param factory - 创建依赖项的工厂函数\n * @returns 容器实例,用于链式调用\n */\n public registerSingleton<T>(token: Token<T>, factory: Factory<T>): this {\n return this.register(token, factory, Lifecycle.Singleton);\n }\n\n /**\n * 直接将值注册为单例。\n *\n * @template T - 值类型\n * @param token - 用于标识依赖项的令牌\n * @param value - 要注册的值\n * @returns 容器实例,用于链式调用\n */\n public registerValue<T>(token: Token<T>, value: T): this {\n this.registrations.set(token, {\n factory: () => value,\n lifecycle: Lifecycle.Singleton,\n instance: value,\n });\n return this;\n }\n\n /**\n * 将类注册为依赖项。\n * 类的实例化会自动解析其依赖项。\n *\n * @template T - 类类型\n * @param ClassConstructor - 要注册的类构造函数\n * @param lifecycle - 依赖项的生命周期(默认:Transient)\n * @returns 容器实例,用于链式调用\n */\n public registerClass<T extends object>(\n ClassConstructor: Constructor<T>,\n lifecycle: Lifecycle = Lifecycle.Transient\n ): this {\n const factory: Factory<T> = container => {\n const injectTokens = this.getInjectMetadata(ClassConstructor);\n const dependencies = injectTokens.map(token => container.resolve(token));\n return new ClassConstructor(...dependencies);\n };\n\n return this.register(ClassConstructor, factory, lifecycle);\n }\n\n /**\n * 通过令牌解析依赖项。\n *\n * @template T - 依赖项类型\n * @param token - 标识依赖项的令牌\n * @returns 已解析的依赖项\n * @throws Error 如果依赖项未注册\n */\n public resolve<T>(token: Token<T>): T {\n const registration = this.registrations.get(token) as Registration<T> | undefined;\n\n if (!registration) {\n // 尝试父容器\n if (this.parent) {\n return this.parent.resolve(token);\n }\n throw new Error(`Dependency not registered: ${String(token)}`);\n }\n\n if (registration.lifecycle === Lifecycle.Singleton) {\n if (registration.instance === undefined) {\n registration.instance = registration.factory(this);\n }\n return registration.instance;\n }\n\n return registration.factory(this);\n }\n\n /**\n * 检查依赖项是否已注册。\n *\n * @param token - 要检查的令牌\n * @returns 如果依赖项已注册则返回 true\n */\n public has(token: Token): boolean {\n if (this.registrations.has(token)) {\n return true;\n }\n return this.parent?.has(token) ?? false;\n }\n\n /**\n * 移除依赖项注册。\n *\n * @param token - 要移除的令牌\n * @returns 如果注册已被移除则返回 true\n */\n public unregister(token: Token): boolean {\n return this.registrations.delete(token);\n }\n\n /**\n * 清除所有注册。\n */\n public clear(): void {\n this.registrations.clear();\n }\n\n /**\n * 创建子容器。\n * 子容器从父容器继承注册。\n *\n * @returns 新的子容器\n */\n public createChild(): Container {\n return new Container(this);\n }\n\n /**\n * 获取类的注入元数据。\n */\n private getInjectMetadata(target: Constructor): Token[] {\n // 如果可用则使用 reflect-metadata,否则返回空数组\n const reflect = Reflect as unknown as {\n getMetadata?: (key: symbol, target: unknown) => Token[] | undefined;\n };\n return reflect.getMetadata?.(INJECT_METADATA, target) ?? [];\n }\n}\n\n/**\n * 为了方便而提供的全局容器实例。\n */\nexport const globalContainer = new Container();\n\n// ============================================================================\n// 依赖注入装饰器\n// ============================================================================\n\n/**\n * 将类标记为可注入。\n * 自动依赖解析所必需。\n *\n * @example\n * ```typescript\n * @Injectable()\n * class UserService {\n * constructor(private userRepo: UserRepository) {}\n * }\n * ```\n *\n * @returns 类装饰器\n */\nexport function Injectable(): ClassDecorator {\n // eslint-disable-next-line @typescript-eslint/ban-types\n return function <TFunction extends Function>(target: TFunction): TFunction {\n // 如果可用则使用 reflect-metadata\n const reflect = Reflect as unknown as {\n defineMetadata?: (key: symbol, value: unknown, target: unknown) => void;\n };\n reflect.defineMetadata?.(INJECTABLE_METADATA, true, target);\n return target;\n };\n}\n\n/**\n * 标记构造函数参数以进行注入。\n *\n * @example\n * ```typescript\n * @Injectable()\n * class UserService {\n * constructor(@Inject('logger') private logger: Logger) {}\n * }\n * ```\n *\n * @param token - 要注入的令牌\n * @returns 参数装饰器\n */\nexport function Inject(token: Token): ParameterDecorator {\n return function (\n target: object,\n _propertyKey: string | symbol | undefined,\n parameterIndex: number\n ): void {\n // 如果可用则使用 reflect-metadata\n const reflect = Reflect as unknown as {\n getMetadata?: (key: symbol, target: unknown) => Token[] | undefined;\n defineMetadata?: (key: symbol, value: unknown, target: unknown) => void;\n };\n const existingTokens: Token[] = reflect.getMetadata?.(INJECT_METADATA, target) ?? [];\n existingTokens[parameterIndex] = token;\n reflect.defineMetadata?.(INJECT_METADATA, existingTokens, target);\n };\n}\n\n/**\n * 将类标记为单例。\n * 结合 @Injectable 和单例生命周期。\n *\n * @example\n * ```typescript\n * @Singleton()\n * class ConfigService {\n * // 只会存在一个实例\n * }\n * ```\n *\n * @returns 类装饰器\n */\nexport function Singleton(): ClassDecorator {\n // eslint-disable-next-line @typescript-eslint/ban-types\n return function <TFunction extends Function>(target: TFunction): TFunction {\n // 如果可用则使用 reflect-metadata\n const reflect = Reflect as unknown as {\n defineMetadata?: (key: symbol | string, value: unknown, target: unknown) => void;\n };\n reflect.defineMetadata?.(INJECTABLE_METADATA, true, target);\n reflect.defineMetadata?.('melange:singleton', true, target);\n return target;\n };\n}\n","/**\n * @fileoverview 方法和类装饰器\n * @module melange/core/decorators\n * @description 提供一系列有用的装饰器,用于增强\n * 类和方法的横切关注点。\n */\n\n/**\n * 用于缓存方法结果的记忆化装饰器。\n * 根据方法的参数缓存结果。\n *\n * @description\n * 此装饰器根据方法的参数缓存其返回值。\n * 后续使用相同参数的调用将返回缓存的值。\n *\n * @example\n * ```typescript\n * class Calculator {\n * @Memoize()\n * fibonacci(n: number): number {\n * if (n <= 1) return n;\n * return this.fibonacci(n - 1) + this.fibonacci(n - 2);\n * }\n * }\n * ```\n *\n * @param keyFn - 生成缓存键的可选函数\n * @returns 方法装饰器\n */\nexport function Memoize(keyFn?: (...args: unknown[]) => string): MethodDecorator {\n return function (\n _target: object,\n _propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ): PropertyDescriptor {\n const originalMethod = descriptor.value as (...args: unknown[]) => unknown;\n const cache = new Map<string, unknown>();\n\n descriptor.value = function (this: unknown, ...args: unknown[]): unknown {\n const key = keyFn ? keyFn(...args) : JSON.stringify(args);\n\n if (cache.has(key)) {\n return cache.get(key);\n }\n\n const result = originalMethod.apply(this, args);\n cache.set(key, result);\n return result;\n };\n\n return descriptor;\n };\n}\n\n/**\n * 用于限制方法调用频率的防抖装饰器。\n * 延迟方法执行直到指定的等待时间过后。\n *\n * @example\n * ```typescript\n * class SearchInput {\n * @Debounce(300)\n * onSearch(query: string): void {\n * // 这将在上次调用后300毫秒才被调用\n * console.log('搜索中:', query);\n * }\n * }\n * ```\n *\n * @param waitMs - 等待的毫秒数\n * @returns 方法装饰器\n */\nexport function Debounce(waitMs: number): MethodDecorator {\n return function (\n _target: object,\n _propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ): PropertyDescriptor {\n const originalMethod = descriptor.value as (...args: unknown[]) => unknown;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n descriptor.value = function (this: unknown, ...args: unknown[]): void {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n timeoutId = setTimeout(() => {\n originalMethod.apply(this, args);\n timeoutId = null;\n }, waitMs);\n };\n\n return descriptor;\n };\n}\n\n/**\n * 用于限制方法调用频率的节流装饰器。\n * 确保方法在指定的时间段内最多被调用一次。\n *\n * @example\n * ```typescript\n * class ScrollHandler {\n * @Throttle(100)\n * onScroll(event: Event): void {\n * // 这将最多每100毫秒被调用一次\n * console.log('滚动中');\n * }\n * }\n * ```\n *\n * @param limitMs - 调用之间的最小时间间隔(毫秒)\n * @returns 方法装饰器\n */\nexport function Throttle(limitMs: number): MethodDecorator {\n return function (\n _target: object,\n _propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ): PropertyDescriptor {\n const originalMethod = descriptor.value as (...args: unknown[]) => unknown;\n let lastCall = 0;\n\n descriptor.value = function (this: unknown, ...args: unknown[]): unknown {\n const now = Date.now();\n\n if (now - lastCall >= limitMs) {\n lastCall = now;\n return originalMethod.apply(this, args);\n }\n\n return undefined;\n };\n\n return descriptor;\n };\n}\n\n/**\n * 用于记录方法调用的日志装饰器。\n * 记录方法进入、退出,以及可选的参数和返回值。\n *\n * @example\n * ```typescript\n * class UserService {\n * @Log({ logArgs: true, logResult: true })\n * getUser(id: string): User {\n * return this.userRepository.findById(id);\n * }\n * }\n * // 日志: \"Entering getUser with args: [\"123\"]\"\n * // 日志: \"Exiting getUser with result: { id: \"123\", name: \"John\" }\"\n * ```\n *\n * @param options - 日志选项\n * @returns 方法装饰器\n */\nexport function Log(\n options: {\n logArgs?: boolean;\n logResult?: boolean;\n prefix?: string;\n } = {}\n): MethodDecorator {\n const { logArgs = false, logResult = false, prefix = '' } = options;\n\n return function (\n _target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ): PropertyDescriptor {\n const originalMethod = descriptor.value as (...args: unknown[]) => unknown;\n const methodName = String(propertyKey);\n\n descriptor.value = function (this: unknown, ...args: unknown[]): unknown {\n const logPrefix = prefix ? `[${prefix}] ` : '';\n\n if (logArgs) {\n // eslint-disable-next-line no-console\n console.log(`${logPrefix}Entering ${methodName} with args:`, args);\n } else {\n // eslint-disable-next-line no-console\n console.log(`${logPrefix}Entering ${methodName}`);\n }\n\n try {\n const result = originalMethod.apply(this, args);\n\n // 处理异步方法\n if (result instanceof Promise) {\n return result\n .then(asyncResult => {\n if (logResult) {\n // eslint-disable-next-line no-console\n console.log(`${logPrefix}Exiting ${methodName} with result:`, asyncResult);\n } else {\n // eslint-disable-next-line no-console\n console.log(`${logPrefix}Exiting ${methodName}`);\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return asyncResult;\n })\n .catch(error => {\n // eslint-disable-next-line no-console\n console.error(`${logPrefix}${methodName} threw error:`, error);\n throw error;\n });\n }\n\n if (logResult) {\n // eslint-disable-next-line no-console\n console.log(`${logPrefix}Exiting ${methodName} with result:`, result);\n } else {\n // eslint-disable-next-line no-console\n console.log(`${logPrefix}Exiting ${methodName}`);\n }\n\n return result;\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(`${logPrefix}${methodName} threw error:`, error);\n throw error;\n }\n };\n\n return descriptor;\n };\n}\n\n/**\n * 用于验证方法参数的验证装饰器。\n * 在方法执行前运行验证函数。\n *\n * @example\n * ```typescript\n * class UserService {\n * @Validate((id: string) => {\n * if (!id) throw new Error('ID 是必需的');\n * })\n * getUser(id: string): User {\n * return this.userRepository.findById(id);\n * }\n * }\n * ```\n *\n * @param validator - 在输入无效时抛出异常的验证函数\n * @returns 方法装饰器\n */\nexport function Validate(validator: (...args: unknown[]) => void): MethodDecorator {\n return function (\n _target: object,\n _propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ): PropertyDescriptor {\n const originalMethod = descriptor.value as (...args: unknown[]) => unknown;\n\n descriptor.value = function (this: unknown, ...args: unknown[]): unknown {\n validator(...args);\n return originalMethod.apply(this, args);\n };\n\n return descriptor;\n };\n}\n\n/**\n * 用于标记方法已弃用的装饰器。\n * 在调用方法时记录警告。\n *\n * @example\n * ```typescript\n * class UserService {\n * @Deprecated('请改用 getUserById')\n * getUser(id: string): User {\n * return this.getUserById(id);\n * }\n * }\n * ```\n *\n * @param message - 弃用消息\n * @returns 方法装饰器\n */\nexport function Deprecated(message?: string): MethodDecorator {\n return function (\n _target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ): PropertyDescriptor {\n const originalMethod = descriptor.value as (...args: unknown[]) => unknown;\n const methodName = String(propertyKey);\n const warningMessage = message ?? `${methodName} is deprecated`;\n\n descriptor.value = function (this: unknown, ...args: unknown[]): unknown {\n // eslint-disable-next-line no-console\n console.warn(`[DEPRECATED] ${warningMessage}`);\n return originalMethod.apply(this, args);\n };\n\n return descriptor;\n };\n}\n\n/**\n * 用于密封类的装饰器。\n * 防止向实例添加新属性。\n *\n * @example\n * ```typescript\n * @Sealed()\n * class Config {\n * readonly apiUrl: string = 'https://api.example.com';\n * }\n *\n * const config = new Config();\n * config.newProp = 'value'; // 错误: 无法添加属性\n * ```\n *\n * @returns 类装饰器\n */\nexport function Sealed(): ClassDecorator {\n // eslint-disable-next-line @typescript-eslint/ban-types\n return function <TFunction extends Function>(target: TFunction): TFunction {\n Object.seal(target);\n Object.seal(target.prototype);\n return target;\n };\n}\n\n/**\n * 用于冻结类的装饰器。\n * 防止对实例进行任何修改。\n *\n * @example\n * ```typescript\n * @Frozen()\n * class Constants {\n * static readonly PI = 3.14159;\n * }\n *\n * Constants.PI = 3; // 错误: 无法修改\n * ```\n *\n * @returns 类装饰器\n */\nexport function Frozen(): ClassDecorator {\n // eslint-disable-next-line @typescript-eslint/ban-types\n return function <TFunction extends Function>(target: TFunction): TFunction {\n Object.freeze(target);\n Object.freeze(target.prototype);\n return target;\n };\n}\n\n/**\n * 用于自动将方法绑定到类实例的装饰器。\n * 对于作为回调函数传递的方法很有用。\n *\n * @example\n * ```typescript\n * class Button {\n * @Bind()\n * onClick() {\n * console.log(this); // 总是指向 Button 实例\n * }\n * }\n *\n * const button = new Button();\n * const handler = button.onClick;\n * handler(); // `this` 仍然是 button 实例\n * ```\n *\n * @returns 方法装饰器\n */\nexport function Bind(): MethodDecorator {\n return function (\n _target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ): PropertyDescriptor {\n const originalMethod = descriptor.value as (...args: unknown[]) => unknown;\n\n return {\n configurable: true,\n get(this: object) {\n const bound = originalMethod.bind(this);\n Object.defineProperty(this, propertyKey, {\n value: bound,\n configurable: true,\n writable: true,\n });\n return bound;\n },\n };\n };\n}\n\n/**\n * 用于自动重试失败方法调用的装饰器。\n *\n * @example\n * ```typescript\n * class ApiClient {\n * @Retry(3, 1000)\n * async fetchData(): Promise<Data> {\n * const response = await fetch('/api/data');\n * if (!response.ok) throw new Error('请求失败');\n * return response.json();\n * }\n * }\n * ```\n *\n * @param maxRetries - 最大重试次数\n * @param delayMs - 重试之间的延迟(毫秒)\n * @returns 方法装饰器\n */\nexport function Retry(maxRetries: number, delayMs: number = 0): MethodDecorator {\n return function (\n _target: object,\n _propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ): PropertyDescriptor {\n const originalMethod = descriptor.value as (...args: unknown[]) => unknown;\n\n descriptor.value = async function (this: unknown, ...args: unknown[]): Promise<unknown> {\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await originalMethod.apply(this, args);\n } catch (error) {\n lastError = error;\n\n if (attempt < maxRetries && delayMs > 0) {\n await new Promise(resolve => setTimeout(resolve, delayMs));\n }\n }\n }\n\n throw lastError;\n };\n\n return descriptor;\n };\n}\n\n/**\n * 用于为异步方法添加超时的装饰器。\n *\n * @example\n * ```typescript\n * class ApiClient {\n * @Timeout(5000)\n * async fetchData(): Promise<Data> {\n * // 如果这花费超过5秒,将抛出异常\n * return await fetch('/api/data').then(r => r.json());\n * }\n * }\n * ```\n *\n * @param timeoutMs - 超时时间(毫秒)\n * @param errorMessage - 可选的错误消息\n * @returns 方法装饰器\n */\nexport function Timeout(timeoutMs: number, errorMessage?: string): MethodDecorator {\n return function (\n _target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ): PropertyDescriptor {\n const originalMethod = descriptor.value as (...args: unknown[]) => Promise<unknown>;\n const methodName = String(propertyKey);\n\n descriptor.value = async function (this: unknown, ...args: unknown[]): Promise<unknown> {\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error(errorMessage ?? `${methodName} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n });\n\n return Promise.race([originalMethod.apply(this, args), timeoutPromise]);\n };\n\n return descriptor;\n };\n}\n","/**\n * @fileoverview 用于资源管理的可释放基类\n * @module melange/core/disposable\n * @description 提供一个基类用于管理可释放资源\n * 包含适当的清理和生命周期管理。\n */\n\n/**\n * 可释放对象的接口。\n * 实现此接口的对象可以被正确清理。\n */\nexport interface IDisposable {\n /**\n * 释放此对象持有的资源。\n */\n dispose(): void;\n\n /**\n * 此对象是否已被释放。\n */\n readonly isDisposed: boolean;\n}\n\n/**\n * 管理可释放资源的对象的抽象基类。\n *\n * @description\n * Disposable 类提供了一种管理模式,用于管理需要显式清理的资源。\n * 它跟踪释放状态并防止重复释放。\n *\n * @example\n * ```typescript\n * class DatabaseConnection extends Disposable {\n * private connection: Connection;\n *\n * constructor() {\n * super();\n * this.connection = createConnection();\n * // 注册清理\n * this.addDisposable({\n * dispose: () => this.connection.close()\n * });\n * }\n *\n * query(sql: string) {\n * this.ensureNotDisposed();\n * return this.connection.query(sql);\n * }\n * }\n *\n * // 使用\n * const db = new DatabaseConnection();\n * try {\n * await db.query('SELECT * FROM users');\n * } finally {\n * db.dispose();\n * }\n * ```\n */\nexport abstract class Disposable implements IDisposable {\n /**\n * 此对象是否已被释放\n */\n private _isDisposed: boolean = false;\n\n /**\n * 待清理的可释放对象列表\n */\n private readonly disposables: IDisposable[] = [];\n\n /**\n * 获取此对象是否已被释放。\n */\n public get isDisposed(): boolean {\n return this._isDisposed;\n }\n\n /**\n * 释放此对象和所有已注册的可释放对象。\n * 多次调用 dispose 是安全的(后续调用无效)。\n */\n public dispose(): void {\n if (this._isDisposed) {\n return;\n }\n\n this._isDisposed = true;\n\n // 按相反顺序释放(后进先出)\n for (let i = this.disposables.length - 1; i >= 0; i--) {\n try {\n this.disposables[i]?.dispose();\n } catch (error) {\n // 记录日志但不抛出异常 - 继续释放其他资源\n // eslint-disable-next-line no-console\n console.error('Error during disposal:', error);\n }\n }\n\n this.disposables.length = 0;\n\n // 调用子类清理方法\n this.onDispose();\n }\n\n /**\n * 注册一个可释放对象,在此对象被释放时进行清理。\n *\n * @template T - 可释放对象类型\n * @param disposable - 要注册的可释放对象\n * @returns 相同的可释放对象,用于链式调用\n */\n protected addDisposable<T extends IDisposable>(disposable: T): T {\n if (this._isDisposed) {\n // 如果已经释放,则立即释放新的可释放对象\n disposable.dispose();\n } else {\n this.disposables.push(disposable);\n }\n return disposable;\n }\n\n /**\n * 注册一个清理函数,在此对象被释放时调用。\n *\n * @param fn - 清理函数\n */\n protected addDisposeFn(fn: () => void): void {\n this.addDisposable({ dispose: fn, isDisposed: false });\n }\n\n /**\n * 如果此对象已被释放则抛出错误。\n * 在不应在释放后调用的方法开头使用此函数。\n *\n * @throws Error 如果对象已被释放\n */\n protected ensureNotDisposed(): void {\n if (this._isDisposed) {\n throw new Error('Object has been disposed');\n }\n }\n\n /**\n * 在对象被释放时调用。\n * 在子类中重写以执行自定义清理。\n */\n protected onDispose(): void {\n // 默认实现不执行任何操作\n }\n}\n\n/**\n * 用于管理多个可释放对象的工具类。\n * 适用于收集应一起释放的可释放对象。\n *\n * @example\n * ```typescript\n * const disposables = new DisposableStore();\n *\n * // 添加各种可释放对象\n * disposables.add(eventListener1);\n * disposables.add(eventListener2);\n * disposables.add({ dispose: () => cleanupSomething() });\n *\n * // 一次性释放所有对象\n * disposables.dispose();\n * ```\n */\nexport class DisposableStore implements IDisposable {\n private readonly items: Set<IDisposable> = new Set();\n private _isDisposed: boolean = false;\n\n /**\n * 获取此存储是否已被释放。\n */\n public get isDisposed(): boolean {\n return this._isDisposed;\n }\n\n /**\n * 向存储中添加可释放对象。\n *\n * @template T - 可释放对象类型\n * @param disposable - 要添加的可释放对象\n * @returns 相同的可释放对象,用于链式调用\n */\n public add<T extends IDisposable>(disposable: T): T {\n if (this._isDisposed) {\n disposable.dispose();\n } else {\n this.items.add(disposable);\n }\n return disposable;\n }\n\n /**\n * 从存储中移除可释放对象而不释放它。\n *\n * @param disposable - 要移除的可释放对象\n */\n public delete(disposable: IDisposable): void {\n this.items.delete(disposable);\n }\n\n /**\n * 释放存储中的所有项目并清空存储。\n */\n public dispose(): void {\n if (this._isDisposed) {\n return;\n }\n\n this._isDisposed = true;\n\n for (const item of this.items) {\n try {\n item.dispose();\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('Error during disposal:', error);\n }\n }\n\n this.items.clear();\n }\n\n /**\n * 释放所有项目但保持存储活跃以接收新项目。\n */\n public clear(): void {\n for (const item of this.items) {\n try {\n item.dispose();\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('Error during disposal:', error);\n }\n }\n this.items.clear();\n }\n\n /**\n * 获取存储中的项目数量。\n */\n public get size(): number {\n return this.items.size;\n }\n}\n\n/**\n * 从清理函数创建可释放对象。\n *\n * @param dispose - 清理函数\n * @returns 可释放对象\n */\nexport function toDisposable(dispose: () => void): IDisposable {\n return {\n dispose,\n isDisposed: false,\n };\n}\n\n/**\n * 将多个可释放对象组合成单个可释放对象。\n *\n * @param disposables - 要组合的可释放对象\n * @returns 一次性释放所有对象的单个可释放对象\n */\nexport function combineDisposables(...disposables: IDisposable[]): IDisposable {\n return {\n dispose: () => {\n for (const d of disposables) {\n d.dispose();\n }\n },\n isDisposed: false,\n };\n}\n"]}
|
|
@@ -8,9 +8,7 @@ function compose(...fns) {
|
|
|
8
8
|
if (fns.length === 1) {
|
|
9
9
|
return fns[0];
|
|
10
10
|
}
|
|
11
|
-
return fns.reduce(
|
|
12
|
-
(composed, fn) => (x) => composed(fn(x))
|
|
13
|
-
);
|
|
11
|
+
return fns.reduce((composed, fn) => (x) => composed(fn(x)));
|
|
14
12
|
}
|
|
15
13
|
__name(compose, "compose");
|
|
16
14
|
function pipe(...fns) {
|
|
@@ -20,9 +18,7 @@ function pipe(...fns) {
|
|
|
20
18
|
if (fns.length === 1) {
|
|
21
19
|
return fns[0];
|
|
22
20
|
}
|
|
23
|
-
return fns.reduce(
|
|
24
|
-
(piped, fn) => (x) => fn(piped(x))
|
|
25
|
-
);
|
|
21
|
+
return fns.reduce((piped, fn) => (x) => fn(piped(x)));
|
|
26
22
|
}
|
|
27
23
|
__name(pipe, "pipe");
|
|
28
24
|
function flow(value, ...fns) {
|
|
@@ -281,5 +277,5 @@ function invert(value) {
|
|
|
281
277
|
__name(invert, "invert");
|
|
282
278
|
|
|
283
279
|
export { allPass, alt, anyPass, apply, compose, constant, curry, err, filterOption, flatMapOption, flatMapResult, flip, flow, fromNullable, getOrElse, getOrElseL, identity, invert, isErr, isNone, isOk, isSome, mapOption, mapResult, matchOption, matchResult, memoize, none, noop, not, ok, once, partial, partialRight, pipe, some, tap, thunk, toNullable, tryCatch, tryCatchAsync, uncurry, unwrapOr, unwrapOrElse };
|
|
284
|
-
//# sourceMappingURL=chunk-
|
|
285
|
-
//# sourceMappingURL=chunk-
|
|
280
|
+
//# sourceMappingURL=chunk-GXFWPL5M.js.map
|
|
281
|
+
//# sourceMappingURL=chunk-GXFWPL5M.js.map
|