hono 4.6.7 → 4.6.9

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 (91) hide show
  1. package/dist/adapter/bun/websocket.js +4 -6
  2. package/dist/adapter/cloudflare-workers/websocket.js +34 -39
  3. package/dist/adapter/deno/serve-static.js +2 -1
  4. package/dist/adapter/lambda-edge/handler.js +1 -1
  5. package/dist/cjs/adapter/bun/websocket.js +4 -6
  6. package/dist/cjs/adapter/cloudflare-workers/websocket.js +34 -39
  7. package/dist/cjs/adapter/deno/serve-static.js +2 -1
  8. package/dist/cjs/adapter/lambda-edge/handler.js +1 -1
  9. package/dist/cjs/client/client.js +3 -3
  10. package/dist/cjs/compose.js +4 -3
  11. package/dist/cjs/context.js +12 -9
  12. package/dist/cjs/helper/cookie/index.js +1 -1
  13. package/dist/cjs/helper/html/index.js +1 -1
  14. package/dist/cjs/helper/ssg/ssg.js +2 -2
  15. package/dist/cjs/helper/ssg/utils.js +2 -2
  16. package/dist/cjs/helper/websocket/index.js +1 -4
  17. package/dist/cjs/hono-base.js +29 -32
  18. package/dist/cjs/jsx/base.js +8 -3
  19. package/dist/cjs/jsx/constants.js +3 -0
  20. package/dist/cjs/jsx/dom/index.js +8 -2
  21. package/dist/cjs/jsx/dom/render.js +15 -12
  22. package/dist/cjs/middleware/etag/digest.js +59 -0
  23. package/dist/cjs/middleware/etag/index.js +5 -2
  24. package/dist/cjs/middleware/ip-restriction/index.js +3 -3
  25. package/dist/cjs/middleware/jsx-renderer/index.js +2 -1
  26. package/dist/cjs/middleware/logger/index.js +13 -11
  27. package/dist/cjs/middleware/timing/timing.js +5 -7
  28. package/dist/cjs/request.js +15 -14
  29. package/dist/cjs/router/pattern-router/router.js +4 -4
  30. package/dist/cjs/router/reg-exp-router/router.js +5 -5
  31. package/dist/cjs/router/reg-exp-router/trie.js +2 -2
  32. package/dist/cjs/router/trie-router/node.js +9 -7
  33. package/dist/cjs/utils/color.js +1 -1
  34. package/dist/cjs/utils/cookie.js +13 -6
  35. package/dist/cjs/utils/crypto.js +0 -9
  36. package/dist/cjs/utils/headers.js +16 -0
  37. package/dist/cjs/utils/jwt/jwt.js +1 -1
  38. package/dist/cjs/utils/mime.js +2 -1
  39. package/dist/cjs/utils/url.js +9 -6
  40. package/dist/client/client.js +3 -3
  41. package/dist/compose.js +4 -3
  42. package/dist/context.js +12 -9
  43. package/dist/helper/cookie/index.js +1 -1
  44. package/dist/helper/html/index.js +1 -1
  45. package/dist/helper/ssg/ssg.js +2 -2
  46. package/dist/helper/ssg/utils.js +2 -2
  47. package/dist/helper/websocket/index.js +1 -4
  48. package/dist/hono-base.js +29 -32
  49. package/dist/jsx/base.js +7 -3
  50. package/dist/jsx/constants.js +2 -0
  51. package/dist/jsx/dom/index.js +7 -1
  52. package/dist/jsx/dom/render.js +22 -13
  53. package/dist/middleware/etag/digest.js +36 -0
  54. package/dist/middleware/etag/index.js +5 -2
  55. package/dist/middleware/ip-restriction/index.js +3 -3
  56. package/dist/middleware/jsx-renderer/index.js +2 -1
  57. package/dist/middleware/logger/index.js +13 -11
  58. package/dist/middleware/timing/timing.js +5 -7
  59. package/dist/request.js +16 -15
  60. package/dist/router/pattern-router/router.js +4 -4
  61. package/dist/router/reg-exp-router/router.js +5 -5
  62. package/dist/router/reg-exp-router/trie.js +2 -2
  63. package/dist/router/trie-router/node.js +9 -7
  64. package/dist/types/adapter/bun/websocket.d.ts +5 -3
  65. package/dist/types/adapter/cloudflare-workers/websocket.d.ts +2 -2
  66. package/dist/types/adapter/deno/websocket.d.ts +1 -20
  67. package/dist/types/context.d.ts +2 -2
  68. package/dist/types/helper/accepts/accepts.d.ts +1 -1
  69. package/dist/types/helper/websocket/index.d.ts +3 -3
  70. package/dist/types/hono-base.d.ts +1 -1
  71. package/dist/types/jsx/base.d.ts +5 -0
  72. package/dist/types/jsx/constants.d.ts +1 -0
  73. package/dist/types/jsx/dom/index.d.ts +6 -5
  74. package/dist/types/jsx/dom/render.d.ts +1 -0
  75. package/dist/types/middleware/etag/digest.d.ts +1 -0
  76. package/dist/types/request.d.ts +3 -1
  77. package/dist/types/types.d.ts +71 -70
  78. package/dist/types/utils/body.d.ts +2 -2
  79. package/dist/types/utils/cookie.d.ts +4 -4
  80. package/dist/types/utils/crypto.d.ts +2 -1
  81. package/dist/types/utils/headers.d.ts +8 -0
  82. package/dist/types/utils/mime.d.ts +58 -1
  83. package/dist/types/utils/url.d.ts +3 -0
  84. package/dist/utils/color.js +1 -1
  85. package/dist/utils/cookie.js +13 -6
  86. package/dist/utils/crypto.js +0 -9
  87. package/dist/utils/headers.js +0 -0
  88. package/dist/utils/jwt/jwt.js +1 -1
  89. package/dist/utils/mime.js +2 -1
  90. package/dist/utils/url.js +7 -5
  91. package/package.json +1 -1
