Skip to content

Commit e638141

Browse files
committed
Merge branch 'main' into feature/docs-ja/yoshi2no
2 parents 11ed757 + 754b31a commit e638141

File tree

15 files changed

+607
-63
lines changed

15 files changed

+607
-63
lines changed

.changeset/hip-years-invite.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

.changeset/lazy-dancers-push.md

Lines changed: 0 additions & 7 deletions
This file was deleted.

docs/examples.md

Lines changed: 231 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,135 @@ The types generated by openapi-typescript are universal, and can be used in a va
1111

1212
Fetching data can be done simply and safely using an **automatically-typed fetch wrapper**:
1313

14-
- [openapi-fetch](/openapi-fetch/) (recommended)
15-
- [openapi-typescript-fetch](https://www.npmjs.com/package/openapi-typescript-fetch) by [@ajaishankar](https://github.com/ajaishankar)
14+
<details>
15+
<summary><a href="/openapi-fetch/">openapi-fetch</a> (recommended)</summary>
16+
17+
::: code-group
18+
19+
```ts [test/my-project.ts]
20+
import createClient from "openapi-fetch";
21+
import type { paths } from "./my-openapi-3-schema"; // generated by openapi-typescript
22+
23+
const client = createClient<paths>({ baseUrl: "https://myapi.dev/v1/" });
24+
25+
const {
26+
data, // only present if 2XX response
27+
error, // only present if 4XX or 5XX response
28+
} = await client.GET("/blogposts/{post_id}", {
29+
params: {
30+
path: { post_id: "123" },
31+
},
32+
});
33+
34+
await client.PUT("/blogposts", {
35+
body: {
36+
title: "My New Post",
37+
},
38+
});
39+
```
40+
41+
:::
42+
43+
</details>
44+
45+
<details>
46+
<summary><a href="https://www.npmjs.com/package/openapi-typescript-fetch" target="_blank" rel="noreferrer">openapi-typescript-fetch</a> by <a href="https://github.com/ajaishankar" target="_blank" rel="noreferrer">@ajaishankar</a></summary>
47+
48+
::: code-group
49+
50+
```ts [test/my-project.ts]
51+
import { Fetcher } from 'openapi-typescript-fetch';
52+
import type { paths } from './my-openapi-3-schema'; // generated by openapi-typescript
53+
54+
const fetcher = Fetcher.for<paths>();
55+
56+
// GET request
57+
const getBlogPost = fetcher.path('/blogposts/{post_id}').method('get').create();
58+
59+
try {
60+
const { status, data } = await getBlogPost({ pathParams: { post_id: '123' } });
61+
console.log(data);
62+
} catch (error) {
63+
console.error('Error:', error);
64+
}
65+
66+
// PUT request
67+
const updateBlogPost = fetcher.path('/blogposts').method('put').create();
68+
69+
try {
70+
await updateBlogPost({ body: { title: 'My New Post' } });
71+
} catch (error) {
72+
console.error('Error:', error);
73+
}
74+
```
75+
76+
:::
77+
78+
</details>
79+
80+
<details>
81+
<summary><a href="https://www.npmjs.com/package/feature-fetch" target="_blank" rel="noreferrer">feature-fetch</a> by <a href="https://github.com/builder-group" target="_blank" rel="noreferrer">builder.group</a></summary>
82+
83+
::: code-group
84+
85+
```ts [test/my-project.ts]
86+
import { createOpenApiFetchClient } from 'feature-fetch';
87+
import type { paths } from './my-openapi-3-schema'; // generated by openapi-typescript
88+
89+
// Create the OpenAPI fetch client
90+
const fetchClient = createOpenApiFetchClient<paths>({
91+
prefixUrl: 'https://myapi.dev/v1'
92+
});
93+
94+
// Send a GET request
95+
const response = await fetchClient.get('/blogposts/{post_id}', {
96+
pathParams: {
97+
post_id: '123',
98+
},
99+
});
100+
101+
// Handle the response (Approach 1: Standard if-else)
102+
if (response.isOk()) {
103+
const data = response.value.data;
104+
console.log(data); // Handle successful response
105+
} else {
106+
const error = response.error;
107+
if (error instanceof NetworkError) {
108+
console.error('Network error:', error.message);
109+
} else if (error instanceof RequestError) {
110+
console.error('Request error:', error.message, 'Status:', error.status);
111+
} else {
112+
console.error('Service error:', error.message);
113+
}
114+
}
115+
116+
// Send a PUT request
117+
const putResponse = await fetchClient.put('/blogposts', {
118+
body: {
119+
title: 'My New Post',
120+
},
121+
});
122+
123+
// Handle the response (Approach 2: Try-catch)
124+
try {
125+
const putData = putResponse.unwrap().data;
126+
console.log(putData); // Handle the successful response
127+
} catch (error) {
128+
// Handle the error
129+
if (error instanceof NetworkError) {
130+
console.error('Network error:', error.message);
131+
} else if (error instanceof RequestError) {
132+
console.error('Request error:', error.message, 'Status:', error.status);
133+
} else {
134+
console.error('Service error:', error.message);
135+
}
136+
}
137+
```
138+
139+
:::
140+
141+
</details>
142+
16143

17144
::: tip
18145

@@ -60,6 +187,108 @@ TypeChecking in server environments can be tricky, as you’re often querying da
60187

61188
:::
62189

190+
## Hono with [`@blgc/openapi-router`](https://github.com/builder-group/community/tree/develop/packages/openapi-router)
191+
192+
Instead of manually typing each route with generics as in the [Hono example](#hono), [`@blgc/openapi-router`](https://github.com/builder-group/community/tree/develop/packages/openapi-router) wraps around the [Hono router](https://hono.dev/docs/api/routing) to deliver full typesafety and enforce your OpenAPI-Schema with validators.
193+
194+
::: tip Good To Know
195+
196+
While TypeScript types ensure compile-time safety, they don't enforce runtime schema validation. For runtime compliance, you need to integrate with validation libraries like Zod or Valibot. Although you must define the validation rules manually, they are type-safe to ensure these rules are correctly defined.
197+
198+
:::
199+
200+
::: code-group
201+
202+
```ts [src/router.ts]
203+
import { createHonoOpenApiRouter } from '@blgc/openapi-router';
204+
import { Hono } from 'hono';
205+
import { zValidator } from 'validation-adapters/zod';
206+
import * as z from 'zod';
207+
208+
import { paths } from './gen/v1'; // OpenAPI-generated types
209+
import { PetSchema } from './schemas'; // Custom reusable Zod schema for validation
210+
211+
export const router = new Hono();
212+
export const openApiRouter = createHonoOpenApiRouter<paths>(router);
213+
214+
// GET /pet/{petId}
215+
openApiRouter.get('/pet/{petId}', {
216+
pathValidator: zValidator(
217+
z.object({
218+
petId: z.number() // Validate that petId is a number
219+
})
220+
),
221+
handler: (c) => {
222+
const { petId } = c.req.valid('param'); // Access validated params
223+
return c.json({ name: 'Falko', photoUrls: [] });
224+
}
225+
});
226+
227+
// POST /pet
228+
openApiRouter.post('/pet', {
229+
bodyValidator: zValidator(PetSchema), // Validate request body using PetSchema
230+
handler: (c) => {
231+
const { name, photoUrls } = c.req.valid('json'); // Access validated body data
232+
return c.json({ name, photoUrls });
233+
}
234+
});
235+
```
236+
237+
:::
238+
239+
[Full example](https://github.com/builder-group/community/tree/develop/examples/openapi-router/hono/petstore)
240+
241+
## Express with [`@blgc/openapi-router`](https://github.com/builder-group/community/tree/develop/packages/openapi-router)
242+
243+
[`@blgc/openapi-router`](https://github.com/builder-group/community/tree/develop/packages/openapi-router) wraps around the [Express router](https://expressjs.com/en/5x/api.html#router) to deliver full typesafety and enforce your OpenAPI-Schema with validators.
244+
245+
::: tip Good To Know
246+
247+
While TypeScript types ensure compile-time safety, they don't enforce runtime schema validation. For runtime compliance, you need to integrate with validation libraries like Zod or Valibot. Although you must define the validation rules manually, they are type-safe to ensure these rules are correctly defined.
248+
249+
:::
250+
251+
::: code-group
252+
253+
```ts [src/router.ts]
254+
import { createExpressOpenApiRouter } from '@blgc/openapi-router';
255+
import { Router } from 'express';
256+
import * as v from 'valibot';
257+
import { vValidator } from 'validation-adapters/valibot';
258+
259+
import { paths } from './gen/v1'; // OpenAPI-generated types
260+
import { PetSchema } from './schemas'; // Custom reusable Zod schema for validation
261+
262+
export const router: Router = Router();
263+
export const openApiRouter = createExpressOpenApiRouter<paths>(router);
264+
265+
// GET /pet/{petId}
266+
openApiRouter.get('/pet/{petId}', {
267+
pathValidator: vValidator(
268+
v.object({
269+
petId: v.number() // Validate that petId is a number
270+
})
271+
),
272+
handler: (req, res) => {
273+
const { petId } = req.params; // Access validated params
274+
res.send({ name: 'Falko', photoUrls: [] });
275+
}
276+
});
277+
278+
// POST /pet
279+
openApiRouter.post('/pet', {
280+
bodyValidator: vValidator(PetSchema), // Validate request body using PetSchema
281+
handler: (req, res) => {
282+
const { name, photoUrls } = req.body; // Access validated body data
283+
res.send({ name, photoUrls });
284+
}
285+
});
286+
```
287+
288+
:::
289+
290+
[Full example](https://github.com/builder-group/community/tree/develop/examples/openapi-router/express/petstore)
291+
63292
## Mock-Service-Worker (MSW)
64293

65294
If you are using [Mock Service Worker (MSW)](https://mswjs.io) to define your API mocks, you can use a **small, automatically-typed wrapper** around MSW, which enables you to address conflicts in your API mocks easily when your OpenAPI specification changes. Ultimately, you can have the same level of confidence in your application's API client **and** API mocks.

docs/openapi-fetch/index.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@ title: openapi-fetch
44

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

7-
openapi-fetch is a type-safe fetch client that pulls in your OpenAPI schema. Weighs **5 kb** and has virtually zero runtime. Works with React, Vue, Svelte, or vanilla JS.
7+
openapi-fetch is a type-safe fetch client that pulls in your OpenAPI schema. Weighs **6 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 | `5 kB` | `300k` ops/s (fastest) |
12-
| openapi-typescript-fetch | `4 kB` | `150k` ops/s (2× slower) |
11+
| openapi-fetch | `6 kB` | `300k` ops/s (fastest) |
12+
| openapi-typescript-fetch | `3 kB` | `300k` ops/s (fastest) |
13+
| feature-fetch | `15 kB` | `300k` ops/s (fastest) |
1314
| axios | `32 kB` | `225k` ops/s (1.3× slower) |
1415
| superagent | `55 kB` | `50k` ops/s (6× slower) |
1516
| openapi-typescript-codegen | `367 kB` | `100k` ops/s (3× slower) |
1617

1718
_\* [Benchmarks are approximate](https://github.com/openapi-ts/openapi-typescript/blob/main/packages/openapi-fetch/test/index.bench.js) to just show rough baseline and will differ among machines and browsers. The relative performance between libraries is more reliable._
1819

19-
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.
20+
The syntax is inspired by popular libraries like react-query or Apollo client, but without all the bells and whistles and in a 6 kb package.
2021

2122
::: code-group
2223

@@ -55,7 +56,7 @@ Notice there are no generics, and no manual typing. Your endpoint’s request an
5556
- ✅ No manual typing of your API
5657
- ✅ Eliminates `any` types that hide bugs
5758
- ✅ Also eliminates `as` type overrides that can also hide bugs
58-
- ✅ All of this in a **5 kb** client package 🎉
59+
- ✅ All of this in a **6 kb** client package 🎉
5960

6061
## Setup
6162

@@ -177,7 +178,9 @@ If you prefer selecting the path as a property, you can create a path based clie
177178
import { createPathBasedClient } from "openapi-fetch";
178179
import type { paths } from "./my-openapi-3-schema"; // generated by openapi-typescript
179180

180-
const client = createPathBasedClient<paths>({ baseUrl: "https://myapi.dev/v1" });
181+
const client = createPathBasedClient<paths>({
182+
baseUrl: "https://myapi.dev/v1",
183+
});
181184

182185
client["/blogposts/{post_id}"].GET({
183186
params: { post_id: "my-post" },

docs/zh/openapi-fetch/index.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ title: openapi-fetch
44

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

7-
`openapi-fetch`是一个类型安全的`fetch`客户端,用于拉取您的OpenAPI模式。大小为**5 kb**,几乎没有运行时。适用于React、Vue、Svelte或纯JS。
7+
`openapi-fetch`是一个类型安全的`fetch`客户端,用于拉取您的OpenAPI模式。大小为**6 kb**,几乎没有运行时。适用于React、Vue、Svelte或纯JS。
88

99
|| 大小(最小) | “GET” 请求 |
1010
| :------------------------- | -----------: | :-------------------------- |
11-
| openapi-fetch | `5 kB` | `278k` 操作/秒(最快) |
12-
| openapi-typescript-fetch | `4 kB` | `130k` 操作/秒(2.1× 较慢) |
13-
| axios | `32 kB` | `217k` 操作/秒(1.3× 较慢) |
14-
| superagent | `55 kB` | `63k` 操作/秒(4.4× 较慢) |
15-
| openapi-typescript-codegen | `367 kB` | `106k` 操作/秒(2.6× 较慢) |
11+
| openapi-fetch | `6 kB` | `300k` 操作/秒(最快) |
12+
| openapi-typescript-fetch | `3 kB` | `300k` 操作/秒(最快) |
13+
| feature-fetch | `15 kB` | `300k` ops/s (fastest) |
14+
| axios | `32 kB` | `225k` 操作/秒(1.3× 较慢) |
15+
| superagent | `55 kB` | `50k` 操作/秒(6× 较慢) |
16+
| openapi-typescript-codegen | `367 kB` | `100k` 操作/秒(3× 较慢) |
1617

1718
语法灵感来自流行的库,如`react-query``Apollo client`,但没有所有这些功能,并且包大小仅为5 kb。
1819

@@ -53,7 +54,7 @@ await client.PUT("/blogposts", {
5354
- ✅ 无需手动输入API
5455
- ✅ 消除隐藏错误的 `any` 类型
5556
- ✅ 还消除了可能隐藏错误的 `as` 类型覆盖
56-
- ✅ 所有这些都在一个 **5 kb** 的客户端包中 🎉
57+
- ✅ 所有这些都在一个 **6 kb** 的客户端包中 🎉
5758

5859
## 安装
5960

packages/openapi-fetch/CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# openapi-fetch
22

3+
## 0.11.1
4+
5+
### Patch Changes
6+
7+
- [#1831](https://github.com/openapi-ts/openapi-typescript/pull/1831) [`091e71a`](https://github.com/openapi-ts/openapi-typescript/commit/091e71ad4bf805be32261a53524f320c2fa42690) Thanks [@SebastienGllmt](https://github.com/SebastienGllmt)! - Add MethodResponse utility type to easily get the return type of an endpoint on a client
8+
9+
- [#1833](https://github.com/openapi-ts/openapi-typescript/pull/1833) [`cec023d`](https://github.com/openapi-ts/openapi-typescript/commit/cec023d3461c79ca355a88366949d0f6382e4e2a) Thanks [@ngraef](https://github.com/ngraef)! - Fix identification of required properties when `strictNullChecks` is disabled
10+
11+
- Updated dependencies [[`cec023d`](https://github.com/openapi-ts/openapi-typescript/commit/cec023d3461c79ca355a88366949d0f6382e4e2a)]:
12+
13+
314
## 0.11.0
415

516
### Minor Changes

0 commit comments

Comments
 (0)