hono 4.12.34 → 4.13.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.
Files changed (56) hide show
  1. package/dist/cjs/context.js +28 -13
  2. package/dist/cjs/hono-base.js +3 -2
  3. package/dist/cjs/jsx/base.js +26 -14
  4. package/dist/cjs/jsx/hooks/index.js +2 -2
  5. package/dist/cjs/middleware/cache/index.js +103 -8
  6. package/dist/cjs/middleware/compress/index.js +5 -0
  7. package/dist/cjs/middleware/cors/index.js +1 -1
  8. package/dist/cjs/middleware/etag/index.js +1 -1
  9. package/dist/cjs/middleware/jwk/jwk.js +9 -4
  10. package/dist/cjs/middleware/jwt/jwt.js +9 -4
  11. package/dist/cjs/middleware/method-not-allowed/index.js +90 -0
  12. package/dist/cjs/request.js +6 -8
  13. package/dist/cjs/router/reg-exp-router/node.js +55 -56
  14. package/dist/cjs/router/reg-exp-router/router.js +64 -85
  15. package/dist/cjs/router/reg-exp-router/trie.js +13 -5
  16. package/dist/cjs/router.js +1 -1
  17. package/dist/cjs/utils/cookie.js +1 -1
  18. package/dist/cjs/utils/url.js +7 -7
  19. package/dist/context.js +28 -13
  20. package/dist/hono-base.js +3 -2
  21. package/dist/jsx/base.js +26 -14
  22. package/dist/jsx/hooks/index.js +2 -2
  23. package/dist/middleware/cache/index.js +103 -8
  24. package/dist/middleware/compress/index.js +5 -0
  25. package/dist/middleware/cors/index.js +1 -1
  26. package/dist/middleware/etag/index.js +1 -1
  27. package/dist/middleware/jwk/jwk.js +9 -4
  28. package/dist/middleware/jwt/jwt.js +9 -4
  29. package/dist/middleware/method-not-allowed/index.js +68 -0
  30. package/dist/request.js +7 -9
  31. package/dist/router/reg-exp-router/node.js +55 -56
  32. package/dist/router/reg-exp-router/router.js +64 -85
  33. package/dist/router/reg-exp-router/trie.js +13 -5
  34. package/dist/router.js +1 -1
  35. package/dist/types/client/types.d.ts +1 -1
  36. package/dist/types/hono-base.d.ts +4 -3
  37. package/dist/types/jsx/base.d.ts +4 -2
  38. package/dist/types/jsx/dom/index.d.ts +5 -5
  39. package/dist/types/jsx/dom/intrinsic-element/components.d.ts +2 -2
  40. package/dist/types/jsx/dom/server.d.ts +5 -5
  41. package/dist/types/jsx/hooks/index.d.ts +8 -6
  42. package/dist/types/jsx/index.d.ts +5 -5
  43. package/dist/types/middleware/cache/index.d.ts +6 -4
  44. package/dist/types/middleware/cors/index.d.ts +1 -1
  45. package/dist/types/middleware/jsx-renderer/index.d.ts +2 -2
  46. package/dist/types/middleware/jwk/jwk.d.ts +2 -0
  47. package/dist/types/middleware/jwt/jwt.d.ts +2 -0
  48. package/dist/types/middleware/method-not-allowed/index.d.ts +49 -0
  49. package/dist/types/router/reg-exp-router/node.d.ts +1 -1
  50. package/dist/types/router/reg-exp-router/trie.d.ts +2 -1
  51. package/dist/types/router.d.ts +1 -1
  52. package/dist/types/utils/headers.d.ts +2 -2
  53. package/dist/types/utils/url.d.ts +1 -0
  54. package/dist/utils/cookie.js +2 -2
  55. package/dist/utils/url.js +5 -6
  56. package/package.json +9 -1
@@ -34,7 +34,7 @@ function compareKey(a, b) {
34
34
  return 1;
35
35
  }
36
36
  if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) {
37
- return 1;
37
+ return b === TAIL_WILDCARD_REG_EXP_STR ? -1 : 1;
38
38
  } else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) {
39
39
  return -1;
40
40
  }
