@lee-zg/melange 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/fp/compose.ts","../src/fp/curry.ts","../src/fp/result.ts","../src/fp/option.ts","../src/fp/hof.ts"],"names":["__name"],"mappings":";;;;;AAuDO,SAAS,WACX,GAAA,EAC8B;AACjC,EAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACpB,IAAA,OAAO,CAAC,CAAA,KAAe,CAAA;AAAA,EACzB;AAEA,EAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACpB,IAAA,OAAO,IAAI,CAAC,CAAA;AAAA,EACd;AAEA,EAAA,OAAO,GAAA,CAAI,MAAA,CAAO,CAAC,QAAA,EAAU,EAAA,KAAO,CAAC,CAAA,KAAe,QAAA,CAAS,EAAA,CAAG,CAAC,CAAC,CAAC,CAAA;AACrE;AAZgBA,wBAAA,CAAA,OAAA,EAAA,SAAA,CAAA;AA6DT,SAAS,QAAQ,GAAA,EAAyE;AAC/F,EAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACpB,IAAA,OAAO,CAAC,CAAA,KAAe,CAAA;AAAA,EACzB;AAEA,EAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACpB,IAAA,OAAO,IAAI,CAAC,CAAA;AAAA,EACd;AAEA,EAAA,OAAO,GAAA,CAAI,MAAA,CAAO,CAAC,KAAA,EAAO,EAAA,KAAO,CAAC,CAAA,KAAe,EAAA,CAAG,KAAA,CAAM,CAAC,CAAC,CAAC,CAAA;AAC/D;AAVgBA,wBAAA,CAAA,IAAA,EAAA,MAAA,CAAA;AA4DT,SAAS,IAAA,CAAK,UAAmB,GAAA,EAAiD;AACvF,EAAA,OAAO,GAAA,CAAI,OAAO,CAAC,GAAA,EAAK,OAAO,EAAA,CAAG,GAAG,GAAG,KAAK,CAAA;AAC/C;AAFgBA,wBAAA,CAAA,IAAA,EAAA,MAAA,CAAA;;;ACrHT,SAAS,MAAM,EAAA,EAA8C;AAClE,EAAA,MAAM,QAAQ,EAAA,CAAG,MAAA;AAEjB,EAAA,SAAS,WAAW,IAAA,EAA0B;AAC5C,IAAA,IAAI,IAAA,CAAK,UAAU,KAAA,EAAO;AACxB,MAAA,OAAO,EAAA,CAAG,GAAG,IAAI,CAAA;AAAA,IACnB;AACA,IAAA,OAAO,IAAI,QAAA,KAAwB,OAAA,CAAQ,GAAG,IAAA,EAAM,GAAG,QAAQ,CAAA;AAAA,EACjE;AALS,EAAAA,wBAAA,CAAA,OAAA,EAAA,SAAA,CAAA;AAOT,EAAA,OAAO,OAAA;AACT;AAXgBA,wBAAA,CAAA,KAAA,EAAA,OAAA,CAAA;AAkCT,SAAS,QAAQ,EAAA,EAA8D;AACpF,EAAA,OAAO,IAAI,IAAA,KAAoB;AAC7B,IAAA,IAAI,MAAA,GAAkB,EAAA;AACtB,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,MAAA,GAAU,OAAmC,GAAG,CAAA;AAAA,IAClD;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;AARgBA,wBAAA,CAAA,OAAA,EAAA,SAAA,CAAA;AAqCT,SAAS,OAAA,CACd,OACG,WAAA,EAC8B;AACjC,EAAA,OAAO,IAAI,aAAA,KAA6B,EAAA,CAAG,GAAG,WAAA,EAAa,GAAG,aAAa,CAAA;AAC7E;AALgBA,wBAAA,CAAA,OAAA,EAAA,SAAA,CAAA;AA2BT,SAAS,YAAA,CACd,OACG,WAAA,EAC4B;AAC/B,EAAA,OAAO,IAAI,WAAA,KAA2B,EAAA,CAAG,GAAG,WAAA,EAAa,GAAG,WAAW,CAAA;AACzE;AALgBA,wBAAA,CAAA,YAAA,EAAA,cAAA,CAAA;;;ACvIT,SAAS,GAAM,KAAA,EAAiB;AACrC,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,KAAA,EAAM;AAC7B;AAFgBA,wBAAA,CAAA,EAAA,EAAA,IAAA,CAAA;AAiBT,SAAS,IAAO,KAAA,EAAkB;AACvC,EAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAM;AAC9B;AAFgBA,wBAAA,CAAA,GAAA,EAAA,KAAA,CAAA;AAoBT,SAAS,KAAW,MAAA,EAAuC;AAChE,EAAA,OAAO,OAAO,IAAA,KAAS,IAAA;AACzB;AAFgBA,wBAAA,CAAA,IAAA,EAAA,MAAA,CAAA;AAoBT,SAAS,MAAY,MAAA,EAAwC;AAClE,EAAA,OAAO,OAAO,IAAA,KAAS,KAAA;AACzB;AAFgBA,wBAAA,CAAA,KAAA,EAAA,OAAA,CAAA;AA0BT,SAAS,SAAA,CAAmB,QAAsB,EAAA,EAAuC;AAC9F,EAAA,IAAI,IAAA,CAAK,MAAM,CAAA,EAAG;AAChB,IAAA,OAAO,EAAA,CAAG,EAAA,CAAG,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EAC5B;AACA,EAAA,OAAO,MAAA;AACT;AALgBA,wBAAA,CAAA,SAAA,EAAA,WAAA,CAAA;AA+BT,SAAS,aAAA,CACd,QACA,EAAA,EACc;AACd,EAAA,IAAI,IAAA,CAAK,MAAM,CAAA,EAAG;AAChB,IAAA,OAAO,EAAA,CAAG,OAAO,KAAK,CAAA;AAAA,EACxB;AACA,EAAA,OAAO,MAAA;AACT;AARgBA,wBAAA,CAAA,aAAA,EAAA,eAAA,CAAA;AA4BT,SAAS,QAAA,CAAe,QAAsB,YAAA,EAAoB;AACvE,EAAA,IAAI,IAAA,CAAK,MAAM,CAAA,EAAG;AAChB,IAAA,OAAO,MAAA,CAAO,KAAA;AAAA,EAChB;AACA,EAAA,OAAO,YAAA;AACT;AALgBA,wBAAA,CAAA,QAAA,EAAA,UAAA,CAAA;AAyBT,SAAS,YAAA,CAAmB,QAAsB,EAAA,EAA4B;AACnF,EAAA,IAAI,IAAA,CAAK,MAAM,CAAA,EAAG;AAChB,IAAA,OAAO,MAAA,CAAO,KAAA;AAAA,EAChB;AACA,EAAA,OAAO,EAAA,CAAG,OAAO,KAAK,CAAA;AACxB;AALgBA,wBAAA,CAAA,YAAA,EAAA,cAAA,CAAA;AA2BT,SAAS,WAAA,CACd,QACA,QAAA,EACG;AACH,EAAA,IAAI,IAAA,CAAK,MAAM,CAAA,EAAG;AAChB,IAAA,OAAO,QAAA,CAAS,EAAA,CAAG,MAAA,CAAO,KAAK,CAAA;AAAA,EACjC;AACA,EAAA,OAAO,QAAA,CAAS,GAAA,CAAI,MAAA,CAAO,KAAK,CAAA;AAClC;AARgBA,wBAAA,CAAA,WAAA,EAAA,aAAA,CAAA;AA0BT,SAAS,SAAY,EAAA,EAAiC;AAC3D,EAAA,IAAI;AACF,IAAA,OAAO,EAAA,CAAG,IAAI,CAAA;AAAA,EAChB,SAAS,KAAA,EAAO;AACd,IAAA,OAAO,IAAI,KAAK,CAAA;AAAA,EAClB;AACF;AANgBA,wBAAA,CAAA,QAAA,EAAA,UAAA,CAAA;AAuBhB,eAAsB,cAAiB,EAAA,EAAmD;AACxF,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,MAAM,EAAA,EAAG;AACxB,IAAA,OAAO,GAAG,MAAM,CAAA;AAAA,EAClB,SAAS,KAAA,EAAO;AACd,IAAA,OAAO,IAAI,KAAK,CAAA;AAAA,EAClB;AACF;AAPsBA,wBAAA,CAAA,aAAA,EAAA,eAAA,CAAA;;;ACnPf,SAAS,KAAQ,KAAA,EAAmB;AACzC,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAM;AAC/B;AAFgBA,wBAAA,CAAA,IAAA,EAAA,MAAA,CAAA;AAeT,SAAS,IAAA,GAAa;AAC3B,EAAA,OAAO,EAAE,MAAM,MAAA,EAAO;AACxB;AAFgBA,wBAAA,CAAA,IAAA,EAAA,MAAA,CAAA;AAmBT,SAAS,OAAU,MAAA,EAAsC;AAC9D,EAAA,OAAO,OAAO,IAAA,KAAS,MAAA;AACzB;AAFgBA,wBAAA,CAAA,MAAA,EAAA,QAAA,CAAA;AAmBT,SAAS,OAAU,MAAA,EAAmC;AAC3D,EAAA,OAAO,OAAO,IAAA,KAAS,MAAA;AACzB;AAFgBA,wBAAA,CAAA,MAAA,EAAA,QAAA,CAAA;AAmBT,SAAS,aAAgB,KAAA,EAAwC;AACtE,EAAA,OAAO,KAAA,IAAS,IAAA,GAAO,IAAA,EAAK,GAAI,KAAK,KAAK,CAAA;AAC5C;AAFgBA,wBAAA,CAAA,YAAA,EAAA,cAAA,CAAA;AAyBT,SAAS,SAAA,CAAgB,QAAmB,EAAA,EAAoC;AACrF,EAAA,IAAI,MAAA,CAAO,MAAM,CAAA,EAAG;AAClB,IAAA,OAAO,IAAA,CAAK,EAAA,CAAG,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EAC9B;AACA,EAAA,OAAO,MAAA;AACT;AALgBA,wBAAA,CAAA,SAAA,EAAA,WAAA,CAAA;AA+BT,SAAS,aAAA,CAAoB,QAAmB,EAAA,EAA4C;AACjG,EAAA,IAAI,MAAA,CAAO,MAAM,CAAA,EAAG;AAClB,IAAA,OAAO,EAAA,CAAG,OAAO,KAAK,CAAA;AAAA,EACxB;AACA,EAAA,OAAO,MAAA;AACT;AALgBA,wBAAA,CAAA,aAAA,EAAA,eAAA,CAAA;AAwBT,SAAS,SAAA,CAAa,QAAmB,YAAA,EAAoB;AAClE,EAAA,IAAI,MAAA,CAAO,MAAM,CAAA,EAAG;AAClB,IAAA,OAAO,MAAA,CAAO,KAAA;AAAA,EAChB;AACA,EAAA,OAAO,YAAA;AACT;AALgBA,wBAAA,CAAA,SAAA,EAAA,WAAA,CAAA;AAwBT,SAAS,UAAA,CAAc,QAAmB,EAAA,EAAgB;AAC/D,EAAA,IAAI,MAAA,CAAO,MAAM,CAAA,EAAG;AAClB,IAAA,OAAO,MAAA,CAAO,KAAA;AAAA,EAChB;AACA,EAAA,OAAO,EAAA,EAAG;AACZ;AALgBA,wBAAA,CAAA,UAAA,EAAA,YAAA,CAAA;AA0BT,SAAS,WAAA,CACd,QACA,QAAA,EACG;AACH,EAAA,IAAI,MAAA,CAAO,MAAM,CAAA,EAAG;AAClB,IAAA,OAAO,QAAA,CAAS,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA;AAAA,EACnC;AACA,EAAA,OAAO,SAAS,IAAA,EAAK;AACvB;AARgBA,wBAAA,CAAA,WAAA,EAAA,aAAA,CAAA;AAuBT,SAAS,WAAc,MAAA,EAA6B;AACzD,EAAA,IAAI,MAAA,CAAO,MAAM,CAAA,EAAG;AAClB,IAAA,OAAO,MAAA,CAAO,KAAA;AAAA,EAChB;AACA,EAAA,OAAO,IAAA;AACT;AALgBA,wBAAA,CAAA,UAAA,EAAA,YAAA,CAAA;AAuBT,SAAS,YAAA,CAAgB,QAAmB,SAAA,EAA6C;AAC9F,EAAA,IAAI,OAAO,MAAM,CAAA,IAAK,SAAA,CAAU,MAAA,CAAO,KAAK,CAAA,EAAG;AAC7C,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAA,EAAK;AACd;AALgBA,wBAAA,CAAA,YAAA,EAAA,cAAA,CAAA;AAsBT,SAAS,GAAA,CAAO,OAAkB,MAAA,EAA8B;AACrE,EAAA,OAAO,MAAA,CAAO,KAAK,CAAA,GAAI,KAAA,GAAQ,MAAA;AACjC;AAFgBA,wBAAA,CAAA,GAAA,EAAA,KAAA,CAAA;;;ACjQT,SAAS,OAAA,CACd,IACA,KAAA,EACG;AACH,EAAA,MAAM,KAAA,uBAAY,GAAA,EAA2B;AAE7C,EAAA,QAAQ,IAAI,IAAA,KAAuC;AACjD,IAAA,MAAM,GAAA,GAAM,QAAQ,KAAA,CAAM,GAAG,IAAI,CAAA,GAAI,IAAA,CAAK,UAAU,IAAI,CAAA;AAExD,IAAA,IAAI,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,EAAG;AAClB,MAAA,OAAO,KAAA,CAAM,IAAI,GAAG,CAAA;AAAA,IACtB;AAEA,IAAA,MAAM,MAAA,GAAS,EAAA,CAAG,GAAG,IAAI,CAAA;AACzB,IAAA,KAAA,CAAM,GAAA,CAAI,KAAK,MAAM,CAAA;AACrB,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;AAjBgBA,wBAAA,CAAA,OAAA,EAAA,SAAA,CAAA;AAsCT,SAAS,KAA4B,EAAA,EAAU;AACpD,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,IAAI,MAAA;AAEJ,EAAA,QAAQ,IAAI,IAAA,KAAuC;AACjD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAA,GAAS,IAAA;AACT,MAAA,MAAA,GAAS,EAAA,CAAG,GAAG,IAAI,CAAA;AAAA,IACrB;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;AAXgBA,wBAAA,CAAA,IAAA,EAAA,MAAA,CAAA;AAqCT,SAAS,IAAO,MAAA,EAA6C;AAClE,EAAA,OAAO,CAAC,KAAA,KAAgB;AACtB,IAAA,MAAA,CAAO,KAAK,CAAA;AACZ,IAAA,OAAO,KAAA;AAAA,EACT,CAAA;AACF;AALgBA,wBAAA,CAAA,GAAA,EAAA,KAAA,CAAA;AAsBT,SAAS,SAAY,KAAA,EAAa;AACvC,EAAA,OAAO,KAAA;AACT;AAFgBA,wBAAA,CAAA,QAAA,EAAA,UAAA,CAAA;AAqBT,SAAS,SAAY,KAAA,EAAmB;AAC7C,EAAA,OAAO,MAAM,KAAA;AACf;AAFgBA,wBAAA,CAAA,QAAA,EAAA,UAAA,CAAA;AAcT,SAAS,IAAA,GAAa;AAE7B;AAFgBA,wBAAA,CAAA,IAAA,EAAA,MAAA,CAAA;AAoBT,SAAS,IAAO,SAAA,EAAyD;AAC9E,EAAA,OAAO,CAAC,KAAA,KAAa,CAAC,SAAA,CAAU,KAAK,CAAA;AACvC;AAFgBA,wBAAA,CAAA,GAAA,EAAA,KAAA,CAAA;AAsBT,SAAS,QAAW,UAAA,EAAiE;AAC1F,EAAA,OAAO,CAAC,KAAA,KAAa,UAAA,CAAW,MAAM,CAAA,SAAA,KAAa,SAAA,CAAU,KAAK,CAAC,CAAA;AACrE;AAFgBA,wBAAA,CAAA,OAAA,EAAA,SAAA,CAAA;AAsBT,SAAS,QAAW,UAAA,EAAiE;AAC1F,EAAA,OAAO,CAAC,KAAA,KAAa,UAAA,CAAW,KAAK,CAAA,SAAA,KAAa,SAAA,CAAU,KAAK,CAAC,CAAA;AACpE;AAFgBA,wBAAA,CAAA,OAAA,EAAA,SAAA,CAAA;AAsBT,SAAS,KAAc,EAAA,EAA0C;AACtE,EAAA,OAAO,CAAC,CAAA,EAAM,CAAA,KAAS,EAAA,CAAG,GAAG,CAAC,CAAA;AAChC;AAFgBA,wBAAA,CAAA,IAAA,EAAA,MAAA,CAAA;AAuBT,SAAS,KAAA,CAAY,OAAU,EAAA,EAAwB;AAC5D,EAAA,OAAO,GAAG,KAAK,CAAA;AACjB;AAFgBA,wBAAA,CAAA,KAAA,EAAA,OAAA,CAAA;AAkBT,SAAS,MAAS,EAAA,EAAsB;AAC7C,EAAA,OAAO,EAAA;AACT;AAFgBA,wBAAA,CAAA,KAAA,EAAA,OAAA,CAAA;AAgBT,SAAS,OAAO,KAAA,EAAyB;AAC9C,EAAA,OAAO,CAAC,KAAA;AACV;AAFgBA,wBAAA,CAAA,MAAA,EAAA,QAAA,CAAA","file":"chunk-UYJUSNDI.cjs","sourcesContent":["/**\n * @fileoverview 函数组合工具\n * @module melange/fp/compose\n * @description 提供组合和连接函数的工具,\n * 实现无点风格编程和函数链式调用。\n */\n\nimport type { UnaryFunction } from '../types';\n\n/**\n * 从右到左组合多个函数。\n * 最右边的函数可以接受多个参数,其他所有函数必须是一元的。\n *\n * @description\n * 函数组合是函数式编程中的基本概念。\n * `compose(f, g, h)(x)` 等价于 `f(g(h(x)))`。\n *\n * @example\n * ```typescript\n * const addOne = (x: number) => x + 1;\n * const double = (x: number) => x * 2;\n * const square = (x: number) => x * x;\n *\n * const composed = compose(square, double, addOne);\n * composed(2); // ((2 + 1) * 2)² = 36\n * ```\n *\n * @param fns - 要组合的函数\n * @returns 一个新函数,从右到左应用所有函数\n */\nexport function compose<A, B>(fn1: UnaryFunction<A, B>): UnaryFunction<A, B>;\nexport function compose<A, B, C>(\n fn2: UnaryFunction<B, C>,\n fn1: UnaryFunction<A, B>\n): UnaryFunction<A, C>;\nexport function compose<A, B, C, D>(\n fn3: UnaryFunction<C, D>,\n fn2: UnaryFunction<B, C>,\n fn1: UnaryFunction<A, B>\n): UnaryFunction<A, D>;\nexport function compose<A, B, C, D, E>(\n fn4: UnaryFunction<D, E>,\n fn3: UnaryFunction<C, D>,\n fn2: UnaryFunction<B, C>,\n fn1: UnaryFunction<A, B>\n): UnaryFunction<A, E>;\nexport function compose<A, B, C, D, E, F>(\n fn5: UnaryFunction<E, F>,\n fn4: UnaryFunction<D, E>,\n fn3: UnaryFunction<C, D>,\n fn2: UnaryFunction<B, C>,\n fn1: UnaryFunction<A, B>\n): UnaryFunction<A, F>;\nexport function compose(...fns: UnaryFunction<unknown, unknown>[]): UnaryFunction<unknown, unknown>;\n\nexport function compose(\n ...fns: UnaryFunction<unknown, unknown>[]\n): UnaryFunction<unknown, unknown> {\n if (fns.length === 0) {\n return (x: unknown) => x;\n }\n\n if (fns.length === 1) {\n return fns[0] as UnaryFunction<unknown, unknown>;\n }\n\n return fns.reduce((composed, fn) => (x: unknown) => composed(fn(x)));\n}\n\n/**\n * 从左到右连接多个函数。\n * 第一个函数可以接受多个参数,其他所有函数必须是一元的。\n *\n * @description\n * Pipe 是 compose 的反向操作,从左到右应用函数。\n * `pipe(f, g, h)(x)` 等价于 `h(g(f(x)))`。\n * 这通常更易读,因为它遵循自然的阅读顺序。\n *\n * @example\n * ```typescript\n * const addOne = (x: number) => x + 1;\n * const double = (x: number) => x * 2;\n * const square = (x: number) => x * x;\n *\n * const piped = pipe(addOne, double, square);\n * piped(2); // ((2 + 1) * 2)² = 36\n * ```\n *\n * @param fns - 要连接的函数\n * @returns 一个新函数,从左到右应用所有函数\n */\nexport function pipe<A, B>(fn1: UnaryFunction<A, B>): UnaryFunction<A, B>;\nexport function pipe<A, B, C>(\n fn1: UnaryFunction<A, B>,\n fn2: UnaryFunction<B, C>\n): UnaryFunction<A, C>;\nexport function pipe<A, B, C, D>(\n fn1: UnaryFunction<A, B>,\n fn2: UnaryFunction<B, C>,\n fn3: UnaryFunction<C, D>\n): UnaryFunction<A, D>;\nexport function pipe<A, B, C, D, E>(\n fn1: UnaryFunction<A, B>,\n fn2: UnaryFunction<B, C>,\n fn3: UnaryFunction<C, D>,\n fn4: UnaryFunction<D, E>\n): UnaryFunction<A, E>;\nexport function pipe<A, B, C, D, E, F>(\n fn1: UnaryFunction<A, B>,\n fn2: UnaryFunction<B, C>,\n fn3: UnaryFunction<C, D>,\n fn4: UnaryFunction<D, E>,\n fn5: UnaryFunction<E, F>\n): UnaryFunction<A, F>;\nexport function pipe(...fns: UnaryFunction<unknown, unknown>[]): UnaryFunction<unknown, unknown>;\n\nexport function pipe(...fns: UnaryFunction<unknown, unknown>[]): UnaryFunction<unknown, unknown> {\n if (fns.length === 0) {\n return (x: unknown) => x;\n }\n\n if (fns.length === 1) {\n return fns[0] as UnaryFunction<unknown, unknown>;\n }\n\n return fns.reduce((piped, fn) => (x: unknown) => fn(piped(x)));\n}\n\n/**\n * 创建函数流,类似于 pipe 但立即返回最终结果。\n * 适用于通过一系列函数转换值。\n *\n * @description\n * Flow 类似于 pipe,但不是返回函数,\n * 而是立即将值通过所有函数应用。\n *\n * @example\n * ```typescript\n * const result = flow(\n * 5,\n * x => x + 1,\n * x => x * 2,\n * x => x.toString()\n * );\n * // result = \"12\"\n * ```\n *\n * @param value - 初始值\n * @param fns - 要应用的函数\n * @returns 将所有函数应用于值的结果\n */\nexport function flow<A>(value: A): A;\nexport function flow<A, B>(value: A, fn1: UnaryFunction<A, B>): B;\nexport function flow<A, B, C>(value: A, fn1: UnaryFunction<A, B>, fn2: UnaryFunction<B, C>): C;\nexport function flow<A, B, C, D>(\n value: A,\n fn1: UnaryFunction<A, B>,\n fn2: UnaryFunction<B, C>,\n fn3: UnaryFunction<C, D>\n): D;\nexport function flow<A, B, C, D, E>(\n value: A,\n fn1: UnaryFunction<A, B>,\n fn2: UnaryFunction<B, C>,\n fn3: UnaryFunction<C, D>,\n fn4: UnaryFunction<D, E>\n): E;\nexport function flow<A, B, C, D, E, F>(\n value: A,\n fn1: UnaryFunction<A, B>,\n fn2: UnaryFunction<B, C>,\n fn3: UnaryFunction<C, D>,\n fn4: UnaryFunction<D, E>,\n fn5: UnaryFunction<E, F>\n): F;\n\nexport function flow(value: unknown, ...fns: UnaryFunction<unknown, unknown>[]): unknown {\n return fns.reduce((acc, fn) => fn(acc), value);\n}\n","/**\n * @fileoverview 柯里化和部分应用工具\n * @module melange/fp/curry\n * @description 提供柯里化函数和部分应用的工具,\n * 实现更灵活的函数组合和重用。\n */\n\n/**\n * 柯里化二元函数。\n * 将接受两个参数的函数转换为接受一个参数并返回接受第二个参数的函数。\n *\n * @description\n * 柯里化以数学家 Haskell Curry 命名。它将具有多个参数的函数转换为一系列函数,每个函数接受一个参数。\n *\n * @example\n * ```typescript\n * const add = (a: number, b: number) => a + b;\n * const curriedAdd = curry(add);\n *\n * curriedAdd(1)(2); // 3\n * const addFive = curriedAdd(5);\n * addFive(10); // 15\n * ```\n *\n * @template A - 第一个参数的类型\n * @template B - 第二个参数的类型\n * @template R - 返回类型\n * @param fn - 要柯里化的二元函数\n * @returns 函数的柯里化版本\n */\nexport function curry<A, B, R>(fn: (a: A, b: B) => R): (a: A) => (b: B) => R;\n\n/**\n * 柯里化三元函数。\n *\n * @template A - 第一个参数的类型\n * @template B - 第二个参数的类型\n * @template C - 第三个参数的类型\n * @template R - 返回类型\n * @param fn - 要柯里化的三元函数\n * @returns 函数的柯里化版本\n */\nexport function curry<A, B, C, R>(fn: (a: A, b: B, c: C) => R): (a: A) => (b: B) => (c: C) => R;\n\n/**\n * 柯里化四元函数。\n *\n * @template A - 第一个参数的类型\n * @template B - 第二个参数的类型\n * @template C - 第三个参数的类型\n * @template D - 第四个参数的类型\n * @template R - 返回类型\n * @param fn - 要柯里化的四元函数\n * @returns 函数的柯里化版本\n */\nexport function curry<A, B, C, D, R>(\n fn: (a: A, b: B, c: C, d: D) => R\n): (a: A) => (b: B) => (c: C) => (d: D) => R;\n\nexport function curry(fn: (...args: unknown[]) => unknown): unknown {\n const arity = fn.length;\n\n function curried(...args: unknown[]): unknown {\n if (args.length >= arity) {\n return fn(...args);\n }\n return (...moreArgs: unknown[]) => curried(...args, ...moreArgs);\n }\n\n return curried;\n}\n\n/**\n * 反柯里化函数。\n * 将一元函数序列转换回接受多个参数的单个函数。\n *\n * @example\n * ```typescript\n * const curriedAdd = (a: number) => (b: number) => a + b;\n * const add = uncurry(curriedAdd);\n *\n * add(1, 2); // 3\n * ```\n *\n * @template A - 第一个参数的类型\n * @template B - 第二个参数的类型\n * @template R - 返回类型\n * @param fn - 要反柯里化的函数\n * @returns 函数的反柯里化版本\n */\nexport function uncurry<A, B, R>(fn: (a: A) => (b: B) => R): (a: A, b: B) => R;\nexport function uncurry<A, B, C, R>(fn: (a: A) => (b: B) => (c: C) => R): (a: A, b: B, c: C) => R;\n\nexport function uncurry(fn: (a: unknown) => unknown): (...args: unknown[]) => unknown {\n return (...args: unknown[]) => {\n let result: unknown = fn;\n for (const arg of args) {\n result = (result as (a: unknown) => unknown)(arg);\n }\n return result;\n };\n}\n\n/**\n * 从左侧部分应用参数到函数。\n * 返回一个接受剩余参数的新函数。\n *\n * @description\n * 部分应用不同于柯里化。柯里化将函数转换为一元函数序列,\n * 而部分应用固定一些参数并返回接受剩余参数的函数。\n *\n * @example\n * ```typescript\n * const greet = (greeting: string, name: string, punctuation: string) =>\n * `${greeting}, ${name}${punctuation}`;\n *\n * const sayHello = partial(greet, 'Hello');\n * sayHello('World', '!'); // \"Hello, World!\"\n *\n * const sayHelloWorld = partial(greet, 'Hello', 'World');\n * sayHelloWorld('!'); // \"Hello, World!\"\n * ```\n *\n * @template T - 部分参数的元组类型\n * @template R - 剩余参数的元组类型\n * @template Result - 返回类型\n * @param fn - 要部分应用的函数\n * @param partialArgs - 要固定的参数\n * @returns 接受剩余参数的新函数\n */\nexport function partial<T extends unknown[], R extends unknown[], Result>(\n fn: (...args: [...T, ...R]) => Result,\n ...partialArgs: T\n): (...remainingArgs: R) => Result {\n return (...remainingArgs: R): Result => fn(...partialArgs, ...remainingArgs);\n}\n\n/**\n * 从右侧部分应用参数到函数。\n * 返回一个接受剩余参数的新函数。\n *\n * @example\n * ```typescript\n * const greet = (greeting: string, name: string, punctuation: string) =>\n * `${greeting}, ${name}${punctuation}`;\n *\n * const greetExcitedly = partialRight(greet, '!');\n * greetExcitedly('Hello', 'World'); // \"Hello, World!\"\n * ```\n *\n * @template L - 前导参数的元组类型\n * @template T - 部分参数的元组类型\n * @template Result - 返回类型\n * @param fn - 要部分应用的函数\n * @param partialArgs - 从右侧固定的参数\n * @returns 接受前导参数的新函数\n */\nexport function partialRight<L extends unknown[], T extends unknown[], Result>(\n fn: (...args: [...L, ...T]) => Result,\n ...partialArgs: T\n): (...leadingArgs: L) => Result {\n return (...leadingArgs: L): Result => fn(...leadingArgs, ...partialArgs);\n}\n","/**\n * @fileoverview 用于函数式错误处理的 Result 类型\n * @module melange/fp/result\n * @description 提供 Result 类型和工具,用于处理可能成功或失败的操作,\n * 而无需抛出异常。\n */\n\nimport type { Result, Ok, Err, UnaryFunction } from '../types';\n\n/**\n * 创建包含给定值的成功 Result。\n *\n * @example\n * ```typescript\n * const result = ok(42);\n * // { _tag: 'Ok', value: 42 }\n * ```\n *\n * @template T - 成功值的类型\n * @param value - 成功值\n * @returns 包含该值的 Ok Result\n */\nexport function ok<T>(value: T): Ok<T> {\n return { _tag: 'Ok', value };\n}\n\n/**\n * 创建包含给定错误的失败 Result。\n *\n * @example\n * ```typescript\n * const result = err(new Error('出错了'));\n * // { _tag: 'Err', error: Error('出错了') }\n * ```\n *\n * @template E - 错误的类型\n * @param error - 错误值\n * @returns 包含该错误的 Err Result\n */\nexport function err<E>(error: E): Err<E> {\n return { _tag: 'Err', error };\n}\n\n/**\n * 类型守卫,用于检查 Result 是否为 Ok。\n *\n * @example\n * ```typescript\n * const result = ok(42);\n * if (isOk(result)) {\n * console.log(result.value); // 42\n * }\n * ```\n *\n * @template T - 成功类型\n * @template E - 错误类型\n * @param result - 要检查的 Result\n * @returns 如果 Result 是 Ok 则返回 true\n */\nexport function isOk<T, E>(result: Result<T, E>): result is Ok<T> {\n return result._tag === 'Ok';\n}\n\n/**\n * 类型守卫,用于检查 Result 是否为 Err。\n *\n * @example\n * ```typescript\n * const result = err('error');\n * if (isErr(result)) {\n * console.log(result.error); // 'error'\n * }\n * ```\n *\n * @template T - 成功类型\n * @template E - 错误类型\n * @param result - 要检查的 Result\n * @returns 如果 Result 是 Err 则返回 true\n */\nexport function isErr<T, E>(result: Result<T, E>): result is Err<E> {\n return result._tag === 'Err';\n}\n\n/**\n * 在 Result 的成功值上映射函数。\n * 如果 Result 是 Err,则错误将原样传递。\n *\n * @example\n * ```typescript\n * const result = ok(5);\n * const doubled = mapResult(result, x => x * 2);\n * // { _tag: 'Ok', value: 10 }\n *\n * const error = err('error');\n * const still = mapResult(error, x => x * 2);\n * // { _tag: 'Err', error: 'error' }\n * ```\n *\n * @template T - 原始成功类型\n * @template U - 映射后的成功类型\n * @template E - 错误类型\n * @param result - 要映射的 Result\n * @param fn - 要应用于成功值的函数\n * @returns 带有映射值的新 Result\n */\nexport function mapResult<T, U, E>(result: Result<T, E>, fn: UnaryFunction<T, U>): Result<U, E> {\n if (isOk(result)) {\n return ok(fn(result.value));\n }\n return result;\n}\n\n/**\n * 在 Result 的成功值上映射返回 Result 的函数。\n * 在其他库中这也被称为 `chain` 或 `bind`。\n *\n * @example\n * ```typescript\n * const safeDivide = (a: number, b: number): Result<number, string> =>\n * b === 0 ? err('除零错误') : ok(a / b);\n *\n * const result = ok(10);\n * const divided = flatMapResult(result, x => safeDivide(x, 2));\n * // { _tag: 'Ok', value: 5 }\n *\n * const divideByZero = flatMapResult(result, x => safeDivide(x, 0));\n * // { _tag: 'Err', error: '除零错误' }\n * ```\n *\n * @template T - 原始成功类型\n * @template U - 映射后的成功类型\n * @template E - 错误类型\n * @param result - 要 flatMap 的 Result\n * @param fn - 应用的返回 Result 的函数\n * @returns 展平后的 Result\n */\nexport function flatMapResult<T, U, E>(\n result: Result<T, E>,\n fn: UnaryFunction<T, Result<U, E>>\n): Result<U, E> {\n if (isOk(result)) {\n return fn(result.value);\n }\n return result;\n}\n\n/**\n * 解包 Result,返回成功值或如果为 Err 则返回默认值。\n *\n * @example\n * ```typescript\n * const success = ok(42);\n * unwrapOr(success, 0); // 42\n *\n * const failure = err('error');\n * unwrapOr(failure, 0); // 0\n * ```\n *\n * @template T - 成功类型\n * @template E - 错误类型\n * @param result - 要解包的 Result\n * @param defaultValue - 如果为 Err 的默认值\n * @returns 成功值或默认值\n */\nexport function unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T {\n if (isOk(result)) {\n return result.value;\n }\n return defaultValue;\n}\n\n/**\n * 解包 Result,返回成功值或如果为 Err 则调用函数。\n *\n * @example\n * ```typescript\n * const success = ok(42);\n * unwrapOrElse(success, () => 0); // 42\n *\n * const failure = err('error');\n * unwrapOrElse(failure, () => 0); // 0\n * ```\n *\n * @template T - 成功类型\n * @template E - 错误类型\n * @param result - 要解包的 Result\n * @param fn - 如果为 Err 要调用的函数\n * @returns 成功值或函数的结果\n */\nexport function unwrapOrElse<T, E>(result: Result<T, E>, fn: UnaryFunction<E, T>): T {\n if (isOk(result)) {\n return result.value;\n }\n return fn(result.error);\n}\n\n/**\n * 将 Result 与成功和错误处理程序匹配。\n *\n * @example\n * ```typescript\n * const result = ok(42);\n * const message = match(result, {\n * ok: value => `得到 ${value}`,\n * err: error => `错误: ${error}`\n * });\n * // \"得到 42\"\n * ```\n *\n * @template T - 成功类型\n * @template E - 错误类型\n * @template R - 返回类型\n * @param result - 要匹配的 Result\n * @param handlers - 带有 ok 和 err 处理程序的对象\n * @returns 匹配处理程序的结果\n */\nexport function matchResult<T, E, R>(\n result: Result<T, E>,\n handlers: { ok: UnaryFunction<T, R>; err: UnaryFunction<E, R> }\n): R {\n if (isOk(result)) {\n return handlers.ok(result.value);\n }\n return handlers.err(result.error);\n}\n\n/**\n * 尝试执行函数并将结果包装在 Result 类型中。\n *\n * @example\n * ```typescript\n * const result = tryCatch(() => JSON.parse('{\"a\": 1}'));\n * // { _tag: 'Ok', value: { a: 1 } }\n *\n * const error = tryCatch(() => JSON.parse('invalid'));\n * // { _tag: 'Err', error: SyntaxError(...) }\n * ```\n *\n * @template T - 函数的返回类型\n * @param fn - 要执行的函数\n * @returns 包含返回值或错误的 Result\n */\nexport function tryCatch<T>(fn: () => T): Result<T, unknown> {\n try {\n return ok(fn());\n } catch (error) {\n return err(error);\n }\n}\n\n/**\n * 尝试执行异步函数并将结果包装在 Result 类型中。\n *\n * @example\n * ```typescript\n * const result = await tryCatchAsync(async () => {\n * const response = await fetch('/api/data');\n * return response.json();\n * });\n * ```\n *\n * @template T - 异步函数的返回类型\n * @param fn - 要执行的异步函数\n * @returns 包含返回值或错误的 Result 的 Promise\n */\nexport async function tryCatchAsync<T>(fn: () => Promise<T>): Promise<Result<T, unknown>> {\n try {\n const result = await fn();\n return ok(result);\n } catch (error) {\n return err(error);\n }\n}\n","/**\n * @fileoverview 用于可空值处理的 Option 类型\n * @module melange/fp/option\n * @description 提供 Option 类型和工具,用于处理可能存在或不存在的值,\n * 而不直接使用 null/undefined。\n */\n\nimport type { Option, Some, None, UnaryFunction } from '../types';\n\n/**\n * 创建包含给定值的 Some Option。\n *\n * @example\n * ```typescript\n * const option = some(42);\n * // { _tag: 'Some', value: 42 }\n * ```\n *\n * @template T - 值的类型\n * @param value - 要包装的值\n * @returns 包含该值的 Some Option\n */\nexport function some<T>(value: T): Some<T> {\n return { _tag: 'Some', value };\n}\n\n/**\n * 创建表示缺失值的 None Option。\n *\n * @example\n * ```typescript\n * const option = none();\n * // { _tag: 'None' }\n * ```\n *\n * @returns None Option\n */\nexport function none(): None {\n return { _tag: 'None' };\n}\n\n/**\n * 类型守卫,用于检查 Option 是否为 Some。\n *\n * @example\n * ```typescript\n * const option = some(42);\n * if (isSome(option)) {\n * console.log(option.value); // 42\n * }\n * ```\n *\n * @template T - 值的类型\n * @param option - 要检查的 Option\n * @returns 如果 Option 是 Some 则返回 true\n */\nexport function isSome<T>(option: Option<T>): option is Some<T> {\n return option._tag === 'Some';\n}\n\n/**\n * 类型守卫,用于检查 Option 是否为 None。\n *\n * @example\n * ```typescript\n * const option = none();\n * if (isNone(option)) {\n * console.log('无值');\n * }\n * ```\n *\n * @template T - 值的类型\n * @param option - 要检查的 Option\n * @returns 如果 Option 是 None 则返回 true\n */\nexport function isNone<T>(option: Option<T>): option is None {\n return option._tag === 'None';\n}\n\n/**\n * 从可空值创建 Option。\n * 如果值为 null 或 undefined,返回 None;否则返回 Some。\n *\n * @example\n * ```typescript\n * fromNullable(42); // Some(42)\n * fromNullable(null); // None\n * fromNullable(undefined);// None\n * ```\n *\n * @template T - 值的类型\n * @param value - 可空值\n * @returns 包装该值的 Option\n */\nexport function fromNullable<T>(value: T | null | undefined): Option<T> {\n return value == null ? none() : some(value);\n}\n\n/**\n * 在 Option 的值上映射函数。\n * 如果 Option 是 None,则原样返回 None。\n *\n * @example\n * ```typescript\n * const option = some(5);\n * const doubled = mapOption(option, x => x * 2);\n * // Some(10)\n *\n * const empty = none();\n * const still = mapOption(empty, x => x * 2);\n * // None\n * ```\n *\n * @template T - 原始值类型\n * @template U - 映射后的值类型\n * @param option - 要映射的 Option\n * @param fn - 要应用于值的函数\n * @returns 带有映射值的新 Option\n */\nexport function mapOption<T, U>(option: Option<T>, fn: UnaryFunction<T, U>): Option<U> {\n if (isSome(option)) {\n return some(fn(option.value));\n }\n return option;\n}\n\n/**\n * 在 Option 的值上映射返回 Option 的函数。\n * 在其他库中这也被称为 `chain` 或 `bind`。\n *\n * @example\n * ```typescript\n * const safeDivide = (n: number): Option<number> =>\n * n === 0 ? none() : some(100 / n);\n *\n * const option = some(10);\n * const divided = flatMapOption(option, safeDivide);\n * // Some(10)\n *\n * const zero = some(0);\n * const divideByZero = flatMapOption(zero, safeDivide);\n * // None\n * ```\n *\n * @template T - 原始值类型\n * @template U - 映射后的值类型\n * @param option - 要 flatMap 的 Option\n * @param fn - 应用的返回 Option 的函数\n * @returns 展平后的 Option\n */\nexport function flatMapOption<T, U>(option: Option<T>, fn: UnaryFunction<T, Option<U>>): Option<U> {\n if (isSome(option)) {\n return fn(option.value);\n }\n return option;\n}\n\n/**\n * 从 Option 获取值,如果为 None 则返回默认值。\n *\n * @example\n * ```typescript\n * const present = some(42);\n * getOrElse(present, 0); // 42\n *\n * const absent = none();\n * getOrElse(absent, 0); // 0\n * ```\n *\n * @template T - 值的类型\n * @param option - 要解包的 Option\n * @param defaultValue - 如果为 None 的默认值\n * @returns 值或默认值\n */\nexport function getOrElse<T>(option: Option<T>, defaultValue: T): T {\n if (isSome(option)) {\n return option.value;\n }\n return defaultValue;\n}\n\n/**\n * 从 Option 获取值,如果为 None 则调用函数。\n *\n * @example\n * ```typescript\n * const present = some(42);\n * getOrElseL(present, () => 0); // 42\n *\n * const absent = none();\n * getOrElseL(absent, () => computeDefault()); // computeDefault() 的结果\n * ```\n *\n * @template T - 值的类型\n * @param option - 要解包的 Option\n * @param fn - 如果为 None 要调用的函数\n * @returns 值或函数的结果\n */\nexport function getOrElseL<T>(option: Option<T>, fn: () => T): T {\n if (isSome(option)) {\n return option.value;\n }\n return fn();\n}\n\n/**\n * 将 Option 与 Some 和 None 处理程序匹配。\n *\n * @example\n * ```typescript\n * const option = some(42);\n * const message = matchOption(option, {\n * some: value => `得到 ${value}`,\n * none: () => '无'\n * });\n * // \"得到 42\"\n * ```\n *\n * @template T - 值的类型\n * @template R - 返回类型\n * @param option - 要匹配的 Option\n * @param handlers - 带有 some 和 none 处理程序的对象\n * @returns 匹配处理程序的结果\n */\nexport function matchOption<T, R>(\n option: Option<T>,\n handlers: { some: UnaryFunction<T, R>; none: () => R }\n): R {\n if (isSome(option)) {\n return handlers.some(option.value);\n }\n return handlers.none();\n}\n\n/**\n * 将 Option 转换为可空值。\n *\n * @example\n * ```typescript\n * toNullable(some(42)); // 42\n * toNullable(none()); // null\n * ```\n *\n * @template T - 值的类型\n * @param option - 要转换的 Option\n * @returns 值或 null\n */\nexport function toNullable<T>(option: Option<T>): T | null {\n if (isSome(option)) {\n return option.value;\n }\n return null;\n}\n\n/**\n * 基于谓词过滤 Option。\n * 如果 Option 是 Some 且谓词返回 false,则返回 None。\n *\n * @example\n * ```typescript\n * const option = some(10);\n * filter(option, x => x > 5); // Some(10)\n * filter(option, x => x > 15); // None\n * ```\n *\n * @template T - 值的类型\n * @param option - 要过滤的 Option\n * @param predicate - 谓词函数\n * @returns 如果谓词通过则返回 Option,否则返回 None\n */\nexport function filterOption<T>(option: Option<T>, predicate: (value: T) => boolean): Option<T> {\n if (isSome(option) && predicate(option.value)) {\n return option;\n }\n return none();\n}\n\n/**\n * 返回第一个为 Some 的 Option,如果都是 None 则返回 None。\n *\n * @example\n * ```typescript\n * alt(none(), some(42)); // Some(42)\n * alt(some(1), some(2)); // Some(1)\n * alt(none(), none()); // None\n * ```\n *\n * @template T - 值的类型\n * @param first - 第一个 Option\n * @param second - 第二个 Option\n * @returns 第一个 Some Option,或 None\n */\nexport function alt<T>(first: Option<T>, second: Option<T>): Option<T> {\n return isSome(first) ? first : second;\n}\n","/**\n * @fileoverview 高阶函数和工具\n * @module melange/fp/hof\n * @description 提供高阶函数用于记忆化、函数控制\n * 和其他函数式编程工具。\n */\n\nimport type { AnyFunction } from '../types';\n\n/**\n * 创建函数的记忆化版本。\n * 记忆化函数根据提供的参数缓存结果。\n *\n * @description\n * 记忆化是一种优化技术,存储昂贵函数调用的结果,\n * 当相同输入再次出现时返回缓存结果。\n *\n * @example\n * ```typescript\n * const expensiveCalculation = (n: number) => {\n * console.log('计算中...');\n * return n * n;\n * };\n *\n * const memoized = memoize(expensiveCalculation);\n * memoized(5); // 记录 '计算中...', 返回 25\n * memoized(5); // 从缓存返回 25, 无记录\n * memoized(3); // 记录 '计算中...', 返回 9\n * ```\n *\n * @template T - 函数类型\n * @param fn - 要记忆化的函数\n * @param keyFn - 生成缓存键的可选函数\n * @returns 函数的记忆化版本\n */\nexport function memoize<T extends AnyFunction>(\n fn: T,\n keyFn?: (...args: Parameters<T>) => string\n): T {\n const cache = new Map<string, ReturnType<T>>();\n\n return ((...args: Parameters<T>): ReturnType<T> => {\n const key = keyFn ? keyFn(...args) : JSON.stringify(args);\n\n if (cache.has(key)) {\n return cache.get(key) as ReturnType<T>;\n }\n\n const result = fn(...args) as ReturnType<T>;\n cache.set(key, result);\n return result;\n }) as T;\n}\n\n/**\n * 创建只能调用一次的函数。\n * 后续调用返回第一次调用的结果。\n *\n * @example\n * ```typescript\n * const initialize = once(() => {\n * console.log('初始化中...');\n * return { initialized: true };\n * });\n *\n * initialize(); // 记录 '初始化中...', 返回 { initialized: true }\n * initialize(); // 返回 { initialized: true }, 无记录\n * ```\n *\n * @template T - 函数类型\n * @param fn - 要包装的函数\n * @returns 只能调用一次的函数\n */\nexport function once<T extends AnyFunction>(fn: T): T {\n let called = false;\n let result: ReturnType<T>;\n\n return ((...args: Parameters<T>): ReturnType<T> => {\n if (!called) {\n called = true;\n result = fn(...args) as ReturnType<T>;\n }\n return result;\n }) as T;\n}\n\n/**\n * 创建调用原始函数然后执行副作用的函数,返回原始结果。\n *\n * @description\n * Tap 适用于在管道中调试或记录日志\n * 而不影响数据流。\n *\n * @example\n * ```typescript\n * const addOne = (x: number) => x + 1;\n * const logValue = tap((x: number) => console.log('值:', x));\n *\n * pipe(\n * 5,\n * addOne,\n * logValue, // 记录 '值: 6', 返回 6\n * x => x * 2\n * ); // 返回 12\n * ```\n *\n * @template T - 值类型\n * @param effect - 要执行的副作用函数\n * @returns 执行副作用并返回输入的函数\n */\nexport function tap<T>(effect: (value: T) => void): (value: T) => T {\n return (value: T): T => {\n effect(value);\n return value;\n };\n}\n\n/**\n * 返回传入的值而不改变。\n * 恒等函数作为默认转换器很有用。\n *\n * @example\n * ```typescript\n * identity(42); // 42\n * identity('hello'); // 'hello'\n * [1, 2, 3].map(identity); // [1, 2, 3]\n * ```\n *\n * @template T - 值类型\n * @param value - 要返回的值\n * @returns 相同的值\n */\nexport function identity<T>(value: T): T {\n return value;\n}\n\n/**\n * 创建总是返回相同值的函数。\n * 适用于创建占位符函数。\n *\n * @example\n * ```typescript\n * const alwaysFive = constant(5);\n * alwaysFive(); // 5\n * alwaysFive(100); // 5\n *\n * [1, 2, 3].map(constant('x')); // ['x', 'x', 'x']\n * ```\n *\n * @template T - 值类型\n * @param value - 总是返回的值\n * @returns 总是返回值的函数\n */\nexport function constant<T>(value: T): () => T {\n return () => value;\n}\n\n/**\n * 不执行任何操作并返回 undefined 的函数。\n * 适合作为默认回调或占位符。\n *\n * @example\n * ```typescript\n * const callback = maybeCallback || noop;\n * callback();\n * ```\n */\nexport function noop(): void {\n // 故意为空\n}\n\n/**\n * 否定谓词函数。\n *\n * @example\n * ```typescript\n * const isEven = (n: number) => n % 2 === 0;\n * const isOdd = not(isEven);\n *\n * isOdd(3); // true\n * isOdd(4); // false\n * ```\n *\n * @template T - 参数类型\n * @param predicate - 要否定的谓词\n * @returns 否定的谓词\n */\nexport function not<T>(predicate: (value: T) => boolean): (value: T) => boolean {\n return (value: T) => !predicate(value);\n}\n\n/**\n * 创建当所有谓词都返回 true 时返回 true 的函数。\n *\n * @example\n * ```typescript\n * const isPositive = (n: number) => n > 0;\n * const isEven = (n: number) => n % 2 === 0;\n * const isPositiveEven = allPass([isPositive, isEven]);\n *\n * isPositiveEven(4); // true\n * isPositiveEven(-4); // false\n * isPositiveEven(3); // false\n * ```\n *\n * @template T - 参数类型\n * @param predicates - 要检查的谓词数组\n * @returns 当所有谓词都通过时返回 true 的函数\n */\nexport function allPass<T>(predicates: Array<(value: T) => boolean>): (value: T) => boolean {\n return (value: T) => predicates.every(predicate => predicate(value));\n}\n\n/**\n * 创建当任何谓词返回 true 时返回 true 的函数。\n *\n * @example\n * ```typescript\n * const isZero = (n: number) => n === 0;\n * const isNegative = (n: number) => n < 0;\n * const isNotPositive = anyPass([isZero, isNegative]);\n *\n * isNotPositive(0); // true\n * isNotPositive(-1); // true\n * isNotPositive(1); // false\n * ```\n *\n * @template T - 参数类型\n * @param predicates - 要检查的谓词数组\n * @returns 当任何谓词通过时返回 true 的函数\n */\nexport function anyPass<T>(predicates: Array<(value: T) => boolean>): (value: T) => boolean {\n return (value: T) => predicates.some(predicate => predicate(value));\n}\n\n/**\n * 翻转二元函数的参数。\n *\n * @example\n * ```typescript\n * const divide = (a: number, b: number) => a / b;\n * const flippedDivide = flip(divide);\n *\n * divide(10, 2); // 5\n * flippedDivide(10, 2); // 0.2\n * ```\n *\n * @template A - 第一个参数类型\n * @template B - 第二个参数类型\n * @template R - 返回类型\n * @param fn - 要翻转的函数\n * @returns 参数翻转后的函数\n */\nexport function flip<A, B, R>(fn: (a: A, b: B) => R): (b: B, a: A) => R {\n return (b: B, a: A) => fn(a, b);\n}\n\n/**\n * 将值应用到函数。\n * 适用于无点编程。\n *\n * @example\n * ```typescript\n * const addOne = (x: number) => x + 1;\n * apply(5, addOne); // 6\n *\n * const funcs = [x => x + 1, x => x * 2];\n * funcs.map(f => apply(5, f)); // [6, 10]\n * ```\n *\n * @template T - 值类型\n * @template R - 返回类型\n * @param value - 要应用的值\n * @param fn - 要应用的函数\n * @returns 将值应用到函数的结果\n */\nexport function apply<T, R>(value: T, fn: (value: T) => R): R {\n return fn(value);\n}\n\n/**\n * 从值创建 thunk(延迟计算)。\n *\n * @example\n * ```typescript\n * const lazyValue = thunk(expensiveComputation);\n * // ... 稍后\n * const result = lazyValue(); // 计算在此处发生\n * ```\n *\n * @template T - 返回类型\n * @param fn - 要延迟的函数\n * @returns 调用时执行函数的 thunk\n */\nexport function thunk<T>(fn: () => T): () => T {\n return fn;\n}\n\n/**\n * 反转布尔值。\n *\n * @example\n * ```typescript\n * invert(true); // false\n * invert(false); // true\n * ```\n *\n * @param value - 要反转的布尔值\n * @returns 反转后的布尔值\n */\nexport function invert(value: boolean): boolean {\n return !value;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/plugins/speech/synthesis.ts","../src/plugins/speech/recognition.ts"],"names":["__name"],"mappings":"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","file":"chunk-YZVCK6VZ.cjs","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, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;AAyTO,IAAM,OAAA,GAAU;AAMhB,IAAM,YAAA,GAAe","file":"index.cjs","sourcesContent":["/**\n * @fileoverview Melange 库的主入口点\n * @module melange\n * @description 一个现代化的 JavaScript/TypeScript 工具库,具有\n * 函数式编程模式、面向对象工具和全面的类型支持。\n *\n * @example\n * ```typescript\n * // 导入所有内容\n * import * as melange from 'melange';\n *\n * // 导入特定模块\n * import { pipe, compose, curry } from 'melange/fp';\n * import { debounce, throttle, deepClone } from 'melange/utils';\n * import { EventEmitter, Container } from 'melange/core';\n * ```\n *\n * @license MIT\n * @author Melange 贡献者\n */\n\n// ============================================================================\n// 类型导出\n// ============================================================================\n\nexport type {\n // 基本类型\n Nullable,\n Optional,\n Primitive,\n AnyFunction,\n Constructor,\n // 函数类型\n Thunk,\n Predicate,\n Mapper,\n Reducer,\n Comparator,\n UnaryFunction,\n BinaryFunction,\n CurriedBinaryFunction,\n // Result 和 Option 类型\n Ok,\n Err,\n Result,\n Some,\n None,\n Option,\n // 异步类型\n AsyncFunction,\n AsyncThunk,\n Deferred,\n // 对象类型\n Dictionary,\n DeepPartial,\n DeepReadonly,\n RequiredKeys,\n OptionalKeys,\n Keys,\n Values,\n // 元组类型\n Pair,\n Triple,\n Head,\n Tail,\n // 装饰器类型\n ClassDecorator,\n MethodDecorator,\n PropertyDecorator,\n ParameterDecorator,\n // 事件类型\n EventHandler,\n EventListener,\n Subscription,\n // 品牌类型\n Brand,\n PositiveNumber,\n NonEmptyString,\n Email,\n UUID,\n // 实用类型\n ReturnTypeOf,\n ParametersOf,\n Mutable,\n JsonValue,\n JsonObject,\n JsonArray,\n} from './types';\n\n// ============================================================================\n// 函数式编程模块\n// ============================================================================\n\nexport {\n // 函数组合\n pipe,\n compose,\n flow,\n // 柯里化\n curry,\n uncurry,\n partial,\n partialRight,\n // Result 类型工具\n ok,\n err,\n isOk,\n isErr,\n mapResult,\n flatMapResult,\n unwrapOr,\n unwrapOrElse,\n matchResult,\n tryCatch,\n tryCatchAsync,\n // Option 类型工具\n some,\n none,\n isSome,\n isNone,\n fromNullable,\n mapOption,\n flatMapOption,\n getOrElse,\n getOrElseL,\n matchOption,\n toNullable,\n filterOption,\n alt,\n // 高阶函数\n memoize,\n once,\n tap,\n identity,\n constant,\n noop,\n not,\n allPass,\n anyPass,\n flip,\n apply,\n thunk,\n invert,\n} from './fp';\n\n// ============================================================================\n// 实用函数模块\n// ============================================================================\n\nexport {\n // 对象工具\n deepClone,\n deepMerge,\n pick,\n omit,\n get,\n set,\n has,\n isPlainObject,\n mapValues,\n filterObject,\n // 数组工具\n chunk,\n flatten,\n flattenDeep,\n unique,\n groupBy,\n sortBy,\n partition,\n zip,\n first,\n last,\n sample,\n shuffle,\n range,\n intersection,\n difference,\n // 字符串工具\n capitalize,\n camelCase,\n pascalCase,\n snakeCase,\n kebabCase,\n constantCase,\n truncate,\n padStart,\n padEnd,\n collapseWhitespace,\n escapeHtml,\n unescapeHtml,\n randomString,\n words,\n titleCase,\n reverse,\n countOccurrences,\n // 计时工具\n debounce,\n throttle,\n delay,\n retry,\n timeout,\n createDeferred,\n parallel,\n sequence,\n // 类型守卫\n isString,\n isNumber,\n isBoolean,\n isObject,\n isArray,\n isFunction,\n isNil,\n isNotNil,\n isEmpty,\n isNotEmpty,\n isDate,\n isPromise,\n // 验证工具\n isEmail,\n isUUID,\n isURL,\n isInteger,\n isPositive,\n isNegative,\n isInRange,\n} from './utils';\n\n// ============================================================================\n// 核心面向对象模块\n// ============================================================================\n\nexport {\n // 事件处理\n EventEmitter,\n // 依赖注入\n Container,\n globalContainer,\n Lifecycle,\n Injectable,\n Inject,\n Singleton,\n // 装饰器\n Memoize,\n Debounce,\n Throttle,\n Log,\n Validate,\n Deprecated,\n Sealed,\n Frozen,\n Bind,\n Retry,\n Timeout,\n // 基础类\n Disposable,\n DisposableStore,\n toDisposable,\n combineDisposables,\n} from './core';\n\n// ============================================================================\n// 插件模块\n// ============================================================================\n\nexport {\n // 语音合成\n SpeechSynthesizerImpl,\n createSpeechSynthesizer,\n isSpeechSynthesisSupported,\n speak,\n // 语音识别\n SpeechRecognizerImpl,\n createSpeechRecognizer,\n isSpeechRecognitionSupported,\n listen,\n} from './plugins';\n\n// 语音模块类型导出\nexport type {\n SpeechProviderType,\n SpeechServiceStatus,\n SpeechError,\n BaseSpeechConfig,\n VoiceInfo,\n SynthesisConfig,\n SynthesisEventType,\n SynthesisEvent,\n SynthesisEventHandler,\n SynthesisProvider,\n SpeechSynthesizer,\n RecognitionResultItem,\n RecognitionResult,\n RecognitionConfig,\n RecognitionEventType,\n RecognitionEvent,\n RecognitionEventHandler,\n RecognitionProvider,\n SpeechRecognizer,\n AzureSpeechConfig,\n GoogleSpeechConfig,\n AWSSpeechConfig,\n CustomProviderConfig,\n ProviderConfig,\n} from './plugins';\n\n// ============================================================================\n// 库版本\n// ============================================================================\n\n/**\n * 当前库版本\n * @constant\n */\nexport const VERSION = '1.0.0';\n\n/**\n * 库名\n * @constant\n */\nexport const LIBRARY_NAME = 'melange';\n"]}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;AAyTO,IAAM,OAAA,GAAU;AAMhB,IAAM,YAAA,GAAe","file":"index.js","sourcesContent":["/**\n * @fileoverview Melange 库的主入口点\n * @module melange\n * @description 一个现代化的 JavaScript/TypeScript 工具库,具有\n * 函数式编程模式、面向对象工具和全面的类型支持。\n *\n * @example\n * ```typescript\n * // 导入所有内容\n * import * as melange from 'melange';\n *\n * // 导入特定模块\n * import { pipe, compose, curry } from 'melange/fp';\n * import { debounce, throttle, deepClone } from 'melange/utils';\n * import { EventEmitter, Container } from 'melange/core';\n * ```\n *\n * @license MIT\n * @author Melange 贡献者\n */\n\n// ============================================================================\n// 类型导出\n// ============================================================================\n\nexport type {\n // 基本类型\n Nullable,\n Optional,\n Primitive,\n AnyFunction,\n Constructor,\n // 函数类型\n Thunk,\n Predicate,\n Mapper,\n Reducer,\n Comparator,\n UnaryFunction,\n BinaryFunction,\n CurriedBinaryFunction,\n // Result 和 Option 类型\n Ok,\n Err,\n Result,\n Some,\n None,\n Option,\n // 异步类型\n AsyncFunction,\n AsyncThunk,\n Deferred,\n // 对象类型\n Dictionary,\n DeepPartial,\n DeepReadonly,\n RequiredKeys,\n OptionalKeys,\n Keys,\n Values,\n // 元组类型\n Pair,\n Triple,\n Head,\n Tail,\n // 装饰器类型\n ClassDecorator,\n MethodDecorator,\n PropertyDecorator,\n ParameterDecorator,\n // 事件类型\n EventHandler,\n EventListener,\n Subscription,\n // 品牌类型\n Brand,\n PositiveNumber,\n NonEmptyString,\n Email,\n UUID,\n // 实用类型\n ReturnTypeOf,\n ParametersOf,\n Mutable,\n JsonValue,\n JsonObject,\n JsonArray,\n} from './types';\n\n// ============================================================================\n// 函数式编程模块\n// ============================================================================\n\nexport {\n // 函数组合\n pipe,\n compose,\n flow,\n // 柯里化\n curry,\n uncurry,\n partial,\n partialRight,\n // Result 类型工具\n ok,\n err,\n isOk,\n isErr,\n mapResult,\n flatMapResult,\n unwrapOr,\n unwrapOrElse,\n matchResult,\n tryCatch,\n tryCatchAsync,\n // Option 类型工具\n some,\n none,\n isSome,\n isNone,\n fromNullable,\n mapOption,\n flatMapOption,\n getOrElse,\n getOrElseL,\n matchOption,\n toNullable,\n filterOption,\n alt,\n // 高阶函数\n memoize,\n once,\n tap,\n identity,\n constant,\n noop,\n not,\n allPass,\n anyPass,\n flip,\n apply,\n thunk,\n invert,\n} from './fp';\n\n// ============================================================================\n// 实用函数模块\n// ============================================================================\n\nexport {\n // 对象工具\n deepClone,\n deepMerge,\n pick,\n omit,\n get,\n set,\n has,\n isPlainObject,\n mapValues,\n filterObject,\n // 数组工具\n chunk,\n flatten,\n flattenDeep,\n unique,\n groupBy,\n sortBy,\n partition,\n zip,\n first,\n last,\n sample,\n shuffle,\n range,\n intersection,\n difference,\n // 字符串工具\n capitalize,\n camelCase,\n pascalCase,\n snakeCase,\n kebabCase,\n constantCase,\n truncate,\n padStart,\n padEnd,\n collapseWhitespace,\n escapeHtml,\n unescapeHtml,\n randomString,\n words,\n titleCase,\n reverse,\n countOccurrences,\n // 计时工具\n debounce,\n throttle,\n delay,\n retry,\n timeout,\n createDeferred,\n parallel,\n sequence,\n // 类型守卫\n isString,\n isNumber,\n isBoolean,\n isObject,\n isArray,\n isFunction,\n isNil,\n isNotNil,\n isEmpty,\n isNotEmpty,\n isDate,\n isPromise,\n // 验证工具\n isEmail,\n isUUID,\n isURL,\n isInteger,\n isPositive,\n isNegative,\n isInRange,\n} from './utils';\n\n// ============================================================================\n// 核心面向对象模块\n// ============================================================================\n\nexport {\n // 事件处理\n EventEmitter,\n // 依赖注入\n Container,\n globalContainer,\n Lifecycle,\n Injectable,\n Inject,\n Singleton,\n // 装饰器\n Memoize,\n Debounce,\n Throttle,\n Log,\n Validate,\n Deprecated,\n Sealed,\n Frozen,\n Bind,\n Retry,\n Timeout,\n // 基础类\n Disposable,\n DisposableStore,\n toDisposable,\n combineDisposables,\n} from './core';\n\n// ============================================================================\n// 插件模块\n// ============================================================================\n\nexport {\n // 语音合成\n SpeechSynthesizerImpl,\n createSpeechSynthesizer,\n isSpeechSynthesisSupported,\n speak,\n // 语音识别\n SpeechRecognizerImpl,\n createSpeechRecognizer,\n isSpeechRecognitionSupported,\n listen,\n} from './plugins';\n\n// 语音模块类型导出\nexport type {\n SpeechProviderType,\n SpeechServiceStatus,\n SpeechError,\n BaseSpeechConfig,\n VoiceInfo,\n SynthesisConfig,\n SynthesisEventType,\n SynthesisEvent,\n SynthesisEventHandler,\n SynthesisProvider,\n SpeechSynthesizer,\n RecognitionResultItem,\n RecognitionResult,\n RecognitionConfig,\n RecognitionEventType,\n RecognitionEvent,\n RecognitionEventHandler,\n RecognitionProvider,\n SpeechRecognizer,\n AzureSpeechConfig,\n GoogleSpeechConfig,\n AWSSpeechConfig,\n CustomProviderConfig,\n ProviderConfig,\n} from './plugins';\n\n// ============================================================================\n// 库版本\n// ============================================================================\n\n/**\n * 当前库版本\n * @constant\n */\nexport const VERSION = '1.0.0';\n\n/**\n * 库名\n * @constant\n */\nexport const LIBRARY_NAME = 'melange';\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}