hono 4.11.7 → 4.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/aws-lambda/conninfo.js +23 -0
- package/dist/adapter/aws-lambda/index.js +2 -0
- package/dist/adapter/cloudflare-pages/conninfo.js +9 -0
- package/dist/adapter/cloudflare-pages/index.js +2 -0
- package/dist/adapter/netlify/conninfo.js +9 -0
- package/dist/adapter/netlify/mod.js +2 -0
- package/dist/cjs/adapter/aws-lambda/conninfo.js +46 -0
- package/dist/cjs/adapter/aws-lambda/index.js +3 -0
- package/dist/cjs/adapter/cloudflare-pages/conninfo.js +32 -0
- package/dist/cjs/adapter/cloudflare-pages/index.js +3 -0
- package/dist/cjs/adapter/netlify/conninfo.js +32 -0
- package/dist/cjs/adapter/netlify/mod.js +3 -0
- package/dist/cjs/client/client.js +8 -2
- package/dist/cjs/context.js +11 -7
- package/dist/cjs/helper/ssg/index.js +5 -0
- package/dist/cjs/helper/ssg/plugins.js +71 -0
- package/dist/cjs/helper/ssg/ssg.js +2 -11
- package/dist/cjs/jsx/context.js +4 -2
- package/dist/cjs/jsx/dom/render.js +7 -9
- package/dist/cjs/middleware/basic-auth/index.js +6 -0
- package/dist/cjs/middleware/bearer-auth/index.js +1 -1
- package/dist/cjs/middleware/language/language.js +13 -2
- package/dist/cjs/middleware/trailing-slash/index.js +18 -4
- package/dist/cjs/router/trie-router/node.js +33 -16
- package/dist/cjs/utils/buffer.js +29 -2
- package/dist/cjs/utils/url.js +4 -2
- package/dist/client/client.js +8 -2
- package/dist/context.js +11 -7
- package/dist/helper/ssg/index.js +3 -0
- package/dist/helper/ssg/plugins.js +47 -0
- package/dist/helper/ssg/ssg.js +2 -10
- package/dist/jsx/context.js +4 -2
- package/dist/jsx/dom/render.js +7 -9
- package/dist/middleware/basic-auth/index.js +6 -0
- package/dist/middleware/bearer-auth/index.js +1 -1
- package/dist/middleware/language/language.js +13 -2
- package/dist/middleware/trailing-slash/index.js +18 -4
- package/dist/router/trie-router/node.js +33 -16
- package/dist/types/adapter/aws-lambda/conninfo.d.ts +27 -0
- package/dist/types/adapter/aws-lambda/index.d.ts +1 -0
- package/dist/types/adapter/cloudflare-pages/conninfo.d.ts +21 -0
- package/dist/types/adapter/cloudflare-pages/index.d.ts +1 -0
- package/dist/types/adapter/netlify/conninfo.d.ts +21 -0
- package/dist/types/adapter/netlify/mod.d.ts +1 -0
- package/dist/types/client/types.d.ts +39 -1
- package/dist/types/context.d.ts +4 -0
- package/dist/types/helper/ssg/index.d.ts +1 -0
- package/dist/types/helper/ssg/plugins.d.ts +27 -0
- package/dist/types/helper/ssg/ssg.d.ts +0 -8
- package/dist/types/middleware/basic-auth/index.d.ts +19 -0
- package/dist/types/middleware/jwt/jwt.d.ts +1 -1
- package/dist/types/middleware/trailing-slash/index.d.ts +43 -2
- package/dist/types/utils/buffer.d.ts +10 -1
- package/dist/utils/buffer.js +29 -2
- package/dist/utils/url.js +4 -2
- package/package.json +2 -2
|
@@ -24,6 +24,12 @@ module.exports = __toCommonJS(node_exports);
|
|
|
24
24
|
var import_router = require("../../router");
|
|
25
25
|
var import_url = require("../../utils/url");
|
|
26
26
|
const emptyParams = /* @__PURE__ */ Object.create(null);
|
|
27
|
+
const hasChildren = (children) => {
|
|
28
|
+
for (const _ in children) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
};
|
|
27
33
|
class Node {
|
|
28
34
|
#methods;
|
|
29
35
|
#children;
|
|
@@ -73,8 +79,7 @@ class Node {
|
|
|
73
79
|
});
|
|
74
80
|
return curNode;
|
|
75
81
|
}
|
|
76
|
-
#
|
|
77
|
-
const handlerSets = [];
|
|
82
|
+
#pushHandlerSets(handlerSets, node, method, nodeParams, params) {
|
|
78
83
|
for (let i = 0, len = node.#methods.length; i < len; i++) {
|
|
79
84
|
const m = node.#methods[i];
|
|
80
85
|
const handlerSet = m[method] || m[import_router.METHOD_NAME_ALL];
|
|
@@ -92,7 +97,6 @@ class Node {
|
|
|
92
97
|
}
|
|
93
98
|
}
|
|
94
99
|
}
|
|
95
|
-
return handlerSets;
|
|
96
100
|
}
|
|
97
101
|
search(method, path) {
|
|
98
102
|
const handlerSets = [];
|
|
@@ -101,7 +105,9 @@ class Node {
|
|
|
101
105
|
let curNodes = [curNode];
|
|
102
106
|
const parts = (0, import_url.splitPath)(path);
|
|
103
107
|
const curNodesQueue = [];
|
|
104
|
-
|
|
108
|
+
const len = parts.length;
|
|
109
|
+
let partOffsets = null;
|
|
110
|
+
for (let i = 0; i < len; i++) {
|
|
105
111
|
const part = parts[i];
|
|
106
112
|
const isLast = i === len - 1;
|
|
107
113
|
const tempNodes = [];
|
|
@@ -112,11 +118,9 @@ class Node {
|
|
|
112
118
|
nextNode.#params = node.#params;
|
|
113
119
|
if (isLast) {
|
|
114
120
|
if (nextNode.#children["*"]) {
|
|
115
|
-
handlerSets
|
|
116
|
-
...this.#getHandlerSets(nextNode.#children["*"], method, node.#params)
|
|
117
|
-
);
|
|
121
|
+
this.#pushHandlerSets(handlerSets, nextNode.#children["*"], method, node.#params);
|
|
118
122
|
}
|
|
119
|
-
|
|
123
|
+
this.#pushHandlerSets(handlerSets, nextNode, method, node.#params);
|
|
120
124
|
} else {
|
|
121
125
|
tempNodes.push(nextNode);
|
|
122
126
|
}
|
|
@@ -127,7 +131,7 @@ class Node {
|
|
|
127
131
|
if (pattern === "*") {
|
|
128
132
|
const astNode = node.#children["*"];
|
|
129
133
|
if (astNode) {
|
|
130
|
-
|
|
134
|
+
this.#pushHandlerSets(handlerSets, astNode, method, node.#params);
|
|
131
135
|
astNode.#params = params;
|
|
132
136
|
tempNodes.push(astNode);
|
|
133
137
|
}
|
|
@@ -138,13 +142,21 @@ class Node {
|
|
|
138
142
|
continue;
|
|
139
143
|
}
|
|
140
144
|
const child = node.#children[key];
|
|
141
|
-
const restPathString = parts.slice(i).join("/");
|
|
142
145
|
if (matcher instanceof RegExp) {
|
|
146
|
+
if (partOffsets === null) {
|
|
147
|
+
partOffsets = new Array(len);
|
|
148
|
+
let offset = path[0] === "/" ? 1 : 0;
|
|
149
|
+
for (let p = 0; p < len; p++) {
|
|
150
|
+
partOffsets[p] = offset;
|
|
151
|
+
offset += parts[p].length + 1;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const restPathString = path.substring(partOffsets[i]);
|
|
143
155
|
const m = matcher.exec(restPathString);
|
|
144
156
|
if (m) {
|
|
145
157
|
params[name] = m[0];
|
|
146
|
-
|
|
147
|
-
if (
|
|
158
|
+
this.#pushHandlerSets(handlerSets, child, method, node.#params, params);
|
|
159
|
+
if (hasChildren(child.#children)) {
|
|
148
160
|
child.#params = params;
|
|
149
161
|
const componentCount = m[0].match(/\//)?.length ?? 0;
|
|
150
162
|
const targetCurNodes = curNodesQueue[componentCount] ||= [];
|
|
@@ -156,10 +168,14 @@ class Node {
|
|
|
156
168
|
if (matcher === true || matcher.test(part)) {
|
|
157
169
|
params[name] = part;
|
|
158
170
|
if (isLast) {
|
|
159
|
-
|
|
171
|
+
this.#pushHandlerSets(handlerSets, child, method, params, node.#params);
|
|
160
172
|
if (child.#children["*"]) {
|
|
161
|
-
|
|
162
|
-
|
|
173
|
+
this.#pushHandlerSets(
|
|
174
|
+
handlerSets,
|
|
175
|
+
child.#children["*"],
|
|
176
|
+
method,
|
|
177
|
+
params,
|
|
178
|
+
node.#params
|
|
163
179
|
);
|
|
164
180
|
}
|
|
165
181
|
} else {
|
|
@@ -169,7 +185,8 @@ class Node {
|
|
|
169
185
|
}
|
|
170
186
|
}
|
|
171
187
|
}
|
|
172
|
-
|
|
188
|
+
const shifted = curNodesQueue.shift();
|
|
189
|
+
curNodes = shifted ? tempNodes.concat(shifted) : tempNodes;
|
|
173
190
|
}
|
|
174
191
|
if (handlerSets.length > 1) {
|
|
175
192
|
handlerSets.sort((a, b) => {
|
package/dist/cjs/utils/buffer.js
CHANGED
|
@@ -42,15 +42,42 @@ const equal = (a, b) => {
|
|
|
42
42
|
}
|
|
43
43
|
return true;
|
|
44
44
|
};
|
|
45
|
+
const constantTimeEqualString = (a, b) => {
|
|
46
|
+
const aLen = a.length;
|
|
47
|
+
const bLen = b.length;
|
|
48
|
+
const maxLen = Math.max(aLen, bLen);
|
|
49
|
+
let out = aLen ^ bLen;
|
|
50
|
+
for (let i = 0; i < maxLen; i++) {
|
|
51
|
+
const aChar = i < aLen ? a.charCodeAt(i) : 0;
|
|
52
|
+
const bChar = i < bLen ? b.charCodeAt(i) : 0;
|
|
53
|
+
out |= aChar ^ bChar;
|
|
54
|
+
}
|
|
55
|
+
return out === 0;
|
|
56
|
+
};
|
|
57
|
+
const timingSafeEqualString = async (a, b, hashFunction) => {
|
|
58
|
+
if (!hashFunction) {
|
|
59
|
+
hashFunction = import_crypto.sha256;
|
|
60
|
+
}
|
|
61
|
+
const [sa, sb] = await Promise.all([hashFunction(a), hashFunction(b)]);
|
|
62
|
+
if (sa == null || sb == null || typeof sa !== "string" || typeof sb !== "string") {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
const hashEqual = constantTimeEqualString(sa, sb);
|
|
66
|
+
const originalEqual = constantTimeEqualString(a, b);
|
|
67
|
+
return hashEqual && originalEqual;
|
|
68
|
+
};
|
|
45
69
|
const timingSafeEqual = async (a, b, hashFunction) => {
|
|
70
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
71
|
+
return timingSafeEqualString(a, b, hashFunction);
|
|
72
|
+
}
|
|
46
73
|
if (!hashFunction) {
|
|
47
74
|
hashFunction = import_crypto.sha256;
|
|
48
75
|
}
|
|
49
76
|
const [sa, sb] = await Promise.all([hashFunction(a), hashFunction(b)]);
|
|
50
|
-
if (!sa || !sb) {
|
|
77
|
+
if (!sa || !sb || typeof sa !== "string" || typeof sb !== "string") {
|
|
51
78
|
return false;
|
|
52
79
|
}
|
|
53
|
-
return sa
|
|
80
|
+
return timingSafeEqualString(sa, sb);
|
|
54
81
|
};
|
|
55
82
|
const bufferToString = (buffer) => {
|
|
56
83
|
if (buffer instanceof ArrayBuffer) {
|
package/dist/cjs/utils/url.js
CHANGED
|
@@ -106,9 +106,11 @@ const getPath = (request) => {
|
|
|
106
106
|
const charCode = url.charCodeAt(i);
|
|
107
107
|
if (charCode === 37) {
|
|
108
108
|
const queryIndex = url.indexOf("?", i);
|
|
109
|
-
const
|
|
109
|
+
const hashIndex = url.indexOf("#", i);
|
|
110
|
+
const end = queryIndex === -1 ? hashIndex === -1 ? void 0 : hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex);
|
|
111
|
+
const path = url.slice(start, end);
|
|
110
112
|
return tryDecodeURI(path.includes("%25") ? path.replace(/%25/g, "%2525") : path);
|
|
111
|
-
} else if (charCode === 63) {
|
|
113
|
+
} else if (charCode === 63 || charCode === 35) {
|
|
112
114
|
break;
|
|
113
115
|
}
|
|
114
116
|
}
|
package/dist/client/client.js
CHANGED
|
@@ -47,6 +47,9 @@ var ClientRequestImpl = class {
|
|
|
47
47
|
if (args.form) {
|
|
48
48
|
const form = new FormData();
|
|
49
49
|
for (const [k, v] of Object.entries(args.form)) {
|
|
50
|
+
if (v === void 0) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
50
53
|
if (Array.isArray(v)) {
|
|
51
54
|
for (const v2 of v) {
|
|
52
55
|
form.append(k, v2);
|
|
@@ -122,7 +125,7 @@ var hc = (baseUrl, options) => createProxy(function proxyCallback(opts) {
|
|
|
122
125
|
}
|
|
123
126
|
const path = parts.join("/");
|
|
124
127
|
const url = mergePath(baseUrl, path);
|
|
125
|
-
if (method === "url") {
|
|
128
|
+
if (method === "url" || method === "path") {
|
|
126
129
|
let result = url;
|
|
127
130
|
if (opts.args[0]) {
|
|
128
131
|
if (opts.args[0].param) {
|
|
@@ -133,7 +136,10 @@ var hc = (baseUrl, options) => createProxy(function proxyCallback(opts) {
|
|
|
133
136
|
}
|
|
134
137
|
}
|
|
135
138
|
result = removeIndexString(result);
|
|
136
|
-
|
|
139
|
+
if (method === "url") {
|
|
140
|
+
return new URL(result);
|
|
141
|
+
}
|
|
142
|
+
return result.slice(baseUrl.replace(/\/+$/, "").length).replace(/^\/?/, "/");
|
|
137
143
|
}
|
|
138
144
|
if (method === "ws") {
|
|
139
145
|
const webSocketUrl = replaceUrlProtocol(
|
package/dist/context.js
CHANGED
|
@@ -8,6 +8,7 @@ var setDefaultContentType = (contentType, headers) => {
|
|
|
8
8
|
...headers
|
|
9
9
|
};
|
|
10
10
|
};
|
|
11
|
+
var createResponseInstance = (body, init) => new Response(body, init);
|
|
11
12
|
var Context = class {
|
|
12
13
|
#rawRequest;
|
|
13
14
|
#req;
|
|
@@ -106,7 +107,7 @@ var Context = class {
|
|
|
106
107
|
* The Response object for the current request.
|
|
107
108
|
*/
|
|
108
109
|
get res() {
|
|
109
|
-
return this.#res ||=
|
|
110
|
+
return this.#res ||= createResponseInstance(null, {
|
|
110
111
|
headers: this.#preparedHeaders ??= new Headers()
|
|
111
112
|
});
|
|
112
113
|
}
|
|
@@ -117,7 +118,7 @@ var Context = class {
|
|
|
117
118
|
*/
|
|
118
119
|
set res(_res) {
|
|
119
120
|
if (this.#res && _res) {
|
|
120
|
-
_res =
|
|
121
|
+
_res = createResponseInstance(_res.body, _res);
|
|
121
122
|
for (const [k, v] of this.#res.headers.entries()) {
|
|
122
123
|
if (k === "content-type") {
|
|
123
124
|
continue;
|
|
@@ -207,7 +208,7 @@ var Context = class {
|
|
|
207
208
|
*/
|
|
208
209
|
header = (name, value, options) => {
|
|
209
210
|
if (this.finalized) {
|
|
210
|
-
this.#res =
|
|
211
|
+
this.#res = createResponseInstance(this.#res.body, this.#res);
|
|
211
212
|
}
|
|
212
213
|
const headers = this.#res ? this.#res.headers : this.#preparedHeaders ??= new Headers();
|
|
213
214
|
if (value === void 0) {
|
|
@@ -296,7 +297,7 @@ var Context = class {
|
|
|
296
297
|
}
|
|
297
298
|
}
|
|
298
299
|
const status = typeof arg === "number" ? arg : arg?.status ?? this.#status;
|
|
299
|
-
return
|
|
300
|
+
return createResponseInstance(data, { status, headers: responseHeaders });
|
|
300
301
|
}
|
|
301
302
|
newResponse = (...args) => this.#newResponse(...args);
|
|
302
303
|
/**
|
|
@@ -321,6 +322,9 @@ var Context = class {
|
|
|
321
322
|
* ```
|
|
322
323
|
*/
|
|
323
324
|
body = (data, arg, headers) => this.#newResponse(data, arg, headers);
|
|
325
|
+
#useFastPath() {
|
|
326
|
+
return !this.#preparedHeaders && !this.#status && !this.finalized;
|
|
327
|
+
}
|
|
324
328
|
/**
|
|
325
329
|
* `.text()` can render text as `Content-Type:text/plain`.
|
|
326
330
|
*
|
|
@@ -334,7 +338,7 @@ var Context = class {
|
|
|
334
338
|
* ```
|
|
335
339
|
*/
|
|
336
340
|
text = (text, arg, headers) => {
|
|
337
|
-
return
|
|
341
|
+
return this.#useFastPath() && !arg && !headers ? createResponseInstance(text) : this.#newResponse(
|
|
338
342
|
text,
|
|
339
343
|
arg,
|
|
340
344
|
setDefaultContentType(TEXT_PLAIN, headers)
|
|
@@ -353,7 +357,7 @@ var Context = class {
|
|
|
353
357
|
* ```
|
|
354
358
|
*/
|
|
355
359
|
json = (object, arg, headers) => {
|
|
356
|
-
return this.#newResponse(
|
|
360
|
+
return this.#useFastPath() && !arg && !headers ? Response.json(object) : this.#newResponse(
|
|
357
361
|
JSON.stringify(object),
|
|
358
362
|
arg,
|
|
359
363
|
setDefaultContentType("application/json", headers)
|
|
@@ -401,7 +405,7 @@ var Context = class {
|
|
|
401
405
|
* ```
|
|
402
406
|
*/
|
|
403
407
|
notFound = () => {
|
|
404
|
-
this.#notFoundHandler ??= () =>
|
|
408
|
+
this.#notFoundHandler ??= () => createResponseInstance();
|
|
405
409
|
return this.#notFoundHandler(this);
|
|
406
410
|
};
|
|
407
411
|
};
|
package/dist/helper/ssg/index.js
CHANGED
|
@@ -7,10 +7,13 @@ import {
|
|
|
7
7
|
disableSSG,
|
|
8
8
|
onlySSG
|
|
9
9
|
} from "./middleware.js";
|
|
10
|
+
import { defaultPlugin, redirectPlugin } from "./plugins.js";
|
|
10
11
|
export {
|
|
11
12
|
X_HONO_DISABLE_SSG_HEADER_KEY,
|
|
13
|
+
defaultPlugin,
|
|
12
14
|
disableSSG,
|
|
13
15
|
isSSGContext,
|
|
14
16
|
onlySSG,
|
|
17
|
+
redirectPlugin,
|
|
15
18
|
ssgParams
|
|
16
19
|
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// src/helper/ssg/plugins.ts
|
|
2
|
+
import { html } from "../html/index.js";
|
|
3
|
+
var defaultPlugin = () => {
|
|
4
|
+
return {
|
|
5
|
+
afterResponseHook: (res) => {
|
|
6
|
+
if (res.status !== 200) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
return res;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
var REDIRECT_STATUS_CODES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
|
|
14
|
+
var generateRedirectHtml = (location) => {
|
|
15
|
+
const content = html`<!DOCTYPE html>
|
|
16
|
+
<title>Redirecting to: ${location}</title>
|
|
17
|
+
<meta http-equiv="refresh" content="0;url=${location}" />
|
|
18
|
+
<meta name="robots" content="noindex" />
|
|
19
|
+
<link rel="canonical" href="${location}" />
|
|
20
|
+
<body>
|
|
21
|
+
<a href="${location}">Redirecting to <code>${location}</code></a>
|
|
22
|
+
</body>
|
|
23
|
+
`;
|
|
24
|
+
return content.toString().replace(/\n/g, "");
|
|
25
|
+
};
|
|
26
|
+
var redirectPlugin = () => {
|
|
27
|
+
return {
|
|
28
|
+
afterResponseHook: (res) => {
|
|
29
|
+
if (REDIRECT_STATUS_CODES.has(res.status)) {
|
|
30
|
+
const location = res.headers.get("Location");
|
|
31
|
+
if (!location) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
const htmlBody = generateRedirectHtml(location);
|
|
35
|
+
return new Response(htmlBody, {
|
|
36
|
+
status: 200,
|
|
37
|
+
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return res;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
export {
|
|
45
|
+
defaultPlugin,
|
|
46
|
+
redirectPlugin
|
|
47
|
+
};
|
package/dist/helper/ssg/ssg.js
CHANGED
|
@@ -3,6 +3,7 @@ import { replaceUrlParam } from "../../client/utils.js";
|
|
|
3
3
|
import { createPool } from "../../utils/concurrent.js";
|
|
4
4
|
import { getExtension } from "../../utils/mime.js";
|
|
5
5
|
import { SSG_CONTEXT, X_HONO_DISABLE_SSG_HEADER_KEY } from "./middleware.js";
|
|
6
|
+
import { defaultPlugin } from "./plugins.js";
|
|
6
7
|
import { dirname, filterStaticGenerateRoutes, isDynamicRoute, joinPaths } from "./utils.js";
|
|
7
8
|
var DEFAULT_CONCURRENCY = 2;
|
|
8
9
|
var DEFAULT_CONTENT_TYPE = "text/plain";
|
|
@@ -184,19 +185,11 @@ var saveContentToFile = async (data, fsModule, outDir, extensionMap) => {
|
|
|
184
185
|
}
|
|
185
186
|
return filePath;
|
|
186
187
|
};
|
|
187
|
-
var defaultPlugin = {
|
|
188
|
-
afterResponseHook: (res) => {
|
|
189
|
-
if (res.status !== 200) {
|
|
190
|
-
return false;
|
|
191
|
-
}
|
|
192
|
-
return res;
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
188
|
var toSSG = async (app, fs, options) => {
|
|
196
189
|
let result;
|
|
197
190
|
const getInfoPromises = [];
|
|
198
191
|
const savePromises = [];
|
|
199
|
-
const plugins = options?.plugins || [defaultPlugin];
|
|
192
|
+
const plugins = options?.plugins || [defaultPlugin()];
|
|
200
193
|
const beforeRequestHooks = [];
|
|
201
194
|
const afterResponseHooks = [];
|
|
202
195
|
const afterGenerateHooks = [];
|
|
@@ -288,7 +281,6 @@ export {
|
|
|
288
281
|
combineAfterResponseHooks,
|
|
289
282
|
combineBeforeRequestHooks,
|
|
290
283
|
defaultExtensionMap,
|
|
291
|
-
defaultPlugin,
|
|
292
284
|
fetchRoutesContent,
|
|
293
285
|
saveContentToFile,
|
|
294
286
|
toSSG
|
package/dist/jsx/context.js
CHANGED
|
@@ -11,12 +11,14 @@ var createContext = (defaultValue) => {
|
|
|
11
11
|
let string;
|
|
12
12
|
try {
|
|
13
13
|
string = props.children ? (Array.isArray(props.children) ? new JSXFragmentNode("", {}, props.children) : props.children).toString() : "";
|
|
14
|
-
}
|
|
14
|
+
} catch (e) {
|
|
15
15
|
values.pop();
|
|
16
|
+
throw e;
|
|
16
17
|
}
|
|
17
18
|
if (string instanceof Promise) {
|
|
18
|
-
return string.then((resString) => raw(resString, resString.callbacks));
|
|
19
|
+
return string.finally(() => values.pop()).then((resString) => raw(resString, resString.callbacks));
|
|
19
20
|
} else {
|
|
21
|
+
values.pop();
|
|
20
22
|
return raw(string);
|
|
21
23
|
}
|
|
22
24
|
});
|
package/dist/jsx/dom/render.js
CHANGED
|
@@ -184,14 +184,10 @@ var getNextChildren = (node, container, nextChildren, childrenToRemove, callback
|
|
|
184
184
|
});
|
|
185
185
|
};
|
|
186
186
|
var findInsertBefore = (node) => {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
return null;
|
|
190
|
-
}
|
|
191
|
-
if (node.tag !== HONO_PORTAL_ELEMENT && node.e) {
|
|
192
|
-
return node.e;
|
|
193
|
-
}
|
|
187
|
+
while (node && (node.tag === HONO_PORTAL_ELEMENT || !node.e)) {
|
|
188
|
+
node = node.tag === HONO_PORTAL_ELEMENT || !node.vC?.[0] ? node.nN : node.vC[0];
|
|
194
189
|
}
|
|
190
|
+
return node?.e;
|
|
195
191
|
};
|
|
196
192
|
var removeNode = (node) => {
|
|
197
193
|
if (!isNodeString(node)) {
|
|
@@ -289,7 +285,7 @@ var applyNodeObject = (node, container, isNew) => {
|
|
|
289
285
|
}
|
|
290
286
|
}
|
|
291
287
|
if (node.pP) {
|
|
292
|
-
|
|
288
|
+
node.pP = void 0;
|
|
293
289
|
}
|
|
294
290
|
if (callbacks.length) {
|
|
295
291
|
const useLayoutEffectCbs = [];
|
|
@@ -330,7 +326,9 @@ var build = (context, node, children) => {
|
|
|
330
326
|
let prevNode;
|
|
331
327
|
for (let i = 0; i < children.length; i++) {
|
|
332
328
|
if (Array.isArray(children[i])) {
|
|
333
|
-
children.splice(i, 1, ...children[i].flat());
|
|
329
|
+
children.splice(i, 1, ...children[i].flat(Infinity));
|
|
330
|
+
i--;
|
|
331
|
+
continue;
|
|
334
332
|
}
|
|
335
333
|
let child = buildNode(children[i]);
|
|
336
334
|
if (child) {
|
|
@@ -24,6 +24,9 @@ var basicAuth = (options, ...users) => {
|
|
|
24
24
|
if (requestUser) {
|
|
25
25
|
if (verifyUserInOptions) {
|
|
26
26
|
if (await options.verifyUser(requestUser.username, requestUser.password, ctx)) {
|
|
27
|
+
if (options.onAuthSuccess) {
|
|
28
|
+
await options.onAuthSuccess(ctx, requestUser.username);
|
|
29
|
+
}
|
|
27
30
|
await next();
|
|
28
31
|
return;
|
|
29
32
|
}
|
|
@@ -34,6 +37,9 @@ var basicAuth = (options, ...users) => {
|
|
|
34
37
|
timingSafeEqual(user.password, requestUser.password, options.hashFunction)
|
|
35
38
|
]);
|
|
36
39
|
if (usernameEqual && passwordEqual) {
|
|
40
|
+
if (options.onAuthSuccess) {
|
|
41
|
+
await options.onAuthSuccess(ctx, requestUser.username);
|
|
42
|
+
}
|
|
37
43
|
await next();
|
|
38
44
|
return;
|
|
39
45
|
}
|
|
@@ -16,7 +16,7 @@ var bearerAuth = (options) => {
|
|
|
16
16
|
}
|
|
17
17
|
const realm = options.realm?.replace(/"/g, '\\"');
|
|
18
18
|
const prefixRegexStr = options.prefix === "" ? "" : `${options.prefix} +`;
|
|
19
|
-
const regexp = new RegExp(`^${prefixRegexStr}(${TOKEN_STRINGS})
|
|
19
|
+
const regexp = new RegExp(`^${prefixRegexStr}(${TOKEN_STRINGS}) *$`, "i");
|
|
20
20
|
const wwwAuthenticatePrefix = options.prefix === "" ? "" : `${options.prefix} `;
|
|
21
21
|
const throwHTTPException = async (c, status, wwwAuthenticateHeader, messageOption) => {
|
|
22
22
|
const wwwAuthenticateHeaderValue = typeof wwwAuthenticateHeader === "function" ? await wwwAuthenticateHeader(c) : wwwAuthenticateHeader;
|
|
@@ -35,8 +35,19 @@ var normalizeLanguage = (lang, options) => {
|
|
|
35
35
|
const compSupported = options.supportedLanguages.map(
|
|
36
36
|
(l) => options.ignoreCase ? l.toLowerCase() : l
|
|
37
37
|
);
|
|
38
|
-
const
|
|
39
|
-
|
|
38
|
+
const exactIndex = compSupported.indexOf(compLang);
|
|
39
|
+
if (exactIndex !== -1) {
|
|
40
|
+
return options.supportedLanguages[exactIndex];
|
|
41
|
+
}
|
|
42
|
+
const parts = compLang.split("-");
|
|
43
|
+
for (let i = parts.length - 1; i > 0; i--) {
|
|
44
|
+
const candidate = parts.slice(0, i).join("-");
|
|
45
|
+
const prefixIndex = compSupported.indexOf(candidate);
|
|
46
|
+
if (prefixIndex !== -1) {
|
|
47
|
+
return options.supportedLanguages[prefixIndex];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return void 0;
|
|
40
51
|
} catch {
|
|
41
52
|
return void 0;
|
|
42
53
|
}
|
|
@@ -1,18 +1,32 @@
|
|
|
1
1
|
// src/middleware/trailing-slash/index.ts
|
|
2
|
-
var trimTrailingSlash = () => {
|
|
2
|
+
var trimTrailingSlash = (options) => {
|
|
3
3
|
return async function trimTrailingSlash2(c, next) {
|
|
4
|
+
if (options?.alwaysRedirect) {
|
|
5
|
+
if ((c.req.method === "GET" || c.req.method === "HEAD") && c.req.path !== "/" && c.req.path.at(-1) === "/") {
|
|
6
|
+
const url = new URL(c.req.url);
|
|
7
|
+
url.pathname = url.pathname.substring(0, url.pathname.length - 1);
|
|
8
|
+
return c.redirect(url.toString(), 301);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
4
11
|
await next();
|
|
5
|
-
if (c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path !== "/" && c.req.path.at(-1) === "/") {
|
|
12
|
+
if (!options?.alwaysRedirect && c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path !== "/" && c.req.path.at(-1) === "/") {
|
|
6
13
|
const url = new URL(c.req.url);
|
|
7
14
|
url.pathname = url.pathname.substring(0, url.pathname.length - 1);
|
|
8
15
|
c.res = c.redirect(url.toString(), 301);
|
|
9
16
|
}
|
|
10
17
|
};
|
|
11
18
|
};
|
|
12
|
-
var appendTrailingSlash = () => {
|
|
19
|
+
var appendTrailingSlash = (options) => {
|
|
13
20
|
return async function appendTrailingSlash2(c, next) {
|
|
21
|
+
if (options?.alwaysRedirect) {
|
|
22
|
+
if ((c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/") {
|
|
23
|
+
const url = new URL(c.req.url);
|
|
24
|
+
url.pathname += "/";
|
|
25
|
+
return c.redirect(url.toString(), 301);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
14
28
|
await next();
|
|
15
|
-
if (c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/") {
|
|
29
|
+
if (!options?.alwaysRedirect && c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/") {
|
|
16
30
|
const url = new URL(c.req.url);
|
|
17
31
|
url.pathname += "/";
|
|
18
32
|
c.res = c.redirect(url.toString(), 301);
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
import { METHOD_NAME_ALL } from "../../router.js";
|
|
3
3
|
import { getPattern, splitPath, splitRoutingPath } from "../../utils/url.js";
|
|
4
4
|
var emptyParams = /* @__PURE__ */ Object.create(null);
|
|
5
|
+
var hasChildren = (children) => {
|
|
6
|
+
for (const _ in children) {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
return false;
|
|
10
|
+
};
|
|
5
11
|
var Node = class _Node {
|
|
6
12
|
#methods;
|
|
7
13
|
#children;
|
|
@@ -51,8 +57,7 @@ var Node = class _Node {
|
|
|
51
57
|
});
|
|
52
58
|
return curNode;
|
|
53
59
|
}
|
|
54
|
-
#
|
|
55
|
-
const handlerSets = [];
|
|
60
|
+
#pushHandlerSets(handlerSets, node, method, nodeParams, params) {
|
|
56
61
|
for (let i = 0, len = node.#methods.length; i < len; i++) {
|
|
57
62
|
const m = node.#methods[i];
|
|
58
63
|
const handlerSet = m[method] || m[METHOD_NAME_ALL];
|
|
@@ -70,7 +75,6 @@ var Node = class _Node {
|
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
77
|
}
|
|
73
|
-
return handlerSets;
|
|
74
78
|
}
|
|
75
79
|
search(method, path) {
|
|
76
80
|
const handlerSets = [];
|
|
@@ -79,7 +83,9 @@ var Node = class _Node {
|
|
|
79
83
|
let curNodes = [curNode];
|
|
80
84
|
const parts = splitPath(path);
|
|
81
85
|
const curNodesQueue = [];
|
|
82
|
-
|
|
86
|
+
const len = parts.length;
|
|
87
|
+
let partOffsets = null;
|
|
88
|
+
for (let i = 0; i < len; i++) {
|
|
83
89
|
const part = parts[i];
|
|
84
90
|
const isLast = i === len - 1;
|
|
85
91
|
const tempNodes = [];
|
|
@@ -90,11 +96,9 @@ var Node = class _Node {
|
|
|
90
96
|
nextNode.#params = node.#params;
|
|
91
97
|
if (isLast) {
|
|
92
98
|
if (nextNode.#children["*"]) {
|
|
93
|
-
handlerSets
|
|
94
|
-
...this.#getHandlerSets(nextNode.#children["*"], method, node.#params)
|
|
95
|
-
);
|
|
99
|
+
this.#pushHandlerSets(handlerSets, nextNode.#children["*"], method, node.#params);
|
|
96
100
|
}
|
|
97
|
-
|
|
101
|
+
this.#pushHandlerSets(handlerSets, nextNode, method, node.#params);
|
|
98
102
|
} else {
|
|
99
103
|
tempNodes.push(nextNode);
|
|
100
104
|
}
|
|
@@ -105,7 +109,7 @@ var Node = class _Node {
|
|
|
105
109
|
if (pattern === "*") {
|
|
106
110
|
const astNode = node.#children["*"];
|
|
107
111
|
if (astNode) {
|
|
108
|
-
|
|
112
|
+
this.#pushHandlerSets(handlerSets, astNode, method, node.#params);
|
|
109
113
|
astNode.#params = params;
|
|
110
114
|
tempNodes.push(astNode);
|
|
111
115
|
}
|
|
@@ -116,13 +120,21 @@ var Node = class _Node {
|
|
|
116
120
|
continue;
|
|
117
121
|
}
|
|
118
122
|
const child = node.#children[key];
|
|
119
|
-
const restPathString = parts.slice(i).join("/");
|
|
120
123
|
if (matcher instanceof RegExp) {
|
|
124
|
+
if (partOffsets === null) {
|
|
125
|
+
partOffsets = new Array(len);
|
|
126
|
+
let offset = path[0] === "/" ? 1 : 0;
|
|
127
|
+
for (let p = 0; p < len; p++) {
|
|
128
|
+
partOffsets[p] = offset;
|
|
129
|
+
offset += parts[p].length + 1;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const restPathString = path.substring(partOffsets[i]);
|
|
121
133
|
const m = matcher.exec(restPathString);
|
|
122
134
|
if (m) {
|
|
123
135
|
params[name] = m[0];
|
|
124
|
-
|
|
125
|
-
if (
|
|
136
|
+
this.#pushHandlerSets(handlerSets, child, method, node.#params, params);
|
|
137
|
+
if (hasChildren(child.#children)) {
|
|
126
138
|
child.#params = params;
|
|
127
139
|
const componentCount = m[0].match(/\//)?.length ?? 0;
|
|
128
140
|
const targetCurNodes = curNodesQueue[componentCount] ||= [];
|
|
@@ -134,10 +146,14 @@ var Node = class _Node {
|
|
|
134
146
|
if (matcher === true || matcher.test(part)) {
|
|
135
147
|
params[name] = part;
|
|
136
148
|
if (isLast) {
|
|
137
|
-
|
|
149
|
+
this.#pushHandlerSets(handlerSets, child, method, params, node.#params);
|
|
138
150
|
if (child.#children["*"]) {
|
|
139
|
-
|
|
140
|
-
|
|
151
|
+
this.#pushHandlerSets(
|
|
152
|
+
handlerSets,
|
|
153
|
+
child.#children["*"],
|
|
154
|
+
method,
|
|
155
|
+
params,
|
|
156
|
+
node.#params
|
|
141
157
|
);
|
|
142
158
|
}
|
|
143
159
|
} else {
|
|
@@ -147,7 +163,8 @@ var Node = class _Node {
|
|
|
147
163
|
}
|
|
148
164
|
}
|
|
149
165
|
}
|
|
150
|
-
|
|
166
|
+
const shifted = curNodesQueue.shift();
|
|
167
|
+
curNodes = shifted ? tempNodes.concat(shifted) : tempNodes;
|
|
151
168
|
}
|
|
152
169
|
if (handlerSets.length > 1) {
|
|
153
170
|
handlerSets.sort((a, b) => {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { GetConnInfo } from '../../helper/conninfo';
|
|
2
|
+
/**
|
|
3
|
+
* Get connection information from AWS Lambda
|
|
4
|
+
*
|
|
5
|
+
* Extracts client IP from various Lambda event sources:
|
|
6
|
+
* - API Gateway v1 (REST API): requestContext.identity.sourceIp
|
|
7
|
+
* - API Gateway v2 (HTTP API/Function URLs): requestContext.http.sourceIp
|
|
8
|
+
* - ALB: Falls back to x-forwarded-for header
|
|
9
|
+
*
|
|
10
|
+
* @param c - Context
|
|
11
|
+
* @returns Connection information including remote address
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { Hono } from 'hono'
|
|
15
|
+
* import { handle, getConnInfo } from 'hono/aws-lambda'
|
|
16
|
+
*
|
|
17
|
+
* const app = new Hono()
|
|
18
|
+
*
|
|
19
|
+
* app.get('/', (c) => {
|
|
20
|
+
* const info = getConnInfo(c)
|
|
21
|
+
* return c.text(`Your IP: ${info.remote.address}`)
|
|
22
|
+
* })
|
|
23
|
+
*
|
|
24
|
+
* export const handler = handle(app)
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare const getConnInfo: GetConnInfo;
|