@typed/fx 2.0.0-beta.4 → 2.0.0-beta.6

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 (663) hide show
  1. package/README.md +34 -20
  2. package/dist/Fx/Fx.d.ts +362 -10
  3. package/dist/Fx/Fx.d.ts.map +1 -1
  4. package/dist/Fx/Fx.js +32 -1
  5. package/dist/Fx/TypeId.d.ts +49 -3
  6. package/dist/Fx/TypeId.d.ts.map +1 -1
  7. package/dist/Fx/TypeId.js +39 -2
  8. package/dist/Fx/combinators/additive.d.ts +156 -5
  9. package/dist/Fx/combinators/additive.d.ts.map +1 -1
  10. package/dist/Fx/combinators/additive.js +156 -5
  11. package/dist/Fx/combinators/catch.d.ts +195 -22
  12. package/dist/Fx/combinators/catch.d.ts.map +1 -1
  13. package/dist/Fx/combinators/catch.js +186 -16
  14. package/dist/Fx/combinators/causes.d.ts +24 -1
  15. package/dist/Fx/combinators/causes.d.ts.map +1 -1
  16. package/dist/Fx/combinators/causes.js +24 -1
  17. package/dist/Fx/combinators/changesWithEffect.d.ts +20 -0
  18. package/dist/Fx/combinators/changesWithEffect.d.ts.map +1 -1
  19. package/dist/Fx/combinators/changesWithEffect.js +20 -0
  20. package/dist/Fx/combinators/compact.d.ts +17 -0
  21. package/dist/Fx/combinators/compact.d.ts.map +1 -1
  22. package/dist/Fx/combinators/compact.js +17 -0
  23. package/dist/Fx/combinators/concatMap.d.ts +86 -0
  24. package/dist/Fx/combinators/concatMap.d.ts.map +1 -0
  25. package/dist/Fx/combinators/concatMap.js +86 -0
  26. package/dist/Fx/combinators/continueWith.d.ts +109 -1
  27. package/dist/Fx/combinators/continueWith.d.ts.map +1 -1
  28. package/dist/Fx/combinators/continueWith.js +109 -1
  29. package/dist/Fx/combinators/debounce.d.ts +34 -0
  30. package/dist/Fx/combinators/debounce.d.ts.map +1 -0
  31. package/dist/Fx/combinators/debounce.js +35 -0
  32. package/dist/Fx/combinators/delay.d.ts +34 -0
  33. package/dist/Fx/combinators/delay.d.ts.map +1 -0
  34. package/dist/Fx/combinators/delay.js +31 -0
  35. package/dist/Fx/combinators/dropUntil.d.ts +42 -0
  36. package/dist/Fx/combinators/dropUntil.d.ts.map +1 -1
  37. package/dist/Fx/combinators/dropUntil.js +42 -0
  38. package/dist/Fx/combinators/during.d.ts +38 -0
  39. package/dist/Fx/combinators/during.d.ts.map +1 -0
  40. package/dist/Fx/combinators/during.js +85 -0
  41. package/dist/Fx/combinators/ensuring.d.ts +33 -3
  42. package/dist/Fx/combinators/ensuring.d.ts.map +1 -1
  43. package/dist/Fx/combinators/ensuring.js +33 -3
  44. package/dist/Fx/combinators/exhaustLatestMap.d.ts +40 -4
  45. package/dist/Fx/combinators/exhaustLatestMap.d.ts.map +1 -1
  46. package/dist/Fx/combinators/exhaustLatestMap.js +40 -4
  47. package/dist/Fx/combinators/exhaustLatestMapEffect.d.ts +39 -3
  48. package/dist/Fx/combinators/exhaustLatestMapEffect.d.ts.map +1 -1
  49. package/dist/Fx/combinators/exhaustLatestMapEffect.js +39 -3
  50. package/dist/Fx/combinators/exhaustMap.d.ts +37 -0
  51. package/dist/Fx/combinators/exhaustMap.d.ts.map +1 -1
  52. package/dist/Fx/combinators/exhaustMap.js +37 -0
  53. package/dist/Fx/combinators/exhaustMapEffect.d.ts +32 -0
  54. package/dist/Fx/combinators/exhaustMapEffect.d.ts.map +1 -1
  55. package/dist/Fx/combinators/exhaustMapEffect.js +32 -0
  56. package/dist/Fx/combinators/exit.d.ts +22 -1
  57. package/dist/Fx/combinators/exit.d.ts.map +1 -1
  58. package/dist/Fx/combinators/exit.js +22 -1
  59. package/dist/Fx/combinators/filter.d.ts +16 -0
  60. package/dist/Fx/combinators/filter.d.ts.map +1 -1
  61. package/dist/Fx/combinators/filter.js +16 -0
  62. package/dist/Fx/combinators/filterEffect.d.ts +21 -0
  63. package/dist/Fx/combinators/filterEffect.d.ts.map +1 -1
  64. package/dist/Fx/combinators/filterEffect.js +21 -0
  65. package/dist/Fx/combinators/filterMap.d.ts +19 -0
  66. package/dist/Fx/combinators/filterMap.d.ts.map +1 -1
  67. package/dist/Fx/combinators/filterMap.js +19 -0
  68. package/dist/Fx/combinators/filterMapEffect.d.ts +20 -0
  69. package/dist/Fx/combinators/filterMapEffect.d.ts.map +1 -1
  70. package/dist/Fx/combinators/filterMapEffect.js +20 -0
  71. package/dist/Fx/combinators/filterMapLoop.d.ts +19 -0
  72. package/dist/Fx/combinators/filterMapLoop.d.ts.map +1 -1
  73. package/dist/Fx/combinators/filterMapLoop.js +19 -0
  74. package/dist/Fx/combinators/filterMapLoopCause.d.ts +20 -0
  75. package/dist/Fx/combinators/filterMapLoopCause.d.ts.map +1 -1
  76. package/dist/Fx/combinators/filterMapLoopCause.js +20 -0
  77. package/dist/Fx/combinators/filterMapLoopCauseEffect.d.ts +20 -0
  78. package/dist/Fx/combinators/filterMapLoopCauseEffect.d.ts.map +1 -1
  79. package/dist/Fx/combinators/filterMapLoopCauseEffect.js +20 -0
  80. package/dist/Fx/combinators/filterMapLoopEffect.d.ts +20 -0
  81. package/dist/Fx/combinators/filterMapLoopEffect.d.ts.map +1 -1
  82. package/dist/Fx/combinators/filterMapLoopEffect.js +20 -0
  83. package/dist/Fx/combinators/flatMap.d.ts +48 -3
  84. package/dist/Fx/combinators/flatMap.d.ts.map +1 -1
  85. package/dist/Fx/combinators/flatMap.js +35 -2
  86. package/dist/Fx/combinators/flatMapConcurrently.d.ts +50 -3
  87. package/dist/Fx/combinators/flatMapConcurrently.d.ts.map +1 -1
  88. package/dist/Fx/combinators/flatMapConcurrently.js +47 -1
  89. package/dist/Fx/combinators/flatMapConcurrentlyEffect.d.ts +47 -3
  90. package/dist/Fx/combinators/flatMapConcurrentlyEffect.d.ts.map +1 -1
  91. package/dist/Fx/combinators/flatMapConcurrentlyEffect.js +39 -1
  92. package/dist/Fx/combinators/flatMapEffect.d.ts +44 -2
  93. package/dist/Fx/combinators/flatMapEffect.d.ts.map +1 -1
  94. package/dist/Fx/combinators/flatMapEffect.js +31 -1
  95. package/dist/Fx/combinators/flip.d.ts +33 -1
  96. package/dist/Fx/combinators/flip.d.ts.map +1 -1
  97. package/dist/Fx/combinators/flip.js +33 -1
  98. package/dist/Fx/combinators/gen.d.ts +28 -9
  99. package/dist/Fx/combinators/gen.d.ts.map +1 -1
  100. package/dist/Fx/combinators/gen.js +27 -3
  101. package/dist/Fx/combinators/genScoped.d.ts +32 -9
  102. package/dist/Fx/combinators/genScoped.d.ts.map +1 -1
  103. package/dist/Fx/combinators/genScoped.js +30 -2
  104. package/dist/Fx/combinators/grouped.d.ts +89 -0
  105. package/dist/Fx/combinators/grouped.d.ts.map +1 -0
  106. package/dist/Fx/combinators/grouped.js +146 -0
  107. package/dist/Fx/combinators/index.d.ts +35 -0
  108. package/dist/Fx/combinators/index.d.ts.map +1 -1
  109. package/dist/Fx/combinators/index.js +35 -0
  110. package/dist/Fx/combinators/keyed.d.ts +121 -7
  111. package/dist/Fx/combinators/keyed.d.ts.map +1 -1
  112. package/dist/Fx/combinators/keyed.js +64 -6
  113. package/dist/Fx/combinators/loop.d.ts +16 -0
  114. package/dist/Fx/combinators/loop.d.ts.map +1 -1
  115. package/dist/Fx/combinators/loop.js +16 -0
  116. package/dist/Fx/combinators/loopCause.d.ts +17 -0
  117. package/dist/Fx/combinators/loopCause.d.ts.map +1 -1
  118. package/dist/Fx/combinators/loopCause.js +17 -0
  119. package/dist/Fx/combinators/loopCauseEffect.d.ts +18 -0
  120. package/dist/Fx/combinators/loopCauseEffect.d.ts.map +1 -1
  121. package/dist/Fx/combinators/loopCauseEffect.js +18 -0
  122. package/dist/Fx/combinators/loopEffect.d.ts +23 -0
  123. package/dist/Fx/combinators/loopEffect.d.ts.map +1 -1
  124. package/dist/Fx/combinators/loopEffect.js +23 -0
  125. package/dist/Fx/combinators/map.d.ts +45 -0
  126. package/dist/Fx/combinators/map.d.ts.map +1 -1
  127. package/dist/Fx/combinators/map.js +42 -0
  128. package/dist/Fx/combinators/mapBoth.d.ts +19 -0
  129. package/dist/Fx/combinators/mapBoth.d.ts.map +1 -1
  130. package/dist/Fx/combinators/mapBoth.js +19 -0
  131. package/dist/Fx/combinators/mapEffect.d.ts +24 -0
  132. package/dist/Fx/combinators/mapEffect.d.ts.map +1 -1
  133. package/dist/Fx/combinators/mapEffect.js +24 -0
  134. package/dist/Fx/combinators/mapError.d.ts +20 -4
  135. package/dist/Fx/combinators/mapError.d.ts.map +1 -1
  136. package/dist/Fx/combinators/mapError.js +20 -4
  137. package/dist/Fx/combinators/mergeAll.d.ts +34 -0
  138. package/dist/Fx/combinators/mergeAll.d.ts.map +1 -1
  139. package/dist/Fx/combinators/mergeAll.js +34 -0
  140. package/dist/Fx/combinators/mergeOrdered.d.ts +35 -3
  141. package/dist/Fx/combinators/mergeOrdered.d.ts.map +1 -1
  142. package/dist/Fx/combinators/mergeOrdered.js +35 -3
  143. package/dist/Fx/combinators/onError.d.ts +33 -3
  144. package/dist/Fx/combinators/onError.d.ts.map +1 -1
  145. package/dist/Fx/combinators/onError.js +33 -3
  146. package/dist/Fx/combinators/onExit.d.ts +28 -2
  147. package/dist/Fx/combinators/onExit.d.ts.map +1 -1
  148. package/dist/Fx/combinators/onExit.js +28 -2
  149. package/dist/Fx/combinators/onInterrupt.d.ts +48 -3
  150. package/dist/Fx/combinators/onInterrupt.d.ts.map +1 -1
  151. package/dist/Fx/combinators/onInterrupt.js +48 -3
  152. package/dist/Fx/combinators/pairwise.d.ts +28 -0
  153. package/dist/Fx/combinators/pairwise.d.ts.map +1 -0
  154. package/dist/Fx/combinators/pairwise.js +31 -0
  155. package/dist/Fx/combinators/provide.d.ts +130 -9
  156. package/dist/Fx/combinators/provide.d.ts.map +1 -1
  157. package/dist/Fx/combinators/provide.js +130 -9
  158. package/dist/Fx/combinators/race.d.ts +92 -0
  159. package/dist/Fx/combinators/race.d.ts.map +1 -0
  160. package/dist/Fx/combinators/race.js +149 -0
  161. package/dist/Fx/combinators/repeat.d.ts +41 -0
  162. package/dist/Fx/combinators/repeat.d.ts.map +1 -0
  163. package/dist/Fx/combinators/repeat.js +57 -0
  164. package/dist/Fx/combinators/result.d.ts +22 -0
  165. package/dist/Fx/combinators/result.d.ts.map +1 -1
  166. package/dist/Fx/combinators/result.js +26 -12
  167. package/dist/Fx/combinators/retry.d.ts +53 -0
  168. package/dist/Fx/combinators/retry.d.ts.map +1 -0
  169. package/dist/Fx/combinators/retry.js +71 -0
  170. package/dist/Fx/combinators/sample.d.ts +31 -0
  171. package/dist/Fx/combinators/sample.d.ts.map +1 -0
  172. package/dist/Fx/combinators/sample.js +42 -0
  173. package/dist/Fx/combinators/scan.d.ts +39 -0
  174. package/dist/Fx/combinators/scan.d.ts.map +1 -1
  175. package/dist/Fx/combinators/scan.js +39 -0
  176. package/dist/Fx/combinators/since.d.ts +30 -0
  177. package/dist/Fx/combinators/since.d.ts.map +1 -0
  178. package/dist/Fx/combinators/since.js +39 -0
  179. package/dist/Fx/combinators/skip.d.ts +31 -0
  180. package/dist/Fx/combinators/skip.d.ts.map +1 -1
  181. package/dist/Fx/combinators/skip.js +31 -0
  182. package/dist/Fx/combinators/skipRepeats.d.ts +16 -0
  183. package/dist/Fx/combinators/skipRepeats.d.ts.map +1 -1
  184. package/dist/Fx/combinators/skipRepeats.js +16 -0
  185. package/dist/Fx/combinators/skipRepeatsWith.d.ts +17 -0
  186. package/dist/Fx/combinators/skipRepeatsWith.d.ts.map +1 -1
  187. package/dist/Fx/combinators/skipRepeatsWith.js +17 -0
  188. package/dist/Fx/combinators/skipWhile.d.ts +68 -0
  189. package/dist/Fx/combinators/skipWhile.d.ts.map +1 -1
  190. package/dist/Fx/combinators/skipWhile.js +68 -0
  191. package/dist/Fx/combinators/slice.d.ts +82 -0
  192. package/dist/Fx/combinators/slice.d.ts.map +1 -1
  193. package/dist/Fx/combinators/slice.js +33 -0
  194. package/dist/Fx/combinators/switchMap.d.ts +38 -0
  195. package/dist/Fx/combinators/switchMap.d.ts.map +1 -1
  196. package/dist/Fx/combinators/switchMap.js +38 -0
  197. package/dist/Fx/combinators/switchMapEffect.d.ts +37 -0
  198. package/dist/Fx/combinators/switchMapEffect.d.ts.map +1 -1
  199. package/dist/Fx/combinators/switchMapEffect.js +37 -0
  200. package/dist/Fx/combinators/take.d.ts +32 -0
  201. package/dist/Fx/combinators/take.d.ts.map +1 -1
  202. package/dist/Fx/combinators/take.js +32 -0
  203. package/dist/Fx/combinators/takeUntil.d.ts +46 -0
  204. package/dist/Fx/combinators/takeUntil.d.ts.map +1 -1
  205. package/dist/Fx/combinators/takeUntil.js +46 -0
  206. package/dist/Fx/combinators/takeWhile.d.ts +31 -0
  207. package/dist/Fx/combinators/takeWhile.d.ts.map +1 -1
  208. package/dist/Fx/combinators/takeWhile.js +31 -0
  209. package/dist/Fx/combinators/tapEffect.d.ts +16 -0
  210. package/dist/Fx/combinators/tapEffect.d.ts.map +1 -1
  211. package/dist/Fx/combinators/tapEffect.js +16 -0
  212. package/dist/Fx/combinators/throttle.d.ts +79 -0
  213. package/dist/Fx/combinators/throttle.d.ts.map +1 -0
  214. package/dist/Fx/combinators/throttle.js +99 -0
  215. package/dist/Fx/combinators/timeout.d.ts +76 -0
  216. package/dist/Fx/combinators/timeout.d.ts.map +1 -0
  217. package/dist/Fx/combinators/timeout.js +110 -0
  218. package/dist/Fx/combinators/tuple.d.ts +30 -0
  219. package/dist/Fx/combinators/tuple.d.ts.map +1 -1
  220. package/dist/Fx/combinators/tuple.js +34 -3
  221. package/dist/Fx/combinators/until.d.ts +27 -0
  222. package/dist/Fx/combinators/until.d.ts.map +1 -0
  223. package/dist/Fx/combinators/until.js +56 -0
  224. package/dist/Fx/combinators/unwrap.d.ts +29 -0
  225. package/dist/Fx/combinators/unwrap.d.ts.map +1 -1
  226. package/dist/Fx/combinators/unwrap.js +29 -0
  227. package/dist/Fx/combinators/unwrapScoped.d.ts +33 -0
  228. package/dist/Fx/combinators/unwrapScoped.d.ts.map +1 -1
  229. package/dist/Fx/combinators/unwrapScoped.js +33 -0
  230. package/dist/Fx/combinators/when.d.ts +35 -0
  231. package/dist/Fx/combinators/when.d.ts.map +1 -1
  232. package/dist/Fx/combinators/when.js +36 -1
  233. package/dist/Fx/combinators/withLatestFrom.d.ts +58 -0
  234. package/dist/Fx/combinators/withLatestFrom.d.ts.map +1 -0
  235. package/dist/Fx/combinators/withLatestFrom.js +68 -0
  236. package/dist/Fx/combinators/withSpan.d.ts +35 -1
  237. package/dist/Fx/combinators/withSpan.d.ts.map +1 -1
  238. package/dist/Fx/combinators/withSpan.js +34 -3
  239. package/dist/Fx/combinators/zip.d.ts +60 -0
  240. package/dist/Fx/combinators/zip.d.ts.map +1 -1
  241. package/dist/Fx/combinators/zip.js +60 -0
  242. package/dist/Fx/constructors/at.d.ts +20 -0
  243. package/dist/Fx/constructors/at.d.ts.map +1 -1
  244. package/dist/Fx/constructors/at.js +20 -0
  245. package/dist/Fx/constructors/die.d.ts +21 -0
  246. package/dist/Fx/constructors/die.d.ts.map +1 -1
  247. package/dist/Fx/constructors/die.js +21 -0
  248. package/dist/Fx/constructors/empty.d.ts +18 -0
  249. package/dist/Fx/constructors/empty.d.ts.map +1 -1
  250. package/dist/Fx/constructors/empty.js +18 -0
  251. package/dist/Fx/constructors/fail.d.ts +21 -0
  252. package/dist/Fx/constructors/fail.d.ts.map +1 -1
  253. package/dist/Fx/constructors/fail.js +21 -0
  254. package/dist/Fx/constructors/failCause.d.ts +22 -0
  255. package/dist/Fx/constructors/failCause.d.ts.map +1 -1
  256. package/dist/Fx/constructors/failCause.js +22 -0
  257. package/dist/Fx/constructors/fn.d.ts +113 -13
  258. package/dist/Fx/constructors/fn.d.ts.map +1 -1
  259. package/dist/Fx/constructors/fn.js +36 -0
  260. package/dist/Fx/constructors/fromEffect.d.ts +43 -1
  261. package/dist/Fx/constructors/fromEffect.d.ts.map +1 -1
  262. package/dist/Fx/constructors/fromEffect.js +43 -1
  263. package/dist/Fx/constructors/fromFailures.d.ts +24 -0
  264. package/dist/Fx/constructors/fromFailures.d.ts.map +1 -1
  265. package/dist/Fx/constructors/fromFailures.js +24 -0
  266. package/dist/Fx/constructors/fromIterable.d.ts +22 -0
  267. package/dist/Fx/constructors/fromIterable.d.ts.map +1 -1
  268. package/dist/Fx/constructors/fromIterable.js +22 -0
  269. package/dist/Fx/constructors/fromSchedule.d.ts +23 -0
  270. package/dist/Fx/constructors/fromSchedule.d.ts.map +1 -1
  271. package/dist/Fx/constructors/fromSchedule.js +25 -2
  272. package/dist/Fx/constructors/index.d.ts +2 -1
  273. package/dist/Fx/constructors/index.d.ts.map +1 -1
  274. package/dist/Fx/constructors/index.js +2 -1
  275. package/dist/Fx/constructors/interrupt.d.ts +21 -1
  276. package/dist/Fx/constructors/interrupt.d.ts.map +1 -1
  277. package/dist/Fx/constructors/interrupt.js +21 -1
  278. package/dist/Fx/constructors/make.d.ts +146 -1
  279. package/dist/Fx/constructors/make.d.ts.map +1 -1
  280. package/dist/Fx/constructors/make.js +54 -3
  281. package/dist/Fx/constructors/periodic.d.ts +29 -0
  282. package/dist/Fx/constructors/periodic.d.ts.map +1 -1
  283. package/dist/Fx/constructors/periodic.js +29 -0
  284. package/dist/Fx/constructors/succeed.d.ts +75 -3
  285. package/dist/Fx/constructors/succeed.d.ts.map +1 -1
  286. package/dist/Fx/constructors/succeed.js +75 -3
  287. package/dist/Fx/constructors/suspend.d.ts +28 -0
  288. package/dist/Fx/constructors/suspend.d.ts.map +1 -1
  289. package/dist/Fx/constructors/suspend.js +28 -0
  290. package/dist/Fx/constructors/sync.d.ts +32 -0
  291. package/dist/Fx/constructors/sync.d.ts.map +1 -0
  292. package/dist/Fx/constructors/sync.js +32 -0
  293. package/dist/Fx/internal/DeferredRef.d.ts +259 -7
  294. package/dist/Fx/internal/DeferredRef.d.ts.map +1 -1
  295. package/dist/Fx/internal/DeferredRef.js +260 -9
  296. package/dist/Fx/internal/UnionToTuple.d.ts +22 -0
  297. package/dist/Fx/internal/UnionToTuple.d.ts.map +1 -1
  298. package/dist/Fx/internal/diff.d.ts +586 -0
  299. package/dist/Fx/internal/diff.d.ts.map +1 -1
  300. package/dist/Fx/internal/diff.js +120 -9
  301. package/dist/Fx/internal/effectableEvaluateKey.d.ts +30 -0
  302. package/dist/Fx/internal/effectableEvaluateKey.d.ts.map +1 -0
  303. package/dist/Fx/internal/effectableEvaluateKey.js +29 -0
  304. package/dist/Fx/internal/effectableWithOverride.d.ts +55 -0
  305. package/dist/Fx/internal/effectableWithOverride.d.ts.map +1 -0
  306. package/dist/Fx/internal/effectableWithOverride.js +46 -0
  307. package/dist/Fx/internal/equivalence.d.ts +29 -0
  308. package/dist/Fx/internal/equivalence.d.ts.map +1 -1
  309. package/dist/Fx/internal/equivalence.js +29 -0
  310. package/dist/Fx/internal/multicast.d.ts +145 -2
  311. package/dist/Fx/internal/multicast.d.ts.map +1 -1
  312. package/dist/Fx/internal/multicast.js +146 -4
  313. package/dist/Fx/internal/ring-buffer.d.ts +149 -0
  314. package/dist/Fx/internal/ring-buffer.d.ts.map +1 -1
  315. package/dist/Fx/internal/ring-buffer.js +155 -0
  316. package/dist/Fx/internal/scope.d.ts +184 -0
  317. package/dist/Fx/internal/scope.d.ts.map +1 -1
  318. package/dist/Fx/internal/scope.js +150 -0
  319. package/dist/Fx/internal/yieldable.d.ts +117 -2
  320. package/dist/Fx/internal/yieldable.d.ts.map +1 -1
  321. package/dist/Fx/internal/yieldable.js +86 -3
  322. package/dist/Fx/run/collect.d.ts +89 -0
  323. package/dist/Fx/run/collect.d.ts.map +1 -1
  324. package/dist/Fx/run/collect.js +90 -1
  325. package/dist/Fx/run/first.d.ts +22 -0
  326. package/dist/Fx/run/first.d.ts.map +1 -1
  327. package/dist/Fx/run/first.js +22 -0
  328. package/dist/Fx/run/fork.d.ts +50 -0
  329. package/dist/Fx/run/fork.d.ts.map +1 -1
  330. package/dist/Fx/run/fork.js +50 -0
  331. package/dist/Fx/run/observe.d.ts +106 -0
  332. package/dist/Fx/run/observe.d.ts.map +1 -1
  333. package/dist/Fx/run/observe.js +106 -0
  334. package/dist/Fx/run/runPromise.d.ts +43 -0
  335. package/dist/Fx/run/runPromise.d.ts.map +1 -1
  336. package/dist/Fx/run/runPromise.js +43 -0
  337. package/dist/Fx/stream.d.ts +92 -0
  338. package/dist/Fx/stream.d.ts.map +1 -1
  339. package/dist/Fx/stream.js +60 -1
  340. package/dist/Push/Push.d.ts +1216 -91
  341. package/dist/Push/Push.d.ts.map +1 -1
  342. package/dist/Push/Push.js +1012 -83
  343. package/dist/RefArray.d.ts +2 -0
  344. package/dist/RefArray.d.ts.map +1 -0
  345. package/dist/RefArray.js +1 -0
  346. package/dist/RefBigDecimal.d.ts +2 -0
  347. package/dist/RefBigDecimal.d.ts.map +1 -0
  348. package/dist/RefBigDecimal.js +1 -0
  349. package/dist/RefBigInt.d.ts +2 -0
  350. package/dist/RefBigInt.d.ts.map +1 -0
  351. package/dist/RefBigInt.js +1 -0
  352. package/dist/RefBoolean.d.ts +2 -0
  353. package/dist/RefBoolean.d.ts.map +1 -0
  354. package/dist/RefBoolean.js +1 -0
  355. package/dist/RefCause.d.ts +2 -0
  356. package/dist/RefCause.d.ts.map +1 -0
  357. package/dist/RefCause.js +1 -0
  358. package/dist/RefChunk.d.ts +2 -0
  359. package/dist/RefChunk.d.ts.map +1 -0
  360. package/dist/RefChunk.js +1 -0
  361. package/dist/RefDateTime.d.ts +2 -0
  362. package/dist/RefDateTime.d.ts.map +1 -0
  363. package/dist/RefDateTime.js +1 -0
  364. package/dist/RefDuration.d.ts +2 -0
  365. package/dist/RefDuration.d.ts.map +1 -0
  366. package/dist/RefDuration.js +1 -0
  367. package/dist/RefGraph.d.ts +2 -0
  368. package/dist/RefGraph.d.ts.map +1 -0
  369. package/dist/RefGraph.js +1 -0
  370. package/dist/RefHashMap.d.ts +2 -0
  371. package/dist/RefHashMap.d.ts.map +1 -0
  372. package/dist/RefHashMap.js +1 -0
  373. package/dist/RefHashRing.d.ts +2 -0
  374. package/dist/RefHashRing.d.ts.map +1 -0
  375. package/dist/RefHashRing.js +1 -0
  376. package/dist/RefHashSet.d.ts +2 -0
  377. package/dist/RefHashSet.d.ts.map +1 -0
  378. package/dist/RefHashSet.js +1 -0
  379. package/dist/RefIterable.d.ts +2 -0
  380. package/dist/RefIterable.d.ts.map +1 -0
  381. package/dist/RefIterable.js +1 -0
  382. package/dist/RefOption.d.ts +2 -0
  383. package/dist/RefOption.d.ts.map +1 -0
  384. package/dist/RefOption.js +1 -0
  385. package/dist/RefRecord.d.ts +2 -0
  386. package/dist/RefRecord.d.ts.map +1 -0
  387. package/dist/RefRecord.js +1 -0
  388. package/dist/RefResult.d.ts +2 -0
  389. package/dist/RefResult.d.ts.map +1 -0
  390. package/dist/RefResult.js +1 -0
  391. package/dist/RefString.d.ts +2 -0
  392. package/dist/RefString.d.ts.map +1 -0
  393. package/dist/RefString.js +1 -0
  394. package/dist/RefStruct.d.ts +2 -0
  395. package/dist/RefStruct.d.ts.map +1 -0
  396. package/dist/RefStruct.js +1 -0
  397. package/dist/RefSubject/Hydration.d.ts +504 -0
  398. package/dist/RefSubject/Hydration.d.ts.map +1 -0
  399. package/dist/RefSubject/Hydration.js +300 -0
  400. package/dist/RefSubject/RefArray.d.ts +351 -4
  401. package/dist/RefSubject/RefArray.d.ts.map +1 -1
  402. package/dist/RefSubject/RefArray.js +339 -3
  403. package/dist/RefSubject/RefBigDecimal.d.ts +221 -1
  404. package/dist/RefSubject/RefBigDecimal.d.ts.map +1 -1
  405. package/dist/RefSubject/RefBigDecimal.js +210 -1
  406. package/dist/RefSubject/RefBigInt.d.ts +166 -1
  407. package/dist/RefSubject/RefBigInt.d.ts.map +1 -1
  408. package/dist/RefSubject/RefBigInt.js +155 -1
  409. package/dist/RefSubject/RefBoolean.d.ts +166 -1
  410. package/dist/RefSubject/RefBoolean.d.ts.map +1 -1
  411. package/dist/RefSubject/RefBoolean.js +155 -1
  412. package/dist/RefSubject/RefCause.d.ts +122 -1
  413. package/dist/RefSubject/RefCause.d.ts.map +1 -1
  414. package/dist/RefSubject/RefCause.js +111 -1
  415. package/dist/RefSubject/RefChunk.d.ts +406 -1
  416. package/dist/RefSubject/RefChunk.d.ts.map +1 -1
  417. package/dist/RefSubject/RefChunk.js +394 -0
  418. package/dist/RefSubject/RefDateTime.d.ts +122 -1
  419. package/dist/RefSubject/RefDateTime.d.ts.map +1 -1
  420. package/dist/RefSubject/RefDateTime.js +111 -1
  421. package/dist/RefSubject/RefDuration.d.ts +155 -1
  422. package/dist/RefSubject/RefDuration.d.ts.map +1 -1
  423. package/dist/RefSubject/RefDuration.js +144 -1
  424. package/dist/RefSubject/RefGraph.d.ts +320 -6
  425. package/dist/RefSubject/RefGraph.d.ts.map +1 -1
  426. package/dist/RefSubject/RefGraph.js +303 -0
  427. package/dist/RefSubject/RefHashMap.d.ts +296 -1
  428. package/dist/RefSubject/RefHashMap.d.ts.map +1 -1
  429. package/dist/RefSubject/RefHashMap.js +284 -0
  430. package/dist/RefSubject/RefHashRing.d.ts +146 -2
  431. package/dist/RefSubject/RefHashRing.d.ts.map +1 -1
  432. package/dist/RefSubject/RefHashRing.js +133 -0
  433. package/dist/RefSubject/RefHashSet.d.ts +230 -1
  434. package/dist/RefSubject/RefHashSet.d.ts.map +1 -1
  435. package/dist/RefSubject/RefHashSet.js +218 -0
  436. package/dist/RefSubject/RefIterable.d.ts +327 -1
  437. package/dist/RefSubject/RefIterable.d.ts.map +1 -1
  438. package/dist/RefSubject/RefIterable.js +315 -0
  439. package/dist/RefSubject/RefOption.d.ts +144 -1
  440. package/dist/RefSubject/RefOption.d.ts.map +1 -1
  441. package/dist/RefSubject/RefOption.js +133 -1
  442. package/dist/RefSubject/RefRecord.d.ts +339 -1
  443. package/dist/RefSubject/RefRecord.d.ts.map +1 -1
  444. package/dist/RefSubject/RefRecord.js +327 -0
  445. package/dist/RefSubject/RefResult.d.ts +155 -23
  446. package/dist/RefSubject/RefResult.d.ts.map +1 -1
  447. package/dist/RefSubject/RefResult.js +122 -1
  448. package/dist/RefSubject/RefString.d.ts +188 -1
  449. package/dist/RefSubject/RefString.d.ts.map +1 -1
  450. package/dist/RefSubject/RefString.js +177 -1
  451. package/dist/RefSubject/RefStruct.d.ts +156 -1
  452. package/dist/RefSubject/RefStruct.d.ts.map +1 -1
  453. package/dist/RefSubject/RefStruct.js +145 -1
  454. package/dist/RefSubject/RefSubject.d.ts +1166 -13
  455. package/dist/RefSubject/RefSubject.d.ts.map +1 -1
  456. package/dist/RefSubject/RefSubject.js +843 -51
  457. package/dist/RefSubject/RefTrie.d.ts +290 -4
  458. package/dist/RefSubject/RefTrie.d.ts.map +1 -1
  459. package/dist/RefSubject/RefTrie.js +278 -3
  460. package/dist/RefSubject/RefTuple.d.ts +117 -1
  461. package/dist/RefSubject/RefTuple.d.ts.map +1 -1
  462. package/dist/RefSubject/RefTuple.js +106 -1
  463. package/dist/RefSubject/index.d.ts +1 -0
  464. package/dist/RefSubject/index.d.ts.map +1 -1
  465. package/dist/RefSubject/index.js +1 -0
  466. package/dist/RefSubject.d.ts +2 -1
  467. package/dist/RefSubject.d.ts.map +1 -1
  468. package/dist/RefSubject.js +2 -1
  469. package/dist/RefTrie.d.ts +2 -0
  470. package/dist/RefTrie.d.ts.map +1 -0
  471. package/dist/RefTrie.js +1 -0
  472. package/dist/RefTuple.d.ts +2 -0
  473. package/dist/RefTuple.d.ts.map +1 -0
  474. package/dist/RefTuple.js +1 -0
  475. package/dist/Sink/Sink.d.ts +381 -10
  476. package/dist/Sink/Sink.d.ts.map +1 -1
  477. package/dist/Sink/Sink.js +49 -2
  478. package/dist/Sink/combinators.d.ts +731 -2
  479. package/dist/Sink/combinators.d.ts.map +1 -1
  480. package/dist/Sink/combinators.js +706 -4
  481. package/dist/Subject/Subject.d.ts +1013 -19
  482. package/dist/Subject/Subject.d.ts.map +1 -1
  483. package/dist/Subject/Subject.js +901 -36
  484. package/dist/Versioned/Versioned.d.ts +424 -7
  485. package/dist/Versioned/Versioned.d.ts.map +1 -1
  486. package/dist/Versioned/Versioned.js +238 -12
  487. package/dist/index.d.ts +22 -3
  488. package/dist/index.d.ts.map +1 -1
  489. package/dist/index.js +22 -3
  490. package/package.json +123 -14
  491. package/dist/Fx/constructors/fromYieldable.d.ts +0 -12
  492. package/dist/Fx/constructors/fromYieldable.d.ts.map +0 -1
  493. package/dist/Fx/constructors/fromYieldable.js +0 -12
  494. package/src/Fx/Fx.ts +0 -164
  495. package/src/Fx/TypeId.ts +0 -25
  496. package/src/Fx/combinators/additive.ts +0 -142
  497. package/src/Fx/combinators/catch.ts +0 -416
  498. package/src/Fx/combinators/causes.ts +0 -23
  499. package/src/Fx/combinators/changesWithEffect.ts +0 -66
  500. package/src/Fx/combinators/compact.ts +0 -15
  501. package/src/Fx/combinators/continueWith.ts +0 -78
  502. package/src/Fx/combinators/dropUntil.ts +0 -47
  503. package/src/Fx/combinators/ensuring.ts +0 -23
  504. package/src/Fx/combinators/exhaustLatestMap.ts +0 -74
  505. package/src/Fx/combinators/exhaustLatestMapEffect.ts +0 -25
  506. package/src/Fx/combinators/exhaustMap.ts +0 -36
  507. package/src/Fx/combinators/exhaustMapEffect.ts +0 -23
  508. package/src/Fx/combinators/exit.ts +0 -15
  509. package/src/Fx/combinators/filter.ts +0 -22
  510. package/src/Fx/combinators/filterEffect.ts +0 -31
  511. package/src/Fx/combinators/filterMap.ts +0 -23
  512. package/src/Fx/combinators/filterMapEffect.ts +0 -32
  513. package/src/Fx/combinators/filterMapLoop.ts +0 -35
  514. package/src/Fx/combinators/filterMapLoopCause.ts +0 -36
  515. package/src/Fx/combinators/filterMapLoopCauseEffect.ts +0 -46
  516. package/src/Fx/combinators/filterMapLoopEffect.ts +0 -36
  517. package/src/Fx/combinators/flatMap.ts +0 -51
  518. package/src/Fx/combinators/flatMapConcurrently.ts +0 -39
  519. package/src/Fx/combinators/flatMapConcurrentlyEffect.ts +0 -26
  520. package/src/Fx/combinators/flatMapEffect.ts +0 -42
  521. package/src/Fx/combinators/flip.ts +0 -14
  522. package/src/Fx/combinators/gen.ts +0 -24
  523. package/src/Fx/combinators/genScoped.ts +0 -24
  524. package/src/Fx/combinators/index.ts +0 -61
  525. package/src/Fx/combinators/keyed.ts +0 -369
  526. package/src/Fx/combinators/loop.ts +0 -27
  527. package/src/Fx/combinators/loopCause.ts +0 -34
  528. package/src/Fx/combinators/loopCauseEffect.ts +0 -36
  529. package/src/Fx/combinators/loopEffect.ts +0 -34
  530. package/src/Fx/combinators/map.ts +0 -22
  531. package/src/Fx/combinators/mapBoth.ts +0 -40
  532. package/src/Fx/combinators/mapEffect.ts +0 -32
  533. package/src/Fx/combinators/mapError.ts +0 -28
  534. package/src/Fx/combinators/mergeAll.ts +0 -22
  535. package/src/Fx/combinators/mergeOrdered.ts +0 -123
  536. package/src/Fx/combinators/onError.ts +0 -40
  537. package/src/Fx/combinators/onExit.ts +0 -82
  538. package/src/Fx/combinators/onInterrupt.ts +0 -87
  539. package/src/Fx/combinators/provide.ts +0 -124
  540. package/src/Fx/combinators/result.ts +0 -39
  541. package/src/Fx/combinators/scan.ts +0 -82
  542. package/src/Fx/combinators/skip.ts +0 -41
  543. package/src/Fx/combinators/skipRepeats.ts +0 -15
  544. package/src/Fx/combinators/skipRepeatsWith.ts +0 -40
  545. package/src/Fx/combinators/skipWhile.ts +0 -100
  546. package/src/Fx/combinators/slice.ts +0 -55
  547. package/src/Fx/combinators/switchMap.ts +0 -55
  548. package/src/Fx/combinators/switchMapEffect.ts +0 -25
  549. package/src/Fx/combinators/take.ts +0 -38
  550. package/src/Fx/combinators/takeUntil.ts +0 -88
  551. package/src/Fx/combinators/takeWhile.ts +0 -47
  552. package/src/Fx/combinators/tapEffect.ts +0 -39
  553. package/src/Fx/combinators/tuple.ts +0 -79
  554. package/src/Fx/combinators/unwrap.ts +0 -21
  555. package/src/Fx/combinators/unwrapScoped.ts +0 -26
  556. package/src/Fx/combinators/when.ts +0 -64
  557. package/src/Fx/combinators/withSpan.ts +0 -24
  558. package/src/Fx/combinators/zip.ts +0 -175
  559. package/src/Fx/constructors/at.ts +0 -23
  560. package/src/Fx/constructors/die.ts +0 -17
  561. package/src/Fx/constructors/empty.ts +0 -10
  562. package/src/Fx/constructors/fail.ts +0 -14
  563. package/src/Fx/constructors/failCause.ts +0 -14
  564. package/src/Fx/constructors/fn.ts +0 -245
  565. package/src/Fx/constructors/fromEffect.ts +0 -24
  566. package/src/Fx/constructors/fromFailures.ts +0 -19
  567. package/src/Fx/constructors/fromIterable.ts +0 -15
  568. package/src/Fx/constructors/fromSchedule.ts +0 -18
  569. package/src/Fx/constructors/fromYieldable.ts +0 -17
  570. package/src/Fx/constructors/index.ts +0 -15
  571. package/src/Fx/constructors/interrupt.ts +0 -13
  572. package/src/Fx/constructors/make.ts +0 -103
  573. package/src/Fx/constructors/periodic.ts +0 -15
  574. package/src/Fx/constructors/succeed.ts +0 -37
  575. package/src/Fx/constructors/suspend.ts +0 -6
  576. package/src/Fx/index.ts +0 -6
  577. package/src/Fx/internal/DeferredRef.ts +0 -87
  578. package/src/Fx/internal/UnionToTuple.ts +0 -12
  579. package/src/Fx/internal/diff.ts +0 -191
  580. package/src/Fx/internal/equivalence.ts +0 -12
  581. package/src/Fx/internal/multicast.ts +0 -51
  582. package/src/Fx/internal/ring-buffer.ts +0 -60
  583. package/src/Fx/internal/scope.ts +0 -58
  584. package/src/Fx/internal/yieldable.ts +0 -31
  585. package/src/Fx/run/collect.ts +0 -79
  586. package/src/Fx/run/first.ts +0 -20
  587. package/src/Fx/run/fork.ts +0 -40
  588. package/src/Fx/run/index.ts +0 -5
  589. package/src/Fx/run/observe.ts +0 -114
  590. package/src/Fx/run/runPromise.ts +0 -32
  591. package/src/Fx/stream.ts +0 -42
  592. package/src/Fx.additive-combinators.test.ts +0 -126
  593. package/src/Fx.catch-additive.test.ts +0 -206
  594. package/src/Fx.catch.test.ts +0 -60
  595. package/src/Fx.dropUntil.test.ts +0 -61
  596. package/src/Fx.fn.test.ts +0 -51
  597. package/src/Fx.lifecycle.test.ts +0 -79
  598. package/src/Fx.mapError-mapBoth.test.ts +0 -101
  599. package/src/Fx.provide-combinators.test.ts +0 -94
  600. package/src/Fx.result-changesWithEffect.test.ts +0 -112
  601. package/src/Fx.scan.test.ts +0 -73
  602. package/src/Fx.takeWhile-skipWhile.test.ts +0 -84
  603. package/src/Fx.test.ts +0 -71
  604. package/src/Fx.ts +0 -1
  605. package/src/Fx.zip-merge-additive.test.ts +0 -171
  606. package/src/Fx.zip.test.ts +0 -133
  607. package/src/Push/Push.ts +0 -1093
  608. package/src/Push/index.ts +0 -1
  609. package/src/Push.additive.test.ts +0 -256
  610. package/src/Push.test.ts +0 -26
  611. package/src/Push.ts +0 -1
  612. package/src/RefSubject/RefArray.ts +0 -516
  613. package/src/RefSubject/RefBigDecimal.test.ts +0 -56
  614. package/src/RefSubject/RefBigDecimal.ts +0 -295
  615. package/src/RefSubject/RefBigInt.test.ts +0 -56
  616. package/src/RefSubject/RefBigInt.ts +0 -189
  617. package/src/RefSubject/RefBoolean.test.ts +0 -57
  618. package/src/RefSubject/RefBoolean.ts +0 -185
  619. package/src/RefSubject/RefCause.test.ts +0 -53
  620. package/src/RefSubject/RefCause.ts +0 -146
  621. package/src/RefSubject/RefChunk.ts +0 -516
  622. package/src/RefSubject/RefDateTime.test.ts +0 -43
  623. package/src/RefSubject/RefDateTime.ts +0 -261
  624. package/src/RefSubject/RefDuration.test.ts +0 -49
  625. package/src/RefSubject/RefDuration.ts +0 -188
  626. package/src/RefSubject/RefGraph.ts +0 -649
  627. package/src/RefSubject/RefHashMap.ts +0 -474
  628. package/src/RefSubject/RefHashRing.ts +0 -262
  629. package/src/RefSubject/RefHashSet.ts +0 -308
  630. package/src/RefSubject/RefIterable.ts +0 -454
  631. package/src/RefSubject/RefOption.test.ts +0 -67
  632. package/src/RefSubject/RefOption.ts +0 -193
  633. package/src/RefSubject/RefRecord.ts +0 -621
  634. package/src/RefSubject/RefResult.test.ts +0 -63
  635. package/src/RefSubject/RefResult.ts +0 -209
  636. package/src/RefSubject/RefString.test.ts +0 -61
  637. package/src/RefSubject/RefString.ts +0 -256
  638. package/src/RefSubject/RefStruct.test.ts +0 -60
  639. package/src/RefSubject/RefStruct.ts +0 -253
  640. package/src/RefSubject/RefSubject.ts +0 -2642
  641. package/src/RefSubject/RefTrie.ts +0 -365
  642. package/src/RefSubject/RefTuple.test.ts +0 -60
  643. package/src/RefSubject/RefTuple.ts +0 -231
  644. package/src/RefSubject/index.ts +0 -21
  645. package/src/RefSubject.additive-parity.test.ts +0 -101
  646. package/src/RefSubject.test.ts +0 -65
  647. package/src/RefSubject.ts +0 -1
  648. package/src/Sink/Sink.ts +0 -159
  649. package/src/Sink/combinators.ts +0 -1115
  650. package/src/Sink/index.ts +0 -2
  651. package/src/Sink.combinators.test.ts +0 -88
  652. package/src/Sink.reduce-collect-head-last.test.ts +0 -107
  653. package/src/Sink.ts +0 -1
  654. package/src/Subject/Subject.ts +0 -440
  655. package/src/Subject/index.ts +0 -1
  656. package/src/Subject.test.ts +0 -47
  657. package/src/Subject.ts +0 -1
  658. package/src/Versioned/Versioned.ts +0 -595
  659. package/src/Versioned/index.ts +0 -1
  660. package/src/Versioned.filterMap.test.ts +0 -91
  661. package/src/Versioned.test.ts +0 -23
  662. package/src/Versioned.ts +0 -1
  663. package/src/index.ts +0 -7
