( cause: Cause.Cause<E> )
| 26 | |
| 27 | /** @internal */ |
| 28 | export const causeResponse = <E>( |
| 29 | cause: Cause.Cause<E> |
| 30 | ): Effect.Effect<readonly [HttpServerResponse, Cause.Cause<E>]> => { |
| 31 | let effect: Effect.Effect<HttpServerResponse> = Effect.succeed(internalServerError) |
| 32 | let stripped: Cause.Cause<E> = Cause.empty as Cause.Cause<E> |
| 33 | let isClientInterrupt = false |
| 34 | let hasResponse = false |
| 35 | |
| 36 | Cause.reduce(cause, void 0 as void, (_, current) => { |
| 37 | const withoutInterrupt = Cause.isInterruptType(stripped) ? Cause.empty : stripped |
| 38 | switch (current._tag) { |
| 39 | case "Fail": { |
| 40 | effect = Respondable.toResponseOrElse(current.error, internalServerError) |
| 41 | stripped = combineCauses(withoutInterrupt, current) |
| 42 | break |
| 43 | } |
| 44 | case "Die": { |
| 45 | const isResponse = internalServerResponse.isServerResponse(current.defect) |
| 46 | effect = Respondable.toResponseOrElseDefect(current.defect, internalServerError) |
| 47 | stripped = isResponse ? withoutInterrupt : combineCauses(withoutInterrupt, current) |
| 48 | hasResponse = hasResponse || isResponse |
| 49 | break |
| 50 | } |
| 51 | case "Interrupt": { |
| 52 | isClientInterrupt = isClientInterrupt || current.fiberId === clientAbortFiberId |
| 53 | if (Cause.isEmptyType(stripped) && !hasResponse) { |
| 54 | stripped = current |
| 55 | } |
| 56 | break |
| 57 | } |
| 58 | } |
| 59 | return Option.none() |
| 60 | }) |
| 61 | |
| 62 | const responseEffect = !hasResponse && Cause.isInterruptType(stripped) |
| 63 | ? Effect.succeed(isClientInterrupt ? clientAbortError : serverAbortError) |
| 64 | : effect |
| 65 | const strippedCause: Cause.Cause<E> = !hasResponse && Cause.isInterruptType(stripped) && isClientInterrupt |
| 66 | ? Cause.interrupt(clientAbortFiberId) as Cause.Cause<E> |
| 67 | : stripped |
| 68 | |
| 69 | return Effect.map(responseEffect, (response) => { |
| 70 | if (Cause.isEmptyType(strippedCause)) { |
| 71 | return [response, Cause.empty] as const |
| 72 | } |
| 73 | return [response, Cause.sequential(strippedCause, Cause.die(response))] as const |
| 74 | }) |
| 75 | } |
| 76 | |
| 77 | const combineCauses = <A = never, B = never>(left: Cause.Cause<A>, right: Cause.Cause<B>): Cause.Cause<A | B> => { |
| 78 | if (Cause.isEmptyType(left)) { |
nothing calls this directly
no test coverage detected