synstate 2.0.1 → 3.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 (161) hide show
  1. package/README.md +2 -2
  2. package/dist/core/base/create-child-observable.d.mts +65 -0
  3. package/dist/core/base/create-child-observable.d.mts.map +1 -0
  4. package/dist/core/base/create-child-observable.mjs +157 -0
  5. package/dist/core/base/create-child-observable.mjs.map +1 -0
  6. package/dist/core/base/create-observable-base.d.mts +82 -0
  7. package/dist/core/base/create-observable-base.d.mts.map +1 -0
  8. package/dist/core/base/create-observable-base.mjs +160 -0
  9. package/dist/core/base/create-observable-base.mjs.map +1 -0
  10. package/dist/core/base/create-root-observable.d.mts +37 -0
  11. package/dist/core/base/create-root-observable.d.mts.map +1 -0
  12. package/dist/core/base/create-root-observable.mjs +36 -0
  13. package/dist/core/base/create-root-observable.mjs.map +1 -0
  14. package/dist/core/base/index.d.mts +3 -0
  15. package/dist/core/base/index.d.mts.map +1 -0
  16. package/dist/core/base/index.mjs +3 -0
  17. package/dist/core/{class → base}/index.mjs.map +1 -1
  18. package/dist/core/combine/combine.d.mts.map +1 -1
  19. package/dist/core/combine/combine.mjs +28 -27
  20. package/dist/core/combine/combine.mjs.map +1 -1
  21. package/dist/core/combine/merge.d.mts.map +1 -1
  22. package/dist/core/combine/merge.mjs +11 -13
  23. package/dist/core/combine/merge.mjs.map +1 -1
  24. package/dist/core/combine/zip.d.mts.map +1 -1
  25. package/dist/core/combine/zip.mjs +32 -31
  26. package/dist/core/combine/zip.mjs.map +1 -1
  27. package/dist/core/create/counter.d.mts.map +1 -1
  28. package/dist/core/create/counter.mjs +39 -50
  29. package/dist/core/create/counter.mjs.map +1 -1
  30. package/dist/core/create/from-abortable-promise.d.mts.map +1 -1
  31. package/dist/core/create/from-abortable-promise.mjs +33 -32
  32. package/dist/core/create/from-abortable-promise.mjs.map +1 -1
  33. package/dist/core/create/from-promise.d.mts.map +1 -1
  34. package/dist/core/create/from-promise.mjs +12 -12
  35. package/dist/core/create/from-promise.mjs.map +1 -1
  36. package/dist/core/create/from-subscribable.d.mts.map +1 -1
  37. package/dist/core/create/from-subscribable.mjs +10 -10
  38. package/dist/core/create/from-subscribable.mjs.map +1 -1
  39. package/dist/core/create/just.d.mts.map +1 -1
  40. package/dist/core/create/just.mjs +5 -4
  41. package/dist/core/create/just.mjs.map +1 -1
  42. package/dist/core/create/source.mjs +11 -12
  43. package/dist/core/create/source.mjs.map +1 -1
  44. package/dist/core/create/timer.d.mts.map +1 -1
  45. package/dist/core/create/timer.mjs +32 -38
  46. package/dist/core/create/timer.mjs.map +1 -1
  47. package/dist/core/index.d.mts +0 -1
  48. package/dist/core/index.d.mts.map +1 -1
  49. package/dist/core/index.mjs +0 -3
  50. package/dist/core/index.mjs.map +1 -1
  51. package/dist/core/operators/audit.d.mts.map +1 -1
  52. package/dist/core/operators/audit.mjs +28 -36
  53. package/dist/core/operators/audit.mjs.map +1 -1
  54. package/dist/core/operators/debounce.d.mts.map +1 -1
  55. package/dist/core/operators/debounce.mjs +26 -33
  56. package/dist/core/operators/debounce.mjs.map +1 -1
  57. package/dist/core/operators/filter.d.mts.map +1 -1
  58. package/dist/core/operators/filter.mjs +23 -27
  59. package/dist/core/operators/filter.mjs.map +1 -1
  60. package/dist/core/operators/map.d.mts.map +1 -1
  61. package/dist/core/operators/map.mjs +21 -28
  62. package/dist/core/operators/map.mjs.map +1 -1
  63. package/dist/core/operators/merge-map.d.mts.map +1 -1
  64. package/dist/core/operators/merge-map.mjs +30 -39
  65. package/dist/core/operators/merge-map.mjs.map +1 -1
  66. package/dist/core/operators/pairwise.d.mts.map +1 -1
  67. package/dist/core/operators/pairwise.mjs +22 -24
  68. package/dist/core/operators/pairwise.mjs.map +1 -1
  69. package/dist/core/operators/scan.d.mts.map +1 -1
  70. package/dist/core/operators/scan.mjs +13 -18
  71. package/dist/core/operators/scan.mjs.map +1 -1
  72. package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
  73. package/dist/core/operators/skip-if-no-change.mjs +22 -26
  74. package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
  75. package/dist/core/operators/skip-until.d.mts.map +1 -1
  76. package/dist/core/operators/skip-until.mjs +23 -24
  77. package/dist/core/operators/skip-until.mjs.map +1 -1
  78. package/dist/core/operators/skip-while.d.mts.map +1 -1
  79. package/dist/core/operators/skip-while.mjs +27 -32
  80. package/dist/core/operators/skip-while.mjs.map +1 -1
  81. package/dist/core/operators/switch-map.d.mts.map +1 -1
  82. package/dist/core/operators/switch-map.mjs +28 -34
  83. package/dist/core/operators/switch-map.mjs.map +1 -1
  84. package/dist/core/operators/take-until.d.mts.map +1 -1
  85. package/dist/core/operators/take-until.mjs +22 -22
  86. package/dist/core/operators/take-until.mjs.map +1 -1
  87. package/dist/core/operators/take-while.d.mts.map +1 -1
  88. package/dist/core/operators/take-while.mjs +25 -29
  89. package/dist/core/operators/take-while.mjs.map +1 -1
  90. package/dist/core/operators/throttle.d.mts.map +1 -1
  91. package/dist/core/operators/throttle.mjs +27 -35
  92. package/dist/core/operators/throttle.mjs.map +1 -1
  93. package/dist/core/operators/with-buffered-from.d.mts.map +1 -1
  94. package/dist/core/operators/with-buffered-from.mjs +24 -24
  95. package/dist/core/operators/with-buffered-from.mjs.map +1 -1
  96. package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
  97. package/dist/core/operators/with-current-value-from.mjs +20 -25
  98. package/dist/core/operators/with-current-value-from.mjs.map +1 -1
  99. package/dist/core/operators/with-initial-value.d.mts.map +1 -1
  100. package/dist/core/operators/with-initial-value.mjs +12 -15
  101. package/dist/core/operators/with-initial-value.mjs.map +1 -1
  102. package/dist/entry-point.mjs +0 -3
  103. package/dist/entry-point.mjs.map +1 -1
  104. package/dist/index.mjs +0 -3
  105. package/dist/index.mjs.map +1 -1
  106. package/package.json +25 -18
  107. package/src/core/{class → base}/circular-dependency-comparison.test.mts +28 -18
  108. package/src/core/base/circular-dependency.test.mts +322 -0
  109. package/src/core/base/create-child-observable.mts +340 -0
  110. package/src/core/base/create-observable-base.mts +358 -0
  111. package/src/core/base/create-root-observable.mts +102 -0
  112. package/src/core/base/index.mts +2 -0
  113. package/src/core/{class/observable.class.test.mts → base/observable-base.test.mts} +25 -17
  114. package/src/core/combine/combine.mts +51 -53
  115. package/src/core/combine/merge.mts +21 -23
  116. package/src/core/combine/zip.mts +54 -58
  117. package/src/core/create/counter.mts +42 -59
  118. package/src/core/create/from-abortable-promise.mts +38 -45
  119. package/src/core/create/from-promise.mts +25 -28
  120. package/src/core/create/from-subscribable.mts +23 -27
  121. package/src/core/create/just.mts +5 -4
  122. package/src/core/create/source.mts +11 -17
  123. package/src/core/create/timer.mts +32 -47
  124. package/src/core/index.mts +0 -1
  125. package/src/core/operators/audit.mts +43 -57
  126. package/src/core/operators/debounce.mts +35 -45
  127. package/src/core/operators/filter.mts +31 -39
  128. package/src/core/operators/map.mts +32 -40
  129. package/src/core/operators/merge-map.mts +44 -59
  130. package/src/core/operators/pairwise.mts +30 -33
  131. package/src/core/operators/scan.mts +24 -35
  132. package/src/core/operators/skip-if-no-change.mts +31 -36
  133. package/src/core/operators/skip-until.mts +32 -35
  134. package/src/core/operators/skip-while.mts +31 -40
  135. package/src/core/operators/switch-map.mts +36 -48
  136. package/src/core/operators/take-until.mts +31 -29
  137. package/src/core/operators/take-while.mts +33 -41
  138. package/src/core/operators/throttle.mts +37 -51
  139. package/src/core/operators/with-buffered-from.mts +35 -30
  140. package/src/core/operators/with-current-value-from.mts +23 -28
  141. package/src/core/operators/with-initial-value.mts +21 -22
  142. package/dist/core/class/child-observable-class.d.mts +0 -39
  143. package/dist/core/class/child-observable-class.d.mts.map +0 -1
  144. package/dist/core/class/child-observable-class.mjs +0 -173
  145. package/dist/core/class/child-observable-class.mjs.map +0 -1
  146. package/dist/core/class/index.d.mts +0 -4
  147. package/dist/core/class/index.d.mts.map +0 -1
  148. package/dist/core/class/index.mjs +0 -4
  149. package/dist/core/class/observable-base-class.d.mts +0 -28
  150. package/dist/core/class/observable-base-class.d.mts.map +0 -1
  151. package/dist/core/class/observable-base-class.mjs +0 -120
  152. package/dist/core/class/observable-base-class.mjs.map +0 -1
  153. package/dist/core/class/root-observable-class.d.mts +0 -14
  154. package/dist/core/class/root-observable-class.d.mts.map +0 -1
  155. package/dist/core/class/root-observable-class.mjs +0 -43
  156. package/dist/core/class/root-observable-class.mjs.map +0 -1
  157. package/src/core/class/child-observable-class.mts +0 -286
  158. package/src/core/class/circular-dependency.test.mts +0 -251
  159. package/src/core/class/index.mts +0 -3
  160. package/src/core/class/observable-base-class.mts +0 -187
  161. package/src/core/class/root-observable-class.mts +0 -73
@@ -1,34 +1,33 @@
1
1
  import { Optional } from 'ts-data-forge';
