h3 2.0.1-rc.2 → 2.0.1-rc.21

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.
Files changed (51) hide show
  1. package/bin/h3.mjs +35 -0
  2. package/dist/THIRD-PARTY-LICENSES.md +70 -0
  3. package/dist/_entries/bun.d.mts +3 -8
  4. package/dist/_entries/bun.mjs +3 -9
  5. package/dist/_entries/cloudflare.d.mts +4 -9
  6. package/dist/_entries/cloudflare.mjs +3 -9
  7. package/dist/_entries/deno.d.mts +3 -8
  8. package/dist/_entries/deno.mjs +3 -9
  9. package/dist/_entries/generic.d.mts +3 -8
  10. package/dist/_entries/generic.mjs +3 -9
  11. package/dist/_entries/node.d.mts +3 -8
  12. package/dist/_entries/node.mjs +3 -12
  13. package/dist/_entries/service-worker.d.mts +3 -8
  14. package/dist/_entries/service-worker.mjs +3 -9
  15. package/dist/docs/0.guide/0.index/index.md +117 -0
  16. package/dist/docs/0.guide/1.basics/0.lifecycle.md +68 -0
  17. package/dist/docs/0.guide/1.basics/1.routing.md +92 -0
  18. package/dist/docs/0.guide/1.basics/2.middleware.md +97 -0
  19. package/dist/docs/0.guide/1.basics/3.handler.md +165 -0
  20. package/dist/docs/0.guide/1.basics/4.response.md +162 -0
  21. package/dist/docs/0.guide/1.basics/5.error.md +117 -0
  22. package/dist/docs/0.guide/1.basics/6.nested-apps.md +57 -0
  23. package/dist/docs/0.guide/2.api/0.h3.md +145 -0
  24. package/dist/docs/0.guide/2.api/1.h3event.md +113 -0
  25. package/dist/docs/0.guide/3.advanced/0.plugins.md +50 -0
  26. package/dist/docs/0.guide/3.advanced/1.websocket.md +124 -0
  27. package/dist/docs/0.guide/3.advanced/2.nightly.md +13 -0
  28. package/dist/docs/1.utils/0.index/index.md +46 -0
  29. package/dist/docs/1.utils/1.request.md +355 -0
  30. package/dist/docs/1.utils/2.response.md +144 -0
  31. package/dist/docs/1.utils/3.cookie.md +33 -0
  32. package/dist/docs/1.utils/4.security.md +109 -0
  33. package/dist/docs/1.utils/5.proxy.md +31 -0
  34. package/dist/docs/1.utils/6.mcp.md +71 -0
  35. package/dist/docs/1.utils/7.more.md +78 -0
  36. package/dist/docs/1.utils/8.community.md +42 -0
  37. package/dist/docs/2.examples/0.index/index.md +16 -0
  38. package/dist/docs/2.examples/1.handle-cookie.md +67 -0
  39. package/dist/docs/2.examples/2.handle-session.md +130 -0
  40. package/dist/docs/2.examples/3.serve-static-assets.md +66 -0
  41. package/dist/docs/2.examples/4.stream-response.md +76 -0
  42. package/dist/docs/2.examples/5.validate-data.md +193 -0
  43. package/dist/docs/3.migration/0.index/index.md +200 -0
  44. package/dist/docs/README.md +35 -0
  45. package/dist/{h3.mjs → h3-CRCltuUf.mjs} +915 -1218
  46. package/dist/h3-D76FUMrE.d.mts +833 -0
  47. package/dist/h3-DagAgogP.mjs +4 -0
  48. package/dist/{h3.d.mts → h3-DiSMXP1G.d.mts} +320 -656
  49. package/dist/tracing.d.mts +24 -0
  50. package/dist/tracing.mjs +76 -0
  51. package/package.json +56 -44