@@ -28,7 +28,8 @@ __export(url_exports, {
28
28
  getQueryStrings: () => getQueryStrings,
29
29
  mergePath: () => mergePath,
30
30
  splitPath: () => splitPath,
31
- splitRoutingPath: () => splitRoutingPath
31
+ splitRoutingPath: () => splitRoutingPath,
32
+ tryDecode: () => tryDecode
32
33
  });
33
34
  module.exports = __toCommonJS(url_exports);
34
35
  const splitPath = (path) => {
@@ -82,19 +83,20 @@ const getPattern = (label) => {
82
83
  }
83
84
  return null;
84
85
  };
85
- const tryDecodeURI = (str) => {
86
+ const tryDecode = (str, decoder) => {
86
87
  try {
87
- return decodeURI(str);
88
+ return decoder(str);
88
89
  } catch {
89
90
  return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match) => {
90
91
  try {
91
- return decodeURI(match);
92
+ return decoder(match);
92
93
  } catch {
93
94
  return match;
94
95
  }
95
96
  });
96
97
  }
97
98
  };
99
+ const tryDecodeURI = (str) => tryDecode(str, decodeURI);
98
100
  const getPath = (request) => {
99
101
  const url = request.url;
100
102
  const start = url.indexOf("/", 8);
@@ -175,7 +177,7 @@ const _decodeURI = (value) => {
175
177
  if (value.indexOf("+") !== -1) {
176
178
  value = value.replace(/\+/g, " ");
177
179
  }
178
- return /%/.test(value) ? decodeURIComponent_(value) : value;
180
+ return value.indexOf("%") !== -1 ? decodeURIComponent_(value) : value;
179
181
  };
180
182
  const _getQueryParam = (url, key, multiple) => {
181
183
  let encoded;
@@ -258,5 +260,6 @@ const decodeURIComponent_ = decodeURIComponent;
258
260
  getQueryStrings,
259
261
  mergePath,
260
262
  splitPath,
261
- splitRoutingPath
263
+ splitRoutingPath,
264
+ tryDecode
262
265
  });
@@ -65,8 +65,8 @@ var ClientRequestImpl = class {
65
65
  }
66
66
  let methodUpperCase = this.method.toUpperCase();
67
67
  const headerValues = {
68
- ...args?.header ?? {},
69
- ...typeof opt?.headers === "function" ? await opt.headers() : opt?.headers ? opt.headers : {}
68
+ ...args?.header,
69
+ ...typeof opt?.headers === "function" ? await opt.headers() : opt?.headers
70
70
  };
