synstate 0.1.1 → 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 (309) hide show
  1. package/README.md +317 -298
  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 +7 -7
  14. package/dist/core/combine/combine.mjs +13 -14
  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 +1 -1
  53. package/dist/core/index.d.mts.map +1 -1
  54. package/dist/core/index.mjs +21 -14
  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 +6 -6
  70. package/dist/core/operators/map.d.mts +41 -0
  71. package/dist/core/operators/map.d.mts.map +1 -0
  72. package/dist/core/operators/map.mjs +71 -0
  73. package/dist/core/operators/map.mjs.map +1 -0
  74. package/dist/core/operators/merge-map.d.mts +57 -30
  75. package/dist/core/operators/merge-map.d.mts.map +1 -1
  76. package/dist/core/operators/merge-map.mjs +59 -32
  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 +21 -9
  85. package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
  86. package/dist/core/operators/skip-if-no-change.mjs +25 -13
  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 -9
  92. package/dist/core/operators/skip-while.d.mts.map +1 -1
  93. package/dist/core/operators/skip-while.mjs +28 -16
  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 -8
  103. package/dist/core/operators/take-while.d.mts.map +1 -1
  104. package/dist/core/operators/take-while.mjs +19 -13
  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 +13 -9
  111. package/dist/core/operators/with-buffered-from.d.mts.map +1 -1
  112. package/dist/core/operators/with-buffered-from.mjs +17 -13
  113. package/dist/core/operators/with-buffered-from.mjs.map +1 -1
  114. package/dist/core/operators/with-current-value-from.d.mts +14 -9
  115. package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
  116. package/dist/core/operators/with-current-value-from.mjs +18 -13
  117. package/dist/core/operators/with-current-value-from.mjs.map +1 -1
  118. package/dist/core/operators/with-initial-value.d.mts +5 -5
  119. package/dist/core/operators/with-initial-value.mjs +8 -8
  120. package/dist/core/operators/with-initial-value.mjs.map +1 -1
  121. package/dist/core/predefined/index.d.mts +2 -0
  122. package/dist/core/predefined/index.d.mts.map +1 -0
  123. package/dist/core/predefined/index.mjs +12 -0
  124. package/dist/core/predefined/index.mjs.map +1 -0
  125. package/dist/core/predefined/operators/attach-index.d.mts +57 -0
  126. package/dist/core/predefined/operators/attach-index.d.mts.map +1 -0
  127. package/dist/core/predefined/operators/attach-index.mjs +62 -0
  128. package/dist/core/predefined/operators/attach-index.mjs.map +1 -0
  129. package/dist/core/predefined/operators/index.d.mts +12 -0
  130. package/dist/core/predefined/operators/index.d.mts.map +1 -0
  131. package/dist/core/predefined/operators/index.mjs +12 -0
  132. package/dist/core/predefined/operators/index.mjs.map +1 -0
  133. package/dist/core/predefined/operators/map-optional.d.mts +51 -0
  134. package/dist/core/predefined/operators/map-optional.d.mts.map +1 -0
  135. package/dist/core/predefined/operators/map-optional.mjs +55 -0
  136. package/dist/core/predefined/operators/map-optional.mjs.map +1 -0
  137. package/dist/core/predefined/operators/map-result-err.d.mts +51 -0
  138. package/dist/core/predefined/operators/map-result-err.d.mts.map +1 -0
  139. package/dist/core/predefined/operators/map-result-err.mjs +55 -0
  140. package/dist/core/predefined/operators/map-result-err.mjs.map +1 -0
  141. package/dist/core/predefined/operators/map-result-ok.d.mts +51 -0
  142. package/dist/core/predefined/operators/map-result-ok.d.mts.map +1 -0
  143. package/dist/core/predefined/operators/map-result-ok.mjs +55 -0
  144. package/dist/core/predefined/operators/map-result-ok.mjs.map +1 -0
  145. package/dist/core/predefined/operators/map-to.d.mts +43 -0
  146. package/dist/core/predefined/operators/map-to.d.mts.map +1 -0
  147. package/dist/core/predefined/operators/map-to.mjs +48 -0
  148. package/dist/core/predefined/operators/map-to.mjs.map +1 -0
  149. package/dist/core/predefined/operators/pluck.d.mts +47 -0
  150. package/dist/core/predefined/operators/pluck.d.mts.map +1 -0
  151. package/dist/core/predefined/operators/pluck.mjs +52 -0
  152. package/dist/core/predefined/operators/pluck.mjs.map +1 -0
  153. package/dist/core/predefined/operators/skip.d.mts +50 -0
  154. package/dist/core/predefined/operators/skip.d.mts.map +1 -0
  155. package/dist/core/predefined/operators/skip.mjs +56 -0
  156. package/dist/core/predefined/operators/skip.mjs.map +1 -0
  157. package/dist/core/predefined/operators/take.d.mts +44 -0
  158. package/dist/core/predefined/operators/take.d.mts.map +1 -0
  159. package/dist/core/predefined/operators/take.mjs +49 -0
  160. package/dist/core/predefined/operators/take.mjs.map +1 -0
  161. package/dist/core/predefined/operators/unwrap-optional.d.mts +44 -0
  162. package/dist/core/predefined/operators/unwrap-optional.d.mts.map +1 -0
  163. package/dist/core/predefined/operators/unwrap-optional.mjs +50 -0
  164. package/dist/core/predefined/operators/unwrap-optional.mjs.map +1 -0
  165. package/dist/core/predefined/operators/unwrap-result-err.d.mts +44 -0
  166. package/dist/core/predefined/operators/unwrap-result-err.d.mts.map +1 -0
  167. package/dist/core/predefined/operators/unwrap-result-err.mjs +48 -0
  168. package/dist/core/predefined/operators/unwrap-result-err.mjs.map +1 -0
  169. package/dist/core/predefined/operators/unwrap-result-ok.d.mts +44 -0
  170. package/dist/core/predefined/operators/unwrap-result-ok.d.mts.map +1 -0
  171. package/dist/core/predefined/operators/unwrap-result-ok.mjs +50 -0
  172. package/dist/core/predefined/operators/unwrap-result-ok.mjs.map +1 -0
  173. package/dist/core/types/id.d.mts +1 -1
  174. package/dist/core/types/id.d.mts.map +1 -1
  175. package/dist/core/types/index.d.mts +1 -0
  176. package/dist/core/types/index.d.mts.map +1 -1
  177. package/dist/core/types/observable-family.d.mts +8 -14
  178. package/dist/core/types/observable-family.d.mts.map +1 -1
  179. package/dist/core/types/observable.d.mts +3 -3
  180. package/dist/core/types/observable.d.mts.map +1 -1
  181. package/dist/core/types/timer.d.mts +2 -0
  182. package/dist/core/types/timer.d.mts.map +1 -0
  183. package/dist/core/types/timer.mjs +2 -0
  184. package/dist/core/types/timer.mjs.map +1 -0
  185. package/dist/core/utils/id-maker.d.mts +2 -2
  186. package/dist/core/utils/id-maker.d.mts.map +1 -1
  187. package/dist/core/utils/id-maker.mjs +3 -3
  188. package/dist/core/utils/id-maker.mjs.map +1 -1
  189. package/dist/core/utils/index.mjs +1 -1
  190. package/dist/entry-point.mjs +24 -15
  191. package/dist/entry-point.mjs.map +1 -1
  192. package/dist/globals.d.mts +0 -3
  193. package/dist/index.mjs +24 -15
  194. package/dist/index.mjs.map +1 -1
  195. package/dist/utils/collect-to-array.d.mts +3 -0
  196. package/dist/utils/collect-to-array.d.mts.map +1 -0
  197. package/dist/utils/collect-to-array.mjs +11 -0
  198. package/dist/utils/collect-to-array.mjs.map +1 -0
  199. package/dist/utils/create-boolean-state.d.mts +40 -0
  200. package/dist/utils/create-boolean-state.d.mts.map +1 -0
  201. package/dist/utils/create-boolean-state.mjs +53 -0
  202. package/dist/utils/create-boolean-state.mjs.map +1 -0
  203. package/dist/utils/create-event-emitter.d.mts +4 -4
  204. package/dist/utils/create-event-emitter.mjs +4 -4
  205. package/dist/utils/create-reducer.d.mts +10 -7
  206. package/dist/utils/create-reducer.d.mts.map +1 -1
  207. package/dist/utils/create-reducer.mjs +7 -7
  208. package/dist/utils/create-reducer.mjs.map +1 -1
  209. package/dist/utils/create-state.d.mts +8 -48
  210. package/dist/utils/create-state.d.mts.map +1 -1
  211. package/dist/utils/create-state.mjs +10 -60
  212. package/dist/utils/create-state.mjs.map +1 -1
  213. package/dist/utils/index.d.mts +2 -0
  214. package/dist/utils/index.d.mts.map +1 -1
  215. package/dist/utils/index.mjs +3 -1
  216. package/dist/utils/index.mjs.map +1 -1
  217. package/package.json +17 -11
  218. package/src/core/class/child-observable-class.mts +65 -9
  219. package/src/core/class/circular-dependency-comparison.test.mts +142 -0
  220. package/src/core/class/circular-dependency.test.mts +251 -0
  221. package/src/core/class/observable-base-class.mts +9 -9
  222. package/src/core/class/root-observable-class.mts +14 -10
  223. package/src/core/combine/combine.mts +15 -15
  224. package/src/core/combine/merge.mts +13 -14
  225. package/src/core/combine/zip.mts +26 -25
  226. package/src/core/create/{interval.mts → counter.mts} +32 -30
  227. package/src/core/create/from-abortable-promise.mts +83 -0
  228. package/src/core/create/from-promise.mts +10 -7
  229. package/src/core/create/from-subscribable.mts +4 -4
  230. package/src/core/create/index.mts +3 -3
  231. package/src/core/create/just.mts +43 -0
  232. package/src/core/create/source.mts +10 -14
  233. package/src/core/create/timer.mts +12 -11
  234. package/src/core/index.mts +1 -1
  235. package/src/core/operators/audit.mts +172 -0
  236. package/src/core/operators/debounce.mts +154 -0
  237. package/src/core/operators/filter.mts +9 -9
  238. package/src/core/operators/index.mts +4 -4
  239. package/src/core/operators/map.mts +124 -0
  240. package/src/core/operators/merge-map.mts +60 -33
  241. package/src/core/operators/pairwise.mts +10 -10
  242. package/src/core/operators/scan.mts +10 -10
  243. package/src/core/operators/skip-if-no-change.mts +26 -14
  244. package/src/core/operators/skip-until.mts +9 -9
  245. package/src/core/operators/skip-while.mts +30 -28
  246. package/src/core/operators/switch-map.mts +60 -29
  247. package/src/core/operators/take-until.mts +9 -9
  248. package/src/core/operators/take-while.mts +21 -19
  249. package/src/core/operators/{throttle-time.mts → throttle.mts} +58 -38
  250. package/src/core/operators/with-buffered-from.mts +18 -14
  251. package/src/core/operators/with-current-value-from.mts +19 -14
  252. package/src/core/operators/with-initial-value.mts +9 -9
  253. package/src/core/predefined/index.mts +1 -0
  254. package/src/core/predefined/operators/attach-index.mts +62 -0
  255. package/src/core/predefined/operators/index.mts +11 -0
  256. package/src/core/predefined/operators/map-optional.mts +55 -0
  257. package/src/core/predefined/operators/map-result-err.mts +55 -0
  258. package/src/core/predefined/operators/map-result-ok.mts +55 -0
  259. package/src/core/predefined/operators/map-to.mts +45 -0
  260. package/src/core/predefined/operators/pluck.mts +51 -0
  261. package/src/core/predefined/operators/skip.mts +57 -0
  262. package/src/core/predefined/operators/take.mts +47 -0
  263. package/src/core/predefined/operators/unwrap-optional.mts +49 -0
  264. package/src/core/predefined/operators/unwrap-result-err.mts +48 -0
  265. package/src/core/predefined/operators/unwrap-result-ok.mts +49 -0
  266. package/src/core/types/id.mts +1 -1
  267. package/src/core/types/index.mts +1 -0
  268. package/src/core/types/observable-family.mts +8 -24
  269. package/src/core/types/observable.mts +3 -3
  270. package/src/core/types/timer.mts +2 -0
  271. package/src/core/utils/id-maker.mts +4 -4
  272. package/src/globals.d.mts +0 -3
  273. package/src/utils/collect-to-array.mts +17 -0
  274. package/src/utils/create-boolean-state.mts +68 -0
  275. package/src/utils/create-event-emitter.mts +4 -4
  276. package/src/utils/create-reducer.mts +11 -8
  277. package/src/utils/create-state.mts +10 -75
  278. package/src/utils/index.mts +2 -0
  279. package/dist/core/create/from-array.d.mts +0 -39
  280. package/dist/core/create/from-array.d.mts.map +0 -1
  281. package/dist/core/create/from-array.mjs +0 -65
  282. package/dist/core/create/from-array.mjs.map +0 -1
  283. package/dist/core/create/interval.d.mts.map +0 -1
  284. package/dist/core/create/interval.mjs.map +0 -1
  285. package/dist/core/create/of.d.mts +0 -39
  286. package/dist/core/create/of.d.mts.map +0 -1
  287. package/dist/core/create/of.mjs +0 -63
  288. package/dist/core/create/of.mjs.map +0 -1
  289. package/dist/core/operators/audit-time.d.mts +0 -62
  290. package/dist/core/operators/audit-time.d.mts.map +0 -1
  291. package/dist/core/operators/audit-time.mjs +0 -109
  292. package/dist/core/operators/audit-time.mjs.map +0 -1
  293. package/dist/core/operators/debounce-time.d.mts +0 -51
  294. package/dist/core/operators/debounce-time.d.mts.map +0 -1
  295. package/dist/core/operators/debounce-time.mjs +0 -93
  296. package/dist/core/operators/debounce-time.mjs.map +0 -1
  297. package/dist/core/operators/map-with-index.d.mts +0 -54
  298. package/dist/core/operators/map-with-index.d.mts.map +0 -1
  299. package/dist/core/operators/map-with-index.mjs +0 -88
  300. package/dist/core/operators/map-with-index.mjs.map +0 -1
  301. package/dist/core/operators/throttle-time.d.mts +0 -62
  302. package/dist/core/operators/throttle-time.d.mts.map +0 -1
  303. package/dist/core/operators/throttle-time.mjs +0 -107
  304. package/dist/core/operators/throttle-time.mjs.map +0 -1
  305. package/src/core/create/from-array.mts +0 -76
  306. package/src/core/create/of.mts +0 -73
  307. package/src/core/operators/audit-time.mts +0 -136
  308. package/src/core/operators/debounce-time.mts +0 -116
  309. package/src/core/operators/map-with-index.mts +0 -183
