h3 0.7.18 → 0.7.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.
- package/dist/index.cjs +482 -4
- package/dist/index.d.ts +258 -31
- package/dist/index.mjs +423 -5
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -2,9 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
require('
|
|
6
|
-
require('
|
|
7
|
-
require('cookie-es');
|
|
5
|
+
const ufo = require('ufo');
|
|
6
|
+
const destr = require('destr');
|
|
7
|
+
const cookieEs = require('cookie-es');
|
|
8
|
+
const radix3 = require('radix3');
|
|
9
|
+
|
|
10
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
|
|
11
|
+
|
|
12
|
+
const destr__default = /*#__PURE__*/_interopDefaultLegacy(destr);
|
|
8
13
|
|
|
9
14
|
class H3Error extends Error {
|
|
10
15
|
constructor() {
|
|
@@ -53,16 +58,243 @@ function createError(input) {
|
|
|
53
58
|
}
|
|
54
59
|
return err;
|
|
55
60
|
}
|
|
61
|
+
function sendError(event, error, debug) {
|
|
62
|
+
if (event.res.writableEnded) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const h3Error = isError(error) ? error : createError(error);
|
|
66
|
+
const responseBody = {
|
|
67
|
+
statusCode: h3Error.statusCode,
|
|
68
|
+
statusMessage: h3Error.statusMessage,
|
|
69
|
+
stack: [],
|
|
70
|
+
data: h3Error.data
|
|
71
|
+
};
|
|
72
|
+
if (debug) {
|
|
73
|
+
responseBody.stack = (h3Error.stack || "").split("\n").map((l) => l.trim());
|
|
74
|
+
}
|
|
75
|
+
if (event.res.writableEnded) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
event.res.statusCode = h3Error.statusCode;
|
|
79
|
+
event.res.statusMessage = h3Error.statusMessage;
|
|
80
|
+
event.res.setHeader("Content-Type", MIMES.json);
|
|
81
|
+
event.res.end(JSON.stringify(responseBody, null, 2));
|
|
82
|
+
}
|
|
56
83
|
function isError(input) {
|
|
57
84
|
return input?.constructor?.__h3_error__ === true;
|
|
58
85
|
}
|
|
59
86
|
|
|
87
|
+
function getQuery(event) {
|
|
88
|
+
return ufo.getQuery(event.req.url || "");
|
|
89
|
+
}
|
|
90
|
+
const useQuery = getQuery;
|
|
91
|
+
function getRouterParams(event) {
|
|
92
|
+
return event.context.params || {};
|
|
93
|
+
}
|
|
94
|
+
function getRouterParam(event, name) {
|
|
95
|
+
const params = getRouterParams(event);
|
|
96
|
+
return params[name];
|
|
97
|
+
}
|
|
98
|
+
function getMethod(event, defaultMethod = "GET") {
|
|
99
|
+
return (event.req.method || defaultMethod).toUpperCase();
|
|
100
|
+
}
|
|
101
|
+
const useMethod = getMethod;
|
|
102
|
+
function isMethod(event, expected, allowHead) {
|
|
103
|
+
const method = getMethod(event);
|
|
104
|
+
if (allowHead && method === "HEAD") {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
if (typeof expected === "string") {
|
|
108
|
+
if (method === expected) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
} else if (expected.includes(method)) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
function assertMethod(event, expected, allowHead) {
|
|
117
|
+
if (!isMethod(event, expected, allowHead)) {
|
|
118
|
+
throw createError({
|
|
119
|
+
statusCode: 405,
|
|
120
|
+
statusMessage: "HTTP method is not allowed."
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function getRequestHeaders(event) {
|
|
125
|
+
return event.req.headers;
|
|
126
|
+
}
|
|
127
|
+
const getHeaders = getRequestHeaders;
|
|
128
|
+
function getRequestHeader(event, name) {
|
|
129
|
+
const headers = getRequestHeaders(event);
|
|
130
|
+
const value = headers[name.toLowerCase()];
|
|
131
|
+
return value;
|
|
132
|
+
}
|
|
133
|
+
const getHeader = getRequestHeader;
|
|
134
|
+
|
|
135
|
+
const RawBodySymbol = Symbol.for("h3RawBody");
|
|
136
|
+
const ParsedBodySymbol = Symbol.for("h3ParsedBody");
|
|
137
|
+
const PayloadMethods = ["PATCH", "POST", "PUT", "DELETE"];
|
|
138
|
+
function readRawBody(event, encoding = "utf-8") {
|
|
139
|
+
assertMethod(event, PayloadMethods);
|
|
140
|
+
if (RawBodySymbol in event.req) {
|
|
141
|
+
const promise2 = Promise.resolve(event.req[RawBodySymbol]);
|
|
142
|
+
return encoding ? promise2.then((buff) => buff.toString(encoding)) : promise2;
|
|
143
|
+
}
|
|
144
|
+
if ("body" in event.req) {
|
|
145
|
+
return Promise.resolve(event.req.body);
|
|
146
|
+
}
|
|
147
|
+
const promise = event.req[RawBodySymbol] = new Promise((resolve, reject) => {
|
|
148
|
+
const bodyData = [];
|
|
149
|
+
event.req.on("error", (err) => {
|
|
150
|
+
reject(err);
|
|
151
|
+
}).on("data", (chunk) => {
|
|
152
|
+
bodyData.push(chunk);
|
|
153
|
+
}).on("end", () => {
|
|
154
|
+
resolve(Buffer.concat(bodyData));
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
return encoding ? promise.then((buff) => buff.toString(encoding)) : promise;
|
|
158
|
+
}
|
|
159
|
+
const useRawBody = readRawBody;
|
|
160
|
+
async function readBody(event) {
|
|
161
|
+
if (ParsedBodySymbol in event.req) {
|
|
162
|
+
return event.req[ParsedBodySymbol];
|
|
163
|
+
}
|
|
164
|
+
const body = await readRawBody(event);
|
|
165
|
+
if (event.req.headers["content-type"] === "application/x-www-form-urlencoded") {
|
|
166
|
+
const parsedForm = Object.fromEntries(new URLSearchParams(body));
|
|
167
|
+
return parsedForm;
|
|
168
|
+
}
|
|
169
|
+
const json = destr__default(body);
|
|
170
|
+
event.req[ParsedBodySymbol] = json;
|
|
171
|
+
return json;
|
|
172
|
+
}
|
|
173
|
+
const useBody = readBody;
|
|
174
|
+
|
|
175
|
+
function handleCacheHeaders(event, opts) {
|
|
176
|
+
const cacheControls = ["public"].concat(opts.cacheControls || []);
|
|
177
|
+
let cacheMatched = false;
|
|
178
|
+
if (opts.maxAge !== void 0) {
|
|
179
|
+
cacheControls.push(`max-age=${+opts.maxAge}`, `s-maxage=${+opts.maxAge}`);
|
|
180
|
+
}
|
|
181
|
+
if (opts.modifiedTime) {
|
|
182
|
+
const modifiedTime = new Date(opts.modifiedTime);
|
|
183
|
+
const ifModifiedSince = event.req.headers["if-modified-since"];
|
|
184
|
+
event.res.setHeader("Last-Modified", modifiedTime.toUTCString());
|
|
185
|
+
if (ifModifiedSince) {
|
|
186
|
+
if (new Date(ifModifiedSince) >= opts.modifiedTime) {
|
|
187
|
+
cacheMatched = true;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (opts.etag) {
|
|
192
|
+
event.res.setHeader("Etag", opts.etag);
|
|
193
|
+
const ifNonMatch = event.req.headers["if-none-match"];
|
|
194
|
+
if (ifNonMatch === opts.etag) {
|
|
195
|
+
cacheMatched = true;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
event.res.setHeader("Cache-Control", cacheControls.join(", "));
|
|
199
|
+
if (cacheMatched) {
|
|
200
|
+
event.res.statusCode = 304;
|
|
201
|
+
event.res.end("");
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
|
|
60
207
|
const MIMES = {
|
|
61
208
|
html: "text/html",
|
|
62
209
|
json: "application/json"
|
|
63
210
|
};
|
|
64
211
|
|
|
65
|
-
typeof setImmediate !== "undefined" ? setImmediate : (fn) => fn();
|
|
212
|
+
const defer = typeof setImmediate !== "undefined" ? setImmediate : (fn) => fn();
|
|
213
|
+
function send(event, data, type) {
|
|
214
|
+
if (type) {
|
|
215
|
+
defaultContentType(event, type);
|
|
216
|
+
}
|
|
217
|
+
return new Promise((resolve) => {
|
|
218
|
+
defer(() => {
|
|
219
|
+
event.res.end(data);
|
|
220
|
+
resolve(void 0);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
function defaultContentType(event, type) {
|
|
225
|
+
if (type && !event.res.getHeader("Content-Type")) {
|
|
226
|
+
event.res.setHeader("Content-Type", type);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function sendRedirect(event, location, code = 302) {
|
|
230
|
+
event.res.statusCode = code;
|
|
231
|
+
event.res.setHeader("Location", location);
|
|
232
|
+
const encodedLoc = location.replace(/"/g, "%22");
|
|
233
|
+
const html = `<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=${encodedLoc}"></head></html>`;
|
|
234
|
+
return send(event, html, MIMES.html);
|
|
235
|
+
}
|
|
236
|
+
function getResponseHeaders(event) {
|
|
237
|
+
return event.res.getHeaders();
|
|
238
|
+
}
|
|
239
|
+
function getResponseHeader(event, name) {
|
|
240
|
+
return event.res.getHeader(name);
|
|
241
|
+
}
|
|
242
|
+
function setResponseHeaders(event, headers) {
|
|
243
|
+
Object.entries(headers).forEach(([name, value]) => event.res.setHeader(name, value));
|
|
244
|
+
}
|
|
245
|
+
const setHeaders = setResponseHeaders;
|
|
246
|
+
function setResponseHeader(event, name, value) {
|
|
247
|
+
event.res.setHeader(name, value);
|
|
248
|
+
}
|
|
249
|
+
const setHeader = setResponseHeader;
|
|
250
|
+
function appendResponseHeaders(event, headers) {
|
|
251
|
+
Object.entries(headers).forEach(([name, value]) => appendResponseHeader(event, name, value));
|
|
252
|
+
}
|
|
253
|
+
const appendHeaders = appendResponseHeaders;
|
|
254
|
+
function appendResponseHeader(event, name, value) {
|
|
255
|
+
let current = event.res.getHeader(name);
|
|
256
|
+
if (!current) {
|
|
257
|
+
event.res.setHeader(name, value);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (!Array.isArray(current)) {
|
|
261
|
+
current = [current.toString()];
|
|
262
|
+
}
|
|
263
|
+
event.res.setHeader(name, current.concat(value));
|
|
264
|
+
}
|
|
265
|
+
const appendHeader = appendResponseHeader;
|
|
266
|
+
function isStream(data) {
|
|
267
|
+
return data && typeof data === "object" && typeof data.pipe === "function" && typeof data.on === "function";
|
|
268
|
+
}
|
|
269
|
+
function sendStream(event, data) {
|
|
270
|
+
return new Promise((resolve, reject) => {
|
|
271
|
+
data.pipe(event.res);
|
|
272
|
+
data.on("end", () => resolve(void 0));
|
|
273
|
+
data.on("error", (error) => reject(createError(error)));
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function parseCookies(event) {
|
|
278
|
+
return cookieEs.parse(event.req.headers.cookie || "");
|
|
279
|
+
}
|
|
280
|
+
const useCookies = parseCookies;
|
|
281
|
+
function getCookie(event, name) {
|
|
282
|
+
return parseCookies(event)[name];
|
|
283
|
+
}
|
|
284
|
+
const useCookie = getCookie;
|
|
285
|
+
function setCookie(event, name, value, serializeOptions) {
|
|
286
|
+
const cookieStr = cookieEs.serialize(name, value, {
|
|
287
|
+
path: "/",
|
|
288
|
+
...serializeOptions
|
|
289
|
+
});
|
|
290
|
+
appendHeader(event, "Set-Cookie", cookieStr);
|
|
291
|
+
}
|
|
292
|
+
function deleteCookie(event, name, serializeOptions) {
|
|
293
|
+
setCookie(event, name, "", {
|
|
294
|
+
...serializeOptions,
|
|
295
|
+
maxAge: 0
|
|
296
|
+
});
|
|
297
|
+
}
|
|
66
298
|
|
|
67
299
|
class H3Headers {
|
|
68
300
|
constructor(init) {
|
|
@@ -189,6 +421,15 @@ function createEvent(req, res) {
|
|
|
189
421
|
return new H3Event(req, res);
|
|
190
422
|
}
|
|
191
423
|
|
|
424
|
+
const defineHandler = (handler) => handler;
|
|
425
|
+
const defineHandle = defineHandler;
|
|
426
|
+
const defineMiddleware = (middleware) => middleware;
|
|
427
|
+
function promisifyHandler(handler) {
|
|
428
|
+
return function(req, res) {
|
|
429
|
+
return callHandler(handler, req, res);
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
const promisifyHandle = promisifyHandler;
|
|
192
433
|
function callHandler(handler, req, res) {
|
|
193
434
|
const isMiddleware = handler.length > 2;
|
|
194
435
|
return new Promise((resolve, reject) => {
|
|
@@ -212,6 +453,30 @@ function callHandler(handler, req, res) {
|
|
|
212
453
|
}
|
|
213
454
|
});
|
|
214
455
|
}
|
|
456
|
+
function defineLazyHandler(handler, promisify) {
|
|
457
|
+
let _promise;
|
|
458
|
+
const resolve = () => {
|
|
459
|
+
if (!_promise) {
|
|
460
|
+
_promise = Promise.resolve(handler()).then((r) => promisify ? promisifyHandler(r.default || r) : r.default || r);
|
|
461
|
+
}
|
|
462
|
+
return _promise;
|
|
463
|
+
};
|
|
464
|
+
return function(req, res) {
|
|
465
|
+
return resolve().then((h) => h(req, res));
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
const lazyHandle = defineLazyHandler;
|
|
469
|
+
function useBase(base, handler) {
|
|
470
|
+
base = ufo.withoutTrailingSlash(base);
|
|
471
|
+
if (!base) {
|
|
472
|
+
return handler;
|
|
473
|
+
}
|
|
474
|
+
return function(req, res) {
|
|
475
|
+
req.originalUrl = req.originalUrl || req.url || "/";
|
|
476
|
+
req.url = ufo.withoutBase(req.url || "/", base);
|
|
477
|
+
return handler(req, res);
|
|
478
|
+
};
|
|
479
|
+
}
|
|
215
480
|
|
|
216
481
|
function defineEventHandler(handler) {
|
|
217
482
|
handler.__is_handler__ = true;
|
|
@@ -272,15 +537,228 @@ function defineLazyEventHandler(factory) {
|
|
|
272
537
|
}
|
|
273
538
|
const lazyEventHandler = defineLazyEventHandler;
|
|
274
539
|
|
|
540
|
+
function createApp(options = {}) {
|
|
541
|
+
const stack = [];
|
|
542
|
+
const handler = createAppEventHandler(stack, options);
|
|
543
|
+
const nodeHandler = async function(req, res) {
|
|
544
|
+
const event = createEvent(req, res);
|
|
545
|
+
try {
|
|
546
|
+
await handler(event);
|
|
547
|
+
} catch (_error) {
|
|
548
|
+
const error = createError(_error);
|
|
549
|
+
if (!isError(_error)) {
|
|
550
|
+
error.unhandled = true;
|
|
551
|
+
}
|
|
552
|
+
if (options.onError) {
|
|
553
|
+
await options.onError(error, event);
|
|
554
|
+
} else {
|
|
555
|
+
if (error.unhandled || error.fatal) {
|
|
556
|
+
console.error("[h3]", error.fatal ? "[fatal]" : "[unhandled]", error);
|
|
557
|
+
}
|
|
558
|
+
await sendError(event, error, !!options.debug);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
const app = nodeHandler;
|
|
563
|
+
app.nodeHandler = nodeHandler;
|
|
564
|
+
app.stack = stack;
|
|
565
|
+
app.handler = handler;
|
|
566
|
+
app.use = (arg1, arg2, arg3) => use(app, arg1, arg2, arg3);
|
|
567
|
+
return app;
|
|
568
|
+
}
|
|
569
|
+
function use(app, arg1, arg2, arg3) {
|
|
570
|
+
if (Array.isArray(arg1)) {
|
|
571
|
+
arg1.forEach((i) => use(app, i, arg2, arg3));
|
|
572
|
+
} else if (Array.isArray(arg2)) {
|
|
573
|
+
arg2.forEach((i) => use(app, arg1, i, arg3));
|
|
574
|
+
} else if (typeof arg1 === "string") {
|
|
575
|
+
app.stack.push(normalizeLayer({ ...arg3, route: arg1, handler: arg2 }));
|
|
576
|
+
} else if (typeof arg1 === "function") {
|
|
577
|
+
app.stack.push(normalizeLayer({ ...arg2, route: "/", handler: arg1 }));
|
|
578
|
+
} else {
|
|
579
|
+
app.stack.push(normalizeLayer({ ...arg1 }));
|
|
580
|
+
}
|
|
581
|
+
return app;
|
|
582
|
+
}
|
|
583
|
+
function createAppEventHandler(stack, options) {
|
|
584
|
+
const spacing = options.debug ? 2 : void 0;
|
|
585
|
+
return eventHandler(async (event) => {
|
|
586
|
+
event.req.originalUrl = event.req.originalUrl || event.req.url || "/";
|
|
587
|
+
const reqUrl = event.req.url || "/";
|
|
588
|
+
for (const layer of stack) {
|
|
589
|
+
if (layer.route.length > 1) {
|
|
590
|
+
if (!reqUrl.startsWith(layer.route)) {
|
|
591
|
+
continue;
|
|
592
|
+
}
|
|
593
|
+
event.req.url = reqUrl.slice(layer.route.length) || "/";
|
|
594
|
+
} else {
|
|
595
|
+
event.req.url = reqUrl;
|
|
596
|
+
}
|
|
597
|
+
if (layer.match && !layer.match(event.req.url, event)) {
|
|
598
|
+
continue;
|
|
599
|
+
}
|
|
600
|
+
const val = await layer.handler(event);
|
|
601
|
+
if (event.res.writableEnded) {
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
const type = typeof val;
|
|
605
|
+
if (type === "string") {
|
|
606
|
+
return send(event, val, MIMES.html);
|
|
607
|
+
} else if (isStream(val)) {
|
|
608
|
+
return sendStream(event, val);
|
|
609
|
+
} else if (val === null) {
|
|
610
|
+
event.res.statusCode = 204;
|
|
611
|
+
return send(event);
|
|
612
|
+
} else if (type === "object" || type === "boolean" || type === "number") {
|
|
613
|
+
if (val.buffer) {
|
|
614
|
+
return send(event, val);
|
|
615
|
+
} else if (val instanceof Error) {
|
|
616
|
+
throw createError(val);
|
|
617
|
+
} else {
|
|
618
|
+
return send(event, JSON.stringify(val, null, spacing), MIMES.json);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
if (!event.res.writableEnded) {
|
|
623
|
+
throw createError({ statusCode: 404, statusMessage: "Not Found" });
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
function normalizeLayer(input) {
|
|
628
|
+
let handler = input.handler || input.handle;
|
|
629
|
+
if (handler.handler) {
|
|
630
|
+
handler = handler.handler;
|
|
631
|
+
}
|
|
632
|
+
if (input.lazy) {
|
|
633
|
+
handler = lazyEventHandler(handler);
|
|
634
|
+
} else if (!isEventHandler(handler)) {
|
|
635
|
+
handler = toEventHandler(handler);
|
|
636
|
+
}
|
|
637
|
+
return {
|
|
638
|
+
route: ufo.withoutTrailingSlash(input.route),
|
|
639
|
+
match: input.match,
|
|
640
|
+
handler
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
const RouterMethods = ["connect", "delete", "get", "head", "options", "post", "put", "trace", "patch"];
|
|
645
|
+
function createRouter() {
|
|
646
|
+
const _router = radix3.createRouter({});
|
|
647
|
+
const routes = {};
|
|
648
|
+
const router = {};
|
|
649
|
+
const addRoute = (path, handler, method) => {
|
|
650
|
+
let route = routes[path];
|
|
651
|
+
if (!route) {
|
|
652
|
+
routes[path] = route = { handlers: {} };
|
|
653
|
+
_router.insert(path, route);
|
|
654
|
+
}
|
|
655
|
+
if (Array.isArray(method)) {
|
|
656
|
+
method.forEach((m) => addRoute(path, handler, m));
|
|
657
|
+
} else {
|
|
658
|
+
route.handlers[method] = toEventHandler(handler);
|
|
659
|
+
}
|
|
660
|
+
return router;
|
|
661
|
+
};
|
|
662
|
+
router.use = router.add = (path, handler, method) => addRoute(path, handler, method || "all");
|
|
663
|
+
for (const method of RouterMethods) {
|
|
664
|
+
router[method] = (path, handle) => router.add(path, handle, method);
|
|
665
|
+
}
|
|
666
|
+
router.handler = eventHandler((event) => {
|
|
667
|
+
let path = event.req.url || "/";
|
|
668
|
+
const queryUrlIndex = path.lastIndexOf("?");
|
|
669
|
+
if (queryUrlIndex > -1) {
|
|
670
|
+
path = path.substring(0, queryUrlIndex);
|
|
671
|
+
}
|
|
672
|
+
const matched = _router.lookup(path);
|
|
673
|
+
if (!matched) {
|
|
674
|
+
throw createError({
|
|
675
|
+
statusCode: 404,
|
|
676
|
+
name: "Not Found",
|
|
677
|
+
statusMessage: `Cannot find any route matching ${event.req.url || "/"}.`
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
const method = (event.req.method || "get").toLowerCase();
|
|
681
|
+
const handler = matched.handlers[method] || matched.handlers.all;
|
|
682
|
+
if (!handler) {
|
|
683
|
+
throw createError({
|
|
684
|
+
statusCode: 405,
|
|
685
|
+
name: "Method Not Allowed",
|
|
686
|
+
statusMessage: `Method ${method} is not allowed on this route.`
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
const params = matched.params || {};
|
|
690
|
+
event.event.context.params = params;
|
|
691
|
+
event.req.context.params = params;
|
|
692
|
+
return handler(event);
|
|
693
|
+
});
|
|
694
|
+
return router;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
exports.H3Error = H3Error;
|
|
275
698
|
exports.H3Event = H3Event;
|
|
276
699
|
exports.H3Headers = H3Headers;
|
|
277
700
|
exports.H3Response = H3Response;
|
|
701
|
+
exports.MIMES = MIMES;
|
|
702
|
+
exports.appendHeader = appendHeader;
|
|
703
|
+
exports.appendHeaders = appendHeaders;
|
|
704
|
+
exports.appendResponseHeader = appendResponseHeader;
|
|
705
|
+
exports.appendResponseHeaders = appendResponseHeaders;
|
|
706
|
+
exports.assertMethod = assertMethod;
|
|
707
|
+
exports.callHandler = callHandler;
|
|
708
|
+
exports.createApp = createApp;
|
|
709
|
+
exports.createAppEventHandler = createAppEventHandler;
|
|
710
|
+
exports.createError = createError;
|
|
278
711
|
exports.createEvent = createEvent;
|
|
712
|
+
exports.createRouter = createRouter;
|
|
713
|
+
exports.defaultContentType = defaultContentType;
|
|
279
714
|
exports.defineEventHandler = defineEventHandler;
|
|
715
|
+
exports.defineHandle = defineHandle;
|
|
716
|
+
exports.defineHandler = defineHandler;
|
|
280
717
|
exports.defineLazyEventHandler = defineLazyEventHandler;
|
|
718
|
+
exports.defineLazyHandler = defineLazyHandler;
|
|
719
|
+
exports.defineMiddleware = defineMiddleware;
|
|
720
|
+
exports.deleteCookie = deleteCookie;
|
|
281
721
|
exports.dynamicEventHandler = dynamicEventHandler;
|
|
282
722
|
exports.eventHandler = eventHandler;
|
|
723
|
+
exports.getCookie = getCookie;
|
|
724
|
+
exports.getHeader = getHeader;
|
|
725
|
+
exports.getHeaders = getHeaders;
|
|
726
|
+
exports.getMethod = getMethod;
|
|
727
|
+
exports.getQuery = getQuery;
|
|
728
|
+
exports.getRequestHeader = getRequestHeader;
|
|
729
|
+
exports.getRequestHeaders = getRequestHeaders;
|
|
730
|
+
exports.getResponseHeader = getResponseHeader;
|
|
731
|
+
exports.getResponseHeaders = getResponseHeaders;
|
|
732
|
+
exports.getRouterParam = getRouterParam;
|
|
733
|
+
exports.getRouterParams = getRouterParams;
|
|
734
|
+
exports.handleCacheHeaders = handleCacheHeaders;
|
|
735
|
+
exports.isError = isError;
|
|
283
736
|
exports.isEvent = isEvent;
|
|
284
737
|
exports.isEventHandler = isEventHandler;
|
|
738
|
+
exports.isMethod = isMethod;
|
|
739
|
+
exports.isStream = isStream;
|
|
285
740
|
exports.lazyEventHandler = lazyEventHandler;
|
|
741
|
+
exports.lazyHandle = lazyHandle;
|
|
742
|
+
exports.parseCookies = parseCookies;
|
|
743
|
+
exports.promisifyHandle = promisifyHandle;
|
|
744
|
+
exports.promisifyHandler = promisifyHandler;
|
|
745
|
+
exports.readBody = readBody;
|
|
746
|
+
exports.readRawBody = readRawBody;
|
|
747
|
+
exports.send = send;
|
|
748
|
+
exports.sendError = sendError;
|
|
749
|
+
exports.sendRedirect = sendRedirect;
|
|
750
|
+
exports.sendStream = sendStream;
|
|
751
|
+
exports.setCookie = setCookie;
|
|
752
|
+
exports.setHeader = setHeader;
|
|
753
|
+
exports.setHeaders = setHeaders;
|
|
754
|
+
exports.setResponseHeader = setResponseHeader;
|
|
755
|
+
exports.setResponseHeaders = setResponseHeaders;
|
|
286
756
|
exports.toEventHandler = toEventHandler;
|
|
757
|
+
exports.use = use;
|
|
758
|
+
exports.useBase = useBase;
|
|
759
|
+
exports.useBody = useBody;
|
|
760
|
+
exports.useCookie = useCookie;
|
|
761
|
+
exports.useCookies = useCookies;
|
|
762
|
+
exports.useMethod = useMethod;
|
|
763
|
+
exports.useQuery = useQuery;
|
|
764
|
+
exports.useRawBody = useRawBody;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,31 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
event: H3Event;
|
|
5
|
-
context: H3EventContext;
|
|
6
|
-
/** Only available with connect and press */
|
|
7
|
-
originalUrl?: string;
|
|
8
|
-
}
|
|
9
|
-
interface IncomingMessage extends http.IncomingMessage, CompatibilityRequestProps {
|
|
10
|
-
req: H3Event['req'];
|
|
11
|
-
res: H3Event['res'];
|
|
12
|
-
}
|
|
13
|
-
interface ServerResponse extends http.ServerResponse {
|
|
14
|
-
event: H3Event;
|
|
15
|
-
res: H3Event['res'];
|
|
16
|
-
req: http.ServerResponse['req'] & CompatibilityRequestProps;
|
|
17
|
-
}
|
|
18
|
-
declare type Handler<T = any, ReqT = {}> = (req: IncomingMessage & ReqT, res: ServerResponse) => T;
|
|
19
|
-
declare type Middleware = (req: IncomingMessage, res: ServerResponse, next: (err?: Error) => any) => any;
|
|
20
|
-
interface H3EventContext extends Record<string, any> {
|
|
21
|
-
}
|
|
22
|
-
declare type HandlerResponse<T = any> = T | Promise<T>;
|
|
23
|
-
interface EventHandler<T = any> {
|
|
24
|
-
'__is_handler__'?: true;
|
|
25
|
-
(event: H3Event): HandlerResponse<T>;
|
|
26
|
-
}
|
|
27
|
-
declare type LazyEventHandler = () => EventHandler | Promise<EventHandler>;
|
|
28
|
-
declare type CompatibilityEventHandler = EventHandler | Handler | Middleware;
|
|
1
|
+
import { IncomingMessage as IncomingMessage$1, ServerResponse as ServerResponse$1, OutgoingMessage } from 'http';
|
|
2
|
+
import { CookieSerializeOptions } from 'cookie-es';
|
|
3
|
+
import * as ufo from 'ufo';
|
|
29
4
|
|
|
30
5
|
declare class H3Headers implements Headers {
|
|
31
6
|
_headers: Record<string, string>;
|
|
@@ -64,11 +39,11 @@ declare class H3Event implements Pick<FetchEvent, 'respondWith'> {
|
|
|
64
39
|
res: ServerResponse;
|
|
65
40
|
event: H3Event;
|
|
66
41
|
context: H3EventContext;
|
|
67
|
-
constructor(req:
|
|
42
|
+
constructor(req: IncomingMessage$1 | IncomingMessage, res: ServerResponse$1 | ServerResponse);
|
|
68
43
|
respondWith(r: H3Response | PromiseLike<H3Response>): void;
|
|
69
44
|
}
|
|
70
45
|
declare function isEvent(input: any): input is H3Event;
|
|
71
|
-
declare function createEvent(req:
|
|
46
|
+
declare function createEvent(req: IncomingMessage$1, res: ServerResponse$1): H3Event;
|
|
72
47
|
|
|
73
48
|
declare function defineEventHandler<T = any>(handler: EventHandler<T>): EventHandler<T>;
|
|
74
49
|
declare const eventHandler: typeof defineEventHandler;
|
|
@@ -81,4 +56,256 @@ declare function dynamicEventHandler(initial?: EventHandler): DynamicEventHandle
|
|
|
81
56
|
declare function defineLazyEventHandler(factory: LazyEventHandler): EventHandler;
|
|
82
57
|
declare const lazyEventHandler: typeof defineLazyEventHandler;
|
|
83
58
|
|
|
84
|
-
|
|
59
|
+
interface CompatibilityRequestProps {
|
|
60
|
+
event: H3Event;
|
|
61
|
+
context: H3EventContext;
|
|
62
|
+
/** Only available with connect and press */
|
|
63
|
+
originalUrl?: string;
|
|
64
|
+
}
|
|
65
|
+
interface IncomingMessage extends IncomingMessage$1, CompatibilityRequestProps {
|
|
66
|
+
req: H3Event['req'];
|
|
67
|
+
res: H3Event['res'];
|
|
68
|
+
}
|
|
69
|
+
interface ServerResponse extends ServerResponse$1 {
|
|
70
|
+
event: H3Event;
|
|
71
|
+
res: H3Event['res'];
|
|
72
|
+
req: ServerResponse$1['req'] & CompatibilityRequestProps;
|
|
73
|
+
}
|
|
74
|
+
declare type Handler<T = any, ReqT = {}> = (req: IncomingMessage & ReqT, res: ServerResponse) => T;
|
|
75
|
+
declare type PromisifiedHandler = Handler<Promise<any>>;
|
|
76
|
+
declare type Middleware = (req: IncomingMessage, res: ServerResponse, next: (err?: Error) => any) => any;
|
|
77
|
+
declare type LazyHandler = () => Handler | Promise<Handler>;
|
|
78
|
+
declare type Encoding = false | 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'latin1' | 'binary' | 'hex';
|
|
79
|
+
declare type HTTPMethod = 'GET' | 'HEAD' | 'PATCH' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE';
|
|
80
|
+
interface H3EventContext extends Record<string, any> {
|
|
81
|
+
}
|
|
82
|
+
declare type CompatibilityEvent = H3Event | IncomingMessage;
|
|
83
|
+
declare type HandlerResponse<T = any> = T | Promise<T>;
|
|
84
|
+
interface EventHandler<T = any> {
|
|
85
|
+
'__is_handler__'?: true;
|
|
86
|
+
(event: H3Event): HandlerResponse<T>;
|
|
87
|
+
}
|
|
88
|
+
declare type LazyEventHandler = () => EventHandler | Promise<EventHandler>;
|
|
89
|
+
declare type CompatibilityEventHandler = EventHandler | Handler | Middleware;
|
|
90
|
+
|
|
91
|
+
interface Layer {
|
|
92
|
+
route: string;
|
|
93
|
+
match?: Matcher;
|
|
94
|
+
handler: EventHandler;
|
|
95
|
+
}
|
|
96
|
+
declare type Stack = Layer[];
|
|
97
|
+
interface InputLayer {
|
|
98
|
+
route?: string;
|
|
99
|
+
match?: Matcher;
|
|
100
|
+
handler: Handler | LazyHandler | EventHandler | LazyEventHandler;
|
|
101
|
+
lazy?: boolean;
|
|
102
|
+
/** @deprecated */
|
|
103
|
+
handle?: Handler;
|
|
104
|
+
/** @deprecated */
|
|
105
|
+
promisify?: boolean;
|
|
106
|
+
}
|
|
107
|
+
declare type InputStack = InputLayer[];
|
|
108
|
+
declare type Matcher = (url: string, event?: CompatibilityEvent) => boolean;
|
|
109
|
+
interface AppUse {
|
|
110
|
+
(route: string | string[], handler: CompatibilityEventHandler | CompatibilityEventHandler[], options?: Partial<InputLayer>): App;
|
|
111
|
+
(handler: CompatibilityEventHandler | CompatibilityEventHandler[], options?: Partial<InputLayer>): App;
|
|
112
|
+
(options: InputLayer): App;
|
|
113
|
+
}
|
|
114
|
+
declare type NodeHandler = (req: IncomingMessage$1, res: ServerResponse$1) => Promise<void>;
|
|
115
|
+
interface App extends NodeHandler {
|
|
116
|
+
stack: Stack;
|
|
117
|
+
handler: EventHandler;
|
|
118
|
+
nodeHandler: NodeHandler;
|
|
119
|
+
use: AppUse;
|
|
120
|
+
}
|
|
121
|
+
interface AppOptions {
|
|
122
|
+
debug?: boolean;
|
|
123
|
+
onError?: (error: Error, event: CompatibilityEvent) => any;
|
|
124
|
+
}
|
|
125
|
+
declare function createApp(options?: AppOptions): App;
|
|
126
|
+
declare function use(app: App, arg1: string | Handler | InputLayer | InputLayer[], arg2?: Handler | Partial<InputLayer> | Handler[] | Middleware | Middleware[], arg3?: Partial<InputLayer>): App;
|
|
127
|
+
declare function createAppEventHandler(stack: Stack, options: AppOptions): EventHandler<void>;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* H3 Runtime Error
|
|
131
|
+
* @class
|
|
132
|
+
* @extends Error
|
|
133
|
+
* @property {Number} statusCode An Integer indicating the HTTP response status code.
|
|
134
|
+
* @property {String} statusMessage A String representing the HTTP status message
|
|
135
|
+
* @property {String} fatal Indicates if the error is a fatal error.
|
|
136
|
+
* @property {String} unhandled Indicates if the error was unhandled and auto captured.
|
|
137
|
+
* @property {Any} data An extra data that will includes in the response.<br>
|
|
138
|
+
* This can be used to pass additional information about the error.
|
|
139
|
+
* @property {Boolean} internal Setting this property to <code>true</code> will mark error as an internal error
|
|
140
|
+
*/
|
|
141
|
+
declare class H3Error extends Error {
|
|
142
|
+
static __h3_error__: boolean;
|
|
143
|
+
statusCode: number;
|
|
144
|
+
fatal: boolean;
|
|
145
|
+
unhandled: boolean;
|
|
146
|
+
statusMessage: string;
|
|
147
|
+
data?: any;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Creates new `Error` that can be used to handle both internal and runtime errors.
|
|
151
|
+
*
|
|
152
|
+
* @param input {Partial<H3Error>}
|
|
153
|
+
* @return {H3Error} An instance of the H3Error
|
|
154
|
+
*/
|
|
155
|
+
declare function createError(input: string | Partial<H3Error>): H3Error;
|
|
156
|
+
/**
|
|
157
|
+
* Receive an error and return the corresponding response.<br>
|
|
158
|
+
* H3 internally uses this function to handle unhandled errors.<br>
|
|
159
|
+
* Note that calling this function will close the connection and no other data will be sent to client afterwards.
|
|
160
|
+
*
|
|
161
|
+
@param event {CompatibilityEvent} H3 event or req passed by h3 handler
|
|
162
|
+
* @param error {H3Error|Error} Raised error
|
|
163
|
+
* @param debug {Boolean} Whether application is in debug mode.<br>
|
|
164
|
+
* In the debug mode the stack trace of errors will be return in response.
|
|
165
|
+
*/
|
|
166
|
+
declare function sendError(event: CompatibilityEvent, error: Error | H3Error, debug?: boolean): void;
|
|
167
|
+
declare function isError(input: any): input is H3Error;
|
|
168
|
+
|
|
169
|
+
declare const defineHandler: <T>(handler: Handler<T, {}>) => Handler<T, {}>;
|
|
170
|
+
/** @deprecated Use defineHandler */
|
|
171
|
+
declare const defineHandle: <T>(handler: Handler<T, {}>) => Handler<T, {}>;
|
|
172
|
+
declare const defineMiddleware: (middleware: Middleware) => Middleware;
|
|
173
|
+
declare function promisifyHandler(handler: Handler | Middleware): PromisifiedHandler;
|
|
174
|
+
/** @deprecated Use defineHandler */
|
|
175
|
+
declare const promisifyHandle: typeof promisifyHandler;
|
|
176
|
+
declare function callHandler(handler: Middleware, req: IncomingMessage, res: ServerResponse): Promise<unknown>;
|
|
177
|
+
declare function defineLazyHandler(handler: LazyHandler, promisify?: boolean): Handler;
|
|
178
|
+
/** @deprecated Use defineLazyHandler */
|
|
179
|
+
declare const lazyHandle: typeof defineLazyHandler;
|
|
180
|
+
declare function useBase(base: string, handler: Handler): Handler;
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Reads body of the request and returns encoded raw string (default) or `Buffer` if encoding if falsy.
|
|
184
|
+
* @param event {CompatibilityEvent} H3 event or req passed by h3 handler
|
|
185
|
+
* @param encoding {Encoding} encoding="utf-8" - The character encoding to use.
|
|
186
|
+
*
|
|
187
|
+
* @return {String|Buffer} Encoded raw string or raw Buffer of the body
|
|
188
|
+
*/
|
|
189
|
+
declare function readRawBody(event: CompatibilityEvent, encoding?: Encoding): Encoding extends false ? Buffer : Promise<string | Buffer>;
|
|
190
|
+
/** @deprecated Use `h3.readRawBody` */
|
|
191
|
+
declare const useRawBody: typeof readRawBody;
|
|
192
|
+
/**
|
|
193
|
+
* Reads request body and try to safely parse using [destr](https://github.com/unjs/destr)
|
|
194
|
+
* @param event {CompatibilityEvent} H3 event or req passed by h3 handler
|
|
195
|
+
* @param encoding {Encoding} encoding="utf-8" - The character encoding to use.
|
|
196
|
+
*
|
|
197
|
+
* @return {*} The `Object`, `Array`, `String`, `Number`, `Boolean`, or `null` value corresponding to the request JSON body
|
|
198
|
+
*
|
|
199
|
+
* ```ts
|
|
200
|
+
* const body = await useBody(req)
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
declare function readBody<T = any>(event: CompatibilityEvent): Promise<T>;
|
|
204
|
+
/** @deprecated Use `h3.readBody` */
|
|
205
|
+
declare const useBody: typeof readBody;
|
|
206
|
+
|
|
207
|
+
interface CacheConditions {
|
|
208
|
+
modifiedTime?: string | Date;
|
|
209
|
+
maxAge?: number;
|
|
210
|
+
etag?: string;
|
|
211
|
+
cacheControls?: string[];
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Check request caching headers (`If-Modified-Since`) and add caching headers (Last-Modified, Cache-Control)
|
|
215
|
+
* Note: `public` cache control will be added by default
|
|
216
|
+
* @returns `true` when cache headers are matching. When `true` is returned, no reponse should be sent anymore
|
|
217
|
+
*/
|
|
218
|
+
declare function handleCacheHeaders(event: CompatibilityEvent, opts: CacheConditions): boolean;
|
|
219
|
+
|
|
220
|
+
declare const MIMES: {
|
|
221
|
+
html: string;
|
|
222
|
+
json: string;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Parse the request to get HTTP Cookie header string and returning an object of all cookie name-value pairs.
|
|
227
|
+
* @param event {CompatibilityEvent} H3 event or req passed by h3 handler
|
|
228
|
+
* @returns Object of cookie name-value pairs
|
|
229
|
+
* ```ts
|
|
230
|
+
* const cookies = parseCookies(event)
|
|
231
|
+
* ```
|
|
232
|
+
*/
|
|
233
|
+
declare function parseCookies(event: CompatibilityEvent): Record<string, string>;
|
|
234
|
+
/** @deprecated Use `h3.parseCookies` */
|
|
235
|
+
declare const useCookies: typeof parseCookies;
|
|
236
|
+
/**
|
|
237
|
+
* Get a cookie value by name.
|
|
238
|
+
* @param event {CompatibilityEvent} H3 event or req passed by h3 handler
|
|
239
|
+
* @param name Name of the cookie to get
|
|
240
|
+
* @returns {*} Value of the cookie (String or undefined)
|
|
241
|
+
* ```ts
|
|
242
|
+
* const authorization = useCookie(request, 'Authorization')
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
declare function getCookie(event: CompatibilityEvent, name: string): string | undefined;
|
|
246
|
+
/** @deprecated Use `h3.getCookie` */
|
|
247
|
+
declare const useCookie: typeof getCookie;
|
|
248
|
+
/**
|
|
249
|
+
* Set a cookie value by name.
|
|
250
|
+
* @param event {CompatibilityEvent} H3 event or res passed by h3 handler
|
|
251
|
+
* @param name Name of the cookie to set
|
|
252
|
+
* @param value Value of the cookie to set
|
|
253
|
+
* @param serializeOptions {CookieSerializeOptions} Options for serializing the cookie
|
|
254
|
+
* ```ts
|
|
255
|
+
* setCookie(res, 'Authorization', '1234567')
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
declare function setCookie(event: CompatibilityEvent, name: string, value: string, serializeOptions?: CookieSerializeOptions): void;
|
|
259
|
+
/**
|
|
260
|
+
* Set a cookie value by name.
|
|
261
|
+
* @param event {CompatibilityEvent} H3 event or res passed by h3 handler
|
|
262
|
+
* @param name Name of the cookie to delete
|
|
263
|
+
* @param serializeOptions {CookieSerializeOptions} Cookie options
|
|
264
|
+
* ```ts
|
|
265
|
+
* deleteCookie(res, 'SessionId')
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
268
|
+
declare function deleteCookie(event: CompatibilityEvent, name: string, serializeOptions?: CookieSerializeOptions): void;
|
|
269
|
+
|
|
270
|
+
declare function getQuery(event: CompatibilityEvent): ufo.QueryObject;
|
|
271
|
+
/** @deprecated Use `h3.getQuery` */
|
|
272
|
+
declare const useQuery: typeof getQuery;
|
|
273
|
+
declare function getRouterParams(event: CompatibilityEvent): CompatibilityEvent['context'];
|
|
274
|
+
declare function getRouterParam(event: CompatibilityEvent, name: string): CompatibilityEvent['context'][string];
|
|
275
|
+
declare function getMethod(event: CompatibilityEvent, defaultMethod?: HTTPMethod): HTTPMethod;
|
|
276
|
+
/** @deprecated Use `h3.getMethod` */
|
|
277
|
+
declare const useMethod: typeof getMethod;
|
|
278
|
+
declare function isMethod(event: CompatibilityEvent, expected: HTTPMethod | HTTPMethod[], allowHead?: boolean): boolean;
|
|
279
|
+
declare function assertMethod(event: CompatibilityEvent, expected: HTTPMethod | HTTPMethod[], allowHead?: boolean): void;
|
|
280
|
+
declare function getRequestHeaders(event: CompatibilityEvent): CompatibilityEvent['req']['headers'];
|
|
281
|
+
declare const getHeaders: typeof getRequestHeaders;
|
|
282
|
+
declare function getRequestHeader(event: CompatibilityEvent, name: string): CompatibilityEvent['req']['headers'][string];
|
|
283
|
+
declare const getHeader: typeof getRequestHeader;
|
|
284
|
+
|
|
285
|
+
declare function send(event: CompatibilityEvent, data?: any, type?: string): Promise<void>;
|
|
286
|
+
declare function defaultContentType(event: CompatibilityEvent, type?: string): void;
|
|
287
|
+
declare function sendRedirect(event: CompatibilityEvent, location: string, code?: number): Promise<void>;
|
|
288
|
+
declare function getResponseHeaders(event: CompatibilityEvent): ReturnType<CompatibilityEvent['res']['getHeaders']>;
|
|
289
|
+
declare function getResponseHeader(event: CompatibilityEvent, name: string): ReturnType<CompatibilityEvent['res']['getHeader']>;
|
|
290
|
+
declare function setResponseHeaders(event: CompatibilityEvent, headers: Record<string, Parameters<OutgoingMessage['setHeader']>[1]>): void;
|
|
291
|
+
declare const setHeaders: typeof setResponseHeaders;
|
|
292
|
+
declare function setResponseHeader(event: CompatibilityEvent, name: string, value: Parameters<OutgoingMessage['setHeader']>[1]): void;
|
|
293
|
+
declare const setHeader: typeof setResponseHeader;
|
|
294
|
+
declare function appendResponseHeaders(event: CompatibilityEvent, headers: Record<string, string>): void;
|
|
295
|
+
declare const appendHeaders: typeof appendResponseHeaders;
|
|
296
|
+
declare function appendResponseHeader(event: CompatibilityEvent, name: string, value: string): void;
|
|
297
|
+
declare const appendHeader: typeof appendResponseHeader;
|
|
298
|
+
declare function isStream(data: any): any;
|
|
299
|
+
declare function sendStream(event: CompatibilityEvent, data: any): Promise<void>;
|
|
300
|
+
|
|
301
|
+
declare type RouterMethod = Lowercase<HTTPMethod>;
|
|
302
|
+
declare type RouterUse = (path: string, handler: CompatibilityEventHandler, method?: RouterMethod | RouterMethod[]) => Router;
|
|
303
|
+
declare type AddRouteShortcuts = Record<RouterMethod, RouterUse>;
|
|
304
|
+
interface Router extends AddRouteShortcuts {
|
|
305
|
+
add: RouterUse;
|
|
306
|
+
use: RouterUse;
|
|
307
|
+
handler: EventHandler;
|
|
308
|
+
}
|
|
309
|
+
declare function createRouter(): Router;
|
|
310
|
+
|
|
311
|
+
export { AddRouteShortcuts, App, AppOptions, AppUse, CacheConditions, CompatibilityEvent, CompatibilityEventHandler, DynamicEventHandler, Encoding, EventHandler, H3Error, H3Event, H3EventContext, H3Headers, H3Response, HTTPMethod, Handler, HandlerResponse, IncomingMessage, InputLayer, InputStack, Layer, LazyEventHandler, LazyHandler, MIMES, Matcher, Middleware, NodeHandler, PromisifiedHandler, Router, RouterMethod, RouterUse, ServerResponse, Stack, appendHeader, appendHeaders, appendResponseHeader, appendResponseHeaders, assertMethod, callHandler, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineHandle, defineHandler, defineLazyEventHandler, defineLazyHandler, defineMiddleware, deleteCookie, dynamicEventHandler, eventHandler, getCookie, getHeader, getHeaders, getMethod, getQuery, getRequestHeader, getRequestHeaders, getResponseHeader, getResponseHeaders, getRouterParam, getRouterParams, handleCacheHeaders, isError, isEvent, isEventHandler, isMethod, isStream, lazyEventHandler, lazyHandle, parseCookies, promisifyHandle, promisifyHandler, readBody, readRawBody, send, sendError, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, toEventHandler, use, useBase, useBody, useCookie, useCookies, useMethod, useQuery, useRawBody };
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
3
|
-
import 'cookie-es';
|
|
1
|
+
import { getQuery as getQuery$1, withoutTrailingSlash, withoutBase } from 'ufo';
|
|
2
|
+
import destr from 'destr';
|
|
3
|
+
import { parse, serialize } from 'cookie-es';
|
|
4
|
+
import { createRouter as createRouter$1 } from 'radix3';
|
|
4
5
|
|
|
5
6
|
class H3Error extends Error {
|
|
6
7
|
constructor() {
|
|
@@ -49,16 +50,243 @@ function createError(input) {
|
|
|
49
50
|
}
|
|
50
51
|
return err;
|
|
51
52
|
}
|
|
53
|
+
function sendError(event, error, debug) {
|
|
54
|
+
if (event.res.writableEnded) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const h3Error = isError(error) ? error : createError(error);
|
|
58
|
+
const responseBody = {
|
|
59
|
+
statusCode: h3Error.statusCode,
|
|
60
|
+
statusMessage: h3Error.statusMessage,
|
|
61
|
+
stack: [],
|
|
62
|
+
data: h3Error.data
|
|
63
|
+
};
|
|
64
|
+
if (debug) {
|
|
65
|
+
responseBody.stack = (h3Error.stack || "").split("\n").map((l) => l.trim());
|
|
66
|
+
}
|
|
67
|
+
if (event.res.writableEnded) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
event.res.statusCode = h3Error.statusCode;
|
|
71
|
+
event.res.statusMessage = h3Error.statusMessage;
|
|
72
|
+
event.res.setHeader("Content-Type", MIMES.json);
|
|
73
|
+
event.res.end(JSON.stringify(responseBody, null, 2));
|
|
74
|
+
}
|
|
52
75
|
function isError(input) {
|
|
53
76
|
return input?.constructor?.__h3_error__ === true;
|
|
54
77
|
}
|
|
55
78
|
|
|
79
|
+
function getQuery(event) {
|
|
80
|
+
return getQuery$1(event.req.url || "");
|
|
81
|
+
}
|
|
82
|
+
const useQuery = getQuery;
|
|
83
|
+
function getRouterParams(event) {
|
|
84
|
+
return event.context.params || {};
|
|
85
|
+
}
|
|
86
|
+
function getRouterParam(event, name) {
|
|
87
|
+
const params = getRouterParams(event);
|
|
88
|
+
return params[name];
|
|
89
|
+
}
|
|
90
|
+
function getMethod(event, defaultMethod = "GET") {
|
|
91
|
+
return (event.req.method || defaultMethod).toUpperCase();
|
|
92
|
+
}
|
|
93
|
+
const useMethod = getMethod;
|
|
94
|
+
function isMethod(event, expected, allowHead) {
|
|
95
|
+
const method = getMethod(event);
|
|
96
|
+
if (allowHead && method === "HEAD") {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
if (typeof expected === "string") {
|
|
100
|
+
if (method === expected) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
} else if (expected.includes(method)) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
function assertMethod(event, expected, allowHead) {
|
|
109
|
+
if (!isMethod(event, expected, allowHead)) {
|
|
110
|
+
throw createError({
|
|
111
|
+
statusCode: 405,
|
|
112
|
+
statusMessage: "HTTP method is not allowed."
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function getRequestHeaders(event) {
|
|
117
|
+
return event.req.headers;
|
|
118
|
+
}
|
|
119
|
+
const getHeaders = getRequestHeaders;
|
|
120
|
+
function getRequestHeader(event, name) {
|
|
121
|
+
const headers = getRequestHeaders(event);
|
|
122
|
+
const value = headers[name.toLowerCase()];
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
const getHeader = getRequestHeader;
|
|
126
|
+
|
|
127
|
+
const RawBodySymbol = Symbol.for("h3RawBody");
|
|
128
|
+
const ParsedBodySymbol = Symbol.for("h3ParsedBody");
|
|
129
|
+
const PayloadMethods = ["PATCH", "POST", "PUT", "DELETE"];
|
|
130
|
+
function readRawBody(event, encoding = "utf-8") {
|
|
131
|
+
assertMethod(event, PayloadMethods);
|
|
132
|
+
if (RawBodySymbol in event.req) {
|
|
133
|
+
const promise2 = Promise.resolve(event.req[RawBodySymbol]);
|
|
134
|
+
return encoding ? promise2.then((buff) => buff.toString(encoding)) : promise2;
|
|
135
|
+
}
|
|
136
|
+
if ("body" in event.req) {
|
|
137
|
+
return Promise.resolve(event.req.body);
|
|
138
|
+
}
|
|
139
|
+
const promise = event.req[RawBodySymbol] = new Promise((resolve, reject) => {
|
|
140
|
+
const bodyData = [];
|
|
141
|
+
event.req.on("error", (err) => {
|
|
142
|
+
reject(err);
|
|
143
|
+
}).on("data", (chunk) => {
|
|
144
|
+
bodyData.push(chunk);
|
|
145
|
+
}).on("end", () => {
|
|
146
|
+
resolve(Buffer.concat(bodyData));
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
return encoding ? promise.then((buff) => buff.toString(encoding)) : promise;
|
|
150
|
+
}
|
|
151
|
+
const useRawBody = readRawBody;
|
|
152
|
+
async function readBody(event) {
|
|
153
|
+
if (ParsedBodySymbol in event.req) {
|
|
154
|
+
return event.req[ParsedBodySymbol];
|
|
155
|
+
}
|
|
156
|
+
const body = await readRawBody(event);
|
|
157
|
+
if (event.req.headers["content-type"] === "application/x-www-form-urlencoded") {
|
|
158
|
+
const parsedForm = Object.fromEntries(new URLSearchParams(body));
|
|
159
|
+
return parsedForm;
|
|
160
|
+
}
|
|
161
|
+
const json = destr(body);
|
|
162
|
+
event.req[ParsedBodySymbol] = json;
|
|
163
|
+
return json;
|
|
164
|
+
}
|
|
165
|
+
const useBody = readBody;
|
|
166
|
+
|
|
167
|
+
function handleCacheHeaders(event, opts) {
|
|
168
|
+
const cacheControls = ["public"].concat(opts.cacheControls || []);
|
|
169
|
+
let cacheMatched = false;
|
|
170
|
+
if (opts.maxAge !== void 0) {
|
|
171
|
+
cacheControls.push(`max-age=${+opts.maxAge}`, `s-maxage=${+opts.maxAge}`);
|
|
172
|
+
}
|
|
173
|
+
if (opts.modifiedTime) {
|
|
174
|
+
const modifiedTime = new Date(opts.modifiedTime);
|
|
175
|
+
const ifModifiedSince = event.req.headers["if-modified-since"];
|
|
176
|
+
event.res.setHeader("Last-Modified", modifiedTime.toUTCString());
|
|
177
|
+
if (ifModifiedSince) {
|
|
178
|
+
if (new Date(ifModifiedSince) >= opts.modifiedTime) {
|
|
179
|
+
cacheMatched = true;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (opts.etag) {
|
|
184
|
+
event.res.setHeader("Etag", opts.etag);
|
|
185
|
+
const ifNonMatch = event.req.headers["if-none-match"];
|
|
186
|
+
if (ifNonMatch === opts.etag) {
|
|
187
|
+
cacheMatched = true;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
event.res.setHeader("Cache-Control", cacheControls.join(", "));
|
|
191
|
+
if (cacheMatched) {
|
|
192
|
+
event.res.statusCode = 304;
|
|
193
|
+
event.res.end("");
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
|
|
56
199
|
const MIMES = {
|
|
57
200
|
html: "text/html",
|
|
58
201
|
json: "application/json"
|
|
59
202
|
};
|
|
60
203
|
|
|
61
|
-
typeof setImmediate !== "undefined" ? setImmediate : (fn) => fn();
|
|
204
|
+
const defer = typeof setImmediate !== "undefined" ? setImmediate : (fn) => fn();
|
|
205
|
+
function send(event, data, type) {
|
|
206
|
+
if (type) {
|
|
207
|
+
defaultContentType(event, type);
|
|
208
|
+
}
|
|
209
|
+
return new Promise((resolve) => {
|
|
210
|
+
defer(() => {
|
|
211
|
+
event.res.end(data);
|
|
212
|
+
resolve(void 0);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
function defaultContentType(event, type) {
|
|
217
|
+
if (type && !event.res.getHeader("Content-Type")) {
|
|
218
|
+
event.res.setHeader("Content-Type", type);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function sendRedirect(event, location, code = 302) {
|
|
222
|
+
event.res.statusCode = code;
|
|
223
|
+
event.res.setHeader("Location", location);
|
|
224
|
+
const encodedLoc = location.replace(/"/g, "%22");
|
|
225
|
+
const html = `<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=${encodedLoc}"></head></html>`;
|
|
226
|
+
return send(event, html, MIMES.html);
|
|
227
|
+
}
|
|
228
|
+
function getResponseHeaders(event) {
|
|
229
|
+
return event.res.getHeaders();
|
|
230
|
+
}
|
|
231
|
+
function getResponseHeader(event, name) {
|
|
232
|
+
return event.res.getHeader(name);
|
|
233
|
+
}
|
|
234
|
+
function setResponseHeaders(event, headers) {
|
|
235
|
+
Object.entries(headers).forEach(([name, value]) => event.res.setHeader(name, value));
|
|
236
|
+
}
|
|
237
|
+
const setHeaders = setResponseHeaders;
|
|
238
|
+
function setResponseHeader(event, name, value) {
|
|
239
|
+
event.res.setHeader(name, value);
|
|
240
|
+
}
|
|
241
|
+
const setHeader = setResponseHeader;
|
|
242
|
+
function appendResponseHeaders(event, headers) {
|
|
243
|
+
Object.entries(headers).forEach(([name, value]) => appendResponseHeader(event, name, value));
|
|
244
|
+
}
|
|
245
|
+
const appendHeaders = appendResponseHeaders;
|
|
246
|
+
function appendResponseHeader(event, name, value) {
|
|
247
|
+
let current = event.res.getHeader(name);
|
|
248
|
+
if (!current) {
|
|
249
|
+
event.res.setHeader(name, value);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (!Array.isArray(current)) {
|
|
253
|
+
current = [current.toString()];
|
|
254
|
+
}
|
|
255
|
+
event.res.setHeader(name, current.concat(value));
|
|
256
|
+
}
|
|
257
|
+
const appendHeader = appendResponseHeader;
|
|
258
|
+
function isStream(data) {
|
|
259
|
+
return data && typeof data === "object" && typeof data.pipe === "function" && typeof data.on === "function";
|
|
260
|
+
}
|
|
261
|
+
function sendStream(event, data) {
|
|
262
|
+
return new Promise((resolve, reject) => {
|
|
263
|
+
data.pipe(event.res);
|
|
264
|
+
data.on("end", () => resolve(void 0));
|
|
265
|
+
data.on("error", (error) => reject(createError(error)));
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function parseCookies(event) {
|
|
270
|
+
return parse(event.req.headers.cookie || "");
|
|
271
|
+
}
|
|
272
|
+
const useCookies = parseCookies;
|
|
273
|
+
function getCookie(event, name) {
|
|
274
|
+
return parseCookies(event)[name];
|
|
275
|
+
}
|
|
276
|
+
const useCookie = getCookie;
|
|
277
|
+
function setCookie(event, name, value, serializeOptions) {
|
|
278
|
+
const cookieStr = serialize(name, value, {
|
|
279
|
+
path: "/",
|
|
280
|
+
...serializeOptions
|
|
281
|
+
});
|
|
282
|
+
appendHeader(event, "Set-Cookie", cookieStr);
|
|
283
|
+
}
|
|
284
|
+
function deleteCookie(event, name, serializeOptions) {
|
|
285
|
+
setCookie(event, name, "", {
|
|
286
|
+
...serializeOptions,
|
|
287
|
+
maxAge: 0
|
|
288
|
+
});
|
|
289
|
+
}
|
|
62
290
|
|
|
63
291
|
class H3Headers {
|
|
64
292
|
constructor(init) {
|
|
@@ -185,6 +413,15 @@ function createEvent(req, res) {
|
|
|
185
413
|
return new H3Event(req, res);
|
|
186
414
|
}
|
|
187
415
|
|
|
416
|
+
const defineHandler = (handler) => handler;
|
|
417
|
+
const defineHandle = defineHandler;
|
|
418
|
+
const defineMiddleware = (middleware) => middleware;
|
|
419
|
+
function promisifyHandler(handler) {
|
|
420
|
+
return function(req, res) {
|
|
421
|
+
return callHandler(handler, req, res);
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
const promisifyHandle = promisifyHandler;
|
|
188
425
|
function callHandler(handler, req, res) {
|
|
189
426
|
const isMiddleware = handler.length > 2;
|
|
190
427
|
return new Promise((resolve, reject) => {
|
|
@@ -208,6 +445,30 @@ function callHandler(handler, req, res) {
|
|
|
208
445
|
}
|
|
209
446
|
});
|
|
210
447
|
}
|
|
448
|
+
function defineLazyHandler(handler, promisify) {
|
|
449
|
+
let _promise;
|
|
450
|
+
const resolve = () => {
|
|
451
|
+
if (!_promise) {
|
|
452
|
+
_promise = Promise.resolve(handler()).then((r) => promisify ? promisifyHandler(r.default || r) : r.default || r);
|
|
453
|
+
}
|
|
454
|
+
return _promise;
|
|
455
|
+
};
|
|
456
|
+
return function(req, res) {
|
|
457
|
+
return resolve().then((h) => h(req, res));
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
const lazyHandle = defineLazyHandler;
|
|
461
|
+
function useBase(base, handler) {
|
|
462
|
+
base = withoutTrailingSlash(base);
|
|
463
|
+
if (!base) {
|
|
464
|
+
return handler;
|
|
465
|
+
}
|
|
466
|
+
return function(req, res) {
|
|
467
|
+
req.originalUrl = req.originalUrl || req.url || "/";
|
|
468
|
+
req.url = withoutBase(req.url || "/", base);
|
|
469
|
+
return handler(req, res);
|
|
470
|
+
};
|
|
471
|
+
}
|
|
211
472
|
|
|
212
473
|
function defineEventHandler(handler) {
|
|
213
474
|
handler.__is_handler__ = true;
|
|
@@ -268,4 +529,161 @@ function defineLazyEventHandler(factory) {
|
|
|
268
529
|
}
|
|
269
530
|
const lazyEventHandler = defineLazyEventHandler;
|
|
270
531
|
|
|
271
|
-
|
|
532
|
+
function createApp(options = {}) {
|
|
533
|
+
const stack = [];
|
|
534
|
+
const handler = createAppEventHandler(stack, options);
|
|
535
|
+
const nodeHandler = async function(req, res) {
|
|
536
|
+
const event = createEvent(req, res);
|
|
537
|
+
try {
|
|
538
|
+
await handler(event);
|
|
539
|
+
} catch (_error) {
|
|
540
|
+
const error = createError(_error);
|
|
541
|
+
if (!isError(_error)) {
|
|
542
|
+
error.unhandled = true;
|
|
543
|
+
}
|
|
544
|
+
if (options.onError) {
|
|
545
|
+
await options.onError(error, event);
|
|
546
|
+
} else {
|
|
547
|
+
if (error.unhandled || error.fatal) {
|
|
548
|
+
console.error("[h3]", error.fatal ? "[fatal]" : "[unhandled]", error);
|
|
549
|
+
}
|
|
550
|
+
await sendError(event, error, !!options.debug);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
const app = nodeHandler;
|
|
555
|
+
app.nodeHandler = nodeHandler;
|
|
556
|
+
app.stack = stack;
|
|
557
|
+
app.handler = handler;
|
|
558
|
+
app.use = (arg1, arg2, arg3) => use(app, arg1, arg2, arg3);
|
|
559
|
+
return app;
|
|
560
|
+
}
|
|
561
|
+
function use(app, arg1, arg2, arg3) {
|
|
562
|
+
if (Array.isArray(arg1)) {
|
|
563
|
+
arg1.forEach((i) => use(app, i, arg2, arg3));
|
|
564
|
+
} else if (Array.isArray(arg2)) {
|
|
565
|
+
arg2.forEach((i) => use(app, arg1, i, arg3));
|
|
566
|
+
} else if (typeof arg1 === "string") {
|
|
567
|
+
app.stack.push(normalizeLayer({ ...arg3, route: arg1, handler: arg2 }));
|
|
568
|
+
} else if (typeof arg1 === "function") {
|
|
569
|
+
app.stack.push(normalizeLayer({ ...arg2, route: "/", handler: arg1 }));
|
|
570
|
+
} else {
|
|
571
|
+
app.stack.push(normalizeLayer({ ...arg1 }));
|
|
572
|
+
}
|
|
573
|
+
return app;
|
|
574
|
+
}
|
|
575
|
+
function createAppEventHandler(stack, options) {
|
|
576
|
+
const spacing = options.debug ? 2 : void 0;
|
|
577
|
+
return eventHandler(async (event) => {
|
|
578
|
+
event.req.originalUrl = event.req.originalUrl || event.req.url || "/";
|
|
579
|
+
const reqUrl = event.req.url || "/";
|
|
580
|
+
for (const layer of stack) {
|
|
581
|
+
if (layer.route.length > 1) {
|
|
582
|
+
if (!reqUrl.startsWith(layer.route)) {
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
event.req.url = reqUrl.slice(layer.route.length) || "/";
|
|
586
|
+
} else {
|
|
587
|
+
event.req.url = reqUrl;
|
|
588
|
+
}
|
|
589
|
+
if (layer.match && !layer.match(event.req.url, event)) {
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
const val = await layer.handler(event);
|
|
593
|
+
if (event.res.writableEnded) {
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
const type = typeof val;
|
|
597
|
+
if (type === "string") {
|
|
598
|
+
return send(event, val, MIMES.html);
|
|
599
|
+
} else if (isStream(val)) {
|
|
600
|
+
return sendStream(event, val);
|
|
601
|
+
} else if (val === null) {
|
|
602
|
+
event.res.statusCode = 204;
|
|
603
|
+
return send(event);
|
|
604
|
+
} else if (type === "object" || type === "boolean" || type === "number") {
|
|
605
|
+
if (val.buffer) {
|
|
606
|
+
return send(event, val);
|
|
607
|
+
} else if (val instanceof Error) {
|
|
608
|
+
throw createError(val);
|
|
609
|
+
} else {
|
|
610
|
+
return send(event, JSON.stringify(val, null, spacing), MIMES.json);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
if (!event.res.writableEnded) {
|
|
615
|
+
throw createError({ statusCode: 404, statusMessage: "Not Found" });
|
|
616
|
+
}
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
function normalizeLayer(input) {
|
|
620
|
+
let handler = input.handler || input.handle;
|
|
621
|
+
if (handler.handler) {
|
|
622
|
+
handler = handler.handler;
|
|
623
|
+
}
|
|
624
|
+
if (input.lazy) {
|
|
625
|
+
handler = lazyEventHandler(handler);
|
|
626
|
+
} else if (!isEventHandler(handler)) {
|
|
627
|
+
handler = toEventHandler(handler);
|
|
628
|
+
}
|
|
629
|
+
return {
|
|
630
|
+
route: withoutTrailingSlash(input.route),
|
|
631
|
+
match: input.match,
|
|
632
|
+
handler
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
const RouterMethods = ["connect", "delete", "get", "head", "options", "post", "put", "trace", "patch"];
|
|
637
|
+
function createRouter() {
|
|
638
|
+
const _router = createRouter$1({});
|
|
639
|
+
const routes = {};
|
|
640
|
+
const router = {};
|
|
641
|
+
const addRoute = (path, handler, method) => {
|
|
642
|
+
let route = routes[path];
|
|
643
|
+
if (!route) {
|
|
644
|
+
routes[path] = route = { handlers: {} };
|
|
645
|
+
_router.insert(path, route);
|
|
646
|
+
}
|
|
647
|
+
if (Array.isArray(method)) {
|
|
648
|
+
method.forEach((m) => addRoute(path, handler, m));
|
|
649
|
+
} else {
|
|
650
|
+
route.handlers[method] = toEventHandler(handler);
|
|
651
|
+
}
|
|
652
|
+
return router;
|
|
653
|
+
};
|
|
654
|
+
router.use = router.add = (path, handler, method) => addRoute(path, handler, method || "all");
|
|
655
|
+
for (const method of RouterMethods) {
|
|
656
|
+
router[method] = (path, handle) => router.add(path, handle, method);
|
|
657
|
+
}
|
|
658
|
+
router.handler = eventHandler((event) => {
|
|
659
|
+
let path = event.req.url || "/";
|
|
660
|
+
const queryUrlIndex = path.lastIndexOf("?");
|
|
661
|
+
if (queryUrlIndex > -1) {
|
|
662
|
+
path = path.substring(0, queryUrlIndex);
|
|
663
|
+
}
|
|
664
|
+
const matched = _router.lookup(path);
|
|
665
|
+
if (!matched) {
|
|
666
|
+
throw createError({
|
|
667
|
+
statusCode: 404,
|
|
668
|
+
name: "Not Found",
|
|
669
|
+
statusMessage: `Cannot find any route matching ${event.req.url || "/"}.`
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
const method = (event.req.method || "get").toLowerCase();
|
|
673
|
+
const handler = matched.handlers[method] || matched.handlers.all;
|
|
674
|
+
if (!handler) {
|
|
675
|
+
throw createError({
|
|
676
|
+
statusCode: 405,
|
|
677
|
+
name: "Method Not Allowed",
|
|
678
|
+
statusMessage: `Method ${method} is not allowed on this route.`
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
const params = matched.params || {};
|
|
682
|
+
event.event.context.params = params;
|
|
683
|
+
event.req.context.params = params;
|
|
684
|
+
return handler(event);
|
|
685
|
+
});
|
|
686
|
+
return router;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
export { H3Error, H3Event, H3Headers, H3Response, MIMES, appendHeader, appendHeaders, appendResponseHeader, appendResponseHeaders, assertMethod, callHandler, createApp, createAppEventHandler, createError, createEvent, createRouter, defaultContentType, defineEventHandler, defineHandle, defineHandler, defineLazyEventHandler, defineLazyHandler, defineMiddleware, deleteCookie, dynamicEventHandler, eventHandler, getCookie, getHeader, getHeaders, getMethod, getQuery, getRequestHeader, getRequestHeaders, getResponseHeader, getResponseHeaders, getRouterParam, getRouterParams, handleCacheHeaders, isError, isEvent, isEventHandler, isMethod, isStream, lazyEventHandler, lazyHandle, parseCookies, promisifyHandle, promisifyHandler, readBody, readRawBody, send, sendError, sendRedirect, sendStream, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, toEventHandler, use, useBase, useBody, useCookie, useCookies, useMethod, useQuery, useRawBody };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "h3",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.21",
|
|
4
4
|
"description": "Tiny JavaScript Server",
|
|
5
5
|
"repository": "unjs/h3",
|
|
6
6
|
"license": "MIT",
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
"require": "./dist/index.cjs"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
-
"main": "dist/index.cjs",
|
|
16
|
-
"module": "dist/index.mjs",
|
|
17
|
-
"types": "dist/index.d.ts",
|
|
15
|
+
"main": "./dist/index.cjs",
|
|
16
|
+
"module": "./dist/index.mjs",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
18
|
"files": [
|
|
19
19
|
"dist"
|
|
20
20
|
],
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@types/supertest": "^2.0.12",
|
|
33
33
|
"@vitest/coverage-c8": "^0.22.1",
|
|
34
34
|
"autocannon": "^7.9.0",
|
|
35
|
-
"changelogen": "^0.
|
|
35
|
+
"changelogen": "^0.3.0",
|
|
36
36
|
"connect": "^3.7.0",
|
|
37
37
|
"eslint": "^8.23.0",
|
|
38
38
|
"express": "^4.18.1",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"listhen": "^0.2.15",
|
|
42
42
|
"supertest": "^6.2.4",
|
|
43
43
|
"typescript": "^4.8.2",
|
|
44
|
-
"unbuild": "^0.8.
|
|
44
|
+
"unbuild": "^0.8.10",
|
|
45
45
|
"vitest": "^0.22.1"
|
|
46
46
|
},
|
|
47
47
|
"packageManager": "pnpm@7.9.5",
|