@fncts/io 0.0.34 → 0.0.36

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 (230) hide show
  1. package/Fiber/FiberRuntime.d.ts +7 -7
  2. package/Fiber/constructors.d.ts +5 -0
  3. package/IO/api/all.d.ts +41 -0
  4. package/IO/api/concurrency.d.ts +11 -0
  5. package/IO/api/interrupt.d.ts +1 -1
  6. package/IO/api/raceWith.d.ts +2 -1
  7. package/IO/api.d.ts +7 -2
  8. package/IO/definition.d.ts +103 -127
  9. package/IO.d.ts +1 -0
  10. package/Push/api.d.ts +86 -36
  11. package/Push/definition.d.ts +28 -13
  12. package/Push/internal.d.ts +7 -11
  13. package/RefSubject/Atomic.d.ts +8 -11
  14. package/RefSubject/Synchronized/definition.d.ts +4 -6
  15. package/RefSubject/api.d.ts +0 -1
  16. package/RefSubject/definition.d.ts +6 -8
  17. package/STM/definition.d.ts +19 -2
  18. package/Sink/api.d.ts +24 -24
  19. package/Subject/Atomic.d.ts +4 -6
  20. package/Subject/definition.d.ts +2 -2
  21. package/_cjs/Channel/api/runScoped.cjs +1 -1
  22. package/_cjs/Channel/api/runScoped.cjs.map +1 -1
  23. package/_cjs/Channel/api.cjs +2 -2
  24. package/_cjs/Channel/api.cjs.map +1 -1
  25. package/_cjs/Fiber/FiberRuntime.cjs +110 -98
  26. package/_cjs/Fiber/FiberRuntime.cjs.map +1 -1
  27. package/_cjs/Fiber/constructors.cjs +10 -2
  28. package/_cjs/Fiber/constructors.cjs.map +1 -1
  29. package/_cjs/Future/api.cjs +1 -1
  30. package/_cjs/Future/api.cjs.map +1 -1
  31. package/_cjs/IO/api/all.cjs +33 -0
  32. package/_cjs/IO/api/all.cjs.map +1 -0
  33. package/_cjs/IO/api/asyncIO.cjs +1 -1
  34. package/_cjs/IO/api/asyncIO.cjs.map +1 -1
  35. package/_cjs/IO/api/bracketExit.cjs +1 -1
  36. package/_cjs/IO/api/bracketExit.cjs.map +1 -1
  37. package/_cjs/IO/api/concurrency.cjs +25 -4
  38. package/_cjs/IO/api/concurrency.cjs.map +1 -1
  39. package/_cjs/IO/api/disconnect.cjs +1 -1
  40. package/_cjs/IO/api/disconnect.cjs.map +1 -1
  41. package/_cjs/IO/api/foreachConcurrent.cjs +1 -1
  42. package/_cjs/IO/api/foreachConcurrent.cjs.map +1 -1
  43. package/_cjs/IO/api/foreachExec.cjs +1 -1
  44. package/_cjs/IO/api/foreachExec.cjs.map +1 -1
  45. package/_cjs/IO/api/forkIn.cjs +1 -1
  46. package/_cjs/IO/api/forkIn.cjs.map +1 -1
  47. package/_cjs/IO/api/forkScoped.cjs +1 -1
  48. package/_cjs/IO/api/forkScoped.cjs.map +1 -1
  49. package/_cjs/IO/api/fulfill.cjs +1 -1
  50. package/_cjs/IO/api/fulfill.cjs.map +1 -1
  51. package/_cjs/IO/api/interrupt.cjs +18 -6
  52. package/_cjs/IO/api/interrupt.cjs.map +1 -1
  53. package/_cjs/IO/api/raceWith.cjs +4 -4
  54. package/_cjs/IO/api/raceWith.cjs.map +1 -1
  55. package/_cjs/IO/api/timeout.cjs +8 -5
  56. package/_cjs/IO/api/timeout.cjs.map +1 -1
  57. package/_cjs/IO/api/zipConcurrent.cjs +1 -1
  58. package/_cjs/IO/api/zipConcurrent.cjs.map +1 -1
  59. package/_cjs/IO/api.cjs +78 -20
  60. package/_cjs/IO/api.cjs.map +1 -1
  61. package/_cjs/IO/definition.cjs +14 -191
  62. package/_cjs/IO/definition.cjs.map +1 -1
  63. package/_cjs/IO.cjs +11 -0
  64. package/_cjs/IO.cjs.map +1 -1
  65. package/_cjs/Layer/MemoMap.cjs +1 -1
  66. package/_cjs/Layer/MemoMap.cjs.map +1 -1
  67. package/_cjs/Layer/api.cjs.map +1 -1
  68. package/_cjs/Push/api.cjs +238 -168
  69. package/_cjs/Push/api.cjs.map +1 -1
  70. package/_cjs/Push/definition.cjs +12 -13
  71. package/_cjs/Push/definition.cjs.map +1 -1
  72. package/_cjs/Push/internal.cjs +37 -29
  73. package/_cjs/Push/internal.cjs.map +1 -1
  74. package/_cjs/RefSubject/Atomic.cjs +15 -19
  75. package/_cjs/RefSubject/Atomic.cjs.map +1 -1
  76. package/_cjs/RefSubject/Synchronized/definition.cjs +9 -10
  77. package/_cjs/RefSubject/Synchronized/definition.cjs.map +1 -1
  78. package/_cjs/RefSubject/api.cjs +5 -6
  79. package/_cjs/RefSubject/api.cjs.map +1 -1
  80. package/_cjs/RefSubject/definition.cjs.map +1 -1
  81. package/_cjs/STM/api/atomically.cjs +1 -1
  82. package/_cjs/STM/api/atomically.cjs.map +1 -1
  83. package/_cjs/STM/api.cjs +2 -2
  84. package/_cjs/STM/api.cjs.map +1 -1
  85. package/_cjs/STM/definition.cjs +1 -1
  86. package/_cjs/STM/definition.cjs.map +1 -1
  87. package/_cjs/ScopedRef/api.cjs +2 -2
  88. package/_cjs/ScopedRef/api.cjs.map +1 -1
  89. package/_cjs/Semaphore.cjs +1 -1
  90. package/_cjs/Semaphore.cjs.map +1 -1
  91. package/_cjs/Sink/api.cjs +13 -13
  92. package/_cjs/Sink/api.cjs.map +1 -1
  93. package/_cjs/Subject/Atomic.cjs +4 -5
  94. package/_cjs/Subject/Atomic.cjs.map +1 -1
  95. package/_cjs/TReentrantLock/api.cjs +2 -2
  96. package/_cjs/TReentrantLock/api.cjs.map +1 -1
  97. package/_cjs/TSemaphore/api.cjs +1 -1
  98. package/_cjs/TSemaphore/api.cjs.map +1 -1
  99. package/_cjs/collection/immutable/Conc/dropUntilIO.cjs +12 -17
  100. package/_cjs/collection/immutable/Conc/dropUntilIO.cjs.map +1 -1
  101. package/_cjs/collection/immutable/Conc/dropWhileIO.cjs +12 -17
  102. package/_cjs/collection/immutable/Conc/dropWhileIO.cjs.map +1 -1
  103. package/_cjs/collection/immutable/Conc/filterIO.cjs +2 -12
  104. package/_cjs/collection/immutable/Conc/filterIO.cjs.map +1 -1
  105. package/_cjs/collection/immutable/Conc/mapIO.cjs +3 -9
  106. package/_cjs/collection/immutable/Conc/mapIO.cjs.map +1 -1
  107. package/_cjs/collection/immutable/Conc/takeWhileIO.cjs +11 -27
  108. package/_cjs/collection/immutable/Conc/takeWhileIO.cjs.map +1 -1
  109. package/_mjs/Channel/api/runScoped.mjs +1 -1
  110. package/_mjs/Channel/api/runScoped.mjs.map +1 -1
  111. package/_mjs/Channel/api.mjs +2 -2
  112. package/_mjs/Channel/api.mjs.map +1 -1
  113. package/_mjs/Fiber/FiberRuntime.mjs +111 -100
  114. package/_mjs/Fiber/FiberRuntime.mjs.map +1 -1
  115. package/_mjs/Fiber/constructors.mjs +7 -1
  116. package/_mjs/Fiber/constructors.mjs.map +1 -1
  117. package/_mjs/Future/api.mjs +1 -1
  118. package/_mjs/Future/api.mjs.map +1 -1
  119. package/_mjs/IO/api/all.mjs +24 -0
  120. package/_mjs/IO/api/all.mjs.map +1 -0
  121. package/_mjs/IO/api/asyncIO.mjs +1 -1
  122. package/_mjs/IO/api/asyncIO.mjs.map +1 -1
  123. package/_mjs/IO/api/bracketExit.mjs +1 -1
  124. package/_mjs/IO/api/bracketExit.mjs.map +1 -1
  125. package/_mjs/IO/api/concurrency.mjs +19 -2
  126. package/_mjs/IO/api/concurrency.mjs.map +1 -1
  127. package/_mjs/IO/api/disconnect.mjs +1 -1
  128. package/_mjs/IO/api/disconnect.mjs.map +1 -1
  129. package/_mjs/IO/api/foreachConcurrent.mjs +1 -1
  130. package/_mjs/IO/api/foreachConcurrent.mjs.map +1 -1
  131. package/_mjs/IO/api/foreachExec.mjs +1 -1
  132. package/_mjs/IO/api/foreachExec.mjs.map +1 -1
  133. package/_mjs/IO/api/forkIn.mjs +1 -1
  134. package/_mjs/IO/api/forkIn.mjs.map +1 -1
  135. package/_mjs/IO/api/forkScoped.mjs +1 -1
  136. package/_mjs/IO/api/forkScoped.mjs.map +1 -1
  137. package/_mjs/IO/api/fulfill.mjs +1 -1
  138. package/_mjs/IO/api/fulfill.mjs.map +1 -1
  139. package/_mjs/IO/api/interrupt.mjs +19 -7
  140. package/_mjs/IO/api/interrupt.mjs.map +1 -1
  141. package/_mjs/IO/api/raceWith.mjs +4 -4
  142. package/_mjs/IO/api/raceWith.mjs.map +1 -1
  143. package/_mjs/IO/api/timeout.mjs +8 -5
  144. package/_mjs/IO/api/timeout.mjs.map +1 -1
  145. package/_mjs/IO/api/zipConcurrent.mjs +1 -1
  146. package/_mjs/IO/api/zipConcurrent.mjs.map +1 -1
  147. package/_mjs/IO/api.mjs +78 -23
  148. package/_mjs/IO/api.mjs.map +1 -1
  149. package/_mjs/IO/definition.mjs +12 -181
  150. package/_mjs/IO/definition.mjs.map +1 -1
  151. package/_mjs/IO.mjs +1 -0
  152. package/_mjs/IO.mjs.map +1 -1
  153. package/_mjs/Layer/MemoMap.mjs +1 -1
  154. package/_mjs/Layer/MemoMap.mjs.map +1 -1
  155. package/_mjs/Layer/api.mjs.map +1 -1
  156. package/_mjs/Push/api.mjs +223 -166
  157. package/_mjs/Push/api.mjs.map +1 -1
  158. package/_mjs/Push/definition.mjs +9 -10
  159. package/_mjs/Push/definition.mjs.map +1 -1
  160. package/_mjs/Push/internal.mjs +33 -22
  161. package/_mjs/Push/internal.mjs.map +1 -1
  162. package/_mjs/RefSubject/Atomic.mjs +15 -19
  163. package/_mjs/RefSubject/Atomic.mjs.map +1 -1
  164. package/_mjs/RefSubject/Synchronized/definition.mjs +9 -10
  165. package/_mjs/RefSubject/Synchronized/definition.mjs.map +1 -1
  166. package/_mjs/RefSubject/api.mjs +6 -7
  167. package/_mjs/RefSubject/api.mjs.map +1 -1
  168. package/_mjs/RefSubject/definition.mjs.map +1 -1
  169. package/_mjs/STM/api/atomically.mjs +1 -1
  170. package/_mjs/STM/api/atomically.mjs.map +1 -1
  171. package/_mjs/STM/api.mjs +2 -2
  172. package/_mjs/STM/api.mjs.map +1 -1
  173. package/_mjs/STM/definition.mjs +1 -1
  174. package/_mjs/STM/definition.mjs.map +1 -1
  175. package/_mjs/ScopedRef/api.mjs +2 -2
  176. package/_mjs/ScopedRef/api.mjs.map +1 -1
  177. package/_mjs/Semaphore.mjs +1 -1
  178. package/_mjs/Semaphore.mjs.map +1 -1
  179. package/_mjs/Sink/api.mjs +10 -10
  180. package/_mjs/Sink/api.mjs.map +1 -1
  181. package/_mjs/Subject/Atomic.mjs +4 -5
  182. package/_mjs/Subject/Atomic.mjs.map +1 -1
  183. package/_mjs/TReentrantLock/api.mjs +2 -2
  184. package/_mjs/TReentrantLock/api.mjs.map +1 -1
  185. package/_mjs/TSemaphore/api.mjs +1 -1
  186. package/_mjs/TSemaphore/api.mjs.map +1 -1
  187. package/_mjs/collection/immutable/Conc/dropUntilIO.mjs +12 -17
  188. package/_mjs/collection/immutable/Conc/dropUntilIO.mjs.map +1 -1
  189. package/_mjs/collection/immutable/Conc/dropWhileIO.mjs +12 -17
  190. package/_mjs/collection/immutable/Conc/dropWhileIO.mjs.map +1 -1
  191. package/_mjs/collection/immutable/Conc/filterIO.mjs +2 -12
  192. package/_mjs/collection/immutable/Conc/filterIO.mjs.map +1 -1
  193. package/_mjs/collection/immutable/Conc/mapIO.mjs +3 -9
  194. package/_mjs/collection/immutable/Conc/mapIO.mjs.map +1 -1
  195. package/_mjs/collection/immutable/Conc/takeWhileIO.mjs +11 -27
  196. package/_mjs/collection/immutable/Conc/takeWhileIO.mjs.map +1 -1
  197. package/_src/Channel/api.ts +3 -3
  198. package/_src/Fiber/FiberRuntime.ts +76 -75
  199. package/_src/Fiber/constructors.ts +5 -0
  200. package/_src/IO/api/all.ts +64 -0
  201. package/_src/IO/api/concurrency.ts +33 -0
  202. package/_src/IO/api/foreachExec.ts +2 -2
  203. package/_src/IO/api/interrupt.ts +20 -7
  204. package/_src/IO/api/raceWith.ts +4 -2
  205. package/_src/IO/api/timeout.ts +21 -1
  206. package/_src/IO/api.ts +79 -27
  207. package/_src/IO/definition.ts +155 -200
  208. package/_src/IO.ts +1 -0
  209. package/_src/Layer/api.ts +0 -1
  210. package/_src/Push/api.ts +305 -304
  211. package/_src/Push/definition.ts +19 -17
  212. package/_src/Push/internal.ts +63 -31
  213. package/_src/RefSubject/Atomic.ts +16 -22
  214. package/_src/RefSubject/Synchronized/definition.ts +6 -9
  215. package/_src/RefSubject/api.ts +9 -12
  216. package/_src/RefSubject/definition.ts +6 -8
  217. package/_src/STM/api.ts +0 -5
  218. package/_src/STM/definition.ts +8 -2
  219. package/_src/Sink/api.ts +9 -9
  220. package/_src/Subject/Atomic.ts +6 -8
  221. package/_src/Subject/definition.ts +2 -2
  222. package/_src/collection/immutable/Conc/dropUntilIO.ts +18 -15
  223. package/_src/collection/immutable/Conc/dropWhileIO.ts +18 -17
  224. package/_src/collection/immutable/Conc/filterIO.ts +1 -11
  225. package/_src/collection/immutable/Conc/mapIO.ts +2 -9
  226. package/_src/collection/immutable/Conc/takeWhileIO.ts +19 -28
  227. package/collection/immutable/Conc/filterIO.d.ts +1 -1
  228. package/collection/immutable/Conc/mapIO.d.ts +1 -1
  229. package/collection/immutable/Conc/takeWhileIO.d.ts +1 -1
  230. package/package.json +2 -2