@@ -0,0 +1,144 @@
1
+ # Response
2
+
3
+ > H3 response utilities.
4
+
5
+ ## Event Stream
6
+
7
+ ### `createEventStream(event, opts?)`
8
+
9
+ Initialize an EventStream instance for creating [server sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events)
10
+
11
+ **Example:**
12
+
13
+ ```ts
14
+ import { createEventStream, sendEventStream } from "h3";
15
+
16
+ app.get("/sse", (event) => {
17
+ const eventStream = createEventStream(event);
18
+
19
+ // Send a message every second
20
+ const interval = setInterval(async () => {
21
+ await eventStream.push("Hello world");
22
+ }, 1000);
23
+
24
+ // cleanup the interval and close the stream when the connection is terminated
25
+ eventStream.onClosed(async () => {
26
+ console.log("closing SSE...");
27
+ clearInterval(interval);
28
+ await eventStream.close();
29
+ });
30
+
31
+ return eventStream.send();
32
+ });
33
+ ```
34
+
35
+ ## Sanitize
36
+
37
+ ### `sanitizeStatusCode(statusCode?, defaultStatusCode)`
38
+
39
+ Make sure the status code is a valid HTTP status code.
40
+
41
+ ### `sanitizeStatusMessage(statusMessage)`
42
+
43
+ Make sure the status message is safe to use in a response.
44
+
45
+ Allowed characters: horizontal tabs, spaces or visible ascii characters: [https://www.rfc-editor.org/rfc/rfc7230#section-3.1.2](https://www.rfc-editor.org/rfc/rfc7230#section-3.1.2)
46
+
47
+ ## Serve Static
48
+
49
+ ### `serveStatic(event, options)`
50
+
51
+ Dynamically serve static assets based on the request path.
52
+
53
+ ## More Response Utils
54
+
55
+ ### `html(first)`
56
+
57
+ ### `iterable(iterable)`
58
+
59
+ Iterate a source of chunks and send back each chunk in order. Supports mixing async work together with emitting chunks.
60
+
61
+ Each chunk must be a string or a buffer.
62
+
63
+ For generator (yielding) functions, the returned value is treated the same as yielded values.
64
+
65
+ **Example:**
66
+
67
+ ```ts
68
+ return iterable(async function* work() {
69
+ // Open document body
70
+ yield "<!DOCTYPE html>\n<html><body><h1>Executing...</h1><ol>\n";
71
+ // Do work ...
72
+ for (let i = 0; i < 1000; i++) {
73
+ await delay(1000);
74
+ // Report progress
75
+ yield `<li>Completed job #`;
76
+ yield i;
77
+ yield `</li>\n`;
78
+ }
79
+ // Close out the report
80
+ return `</ol></body></html>`;
81
+ });
82
+ async function delay(ms) {
83
+ return new Promise((resolve) => setTimeout(resolve, ms));
84
+ }
85
+ ```
86
+
87
+ ### `noContent(status)`
88
+
89
+ Respond with an empty payload.
90
+
91
+ **Example:**
92
+
93
+ ```ts
94
+ app.get("/", () => noContent());
95
+ ```
96
+
97
+ ### `redirect(location, status, statusText?)`
98
+
99
+ Send a redirect response to the client.
100
+
101
+ It adds the `location` header to the response and sets the status code to 302 by default.
102
+
103
+ In the body, it sends a simple HTML page with a meta refresh tag to redirect the client in case the headers are ignored.
104
+
105
+ **Example:**
106
+
107
+ ```ts
108
+ app.get("/", () => {
109
+ return redirect("https://example.com");
110
+ });
111
+ ```
112
+
113
+ **Example:**
114
+
115
+ ```ts
116
+ app.get("/", () => {
117
+ return redirect("https://example.com", 301); // Permanent redirect
118
+ });
119
+ ```
120
+
121
+ ### `redirectBack(event)`
122
+
123
+ Redirect the client back to the previous page using the `referer` header.
124
+
125
+ If the `referer` header is missing or is a different origin, it falls back to the provided URL (default `"/"`).
126
+
127
+ By default, only the **pathname** of the referer is used (query string and hash are stripped) to prevent spoofed referers from carrying unintended parameters. Set `allowQuery: true` to preserve the query string.
128
+
129
+ **Security:** The `fallback` value MUST be a trusted, hardcoded path — never use user input. Passing user-controlled values (e.g., query params) as `fallback` creates an open redirect vulnerability.
130
+
131
+ **Example:**
132
+
133
+ ```ts
134
+ app.post("/submit", (event) => {
135
+ // process form...
136
+ return redirectBack(event, { fallback: "/form" });
137
+ });
138
+ ```
139
+
140
+ ### `writeEarlyHints(event, hints)`
141
+
142
+ Write `HTTP/1.1 103 Early Hints` to the client.
143
+
144
+ In runtimes that don't support early hints natively, this function falls back to setting response headers which can be used by CDN.
@@ -0,0 +1,33 @@
1
+ # Cookie
2
+
3
+ > H3 cookie utilities.
4
+
5
+ ### `deleteChunkedCookie(event, name, serializeOptions?)`
6
+
7
+ Remove a set of chunked cookies by name.
8
+
9
+ ### `deleteCookie(event, name, serializeOptions?)`
10
+
11
+ Remove a cookie by name.
12
+
13
+ ### `getChunkedCookie(event, name)`
14
+
15
+ Get a chunked cookie value by name. Will join chunks together.
16
+
17
+ ### `getCookie(event, name)`
18
+
19
+ Get a cookie value by name.
20
+
21
+ ### `getValidatedCookies(event, validate, options?: { onError?: OnValidateError })`
22
+
23
+ ### `parseCookies(event)`
24
+
25
+ Parse the request to get HTTP Cookie header string and returning an object of all cookie name-value pairs.
26
+
27
+ ### `setChunkedCookie(event, name, value, options?)`
28
+
29
+ Set a cookie value by name. Chunked cookies will be created as needed.
30
+
31
+ ### `setCookie(event, name, value, options?)`
32
+
33
+ Set a cookie value by name.
@@ -0,0 +1,109 @@
1
+ # Security
2
+
3
+ > H3 security utilities.
4
+
5
+ ## Authentication
6
+
7
+ ### `basicAuth(opts)`
8
+
9
+ Create a basic authentication middleware.
10
+
11
+ **Example:**
12
+
13
+ ```ts
14
+ import { H3, serve, basicAuth } from "h3";
15
+ const auth = basicAuth({ password: "test" });
16
+ app.get("/", (event) => `Hello ${event.context.basicAuth?.username}!`, [auth]);
17
+ serve(app, { port: 3000 });
18
+ ```
19
+
20
+ ### `requireBasicAuth(event, opts)`
21
+
22
+ Apply basic authentication for current request.
23
+
24
+ **Example:**
25
+
26
+ ```ts
27
+ import { defineHandler, requireBasicAuth } from "h3";
28
+ export default defineHandler(async (event) => {
29
+ await requireBasicAuth(event, { password: "test" });
30
+ return `Hello, ${event.context.basicAuth.username}!`;
31
+ });
32
+ ```
33
+
34
+ ## Session
35
+
36
+ ### `clearSession(event, config)`
37
+
38
+ Clear the session data for the current request.
39
+
40
+ ### `getSession(event, config)`
41
+
42
+ Get the session for the current request.
43
+
44
+ ### `sealSession(event, config)`
45
+
46
+ Encrypt and sign the session data for the current request.
47
+
48
+ ### `unsealSession(_event, config, sealed)`
49
+
50
+ Decrypt and verify the session data for the current request.
51
+
52
+ ### `updateSession(event, config, update?)`
53
+
54
+ Update the session data for the current request.
55
+
56
+ ### `useSession(event, config)`
57
+
58
+ Create a session manager for the current request.
59
+
60
+ ## Fingerprint
61
+
62
+ ### `getRequestFingerprint(event, opts)`
63
+
64
+ Get a unique fingerprint for the incoming request.
65
+
66
+ ## CORS
67
+
68
+ ### `appendCorsHeaders(event, options)`
69
+
70
+ Append CORS headers to the response.
71
+
72
+ ### `appendCorsPreflightHeaders(event, options)`
73
+
74
+ Append CORS preflight headers to the response.
75
+
76
+ ### `handleCors(event, options)`
77
+
78
+ Handle CORS for the incoming request.
79
+
80
+ If the incoming request is a CORS preflight request, it will append the CORS preflight headers and send a 204 response.
81
+
82
+ If return value is not `false`, the request is handled and no further action is needed.
83
+
84
+ **Example:**
85
+
86
+ ```ts
87
+ const app = new H3();
88
+ app.all("/", async (event) => {
89
+ const corsRes = handleCors(event, {
90
+ origin: "*",
91
+ preflight: {
92
+ statusCode: 204,
93
+ },
94
+ methods: "*",
95
+ });
96
+ if (corsRes !== false) {
97
+ return corsRes;
98
+ }
99
+ // Your code here
100
+ });
101
+ ```
102
+
103
+ ### `isCorsOriginAllowed(origin, options)`
104
+
105
+ Check if the origin is allowed.
106
+
107
+ ### `isPreflightRequest(event)`
108
+
109
+ Check if the incoming request is a CORS preflight request.
@@ -0,0 +1,31 @@
1
+ # Proxy
2
+
3
+ > H3 proxy utilities.
4
+
5
+ ### `fetchWithEvent(event, url, init?)`
6
+
7
+ Make a fetch request with the event's context and headers.
8
+
9
+ If the `url` starts with `/`, the request is dispatched internally via `event.app.fetch()` (sub-request) and never leaves the process.
10
+
11
+ **Security:** Never pass unsanitized user input as the `url`. Callers are responsible for validating and restricting the URL.
12
+
13
+ ### `getProxyRequestHeaders(event)`
14
+
15
+ Get the request headers object without headers known to cause issues when proxying.
16
+
17
+ ### `proxy(event, target, opts)`
18
+
19
+ Make a proxy request to a target URL and send the response back to the client.
20
+
21
+ If the `target` starts with `/`, the request is dispatched internally via `event.app.fetch()` (sub-request) and never leaves the process. This bypasses any external security layer (reverse proxy auth, IP allowlisting, mTLS).
22
+
23
+ **Security:** Never pass unsanitized user input as the `target`. Callers are responsible for validating and restricting the target URL (e.g. allowlisting hosts, blocking internal paths, enforcing protocol).
24
+
25
+ ### `proxyRequest(event, target, opts)`
26
+
27
+ Proxy the incoming request to a target URL.
28
+
29
+ If the `target` starts with `/`, the request is handled internally by the app router via `event.app.fetch()` instead of making an external HTTP request.
30
+
31
+ **Security:** Never pass unsanitized user input as the `target`. Callers are responsible for validating and restricting the target URL (e.g. allowlisting hosts, blocking internal paths, enforcing protocol). Consider using `bodyLimit()` middleware to prevent large request bodies from consuming excessive resources when proxying untrusted input.
@@ -0,0 +1,71 @@
1
+ # MCP
2
+
3
+ > H3 MCP related utils.
4
+
5
+ ### `defineJsonRpcHandler()`
6
+
7
+ Creates an H3 event handler that implements the JSON-RPC 2.0 specification.
8
+
9
+ **Example:**
10
+
11
+ ```ts
12
+ app.post(
13
+ "/rpc",
14
+ defineJsonRpcHandler({
15
+ methods: {
16
+ echo: ({ params }, event) => {
17
+ return `Received \`${params}\` on path \`${event.url.pathname}\``;
18
+ },
19
+ sum: ({ params }, event) => {
20
+ return params.a + params.b;
21
+ },
22
+ },
23
+ }),
24
+ );
25
+ ```
26
+
27
+ ### `defineJsonRpcWebSocketHandler()`
28
+
29
+ Creates an H3 event handler that implements JSON-RPC 2.0 over WebSocket.
30
+
31
+ This is an opt-in feature that allows JSON-RPC communication over WebSocket connections for bi-directional messaging. Each incoming WebSocket text message is processed as a JSON-RPC request, and responses are sent back to the peer.
32
+
33
+ **Example:**
34
+
35
+ ```ts
36
+ app.get(
37
+ "/rpc/ws",
38
+ defineJsonRpcWebSocketHandler({
39
+ methods: {
40
+ echo: ({ params }) => {
41
+ return `Received: ${Array.isArray(params) ? params[0] : params?.message}`;
42
+ },
43
+ sum: ({ params }) => {
44
+ return params.a + params.b;
45
+ },
46
+ },
47
+ }),
48
+ );
49
+ ```
50
+
51
+ **Example:**
52
+
53
+ ```ts
54
+ // With additional WebSocket hooks
55
+ app.get(
56
+ "/rpc/ws",
57
+ defineJsonRpcWebSocketHandler({
58
+ methods: {
59
+ greet: ({ params }) => `Hello, ${params.name}!`,
60
+ },
61
+ hooks: {
62
+ open(peer) {
63
+ console.log(`Peer connected: ${peer.id}`);
64
+ },
65
+ close(peer, details) {
66
+ console.log(`Peer disconnected: ${peer.id}`, details);
67
+ },
68
+ },
69
+ }),
70
+ );
71
+ ```
@@ -0,0 +1,78 @@
1
+ # More utils
2
+
3
+ > More H3 utilities.
4
+
5
+ ## Base
6
+
7
+ ### `withBase(base, input)`
8
+
9
+ Returns a new event handler that removes the base url of the event before calling the original handler.
10
+
11
+ **Example:**
12
+
13
+ ```ts
14
+ const api = new H3()
15
+ .get("/", () => "Hello API!");
16
+ const app = new H3();
17
+ .use("/api/**", withBase("/api", api.handler));
18
+ ```
19
+
20
+ ## Event
21
+
22
+ ### `getEventContext(event)`
23
+
24
+ Gets the context of the event, if it does not exists, initializes a new context on `req.context`.
25
+
26
+ ### `isEvent(input)`
27
+
28
+ Checks if the input is an H3Event object.
29
+
30
+ ### `isHTTPEvent(input)`
31
+
32
+ Checks if the input is an object with `{ req: Request }` signature.
33
+
34
+ ### `mockEvent(_request, options?)`
35
+
36
+ ## Middleware
37
+
38
+ ### `bodyLimit(limit)`
39
+
40
+ Define a middleware that checks whether request body size is within specified limit.
41
+
42
+ If body size exceeds the limit, throws a `413` Request Entity Too Large response error. If you need custom handling for this case, use `assertBodySize` instead.
43
+
44
+ ### `onError(hook)`
45
+
46
+ Define a middleware that runs when an error occurs.
47
+
48
+ You can return a new Response from the handler to gracefully handle the error.
49
+
50
+ ### `onRequest(hook)`
51
+
52
+ Define a middleware that runs on each request.
53
+
54
+ ### `onResponse(hook)`
55
+
56
+ Define a middleware that runs after Response is generated.
57
+
58
+ You can return a new Response from the handler to replace the original response.
59
+
60
+ ## WebSocket
61
+
62
+ ### `defineWebSocket(hooks)`
63
+
64
+ Define WebSocket hooks.
65
+
66
+ ### `defineWebSocketHandler()`
67
+
68
+ Define WebSocket event handler.
69
+
70
+ ## Adapters
71
+
72
+ ### `defineNodeHandler(handler)`
73
+
74
+ ### `defineNodeMiddleware(handler)`
75
+
76
+ ### `fromNodeHandler(handler)`
77
+
78
+ ### `fromWebHandler(handler)`
@@ -0,0 +1,42 @@
1
+ # Community
2
+
3
+ > H3 utils from community.
4
+
5
+ You can use external H3 event utilities made by the community.
6
+
7
+ This section is placeholder for any new H3 version 2 compatible community library.
8
+
9
+
10
+
11
+ > [!TIP]
12
+ > 💛 PR is more than welcome to list yours.
13
+
14
+ ## `apitally`
15
+
16
+ [Apitally](https://apitally.io/h3) is a simple API monitoring, analytics, and request logging tool with a plugin for H3. See setup guide [here](https://docs.apitally.io/frameworks/h3).
17
+
18
+ <read-more></read-more>
19
+
20
+ ## `H3ravel Framework`
21
+
22
+ [H3ravel Framework](https://h3ravel.toneflix.net) is a modern TypeScript runtime-agnostic web framework built on top of H3, designed to bring the elegance and developer experience of Laravel PHP to the JavaScript ecosystem. See the getting started guide [here](https://h3ravel.toneflix.net/guide/get-started).
23
+
24
+ <read-more></read-more>
25
+
26
+ ## `Intlify`
27
+
28
+ [Intlify](https://intlify.dev/) is a project that aims to improve Developer Experience in software internationalization. That project provides server-side frameworks, middleware, and utilities. About those, see the [here](https://github.com/intlify/srvmid)
29
+
30
+ <read-more></read-more>
31
+
32
+ ## `Clear Router`
33
+
34
+ Laravel-style routing system for H3 and Express.js. Clean route definitions, middleware support, and controller bindings with full TypeScript support.
35
+
36
+ <read-more></read-more>
37
+
38
+ ## `unjwt`
39
+
40
+ `unjwt` is a collection of low-level JWT utilities (JWS, JWE, JWK) built on the Web Crypto API, with zero runtime dependencies. It includes a dedicated H3 v2 adapter for header and cookie-based session management with support for encrypted (JWE) and signed (JWS) tokens.
41
+
42
+ <read-more></read-more>
@@ -0,0 +1,16 @@
1
+ # Examples
2
+
3
+ > Common examples for h3.
4
+
5
+ <read-more>
6
+
7
+ Check [`examples/` dir](https://github.com/h3js/h3/tree/main/examples) for more examples.
8
+ </read-more>
9
+
10
+ **Examples:**
11
+
12
+ - [Cookies](/examples/handle-cookie)
13
+ - [Session](/examples/handle-session)
14
+ - [Static Assets](/examples/serve-static-assets)
15
+ - [Streaming Response](/examples/stream-response)
16
+ - [Validation](/examples/validate-data)
@@ -0,0 +1,67 @@
1
+ # Cookies
2
+
3
+ > Use cookies to store data on the client.
4
+
5
+ Handling cookies with H3 is straightforward. There is three utilities to handle cookies:
6
+
7
+ - `setCookie` to attach a cookie to the response.
8
+ - `getCookie` to get a cookie from the request.
9
+ - `deleteCookie` to clear a cookie from the response.
10
+
11
+ ## Set a Cookie
12
+ To set a cookie, you need to use `setCookie` in an event handler:
13
+
14
+ ```ts
15
+ import { setCookie } from "h3";
16
+
17
+ app.use(async (event) => {
18
+ setCookie(event, "name", "value", { maxAge: 60 * 60 * 24 * 7 });
19
+ return "";
20
+ });
21
+ ```
22
+
23
+ In the options, you can configure the [cookie flags](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie):
24
+
25
+ - `maxAge` to set the expiration date of the cookie in seconds.
26
+ - `expires` to set the expiration date of the cookie in a `Date` object.
27
+ - `path` to set the path of the cookie.
28
+ - `domain` to set the domain of the cookie.
29
+ - `secure` to set the `Secure` flag of the cookie.
30
+ - `httpOnly` to set the `HttpOnly` flag of the cookie.
31
+ - `sameSite` to set the `SameSite` flag of the cookie.
32
+ <read-more></read-more>
33
+
34
+ ## Get a Cookie
35
+
36
+ To get a cookie, you need to use `getCookie` in an event handler.
37
+
38
+ ```ts
39
+ import { getCookie } from "h3";
40
+
41
+ app.use(async (event) => {
42
+ const name = getCookie(event, "name");
43
+
44
+ // do something...
45
+
46
+ return "";
47
+ });
48
+ ```
49
+
50
+ This will return the value of the cookie if it exists, or `undefined` otherwise.
51
+
52
+ ## Delete a Cookie
53
+
54
+ To delete a cookie, you need to use `deleteCookie` in an event handler:
55
+
56
+ ```ts
57
+ import { deleteCookie } from "h3";
58
+
59
+ app.use(async (event) => {
60
+ deleteCookie(event, "name");
61
+ return "";
62
+ });
63
+ ```
64
+
65
+ The utility `deleteCookie` is a wrapper around `setCookie` with the value set to `""` and the `maxAge` set to `0`.
66
+
67
+ This will erase the cookie from the client.