@fncts/io 0.0.34 → 0.0.36

Sign up to get free protection for your applications and to get access to all the features.
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
  };