synstate 0.1.2 → 1.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 (323) hide show
  1. package/README.md +200 -147
  2. package/assets/old/synstate-icon-square.png +0 -0
  3. package/assets/synstate-logo.png +0 -0
  4. package/dist/core/class/child-observable-class.d.mts +2 -0
  5. package/dist/core/class/child-observable-class.d.mts.map +1 -1
  6. package/dist/core/class/child-observable-class.mjs +44 -13
  7. package/dist/core/class/child-observable-class.mjs.map +1 -1
  8. package/dist/core/class/observable-base-class.d.mts +4 -4
  9. package/dist/core/class/observable-base-class.d.mts.map +1 -1
  10. package/dist/core/class/observable-base-class.mjs +8 -8
  11. package/dist/core/class/observable-base-class.mjs.map +1 -1
  12. package/dist/core/class/root-observable-class.d.mts +3 -1
  13. package/dist/core/class/root-observable-class.d.mts.map +1 -1
  14. package/dist/core/class/root-observable-class.mjs +9 -9
  15. package/dist/core/class/root-observable-class.mjs.map +1 -1
  16. package/dist/core/combine/combine.d.mts +7 -6
  17. package/dist/core/combine/combine.d.mts.map +1 -1
  18. package/dist/core/combine/combine.mjs +11 -12
  19. package/dist/core/combine/combine.mjs.map +1 -1
  20. package/dist/core/combine/merge.d.mts +7 -6
  21. package/dist/core/combine/merge.d.mts.map +1 -1
  22. package/dist/core/combine/merge.mjs +9 -9
  23. package/dist/core/combine/merge.mjs.map +1 -1
  24. package/dist/core/combine/zip.d.mts +21 -19
  25. package/dist/core/combine/zip.d.mts.map +1 -1
  26. package/dist/core/combine/zip.mjs +22 -21
  27. package/dist/core/combine/zip.mjs.map +1 -1
  28. package/dist/core/create/{interval.d.mts → counter.d.mts} +14 -12
  29. package/dist/core/create/counter.d.mts.map +1 -0
  30. package/dist/core/create/{interval.mjs → counter.mjs} +21 -23
  31. package/dist/core/create/counter.mjs.map +1 -0
  32. package/dist/core/create/from-abortable-promise.d.mts +29 -0
  33. package/dist/core/create/from-abortable-promise.d.mts.map +1 -0
  34. package/dist/core/create/from-abortable-promise.mjs +70 -0
  35. package/dist/core/create/from-abortable-promise.mjs.map +1 -0
  36. package/dist/core/create/from-promise.d.mts +9 -6
  37. package/dist/core/create/from-promise.d.mts.map +1 -1
  38. package/dist/core/create/from-promise.mjs +8 -5
  39. package/dist/core/create/from-promise.mjs.map +1 -1
  40. package/dist/core/create/from-subscribable.d.mts +4 -4
  41. package/dist/core/create/from-subscribable.mjs +4 -4
  42. package/dist/core/create/index.d.mts +3 -3
  43. package/dist/core/create/index.d.mts.map +1 -1
  44. package/dist/core/create/index.mjs +4 -4
  45. package/dist/core/create/just.d.mts +32 -0
  46. package/dist/core/create/just.d.mts.map +1 -0
  47. package/dist/core/create/just.mjs +44 -0
  48. package/dist/core/create/just.mjs.map +1 -0
  49. package/dist/core/create/source.d.mts +7 -12
  50. package/dist/core/create/source.d.mts.map +1 -1
  51. package/dist/core/create/source.mjs +1 -6
  52. package/dist/core/create/source.mjs.map +1 -1
  53. package/dist/core/create/timer.d.mts +6 -4
  54. package/dist/core/create/timer.d.mts.map +1 -1
  55. package/dist/core/create/timer.mjs +6 -7
  56. package/dist/core/create/timer.mjs.map +1 -1
  57. package/dist/core/index.d.mts +0 -1
  58. package/dist/core/index.d.mts.map +1 -1
  59. package/dist/core/index.mjs +8 -13
  60. package/dist/core/index.mjs.map +1 -1
  61. package/dist/core/operators/audit.d.mts +97 -0
  62. package/dist/core/operators/audit.d.mts.map +1 -0
  63. package/dist/core/operators/audit.mjs +144 -0
  64. package/dist/core/operators/audit.mjs.map +1 -0
  65. package/dist/core/operators/debounce.d.mts +88 -0
  66. package/dist/core/operators/debounce.d.mts.map +1 -0
  67. package/dist/core/operators/debounce.mjs +130 -0
  68. package/dist/core/operators/debounce.mjs.map +1 -0
  69. package/dist/core/operators/filter.d.mts +6 -5
  70. package/dist/core/operators/filter.d.mts.map +1 -1
  71. package/dist/core/operators/filter.mjs +3 -3
  72. package/dist/core/operators/filter.mjs.map +1 -1
  73. package/dist/core/operators/index.d.mts +4 -4
  74. package/dist/core/operators/index.d.mts.map +1 -1
  75. package/dist/core/operators/index.mjs +4 -4
  76. package/dist/core/operators/{map-with-index.d.mts → map.d.mts} +12 -11
  77. package/dist/core/operators/map.d.mts.map +1 -0
  78. package/dist/core/operators/{map-with-index.mjs → map.mjs} +17 -17
  79. package/dist/core/operators/map.mjs.map +1 -0
  80. package/dist/core/operators/merge-map.d.mts +56 -29
  81. package/dist/core/operators/merge-map.d.mts.map +1 -1
  82. package/dist/core/operators/merge-map.mjs +58 -31
  83. package/dist/core/operators/merge-map.mjs.map +1 -1
  84. package/dist/core/operators/pairwise.d.mts +6 -6
  85. package/dist/core/operators/pairwise.mjs +9 -9
  86. package/dist/core/operators/pairwise.mjs.map +1 -1
  87. package/dist/core/operators/scan.d.mts +6 -6
  88. package/dist/core/operators/scan.mjs +9 -9
  89. package/dist/core/operators/scan.mjs.map +1 -1
  90. package/dist/core/operators/skip-if-no-change.d.mts +20 -8
  91. package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
  92. package/dist/core/operators/skip-if-no-change.mjs +23 -11
  93. package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
  94. package/dist/core/operators/skip-until.d.mts +5 -5
  95. package/dist/core/operators/skip-until.mjs +8 -8
  96. package/dist/core/operators/skip-until.mjs.map +1 -1
  97. package/dist/core/operators/skip-while.d.mts +19 -8
  98. package/dist/core/operators/skip-while.d.mts.map +1 -1
  99. package/dist/core/operators/skip-while.mjs +26 -11
  100. package/dist/core/operators/skip-while.mjs.map +1 -1
  101. package/dist/core/operators/switch-map.d.mts +57 -26
  102. package/dist/core/operators/switch-map.d.mts.map +1 -1
  103. package/dist/core/operators/switch-map.mjs +59 -28
  104. package/dist/core/operators/switch-map.mjs.map +1 -1
  105. package/dist/core/operators/take-until.d.mts +5 -5
  106. package/dist/core/operators/take-until.mjs +8 -8
  107. package/dist/core/operators/take-until.mjs.map +1 -1
  108. package/dist/core/operators/take-while.d.mts +16 -7
  109. package/dist/core/operators/take-while.d.mts.map +1 -1
  110. package/dist/core/operators/take-while.mjs +18 -10
  111. package/dist/core/operators/take-while.mjs.map +1 -1
  112. package/dist/core/operators/throttle.d.mts +81 -0
  113. package/dist/core/operators/throttle.d.mts.map +1 -0
  114. package/dist/core/operators/throttle.mjs +126 -0
  115. package/dist/core/operators/throttle.mjs.map +1 -0
  116. package/dist/core/operators/with-buffered-from.d.mts +9 -9
  117. package/dist/core/operators/with-buffered-from.mjs +12 -12
  118. package/dist/core/operators/with-buffered-from.mjs.map +1 -1
  119. package/dist/core/operators/with-current-value-from.d.mts +10 -9
  120. package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
  121. package/dist/core/operators/with-current-value-from.mjs +13 -12
  122. package/dist/core/operators/with-current-value-from.mjs.map +1 -1
  123. package/dist/core/operators/with-initial-value.d.mts +5 -5
  124. package/dist/core/operators/with-initial-value.mjs +8 -8
  125. package/dist/core/operators/with-initial-value.mjs.map +1 -1
  126. package/dist/core/predefined/index.mjs +0 -1
  127. package/dist/core/predefined/index.mjs.map +1 -1
  128. package/dist/core/predefined/operators/attach-index.d.mts +50 -0
  129. package/dist/core/predefined/operators/attach-index.d.mts.map +1 -1
  130. package/dist/core/predefined/operators/attach-index.mjs +51 -2
  131. package/dist/core/predefined/operators/attach-index.mjs.map +1 -1
  132. package/dist/core/predefined/operators/index.d.mts +0 -1
  133. package/dist/core/predefined/operators/index.d.mts.map +1 -1
  134. package/dist/core/predefined/operators/index.mjs +0 -1
  135. package/dist/core/predefined/operators/index.mjs.map +1 -1
  136. package/dist/core/predefined/operators/map-optional.d.mts +48 -1
  137. package/dist/core/predefined/operators/map-optional.d.mts.map +1 -1
  138. package/dist/core/predefined/operators/map-optional.mjs +49 -1
  139. package/dist/core/predefined/operators/map-optional.mjs.map +1 -1
  140. package/dist/core/predefined/operators/map-result-err.d.mts +48 -1
  141. package/dist/core/predefined/operators/map-result-err.d.mts.map +1 -1
  142. package/dist/core/predefined/operators/map-result-err.mjs +49 -1
  143. package/dist/core/predefined/operators/map-result-err.mjs.map +1 -1
  144. package/dist/core/predefined/operators/map-result-ok.d.mts +48 -1
  145. package/dist/core/predefined/operators/map-result-ok.d.mts.map +1 -1
  146. package/dist/core/predefined/operators/map-result-ok.mjs +49 -1
  147. package/dist/core/predefined/operators/map-result-ok.mjs.map +1 -1
  148. package/dist/core/predefined/operators/map-to.d.mts +40 -0
  149. package/dist/core/predefined/operators/map-to.d.mts.map +1 -1
  150. package/dist/core/predefined/operators/map-to.mjs +43 -1
  151. package/dist/core/predefined/operators/map-to.mjs.map +1 -1
  152. package/dist/core/predefined/operators/pluck.d.mts +39 -0
  153. package/dist/core/predefined/operators/pluck.d.mts.map +1 -1
  154. package/dist/core/predefined/operators/pluck.mjs +42 -1
  155. package/dist/core/predefined/operators/pluck.mjs.map +1 -1
  156. package/dist/core/predefined/operators/skip.d.mts +48 -0
  157. package/dist/core/predefined/operators/skip.d.mts.map +1 -1
  158. package/dist/core/predefined/operators/skip.mjs +47 -0
  159. package/dist/core/predefined/operators/skip.mjs.map +1 -1
  160. package/dist/core/predefined/operators/take.d.mts +42 -0
  161. package/dist/core/predefined/operators/take.d.mts.map +1 -1
  162. package/dist/core/predefined/operators/take.mjs +41 -0
  163. package/dist/core/predefined/operators/take.mjs.map +1 -1
  164. package/dist/core/predefined/operators/unwrap-optional.d.mts +41 -1
  165. package/dist/core/predefined/operators/unwrap-optional.d.mts.map +1 -1
  166. package/dist/core/predefined/operators/unwrap-optional.mjs +42 -1
  167. package/dist/core/predefined/operators/unwrap-optional.mjs.map +1 -1
  168. package/dist/core/predefined/operators/unwrap-result-err.d.mts +41 -1
  169. package/dist/core/predefined/operators/unwrap-result-err.d.mts.map +1 -1
  170. package/dist/core/predefined/operators/unwrap-result-err.mjs +42 -1
  171. package/dist/core/predefined/operators/unwrap-result-err.mjs.map +1 -1
  172. package/dist/core/predefined/operators/unwrap-result-ok.d.mts +41 -1
  173. package/dist/core/predefined/operators/unwrap-result-ok.d.mts.map +1 -1
  174. package/dist/core/predefined/operators/unwrap-result-ok.mjs +42 -1
  175. package/dist/core/predefined/operators/unwrap-result-ok.mjs.map +1 -1
  176. package/dist/core/types/id.d.mts +2 -1
  177. package/dist/core/types/id.d.mts.map +1 -1
  178. package/dist/core/types/index.d.mts +1 -0
  179. package/dist/core/types/index.d.mts.map +1 -1
  180. package/dist/core/types/observable-family.d.mts +10 -14
  181. package/dist/core/types/observable-family.d.mts.map +1 -1
  182. package/dist/core/types/observable-kind.d.mts +1 -0
  183. package/dist/core/types/observable-kind.d.mts.map +1 -1
  184. package/dist/core/types/observable.d.mts +5 -3
  185. package/dist/core/types/observable.d.mts.map +1 -1
  186. package/dist/core/types/observable.mjs.map +1 -1
  187. package/dist/core/types/timer.d.mts +2 -0
  188. package/dist/core/types/timer.d.mts.map +1 -0
  189. package/dist/core/types/timer.mjs +2 -0
  190. package/dist/core/types/timer.mjs.map +1 -0
  191. package/dist/core/utils/id-maker.d.mts +2 -2
  192. package/dist/core/utils/id-maker.d.mts.map +1 -1
  193. package/dist/core/utils/id-maker.mjs +3 -3
  194. package/dist/core/utils/id-maker.mjs.map +1 -1
  195. package/dist/core/utils/index.mjs +1 -1
  196. package/dist/core/utils/utils.d.mts +2 -0
  197. package/dist/core/utils/utils.d.mts.map +1 -1
  198. package/dist/core/utils/utils.mjs.map +1 -1
  199. package/dist/entry-point.mjs +11 -14
  200. package/dist/entry-point.mjs.map +1 -1
  201. package/dist/index.mjs +11 -14
  202. package/dist/index.mjs.map +1 -1
  203. package/dist/types.d.mts +1 -2
  204. package/dist/utils/collect-to-array.d.mts +3 -0
  205. package/dist/utils/collect-to-array.d.mts.map +1 -0
  206. package/dist/utils/collect-to-array.mjs +11 -0
  207. package/dist/utils/collect-to-array.mjs.map +1 -0
  208. package/dist/utils/create-boolean-state.d.mts +40 -0
  209. package/dist/utils/create-boolean-state.d.mts.map +1 -0
  210. package/dist/utils/create-boolean-state.mjs +53 -0
  211. package/dist/utils/create-boolean-state.mjs.map +1 -0
  212. package/dist/utils/create-event-emitter.d.mts +4 -4
  213. package/dist/utils/create-event-emitter.mjs +4 -4
  214. package/dist/utils/create-reducer.d.mts +11 -7
  215. package/dist/utils/create-reducer.d.mts.map +1 -1
  216. package/dist/utils/create-reducer.mjs +7 -7
  217. package/dist/utils/create-reducer.mjs.map +1 -1
  218. package/dist/utils/create-state.d.mts +8 -48
  219. package/dist/utils/create-state.d.mts.map +1 -1
  220. package/dist/utils/create-state.mjs +10 -60
  221. package/dist/utils/create-state.mjs.map +1 -1
  222. package/dist/utils/index.d.mts +2 -0
  223. package/dist/utils/index.d.mts.map +1 -1
  224. package/dist/utils/index.mjs +3 -1
  225. package/dist/utils/index.mjs.map +1 -1
  226. package/package.json +21 -14
  227. package/src/core/class/child-observable-class.mts +68 -14
  228. package/src/core/class/circular-dependency-comparison.test.mts +142 -0
  229. package/src/core/class/circular-dependency.test.mts +251 -0
  230. package/src/core/class/observable-base-class.mts +10 -9
  231. package/src/core/class/root-observable-class.mts +15 -10
  232. package/src/core/combine/combine.mts +14 -13
  233. package/src/core/combine/merge.mts +14 -14
  234. package/src/core/combine/zip.mts +27 -25
  235. package/src/core/create/{interval.mts → counter.mts} +32 -30
  236. package/src/core/create/from-abortable-promise.mts +83 -0
  237. package/src/core/create/from-promise.mts +10 -7
  238. package/src/core/create/from-subscribable.mts +4 -4
  239. package/src/core/create/index.mts +3 -3
  240. package/src/core/create/just.mts +43 -0
  241. package/src/core/create/source.mts +10 -14
  242. package/src/core/create/timer.mts +12 -11
  243. package/src/core/index.mts +0 -1
  244. package/src/core/operators/audit.mts +172 -0
  245. package/src/core/operators/debounce.mts +154 -0
  246. package/src/core/operators/filter.mts +9 -9
  247. package/src/core/operators/index.mts +4 -4
  248. package/src/core/operators/{map-with-index.mts → map.mts} +20 -20
  249. package/src/core/operators/merge-map.mts +59 -32
  250. package/src/core/operators/pairwise.mts +10 -10
  251. package/src/core/operators/scan.mts +10 -10
  252. package/src/core/operators/skip-if-no-change.mts +24 -12
  253. package/src/core/operators/skip-until.mts +9 -9
  254. package/src/core/operators/skip-while.mts +29 -12
  255. package/src/core/operators/switch-map.mts +60 -29
  256. package/src/core/operators/take-until.mts +9 -9
  257. package/src/core/operators/take-while.mts +19 -11
  258. package/src/core/operators/{throttle-time.mts → throttle.mts} +58 -38
  259. package/src/core/operators/with-buffered-from.mts +13 -13
  260. package/src/core/operators/with-current-value-from.mts +14 -13
  261. package/src/core/operators/with-initial-value.mts +9 -9
  262. package/src/core/predefined/operators/attach-index.mts +52 -2
  263. package/src/core/predefined/operators/index.mts +0 -1
  264. package/src/core/predefined/operators/map-optional.mts +49 -2
  265. package/src/core/predefined/operators/map-result-err.mts +49 -2
  266. package/src/core/predefined/operators/map-result-ok.mts +49 -2
  267. package/src/core/predefined/operators/map-to.mts +41 -1
  268. package/src/core/predefined/operators/pluck.mts +40 -1
  269. package/src/core/predefined/operators/skip.mts +48 -0
  270. package/src/core/predefined/operators/take.mts +42 -0
  271. package/src/core/predefined/operators/unwrap-optional.mts +43 -2
  272. package/src/core/predefined/operators/unwrap-result-err.mts +43 -2
  273. package/src/core/predefined/operators/unwrap-result-ok.mts +43 -2
  274. package/src/core/types/id.mts +3 -1
  275. package/src/core/types/index.mts +1 -0
  276. package/src/core/types/observable-family.mts +13 -24
  277. package/src/core/types/observable-kind.mts +2 -0
  278. package/src/core/types/observable.mts +5 -4
  279. package/src/core/types/timer.mts +2 -0
  280. package/src/core/utils/id-maker.mts +4 -4
  281. package/src/core/utils/utils.mts +1 -0
  282. package/src/utils/collect-to-array.mts +17 -0
  283. package/src/utils/create-boolean-state.mts +68 -0
  284. package/src/utils/create-event-emitter.mts +4 -4
  285. package/src/utils/create-reducer.mts +12 -8
  286. package/src/utils/create-state.mts +10 -75
  287. package/src/utils/index.mts +2 -0
  288. package/dist/core/create/from-array.d.mts +0 -39
  289. package/dist/core/create/from-array.d.mts.map +0 -1
  290. package/dist/core/create/from-array.mjs +0 -65
  291. package/dist/core/create/from-array.mjs.map +0 -1
  292. package/dist/core/create/interval.d.mts.map +0 -1
  293. package/dist/core/create/interval.mjs.map +0 -1
  294. package/dist/core/create/of.d.mts +0 -39
  295. package/dist/core/create/of.d.mts.map +0 -1
  296. package/dist/core/create/of.mjs +0 -63
  297. package/dist/core/create/of.mjs.map +0 -1
  298. package/dist/core/operators/audit-time.d.mts +0 -62
  299. package/dist/core/operators/audit-time.d.mts.map +0 -1
  300. package/dist/core/operators/audit-time.mjs +0 -109
  301. package/dist/core/operators/audit-time.mjs.map +0 -1
  302. package/dist/core/operators/debounce-time.d.mts +0 -51
  303. package/dist/core/operators/debounce-time.d.mts.map +0 -1
  304. package/dist/core/operators/debounce-time.mjs +0 -93
  305. package/dist/core/operators/debounce-time.mjs.map +0 -1
  306. package/dist/core/operators/map-with-index.d.mts.map +0 -1
  307. package/dist/core/operators/map-with-index.mjs.map +0 -1
  308. package/dist/core/operators/throttle-time.d.mts +0 -62
  309. package/dist/core/operators/throttle-time.d.mts.map +0 -1
  310. package/dist/core/operators/throttle-time.mjs +0 -107
  311. package/dist/core/operators/throttle-time.mjs.map +0 -1
  312. package/dist/core/predefined/operators/map.d.mts +0 -3
  313. package/dist/core/predefined/operators/map.d.mts.map +0 -1
  314. package/dist/core/predefined/operators/map.mjs +0 -8
  315. package/dist/core/predefined/operators/map.mjs.map +0 -1
  316. package/dist/globals.d.mts +0 -4
  317. package/src/core/create/from-array.mts +0 -76
  318. package/src/core/create/of.mts +0 -73
  319. package/src/core/operators/audit-time.mts +0 -136
  320. package/src/core/operators/debounce-time.mts +0 -116
  321. package/src/core/predefined/operators/map.mts +0 -5
  322. package/src/globals.d.mts +0 -4
  323. /package/assets/{synstate-icon.png → old/synstate-icon.png} +0 -0
