synstate 0.1.2 → 1.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 (307) hide show
  1. package/README.md +199 -146
  2. package/dist/core/class/child-observable-class.d.mts.map +1 -1
  3. package/dist/core/class/child-observable-class.mjs +43 -10
  4. package/dist/core/class/child-observable-class.mjs.map +1 -1
  5. package/dist/core/class/observable-base-class.d.mts +4 -4
  6. package/dist/core/class/observable-base-class.d.mts.map +1 -1
  7. package/dist/core/class/observable-base-class.mjs +8 -8
  8. package/dist/core/class/observable-base-class.mjs.map +1 -1
  9. package/dist/core/class/root-observable-class.d.mts +1 -1
  10. package/dist/core/class/root-observable-class.d.mts.map +1 -1
  11. package/dist/core/class/root-observable-class.mjs +9 -9
  12. package/dist/core/class/root-observable-class.mjs.map +1 -1
  13. package/dist/core/combine/combine.d.mts +6 -6
  14. package/dist/core/combine/combine.mjs +11 -12
  15. package/dist/core/combine/combine.mjs.map +1 -1
  16. package/dist/core/combine/merge.d.mts +6 -6
  17. package/dist/core/combine/merge.mjs +9 -9
  18. package/dist/core/combine/merge.mjs.map +1 -1
  19. package/dist/core/combine/zip.d.mts +20 -19
  20. package/dist/core/combine/zip.d.mts.map +1 -1
  21. package/dist/core/combine/zip.mjs +22 -21
  22. package/dist/core/combine/zip.mjs.map +1 -1
  23. package/dist/core/create/{interval.d.mts → counter.d.mts} +14 -12
  24. package/dist/core/create/counter.d.mts.map +1 -0
  25. package/dist/core/create/{interval.mjs → counter.mjs} +21 -23
  26. package/dist/core/create/counter.mjs.map +1 -0
  27. package/dist/core/create/from-abortable-promise.d.mts +29 -0
  28. package/dist/core/create/from-abortable-promise.d.mts.map +1 -0
  29. package/dist/core/create/from-abortable-promise.mjs +70 -0
  30. package/dist/core/create/from-abortable-promise.mjs.map +1 -0
  31. package/dist/core/create/from-promise.d.mts +9 -6
  32. package/dist/core/create/from-promise.d.mts.map +1 -1
  33. package/dist/core/create/from-promise.mjs +8 -5
  34. package/dist/core/create/from-promise.mjs.map +1 -1
  35. package/dist/core/create/from-subscribable.d.mts +4 -4
  36. package/dist/core/create/from-subscribable.mjs +4 -4
  37. package/dist/core/create/index.d.mts +3 -3
  38. package/dist/core/create/index.d.mts.map +1 -1
  39. package/dist/core/create/index.mjs +4 -4
  40. package/dist/core/create/just.d.mts +32 -0
  41. package/dist/core/create/just.d.mts.map +1 -0
  42. package/dist/core/create/just.mjs +44 -0
  43. package/dist/core/create/just.mjs.map +1 -0
  44. package/dist/core/create/source.d.mts +7 -12
  45. package/dist/core/create/source.d.mts.map +1 -1
  46. package/dist/core/create/source.mjs +1 -6
  47. package/dist/core/create/source.mjs.map +1 -1
  48. package/dist/core/create/timer.d.mts +6 -4
  49. package/dist/core/create/timer.d.mts.map +1 -1
  50. package/dist/core/create/timer.mjs +6 -7
  51. package/dist/core/create/timer.mjs.map +1 -1
  52. package/dist/core/index.d.mts +0 -1
  53. package/dist/core/index.d.mts.map +1 -1
  54. package/dist/core/index.mjs +8 -13
  55. package/dist/core/index.mjs.map +1 -1
  56. package/dist/core/operators/audit.d.mts +97 -0
  57. package/dist/core/operators/audit.d.mts.map +1 -0
  58. package/dist/core/operators/audit.mjs +144 -0
  59. package/dist/core/operators/audit.mjs.map +1 -0
  60. package/dist/core/operators/debounce.d.mts +88 -0
  61. package/dist/core/operators/debounce.d.mts.map +1 -0
  62. package/dist/core/operators/debounce.mjs +130 -0
  63. package/dist/core/operators/debounce.mjs.map +1 -0
  64. package/dist/core/operators/filter.d.mts +5 -5
  65. package/dist/core/operators/filter.mjs +3 -3
  66. package/dist/core/operators/filter.mjs.map +1 -1
  67. package/dist/core/operators/index.d.mts +4 -4
  68. package/dist/core/operators/index.d.mts.map +1 -1
  69. package/dist/core/operators/index.mjs +4 -4
  70. package/dist/core/operators/{map-with-index.d.mts → map.d.mts} +11 -11
  71. package/dist/core/operators/map.d.mts.map +1 -0
  72. package/dist/core/operators/{map-with-index.mjs → map.mjs} +17 -17
  73. package/dist/core/operators/map.mjs.map +1 -0
  74. package/dist/core/operators/merge-map.d.mts +56 -29
  75. package/dist/core/operators/merge-map.d.mts.map +1 -1
  76. package/dist/core/operators/merge-map.mjs +58 -31
  77. package/dist/core/operators/merge-map.mjs.map +1 -1
  78. package/dist/core/operators/pairwise.d.mts +6 -6
  79. package/dist/core/operators/pairwise.mjs +9 -9
  80. package/dist/core/operators/pairwise.mjs.map +1 -1
  81. package/dist/core/operators/scan.d.mts +6 -6
  82. package/dist/core/operators/scan.mjs +9 -9
  83. package/dist/core/operators/scan.mjs.map +1 -1
  84. package/dist/core/operators/skip-if-no-change.d.mts +20 -8
  85. package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
  86. package/dist/core/operators/skip-if-no-change.mjs +23 -11
  87. package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
  88. package/dist/core/operators/skip-until.d.mts +5 -5
  89. package/dist/core/operators/skip-until.mjs +8 -8
  90. package/dist/core/operators/skip-until.mjs.map +1 -1
  91. package/dist/core/operators/skip-while.d.mts +18 -8
  92. package/dist/core/operators/skip-while.d.mts.map +1 -1
  93. package/dist/core/operators/skip-while.mjs +26 -11
  94. package/dist/core/operators/skip-while.mjs.map +1 -1
  95. package/dist/core/operators/switch-map.d.mts +57 -26
  96. package/dist/core/operators/switch-map.d.mts.map +1 -1
  97. package/dist/core/operators/switch-map.mjs +59 -28
  98. package/dist/core/operators/switch-map.mjs.map +1 -1
  99. package/dist/core/operators/take-until.d.mts +5 -5
  100. package/dist/core/operators/take-until.mjs +8 -8
  101. package/dist/core/operators/take-until.mjs.map +1 -1
  102. package/dist/core/operators/take-while.d.mts +15 -7
  103. package/dist/core/operators/take-while.d.mts.map +1 -1
  104. package/dist/core/operators/take-while.mjs +18 -10
  105. package/dist/core/operators/take-while.mjs.map +1 -1
  106. package/dist/core/operators/throttle.d.mts +81 -0
  107. package/dist/core/operators/throttle.d.mts.map +1 -0
  108. package/dist/core/operators/throttle.mjs +126 -0
  109. package/dist/core/operators/throttle.mjs.map +1 -0
  110. package/dist/core/operators/with-buffered-from.d.mts +9 -9
  111. package/dist/core/operators/with-buffered-from.mjs +12 -12
  112. package/dist/core/operators/with-buffered-from.mjs.map +1 -1
  113. package/dist/core/operators/with-current-value-from.d.mts +10 -9
  114. package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
  115. package/dist/core/operators/with-current-value-from.mjs +13 -12
  116. package/dist/core/operators/with-current-value-from.mjs.map +1 -1
  117. package/dist/core/operators/with-initial-value.d.mts +5 -5
  118. package/dist/core/operators/with-initial-value.mjs +8 -8
  119. package/dist/core/operators/with-initial-value.mjs.map +1 -1
  120. package/dist/core/predefined/index.mjs +0 -1
  121. package/dist/core/predefined/index.mjs.map +1 -1
  122. package/dist/core/predefined/operators/attach-index.d.mts +49 -0
  123. package/dist/core/predefined/operators/attach-index.d.mts.map +1 -1
  124. package/dist/core/predefined/operators/attach-index.mjs +51 -2
  125. package/dist/core/predefined/operators/attach-index.mjs.map +1 -1
  126. package/dist/core/predefined/operators/index.d.mts +0 -1
  127. package/dist/core/predefined/operators/index.d.mts.map +1 -1
  128. package/dist/core/predefined/operators/index.mjs +0 -1
  129. package/dist/core/predefined/operators/index.mjs.map +1 -1
  130. package/dist/core/predefined/operators/map-optional.d.mts +47 -0
  131. package/dist/core/predefined/operators/map-optional.d.mts.map +1 -1
  132. package/dist/core/predefined/operators/map-optional.mjs +49 -1
  133. package/dist/core/predefined/operators/map-optional.mjs.map +1 -1
  134. package/dist/core/predefined/operators/map-result-err.d.mts +47 -0
  135. package/dist/core/predefined/operators/map-result-err.d.mts.map +1 -1
  136. package/dist/core/predefined/operators/map-result-err.mjs +49 -1
  137. package/dist/core/predefined/operators/map-result-err.mjs.map +1 -1
  138. package/dist/core/predefined/operators/map-result-ok.d.mts +47 -0
  139. package/dist/core/predefined/operators/map-result-ok.d.mts.map +1 -1
  140. package/dist/core/predefined/operators/map-result-ok.mjs +49 -1
  141. package/dist/core/predefined/operators/map-result-ok.mjs.map +1 -1
  142. package/dist/core/predefined/operators/map-to.d.mts +40 -0
  143. package/dist/core/predefined/operators/map-to.d.mts.map +1 -1
  144. package/dist/core/predefined/operators/map-to.mjs +43 -1
  145. package/dist/core/predefined/operators/map-to.mjs.map +1 -1
  146. package/dist/core/predefined/operators/pluck.d.mts +39 -0
  147. package/dist/core/predefined/operators/pluck.d.mts.map +1 -1
  148. package/dist/core/predefined/operators/pluck.mjs +42 -1
  149. package/dist/core/predefined/operators/pluck.mjs.map +1 -1
  150. package/dist/core/predefined/operators/skip.d.mts +47 -0
  151. package/dist/core/predefined/operators/skip.d.mts.map +1 -1
  152. package/dist/core/predefined/operators/skip.mjs +47 -0
  153. package/dist/core/predefined/operators/skip.mjs.map +1 -1
  154. package/dist/core/predefined/operators/take.d.mts +41 -0
  155. package/dist/core/predefined/operators/take.d.mts.map +1 -1
  156. package/dist/core/predefined/operators/take.mjs +41 -0
  157. package/dist/core/predefined/operators/take.mjs.map +1 -1
  158. package/dist/core/predefined/operators/unwrap-optional.d.mts +40 -0
  159. package/dist/core/predefined/operators/unwrap-optional.d.mts.map +1 -1
  160. package/dist/core/predefined/operators/unwrap-optional.mjs +42 -1
  161. package/dist/core/predefined/operators/unwrap-optional.mjs.map +1 -1
  162. package/dist/core/predefined/operators/unwrap-result-err.d.mts +40 -0
  163. package/dist/core/predefined/operators/unwrap-result-err.d.mts.map +1 -1
  164. package/dist/core/predefined/operators/unwrap-result-err.mjs +42 -1
  165. package/dist/core/predefined/operators/unwrap-result-err.mjs.map +1 -1
  166. package/dist/core/predefined/operators/unwrap-result-ok.d.mts +40 -0
  167. package/dist/core/predefined/operators/unwrap-result-ok.d.mts.map +1 -1
  168. package/dist/core/predefined/operators/unwrap-result-ok.mjs +42 -1
  169. package/dist/core/predefined/operators/unwrap-result-ok.mjs.map +1 -1
  170. package/dist/core/types/id.d.mts +1 -1
  171. package/dist/core/types/id.d.mts.map +1 -1
  172. package/dist/core/types/index.d.mts +1 -0
  173. package/dist/core/types/index.d.mts.map +1 -1
  174. package/dist/core/types/observable-family.d.mts +8 -14
  175. package/dist/core/types/observable-family.d.mts.map +1 -1
  176. package/dist/core/types/observable.d.mts +3 -3
  177. package/dist/core/types/observable.d.mts.map +1 -1
  178. package/dist/core/types/timer.d.mts +2 -0
  179. package/dist/core/types/timer.d.mts.map +1 -0
  180. package/dist/core/types/timer.mjs +2 -0
  181. package/dist/core/types/timer.mjs.map +1 -0
  182. package/dist/core/utils/id-maker.d.mts +2 -2
  183. package/dist/core/utils/id-maker.d.mts.map +1 -1
  184. package/dist/core/utils/id-maker.mjs +3 -3
  185. package/dist/core/utils/id-maker.mjs.map +1 -1
  186. package/dist/core/utils/index.mjs +1 -1
  187. package/dist/entry-point.mjs +11 -14
  188. package/dist/entry-point.mjs.map +1 -1
  189. package/dist/globals.d.mts +0 -3
  190. package/dist/index.mjs +11 -14
  191. package/dist/index.mjs.map +1 -1
  192. package/dist/utils/collect-to-array.d.mts +3 -0
  193. package/dist/utils/collect-to-array.d.mts.map +1 -0
  194. package/dist/utils/collect-to-array.mjs +11 -0
  195. package/dist/utils/collect-to-array.mjs.map +1 -0
  196. package/dist/utils/create-boolean-state.d.mts +40 -0
  197. package/dist/utils/create-boolean-state.d.mts.map +1 -0
  198. package/dist/utils/create-boolean-state.mjs +53 -0
  199. package/dist/utils/create-boolean-state.mjs.map +1 -0
  200. package/dist/utils/create-event-emitter.d.mts +4 -4
  201. package/dist/utils/create-event-emitter.mjs +4 -4
  202. package/dist/utils/create-reducer.d.mts +10 -7
  203. package/dist/utils/create-reducer.d.mts.map +1 -1
  204. package/dist/utils/create-reducer.mjs +7 -7
  205. package/dist/utils/create-reducer.mjs.map +1 -1
  206. package/dist/utils/create-state.d.mts +8 -48
  207. package/dist/utils/create-state.d.mts.map +1 -1
  208. package/dist/utils/create-state.mjs +10 -60
  209. package/dist/utils/create-state.mjs.map +1 -1
  210. package/dist/utils/index.d.mts +2 -0
  211. package/dist/utils/index.d.mts.map +1 -1
  212. package/dist/utils/index.mjs +3 -1
  213. package/dist/utils/index.mjs.map +1 -1
  214. package/package.json +17 -11
  215. package/src/core/class/child-observable-class.mts +65 -9
  216. package/src/core/class/circular-dependency-comparison.test.mts +142 -0
  217. package/src/core/class/circular-dependency.test.mts +251 -0
  218. package/src/core/class/observable-base-class.mts +9 -9
  219. package/src/core/class/root-observable-class.mts +14 -10
  220. package/src/core/combine/combine.mts +13 -13
  221. package/src/core/combine/merge.mts +13 -14
  222. package/src/core/combine/zip.mts +26 -25
  223. package/src/core/create/{interval.mts → counter.mts} +32 -30
  224. package/src/core/create/from-abortable-promise.mts +83 -0
  225. package/src/core/create/from-promise.mts +10 -7
  226. package/src/core/create/from-subscribable.mts +4 -4
  227. package/src/core/create/index.mts +3 -3
  228. package/src/core/create/just.mts +43 -0
  229. package/src/core/create/source.mts +10 -14
  230. package/src/core/create/timer.mts +12 -11
  231. package/src/core/index.mts +0 -1
  232. package/src/core/operators/audit.mts +172 -0
  233. package/src/core/operators/debounce.mts +154 -0
  234. package/src/core/operators/filter.mts +9 -9
  235. package/src/core/operators/index.mts +4 -4
  236. package/src/core/operators/{map-with-index.mts → map.mts} +20 -20
  237. package/src/core/operators/merge-map.mts +59 -32
  238. package/src/core/operators/pairwise.mts +10 -10
  239. package/src/core/operators/scan.mts +10 -10
  240. package/src/core/operators/skip-if-no-change.mts +24 -12
  241. package/src/core/operators/skip-until.mts +9 -9
  242. package/src/core/operators/skip-while.mts +29 -12
  243. package/src/core/operators/switch-map.mts +60 -29
  244. package/src/core/operators/take-until.mts +9 -9
  245. package/src/core/operators/take-while.mts +19 -11
  246. package/src/core/operators/{throttle-time.mts → throttle.mts} +58 -38
  247. package/src/core/operators/with-buffered-from.mts +13 -13
  248. package/src/core/operators/with-current-value-from.mts +14 -13
  249. package/src/core/operators/with-initial-value.mts +9 -9
  250. package/src/core/predefined/operators/attach-index.mts +51 -2
  251. package/src/core/predefined/operators/index.mts +0 -1
  252. package/src/core/predefined/operators/map-optional.mts +48 -1
  253. package/src/core/predefined/operators/map-result-err.mts +48 -1
  254. package/src/core/predefined/operators/map-result-ok.mts +48 -1
  255. package/src/core/predefined/operators/map-to.mts +41 -1
  256. package/src/core/predefined/operators/pluck.mts +40 -1
  257. package/src/core/predefined/operators/skip.mts +47 -0
  258. package/src/core/predefined/operators/take.mts +41 -0
  259. package/src/core/predefined/operators/unwrap-optional.mts +41 -1
  260. package/src/core/predefined/operators/unwrap-result-err.mts +41 -1
  261. package/src/core/predefined/operators/unwrap-result-ok.mts +41 -1
  262. package/src/core/types/id.mts +1 -1
  263. package/src/core/types/index.mts +1 -0
  264. package/src/core/types/observable-family.mts +8 -24
  265. package/src/core/types/observable.mts +3 -3
  266. package/src/core/types/timer.mts +2 -0
  267. package/src/core/utils/id-maker.mts +4 -4
  268. package/src/globals.d.mts +0 -3
  269. package/src/utils/collect-to-array.mts +17 -0
  270. package/src/utils/create-boolean-state.mts +68 -0
  271. package/src/utils/create-event-emitter.mts +4 -4
  272. package/src/utils/create-reducer.mts +11 -8
  273. package/src/utils/create-state.mts +10 -75
  274. package/src/utils/index.mts +2 -0
  275. package/dist/core/create/from-array.d.mts +0 -39
  276. package/dist/core/create/from-array.d.mts.map +0 -1
  277. package/dist/core/create/from-array.mjs +0 -65
  278. package/dist/core/create/from-array.mjs.map +0 -1
  279. package/dist/core/create/interval.d.mts.map +0 -1
  280. package/dist/core/create/interval.mjs.map +0 -1
  281. package/dist/core/create/of.d.mts +0 -39
  282. package/dist/core/create/of.d.mts.map +0 -1
  283. package/dist/core/create/of.mjs +0 -63
  284. package/dist/core/create/of.mjs.map +0 -1
  285. package/dist/core/operators/audit-time.d.mts +0 -62
  286. package/dist/core/operators/audit-time.d.mts.map +0 -1
  287. package/dist/core/operators/audit-time.mjs +0 -109
  288. package/dist/core/operators/audit-time.mjs.map +0 -1
  289. package/dist/core/operators/debounce-time.d.mts +0 -51
  290. package/dist/core/operators/debounce-time.d.mts.map +0 -1
  291. package/dist/core/operators/debounce-time.mjs +0 -93
  292. package/dist/core/operators/debounce-time.mjs.map +0 -1
  293. package/dist/core/operators/map-with-index.d.mts.map +0 -1
  294. package/dist/core/operators/map-with-index.mjs.map +0 -1
  295. package/dist/core/operators/throttle-time.d.mts +0 -62
  296. package/dist/core/operators/throttle-time.d.mts.map +0 -1
  297. package/dist/core/operators/throttle-time.mjs +0 -107
  298. package/dist/core/operators/throttle-time.mjs.map +0 -1
  299. package/dist/core/predefined/operators/map.d.mts +0 -3
  300. package/dist/core/predefined/operators/map.d.mts.map +0 -1
  301. package/dist/core/predefined/operators/map.mjs +0 -8
  302. package/dist/core/predefined/operators/map.mjs.map +0 -1
  303. package/src/core/create/from-array.mts +0 -76
  304. package/src/core/create/of.mts +0 -73
  305. package/src/core/operators/audit-time.mts +0 -136
  306. package/src/core/operators/debounce-time.mts +0 -116
  307. package/src/core/predefined/operators/map.mts +0 -5