package/dist/Push/Push.js CHANGED
@@ -10,7 +10,23 @@ import * as Fx from "../Fx/index.js";
10
10
  import { FxTypeId } from "../Fx/TypeId.js";
11
11
  import * as Sink from "../Sink.js";
12
12
  /**
13
- * Creates a `Push` from a `Sink` and an `Fx`.
13
+ * Couples a `Sink` input with an independent `Fx` output.
14
+ *
15
+ * The result forwards each input callback directly to `sink` and delegates every
16
+ * output subscription to `fx`. It does not connect the two values, change output
17
+ * cardinality or ordering, buffer inputs, or start either side eagerly.
18
+ *
19
+ * @remarks
20
+ * ## Why
21
+ *
22
+ * `make` is the explicit boundary where a command consumer and event producer
23
+ * become one bidirectional capability without hiding either contract.
24
+ *
25
+ * ## Ownership and lifetime
26
+ *
27
+ * Construction is allocation-free apart from the wrapper. Each input callback is
28
+ * owned by its caller; each output run is owned by the wrapped Fx run and inherits
29
+ * its interruption, Scope, cleanup, failures, and services.
14
30
  *
15
31
  * @example
16
32
  * ```ts
@@ -19,26 +35,17 @@ import * as Sink from "../Sink.js";
19
35
  * import { Fx } from "@typed/fx"
20
36
  * import * as Sink from "@typed/fx/Sink"
21
37
  *
22
- * const program = Effect.gen(function* () {
23
- * const sink = Sink.make(
24
- * (cause) => Effect.sync(() => console.log("Failed:", cause)),
25
- * (value) => Effect.sync(() => console.log("Success:", value))
26
- * )
27
- *
28
- * const fx = Fx.succeed("Output")
29
- *
30
- * const push = Push.make(sink, fx)
38
+ * const received: Array<number> = []
39
+ * const sink = Sink.make(() => Effect.void, (value: number) =>
40
+ * Effect.sync(() => received.push(value))
41
+ * )
42
+ * const push = Push.make(sink, Fx.fromIterable(["ready", "done"]))
31
43
  *
32
- * // Push a value
33
- * yield* push.onSuccess(42)
34
- * // Output: "Success: 42"
35
- *
36
- * // Observe the Fx
37
- * yield* Fx.observe(push, (value) =>
38
- * Effect.sync(() => console.log("Emitted:", value))
39
- * )
40
- * // Output: "Emitted: Output"
41
- * })
44
+ * const program = Effect.gen(function* () {
45
+ * yield* push.onSuccess(42) // acknowledges the Sink callback
46
+ * const output = yield* Fx.collectAll(push)
47
+ * return { received, output }
48
+ * }).pipe(Effect.scoped)
42
49
  * ```
43
50
  *
44
51
  * @since 1.0.0
@@ -74,31 +81,46 @@ class PushImpl {
74
81
  }
75
82
  }
76
83
  /**
77
- * Maps over the input (Sink) side of a `Push`.
84
+ * Synchronously transforms each successful input before sending it to the Sink.
85
+ *
86
+ * One input maps to exactly one downstream input. Calling `onSuccess` evaluates
87
+ * `f` immediately, before the returned downstream Effect is run; allocation and
88
+ * thrown exceptions therefore occur at callback invocation (and become defects
89
+ * only when that invocation itself occurs inside Effect evaluation). The Sink
90
+ * callback Effect remains the acknowledgment. Calls are not serialized; execution
91
+ * order and concurrency follow the producer. The Fx output is unchanged.
92
+ *
93
+ * @remarks
94
+ * ## Why
95
+ *
96
+ * Adapt an external command shape to an existing consumer without rebuilding or
97
+ * changing the independent output stream.
98
+ *
99
+ * ## Ownership and lifetime
100
+ *
101
+ * `f` runs synchronously when `onSuccess` is called, before its returned Effect
102
+ * exists, and acquires no resource. Downstream handling retains the original
103
+ * Sink's `E`, `R`, caller fiber, interruption, and cleanup behavior.
78
104
  *
79
105
  * @example
80
106
  * ```ts
81
107
  * import { Effect } from "effect"
108
+ * import * as Fx from "@typed/fx/Fx"
82
109
  * import * as Push from "@typed/fx/Push"
83
- * import { Fx } from "@typed/fx"
84
110
  * import * as Sink from "@typed/fx/Sink"
85
111
  *
86
- * const program = Effect.gen(function* () {
87
- * const push = Push.make(
88
- * Sink.make(
89
- * (cause) => Effect.void,
90
- * (value) => Effect.sync(() => console.log("Number:", value))
91
- * ),
92
- * Fx.succeed("Output")
93
- * )
94
- *
95
- * // Map input from string to number
96
- * const mapped = Push.mapInput(push, (str: string) => parseInt(str))
97
- *
98
- * // Push a string, which gets converted to a number
99
- * yield* mapped.onSuccess("42")
100
- * // Output: "Number: 42"
112
+ * const events: Array<string> = []
113
+ * const base = Push.make(
114
+ * Sink.make(() => Effect.void, (n: number) => Effect.sync(() => events.push(`sink:${n}`))),
115
+ * Fx.empty
116
+ * )
117
+ * const mapped = Push.mapInput(base, (text: string) => {
118
+ * events.push(`map:${text}`)
119
+ * return Number(text)
101
120
  * })
121
+ * const acknowledgement = mapped.onSuccess("42")
122
+ * // events is already ["map:42"]; the Sink Effect has not run yet.
123
+ * const program = Effect.as(acknowledgement, events)
102
124
  * ```
103
125
  *
104
126
  * @since 1.0.0
@@ -107,23 +129,241 @@ class PushImpl {
107
129
  export const mapInput = dual(2, function mapInput(push, f) {
108
130
  return make(Sink.map(push, f), push);
109
131
  });
132
+ /**
133
+ * Effectfully transforms each successful input before sending it to the Sink.
134
+ *
135
+ * Calling `onSuccess(value)` invokes `f(value)` immediately to construct an
136
+ * Effect. Allocation and thrown exceptions therefore occur before an
137
+ * acknowledgment Effect is returned. Running that returned Effect later executes
138
+ * the constructed Effect in the caller's fiber. On success its single `A` reaches
139
+ * the Sink; typed failure, defect, or interruption sends its full Cause to the
140
+ * Sink failure callback. Calls are not serialized, so the producer controls order
141
+ * and concurrency. Output values and order are unchanged.
142
+ *
143
+ * @remarks
144
+ * ## Why
145
+ *
146
+ * Use this at an input boundary that must decode, validate, or load Effect
147
+ * services before the existing consumer can accept a value.
148
+ *
149
+ * ## Ownership and lifetime
150
+ *
151
+ * Effect construction happens eagerly at `onSuccess`; only execution is deferred.
152
+ * The fiber running the returned acknowledgment owns execution and interruption
153
+ * of the constructed Effect and downstream callback. `E` is handled by the Sink
154
+ * failure channel, while `R3` joins the input service requirements.
155
+ *
156
+ * @example
157
+ * ```ts
158
+ * import { Effect } from "effect"
159
+ * import * as Fx from "@typed/fx/Fx"
160
+ * import * as Push from "@typed/fx/Push"
161
+ * import * as Sink from "@typed/fx/Sink"
162
+ *
163
+ * const numbers: Array<number> = []
164
+ * const base = Push.make(
165
+ * Sink.make(() => Effect.void, (n: number) => Effect.sync(() => numbers.push(n))),
166
+ * Fx.empty
167
+ * )
168
+ * const parsed = Push.mapInputEffect(base, (text: string) =>
169
+ * text === "" ? Effect.fail("empty" as const) : Effect.succeed(Number(text))
170
+ * )
171
+ * ```
172
+ *
173
+ * @since 1.0.0
174
+ * @category combinators
175
+ */
110
176
  export const mapInputEffect = dual(2, function mapInputEffect(push, f) {
111
177
  return make(Sink.mapEffect(push, f), push);
112
178
  });