@@ -5,7 +5,7 @@ import {
5
5
  type MergeMapOperatorObservable,
6
6
  type Observable,
7
7
  type Subscription,
8
- type UpdaterSymbol,
8
+ type UpdateToken,
9
9
  } from '../types/index.mjs';
10
10
 
11
11
  /**
@@ -21,56 +21,83 @@ import {
21
21
  * ```ts
22
22
  * // Timeline:
23
23
  * //
24
- * // ids$ 1 2 3
25
- * // requests fetch(1) fetch(2) fetch(3)
26
- * // users$ result1 result2 result3
27
- * // (parallel) (parallel) (parallel)
24
+ * // input$ A B C
25
+ * // inner A A1 A2 A3
26
+ * // inner B B1 B2 B3
27
+ * // inner C C1 C2 C3
28
+ * // result$ A1 A2 A3 B1 B2 C1 B3 C2 C3
28
29
  * //
29
30
  * // Explanation:
30
- * // - mergeMap runs all inner observables in parallel
31
- * // - Results are emitted as they arrive (may be out of order)
32
- * // - Does NOT cancel previous requests
33
- * // - All requests run concurrently and all results are emitted
31
+ * // - mergeMap creates an inner observable for each source value
32
+ * // - Unlike switchMap, previous inner observables are NOT cancelled
33
+ * // - B's inner continues even after C arrives (B3 is still emitted)
34
+ * // - All inner observables run concurrently and their results are merged
34
35
  *
35
- * const ids$ = source<number>();
36
+ * const input$ = source<string>();
36
37
  *
37
- * const users$ = ids$.pipe(
38
- * mergeMap((id) => {
39
- * const result$ = source<{ id: number }>();
38
+ * const result$ = input$.pipe(
39
+ * mergeMap((letter) => {
40
+ * const inner$ = source<string>();
40
41
  *
41
42
  * setTimeout(() => {
42
- * result$.next({ id });
43
- *
44
- * result$.complete();
43
+ * inner$.next(`${letter}1`);
45
44
  * }, 10);
46
45
  *
47
- * return result$;
46
+ * setTimeout(() => {
47
+ * inner$.next(`${letter}2`);
48
+ * }, 110);
49
+ *
50
+ * setTimeout(() => {
51
+ * inner$.next(`${letter}3`);
52
+ * }, 210);
53
+ *
54
+ * return inner$;
48
55
  * }),
49
56
  * );
50
57
  *
51
- * const mut_history: { id: number }[] = [];
58
+ * const valueHistory: string[] = [];
52
59
  *
53
- * users$.subscribe((value) => {
54
- * mut_history.push(value);
60
+ * result$.subscribe((value) => {
61
+ * valueHistory.push(value);
55
62
  * });
56
63
  *
57
- * ids$.next(1);
64
+ * const sleep = (ms: number): Promise<void> =>
65
+ * new Promise((resolve) => {
66
+ * setTimeout(resolve, ms);
67
+ * });
58
68
  *
59
- * ids$.next(2);
69
+ * // Emit A - inner emits A1, A2, A3 at 10ms, 110ms, 210ms
70
+ * input$.next('A');
60
71
  *
61
- * ids$.next(3);
72
+ * await sleep(250);
62
73
  *
63
- * await new Promise((resolve) => {
64
- * setTimeout(resolve, 200);
65
- * });
74
+ * assert.deepStrictEqual(valueHistory, ['A1', 'A2', 'A3']);
75
+ *
76
+ * // Emit B - inner starts emitting B1, B2 at 10ms, 110ms
77
+ * input$.next('B');
78
+ *
79
+ * await sleep(150);
66
80
  *
67
- * assert.deepStrictEqual(mut_history.length, 3);
81
+ * assert.deepStrictEqual(valueHistory, ['A1', 'A2', 'A3', 'B1', 'B2']);
68
82
  *
69
- * assert.isTrue(mut_history.some((u) => u.id === 1));
83
+ * // Emit C while B's inner is still running (B3 at 210ms not yet fired)
84
+ * // Unlike switchMap, B's inner is NOT cancelled
85
+ * input$.next('C');
70
86
  *
71
- * assert.isTrue(mut_history.some((u) => u.id === 2));
87
+ * await sleep(250);
72
88
  *
73
- * assert.isTrue(mut_history.some((u) => u.id === 3));
89
+ * // B3 appears between C1 and C2, showing the merge behavior
90
+ * assert.deepStrictEqual(valueHistory, [
91
+ * 'A1',
92
+ * 'A2',
93
+ * 'A3',
94
+ * 'B1',
95
+ * 'B2',
96
+ * 'C1',
97
+ * 'B3',
98
+ * 'C2',
99
+ * 'C3',
100
+ * ]);
74
101
  * ```
75
102
  *
76
103
  * @note To improve code readability, consider using `createState` instead of `mergeMap`,
@@ -113,12 +140,12 @@ class MergeMapObservableClass<A, B>
113
140
  this.#mut_subscriptions = [];
114
141
  }
115
142
 
116
- override tryUpdate(updaterSymbol: UpdaterSymbol): void {
143
+ override tryUpdate(updateToken: UpdateToken): void {
117
144
  const par = this.parents[0];
118
145
 
119
146
  const sn = par.getSnapshot();
120
147
 
121
- if (par.updaterSymbol !== updaterSymbol || Optional.isNone(sn)) {
148
+ if (par.updateToken !== updateToken || Optional.isNone(sn)) {
122
149
  return; // skip update
123
150
  }
124
151
 
@@ -4,7 +4,7 @@ import {
4
4
  type DropInitialValueOperator,
5
5
  type Observable,
6
6
  type PairwiseOperatorObservable,
7
- type UpdaterSymbol,
7
+ type UpdateToken,
8
8
  } from '../types/index.mjs';
9
9
 
10
10
  /**
@@ -30,30 +30,30 @@ import {
30
30
  *
31
31
  * const pairs$ = num$.pipe(pairwise());
32
32
  *
33
- * const mut_history: (readonly [number, number])[] = [];
33
+ * const valueHistory: (readonly [number, number])[] = [];
34
34
  *
35
35
  * pairs$.subscribe(([prev, curr]) => {
36
- * mut_history.push([prev, curr]);
36
+ * valueHistory.push([prev, curr]);
37
37
  * });
38
38
  *
39
39
  * num$.next(1); // nothing logged
40
40
  *
41
- * assert.deepStrictEqual(mut_history, []);
41
+ * assert.deepStrictEqual(valueHistory, []);
42
42
  *
43
43
  * num$.next(2); // logs: 1, 2
44
44
  *
45
- * assert.deepStrictEqual(mut_history, [[1, 2]]);
45
+ * assert.deepStrictEqual(valueHistory, [[1, 2]]);
46
46
  *
47
47
  * num$.next(3); // logs: 2, 3
48
48
  *
49
- * assert.deepStrictEqual(mut_history, [
49
+ * assert.deepStrictEqual(valueHistory, [
50
50
  * [1, 2],
51
51
  * [2, 3],
52
52
  * ]);
53
53
  *
54
54
  * num$.next(4); // logs: 3, 4
55
55
  *
56
- * assert.deepStrictEqual(mut_history, [
56
+ * assert.deepStrictEqual(valueHistory, [
57
57
  * [1, 2],
58
58
  * [2, 3],
59
59
  * [3, 4],
@@ -83,12 +83,12 @@ class PairwiseObservableClass<A>
83
83
  this.#mut_previousValue = parentObservable.getSnapshot();
84
84
  }
85
85
 
86
- override tryUpdate(updaterSymbol: UpdaterSymbol): void {
86
+ override tryUpdate(updateToken: UpdateToken): void {
87
87
  const par = this.parents[0];
88
88
 
89
89
  const sn = par.getSnapshot();
90
90
 
91
- if (par.updaterSymbol !== updaterSymbol || Optional.isNone(sn)) {
91
+ if (par.updateToken !== updateToken || Optional.isNone(sn)) {
92
92
  return; // skip update
93
93
  }
94
94
 
@@ -100,7 +100,7 @@ class PairwiseObservableClass<A>
100
100
  this.#mut_previousValue = par.getSnapshot();
101
101
 
102
102
  if (cond) {
103
- this.setNext([prev.value, sn.value], updaterSymbol);
103
+ this.setNext([prev.value, sn.value], updateToken);
104
104
  }
105
105
  }
106
106
  }
@@ -3,7 +3,7 @@ import { InitializedSyncChildObservableClass } from '../class/index.mjs';
3
3
  import {
4
4
  type Observable,
5
5
  type ScanOperatorObservable,
6
- type UpdaterSymbol,
6
+ type UpdateToken,
7
7
  type WithInitialValueOperator,
8
8
  } from '../types/index.mjs';
9
9
 
@@ -35,25 +35,25 @@ import {
35
35
  *
36
36
  * const sum$ = num$.pipe(scan((acc, curr) => acc + curr, 0));
37
37
  *
38
- * const mut_history: number[] = [];
38
+ * const valueHistory: number[] = [];
39
39
  *
40
40
  * sum$.subscribe((x) => {
41
- * mut_history.push(x);
41
+ * valueHistory.push(x);
42
42
  * });
43
43
  *
44
- * assert.deepStrictEqual(mut_history, [0]);
44
+ * assert.deepStrictEqual(valueHistory, [0]);
45
45
  *
46
46
  * num$.next(1); // logs: 1
47
47
  *
48
- * assert.deepStrictEqual(mut_history, [0, 1]);
48
+ * assert.deepStrictEqual(valueHistory, [0, 1]);
49
49
  *
50
50
  * num$.next(2); // logs: 3
51
51
  *
52
- * assert.deepStrictEqual(mut_history, [0, 1, 3]);
52
+ * assert.deepStrictEqual(valueHistory, [0, 1, 3]);
53
53
  *
54
54
  * num$.next(3); // logs: 6
55
55
  *
56
- * assert.deepStrictEqual(mut_history, [0, 1, 3, 6]);
56
+ * assert.deepStrictEqual(valueHistory, [0, 1, 3, 6]);
57
57
  * ```
58
58
  */
59
59
  export const scan =
@@ -83,7 +83,7 @@ class ScanObservableClass<A, B>
83
83
  this.#reducer = reducer;
84
84
  }
85
85
 
86
- override tryUpdate(updaterSymbol: UpdaterSymbol): void {
86
+ override tryUpdate(updateToken: UpdateToken): void {
87
87
  const par = this.parents[0];
88
88
 
89
89
  const psn = par.getSnapshot();
@@ -91,13 +91,13 @@ class ScanObservableClass<A, B>
91
91
  const sn = this.getSnapshot();
92
92
 
93
93
  if (
94
- par.updaterSymbol !== updaterSymbol ||
94
+ par.updateToken !== updateToken ||
95
95
  Optional.isNone(psn) ||
96
96
  Optional.isNone(sn)
97
97
  ) {
98
98
  return; // skip update
99
99
  }
100
100
 
101
- this.setNext(this.#reducer(sn.value, psn.value), updaterSymbol);
101
+ this.setNext(this.#reducer(sn.value, psn.value), updateToken);
102
102
  }
103
103
  }
@@ -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