( handler: (...args: Args) => Stream.Stream<A, E, R> )
| 221 | )) |
| 222 | ) |
| 223 | |
| 224 | return tuple(computed(() => state.value), act) |
| 225 | } |
| 226 | |
| 227 | /** |
| 228 | * Like `asResult`, but for streams. The ref is updated with each emitted value |
| 229 | * (keeping `waiting: true`) and is finalised (with `waiting: false`) once the |
| 230 | * stream terminates successfully. Errors are surfaced as `AsyncResult.failure`. |
| 231 | */ |
| 232 | export const asStreamResult = <Args extends readonly any[], A, E, R>( |
| 233 | handler: (...args: Args) => Stream.Stream<A, E, R> |
| 234 | ): readonly [ComputedRef<AsyncResult.AsyncResult<A, E>>, (...args: Args) => Effect.Effect<void, never, R>] => { |
| 235 | const state = shallowRef<AsyncResult.AsyncResult<A, E>>(AsyncResult.initial()) |
| 236 | |
| 237 | const runStream = (stream: Stream.Stream<A, E, R>): Effect.Effect<void, never, R> => |
| 238 | Effect |
| 239 | .sync(() => { |
| 240 | state.value = AsyncResult.initial(true) |
| 241 | }) |
| 242 | .pipe( |
| 243 | Effect.andThen( |
| 244 | stream.pipe( |
| 245 | Stream.runForEach((value) => |
| 246 | Effect.sync(() => { |
| 247 | state.value = AsyncResult.success(value, { waiting: true }) |
| 248 | }) |
| 249 | ), |
| 250 | Effect.exit, |
| 251 | Effect.flatMap((exit) => |
| 252 | Effect.sync(() => { |
| 253 | if (exit._tag === "Success") { |
| 254 | const current = state.value |
| 255 | if (AsyncResult.isSuccess(current)) { |
| 256 | state.value = AsyncResult.success(current.value, { waiting: false }) |
| 257 | } else { |
| 258 | state.value = AsyncResult.initial(false) |
| 259 | } |
| 260 | } else { |
| 261 | state.value = AsyncResult.failure(exit.cause) |
| 262 | } |
| 263 | }) |
| 264 | ) |
| 265 | ) |
| 266 | ) |
no test coverage detected
searching dependent graphs…