@@ -2,8 +2,8 @@ import * as ParseResult from "@effect/schema/ParseResult"
22import type * as Schema from "@effect/schema/Schema"
33import * as TreeFormatter from "@effect/schema/TreeFormatter"
44import { createClientEffect } from "@prover-coder-ai/openapi-effect"
5- import type { ClientOptions , Middleware } from "@prover-coder-ai/openapi-effect"
6- import { Effect , Either , Option } from "effect"
5+ import type { BoundaryError , ClientOptions , Middleware } from "@prover-coder-ai/openapi-effect"
6+ import { Effect , Either , Match } from "effect"
77
88import type { paths } from "./openapi-paths.js"
99
@@ -20,13 +20,19 @@ export type ApiTransportValue =
2020 | ReadonlyArray < ApiTransportValue >
2121 | { readonly [ key : string ] : ApiTransportValue }
2222
23- export type OpenApiResponse < A > = {
24- readonly data ?: A
25- readonly error ?: unknown
26- readonly response : Response
23+ export type OpenApiSuccess = {
24+ readonly status : number | string
25+ readonly contentType : string
26+ readonly body : unknown
2727}
2828
29- export type OpenApiRequestResult = Effect . Effect < OpenApiResponse < unknown > , Error >
29+ export type OpenApiHttpError = OpenApiSuccess & {
30+ readonly _tag : "HttpError"
31+ }
32+
33+ export type OpenApiFailure = OpenApiHttpError | BoundaryError
34+
35+ export type OpenApiRequestResult = Effect . Effect < OpenApiSuccess , OpenApiFailure >
3036
3137export type OpenApiRequest = ( client : DockerGitOpenApiTransportClient ) => OpenApiRequestResult
3238
@@ -44,7 +50,7 @@ export type DockerGitOpenApiClient = {
4450 readonly openApiVoid : ( request : OpenApiRequest ) => Effect . Effect < void , string >
4551}
4652
47- type RunOpenApi = ( request : OpenApiRequest ) => Effect . Effect < OpenApiResponse < unknown > , string >
53+ type RunOpenApi = ( request : OpenApiRequest ) => Effect . Effect < OpenApiSuccess , OpenApiFailure >
4854
4955const noCacheHeaders : Readonly < Record < string , string > > = {
5056 accept : "application/json" ,
@@ -102,14 +108,13 @@ const decodeTransportValue = (value: unknown): Effect.Effect<ApiTransportValue,
102108 Effect . flatMap ( ( rendered ) => Effect . fail ( `Invalid JSON response payload: ${ rendered } ` ) )
103109 )
104110
105- const renderOpenApiError = (
106- response : Response ,
107- error : unknown
111+ const renderOpenApiHttpError = (
112+ error : OpenApiHttpError
108113) : Effect . Effect < string > => {
109- if ( response . status === 429 ) {
114+ if ( String ( error . status ) === " 429" ) {
110115 return Effect . succeed ( "HTTP 429: tunnel or proxy rate limited the request. Retry or request a fresh tunnel URL." )
111116 }
112- return error === undefined ? Effect . succeed ( `HTTP ${ response . status } ` ) : renderTransportValue ( error )
117+ return error . body === undefined ? Effect . succeed ( `HTTP ${ error . status } ` ) : renderTransportValue ( error . body )
113118}
114119
115120const noCacheGetMiddleware : DockerGitOpenApiMiddleware = {
@@ -175,16 +180,27 @@ export const createTransportClient = (
175180export const runOpenApi = (
176181 client : DockerGitOpenApiTransportClient ,
177182 request : OpenApiRequest
178- ) : Effect . Effect < OpenApiResponse < unknown > , string > =>
179- request ( client ) . pipe (
180- Effect . mapError ( String )
183+ ) : Effect . Effect < OpenApiSuccess , OpenApiFailure > => request ( client )
184+
185+ const renderOpenApiFailure = ( failure : OpenApiFailure ) : Effect . Effect < string > =>
186+ Match . value ( failure ) . pipe (
187+ Match . when ( { _tag : "HttpError" } , renderOpenApiHttpError ) ,
188+ Match . when ( { _tag : "TransportError" } , ( error ) => Effect . succeed ( error . error . message ) ) ,
189+ Match . when ( { _tag : "UnexpectedStatus" } , ( error ) => Effect . succeed ( `HTTP ${ error . status } : ${ error . body } ` ) ) ,
190+ Match . when ( { _tag : "UnexpectedContentType" } , ( error ) =>
191+ Effect . succeed ( `HTTP ${ error . status } : unexpected content type ${ error . actual ?? "none" } : ${ error . body } ` )
192+ ) ,
193+ Match . when ( { _tag : "ParseError" } , ( error ) =>
194+ Effect . succeed ( `HTTP ${ error . status } : invalid ${ error . contentType } response: ${ error . error . message } ` )
195+ ) ,
196+ Match . when ( { _tag : "DecodeError" } , ( error ) =>
197+ Effect . succeed ( `HTTP ${ error . status } : invalid decoded response: ${ error . error . message } ` )
198+ ) ,
199+ Match . exhaustive
181200 )
182201
183- const failRenderedOpenApiError = (
184- response : Response ,
185- error : unknown
186- ) : Effect . Effect < never , string > =>
187- renderOpenApiError ( response , error ) . pipe (
202+ const failRenderedOpenApiFailure = ( failure : OpenApiFailure ) : Effect . Effect < never , string > =>
203+ renderOpenApiFailure ( failure ) . pipe (
188204 Effect . flatMap ( ( message ) => Effect . fail ( message ) )
189205 )
190206
@@ -193,16 +209,11 @@ const openApiJsonWithRunner = (
193209 request : OpenApiRequest
194210) : Effect . Effect < ApiTransportValue , string > =>
195211 runner ( request ) . pipe (
196- Effect . flatMap ( ( { data, error, response } ) =>
197- Option . match ( Option . fromNullable ( error ) , {
198- onNone : ( ) =>
199- response . ok
200- ? data === undefined
201- ? Effect . fail ( `HTTP ${ response . status } : empty response` )
202- : decodeTransportValue ( data )
203- : failRenderedOpenApiError ( response , error ) ,
204- onSome : ( apiError ) => failRenderedOpenApiError ( response , apiError )
205- } )
212+ Effect . catchAll ( failRenderedOpenApiFailure ) ,
213+ Effect . flatMap ( ( success ) =>
214+ success . body === undefined
215+ ? Effect . fail ( `HTTP ${ success . status } : empty response` )
216+ : decodeTransportValue ( success . body )
206217 )
207218 )
208219
@@ -226,14 +237,8 @@ const openApiVoidWithRunner = (
226237 request : OpenApiRequest
227238) : Effect . Effect < void , string > =>
228239 runner ( request ) . pipe (
229- Effect . flatMap ( ( { error, response } ) =>
230- response . ok
231- ? Option . match ( Option . fromNullable ( error ) , {
232- onNone : ( ) => Effect . void ,
233- onSome : ( apiError ) => failRenderedOpenApiError ( response , apiError )
234- } )
235- : failRenderedOpenApiError ( response , error )
236- )
240+ Effect . asVoid ,
241+ Effect . catchAll ( failRenderedOpenApiFailure )
237242 )
238243
239244/**
@@ -335,10 +340,8 @@ export const createClient = (
335340 return clientCache . client
336341 }
337342
338- const runRuntimeOpenApi = ( request : OpenApiRequest ) : Effect . Effect < OpenApiResponse < unknown > , string > =>
339- request ( getOpenApiClient ( ) ) . pipe (
340- Effect . mapError ( String )
341- )
343+ const runRuntimeOpenApi = ( request : OpenApiRequest ) : Effect . Effect < OpenApiSuccess , OpenApiFailure > =>
344+ request ( getOpenApiClient ( ) )
342345
343346 return {
344347 openApiJson : ( request ) => openApiJsonWithRunner ( runRuntimeOpenApi , request ) ,
0 commit comments