package/_src/Push/api.ts CHANGED
@@ -1,9 +1,8 @@
1
- import type { _A, _E, _R } from "@fncts/base/types";
2
-
3
1
  import { AtomicReference } from "@fncts/base/internal/AtomicReference";
2
+ import { IO } from "@fncts/io/IO";
3
+ import { withExhaust, withSwitch, withUnboundedConcurrency } from "@fncts/io/Push/internal";
4
4
 
5
- import { Emitter, Push, PushTypeId, PushVariance } from "./definition.js";
6
- import { earlyExit, onEarlyExit } from "./internal.js";
5
+ import { Push, PushTypeId, PushVariance, Sink } from "./definition.js";
7
6
 
8
7
  /**
9
8
  * @tsplus pipeable fncts.io.Push as
@@ -14,36 +13,73 @@ export function as<B>(b: Lazy<B>) {
14
13
  };
15
14
  }
16
15
 
16
+ interface UnsafeSink<E, A> {
17
+ event: (value: A) => void;
18
+ error: (cause: Cause<E>) => void;
19
+ }
20
+
21
+ /**
22
+ * @tsplus static fncts.io.PushOps asyncInterrupt
23
+ */
24
+ export function asyncInterrupt<R, E, A>(
25
+ make: (emitter: UnsafeSink<E, A>) => Either<IO<R, never, void>, Push<R, E, A>>,
26
+ ): Push<R, E, A> {
27
+ return Push<R, E, A>(
28
+ <R1>(sink: Sink<R | R1, E, A>) =>
29
+ Do((Δ) => {
30
+ const future = Δ(Future.make<never, void>());
31
+ const scope = Δ(IO.scope);
32
+ const runtime = Δ(IO.runtime<R | R1>());
33
+ const unsafeSink: UnsafeSink<E, A> = {
34
+ event: (value) => runtime.unsafeRunOrFork(sink.event(value).forkIn(scope)),
35
+ error: (cause) => runtime.unsafeRunOrFork(sink.error(cause).fulfill(future).forkIn(scope)),
36
+ };
37
+ const eitherPush = Δ(IO(make(unsafeSink)));
38
+ Δ(
39
+ eitherPush.match(
40
+ (canceller) => future.await.onInterrupt(canceller),
41
+ (push) => push.run(sink),
42
+ ),
43
+ );
44
+ }).scoped,
45
+ );
46
+ }
47
+
48
+ /**
49
+ * @tsplus static fncts.io.PushOps async
50
+ */
51
+ export function async<E, A>(make: (sink: UnsafeSink<E, A>) => void): Push<never, E, A> {
52
+ return Push.asyncInterrupt((sink) => {
53
+ make(sink);
54
+ return Either.left(IO.unit);
55
+ });
56
+ }
57
+
17
58
  /**
18
59
  * @tsplus static fncts.io.PushOps combineLatest
19
60
  */