179
+ /**
180
+ * Keeps successful inputs that satisfy `f` and discards the rest.
181
+ *
182
+ * Calling `onSuccess` runs the predicate immediately. A match constructs one Sink
183
+ * callback Effect; a non-match immediately returns an empty acknowledgment.
184
+ * Predicate allocation and throws therefore occur before the returned Effect is
185
+ * run. The producer controls call order and concurrency; output is preserved.
186
+ *
187
+ * @remarks
188
+ * ## Why
189
+ *
190
+ * Filtering before the consumer avoids teaching the underlying Sink about input
191
+ * values that are irrelevant to it.
192
+ *
193
+ * ## Ownership and lifetime
194
+ *
195
+ * The predicate is synchronous at `onSuccess` invocation and acquires no
196
+ * resources. Accepted callback Effects retain the original Sink's errors,
197
+ * services, interruption, and cleanup.
198
+ *
199
+ * @example
200
+ * ```ts
201
+ * import { Effect } from "effect"
202
+ * import * as Fx from "@typed/fx/Fx"
203
+ * import * as Push from "@typed/fx/Push"
204
+ * import * as Sink from "@typed/fx/Sink"
205
+ *
206
+ * const checks: Array<number> = []
207
+ * const positives = Push.filterInput(
208
+ * Push.make(Sink.make(() => Effect.void, (n: number) => Effect.log(n)), Fx.empty),
209
+ * (n) => (checks.push(n), n > 0)
210
+ * )
211
+ * const acknowledgement = positives.onSuccess(-1)
212
+ * // checks is already [-1]; acknowledgement performs no Sink callback.
213
+ * ```
214
+ *
215
+ * @since 1.0.0
216
+ * @category combinators
217
+ */
113
218
  export const filterInput = dual(2, function filterInput(push, f) {
114
219
  return make(Sink.filter(push, f), push);
115
220
  });
