h3 1.7.0 → 1.7.1
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 +43 -19
- package/dist/index.cjs +3 -4
- package/dist/index.d.ts +27 -21
- package/dist/index.mjs +3 -4
- package/package.json +12 -12
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ listen(toNodeListener(app));
|
|
|
68
68
|
|
|
69
69
|
## Router
|
|
70
70
|
|
|
71
|
-
The `app` instance created by `h3` uses a middleware stack (see [how it works](
|
|
71
|
+
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.
|
|
72
72
|
|
|
73
73
|
To opt-in using a more advanced and convenient routing system, we can create a router instance and register it to app instance.
|
|
74
74
|
|
|
@@ -98,36 +98,60 @@ Routes are internally stored in a [Radix Tree](https://en.wikipedia.org/wiki/Rad
|
|
|
98
98
|
|
|
99
99
|
```js
|
|
100
100
|
// Handle can directly return object or Promise<object> for JSON response
|
|
101
|
-
app.use(
|
|
101
|
+
app.use(
|
|
102
|
+
"/api",
|
|
103
|
+
eventHandler((event) => ({ url: event.node.req.url }))
|
|
104
|
+
);
|
|
102
105
|
|
|
103
106
|
// We can have better matching other than quick prefix match
|
|
104
|
-
app.use(
|
|
107
|
+
app.use(
|
|
108
|
+
"/odd",
|
|
109
|
+
eventHandler(() => "Is odd!"),
|
|
110
|
+
{ match: (url) => url.substr(1) % 2 }
|
|
111
|
+
);
|
|
105
112
|
|
|
106
113
|
// Handle can directly return string for HTML response
|
|
107
|
-
app.use(eventHandler(() =>
|
|
114
|
+
app.use(eventHandler(() => "<h1>Hello world!</h1>"));
|
|
108
115
|
|
|
109
116
|
// We can chain calls to .use()
|
|
110
|
-
app
|
|
111
|
-
|
|
117
|
+
app
|
|
118
|
+
.use(
|
|
119
|
+
"/1",
|
|
120
|
+
eventHandler(() => "<h1>Hello world!</h1>")
|
|
121
|
+
)
|
|
122
|
+
.use(
|
|
123
|
+
"/2",
|
|
124
|
+
eventHandler(() => "<h1>Goodbye!</h1>")
|
|
125
|
+
);
|
|
112
126
|
|
|
113
127
|
// We can proxy requests and rewrite cookie's domain and path
|
|
114
|
-
app.use(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
128
|
+
app.use(
|
|
129
|
+
"/api",
|
|
130
|
+
eventHandler((event) =>
|
|
131
|
+
proxyRequest(event, "https://example.com", {
|
|
132
|
+
// f.e. keep one domain unchanged, rewrite one domain and remove other domains
|
|
133
|
+
cookieDomainRewrite: {
|
|
134
|
+
"example.com": "example.com",
|
|
135
|
+
"example.com": "somecompany.co.uk",
|
|
136
|
+
"*": "",
|
|
137
|
+
},
|
|
138
|
+
cookiePathRewrite: {
|
|
139
|
+
"/": "/api",
|
|
140
|
+
},
|
|
141
|
+
})
|
|
142
|
+
)
|
|
143
|
+
);
|
|
125
144
|
|
|
126
145
|
// Legacy middleware with 3rd argument are automatically promisified
|
|
127
|
-
app.use(
|
|
146
|
+
app.use(
|
|
147
|
+
fromNodeMiddleware((req, res, next) => {
|
|
148
|
+
req.setHeader("x-foo", "bar");
|
|
149
|
+
next();
|
|
150
|
+
})
|
|
151
|
+
);
|
|
128
152
|
|
|
129
153
|
// Lazy loaded routes using { lazy: true }
|
|
130
|
-
app.use(
|
|
154
|
+
app.use("/big", () => import("./big-handler"), { lazy: true });
|
|
131
155
|
```
|
|
132
156
|
|
|
133
157
|
## Utilities
|
package/dist/index.cjs
CHANGED
|
@@ -108,7 +108,6 @@ class H3Error extends Error {
|
|
|
108
108
|
this.statusCode = 500;
|
|
109
109
|
this.fatal = false;
|
|
110
110
|
this.unhandled = false;
|
|
111
|
-
this.statusMessage = void 0;
|
|
112
111
|
}
|
|
113
112
|
toJSON() {
|
|
114
113
|
const obj = {
|
|
@@ -133,8 +132,8 @@ function createError(input) {
|
|
|
133
132
|
return input;
|
|
134
133
|
}
|
|
135
134
|
const err = new H3Error(
|
|
136
|
-
input.message ?? input.statusMessage,
|
|
137
|
-
// @ts-ignore
|
|
135
|
+
input.message ?? input.statusMessage ?? "",
|
|
136
|
+
// @ts-ignore https://v8.dev/features/error-cause
|
|
138
137
|
input.cause ? { cause: input.cause } : void 0
|
|
139
138
|
);
|
|
140
139
|
if ("stack" in input) {
|
|
@@ -169,7 +168,7 @@ function createError(input) {
|
|
|
169
168
|
const sanitizedMessage = sanitizeStatusMessage(err.statusMessage);
|
|
170
169
|
if (sanitizedMessage !== originalMessage) {
|
|
171
170
|
console.warn(
|
|
172
|
-
"[h3] Please prefer using `message` for longer error messages instead of `statusMessage`. In the future `statusMessage` will be sanitized by default."
|
|
171
|
+
"[h3] Please prefer using `message` for longer error messages instead of `statusMessage`. In the future, `statusMessage` will be sanitized by default."
|
|
173
172
|
);
|
|
174
173
|
}
|
|
175
174
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -170,44 +170,50 @@ declare function createAppEventHandler(stack: Stack, options: AppOptions): Event
|
|
|
170
170
|
* H3 Runtime Error
|
|
171
171
|
* @class
|
|
172
172
|
* @extends Error
|
|
173
|
-
* @property {
|
|
174
|
-
* @property {
|
|
175
|
-
* @property {
|
|
176
|
-
* @property {
|
|
177
|
-
* @property {
|
|
178
|
-
*
|
|
179
|
-
* @property {
|
|
173
|
+
* @property {number} statusCode - An integer indicating the HTTP response status code.
|
|
174
|
+
* @property {string} statusMessage - A string representing the HTTP status message.
|
|
175
|
+
* @property {boolean} fatal - Indicates if the error is a fatal error.
|
|
176
|
+
* @property {boolean} unhandled - Indicates if the error was unhandled and auto captured.
|
|
177
|
+
* @property {any} data - An extra data that will be included in the response.
|
|
178
|
+
* This can be used to pass additional information about the error.
|
|
179
|
+
* @property {boolean} internal - Setting this property to `true` will mark the error as an internal error.
|
|
180
180
|
*/
|
|
181
181
|
declare class H3Error extends Error {
|
|
182
182
|
static __h3_error__: boolean;
|
|
183
|
-
toJSON(): Pick<H3Error, "data" | "statusCode" | "statusMessage" | "message">;
|
|
184
183
|
statusCode: number;
|
|
185
184
|
fatal: boolean;
|
|
186
185
|
unhandled: boolean;
|
|
187
186
|
statusMessage?: string;
|
|
188
187
|
data?: any;
|
|
188
|
+
toJSON(): Pick<H3Error, "data" | "statusCode" | "statusMessage" | "message">;
|
|
189
189
|
}
|
|
190
190
|
/**
|
|
191
|
-
* Creates new `Error` that can be used to handle both internal and runtime errors.
|
|
191
|
+
* Creates a new `Error` that can be used to handle both internal and runtime errors.
|
|
192
192
|
*
|
|
193
|
-
* @param input {Partial<H3Error>}
|
|
194
|
-
* @return {H3Error} An instance of
|
|
193
|
+
* @param input {string | (Partial<H3Error> & { status?: number; statusText?: string })} - The error message or an object containing error properties.
|
|
194
|
+
* @return {H3Error} - An instance of H3Error.
|
|
195
195
|
*/
|
|
196
196
|
declare function createError(input: string | (Partial<H3Error> & {
|
|
197
197
|
status?: number;
|
|
198
198
|
statusText?: string;
|
|
199
199
|
})): H3Error;
|
|
200
200
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
201
|
+
* Receives an error and returns the corresponding response.
|
|
202
|
+
* H3 internally uses this function to handle unhandled errors.
|
|
203
|
+
* Note that calling this function will close the connection and no other data will be sent to the client afterwards.
|
|
204
204
|
*
|
|
205
|
-
@param event {H3Event} H3 event or req passed by h3 handler
|
|
206
|
-
* @param error {H3Error
|
|
207
|
-
* @param debug {
|
|
208
|
-
*
|
|
205
|
+
* @param event {H3Event} - H3 event or req passed by h3 handler.
|
|
206
|
+
* @param error {Error | H3Error} - The raised error.
|
|
207
|
+
* @param debug {boolean} - Whether the application is in debug mode.
|
|
208
|
+
* In the debug mode, the stack trace of errors will be returned in the response.
|
|
209
209
|
*/
|
|
210
210
|
declare function sendError(event: H3Event, error: Error | H3Error, debug?: boolean): void;
|
|
211
|
+
/**
|
|
212
|
+
* Checks if the given input is an instance of H3Error.
|
|
213
|
+
*
|
|
214
|
+
* @param input {*} - The input to check.
|
|
215
|
+
* @return {boolean} - Returns true if the input is an instance of H3Error, false otherwise.
|
|
216
|
+
*/
|
|
211
217
|
declare function isError(input: any): input is H3Error;
|
|
212
218
|
|
|
213
219
|
declare function useBase(base: string, handler: EventHandler): EventHandler;
|
|
@@ -322,11 +328,11 @@ interface ProxyOptions {
|
|
|
322
328
|
declare function proxyRequest(event: H3Event, target: string, opts?: ProxyOptions): Promise<any>;
|
|
323
329
|
declare function sendProxy(event: H3Event, target: string, opts?: ProxyOptions): Promise<any>;
|
|
324
330
|
declare function getProxyRequestHeaders(event: H3Event): any;
|
|
325
|
-
declare function fetchWithEvent(event: H3Event, req: RequestInfo | URL, init?: RequestInit & {
|
|
331
|
+
declare function fetchWithEvent<T = unknown, _R = any, F extends (req: RequestInfo | URL, opts?: any) => any = typeof fetch>(event: H3Event, req: RequestInfo | URL, init?: RequestInit & {
|
|
326
332
|
context?: H3EventContext;
|
|
327
333
|
}, options?: {
|
|
328
|
-
fetch:
|
|
329
|
-
}):
|
|
334
|
+
fetch: F;
|
|
335
|
+
}): unknown extends T ? ReturnType<F> : T;
|
|
330
336
|
|
|
331
337
|
declare function getQuery(event: H3Event): ufo.QueryObject;
|
|
332
338
|
declare function getRouterParams(event: H3Event): NonNullable<H3Event["context"]["params"]>;
|
package/dist/index.mjs
CHANGED
|
@@ -101,7 +101,6 @@ class H3Error extends Error {
|
|
|
101
101
|
this.statusCode = 500;
|
|
102
102
|
this.fatal = false;
|
|
103
103
|
this.unhandled = false;
|
|
104
|
-
this.statusMessage = void 0;
|
|
105
104
|
}
|
|
106
105
|
toJSON() {
|
|
107
106
|
const obj = {
|
|
@@ -126,8 +125,8 @@ function createError(input) {
|
|
|
126
125
|
return input;
|
|
127
126
|
}
|
|
128
127
|
const err = new H3Error(
|
|
129
|
-
input.message ?? input.statusMessage,
|
|
130
|
-
// @ts-ignore
|
|
128
|
+
input.message ?? input.statusMessage ?? "",
|
|
129
|
+
// @ts-ignore https://v8.dev/features/error-cause
|
|
131
130
|
input.cause ? { cause: input.cause } : void 0
|
|
132
131
|
);
|
|
133
132
|
if ("stack" in input) {
|
|
@@ -162,7 +161,7 @@ function createError(input) {
|
|
|
162
161
|
const sanitizedMessage = sanitizeStatusMessage(err.statusMessage);
|
|
163
162
|
if (sanitizedMessage !== originalMessage) {
|
|
164
163
|
console.warn(
|
|
165
|
-
"[h3] Please prefer using `message` for longer error messages instead of `statusMessage`. In the future `statusMessage` will be sanitized by default."
|
|
164
|
+
"[h3] Please prefer using `message` for longer error messages instead of `statusMessage`. In the future, `statusMessage` will be sanitized by default."
|
|
166
165
|
);
|
|
167
166
|
}
|
|
168
167
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "h3",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Tiny JavaScript Server",
|
|
5
5
|
"repository": "unjs/h3",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,16 +19,6 @@
|
|
|
19
19
|
"files": [
|
|
20
20
|
"dist"
|
|
21
21
|
],
|
|
22
|
-
"scripts": {
|
|
23
|
-
"build": "unbuild",
|
|
24
|
-
"dev": "vitest",
|
|
25
|
-
"lint": "eslint --cache --ext .ts,.js,.mjs,.cjs . && prettier -c src test playground",
|
|
26
|
-
"lint:fix": "eslint --cache --ext .ts,.js,.mjs,.cjs . --fix && prettier -c src test playground -w",
|
|
27
|
-
"play": "jiti ./playground/index.ts",
|
|
28
|
-
"profile": "0x -o -D .profile -P 'autocannon -c 100 -p 10 -d 40 http://localhost:$PORT' ./playground/server.cjs",
|
|
29
|
-
"release": "pnpm test && pnpm build && changelogen --release && pnpm publish && git push --follow-tags",
|
|
30
|
-
"test": "pnpm lint && vitest run --coverage"
|
|
31
|
-
},
|
|
32
22
|
"dependencies": {
|
|
33
23
|
"cookie-es": "^1.0.0",
|
|
34
24
|
"defu": "^6.1.2",
|
|
@@ -60,5 +50,15 @@
|
|
|
60
50
|
"unbuild": "^1.2.1",
|
|
61
51
|
"vitest": "^0.32.2"
|
|
62
52
|
},
|
|
63
|
-
"packageManager": "pnpm@8.6.3"
|
|
53
|
+
"packageManager": "pnpm@8.6.3",
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "unbuild",
|
|
56
|
+
"dev": "vitest",
|
|
57
|
+
"lint": "eslint --cache --ext .ts,.js,.mjs,.cjs . && prettier -c src test playground",
|
|
58
|
+
"lint:fix": "eslint --cache --ext .ts,.js,.mjs,.cjs . --fix && prettier -c src test playground -w",
|
|
59
|
+
"play": "jiti ./playground/index.ts",
|
|
60
|
+
"profile": "0x -o -D .profile -P 'autocannon -c 100 -p 10 -d 40 http://localhost:$PORT' ./playground/server.cjs",
|
|
61
|
+
"release": "pnpm test && pnpm build && changelogen --release && pnpm publish && git push --follow-tags",
|
|
62
|
+
"test": "pnpm lint && vitest run --coverage"
|
|
63
|
+
}
|
|
64
64
|
}
|