0.1.11 #14

Merged
Thilawyn merged 318 commits from next into master 2025-05-19 14:01:41 +02:00
Showing only changes of commit 88fab2c7d7 - Show all commits

View File

@@ -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,
) {}