221
+ /**
222
+ * Effectfully decides whether each successful input reaches the Sink.
223
+ *
224
+ * Calling `onSuccess(value)` invokes `f(value)` immediately to construct the
225
+ * predicate Effect; allocation and throws happen before an acknowledgment is
226
+ * returned. Running the acknowledgment later executes that Effect in the caller's
227
+ * fiber. `true` forwards one value, `false` none, and failure sends its Cause to
228
+ * the Sink failure callback. Calls are not serialized; the producer controls
229
+ * order and concurrency. Output behavior is unchanged.
230
+ *
231
+ * @remarks
232
+ * ## Why
233
+ *
234
+ * This supports authorization and service-backed eligibility checks directly at
235
+ * the consumer boundary.
236
+ *
237
+ * ## Ownership and lifetime
238
+ *
239
+ * Predicate Effect construction is eager; its execution and downstream callback
240
+ * belong to the fiber that runs the returned acknowledgment, whose interruption
241
+ * stops them. Predicate services join input `R`; typed `E` is consumed through
242
+ * the Sink failure channel.
243
+ *
244
+ * @example
245
+ * ```ts
246
+ * import { Effect } from "effect"
247
+ * import * as Fx from "@typed/fx/Fx"
248
+ * import * as Push from "@typed/fx/Push"
249
+ * import * as Sink from "@typed/fx/Sink"
250
+ *
251
+ * const even = Push.filterInputEffect(
252
+ * Push.make(Sink.make(() => Effect.void, (_n: number) => Effect.void), Fx.empty),
253
+ * (n) => Effect.succeed(n % 2 === 0)
254
+ * )
255
+ * ```
256
+ *
257
+ * @since 1.0.0
258
+ * @category combinators
259
+ */
116
260
  export const filterInputEffect = dual(2, function filterInputEffect(push, f) {
117
261
  return make(Sink.filterEffect(push, f), push);
118
262
  });