@@ -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
 
@@ -3,7 +3,7 @@ import { SyncChildObservableClass } from '../class/index.mjs';
3
3
  import {
4
4
  type KeepInitialValueOperator,
5
5
  type Observable,
6
- type UpdaterSymbol,
6
+ type UpdateToken,
7
7
  type WithBufferedFromOperatorObservable,
8
8
  } from '../types/index.mjs';
9
9
  import { maxDepth } from '../utils/index.mjs';
@@ -37,27 +37,27 @@ import { maxDepth } from '../utils/index.mjs';
37
37
  *
38
38
  * const result$ = trigger$.pipe(withBufferedFrom(data$));
39
39
  *
40
- * const mut_history: (readonly [number, readonly string[]])[] = [];
40
+ * const valueHistory: (readonly [number, readonly string[]])[] = [];
41
41
  *
42
42
  * result$.subscribe(([triggerValue, bufferedData]) => {
43
- * mut_history.push([triggerValue, bufferedData]);
43
+ * valueHistory.push([triggerValue, bufferedData]);
44
44
  * });
45
45
  *
46
- * data$.next('a');
46
+ * data$.next('A');
47
47
  *
48
- * data$.next('b');
48
+ * data$.next('B');
49
49
  *
50
50
  * trigger$.next(1);
