synstate 1.0.2 → 2.0.1

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 +16 -17
  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 +42 -29
  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
@@ -2,93 +2,33 @@ import { pipe, 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
- * Emits values from the source observable while the predicate returns true.
7
- * Completes immediately when the predicate returns false.
8
- *
9
- * @template A - The type of values from the source
10
- * @param predicate - Function to test each value
11
- * @returns An operator that takes values while the predicate is true
12
- *
13
- * @example
14
- * ```ts
15
- * // Timeline:
16
- * //
17
- * // num$ 1 2 3 4 5 6 1 2 (ignored)
18
- * // taken$ 1 2 3 4 | (completes)
19
- * //
20
- * // Explanation:
21
- * // - takeWhile emits values while the predicate returns true
22
- * // - Completes immediately when the predicate returns false
23
- * // - No further values are emitted after completion
24
- *
25
- * const num$ = source<number>();
26
- *
27
- * const taken$ = num$.pipe(takeWhile((x) => x < 5));
28
- *
29
- * const valueHistory: number[] = [];
30
- *
31
- * taken$.subscribe((x) => {
32
- * valueHistory.push(x);
33
- * });
34
- *
35
- * num$.next(1); // logs: 1
36
- *
37
- * assert.deepStrictEqual(valueHistory, [1]);
38
- *
39
- * num$.next(2); // logs: 2
40
- *
41
- * num$.next(3); // logs: 3
42
- *
43
- * num$.next(4); // logs: 4
44
- *
45
- * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);
46
- *
47
- * num$.next(5); // nothing logged (completes)
48
- *
49
- * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);
50
- *
51
- * num$.next(6); // nothing logged (already completed)
52
- *
53
- * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);
54
- *
55
- * num$.next(1); // logs: 1
56
- *
57
- * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);
58
- * ```
59
- */
60
5
  const takeWhile = (predicate) => (parentObservable) => new TakeWhileObservableClass(parentObservable, predicate);
61
- /* implementation */
62
6
  class TakeWhileObservableClass extends SyncChildObservableClass {
63
- #predicate;
64
- #mut_index;
65
- constructor(parentObservable, predicate) {
66
- super({
67
- parents: [parentObservable],
68
- initialValue: pipe(parentObservable.getSnapshot()).map((par) => Optional.isNone(par)
69
- ? Optional.none
70
- : predicate(par.value, -1)
71
- ? par
72
- : Optional.none).value,
73
- });
74
- this.#mut_index = -1;
75
- this.#predicate = predicate;
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;
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;
76
24
  }
77
- tryUpdate(updateToken) {
78
- const par = this.parents[0];
79
- const sn = par.getSnapshot();
80
- if (par.updateToken !== updateToken || Optional.isNone(sn)) {
81
- return; // skip update
82
- }
83
- this.#mut_index =
84
- this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
85
- if (this.#predicate(sn.value, this.#mut_index)) {
86
- this.setNext(sn.value, updateToken);
87
- }
88
- else {
89
- this.complete();
90
- }
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();
91
30
  }
31
+ }
92
32
  }
93
33
 
94
34
  export { takeWhile };