263
+ /**
264
+ * Transforms an input and forwards it only when `f` returns `Some`.
265
+ *
266
+ * Calling `onSuccess` evaluates `f` immediately. `Some(a)` constructs one Sink
267
+ * callback Effect; `None` immediately returns an empty acknowledgment. Mapping
268
+ * allocation and throws therefore happen before the returned Effect runs. Calls
269
+ * are not serialized, so ordering follows the producer. Output is unchanged.
270
+ *
271
+ * @remarks
272
+ * ## Why
273
+ *
274
+ * `Option` combines parsing and filtering without a sentinel value or a separate
275
+ * predicate pass.
276
+ *
277
+ * ## Ownership and lifetime
278
+ *
279
+ * The mapping is synchronous at `onSuccess` invocation and resource-free. A
280
+ * forwarded callback Effect retains the original Sink's lifetime, error channel,
281
+ * and service requirements.
282
+ *
283
+ * @example
284
+ * ```ts
285
+ * import { Effect, Option } from "effect"
286
+ * import * as Fx from "@typed/fx/Fx"
287
+ * import * as Push from "@typed/fx/Push"
288
+ * import * as Sink from "@typed/fx/Sink"
289
+ *
290
+ * const parsed: Array<string> = []
291
+ * const integers = Push.filterMapInput(
292
+ * Push.make(Sink.make(() => Effect.void, (n: number) => Effect.log(n)), Fx.empty),
293
+ * (text: string) => {
294
+ * parsed.push(text)
295
+ * return /^\d+$/.test(text) ? Option.some(Number(text)) : Option.none()
296
+ * }
297
+ * )
298
+ * const acknowledgement = integers.onSuccess("nope")
299
+ * // parsed is already ["nope"]; acknowledgement performs no Sink callback.
300
+ * ```
301
+ *
302
+ * @since 1.0.0
303
+ * @category combinators
304
+ */
119
305
  export const filterMapInput = dual(2, function filterMapInput(push, f) {
120
306
  return make(Sink.filterMap(push, f), push);
121
307
  });
308
+ /**
309
+ * Effectfully transforms an input and forwards only a resulting `Some` value.
310
+ *
311
+ * Calling `onSuccess(value)` invokes `f(value)` immediately to construct an
312
+ * Effect; allocation and throws happen before an acknowledgment is returned.
313
+ * Running that acknowledgment later executes the constructed Effect in the
314
+ * caller's fiber. `Some(a)` produces one Sink callback, `None` none, and failure
315
+ * sends its full Cause to the Sink failure callback. Concurrent calls are not
316
+ * serialized.
317
+ *
318
+ * @remarks
319
+ * ## Why
320
+ *
321
+ * This is the input-boundary form for service-backed lookup or validation where
322
+ * absence is expected but failure remains meaningful.
323
+ *
324
+ * ## Ownership and lifetime
325
+ *
326
+ * Mapper Effect construction is eager; execution belongs to the fiber that runs
327
+ * the returned acknowledgment and can be interrupted there. Mapper requirements
328
+ * join the Sink input requirements; its `E` is handled through the same failure
329
+ * callback. The output Fx is untouched.
330
+ *
331
+ * @example
332
+ * ```ts
333
+ * import { Effect, Option } from "effect"
334
+ * import * as Fx from "@typed/fx/Fx"
335
+ * import * as Push from "@typed/fx/Push"
336
+ * import * as Sink from "@typed/fx/Sink"
337
+ *
338
+ * const known = Push.filterMapInputEffect(
339
+ * Push.make(Sink.make(() => Effect.void, (_n: number) => Effect.void), Fx.empty),
340
+ * (text: string) => Effect.succeed(text === "one" ? Option.some(1) : Option.none())
341
+ * )
342
+ * ```
343
+ *
344
+ * @since 1.0.0
345
+ * @category combinators
346
+ */
122
347
  export const filterMapInputEffect = dual(2, function filterMapInputEffect(push, f) {
123
348
  return make(Sink.filterMapEffect(push, f), push);
124
349
  });
125
350
  /**
126
- * Maps over the output (Fx) side of a `Push`.
351
+ * Synchronously transforms every value emitted by the Fx output side.
352
+ *
353
+ * It emits exactly one `C` for every upstream `B`, preserving order and the
354
+ * complete input Sink. The mapping does not buffer or introduce concurrency.
355
+ *
356
+ * @remarks
357
+ * ## Why
358
+ *
359
+ * Adapt observed events without changing the commands the bidirectional boundary
360
+ * accepts.
361
+ *
362
+ * ## Ownership and lifetime
363
+ *
364
+ * `f` runs in the upstream Fx delivery path and owns no resource. Output
365
+ * subscription, interruption, failures, services, and cleanup remain those of the
366
+ * wrapped Fx and downstream Sink.
127
367
  *
128
368
  * @example
129
369
  * ```ts
@@ -158,6 +398,39 @@ export const filterMapInputEffect = dual(2, function filterMapInputEffect(push,
158
398
  export const map = dual(2, function map(push, f) {
159
399
  return make(push, Fx.map(push, f));
160
400
  });
401
+ /**
402
+ * Effectfully transforms each Fx output value.
403
+ *
404
+ * The mapper runs once per upstream value and emits one result on success, in
405
+ * upstream order for a sequential source. Its typed failures join `E2`; its
406
+ * required services join `R2`. The input side is unchanged.
407
+ *
408
+ * @remarks
409
+ * ## Why
410
+ *
411
+ * Use this for output enrichment that needs Effect services or can fail while
412
+ * keeping input handling independent.
413
+ *
414
+ * ## Ownership and lifetime
415
+ *
416
+ * Each mapper Effect runs inside the output subscription and is interrupted with
417
+ * it. No work starts before `run`; cleanup belongs to the upstream Fx and mapper
418
+ * effects. `mapEffect` itself introduces no separate buffer or long-lived fiber.
419
+ *
420
+ * @example
421
+ * ```ts
422
+ * import { Effect } from "effect"
423
+ * import * as Fx from "@typed/fx/Fx"
424
+ * import * as Push from "@typed/fx/Push"
425
+ * import * as Sink from "@typed/fx/Sink"
426
+ *
427
+ * const push = Push.make(Sink.make(() => Effect.void, (_: string) => Effect.void), Fx.succeed(2))
428
+ * const doubled = Push.mapEffect(push, (n) => Effect.succeed(n * 2))
429
+ * ```
430
+ *
431
+ * @since 1.0.0
432
+ * @category combinators
433
+ */
161
434
  export const mapEffect = dual(2, function mapEffect(push, f) {
162
435
  return make(push, Fx.mapEffect(push, f));
163
436
  });
