Skip to content

Commit

Permalink
add withResponse option to HttpApiClient methods (#3884)
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart authored Nov 4, 2024
1 parent 257ab1b commit 07c493a
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 8 deletions.
6 changes: 6 additions & 0 deletions .changeset/ten-eels-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@effect/platform-node": patch
"@effect/platform": patch
---

add withResponse option to HttpApiClient methods
2 changes: 1 addition & 1 deletion packages/platform-node/examples/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ Effect.gen(function*() {
user = yield* client.users.me()
console.log("json me", user)

const csv = yield* client.csv()
const csv = yield* client.csv({ withResponse: true })
console.log("csv", csv)

const urlParams = yield* client.urlParams()
Expand Down
8 changes: 8 additions & 0 deletions packages/platform-node/test/HttpApi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@ describe("HttpApi", () => {
}).pipe(Effect.provide(HttpLive)))
})

it.effect("client withResponse", () =>
Effect.gen(function*() {
const client = yield* HttpApiClient.make(Api)
const [users, response] = yield* client.users.list({ headers: { page: 1 }, withResponse: true })
assert.strictEqual(users[0].name, "page 1")
assert.strictEqual(response.status, 200)
}).pipe(Effect.provide(HttpLive)))

it("OpenAPI spec", () => {
const spec = OpenApi.fromApi(Api)
assert.deepStrictEqual(spec, OpenApiFixture as any)
Expand Down
16 changes: 11 additions & 5 deletions packages/platform/src/HttpApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ export declare namespace Client {
infer _R,
infer _RE
>
] ? (
request: Simplify<HttpApiEndpoint.ClientRequest<_Path, _UrlParams, _Payload, _Headers>>
] ? <WithResponse extends boolean = false>(
request: Simplify<HttpApiEndpoint.ClientRequest<_Path, _UrlParams, _Payload, _Headers, WithResponse>>
) => Effect.Effect<
_Success,
WithResponse extends true ? [_Success, HttpClientResponse.HttpClientResponse] : _Success,
_Error | GroupError | ApiError | HttpClientError.HttpClientError
> :
never
Expand Down Expand Up @@ -120,6 +120,7 @@ export const make = <Groups extends HttpApiGroup.Any, ApiError, ApiR>(
number | "orElse",
(response: HttpClientResponse.HttpClientResponse) => Effect.Effect<any, any>
> = { orElse: statusOrElse }
const decodeResponse = HttpClientResponse.matchStatus(decodeMap)
errors.forEach((ast, status) => {
if (ast._tag === "None") {
decodeMap[status] = statusCodeError
Expand Down Expand Up @@ -150,6 +151,7 @@ export const make = <Groups extends HttpApiGroup.Any, ApiError, ApiR>(
readonly urlParams: any
readonly payload: any
readonly headers: any
readonly withResponse?: boolean
}) => {
const url = request && request.path ? makeUrl(request.path) : endpoint.path
const baseRequest = HttpClientRequest.make(endpoint.method)(url)
Expand Down Expand Up @@ -184,8 +186,12 @@ export const make = <Groups extends HttpApiGroup.Any, ApiError, ApiR>(
)
: identity,
Effect.flatMap(httpClient.execute),
Effect.flatMap(HttpClientResponse.matchStatus(decodeMap)),
options?.transformResponse === undefined ? identity : options.transformResponse,
Effect.flatMap((response) => {
const value = options?.transformResponse === undefined
? decodeResponse(response)
: options.transformResponse(decodeResponse(response))
return request?.withResponse === true ? Effect.map(value, (value) => [value, response]) : value
}),
Effect.scoped,
Effect.catchIf(ParseResult.isParseError, Effect.die),
Effect.mapInputContext((input) => Context.merge(context, input))
Expand Down
6 changes: 4 additions & 2 deletions packages/platform/src/HttpApiEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,14 +402,16 @@ export declare namespace HttpApiEndpoint {
* @since 1.0.0
* @category models
*/
export type ClientRequest<Path, UrlParams, Payload, Headers> = (
export type ClientRequest<Path, UrlParams, Payload, Headers, WithResponse extends boolean> = (
& ([Path] extends [void] ? {} : { readonly path: Path })
& ([UrlParams] extends [never] ? {} : { readonly urlParams: UrlParams })
& ([Headers] extends [never] ? {} : { readonly headers: Headers })
& ([Payload] extends [never] ? {}
: [Payload] extends [Brand<HttpApiSchema.MultipartTypeId>] ? { readonly payload: FormData }
: { readonly payload: Payload })
) extends infer Req ? keyof Req extends never ? void : Req : void
) extends infer Req ? keyof Req extends never ? (void | { readonly withResponse?: WithResponse }) :
Req & { readonly withResponse?: WithResponse } :
void

/**
* @since 1.0.0
Expand Down

0 comments on commit 07c493a

Please sign in to comment.