@@ -4,7 +4,7 @@ import {
4
4
  type KeepInitialValueOperator,
5
5
  type Observable,
6
6
  type SkipIfNoChangeOperatorObservable,
7
- type UpdaterSymbol,
7
+ type UpdateToken,
8
8
  } from '../types/index.mjs';
9
9
 
10
10
  /**
@@ -19,8 +19,8 @@ import {
19
19
  * ```ts
20
20
  * // Timeline:
21
21
  * //
22
- * // num$ 1 1 2 2 2 3
23
- * // distinct$ 1 2 3
22
+ * // num$ 1 1 2 2 1 2 3 2
23
+ * // distinct$ 1 2 1 2 3 2
24
24
  * //
25
25
  * // Explanation:
26
26
  * // - skipIfNoChange filters out consecutive duplicate values
@@ -31,29 +31,41 @@ import {
31
31
  *
32
32
  * const distinct$ = num$.pipe(skipIfNoChange());
33
33
  *
34
- * const mut_history: number[] = [];
34
+ * const valueHistory: number[] = [];
35
35
  *
36
36
  * distinct$.subscribe((x) => {
37
- * mut_history.push(x);
37
+ * valueHistory.push(x);
38
38
  * });
39
39
  *
40
40
  * num$.next(1); // logs: 1
41
41
  *
42
- * assert.deepStrictEqual(mut_history, [1]);
42
+ * assert.deepStrictEqual(valueHistory, [1]);
43
43
  *
44
44
  * num$.next(1); // nothing logged
45
45
  *
46
- * assert.deepStrictEqual(mut_history, [1]);
46
+ * assert.deepStrictEqual(valueHistory, [1]);
47
47
  *
48
48
  * num$.next(2); // logs: 2
49
49
  *
50
- * assert.deepStrictEqual(mut_history, [1, 2]);
50
+ * assert.deepStrictEqual(valueHistory, [1, 2]);
51
51
  *
52
52
  * num$.next(2); // nothing logged
53
53
  *
54
+ * num$.next(1); // logs: 1
55
+ *
56
+ * assert.deepStrictEqual(valueHistory, [1, 2, 1]);
57
+ *
58
+ * num$.next(2); // logs: 2
59
+ *
60
+ * assert.deepStrictEqual(valueHistory, [1, 2, 1, 2]);
61
+ *
54
62
  * num$.next(3); // logs: 3
55
63
  *
56
- * assert.deepStrictEqual(mut_history, [1, 2, 3]);
64
+ * assert.deepStrictEqual(valueHistory, [1, 2, 1, 2, 3]);
65
+ *
66
+ * num$.next(2); // logs: 2
67
+ *
68
+ * assert.deepStrictEqual(valueHistory, [1, 2, 1, 2, 3, 2]);
57
69
  * ```
58
70
  */