@@ -1 +1 @@
1
- {"version":3,"file":"take-while.mjs","sources":["../../../src/core/operators/take-while.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAkBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDG;AACI,MAAM,SAAS,GACpB,CACE,SAAsD,KAExD,CAAC,gBAAgB,KACf,IAAI,wBAAwB,CAAC,gBAAgB,EAAE,SAAS;AAE5D;AAEA,MAAM,wBACJ,SAAQ,wBAAyC,CAAA;AAGxC,IAAA,UAAU;AACnB,IAAA,UAAU;IAEV,WAAA,CACE,gBAA+B,EAC/B,SAAsD,EAAA;AAEtD,QAAA,KAAK,CAAC;YACJ,OAAO,EAAE,CAAC,gBAAgB,CAAC;YAC3B,YAAY,EAAE,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KACzD,QAAQ,CAAC,MAAM,CAAC,GAAG;kBACf,QAAQ,CAAC;kBACT,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE;AACvB,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;;aAC9B;YACL,IAAI,CAAC,QAAQ,EAAE;;;AAGpB;;;;"}
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 +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,EACxB,cAAc,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,EAK9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,gBACV,MAAM,KACnB,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAMQ,CAAC"}
@@ -2,124 +2,47 @@ 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 first value, then ignores subsequent values for a specified duration.
7
- * After the duration, the next emission is allowed through.
8
- *
9
- * @template A - The type of values from the source
10
- * @param milliSeconds - The throttle duration in milliseconds
11
- * @returns An operator that throttles emissions
12
- *
13
- * @example
14
- * ```ts
15
- * // Timeline (250ms throttle):
16
- * //
17
- * // 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
18
- * //
19
- * // input$ 0 2 3 9 10 11 12 13 14
20
- * // |- 250ms -> |- 250ms -> |- 250ms -> |- 250ms ->
21
- * // throttled$ 0 3 9 12 (emitted at start of window)
22
- * //
23
- * // Explanation:
24
- * // - throttle emits the FIRST value received, then ignores subsequent values
25
- * // for the specified duration (250ms)
26
- * // - Unlike audit (which emits the LAST value), throttle emits the FIRST
27
- * // - Useful for rate-limiting scroll/resize events
28
- *
29
- * const input$ = source<number>();
30
- *
31
- * const throttled$ = input$.pipe(throttle(250));
32
- *
33
- * const valueHistory: number[] = [];
34
- *
35
- * throttled$.subscribe((value) => {
36
- * valueHistory.push(value);
37
- * });
38
- *
39
- * const sleep = (ms: number): Promise<void> =>
40
- * new Promise((resolve) => {
41
- * setTimeout(resolve, ms);
42
- * });
43
- *
44
- * input$.next(0);
45
- *
46
- * assert.deepStrictEqual(valueHistory, [0]);
47
- *
48
- * await sleep(200);
49
- *
50
- * input$.next(2);
51
- *
52
- * assert.deepStrictEqual(valueHistory, [0]);
53
- *
54
- * await sleep(100);
55
- *
56
- * input$.next(3);
57
- *
58
- * assert.deepStrictEqual(valueHistory, [0, 3]);
59
- *
60
- * await sleep(300);
61
- *
62
- * input$.next(9);
63
- *
64
- * assert.deepStrictEqual(valueHistory, [0, 3, 9]);
65
- *
66
- * await sleep(100);
67
- *
68
- * input$.next(10);
69
- *
70
- * await sleep(100);
71
- *
72
- * input$.next(11);
73
- *
74
- * assert.deepStrictEqual(valueHistory, [0, 3, 9]);
75
- *
76
- * await sleep(100);
77
- *
78
- * input$.next(12);
79
- *
80
- * assert.deepStrictEqual(valueHistory, [0, 3, 9, 12]);
81
- * ```
82
- */
83
- const throttle = (milliSeconds) =>
84
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
85
- ((parentObservable) => new ThrottleObservableClass(parentObservable, milliSeconds));
5
+ const throttle = (milliSeconds) => (
6
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
7
+ ((parentObservable) => new ThrottleObservableClass(
8
+ parentObservable,
9
+ milliSeconds
10
+ ))
11
+ );
86
12
  class ThrottleObservableClass extends SyncChildObservableClass {
87
- #milliSeconds;
88
- #mut_timerId;
89
- #mut_isSkipping;
90
- constructor(parentObservable, milliSeconds) {
91
- super({
92
- parents: [parentObservable],
93
- initialValue: parentObservable.getSnapshot(),
94
- });
95
- this.#mut_timerId = undefined;
96
- this.#mut_isSkipping = false;
97
- this.#milliSeconds = milliSeconds;
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);
98
28
  }
99
- tryUpdate(updateToken) {
100
- const par = this.parents[0];
101
- const sn = par.getSnapshot();
102
- if (par.updateToken !== updateToken ||
103
- Optional.isNone(sn) ||
104
- this.#mut_isSkipping) {
105
- return; // skip update
106
- }
107
- this.setNext(sn.value, updateToken);
108
- this.#mut_isSkipping = true;
109
- // set timer
110
- this.#mut_timerId = setTimeout(() => {
111
- this.#mut_isSkipping = false;
112
- }, this.#milliSeconds);
113
- }
114
- #resetTimer() {
115
- if (this.#mut_timerId !== undefined) {
116
- clearTimeout(this.#mut_timerId);
117
- }
118
- }
119
- complete() {
120
- this.#resetTimer();
121
- super.complete();
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;
122
35
  }
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
+ }
123
46
  }
