diff --git a/.changeset/purple-cobras-strive.md b/.changeset/purple-cobras-strive.md new file mode 100644 index 0000000..dd451b3 --- /dev/null +++ b/.changeset/purple-cobras-strive.md @@ -0,0 +1,5 @@ +--- +"@tim-smart/openapi-gen": patch +--- + +Allow inclusion of `HttpClientResponse` in client output to enable accessing response properties diff --git a/src/JsonSchemaGen.ts b/src/JsonSchemaGen.ts index deb197e..eda56f8 100644 --- a/src/JsonSchemaGen.ts +++ b/src/JsonSchemaGen.ts @@ -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, diff --git a/src/OpenApi.ts b/src/OpenApi.ts index b84f981..041ff53 100644 --- a/src/OpenApi.ts +++ b/src/OpenApi.ts @@ -280,7 +280,7 @@ export const layerTransformerSchema = Layer.sync(OpenApiTransformer, () => { const operationsToInterface = ( name: string, operations: ReadonlyArray, - ) => `export interface ${name} { + ) => `export interface ${name} { readonly httpClient: HttpClient.HttpClient ${operations.map((op) => operationToMethod(name, op)).join("\n ")} } @@ -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, ${errors.join(" | ")}>` } const operationsToImpl = ( name: string, operations: ReadonlyArray, - ) => `export const make = ( + ) => `export type MakeOptions = { + readonly includeResponse?: boolean | undefined + readonly transformClient?: ((client: HttpClient.HttpClient) => Effect.Effect) | undefined +} + +export type WithResponse = Options extends { readonly includeResponse: true } + ? [A, HttpClientResponse.HttpClientResponse] + : A + +export const make = ( httpClient: HttpClient.HttpClient, - options: { - readonly transformClient?: ((client: HttpClient.HttpClient) => Effect.Effect) | undefined - } = {} -): ${name} => { + options?: Options +): ${name} => { ${commonSource} const decodeSuccess = (schema: S.Schema) => @@ -438,7 +445,7 @@ export const layerTransformerTs = Layer.sync(OpenApiTransformer, () => { const operationsToInterface = ( name: string, operations: ReadonlyArray, - ) => `export interface ${name} { + ) => `export interface ${name} { readonly httpClient: HttpClient.HttpClient ${operations.map((s) => operationToMethod(name, s)).join("\n ")} } @@ -626,19 +633,26 @@ const commonSource = `const unexpectedStatus = (response: HttpClientResponse.Htt }), ), ) - const withResponse: ( + const withResponse = ( f: (response: HttpClientResponse.HttpClientResponse) => Effect.Effect, - ) => ( + ): ( request: HttpClientRequest.HttpClientRequest, - ) => Effect.Effect = options.transformClient - ? (f) => (request) => + ) => Effect.Effect => { + 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,