hono 4.0.1 → 4.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  <p align="center">
10
10
  <a href="https://hono.dev"><b>Documentation :point_right: hono.dev</b></a><br />
11
- <i>v3 has been released!</i> <a href="docs/MIGRATION.md">Migration guide</b>
11
+ <i>v4 has been released!</i> <a href="docs/MIGRATION.md">Migration guide</b>
12
12
  </p>
13
13
 
14
14
  <hr />
@@ -42,13 +42,13 @@ export default app
42
42
  ## Quick Start
43
43
 
44
44
  ```
45
- npm create hono@latest my-app
45
+ npm create hono@latest
46
46
  ```
47
47
 
48
48
  ## Features
49
49
 
50
50
  - **Ultrafast** 🚀 - The router `RegExpRouter` is really fast. Not using linear loops. Fast.
51
- - **Lightweight** ðŸŠķ - The `hono/tiny` preset is under 14kB. Hono has zero dependencies and uses only the Web Standard API.
51
+ - **Lightweight** ðŸŠķ - The `hono/tiny` preset is under 13kB. Hono has zero dependencies and uses only the Web Standard API.
52
52
  - **Multi-runtime** 🌍 - Works on Cloudflare Workers, Fastly Compute, Deno, Bun, AWS Lambda, Lambda@Edge, or Node.js. The same code runs on all platforms.
53
53
  - **Batteries Included** 🔋 - Hono has built-in middleware, custom middleware, and third-party middleware. Batteries included.
54
54
  - **Delightful DX** 😃 - Super clean APIs. First-class TypeScript support. Now, we've got "Types".
@@ -32,7 +32,7 @@ const mergePath = (base, path) => {
32
32
  };
