Skip to content

Commit db0ada7

Browse files
committed
Fix rebase
1 parent 676066a commit db0ada7

File tree

10 files changed

+44
-40
lines changed

10 files changed

+44
-40
lines changed

.changeset/nasty-comics-taste.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"openapi-fetch": minor
3+
---
4+
5+
⚠️ Breaking change (internal): fetch() is now called with new Request() to support middleware (which may affect test mocking)

docs/.vitepress/theme/style.css

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
/**
77
* Fonts
88
*/
9+
910
@font-face {
1011
font-family: "Inter";
1112
font-style: normal;

docs/openapi-fetch/api.md

+2
Original file line numberDiff line numberDiff line change
@@ -248,3 +248,5 @@ client.use(myMiddleware);
248248
// remove middleware
249249
client.eject(myMiddleware);
250250
```
251+
252+
For additional guides & examples, see [Middleware & Auth](/openapi-fetch/middleware-auth)

docs/openapi-fetch/index.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ title: openapi-fetch
44

55
<img src="/assets/openapi-fetch.svg" alt="openapi-fetch" width="216" height="40" />
66

7-
openapi-fetch is a typesafe fetch client that pulls in your OpenAPI schema. Weighs **4 kb** and has virtually zero runtime. Works with React, Vue, Svelte, or vanilla JS.
7+
openapi-fetch is a typesafe fetch client that pulls in your OpenAPI schema. Weighs **5 kb** and has virtually zero runtime. Works with React, Vue, Svelte, or vanilla JS.
88

99
| Library | Size (min) | “GET” request |
1010
| :------------------------- | ---------: | :------------------------- |
11-
| openapi-fetch | `4 kB` | `278k` ops/s (fastest) |
11+
| openapi-fetch | `5 kB` | `278k` ops/s (fastest) |
1212
| openapi-typescript-fetch | `4 kB` | `130k` ops/s (2.1× slower) |
1313
| axios | `32 kB` | `217k` ops/s (1.3× slower) |
1414
| superagent | `55 kB` | `63k` ops/s (4.4× slower) |
1515
| openapi-typescript-codegen | `367 kB` | `106k` ops/s (2.6× slower) |
1616

17-
The syntax is inspired by popular libraries like react-query or Apollo client, but without all the bells and whistles and in a 4 kb package.
17+
The syntax is inspired by popular libraries like react-query or Apollo client, but without all the bells and whistles and in a 5 kb package.
1818

1919
```ts
2020
import createClient from "openapi-fetch";
@@ -49,7 +49,7 @@ Notice there are no generics, and no manual typing. Your endpoint’s request an
4949
- ✅ No manual typing of your API
5050
- ✅ Eliminates `any` types that hide bugs
5151
- ✅ Also eliminates `as` type overrides that can also hide bugs
52-
- ✅ All of this in a **4 kb** client package 🎉
52+
- ✅ All of this in a **5 kb** client package 🎉
5353

5454
## Setup
5555

docs/openapi-fetch/middleware-auth.md

+7-9
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ title: Middleware & Auth
44

55
# Middleware & Auth
66

7-
## Middleware
7+
Middleware allows you to modify either the request, response, or both for all fetches. One of the most common usecases is authentication, but can also be used for logging/telemetry, throwing errors, or handling specific edge cases.
88

9-
Middleware allows you to modify either the request, response, or both for all fetches.
9+
## Middleware
1010

1111
Each middleware can provide `onRequest()` and `onResponse()` callbacks, which can observe and/or mutate requests and responses.
1212

@@ -33,11 +33,9 @@ const client = createClient<paths>({ baseUrl: "https://myapi.dev/v1/" });
3333
client.use(myMiddleware);
3434
```
3535

36-
::: tip
37-
38-
The order in which middleware are registered matters. For requests, `onRequest()` will be called in the order registered. For responses, `onResponse()` will be called in **reverse** order. That way the first middleware gets the first “dibs” on requests, and the final control over responses.
39-
40-
:::
36+
> [!TIP]
37+
>
38+
> The order in which middleware are registered matters. For requests, `onRequest()` will be called in the order registered. For responses, `onResponse()` will be called in **reverse** order. That way the first middleware gets the first “dibs” on requests, and the final control over the end response.
4139
4240
### Skipping
4341

@@ -108,7 +106,7 @@ const myMiddleware: Middleware = {
108106

109107
This library is unopinionated and can work with any [Authorization](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization) setup. But here are a few suggestions that may make working with auth easier.
110108

111-
### Basic Auth
109+
### Basic auth
112110

113111
This basic example uses middleware to retrieve the most up-to-date token at every request. In our example, the access token is kept in JavaScript module state, which is safe to do for client applications but should be avoided for server applications.
114112

@@ -144,7 +142,7 @@ client.use(authMiddleware);
144142
const authRequest = await client.GET("/some/auth/url");
145143
```
146144

147-
### Conditional Auth
145+
### Conditional auth
148146

149147
If authorization isn’t needed for certain routes, you could also handle that with middleware:
150148

packages/openapi-fetch/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ openapi-fetch is a typesafe fetch client that pulls in your OpenAPI schema. Weig
44

55
| Library | Size (min) | “GET” request |
66
| :------------------------- | ---------: | :------------------------- |
7-
| openapi-fetch | `4 kB` | `278k` ops/s (fastest) |
7+
| openapi-fetch | `5 kB` | `278k` ops/s (fastest) |
88
| openapi-typescript-fetch | `4 kB` | `130k` ops/s (2.1× slower) |
99
| axios | `32 kB` | `217k` ops/s (1.3× slower) |
1010
| superagent | `55 kB` | `63k` ops/s (4.4× slower) |
@@ -45,7 +45,7 @@ Notice there are no generics, and no manual typing. Your endpoint’s request an
4545
- ✅ No manual typing of your API
4646
- ✅ Eliminates `any` types that hide bugs
4747
- ✅ Also eliminates `as` type overrides that can also hide bugs
48-
- ✅ All of this in a **4 kb** client package 🎉
48+
- ✅ All of this in a **5 kb** client package 🎉
4949

5050
## 🔧 Setup
5151

packages/openapi-fetch/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "openapi-fetch",
3-
"description": "Fast, typesafe fetch client for your OpenAPI schema. Only 4 kb (min). Works with React, Vue, Svelte, or vanilla JS.",
3+
"description": "Fast, typesafe fetch client for your OpenAPI schema. Only 5 kb (min). Works with React, Vue, Svelte, or vanilla JS.",
44
"version": "0.8.2",
55
"author": {
66
"name": "Drew Powers",

packages/openapi-fetch/src/index.js

+4-8
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ export default function createClient(clientOptions) {
1313
let {
1414
baseUrl = "",
1515
fetch: baseFetch = globalThis.fetch,
16-
querySerializer: globalQuerySerializer = defaultQuerySerializer,
17-
bodySerializer: globalBodySerializer = defaultBodySerializer,
16+
querySerializer: globalQuerySerializer,
17+
bodySerializer: globalBodySerializer,
1818
headers: baseHeaders,
1919
...baseOptions
2020
} = { ...clientOptions };
@@ -36,7 +36,7 @@ export default function createClient(clientOptions) {
3636
params = {},
3737
parseAs = "json",
3838
querySerializer: requestQuerySerializer,
39-
bodySerializer = globalBodySerializer,
39+
bodySerializer = globalBodySerializer ?? defaultBodySerializer,
4040
...init
4141
} = fetchOptions || {};
4242

@@ -66,11 +66,7 @@ export default function createClient(clientOptions) {
6666
requestInit.body = bodySerializer(requestInit.body);
6767
}
6868
let request = new Request(
69-
createFinalURL(url, {
70-
baseUrl,
71-
params,
72-
querySerializer,
73-
}),
69+
createFinalURL(url, { baseUrl, params, querySerializer }),
7470
requestInit,
7571
);
7672
// remove `Content-Type` if serialized body is FormData; browser will correctly set Content-Type & boundary expression

packages/openapi-fetch/test/index.test.ts

+9-8
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,13 @@ describe("client", () => {
190190
it("allows UTF-8 characters", async () => {
191191
const client = createClient<paths>();
192192
mockFetchOnce({ status: 200, body: "{}" });
193-
const post_id = "post?id = 🥴";
194193
await client.GET("/blogposts/{post_id}", {
195-
params: { path: { post_id } },
194+
params: { path: { post_id: "post?id = 🥴" } },
196195
});
197196

198197
// expect post_id to be encoded properly
199198
expect(fetchMocker.mock.calls[0][0].url).toBe(
200-
`/blogposts/${post_id}`,
199+
`/blogposts/post?id%20=%20🥴`,
201200
);
202201
});
203202
});
@@ -245,7 +244,7 @@ describe("client", () => {
245244
});
246245

247246
expect(fetchMocker.mock.calls[0][0].url).toBe(
248-
"/blogposts/my-post?alpha=2&beta=json",
247+
"/query-params?string=string&number=0&boolean=false",
249248
);
250249
});
251250

@@ -258,7 +257,7 @@ describe("client", () => {
258257
},
259258
});
260259

