Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/purple-cobras-strive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tim-smart/openapi-gen": patch
---

Allow inclusion of `HttpClientResponse` in client output to enable accessing response properties
13 changes: 10 additions & 3 deletions src/JsonSchemaGen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,16 @@ const make = Effect.gen(function* () {
isClass,
isEnum,
})
return toSource(importName, Object.keys(schema).length ? schema : {
properties: {},
} as JsonSchema.JsonSchema, name, topLevel).pipe(
return toSource(
importName,
Object.keys(schema).length
? schema
: ({
properties: {},
} as JsonSchema.JsonSchema),
name,
topLevel,
).pipe(
Option.map((source) =>
transformer.onTopLevel({
importName,
Expand Down
42 changes: 28 additions & 14 deletions src/OpenApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ export const layerTransformerSchema = Layer.sync(OpenApiTransformer, () => {
const operationsToInterface = (
name: string,
operations: ReadonlyArray<ParsedOperation>,
) => `export interface ${name} {
) => `export interface ${name}<Options extends MakeOptions = {}> {
readonly httpClient: HttpClient.HttpClient
${operations.map((op) => operationToMethod(name, op)).join("\n ")}
}
Expand Down Expand Up @@ -327,18 +327,25 @@ ${clientErrorSource(name)}`
),
)
}
return `${toComment(operation.description)}readonly "${operation.id}": (${args.join(", ")}) => Effect.Effect<${success}, ${errors.join(" | ")}>`
return `${toComment(operation.description)}readonly "${operation.id}": (${args.join(", ")}) => Effect.Effect<WithResponse<Options, ${success}>, ${errors.join(" | ")}>`
}

const operationsToImpl = (
name: string,
operations: ReadonlyArray<ParsedOperation>,
) => `export const make = (
) => `export type MakeOptions = {
readonly includeResponse?: boolean | undefined
readonly transformClient?: ((client: HttpClient.HttpClient) => Effect.Effect<HttpClient.HttpClient>) | undefined
}

export type WithResponse<Options extends MakeOptions, A> = Options extends { readonly includeResponse: true }
? [A, HttpClientResponse.HttpClientResponse]
: A

export const make = <Options extends MakeOptions = {}>(
httpClient: HttpClient.HttpClient,
options: {
readonly transformClient?: ((client: HttpClient.HttpClient) => Effect.Effect<HttpClient.HttpClient>) | undefined
} = {}
): ${name} => {
options?: Options
): ${name}<Options> => {
${commonSource}
const decodeSuccess =
<A, I, R>(schema: S.Schema<A, I, R>) =>
Expand Down Expand Up @@ -438,7 +445,7 @@ export const layerTransformerTs = Layer.sync(OpenApiTransformer, () => {
const operationsToInterface = (
name: string,
operations: ReadonlyArray<ParsedOperation>,
) => `export interface ${name} {
) => `export interface ${name}<Options extends MakeOptions> {
readonly httpClient: HttpClient.HttpClient
${operations.map((s) => operationToMethod(name, s)).join("\n ")}
}
Expand Down Expand Up @@ -626,19 +633,26 @@ const commonSource = `const unexpectedStatus = (response: HttpClientResponse.Htt
}),
),
)
const withResponse: <A, E>(
const withResponse = <A, E>(
f: (response: HttpClientResponse.HttpClientResponse) => Effect.Effect<A, E>,
) => (
): (
request: HttpClientRequest.HttpClientRequest,
) => Effect.Effect<any, any> = options.transformClient
? (f) => (request) =>
) => Effect.Effect<any, any> => {
const includeResponse = (
options?.includeResponse
? (response: HttpClientResponse.HttpClientResponse) => Effect.map(f(response), (a) => [a, response])
: (response: HttpClientResponse.HttpClientResponse) => f(response)
) as any
return options?.transformClient
? (request) =>
Effect.flatMap(
Effect.flatMap(options.transformClient!(httpClient), (client) =>
client.execute(request),
),
f,
includeResponse,
)
: (f) => (request) => Effect.flatMap(httpClient.execute(request), f)`
: (request) => Effect.flatMap(httpClient.execute(request), includeResponse)
}`

const clientErrorSource = (
name: string,
Expand Down