33
33
  const replaceUrlParam = (urlString, params) => {
34
34
  for (const [k, v] of Object.entries(params)) {
35
- const reg = new RegExp("/:" + k + "({[^}]*})?");
35
+ const reg = new RegExp("/:" + k + "(?:{[^/]+})?");
36
36
  urlString = urlString.replace(reg, `/${v}`);
37
37
  }
38
38
  return urlString;
@@ -124,7 +124,7 @@ class Context {
124
124
  const headers2 = setHeaders(new Headers(arg.headers), __privateGet(this, _preparedHeaders));
125
125
  return new Response(data, {
126
126
  headers: headers2,
127
- status: arg.status
127
+ status: arg.status ?? __privateGet(this, _status)
128
128
  });
129
129
  }
130
130
  const status = typeof arg === "number" ? arg : __privateGet(this, _status);
@@ -23,22 +23,18 @@ __export(dev_exports, {
23
23
  showRoutes: () => showRoutes
24
24
  });
25
25
  module.exports = __toCommonJS(dev_exports);
26
- var import_hono_base = require("../../hono-base");
27
- const isMiddleware = (handler) => handler.length > 1;
26
+ var import_handler = require("../../utils/handler");
28
27
  const handlerName = (handler) => {
29
- return handler.name || (isMiddleware(handler) ? "[middleware]" : "[handler]");
30
- };
31
- const findTargetHandler = (handler) => {
32
- return handler[import_hono_base.COMPOSED_HANDLER] ? findTargetHandler(handler[import_hono_base.COMPOSED_HANDLER]) : handler;
28
+ return handler.name || ((0, import_handler.isMiddleware)(handler) ? "[middleware]" : "[handler]");
33
29
  };
34
30
  const inspectRoutes = (hono) => {
35
31
  return hono.routes.map(({ path, method, handler }) => {
36
- const targetHandler = findTargetHandler(handler);
32
+ const targetHandler = (0, import_handler.findTargetHandler)(handler);
37
33
  return {
38
34
  path,
39
35
  method,
40
36
  name: handlerName(targetHandler),
41
- isMiddleware: isMiddleware(targetHandler)
37
+ isMiddleware: (0, import_handler.isMiddleware)(targetHandler)
42
38
  };
43
39
  });
44
40
  };
@@ -18,10 +18,10 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var ssg_exports = {};
20
20
  __export(ssg_exports, {
21
- X_HONO_DISABLE_SSG_HEADER_KEY: () => X_HONO_DISABLE_SSG_HEADER_KEY,
22
- X_HONO_SSG_HEADER_KEY: () => X_HONO_SSG_HEADER_KEY,
21
+ SSG_DISABLED_RESPONSE: () => SSG_DISABLED_RESPONSE,
23
22
  disableSSG: () => disableSSG,
24
23
  fetchRoutesContent: () => fetchRoutesContent,
24
+ isSSGContext: () => isSSGContext,
25
25
  onlySSG: () => onlySSG,
26
26
  saveContentToFiles: () => saveContentToFiles,
27
27
  ssgParams: () => ssgParams,
@@ -29,12 +29,11 @@ __export(ssg_exports, {
29
29
  });
30
30
  module.exports = __toCommonJS(ssg_exports);
31
31
  var import_utils = require("../../client/utils");
32
- var import_dev = require("../../helper/dev");
33
32
  var import_buffer = require("../../utils/buffer");
34
33
  var import_mime = require("../../utils/mime");
35
34
  var import_utils2 = require("./utils");
36
- const X_HONO_SSG_HEADER_KEY = "x-hono-ssg";
37
- const X_HONO_DISABLE_SSG_HEADER_KEY = "x-hono-disable-ssg";
35
+ const SSG_CONTEXT = "HONO_SSG_CONTEXT";
36
+ const SSG_DISABLED_RESPONSE = new Response("SSG is disabled", { status: 404 });
38
37
  const generateFilePath = (routePath, outDir, mimeType) => {
39
38
  const extension = determineExtension(mimeType);
40
39
  if (routePath === "/") {
@@ -79,13 +78,9 @@ const ssgParams = (params) => async (c, next) => {
79
78
  const fetchRoutesContent = async (app, beforeRequestHook, afterResponseHook) => {
80
79
  const htmlMap = /* @__PURE__ */ new Map();
81
80
  const baseURL = "http://localhost";
82
- for (const route of (0, import_dev.inspectRoutes)(app)) {
83
- if (route.isMiddleware) {
84
- continue;
85
- }
81
+ for (const route of (0, import_utils2.filterStaticGenerateRoutes)(app)) {
86
82
  const thisRouteBaseURL = new URL(route.path, baseURL).toString();
87
83
  let forGetInfoURLRequest = new Request(thisRouteBaseURL);
88
- forGetInfoURLRequest.headers.set(X_HONO_SSG_HEADER_KEY, "true");
89
84
  if (beforeRequestHook) {
90
85
  const maybeRequest = beforeRequestHook(forGetInfoURLRequest);
91
86
  if (!maybeRequest) {
@@ -106,8 +101,10 @@ const fetchRoutesContent = async (app, beforeRequestHook, afterResponseHook) =>
106
101
  };
107
102
  for (const param of forGetInfoURLRequest.ssgParams) {
108
103
  const replacedUrlParam = (0, import_utils.replaceUrlParam)(route.path, param);
109
- let response = await app.request(replacedUrlParam, requestInit);
110
- if (response.headers.get(X_HONO_DISABLE_SSG_HEADER_KEY)) {
104
+ let response = await app.request(replacedUrlParam, requestInit, {
105
+ [SSG_CONTEXT]: true
106
+ });
107
+ if (response === SSG_DISABLED_RESPONSE) {
111
108
  continue;
112
109
  }
113
110
  if (afterResponseHook) {
@@ -163,23 +160,25 @@ const toSSG = async (app, fs, options) => {
163
160
  await options?.afterGenerateHook?.(result);
164
161
  return result;
165
162
  };
163
+ const isSSGContext = (c) => !!c.env?.[SSG_CONTEXT];
166
164
  const disableSSG = () => async function disableSSG2(c, next) {
165
+ if (isSSGContext(c)) {
166
+ return SSG_DISABLED_RESPONSE;
167
+ }
167
168
  await next();
168
- c.header(X_HONO_DISABLE_SSG_HEADER_KEY, "true");
169
169
  };
170
170
  const onlySSG = () => async function onlySSG2(c, next) {
171
- const headerValue = c.req.raw.headers.get(X_HONO_SSG_HEADER_KEY);
172
- if (headerValue) {
173
- await next();
171
+ if (!isSSGContext(c)) {
172
+ return c.notFound();
174
173
  }
175
- return c.notFound();
174
+ await next();
176
175
  };
177
176
  // Annotate the CommonJS export names for ESM import in node:
178
177
  0 && (module.exports = {
179
- X_HONO_DISABLE_SSG_HEADER_KEY,
180
- X_HONO_SSG_HEADER_KEY,
178
+ SSG_DISABLED_RESPONSE,
181
179
  disableSSG,
182
180
  fetchRoutesContent,
181
+ isSSGContext,
183
182
  onlySSG,
184
183
  saveContentToFiles,
185
184
  ssgParams,
@@ -19,9 +19,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var utils_exports = {};
20
20
  __export(utils_exports, {
21
21
  dirname: () => dirname,
22
+ filterStaticGenerateRoutes: () => filterStaticGenerateRoutes,
22
23
  joinPaths: () => joinPaths
23
24
  });
24
25
  module.exports = __toCommonJS(utils_exports);
26
+ var import_router = require("../../router");
27
+ var import_handler = require("../../utils/handler");
25
28
  const dirname = (path) => {
26
29
  const splitedPath = path.split(/[\/\\]/);
27
30
  return splitedPath.slice(0, -1).join("/");
@@ -57,8 +60,18 @@ const joinPaths = (...paths) => {
57
60
  handleSegments(paths.join("/").split("/"), resultPaths);
58
61
  return (paths[0][0] === "/" ? "/" : "") + resultPaths.join("/");
59
62
  };
63
+ const filterStaticGenerateRoutes = (hono) => {
64
+ return hono.routes.reduce((acc, { method, handler, path }) => {
65
+ const targetHandler = (0, import_handler.findTargetHandler)(handler);
66
+ if (["GET", import_router.METHOD_NAME_ALL].includes(method) && !(0, import_handler.isMiddleware)(targetHandler)) {
67
+ acc.push({ path });
68
+ }
69
+ return acc;
70
+ }, []);
71
+ };
60
72
  // Annotate the CommonJS export names for ESM import in node:
61
73
  0 && (module.exports = {
62
74
  dirname,
75
+ filterStaticGenerateRoutes,
63
76
  joinPaths
64
77
  });
@@ -233,10 +233,8 @@ const _Hono = class extends defineDynamicClass() {
233
233
  let res;
234
234
  try {
235
235
  res = matchResult[0][0][0][0](c, async () => {
236
+ c.res = await this.notFoundHandler(c);
236
237
  });
237
- if (!res) {
238
- return this.notFoundHandler(c);
239
- }
240
238
  } catch (err) {
241
239
  return this.handleError(err, c);
242
240
  }
@@ -77,7 +77,7 @@ const ErrorBoundary = async ({ children, fallback, fallbackRender, onError }) =>
77
77
  if (buffer) {
78
78
  buffer[0] = buffer[0].replace(replaceRe, fallbackResString);
79
79
  }
80
- return buffer ? "" : `<template>${fallbackResString}</template><script>
80
+ return buffer ? "" : `<template data-hono-target="E:${index}">${fallbackResString}</template><script>
81
81
  ((d,c,n) => {
82
82
  c=d.currentScript.previousSibling
83
83
  d=d.getElementById('E:${index}')
@@ -95,7 +95,7 @@ d.replaceWith(c.content)
95
95
  return Promise.all(resArray).then(async (htmlArray) => {
96
96
  htmlArray = htmlArray.flat();
97
97
  const content = htmlArray.join("");
98
- let html = buffer ? "" : `<template>${content}</template><script>
98
+ let html = buffer ? "" : `<template data-hono-target="E:${index}">${content}</template><script>
99
99
  ((d,c) => {
100
100
  c=d.currentScript.previousSibling
101
101
  d=d.getElementById('E:${index}')
@@ -141,7 +141,7 @@ d.parentElement.insertBefore(c.content,d.nextSibling)
141
141
  d=d.getElementById('E:${index}')
142
142
  if(!d)return
143
143
  n=d.nextSibling
144
- do{n=n.nextSibling}while(n.nodeType!=8||n.nodeValue!='E:${index}')
144
+ while(n.nodeType!=8||n.nodeValue!='E:${index}'){n=n.nextSibling}
145
145
  n.remove()
146
146
  d.remove()
147
147
  })(document)
@@ -193,6 +193,7 @@ const applyNodeObject = (node, container) => {
193
193
  }
194
194
  }
195
195
  }
196
+ const childNodes = container.childNodes;
196
197
  for (let i = 0, len = next.length; i < len; i++, offset++) {
197
198
  const child = next[i];
198
199
  let el;
@@ -206,8 +207,8 @@ const applyNodeObject = (node, container) => {
206
207
  applyProps(el, child.props, child.pP);
207
208
  applyNode(child, el);
208
209
  }
209
- if (container.childNodes[offset] !== el) {
210
- container.insertBefore(el, container.childNodes[offset] || null);
210
+ if (childNodes[offset] !== el && childNodes[offset - 1] !== child.e) {
211
+ container.insertBefore(el, childNodes[offset] || null);
211
212
  }
212
213
  }
213
214
  remove.forEach(removeNode);
@@ -82,7 +82,7 @@ const Suspense = async ({
82
82
  content
83
83
  );
84
84
  }
85
- let html = buffer ? "" : `<template>${content}</template><script>
85
+ let html = buffer ? "" : `<template data-hono-target="H:${index}">${content}</template><script>
86
86
  ((d,c,n) => {
87
87
  c=d.currentScript.previousSibling
88
88
  d=d.getElementById('H:${index}')
@@ -29,10 +29,13 @@ var import_streaming = require("../../jsx/streaming");
29
29
  const RequestContext = (0, import_jsx.createContext)(null);
30
30
  const createRenderer = (c, Layout, component, options) => (children, props) => {
31
31
  const docType = typeof options?.docType === "string" ? options.docType : options?.docType === false ? "" : "<!DOCTYPE html>";
32
- const currentLayout = component ? component({
33
- children,
34
- ...{ Layout, ...props }
35
- }) : children;
32
+ const currentLayout = component ? (0, import_jsx.jsx)(
33
+ component,
34
+ {
35
+ ...{ Layout, ...props }
36
+ },
37
+ children
38
+ ) : children;
36
39
  const body = import_html.html`${(0, import_html.raw)(docType)}${(0, import_jsx.jsx)(
37
40
  RequestContext.Provider,
38
41
  { value: c },
@@ -24,7 +24,7 @@ module.exports = __toCommonJS(router_exports);
24
24
  var import_router = require("../../router");
25
25
  var import_url = require("../../utils/url");
26
26
  const emptyParams = {};
27
- const splitPathRe = /\/(:\w+(?:{[^}]+})?)|\/[^\/\?]+|(\?)/g;
27
+ const splitPathRe = /\/(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/[^\/\?]+|(\?)/g;
28
28
  const splitByStarRe = /\*/;
29
29
  class LinearRouter {
30
30
  constructor() {
@@ -32,7 +32,7 @@ class PatternRouter {
32
32
  if (endsWithWildcard) {
33
33
  path = path.slice(0, -2);
34
34
  }
35
- const parts = path.match(/\/?(:\w+(?:{[^}]+})?)|\/?[^\/\?]+|(\?)/g) || [];
35
+ const parts = path.match(/\/?(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/?[^\/\?]+|(\?)/g) || [];
36
36
  if (parts[parts.length - 1] === "?") {
37
37
  this.add(method, parts.slice(0, parts.length - 2).join(""), handler);
38
38
  parts.pop();
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var handler_exports = {};
20
+ __export(handler_exports, {
21
+ findTargetHandler: () => findTargetHandler,
22
+ isMiddleware: () => isMiddleware
23
+ });
24
+ module.exports = __toCommonJS(handler_exports);
25
+ var import_hono_base = require("../hono-base");
26
+ const isMiddleware = (handler) => handler.length > 1;
27
+ const findTargetHandler = (handler) => {
28
+ return handler[import_hono_base.COMPOSED_HANDLER] ? findTargetHandler(handler[import_hono_base.COMPOSED_HANDLER]) : handler;
29
+ };
30
+ // Annotate the CommonJS export names for ESM import in node:
31
+ 0 && (module.exports = {
32
+ findTargetHandler,
33
+ isMiddleware
34
+ });
@@ -7,7 +7,7 @@ var mergePath = (base, path) => {
7
7
  };
8
8
  var replaceUrlParam = (urlString, params) => {
9
9
  for (const [k, v] of Object.entries(params)) {
10
- const reg = new RegExp("/:" + k + "({[^}]*})?");
10
+ const reg = new RegExp("/:" + k + "(?:{[^/]+})?");
11
11
  urlString = urlString.replace(reg, `/${v}`);
12
12
  }
13
13
  return urlString;
package/dist/context.js CHANGED
@@ -102,7 +102,7 @@ var Context = class {
102
102
  const headers2 = setHeaders(new Headers(arg.headers), __privateGet(this, _preparedHeaders));
103
103
  return new Response(data, {
104
104
  headers: headers2,
105
- status: arg.status
105
+ status: arg.status ?? __privateGet(this, _status)
106
106
  });
107
107
  }
108
108
  const status = typeof arg === "number" ? arg : __privateGet(this, _status);
@@ -1,12 +1,8 @@
1
1
  // src/helper/dev/index.ts
2
- import { COMPOSED_HANDLER } from "../../hono-base.js";
3
- var isMiddleware = (handler) => handler.length > 1;
2
+ import { findTargetHandler, isMiddleware } from "../../utils/handler.js";
4
3
  var handlerName = (handler) => {
5
4
  return handler.name || (isMiddleware(handler) ? "[middleware]" : "[handler]");
6
5
  };
7
- var findTargetHandler = (handler) => {
8
- return handler[COMPOSED_HANDLER] ? findTargetHandler(handler[COMPOSED_HANDLER]) : handler;
9
- };
10
6
  var inspectRoutes = (hono) => {
11
7
  return hono.routes.map(({ path, method, handler }) => {
12
8
  const targetHandler = findTargetHandler(handler);
@@ -1,11 +1,10 @@
1
1
  // src/helper/ssg/index.ts
2
2
  import { replaceUrlParam } from "../../client/utils.js";
3
- import { inspectRoutes } from "../../helper/dev/index.js";
4
3
  import { bufferToString } from "../../utils/buffer.js";
5
4
  import { getExtension } from "../../utils/mime.js";
6
- import { joinPaths, dirname } from "./utils.js";
7
- var X_HONO_SSG_HEADER_KEY = "x-hono-ssg";
8
- var X_HONO_DISABLE_SSG_HEADER_KEY = "x-hono-disable-ssg";
5
+ import { joinPaths, dirname, filterStaticGenerateRoutes } from "./utils.js";
6
+ var SSG_CONTEXT = "HONO_SSG_CONTEXT";
7
+ var SSG_DISABLED_RESPONSE = new Response("SSG is disabled", { status: 404 });
9
8
  var generateFilePath = (routePath, outDir, mimeType) => {
10
9
  const extension = determineExtension(mimeType);
11
10
  if (routePath === "/") {
@@ -50,13 +49,9 @@ var ssgParams = (params) => async (c, next) => {
50
49
  var fetchRoutesContent = async (app, beforeRequestHook, afterResponseHook) => {
51
50
  const htmlMap = /* @__PURE__ */ new Map();
52
51
  const baseURL = "http://localhost";
53
- for (const route of inspectRoutes(app)) {
54
- if (route.isMiddleware) {
55
- continue;
56
- }
52
+ for (const route of filterStaticGenerateRoutes(app)) {
57
53
  const thisRouteBaseURL = new URL(route.path, baseURL).toString();
58
54
  let forGetInfoURLRequest = new Request(thisRouteBaseURL);
59
- forGetInfoURLRequest.headers.set(X_HONO_SSG_HEADER_KEY, "true");
60
55
  if (beforeRequestHook) {
61
56
  const maybeRequest = beforeRequestHook(forGetInfoURLRequest);
62
57
  if (!maybeRequest) {
@@ -77,8 +72,10 @@ var fetchRoutesContent = async (app, beforeRequestHook, afterResponseHook) => {
77
72
  };
78
73
  for (const param of forGetInfoURLRequest.ssgParams) {
79
74
  const replacedUrlParam = replaceUrlParam(route.path, param);
80
- let response = await app.request(replacedUrlParam, requestInit);
81
- if (response.headers.get(X_HONO_DISABLE_SSG_HEADER_KEY)) {
75
+ let response = await app.request(replacedUrlParam, requestInit, {
76
+ [SSG_CONTEXT]: true
77
+ });
78
+ if (response === SSG_DISABLED_RESPONSE) {
82
79
  continue;
83
80
  }
84
81
  if (afterResponseHook) {
@@ -134,22 +131,24 @@ var toSSG = async (app, fs, options) => {
134
131
  await options?.afterGenerateHook?.(result);
135
132
  return result;
136
133
  };
134
+ var isSSGContext = (c) => !!c.env?.[SSG_CONTEXT];
137
135
  var disableSSG = () => async function disableSSG2(c, next) {
136
+ if (isSSGContext(c)) {
137
+ return SSG_DISABLED_RESPONSE;
138
+ }
138
139
  await next();
139
- c.header(X_HONO_DISABLE_SSG_HEADER_KEY, "true");
140
140
  };
141
141
  var onlySSG = () => async function onlySSG2(c, next) {
142
- const headerValue = c.req.raw.headers.get(X_HONO_SSG_HEADER_KEY);
143
- if (headerValue) {
144
- await next();
142
+ if (!isSSGContext(c)) {
143
+ return c.notFound();
145
144
  }
146
- return c.notFound();
145
+ await next();
147
146
  };
148
147
  export {
149
- X_HONO_DISABLE_SSG_HEADER_KEY,
150
- X_HONO_SSG_HEADER_KEY,
148
+ SSG_DISABLED_RESPONSE,
151
149
  disableSSG,
152
150
  fetchRoutesContent,
151
+ isSSGContext,
153
152
  onlySSG,
154
153
  saveContentToFiles,
155
154
  ssgParams,
@@ -1,4 +1,6 @@
1
1
  // src/helper/ssg/utils.ts
2
+ import { METHOD_NAME_ALL } from "../../router.js";
3
+ import { findTargetHandler, isMiddleware } from "../../utils/handler.js";
2
4
  var dirname = (path) => {
3
5
  const splitedPath = path.split(/[\/\\]/);
4
6
  return splitedPath.slice(0, -1).join("/");
@@ -34,7 +36,17 @@ var joinPaths = (...paths) => {
34
36
  handleSegments(paths.join("/").split("/"), resultPaths);
35
37
  return (paths[0][0] === "/" ? "/" : "") + resultPaths.join("/");
36
38
  };
39
+ var filterStaticGenerateRoutes = (hono) => {
40
+ return hono.routes.reduce((acc, { method, handler, path }) => {
41
+ const targetHandler = findTargetHandler(handler);
42
+ if (["GET", METHOD_NAME_ALL].includes(method) && !isMiddleware(targetHandler)) {
43
+ acc.push({ path });
44
+ }
45
+ return acc;
46
+ }, []);
47
+ };
37
48
  export {
38
49
  dirname,
50
+ filterStaticGenerateRoutes,
39
51
  joinPaths
40
52
  };
package/dist/hono-base.js CHANGED
@@ -211,10 +211,8 @@ var _Hono = class extends defineDynamicClass() {
211
211
  let res;
212
212
  try {
213
213
  res = matchResult[0][0][0][0](c, async () => {
214
+ c.res = await this.notFoundHandler(c);
214
215
  });
215
- if (!res) {
216
- return this.notFoundHandler(c);
217
- }
218
216
  } catch (err) {
219
217
  return this.handleError(err, c);
220
218
  }
@@ -54,7 +54,7 @@ var ErrorBoundary = async ({ children, fallback, fallbackRender, onError }) => {
54
54
  if (buffer) {
55
55
  buffer[0] = buffer[0].replace(replaceRe, fallbackResString);
56
56
  }
57
- return buffer ? "" : `<template>${fallbackResString}</template><script>
57
+ return buffer ? "" : `<template data-hono-target="E:${index}">${fallbackResString}</template><script>
58
58
  ((d,c,n) => {
59
59
  c=d.currentScript.previousSibling
60
60
  d=d.getElementById('E:${index}')
@@ -72,7 +72,7 @@ d.replaceWith(c.content)
72
72
  return Promise.all(resArray).then(async (htmlArray) => {
73
73
  htmlArray = htmlArray.flat();
74
74
  const content = htmlArray.join("");
75
- let html = buffer ? "" : `<template>${content}</template><script>
75
+ let html = buffer ? "" : `<template data-hono-target="E:${index}">${content}</template><script>
76
76
  ((d,c) => {
77
77
  c=d.currentScript.previousSibling
78
78
  d=d.getElementById('E:${index}')
@@ -118,7 +118,7 @@ d.parentElement.insertBefore(c.content,d.nextSibling)
118
118
  d=d.getElementById('E:${index}')
119
119
  if(!d)return
120
120
  n=d.nextSibling
121
- do{n=n.nextSibling}while(n.nodeType!=8||n.nodeValue!='E:${index}')
121
+ while(n.nodeType!=8||n.nodeValue!='E:${index}'){n=n.nextSibling}
122
122
  n.remove()
123
123
  d.remove()
124
124
  })(document)
@@ -168,6 +168,7 @@ var applyNodeObject = (node, container) => {
168
168
  }
169
169
  }
170
170
  }
171
+ const childNodes = container.childNodes;
171
172
  for (let i = 0, len = next.length; i < len; i++, offset++) {
172
173
  const child = next[i];
173
174
  let el;
@@ -181,8 +182,8 @@ var applyNodeObject = (node, container) => {
181
182
  applyProps(el, child.props, child.pP);
182
183
  applyNode(child, el);
183
184
  }
184
- if (container.childNodes[offset] !== el) {
185
- container.insertBefore(el, container.childNodes[offset] || null);
185
+ if (childNodes[offset] !== el && childNodes[offset - 1] !== child.e) {
186
+ container.insertBefore(el, childNodes[offset] || null);
186
187
  }
187
188
  }
188
189
  remove.forEach(removeNode);
@@ -59,7 +59,7 @@ var Suspense = async ({
59
59
  content
60
60
  );
61
61
  }
62
- let html = buffer ? "" : `<template>${content}</template><script>
62
+ let html = buffer ? "" : `<template data-hono-target="H:${index}">${content}</template><script>
63
63
  ((d,c,n) => {
64
64
  c=d.currentScript.previousSibling
65
65
  d=d.getElementById('H:${index}')
@@ -5,10 +5,13 @@ import { renderToReadableStream } from "../../jsx/streaming.js";
5
5
  var RequestContext = createContext(null);
6
6
  var createRenderer = (c, Layout, component, options) => (children, props) => {
7
7
  const docType = typeof options?.docType === "string" ? options.docType : options?.docType === false ? "" : "<!DOCTYPE html>";
8
- const currentLayout = component ? component({
9
- children,
10
- ...{ Layout, ...props }
11
- }) : children;
8
+ const currentLayout = component ? jsx(
9
+ component,
10
+ {
11
+ ...{ Layout, ...props }
12
+ },
13
+ children
14
+ ) : children;
12
15
  const body = html`${raw(docType)}${jsx(
13
16
  RequestContext.Provider,
14
17
  { value: c },
@@ -2,7 +2,7 @@
2
2
  import { METHOD_NAME_ALL, UnsupportedPathError } from "../../router.js";
3
3
  import { checkOptionalParameter } from "../../utils/url.js";
4
4
  var emptyParams = {};
5
- var splitPathRe = /\/(:\w+(?:{[^}]+})?)|\/[^\/\?]+|(\?)/g;
5
+ var splitPathRe = /\/(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/[^\/\?]+|(\?)/g;
6
6
  var splitByStarRe = /\*/;
7
7
  var LinearRouter = class {
8
8
  constructor() {
@@ -10,7 +10,7 @@ var PatternRouter = class {
10
10
  if (endsWithWildcard) {
11
11
  path = path.slice(0, -2);
12
12
  }
13
- const parts = path.match(/\/?(:\w+(?:{[^}]+})?)|\/?[^\/\?]+|(\?)/g) || [];
13
+ const parts = path.match(/\/?(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/?[^\/\?]+|(\?)/g) || [];
14
14
  if (parts[parts.length - 1] === "?") {
15
15
  this.add(method, parts.slice(0, parts.length - 2).join(""), handler);
16
16
  parts.pop();
@@ -1,7 +1,7 @@
1
- import type { Env, Input, MiddlewareHandler, H, HandlerResponse } from '../../types';
1
+ import type { Env, H, HandlerResponse, Input, MiddlewareHandler } from '../../types';
2
2
  export declare class Factory<E extends Env = any, P extends string = any> {
3
3
  createMiddleware: <I extends Input = {}>(middleware: MiddlewareHandler<E, P, I>) => MiddlewareHandler<E, P, I>;
4
- createHandlers<I extends Input = {}>(handler1: H<E, P, I>): [H<E, P, I>];
4
+ createHandlers<I extends Input = {}, R extends HandlerResponse<any> = any>(handler1: H<E, P, I, R>): [H<E, P, I, R>];
5
5
  createHandlers<I extends Input = {}, I2 extends Input = I, R extends HandlerResponse<any> = any>(handler1: H<E, P, I, R>, handler2: H<E, P, I2, R>): [H<E, P, I, R>, H<E, P, I2, R>];
6
6
  createHandlers<I extends Input = {}, I2 extends Input = I, I3 extends Input = I & I2, R extends HandlerResponse<any> = any>(handler1: H<E, P, I, R>, handler2: H<E, P, I2, R>, handler3: H<E, P, I3, R>): [H<E, P, I, R>, H<E, P, I2, R>, H<E, P, I3, R>];
7
7
  createHandlers<I extends Input = {}, I2 extends Input = I, I3 extends Input = I & I2, I4 extends Input = I & I2 & I3, R extends HandlerResponse<any> = any>(handler1: H<E, P, I, R>, handler2: H<E, P, I2, R>, handler3: H<E, P, I3, R>, handler4: H<E, P, I4, R>): [H<E, P, I, R>, H<E, P, I2, R>, H<E, P, I3, R>, H<E, P, I4, R>];
@@ -1,8 +1,7 @@
1
1
  import type { Context } from '../../context';
2
2
  import type { Hono } from '../../hono';
3
3
  import type { Env, MiddlewareHandler, Schema } from '../../types';
4
- export declare const X_HONO_SSG_HEADER_KEY = "x-hono-ssg";
5
- export declare const X_HONO_DISABLE_SSG_HEADER_KEY = "x-hono-disable-ssg";
4
+ export declare const SSG_DISABLED_RESPONSE: Response;
6
5
  /**
7
6
  * @experimental
8
7
  * `FileSystemModule` is an experimental feature.
@@ -85,6 +84,12 @@ export interface ToSSGAdaptorInterface<E extends Env = Env, S extends Schema = {
85
84
  * The API might be changed.
86
85
  */
87
86
  export declare const toSSG: ToSSGInterface;
87
+ /**
88
+ * @experimental
89
+ * `isSSGContext` is an experimental feature.
90
+ * The API might be changed.
91
+ */
92
+ export declare const isSSGContext: (c: Context) => boolean;
88
93
  /**
89
94
  * @experimental
90
95
  * `disableSSG` is an experimental feature.
@@ -1,3 +1,5 @@
1
+ import type { Hono } from '../../hono';
2
+ import type { Env } from '../../types';
1
3
  /**
2
4
  * Get dirname
3
5
  * @param path File Path
@@ -5,3 +7,8 @@
5
7
  */
6
8
  export declare const dirname: (path: string) => string;
7
9
  export declare const joinPaths: (...paths: string[]) => string;
10
+ interface FilterStaticGenerateRouteData {
11
+ path: string;
12
+ }
13
+ export declare const filterStaticGenerateRoutes: <E extends Env>(hono: Hono<E, import("../../types").BlankSchema, "/">) => FilterStaticGenerateRouteData[];
14
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare const isMiddleware: (handler: Function) => boolean;
2
+ export declare const findTargetHandler: (handler: Function) => Function;
@@ -0,0 +1,10 @@
1
+ // src/utils/handler.ts
2
+ import { COMPOSED_HANDLER } from "../hono-base.js";
3
+ var isMiddleware = (handler) => handler.length > 1;
4
+ var findTargetHandler = (handler) => {
5
+ return handler[COMPOSED_HANDLER] ? findTargetHandler(handler[COMPOSED_HANDLER]) : handler;
6
+ };
7
+ export {
8
+ findTargetHandler,
9
+ isMiddleware
10
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "4.0.1",
3
+ "version": "4.0.3",
4
4
  "description": "Ultrafast web framework for the Edges",
5
5
  "main": "dist/cjs/index.js",
6
6
  "type": "module",