h3 1.10.1 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -333
- package/dist/index.cjs +391 -46
- package/dist/index.d.cts +456 -44
- package/dist/index.d.mts +456 -44
- package/dist/index.d.ts +456 -44
- package/dist/index.mjs +389 -48
- package/package.json +15 -13
package/README.md
CHANGED
|
@@ -1,354 +1,48 @@
|
|
|
1
1
|
# H3
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
|
-
[![bundle][bundle-src]][bundle-href]
|
|
6
|
-
[![Codecov][codecov-src]][codecov-href]
|
|
7
|
-
[![License][license-src]][license-href]
|
|
8
|
-
[![JSDocs][jsdocs-src]][jsdocs-href]
|
|
3
|
+
<!-- automd:badges -->
|
|
9
4
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
👉 [Online Playground](https://stackblitz.com/github/unjs/h3/tree/main/playground)
|
|
13
|
-
|
|
14
|
-
👉 [Online Examples Playground](https://stackblitz.com/github/unjs/h3/tree/main/examples)
|
|
15
|
-
|
|
16
|
-
## Features
|
|
17
|
-
|
|
18
|
-
✔️ **Portable:** Works perfectly in Serverless, Workers, and Node.js
|
|
19
|
-
|
|
20
|
-
✔️ **Minimal:** Small and tree-shakable
|
|
21
|
-
|
|
22
|
-
✔️ **Modern:** Native promise support
|
|
23
|
-
|
|
24
|
-
✔️ **Extendable:** Ships with a set of composable utilities but can be extended
|
|
25
|
-
|
|
26
|
-
✔️ **Router:** Super fast route matching using [unjs/radix3](https://github.com/unjs/radix3)
|
|
5
|
+
[](https://npmjs.com/package/h3)
|
|
6
|
+
[](https://npmjs.com/package/h3)
|
|
27
7
|
|
|
28
|
-
|
|
8
|
+
<!-- /automd -->
|
|
29
9
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
# Using npm
|
|
34
|
-
npm install h3
|
|
10
|
+
H3 (pronounced as /eɪtʃθriː/, like h-3) is a minimal h(ttp) framework built for high performance and portability.
|
|
35
11
|
|
|
36
|
-
|
|
37
|
-
yarn add h3
|
|
12
|
+
👉 [Documentation](https://h3.unjs.io)
|
|
38
13
|
|
|
39
|
-
|
|
40
|
-
pnpm add h3
|
|
41
|
-
```
|
|
14
|
+
## Contribution
|
|
42
15
|
|
|
43
16
|
<details>
|
|
44
|
-
<summary>
|
|
45
|
-
|
|
46
|
-
If you are directly using `h3` as a dependency:
|
|
47
|
-
|
|
48
|
-
```json
|
|
49
|
-
{
|
|
50
|
-
"dependencies": {
|
|
51
|
-
"h3": "npm:h3-nightly@latest"
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
If you are using a framework ([Nuxt](https://nuxt.com/) or [Nitro](https://nitro.unjs.io/)) that is using `h3`:
|
|
57
|
-
|
|
58
|
-
pnpm and yarn:
|
|
59
|
-
|
|
60
|
-
```json
|
|
61
|
-
{
|
|
62
|
-
"resolutions": {
|
|
63
|
-
"h3": "npm:h3-nightly@latest"
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
npm:
|
|
69
|
-
|
|
70
|
-
```json
|
|
71
|
-
{
|
|
72
|
-
"overrides": {
|
|
73
|
-
"h3": "npm:h3-nightly@latest"
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
```
|
|
17
|
+
<summary>Local development</summary>
|
|
77
18
|
|
|
78
|
-
|
|
19
|
+
- Clone this repository
|
|
20
|
+
- Install the latest LTS version of [Node.js](https://nodejs.org/en/)
|
|
21
|
+
- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`
|
|
22
|
+
- Install dependencies using `pnpm install`
|
|
23
|
+
- Run tests using `pnpm dev` or `pnpm test`
|
|
79
24
|
|
|
80
25
|
</details>
|
|
81
26
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
```ts
|
|
85
|
-
import { createServer } from "node:http";
|
|
86
|
-
import { createApp, eventHandler, toNodeListener } from "h3";
|
|
87
|
-
|
|
88
|
-
const app = createApp();
|
|
89
|
-
app.use(
|
|
90
|
-
"/",
|
|
91
|
-
eventHandler(() => "Hello world!"),
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
createServer(toNodeListener(app)).listen(process.env.PORT || 3000);
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Example using <a href="https://github.com/unjs/listhen">listhen</a> for an elegant listener:
|
|
98
|
-
|
|
99
|
-
```ts
|
|
100
|
-
import { createApp, eventHandler, toNodeListener } from "h3";
|
|
101
|
-
import { listen } from "listhen";
|
|
102
|
-
|
|
103
|
-
const app = createApp();
|
|
104
|
-
app.use(
|
|
105
|
-
"/",
|
|
106
|
-
eventHandler(() => "Hello world!"),
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
listen(toNodeListener(app));
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
## Router
|
|
113
|
-
|
|
114
|
-
The `app` instance created by `h3` uses a middleware stack (see [how it works](./src/app.ts)) with the ability to match route prefix and apply matched middleware.
|
|
115
|
-
|
|
116
|
-
To opt-in using a more advanced and convenient routing system, we can create a router instance and register it to app instance.
|
|
117
|
-
|
|
118
|
-
```ts
|
|
119
|
-
import { createApp, eventHandler, createRouter } from "h3";
|
|
120
|
-
|
|
121
|
-
const app = createApp();
|
|
122
|
-
|
|
123
|
-
const router = createRouter()
|
|
124
|
-
.get(
|
|
125
|
-
"/",
|
|
126
|
-
eventHandler(() => "Hello World!"),
|
|
127
|
-
)
|
|
128
|
-
.get(
|
|
129
|
-
"/hello/:name",
|
|
130
|
-
eventHandler((event) => `Hello ${event.context.params.name}!`),
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
app.use(router);
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
**Tip:** We can register the same route more than once with different methods.
|
|
137
|
-
|
|
138
|
-
Routes are internally stored in a [Radix Tree](https://en.wikipedia.org/wiki/Radix_tree) and matched using [unjs/radix3](https://github.com/unjs/radix3).
|
|
139
|
-
|
|
140
|
-
For using nested routers, see [this example](./examples/nested-router.ts)
|
|
141
|
-
|
|
142
|
-
## More app usage examples
|
|
27
|
+
<!-- /automd -->
|
|
143
28
|
|
|
144
|
-
|
|
145
|
-
// Handle can directly return object or Promise<object> for JSON response
|
|
146
|
-
app.use(
|
|
147
|
-
"/api",
|
|
148
|
-
eventHandler((event) => ({ url: event.node.req.url })),
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
// We can have better matching other than quick prefix match
|
|
152
|
-
app.use(
|
|
153
|
-
"/odd",
|
|
154
|
-
eventHandler(() => "Is odd!"),
|
|
155
|
-
{ match: (url) => url.substr(1) % 2 },
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
// Handle can directly return string for HTML response
|
|
159
|
-
app.use(eventHandler(() => "<h1>Hello world!</h1>"));
|
|
160
|
-
|
|
161
|
-
// We can chain calls to .use()
|
|
162
|
-
app
|
|
163
|
-
.use(
|
|
164
|
-
"/1",
|
|
165
|
-
eventHandler(() => "<h1>Hello world!</h1>"),
|
|
166
|
-
)
|
|
167
|
-
.use(
|
|
168
|
-
"/2",
|
|
169
|
-
eventHandler(() => "<h1>Goodbye!</h1>"),
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
// We can proxy requests and rewrite cookie's domain and path
|
|
173
|
-
app.use(
|
|
174
|
-
"/api",
|
|
175
|
-
eventHandler((event) =>
|
|
176
|
-
proxyRequest(event, "https://example.com", {
|
|
177
|
-
// f.e. keep one domain unchanged, rewrite one domain and remove other domains
|
|
178
|
-
cookieDomainRewrite: {
|
|
179
|
-
"example.com": "example.com",
|
|
180
|
-
"example.com": "somecompany.co.uk",
|
|
181
|
-
"*": "",
|
|
182
|
-
},
|
|
183
|
-
cookiePathRewrite: {
|
|
184
|
-
"/": "/api",
|
|
185
|
-
},
|
|
186
|
-
}),
|
|
187
|
-
),
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
// Legacy middleware with 3rd argument are automatically promisified
|
|
191
|
-
app.use(
|
|
192
|
-
fromNodeMiddleware((req, res, next) => {
|
|
193
|
-
req.setHeader("x-foo", "bar");
|
|
194
|
-
next();
|
|
195
|
-
}),
|
|
196
|
-
);
|
|
197
|
-
|
|
198
|
-
// Lazy loaded routes using { lazy: true }
|
|
199
|
-
app.use("/big", () => import("./big-handler"), { lazy: true });
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
## Utilities
|
|
203
|
-
|
|
204
|
-
H3 has a concept of composable utilities that accept `event` (from `eventHandler((event) => {})`) as their first argument. This has several performance benefits over injecting them to `event` or `app` instances in global middleware commonly used in Node.js frameworks, such as Express. This concept means only required code is evaluated and bundled, and the rest of the utilities can be tree-shaken when not used.
|
|
205
|
-
|
|
206
|
-
👉 You can check list of exported built-in utils from [JSDocs Documentation](https://www.jsdocs.io/package/h3#package-functions).
|
|
207
|
-
|
|
208
|
-
#### Body
|
|
209
|
-
|
|
210
|
-
- `readRawBody(event, encoding?)`
|
|
211
|
-
- `readBody(event)`
|
|
212
|
-
- `readValidatedBody(event, validate)`
|
|
213
|
-
- `readMultipartFormData(event)`
|
|
214
|
-
|
|
215
|
-
#### Request
|
|
216
|
-
|
|
217
|
-
- `getQuery(event)`
|
|
218
|
-
- `getValidatedQuery(event, validate)`
|
|
219
|
-
- `getRouterParams(event, { decode? })`
|
|
220
|
-
- `getRouterParam(event, name, { decode? })`
|
|
221
|
-
- `getValidatedRouterParams(event, validate, { decode? })`
|
|
222
|
-
- `getMethod(event, default?)`
|
|
223
|
-
- `isMethod(event, expected, allowHead?)`
|
|
224
|
-
- `assertMethod(event, expected, allowHead?)`
|
|
225
|
-
- `getRequestHeaders(event)` (alias: `getHeaders`)
|
|
226
|
-
- `getRequestHeader(event, name)` (alias: `getHeader`)
|
|
227
|
-
- `getRequestURL(event)`
|
|
228
|
-
- `getRequestHost(event)`
|
|
229
|
-
- `getRequestProtocol(event)`
|
|
230
|
-
- `getRequestPath(event)`
|
|
231
|
-
- `getRequestIP(event, { xForwardedFor: boolean })`
|
|
232
|
-
|
|
233
|
-
#### Response
|
|
234
|
-
|
|
235
|
-
- `send(event, data, type?)`
|
|
236
|
-
- `sendNoContent(event, code = 204)`
|
|
237
|
-
- `setResponseStatus(event, status)`
|
|
238
|
-
- `getResponseStatus(event)`
|
|
239
|
-
- `getResponseStatusText(event)`
|
|
240
|
-
- `getResponseHeaders(event)`
|
|
241
|
-
- `getResponseHeader(event, name)`
|
|
242
|
-
- `setResponseHeaders(event, headers)` (alias: `setHeaders`)
|
|
243
|
-
- `setResponseHeader(event, name, value)` (alias: `setHeader`)
|
|
244
|
-
- `appendResponseHeaders(event, headers)` (alias: `appendHeaders`)
|
|
245
|
-
- `appendResponseHeader(event, name, value)` (alias: `appendHeader`)
|
|
246
|
-
- `defaultContentType(event, type)`
|
|
247
|
-
- `sendRedirect(event, location, code=302)`
|
|
248
|
-
- `isStream(data)`
|
|
249
|
-
- `sendStream(event, data)`
|
|
250
|
-
- `writeEarlyHints(event, links, callback)`
|
|
251
|
-
|
|
252
|
-
#### Sanitize
|
|
253
|
-
|
|
254
|
-
- `sanitizeStatusMessage(statusMessage)`
|
|
255
|
-
- `sanitizeStatusCode(statusCode, default = 200)`
|
|
256
|
-
|
|
257
|
-
#### Error
|
|
258
|
-
|
|
259
|
-
- `sendError(event, error, debug?)`
|
|
260
|
-
- `createError({ statusCode, statusMessage, data? })`
|
|
261
|
-
|
|
262
|
-
#### Route
|
|
263
|
-
|
|
264
|
-
- `useBase(base, handler)`
|
|
265
|
-
|
|
266
|
-
#### Proxy
|
|
267
|
-
|
|
268
|
-
- `sendProxy(event, { target, ...options })`
|
|
269
|
-
- `proxyRequest(event, { target, ...options })`
|
|
270
|
-
- `fetchWithEvent(event, req, init, { fetch? }?)`
|
|
271
|
-
- `getProxyRequestHeaders(event)`
|
|
272
|
-
|
|
273
|
-
#### Cookie
|
|
274
|
-
|
|
275
|
-
- `parseCookies(event)`
|
|
276
|
-
- `getCookie(event, name)`
|
|
277
|
-
- `setCookie(event, name, value, opts?)`
|
|
278
|
-
- `deleteCookie(event, name, opts?)`
|
|
279
|
-
- `splitCookiesString(cookiesString)`
|
|
280
|
-
|
|
281
|
-
#### Session
|
|
282
|
-
|
|
283
|
-
- `useSession(event, config = { password, maxAge?, name?, cookie?, seal?, crypto? })`
|
|
284
|
-
- `getSession(event, config)`
|
|
285
|
-
- `updateSession(event, config, update)`
|
|
286
|
-
- `sealSession(event, config)`
|
|
287
|
-
- `unsealSession(event, config, sealed)`
|
|
288
|
-
- `clearSession(event, config)`
|
|
289
|
-
|
|
290
|
-
#### Cache
|
|
291
|
-
|
|
292
|
-
- `handleCacheHeaders(event, opts)`
|
|
293
|
-
|
|
294
|
-
#### Cors
|
|
295
|
-
|
|
296
|
-
- `handleCors(options)` (see [h3-cors](https://github.com/NozomuIkuta/h3-cors) for more detail about options)
|
|
297
|
-
- `isPreflightRequest(event)`
|
|
298
|
-
- `isCorsOriginAllowed(event)`
|
|
299
|
-
- `appendCorsHeaders(event, options)` (see [h3-cors](https://github.com/NozomuIkuta/h3-cors) for more detail about options)
|
|
300
|
-
- `appendCorsPreflightHeaders(event, options)` (see [h3-cors](https://github.com/NozomuIkuta/h3-cors) for more detail about options)
|
|
301
|
-
|
|
302
|
-
## Community Packages
|
|
303
|
-
|
|
304
|
-
You can use more H3 event utilities made by the community.
|
|
29
|
+
## License
|
|
305
30
|
|
|
306
|
-
|
|
31
|
+
<!-- automd:contributors license=MIT author="pi0" -->
|
|
307
32
|
|
|
308
|
-
|
|
33
|
+
Published under the [MIT](https://github.com/unjs/h3/blob/main/LICENSE) license.
|
|
34
|
+
Made by [@pi0](https://github.com/pi0) and [community](https://github.com/unjs/h3/graphs/contributors) 💛
|
|
35
|
+
<br><br>
|
|
36
|
+
<a href="https://github.com/unjs/h3/graphs/contributors">
|
|
37
|
+
<img src="https://contrib.rocks/image?repo=unjs/h3" />
|
|
38
|
+
</a>
|
|
309
39
|
|
|
310
|
-
|
|
311
|
-
- `validateBody(event, schema)`
|
|
312
|
-
- `validateQuery(event, schema)`
|
|
313
|
-
- [h3-zod](https://github.com/wobsoriano/h3-zod)
|
|
314
|
-
- `useValidatedBody(event, schema)`
|
|
315
|
-
- `useValidatedQuery(event, schema)`
|
|
316
|
-
- [h3-valibot](https://github.com/intevel/h3-valibot)
|
|
317
|
-
- `useValidateBody(event, schema)`
|
|
318
|
-
- `useValidateParams(event, schema)`
|
|
319
|
-
- [h3-compression](https://github.com/CodeDredd/h3-compression)
|
|
320
|
-
- `useGZipCompression(event, response)`
|
|
321
|
-
- `useDeflateCompression(event, response)`
|
|
322
|
-
- `useBrotliCompression(event, response)`
|
|
323
|
-
- `useCompression(event, response)`
|
|
324
|
-
- `useGZipCompressionStream(event, response)`
|
|
325
|
-
- `useDeflateCompressionStream(event, response)`
|
|
326
|
-
- `useCompressionStream(event, response)`
|
|
327
|
-
- [@intlify/h3](https://github.com/intlify/h3)
|
|
328
|
-
- `defineI18nMiddleware(options)`
|
|
329
|
-
- `useTranslation(event)`
|
|
330
|
-
- `getHeaderLocale(event, options)`
|
|
331
|
-
- `getHeaderLocales(event, options)`
|
|
332
|
-
- `getCookieLocale(event, options)`
|
|
333
|
-
- `setCookieLocale(event, options)`
|
|
334
|
-
- `getPathLocale(event, options)`
|
|
335
|
-
- `getQueryLocale(event, options)`
|
|
40
|
+
<!-- /automd -->
|
|
336
41
|
|
|
337
|
-
|
|
42
|
+
<!-- automd:with-automd -->
|
|
338
43
|
|
|
339
|
-
|
|
44
|
+
---
|
|
340
45
|
|
|
341
|
-
|
|
46
|
+
_🤖 auto updated with [automd](https://automd.unjs.io)_
|
|
342
47
|
|
|
343
|
-
|
|
344
|
-
[npm-version-href]: https://npmjs.com/package/h3
|
|
345
|
-
[npm-downloads-src]: https://img.shields.io/npm/dm/h3?style=flat&colorA=18181B&colorB=F0DB4F
|
|
346
|
-
[npm-downloads-href]: https://npmjs.com/package/h3
|
|
347
|
-
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/h3/main?style=flat&colorA=18181B&colorB=F0DB4F
|
|
348
|
-
[codecov-href]: https://codecov.io/gh/unjs/h3
|
|
349
|
-
[bundle-src]: https://img.shields.io/bundlephobia/minzip/h3?style=flat&colorA=18181B&colorB=F0DB4F
|
|
350
|
-
[bundle-href]: https://bundlephobia.com/result?p=h3
|
|
351
|
-
[license-src]: https://img.shields.io/github/license/unjs/h3.svg?style=flat&colorA=18181B&colorB=F0DB4F
|
|
352
|
-
[license-href]: https://github.com/unjs/h3/blob/main/LICENSE
|
|
353
|
-
[jsdocs-src]: https://img.shields.io/badge/jsDocs.io-reference-18181B?style=flat&colorA=18181B&colorB=F0DB4F
|
|
354
|
-
[jsdocs-href]: https://www.jsdocs.io/package/h3
|
|
48
|
+
<!-- /automd -->
|