2
- import { SyncChildObservableClass } from '../class/child-observable-class.mjs';
2
+ import { createSyncChildObservable } from '../base/create-child-observable.mjs';
3
3
  import '../utils/id-maker.mjs';
4
4
 
5
- const skipUntil = (notifier) => (parentObservable) => new SkipUntilObservableClass(parentObservable, notifier);
6
- class SkipUntilObservableClass extends SyncChildObservableClass {
7
- #mut_isSkipping;
8
- constructor(parentObservable, notifier) {
9
- super({
5
+ const skipUntil = (notifier) => (parentObservable) => createSkipUntilObservable(parentObservable, notifier);
6
+ const createSkipUntilObservable = (parentObservable, notifier) => {
7
+ let mut_isSkipping = true;
8
+ const observable = createSyncChildObservable(
9
+ {
10
10
  parents: [parentObservable],
11
11
  initialValue: Optional.none
12
- });
13
- this.#mut_isSkipping = true;
14
- notifier.subscribe(
15
- () => {
16
- this.#mut_isSkipping = false;
17
- },
18
- () => {
19
- this.#mut_isSkipping = false;
12
+ },
13
+ ({ setNext }) => (updateToken) => {
14
+ const sn = parentObservable.getSnapshot();
15
+ if (mut_isSkipping || parentObservable.updateToken !== updateToken || Optional.isNone(sn)) {
16
+ return;
20
17
  }
21
- );
22
- }
23
- tryUpdate(updateToken) {
24
- const par = this.parents[0];
25
- const sn = par.getSnapshot();
26
- if (par.updateToken !== updateToken || Optional.isNone(sn) || this.#mut_isSkipping) {
27
- return;
18
+ setNext(sn.value, updateToken);
28
19
  }
29
- this.setNext(sn.value, updateToken);
30
- }
31
- }
20
+ );
21
+ notifier.subscribe(
22
+ () => {
23
+ mut_isSkipping = false;
24
+ },
25
+ () => {
26
+ mut_isSkipping = false;
27
+ }
28
+ );
29
+ return observable;
30
+ };
32
31
 
33
32
  export { skipUntil };
34
33
  //# sourceMappingURL=skip-until.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"skip-until.mjs","sources":["../../../src/core/operators/skip-until.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { SyncChildObservableClass } from '../class/index.mjs';\nimport {\n type DropInitialValueOperator,\n type Observable,\n type SkipUntilOperatorObservable,\n type UpdateToken,\n} from '../types/index.mjs';\n\n/**\n * Skips all values from the source observable until the notifier observable emits.\n *\n * @template A - The type of values from the source\n * @param notifier - An observable that signals when to start emitting\n * @returns An operator that skips values until the notifier emits\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ 1 2 3 start 4 5 6\n * // startNotifier X\n * // skipped$ 4 5 6\n * // |------ skipped -------|\n * //\n * // Explanation:\n * // - skipUntil ignores all values until the notifier emits\n * // - After the notifier emits, all subsequent values are passed through\n * // - Opposite of takeUntil (which completes when notifier emits)\n *\n * const num$ = source<number>();\n *\n * const [startNotifier, start_] = createEventEmitter();\n *\n * const skipped$ = num$.pipe(skipUntil(startNotifier));\n *\n * const valueHistory: number[] = [];\n *\n * skipped$.subscribe((x) => {\n * valueHistory.push(x);\n * });\n *\n * num$.next(1); // nothing logged\n *\n * num$.next(2); // nothing logged\n *\n * assert.deepStrictEqual(valueHistory, []);\n *\n * start_();\n *\n * num$.next(4); // logs: 4\n *\n * assert.deepStrictEqual(valueHistory, [4]);\n *\n * num$.next(5); // logs: 5\n *\n * assert.deepStrictEqual(valueHistory, [4, 5]);\n * ```\n */\nexport const skipUntil =\n <A,>(notifier: Observable<unknown>): DropInitialValueOperator<A, A> =>\n (parentObservable) =>\n new SkipUntilObservableClass(parentObservable, notifier);\n\nclass SkipUntilObservableClass<A>\n extends SyncChildObservableClass<A, readonly [A]>\n implements SkipUntilOperatorObservable<A>\n{\n #mut_isSkipping: boolean;\n\n constructor(parentObservable: Observable<A>, notifier: Observable<unknown>) {\n super({\n parents: [parentObservable],\n initialValue: Optional.none,\n });\n\n this.#mut_isSkipping = true;\n\n notifier.subscribe(\n () => {\n this.#mut_isSkipping = false;\n },\n () => {\n this.#mut_isSkipping = false;\n },\n );\n }\n\n override tryUpdate(updateToken: UpdateToken): void {\n const par = this.parents[0];\n\n const sn = par.getSnapshot();\n\n if (\n par.updateToken !== updateToken ||\n Optional.isNone(sn) ||\n this.#mut_isSkipping\n ) {\n return; // skip update\n }\n\n this.setNext(sn.value, updateToken);\n }\n}\n"],"names":[],"mappings":";;;;AA2DO,MAAM,SAAA,GACX,CAAK,QAAA,KACL,CAAC,qBACC,IAAI,wBAAA,CAAyB,kBAAkB,QAAQ;AAE3D,MAAM,iCACI,wBAAA,CAEV;AAAA,EACE,eAAA;AAAA,EAEA,WAAA,CAAY,kBAAiC,QAAA,EAA+B;AAC1E,IAAA,KAAA,CAAM;AAAA,MACJ,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,cAAc,QAAA,CAAS;AAAA,KACxB,CAAA;AAED,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAEvB,IAAA,QAAA,CAAS,SAAA;AAAA,MACP,MAAM;AACJ,QAAA,IAAA,CAAK,eAAA,GAAkB,KAAA;AAAA,MACzB,CAAA;AAAA,MACA,MAAM;AACJ,QAAA,IAAA,CAAK,eAAA,GAAkB,KAAA;AAAA,MACzB;AAAA,KACF;AAAA,EACF;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,IACE,GAAA,CAAI,gBAAgB,WAAA,IACpB,QAAA,CAAS,OAAO,EAAE,CAAA,IAClB,KAAK,eAAA,EACL;AACA,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,OAAA,CAAQ,EAAA,CAAG,KAAA,EAAO,WAAW,CAAA;AAAA,EACpC;AACF;;;;"}
1
+ {"version":3,"file":"skip-until.mjs","sources":["../../../src/core/operators/skip-until.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { createSyncChildObservable } from '../base/index.mjs';\nimport {\n type DropInitialValueOperator,\n type Observable,\n type SkipUntilOperatorObservable,\n} from '../types/index.mjs';\n\n/**\n * Skips all values from the source observable until the notifier observable emits.\n *\n * @template A - The type of values from the source\n * @param notifier - An observable that signals when to start emitting\n * @returns An operator that skips values until the notifier emits\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ 1 2 3 start 4 5 6\n * // startNotifier X\n * // skipped$ 4 5 6\n * // |------ skipped -------|\n * //\n * // Explanation:\n * // - skipUntil ignores all values until the notifier emits\n * // - After the notifier emits, all subsequent values are passed through\n * // - Opposite of takeUntil (which completes when notifier emits)\n *\n * const num$ = source<number>();\n *\n * const [startNotifier, start_] = createEventEmitter();\n *\n * const skipped$ = num$.pipe(skipUntil(startNotifier));\n *\n * const valueHistory: number[] = [];\n *\n * skipped$.subscribe((x) => {\n * valueHistory.push(x);\n * });\n *\n * num$.next(1); // nothing logged\n *\n * num$.next(2); // nothing logged\n *\n * assert.deepStrictEqual(valueHistory, []);\n *\n * start_();\n *\n * num$.next(4); // logs: 4\n *\n * assert.deepStrictEqual(valueHistory, [4]);\n *\n * num$.next(5); // logs: 5\n *\n * assert.deepStrictEqual(valueHistory, [4, 5]);\n * ```\n */\nexport const skipUntil =\n <A,>(notifier: Observable<unknown>): DropInitialValueOperator<A, A> =>\n (parentObservable) =>\n createSkipUntilObservable(parentObservable, notifier);\n\nconst createSkipUntilObservable = <A,>(\n parentObservable: Observable<A>,\n notifier: Observable<unknown>,\n): SkipUntilOperatorObservable<A> => {\n let mut_isSkipping = true;\n\n const observable = createSyncChildObservable<A, readonly [A]>(\n {\n parents: [parentObservable],\n initialValue: Optional.none,\n },\n ({ setNext }) =>\n (updateToken) => {\n const sn = parentObservable.getSnapshot();\n\n if (\n mut_isSkipping ||\n parentObservable.updateToken !== updateToken ||\n Optional.isNone(sn)\n ) {\n return; // skip update\n }\n\n setNext(sn.value, updateToken);\n },\n );\n\n notifier.subscribe(\n () => {\n mut_isSkipping = false;\n },\n () => {\n mut_isSkipping = false;\n },\n );\n\n return observable;\n};\n"],"names":[],"mappings":";;;;AA0DO,MAAM,YACX,CAAK,QAAA,KACL,CAAC,gBAAA,KACC,yBAAA,CAA0B,kBAAkB,QAAQ;AAExD,MAAM,yBAAA,GAA4B,CAChC,gBAAA,EACA,QAAA,KACmC;AACnC,EAAA,IAAI,cAAA,GAAiB,IAAA;AAErB,EAAA,MAAM,UAAA,GAAa,yBAAA;AAAA,IACjB;AAAA,MACE,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,cAAc,QAAA,CAAS;AAAA,KACzB;AAAA,IACA,CAAC,EAAE,OAAA,EAAQ,KACT,CAAC,WAAA,KAAgB;AACf,MAAA,MAAM,EAAA,GAAK,iBAAiB,WAAA,EAAY;AAExC,MAAA,IACE,kBACA,gBAAA,CAAiB,WAAA,KAAgB,eACjC,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAClB;AACA,QAAA;AAAA,MACF;AAEA,MAAA,OAAA,CAAQ,EAAA,CAAG,OAAO,WAAW,CAAA;AAAA,IAC/B;AAAA,GACJ;AAEA,EAAA,QAAA,CAAS,SAAA;AAAA,IACP,MAAM;AACJ,MAAA,cAAA,GAAiB,KAAA;AAAA,IACnB,CAAA;AAAA,IACA,MAAM;AACJ,MAAA,cAAA,GAAiB,KAAA;AAAA,IACnB;AAAA,GACF;AAEA,EAAA,OAAO,UAAA;AACT,CAAA;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"skip-while.d.mts","sourceRoot":"","sources":["../../../src/core/operators/skip-while.mts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAAoB,MAAM,eAAe,CAAC;AAErE,OAAO,EACL,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,eAAO,MAAM,SAAS,GACnB,CAAC,aACW,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,OAAO,KACrD,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAE2B,CAAC"}
1
+ {"version":3,"file":"skip-while.d.mts","sourceRoot":"","sources":["../../../src/core/operators/skip-while.mts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAAoB,MAAM,eAAe,CAAC;AAErE,OAAO,EACL,KAAK,wBAAwB,EAG9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,eAAO,MAAM,SAAS,GACnB,CAAC,aACW,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,OAAO,KACrD,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAEwB,CAAC"}
@@ -1,38 +1,33 @@
1
- import { pipe, Optional, asSafeUint, SafeUint } from 'ts-data-forge';
2
- import { SyncChildObservableClass } from '../class/child-observable-class.mjs';
1
+ import { Optional, asSafeUint, SafeUint, pipe } from 'ts-data-forge';
2
+ import { createSyncChildObservable } from '../base/create-child-observable.mjs';
3
3
  import '../utils/id-maker.mjs';
4
4
 
5
- const skipWhile = (predicate) => (parentObservable) => new SkipWhileObservableClass(parentObservable, predicate);
6
- class SkipWhileObservableClass extends SyncChildObservableClass {
7
- #predicate;
8
- #mut_index;
9
- #mut_skipping;
10
- constructor(parentObservable, predicate) {
11
- super({
12
- parents: [parentObservable],
13
- initialValue: pipe(parentObservable.getSnapshot()).map(
14
- (sn) => Optional.isNone(sn) || predicate(sn.value, -1) ? Optional.none : sn
15
- ).value
16
- });
17
- this.#mut_index = -1;
18
- this.#predicate = predicate;
19
- this.#mut_skipping = true;
5
+ const skipWhile = (predicate) => (parentObservable) => createSkipWhileObservable(parentObservable, predicate);
6
+ const createSkipWhileObservable = (parentObservable, predicate) => createSyncChildObservable(
7
+ {
8
+ parents: [parentObservable],
9
+ initialValue: pipe(parentObservable.getSnapshot()).map(
10
+ (sn) => Optional.isNone(sn) || predicate(sn.value, -1) ? Optional.none : sn
11
+ ).value
12
+ },
13
+ ({ setNext }) => {
14
+ let mut_index = -1;
15
+ let mut_skipping = true;
16
+ return (updateToken) => {
17
+ const sn = parentObservable.getSnapshot();
18
+ if (parentObservable.updateToken !== updateToken || Optional.isNone(sn)) {
19
+ return;
20
+ }
21
+ mut_index = mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, mut_index);
22
+ if (!predicate(sn.value, mut_index)) {
23
+ mut_skipping = false;
24
+ }
25
+ if (!mut_skipping) {
26
+ setNext(sn.value, updateToken);
27
+ }
28
+ };
20
29
  }
21
- tryUpdate(updateToken) {
22
- const par = this.parents[0];
23
- const sn = par.getSnapshot();
24
- if (par.updateToken !== updateToken || Optional.isNone(sn)) {
25
- return;
26
- }
27
- this.#mut_index = this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
28
- if (!this.#predicate(sn.value, this.#mut_index)) {
29
- this.#mut_skipping = false;
30
- }
31
- if (!this.#mut_skipping) {
32
- this.setNext(sn.value, updateToken);
33
- }
34
- }
35
- }
30
+ );
36
31
 
37
32
  export { skipWhile };
38
33
  //# sourceMappingURL=skip-while.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"skip-while.mjs","sources":["../../../src/core/operators/skip-while.mts"],"sourcesContent":["import { Optional, SafeUint, asSafeUint, pipe } from 'ts-data-forge';\nimport { SyncChildObservableClass } from '../class/index.mjs';\nimport {\n type DropInitialValueOperator,\n type Observable,\n type SkipWhileOperatorObservable,\n type UpdateToken,\n} from '../types/index.mjs';\n\n/**\n * Skips values from the source observable while the predicate returns true.\n * Once the predicate returns false, all subsequent values pass through.\n *\n * @template A - The type of values from the source\n * @param predicate - Function to test each value\n * @returns An operator that skips values while the predicate is true\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ 1 2 3 4 5 6 7 1 2\n * // skipped$ 5 6 7 1 2\n * // |-------- skip --------|\n * //\n * // Explanation:\n * // - skipWhile skips values while the predicate returns true\n * // - Once the predicate returns false, all subsequent values pass through\n * // - Unlike filter, the predicate is never checked again after the first false\n *\n * const num$ = source<number>();\n *\n * const skipped$ = num$.pipe(skipWhile((x) => x < 5));\n *\n * const valueHistory: number[] = [];\n *\n * skipped$.subscribe((x) => {\n * valueHistory.push(x);\n * });\n *\n * num$.next(1); // nothing logged\n *\n * num$.next(2); // nothing logged\n *\n * num$.next(3); // nothing logged\n *\n * num$.next(4); // nothing logged\n *\n * num$.next(5); // logs: 5\n *\n * assert.deepStrictEqual(valueHistory, [5]);\n *\n * num$.next(6); // logs: 6\n *\n * assert.deepStrictEqual(valueHistory, [5, 6]);\n *\n * num$.next(7); // logs: 7\n *\n * assert.deepStrictEqual(valueHistory, [5, 6, 7]);\n *\n * num$.next(1); // logs: 1\n *\n * num$.next(2); // logs: 2\n *\n * assert.deepStrictEqual(valueHistory, [5, 6, 7, 1, 2]);\n * ```\n */\nexport const skipWhile =\n <A,>(\n predicate: (value: A, index: SafeUint | -1) => boolean,\n ): DropInitialValueOperator<A, A> =>\n (parentObservable) =>\n new SkipWhileObservableClass(parentObservable, predicate);\n\n/* implementation */\n\nclass SkipWhileObservableClass<A>\n extends SyncChildObservableClass<A, readonly [A]>\n implements SkipWhileOperatorObservable<A>\n{\n readonly #predicate: (value: A, index: SafeUint | -1) => boolean;\n #mut_index: SafeUint | -1;\n #mut_skipping: boolean;\n\n constructor(\n parentObservable: Observable<A>,\n predicate: (value: A, index: SafeUint | -1) => boolean,\n ) {\n super({\n parents: [parentObservable],\n initialValue: pipe(parentObservable.getSnapshot()).map((sn) =>\n Optional.isNone(sn) || predicate(sn.value, -1) ? Optional.none : sn,\n ).value,\n });\n\n this.#mut_index = -1;\n\n this.#predicate = predicate;\n\n this.#mut_skipping = true;\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.#mut_skipping = false;\n }\n\n if (!this.#mut_skipping) {\n this.setNext(sn.value, updateToken);\n }\n }\n}\n"],"names":[],"mappings":";;;;AAmEO,MAAM,SAAA,GACX,CACE,SAAA,KAEF,CAAC,qBACC,IAAI,wBAAA,CAAyB,kBAAkB,SAAS;AAI5D,MAAM,iCACI,wBAAA,CAEV;AAAA,EACW,UAAA;AAAA,EACT,UAAA;AAAA,EACA,aAAA;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,IAAK,SAAA,CAAU,EAAA,CAAG,KAAA,EAAO,EAAE,CAAA,GAAI,QAAA,CAAS,IAAA,GAAO;AAAA,OACnE,CAAE;AAAA,KACH,CAAA;AAED,IAAA,IAAA,CAAK,UAAA,GAAa,EAAA;AAElB,IAAA,IAAA,CAAK,UAAA,GAAa,SAAA;AAElB,IAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AAAA,EACvB;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,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,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,KAAA,EAAO,IAAA,CAAK,UAAU,CAAA,EAAG;AAC/C,MAAA,IAAA,CAAK,aAAA,GAAgB,KAAA;AAAA,IACvB;AAEA,IAAA,IAAI,CAAC,KAAK,aAAA,EAAe;AACvB,MAAA,IAAA,CAAK,OAAA,CAAQ,EAAA,CAAG,KAAA,EAAO,WAAW,CAAA;AAAA,IACpC;AAAA,EACF;AACF;;;;"}
1
+ {"version":3,"file":"skip-while.mjs","sources":["../../../src/core/operators/skip-while.mts"],"sourcesContent":["import { Optional, SafeUint, asSafeUint, pipe } from 'ts-data-forge';\nimport { createSyncChildObservable } from '../base/index.mjs';\nimport {\n type DropInitialValueOperator,\n type Observable,\n type SkipWhileOperatorObservable,\n} from '../types/index.mjs';\n\n/**\n * Skips values from the source observable while the predicate returns true.\n * Once the predicate returns false, all subsequent values pass through.\n *\n * @template A - The type of values from the source\n * @param predicate - Function to test each value\n * @returns An operator that skips values while the predicate is true\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ 1 2 3 4 5 6 7 1 2\n * // skipped$ 5 6 7 1 2\n * // |-------- skip --------|\n * //\n * // Explanation:\n * // - skipWhile skips values while the predicate returns true\n * // - Once the predicate returns false, all subsequent values pass through\n * // - Unlike filter, the predicate is never checked again after the first false\n *\n * const num$ = source<number>();\n *\n * const skipped$ = num$.pipe(skipWhile((x) => x < 5));\n *\n * const valueHistory: number[] = [];\n *\n * skipped$.subscribe((x) => {\n * valueHistory.push(x);\n * });\n *\n * num$.next(1); // nothing logged\n *\n * num$.next(2); // nothing logged\n *\n * num$.next(3); // nothing logged\n *\n * num$.next(4); // nothing logged\n *\n * num$.next(5); // logs: 5\n *\n * assert.deepStrictEqual(valueHistory, [5]);\n *\n * num$.next(6); // logs: 6\n *\n * assert.deepStrictEqual(valueHistory, [5, 6]);\n *\n * num$.next(7); // logs: 7\n *\n * assert.deepStrictEqual(valueHistory, [5, 6, 7]);\n *\n * num$.next(1); // logs: 1\n *\n * num$.next(2); // logs: 2\n *\n * assert.deepStrictEqual(valueHistory, [5, 6, 7, 1, 2]);\n * ```\n */\nexport const skipWhile =\n <A,>(\n predicate: (value: A, index: SafeUint | -1) => boolean,\n ): DropInitialValueOperator<A, A> =>\n (parentObservable) =>\n createSkipWhileObservable(parentObservable, predicate);\n\n/* implementation */\n\nconst createSkipWhileObservable = <A,>(\n parentObservable: Observable<A>,\n predicate: (value: A, index: SafeUint | -1) => boolean,\n): SkipWhileOperatorObservable<A> =>\n createSyncChildObservable(\n {\n parents: [parentObservable],\n initialValue: pipe(parentObservable.getSnapshot()).map((sn) =>\n Optional.isNone(sn) || predicate(sn.value, -1) ? Optional.none : sn,\n ).value,\n },\n ({ setNext }) => {\n let mut_index: SafeUint | -1 = -1;\n\n let mut_skipping = true;\n\n return (updateToken) => {\n const sn = parentObservable.getSnapshot();\n\n if (\n parentObservable.updateToken !== updateToken ||\n Optional.isNone(sn)\n ) {\n return; // skip update\n }\n\n mut_index =\n mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, mut_index);\n\n if (!predicate(sn.value, mut_index)) {\n mut_skipping = false;\n }\n\n if (!mut_skipping) {\n setNext(sn.value, updateToken);\n }\n };\n },\n );\n"],"names":[],"mappings":";;;;AAkEO,MAAM,YACX,CACE,SAAA,KAEF,CAAC,gBAAA,KACC,yBAAA,CAA0B,kBAAkB,SAAS;AAIzD,MAAM,yBAAA,GAA4B,CAChC,gBAAA,EACA,SAAA,KAEA,yBAAA;AAAA,EACE;AAAA,IACE,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,IAC1B,YAAA,EAAc,IAAA,CAAK,gBAAA,CAAiB,WAAA,EAAa,CAAA,CAAE,GAAA;AAAA,MAAI,CAAC,EAAA,KACtD,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,IAAK,SAAA,CAAU,EAAA,CAAG,KAAA,EAAO,EAAE,CAAA,GAAI,QAAA,CAAS,IAAA,GAAO;AAAA,KACnE,CAAE;AAAA,GACJ;AAAA,EACA,CAAC,EAAE,OAAA,EAAQ,KAAM;AACf,IAAA,IAAI,SAAA,GAA2B,EAAA;AAE/B,IAAA,IAAI,YAAA,GAAe,IAAA;AAEnB,IAAA,OAAO,CAAC,WAAA,KAAgB;AACtB,MAAA,MAAM,EAAA,GAAK,iBAAiB,WAAA,EAAY;AAExC,MAAA,IACE,iBAAiB,WAAA,KAAgB,WAAA,IACjC,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAClB;AACA,QAAA;AAAA,MACF;AAEA,MAAA,SAAA,GACE,SAAA,KAAc,KAAK,UAAA,CAAW,CAAC,IAAI,QAAA,CAAS,GAAA,CAAI,GAAG,SAAS,CAAA;AAE9D,MAAA,IAAI,CAAC,SAAA,CAAU,EAAA,CAAG,KAAA,EAAO,SAAS,CAAA,EAAG;AACnC,QAAA,YAAA,GAAe,KAAA;AAAA,MACjB;AAEA,MAAA,IAAI,CAAC,YAAA,EAAc;AACjB,QAAA,OAAA,CAAQ,EAAA,CAAG,OAAO,WAAW,CAAA;AAAA,MAC/B;AAAA,IACF,CAAA;AAAA,EACF;AACF,CAAA;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"switch-map.d.mts","sourceRoot":"","sources":["../../../src/core/operators/switch-map.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,UAAU,EAIhB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4FG;AACH,eAAO,MAAM,SAAS,GACnB,CAAC,EAAE,CAAC,mBACc,CAAC,IAAI,EAAE,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,KAC1C,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAEiC,CAAC"}
1
+ {"version":3,"file":"switch-map.d.mts","sourceRoot":"","sources":["../../../src/core/operators/switch-map.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,UAAU,EAGhB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4FG;AACH,eAAO,MAAM,SAAS,GACnB,CAAC,EAAE,CAAC,mBACc,CAAC,IAAI,EAAE,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,KAC1C,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAE8B,CAAC"}
@@ -1,42 +1,36 @@
1
1
  import { Optional } from 'ts-data-forge';
2
- import { AsyncChildObservableClass } from '../class/child-observable-class.mjs';
2
+ import { createAsyncChildObservable } from '../base/create-child-observable.mjs';
3
3
  import '../utils/id-maker.mjs';
4
4
 
5
- const switchMap = (mapToObservable) => (parentObservable) => new SwitchMapObservableClass(parentObservable, mapToObservable);
6
- class SwitchMapObservableClass extends AsyncChildObservableClass {
7
- #mapToObservable;
8
- #mut_observable;
9
- #mut_subscription;
10
- constructor(parentObservable, mapToObservable) {
11
- super({
5
+ const switchMap = (mapToObservable) => (parentObservable) => createSwitchMapObservable(parentObservable, mapToObservable);
6
+ const createSwitchMapObservable = (parentObservable, mapToObservable) => {
7
+ let mut_observable = void 0;
8
+ let mut_subscription = void 0;
9
+ return createAsyncChildObservable(
10
+ {
12
11
  parents: [parentObservable],
13
- initialValue: Optional.none
14
- });
15
- this.#mapToObservable = mapToObservable;
16
- this.#mut_observable = void 0;
17
- this.#mut_subscription = void 0;
18
- }
19
- tryUpdate(updateToken) {
20
- const par = this.parents[0];
21
- const sn = par.getSnapshot();
22
- if (par.updateToken !== updateToken || Optional.isNone(sn)) {
23
- return;
12
+ initialValue: Optional.none,
13
+ onComplete: () => {
14
+ mut_subscription?.unsubscribe();
15
+ mut_observable?.complete();
16
+ }
17
+ },
18
+ ({ startUpdate }) => (updateToken) => {
19
+ const sn = parentObservable.getSnapshot();
20
+ if (parentObservable.updateToken !== updateToken || Optional.isNone(sn)) {
21
+ return;
22
+ }
23
+ mut_observable?.complete();
24
+ mut_subscription?.unsubscribe();
25
+ const observable = mapToObservable(sn.value);
26
+ mut_observable = observable;
27
+ const subscription = observable.subscribe((curr) => {
28
+ startUpdate(curr);
29
+ });
30
+ mut_subscription = subscription;
24
31
  }
25
- this.#mut_observable?.complete();
26
- this.#mut_subscription?.unsubscribe();
27
- const observable = this.#mapToObservable(sn.value);
28
- this.#mut_observable = observable;
29
- const subscription = observable.subscribe((curr) => {
30
- this.startUpdate(curr);
31
- });
32
- this.#mut_subscription = subscription;
33
- }
34
- complete() {
35
- this.#mut_subscription?.unsubscribe();
36
- this.#mut_observable?.complete();
37
- super.complete();
38
- }
39
- }
32
+ );
33
+ };
40
34
 
41
35
  export { switchMap };
42
36
  //# sourceMappingURL=switch-map.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"switch-map.mjs","sources":["../../../src/core/operators/switch-map.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { AsyncChildObservableClass } from '../class/index.mjs';\nimport {\n type DropInitialValueOperator,\n type Observable,\n type Subscription,\n type SwitchMapOperatorObservable,\n type UpdateToken,\n} from '../types/index.mjs';\n\n/**\n * Projects each source value to an observable, subscribes to it, and emits its values.\n * When a new value arrives from the source, the previous inner observable is unsubscribed.\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 switches to new 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 (switched!)\n * // inner C C1 C2 C3\n * // result$ A1 A2 A3 B1 B2 C1 C2 C3\n * //\n * // Explanation:\n * // - switchMap creates an inner observable for each source value\n * // - When a new source value arrives, the previous inner is unsubscribed\n * // - A's inner completes normally (all 3 values emitted)\n * // - B's inner is interrupted by C (only 2 values emitted)\n * // - C's inner completes normally (all 3 values emitted)\n *\n * const input$ = source<string>();\n *\n * const result$ = input$.pipe(\n * switchMap((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 - switches away from B (B3 cancelled), C's inner starts\n * input$.next('C');\n *\n * await sleep(250);\n *\n * assert.deepStrictEqual(valueHistory, [\n * 'A1',\n * 'A2',\n * 'A3',\n * 'B1',\n * 'B2',\n * 'C1',\n * 'C2',\n * 'C3',\n * ]);\n * ```\n *\n * @note To improve code readability, consider using `createState` instead of `switchMap`,\n * subscribe to `parentObservable` and call `setState` within it.\n */\nexport const switchMap =\n <A, B>(\n mapToObservable: (curr: A) => Observable<B>,\n ): DropInitialValueOperator<A, B> =>\n (parentObservable) =>\n new SwitchMapObservableClass(parentObservable, mapToObservable);\n\nclass SwitchMapObservableClass<A, B>\n extends AsyncChildObservableClass<B, readonly [A]>\n implements SwitchMapOperatorObservable<A, B>\n{\n readonly #mapToObservable: (curr: A) => Observable<B>;\n #mut_observable: Observable<B> | undefined;\n #mut_subscription: Subscription | undefined;\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_observable = undefined;\n\n this.#mut_subscription = undefined;\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_observable?.complete();\n\n this.#mut_subscription?.unsubscribe();\n\n const observable = this.#mapToObservable(sn.value);\n\n this.#mut_observable = observable;\n\n const subscription = observable.subscribe((curr) => {\n this.startUpdate(curr);\n });\n\n this.#mut_subscription = subscription;\n }\n\n override complete(): void {\n this.#mut_subscription?.unsubscribe();\n\n this.#mut_observable?.complete();\n\n super.complete();\n }\n}\n"],"names":[],"mappings":";;;;AAuGO,MAAM,SAAA,GACX,CACE,eAAA,KAEF,CAAC,qBACC,IAAI,wBAAA,CAAyB,kBAAkB,eAAe;AAElE,MAAM,iCACI,yBAAA,CAEV;AAAA,EACW,gBAAA;AAAA,EACT,eAAA;AAAA,EACA,iBAAA;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,eAAA,GAAkB,MAAA;AAEvB,IAAA,IAAA,CAAK,iBAAA,GAAoB,MAAA;AAAA,EAC3B;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,IAAA,CAAK,iBAAiB,QAAA,EAAS;AAE/B,IAAA,IAAA,CAAK,mBAAmB,WAAA,EAAY;AAEpC,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,gBAAA,CAAiB,EAAA,CAAG,KAAK,CAAA;AAEjD,IAAA,IAAA,CAAK,eAAA,GAAkB,UAAA;AAEvB,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,iBAAA,GAAoB,YAAA;AAAA,EAC3B;AAAA,EAES,QAAA,GAAiB;AACxB,IAAA,IAAA,CAAK,mBAAmB,WAAA,EAAY;AAEpC,IAAA,IAAA,CAAK,iBAAiB,QAAA,EAAS;AAE/B,IAAA,KAAA,CAAM,QAAA,EAAS;AAAA,EACjB;AACF;;;;"}
1
+ {"version":3,"file":"switch-map.mjs","sources":["../../../src/core/operators/switch-map.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { createAsyncChildObservable } from '../base/index.mjs';\nimport {\n type DropInitialValueOperator,\n type Observable,\n type Subscription,\n type SwitchMapOperatorObservable,\n} from '../types/index.mjs';\n\n/**\n * Projects each source value to an observable, subscribes to it, and emits its values.\n * When a new value arrives from the source, the previous inner observable is unsubscribed.\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 switches to new 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 (switched!)\n * // inner C C1 C2 C3\n * // result$ A1 A2 A3 B1 B2 C1 C2 C3\n * //\n * // Explanation:\n * // - switchMap creates an inner observable for each source value\n * // - When a new source value arrives, the previous inner is unsubscribed\n * // - A's inner completes normally (all 3 values emitted)\n * // - B's inner is interrupted by C (only 2 values emitted)\n * // - C's inner completes normally (all 3 values emitted)\n *\n * const input$ = source<string>();\n *\n * const result$ = input$.pipe(\n * switchMap((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 - switches away from B (B3 cancelled), C's inner starts\n * input$.next('C');\n *\n * await sleep(250);\n *\n * assert.deepStrictEqual(valueHistory, [\n * 'A1',\n * 'A2',\n * 'A3',\n * 'B1',\n * 'B2',\n * 'C1',\n * 'C2',\n * 'C3',\n * ]);\n * ```\n *\n * @note To improve code readability, consider using `createState` instead of `switchMap`,\n * subscribe to `parentObservable` and call `setState` within it.\n */\nexport const switchMap =\n <A, B>(\n mapToObservable: (curr: A) => Observable<B>,\n ): DropInitialValueOperator<A, B> =>\n (parentObservable) =>\n createSwitchMapObservable(parentObservable, mapToObservable);\n\nconst createSwitchMapObservable = <A, B>(\n parentObservable: Observable<A>,\n mapToObservable: (curr: A) => Observable<B>,\n): SwitchMapOperatorObservable<A, B> => {\n let mut_observable: Observable<B> | undefined = undefined;\n\n let mut_subscription: Subscription | undefined = undefined;\n\n return createAsyncChildObservable(\n {\n parents: [parentObservable],\n initialValue: Optional.none,\n onComplete: () => {\n mut_subscription?.unsubscribe();\n\n mut_observable?.complete();\n },\n },\n ({ startUpdate }) =>\n (updateToken) => {\n const sn = parentObservable.getSnapshot();\n\n if (\n parentObservable.updateToken !== updateToken ||\n Optional.isNone(sn)\n ) {\n return; // skip update\n }\n\n mut_observable?.complete();\n\n mut_subscription?.unsubscribe();\n\n const observable = mapToObservable(sn.value);\n\n mut_observable = observable;\n\n const subscription = observable.subscribe((curr) => {\n startUpdate(curr);\n });\n\n mut_subscription = subscription;\n },\n );\n};\n"],"names":[],"mappings":";;;;AAsGO,MAAM,YACX,CACE,eAAA,KAEF,CAAC,gBAAA,KACC,yBAAA,CAA0B,kBAAkB,eAAe;AAE/D,MAAM,yBAAA,GAA4B,CAChC,gBAAA,EACA,eAAA,KACsC;AACtC,EAAA,IAAI,cAAA,GAA4C,MAAA;AAEhD,EAAA,IAAI,gBAAA,GAA6C,MAAA;AAEjD,EAAA,OAAO,0BAAA;AAAA,IACL;AAAA,MACE,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,cAAc,QAAA,CAAS,IAAA;AAAA,MACvB,YAAY,MAAM;AAChB,QAAA,gBAAA,EAAkB,WAAA,EAAY;AAE9B,QAAA,cAAA,EAAgB,QAAA,EAAS;AAAA,MAC3B;AAAA,KACF;AAAA,IACA,CAAC,EAAE,WAAA,EAAY,KACb,CAAC,WAAA,KAAgB;AACf,MAAA,MAAM,EAAA,GAAK,iBAAiB,WAAA,EAAY;AAExC,MAAA,IACE,iBAAiB,WAAA,KAAgB,WAAA,IACjC,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAClB;AACA,QAAA;AAAA,MACF;AAEA,MAAA,cAAA,EAAgB,QAAA,EAAS;AAEzB,MAAA,gBAAA,EAAkB,WAAA,EAAY;AAE9B,MAAA,MAAM,UAAA,GAAa,eAAA,CAAgB,EAAA,CAAG,KAAK,CAAA;AAE3C,MAAA,cAAA,GAAiB,UAAA;AAEjB,MAAA,MAAM,YAAA,GAAe,UAAA,CAAW,SAAA,CAAU,CAAC,IAAA,KAAS;AAClD,QAAA,WAAA,CAAY,IAAI,CAAA;AAAA,MAClB,CAAC,CAAA;AAED,MAAA,gBAAA,GAAmB,YAAA;AAAA,IACrB;AAAA,GACJ;AACF,CAAA;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"take-until.d.mts","sourceRoot":"","sources":["../../../src/core/operators/take-until.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,UAAU,EAGhB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,YACf,UAAU,CAAC,OAAO,CAAC,KAC5B,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAMQ,CAAC"}
1
+ {"version":3,"file":"take-until.d.mts","sourceRoot":"","sources":["../../../src/core/operators/take-until.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,YACf,UAAU,CAAC,OAAO,CAAC,KAC5B,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAMQ,CAAC"}
@@ -1,38 +1,38 @@
1
1
  import { Optional } from 'ts-data-forge';
2
- import { SyncChildObservableClass } from '../class/child-observable-class.mjs';
2
+ import { createSyncChildObservable } from '../base/create-child-observable.mjs';
3
3
  import '../utils/id-maker.mjs';
4
4
 
5
5
  const takeUntil = (notifier) => (
6
6
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
7
- ((parentObservable) => new TakeUntilObservableClass(
7
+ ((parentObservable) => createTakeUntilObservable(
8
8
  parentObservable,
9
9
  notifier
10
10
  ))
11
11
  );
12
- class TakeUntilObservableClass extends SyncChildObservableClass {
13
- constructor(parentObservable, notifier) {
14
- super({
12
+ const createTakeUntilObservable = (parentObservable, notifier) => {
13
+ const observable = createSyncChildObservable(
14
+ {
15
15
  parents: [parentObservable],
16
16
  initialValue: parentObservable.getSnapshot()
17
- });
18
- notifier.subscribe(
19
- () => {
20
- this.complete();
21
- },
22
- () => {
23
- this.complete();
17
+ },
18
+ ({ setNext }) => (updateToken) => {
19
+ const sn = parentObservable.getSnapshot();
20
+ if (parentObservable.updateToken !== updateToken || Optional.isNone(sn)) {
21
+ return;
24
22
  }
25
- );
26
- }
27
- tryUpdate(updateToken) {
28
- const par = this.parents[0];
29
- const sn = par.getSnapshot();
30
- if (par.updateToken !== updateToken || Optional.isNone(sn)) {
31
- return;
23
+ setNext(sn.value, updateToken);
32
24
  }
33
- this.setNext(sn.value, updateToken);
34
- }
35
- }
25
+ );
26
+ notifier.subscribe(
27
+ () => {
28
+ observable.complete();
29
+ },
30
+ () => {
31
+ observable.complete();
32
+ }
33
+ );
34
+ return observable;
35
+ };
36
36
 
37
37
  export { takeUntil };
38
38
  //# sourceMappingURL=take-until.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"take-until.mjs","sources":["../../../src/core/operators/take-until.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { SyncChildObservableClass } from '../class/index.mjs';\nimport {\n type KeepInitialValueOperator,\n type Observable,\n type TakeUntilOperatorObservable,\n type UpdateToken,\n} from '../types/index.mjs';\n\n/**\n * Emits values from the source until the notifier observable emits.\n * When the notifier emits, this observable completes.\n *\n * @template A - The type of values from the source\n * @param notifier - An observable that signals when to complete\n * @returns An operator that takes values until notifier emits\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ 1 2 stop 3 (ignored)\n * // stopNotifier X\n * // limited$ 1 2 |------- (completed)\n * //\n * // Explanation:\n * // - takeUntil completes the observable when the notifier emits\n * // - After stop() is called, no further values are emitted\n * // - Useful for cleanup and cancellation patterns\n *\n * const num$ = source<number>();\n *\n * const [stopNotifier, stop_] = createEventEmitter();\n *\n * const limited$ = num$.pipe(takeUntil(stopNotifier));\n *\n * const valueHistory: number[] = [];\n *\n * limited$.subscribe((x) => {\n * valueHistory.push(x);\n * });\n *\n * num$.next(1); // logs: 1\n *\n * assert.deepStrictEqual(valueHistory, [1]);\n *\n * num$.next(2); // logs: 2\n *\n * assert.deepStrictEqual(valueHistory, [1, 2]);\n *\n * stop_();\n *\n * num$.next(3); // nothing logged (completed)\n *\n * assert.deepStrictEqual(valueHistory, [1, 2]);\n * ```\n */\nexport const takeUntil = <A,>(\n notifier: Observable<unknown>,\n): KeepInitialValueOperator<A, A> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n new TakeUntilObservableClass(\n parentObservable,\n notifier,\n )) as KeepInitialValueOperator<A, A>;\n\nclass TakeUntilObservableClass<A>\n extends SyncChildObservableClass<A, readonly [A]>\n implements TakeUntilOperatorObservable<A>\n{\n constructor(parentObservable: Observable<A>, notifier: Observable<unknown>) {\n super({\n parents: [parentObservable],\n initialValue: parentObservable.getSnapshot(),\n });\n\n notifier.subscribe(\n () => {\n this.complete();\n },\n () => {\n this.complete();\n },\n );\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.setNext(sn.value, updateToken);\n }\n}\n"],"names":[],"mappings":";;;;AAyDO,MAAM,YAAY,CACvB,QAAA;AAAA;AAAA,GAGC,CAAC,qBACA,IAAI,wBAAA;AAAA,IACF,gBAAA;AAAA,IACA;AAAA,GACF;AAAA;AAEJ,MAAM,iCACI,wBAAA,CAEV;AAAA,EACE,WAAA,CAAY,kBAAiC,QAAA,EAA+B;AAC1E,IAAA,KAAA,CAAM;AAAA,MACJ,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,YAAA,EAAc,iBAAiB,WAAA;AAAY,KAC5C,CAAA;AAED,IAAA,QAAA,CAAS,SAAA;AAAA,MACP,MAAM;AACJ,QAAA,IAAA,CAAK,QAAA,EAAS;AAAA,MAChB,CAAA;AAAA,MACA,MAAM;AACJ,QAAA,IAAA,CAAK,QAAA,EAAS;AAAA,MAChB;AAAA,KACF;AAAA,EACF;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,IAAA,CAAK,OAAA,CAAQ,EAAA,CAAG,KAAA,EAAO,WAAW,CAAA;AAAA,EACpC;AACF;;;;"}
1
+ {"version":3,"file":"take-until.mjs","sources":["../../../src/core/operators/take-until.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { createSyncChildObservable } from '../base/index.mjs';\nimport {\n type KeepInitialValueOperator,\n type Observable,\n type TakeUntilOperatorObservable,\n} from '../types/index.mjs';\n\n/**\n * Emits values from the source until the notifier observable emits.\n * When the notifier emits, this observable completes.\n *\n * @template A - The type of values from the source\n * @param notifier - An observable that signals when to complete\n * @returns An operator that takes values until notifier emits\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ 1 2 stop 3 (ignored)\n * // stopNotifier X\n * // limited$ 1 2 |------- (completed)\n * //\n * // Explanation:\n * // - takeUntil completes the observable when the notifier emits\n * // - After stop() is called, no further values are emitted\n * // - Useful for cleanup and cancellation patterns\n *\n * const num$ = source<number>();\n *\n * const [stopNotifier, stop_] = createEventEmitter();\n *\n * const limited$ = num$.pipe(takeUntil(stopNotifier));\n *\n * const valueHistory: number[] = [];\n *\n * limited$.subscribe((x) => {\n * valueHistory.push(x);\n * });\n *\n * num$.next(1); // logs: 1\n *\n * assert.deepStrictEqual(valueHistory, [1]);\n *\n * num$.next(2); // logs: 2\n *\n * assert.deepStrictEqual(valueHistory, [1, 2]);\n *\n * stop_();\n *\n * num$.next(3); // nothing logged (completed)\n *\n * assert.deepStrictEqual(valueHistory, [1, 2]);\n * ```\n */\nexport const takeUntil = <A,>(\n notifier: Observable<unknown>,\n): KeepInitialValueOperator<A, A> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n createTakeUntilObservable(\n parentObservable,\n notifier,\n )) as KeepInitialValueOperator<A, A>;\n\nconst createTakeUntilObservable = <A,>(\n parentObservable: Observable<A>,\n notifier: Observable<unknown>,\n): TakeUntilOperatorObservable<A> => {\n const observable = createSyncChildObservable<A, readonly [A]>(\n {\n parents: [parentObservable],\n initialValue: parentObservable.getSnapshot(),\n },\n ({ setNext }) =>\n (updateToken) => {\n const sn = parentObservable.getSnapshot();\n\n if (\n parentObservable.updateToken !== updateToken ||\n Optional.isNone(sn)\n ) {\n return; // skip update\n }\n\n setNext(sn.value, updateToken);\n },\n );\n\n notifier.subscribe(\n () => {\n observable.complete();\n },\n () => {\n observable.complete();\n },\n );\n\n return observable;\n};\n"],"names":[],"mappings":";;;;AAwDO,MAAM,YAAY,CACvB,QAAA;AAAA;AAAA,GAGC,CAAC,gBAAA,KACA,yBAAA;AAAA,IACE,gBAAA;AAAA,IACA;AAAA,GACF;AAAA;AAEJ,MAAM,yBAAA,GAA4B,CAChC,gBAAA,EACA,QAAA,KACmC;AACnC,EAAA,MAAM,UAAA,GAAa,yBAAA;AAAA,IACjB;AAAA,MACE,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,YAAA,EAAc,iBAAiB,WAAA;AAAY,KAC7C;AAAA,IACA,CAAC,EAAE,OAAA,EAAQ,KACT,CAAC,WAAA,KAAgB;AACf,MAAA,MAAM,EAAA,GAAK,iBAAiB,WAAA,EAAY;AAExC,MAAA,IACE,iBAAiB,WAAA,KAAgB,WAAA,IACjC,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAClB;AACA,QAAA;AAAA,MACF;AAEA,MAAA,OAAA,CAAQ,EAAA,CAAG,OAAO,WAAW,CAAA;AAAA,IAC/B;AAAA,GACJ;AAEA,EAAA,QAAA,CAAS,SAAA;AAAA,IACP,MAAM;AACJ,MAAA,UAAA,CAAW,QAAA,EAAS;AAAA,IACtB,CAAA;AAAA,IACA,MAAM;AACJ,MAAA,UAAA,CAAW,QAAA,EAAS;AAAA,IACtB;AAAA,GACF;AAEA,EAAA,OAAO,UAAA;AACT,CAAA;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"take-while.d.mts","sourceRoot":"","sources":["../../../src/core/operators/take-while.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAIT,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,KAAK,wBAAwB,EAK9B,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,eAAO,MAAM,SAAS,GACnB,CAAC,aACW,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,OAAO,KACrD,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAE2B,CAAC"}
1
+ {"version":3,"file":"take-while.d.mts","sourceRoot":"","sources":["../../../src/core/operators/take-while.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAIT,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,eAAO,MAAM,SAAS,GACnB,CAAC,aACW,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,OAAO,KACrD,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAEwB,CAAC"}
@@ -1,35 +1,31 @@
1
- import { pipe, Optional, asSafeUint, SafeUint } from 'ts-data-forge';
2
- import { SyncChildObservableClass } from '../class/child-observable-class.mjs';
1
+ import { Optional, asSafeUint, SafeUint, pipe } from 'ts-data-forge';
2
+ import { createSyncChildObservable } from '../base/create-child-observable.mjs';
3
3
  import '../utils/id-maker.mjs';
4
4
 
5
- const takeWhile = (predicate) => (parentObservable) => new TakeWhileObservableClass(parentObservable, predicate);
6
- class TakeWhileObservableClass extends SyncChildObservableClass {
7
- #predicate;
8
- #mut_index;
9
- constructor(parentObservable, predicate) {
10
- super({
11
- parents: [parentObservable],
12
- initialValue: pipe(parentObservable.getSnapshot()).map(
13
- (par) => Optional.isNone(par) ? Optional.none : predicate(par.value, -1) ? par : Optional.none
14
- ).value
15
- });
16
- this.#mut_index = -1;
17
- this.#predicate = predicate;
5
+ const takeWhile = (predicate) => (parentObservable) => createTakeWhileObservable(parentObservable, predicate);
6
+ const createTakeWhileObservable = (parentObservable, predicate) => createSyncChildObservable(
7
+ {
8
+ parents: [parentObservable],
9
+ initialValue: pipe(parentObservable.getSnapshot()).map(
10
+ (par) => Optional.isNone(par) ? Optional.none : predicate(par.value, -1) ? par : Optional.none
11
+ ).value
12
+ },
13
+ ({ setNext, complete }) => {
14
+ let mut_index = -1;
15
+ return (updateToken) => {
16
+ const sn = parentObservable.getSnapshot();
17
+ if (parentObservable.updateToken !== updateToken || Optional.isNone(sn)) {
18
+ return;
19
+ }
20
+ mut_index = mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, mut_index);
21
+ if (predicate(sn.value, mut_index)) {
22
+ setNext(sn.value, updateToken);
23
+ } else {
24
+ complete();
25
+ }
26
+ };
18
27
  }
19
- tryUpdate(updateToken) {
20
- const par = this.parents[0];
21
- const sn = par.getSnapshot();
22
- if (par.updateToken !== updateToken || Optional.isNone(sn)) {
23
- return;
24
- }
25
- this.#mut_index = this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
26
- if (this.#predicate(sn.value, this.#mut_index)) {
27
- this.setNext(sn.value, updateToken);
28
- } else {
29
- this.complete();
30
- }
31
- }
32
- }
28
+ );
33
29
 
34
30
  export { takeWhile };
35
31
  //# sourceMappingURL=take-while.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"take-while.mjs","sources":["../../../src/core/operators/take-while.mts"],"sourcesContent":["import {\n Optional,\n SafeUint,\n asSafeUint,\n expectType,\n pipe,\n} from 'ts-data-forge';\nimport { SyncChildObservableClass } from '../class/index.mjs';\nimport { source } from '../create/index.mjs';\nimport {\n type DropInitialValueOperator,\n type InitializedObservable,\n type Observable,\n type TakeWhileOperatorObservable,\n type UpdateToken,\n} from '../types/index.mjs';\nimport { withInitialValue } from './with-initial-value.mjs';\n\n/**\n * Emits values from the source observable while the predicate returns true.\n * Completes immediately when the predicate returns false.\n *\n * @template A - The type of values from the source\n * @param predicate - Function to test each value\n * @returns An operator that takes values while the predicate is true\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ 1 2 3 4 5 6 1 2 (ignored)\n * // taken$ 1 2 3 4 | (completes)\n * //\n * // Explanation:\n * // - takeWhile emits values while the predicate returns true\n * // - Completes immediately when the predicate returns false\n * // - No further values are emitted after completion\n *\n * const num$ = source<number>();\n *\n * const taken$ = num$.pipe(takeWhile((x) => x < 5));\n *\n * const valueHistory: number[] = [];\n *\n * taken$.subscribe((x) => {\n * valueHistory.push(x);\n * });\n *\n * num$.next(1); // logs: 1\n *\n * assert.deepStrictEqual(valueHistory, [1]);\n *\n * num$.next(2); // logs: 2\n *\n * num$.next(3); // logs: 3\n *\n * num$.next(4); // logs: 4\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);\n *\n * num$.next(5); // nothing logged (completes)\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);\n *\n * num$.next(6); // nothing logged (already completed)\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);\n *\n * num$.next(1); // logs: 1\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);\n * ```\n */\nexport const takeWhile =\n <A,>(\n predicate: (value: A, index: SafeUint | -1) => boolean,\n ): DropInitialValueOperator<A, A> =>\n (parentObservable) =>\n new TakeWhileObservableClass(parentObservable, predicate);\n\n/* implementation */\n\nclass TakeWhileObservableClass<A>\n extends SyncChildObservableClass<A, readonly [A]>\n implements TakeWhileOperatorObservable<A>\n{\n readonly #predicate: (value: A, index: SafeUint | -1) => boolean;\n #mut_index: SafeUint | -1;\n\n constructor(\n parentObservable: Observable<A>,\n predicate: (value: A, index: SafeUint | -1) => boolean,\n ) {\n super({\n parents: [parentObservable],\n initialValue: pipe(parentObservable.getSnapshot()).map((par) =>\n Optional.isNone(par)\n ? Optional.none\n : predicate(par.value, -1)\n ? par\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 } else {\n this.complete();\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(takeWhile((_, index) => index + 1 <= 3));\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(takeWhile((_, index) => index + 1 <= 3));\n\n expectType<typeof _d, Observable<number>>('=');\n }\n}\n"],"names":[],"mappings":";;;;AAyEO,MAAM,SAAA,GACX,CACE,SAAA,KAEF,CAAC,qBACC,IAAI,wBAAA,CAAyB,kBAAkB,SAAS;AAI5D,MAAM,iCACI,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,GAAA,KACtD,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,GACf,QAAA,CAAS,IAAA,GACT,SAAA,CAAU,GAAA,CAAI,KAAA,EAAO,EAAE,CAAA,GACrB,MACA,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,CACpC,MAAO;AACL,MAAA,IAAA,CAAK,QAAA,EAAS;AAAA,IAAA;AAChB,EAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"take-while.mjs","sources":["../../../src/core/operators/take-while.mts"],"sourcesContent":["import {\n Optional,\n SafeUint,\n asSafeUint,\n expectType,\n pipe,\n} from 'ts-data-forge';\nimport { createSyncChildObservable } from '../base/index.mjs';\nimport { source } from '../create/index.mjs';\nimport {\n type DropInitialValueOperator,\n type InitializedObservable,\n type Observable,\n type TakeWhileOperatorObservable,\n} from '../types/index.mjs';\nimport { withInitialValue } from './with-initial-value.mjs';\n\n/**\n * Emits values from the source observable while the predicate returns true.\n * Completes immediately when the predicate returns false.\n *\n * @template A - The type of values from the source\n * @param predicate - Function to test each value\n * @returns An operator that takes values while the predicate is true\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ 1 2 3 4 5 6 1 2 (ignored)\n * // taken$ 1 2 3 4 | (completes)\n * //\n * // Explanation:\n * // - takeWhile emits values while the predicate returns true\n * // - Completes immediately when the predicate returns false\n * // - No further values are emitted after completion\n *\n * const num$ = source<number>();\n *\n * const taken$ = num$.pipe(takeWhile((x) => x < 5));\n *\n * const valueHistory: number[] = [];\n *\n * taken$.subscribe((x) => {\n * valueHistory.push(x);\n * });\n *\n * num$.next(1); // logs: 1\n *\n * assert.deepStrictEqual(valueHistory, [1]);\n *\n * num$.next(2); // logs: 2\n *\n * num$.next(3); // logs: 3\n *\n * num$.next(4); // logs: 4\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);\n *\n * num$.next(5); // nothing logged (completes)\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);\n *\n * num$.next(6); // nothing logged (already completed)\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);\n *\n * num$.next(1); // logs: 1\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);\n * ```\n */\nexport const takeWhile =\n <A,>(\n predicate: (value: A, index: SafeUint | -1) => boolean,\n ): DropInitialValueOperator<A, A> =>\n (parentObservable) =>\n createTakeWhileObservable(parentObservable, predicate);\n\n/* implementation */\n\nconst createTakeWhileObservable = <A,>(\n parentObservable: Observable<A>,\n predicate: (value: A, index: SafeUint | -1) => boolean,\n): TakeWhileOperatorObservable<A> =>\n createSyncChildObservable(\n {\n parents: [parentObservable],\n initialValue: pipe(parentObservable.getSnapshot()).map((par) =>\n Optional.isNone(par)\n ? Optional.none\n : predicate(par.value, -1)\n ? par\n : Optional.none,\n ).value,\n },\n ({ setNext, complete }) => {\n let mut_index: SafeUint | -1 = -1;\n\n return (updateToken) => {\n const sn = parentObservable.getSnapshot();\n\n if (\n parentObservable.updateToken !== updateToken ||\n Optional.isNone(sn)\n ) {\n return; // skip update\n }\n\n mut_index =\n mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, mut_index);\n\n if (predicate(sn.value, mut_index)) {\n setNext(sn.value, updateToken);\n } else {\n complete();\n }\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(takeWhile((_, index) => index + 1 <= 3));\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(takeWhile((_, index) => index + 1 <= 3));\n\n expectType<typeof _d, Observable<number>>('=');\n }\n}\n"],"names":[],"mappings":";;;;AAwEO,MAAM,YACX,CACE,SAAA,KAEF,CAAC,gBAAA,KACC,yBAAA,CAA0B,kBAAkB,SAAS;AAIzD,MAAM,yBAAA,GAA4B,CAChC,gBAAA,EACA,SAAA,KAEA,yBAAA;AAAA,EACE;AAAA,IACE,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,IAC1B,YAAA,EAAc,IAAA,CAAK,gBAAA,CAAiB,WAAA,EAAa,CAAA,CAAE,GAAA;AAAA,MAAI,CAAC,GAAA,KACtD,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,GACf,QAAA,CAAS,IAAA,GACT,SAAA,CAAU,GAAA,CAAI,KAAA,EAAO,EAAE,CAAA,GACrB,MACA,QAAA,CAAS;AAAA,KACjB,CAAE;AAAA,GACJ;AAAA,EACA,CAAC,EAAE,OAAA,EAAS,QAAA,EAAS,KAAM;AACzB,IAAA,IAAI,SAAA,GAA2B,EAAA;AAE/B,IAAA,OAAO,CAAC,WAAA,KAAgB;AACtB,MAAA,MAAM,EAAA,GAAK,iBAAiB,WAAA,EAAY;AAExC,MAAA,IACE,iBAAiB,WAAA,KAAgB,WAAA,IACjC,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAClB;AACA,QAAA;AAAA,MAAA;AAGF,MAAA,SAAA,GACE,SAAA,KAAc,KAAK,UAAA,CAAW,CAAC,IAAI,QAAA,CAAS,GAAA,CAAI,GAAG,SAAS,CAAA;AAE9D,MAAA,IAAI,SAAA,CAAU,EAAA,CAAG,KAAA,EAAO,SAAS,CAAA,EAAG;AAClC,QAAA,OAAA,CAAQ,EAAA,CAAG,OAAO,WAAW,CAAA;AAAA,MAAA,CAC/B,MAAO;AACL,QAAA,QAAA,EAAS;AAAA,MAAA;AACX,IAAA,CACF;AAAA,EAAA;AAEJ,CAAA;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"throttle.d.mts","sourceRoot":"","sources":["../../../src/core/operators/throttle.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAK9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,gBACV,MAAM,KACnB,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAMQ,CAAC"}
1
+ {"version":3,"file":"throttle.d.mts","sourceRoot":"","sources":["../../../src/core/operators/throttle.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,gBACV,MAAM,KACnB,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAMQ,CAAC"}
@@ -1,49 +1,41 @@
1
1
  import { Optional } from 'ts-data-forge';
2
- import { SyncChildObservableClass } from '../class/child-observable-class.mjs';
2
+ import { createSyncChildObservable } from '../base/create-child-observable.mjs';
3
3
  import '../utils/id-maker.mjs';
4
4
 
5
5
  const throttle = (milliSeconds) => (
6
6
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
7
- ((parentObservable) => new ThrottleObservableClass(
7
+ ((parentObservable) => createThrottleObservable(
8
8
  parentObservable,
9
9
  milliSeconds
10
10
  ))
11
11
  );
12
- class ThrottleObservableClass extends SyncChildObservableClass {
13
- #milliSeconds;
14
- #mut_timerId;
15
- #mut_isSkipping;
16
- constructor(parentObservable, milliSeconds) {
17
- super({
18
- parents: [parentObservable],
19
- initialValue: parentObservable.getSnapshot()
20
- });
21
- this.#mut_timerId = void 0;
22
- this.#mut_isSkipping = false;
23
- this.#milliSeconds = milliSeconds;
24
- }
25
- #resetTimer() {
26
- if (this.#mut_timerId !== void 0) {
27
- clearTimeout(this.#mut_timerId);
12
+ const createThrottleObservable = (parentObservable, milliSeconds) => {
13
+ let mut_timerId = void 0;
14
+ let mut_isSkipping = false;
15
+ const resetTimer = () => {
16
+ if (mut_timerId !== void 0) {
17
+ clearTimeout(mut_timerId);
28
18
  }
29
- }
30
- tryUpdate(updateToken) {
31
- const par = this.parents[0];
32
- const sn = par.getSnapshot();
33
- if (par.updateToken !== updateToken || Optional.isNone(sn) || this.#mut_isSkipping) {
34
- return;
19
+ };
20
+ return createSyncChildObservable(
21
+ {
22
+ parents: [parentObservable],
23
+ initialValue: parentObservable.getSnapshot(),
24
+ onComplete: resetTimer
25
+ },
26
+ ({ setNext }) => (updateToken) => {
27
+ const sn = parentObservable.getSnapshot();
28
+ if (mut_isSkipping || parentObservable.updateToken !== updateToken || Optional.isNone(sn)) {
29
+ return;
30
+ }
31
+ setNext(sn.value, updateToken);
32
+ mut_isSkipping = true;
33
+ mut_timerId = setTimeout(() => {
34
+ mut_isSkipping = false;
35
+ }, milliSeconds);
35
36
  }
36
- this.setNext(sn.value, updateToken);
37
- this.#mut_isSkipping = true;
38
- this.#mut_timerId = setTimeout(() => {
39
- this.#mut_isSkipping = false;
40
- }, this.#milliSeconds);
41
- }
42
- complete() {
43
- this.#resetTimer();
44
- super.complete();
45
- }
46
- }
37
+ );
38
+ };
47
39
 
48
40
  export { throttle };
49
41
  //# sourceMappingURL=throttle.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"throttle.mjs","sources":["../../../src/core/operators/throttle.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { SyncChildObservableClass } from '../class/index.mjs';\nimport {\n type KeepInitialValueOperator,\n type Observable,\n type ThrottleOperatorObservable,\n type TimerId,\n type UpdateToken,\n} from '../types/index.mjs';\n\n/**\n * Emits the first value, then ignores subsequent values for a specified duration.\n * After the duration, the next emission is allowed through.\n *\n * @template A - The type of values from the source\n * @param milliSeconds - The throttle duration in milliseconds\n * @returns An operator that throttles emissions\n *\n * @example\n * ```ts\n * // Timeline (250ms throttle):\n * //\n * // Time(x50ms) 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0\n * //\n * // input$ 0 2 3 9 10 11 12 13 14\n * // |- 250ms -> |- 250ms -> |- 250ms -> |- 250ms ->\n * // throttled$ 0 3 9 12 (emitted at start of window)\n * //\n * // Explanation:\n * // - throttle emits the FIRST value received, then ignores subsequent values\n * // for the specified duration (250ms)\n * // - Unlike audit (which emits the LAST value), throttle emits the FIRST\n * // - Useful for rate-limiting scroll/resize events\n *\n * const input$ = source<number>();\n *\n * const throttled$ = input$.pipe(throttle(250));\n *\n * const valueHistory: number[] = [];\n *\n * throttled$.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 * input$.next(0);\n *\n * assert.deepStrictEqual(valueHistory, [0]);\n *\n * await sleep(200);\n *\n * input$.next(2);\n *\n * assert.deepStrictEqual(valueHistory, [0]);\n *\n * await sleep(100);\n *\n * input$.next(3);\n *\n * assert.deepStrictEqual(valueHistory, [0, 3]);\n *\n * await sleep(300);\n *\n * input$.next(9);\n *\n * assert.deepStrictEqual(valueHistory, [0, 3, 9]);\n *\n * await sleep(100);\n *\n * input$.next(10);\n *\n * await sleep(100);\n *\n * input$.next(11);\n *\n * assert.deepStrictEqual(valueHistory, [0, 3, 9]);\n *\n * await sleep(100);\n *\n * input$.next(12);\n *\n * assert.deepStrictEqual(valueHistory, [0, 3, 9, 12]);\n * ```\n */\nexport const throttle = <A,>(\n milliSeconds: number,\n): KeepInitialValueOperator<A, A> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n new ThrottleObservableClass(\n parentObservable,\n milliSeconds,\n )) as KeepInitialValueOperator<A, A>;\n\nclass ThrottleObservableClass<A>\n extends SyncChildObservableClass<A, readonly [A]>\n implements ThrottleOperatorObservable<A>\n{\n readonly #milliSeconds: number;\n #mut_timerId: TimerId | undefined;\n #mut_isSkipping: boolean;\n\n constructor(parentObservable: Observable<A>, milliSeconds: number) {\n super({\n parents: [parentObservable],\n initialValue: parentObservable.getSnapshot(),\n });\n\n this.#mut_timerId = undefined;\n\n this.#mut_isSkipping = false;\n\n this.#milliSeconds = milliSeconds;\n }\n\n #resetTimer(): void {\n if (this.#mut_timerId !== undefined) {\n clearTimeout(this.#mut_timerId);\n }\n }\n\n override tryUpdate(updateToken: UpdateToken): void {\n const par = this.parents[0];\n\n const sn = par.getSnapshot();\n\n if (\n par.updateToken !== updateToken ||\n Optional.isNone(sn) ||\n this.#mut_isSkipping\n ) {\n return; // skip update\n }\n\n this.setNext(sn.value, updateToken);\n\n this.#mut_isSkipping = true;\n\n // set timer\n this.#mut_timerId = setTimeout(() => {\n this.#mut_isSkipping = false;\n }, this.#milliSeconds);\n }\n\n override complete(): void {\n this.#resetTimer();\n\n super.complete();\n }\n}\n"],"names":[],"mappings":";;;;AAwFO,MAAM,WAAW,CACtB,YAAA;AAAA;AAAA,GAGC,CAAC,qBACA,IAAI,uBAAA;AAAA,IACF,gBAAA;AAAA,IACA;AAAA,GACF;AAAA;AAEJ,MAAM,gCACI,wBAAA,CAEV;AAAA,EACW,aAAA;AAAA,EACT,YAAA;AAAA,EACA,eAAA;AAAA,EAEA,WAAA,CAAY,kBAAiC,YAAA,EAAsB;AACjE,IAAA,KAAA,CAAM;AAAA,MACJ,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,YAAA,EAAc,iBAAiB,WAAA;AAAY,KAC5C,CAAA;AAED,IAAA,IAAA,CAAK,YAAA,GAAe,MAAA;AAEpB,IAAA,IAAA,CAAK,eAAA,GAAkB,KAAA;AAEvB,IAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AAAA,EACvB;AAAA,EAEA,WAAA,GAAoB;AAClB,IAAA,IAAI,IAAA,CAAK,iBAAiB,MAAA,EAAW;AACnC,MAAA,YAAA,CAAa,KAAK,YAAY,CAAA;AAAA,IAChC;AAAA,EACF;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,IACE,GAAA,CAAI,gBAAgB,WAAA,IACpB,QAAA,CAAS,OAAO,EAAE,CAAA,IAClB,KAAK,eAAA,EACL;AACA,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,OAAA,CAAQ,EAAA,CAAG,KAAA,EAAO,WAAW,CAAA;AAElC,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAGvB,IAAA,IAAA,CAAK,YAAA,GAAe,WAAW,MAAM;AACnC,MAAA,IAAA,CAAK,eAAA,GAAkB,KAAA;AAAA,IACzB,CAAA,EAAG,KAAK,aAAa,CAAA;AAAA,EACvB;AAAA,EAES,QAAA,GAAiB;AACxB,IAAA,IAAA,CAAK,WAAA,EAAY;AAEjB,IAAA,KAAA,CAAM,QAAA,EAAS;AAAA,EACjB;AACF;;;;"}
1
+ {"version":3,"file":"throttle.mjs","sources":["../../../src/core/operators/throttle.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { createSyncChildObservable } from '../base/index.mjs';\nimport {\n type KeepInitialValueOperator,\n type Observable,\n type ThrottleOperatorObservable,\n type TimerId,\n} from '../types/index.mjs';\n\n/**\n * Emits the first value, then ignores subsequent values for a specified duration.\n * After the duration, the next emission is allowed through.\n *\n * @template A - The type of values from the source\n * @param milliSeconds - The throttle duration in milliseconds\n * @returns An operator that throttles emissions\n *\n * @example\n * ```ts\n * // Timeline (250ms throttle):\n * //\n * // Time(x50ms) 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0\n * //\n * // input$ 0 2 3 9 10 11 12 13 14\n * // |- 250ms -> |- 250ms -> |- 250ms -> |- 250ms ->\n * // throttled$ 0 3 9 12 (emitted at start of window)\n * //\n * // Explanation:\n * // - throttle emits the FIRST value received, then ignores subsequent values\n * // for the specified duration (250ms)\n * // - Unlike audit (which emits the LAST value), throttle emits the FIRST\n * // - Useful for rate-limiting scroll/resize events\n *\n * const input$ = source<number>();\n *\n * const throttled$ = input$.pipe(throttle(250));\n *\n * const valueHistory: number[] = [];\n *\n * throttled$.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 * input$.next(0);\n *\n * assert.deepStrictEqual(valueHistory, [0]);\n *\n * await sleep(200);\n *\n * input$.next(2);\n *\n * assert.deepStrictEqual(valueHistory, [0]);\n *\n * await sleep(100);\n *\n * input$.next(3);\n *\n * assert.deepStrictEqual(valueHistory, [0, 3]);\n *\n * await sleep(300);\n *\n * input$.next(9);\n *\n * assert.deepStrictEqual(valueHistory, [0, 3, 9]);\n *\n * await sleep(100);\n *\n * input$.next(10);\n *\n * await sleep(100);\n *\n * input$.next(11);\n *\n * assert.deepStrictEqual(valueHistory, [0, 3, 9]);\n *\n * await sleep(100);\n *\n * input$.next(12);\n *\n * assert.deepStrictEqual(valueHistory, [0, 3, 9, 12]);\n * ```\n */\nexport const throttle = <A,>(\n milliSeconds: number,\n): KeepInitialValueOperator<A, A> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n createThrottleObservable(\n parentObservable,\n milliSeconds,\n )) as KeepInitialValueOperator<A, A>;\n\nconst createThrottleObservable = <A,>(\n parentObservable: Observable<A>,\n milliSeconds: number,\n): ThrottleOperatorObservable<A> => {\n let mut_timerId: TimerId | undefined = undefined;\n\n let mut_isSkipping = false;\n\n const resetTimer = (): void => {\n if (mut_timerId !== undefined) {\n clearTimeout(mut_timerId);\n }\n };\n\n return createSyncChildObservable(\n {\n parents: [parentObservable],\n initialValue: parentObservable.getSnapshot(),\n onComplete: resetTimer,\n },\n ({ setNext }) =>\n (updateToken) => {\n const sn = parentObservable.getSnapshot();\n\n if (\n mut_isSkipping ||\n parentObservable.updateToken !== updateToken ||\n Optional.isNone(sn)\n ) {\n return; // skip update\n }\n\n setNext(sn.value, updateToken);\n\n mut_isSkipping = true;\n\n // set timer\n mut_timerId = setTimeout(() => {\n mut_isSkipping = false;\n }, milliSeconds);\n },\n );\n};\n"],"names":[],"mappings":";;;;AAuFO,MAAM,WAAW,CACtB,YAAA;AAAA;AAAA,GAGC,CAAC,gBAAA,KACA,wBAAA;AAAA,IACE,gBAAA;AAAA,IACA;AAAA,GACF;AAAA;AAEJ,MAAM,wBAAA,GAA2B,CAC/B,gBAAA,EACA,YAAA,KACkC;AAClC,EAAA,IAAI,WAAA,GAAmC,MAAA;AAEvC,EAAA,IAAI,cAAA,GAAiB,KAAA;AAErB,EAAA,MAAM,aAAa,MAAY;AAC7B,IAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,MAAA,YAAA,CAAa,WAAW,CAAA;AAAA,IAC1B;AAAA,EACF,CAAA;AAEA,EAAA,OAAO,yBAAA;AAAA,IACL;AAAA,MACE,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,YAAA,EAAc,iBAAiB,WAAA,EAAY;AAAA,MAC3C,UAAA,EAAY;AAAA,KACd;AAAA,IACA,CAAC,EAAE,OAAA,EAAQ,KACT,CAAC,WAAA,KAAgB;AACf,MAAA,MAAM,EAAA,GAAK,iBAAiB,WAAA,EAAY;AAExC,MAAA,IACE,kBACA,gBAAA,CAAiB,WAAA,KAAgB,eACjC,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAClB;AACA,QAAA;AAAA,MACF;AAEA,MAAA,OAAA,CAAQ,EAAA,CAAG,OAAO,WAAW,CAAA;AAE7B,MAAA,cAAA,GAAiB,IAAA;AAGjB,MAAA,WAAA,GAAc,WAAW,MAAM;AAC7B,QAAA,cAAA,GAAiB,KAAA;AAAA,MACnB,GAAG,YAAY,CAAA;AAAA,IACjB;AAAA,GACJ;AACF,CAAA;;;;"}