51
51
  *
52
- * assert.deepStrictEqual(mut_history, [[1, ['a', 'b']]]);
52
+ * assert.deepStrictEqual(valueHistory, [[1, ['A', 'B']]]);
53
53
  *
54
- * data$.next('c');
54
+ * data$.next('C');
55
55
  *
56
56
  * trigger$.next(2);
57
57
  *
58
- * assert.deepStrictEqual(mut_history, [
59
- * [1, ['a', 'b']],
60
- * [2, ['c']],
58
+ * assert.deepStrictEqual(valueHistory, [
59
+ * [1, ['A', 'B']],
60
+ * [2, ['C']],
61
61
  * ]);
62
62
  * ```
63
63
  */
@@ -71,7 +71,11 @@ export const withBufferedFrom = <A, B>(
71
71
  observable,
72
72
  )) as KeepInitialValueOperator<A, readonly [A, readonly B[]]>;
73
73
 
74
- export const withBuffered = withBufferedFrom; // alias
74
+ /**
75
+ * Alias for `withBufferedFrom`.
76
+ * @see withBufferedFrom
77
+ */
78
+ export const withBuffered = withBufferedFrom;
75
79
 
76
80
  class WithBufferedFromObservableClass<A, B>
77
81
  extends SyncChildObservableClass<readonly [A, readonly B[]], readonly [A]>
@@ -101,16 +105,16 @@ class WithBufferedFromObservableClass<A, B>
101
105
  });
102
106
  }
103
107
 
104
- override tryUpdate(updaterSymbol: UpdaterSymbol): void {
108
+ override tryUpdate(updateToken: UpdateToken): void {
105
109
  const par = this.parents[0];
106
110
 
107
111
  const sn = par.getSnapshot();
108
112
 
109
- if (par.updaterSymbol !== updaterSymbol || Optional.isNone(sn)) {
113
+ if (par.updateToken !== updateToken || Optional.isNone(sn)) {
110
114
  return; // skip update
111
115
  }
112
116
 
113
- this.setNext([sn.value, this.#mut_bufferedValues], updaterSymbol);
117
+ this.setNext([sn.value, this.#mut_bufferedValues], updateToken);
114
118
 
115
119
  this.#clearBuffer();
116
120
  }
@@ -3,7 +3,7 @@ import { SyncChildObservableClass } from '../class/index.mjs';
3
3
  import {
4
4
  type DropInitialValueOperator,
5
5
  type Observable,
6
- type UpdaterSymbol,
6
+ type UpdateToken,
7
7
  type WithCurrentValueFromOperatorObservable,
8
8
  } from '../types/index.mjs';
9
9
  import { maxDepth } from '../utils/index.mjs';
@@ -22,14 +22,15 @@ import { maxDepth } from '../utils/index.mjs';
22
22
  * // Timeline:
23
23
  * //
24
24
  * // name$ "Alice" "Bob" "Charlie"
25
- * // age$ 25 30 35 40
26
- * // result$ ["Alice",25] ["Bob",30] ["Bob",35] ["Charlie",40]
25
+ * // age$ 25 30
26
+ * // result$ (skip) ["Bob",25] ["Charlie",30]
27
27
  * //
28
28
  * // Explanation:
29
29
  * // - withCurrentValueFrom samples the current value from another observable
30
- * // - Emits a tuple [sourceValue, sampledValue] each time the source emits
30
+ * // - Emits a tuple [sourceValue, sampledValue] each time the SOURCE emits
31
+ * // - Does NOT emit when the sampled observable (age$) emits
31
32
  * // - Does not emit until both observables have emitted at least once
32
- * // - Similar to combine, but only emits when the source (not the sampled) emits
33
+ * // - "Alice" is skipped because age$ hasn't emitted yet
33
34
  *
34
35
  * const name$ = source<string>();
35
36
  *
@@ -37,27 +38,27 @@ import { maxDepth } from '../utils/index.mjs';
37
38
  *
38
39
  * const result$ = name$.pipe(withCurrentValueFrom(age$));
39
40
  *
40
- * const mut_history: (readonly [string, number])[] = [];
41
+ * const valueHistory: (readonly [string, number])[] = [];
41
42
  *
42
43
  * result$.subscribe(([name_, currentAge]) => {
43
- * mut_history.push([name_, currentAge]);
44
+ * valueHistory.push([name_, currentAge]);
44
45
  * });
45
46
  *
46
47
  * name$.next('Alice'); // nothing logged (age$ hasn't emitted)
47
48
  *
48
- * assert.deepStrictEqual(mut_history, []);
49
+ * assert.deepStrictEqual(valueHistory, []);
49
50
  *
50
51
  * age$.next(25);
51
52
  *
52
53
  * name$.next('Bob'); // logs: Bob is 25 years old
53
54
  *
54
- * assert.deepStrictEqual(mut_history, [['Bob', 25]]);
55
+ * assert.deepStrictEqual(valueHistory, [['Bob', 25]]);
55
56
  *
56
57
  * age$.next(30);
57
58
  *
58
59
  * name$.next('Charlie'); // logs: Charlie is 30 years old
59
60
  *
60
- * assert.deepStrictEqual(mut_history, [
61
+ * assert.deepStrictEqual(valueHistory, [
61
62
  * ['Bob', 25],
62
63
  * ['Charlie', 30],
63
64
  * ]);
@@ -70,7 +71,11 @@ export const withCurrentValueFrom =
70
71
  (parentObservable) =>
71
72
  new WithCurrentValueFromObservableClass(parentObservable, observable);
72
73
 
73
- export const withLatestFrom = withCurrentValueFrom; // alias
74
+ /**
75
+ * Alias for `withCurrentValueFrom`.
76
+ * @see withCurrentValueFrom
77
+ */
78
+ export const withLatestFrom = withCurrentValueFrom;
74
79
 
75
80
  class WithCurrentValueFromObservableClass<A, B>
76
81
  extends SyncChildObservableClass<readonly [A, B], readonly [A]>
@@ -95,12 +100,12 @@ class WithCurrentValueFromObservableClass<A, B>
95
100
  this.#observable = observable;
96
101
  }
97
102
 
98
- override tryUpdate(updaterSymbol: UpdaterSymbol): void {
103
+ override tryUpdate(updateToken: UpdateToken): void {
99
104
  const par = this.parents[0];
100
105
 
101
106
  const ps = par.getSnapshot();
102
107
 
103
- if (par.updaterSymbol !== updaterSymbol || Optional.isNone(ps)) {
108
+ if (par.updateToken !== updateToken || Optional.isNone(ps)) {
104
109
  return; // skip update
105
110
  }
106
111
 
@@ -108,6 +113,6 @@ class WithCurrentValueFromObservableClass<A, B>
108
113
 
109
114
  if (Optional.isNone(curr)) return; // skip update
110
115
 
111
- this.setNext([ps.value, curr.value], updaterSymbol);
116
+ this.setNext([ps.value, curr.value], updateToken);
112
117
  }
113
118
  }
@@ -4,7 +4,7 @@ import { source } from '../create/index.mjs';
4
4
  import {
5
5
  type InitializedObservable,
6
6
  type Observable,
7
- type UpdaterSymbol,
7
+ type UpdateToken,
8
8
  type WithInitialValueOperator,
9
9
  type WithInitialValueOperatorObservable,
10
10
  } from '../types/index.mjs';
@@ -37,21 +37,21 @@ import {
37
37
  *
38
38
  * const initialized$ = num$.pipe(withInitialValue(0));
39
39
  *
40
- * const mut_history: number[] = [];
40
+ * const valueHistory: number[] = [];
41
41
  *
42
42
  * initialized$.subscribe((x) => {
43
- * mut_history.push(x);
43
+ * valueHistory.push(x);
44
44
  * });
45
45
  *
46
- * assert.deepStrictEqual(mut_history, [0]);
46
+ * assert.deepStrictEqual(valueHistory, [0]);
47
47
  *
48
48
  * num$.next(1); // logs: 1
49
49
  *
50
- * assert.deepStrictEqual(mut_history, [0, 1]);
50
+ * assert.deepStrictEqual(valueHistory, [0, 1]);
51
51
  *
52
52
  * num$.next(2); // logs: 2
53
53
  *
54
- * assert.deepStrictEqual(mut_history, [0, 1, 2]);
54
+ * assert.deepStrictEqual(valueHistory, [0, 1, 2]);
55
55
  * ```
56
56
  */
57
57
  export const withInitialValue =
@@ -70,16 +70,16 @@ class WithInitialValueObservableClass<A, I>
70
70
  });
