import { Cause, Effect, PubSub, Stream } from "effect" export interface QueryErrorHandler { readonly errors: Stream.Stream> readonly handle: (self: Effect.Effect) => Effect.Effect, R> } export type Fallback = T extends QueryErrorHandler ? A : never export type Error = T extends QueryErrorHandler ? E : never export const make = () => ( ( f: ( self: Effect.Effect, failure: (failure: HandledE) => Effect.Effect, defect: (defect: unknown) => Effect.Effect, ) => Effect.Effect ): Effect.Effect> => Effect.gen(function*() { const pubsub = yield* PubSub.unbounded>() const errors = Stream.fromPubSub(pubsub) const handle = ( self: Effect.Effect ): Effect.Effect, R> => f( self as unknown as Effect.Effect, (failure: HandledE) => Effect.andThen( PubSub.publish(pubsub, Cause.fail(failure)), Effect.failCause(Cause.empty), ), (defect: unknown) => Effect.andThen( PubSub.publish(pubsub, Cause.die(defect)), Effect.failCause(Cause.empty), ), ) return { errors, handle } }) )