124
47
 
125
48
  export { throttle };
@@ -1 +1 @@
1
- {"version":3,"file":"throttle.mjs","sources":["../../../src/core/operators/throttle.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6EG;AACI,MAAM,QAAQ,GAAG,CACtB,YAAoB;AAEpB;AACA,CAAC,CAAC,gBAAgB,KAChB,IAAI,uBAAuB,CACzB,gBAAgB,EAChB,YAAY,CACb;AAEL,MAAM,uBACJ,SAAQ,wBAAyC,CAAA;AAGxC,IAAA,aAAa;AACtB,IAAA,YAAY;AACZ,IAAA,eAAe;IAEf,WAAA,CAAY,gBAA+B,EAAE,YAAoB,EAAA;AAC/D,QAAA,KAAK,CAAC;YACJ,OAAO,EAAE,CAAC,gBAAgB,CAAC;AAC3B,YAAA,YAAY,EAAE,gBAAgB,CAAC,WAAW,EAAE;AAC7C,SAAA,CAAC;AAEF,QAAA,IAAI,CAAC,YAAY,GAAG,SAAS;AAE7B,QAAA,IAAI,CAAC,eAAe,GAAG,KAAK;AAE5B,QAAA,IAAI,CAAC,aAAa,GAAG,YAAY;IACnC;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,IACE,GAAG,CAAC,WAAW,KAAK,WAAW;AAC/B,YAAA,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,eAAe,EACpB;AACA,YAAA,OAAO;QACT;QAEA,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC;AAEnC,QAAA,IAAI,CAAC,eAAe,GAAG,IAAI;;AAG3B,QAAA,IAAI,CAAC,YAAY,GAAG,UAAU,CAAC,MAAK;AAClC,YAAA,IAAI,CAAC,eAAe,GAAG,KAAK;AAC9B,QAAA,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC;IACxB;IAEA,WAAW,GAAA;AACT,QAAA,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE;AACnC,YAAA,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC;QACjC;IACF;IAES,QAAQ,GAAA;QACf,IAAI,CAAC,WAAW,EAAE;QAElB,KAAK,CAAC,QAAQ,EAAE;IAClB;AACD;;;;"}
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;;;;"}
@@ -57,5 +57,5 @@ export declare const withBufferedFrom: <A, B>(observable: Observable<B>) => Keep
57
57
  * Alias for `withBufferedFrom`.
58
58
  * @see withBufferedFrom
59
59
  */
60
- export declare const withBuffered: <A, B>(observable: Observable<B>) => KeepInitialValueOperator<A, readonly [A, readonly B[]]>;
60
+ export declare const withBuffered: typeof withBufferedFrom;
61
61
  //# sourceMappingURL=with-buffered-from.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"with-buffered-from.d.mts","sourceRoot":"","sources":["../../../src/core/operators/with-buffered-from.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,UAAU,EAGhB,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,EAAE,CAAC,EACnC,YAAY,UAAU,CAAC,CAAC,CAAC,KACxB,wBAAwB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC,CAMQ,CAAC;AAElE;;;GAGG;AACH,eAAO,MAAM,YAAY,GAdQ,CAAC,EAAE,CAAC,cACvB,UAAU,CAAC,CAAC,CAAC,KACxB,wBAAwB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC,CAYb,CAAC"}
1
+ {"version":3,"file":"with-buffered-from.d.mts","sourceRoot":"","sources":["../../../src/core/operators/with-buffered-from.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,UAAU,EAGhB,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,EAAE,CAAC,cACvB,UAAU,CAAC,CAAC,CAAC,KACxB,wBAAwB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC,CAMQ,CAAC;AAElE;;;GAGG;AACH,eAAO,MAAM,YAAY,yBAAmB,CAAC"}
@@ -3,99 +3,46 @@ import { SyncChildObservableClass } from '../class/child-observable-class.mjs';
3
3
  import '../utils/id-maker.mjs';
4
4
  import { maxDepth } from '../utils/max-depth.mjs';
5
5
 
6
- /**
7
- * Buffers values from the source observable and emits them along with the parent value
8
- * when the parent emits. The buffer is cleared after each emission.
9
- *
10
- * @template A - The type of values from the parent observable
11
- * @template B - The type of values from the source observable
12
- * @param observable - The observable whose values will be buffered
13
- * @returns An operator that emits tuples of [parentValue, bufferedValues]
14
- *
15
- * @example
16
- * ```ts
17
- * // Timeline:
18
- * //
19
- * // data$ d1 d2 d3 d4 d5 d6 d7 d8
20
- * // trigger$ T1 T2 T3
21
- * // result$ [T1,[d1,d2,d3]] [T2,[d4,d5,d6]] [T3,[d7,d8]]
22
- * //
23
- * // Explanation:
24
- * // - withBufferedFrom collects values from the source observable
25
- * // - When the trigger emits, it emits a tuple of [triggerValue, bufferedValues]
26
- * // - Buffer is cleared after each emission
27
- * // - Useful for batching data collection triggered by events
28
- *
29
- * const data$ = source<string>();
30
- *
31
- * const trigger$ = source<number>();
32
- *
33
- * const result$ = trigger$.pipe(withBufferedFrom(data$));
34
- *
35
- * const valueHistory: (readonly [number, readonly string[]])[] = [];
36
- *
37
- * result$.subscribe(([triggerValue, bufferedData]) => {
38
- * valueHistory.push([triggerValue, bufferedData]);
39
- * });
40
- *
41
- * data$.next('A');
42
- *
43
- * data$.next('B');
44
- *
45
- * trigger$.next(1);
46
- *
47
- * assert.deepStrictEqual(valueHistory, [[1, ['A', 'B']]]);
48
- *
49
- * data$.next('C');
50
- *
51
- * trigger$.next(2);
52
- *
53
- * assert.deepStrictEqual(valueHistory, [
54
- * [1, ['A', 'B']],
55
- * [2, ['C']],
56
- * ]);
57
- * ```
58
- */
59
- const withBufferedFrom = (observable) =>
60
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
61
- ((parentObservable) => new WithBufferedFromObservableClass(parentObservable, observable));
62
- /**
63
- * Alias for `withBufferedFrom`.
64
- * @see withBufferedFrom
65
- */
6
+ const withBufferedFrom = (observable) => (
7
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
8
+ ((parentObservable) => new WithBufferedFromObservableClass(
9
+ parentObservable,
10
+ observable
11
+ ))
12
+ );
66
13
  const withBuffered = withBufferedFrom;
67
14
  class WithBufferedFromObservableClass extends SyncChildObservableClass {
68
- #mut_bufferedValues = [];
69
- constructor(parentObservable, observable) {
70
- super({
71
- parents: [parentObservable],
72
- depth: 1 + maxDepth([parentObservable, observable]),
73
- initialValue: pipe({
74
- par: parentObservable.getSnapshot(),
75
- me: observable.getSnapshot(),
76
- }).map(({ par, me }) => Optional.isNone(par)
77
- ? Optional.none
78
- : Optional.some([
79
- par.value,
80
- Optional.isNone(me) ? [] : [me.value],
81
- ])).value,
82
- });
83
- observable.subscribe((value) => {
84
- this.#mut_bufferedValues = Arr.toPushed(this.#mut_bufferedValues, value);
85
- });
86
- }
87
- tryUpdate(updateToken) {
88
- const par = this.parents[0];
89
- const sn = par.getSnapshot();
90
- if (par.updateToken !== updateToken || Optional.isNone(sn)) {
91
- return; // skip update
92
- }
93
- this.setNext([sn.value, this.#mut_bufferedValues], updateToken);
94
- this.#clearBuffer();
95
- }
96
- #clearBuffer() {
97
- this.#mut_bufferedValues = [];
15
+ #mut_bufferedValues = [];
16
+ constructor(parentObservable, observable) {
17
+ super({
18
+ parents: [parentObservable],
19
+ depth: 1 + maxDepth([parentObservable, observable]),
20
+ initialValue: pipe({
21
+ par: parentObservable.getSnapshot(),
22
+ me: observable.getSnapshot()
23
+ }).map(
24
+ ({ par, me }) => Optional.isNone(par) ? Optional.none : Optional.some([
25
+ par.value,
26
+ Optional.isNone(me) ? [] : [me.value]
27
+ ])
28
+ ).value
29
+ });
30
+ observable.subscribe((value) => {
31
+ this.#mut_bufferedValues = Arr.toPushed(this.#mut_bufferedValues, value);
32
+ });
33
+ }
34
+ #clearBuffer() {
35
+ this.#mut_bufferedValues = [];
36
+ }
37
+ tryUpdate(updateToken) {
38
+ const par = this.parents[0];
39
+ const sn = par.getSnapshot();
40
+ if (par.updateToken !== updateToken || Optional.isNone(sn)) {
41
+ return;
98
42
  }
43
+ this.setNext([sn.value, this.#mut_bufferedValues], updateToken);
44
+ this.#clearBuffer();
45
+ }
99
46
  }
100
47
 
101
48
  export { withBuffered, withBufferedFrom };
@@ -1 +1 @@
1
- {"version":3,"file":"with-buffered-from.mjs","sources":["../../../src/core/operators/with-buffered-from.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDG;AACI,MAAM,gBAAgB,GAAG,CAC9B,UAAyB;AAEzB;AACA,CAAC,CAAC,gBAAgB,KAChB,IAAI,+BAA+B,CACjC,gBAAgB,EAChB,UAAU,CACX;AAEL;;;AAGG;AACI,MAAM,YAAY,GAAG;AAE5B,MAAM,+BACJ,SAAQ,wBAAkE,CAAA;IAG1E,mBAAmB,GAAiB,EAAE;IAEtC,WAAA,CAAY,gBAA+B,EAAE,UAAyB,EAAA;AACpE,QAAA,KAAK,CAAC;YACJ,OAAO,EAAE,CAAC,gBAAgB,CAAC;YAC3B,KAAK,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;YACnD,YAAY,EAAE,IAAI,CAAC;AACjB,gBAAA,GAAG,EAAE,gBAAgB,CAAC,WAAW,EAAE;AACnC,gBAAA,EAAE,EAAE,UAAU,CAAC,WAAW,EAAE;AAC7B,aAAA,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,KACjB,QAAQ,CAAC,MAAM,CAAC,GAAG;kBACf,QAAQ,CAAC;AACX,kBAAE,QAAQ,CAAC,IAAI,CAAC;AACZ,oBAAA,GAAG,CAAC,KAAK;AACT,oBAAA,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC;iBAC7B,CAAC,CAChB,CAAC,KAAK;AACR,SAAA,CAAC;AAEF,QAAA,UAAU,CAAC,SAAS,CAAC,CAAC,KAAK,KAAI;AAC7B,YAAA,IAAI,CAAC,mBAAmB,GAAG,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,mBAAmB,EAAE,KAAK,CAAC;AAC1E,QAAA,CAAC,CAAC;IACJ;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,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,mBAAmB,CAAC,EAAE,WAAW,CAAC;QAE/D,IAAI,CAAC,YAAY,EAAE;IACrB;IAEA,YAAY,GAAA;AACV,QAAA,IAAI,CAAC,mBAAmB,GAAG,EAAE;IAC/B;AACD;;;;"}
1
+ {"version":3,"file":"with-buffered-from.mjs","sources":["../../../src/core/operators/with-buffered-from.mts"],"sourcesContent":["import { Arr, Optional, pipe } from 'ts-data-forge';\nimport { SyncChildObservableClass } from '../class/index.mjs';\nimport {\n type KeepInitialValueOperator,\n type Observable,\n type UpdateToken,\n type WithBufferedFromOperatorObservable,\n} from '../types/index.mjs';\nimport { maxDepth } from '../utils/index.mjs';\n\n/**\n * Buffers values from the source observable and emits them along with the parent value\n * when the parent emits. The buffer is cleared after each emission.\n *\n * @template A - The type of values from the parent observable\n * @template B - The type of values from the source observable\n * @param observable - The observable whose values will be buffered\n * @returns An operator that emits tuples of [parentValue, bufferedValues]\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // data$ d1 d2 d3 d4 d5 d6 d7 d8\n * // trigger$ T1 T2 T3\n * // result$ [T1,[d1,d2,d3]] [T2,[d4,d5,d6]] [T3,[d7,d8]]\n * //\n * // Explanation:\n * // - withBufferedFrom collects values from the source observable\n * // - When the trigger emits, it emits a tuple of [triggerValue, bufferedValues]\n * // - Buffer is cleared after each emission\n * // - Useful for batching data collection triggered by events\n *\n * const data$ = source<string>();\n *\n * const trigger$ = source<number>();\n *\n * const result$ = trigger$.pipe(withBufferedFrom(data$));\n *\n * const valueHistory: (readonly [number, readonly string[]])[] = [];\n *\n * result$.subscribe(([triggerValue, bufferedData]) => {\n * valueHistory.push([triggerValue, bufferedData]);\n * });\n *\n * data$.next('A');\n *\n * data$.next('B');\n *\n * trigger$.next(1);\n *\n * assert.deepStrictEqual(valueHistory, [[1, ['A', 'B']]]);\n *\n * data$.next('C');\n *\n * trigger$.next(2);\n *\n * assert.deepStrictEqual(valueHistory, [\n * [1, ['A', 'B']],\n * [2, ['C']],\n * ]);\n * ```\n */\nexport const withBufferedFrom = <A, B>(\n observable: Observable<B>,\n): KeepInitialValueOperator<A, readonly [A, readonly B[]]> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n new WithBufferedFromObservableClass(\n parentObservable,\n observable,\n )) as KeepInitialValueOperator<A, readonly [A, readonly B[]]>;\n\n/**\n * Alias for `withBufferedFrom`.\n * @see withBufferedFrom\n */\nexport const withBuffered = withBufferedFrom;\n\nclass WithBufferedFromObservableClass<A, B>\n extends SyncChildObservableClass<readonly [A, readonly B[]], readonly [A]>\n implements WithBufferedFromOperatorObservable<A, B>\n{\n #mut_bufferedValues: readonly B[] = [];\n\n constructor(parentObservable: Observable<A>, observable: Observable<B>) {\n super({\n parents: [parentObservable],\n depth: 1 + maxDepth([parentObservable, observable]),\n initialValue: pipe({\n par: parentObservable.getSnapshot(),\n me: observable.getSnapshot(),\n }).map(({ par, me }) =>\n Optional.isNone(par)\n ? Optional.none\n : Optional.some([\n par.value,\n Optional.isNone(me) ? [] : [me.value],\n ] as const),\n ).value,\n });\n\n observable.subscribe((value) => {\n this.#mut_bufferedValues = Arr.toPushed(this.#mut_bufferedValues, value);\n });\n }\n\n #clearBuffer(): void {\n this.#mut_bufferedValues = [];\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, this.#mut_bufferedValues], updateToken);\n\n this.#clearBuffer();\n }\n}\n"],"names":[],"mappings":";;;;;AA+DO,MAAM,mBAAmB,CAC9B,UAAA;AAAA;AAAA,GAGC,CAAC,qBACA,IAAI,+BAAA;AAAA,IACF,gBAAA;AAAA,IACA;AAAA,GACF;AAAA;AAMG,MAAM,YAAA,GAAe;AAE5B,MAAM,wCACI,wBAAA,CAEV;AAAA,EACE,sBAAoC,EAAC;AAAA,EAErC,WAAA,CAAY,kBAAiC,UAAA,EAA2B;AACtE,IAAA,KAAA,CAAM;AAAA,MACJ,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,OAAO,CAAA,GAAI,QAAA,CAAS,CAAC,gBAAA,EAAkB,UAAU,CAAC,CAAA;AAAA,MAClD,cAAc,IAAA,CAAK;AAAA,QACjB,GAAA,EAAK,iBAAiB,WAAA,EAAY;AAAA,QAClC,EAAA,EAAI,WAAW,WAAA;AAAY,OAC5B,CAAA,CAAE,GAAA;AAAA,QAAI,CAAC,EAAE,GAAA,EAAK,EAAA,EAAG,KAChB,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,GACf,QAAA,CAAS,IAAA,GACT,QAAA,CAAS,IAAA,CAAK;AAAA,UACZ,GAAA,CAAI,KAAA;AAAA,UACJ,QAAA,CAAS,OAAO,EAAE,CAAA,GAAI,EAAC,GAAI,CAAC,GAAG,KAAK;AAAA,SAC5B;AAAA,OAChB,CAAE;AAAA,KACH,CAAA;AAED,IAAA,UAAA,CAAW,SAAA,CAAU,CAAC,KAAA,KAAU;AAC9B,MAAA,IAAA,CAAK,mBAAA,GAAsB,GAAA,CAAI,QAAA,CAAS,IAAA,CAAK,qBAAqB,KAAK,CAAA;AAAA,IACzE,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,YAAA,GAAqB;AACnB,IAAA,IAAA,CAAK,sBAAsB,EAAC;AAAA,EAC9B;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,QAAQ,CAAC,EAAA,CAAG,OAAO,IAAA,CAAK,mBAAmB,GAAG,WAAW,CAAA;AAE9D,IAAA,IAAA,CAAK,YAAA,EAAa;AAAA,EACpB;AACF;;;;"}
@@ -60,5 +60,5 @@ export declare const withCurrentValueFrom: <A, B>(observable: Observable<B>) =>
60
60
  * Alias for `withCurrentValueFrom`.
61
61
  * @see withCurrentValueFrom
62
62
  */
63
- export declare const withLatestFrom: <A, B>(observable: Observable<B>) => DropInitialValueOperator<A, readonly [A, B]>;
63
+ export declare const withLatestFrom: typeof withCurrentValueFrom;
64
64
  //# sourceMappingURL=with-current-value-from.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"with-current-value-from.d.mts","sourceRoot":"","sources":["../../../src/core/operators/with-current-value-from.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,UAAU,EAGhB,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,eAAO,MAAM,oBAAoB,GAC9B,CAAC,EAAE,CAAC,EACH,YAAY,UAAU,CAAC,CAAC,CAAC,KACxB,wBAAwB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAEyB,CAAC;AAE1E;;;GAGG;AACH,eAAO,MAAM,cAAc,GAVxB,CAAC,EAAE,CAAC,cACS,UAAU,CAAC,CAAC,CAAC,KACxB,wBAAwB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAQE,CAAC"}
1
+ {"version":3,"file":"with-current-value-from.d.mts","sourceRoot":"","sources":["../../../src/core/operators/with-current-value-from.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,UAAU,EAGhB,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,eAAO,MAAM,oBAAoB,GAC9B,CAAC,EAAE,CAAC,cACS,UAAU,CAAC,CAAC,CAAC,KACxB,wBAAwB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAEyB,CAAC;AAE1E;;;GAGG;AACH,eAAO,MAAM,cAAc,6BAAuB,CAAC"}
@@ -3,94 +3,33 @@ import { SyncChildObservableClass } from '../class/child-observable-class.mjs';
3
3
  import '../utils/id-maker.mjs';
4
4
  import { maxDepth } from '../utils/max-depth.mjs';
5
5
 
6
- /**
7
- * Samples the current value from another observable each time the source emits.
8
- * Emits a tuple of [sourceValue, sampledValue].
9
- *
10
- * @template A - The type of values from the source observable
11
- * @template B - The type of values from the sampled observable
12
- * @param observable - The observable to sample from
13
- * @returns An operator that emits tuples of source and sampled values
14
- *
15
- * @example
16
- * ```ts
17
- * // Timeline:
18
- * //
19
- * // name$ "Alice" "Bob" "Charlie"
20
- * // age$ 25 30
21
- * // result$ (skip) ["Bob",25] ["Charlie",30]
22
- * //
23
- * // Explanation:
24
- * // - withCurrentValueFrom samples the current value from another observable
25
- * // - Emits a tuple [sourceValue, sampledValue] each time the SOURCE emits
26
- * // - Does NOT emit when the sampled observable (age$) emits
27
- * // - Does not emit until both observables have emitted at least once
28
- * // - "Alice" is skipped because age$ hasn't emitted yet
29
- *
30
- * const name$ = source<string>();
31
- *
32
- * const age$ = source<number>();
33
- *
34
- * const result$ = name$.pipe(withCurrentValueFrom(age$));
35
- *
36
- * const valueHistory: (readonly [string, number])[] = [];
37
- *
38
- * result$.subscribe(([name_, currentAge]) => {
39
- * valueHistory.push([name_, currentAge]);
40
- * });
41
- *
42
- * name$.next('Alice'); // nothing logged (age$ hasn't emitted)
43
- *
44
- * assert.deepStrictEqual(valueHistory, []);
45
- *
46
- * age$.next(25);
47
- *
48
- * name$.next('Bob'); // logs: Bob is 25 years old
49
- *
50
- * assert.deepStrictEqual(valueHistory, [['Bob', 25]]);
51
- *
52
- * age$.next(30);
53
- *
54
- * name$.next('Charlie'); // logs: Charlie is 30 years old
55
- *
56
- * assert.deepStrictEqual(valueHistory, [
57
- * ['Bob', 25],
58
- * ['Charlie', 30],
59
- * ]);
60
- * ```
61
- */
62
6
  const withCurrentValueFrom = (observable) => (parentObservable) => new WithCurrentValueFromObservableClass(parentObservable, observable);
63
- /**
64
- * Alias for `withCurrentValueFrom`.
65
- * @see withCurrentValueFrom
66
- */
67
7
  const withLatestFrom = withCurrentValueFrom;
68
8
  class WithCurrentValueFromObservableClass extends SyncChildObservableClass {
69
- #observable;
70
- constructor(parentObservable, observable) {
71
- super({
72
- parents: [parentObservable],
73
- depth: 1 + maxDepth([parentObservable, observable]),
74
- initialValue: pipe({
75
- par: parentObservable.getSnapshot(),
76
- me: observable.getSnapshot(),
77
- }).map(({ me, par }) => Optional.isNone(par) || Optional.isNone(me)
78
- ? Optional.none
79
- : Optional.some([par.value, me.value])).value,
80
- });
81
- this.#observable = observable;
82
- }
83
- tryUpdate(updateToken) {
84
- const par = this.parents[0];
85
- const ps = par.getSnapshot();
86
- if (par.updateToken !== updateToken || Optional.isNone(ps)) {
87
- return; // skip update
88
- }
89
- const curr = this.#observable.getSnapshot();
90
- if (Optional.isNone(curr))
91
- return; // skip update
92
- this.setNext([ps.value, curr.value], updateToken);
9
+ #observable;
10
+ constructor(parentObservable, observable) {
11
+ super({
12
+ parents: [parentObservable],
13
+ depth: 1 + maxDepth([parentObservable, observable]),
14
+ initialValue: pipe({
15
+ par: parentObservable.getSnapshot(),
16
+ me: observable.getSnapshot()
17
+ }).map(
18
+ ({ me, par }) => Optional.isNone(par) || Optional.isNone(me) ? Optional.none : Optional.some([par.value, me.value])
19
+ ).value
20
+ });
21
+ this.#observable = observable;
22
+ }
23
+ tryUpdate(updateToken) {
24
+ const par = this.parents[0];
25
+ const ps = par.getSnapshot();
26
+ if (par.updateToken !== updateToken || Optional.isNone(ps)) {
27
+ return;
93
28
  }
29
+ const curr = this.#observable.getSnapshot();
30
+ if (Optional.isNone(curr)) return;
31
+ this.setNext([ps.value, curr.value], updateToken);
32
+ }
94
33
  }
95
34
 
96
35
  export { withCurrentValueFrom, withLatestFrom };