59
71
  export const skipIfNoChange = <A,>(
@@ -92,12 +104,12 @@ class SkipIfNoChangeObservableClass<A>
92
104
  this.#eq = eq;
93
105
  }
94
106
 
95
- override tryUpdate(updaterSymbol: UpdaterSymbol): void {
107
+ override tryUpdate(updateToken: UpdateToken): void {
96
108
  const par = this.parents[0];
97
109
 
98
110
  const sn = par.getSnapshot();
99
111
 
100
- if (par.updaterSymbol !== updaterSymbol || Optional.isNone(sn)) {
112
+ if (par.updateToken !== updateToken || Optional.isNone(sn)) {
101
113
  return; // skip update
102
114
  }
103
115
 
@@ -109,7 +121,7 @@ class SkipIfNoChangeObservableClass<A>
109
121
  this.#mut_previousValue = sn;
110
122
 
111
123
  if (cond) {
112
- this.setNext(sn.value, updaterSymbol);
124
+ this.setNext(sn.value, updateToken);
113
125
  }
114
126
  }
115
127
  }
@@ -4,7 +4,7 @@ import {
4
4
  type DropInitialValueOperator,
5
5
  type Observable,
6
6
  type SkipUntilOperatorObservable,
7
- type UpdaterSymbol,
7
+ type UpdateToken,
8
8
  } from '../types/index.mjs';
9
9
 
10
10
  /**
@@ -34,27 +34,27 @@ import {
34
34
  *
35
35
  * const skipped$ = num$.pipe(skipUntil(startNotifier));
36
36
  *
37
- * const mut_history: number[] = [];
37
+ * const valueHistory: number[] = [];
38
38
  *
39
39
  * skipped$.subscribe((x) => {
40
- * mut_history.push(x);
40
+ * valueHistory.push(x);
41
41
  * });
42
42
  *
43
43
  * num$.next(1); // nothing logged
44
44
  *
45
45
  * num$.next(2); // nothing logged
46
46
  *
47
- * assert.deepStrictEqual(mut_history, []);
47
+ * assert.deepStrictEqual(valueHistory, []);
48
48
  *
49
49
  * start_();
50
50
  *
51
51
  * num$.next(4); // logs: 4
52
52
  *
53
- * assert.deepStrictEqual(mut_history, [4]);
53
+ * assert.deepStrictEqual(valueHistory, [4]);
54
54
  *
55
55
  * num$.next(5); // logs: 5
56
56
  *
57
- * assert.deepStrictEqual(mut_history, [4, 5]);
57
+ * assert.deepStrictEqual(valueHistory, [4, 5]);
58
58
  * ```
59
59
  */
60
60
  export const skipUntil =
@@ -86,19 +86,19 @@ class SkipUntilObservableClass<A>
86
86
  );