@@ -46,76 +46,75 @@ function compareKey(a, b) {
46
46
  return a.length === b.length ? a < b ? -1 : 1 : b.length - a.length;
47
47
  }
48
48
  class Node {
49
+ // handler index of a dynamic path, or -1 for a static path terminal
49
50
  #index;
50
51
  #varIndex;
51
52
  #children = /* @__PURE__ */ Object.create(null);
52
- insert(tokens, index, paramMap, context, pathErrorCheckOnly) {
53
- if (tokens.length === 0) {
54
- if (this.#index !== void 0) {
55
- throw PATH_ERROR;
56
- }
57
- if (pathErrorCheckOnly) {
58
- return;
59
- }
60
- this.#index = index;
61
- return;
62
- }
63
- const [token, ...restTokens] = tokens;
64
- const pattern = token === "*" ? restTokens.length === 0 ? ["", "", ONLY_WILDCARD_REG_EXP_STR] : ["", "", LABEL_REG_EXP_STR] : token === "/*" ? ["", "", TAIL_WILDCARD_REG_EXP_STR] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
65
- let node;
66
- if (pattern) {
67
- const name = pattern[1];
68
- let regexpStr = pattern[2] || LABEL_REG_EXP_STR;
69
- if (name && pattern[2]) {
70
- if (regexpStr === ".*") {
71
- throw PATH_ERROR;
72
- }
73
- regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:");
74
- if (/\((?!\?:)/.test(regexpStr)) {
75
- throw PATH_ERROR;
53
+ insert(tokens, index, paramMap, context, isStatic) {
54
+ let node = this;
55
+ for (let i = 0, len = tokens.length; i < len; i++) {
56
+ const token = tokens[i];
57
+ const pattern = token.length === 1 ? token === "*" ? i === len - 1 ? ["", "", ONLY_WILDCARD_REG_EXP_STR] : ["", "", LABEL_REG_EXP_STR] : null : token === "/*" ? ["", "", TAIL_WILDCARD_REG_EXP_STR] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
58
+ let nextNode;
59
+ if (pattern) {
60
+ const name = pattern[1];
61
+ let regexpStr = pattern[2] || LABEL_REG_EXP_STR;
62
+ if (name && pattern[2]) {
63
+ if (regexpStr === ".*") {
64
+ throw PATH_ERROR;
65
+ }
66
+ regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:");
67
+ if (/\((?!\?:)/.test(regexpStr)) {
68
+ throw PATH_ERROR;
69
+ }
70
+ if (regexpStr.length === 1 && regExpMetaChars.has(regexpStr)) {
71
+ throw PATH_ERROR;
72
+ }
76
73
  }
77
- }
78
- node = this.#children[regexpStr];
79
- if (!node) {
80
- if (Object.keys(this.#children).some(
81
- (k) => k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
82
- )) {
83
- throw PATH_ERROR;
74
+ nextNode = node.#children[regexpStr];
75
+ if (!nextNode) {
76
+ if (regexpStr !== ONLY_WILDCARD_REG_EXP_STR && regexpStr !== TAIL_WILDCARD_REG_EXP_STR) {
77
+ for (const k in node.#children) {
78
+ if (
79
+ // a single-char pattern coexists with single-char literals as a literal does
80
+ (regexpStr.length > 1 || k.length > 1) && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
81
+ ) {
82
+ throw PATH_ERROR;
83
+ }
84
+ }
85
+ }
86
+ nextNode = node.#children[regexpStr] = new Node();
84
87
  }
85
- if (pathErrorCheckOnly) {
86
- return;
87
- }
88
- node = this.#children[regexpStr] = new Node();
89
88
  if (name !== "") {
90
- node.#varIndex = context.varIndex++;
89
+ nextNode.#varIndex ??= context.varIndex++;
90
+ paramMap.push([name, nextNode.#varIndex]);
91
91
  }
92
- }
93
- if (!pathErrorCheckOnly && name !== "") {
94
- paramMap.push([name, node.#varIndex]);
95
- }
96
- } else {
97
- node = this.#children[token];
98
- if (!node) {
99
- if (Object.keys(this.#children).some(
100
- (k) => k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
101
- )) {
102
- throw PATH_ERROR;
92
+ } else {
93
+ nextNode = node.#children[token];
94
+ if (!nextNode) {
95
+ for (const k in node.#children) {
96
+ if (k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR) {
97
+ throw PATH_ERROR;
98
+ }
99
+ }
100
+ nextNode = node.#children[token] = new Node();
103
101
  }
104
- if (pathErrorCheckOnly) {
105
- return;
106
- }
107
- node = this.#children[token] = new Node();
108
102
  }
103
+ node = nextNode;
104
+ }
105
+ if (node.#index !== void 0) {
106
+ throw PATH_ERROR;
109
107
  }
110
- node.insert(restTokens, index, paramMap, context, pathErrorCheckOnly);
108
+ node.#index = isStatic ? -1 : index;
111
109
  }
112
110
  buildRegExpStr() {
113
111
  const childKeys = Object.keys(this.#children).sort(compareKey);
114
112
  const strList = childKeys.map((k) => {
115
113
  const c = this.#children[k];
116
- return (typeof c.#varIndex === "number" ? `(${k})@${c.#varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c.buildRegExpStr();
117
- });
118
- if (typeof this.#index === "number") {
114
+ const childStr = c.buildRegExpStr();
115
+ return childStr === "" ? "" : (typeof c.#varIndex === "number" ? `(${k})@${c.#varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + childStr;
116
+ }).filter(Boolean);
117
+ if (typeof this.#index === "number" && this.#index !== -1) {
119
118
  strList.unshift(`#${this.#index}`);
120
119
  }
121
120
  if (strList.length === 0) {
@@ -25,7 +25,6 @@ var import_url = require("../../utils/url");
25
25
  var import_matcher = require("./matcher");
26
26
  var import_node = require("./node");
27
27
  var import_trie = require("./trie");
28
- const nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
29
28
  let wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
30
29
  function buildWildcardRegExp(path) {
31
30
  return wildcardRegExpCache[path] ??= new RegExp(
@@ -38,63 +37,6 @@ function buildWildcardRegExp(path) {
38
37
  function clearWildcardRegExpCache() {
39
38
  wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
40
39
  }
41
- function buildMatcherFromPreprocessedRoutes(routes) {
42
- const trie = new import_trie.Trie();
43
- const handlerData = [];
44
- if (routes.length === 0) {
45
- return nullMatcher;
46
- }
47
- const routesWithStaticPathFlag = routes.map(
48
- (route) => [!/\*|\/:/.test(route[0]), ...route]
49
- ).sort(
50
- ([isStaticA, pathA], [isStaticB, pathB]) => isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length
51
- );
52
- const staticMap = /* @__PURE__ */ Object.create(null);
53
- for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
54
- const [pathErrorCheckOnly, path, handlers] = routesWithStaticPathFlag[i];
55
- if (pathErrorCheckOnly) {
56
- staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), import_matcher.emptyParam];
57
- } else {
58
- j++;
59
- }
60
- let paramAssoc;
61
- try {
62
- paramAssoc = trie.insert(path, j, pathErrorCheckOnly);
63
- } catch (e) {
64
- throw e === import_node.PATH_ERROR ? new import_router.UnsupportedPathError(path) : e;
65
- }
66
- if (pathErrorCheckOnly) {
67
- continue;
68
- }
69
- handlerData[j] = handlers.map(([h, paramCount]) => {
70
- const paramIndexMap = /* @__PURE__ */ Object.create(null);
71
- paramCount -= 1;
72
- for (; paramCount >= 0; paramCount--) {
73
- const [key, value] = paramAssoc[paramCount];
74
- paramIndexMap[key] = value;
75
- }
76
- return [h, paramIndexMap];
77
- });
78
- }
79
- const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
80
- for (let i = 0, len = handlerData.length; i < len; i++) {
81
- for (let j = 0, len2 = handlerData[i].length; j < len2; j++) {
82
- const map = handlerData[i][j]?.[1];
83
- if (!map) {
84
- continue;
85
- }
86
- const keys = Object.keys(map);
87
- for (let k = 0, len3 = keys.length; k < len3; k++) {
88
- map[keys[k]] = paramReplacementMap[map[keys[k]]];
89
- }
90
- }
91
- }
92
- const handlerMap = [];
93
- for (const i in indexReplacementMap) {
94
- handlerMap[i] = handlerData[indexReplacementMap[i]];
95
- }
96
- return [regexp, handlerMap, staticMap];
97
- }
98
40
  function findMiddleware(middleware, path) {
99
41
  if (!middleware) {
100
42
  return void 0;
@@ -110,9 +52,18 @@ class RegExpRouter {
110
52
  name = "RegExpRouter";
111
53
  #middleware;
112
54
  #routes;
55
+ #tries;
113
56
  constructor() {
114
57
  this.#middleware = { [import_router.METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
115
58
  this.#routes = { [import_router.METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
59
+ this.#tries = { [import_router.METHOD_NAME_ALL]: new import_trie.Trie() };
60
+ }
61
+ #insertPath(method, path) {
62
+ try {
63
+ this.#tries[method].insert(path, !/\*|\/:/.test(path));
64
+ } catch (e) {
65
+ throw e === import_node.PATH_ERROR ? new import_router.UnsupportedPathError(path) : e;
66
+ }
116
67
  }
117
68
  add(method, path, handler) {
118
69
  const middleware = this.#middleware;
@@ -121,11 +72,12 @@ class RegExpRouter {
121
72
  throw new Error(import_router.MESSAGE_MATCHER_IS_ALREADY_BUILT);
122
73
  }
123
74
  if (!middleware[method]) {
124
- ;
75
+ this.#tries[method] = new import_trie.Trie();
125
76
  [middleware, routes].forEach((handlerMap) => {
126
77
  handlerMap[method] = /* @__PURE__ */ Object.create(null);
127
78
  Object.keys(handlerMap[import_router.METHOD_NAME_ALL]).forEach((p) => {
128
79
  handlerMap[method][p] = [...handlerMap[import_router.METHOD_NAME_ALL][p]];
80
+ this.#insertPath(method, p);
129
81
  });
130
82
  });
131
83
  }
@@ -135,13 +87,12 @@ class RegExpRouter {
135
87
  const paramCount = (path.match(/\/:/g) || []).length;
136
88
  if (/\*$/.test(path)) {
137
89
  const re = buildWildcardRegExp(path);
138
- if (method === import_router.METHOD_NAME_ALL) {
139
- Object.keys(middleware).forEach((m) => {
140
- middleware[m][path] ||= findMiddleware(middleware[m], path) || findMiddleware(middleware[import_router.METHOD_NAME_ALL], path) || [];
141
- });
142
- } else {
143
- middleware[method][path] ||= findMiddleware(middleware[method], path) || findMiddleware(middleware[import_router.METHOD_NAME_ALL], path) || [];
144
- }
90
+ Object.keys(middleware).forEach((m) => {
91
+ if ((method === import_router.METHOD_NAME_ALL || method === m) && !middleware[m][path]) {
92
+ this.#insertPath(m, path);
93
+ middleware[m][path] = findMiddleware(middleware[m], path) || findMiddleware(middleware[import_router.METHOD_NAME_ALL], path) || [];
94
+ }
95
+ });
145
96
  Object.keys(middleware).forEach((m) => {
146
97
  if (method === import_router.METHOD_NAME_ALL || method === m) {
147
98
  Object.keys(middleware[m]).forEach((p) => {
@@ -163,9 +114,12 @@ class RegExpRouter {
163
114
  const path2 = paths[i];
164
115
  Object.keys(routes).forEach((m) => {
165
116
  if (method === import_router.METHOD_NAME_ALL || method === m) {
166
- routes[m][path2] ||= [
167
- ...findMiddleware(middleware[m], path2) || findMiddleware(middleware[import_router.METHOD_NAME_ALL], path2) || []
168
- ];
117
+ if (!routes[m][path2]) {
118
+ this.#insertPath(m, path2);
119
+ routes[m][path2] = [
120
+ ...findMiddleware(middleware[m], path2) || findMiddleware(middleware[import_router.METHOD_NAME_ALL], path2) || []
121
+ ];
122
+ }
169
123
  routes[m][path2].push([handler, paramCount - len + i + 1]);
170
124
  }
171
125
  });
@@ -177,29 +131,54 @@ class RegExpRouter {
177
131
  Object.keys(this.#routes).concat(Object.keys(this.#middleware)).forEach((method) => {
178
132
  matchers[method] ||= this.#buildMatcher(method);
179
133
  });
180
- this.#middleware = this.#routes = void 0;
134
+ this.#middleware = this.#routes = this.#tries = void 0;
181
135
  clearWildcardRegExpCache();
182
136
  return matchers;
183
137
  }
184
138
  #buildMatcher(method) {
185
- const routes = [];
186
- let hasOwnRoute = method === import_router.METHOD_NAME_ALL;
187
- [this.#middleware, this.#routes].forEach((r) => {
188
- const ownRoute = r[method] ? Object.keys(r[method]).map((path) => [path, r[method][path]]) : [];
189
- if (ownRoute.length !== 0) {
190
- hasOwnRoute ||= true;
191
- routes.push(...ownRoute);
192
- } else if (method !== import_router.METHOD_NAME_ALL) {
193
- routes.push(
194
- ...Object.keys(r[import_router.METHOD_NAME_ALL]).map((path) => [path, r[import_router.METHOD_NAME_ALL][path]])
195
- );
139
+ const middleware = this.#middleware[method];
140
+ const routes = this.#routes[method];
141
+ const trie = this.#tries[method];
142
+ const staticMap = /* @__PURE__ */ Object.create(null);
143
+ const handlerData = [];
144
+ [middleware, routes].forEach((r) => {
145
+ for (const path in r) {
146
+ const handlers = r[path];
147
+ const pathData = trie.paths[path];
148
+ if (!pathData) {
149
+ staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), import_matcher.emptyParam];
150
+ continue;
151
+ }
152
+ const paramAssoc = pathData[1];
153
+ handlerData[pathData[0]] = handlers.map(([h, paramCount]) => {
154
+ const paramIndexMap = /* @__PURE__ */ Object.create(null);
155
+ paramCount -= 1;
156
+ for (; paramCount >= 0; paramCount--) {
157
+ const [key, value] = paramAssoc[paramCount];
158
+ paramIndexMap[key] = value;
159
+ }
160
+ return [h, paramIndexMap];
161
+ });
196
162
  }
197
163
  });
198
- if (!hasOwnRoute) {
199
- return null;
200
- } else {
201
- return buildMatcherFromPreprocessedRoutes(routes);
164
+ const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
165
+ for (let i = 0, len = handlerData.length; i < len; i++) {
166
+ for (let j = 0, len2 = handlerData[i].length; j < len2; j++) {
167
+ const map = handlerData[i][j]?.[1];
168
+ if (!map) {
169
+ continue;
170
+ }
171
+ const keys = Object.keys(map);
172
+ for (let k = 0, len3 = keys.length; k < len3; k++) {
173
+ map[keys[k]] = paramReplacementMap[map[keys[k]]];
174
+ }
175
+ }
176
+ }
177
+ const handlerMap = [];
178
+ for (const i in indexReplacementMap) {
179
+ handlerMap[i] = handlerData[indexReplacementMap[i]];
202
180
  }
181
+ return [regexp, handlerMap, staticMap];
203
182
  }
204
183
  }
205
184
  // Annotate the CommonJS export names for ESM import in node:
@@ -24,12 +24,20 @@ var import_node = require("./node");
24
24
  class Trie {
25
25
  #context = { varIndex: 0 };
26
26
  #root = new import_node.Node();
27
- insert(path, index, pathErrorCheckOnly) {
27
+ #index = 0;
28
+ // dynamic path -> [handler index, param assoc]; static paths are not registered
29
+ paths = /* @__PURE__ */ Object.create(null);
30
+ insert(path, isStatic) {
31
+ if (isStatic) {
32
+ this.#root.insert(path.split(""), 0, [], this.#context, true);
33
+ return;
34
+ }
28
35
  const paramAssoc = [];
29
36
  const groups = [];
37
+ let markedPath = path;
30
38
  for (let i = 0; ; ) {
31
39
  let replaced = false;
32
- path = path.replace(/\{[^}]+\}/g, (m) => {
40
+ markedPath = markedPath.replace(/\{[^}]+\}/g, (m) => {
33
41
  const mark = `@\\${i}`;
34
42
  groups[i] = [mark, m];
35
43
  i++;
@@ -40,7 +48,7 @@ class Trie {
40
48
  break;
41
49
  }
42
50
  }
43
- const tokens = path.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
51
+ const tokens = markedPath.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
44
52
  for (let i = groups.length - 1; i >= 0; i--) {
45
53
  const [mark] = groups[i];
46
54
  for (let j = tokens.length - 1; j >= 0; j--) {
@@ -50,8 +58,8 @@ class Trie {
50
58
  }
51
59
  }
52
60
  }
53
- this.#root.insert(tokens, index, paramAssoc, this.#context, pathErrorCheckOnly);
54
- return paramAssoc;
61
+ this.#root.insert(tokens, this.#index, paramAssoc, this.#context, false);
62
+ this.paths[path] = [this.#index++, paramAssoc];
55
63
  }
56
64
  buildRegExp() {
57
65
  let regexp = this.#root.buildRegExpStr();
@@ -26,7 +26,7 @@ __export(router_exports, {
26
26
  module.exports = __toCommonJS(router_exports);
27
27
  const METHOD_NAME_ALL = "ALL";
28
28
  const METHOD_NAME_ALL_LOWERCASE = "all";
29
- const METHODS = ["get", "post", "put", "delete", "options", "patch"];
29
+ const METHODS = ["get", "post", "put", "delete", "options", "patch", "query"];
30
30
  const MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built.";
31
31
  class UnsupportedPathError extends Error {
32
32
  }
@@ -88,7 +88,7 @@ const parse = (cookie, name) => {
88
88
  cookieValue = cookieValue.slice(1, -1);
89
89
  }
90
90
  if (validCookieValueRegEx.test(cookieValue)) {
91
- parsedCookie[cookieName] = cookieValue.indexOf("%") !== -1 ? (0, import_url.tryDecode)(cookieValue, import_url.decodeURIComponent_) : cookieValue;
91
+ parsedCookie[cookieName] = (0, import_url.tryDecodeURIComponent)(cookieValue);
92
92
  if (name) {
93
93
  break;
94
94
  }
@@ -29,7 +29,8 @@ __export(url_exports, {
29
29
  splitPath: () => splitPath,
30
30
  splitRoutingPath: () => splitRoutingPath,
31
31
  tryDecode: () => tryDecode,
32
- tryDecodeURI: () => tryDecodeURI
32
+ tryDecodeURI: () => tryDecodeURI,
33
+ tryDecodeURIComponent: () => tryDecodeURIComponent
33
34
  });
34
35
  module.exports = __toCommonJS(url_exports);
35
36
  const splitPath = (path) => {
@@ -157,18 +158,16 @@ const checkOptionalParameter = (path) => {
157
158
  });
158
159
  return results.filter((v, i, a) => a.indexOf(v) === i);
159
160
  };
161
+ const tryDecodeURIComponent = (str) => str.indexOf("%") !== -1 ? tryDecode(str, decodeURIComponent_) : str;
160
162
  const _decodeURI = (value) => {
161
- if (!/[%+]/.test(value)) {
162
- return value;
163
- }
164
163
  if (value.indexOf("+") !== -1) {
165
164
  value = value.replace(/\+/g, " ");
166
165
  }
167
- return value.indexOf("%") !== -1 ? tryDecode(value, decodeURIComponent_) : value;
166
+ return tryDecodeURIComponent(value);
168
167
  };
169
168
  const _getQueryParam = (url, key, multiple) => {
170
169
  let encoded;
171
- if (!multiple && key && !/[%+]/.test(key)) {
170
+ if (!multiple && key && key.indexOf("%") === -1 && key.indexOf("+") === -1) {
172
171
  let keyIndex2 = url.indexOf("?", 8);
173
172
  if (keyIndex2 === -1) {
174
173
  return void 0;
@@ -252,5 +251,6 @@ const decodeURIComponent_ = decodeURIComponent;
252
251
  splitPath,
253
252
  splitRoutingPath,
254
253
  tryDecode,
255
- tryDecodeURI
254
+ tryDecodeURI,
255
+ tryDecodeURIComponent
256
256
  });
package/dist/context.js CHANGED
@@ -273,11 +273,11 @@ var Context = class {
273
273
  return Object.fromEntries(this.#var);
274
274
  }
275
275
  #newResponse(data, arg, headers) {
276
- const responseHeaders = this.#res ? new Headers(this.#res.headers) : this.#preparedHeaders ?? new Headers();
277
- if (typeof arg === "object" && "headers" in arg) {
278
- const argHeaders = arg.headers instanceof Headers ? arg.headers : new Headers(arg.headers);
279
- for (const [key, value] of argHeaders) {
280
- if (key.toLowerCase() === "set-cookie") {
276
+ let responseHeaders = this.#res ? new Headers(this.#res.headers) : this.#preparedHeaders;
277
+ if (typeof arg === "object" && arg.headers) {
278
+ responseHeaders ??= new Headers();
279
+ for (const [key, value] of new Headers(arg.headers)) {
280
+ if (key === "set-cookie") {
281
281
  responseHeaders.append(key, value);
282
282
  } else {
283
283
  responseHeaders.set(key, value);
@@ -285,19 +285,34 @@ var Context = class {
285
285
  }
286
286
  }
287
287
  if (headers) {
288
- for (const [k, v] of Object.entries(headers)) {
289
- if (typeof v === "string") {
290
- responseHeaders.set(k, v);
291
- } else {
292
- responseHeaders.delete(k);
293
- for (const v2 of v) {
294
- responseHeaders.append(k, v2);
288
+ if (!responseHeaders) {
289
+ let count = 0;
290
+ for (const k in headers) {
291
+ if (++count > 1 || typeof headers[k] !== "string") {
292
+ responseHeaders = new Headers();
293
+ break;
294
+ }
295
+ }
296
+ }
297
+ if (responseHeaders) {
298
+ for (const k in headers) {
299
+ const v = headers[k];
300
+ if (typeof v === "string") {
301
+ responseHeaders.set(k, v);
302
+ } else {
303
+ responseHeaders.delete(k);
304
+ for (const v2 of v) {
305
+ responseHeaders.append(k, v2);
306
+ }
295
307
  }
296
308
  }
297
309
  }
298
310
  }
299
311
  const status = typeof arg === "number" ? arg : arg?.status ?? this.#status;
300
- return createResponseInstance(data, { status, headers: responseHeaders });
312
+ return createResponseInstance(data, {
313
+ status,
314
+ headers: responseHeaders ?? headers
315
+ });
301
316
  }
302
317
  newResponse = (...args) => this.#newResponse(...args);
303
318
  /**
package/dist/hono-base.js CHANGED
@@ -22,6 +22,7 @@ var Hono = class _Hono {
22
22
  delete;
23
23
  options;
24
24
  patch;
25
+ query;
25
26
  all;
26
27
  on;
27
28
  use;
@@ -321,8 +322,8 @@ var Hono = class _Hono {
321
322
  * @see {@link https://hono.dev/docs/api/hono#fetch}
322
323
  *
323
324
  * @param {Request} request - request Object of request
324
- * @param {Env} Env - env Object
325
- * @param {ExecutionContext} - context of execution
325
+ * @param {Env} env - env Object
326
+ * @param {ExecutionContext} executionCtx - context of execution
326
327
  * @returns {Response | Promise<Response>} response of request
327
328
  *
328
329
  */
package/dist/jsx/base.js CHANGED
@@ -69,6 +69,18 @@ var booleanAttributes = [
69
69
  "reversed",
70
70
  "selected"
71
71
  ];
72
+ var resolveFunctionComponentResult = (result, suspendedContext) => result.then((resolved) => {
73
+ if (!Array.isArray(resolved) && !(resolved instanceof JSXNode)) {
74
+ return resolved;
75
+ }
76
+ const children = Array.isArray(resolved) ? resolved : [resolved];
77
+ const render = () => {
78
+ const buffer = [""];
79
+ childrenToStringToBuffer(children, buffer);
80
+ return buffer.length === 1 ? raw(buffer[0], buffer.callbacks) : stringBufferToString(buffer, buffer.callbacks);
81
+ };
82
+ return suspendedContext ? suspendedContext(render) : runWithRenderContext(render);
83
+ });
72
84
  var childrenToStringToBuffer = (children, buffer) => {
73
85
  for (let i = 0, len = children.length; i < len; i++) {
74
86
  const child = children[i];
@@ -78,9 +90,17 @@ var childrenToStringToBuffer = (children, buffer) => {
78
90
  continue;
79
91
  } else if (child instanceof JSXNode) {
80
92
  child.toStringToBuffer(buffer);
81
- } else if (typeof child === "number" || child.isEscaped) {
93
+ } else if (typeof child === "number") {
94
+ ;
95
+ buffer[0] += child;
96
+ } else if (child.isEscaped) {
82
97
  ;
83
98
  buffer[0] += child;
99
+ const callbacks = child.callbacks;
100
+ if (callbacks) {
101
+ buffer.callbacks ||= [];
102
+ buffer.callbacks.push(...callbacks);
103
+ }
84
104
  } else if (child instanceof Promise) {
85
105
  buffer.unshift("", child);
86
106
  } else {
@@ -94,7 +114,6 @@ var JSXNode = class {
94
114
  key;
95
115
  children;
96
116
  isEscaped = true;
97
- suspendedContext;
98
117
  constructor(tag, props, children) {
99
118
  if (typeof tag !== "function" && !isValidTagName(tag)) {
100
119
  throw new Error(`Invalid JSX tag name: ${tag}`);
@@ -117,7 +136,7 @@ var JSXNode = class {
117
136
  this.toStringToBuffer(buffer);
118
137
  return buffer.length === 1 ? "callbacks" in buffer ? resolveCallbackSync(raw(buffer[0], buffer.callbacks)).toString() : buffer[0] : stringBufferToString(buffer, buffer.callbacks);
119
138
  };
120
- return this.suspendedContext ? this.suspendedContext(render) : runWithRenderContext(render);
139
+ return runWithRenderContext(render);
121
140
  }
122
141
  toStringToBuffer(buffer) {
123
142
  const tag = this.tag;
@@ -191,21 +210,14 @@ var JSXFunctionNode = class extends JSXNode {
191
210
  return;
192
211
  } else if (res instanceof Promise) {
193
212
  if (globalContexts.length === 0) {
194
- buffer.unshift("", res);
213
+ buffer.unshift("", resolveFunctionComponentResult(res));
195
214
  } else {
196
- const suspendedContext = captureRenderContext();
197
- buffer.unshift(
198
- "",
199
- res.then((childRes) => {
200
- if (childRes instanceof JSXNode) {
201
- childRes.suspendedContext = suspendedContext;
202
- }
203
- return childRes;
204
- })
205
- );
215
+ buffer.unshift("", resolveFunctionComponentResult(res, captureRenderContext()));
206
216
  }
207
217
  } else if (res instanceof JSXNode) {
208
218
  res.toStringToBuffer(buffer);
219
+ } else if (Array.isArray(res)) {
220
+ childrenToStringToBuffer(res, buffer);
209
221
  } else if (typeof res === "number" || res.isEscaped) {
210
222
  buffer[0] += res;
211
223
  if (res.callbacks) {
@@ -222,7 +222,7 @@ var useCallback = (callback, deps) => {
222
222
  }
223
223
  return callback;
224
224
  };
225
- var useRef = (initialValue) => {
225
+ function useRef(initialValue) {
226
226
  const buildData = buildDataStack.at(-1);
227
227
  if (!buildData) {
228
228
  return { current: initialValue };
@@ -231,7 +231,7 @@ var useRef = (initialValue) => {
231
231
  const refArray = node[DOM_STASH][1][STASH_REF] ||= [];
232
232
  const hookIndex = node[DOM_STASH][0]++;
233
233
  return refArray[hookIndex] ||= { current: initialValue };
234
- };
234
+ }
235
235
  var use = (promise) => {
236
236
  const cachedRes = resolvedPromiseValueMap.get(promise);
237
237
  if (cachedRes) {