From 1f7ad9d41f1f1ca7b1195a381c907393f9ef743b Mon Sep 17 00:00:00 2001 From: Armand Abric Date: Wed, 27 Mar 2024 18:11:00 +0100 Subject: [PATCH] Allow to select the response content type (#1597) --- .changeset/few-tomatoes-try.md | 5 +++ packages/openapi-fetch/src/index.d.ts | 30 +++++++++------- packages/openapi-fetch/test/fixtures/api.d.ts | 23 ++++++++++-- packages/openapi-fetch/test/index.test.ts | 36 +++++++++++++++++++ 4 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 .changeset/few-tomatoes-try.md diff --git a/.changeset/few-tomatoes-try.md b/.changeset/few-tomatoes-try.md new file mode 100644 index 000000000..0161d284a --- /dev/null +++ b/.changeset/few-tomatoes-try.md @@ -0,0 +1,5 @@ +--- +"openapi-fetch": patch +--- + +Allow to select the response content type diff --git a/packages/openapi-fetch/src/index.d.ts b/packages/openapi-fetch/src/index.d.ts index 3d7b70c99..b85861113 100644 --- a/packages/openapi-fetch/src/index.d.ts +++ b/packages/openapi-fetch/src/index.d.ts @@ -111,10 +111,10 @@ export type RequestBodyOption = export type FetchOptions = RequestOptions & Omit; -export type FetchResponse = +export type FetchResponse = | { data: ParseAsResponse< - FilterKeys>, MediaType>, + FilterKeys>, Media>, O >; error?: never; @@ -122,7 +122,7 @@ export type FetchResponse = } | { data?: never; - error: FilterKeys>, MediaType>; + error: FilterKeys>, Media>; response: Response; }; @@ -180,33 +180,37 @@ export type MaybeOptionalInit

= export type ClientMethod< Paths extends Record, M extends HttpMethod, + Media extends MediaType, > = < P extends PathsWithMethod, I extends MaybeOptionalInit, >( url: P, ...init: I -) => Promise>; +) => Promise>; -export default function createClient( +export default function createClient< + Paths extends {}, + Media extends MediaType = MediaType, +>( clientOptions?: ClientOptions, ): { /** Call a GET endpoint */ - GET: ClientMethod; + GET: ClientMethod; /** Call a PUT endpoint */ - PUT: ClientMethod; + PUT: ClientMethod; /** Call a POST endpoint */ - POST: ClientMethod; + POST: ClientMethod; /** Call a DELETE endpoint */ - DELETE: ClientMethod; + DELETE: ClientMethod; /** Call a OPTIONS endpoint */ - OPTIONS: ClientMethod; + OPTIONS: ClientMethod; /** Call a HEAD endpoint */ - HEAD: ClientMethod; + HEAD: ClientMethod; /** Call a PATCH endpoint */ - PATCH: ClientMethod; + PATCH: ClientMethod; /** Call a TRACE endpoint */ - TRACE: ClientMethod; + TRACE: ClientMethod; /** Register middleware */ use(...middleware: Middleware[]): void; /** Unregister middleware */ diff --git a/packages/openapi-fetch/test/fixtures/api.d.ts b/packages/openapi-fetch/test/fixtures/api.d.ts index c3238d82f..7131c0e31 100644 --- a/packages/openapi-fetch/test/fixtures/api.d.ts +++ b/packages/openapi-fetch/test/fixtures/api.d.ts @@ -3,7 +3,6 @@ * Do not make direct changes to the file. */ - export interface paths { "/comment": { put: { @@ -396,6 +395,13 @@ export interface paths { }; }; }; + "/multiple-response-content": { + get: { + responses: { + 200: components["responses"]["MultipleResponse"]; + }; + }; + }; } export type webhooks = Record; @@ -492,6 +498,20 @@ export interface components { "application/json": components["schemas"]["User"]; }; }; + MultipleResponse: { + content: { + "application/json": { + id: string; + email: string; + name?: string; + }; + "application/ld+json": { + "@id": string; + email: string; + name?: string; + }; + }; + }; }; parameters: never; requestBodies: { @@ -557,7 +577,6 @@ export type $defs = Record; export type external = Record; export interface operations { - getHeaderParams: { parameters: { header: { diff --git a/packages/openapi-fetch/test/index.test.ts b/packages/openapi-fetch/test/index.test.ts index 17d37c266..66ab694a0 100644 --- a/packages/openapi-fetch/test/index.test.ts +++ b/packages/openapi-fetch/test/index.test.ts @@ -1049,6 +1049,42 @@ describe("client", () => { expect(data.byteLength).toBe(2); }); + + it("use the selected content", async () => { + const client = createClient(); + mockFetchOnce({ + status: 200, + headers: { "Content-Type": "application/ld+json" }, + body: JSON.stringify({ + "@id": "some-resource-identifier", + email: "foo@bar.fr", + name: null, + }), + }); + const { data } = await client.GET("/multiple-response-content", { + headers: { + Accept: "application/ld+json", + }, + }); + + data satisfies + | { + "@id": string; + email: string; + name?: string; + } + | undefined; + + if (!data) { + throw new Error(`Missing response`); + } + + expect(data).toEqual({ + "@id": "some-resource-identifier", + email: "foo@bar.fr", + name: null, + }); + }); }); });