87
87
  }
88
88
 
89
- override tryUpdate(updaterSymbol: UpdaterSymbol): void {
89
+ override tryUpdate(updateToken: UpdateToken): void {
90
90
  const par = this.parents[0];
91
91
 
92
92
  const sn = par.getSnapshot();
93
93
 
94
94
  if (
95
- par.updaterSymbol !== updaterSymbol ||
95
+ par.updateToken !== updateToken ||
96
96
  Optional.isNone(sn) ||
97
97
  this.#mut_isSkipping
98
98
  ) {
99
99
  return; // skip update
100
100
  }
101
101
 
102
- this.setNext(sn.value, updaterSymbol);
102
+ this.setNext(sn.value, updateToken);
103
103
  }
104
104
  }
@@ -4,7 +4,7 @@ import {
4
4
  type DropInitialValueOperator,
5
5
  type Observable,
6
6
  type SkipWhileOperatorObservable,
7
- type UpdaterSymbol,
7
+ type UpdateToken,
8
8
  } from '../types/index.mjs';
9
9
 
10
10
  /**
@@ -19,9 +19,9 @@ import {
19
19
  * ```ts
20
20
  * // Timeline:
21
21
  * //
22
- * // num$ 1 2 3 4 5 6 7
23
- * // skipped$ 5 6 7
24
- * // |---- skip -----|
22
+ * // num$ 1 2 3 4 5 6 7 1 2
23
+ * // skipped$ 5 6 7 1 2
24
+ * // |-------- skip --------|
25
25
  * //
26
26
  * // Explanation:
27
27
  * // - skipWhile skips values while the predicate returns true
@@ -32,27 +32,37 @@ import {
32
32
  *
33
33
  * const skipped$ = num$.pipe(skipWhile((x) => x < 5));
34
34
  *
35
- * const mut_history: number[] = [];
35
+ * const valueHistory: number[] = [];
36
36
  *
37
37
  * skipped$.subscribe((x) => {
38
- * mut_history.push(x);
38
+ * valueHistory.push(x);
39
39
  * });
40
40
  *
41
41
  * num$.next(1); // nothing logged
42
42
  *
43
43
  * num$.next(2); // nothing logged
44
44
  *
45
+ * num$.next(3); // nothing logged
46
+ *
47
+ * num$.next(4); // nothing logged
48
+ *
45
49
  * num$.next(5); // logs: 5
46
50
  *
47
- * assert.deepStrictEqual(mut_history, [5]);
51
+ * assert.deepStrictEqual(valueHistory, [5]);
48
52
  *
49
53
  * num$.next(6); // logs: 6
50
54
  *
51
- * assert.deepStrictEqual(mut_history, [5, 6]);
55
+ * assert.deepStrictEqual(valueHistory, [5, 6]);
52
56
  *
53
57
  * num$.next(7); // logs: 7
54
58
  *
55
- * assert.deepStrictEqual(mut_history, [5, 6, 7]);
59
+ * assert.deepStrictEqual(valueHistory, [5, 6, 7]);
60
+ *
61
+ * num$.next(1); // logs: 1
62
+ *
63
+ * num$.next(2); // logs: 2
64
+ *
65
+ * assert.deepStrictEqual(valueHistory, [5, 6, 7, 1, 2]);
56
66
  * ```
57
67
  */
