Skip to content

Commit ca6f394

Browse files
authored
Fix openapi fetch types (#1378)
* Fix openapi-fetch types * Don’t publish examples to npm
1 parent fd3e96f commit ca6f394

File tree

9 files changed

+2156
-782
lines changed

9 files changed

+2156
-782
lines changed

packages/openapi-fetch/.npmignore

+4
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1+
.eslintignore
2+
.prettierignore
3+
examples
14
test
5+
vitest.config.ts

packages/openapi-fetch/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
"del-cli": "^5.1.0",
7171
"esbuild": "^0.19.4",
7272
"nanostores": "^0.9.3",
73-
"openapi-typescript": "workspace:^",
73+
"openapi-typescript": "^6.7.0",
7474
"openapi-typescript-codegen": "^0.25.0",
7575
"openapi-typescript-fetch": "^1.1.3",
7676
"superagent": "^8.1.2",

packages/openapi-fetch/src/index.ts

+5-10
Original file line numberDiff line numberDiff line change
@@ -51,27 +51,21 @@ export interface DefaultParamsOption {
5151
params?: { query?: Record<string, unknown> };
5252
}
5353

54-
export interface EmptyParameters {
55-
query?: never;
56-
header?: never;
57-
path?: never;
58-
cookie?: never;
59-
}
60-
6154
export type ParamsOption<T> = T extends { parameters: any }
6255
? HasRequiredKeys<T["parameters"]> extends never
6356
? { params?: T["parameters"] }
6457
: { params: T["parameters"] }
65-
: never;
58+
: DefaultParamsOption;
59+
// v7 breaking change: TODO uncomment for openapi-typescript@7 support
60+
// : never;
6661

6762
export type RequestBodyOption<T> = OperationRequestBodyContent<T> extends never
6863
? { body?: never }
6964
: undefined extends OperationRequestBodyContent<T>
7065
? { body?: OperationRequestBodyContent<T> }
7166
: { body: OperationRequestBodyContent<T> };
7267

73-
export type FetchOptions<T> = RequestOptions<T> &
74-
Omit<RequestInit, "body"> & { fetch?: ClientOptions["fetch"] };
68+
export type FetchOptions<T> = RequestOptions<T> & Omit<RequestInit, "body">;
7569

7670
export type FetchResponse<T> =
7771
| {
@@ -90,6 +84,7 @@ export type RequestOptions<T> = ParamsOption<T> &
9084
querySerializer?: QuerySerializer<T>;
9185
bodySerializer?: BodySerializer<T>;
9286
parseAs?: ParseAs;
87+
fetch?: ClientOptions["fetch"];
9388
};
9489

9590
export default function createClient<Paths extends {}>(

packages/openapi-fetch/src/index.test.ts renamed to packages/openapi-fetch/test/index.test.ts

+44-11
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { atom, computed } from "nanostores";
22
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
33
// @ts-expect-error
44
import createFetchMock from "vitest-fetch-mock";
5-
import type { paths } from "../test/v1.js";
6-
import createClient from "./index.js";
5+
import createClient from "../src/index.js";
6+
import type { paths } from "./v1.d.js";
77

88
const fetchMocker = createFetchMock(vi);
99

@@ -395,7 +395,7 @@ describe("client", () => {
395395
expect(options?.headers).toEqual(new Headers());
396396
});
397397

398-
it("accepts a custom fetch function", async () => {
398+
it("accepts a custom fetch function on createClient", async () => {
399399
function createCustomFetch(data: any) {
400400
const response = {
401401
clone: () => ({ ...response }),
@@ -407,15 +407,48 @@ describe("client", () => {
407407
return async () => Promise.resolve(response);
408408
}
409409

410-
const baseData = { works: true };
411-
const customBaseFetch = createCustomFetch(baseData);
412-
const client = createClient<paths>({ fetch: customBaseFetch });
413-
expect((await client.GET("/self")).data).toBe(baseData);
410+
const customFetch = createCustomFetch({ works: true });
411+
mockFetchOnce({ status: 200, body: "{}" });
412+
413+
const client = createClient<paths>({ fetch: customFetch });
414+
const { data } = await client.GET("/self");
415+
416+
// assert data was returned from custom fetcher
417+
expect(data).toEqual({ works: true });
418+
419+
// assert global fetch was never called
420+
expect(fetchMocker).not.toHaveBeenCalled();
421+
});
422+
423+
it("accepts a custom fetch function per-request", async () => {
424+
function createCustomFetch(data: any) {
425+
const response = {
426+
clone: () => ({ ...response }),
427+
headers: new Headers(),
428+
json: async () => data,
429+
status: 200,
430+
ok: true,
431+
} as Response;
432+
return async () => Promise.resolve(response);
433+
}
434+
435+
const fallbackFetch = createCustomFetch({ fetcher: "fallback" });
436+
const overrideFetch = createCustomFetch({ fetcher: "override" });
437+
438+
mockFetchOnce({ status: 200, body: "{}" });
439+
440+
const client = createClient<paths>({ fetch: fallbackFetch });
441+
442+
// assert override function was called
443+
const fetch1 = await client.GET("/self", { fetch: overrideFetch });
444+
expect(fetch1.data).toEqual({ fetcher: "override" });
445+
446+
// assert fallback function still persisted (and wasn’t overridden)
447+
const fetch2 = await client.GET("/self");
448+
expect(fetch2.data).toEqual({ fetcher: "fallback" });
414449

415-
const data = { result: "it's working" };
416-
const customFetch = createCustomFetch(data);
417-
const customResponse = await client.GET("/self", { fetch: customFetch });
418-
expect(customResponse.data).toBe(data);
450+
// assert global fetch was never called
451+
expect(fetchMocker).not.toHaveBeenCalled();
419452
});
420453
});
421454

0 commit comments

Comments
 (0)