0.1.8 #11
@@ -1,10 +1,10 @@
|
|||||||
import { type Cause, Context, Effect, Layer, Queue, Stream } from "effect"
|
import { Cause, Context, Effect, identity, Layer, Queue, Stream } from "effect"
|
||||||
import type { Mutable } from "effect/Types"
|
import type { Mutable } from "effect/Types"
|
||||||
|
|
||||||
|
|
||||||
export interface ErrorHandler<E> {
|
export interface ErrorHandler<E> {
|
||||||
readonly errors: Stream.Stream<Cause.Cause<E>>
|
readonly errors: Stream.Stream<Cause.Cause<E>>
|
||||||
readonly handle: <A, SelfE, R>(self: Effect.Effect<A, SelfE, R>) => Effect.Effect<A, Exclude<SelfE, E>, R>
|
readonly handle: <A, SelfE extends E, R>(self: Effect.Effect<A, SelfE, R>) => Effect.Effect<A, Exclude<SelfE, E>, R>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Error<T> = T extends ErrorHandler<infer E> ? E : never
|
export type Error<T> = T extends ErrorHandler<infer E> ? E : never
|
||||||
@@ -14,24 +14,41 @@ export interface ServiceResult<Self, Id extends string, E> extends Context.TagCl
|
|||||||
readonly Live: Layer.Layer<Self>
|
readonly Live: Layer.Layer<Self>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Service = <const Id extends string>(id: Id) => (
|
export const Service = <Self, E = never>() => (
|
||||||
<Self, E = never>(): ServiceResult<Self, Id, E> => {
|
<const Id extends string>(
|
||||||
|
id: Id,
|
||||||
|
f: <A, R>(
|
||||||
|
self: Effect.Effect<A, E, R>,
|
||||||
|
failure: (failure: E) => Effect.Effect<never>,
|
||||||
|
defect: (defect: unknown) => Effect.Effect<never>,
|
||||||
|
) => Effect.Effect<A, never, R>,
|
||||||
|
): ServiceResult<Self, Id, E> => {
|
||||||
const TagClass = Context.Tag(id)() as ServiceResult<Self, Id, E>
|
const TagClass = Context.Tag(id)() as ServiceResult<Self, Id, E>
|
||||||
|
|
||||||
(TagClass as Mutable<typeof TagClass>).Live = Layer.effect(TagClass, Effect.gen(function*() {
|
(TagClass as Mutable<typeof TagClass>).Live = Layer.effect(TagClass, Effect.gen(function*() {
|
||||||
const queue = yield* Queue.unbounded<Cause.Cause<E>>()
|
const queue = yield* Queue.unbounded<Cause.Cause<E>>()
|
||||||
const errors = Stream.fromQueue(queue)
|
const errors = Stream.fromQueue(queue)
|
||||||
|
|
||||||
const handle = <A, SelfE, R>(
|
const handle = <A, SelfE extends E, R>(
|
||||||
self: Effect.Effect<A, SelfE, R>
|
self: Effect.Effect<A, SelfE, R>
|
||||||
) => Effect.tapErrorCause(self, cause =>
|
): Effect.Effect<A, Exclude<SelfE, E>, R> => f(self,
|
||||||
Queue.offer(queue, cause as Cause.Cause<E>)
|
(failure: E) => Queue.offer(queue, Cause.fail(failure)).pipe(
|
||||||
) as Effect.Effect<A, Exclude<SelfE, E>, R>
|
Effect.andThen(Effect.failCause(Cause.empty))
|
||||||
|
),
|
||||||
|
(defect: unknown) => Queue.offer(queue, Cause.die(defect)).pipe(
|
||||||
|
Effect.andThen(Effect.failCause(Cause.empty))
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
return { errors, handle }
|
return { errors, handle }
|
||||||
}))
|
}))
|
||||||
|
|
||||||
return TagClass
|
return TagClass
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
export class DefaultErrorHandler extends Service("@reffuse/extension-query/DefaultErrorHandler")<DefaultErrorHandler>() {}
|
export class DefaultErrorHandler extends Service<DefaultErrorHandler>()(
|
||||||
|
"@reffuse/extension-query/DefaultErrorHandler",
|
||||||
|
identity,
|
||||||
|
) {}
|
||||||
|
|||||||
Reference in New Issue
Block a user