@@ -167,7 +440,31 @@ export const mapEffect = dual(2, function mapEffect(push, f) {
167
440
  * Failures (Cause) are mapped via `Cause.map`, so only the typed failure (`Fail`)
168
441
  * is transformed; defects and interrupts are preserved unchanged.
169
442
  *
170
- * Mirrors `Effect.mapError` on the Fx side.
443
+ * Mirrors `Effect.mapError` on the Fx side. Cardinality, value order, input
444
+ * callbacks, and output service requirements are unchanged.
445
+ *
446
+ * @remarks
447
+ * ## Why
448
+ *
449
+ * Normalize an output failure type at the observation boundary without touching
450
+ * input errors or collapsing defects and interruption into typed failures.
451
+ *
452
+ * ## Ownership and lifetime
453
+ *
454
+ * The mapping is synchronous and resource-free. It runs when the output Cause is
455
+ * delivered and preserves the upstream subscription, Scope, interruption, and
456
+ * cleanup behavior.
457
+ *
458
+ * @example
459
+ * ```ts
460
+ * import { Effect } from "effect"
461
+ * import * as Fx from "@typed/fx/Fx"
462
+ * import * as Push from "@typed/fx/Push"
463
+ * import * as Sink from "@typed/fx/Sink"
464
+ *
465
+ * const push = Push.make(Sink.make(() => Effect.void, (_: string) => Effect.void), Fx.fail("offline"))
466
+ * const normalized = Push.mapError(push, (message) => ({ message }))
467
+ * ```
171
468
  *
172
469
  * @since 1.0.0
173
470
  * @category combinators
@@ -178,8 +475,34 @@ export const mapError = dual(2, function mapError(push, f) {
178
475
  /**
179
476
  * Transforms both the output (Fx) success and error channels of a `Push` using the provided options.
180
477
  *
181
- * Mirrors `Effect.mapBoth` on the Fx side: `onSuccess` maps emitted values,
182
- * `onFailure` maps the typed failure (via `Cause.map`); defects and interrupts are preserved.
478
+ * Mirrors `Effect.mapBoth` on the Fx side: `onSuccess` maps every emitted value
479
+ * one-to-one and `onFailure` maps typed failures via `Cause.map`; defects and
480
+ * interrupts are preserved. Ordering, services, and the input side are unchanged.
481
+ *
482
+ * @remarks
483
+ * ## Why
484
+ *
485
+ * Adapt both observable result channels at once while leaving command handling
486
+ * and non-typed Cause information intact.
487
+ *
488
+ * ## Ownership and lifetime
489
+ *
490
+ * Both functions run synchronously in the output delivery path and acquire no
491
+ * resources. The wrapped Fx retains ownership of its subscription and finalizers.
492
+ *
493
+ * @example
494
+ * ```ts
495
+ * import { Effect } from "effect"
496
+ * import * as Fx from "@typed/fx/Fx"
497
+ * import * as Push from "@typed/fx/Push"
498
+ * import * as Sink from "@typed/fx/Sink"
499
+ *
500
+ * const push = Push.make(Sink.make(() => Effect.void, (_: string) => Effect.void), Fx.succeed(2))
501
+ * const labeled = Push.mapBoth(push, {
502
+ * onFailure: (error: never) => error,
503
+ * onSuccess: (value) => `value:${value}`
504
+ * })
505
+ * ```
183
506
  *
184
507
  * @since 1.0.0
185
508
  * @category combinators
@@ -187,47 +510,202 @@ export const mapError = dual(2, function mapError(push, f) {
187
510
  export const mapBoth = dual(2, function mapBoth(push, options) {
188
511
  return make(push, Fx.mapBoth(push, options));
189
512
  });
513
+ /**
514
+ * Keeps Fx output values that satisfy `f`.
515
+ *
516
+ * The upstream Sink invokes the predicate synchronously for each output value,
517
+ * before the returned downstream callback Effect runs. Predicate allocation and
518
+ * throws therefore occur at upstream callback invocation. Matches preserve their
519
+ * relative order; non-matches produce no output. No buffer is added and every
520
+ * input callback is unchanged.
521
+ *
522
+ * @remarks
523
+ * ## Why
524
+ *
525
+ * Restrict observed events without restricting which commands the Push accepts.
526
+ *
527
+ * ## Ownership and lifetime
528
+ *
529
+ * The predicate is synchronous at upstream `onSuccess` invocation and
530
+ * resource-free. Subscription, interruption, failures, services, and cleanup
531
+ * remain those of the wrapped Fx.
532
+ *
533
+ * @example
534
+ * ```ts
535
+ * import { Effect } from "effect"
536
+ * import * as Fx from "@typed/fx/Fx"
537
+ * import * as Push from "@typed/fx/Push"
538
+ * import * as Sink from "@typed/fx/Sink"
539
+ *
540
+ * const push = Push.make(Sink.make(() => Effect.void, (_: string) => Effect.void), Fx.fromIterable([1, 2, 3]))
541
+ * const even = Push.filter(push, (n) => n % 2 === 0)
542
+ * ```
543
+ *
544
+ * @since 1.0.0
545
+ * @category combinators
546
+ */
190
547
  export const filter = dual(2, function filter(push, f) {
191
548
  return make(push, Fx.filter(push, f));
192
549
  });
550
+ /**
551
+ * Effectfully decides which Fx output values are emitted.
552
+ *
553
+ * Each upstream value runs one predicate. `true` emits that value, `false` emits
554
+ * none, and predicate failures join the output error channel. For a sequential
555
+ * source the predicate is acknowledged before the next delivery, preserving
556
+ * order; the input side is unchanged.
557
+ *
558
+ * @remarks
559
+ * ## Why
560
+ *
561
+ * Use this when an observed event needs an Effect service or fallible check before
562
+ * it is visible downstream.
563
+ *
564
+ * ## Ownership and lifetime
565
+ *
566
+ * Predicate effects run inside and are interrupted with the output subscription.
567
+ * Their `E3` failures and `R3` services join the Fx channels. No separate queue or
568
+ * persistent fiber is introduced.
569
+ *
570
+ * @example
571
+ * ```ts
572
+ * import { Effect } from "effect"
573
+ * import * as Fx from "@typed/fx/Fx"
574
+ * import * as Push from "@typed/fx/Push"
575
+ * import * as Sink from "@typed/fx/Sink"
576
+ *
577
+ * const push = Push.make(Sink.make(() => Effect.void, (_: string) => Effect.void), Fx.fromIterable([1, 2]))
578
+ * const positive = Push.filterEffect(push, (n) => Effect.succeed(n > 0))
579
+ * ```
580
+ *
581
+ * @since 1.0.0
582
+ * @category combinators
583
+ */
193
584
  export const filterEffect = dual(2, function filterEffect(push, f) {
194
585
  return make(push, Fx.filterEffect(push, f));
195
586
  });
587
+ /**
588
+ * Maps each Fx output and emits only resulting `Some` values.
589
+ *
590
+ * The upstream Sink evaluates `f` synchronously for each value, before its
591
+ * returned downstream callback Effect runs. Mapping allocation and throws occur
592
+ * at that callback invocation. `Some(c)` emits exactly one `c`; `None` emits
593
+ * nothing. Relative order, errors, services, and input behavior are preserved.
594
+ *
595
+ * @remarks
596
+ * ## Why
597
+ *
598
+ * Combine output parsing and filtering without a sentinel value or a second pass.
599
+ *
600
+ * ## Ownership and lifetime
601
+ *
602
+ * The mapper is synchronous at upstream `onSuccess` invocation and resource-free.
603
+ * The wrapped Fx retains ownership of subscription, Scope, interruption, and
604
+ * finalizers.
605
+ *
606
+ * @example
607
+ * ```ts
608
+ * import { Effect, Option } from "effect"
609
+ * import * as Fx from "@typed/fx/Fx"
610
+ * import * as Push from "@typed/fx/Push"
611
+ * import * as Sink from "@typed/fx/Sink"
612
+ *
613
+ * const push = Push.make(Sink.make(() => Effect.void, (_: string) => Effect.void), Fx.fromIterable(["1", "x"]))
614
+ * const numbers = Push.filterMap(push, (text) => /^\d+$/.test(text) ? Option.some(Number(text)) : Option.none())
615
+ * ```
616
+ *
617
+ * @since 1.0.0
618
+ * @category combinators
619
+ */
196
620
  export const filterMap = dual(2, function filterMap(push, f) {
197
621
  return make(push, Fx.filterMap(push, f));
198
622
  });
623
+ /**
624
+ * Effectfully maps each Fx output and emits only resulting `Some` values.
625
+ *
626
+ * One mapper Effect runs per upstream value. `Some(c)` emits once, `None` emits
627
+ * nothing, and failures join the output error channel. Sequential sources retain
628
+ * order; the input Sink remains unchanged.
629
+ *
630
+ * @remarks
631
+ * ## Why
632
+ *
633
+ * This models service-backed lookup where absence is an ordinary filtered result
634
+ * but operational failure must remain observable.
635
+ *
636
+ * ## Ownership and lifetime
637
+ *
638
+ * Mapper effects are owned and interrupted by the output subscription. Their
639
+ * services join `R2` and failures join `E2`; the combinator adds no independent
640
+ * buffer or resource.
641
+ *
642
+ * @example
643
+ * ```ts
644
+ * import { Effect, Option } from "effect"
645
+ * import * as Fx from "@typed/fx/Fx"
646
+ * import * as Push from "@typed/fx/Push"
647
+ * import * as Sink from "@typed/fx/Sink"
648
+ *
649
+ * const push = Push.make(Sink.make(() => Effect.void, (_: string) => Effect.void), Fx.succeed("one"))
650
+ * const ids = Push.filterMapEffect(push, (name) => Effect.succeed(name === "one" ? Option.some(1) : Option.none()))
651
+ * ```
652
+ *
653
+ * @since 1.0.0
654
+ * @category combinators
655
+ */
199
656
  export const filterMapEffect = dual(2, function filterMapEffect(push, f) {
200
657
  return make(push, Fx.filterMapEffect(push, f));
201
658
  });
202
659
  /**
203
- * Transforms each output value into a new `Fx`, switching to the latest inner `Fx` when a new value arrives.
660
+ * Transforms each output value into an inner `Fx`, observing only the latest one.
661
+ *
662
+ * A new outer value interrupts the previous inner fiber before starting the next.
663
+ * Output cardinality is the cardinality of the successive active inners; values
664
+ * from an interrupted inner stop. Outer order determines replacement order, while
665
+ * each active inner preserves its own order. The input Sink is unchanged.
666
+ *
667
+ * @remarks
668
+ * ## Why
669
+ *
670
+ * Latest-wins composition models search, navigation, and other work where a newer
671
+ * request makes the previous result irrelevant.
672
+ *
673
+ * ## Ownership and lifetime
674
+ *
675
+ * Running the result requires `Scope.Scope`. Each inner runs in that Scope and is
676
+ * interrupted on replacement or outer interruption; the last inner is joined
677
+ * before normal completion. Outer and inner errors/services are combined.
204
678
  *
205
679
  * @example
206
680
  * ```ts
207
681
  * import { Effect } from "effect"
682
+ * import * as Fx from "@typed/fx/Fx"
208
683
  * import * as Push from "@typed/fx/Push"
209
- * import { Fx } from "@typed/fx"
210
684
  * import * as Sink from "@typed/fx/Sink"
211
685
  *
212
- * const program = Effect.gen(function* () {
213
- * const push = Push.make(
214
- * Sink.make(
215
- * (cause) => Effect.void,
216
- * (value) => Effect.void
217
- * ),
218
- * Fx.succeed(1)
219
- * )
220
- *
221
- * // Switch to a new Fx for each value
222
- * const switched = Push.switchMap(push, (n) =>
223
- * Fx.fromIterable([n, n * 2, n * 3])
686
+ * const finalized: Array<number> = []
687
+ * const outer = Fx.make<number>((sink) =>
688
+ * sink.onSuccess(1).pipe(
689
+ * Effect.andThen(Effect.sleep("5 millis")),
690
+ * Effect.andThen(sink.onSuccess(2))
224
691
  * )
225
- *
226
- * // Only the latest Fx's values are emitted
227
- * yield* Fx.observe(switched, (value) =>
228
- * Effect.sync(() => console.log(value))
692
+ * )
693
+ * const push = Push.make(Sink.make(() => Effect.void, (_: string) => Effect.void), outer)
694
+ * const switched = Push.switchMap(push, (id) =>
695
+ * Fx.make<number>((sink) =>
696
+ * Effect.gen(function* () {
697
+ * yield* Effect.sleep("2 millis")
698
+ * yield* sink.onSuccess(id * 10 + 1)
699
+ * yield* Effect.sleep(id === 1 ? "20 millis" : "2 millis")
700
+ * yield* sink.onSuccess(id * 10 + 2)
701
+ * }).pipe(Effect.ensuring(Effect.sync(() => finalized.push(id))))
229
702
  * )
230
- * })
703
+ * )
704
+ * const program = Fx.collectAll(switched).pipe(
705
+ * Effect.map((values) => ({ values, finalized })),
706
+ * Effect.scoped
707
+ * )
708
+ * // Effect.runPromise(program) => { values: [11, 21, 22], finalized: [1, 2] }
231
709
  * ```
232
710
  *
233
711
  * @since 1.0.0
@@ -236,38 +714,106 @@ export const filterMapEffect = dual(2, function filterMapEffect(push, f) {
236
714
  export const switchMap = dual(2, function switchMap(push, f) {
237
715
  return make(push, Fx.switchMap(push, f));
238
716
  });
239
- export const switchMapEffect = dual(2, function switchMapEffect(push, f) {
240
- return make(push, Fx.switchMapEffect(push, f));
241
- });
242
717
  /**
243
- * Transforms each output value into a new `Fx` and merges all inner `Fx` values concurrently.
718
+ * Transforms each output value into an Effect, keeping only the latest Effect.
719
+ *
720
+ * Each new outer value interrupts the previous Effect before starting its own.
721
+ * Every Effect can emit at most one value; interrupted Effects emit none. The
722
+ * input side is unchanged.
723
+ *
724
+ * @remarks
725
+ * ## Why
726
+ *
727
+ * This is latest-wins Effect composition without manually wrapping each Effect as
728
+ * an Fx.
729
+ *
730
+ * ## Ownership and lifetime
731
+ *
732
+ * The output subscription's Scope owns the active Effect fiber. Replacement and
733
+ * subscription interruption run its interruption/finalizers. `E3` joins output
734
+ * errors and `R3` joins required services.
244
735
  *
245
736
  * @example
246
737
  * ```ts
247
738
  * import { Effect } from "effect"
739
+ * import * as Fx from "@typed/fx/Fx"
248
740
  * import * as Push from "@typed/fx/Push"
249
- * import { Fx } from "@typed/fx"
250
741
  * import * as Sink from "@typed/fx/Sink"
251
742
  *
252
- * const program = Effect.gen(function* () {
253
- * const push = Push.make(
254
- * Sink.make(
255
- * (cause) => Effect.void,
256
- * (value) => Effect.void
257
- * ),
258
- * Fx.succeed(1)
743
+ * const finalized: Array<number> = []
744
+ * const source = Fx.make<number>((sink) =>
745
+ * sink.onSuccess(1).pipe(
746
+ * Effect.andThen(Effect.sleep("2 millis")),
747
+ * Effect.andThen(sink.onSuccess(2))
259
748
  * )
260
- *
261
- * // FlatMap merges all inner Fx values
262
- * const flattened = Push.flatMap(push, (n) =>
263
- * Fx.fromIterable([n, n * 2, n * 3])
749
+ * )
750
+ * const push = Push.make(Sink.make(() => Effect.void, (_: string) => Effect.void), source)
751
+ * const latest = Push.switchMapEffect(push, (id) =>
752
+ * Effect.sleep(id === 1 ? "20 millis" : "1 millis").pipe(
753
+ * Effect.as(id),
754
+ * Effect.ensuring(Effect.sync(() => finalized.push(id)))
264
755
  * )
756
+ * )
757
+ * const program = Fx.collectAll(latest).pipe(
758
+ * Effect.map((values) => ({ values, finalized })),
759
+ * Effect.scoped
760
+ * )
761
+ * // Effect.runPromise(program) => { values: [2], finalized: [1, 2] }
762
+ * ```
265
763
  *
266
- * // All values from all inner Fx are emitted
267
- * yield* Fx.observe(flattened, (value) =>
268
- * Effect.sync(() => console.log(value))
764
+ * @since 1.0.0
765
+ * @category combinators
766
+ */
767
+ export const switchMapEffect = dual(2, function switchMapEffect(push, f) {
768
+ return make(push, Fx.switchMapEffect(push, f));
769
+ });
770
+ /**
771
+ * Transforms each output value into an inner `Fx` and merges all inners concurrently.
772
+ *
773
+ * Every outer value starts one inner. All inner values are emitted; order within
774
+ * each inner is preserved, but values from different inners may interleave. The
775
+ * outer stream waits for all inners before normal completion. The input Sink is
776
+ * unchanged.
777
+ *
778
+ * @remarks
779
+ * ## Why
780
+ *
781
+ * Use concurrent flattening when every produced task matters and independent work
782
+ * should overlap.
783
+ *
784
+ * ## Ownership and lifetime
785
+ *
786
+ * The output Scope owns a fiber set containing all active inners. Outer
787
+ * interruption interrupts that set and runs inner cleanup. Inner failures and
788
+ * services join the outer Fx channels; no ordering buffer is added.
789
+ *
790
+ * @example
791
+ * ```ts
792
+ * import { Effect } from "effect"
793
+ * import * as Fx from "@typed/fx/Fx"
794
+ * import * as Push from "@typed/fx/Push"
795
+ * import * as Sink from "@typed/fx/Sink"
796
+ *
797
+ * const finalized: Array<number> = []
798
+ * const push = Push.make(
799
+ * Sink.make(() => Effect.void, (_: string) => Effect.void),
800
+ * Fx.fromIterable([1, 2])
801
+ * )
802
+ * const merged = Push.flatMap(push, (id) =>
803
+ * Fx.make<number>((sink) =>
804
+ * Effect.gen(function* () {
805
+ * yield* Effect.sleep(id === 1 ? "5 millis" : "10 millis")
806
+ * yield* sink.onSuccess(id * 10 + 1)
807
+ * yield* Effect.sleep("20 millis")
808
+ * yield* sink.onSuccess(id * 10 + 2)
809
+ * }).pipe(Effect.ensuring(Effect.sync(() => finalized.push(id))))
269
810
  * )
270
- * })
811
+ * )
812
+ * const program = Fx.collectAll(merged).pipe(
813
+ * Effect.map((values) => ({ values, finalized })),
814
+ * Effect.scoped
815
+ * )
816
+ * // Effect.runPromise(program) => { values: [11, 21, 12, 22], finalized: [1, 2] }
271
817
  * ```
272
818
  *
273
819
  * @since 1.0.0
@@ -276,18 +822,277 @@ export const switchMapEffect = dual(2, function switchMapEffect(push, f) {
276
822
  export const flatMap = dual(2, function flatMap(push, f) {
277
823
  return make(push, Fx.flatMap(push, f));
278
824
  });
825
+ /**
826
+ * Transforms every output value into an Effect and merges their results concurrently.
827
+ *
828
+ * One Effect starts per outer value and can emit one result. All successful
829
+ * results are emitted, but concurrent completion order may differ from input
830
+ * order. The input side is unchanged.
831
+ *
832
+ * @remarks
833
+ * ## Why
834
+ *
835
+ * This runs independent Effect work concurrently without manually lifting each
836
+ * Effect into Fx.
837
+ *
838
+ * ## Ownership and lifetime
839
+ *
840
+ * Active Effects are fibers owned by the output Scope. Completion waits for all
841
+ * of them; interruption stops them and runs their finalizers. `E3` and `R3` join
842
+ * the output failure and service channels.
843
+ *
844
+ * @example
845
+ * ```ts
846
+ * import { Effect } from "effect"
847
+ * import * as Fx from "@typed/fx/Fx"
848
+ * import * as Push from "@typed/fx/Push"
849
+ * import * as Sink from "@typed/fx/Sink"
850
+ *
851
+ * const finalized: Array<number> = []
852
+ * const push = Push.make(
853
+ * Sink.make(() => Effect.void, (_: string) => Effect.void),
854
+ * Fx.fromIterable([1, 2])
855
+ * )
856
+ * const loaded = Push.flatMapEffect(push, (id) =>
857
+ * Effect.sleep(id === 1 ? "20 millis" : "1 millis").pipe(
858
+ * Effect.as(id),
859
+ * Effect.ensuring(Effect.sync(() => finalized.push(id)))
860
+ * )
861
+ * )
862
+ * const program = Fx.collectAll(loaded).pipe(
863
+ * Effect.map((values) => ({ values, finalized })),
864
+ * Effect.scoped
865
+ * )
866
+ * // Effect.runPromise(program) => { values: [2, 1], finalized: [2, 1] }
867
+ * ```
868
+ *
869
+ * @since 1.0.0
870
+ * @category combinators
871
+ */
279
872
  export const flatMapEffect = dual(2, function flatMapEffect(push, f) {
280
873
  return make(push, Fx.flatMapEffect(push, f));
281
874
  });
875
+ /**
876
+ * Runs at most one inner Fx and ignores outer values while it is active.
877
+ *
878
+ * The first value seen while idle starts an inner; every value arriving before
879
+ * that inner completes is dropped. `f(value)` is still evaluated and its inner Fx
880
+ * is constructed before the busy check; dropping means the returned Fx is not
881
+ * run. Accepted inners preserve their own order and all values. Input is unchanged.
882
+ *
883
+ * @remarks
884
+ * ## Why
885
+ *
886
+ * Exhaust semantics prevent duplicate work, such as repeated submit clicks, while
887
+ * allowing another request after the active one completes.
888
+ *
889
+ * ## Ownership and lifetime
890
+ *
891
+ * The output Scope owns the active inner fiber, joins it before completion, and
892
+ * interrupts it with the subscription. Inner failures and services join the
893
+ * outer channels; there is no pending-value buffer.
894
+ *
895
+ * @example
896
+ * ```ts
897
+ * import { Effect } from "effect"
898
+ * import * as Fx from "@typed/fx/Fx"
899
+ * import * as Push from "@typed/fx/Push"
900
+ * import * as Sink from "@typed/fx/Sink"
901
+ *
902
+ * const constructed: Array<number> = []
903
+ * const started: Array<number> = []
904
+ * const finalized: Array<number> = []
905
+ * const push = Push.make(
906
+ * Sink.make(() => Effect.void, (_: string) => Effect.void),
907
+ * Fx.fromIterable([1, 2])
908
+ * )
909
+ * const exhausted = Push.exhaustMap(push, (id) => {
910
+ * constructed.push(id)
911
+ * return Fx.make<number>((sink) =>
912
+ * Effect.gen(function* () {
913
+ * yield* Effect.sync(() => started.push(id))
914
+ * yield* Effect.sleep("5 millis")
915
+ * yield* sink.onSuccess(id * 10 + 1)
916
+ * yield* Effect.sleep("5 millis")
917
+ * yield* sink.onSuccess(id * 10 + 2)
918
+ * }).pipe(Effect.ensuring(Effect.sync(() => finalized.push(id))))
919
+ * )
920
+ * })
921
+ * const program = Fx.collectAll(exhausted).pipe(
922
+ * Effect.map((values) => ({ values, constructed, started, finalized })),
923
+ * Effect.scoped
924
+ * )
925
+ * // => { values: [11, 12], constructed: [1, 2], started: [1], finalized: [1] }
926
+ * ```
927
+ *
928
+ * @since 1.0.0
929
+ * @category combinators
930
+ */
282
931
  export const exhaustMap = dual(2, function exhaustMap(push, f) {
283
932
  return make(push, Fx.exhaustMap(push, f));
284
933
  });
934
+ /**
935
+ * Runs at most one mapped Effect and ignores values while it is active.
936
+ *
937
+ * The first value while idle starts one Effect and can emit one result; all values
938
+ * received before it completes are dropped. The mapping callback is still invoked
939
+ * and constructs an Effect for every value before the busy check; dropped Effects
940
+ * are not run. The input side is unchanged.
941
+ *
942
+ * @remarks
943
+ * ## Why
944
+ *
945
+ * This guards non-overlapping Effect work without manual busy state.
946
+ *
947
+ * ## Ownership and lifetime
948
+ *
949
+ * The output Scope owns and joins the active Effect fiber. Subscription
950
+ * interruption stops it and runs finalizers. Its errors and services join the
951
+ * output channels; no value is buffered for later.
952
+ *
953
+ * @example
954
+ * ```ts
955
+ * import { Effect } from "effect"
956
+ * import * as Fx from "@typed/fx/Fx"
957
+ * import * as Push from "@typed/fx/Push"
958
+ * import * as Sink from "@typed/fx/Sink"
959
+ *
960
+ * const constructed: Array<number> = []
961
+ * const finalized: Array<number> = []
962
+ * const push = Push.make(
963
+ * Sink.make(() => Effect.void, (_: string) => Effect.void),
964
+ * Fx.fromIterable([1, 2])
965
+ * )
966
+ * const saving = Push.exhaustMapEffect(push, (id) => {
967
+ * constructed.push(id)
968
+ * return Effect.sleep("10 millis").pipe(
969
+ * Effect.as(id),
970
+ * Effect.ensuring(Effect.sync(() => finalized.push(id)))
971
+ * )
972
+ * })
973
+ * const program = Fx.collectAll(saving).pipe(
974
+ * Effect.map((values) => ({ values, constructed, finalized })),
975
+ * Effect.scoped
976
+ * )
977
+ * // Effect.runPromise(program) => { values: [1], constructed: [1, 2], finalized: [1] }
978
+ * ```
979
+ *
980
+ * @since 1.0.0
981
+ * @category combinators
982
+ */
285
983
  export const exhaustMapEffect = dual(2, function exhaustMapEffect(push, f) {
286
984
  return make(push, Fx.exhaustMapEffect(push, f));
287
985
  });
986
+ /**
987
+ * Runs one inner Fx at a time and retains only the latest value received while busy.
988
+ *
989
+ * A value while idle starts immediately. While its inner runs, newer outer values
990
+ * replace a single pending slot. `f(value)` is evaluated and an inner Fx is
991
+ * constructed before every replacement; a superseded pending Fx is never run.
992
+ * After completion, only the latest pending Fx starts. Accepted inners preserve
993
+ * their own order and all values. The input Sink is unchanged.
994
+ *
995
+ * @remarks
996
+ * ## Why
997
+ *
998
+ * This is useful when work must not overlap but the newest requested state must
999
+ * eventually be processed.
1000
+ *
1001
+ * ## Ownership and lifetime
1002
+ *
1003
+ * The output Scope owns one active inner fiber and an in-memory latest slot. It
1004
+ * joins the final inner before completion and interrupts it with the subscription.
1005
+ * Inner failures and services join the output channels.
1006
+ *
1007
+ * @example
1008
+ * ```ts
1009
+ * import { Effect } from "effect"
1010
+ * import * as Fx from "@typed/fx/Fx"
1011
+ * import * as Push from "@typed/fx/Push"
1012
+ * import * as Sink from "@typed/fx/Sink"
1013
+ *
1014
+ * const constructed: Array<number> = []
1015
+ * const started: Array<number> = []
1016
+ * const finalized: Array<number> = []
1017
+ * const push = Push.make(
1018
+ * Sink.make(() => Effect.void, (_: string) => Effect.void),
1019
+ * Fx.fromIterable([1, 2, 3])
1020
+ * )
1021
+ * const latest = Push.exhaustLatestMap(push, (id) => {
1022
+ * constructed.push(id)
1023
+ * return Fx.make<number>((sink) =>
1024
+ * Effect.gen(function* () {
1025
+ * yield* Effect.sync(() => started.push(id))
1026
+ * yield* Effect.sleep("5 millis")
1027
+ * yield* sink.onSuccess(id * 10 + 1)
1028
+ * yield* Effect.sleep("5 millis")
1029
+ * yield* sink.onSuccess(id * 10 + 2)
1030
+ * }).pipe(Effect.ensuring(Effect.sync(() => finalized.push(id))))
1031
+ * )
1032
+ * })
1033
+ * const program = Fx.collectAll(latest).pipe(
1034
+ * Effect.map((values) => ({ values, constructed, started, finalized })),
1035
+ * Effect.scoped
1036
+ * )
1037
+ * // => values [11, 12, 31, 32]; constructed [1, 2, 3]; started/finalized [1, 3].
1038
+ * ```
1039
+ *
1040
+ * @since 1.0.0
1041
+ * @category combinators
1042
+ */
288
1043
  export const exhaustLatestMap = dual(2, function exhaustLatestMap(push, f) {
289
1044
  return make(push, Fx.exhaustLatestMap(push, f));
290
1045
  });
1046
+ /**
1047
+ * Runs one mapped Effect at a time and retains only the latest value received while busy.
1048
+ *
1049
+ * Each accepted Effect can emit one result. While it runs, one pending Effect is
1050
+ * repeatedly overwritten; after completion only the latest pending Effect starts.
1051
+ * The mapping callback still runs and constructs an Effect for every value before
1052
+ * replacement; superseded Effects are not run. The input side is unchanged.
1053
+ *
1054
+ * @remarks
1055
+ * ## Why
1056
+ *
1057
+ * This provides non-overlapping Effect work with eventual latest-state handling,
1058
+ * avoiding an unbounded queue of obsolete requests.
1059
+ *
1060
+ * ## Ownership and lifetime
1061
+ *
1062
+ * The output Scope owns the active Effect fiber and pending slot. It waits for the
1063
+ * final Effect, interrupts it with the subscription, and runs its finalizers.
1064
+ * Effect failures and services join the output channels.
1065
+ *
1066
+ * @example
1067
+ * ```ts
1068
+ * import { Effect } from "effect"
1069
+ * import * as Fx from "@typed/fx/Fx"
1070
+ * import * as Push from "@typed/fx/Push"
1071
+ * import * as Sink from "@typed/fx/Sink"
1072
+ *
1073
+ * const constructed: Array<number> = []
1074
+ * const finalized: Array<number> = []
1075
+ * const push = Push.make(
1076
+ * Sink.make(() => Effect.void, (_: string) => Effect.void),
1077
+ * Fx.fromIterable([1, 2, 3])
1078
+ * )
1079
+ * const latestSaved = Push.exhaustLatestMapEffect(push, (id) => {
1080
+ * constructed.push(id)
1081
+ * return Effect.sleep("10 millis").pipe(
1082
+ * Effect.as(id),
1083
+ * Effect.ensuring(Effect.sync(() => finalized.push(id)))
1084
+ * )
1085
+ * })
1086
+ * const program = Fx.collectAll(latestSaved).pipe(
1087
+ * Effect.map((values) => ({ values, constructed, finalized })),
1088
+ * Effect.scoped
1089
+ * )
1090
+ * // Effect.runPromise(program) => { values: [1, 3], constructed: [1, 2, 3], finalized: [1, 3] }
1091
+ * ```
1092
+ *
1093
+ * @since 1.0.0
1094
+ * @category combinators
1095
+ */
291
1096
  export const exhaustLatestMapEffect = dual(2, function exhaustLatestMapEffect(push, f) {
292
1097
  return make(push, Fx.exhaustLatestMapEffect(push, f));
293
1098
  });
@@ -295,6 +1100,30 @@ export const exhaustLatestMapEffect = dual(2, function exhaustLatestMapEffect(pu
295
1100
  * Maps over the output (Fx) side of a `Push` with an accumulator: for each emitted value `b`,
296
1101
  * applies `f(state, b)` to get `[nextState, emitted]` and emits the second element.
297
1102
  * The first element is the initial state; subsequent states are updated by each step.
1103
+ * It emits exactly one `C` per upstream value, in order. Accumulator state is
1104
+ * private to each output subscription; the input Sink is unchanged.
1105
+ *
1106
+ * @remarks
1107
+ * ## Why
1108
+ *
1109
+ * Stateful output projection can derive running totals or protocol state without
1110
+ * moving that state into the bidirectional input boundary.
1111
+ *
1112
+ * ## Ownership and lifetime
1113
+ *
1114
+ * Each run owns its own synchronous accumulator. It is discarded when that run
1115
+ * completes or is interrupted and acquires no Scope or external resource.
1116
+ *
1117
+ * @example
1118
+ * ```ts
1119
+ * import { Effect } from "effect"
1120
+ * import * as Fx from "@typed/fx/Fx"
1121
+ * import * as Push from "@typed/fx/Push"
1122
+ * import * as Sink from "@typed/fx/Sink"
1123
+ *
1124
+ * const push = Push.make(Sink.make(() => Effect.void, (_: string) => Effect.void), Fx.fromIterable([1, 2, 3]))
1125
+ * const totals = Push.mapAccum(push, 0, (total, value) => [total + value, total + value] as const)
1126
+ * ```
298
1127
  *
299
1128
  * @param initial - Initial accumulator state.
300
1129
  * @param f - Reducer `(state, value) => [nextState, emitted]`.
@@ -311,6 +1140,67 @@ export const mapAccum = dual(3, function mapAccum(push, initial, f) {
311
1140
  /**
312
1141
  * Maps over the output (Fx) side of a `Push` with an effectful accumulator: for each emitted value `b`,
313
1142
  * runs `f(state, b)` to get `[nextState, emitted]` and emits the second element.
1143
+ * The adapter does not serialize callbacks. Calling `onSuccess` invokes `f`
1144
+ * immediately with the current seed and constructs its Effect; overlapping calls
1145
+ * can therefore observe the same seed. Successful completion commits the returned
1146
+ * seed and emits in completion order, so later completion may overwrite newer
1147
+ * state. Reducer failure is sent to the output Sink, emits nothing, restores that
1148
+ * call's previous seed, and completes normally so a continuing producer can send
1149
+ * later values. The input Sink is unchanged.
1150
+ *
1151
+ * @remarks
1152
+ * ## Why
1153
+ *
1154
+ * Use an effectful accumulator when each transition needs services or can fail,
1155
+ * while keeping state local to observation rather than global application state.
1156
+ *
1157
+ * ## Ownership and lifetime
1158
+ *
1159
+ * Each output run owns one mutable seed, but concurrent producer callbacks may
1160
+ * race over it; callers needing serialized state transitions must serialize the
1161
+ * upstream deliveries. Each callback fiber runs and interrupts its own reducer
1162
+ * Effect. `E3` and `R3` join the output channels. State is discarded when the
1163
+ * subscription ends.
1164
+ *
1165
+ * @example
1166
+ * ```ts
1167
+ * import { Effect } from "effect"
1168
+ * import * as Fx from "@typed/fx/Fx"
1169
+ * import * as Push from "@typed/fx/Push"
1170
+ * import * as Sink from "@typed/fx/Sink"
1171
+ *
1172
+ * const concurrent = Fx.make<number>((sink) =>
1173
+ * Effect.all([sink.onSuccess(1), sink.onSuccess(2)], {
1174
+ * concurrency: "unbounded",
1175
+ * discard: true
1176
+ * })
1177
+ * )
1178
+ * const push = Push.make(Sink.make(() => Effect.void, (_: string) => Effect.void), concurrent)
1179
+ * const totals = Push.mapAccumEffect(push, 0, (seed, value) =>
1180
+ * Effect.sleep(value === 1 ? "20 millis" : "1 millis").pipe(
1181
+ * Effect.as([seed + value, seed + value] as const)
1182
+ * )
1183
+ * )
1184
+ * const program = Fx.collectAll(totals).pipe(Effect.scoped)
1185
+ * // Both reducers see seed 0; Effect.runPromise(program) resolves to [2, 1].
1186
+ *
1187
+ * const values: Array<number> = []
1188
+ * let failures = 0
1189
+ * const sequential = Push.make(
1190
+ * Sink.make(() => Effect.void, (_: string) => Effect.void),
1191
+ * Fx.fromIterable([1, 2, 3])
1192
+ * )
1193
+ * const continued = Push.mapAccumEffect(sequential, 0, (seed, value) =>
1194
+ * value === 2
1195
+ * ? Effect.fail("rejected" as const)
1196
+ * : Effect.succeed([seed + value, seed + value] as const)
1197
+ * )
1198
+ * const recovery = continued.run(Sink.make(
1199
+ * () => Effect.sync(() => { failures += 1 }),
1200
+ * (value) => Effect.sync(() => values.push(value))
1201
+ * ))
1202
+ * // Effect.runPromise(recovery) leaves values [1, 4] and failures 1.
1203
+ * ```
314
1204
  *
315
1205
  * @param initial - Initial accumulator state.
316
1206
  * @param f - Effectful reducer `(state, value) => Effect<[nextState, emitted]>`.
@@ -321,6 +1211,45 @@ export const mapAccum = dual(3, function mapAccum(push, initial, f) {
321
1211
  export const mapAccumEffect = dual(3, function mapAccumEffect(push, initial, f) {
322
1212
  return make(push, Fx.make((sink) => push.run(Sink.filterMapLoopEffect(sink, initial, (s, b) => f(s, b).pipe(Effect.map(([sNext, c]) => [Option.some(c), sNext]), Effect.catchCause((cause) => sink.onFailure(cause).pipe(Effect.as([Option.none(), s]))))))));
323
1213
  });
1214
+ /**
1215
+ * Defines a named Effect service whose value is a `Push`.
1216
+ *
1217
+ * The returned class exposes `onSuccess`, `onFailure`, and `run` as Effects that
1218
+ * first resolve the service from Context. `make` captures the Sink construction
1219
+ * context and combines it with each output subscriber's context; it does not start
1220
+ * the Fx or send an input while building the Layer.
1221
+ *
1222
+ * @remarks
1223
+ * ## Why
1224
+ *
1225
+ * A service gives a bidirectional application capability one stable identity, so
1226
+ * producers and observers can depend on it through ordinary Effect requirements.
1227
+ *
1228
+ * ## Ownership and lifetime
1229
+ *
1230
+ * The returned Layer owns service installation and captures non-Scope services
1231
+ * needed by both sides. Output runs retain the caller's Scope and interruption;
1232
+ * input acknowledgment Effects run in their caller. Layer release drops the
1233
+ * service but does not invent cleanup beyond the supplied Sink and Fx.
1234
+ *
1235
+ * @example
1236
+ * ```ts
1237
+ * import { Effect, Layer } from "effect"
1238
+ * import * as Fx from "@typed/fx/Fx"
1239
+ * import * as Push from "@typed/fx/Push"
1240
+ * import * as Sink from "@typed/fx/Sink"
1241
+ *
1242
+ * class Messages extends Push.Service<Messages, string, never, string>()("Messages") {}
1243
+ * const MessagesLive = Messages.make(
1244
+ * Sink.make(() => Effect.void, (message) => Effect.log(message)),
1245
+ * Fx.succeed("ready")
1246
+ * )
1247
+ * const send = Messages.onSuccess("hello").pipe(Effect.provide(MessagesLive))
1248
+ * ```
1249
+ *
1250
+ * @since 1.0.0
1251
+ * @category services
1252
+ */
324
1253
  export function Service() {
325
1254
  return (id) => {
326
1255
  const service = Context.Service(id);
@@ -334,10 +1263,10 @@ export function Service() {
334
1263
  return pipeArguments(this, arguments);
335
1264
  };
336
1265
  // Fx methods
337
- static run = (sink) => Effect.flatMap(service.asEffect(), (push) => push.run(sink));
1266
+ static run = (sink) => Effect.flatMap(service, (push) => push.run(sink));
338
1267
  // Sink methods
339
- static onSuccess = (value) => Effect.flatMap(service.asEffect(), (push) => push.onSuccess(value));
340
- static onFailure = (cause) => Effect.flatMap(service.asEffect(), (push) => push.onFailure(cause));
1268
+ static onSuccess = (value) => Effect.flatMap(service, (push) => push.onSuccess(value));
1269
+ static onFailure = (cause) => Effect.flatMap(service, (push) => push.onFailure(cause));
341
1270
  constructor() {
342
1271
  return PushService;
343
1272
  }