71
71
  if (args?.cookie) {
72
72
  const cookies = [];
@@ -157,7 +157,7 @@ var hc = (baseUrl, options) => createProxy(function proxyCallback(opts) {
157
157
  const req = new ClientRequestImpl(url, method);
158
158
  if (method) {
159
159
  options ??= {};
160
- const args = deepMerge(options, { ...opts.args[1] ?? {} });
160
+ const args = deepMerge(options, { ...opts.args[1] });
161
161
  return req.fetch(opts.args[0], args);
162
162
  }
163
163
  return req;
package/dist/compose.js CHANGED
@@ -3,6 +3,7 @@ import { Context } from "./context.js";
3
3
  var compose = (middleware, onError, onNotFound) => {
4
4
  return (context, next) => {
5
5
  let index = -1;
6
+ const isContext = context instanceof Context;
6
7
  return dispatch(0);
7
8
  async function dispatch(i) {
8
9
  if (i <= index) {
@@ -14,14 +15,14 @@ var compose = (middleware, onError, onNotFound) => {
14
15
  let handler;
15
16
  if (middleware[i]) {
16
17
  handler = middleware[i][0][0];
17
- if (context instanceof Context) {
18
+ if (isContext) {
18
19
  context.req.routeIndex = i;
19
20
  }
20
21
  } else {
21
22
  handler = i === middleware.length && next || void 0;
22
23
  }
23
24
  if (!handler) {
24
- if (context instanceof Context && context.finalized === false && onNotFound) {
25
+ if (isContext && context.finalized === false && onNotFound) {
25
26
  res = await onNotFound(context);
26
27
  }
27
28
  } else {
@@ -30,7 +31,7 @@ var compose = (middleware, onError, onNotFound) => {
30
31
  return dispatch(i + 1);
31
32
  });
32
33
  } catch (err) {
33
- if (err instanceof Error && context instanceof Context && onError) {
34
+ if (err instanceof Error && isContext && onError) {
34
35
  context.error = err;
35
36
  res = await onError(err, context);
36
37
  isError = true;
package/dist/context.js CHANGED
@@ -3,7 +3,9 @@ import { HonoRequest } from "./request.js";
3
3
  import { HtmlEscapedCallbackPhase, resolveCallback } from "./utils/html.js";
4
4
  var TEXT_PLAIN = "text/plain; charset=UTF-8";
5
5
  var setHeaders = (headers, map = {}) => {
6
- Object.entries(map).forEach(([key, value]) => headers.set(key, value));
6
+ for (const key of Object.keys(map)) {
7
+ headers.set(key, map[key]);
8
+ }
7
9
  return headers;
8
10
  };
9
11
  var Context = class {
@@ -150,7 +152,7 @@ var Context = class {
150
152
  }
151
153
  return Object.fromEntries(this.#var);
152
154
  }
153
- newResponse = (data, arg, headers) => {
155
+ #newResponse(data, arg, headers) {
154
156
  if (this.#isFresh && !headers && !arg && this.#status === 200) {
155
157
  return new Response(data, {
156
158
  headers: this.#preparedHeaders
@@ -202,9 +204,10 @@ var Context = class {
202
204
  status,
203
205
  headers: this.#headers
204
206
  });
205
- };
207
+ }
208
+ newResponse = (...args) => this.#newResponse(...args);
206
209
  body = (data, arg, headers) => {
207
- return typeof arg === "number" ? this.newResponse(data, arg, headers) : this.newResponse(data, arg);
210
+ return typeof arg === "number" ? this.#newResponse(data, arg, headers) : this.#newResponse(data, arg);
208
211
  };
209
212
  text = (text, arg, headers) => {
210
213
  if (!this.#preparedHeaders) {
@@ -214,27 +217,27 @@ var Context = class {
214
217
  this.#preparedHeaders = {};
215
218
  }
216
219
  this.#preparedHeaders["content-type"] = TEXT_PLAIN;
217
- return typeof arg === "number" ? this.newResponse(text, arg, headers) : this.newResponse(text, arg);
220
+ return typeof arg === "number" ? this.#newResponse(text, arg, headers) : this.#newResponse(text, arg);
218
221
  };
219
222
  json = (object, arg, headers) => {
220
223
  const body = JSON.stringify(object);
221
224
  this.#preparedHeaders ??= {};
222
225
  this.#preparedHeaders["content-type"] = "application/json; charset=UTF-8";
223
- return typeof arg === "number" ? this.newResponse(body, arg, headers) : this.newResponse(body, arg);
226
+ return typeof arg === "number" ? this.#newResponse(body, arg, headers) : this.#newResponse(body, arg);
224
227
  };
225
228
  html = (html, arg, headers) => {
226
229
  this.#preparedHeaders ??= {};
227
230
  this.#preparedHeaders["content-type"] = "text/html; charset=UTF-8";
228
231
  if (typeof html === "object") {
229
232
  return resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then((html2) => {
230
- return typeof arg === "number" ? this.newResponse(html2, arg, headers) : this.newResponse(html2, arg);
233
+ return typeof arg === "number" ? this.#newResponse(html2, arg, headers) : this.#newResponse(html2, arg);
231
234
  });
232
235
  }
233
- return typeof arg === "number" ? this.newResponse(html, arg, headers) : this.newResponse(html, arg);
236
+ return typeof arg === "number" ? this.#newResponse(html, arg, headers) : this.#newResponse(html, arg);
234
237
  };
235
238
  redirect = (location, status) => {
236
239
  this.#headers ??= new Headers();
237
- this.#headers.set("Location", location);
240
+ this.#headers.set("Location", String(location));
238
241
  return this.newResponse(null, status ?? 302);
239
242
  };
240
243
  notFound = () => {
@@ -56,7 +56,7 @@ var setCookie = (c, name, value, opt) => {
56
56
  } else {
57
57
  cookie = serialize(name, value, { path: "/", ...opt });
58
58
  }
59
- c.header("set-cookie", cookie, { append: true });
59
+ c.header("Set-Cookie", cookie, { append: true });
60
60
  };
61
61
  var setSignedCookie = async (c, name, value, secret, opt) => {
62
62
  let cookie;
@@ -4,7 +4,7 @@ var html = (strings, ...values) => {
4
4
  const buffer = [""];
5
5
  for (let i = 0, len = strings.length - 1; i < len; i++) {
6
6
  buffer[0] += strings[i];
7
- const children = values[i] instanceof Array ? values[i].flat(Infinity) : [values[i]];
7
+ const children = Array.isArray(values[i]) ? values[i].flat(Infinity) : [values[i]];
8
8
  for (let i2 = 0, len2 = children.length; i2 < len2; i2++) {
9
9
  const child = children[i2];
10
10
  if (typeof child === "string") {
@@ -233,8 +233,8 @@ var toSSG = async (app, fs, options) => {
233
233
  result = { success: false, files: [], error: errorObj };
234
234
  }
235
235
  if (options?.afterGenerateHook) {
236
- const conbinedAfterGenerateHooks = combineAfterGenerateHooks(options?.afterGenerateHook);
237
- await conbinedAfterGenerateHooks(result);
236
+ const combinedAfterGenerateHooks = combineAfterGenerateHooks(options?.afterGenerateHook);
237
+ await combinedAfterGenerateHooks(result);
238
238
  }
239
239
  return result;
240
240
  };
@@ -2,8 +2,8 @@
2
2
  import { METHOD_NAME_ALL } from "../../router.js";
3
3
  import { findTargetHandler, isMiddleware } from "../../utils/handler.js";
4
4
  var dirname = (path) => {
5
- const splittedPath = path.split(/[\/\\]/);
6
- return splittedPath.slice(0, -1).join("/");
5
+ const separatedPath = path.split(/[\/\\]/);
6
+ return separatedPath.slice(0, -1).join("/");
7
7
  };
8
8
  var normalizePath = (path) => {
9
9
  return path.replace(/(\\)/g, "/").replace(/\/$/g, "");
@@ -8,10 +8,7 @@ var WSContext = class {
8
8
  this.protocol = init.protocol ?? null;
9
9
  }
10
10
  send(source, options) {
11
- this.#init.send(
12
- typeof source === "string" ? source : source instanceof Uint8Array ? source.buffer : source,
13
- options ?? {}
14
- );
11
+ this.#init.send(source, options ?? {});
15
12
  }
16
13
  raw;
17
14
  binaryType = "arraybuffer";
package/dist/hono-base.js CHANGED
@@ -36,11 +36,11 @@ var Hono = class {
36
36
  if (typeof args1 === "string") {
37
37
  this.#path = args1;
38
38
  } else {
39
- this.addRoute(method, this.#path, args1);
39
+ this.#addRoute(method, this.#path, args1);
40
40
  }
41
41
  args.forEach((handler) => {
42
42
  if (typeof handler !== "string") {
43
- this.addRoute(method, this.#path, handler);
43
+ this.#addRoute(method, this.#path, handler);
44
44
  }
45
45
  });
46
46
  return this;
@@ -51,7 +51,7 @@ var Hono = class {
51
51
  this.#path = p;
52
52
  for (const m of [method].flat()) {
53
53
  handlers.map((handler) => {
54
- this.addRoute(m.toUpperCase(), this.#path, handler);
54
+ this.#addRoute(m.toUpperCase(), this.#path, handler);
55
55
  });
56
56
  }
57
57
  }
@@ -65,7 +65,7 @@ var Hono = class {
65
65
  handlers.unshift(arg1);
66
66
  }
67
67
  handlers.forEach((handler) => {
68
- this.addRoute(METHOD_NAME_ALL, this.#path, handler);
68
+ this.#addRoute(METHOD_NAME_ALL, this.#path, handler);
69
69
  });
70
70
  return this;
71
71
  };
@@ -74,7 +74,7 @@ var Hono = class {
74
74
  Object.assign(this, options);
75
75
  this.getPath = strict ? options.getPath ?? getPath : getPathNoStrict;
76
76
  }
77
- clone() {
77
+ #clone() {
78
78
  const clone = new Hono({
79
79
  router: this.router,
80
80
  getPath: this.getPath
@@ -82,33 +82,33 @@ var Hono = class {
82
82
  clone.routes = this.routes;
83
83
  return clone;
84
84
  }
85
- notFoundHandler = notFoundHandler;
86
- errorHandler = errorHandler;
85
+ #notFoundHandler = notFoundHandler;
86
+ #errorHandler = errorHandler;
87
87
  route(path, app) {
88
88
  const subApp = this.basePath(path);
89
89
  app.routes.map((r) => {
90
90
  let handler;
91
- if (app.errorHandler === errorHandler) {
91
+ if (app.#errorHandler === errorHandler) {
92
92
  handler = r.handler;
93
93
  } else {
94
- handler = async (c, next) => (await compose([], app.errorHandler)(c, () => r.handler(c, next))).res;
94
+ handler = async (c, next) => (await compose([], app.#errorHandler)(c, () => r.handler(c, next))).res;
95
95
  handler[COMPOSED_HANDLER] = r.handler;
96
96
  }
97
- subApp.addRoute(r.method, r.path, handler);
97
+ subApp.#addRoute(r.method, r.path, handler);
98
98
  });
99
99
  return this;
100
100
  }
101
101
  basePath(path) {
102
- const subApp = this.clone();
102
+ const subApp = this.#clone();
103
103
  subApp._basePath = mergePath(this._basePath, path);
104
104
  return subApp;
105
105
  }
106
106
  onError = (handler) => {
107
- this.errorHandler = handler;
107
+ this.#errorHandler = handler;
108
108
  return this;
109
109
  };
110
110
  notFound = (handler) => {
111
- this.notFoundHandler = handler;
111
+ this.#notFoundHandler = handler;
112
112
  return this;
113
113
  };
114
114
  mount(path, applicationHandler, options) {
@@ -149,52 +149,49 @@ var Hono = class {
149
149
  }
150
150
  await next();
151
151
  };
152
- this.addRoute(METHOD_NAME_ALL, mergePath(path, "*"), handler);
152
+ this.#addRoute(METHOD_NAME_ALL, mergePath(path, "*"), handler);
153
153
  return this;
154
154
  }
155
- addRoute(method, path, handler) {
155
+ #addRoute(method, path, handler) {
156
156
  method = method.toUpperCase();
157
157
  path = mergePath(this._basePath, path);
158
158
  const r = { path, method, handler };
159
159
  this.router.add(method, path, [handler, r]);
160
160
  this.routes.push(r);
161
161
  }
162
- matchRoute(method, path) {
163
- return this.router.match(method, path);
164
- }
165
- handleError(err, c) {
162
+ #handleError(err, c) {
166
163
  if (err instanceof Error) {
167
- return this.errorHandler(err, c);
164
+ return this.#errorHandler(err, c);
168
165
  }
169
166
  throw err;
170
167
  }
171
- dispatch(request, executionCtx, env, method) {
168
+ #dispatch(request, executionCtx, env, method) {
172
169
  if (method === "HEAD") {
173
- return (async () => new Response(null, await this.dispatch(request, executionCtx, env, "GET")))();
170
+ return (async () => new Response(null, await this.#dispatch(request, executionCtx, env, "GET")))();
174
171
  }
175
172
  const path = this.getPath(request, { env });
176
- const matchResult = this.matchRoute(method, path);
173
+ const matchResult = this.router.match(method, path);
177
174
  const c = new Context(request, {
178
175
  path,
179
176
  matchResult,
180
177
  env,
181
178
  executionCtx,
182
- notFoundHandler: this.notFoundHandler
179
+ notFoundHandler: this.#notFoundHandler
183
180
  });
184
181
  if (matchResult[0].length === 1) {
185
182
  let res;
186
183
  try {
187
184
  res = matchResult[0][0][0][0](c, async () => {
188
- c.res = await this.notFoundHandler(c);
185
+ c.res = await this.#notFoundHandler(c);
189
186
  });
190
187
  } catch (err) {
191
- return this.handleError(err, c);
188
+ return this.#handleError(err, c);
192
189
  }
193
190
  return res instanceof Promise ? res.then(
194
- (resolved) => resolved || (c.finalized ? c.res : this.notFoundHandler(c))
195
- ).catch((err) => this.handleError(err, c)) : res ?? this.notFoundHandler(c);
191
+ (resolved) => resolved || (c.finalized ? c.res : this.#notFoundHandler(c))
192
+ ).catch((err) => this.#handleError(err, c)) : res ?? this.#notFoundHandler(c);
196
193
  }
197
- const composed = compose(matchResult[0], this.errorHandler, this.notFoundHandler);
194
+ const composed = compose(matchResult[0], this.#errorHandler, this.#notFoundHandler);
198
195
  return (async () => {
199
196
  try {
200
197
  const context = await composed(c);
@@ -205,12 +202,12 @@ var Hono = class {
205
202
  }
206
203
  return context.res;
207
204
  } catch (err) {
208
- return this.handleError(err, c);
205
+ return this.#handleError(err, c);
209
206
  }
210
207
  })();
211
208
  }
212
209
  fetch = (request, ...rest) => {
213
- return this.dispatch(request, rest[1], rest[0], request.method);
210
+ return this.#dispatch(request, rest[1], rest[0], request.method);
214
211
  };
215
212
  request = (input, requestInit, Env, executionCtx) => {
216
213
  if (input instanceof Request) {
@@ -226,7 +223,7 @@ var Hono = class {
226
223
  };
227
224
  fire = () => {
228
225
  addEventListener("fetch", (event) => {
229
- event.respondWith(this.dispatch(event.request, event, void 0, event.request.method));
226
+ event.respondWith(this.#dispatch(event.request, event, void 0, event.request.method));
230
227
  });
231
228
  };
232
229
  };
package/dist/jsx/base.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/jsx/base.ts
2
2
  import { raw } from "../helper/html/index.js";
3
3
  import { escapeToBuffer, resolveCallbackSync, stringBufferToString } from "../utils/html.js";
4
- import { DOM_RENDERER } from "./constants.js";
4
+ import { DOM_RENDERER, DOM_MEMO } from "./constants.js";
5
5
  import { createContext, globalContexts, useContext } from "./context.js";
6
6
  import { domRenderers } from "./intrinsic-element/common.js";
7
7
  import * as intrinsicElementTags from "./intrinsic-element/components.js";
@@ -270,13 +270,16 @@ var shallowEqual = (a, b) => {
270
270
  var memo = (component, propsAreEqual = shallowEqual) => {
271
271
  let computed = null;
272
272
  let prevProps = void 0;
273
- return (props) => {
273
+ const wrapper = (props) => {
274
274
  if (prevProps && !propsAreEqual(prevProps, props)) {
275
275
  computed = null;
276
276
  }
277
277
  prevProps = props;
278
278
  return computed ||= component(props);
279
279
  };
280
+ wrapper[DOM_MEMO] = propsAreEqual;
281
+ wrapper[DOM_RENDERER] = component;
282
+ return wrapper;
280
283
  };
281
284
  var Fragment = ({
282
285
  children
@@ -311,5 +314,6 @@ export {
311
314
  jsx,
312
315
  jsxFn,
313
316
  memo,
314
- reactAPICompatVersion
317
+ reactAPICompatVersion,
318
+ shallowEqual
315
319
  };
@@ -3,10 +3,12 @@ var DOM_RENDERER = Symbol("RENDERER");
3
3
  var DOM_ERROR_HANDLER = Symbol("ERROR_HANDLER");
4
4
  var DOM_STASH = Symbol("STASH");
5
5
  var DOM_INTERNAL_TAG = Symbol("INTERNAL");
6
+ var DOM_MEMO = Symbol("MEMO");
6
7
  var PERMALINK = Symbol("PERMALINK");
7
8
  export {
8
9
  DOM_ERROR_HANDLER,
9
10
  DOM_INTERNAL_TAG,
11
+ DOM_MEMO,
10
12
  DOM_RENDERER,
11
13
  DOM_STASH,
12
14
  PERMALINK
@@ -1,6 +1,7 @@
1
1
  // src/jsx/dom/index.ts
2
- import { isValidElement, memo, reactAPICompatVersion } from "../base.js";
2
+ import { isValidElement, reactAPICompatVersion, shallowEqual } from "../base.js";
3
3
  import { Children } from "../children.js";
4
+ import { DOM_MEMO } from "../constants.js";
4
5
  import { useContext } from "../context.js";
5
6
  import {
6
7
  createRef,
@@ -53,6 +54,11 @@ var cloneElement = (element, props, ...children) => {
53
54
  element.key
54
55
  );
55
56
  };
57
+ var memo = (component, propsAreEqual = shallowEqual) => {
58
+ const wrapper = (props) => component(props);
59
+ wrapper[DOM_MEMO] = propsAreEqual;
60
+ return wrapper;
61
+ };
56
62
  var dom_default = {
57
63
  version: reactAPICompatVersion,
58
64
  useState,
@@ -1,6 +1,12 @@
1
1
  // src/jsx/dom/render.ts
2
2
  import { toArray } from "../children.js";
3
- import { DOM_ERROR_HANDLER, DOM_INTERNAL_TAG, DOM_RENDERER, DOM_STASH } from "../constants.js";
3
+ import {
4
+ DOM_ERROR_HANDLER,
5
+ DOM_INTERNAL_TAG,
6
+ DOM_MEMO,
7
+ DOM_RENDERER,
8
+ DOM_STASH
9
+ } from "../constants.js";
4
10
  import { globalContexts as globalJSXContexts, useContext } from "../context.js";
5
11
  import { STASH_EFFECT } from "../hooks/index.js";
6
12
  import { normalizeIntrinsicElementKey, styleObjectForEach } from "../utils.js";
@@ -228,13 +234,19 @@ var applyNodeObject = (node, container, isNew) => {
228
234
  remove.forEach(removeNode);
229
235
  const childNodes = isNew ? void 0 : container.childNodes;
230
236
  let offset;
237
+ let insertBeforeNode = null;
231
238
  if (isNew) {
232
239
  offset = -1;
240
+ } else if (!childNodes.length) {
241
+ offset = 0;
233
242
  } else {
234
- offset = (childNodes.length && (findChildNodeIndex(childNodes, findInsertBefore(node.nN)) ?? findChildNodeIndex(
235
- childNodes,
236
- next.find((n) => n.tag !== HONO_PORTAL_ELEMENT && n.e)?.e
237
- ))) ?? -1;
243
+ const offsetByNextNode = findChildNodeIndex(childNodes, findInsertBefore(node.nN));
244
+ if (offsetByNextNode !== void 0) {
245
+ insertBeforeNode = childNodes[offsetByNextNode];
246
+ offset = offsetByNextNode;
247
+ } else {
248
+ offset = findChildNodeIndex(childNodes, next.find((n) => n.tag !== HONO_PORTAL_ELEMENT && n.e)?.e) ?? -1;
249
+ }
238
250
  if (offset === -1) {
239
251
  isNew = true;
240
252
  }
@@ -269,7 +281,7 @@ var applyNodeObject = (node, container, isNew) => {
269
281
  if (childNodes[offset + 1] === el) {
270
282
  container.appendChild(childNodes[offset]);
271
283
  } else {
272
- container.insertBefore(el, childNodes[offset] || null);
284
+ container.insertBefore(el, insertBeforeNode || childNodes[offset] || null);
273
285
  }
274
286
  }
275
287
  }
@@ -351,12 +363,8 @@ var build = (context, node, children) => {
351
363
  if (typeof child.tag === "function") {
352
364
  oldChild[DOM_STASH][2] = child[DOM_STASH][2] || [];
353
365
  oldChild[DOM_STASH][3] = child[DOM_STASH][3];
354
- if (!oldChild.f) {
355
- const prevPropsKeys = Object.keys(pP);
356
- const currentProps = oldChild.props;
357
- if (prevPropsKeys.length === Object.keys(currentProps).length && prevPropsKeys.every((k) => k in currentProps && currentProps[k] === pP[k])) {
358
- oldChild.s = true;
359
- }
366
+ if (!oldChild.f && ((oldChild.o || oldChild) === child.o || oldChild.tag[DOM_MEMO]?.(pP, oldChild.props))) {
367
+ oldChild.s = true;
360
368
  }
361
369
  }
362
370
  child = oldChild;
@@ -443,7 +451,8 @@ var buildNode = (node) => {
443
451
  key: node.key,
444
452
  f: node.f,
445
453
  type: node.tag,
446
- ref: node.props.ref
454
+ ref: node.props.ref,
455
+ o: node.o || node
447
456
  };
448
457
  }
449
458
  if (typeof node.tag === "function") {
@@ -0,0 +1,36 @@
1
+ // src/middleware/etag/digest.ts
2
+ var mergeBuffers = (buffer1, buffer2) => {
3
+ if (!buffer1) {
4
+ return buffer2;
5
+ }
6
+ const merged = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
7
+ merged.set(new Uint8Array(buffer1), 0);
8
+ merged.set(buffer2, buffer1.byteLength);
9
+ return merged;
10
+ };
11
+ var generateDigest = async (stream) => {
12
+ if (!stream || !crypto || !crypto.subtle) {
13
+ return null;
14
+ }
15
+ let result = void 0;
16
+ const reader = stream.getReader();
17
+ for (; ; ) {
18
+ const { value, done } = await reader.read();
19
+ if (done) {
20
+ break;
21
+ }
22
+ result = await crypto.subtle.digest(
23
+ {
24
+ name: "SHA-1"
25
+ },
26
+ mergeBuffers(result, value)
27
+ );
28
+ }
29
+ if (!result) {
30
+ return null;
31
+ }
32
+ return Array.prototype.map.call(new Uint8Array(result), (x) => x.toString(16).padStart(2, "0")).join("");
33
+ };
34
+ export {
35
+ generateDigest
36
+ };
@@ -1,5 +1,5 @@
1
1
  // src/middleware/etag/index.ts
2
- import { sha1 } from "../../utils/crypto.js";
2
+ import { generateDigest } from "./digest.js";
3
3
  var RETAINED_304_HEADERS = [
4
4
  "cache-control",
5
5
  "content-location",
@@ -20,7 +20,10 @@ var etag = (options) => {
20
20
  const res = c.res;
21
21
  let etag3 = res.headers.get("ETag");
22
22
  if (!etag3) {
23
- const hash = await sha1(res.clone().body || "");
23
+ const hash = await generateDigest(res.clone().body);
24
+ if (hash === null) {
25
+ return;
26
+ }
24
27
  etag3 = weak ? `W/"${hash}"` : `"${hash}"`;
25
28
  }
26
29
  if (etagMatches(etag3, ifNoneMatch)) {
@@ -18,14 +18,14 @@ var buildMatcher = (rules) => {
18
18
  functionRules.push(rule);
19
19
  } else {
20
20
  if (IS_CIDR_NOTATION_REGEX.test(rule)) {
21
- const splittedRule = rule.split("/");
22
- const addrStr = splittedRule[0];
21
+ const separatedRule = rule.split("/");
22
+ const addrStr = separatedRule[0];
23
23
  const type2 = distinctRemoteAddr(addrStr);
24
24
  if (type2 === void 0) {
25
25
  throw new TypeError(`Invalid rule: ${rule}`);
26
26
  }
27
27
  const isIPv4 = type2 === "IPv4";
28
- const prefix = parseInt(splittedRule[1]);
28
+ const prefix = parseInt(separatedRule[1]);
29
29
  if (isIPv4 ? prefix === 32 : prefix === 128) {
30
30
  rule = addrStr;
31
31
  } else {
@@ -8,7 +8,8 @@ var createRenderer = (c, Layout, component, options) => (children, props) => {
8
8
  const currentLayout = component ? jsx(
9
9
  (props2) => component(props2, c),
10
10
  {
11
- ...{ Layout, ...props }
11
+ Layout,
12
+ ...props
12
13
  },
13
14
  children
14
15
  ) : children;
@@ -12,17 +12,19 @@ var time = (start) => {
12
12
  };
13
13
  var colorStatus = (status) => {
14
14
  const colorEnabled = getColorEnabled();
15
- const out = {
16
- 7: colorEnabled ? `\x1B[35m${status}\x1B[0m` : `${status}`,
17
- 5: colorEnabled ? `\x1B[31m${status}\x1B[0m` : `${status}`,
18
- 4: colorEnabled ? `\x1B[33m${status}\x1B[0m` : `${status}`,
19
- 3: colorEnabled ? `\x1B[36m${status}\x1B[0m` : `${status}`,
20
- 2: colorEnabled ? `\x1B[32m${status}\x1B[0m` : `${status}`,
21
- 1: colorEnabled ? `\x1B[32m${status}\x1B[0m` : `${status}`,
22
- 0: colorEnabled ? `\x1B[33m${status}\x1B[0m` : `${status}`
23
- };
24
- const calculateStatus = status / 100 | 0;
25
- return out[calculateStatus];
15
+ if (colorEnabled) {
16
+ switch (status / 100 | 0) {
17
+ case 5:
18
+ return `\x1B[31m${status}\x1B[0m`;
19
+ case 4:
20
+ return `\x1B[33m${status}\x1B[0m`;
21
+ case 3:
22
+ return `\x1B[36m${status}\x1B[0m`;
23
+ case 2:
24
+ return `\x1B[32m${status}\x1B[0m`;
25
+ }
26
+ }
27
+ return `${status}`;
26
28
  };
27
29
  function log(fn, prefix, method, path, status = 0, elapsed) {
28
30
  const out = prefix === "<--" /* Incoming */ ? `${prefix} ${method} ${path}` : `${prefix} ${method} ${path} ${colorStatus(status)} ${elapsed}`;