20
61
  export function combineLatest<A extends ReadonlyArray<Push<any, any, any>>>(
21
62
  streams: [...A],
22
- ): Push<_R<A[number]>, _E<A[number]>, { [K in keyof A]: [A[K]] extends [Push<any, any, infer A>] ? A : never }>;
63
+ ): Push<Push.EnvironmentOf<A[number]>, Push.ErrorOf<A[number]>, { [K in keyof A]: Push.ValueOf<A[K]> }>;
23
64
  export function combineLatest<R, E, A>(streams: Iterable<Push<R, E, A>>): Push<R, E, ReadonlyArray<A>>;
24
65
  export function combineLatest<R, E, A>(streams: Iterable<Push<R, E, A>>): Push<R, E, ReadonlyArray<A>> {
25
66
  return Push((emitter) =>
26
67
  Do((Δ) => {
27
68
  const size = streams.size;
28
69
  const ref: Array<A> = Δ(IO(Array(size)));
29
- const latch = Δ(CountdownLatch(size));
30
70
  const emitIfReady = IO(ref.filter((a) => a != null)).flatMap((as) =>
31
- as.length === size ? emitter.emit(as) : IO.unit,
71
+ as.length === size ? emitter.event(as) : IO.unit,
32
72
  );
33
73
  Δ(
34
- IO.foreachWithIndex(
35
- streams,
36
- (i, stream) =>
37
- stream.run(
38
- Emitter(
39
- (value) => IO((ref[i] = value)) > emitIfReady,
40
- (cause) => emitter.failCause(cause),
41
- latch.countDown,
42
- ),
43
- ).forkScoped,
74
+ IO.foreachConcurrent(streams.zipWithIndex, ([i, stream]) =>
75
+ stream.run(
76
+ Sink(
77
+ (value) => IO((ref[i] = value)) > emitIfReady,
78
+ (cause) => emitter.error(cause),
79
+ ),
80
+ ),
44
81
  ),
45
82
  );
46
- Δ(latch.await > emitter.end);
47
83
  }),
48
84
  );
49
85
  }
@@ -62,28 +98,7 @@ export function combineLatestWith<A, R1, E1, B, C>(that: Push<R1, E1, B>, f: (a:
62
98
  */
63
99
  export function debounce(duration: Lazy<Duration>) {
64
100
  return <R, E, A>(self: Push<R, E, A>): Push<R, E, A> => {
65
- return Push((emitter) =>
66
- Do((Δ) => {
67
- const ref = Δ(Ref.Synchronized.make<Fiber<never, unknown> | null>(null));
68
- const latch = Δ(CountdownLatch(1));
69
- Δ(
70
- self.run(
71
- Emitter(
72
- (value) =>
73
- ref.updateIO((previous) =>
74
- Do((Δ) => {
75
- Δ(IO.defer(previous ? previous.interrupt : latch.increment));
76
- return Δ(IO.acquireRelease(emitter.emit(value).delay(duration), () => latch.countDown).forkScoped);
77
- }),
78
- ),
79
- (cause) => emitter.failCause(cause),
80
- latch.countDown,
81
- ),
82
- ),
83
- );
84
- Δ(latch.await > emitter.end);
85
- }),
86
- );
101
+ return self.switchMapIO((a) => IO.succeedNow(a).delay(duration));
87
102
  };
88
103
  }
89
104
 
@@ -94,14 +109,90 @@ export function defer<R, E, A>(self: Lazy<Push<R, E, A>>): Push<R, E, A> {
94
109
  return Push((emitter) => IO(self).flatMap((push) => push.run(emitter)));
95
110
  }
96
111
 
112
+ /**
113
+ * @tsplus pipeable fncts.io.Push exhaustMap
114
+ */
115
+ export function exhaustMap<A, R1, E1, B>(f: (a: A) => Push<R1, E1, B>) {
116
+ return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> => {
117
+ return Push((sink) => withExhaust((fork) => self.run(Sink((a) => fork(f(a).run(sink)), sink.error))));
118
+ };
119
+ }
120
+
121
+ /**
122
+ * @tsplus pipeable fncts.io.Push exhaustMapIO
123
+ */
124
+ export function exhaustMapIO<A, R1, E1, B>(f: (a: A) => IO<R1, E1, B>) {
125
+ return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> => {
126
+ return self.exhaustMap((a) => Push.fromIO(f(a)));
127
+ };
128
+ }
129
+
130
+ /**
131
+ * @tsplus pipeable fncts.io.Push filterIO
132
+ */
133
+ export function filterIO<A, R1, E1>(predicate: (a: A) => IO<R1, E1, boolean>) {
134
+ return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, A> => {
135
+ return Push((sink) =>
136
+ self.run(
137
+ Sink(
138
+ (a) =>
139
+ predicate(a)
140
+ .flatMap((b) => (b ? sink.event(a) : IO.unit))
141
+ .catchAllCause(sink.error),
142
+ sink.error,
143
+ ),
144
+ ),
145
+ );
146
+ };
147
+ }
148
+
149
+ /**
150
+ * @tsplus pipeable fncts.io.Push filterMapIO
151
+ */
152
+ export function filterMapIO<A, R1, E1, B>(f: (a: A) => IO<R1, E1, Maybe<B>>) {
153
+ return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> => {
154
+ return Push((sink) =>
155
+ self.run(
156
+ Sink(
157
+ (a) =>
158
+ f(a)
159
+ .flatMap((mb) => mb.match(() => IO.unit, sink.event))
160
+ .catchAllCause(sink.error),
161
+ sink.error,
162
+ ),
163
+ ),
164
+ );
165
+ };
166
+ }
167
+
168
+ /**
169
+ * @tsplus pipeable fncts.io.Push filter
170
+ */
171
+ export function filter<A, B extends A>(refinement: Refinement<A, B>): <R, E>(self: Push<R, E, A>) => Push<R, E, B>;
172
+ export function filter<A>(predicate: Predicate<A>): <R, E>(self: Push<R, E, A>) => Push<R, E, A>;
173
+ export function filter<A>(predicate: Predicate<A>) {
174
+ return <R, E>(self: Push<R, E, A>): Push<R, E, A> => {
175
+ return Push((sink) => self.run(Sink((a) => (predicate(a) ? sink.event(a) : IO.unit), sink.error)));
176
+ };
177
+ }
178
+
179
+ /**
180
+ * @tsplus pipeable fncts.io.Push filterMap
181
+ */
182
+ export function filterMap<A, B>(f: (a: A) => Maybe<B>) {
183
+ return <R, E>(self: Push<R, E, A>): Push<R, E, B> => {
184
+ return Push((sink) => self.run(Sink((a) => f(a).match(() => IO.unit, sink.event), sink.error)));
185
+ };
186
+ }
187
+
97
188
  /**
98
189
  * @tsplus pipeable fncts.io.Push flatMapConcurrentBounded
99
190
  */
100
191
  export function flatMapConcurrentBounded<A, R1, E1, B>(f: (a: A) => Push<R1, E1, B>, concurrency: number) {
101
192
  return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> => {
102
- return Push(<R2>(emitter: Emitter<R | R1 | R2, E | E1, B>) =>
193
+ return Push(<R2>(emitter: Sink<R | R1 | R2, E | E1, B>) =>
103
194
  Do((Δ) => {
104
- const semaphore = Δ(TSemaphore(concurrency).commit);
195
+ const semaphore = Δ(Semaphore(concurrency));
105
196
  Δ(self.flatMapConcurrentUnbounded((a) => f(a).transform((io) => semaphore.withPermit(io))).run(emitter));
106
197
  }),
107
198
  );
@@ -113,22 +204,7 @@ export function flatMapConcurrentBounded<A, R1, E1, B>(f: (a: A) => Push<R1, E1,
113
204
  */
114
205
  export function flatMapConcurrentUnbounded<A, R1, E1, B>(f: (a: A) => Push<R1, E1, B>) {
115
206
  return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> => {
116
- return Push((emitter) =>
117
- Do((Δ) => {
118
- const latch = Δ(CountdownLatch(1));
119
- Δ(
120
- self.run(
121
- Emitter(
122
- (value) =>
123
- latch.increment > f(value).run(Emitter(emitter.emit, emitter.failCause, latch.countDown)).forkScoped,
124
- emitter.failCause,
125
- latch.countDown,
126
- ),
127
- ),
128
- );
129
- Δ(latch.await > emitter.end);
130
- }),
131
- );
207
+ return Push((sink) => withUnboundedConcurrency((fork) => self.run(Sink((a) => fork(f(a).run(sink)), sink.error))));
132
208
  };
133
209
  }
134
210
 
@@ -168,12 +244,11 @@ export function flatten<R, E, R1, E1, A>(self: Push<R, E, Push<R1, E1, A>>): Pus
168
244
  * @tsplus static fncts.io.PushOps fromIO
169
245
  */
170
246
  export function fromIO<R, E, A>(io: Lazy<IO<R, E, A>>): Push<R, E, A> {
171
- return Push(
172
- (emitter) =>
173
- IO.defer(io).matchCauseIO(
174
- (cause) => emitter.failCause(cause),
175
- (value) => emitter.emit(value),
176
- ) > emitter.end,
247
+ return Push((emitter) =>
248
+ IO.defer(io).matchCauseIO(
249
+ (cause) => emitter.error(cause),
250
+ (value) => emitter.event(value),
251
+ ),
177
252
  );
178
253
  }
179
254
 
@@ -181,17 +256,20 @@ export function fromIO<R, E, A>(io: Lazy<IO<R, E, A>>): Push<R, E, A> {
181
256
  * @tsplus static fncts.io.PushOps fromAsyncIterable
182
257
  */
183
258
  export function fromAsyncIterable<A>(iterable: AsyncIterable<A>): Push<never, never, A> {
184
- return Push((emitter) => IO.defer(fromAsyncIterableLoop(iterable[Symbol.asyncIterator](), emitter)));
259
+ return Push(<R>(sink: Sink<R, never, A>) =>
260
+ IO.asyncIO<R, never, void>((cb) => IO.defer(fromAsyncIterableLoop(iterable[Symbol.asyncIterator](), sink, cb))),
261
+ );
185
262
  }
186
263
 
187
264
  function fromAsyncIterableLoop<A, R>(
188
265
  iterator: AsyncIterator<A>,
189
- emitter: Emitter<R, never, A>,
266
+ sink: Sink<R, never, A>,
267
+ cb: (io: UIO<void>) => void,
190
268
  __tsplusTrace?: string,
191
269
  ): IO<R, never, void> {
192
270
  return IO.fromPromiseHalt(iterator.next).matchCauseIO(
193
- (cause) => emitter.failCause(cause) > emitter.end,
194
- (result) => (result.done ? emitter.end : emitter.emit(result.value) > fromAsyncIterableLoop(iterator, emitter)),
271
+ (cause) => sink.error(cause),
272
+ (result) => (result.done ? IO(cb(IO.unit)) : sink.event(result.value) > fromAsyncIterableLoop(iterator, sink, cb)),
195
273
  );
196
274
  }
197
275
 
@@ -199,13 +277,19 @@ function fromAsyncIterableLoop<A, R>(
199
277
  * @tsplus static fncts.io.PushOps fromIterable
200
278
  */
201
279
  export function fromIterable<A>(iterable: Iterable<A>): Push<never, never, A> {
202
- return Push((emitter) => IO.defer(fromIterableLoop(iterable[Symbol.iterator](), emitter)));
280
+ return Push(<R>(sink: Sink<R, never, A>) =>
281
+ IO.asyncIO<R, never, void>((cb) => IO.defer(fromIterableLoop(iterable[Symbol.iterator](), sink, cb))),
282
+ );
203
283
  }
204
284
 
205
- function fromIterableLoop<A, R>(iterator: Iterator<A>, emitter: Emitter<R, never, A>): IO<R, never, void> {
285
+ function fromIterableLoop<A, R>(
286
+ iterator: Iterator<A>,
287
+ sink: Sink<R, never, A>,
288
+ cb: (io: UIO<void>) => void,
289
+ ): IO<R, never, void> {
206
290
  return IO.defer(() => {
207
291
  const value = iterator.next();
208
- return value.done ? emitter.end : emitter.emit(value.value) > fromIterableLoop(iterator, emitter);
292
+ return value.done ? IO(cb(IO.unit)) : sink.event(value.value) > fromIterableLoop(iterator, sink, cb);
209
293
  });
210
294
  }
211
295
 
@@ -217,12 +301,11 @@ export function multicast<R, E, A>(self: Push<R, E, A>): Push<R, E, A> {
217
301
  }
218
302
 
219
303
  interface MulticastObserver<E, A> {
220
- readonly emitter: Emitter<any, E, A>;
304
+ readonly sink: Sink<any, E, A>;
221
305
  readonly environment: Environment<any>;
222
- readonly future: Future<never, void>;
223
306
  }
224
307
 
225
- export class Multicast<R, E, A> implements Push<R, E, A>, Emitter<never, E, A> {
308
+ export class Multicast<R, E, A> implements Push<R, E, A>, Sink<never, E, A> {
226
309
  readonly [PushTypeId]: PushTypeId = PushTypeId;
227
310
  declare [PushVariance]: {
228
311
  readonly _R: (_: never) => R;
@@ -233,67 +316,59 @@ export class Multicast<R, E, A> implements Push<R, E, A>, Emitter<never, E, A> {
233
316
  protected fiber: Fiber<never, unknown> | undefined;
234
317
  constructor(readonly push: Push<R, E, A>) {}
235
318
 
236
- run<R1>(emitter: Emitter<R1, E, A>): IO<R | R1 | Scope, never, unknown> {
319
+ run<R1>(sink: Sink<R1, E, A>): IO<R | R1, never, void> {
237
320
  return Do((Δ) => {
238
321
  const environment = Δ(IO.environment<R1>());
239
- const future = Δ(Future.make<never, void>());
240
322
  Δ(
241
323
  IO.defer(() => {
242
- this.observers.push({ emitter, environment, future });
243
- if (this.fiber) {
244
- return IO.unit;
245
- } else {
246
- return this.push
247
- .run(this)
248
- .schedule(Schedule.asap)
249
- .forkScoped.tap((fiber) => IO((this.fiber = fiber)));
324
+ let io: URIO<R, void> = IO.unit;
325
+ if (this.observers.push({ sink: sink, environment }) === 1) {
326
+ io = this.push.run(this).forkDaemon.flatMap((fiber) => IO((this.fiber = fiber)));
250
327
  }
328
+ return io > this.fiber!.await.ensuring(this.removeSink(sink));
251
329
  }),
252
330
  );
253
- return Δ(future.await);
254
331
  });
255
332
  }
256
333
 
257
- emit(value: A) {
258
- return IO.defer(IO.foreachDiscard(this.observers.slice(), (observer) => this.runEvent(value, observer)));
334
+ event(value: A) {
335
+ return IO.defer(IO.foreachDiscard(this.observers.slice(), (observer) => this.runValue(value, observer)));
259
336
  }
260
337
 
261
- failCause(cause: Cause<E>) {
262
- return (
263
- IO.defer(IO.foreachDiscard(this.observers.slice(), (observer) => this.runFailCause(cause, observer))) >
264
- IO.defer(this.cleanup())
265
- );
338
+ error(cause: Cause<E>) {
339
+ return IO.defer(IO.foreachDiscard(this.observers.slice(), (observer) => this.runError(cause, observer)));
266
340
  }
267
341
 
268
- get end() {
269
- return (
270
- IO.defer(IO.foreachDiscard(this.observers.slice(), (observer) => this.runEnd(observer))) >
271
- IO.defer(this.cleanup())
272
- );
342
+ protected runValue(value: A, observer: MulticastObserver<E, A>) {
343
+ return observer.sink
344
+ .event(value)
345
+ .provideEnvironment(observer.environment)
346
+ .catchAllCause(() => this.removeSink(observer.sink));
273
347
  }
274
348
 
275
- protected runEvent(value: A, observer: MulticastObserver<E, A>) {
276
- return observer.emitter
277
- .emit(value)
278
- .tapErrorCause((cause) => this.runFailCause(cause, observer))
279
- .provideEnvironment(observer.environment);
349
+ protected runError(cause: Cause<E>, observer: MulticastObserver<E, A>) {
350
+ return observer.sink
351
+ .error(cause)
352
+ .provideEnvironment(observer.environment)
353
+ .catchAllCause(() => this.removeSink(observer.sink));
280
354
  }
281
355
 
282
- protected runFailCause(cause: Cause<E>, observer: MulticastObserver<E, A>) {
283
- this.observers.splice(this.observers.indexOf(observer), 1);
284
- return observer.emitter.failCause(cause).fulfill(observer.future).provideEnvironment(observer.environment);
285
- }
286
-
287
- protected runEnd(observer: MulticastObserver<E, A>) {
288
- this.observers.splice(this.observers.indexOf(observer), 1);
289
- return observer.emitter.end.fulfill(observer.future).provideEnvironment(observer.environment);
290
- }
291
-
292
- protected cleanup() {
293
- if (this.fiber) {
294
- return this.fiber.interrupt > IO((this.fiber = undefined));
295
- }
296
- return IO.unit;
356
+ protected removeSink(sink: Sink<any, E, A>) {
357
+ return IO.defer(() => {
358
+ if (this.observers.length === 0) {
359
+ return IO.unit;
360
+ }
361
+ const index = this.observers.findIndex((observer) => observer.sink === sink);
362
+ if (index > -1) {
363
+ this.observers.splice(index, 1);
364
+ if (this.observers.length === 0) {
365
+ const interrupt = this.fiber!.interrupt;
366
+ this.fiber = undefined;
367
+ return interrupt;
368
+ }
369
+ }
370
+ return IO.unit;
371
+ });
297
372
  }
298
373
  }
299
374
 
@@ -305,87 +380,26 @@ export function hold<R, E, A>(self: Push<R, E, A>): Push<R, E, A> {
305
380
  }
306
381
 
307
382
  export class Hold<R, E, A> extends Multicast<R, E, A> {
308
- readonly value = new AtomicReference(Nothing<A>());
309
- protected pendingEmitters: Array<readonly [Emitter<unknown, E, A>, Array<A>]> = [];
310
- protected scheduledFiber: Fiber<any, any> | null = null;
383
+ readonly current = new AtomicReference(Nothing<A>());
311
384
 
312
- constructor(readonly push: Push<R, E, A>) {
385
+ constructor(public push: Push<R, E, A>) {
313
386
  super(push);
314
387
  }
315
388
 
316
- run<R1>(emitter: Emitter<R1, E, A>): IO<R | R1 | Scope, never, void> {
317
- if (this.shouldScheduleFlush()) {
318
- return this.scheduleFlush(emitter).flatMap(() => super.run(emitter));
319
- }
389
+ run<R1>(sink: Sink<R1, E, A>): IO<R | R1, never, void> {
390
+ const current = this.current.get;
320
391
 
321
- const value = this.value.get;
322
- if (value.isJust() && this.observers.length === 0) {
323
- return emitter.emit(value.value).flatMap(() => super.run(emitter));
392
+ if (current.isJust()) {
393
+ return sink.event(current.value) > super.run(sink);
324
394
  }
325
395
 
326
- return super.run(emitter);
396
+ return super.run(sink);
327
397
  }
328
398
 
329
- emit(value: A) {
399
+ event(value: A): IO<never, never, void> {
330
400
  return IO.defer(() => {
331
- this.addValue(value);
332
- return this.flushPending().flatMap(() => super.emit(value));
333
- });
334
- }
335
-
336
- failCause(cause: Cause<E>) {
337
- return IO.defer(this.flushPending().flatMap(() => super.failCause(cause)));
338
- }
339
-
340
- get end() {
341
- return IO.defer(this.flushPending().flatMap(() => super.end));
342
- }
343
-
344
- protected shouldScheduleFlush() {
345
- return this.value.get.isJust() && this.observers.length > 0;
346
- }
347
-
348
- protected scheduleFlush<R>(observer: Emitter<R, E, A>) {
349
- this.pendingEmitters.push([
350
- observer,
351
- this.value.get.match(
352
- () => [],
353
- (a) => [a],
354
- ),
355
- ]);
356
-
357
- const interrupt = this.scheduledFiber ? this.scheduledFiber.interruptAsFork(FiberId.none) : IO.unit;
358
- this.scheduledFiber = null;
359
-
360
- return (IO.yieldNow > interrupt.flatMap(() => this.flushPending())).forkScoped.tap((fiber) =>
361
- IO((this.scheduledFiber = fiber)),
362
- );
363
- }
364
-
365
- protected flushPending() {
366
- if (this.pendingEmitters.length === 0) {
367
- return IO.unit;
368
- }
369
-
370
- const emitters = this.pendingEmitters;
371
- this.pendingEmitters = [];
372
-
373
- return IO.foreachDiscard(emitters, (pendingEmitter) => {
374
- return IO.defer(() => {
375
- const [emitter, values] = pendingEmitter;
376
- const observer = this.observers.find((observer) => observer.emitter === emitter);
377
- if (!observer) {
378
- return IO.unit;
379
- }
380
- return IO.foreachDiscard(values, (value) => this.runEvent(value, observer));
381
- });
382
- });
383
- }
384
-
385
- protected addValue(value: A) {
386
- this.value.set(Just(value));
387
- this.pendingEmitters.forEach(([, values]) => {
388
- values.push(value);
401
+ this.current.set(Just(value));
402
+ return super.event(value);
389
403
  });
390
404
  }
391
405
  }
@@ -406,10 +420,9 @@ export function mapError<E, E1>(f: (e: E) => E1) {
406
420
  return <R, A>(self: Push<R, E, A>): Push<R, E1, A> => {
407
421
  return Push((emitter) =>
408
422
  self.run(
409
- Emitter(
410
- (value) => emitter.emit(value),
411
- (cause) => emitter.failCause(cause.map(f)),
412
- emitter.end,
423
+ Sink(
424
+ (value) => emitter.event(value),
425
+ (cause) => emitter.error(cause.map(f)),
413
426
  ),
414
427
  ),
415
428
  );
@@ -423,10 +436,9 @@ export function mapErrorCause<E, E1>(f: (cause: Cause<E>) => Cause<E1>) {
423
436
  return <R, A>(self: Push<R, E, A>): Push<R, E1, A> => {
424
437
  return Push((emitter) =>
425
438
  self.run(
426
- Emitter(
427
- (value) => emitter.emit(value),
428
- (cause) => emitter.failCause(f(cause)),
429
- emitter.end,
439
+ Sink(
440
+ (value) => emitter.event(value),
441
+ (cause) => emitter.error(f(cause)),
430
442
  ),
431
443
  ),
432
444
  );
@@ -440,14 +452,13 @@ export function mapIO<A, R1, E1, B>(f: (a: A) => IO<R1, E1, B>) {
440
452
  return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> =>
441
453
  Push((emitter) =>
442
454
  self.run(
443
- Emitter(
455
+ Sink(
444
456
  (value) =>
445
457
  f(value).matchCauseIO(
446
- (cause) => emitter.failCause(cause),
447
- (b) => emitter.emit(b),
458
+ (cause) => emitter.error(cause),
459
+ (b) => emitter.event(b),
448
460
  ),
449
- (cause) => emitter.failCause(cause),
450
- emitter.end,
461
+ (cause) => emitter.error(cause),
451
462
  ),
452
463
  ),
453
464
  );
@@ -467,29 +478,40 @@ export function merge<R1, E1, B>(that: Push<R1, E1, B>) {
467
478
  */
468
479
  export function mergeAll<A extends ReadonlyArray<Push<any, any, any>>>(
469
480
  streams: [...A],
470
- ): Push<_R<A[number]>, _E<A[number]>, _A<A[number]>>;
481
+ ): Push<Push.EnvironmentOf<A[number]>, Push.ErrorOf<A[number]>, Push.ValueOf<A[number]>>;
471
482
  export function mergeAll<R, E, A>(streams: Iterable<Push<R, E, A>>): Push<R, E, A>;
472
483
  export function mergeAll<R, E, A>(streams: Iterable<Push<R, E, A>>): Push<R, E, A> {
473
- return Push((emitter) =>
474
- Do((Δ) => {
475
- const latch = Δ(CountdownLatch(streams.size));
476
- Δ(
477
- streams.traverseIOConcurrent(
478
- (stream) =>
479
- stream.run(
480
- Emitter(
481
- (value) => emitter.emit(value),
482
- (cause) => emitter.failCause(cause),
483
- latch.countDown,
484
- ),
485
- ).forkScoped,
486
- ),
487
- );
488
- Δ(latch.await > emitter.end);
489
- }),
484
+ return Push((sink) =>
485
+ IO.foreachConcurrentDiscard(streams, (stream) =>
486
+ stream.run(Sink(sink.event, (cause) => (cause.isInterruptedOnly ? IO.unit : sink.error(cause)))),
487
+ ),
490
488
  );
491
489
  }
492
490
 
491
+ /**
492
+ * @tsplus pipeable fncts.io.Push observe
493
+ */
494
+ export function observe<A, R1, E1>(f: (a: A) => IO<R1, E1, void>, __tsplusTrace?: string) {
495
+ return <R, E>(self: Push<R, E, A>): IO<R | R1 | Scope, E | E1, void> => {
496
+ return Do((Δ) => {
497
+ const future = Δ(Future.make<E | E1, void>());
498
+ const fiber = Δ(
499
+ self
500
+ .run(
501
+ Sink(
502
+ (a) => f(a).catchAllCause((cause) => future.failCause(cause)),
503
+ (cause) => future.failCause(cause),
504
+ ),
505
+ )
506
+ .flatMap(() => future.succeed(undefined)).forkScoped,
507
+ );
508
+
509
+ Δ(future.await);
510
+ Δ(fiber.interruptFork);
511
+ });
512
+ };
513
+ }
514
+
493
515
  /**
494
516
  * @tsplus static fncts.io.PushOps repeatIOMaybe
495
517
  */
@@ -507,18 +529,7 @@ export function repeatIOMaybe<R, E, A>(io: IO<R, Maybe<E>, A>, __tsplusTrace?: s
507
529
  export function runCollect<R, E, A>(self: Push<R, E, A>): IO<R | Scope, E, Conc<A>> {
508
530
  return IO.defer(() => {
509
531
  const out: Array<A> = [];
510
- return Future.make<E, void>().flatMap(
511
- (future) =>
512
- self.run(
513
- Emitter(
514
- (value) => IO(out.push(value)),
515
- (cause) => future.failCause(cause),
516
- future.succeed(undefined),
517
- ),
518
- ) >
519
- future.await >
520
- IO(Conc.fromArray(out)),
521
- );
532
+ return self.observe((a) => IO(out.push(a))).as(Conc.fromArray(out));
522
533
  });
523
534
  }
524
535
 
@@ -526,28 +537,18 @@ export function runCollect<R, E, A>(self: Push<R, E, A>): IO<R | Scope, E, Conc<
526
537
  * @tsplus getter fncts.io.Push runDrain
527
538
  */
528
539
  export function runDrain<R, E, A>(self: Push<R, E, A>): IO<R | Scope, E, void> {
529
- return Future.make<E, void>().flatMap(
530
- (future) =>
531
- self.run(
532
- Emitter(
533
- () => IO.unit,
534
- (cause) => future.failCause(cause),
535
- future.succeed(undefined),
536
- ),
537
- ) > future.await,
538
- );
540
+ return self.observe(() => IO.unit);
539
541
  }
540
542
 
541
543
  /**
542
544
  * @tsplus static fncts.io.PushOps scoped
543
545
  */
544
546
  export function scoped<R, E, A>(io: Lazy<IO<R, E, A>>, __tsplusTrace?: string): Push<Exclude<R, Scope>, E, A> {
545
- return Push(
546
- (emitter) =>
547
- IO.defer(io).scoped.matchCauseIO(
548
- (cause) => emitter.failCause(cause),
549
- (value) => emitter.emit(value),
550
- ) > emitter.end,
547
+ return Push((emitter) =>
548
+ IO.defer(io).scoped.matchCauseIO(
549
+ (cause) => emitter.error(cause),
550
+ (value) => emitter.event(value),
551
+ ),
551
552
  );
552
553
  }
553
554
 
@@ -559,34 +560,29 @@ export function succeed<A>(value: Lazy<A>): Push<never, never, A> {
559
560
  }
560
561
 
561
562
  /**
562
- * @tsplus pipeable fncts.io.PushOps switchMap
563
+ * @tsplus pipeable fncts.io.Push switchMap
563
564
  */
564
565
  export function switchMap<A, R1, E1, B>(f: (a: A) => Push<R1, E1, B>) {
565
566
  return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> => {
566
- return Push(<R2>(emitter: Emitter<R2, E | E1, B>) =>
567
- Do((Δ) => {
568
- const current = Δ(Ref.Synchronized.make<Fiber<never, void> | null>(null));
569
- const latch = Δ(CountdownLatch(1));
570
- const innerEmitter = Emitter<R2, E | E1, B>(
571
- (value) => emitter.emit(value),
572
- (cause) => current.set(null) > emitter.failCause(cause),
573
- latch.countDown,
574
- );
575
- Δ(
576
- self.run(
577
- Emitter(
578
- (value) =>
579
- current.updateIO((fiber) =>
580
- (fiber ? fiber.interrupt : latch.increment).zipRight(f(value).run(innerEmitter).forkScoped),
581
- ),
582
- (cause) => emitter.failCause(cause),
583
- latch.countDown,
584
- ),
585
- ),
586
- );
587
- Δ(latch.await > emitter.end);
588
- }),
589
- );
567
+ return Push((sink) => withSwitch((fork) => self.run(Sink((a) => fork(f(a).run(sink)), sink.error))));
568
+ };
569
+ }
570
+
571
+ /**
572
+ * @tsplus pipeable fncts.io.Push switchMapIO
573
+ */
574
+ export function switchMapIO<A, R1, E1, B>(f: (a: A) => IO<R1, E1, B>) {
575
+ return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, B> => {
576
+ return self.switchMap((a) => Push.fromIO(f(a)));
577
+ };
578
+ }
579
+
580
+ /**
581
+ * @tsplus pipeable fncts.io.Push tap
582
+ */
583
+ export function tap<A, R1, E1, B>(f: (a: A) => IO<R1, E1, B>) {
584
+ return <R, E>(self: Push<R, E, A>): Push<R | R1, E | E1, A> => {
585
+ return Push((sink) => self.run(Sink((a) => f(a).matchCauseIO(sink.error, () => sink.event(a)), sink.error)));
590
586
  };
591
587
  }
592
588
 
@@ -600,11 +596,11 @@ export function transform<R1 = never>(f: <R, E, A>(io: IO<R, E, A>) => IO<R | R1
600
596
  function unfoldLoop<S, A, R1>(
601
597
  s: S,
602
598
  f: (s: S) => Maybe<readonly [A, S]>,
603
- emitter: Emitter<R1, never, A>,
599
+ emitter: Sink<R1, never, A>,
604
600
  ): IO<R1, never, void> {
605
601
  return f(s).match(
606
- () => emitter.end,
607
- ([a, s]) => emitter.emit(a) > unfoldLoop(s, f, emitter),
602
+ () => IO.unit,
603
+ ([a, s]) => emitter.event(a) > unfoldLoop(s, f, emitter),
608
604
  );
609
605
  }
610
606
 
@@ -618,16 +614,16 @@ export function unfold<S, A>(s: S, f: (s: S) => Maybe<readonly [A, S]>): Push<ne
618
614
  function unfoldIOLoop<S, R, E, A, R1>(
619
615
  s: S,
620
616
  f: (s: S) => IO<R, E, Maybe<readonly [A, S]>>,
621
- emitter: Emitter<R1, E, A>,
617
+ emitter: Sink<R1, E, A>,
622
618
  ): IO<R | R1, never, void> {
623
619
  return f(s)
624
620
  .flatMap((result) =>
625
621
  result.match(
626
- () => emitter.end,
627
- ([a, s]) => emitter.emit(a) > unfoldIOLoop(s, f, emitter),
622
+ () => IO.unit,
623
+ ([a, s]) => emitter.event(a) > unfoldIOLoop(s, f, emitter),
628
624
  ),
629
625
  )
630
- .catchAllCause((cause) => emitter.failCause(cause));
626
+ .catchAllCause((cause) => emitter.error(cause));
631
627
  }
632
628
 
633
629
  /**
@@ -642,18 +638,21 @@ export function unfoldIO<S, R, E, A>(s: S, f: (s: S) => IO<R, E, Maybe<readonly
642
638
  */
643
639
  export function untilFuture<E1, B>(future: Future<E1, B>) {
644
640
  return <R, E, A>(self: Push<R, E, A>): Push<R, E | E1, A> => {
645
- return Push((emitter) =>
646
- Do((Δ) => {
647
- const futureFiber = Δ(
648
- future.await
649
- .matchCauseIO(
650
- (cause) => emitter.failCause(cause),
651
- () => IO.unit,
652
- )
653
- .zipRight(earlyExit).forkScoped,
654
- );
655
- const streamFiber = Δ(self.run(emitter).forkScoped);
656
- Δ(Fiber.joinAll([futureFiber, streamFiber])(onEarlyExit(emitter.end)));
641
+ return Push(<R1>(sink: Sink<R1, E | E1, A>) =>
642
+ IO.asyncIO<R | R1, never, void>((cb) => {
643
+ const exit = IO(cb(IO.unit));
644
+ return Do((Δ) => {
645
+ const streamFiber = Δ(self.run(sink).fork);
646
+ const futureFiber = Δ(
647
+ future.await
648
+ .matchCauseIO(
649
+ (cause) => sink.error(cause),
650
+ () => IO.unit,
651
+ )
652
+ .zipRight(exit).fork,
653
+ );
654
+ Δ(Fiber.joinAll([streamFiber, futureFiber]));
655
+ });
657
656
  }),
658
657
  );
659
658
  };
@@ -664,19 +663,21 @@ export function untilFuture<E1, B>(future: Future<E1, B>) {
664
663
  */
665
664
  export function untilPush<R1, E1, B>(signal: Push<R1, E1, B>) {
666
665
  return <R, E, A>(self: Push<R, E, A>): Push<R | R1, E | E1, A> => {
667
- return Push((emitter) =>
668
- Do((Δ) => {
669
- const signalFiber = Δ(
670
- signal.run(
671
- Emitter(
672
- () => earlyExit,
673
- (cause) => emitter.failCause(cause),
674
- earlyExit,
675
- ),
676
- ).forkScoped,
677
- );
678
- const streamFiber = Δ(self.run(emitter).forkScoped);
679
- Δ(Fiber.joinAll([signalFiber, streamFiber])(onEarlyExit(emitter.end)));
666
+ return Push(<R2>(sink: Sink<R2, E | E1, A>) =>
667
+ IO.asyncIO<R | R1 | R2, never, void>((cb) => {
668
+ const exit = IO(cb(IO.unit));
669
+ return Do((Δ) => {
670
+ const signalFiber = Δ(
671
+ signal.run(
672
+ Sink(
673
+ () => exit,
674
+ (cause) => sink.error(cause),
675
+ ),
676
+ ).fork,
677
+ );
678
+ const streamFiber = Δ(self.run(sink).fork);
679
+ Δ(Fiber.joinAll([signalFiber, streamFiber]));
680
+ });
680
681
  }),
681
682
  );
682
683
  };