diff --git a/.changeset/wise-poems-do.md b/.changeset/wise-poems-do.md
new file mode 100644
index 000000000..764b19c4b
--- /dev/null
+++ b/.changeset/wise-poems-do.md
@@ -0,0 +1,5 @@
+---
+"openapi-fetch": patch
+---
+
+Added the option to provide custom fetch function to individual API calls.
diff --git a/docs/astro.config.js b/docs/astro.config.js
index e73ec98ac..fc6cf0071 100644
--- a/docs/astro.config.js
+++ b/docs/astro.config.js
@@ -1,7 +1,7 @@
-import { defineConfig } from "astro/config";
import preact from "@astrojs/preact";
import react from "@astrojs/react";
import sitemap from "@astrojs/sitemap";
+import { defineConfig } from "astro/config";
import sassDts from "vite-plugin-sass-dts";
// https://astro.build/config
@@ -21,9 +21,15 @@ export default defineConfig({
},
},
define: {
- "import.meta.env.VITE_ALGOLIA_APP_ID": JSON.stringify(process.env.ALGOLIA_APP_ID ?? ""),
- "import.meta.env.VITE_ALGOLIA_INDEX_NAME": JSON.stringify(process.env.ALGOLIA_INDEX_NAME ?? ""),
- "import.meta.env.VITE_ALGOLIA_SEARCH_KEY": JSON.stringify(process.env.ALGOLIA_SEARCH_KEY ?? ""),
+ "import.meta.env.VITE_ALGOLIA_APP_ID": JSON.stringify(
+ process.env.ALGOLIA_APP_ID ?? "",
+ ),
+ "import.meta.env.VITE_ALGOLIA_INDEX_NAME": JSON.stringify(
+ process.env.ALGOLIA_INDEX_NAME ?? "",
+ ),
+ "import.meta.env.VITE_ALGOLIA_SEARCH_KEY": JSON.stringify(
+ process.env.ALGOLIA_SEARCH_KEY ?? "",
+ ),
},
plugins: [sassDts()],
},
diff --git a/docs/src/content/docs/openapi-fetch/api.md b/docs/src/content/docs/openapi-fetch/api.md
index dc6ba2360..3fac22d1f 100644
--- a/docs/src/content/docs/openapi-fetch/api.md
+++ b/docs/src/content/docs/openapi-fetch/api.md
@@ -34,6 +34,7 @@ client.get("/my-url", options);
| `querySerializer` | QuerySerializer | (optional) Provide a [querySerializer](#queryserializer) |
| `bodySerializer` | BodySerializer | (optional) Provide a [bodySerializer](#bodyserializer) |
| `parseAs` | `"json"` \| `"text"` \| `"arrayBuffer"` \| `"blob"` \| `"stream"` | (optional) Parse the response using a built-in instance method (default: `"json"`). `"stream"` skips parsing altogether and returns the raw stream. |
+| `fetch` | `fetch` | Fetch instance used for requests (default: fetch from `createClient`) |
| (Fetch options) | | Any valid fetch option (`headers`, `mode`, `cache`, `signal`, …) (docs) |
### querySerializer
diff --git a/docs/src/content/docs/openapi-fetch/examples.md b/docs/src/content/docs/openapi-fetch/examples.md
index 38c70a8f7..8f6edbd97 100644
--- a/docs/src/content/docs/openapi-fetch/examples.md
+++ b/docs/src/content/docs/openapi-fetch/examples.md
@@ -90,7 +90,7 @@ openapi-fetch is simple vanilla JS that can be used in any project. But sometime
### Svelte / SvelteKit
-SvelteKit’s automatic type inference can easily pick up openapi-fetch’s types in both clientside fetching and Page Data fetching. And it doesn’t need any additional libraries to work.
+SvelteKit’s automatic type inference can easily pick up openapi-fetch’s types in both clientside fetching and Page Data fetching. And it doesn’t need any additional libraries to work. SvelteKit also advises to use their custom fetch in load functions - this can be achieved with fetch options.
_Note: if you’re using Svelte without SvelteKit, the root example in `src/routes/+page.svelte` doesn’t use any SvelteKit features and is generally-applicable to any setup._
diff --git a/packages/openapi-fetch/examples/sveltekit/src/hooks.server.ts b/packages/openapi-fetch/examples/sveltekit/src/hooks.server.ts
new file mode 100644
index 000000000..5d1e65207
--- /dev/null
+++ b/packages/openapi-fetch/examples/sveltekit/src/hooks.server.ts
@@ -0,0 +1,10 @@
+import type { Handle } from "@sveltejs/kit";
+
+export const handle: Handle = async ({ event, resolve }) => {
+ return resolve(event, {
+ filterSerializedResponseHeaders(name) {
+ // SvelteKit doesn't serialize any headers on server-side fetches by default but openapi-fetch uses this header for empty responses.
+ return name === "content-length";
+ },
+ });
+};
diff --git a/packages/openapi-fetch/examples/sveltekit/src/lib/api/index.ts b/packages/openapi-fetch/examples/sveltekit/src/lib/api/index.ts
index 0528b2e94..bdbdcbd21 100644
--- a/packages/openapi-fetch/examples/sveltekit/src/lib/api/index.ts
+++ b/packages/openapi-fetch/examples/sveltekit/src/lib/api/index.ts
@@ -1,12 +1,5 @@
import createClient from "openapi-fetch";
import type { paths } from "./v1";
-import type { PageServerLoadEvent } from "../../routes/page-data/$types";
const client = createClient({ baseUrl: "https://catfact.ninja/" });
export default client;
-
-export const createServerClient = (fetcher: PageServerLoadEvent["fetch"]) =>
- createClient({
- baseUrl: "https://catfact.ninja/",
- fetch: fetcher,
- });
diff --git a/packages/openapi-fetch/examples/sveltekit/src/routes/page-data/+page.server.ts b/packages/openapi-fetch/examples/sveltekit/src/routes/page-data/+page.ts
similarity index 71%
rename from packages/openapi-fetch/examples/sveltekit/src/routes/page-data/+page.server.ts
rename to packages/openapi-fetch/examples/sveltekit/src/routes/page-data/+page.ts
index 53b9c6784..610f6ded4 100644
--- a/packages/openapi-fetch/examples/sveltekit/src/routes/page-data/+page.server.ts
+++ b/packages/openapi-fetch/examples/sveltekit/src/routes/page-data/+page.ts
@@ -1,14 +1,12 @@
-import { createServerClient } from "$lib/api/index.js";
+import client from "$lib/api/index.js";
// Note: this uses Svelte’s custom fetcher as an example, but Node’s
// native fetch works, too. See Svelte’s docs to learn the difference:
// @see https://kit.svelte.dev/docs/load#making-fetch-requests
export async function load({ fetch }) {
- const client = createServerClient(fetch);
const fact = await client.GET("/fact", {
- params: {
- query: { max_length: 500 },
- },
+ params: { query: { max_length: 500 } },
+ fetch,
});
return {
diff --git a/packages/openapi-fetch/src/index.test.ts b/packages/openapi-fetch/src/index.test.ts
index 90e0030af..1e68ac651 100644
--- a/packages/openapi-fetch/src/index.test.ts
+++ b/packages/openapi-fetch/src/index.test.ts
@@ -396,18 +396,26 @@ describe("client", () => {
});
it("accepts a custom fetch function", async () => {
- const data = { works: true };
- const customFetch = {
- clone: () => ({ ...customFetch }),
- headers: new Headers(),
- json: async () => data,
- status: 200,
- ok: true,
- };
- const client = createClient({
- fetch: async () => Promise.resolve(customFetch as Response),
- });
- expect((await client.GET("/self")).data).toBe(data);
+ function createCustomFetch(data: any) {
+ const response = {
+ clone: () => ({ ...response }),
+ headers: new Headers(),
+ json: async () => data,
+ status: 200,
+ ok: true,
+ } as Response;
+ return async () => Promise.resolve(response);
+ }
+
+ const baseData = { works: true };
+ const customBaseFetch = createCustomFetch(baseData);
+ const client = createClient({ fetch: customBaseFetch });
+ expect((await client.GET("/self")).data).toBe(baseData);
+
+ const data = { result: "it's working" };
+ const customFetch = createCustomFetch(data);
+ const customResponse = await client.GET("/self", { fetch: customFetch });
+ expect(customResponse.data).toBe(data);
});
});
diff --git a/packages/openapi-fetch/src/index.ts b/packages/openapi-fetch/src/index.ts
index 6f78db13c..51b04f1e3 100644
--- a/packages/openapi-fetch/src/index.ts
+++ b/packages/openapi-fetch/src/index.ts
@@ -70,7 +70,8 @@ export type RequestBodyOption = OperationRequestBodyContent extends never
? { body?: OperationRequestBodyContent }
: { body: OperationRequestBodyContent };
-export type FetchOptions = RequestOptions & Omit;
+export type FetchOptions = RequestOptions &
+ Omit & { fetch?: ClientOptions["fetch"] };
export type FetchResponse =
| {
@@ -95,7 +96,7 @@ export default function createClient(
clientOptions: ClientOptions = {},
) {
const {
- fetch = globalThis.fetch,
+ fetch: baseFetch = globalThis.fetch,
querySerializer: globalQuerySerializer,
bodySerializer: globalBodySerializer,
...options
@@ -110,6 +111,7 @@ export default function createClient(
fetchOptions: FetchOptions,
): Promise> {
const {
+ fetch = baseFetch,
headers,
body: requestBody,
params = {},