71
71
  }
72
72
 
73
- override tryUpdate(updaterSymbol: UpdaterSymbol): void {
73
+ override tryUpdate(updateToken: UpdateToken): void {
74
74
  const par = this.parents[0];
75
75
 
76
76
  const sn = par.getSnapshot();
77
77
 
78
- if (par.updaterSymbol !== updaterSymbol || Optional.isNone(sn)) {
78
+ if (par.updateToken !== updateToken || Optional.isNone(sn)) {
79
79
  return; // skip update
80
80
  }
81
81
 
82
- this.setNext(sn.value, updaterSymbol);
82
+ this.setNext(sn.value, updateToken);
83
83
  }
84
84
  }
85
85
 
@@ -0,0 +1 @@
1
+ export * from './operators/index.mjs';
@@ -0,0 +1,62 @@
1
+ import { map } from '../../operators/index.mjs';
2
+ import { type KeepInitialValueOperator } from '../../types/index.mjs';
3
+
4
+ /**
5
+ * Attaches a sequential index to each emitted value, producing `[index, value]` tuples.
6
+ * Index starts at 0 and increments with each emission.
7
+ *
8
+ * @template A - The type of values from the source
9
+ * @returns An operator that emits `[index, value]` tuples
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * // Timeline:
14
+ * //
15
+ * // letter$ "A" "B" "C"
16
+ * // indexed$ [0,"A"] [1,"B"] [2,"C"]
17
+ * //
18
+ * // Explanation:
19
+ * // - attachIndex attaches a sequential index to each emitted value
20
+ * // - Produces [index, value] tuples
21
+ * // - Index starts at 0 and increments with each emission
22
+ *
23
+ * const letter$ = source<string>();
24
+ *
25
+ * const indexed$ = letter$.pipe(attachIndex());
26
+ *
27
+ * const valueHistory: (readonly [number, string])[] = [];
28
+ *
29
+ * indexed$.subscribe(([i, letter]) => {
30
+ * valueHistory.push([i, letter]);
31
+ * });
32
+ *
33
+ * letter$.next('A');
34
+ *
35
+ * assert.deepStrictEqual(valueHistory, [[0, 'A']]);
36
+ *
37
+ * letter$.next('B');
38
+ *
39
+ * assert.deepStrictEqual(valueHistory, [
40
+ * [0, 'A'],
41
+ * [1, 'B'],
42
+ * ]);
43
+ *
44
+ * letter$.next('C');
45
+ *
46
+ * assert.deepStrictEqual(valueHistory, [
47
+ * [0, 'A'],
48
+ * [1, 'B'],
49
+ * [2, 'C'],
50
+ * ]);
51
+ * ```
52
+ */
53
+ export const withIndex = <A,>(): KeepInitialValueOperator<
54
+ A,
55
+ readonly [SafeUint | -1, A]
56
+ > => map((a, i) => [i, a] as const);
57
+
58
+ /**
59
+ * Alias for `withIndex`.
60
+ * @see withIndex
61
+ */
62
+ export const attachIndex = withIndex;
@@ -0,0 +1,11 @@
1
+ export * from './attach-index.mjs';
2
+ export * from './map-optional.mjs';
3
+ export * from './map-result-err.mjs';
4
+ export * from './map-result-ok.mjs';
5
+ export * from './map-to.mjs';
6
+ export * from './pluck.mjs';
7
+ export * from './skip.mjs';
8
+ export * from './take.mjs';
9
+ export * from './unwrap-optional.mjs';
10
+ export * from './unwrap-result-err.mjs';
11
+ export * from './unwrap-result-ok.mjs';
@@ -0,0 +1,55 @@
1
+ import { Optional } from 'ts-data-forge';
2
+ import { map } from '../../operators/index.mjs';
3
+ import { type KeepInitialValueOperator } from '../../types/index.mjs';
4
+
5
+ /**
6
+ * Transforms the inner value of an `Optional` type emitted by the source.
7
+ * If the value is `Some`, the mapping function is applied; if `None`, it remains `None`.
8
+ *
9
+ * @template O - The Optional type from the source
10
+ * @template B - The type of the mapped inner value
11
+ * @param mapFn - A function to transform the unwrapped value
12
+ * @returns An operator that maps the inner value of Optional emissions
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * // Timeline:
17
+ * //
18
+ * // value$ Some(2) None Some(5)
19
+ * // doubled$ Some(4) None Some(10)
20
+ * //
21
+ * // Explanation:
22
+ * // - mapOptional transforms the inner value of Optional emissions
23
+ * // - Some values are mapped; None values pass through unchanged
24
+ *
25
+ * const value$ = source<Optional<number>>();
26
+ *
27
+ * const doubled$ = value$.pipe(mapOptional((x) => x * 2));
28
+ *
29
+ * const valueHistory: Optional<number>[] = [];
30
+ *
31
+ * doubled$.subscribe((v) => {
32
+ * valueHistory.push(v);
33
+ * });
34
+ *
35
+ * value$.next(Optional.some(2));
36
+ *
37
+ * assert.deepStrictEqual(valueHistory, [Optional.some(4)]);
38
+ *
39
+ * value$.next(Optional.none);
40
+ *
41
+ * assert.deepStrictEqual(valueHistory, [Optional.some(4), Optional.none]);
42
+ *
43
+ * value$.next(Optional.some(5));
44
+ *
45
+ * assert.deepStrictEqual(valueHistory, [
46
+ * Optional.some(4),
47
+ * Optional.none,
48
+ * Optional.some(10),
49
+ * ]);
50
+ * ```
51
+ */
52
+ export const mapOptional = <O extends UnknownOptional, B>(
53
+ mapFn: (x: Optional.Unwrap<O>) => B,
54
+ ): KeepInitialValueOperator<O, Optional<B>> =>
55
+ map((a) => Optional.map(a, mapFn));
@@ -0,0 +1,55 @@
1
+ import { Result } from 'ts-data-forge';
2
+ import { map } from '../../operators/index.mjs';
3
+ import { type KeepInitialValueOperator } from '../../types/index.mjs';
4
+
5
+ /**
6
+ * Transforms the error value (`Err`) of a `Result` type emitted by the source.
7
+ * If the value is `Err`, the mapping function is applied; if `Ok`, it remains unchanged.
8
+ *
9
+ * @template R - The Result type from the source
10
+ * @template E2 - The type of the mapped error value
11
+ * @param mapFn - A function to transform the Err value
12
+ * @returns An operator that maps the Err side of Result emissions
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * // Timeline:
17
+ * //
18
+ * // result$ Ok(1) Err("bad") Err("fail")
19
+ * // mapped$ Ok(1) Err("BAD") Err("FAIL")
20
+ * //
21
+ * // Explanation:
22
+ * // - mapResultErr transforms the Err value of Result emissions
23
+ * // - Ok values pass through unchanged
24
+ *
25
+ * const result$ = source<Result<number, string>>();
26
+ *
27
+ * const mapped$ = result$.pipe(mapResultErr((e) => e.toUpperCase()));
28
+ *
29
+ * const valueHistory: Result<number, string>[] = [];
30
+ *
31
+ * mapped$.subscribe((v) => {
32
+ * valueHistory.push(v);
33
+ * });
34
+ *
35
+ * result$.next(Result.ok(1));
36
+ *
37
+ * assert.deepStrictEqual(valueHistory, [Result.ok(1)]);
38
+ *
39
+ * result$.next(Result.err('bad'));
40
+ *
41
+ * assert.deepStrictEqual(valueHistory, [Result.ok(1), Result.err('BAD')]);
42
+ *
43
+ * result$.next(Result.err('fail'));
44
+ *
45
+ * assert.deepStrictEqual(valueHistory, [
46
+ * Result.ok(1),
47
+ * Result.err('BAD'),
48
+ * Result.err('FAIL'),
49
+ * ]);
50
+ * ```
51
+ */
52
+ export const mapResultErr = <R extends UnknownResult, E2>(
53
+ mapFn: (x: Result.UnwrapErr<R>) => E2,
54
+ ): KeepInitialValueOperator<R, Result<Result.UnwrapOk<R>, E2>> =>
55
+ map((a) => Result.mapErr(a, mapFn));
@@ -0,0 +1,55 @@
1
+ import { Result } from 'ts-data-forge';
2
+ import { map } from '../../operators/index.mjs';
3
+ import { type KeepInitialValueOperator } from '../../types/index.mjs';
4
+
5
+ /**
6
+ * Transforms the success value (`Ok`) of a `Result` type emitted by the source.
7
+ * If the value is `Ok`, the mapping function is applied; if `Err`, it remains unchanged.
8
+ *
9
+ * @template R - The Result type from the source
10
+ * @template S2 - The type of the mapped success value
11
+ * @param mapFn - A function to transform the Ok value
12
+ * @returns An operator that maps the Ok side of Result emissions
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * // Timeline:
17
+ * //
18
+ * // result$ Ok(2) Err("e") Ok(5)
19
+ * // doubled$ Ok(4) Err("e") Ok(10)
20
+ * //
21
+ * // Explanation:
22
+ * // - mapResultOk transforms the Ok value of Result emissions
23
+ * // - Err values pass through unchanged
24
+ *
25
+ * const result$ = source<Result<number, string>>();
26
+ *
27
+ * const doubled$ = result$.pipe(mapResultOk((x) => x * 2));
28
+ *
29
+ * const valueHistory: Result<number, string>[] = [];
30
+ *
31
+ * doubled$.subscribe((v) => {
32
+ * valueHistory.push(v);
33
+ * });
34
+ *
35
+ * result$.next(Result.ok(2));
36
+ *
37
+ * assert.deepStrictEqual(valueHistory, [Result.ok(4)]);
38
+ *
39
+ * result$.next(Result.err('e'));
40
+ *
41
+ * assert.deepStrictEqual(valueHistory, [Result.ok(4), Result.err('e')]);
42
+ *
43
+ * result$.next(Result.ok(5));
44
+ *
45
+ * assert.deepStrictEqual(valueHistory, [
46
+ * Result.ok(4),
47
+ * Result.err('e'),
48
+ * Result.ok(10),
49
+ * ]);
50
+ * ```
51
+ */
52
+ export const mapResultOk = <R extends UnknownResult, S2>(
53
+ mapFn: (x: Result.UnwrapOk<R>) => S2,
54
+ ): KeepInitialValueOperator<R, Result<S2, Result.UnwrapErr<R>>> =>
55
+ map((a) => Result.map(a, mapFn));
@@ -0,0 +1,45 @@
1
+ import { map } from '../../operators/index.mjs';
2
+ import { type KeepInitialValueOperator } from '../../types/index.mjs';
3
+
4
+ /**
5
+ * Maps all emitted values to a constant value, ignoring the source values.
6
+ * Equivalent to `map(() => value)`.
7
+ *
8
+ * @template A - The type of values from the source
9
+ * @template B - The type of the constant value
10
+ * @param value - The constant value to emit
11
+ * @returns An operator that always emits the given constant
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * // Timeline:
16
+ * //
17
+ * // click$ MouseEvent MouseEvent MouseEvent
18
+ * // count$ 1 1 1
19
+ * //
20
+ * // Explanation:
21
+ * // - mapTo maps all emitted values to a constant value
22
+ * // - Ignores the source values entirely
23
+ * // - Useful for converting events to signals
24
+ *
25
+ * const click$ = source<string>();
26
+ *
27
+ * const one$ = click$.pipe(mapTo(1));
28
+ *
29
+ * const valueHistory: number[] = [];
30
+ *
31
+ * one$.subscribe((value) => {
32
+ * valueHistory.push(value);
33
+ * });
34
+ *
35
+ * click$.next('click1');
36
+ *
37
+ * click$.next('click2');
38
+ *
39
+ * click$.next('click3');
40
+ *
41
+ * assert.deepStrictEqual(valueHistory, [1, 1, 1]);
42
+ * ```
43
+ */
44
+ export const mapTo = <A, B>(value: B): KeepInitialValueOperator<A, B> =>
45
+ map(() => value);