58
68
  export const skipWhile =
@@ -70,6 +80,7 @@ class SkipWhileObservableClass<A>
70
80
  {
71
81
  readonly #predicate: (value: A, index: SafeUint | -1) => boolean;
72
82
  #mut_index: SafeUint | -1;
83
+ #mut_skipping: boolean;
73
84
 
74
85
  constructor(
75
86
  parentObservable: Observable<A>,
@@ -89,14 +100,16 @@ class SkipWhileObservableClass<A>
89
100
  this.#mut_index = -1;
90
101
 
91
102
  this.#predicate = predicate;
103
+
104
+ this.#mut_skipping = true;
92
105
  }
93
106
 
94
- override tryUpdate(updaterSymbol: UpdaterSymbol): void {
107
+ override tryUpdate(updateToken: UpdateToken): void {
95
108
  const par = this.parents[0];
96
109
 
97
110
  const sn = par.getSnapshot();
98
111
 
99
- if (par.updaterSymbol !== updaterSymbol || Optional.isNone(sn)) {
112
+ if (par.updateToken !== updateToken || Optional.isNone(sn)) {
100
113
  return; // skip update
101
114
  }
102
115
 
@@ -104,7 +117,11 @@ class SkipWhileObservableClass<A>
104
117
  this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
105
118
 
106
119
  if (!this.#predicate(sn.value, this.#mut_index)) {
107
- this.setNext(sn.value, updaterSymbol);
120
+ this.#mut_skipping = false;
121
+ }
122
+
123
+ if (!this.#mut_skipping) {
124
+ this.setNext(sn.value, updateToken);
108
125
  }
109
126
  }
110
127
  }
@@ -5,7 +5,7 @@ import {
5
5
  type Observable,
6
6
  type Subscription,
7
7
  type SwitchMapOperatorObservable,
8
- type UpdaterSymbol,
8
+ type UpdateToken,
9
9
  } from '../types/index.mjs';
10
10
 
11
11
  /**
@@ -21,50 +21,81 @@ import {
21
21
  * ```ts
22
22
  * // Timeline:
23
23
  * //
24
- * // searchQuery$ "a" "ab" "abc"
25
- * // requests fetch1 fetch2 fetch3
26
- * // results$ cancel cancel result3
27
- * // fetch1 fetch2
24
+ * // input$ A B C
25
+ * // inner A A1 A2 A3
26
+ * // inner B B1 B2 (switched!)
27
+ * // inner C C1 C2 C3
28
+ * // result$ A1 A2 A3 B1 B2 C1 C2 C3
28
29
  * //
29
30
  * // Explanation:
30
- * // - switchMap cancels previous inner observables when a new value arrives
31
- * // - Only the result from the latest search query is emitted
32
- * // - Previous ongoing requests are cancelled
33
- * // - Ideal for search-as-you-type scenarios
31
+ * // - switchMap creates an inner observable for each source value
32
+ * // - When a new source value arrives, the previous inner is unsubscribed
33
+ * // - A's inner completes normally (all 3 values emitted)
34
+ * // - B's inner is interrupted by C (only 2 values emitted)
35
+ * // - C's inner completes normally (all 3 values emitted)
34
36
  *
35
- * const searchQuery$ = source<string>();
37
+ * const input$ = source<string>();
36
38
  *
37
- * const results$ = searchQuery$.pipe(
38
- * switchMap((query) => {
39
- * const result$ = source<string[]>();
39
+ * const result$ = input$.pipe(
40
+ * switchMap((letter) => {
41
+ * const inner$ = source<string>();
40
42
  *
41
43
  * setTimeout(() => {
42
- * result$.next([query]);
43
- *
44
- * result$.complete();
44
+ * inner$.next(`${letter}1`);
45
45
  * }, 10);
46
46
  *
47
- * return result$;
47
+ * setTimeout(() => {
48
+ * inner$.next(`${letter}2`);
49
+ * }, 110);
50
+ *
51
+ * setTimeout(() => {
52
+ * inner$.next(`${letter}3`);
53
+ * }, 210);
54
+ *
55
+ * return inner$;
48
56
  * }),
49
57
  * );
50
58
  *
51
- * const mut_history: string[][] = [];
59
+ * const valueHistory: string[] = [];
52
60
  *
53
- * results$.subscribe((value) => {
54
- * mut_history.push(value);
61
+ * result$.subscribe((value) => {
62
+ * valueHistory.push(value);
55
63
  * });
56
64
  *
57
- * searchQuery$.next('a');
65
+ * const sleep = (ms: number): Promise<void> =>
66
+ * new Promise((resolve) => {
67
+ * setTimeout(resolve, ms);
68
+ * });
58
69
  *
59
- * searchQuery$.next('ab');
70
+ * // Emit A - inner emits A1, A2, A3 at 10ms, 110ms, 210ms
71
+ * input$.next('A');
60
72
  *
61
- * searchQuery$.next('abc');
73
+ * await sleep(250);
62
74
  *
63
- * await new Promise((resolve) => {
64
- * setTimeout(resolve, 200);
65
- * });
75
+ * assert.deepStrictEqual(valueHistory, ['A1', 'A2', 'A3']);
76
+ *
77
+ * // Emit B - inner starts emitting B1, B2 at 10ms, 110ms
78
+ * input$.next('B');
79
+ *
80
+ * await sleep(150);
81
+ *
82
+ * assert.deepStrictEqual(valueHistory, ['A1', 'A2', 'A3', 'B1', 'B2']);
83
+ *
84
+ * // Emit C - switches away from B (B3 cancelled), C's inner starts
85
+ * input$.next('C');
86
+ *
87
+ * await sleep(250);
66
88
  *
67
- * assert.deepStrictEqual(mut_history, [['abc']]);
89
+ * assert.deepStrictEqual(valueHistory, [
90
+ * 'A1',
91
+ * 'A2',
92
+ * 'A3',
93
+ * 'B1',
94
+ * 'B2',
95
+ * 'C1',
96
+ * 'C2',
97
+ * 'C3',
98
+ * ]);
68
99
  * ```
69
100
  *
70
101
  * @note To improve code readability, consider using `createState` instead of `switchMap`,
@@ -101,12 +132,12 @@ class SwitchMapObservableClass<A, B>
101
132
  this.#mut_subscription = undefined;
102
133
  }
103
134
 
104
- override tryUpdate(updaterSymbol: UpdaterSymbol): void {
135
+ override tryUpdate(updateToken: UpdateToken): void {
105
136
  const par = this.parents[0];
106
137
 
107
138
  const sn = par.getSnapshot();
108
139
 
109
- if (par.updaterSymbol !== updaterSymbol || Optional.isNone(sn)) {
140
+ if (par.updateToken !== updateToken || Optional.isNone(sn)) {
110
141
  return; // skip update
111
142
  }
112
143
 
@@ -4,7 +4,7 @@ import {
4
4
  type KeepInitialValueOperator,
5
5
  type Observable,
6
6
  type TakeUntilOperatorObservable,
7
- type UpdaterSymbol,
7
+ type UpdateToken,
8
8
  } from '../types/index.mjs';
9
9
 
10
10
  /**
@@ -34,25 +34,25 @@ import {
34
34
  *
35
35
  * const limited$ = num$.pipe(takeUntil(stopNotifier));
36
36
  *
37
- * const mut_history: number[] = [];
37
+ * const valueHistory: number[] = [];
38
38
  *
39
39
  * limited$.subscribe((x) => {
40
- * mut_history.push(x);
40
+ * valueHistory.push(x);
41
41
  * });
42
42
  *
43
43
  * num$.next(1); // logs: 1
44
44
  *
45
- * assert.deepStrictEqual(mut_history, [1]);
45
+ * assert.deepStrictEqual(valueHistory, [1]);
46
46
  *
47
47
  * num$.next(2); // logs: 2
48
48
  *
49
- * assert.deepStrictEqual(mut_history, [1, 2]);
49
+ * assert.deepStrictEqual(valueHistory, [1, 2]);
50
50
  *
51
51
  * stop_();
52
52
  *
53
53
  * num$.next(3); // nothing logged (completed)
54
54
  *
55
- * assert.deepStrictEqual(mut_history, [1, 2]);
55
+ * assert.deepStrictEqual(valueHistory, [1, 2]);
56
56
  * ```
57
57
  */
58
58
  export const takeUntil = <A,>(
@@ -85,15 +85,15 @@ class TakeUntilObservableClass<A>
85
85
  );
86
86
  }
87
87
 
88
- override tryUpdate(updaterSymbol: UpdaterSymbol): void {
88
+ override tryUpdate(updateToken: UpdateToken): void {
89
89
  const par = this.parents[0];
90
90
 
91
91
  const sn = par.getSnapshot();
92
92
 
93
- if (par.updaterSymbol !== updaterSymbol || Optional.isNone(sn)) {
93
+ if (par.updateToken !== updateToken || Optional.isNone(sn)) {
94
94
  return; // skip update
95
95
  }
96
96
 
97
- this.setNext(sn.value, updaterSymbol);
97
+ this.setNext(sn.value, updateToken);
98
98
  }
99
99
  }
@@ -12,7 +12,7 @@ import {
12
12
  type InitializedObservable,
13
13
  type Observable,
14
14
  type TakeWhileOperatorObservable,
15
- type UpdaterSymbol,
15
+ type UpdateToken,
16
16
  } from '../types/index.mjs';
17
17
  import { withInitialValue } from './with-initial-value.mjs';
18
18
 
@@ -28,7 +28,7 @@ import { withInitialValue } from './with-initial-value.mjs';
28
28
  * ```ts
29
29
  * // Timeline:
30
30
  * //
31
- * // num$ 1 2 3 4 5 6 (ignored)
31
+ * // num$ 1 2 3 4 5 6 1 2 (ignored)
32
32
  * // taken$ 1 2 3 4 | (completes)
33
33
  * //
34
34
  * // Explanation:
@@ -40,27 +40,35 @@ import { withInitialValue } from './with-initial-value.mjs';
40
40
  *
41
41
  * const taken$ = num$.pipe(takeWhile((x) => x < 5));
42
42
  *
43
- * const mut_history: number[] = [];
43
+ * const valueHistory: number[] = [];
44
44
  *
45
45
  * taken$.subscribe((x) => {
46
- * mut_history.push(x);
46
+ * valueHistory.push(x);
47
47
  * });
48
48
  *
49
49
  * num$.next(1); // logs: 1
50
50
  *
51
- * assert.deepStrictEqual(mut_history, [1]);
51
+ * assert.deepStrictEqual(valueHistory, [1]);
52
52
  *
53
53
  * num$.next(2); // logs: 2
54
54
  *
55
- * assert.deepStrictEqual(mut_history, [1, 2]);
55
+ * num$.next(3); // logs: 3
56
+ *
57
+ * num$.next(4); // logs: 4
58
+ *
59
+ * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);
56
60
  *
57
61
  * num$.next(5); // nothing logged (completes)
58
62
  *
59
- * assert.deepStrictEqual(mut_history, [1, 2]);
63
+ * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);
60
64
  *
61
65
  * num$.next(6); // nothing logged (already completed)
62
66
  *
63
- * assert.deepStrictEqual(mut_history, [1, 2]);
67
+ * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);
68
+ *
69
+ * num$.next(1); // logs: 1
70
+ *
71
+ * assert.deepStrictEqual(valueHistory, [1, 2, 3, 4]);
64
72
  * ```
65
73
  */
66
74
  export const takeWhile =
@@ -99,12 +107,12 @@ class TakeWhileObservableClass<A>
99
107
  this.#predicate = predicate;
100
108
  }
101
109
 
102
- override tryUpdate(updaterSymbol: UpdaterSymbol): void {
110
+ override tryUpdate(updateToken: UpdateToken): void {
103
111
  const par = this.parents[0];
104
112
 
105
113
  const sn = par.getSnapshot();
106
114
 
107
- if (par.updaterSymbol !== updaterSymbol || Optional.isNone(sn)) {
115
+ if (par.updateToken !== updateToken || Optional.isNone(sn)) {
108
116
  return; // skip update
109
117
  }
110
118
 
@@ -112,7 +120,7 @@ class TakeWhileObservableClass<A>
112
120
  this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
113
121
 
114
122
  if (this.#predicate(sn.value, this.#mut_index)) {
115
- this.setNext(sn.value, updaterSymbol);
123
+ this.setNext(sn.value, updateToken);
116
124
  } else {
117
125
  this.complete();
118
126
  }
@@ -3,8 +3,9 @@ import { SyncChildObservableClass } from '../class/index.mjs';
3
3
  import {
4
4
  type KeepInitialValueOperator,
5
5
  type Observable,
6
- type ThrottleTimeOperatorObservable,
7
- type UpdaterSymbol,
6
+ type ThrottleOperatorObservable,
7
+ type TimerId,
8
+ type UpdateToken,
8
9
  } from '../types/index.mjs';
9
10
 
10
11
  /**
@@ -17,68 +18,87 @@ import {
17
18
  *
18
19
  * @example
19
20
  * ```ts
20
- * // Timeline (1000ms throttle):
21
+ * // Timeline (250ms throttle):
21
22
  * //
22
- * // Time(ms) 0 100 200 300 ... 1000 1100 1200 ... 2000 2100
23
- * // scroll$ e1 e2 e3 e4 e5 e6 e7 e8 e9
24
- * // throttled$ e1 e5 e8
25
- * // |-------1000ms------> |------1000ms------> |------1000ms------>
23
+ * // 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
24
+ * //
25
+ * // input$ 0 2 3 9 10 11 12 13 14
26
+ * // |- 250ms -> |- 250ms -> |- 250ms -> |- 250ms ->
27
+ * // throttled$ 0 3 9 12 (emitted at start of window)
26
28
  * //
27
29
  * // Explanation:
28
- * // - throttleTime emits the first value immediately, then ignores subsequent values
29
- * // for the specified duration (1000ms)
30
- * // - At 0ms: e1 is emitted immediately
31
- * // - At 100-300ms: e2, e3, e4 are ignored (within 1000ms window)
32
- * // - At 1000ms: e5 is emitted (1000ms has passed since e1)
33
- * // - At 1100-1200ms: e6, e7 are ignored
34
- * // - At 2000ms: e8 is emitted (1000ms has passed since e5)
30
+ * // - throttle emits the FIRST value received, then ignores subsequent values
31
+ * // for the specified duration (250ms)
32
+ * // - Unlike audit (which emits the LAST value), throttle emits the FIRST
33
+ * // - Useful for rate-limiting scroll/resize events
35
34
  *
36
- * const scroll$ = source<number>();
35
+ * const input$ = source<number>();
37
36
  *
38
- * const throttled$ = scroll$.pipe(throttleTime(200));
37
+ * const throttled$ = input$.pipe(throttle(250));
39
38
  *
40
- * const mut_history: number[] = [];
39
+ * const valueHistory: number[] = [];
41
40
  *
42
41
  * throttled$.subscribe((value) => {
43
- * mut_history.push(value);
42
+ * valueHistory.push(value);
44
43
  * });
45
44
  *
46
- * scroll$.next(1);
45
+ * const sleep = (ms: number): Promise<void> =>
46
+ * new Promise((resolve) => {
47
+ * setTimeout(resolve, ms);
48
+ * });
47
49
  *
48
- * assert.deepStrictEqual(mut_history, [1]);
50
+ * input$.next(0);
49
51
  *
50
- * await new Promise((resolve) => {
51
- * setTimeout(resolve, 50);
52
- * });
52
+ * assert.deepStrictEqual(valueHistory, [0]);
53
53
  *
54
- * scroll$.next(2);
54
+ * await sleep(200);
55
55
  *
56
- * scroll$.next(3);
56
+ * input$.next(2);
57
57
  *
58
- * assert.deepStrictEqual(mut_history, [1]);
58
+ * assert.deepStrictEqual(valueHistory, [0]);
59
59
  *
60
- * await new Promise((resolve) => {
61
- * setTimeout(resolve, 200);
62
- * });
60
+ * await sleep(100);
61
+ *
62
+ * input$.next(3);
63
+ *
64
+ * assert.deepStrictEqual(valueHistory, [0, 3]);
65
+ *
66
+ * await sleep(300);
67
+ *
68
+ * input$.next(9);
69
+ *
70
+ * assert.deepStrictEqual(valueHistory, [0, 3, 9]);
71
+ *
72
+ * await sleep(100);
73
+ *
74
+ * input$.next(10);
75
+ *
76
+ * await sleep(100);
77
+ *
78
+ * input$.next(11);
79
+ *
80
+ * assert.deepStrictEqual(valueHistory, [0, 3, 9]);
81
+ *
82
+ * await sleep(100);
63
83
  *
64
- * scroll$.next(4);
84
+ * input$.next(12);
65
85
  *
66
- * assert.deepStrictEqual(mut_history, [1, 4]);
86
+ * assert.deepStrictEqual(valueHistory, [0, 3, 9, 12]);
67
87
  * ```
68
88
  */
69
- export const throttleTime = <A,>(
89
+ export const throttle = <A,>(
70
90
  milliSeconds: number,
71
91
  ): KeepInitialValueOperator<A, A> =>
72
92
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
73
93
  ((parentObservable) =>
74
- new ThrottleTimeObservableClass(
94
+ new ThrottleObservableClass(
75
95
  parentObservable,
76
96
  milliSeconds,
77
97
  )) as KeepInitialValueOperator<A, A>;
78
98
 
79
- class ThrottleTimeObservableClass<A>
99
+ class ThrottleObservableClass<A>
80
100
  extends SyncChildObservableClass<A, readonly [A]>
81
- implements ThrottleTimeOperatorObservable<A>
101
+ implements ThrottleOperatorObservable<A>
82
102
  {
83
103
  readonly #milliSeconds: number;
84
104
  #mut_timerId: TimerId | undefined;
@@ -97,20 +117,20 @@ class ThrottleTimeObservableClass<A>
97
117
  this.#milliSeconds = milliSeconds;
98
118
  }
99
119
 
100
- override tryUpdate(updaterSymbol: UpdaterSymbol): void {
120
+ override tryUpdate(updateToken: UpdateToken): void {
101
121
  const par = this.parents[0];
102
122
 
103
123
  const sn = par.getSnapshot();
104
124
 
105
125
  if (
106
- par.updaterSymbol !== updaterSymbol ||
126
+ par.updateToken !== updateToken ||
107
127
  Optional.isNone(sn) ||
108
128
  this.#mut_isSkipping
109
129
  ) {
110
130
  return; // skip update
111
131
  }
112
132
 
113
- this.setNext(sn.value, updaterSymbol);
133
+ this.setNext(sn.value, updateToken);
114
134
 
115
135
  this.#mut_isSkipping = true;
116
136