synstate 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/README.md +9 -10
  2. package/dist/core/class/child-observable-class.d.mts.map +1 -1
  3. package/dist/core/class/child-observable-class.mjs +148 -140
  4. package/dist/core/class/child-observable-class.mjs.map +1 -1
  5. package/dist/core/class/observable-base-class.d.mts.map +1 -1
  6. package/dist/core/class/observable-base-class.mjs +111 -107
  7. package/dist/core/class/observable-base-class.mjs.map +1 -1
  8. package/dist/core/class/root-observable-class.d.mts.map +1 -1
  9. package/dist/core/class/root-observable-class.mjs +32 -24
  10. package/dist/core/class/root-observable-class.mjs.map +1 -1
  11. package/dist/core/combine/combine.d.mts +3 -3
  12. package/dist/core/combine/combine.d.mts.map +1 -1
  13. package/dist/core/combine/combine.mjs +31 -113
  14. package/dist/core/combine/combine.mjs.map +1 -1
  15. package/dist/core/combine/merge.d.mts +2 -2
  16. package/dist/core/combine/merge.d.mts.map +1 -1
  17. package/dist/core/combine/merge.mjs +21 -69
  18. package/dist/core/combine/merge.mjs.map +1 -1
  19. package/dist/core/combine/zip.d.mts +2 -2
  20. package/dist/core/combine/zip.d.mts.map +1 -1
  21. package/dist/core/combine/zip.mjs +34 -79
  22. package/dist/core/combine/zip.mjs.map +1 -1
  23. package/dist/core/create/counter.d.mts +1 -1
  24. package/dist/core/create/counter.d.mts.map +1 -1
  25. package/dist/core/create/counter.mjs +45 -84
  26. package/dist/core/create/counter.mjs.map +1 -1
  27. package/dist/core/create/from-abortable-promise.d.mts.map +1 -1
  28. package/dist/core/create/from-abortable-promise.mjs +29 -61
  29. package/dist/core/create/from-abortable-promise.mjs.map +1 -1
  30. package/dist/core/create/from-promise.d.mts.map +1 -1
  31. package/dist/core/create/from-promise.mjs +17 -66
  32. package/dist/core/create/from-promise.mjs.map +1 -1
  33. package/dist/core/create/from-subscribable.d.mts.map +1 -1
  34. package/dist/core/create/from-subscribable.mjs +18 -69
  35. package/dist/core/create/from-subscribable.mjs.map +1 -1
  36. package/dist/core/create/just.d.mts.map +1 -1
  37. package/dist/core/create/just.mjs +5 -35
  38. package/dist/core/create/just.mjs.map +1 -1
  39. package/dist/core/create/source.mjs +10 -13
  40. package/dist/core/create/source.mjs.map +1 -1
  41. package/dist/core/create/timer.d.mts.map +1 -1
  42. package/dist/core/create/timer.mjs +32 -68
  43. package/dist/core/create/timer.mjs.map +1 -1
  44. package/dist/core/operators/audit.d.mts.map +1 -1
  45. package/dist/core/operators/audit.mjs +39 -133
  46. package/dist/core/operators/audit.mjs.map +1 -1
  47. package/dist/core/operators/debounce.d.mts.map +1 -1
  48. package/dist/core/operators/debounce.mjs +36 -119
  49. package/dist/core/operators/debounce.mjs.map +1 -1
  50. package/dist/core/operators/filter.mjs +22 -25
  51. package/dist/core/operators/filter.mjs.map +1 -1
  52. package/dist/core/operators/map.d.mts.map +1 -1
  53. package/dist/core/operators/map.mjs +28 -61
  54. package/dist/core/operators/map.mjs.map +1 -1
  55. package/dist/core/operators/merge-map.d.mts +1 -1
  56. package/dist/core/operators/merge-map.d.mts.map +1 -1
  57. package/dist/core/operators/merge-map.mjs +34 -130
  58. package/dist/core/operators/merge-map.mjs.map +1 -1
  59. package/dist/core/operators/pairwise.d.mts +3 -2
  60. package/dist/core/operators/pairwise.d.mts.map +1 -1
  61. package/dist/core/operators/pairwise.mjs +19 -75
  62. package/dist/core/operators/pairwise.mjs.map +1 -1
  63. package/dist/core/operators/scan.d.mts.map +1 -1
  64. package/dist/core/operators/scan.mjs +16 -67
  65. package/dist/core/operators/scan.mjs.map +1 -1
  66. package/dist/core/operators/skip-if-no-change.d.mts +1 -1
  67. package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
  68. package/dist/core/operators/skip-if-no-change.mjs +28 -92
  69. package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
  70. package/dist/core/operators/skip-until.d.mts.map +1 -1
  71. package/dist/core/operators/skip-until.mjs +23 -72
  72. package/dist/core/operators/skip-until.mjs.map +1 -1
  73. package/dist/core/operators/skip-while.d.mts.map +1 -1
  74. package/dist/core/operators/skip-while.mjs +26 -88
  75. package/dist/core/operators/skip-while.mjs.map +1 -1
  76. package/dist/core/operators/switch-map.d.mts.map +1 -1
  77. package/dist/core/operators/switch-map.mjs +31 -124
  78. package/dist/core/operators/switch-map.mjs.map +1 -1
  79. package/dist/core/operators/take-until.d.mts.map +1 -1
  80. package/dist/core/operators/take-until.mjs +28 -69
  81. package/dist/core/operators/take-until.mjs.map +1 -1
  82. package/dist/core/operators/take-while.d.mts.map +1 -1
  83. package/dist/core/operators/take-while.mjs +23 -83
  84. package/dist/core/operators/take-while.mjs.map +1 -1
  85. package/dist/core/operators/throttle.d.mts.map +1 -1
  86. package/dist/core/operators/throttle.mjs +38 -115
  87. package/dist/core/operators/throttle.mjs.map +1 -1
  88. package/dist/core/operators/with-buffered-from.d.mts +1 -1
  89. package/dist/core/operators/with-buffered-from.d.mts.map +1 -1
  90. package/dist/core/operators/with-buffered-from.mjs +37 -90
  91. package/dist/core/operators/with-buffered-from.mjs.map +1 -1
  92. package/dist/core/operators/with-current-value-from.d.mts +1 -1
  93. package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
  94. package/dist/core/operators/with-current-value-from.mjs +23 -84
  95. package/dist/core/operators/with-current-value-from.mjs.map +1 -1
  96. package/dist/core/operators/with-initial-value.d.mts.map +1 -1
  97. package/dist/core/operators/with-initial-value.mjs +13 -58
  98. package/dist/core/operators/with-initial-value.mjs.map +1 -1
  99. package/dist/core/predefined/operators/attach-index.d.mts +1 -1
  100. package/dist/core/predefined/operators/attach-index.d.mts.map +1 -1
  101. package/dist/core/predefined/operators/attach-index.mjs +0 -53
  102. package/dist/core/predefined/operators/attach-index.mjs.map +1 -1
  103. package/dist/core/predefined/operators/map-optional.d.mts.map +1 -1
  104. package/dist/core/predefined/operators/map-optional.mjs +1 -48
  105. package/dist/core/predefined/operators/map-optional.mjs.map +1 -1
  106. package/dist/core/predefined/operators/map-result-err.d.mts.map +1 -1
  107. package/dist/core/predefined/operators/map-result-err.mjs +1 -48
  108. package/dist/core/predefined/operators/map-result-err.mjs.map +1 -1
  109. package/dist/core/predefined/operators/map-result-ok.d.mts.map +1 -1
  110. package/dist/core/predefined/operators/map-result-ok.mjs +1 -48
  111. package/dist/core/predefined/operators/map-result-ok.mjs.map +1 -1
  112. package/dist/core/predefined/operators/map-to.d.mts.map +1 -1
  113. package/dist/core/predefined/operators/map-to.mjs +0 -40
  114. package/dist/core/predefined/operators/map-to.mjs.map +1 -1
  115. package/dist/core/predefined/operators/pluck.d.mts +1 -1
  116. package/dist/core/predefined/operators/pluck.d.mts.map +1 -1
  117. package/dist/core/predefined/operators/pluck.mjs +0 -43
  118. package/dist/core/predefined/operators/pluck.mjs.map +1 -1
  119. package/dist/core/predefined/operators/skip.d.mts.map +1 -1
  120. package/dist/core/predefined/operators/skip.mjs +0 -47
  121. package/dist/core/predefined/operators/skip.mjs.map +1 -1
  122. package/dist/core/predefined/operators/take.d.mts.map +1 -1
  123. package/dist/core/predefined/operators/take.mjs +0 -41
  124. package/dist/core/predefined/operators/take.mjs.map +1 -1
  125. package/dist/core/predefined/operators/unwrap-optional.mjs +4 -43
  126. package/dist/core/predefined/operators/unwrap-optional.mjs.map +1 -1
  127. package/dist/core/predefined/operators/unwrap-result-err.mjs +0 -40
  128. package/dist/core/predefined/operators/unwrap-result-err.mjs.map +1 -1
  129. package/dist/core/predefined/operators/unwrap-result-ok.mjs +4 -43
  130. package/dist/core/predefined/operators/unwrap-result-ok.mjs.map +1 -1
  131. package/dist/core/types/observable-family.d.mts +10 -10
  132. package/dist/core/types/observable-family.d.mts.map +1 -1
  133. package/dist/core/types/observable.d.mts.map +1 -1
  134. package/dist/core/types/observable.mjs +3 -5
  135. package/dist/core/types/observable.mjs.map +1 -1
  136. package/dist/core/types/types.d.mts +2 -1
  137. package/dist/core/types/types.d.mts.map +1 -1
  138. package/dist/core/utils/id-maker.mjs +5 -6
  139. package/dist/core/utils/id-maker.mjs.map +1 -1
  140. package/dist/core/utils/max-depth.d.mts.map +1 -1
  141. package/dist/core/utils/max-depth.mjs +1 -3
  142. package/dist/core/utils/max-depth.mjs.map +1 -1
  143. package/dist/core/utils/observable-utils.d.mts.map +1 -1
  144. package/dist/core/utils/observable-utils.mjs +3 -2
  145. package/dist/core/utils/observable-utils.mjs.map +1 -1
  146. package/dist/core/utils/utils.d.mts.map +1 -1
  147. package/dist/core/utils/utils.mjs +23 -30
  148. package/dist/core/utils/utils.mjs.map +1 -1
  149. package/dist/utils/collect-to-array.d.mts.map +1 -1
  150. package/dist/utils/collect-to-array.mjs +9 -6
  151. package/dist/utils/collect-to-array.mjs.map +1 -1
  152. package/dist/utils/create-boolean-state.d.mts +1 -1
  153. package/dist/utils/create-boolean-state.d.mts.map +1 -1
  154. package/dist/utils/create-boolean-state.mjs +18 -46
  155. package/dist/utils/create-boolean-state.mjs.map +1 -1
  156. package/dist/utils/create-event-emitter.mjs +10 -64
  157. package/dist/utils/create-event-emitter.mjs.map +1 -1
  158. package/dist/utils/create-reducer.d.mts +1 -1
  159. package/dist/utils/create-reducer.d.mts.map +1 -1
  160. package/dist/utils/create-reducer.mjs +8 -52
  161. package/dist/utils/create-reducer.mjs.map +1 -1
  162. package/dist/utils/create-state.d.mts +1 -1
  163. package/dist/utils/create-state.d.mts.map +1 -1
  164. package/dist/utils/create-state.mjs +23 -53
  165. package/dist/utils/create-state.mjs.map +1 -1
  166. package/package.json +16 -16
  167. package/src/core/class/child-observable-class.mts +1 -1
  168. package/src/core/class/observable-base-class.mts +16 -16
  169. package/src/core/combine/combine.mts +38 -16
  170. package/src/core/combine/merge.mts +3 -3
  171. package/src/core/combine/zip.mts +24 -13
  172. package/src/core/create/counter.mts +11 -9
  173. package/src/core/create/counter.test.mts +11 -0
  174. package/src/core/create/timer.mts +6 -6
  175. package/src/core/create/timer.test.mts +11 -0
  176. package/src/core/operators/audit-throttle-teardown.test.mts +21 -0
  177. package/src/core/operators/audit.mts +6 -6
  178. package/src/core/operators/debounce.mts +6 -6
  179. package/src/core/operators/pairwise.mts +10 -5
  180. package/src/core/operators/skip-while.mts +1 -5
  181. package/src/core/operators/skip-while.test.mts +20 -0
  182. package/src/core/operators/throttle.mts +6 -6
  183. package/src/core/operators/with-buffered-from.mts +4 -4
  184. package/src/core/predefined/operators/map-optional.mts +1 -2
  185. package/src/core/predefined/operators/map-result-err.mts +1 -1
  186. package/src/core/predefined/operators/map-result-ok.mts +1 -1
  187. package/src/core/types/observable-family.mts +12 -11
  188. package/src/core/types/observable.mts +5 -7
  189. package/src/core/types/types.mts +2 -1
  190. package/src/core/utils/max-depth.mts +5 -1
  191. package/src/core/utils/utils.mts +1 -1
  192. package/src/utils/create-boolean-state.mts +1 -1
  193. package/src/utils/create-reducer.mts +1 -1
  194. package/src/utils/create-state.mts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"filter.mjs","sources":["../../../src/core/operators/filter.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AA2EM,SAAU,MAAM,CACpB,SAAsD,EAAA;AAEtD,IAAA,OAAO,CAAC,gBAAgB,KACtB,IAAI,qBAAqB,CAAC,gBAAgB,EAAE,SAAS,CAAC;AAC1D;AAEA,MAAM,qBACJ,SAAQ,wBAAyC,CAAA;AAGxC,IAAA,UAAU;AACnB,IAAA,UAAU;IAEV,WAAA,CACE,gBAA+B,EAC/B,SAAkD,EAAA;AAElD,QAAA,KAAK,CAAC;YACJ,OAAO,EAAE,CAAC,gBAAgB,CAAC;YAC3B,YAAY,EAAE,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,KACxD,QAAQ,CAAC,MAAM,CAAC,EAAE;kBACd,QAAQ,CAAC;kBACT,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE;AACtB,sBAAE;AACF,sBAAE,QAAQ,CAAC,IAAI,CACpB,CAAC,KAAK;AACR,SAAA,CAAC;AAEF,QAAA,IAAI,CAAC,UAAU,GAAG,EAAE;AAEpB,QAAA,IAAI,CAAC,UAAU,GAAG,SAAS;;AAGpB,IAAA,SAAS,CAAC,WAAwB,EAAA;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AAE3B,QAAA,MAAM,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE;AAE5B,QAAA,IAAI,GAAG,CAAC,WAAW,KAAK,WAAW,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;AAC1D,YAAA,OAAO;;AAGT,QAAA,IAAI,CAAC,UAAU;YACb,IAAI,CAAC,UAAU,KAAK,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC;AAE3E,QAAA,IAAI,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE;YAC9C,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC;;;AAGxC;;;;"}