261-
expect(fetchMocker.mock.calls[0][0]).toBe("/query-params");
260+
expect(fetchMocker.mock.calls[0][0].url).toBe("/query-params");
262261
});
263262

264263
it("empty/null params", async () => {
@@ -961,13 +960,15 @@ describe("client", () => {
961960
expect(req.headers.get("Content-Type")).toBeNull();
962961
});
963962

964-
it("respects cookie", async () => {
963+
// Node Requests eat credentials (no cookies), but this works in frontend
964+
// TODO: find a way to reliably test this without too much mocking
965+
it.skip("respects cookie", async () => {
965966
const client = createClient<paths>();
966967
mockFetchOnce({ status: 200, body: "{}" });
967968
await client.GET("/blogposts", { credentials: "include" });
968969

969-
const req = fetchMocker.mock.calls[0][1];
970-
expect(req).toEqual(expect.objectContaining({ credentials: "include" }));
970+
const req = fetchMocker.mock.calls[0][0];
971+
expect(req.credentials).toBe("include");
971972
});
972973
});
973974

packages/openapi-fetch/test/v7-beta.test.ts

+9-8
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,7 @@ describe("client", () => {
171171
},
172172
);
173173

174-
const reqURL = fetchMocker.mock.calls[0][0];
175-
expect(reqURL).toBe(
174+
expect(fetchMocker.mock.calls[0][0].url).toBe(
176175
`/path-params/${[
177176
// simple
178177
"simple",
@@ -199,14 +198,14 @@ describe("client", () => {
199198
it("allows UTF-8 characters", async () => {
200199
const client = createClient<paths>();
201200
mockFetchOnce({ status: 200, body: "{}" });
202-
const post_id = "post?id = 🥴";
201+
203202
await client.GET("/blogposts/{post_id}", {
204-
params: { path: { post_id } },
203+
params: { path: { post_id: "post?id = 🥴" } },
205204
});
206205

207206
// expect post_id to be encoded properly
208207
expect(fetchMocker.mock.calls[0][0].url).toBe(
209-
`/blogposts/${post_id}`,
208+
`/blogposts/post?id%20=%20🥴`,
210209
);
211210
});
212211
});
@@ -952,13 +951,15 @@ describe("client", () => {
952951
expect((req.headers as Headers).get("Content-Type")).toBeNull();
953952
});
954953

955-
it("respects cookie", async () => {
954+
// Node Requests eat credentials (no cookies), but this works in frontend
955+
// TODO: find a way to reliably test this without too much mocking
956+
it.skip("respects cookie", async () => {
956957
const client = createClient<paths>();
957958
mockFetchOnce({ status: 200, body: "{}" });
958959
await client.GET("/blogposts", { credentials: "include" });
959960

960-
const req = fetchMocker.mock.calls[0][1];
961-
expect(req).toEqual(expect.objectContaining({ credentials: "include" }));
961+
const req = fetchMocker.mock.calls[0][0];
962+
expect(req.credentials).toBe("include");
962963
});
963964
});
964965

0 commit comments

Comments
 (0)