1
+ {"version":3,"file":"filter.mjs","sources":["../../../src/core/operators/filter.mts"],"sourcesContent":["import {\n asSafeUint,\n expectType,\n Optional,\n pipe,\n SafeUint,\n} from 'ts-data-forge';\nimport { SyncChildObservableClass } from '../class/index.mjs';\nimport { source } from '../create/index.mjs';\nimport {\n type DropInitialValueOperator,\n type FilterOperatorObservable,\n type InitializedObservable,\n type Observable,\n type UpdateToken,\n} from '../types/index.mjs';\nimport { withInitialValue } from './with-initial-value.mjs';\n\n/**\n * Filters values emitted by the source observable based on a predicate function.\n * Only values that satisfy the predicate will be emitted by the resulting observable.\n *\n * @template A - The type of values from the source\n * @template B - The narrowed type when using type guard\n * @param predicate - A function that tests each value (receives value and index)\n * @returns An operator that filters the observable\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ 1 2 3 4 5 6\n * // even$ 2 4 6\n * //\n * // Explanation:\n * // - filter passes through only values that satisfy the predicate\n * // - Only even numbers (2, 4, 6) are emitted\n *\n * const num$ = source<number>();\n *\n * const even$ = num$.pipe(filter((x) => x % 2 === 0));\n *\n * const valueHistory: number[] = [];\n *\n * even$.subscribe((x) => {\n * valueHistory.push(x);\n * });\n *\n * num$.next(1); // nothing logged\n *\n * num$.next(2); // logs: 2\n *\n * assert.deepStrictEqual(valueHistory, [2]);\n *\n * num$.next(3); // nothing logged\n *\n * num$.next(4); // logs: 4\n *\n * assert.deepStrictEqual(valueHistory, [2, 4]);\n *\n * num$.next(5);\n *\n * num$.next(6);\n *\n * assert.deepStrictEqual(valueHistory, [2, 4, 6]);\n * ```\n */\nexport function filter<A, B extends A>(\n predicate: (value: A, index: SafeUint | -1) => value is B,\n): DropInitialValueOperator<A, B>;\n\nexport function filter<A>(\n predicate: (value: A, index: SafeUint | -1) => boolean,\n): DropInitialValueOperator<A, A>;\n\nexport function filter<A>(\n predicate: (value: A, index: SafeUint | -1) => boolean,\n): DropInitialValueOperator<A, A> {\n return (parentObservable) =>\n new FilterObservableClass(parentObservable, predicate);\n}\n\nclass FilterObservableClass<A>\n extends SyncChildObservableClass<A, readonly [A]>\n implements FilterOperatorObservable<A>\n{\n readonly #predicate: (x: A, index: SafeUint | -1) => boolean;\n #mut_index: SafeUint | -1;\n\n constructor(\n parentObservable: Observable<A>,\n predicate: (x: A, index: SafeUint | -1) => boolean,\n ) {\n super({\n parents: [parentObservable],\n initialValue: pipe(parentObservable.getSnapshot()).map((sn) =>\n Optional.isNone(sn)\n ? Optional.none\n : predicate(sn.value, -1)\n ? sn\n : Optional.none,\n ).value,\n });\n\n this.#mut_index = -1;\n\n this.#predicate = predicate;\n }\n\n override tryUpdate(updateToken: UpdateToken): void {\n const par = this.parents[0];\n\n const sn = par.getSnapshot();\n\n if (par.updateToken !== updateToken || Optional.isNone(sn)) {\n return; // skip update\n }\n\n this.#mut_index =\n this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);\n\n if (this.#predicate(sn.value, this.#mut_index)) {\n this.setNext(sn.value, updateToken);\n }\n }\n}\n\nif (import.meta.vitest !== undefined) {\n test('type test', () => {\n expect(1).toBe(1); // dummy\n });\n\n {\n const s: Observable<number> = source<number>();\n\n const _d1 = s.pipe(filter((x) => x % 2 === 0));\n\n expectType<typeof _d1, Observable<number>>('=');\n }\n\n {\n const s = source<number>();\n\n const m: InitializedObservable<number> = s.pipe(withInitialValue(0));\n\n const _d = m.pipe(filter((x) => x % 2 === 0));\n\n expectType<typeof _d, Observable<number>>('=');\n }\n}\n"],"names":[],"mappings":";;;;AA2EO,SAAS,OACd,SAAA,EACgC;AAChC,EAAA,OAAO,CAAC,gBAAA,KACN,IAAI,qBAAA,CAAsB,kBAAkB,SAAS,CAAA;AACzD;AAEA,MAAM,8BACI,wBAAA,CAEV;AAAA,EACW,UAAA;AAAA,EACT,UAAA;AAAA,EAEA,WAAA,CACE,kBACA,SAAA,EACA;AACA,IAAA,KAAA,CAAM;AAAA,MACJ,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,YAAA,EAAc,IAAA,CAAK,gBAAA,CAAiB,WAAA,EAAa,CAAA,CAAE,GAAA;AAAA,QAAI,CAAC,EAAA,KACtD,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,GACd,QAAA,CAAS,IAAA,GACT,SAAA,CAAU,EAAA,CAAG,KAAA,EAAO,EAAE,CAAA,GACpB,KACA,QAAA,CAAS;AAAA,OACjB,CAAE;AAAA,KACH,CAAA;AAED,IAAA,IAAA,CAAK,UAAA,GAAa,EAAA;AAElB,IAAA,IAAA,CAAK,UAAA,GAAa,SAAA;AAAA,EAAA;AACpB,EAES,UAAU,WAAA,EAAgC;AACjD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA;AAE1B,IAAA,MAAM,EAAA,GAAK,IAAI,WAAA,EAAY;AAE3B,IAAA,IAAI,IAAI,WAAA,KAAgB,WAAA,IAAe,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAC1D,MAAA;AAAA,IAAA;AAGF,IAAA,IAAA,CAAK,UAAA,GACH,IAAA,CAAK,UAAA,KAAe,EAAA,GAAK,UAAA,CAAW,CAAC,CAAA,GAAI,QAAA,CAAS,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,UAAU,CAAA;AAE1E,IAAA,IAAI,KAAK,UAAA,CAAW,EAAA,CAAG,KAAA,EAAO,IAAA,CAAK,UAAU,CAAA,EAAG;AAC9C,MAAA,IAAA,CAAK,OAAA,CAAQ,EAAA,CAAG,KAAA,EAAO,WAAW,CAAA;AAAA,IAAA;AACpC,EAAA;AAEJ;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"map.d.mts","sourceRoot":"","sources":["../../../src/core/operators/map.mts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAA0B,MAAM,eAAe,CAAC;AAG3E,OAAO,EAEL,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,EAAE,CAAC,EACtB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,KACvC,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAMQ,CAAC"}
1
+ {"version":3,"file":"map.d.mts","sourceRoot":"","sources":["../../../src/core/operators/map.mts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAA0B,MAAM,eAAe,CAAC;AAG3E,OAAO,EAEL,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,EAAE,CAAC,SACf,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,KACvC,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAMQ,CAAC"}
@@ -2,69 +2,36 @@ import { Optional, asSafeUint, SafeUint } from 'ts-data-forge';
2
2
  import { SyncChildObservableClass } from '../class/child-observable-class.mjs';
3
3
  import '../utils/id-maker.mjs';
4
4
 
5
- /**
6
- * Transforms each value emitted by the source using a mapping function that also receives the emission index.
7
- *
8
- * @template A - The type of values from the source
9
- * @template B - The type of mapped values
10
- * @param mapFn - A function that maps each value (receives value and index)
11
- * @returns An operator that maps values with index
12
- *
13
- * @example
14
- * ```ts
15
- * // Timeline:
16
- * //
17
- * // num$ "A" "B" "C"
18
- * // indexed$ "0: A" "1: B" "2: C"
19
- * //
20
- * // Explanation:
21
- * // - mapWithIndex transforms each value along with its index
22
- * // - Index starts at 0 and increments with each emission
23
- *
24
- * const num$ = source<string>();
25
- *
26
- * const indexed$ = num$.pipe(map((x, i) => `${i}: ${x}`));
27
- *
28
- * const valueHistory: string[] = [];
29
- *
30
- * indexed$.subscribe((s) => {
31
- * valueHistory.push(s);
32
- * });
33
- *
34
- * num$.next('A'); // 0: A
35
- *
36
- * num$.next('B'); // 1: B
37
- *
38
- * num$.next('C'); // 2: C
39
- *
40
- * assert.deepStrictEqual(valueHistory, ['0: A', '1: B', '2: C']);
41
- * ```
42
- */
43
- const map = (mapFn) =>
44
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
45
- ((parentObservable) => new MapObservableClass(parentObservable, mapFn));
46
- /* implementation */
5
+ const map = (mapFn) => (
6
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
7
+ ((parentObservable) => new MapObservableClass(
8
+ parentObservable,
9
+ mapFn
10
+ ))
11
+ );
47
12
  class MapObservableClass extends SyncChildObservableClass {
48
- #mapFn;
49
- #mut_index;
50
- constructor(parentObservable, mapFn) {
51
- super({
52
- parents: [parentObservable],
53
- initialValue: Optional.map(parentObservable.getSnapshot(), (x) => mapFn(x, -1)),
54
- });
55
- this.#mut_index = -1;
56
- this.#mapFn = mapFn;
57
- }
58
- tryUpdate(updateToken) {
59
- const par = this.parents[0];
60
- const sn = par.getSnapshot();
61
- if (par.updateToken !== updateToken || Optional.isNone(sn)) {
62
- return; // skip update
63
- }
64
- this.#mut_index =
65
- this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
66
- this.setNext(this.#mapFn(sn.value, this.#mut_index), updateToken);
13
+ #mapFn;
14
+ #mut_index;
15
+ constructor(parentObservable, mapFn) {
16
+ super({
17
+ parents: [parentObservable],
18
+ initialValue: Optional.map(
19
+ parentObservable.getSnapshot(),
20
+ (x) => mapFn(x, -1)
21
+ )
22
+ });
23
+ this.#mut_index = -1;
24
+ this.#mapFn = mapFn;
25
+ }
26
+ tryUpdate(updateToken) {
27
+ const par = this.parents[0];
28
+ const sn = par.getSnapshot();
29
+ if (par.updateToken !== updateToken || Optional.isNone(sn)) {
30
+ return;
67
31
  }
32
+ this.#mut_index = this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
33
+ this.setNext(this.#mapFn(sn.value, this.#mut_index), updateToken);
34
+ }
68
35
  }
69
36
 
70
37
  export { map };
@@ -1 +1 @@
1
- {"version":3,"file":"map.mjs","sources":["../../../src/core/operators/map.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCG;AACI,MAAM,GAAG,GAAG,CACjB,KAAwC;AAExC;AACA,CAAC,CAAC,gBAAgB,KAChB,IAAI,kBAAkB,CACpB,gBAAgB,EAChB,KAAK,CACN;AAEL;AAEA,MAAM,kBACJ,SAAQ,wBAAyC,CAAA;AAGxC,IAAA,MAAM;AACf,IAAA,UAAU;IAEV,WAAA,CACE,gBAA+B,EAC/B,KAAwC,EAAA;AAExC,QAAA,KAAK,CAAC;YACJ,OAAO,EAAE,CAAC,gBAAgB,CAAC;YAC3B,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,KAC3D,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CACb;AACF,SAAA,CAAC;AAEF,QAAA,IAAI,CAAC,UAAU,GAAG,EAAE;AAEpB,QAAA,IAAI,CAAC,MAAM,GAAG,KAAK;;AAGZ,IAAA,SAAS,CAAC,WAAwB,EAAA;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AAE3B,QAAA,MAAM,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE;AAE5B,QAAA,IAAI,GAAG,CAAC,WAAW,KAAK,WAAW,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;AAC1D,YAAA,OAAO;;AAGT,QAAA,IAAI,CAAC,UAAU;YACb,IAAI,CAAC,UAAU,KAAK,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC;AAE3E,QAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,WAAW,CAAC;;AAEpE;;;;"}
1
+ {"version":3,"file":"map.mjs","sources":["../../../src/core/operators/map.mts"],"sourcesContent":["import { Optional, SafeUint, asSafeUint, expectType } from 'ts-data-forge';\nimport { SyncChildObservableClass } from '../class/index.mjs';\nimport { source } from '../create/index.mjs';\nimport {\n type InitializedObservable,\n type KeepInitialValueOperator,\n type MapOperatorObservable,\n type Observable,\n type UpdateToken,\n} from '../types/index.mjs';\nimport { withInitialValue } from './with-initial-value.mjs';\n\n/**\n * Transforms each value emitted by the source using a mapping function that also receives the emission index.\n *\n * @template A - The type of values from the source\n * @template B - The type of mapped values\n * @param mapFn - A function that maps each value (receives value and index)\n * @returns An operator that maps values with index\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ \"A\" \"B\" \"C\"\n * // indexed$ \"0: A\" \"1: B\" \"2: C\"\n * //\n * // Explanation:\n * // - mapWithIndex transforms each value along with its index\n * // - Index starts at 0 and increments with each emission\n *\n * const num$ = source<string>();\n *\n * const indexed$ = num$.pipe(map((x, i) => `${i}: ${x}`));\n *\n * const valueHistory: string[] = [];\n *\n * indexed$.subscribe((s) => {\n * valueHistory.push(s);\n * });\n *\n * num$.next('A'); // 0: A\n *\n * num$.next('B'); // 1: B\n *\n * num$.next('C'); // 2: C\n *\n * assert.deepStrictEqual(valueHistory, ['0: A', '1: B', '2: C']);\n * ```\n */\nexport const map = <A, B>(\n mapFn: (x: A, index: SafeUint | -1) => B,\n): KeepInitialValueOperator<A, B> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n new MapObservableClass(\n parentObservable,\n mapFn,\n )) as KeepInitialValueOperator<A, B>;\n\n/* implementation */\n\nclass MapObservableClass<A, B>\n extends SyncChildObservableClass<B, readonly [A]>\n implements MapOperatorObservable<A, B>\n{\n readonly #mapFn: (x: A, index: SafeUint | -1) => B;\n #mut_index: SafeUint | -1;\n\n constructor(\n parentObservable: Observable<A>,\n mapFn: (x: A, index: SafeUint | -1) => B,\n ) {\n super({\n parents: [parentObservable],\n initialValue: Optional.map(parentObservable.getSnapshot(), (x) =>\n mapFn(x, -1),\n ),\n });\n\n this.#mut_index = -1;\n\n this.#mapFn = mapFn;\n }\n\n override tryUpdate(updateToken: UpdateToken): void {\n const par = this.parents[0];\n\n const sn = par.getSnapshot();\n\n if (par.updateToken !== updateToken || Optional.isNone(sn)) {\n return; // skip update\n }\n\n this.#mut_index =\n this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);\n\n this.setNext(this.#mapFn(sn.value, this.#mut_index), updateToken);\n }\n}\n\nif (import.meta.vitest !== undefined) {\n test('type test', () => {\n expect(1).toBe(1); // dummy\n });\n\n {\n const s: Observable<number> = source<number>();\n\n const _d1 = s.pipe(map((x, i) => x + i));\n\n expectType<typeof _d1, Observable<number>>('=');\n }\n\n {\n const s = source<number>();\n\n const m: InitializedObservable<number> = s.pipe(withInitialValue(0));\n\n const _d = m.pipe(map((x, i) => x + i));\n\n expectType<typeof _d, InitializedObservable<number>>('=');\n }\n}\n"],"names":[],"mappings":";;;;AAkDO,MAAM,MAAM,CACjB,KAAA;AAAA;AAAA,GAGC,CAAC,qBACA,IAAI,kBAAA;AAAA,IACF,gBAAA;AAAA,IACA;AAAA,GACF;AAAA;AAIJ,MAAM,2BACI,wBAAA,CAEV;AAAA,EACW,MAAA;AAAA,EACT,UAAA;AAAA,EAEA,WAAA,CACE,kBACA,KAAA,EACA;AACA,IAAA,KAAA,CAAM;AAAA,MACJ,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,cAAc,QAAA,CAAS,GAAA;AAAA,QAAI,iBAAiB,WAAA,EAAY;AAAA,QAAG,CAAC,CAAA,KAC1D,KAAA,CAAM,CAAA,EAAG,EAAE;AAAA;AACb,KACD,CAAA;AAED,IAAA,IAAA,CAAK,UAAA,GAAa,EAAA;AAElB,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAAA;AAChB,EAES,UAAU,WAAA,EAAgC;AACjD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA;AAE1B,IAAA,MAAM,EAAA,GAAK,IAAI,WAAA,EAAY;AAE3B,IAAA,IAAI,IAAI,WAAA,KAAgB,WAAA,IAAe,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAC1D,MAAA;AAAA,IAAA;AAGF,IAAA,IAAA,CAAK,UAAA,GACH,IAAA,CAAK,UAAA,KAAe,EAAA,GAAK,UAAA,CAAW,CAAC,CAAA,GAAI,QAAA,CAAS,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,UAAU,CAAA;AAE1E,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,MAAA,CAAO,EAAA,CAAG,OAAO,IAAA,CAAK,UAAU,GAAG,WAAW,CAAA;AAAA,EAAA;AAEpE;;;;"}
@@ -99,5 +99,5 @@ export declare const mergeMap: <A, B>(mapToObservable: (curr: A) => Observable<B
99
99
  * Alias for `mergeMap`.
100
100
  * @see mergeMap
101
101
  */
102
- export declare const flatMap: <A, B>(mapToObservable: (curr: A) => Observable<B>) => DropInitialValueOperator<A, B>;
102
+ export declare const flatMap: typeof mergeMap;
103
103
  //# sourceMappingURL=merge-map.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"merge-map.d.mts","sourceRoot":"","sources":["../../../src/core/operators/merge-map.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAE7B,KAAK,UAAU,EAGhB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8FG;AACH,eAAO,MAAM,QAAQ,GAClB,CAAC,EAAE,CAAC,EACH,iBAAiB,CAAC,IAAI,EAAE,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,KAC1C,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAEgC,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,OAAO,GAVjB,CAAC,EAAE,CAAC,mBACc,CAAC,IAAI,EAAE,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,KAC1C,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAQH,CAAC"}
1
+ {"version":3,"file":"merge-map.d.mts","sourceRoot":"","sources":["../../../src/core/operators/merge-map.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAE7B,KAAK,UAAU,EAGhB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8FG;AACH,eAAO,MAAM,QAAQ,GAClB,CAAC,EAAE,CAAC,mBACc,CAAC,IAAI,EAAE,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,KAC1C,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAEgC,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,OAAO,iBAAW,CAAC"}
@@ -2,142 +2,46 @@ import { Optional, Arr } from 'ts-data-forge';
2
2
  import { AsyncChildObservableClass } from '../class/child-observable-class.mjs';
3
3
  import '../utils/id-maker.mjs';
4
4
 
5
- /**
6
- * Projects each source value to an observable and merges all inner observables.
7
- * Unlike `switchMap`, does not cancel previous inner observables.
8
- *
9
- * @template A - The type of values from the source
10
- * @template B - The type of values from the projected observable
11
- * @param mapToObservable - A function that maps each source value to an observable
12
- * @returns An operator that merges mapped observables
13
- *
14
- * @example
15
- * ```ts
16
- * // Timeline:
17
- * //
18
- * // input$ A B C
19
- * // inner A A1 A2 A3
20
- * // inner B B1 B2 B3
21
- * // inner C C1 C2 C3
22
- * // result$ A1 A2 A3 B1 B2 C1 B3 C2 C3
23
- * //
24
- * // Explanation:
25
- * // - mergeMap creates an inner observable for each source value
26
- * // - Unlike switchMap, previous inner observables are NOT cancelled
27
- * // - B's inner continues even after C arrives (B3 is still emitted)
28
- * // - All inner observables run concurrently and their results are merged
29
- *
30
- * const input$ = source<string>();
31
- *
32
- * const result$ = input$.pipe(
33
- * mergeMap((letter) => {
34
- * const inner$ = source<string>();
35
- *
36
- * setTimeout(() => {
37
- * inner$.next(`${letter}1`);
38
- * }, 10);
39
- *
40
- * setTimeout(() => {
41
- * inner$.next(`${letter}2`);
42
- * }, 110);
43
- *
44
- * setTimeout(() => {
45
- * inner$.next(`${letter}3`);
46
- * }, 210);
47
- *
48
- * return inner$;
49
- * }),
50
- * );
51
- *
52
- * const valueHistory: string[] = [];
53
- *
54
- * result$.subscribe((value) => {
55
- * valueHistory.push(value);
56
- * });
57
- *
58
- * const sleep = (ms: number): Promise<void> =>
59
- * new Promise((resolve) => {
60
- * setTimeout(resolve, ms);
61
- * });
62
- *
63
- * // Emit A - inner emits A1, A2, A3 at 10ms, 110ms, 210ms
64
- * input$.next('A');
65
- *
66
- * await sleep(250);
67
- *
68
- * assert.deepStrictEqual(valueHistory, ['A1', 'A2', 'A3']);
69
- *
70
- * // Emit B - inner starts emitting B1, B2 at 10ms, 110ms
71
- * input$.next('B');
72
- *
73
- * await sleep(150);
74
- *
75
- * assert.deepStrictEqual(valueHistory, ['A1', 'A2', 'A3', 'B1', 'B2']);
76
- *
77
- * // Emit C while B's inner is still running (B3 at 210ms not yet fired)
78
- * // Unlike switchMap, B's inner is NOT cancelled
79
- * input$.next('C');
80
- *
81
- * await sleep(250);
82
- *
83
- * // B3 appears between C1 and C2, showing the merge behavior
84
- * assert.deepStrictEqual(valueHistory, [
85
- * 'A1',
86
- * 'A2',
87
- * 'A3',
88
- * 'B1',
89
- * 'B2',
90
- * 'C1',
91
- * 'B3',
92
- * 'C2',
93
- * 'C3',
94
- * ]);
95
- * ```
96
- *
97
- * @note To improve code readability, consider using `createState` instead of `mergeMap`,
98
- * subscribing to `parentObservable` and calling `setState` within it.
99
- */
100
5
  const mergeMap = (mapToObservable) => (parentObservable) => new MergeMapObservableClass(parentObservable, mapToObservable);
101
- /**
102
- * Alias for `mergeMap`.
103
- * @see mergeMap
104
- */
105
6
  const flatMap = mergeMap;
106
7
  class MergeMapObservableClass extends AsyncChildObservableClass {
107
- #mapToObservable;
108
- #mut_observables;
109
- #mut_subscriptions;
110
- constructor(parentObservable, mapToObservable) {
111
- super({
112
- parents: [parentObservable],
113
- initialValue: Optional.none,
114
- });
115
- this.#mapToObservable = mapToObservable;
116
- this.#mut_observables = [];
117
- this.#mut_subscriptions = [];
8
+ #mapToObservable;
9
+ #mut_observables;
10
+ #mut_subscriptions;
11
+ constructor(parentObservable, mapToObservable) {
12
+ super({
13
+ parents: [parentObservable],
14
+ initialValue: Optional.none
15
+ });
16
+ this.#mapToObservable = mapToObservable;
17
+ this.#mut_observables = [];
18
+ this.#mut_subscriptions = [];
19
+ }
20
+ tryUpdate(updateToken) {
21
+ const par = this.parents[0];
22
+ const sn = par.getSnapshot();
23
+ if (par.updateToken !== updateToken || Optional.isNone(sn)) {
24
+ return;
118
25
  }
119
- tryUpdate(updateToken) {
120
- const par = this.parents[0];
121
- const sn = par.getSnapshot();
122
- if (par.updateToken !== updateToken || Optional.isNone(sn)) {
123
- return; // skip update
124
- }
125
- const observable = this.#mapToObservable(sn.value);
126
- this.#mut_observables = Arr.toPushed(this.#mut_observables, observable);
127
- const subscription = observable.subscribe((curr) => {
128
- this.startUpdate(curr);
129
- });
130
- this.#mut_subscriptions = Arr.toPushed(this.#mut_subscriptions, subscription);
26
+ const observable = this.#mapToObservable(sn.value);
27
+ this.#mut_observables = Arr.toPushed(this.#mut_observables, observable);
28
+ const subscription = observable.subscribe((curr) => {
29
+ this.startUpdate(curr);
30
+ });
31
+ this.#mut_subscriptions = Arr.toPushed(
32
+ this.#mut_subscriptions,
33
+ subscription
34
+ );
35
+ }
36
+ complete() {
37
+ for (const s of this.#mut_subscriptions) {
38
+ s.unsubscribe();
131
39
  }
132
- complete() {
133
- for (const s of this.#mut_subscriptions) {
134
- s.unsubscribe();
135
- }
136
- for (const o of this.#mut_observables) {
137
- o.complete();
138
- }
139
- super.complete();
40
+ for (const o of this.#mut_observables) {
41
+ o.complete();
140
42
  }
43
+ super.complete();
44
+ }
141
45
  }
142
46
 
143
47
  export { flatMap, mergeMap };
@@ -1 +1 @@
1
- {"version":3,"file":"merge-map.mjs","sources":["../../../src/core/operators/merge-map.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8FG;MACU,QAAQ,GACnB,CACE,eAA2C,KAE7C,CAAC,gBAAgB,KACf,IAAI,uBAAuB,CAAC,gBAAgB,EAAE,eAAe;AAEjE;;;AAGG;AACI,MAAM,OAAO,GAAG;AAEvB,MAAM,uBACJ,SAAQ,yBAA0C,CAAA;AAGzC,IAAA,gBAAgB;AACzB,IAAA,gBAAgB;AAChB,IAAA,kBAAkB;IAElB,WAAA,CACE,gBAA+B,EAC/B,eAA2C,EAAA;AAE3C,QAAA,KAAK,CAAC;YACJ,OAAO,EAAE,CAAC,gBAAgB,CAAC;YAC3B,YAAY,EAAE,QAAQ,CAAC,IAAI;AAC5B,SAAA,CAAC;AAEF,QAAA,IAAI,CAAC,gBAAgB,GAAG,eAAe;AAEvC,QAAA,IAAI,CAAC,gBAAgB,GAAG,EAAE;AAE1B,QAAA,IAAI,CAAC,kBAAkB,GAAG,EAAE;IAC9B;AAES,IAAA,SAAS,CAAC,WAAwB,EAAA;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AAE3B,QAAA,MAAM,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE;AAE5B,QAAA,IAAI,GAAG,CAAC,WAAW,KAAK,WAAW,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;AAC1D,YAAA,OAAO;QACT;QAEA,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,KAAK,CAAC;AAElD,QAAA,IAAI,CAAC,gBAAgB,GAAG,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC;QAEvE,MAAM,YAAY,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,IAAI,KAAI;AACjD,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;AACxB,QAAA,CAAC,CAAC;AAEF,QAAA,IAAI,CAAC,kBAAkB,GAAG,GAAG,CAAC,QAAQ,CACpC,IAAI,CAAC,kBAAkB,EACvB,YAAY,CACb;IACH;IAES,QAAQ,GAAA;AACf,QAAA,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,kBAAkB,EAAE;YACvC,CAAC,CAAC,WAAW,EAAE;QACjB;AAEA,QAAA,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE;YACrC,CAAC,CAAC,QAAQ,EAAE;QACd;QAEA,KAAK,CAAC,QAAQ,EAAE;IAClB;AACD;;;;"}
1
+ {"version":3,"file":"merge-map.mjs","sources":["../../../src/core/operators/merge-map.mts"],"sourcesContent":["import { Arr, Optional } from 'ts-data-forge';\nimport { AsyncChildObservableClass } from '../class/index.mjs';\nimport {\n type DropInitialValueOperator,\n type MergeMapOperatorObservable,\n type Observable,\n type Subscription,\n type UpdateToken,\n} from '../types/index.mjs';\n\n/**\n * Projects each source value to an observable and merges all inner observables.\n * Unlike `switchMap`, does not cancel previous inner observables.\n *\n * @template A - The type of values from the source\n * @template B - The type of values from the projected observable\n * @param mapToObservable - A function that maps each source value to an observable\n * @returns An operator that merges mapped observables\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // input$ A B C\n * // inner A A1 A2 A3\n * // inner B B1 B2 B3\n * // inner C C1 C2 C3\n * // result$ A1 A2 A3 B1 B2 C1 B3 C2 C3\n * //\n * // Explanation:\n * // - mergeMap creates an inner observable for each source value\n * // - Unlike switchMap, previous inner observables are NOT cancelled\n * // - B's inner continues even after C arrives (B3 is still emitted)\n * // - All inner observables run concurrently and their results are merged\n *\n * const input$ = source<string>();\n *\n * const result$ = input$.pipe(\n * mergeMap((letter) => {\n * const inner$ = source<string>();\n *\n * setTimeout(() => {\n * inner$.next(`${letter}1`);\n * }, 10);\n *\n * setTimeout(() => {\n * inner$.next(`${letter}2`);\n * }, 110);\n *\n * setTimeout(() => {\n * inner$.next(`${letter}3`);\n * }, 210);\n *\n * return inner$;\n * }),\n * );\n *\n * const valueHistory: string[] = [];\n *\n * result$.subscribe((value) => {\n * valueHistory.push(value);\n * });\n *\n * const sleep = (ms: number): Promise<void> =>\n * new Promise((resolve) => {\n * setTimeout(resolve, ms);\n * });\n *\n * // Emit A - inner emits A1, A2, A3 at 10ms, 110ms, 210ms\n * input$.next('A');\n *\n * await sleep(250);\n *\n * assert.deepStrictEqual(valueHistory, ['A1', 'A2', 'A3']);\n *\n * // Emit B - inner starts emitting B1, B2 at 10ms, 110ms\n * input$.next('B');\n *\n * await sleep(150);\n *\n * assert.deepStrictEqual(valueHistory, ['A1', 'A2', 'A3', 'B1', 'B2']);\n *\n * // Emit C while B's inner is still running (B3 at 210ms not yet fired)\n * // Unlike switchMap, B's inner is NOT cancelled\n * input$.next('C');\n *\n * await sleep(250);\n *\n * // B3 appears between C1 and C2, showing the merge behavior\n * assert.deepStrictEqual(valueHistory, [\n * 'A1',\n * 'A2',\n * 'A3',\n * 'B1',\n * 'B2',\n * 'C1',\n * 'B3',\n * 'C2',\n * 'C3',\n * ]);\n * ```\n *\n * @note To improve code readability, consider using `createState` instead of `mergeMap`,\n * subscribing to `parentObservable` and calling `setState` within it.\n */\nexport const mergeMap =\n <A, B>(\n mapToObservable: (curr: A) => Observable<B>,\n ): DropInitialValueOperator<A, B> =>\n (parentObservable) =>\n new MergeMapObservableClass(parentObservable, mapToObservable);\n\n/**\n * Alias for `mergeMap`.\n * @see mergeMap\n */\nexport const flatMap = mergeMap;\n\nclass MergeMapObservableClass<A, B>\n extends AsyncChildObservableClass<B, readonly [A]>\n implements MergeMapOperatorObservable<A, B>\n{\n readonly #mapToObservable: (curr: A) => Observable<B>;\n #mut_observables: readonly Observable<B>[];\n #mut_subscriptions: readonly Subscription[];\n\n constructor(\n parentObservable: Observable<A>,\n mapToObservable: (curr: A) => Observable<B>,\n ) {\n super({\n parents: [parentObservable],\n initialValue: Optional.none,\n });\n\n this.#mapToObservable = mapToObservable;\n\n this.#mut_observables = [];\n\n this.#mut_subscriptions = [];\n }\n\n override tryUpdate(updateToken: UpdateToken): void {\n const par = this.parents[0];\n\n const sn = par.getSnapshot();\n\n if (par.updateToken !== updateToken || Optional.isNone(sn)) {\n return; // skip update\n }\n\n const observable = this.#mapToObservable(sn.value);\n\n this.#mut_observables = Arr.toPushed(this.#mut_observables, observable);\n\n const subscription = observable.subscribe((curr) => {\n this.startUpdate(curr);\n });\n\n this.#mut_subscriptions = Arr.toPushed(\n this.#mut_subscriptions,\n subscription,\n );\n }\n\n override complete(): void {\n for (const s of this.#mut_subscriptions) {\n s.unsubscribe();\n }\n\n for (const o of this.#mut_observables) {\n o.complete();\n }\n\n super.complete();\n }\n}\n"],"names":[],"mappings":";;;;AAyGO,MAAM,QAAA,GACX,CACE,eAAA,KAEF,CAAC,qBACC,IAAI,uBAAA,CAAwB,kBAAkB,eAAe;AAM1D,MAAM,OAAA,GAAU;AAEvB,MAAM,gCACI,yBAAA,CAEV;AAAA,EACW,gBAAA;AAAA,EACT,gBAAA;AAAA,EACA,kBAAA;AAAA,EAEA,WAAA,CACE,kBACA,eAAA,EACA;AACA,IAAA,KAAA,CAAM;AAAA,MACJ,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,cAAc,QAAA,CAAS;AAAA,KACxB,CAAA;AAED,IAAA,IAAA,CAAK,gBAAA,GAAmB,eAAA;AAExB,IAAA,IAAA,CAAK,mBAAmB,EAAC;AAEzB,IAAA,IAAA,CAAK,qBAAqB,EAAC;AAAA,EAC7B;AAAA,EAES,UAAU,WAAA,EAAgC;AACjD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA;AAE1B,IAAA,MAAM,EAAA,GAAK,IAAI,WAAA,EAAY;AAE3B,IAAA,IAAI,IAAI,WAAA,KAAgB,WAAA,IAAe,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAC1D,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,gBAAA,CAAiB,EAAA,CAAG,KAAK,CAAA;AAEjD,IAAA,IAAA,CAAK,gBAAA,GAAmB,GAAA,CAAI,QAAA,CAAS,IAAA,CAAK,kBAAkB,UAAU,CAAA;AAEtE,IAAA,MAAM,YAAA,GAAe,UAAA,CAAW,SAAA,CAAU,CAAC,IAAA,KAAS;AAClD,MAAA,IAAA,CAAK,YAAY,IAAI,CAAA;AAAA,IACvB,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,qBAAqB,GAAA,CAAI,QAAA;AAAA,MAC5B,IAAA,CAAK,kBAAA;AAAA,MACL;AAAA,KACF;AAAA,EACF;AAAA,EAES,QAAA,GAAiB;AACxB,IAAA,KAAA,MAAW,CAAA,IAAK,KAAK,kBAAA,EAAoB;AACvC,MAAA,CAAA,CAAE,WAAA,EAAY;AAAA,IAChB;AAEA,IAAA,KAAA,MAAW,CAAA,IAAK,KAAK,gBAAA,EAAkB;AACrC,MAAA,CAAA,CAAE,QAAA,EAAS;AAAA,IACb;AAEA,IAAA,KAAA,CAAM,QAAA,EAAS;AAAA,EACjB;AACF;;;;"}
@@ -1,3 +1,4 @@
1
+ import { type FixedLengthTuple } from 'ts-type-forge';
1
2
  import { type DropInitialValueOperator } from '../types/index.mjs';
2
3
  /**
3
4
  * Emits the previous and current values as a pair.
@@ -22,7 +23,7 @@ import { type DropInitialValueOperator } from '../types/index.mjs';
22
23
  *
23
24
  * const pairs$ = num$.pipe(pairwise());
24
25
  *
25
- * const valueHistory: (readonly [number, number])[] = [];
26
+ * const valueHistory: FixedLengthTuple<2, number>[] = [];
26
27
  *
27
28
  * pairs$.subscribe(([prev, curr]) => {
28
29
  * valueHistory.push([prev, curr]);
@@ -52,5 +53,5 @@ import { type DropInitialValueOperator } from '../types/index.mjs';
52
53
  * ]);
53
54
  * ```
54
55
  */
55
- export declare const pairwise: <A>() => DropInitialValueOperator<A, readonly [A, A]>;
56
+ export declare const pairwise: <A>() => DropInitialValueOperator<A, FixedLengthTuple<2, A>>;
56
57
  //# sourceMappingURL=pairwise.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pairwise.d.mts","sourceRoot":"","sources":["../../../src/core/operators/pairwise.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,OAAM,wBAAwB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CACxE,CAAC"}
1
+ {"version":3,"file":"pairwise.d.mts","sourceRoot":"","sources":["../../../src/core/operators/pairwise.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EACL,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,OAAM,wBAAwB,CACtD,CAAC,EACD,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAClB,CAAC"}
@@ -2,86 +2,30 @@ import { Optional } from 'ts-data-forge';
2
2
  import { SyncChildObservableClass } from '../class/child-observable-class.mjs';
3
3
  import '../utils/id-maker.mjs';
4
4
 
5
- /**
6
- * Emits the previous and current values as a pair.
7
- * Does not emit until the source has emitted at least twice.
8
- *
9
- * @template A - The type of values from the source
10
- * @returns An operator that pairs consecutive values
11
- *
12
- * @example
13
- * ```ts
14
- * // Timeline:
15
- * //
16
- * // num$ 1 2 3 4
17
- * // pairs$ [1,2] [2,3] [3,4]
18
- * //
19
- * // Explanation:
20
- * // - pairwise emits the current and previous values as a tuple
21
- * // - Nothing is emitted for the first value (no previous value yet)
22
- * // - Useful for tracking changes between consecutive values
23
- *
24
- * const num$ = source<number>();
25
- *
26
- * const pairs$ = num$.pipe(pairwise());
27
- *
28
- * const valueHistory: (readonly [number, number])[] = [];
29
- *
30
- * pairs$.subscribe(([prev, curr]) => {
31
- * valueHistory.push([prev, curr]);
32
- * });
33
- *
34
- * num$.next(1); // nothing logged
35
- *
36
- * assert.deepStrictEqual(valueHistory, []);
37
- *
38
- * num$.next(2); // logs: 1, 2
39
- *
40
- * assert.deepStrictEqual(valueHistory, [[1, 2]]);
41
- *
42
- * num$.next(3); // logs: 2, 3
43
- *
44
- * assert.deepStrictEqual(valueHistory, [
45
- * [1, 2],
46
- * [2, 3],
47
- * ]);
48
- *
49
- * num$.next(4); // logs: 3, 4
50
- *
51
- * assert.deepStrictEqual(valueHistory, [
52
- * [1, 2],
53
- * [2, 3],
54
- * [3, 4],
55
- * ]);
56
- * ```
57
- */
58
5
  const pairwise = () => f;
59
6
  const f = (parentObservable) => new PairwiseObservableClass(parentObservable);
60
7
  class PairwiseObservableClass extends SyncChildObservableClass {
61
- #mut_previousValue;
62
- constructor(parentObservable) {
63
- super({
64
- parents: [parentObservable],
65
- initialValue: Optional.none,
66
- });
67
- // parentObservable.snapshot has value
68
- // if parentObservable is InitializedObservable
69
- this.#mut_previousValue = parentObservable.getSnapshot();
8
+ #mut_previousValue;
9
+ constructor(parentObservable) {
10
+ super({
11
+ parents: [parentObservable],
12
+ initialValue: Optional.none
13
+ });
14
+ this.#mut_previousValue = parentObservable.getSnapshot();
15
+ }
16
+ tryUpdate(updateToken) {
17
+ const par = this.parents[0];
18
+ const sn = par.getSnapshot();
19
+ if (par.updateToken !== updateToken || Optional.isNone(sn)) {
20
+ return;
70
21
  }
71
- tryUpdate(updateToken) {
72
- const par = this.parents[0];
73
- const sn = par.getSnapshot();
74
- if (par.updateToken !== updateToken || Optional.isNone(sn)) {
75
- return; // skip update
76
- }
77
- const prev = this.#mut_previousValue;
78
- const cond = !Optional.isNone(prev);
79
- // NOTE: Must update before setNext, otherwise Optional.isNone(prev) remains true when tryUpdate is called consecutively
80
- this.#mut_previousValue = par.getSnapshot();
81
- if (cond) {
82
- this.setNext([prev.value, sn.value], updateToken);
83
- }
22
+ const prev = this.#mut_previousValue;
23
+ const cond = !Optional.isNone(prev);
24
+ this.#mut_previousValue = par.getSnapshot();
25
+ if (cond) {
26
+ this.setNext([prev.value, sn.value], updateToken);
84
27
  }
28
+ }
85
29
  }
86
30
 
87
31
  export { pairwise };
@@ -1 +1 @@
1
- {"version":3,"file":"pairwise.mjs","sources":["../../../src/core/operators/pairwise.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDG;MACU,QAAQ,GAAG,MACtB;AAEF,MAAM,CAAC,GAAG,CAAK,gBAA+B,KAC5C,IAAI,uBAAuB,CAAC,gBAAgB,CAAC;AAE/C,MAAM,uBACJ,SAAQ,wBAAuD,CAAA;AAG/D,IAAA,kBAAkB;AAElB,IAAA,WAAA,CAAY,gBAA+B,EAAA;AACzC,QAAA,KAAK,CAAC;YACJ,OAAO,EAAE,CAAC,gBAAgB,CAAC;YAC3B,YAAY,EAAE,QAAQ,CAAC,IAAI;AAC5B,SAAA,CAAC;;;AAIF,QAAA,IAAI,CAAC,kBAAkB,GAAG,gBAAgB,CAAC,WAAW,EAAE;IAC1D;AAES,IAAA,SAAS,CAAC,WAAwB,EAAA;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AAE3B,QAAA,MAAM,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE;AAE5B,QAAA,IAAI,GAAG,CAAC,WAAW,KAAK,WAAW,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;AAC1D,YAAA,OAAO;QACT;AAEA,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,kBAAkB;QAEpC,MAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;;AAGnC,QAAA,IAAI,CAAC,kBAAkB,GAAG,GAAG,CAAC,WAAW,EAAE;QAE3C,IAAI,IAAI,EAAE;AACR,YAAA,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;QACnD;IACF;AACD;;;;"}
1
+ {"version":3,"file":"pairwise.mjs","sources":["../../../src/core/operators/pairwise.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { type FixedLengthTuple } from 'ts-type-forge';\nimport { SyncChildObservableClass } from '../class/index.mjs';\nimport {\n type DropInitialValueOperator,\n type Observable,\n type PairwiseOperatorObservable,\n type UpdateToken,\n} from '../types/index.mjs';\n\n/**\n * Emits the previous and current values as a pair.\n * Does not emit until the source has emitted at least twice.\n *\n * @template A - The type of values from the source\n * @returns An operator that pairs consecutive values\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ 1 2 3 4\n * // pairs$ [1,2] [2,3] [3,4]\n * //\n * // Explanation:\n * // - pairwise emits the current and previous values as a tuple\n * // - Nothing is emitted for the first value (no previous value yet)\n * // - Useful for tracking changes between consecutive values\n *\n * const num$ = source<number>();\n *\n * const pairs$ = num$.pipe(pairwise());\n *\n * const valueHistory: FixedLengthTuple<2, number>[] = [];\n *\n * pairs$.subscribe(([prev, curr]) => {\n * valueHistory.push([prev, curr]);\n * });\n *\n * num$.next(1); // nothing logged\n *\n * assert.deepStrictEqual(valueHistory, []);\n *\n * num$.next(2); // logs: 1, 2\n *\n * assert.deepStrictEqual(valueHistory, [[1, 2]]);\n *\n * num$.next(3); // logs: 2, 3\n *\n * assert.deepStrictEqual(valueHistory, [\n * [1, 2],\n * [2, 3],\n * ]);\n *\n * num$.next(4); // logs: 3, 4\n *\n * assert.deepStrictEqual(valueHistory, [\n * [1, 2],\n * [2, 3],\n * [3, 4],\n * ]);\n * ```\n */\nexport const pairwise = <A,>(): DropInitialValueOperator<\n A,\n FixedLengthTuple<2, A>\n> => f;\n\nconst f = <A,>(\n parentObservable: Observable<A>,\n): Observable<FixedLengthTuple<2, A>> =>\n new PairwiseObservableClass(parentObservable);\n\nclass PairwiseObservableClass<A>\n extends SyncChildObservableClass<FixedLengthTuple<2, A>, readonly [A]>\n implements PairwiseOperatorObservable<A>\n{\n #mut_previousValue: Optional<A>;\n\n constructor(parentObservable: Observable<A>) {\n super({\n parents: [parentObservable],\n initialValue: Optional.none,\n });\n\n // parentObservable.snapshot has value\n // if parentObservable is InitializedObservable\n this.#mut_previousValue = parentObservable.getSnapshot();\n }\n\n override tryUpdate(updateToken: UpdateToken): void {\n const par = this.parents[0];\n\n const sn = par.getSnapshot();\n\n if (par.updateToken !== updateToken || Optional.isNone(sn)) {\n return; // skip update\n }\n\n const prev = this.#mut_previousValue;\n\n const cond = !Optional.isNone(prev);\n\n // NOTE: Must update before setNext, otherwise Optional.isNone(prev) remains true when tryUpdate is called consecutively\n this.#mut_previousValue = par.getSnapshot();\n\n if (cond) {\n this.setNext([prev.value, sn.value], updateToken);\n }\n }\n}\n"],"names":[],"mappings":";;;;AA+DO,MAAM,WAAW,MAGnB;AAEL,MAAM,CAAA,GAAI,CACR,gBAAA,KAEA,IAAI,wBAAwB,gBAAgB,CAAA;AAE9C,MAAM,gCACI,wBAAA,CAEV;AAAA,EACE,kBAAA;AAAA,EAEA,YAAY,gBAAA,EAAiC;AAC3C,IAAA,KAAA,CAAM;AAAA,MACJ,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,cAAc,QAAA,CAAS;AAAA,KACxB,CAAA;AAID,IAAA,IAAA,CAAK,kBAAA,GAAqB,iBAAiB,WAAA,EAAY;AAAA,EACzD;AAAA,EAES,UAAU,WAAA,EAAgC;AACjD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA;AAE1B,IAAA,MAAM,EAAA,GAAK,IAAI,WAAA,EAAY;AAE3B,IAAA,IAAI,IAAI,WAAA,KAAgB,WAAA,IAAe,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAC1D,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,OAAO,IAAA,CAAK,kBAAA;AAElB,IAAA,MAAM,IAAA,GAAO,CAAC,QAAA,CAAS,MAAA,CAAO,IAAI,CAAA;AAGlC,IAAA,IAAA,CAAK,kBAAA,GAAqB,IAAI,WAAA,EAAY;AAE1C,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,IAAA,CAAK,QAAQ,CAAC,IAAA,CAAK,OAAO,EAAA,CAAG,KAAK,GAAG,WAAW,CAAA;AAAA,IAClD;AAAA,EACF;AACF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"scan.d.mts","sourceRoot":"","sources":["../../../src/core/operators/scan.mts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,wBAAwB,EAC9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,eAAO,MAAM,IAAI,GACd,CAAC,EAAE,CAAC,EACH,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,EAC/B,cAAc,CAAC,KACd,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAEkC,CAAC"}
1
+ {"version":3,"file":"scan.d.mts","sourceRoot":"","sources":["../../../src/core/operators/scan.mts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,wBAAwB,EAC9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,eAAO,MAAM,IAAI,GACd,CAAC,EAAE,CAAC,WACM,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,gBACjB,CAAC,KACd,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAEkC,CAAC"}
@@ -2,76 +2,25 @@ import { Optional } from 'ts-data-forge';
2
2
  import { InitializedSyncChildObservableClass } from '../class/child-observable-class.mjs';
3
3
  import '../utils/id-maker.mjs';
4
4
 
5
- /**
6
- * Applies an accumulator function over the source observable and emits each intermediate result.
7
- * Similar to Array.reduce but emits accumulated value after each source emission.
8
- *
9
- * @template A - The type of values from the source
10
- * @template B - The type of the accumulated value
11
- * @param reducer - The accumulator function
12
- * @param initialValue - The initial accumulated value (seed)
13
- * @returns An operator that accumulates values
14
- *
15
- * @example
16
- * ```ts
17
- * // Timeline (accumulating sum):
18
- * //
19
- * // num$ 1 2 3 4 5
20
- * // sum$ 1 3 6 10 15
21
- * // | | | | |
22
- * // 0+1 1+2 3+3 6+4 10+5
23
- * //
24
- * // Explanation:
25
- * // - scan accumulates values over time using a reducer function
26
- * // - Starting with seed value 0, each emission adds to the accumulator
27
- * // - Similar to Array.reduce, but for streams
28
- *
29
- * const num$ = source<number>();
30
- *
31
- * const sum$ = num$.pipe(scan((acc, curr) => acc + curr, 0));
32
- *
33
- * const valueHistory: number[] = [];
34
- *
35
- * sum$.subscribe((x) => {
36
- * valueHistory.push(x);
37
- * });
38
- *
39
- * assert.deepStrictEqual(valueHistory, [0]);
40
- *
41
- * num$.next(1); // logs: 1
42
- *
43
- * assert.deepStrictEqual(valueHistory, [0, 1]);
44
- *
45
- * num$.next(2); // logs: 3
46
- *
47
- * assert.deepStrictEqual(valueHistory, [0, 1, 3]);
48
- *
49
- * num$.next(3); // logs: 6
50
- *
51
- * assert.deepStrictEqual(valueHistory, [0, 1, 3, 6]);
52
- * ```
53
- */
54
5
  const scan = (reducer, initialValue) => (parentObservable) => new ScanObservableClass(parentObservable, reducer, initialValue);
55
6
  class ScanObservableClass extends InitializedSyncChildObservableClass {
56
- #reducer;
57
- constructor(parentObservable, reducer, initialValue) {
58
- super({
59
- parents: [parentObservable],
60
- initialValue: Optional.some(initialValue),
61
- });
62
- this.#reducer = reducer;
63
- }
64
- tryUpdate(updateToken) {
65
- const par = this.parents[0];
66
- const psn = par.getSnapshot();
67
- const sn = this.getSnapshot();
68
- if (par.updateToken !== updateToken ||
69
- Optional.isNone(psn) ||
70
- Optional.isNone(sn)) {
71
- return; // skip update
72
- }
73
- this.setNext(this.#reducer(sn.value, psn.value), updateToken);
7
+ #reducer;
8
+ constructor(parentObservable, reducer, initialValue) {
9
+ super({
10
+ parents: [parentObservable],
11
+ initialValue: Optional.some(initialValue)
12
+ });
13
+ this.#reducer = reducer;
14
+ }
15
+ tryUpdate(updateToken) {
16
+ const par = this.parents[0];
17
+ const psn = par.getSnapshot();
18
+ const sn = this.getSnapshot();
19
+ if (par.updateToken !== updateToken || Optional.isNone(psn) || Optional.isNone(sn)) {
20
+ return;
74
21
  }
22
+ this.setNext(this.#reducer(sn.value, psn.value), updateToken);
23
+ }
75
24
  }
76
25
 
77
26
  export { scan };