hono 4.4.4 → 4.5.0-rc.1

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.
@@ -31,7 +31,7 @@ const setHeaders = (headers, map = {}) => {
31
31
  class Context {
32
32
  req;
33
33
  env = {};
34
- _var = {};
34
+ _var;
35
35
  finalized = false;
36
36
  error = void 0;
37
37
  #status = 200;
@@ -71,9 +71,6 @@ class Hono {
71
71
  };
72
72
  });
73
73
  this.on = (method, path, ...handlers) => {
74
- if (!method) {
75
- return this;
76
- }
77
74
  for (const p of [path].flat()) {
78
75
  this.#path = p;
79
76
  for (const m of [method].flat()) {
@@ -113,9 +110,6 @@ class Hono {
113
110
  errorHandler = errorHandler;
114
111
  route(path, app) {
115
112
  const subApp = this.basePath(path);
116
- if (!app) {
117
- return subApp;
118
- }
119
113
  app.routes.map((r) => {
120
114
  let handler;
121
115
  if (app.errorHandler === errorHandler) {
@@ -133,10 +133,8 @@ class JSXNode {
133
133
  const props = this.props;
134
134
  let { children } = this;
135
135
  buffer[0] += `<${tag}`;
136
- const propsKeys = Object.keys(props || {});
137
- for (let i = 0, len = propsKeys.length; i < len; i++) {
138
- const key = propsKeys[i];
139
- const v = props[key];
136
+ for (let [key, v] of Object.entries(props)) {
137
+ key = (0, import_utils.normalizeIntrinsicElementKey)(key);
140
138
  if (key === "children") {
141
139
  } else if (key === "style" && typeof v === "object") {
142
140
  let styleStr = "";
@@ -237,7 +235,6 @@ const jsxFn = (tag, props, children) => {
237
235
  if (typeof tag === "function") {
238
236
  return new JSXFunctionNode(tag, props, children);
239
237
  } else {
240
- (0, import_utils.normalizeIntrinsicElementProps)(props);
241
238
  return new JSXNode(tag, props, children);
242
239
  }
243
240
  };
@@ -19,6 +19,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var client_exports = {};
20
20
  __export(client_exports, {
21
21
  createRoot: () => createRoot,
22
+ default: () => client_default,
22
23
  hydrateRoot: () => hydrateRoot
23
24
  });
24
25
  module.exports = __toCommonJS(client_exports);
@@ -61,6 +62,10 @@ const hydrateRoot = (element, reactNode, options = {}) => {
61
62
  root.render(reactNode);
62
63
  return root;
63
64
  };
65
+ var client_default = {
66
+ createRoot,
67
+ hydrateRoot
68
+ };
64
69
  // Annotate the CommonJS export names for ESM import in node:
65
70
  0 && (module.exports = {
66
71
  createRoot,
@@ -21,6 +21,7 @@ __export(dom_exports, {
21
21
  Children: () => import_children.Children,
22
22
  ErrorBoundary: () => import_components.ErrorBoundary,
23
23
  Fragment: () => import_jsx_runtime.Fragment,
24
+ StrictMode: () => import_jsx_runtime.Fragment,
24
25
  Suspense: () => import_components.Suspense,
25
26
  cloneElement: () => cloneElement,
26
27
  createContext: () => import_context2.createContext,
@@ -120,6 +121,7 @@ var dom_default = {
120
121
  cloneElement,
121
122
  Children: import_children.Children,
122
123
  Fragment: import_jsx_runtime.Fragment,
124
+ StrictMode: import_jsx_runtime.Fragment,
123
125
  flushSync: import_render.flushSync,
124
126
  createPortal: import_render.createPortal
125
127
  };
@@ -128,6 +130,7 @@ var dom_default = {
128
130
  Children,
129
131
  ErrorBoundary,
130
132
  Fragment,
133
+ StrictMode,
131
134
  Suspense,
132
135
  cloneElement,
133
136
  createContext,
@@ -22,13 +22,9 @@ __export(jsx_dev_runtime_exports, {
22
22
  jsxDEV: () => jsxDEV
23
23
  });
24
24
  module.exports = __toCommonJS(jsx_dev_runtime_exports);
25
- var import_utils = require("../utils");
26
- var import_utils2 = require("./utils");
25
+ var import_utils = require("./utils");
27
26
  const jsxDEV = (tag, props, key) => {
28
- if (typeof tag === "string") {
29
- (0, import_utils.normalizeIntrinsicElementProps)(props);
30
- }
31
- return (0, import_utils2.newJSXNode)({
27
+ return (0, import_utils.newJSXNode)({
32
28
  tag,
33
29
  props,
34
30
  key
@@ -41,8 +41,8 @@ const eventAliasMap = {
41
41
  DoubleClick: "DblClick"
42
42
  };
43
43
  const nameSpaceMap = {
44
- svg: "http://www.w3.org/2000/svg",
45
- math: "http://www.w3.org/1998/Math/MathML"
44
+ svg: "2000/svg",
45
+ math: "1998/Math/MathML"
46
46
  };
47
47
  const skipProps = /* @__PURE__ */ new Set(["children"]);
48
48
  const buildDataStack = [];
@@ -59,8 +59,9 @@ const getEventSpec = (key) => {
59
59
  const toAttributeName = (element, key) => element instanceof SVGElement && /[A-Z]/.test(key) && (key in element.style || key.match(/^(?:o|pai|str|u|ve)/)) ? key.replace(/([A-Z])/g, "-$1").toLowerCase() : key;
60
60
  const applyProps = (container, attributes, oldAttributes) => {
61
61
  attributes ||= {};
62
- for (const [key, value] of Object.entries(attributes)) {
62
+ for (let [key, value] of Object.entries(attributes)) {
63
63
  if (!skipProps.has(key) && (!oldAttributes || oldAttributes[key] !== value)) {
64
+ key = (0, import_utils.normalizeIntrinsicElementKey)(key);
64
65
  const eventSpec = getEventSpec(key);
65
66
  if (eventSpec) {
66
67
  if (oldAttributes) {
@@ -125,8 +126,9 @@ const applyProps = (container, attributes, oldAttributes) => {
125
126
  }
126
127
  }
127
128
  if (oldAttributes) {
128
- for (const [key, value] of Object.entries(oldAttributes)) {
129
+ for (let [key, value] of Object.entries(oldAttributes)) {
129
130
  if (!skipProps.has(key) && !(key in attributes)) {
131
+ key = (0, import_utils.normalizeIntrinsicElementKey)(key);
130
132
  const eventSpec = getEventSpec(key);
131
133
  if (eventSpec) {
132
134
  container.removeEventListener(eventSpec[0], value, eventSpec[1]);
@@ -386,14 +388,12 @@ const buildNode = (node) => {
386
388
  } else {
387
389
  const ns = nameSpaceMap[node.tag];
388
390
  if (ns) {
389
- ;
390
- node.n = ns;
391
391
  nameSpaceContext ||= (0, import_context2.createContext)("");
392
392
  node.props.children = [
393
393
  {
394
394
  tag: nameSpaceContext.Provider,
395
395
  props: {
396
- value: ns,
396
+ value: node.n = `http://www.w3.org/${ns}`,
397
397
  children: node.props.children
398
398
  }
399
399
  }
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
25
+ var server_exports = {};
26
+ __export(server_exports, {
27
+ default: () => server_default,
28
+ renderToReadableStream: () => renderToReadableStream,
29
+ renderToString: () => renderToString,
30
+ version: () => import__.default
31
+ });
32
+ module.exports = __toCommonJS(server_exports);
33
+ var import_streaming = require("../streaming");
34
+ var import__ = __toESM(require("./"), 1);
35
+ const renderToString = (element, options = {}) => {
36
+ if (Object.keys(options).length > 0) {
37
+ console.warn("options are not supported yet");
38
+ }
39
+ const res = element?.toString() ?? "";
40
+ if (typeof res !== "string") {
41
+ throw new Error("Async component is not supported in renderToString");
42
+ }
43
+ return res;
44
+ };
45
+ const renderToReadableStream = async (element, options = {}) => {
46
+ if (Object.keys(options).some((key) => key !== "onError")) {
47
+ console.warn("options are not supported yet, except onError");
48
+ }
49
+ if (!element || typeof element !== "object") {
50
+ element = element?.toString() ?? "";
51
+ }
52
+ return (0, import_streaming.renderToReadableStream)(element, options.onError);
53
+ };
54
+ var server_default = {
55
+ renderToString,
56
+ renderToReadableStream,
57
+ version: import__.default
58
+ };
59
+ // Annotate the CommonJS export names for ESM import in node:
60
+ 0 && (module.exports = {
61
+ renderToReadableStream,
62
+ renderToString,
63
+ version
64
+ });
@@ -21,6 +21,7 @@ __export(jsx_exports, {
21
21
  Children: () => import_children.Children,
22
22
  ErrorBoundary: () => import_components.ErrorBoundary,
23
23
  Fragment: () => import_base.Fragment,
24
+ StrictMode: () => import_base.Fragment,
24
25
  Suspense: () => import_streaming.Suspense,
25
26
  cloneElement: () => import_base.cloneElement,
26
27
  createContext: () => import_context.createContext,
@@ -63,6 +64,7 @@ var jsx_default = {
63
64
  version: import_base.reactAPICompatVersion,
64
65
  memo: import_base.memo,
65
66
  Fragment: import_base.Fragment,
67
+ StrictMode: import_base.Fragment,
66
68
  isValidElement: import_base.isValidElement,
67
69
  createElement: import_base.jsx,
68
70
  cloneElement: import_base.cloneElement,
@@ -97,6 +99,7 @@ var jsx_default = {
97
99
  Children,
98
100
  ErrorBoundary,
99
101
  Fragment,
102
+ StrictMode,
100
103
  Suspense,
101
104
  cloneElement,
102
105
  createContext,
@@ -18,20 +18,15 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var utils_exports = {};
20
20
  __export(utils_exports, {
21
- normalizeIntrinsicElementProps: () => normalizeIntrinsicElementProps,
21
+ normalizeIntrinsicElementKey: () => normalizeIntrinsicElementKey,
22
22
  styleObjectForEach: () => styleObjectForEach
23
23
  });
24
24
  module.exports = __toCommonJS(utils_exports);
25
- const normalizeIntrinsicElementProps = (props) => {
26
- if (props && "className" in props) {
27
- props["class"] = props["className"];
28
- delete props["className"];
29
- }
30
- if (props && "htmlFor" in props) {
31
- props["for"] = props["htmlFor"];
32
- delete props["htmlFor"];
33
- }
34
- };
25
+ const normalizeElementKeyMap = /* @__PURE__ */ new Map([
26
+ ["className", "class"],
27
+ ["htmlFor", "for"]
28
+ ]);
29
+ const normalizeIntrinsicElementKey = (key) => normalizeElementKeyMap.get(key) || key;
35
30
  const styleObjectForEach = (style, fn) => {
36
31
  for (const [k, v] of Object.entries(style)) {
37
32
  const key = k[0] === "-" || !/[A-Z]/.test(k) ? k : k.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
@@ -45,6 +40,6 @@ const styleObjectForEach = (style, fn) => {
45
40
  };
46
41
  // Annotate the CommonJS export names for ESM import in node:
47
42
  0 && (module.exports = {
48
- normalizeIntrinsicElementProps,
43
+ normalizeIntrinsicElementKey,
49
44
  styleObjectForEach
50
45
  });
@@ -50,7 +50,12 @@ const cors = (options) => {
50
50
  set("Access-Control-Allow-Origin", allowOrigin);
51
51
  }
52
52
  if (opts.origin !== "*") {
53
- set("Vary", "Origin");
53
+ const existingVary = c.req.header("Vary");
54
+ if (existingVary) {
55
+ set("Vary", existingVary);
56
+ } else {
57
+ set("Vary", "Origin");
58
+ }
54
59
  }
55
60
  if (opts.credentials) {
56
61
  set("Access-Control-Allow-Credentials", "true");
@@ -75,12 +75,7 @@ class HonoRequest {
75
75
  return headerData;
76
76
  }
77
77
  async parseBody(options) {
78
- if (this.bodyCache.parsedBody) {
79
- return this.bodyCache.parsedBody;
80
- }
81
- const parsedBody = await (0, import_body.parseBody)(this, options);
82
- this.bodyCache.parsedBody = parsedBody;
83
- return parsedBody;
78
+ return this.bodyCache.parsedBody ??= await (0, import_body.parseBody)(this, options);
84
79
  }
85
80
  cachedBody = (key) => {
86
81
  const { bodyCache, raw } = this;
@@ -88,19 +83,14 @@ class HonoRequest {
88
83
  if (cachedBody) {
89
84
  return cachedBody;
90
85
  }
91
- if (!bodyCache[key]) {
92
- for (const keyOfBodyCache of Object.keys(bodyCache)) {
93
- if (keyOfBodyCache === "parsedBody") {
94
- continue;
86
+ const anyCachedKey = Object.keys(bodyCache)[0];
87
+ if (anyCachedKey) {
88
+ return bodyCache[anyCachedKey].then((body) => {
89
+ if (anyCachedKey === "json") {
90
+ body = JSON.stringify(body);
95
91
  }
96
- return (async () => {
97
- let body = await bodyCache[keyOfBodyCache];
98
- if (keyOfBodyCache === "json") {
99
- body = JSON.stringify(body);
100
- }
101
- return await new Response(body)[key]();
102
- })();
103
- }
92
+ return new Response(body)[key]();
93
+ });
104
94
  }
105
95
  return bodyCache[key] = raw[key]();
106
96
  };
package/dist/context.js CHANGED
@@ -8,7 +8,7 @@ var setHeaders = (headers, map = {}) => {
8
8
  var Context = class {
9
9
  req;
10
10
  env = {};
11
- _var = {};
11
+ _var;
12
12
  finalized = false;
13
13
  error = void 0;
14
14
  #status = 200;
package/dist/hono-base.js CHANGED
@@ -48,9 +48,6 @@ var Hono = class {
48
48
  };
49
49
  });
50
50
  this.on = (method, path, ...handlers) => {
51
- if (!method) {
52
- return this;
53
- }
54
51
  for (const p of [path].flat()) {
55
52
  this.#path = p;
56
53
  for (const m of [method].flat()) {
@@ -90,9 +87,6 @@ var Hono = class {
90
87
  errorHandler = errorHandler;
91
88
  route(path, app) {
92
89
  const subApp = this.basePath(path);
93
- if (!app) {
94
- return subApp;
95
- }
96
90
  app.routes.map((r) => {
97
91
  let handler;
98
92
  if (app.errorHandler === errorHandler) {
package/dist/jsx/base.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { raw } from "../helper/html/index.js";
3
3
  import { escapeToBuffer, stringBufferToString } from "../utils/html.js";
4
4
  import { globalContexts } from "./context.js";
5
- import { normalizeIntrinsicElementProps, styleObjectForEach } from "./utils.js";
5
+ import { normalizeIntrinsicElementKey, styleObjectForEach } from "./utils.js";
6
6
  var emptyTags = [
7
7
  "area",
8
8
  "base",
@@ -103,10 +103,8 @@ var JSXNode = class {
103
103
  const props = this.props;
104
104
  let { children } = this;
105
105
  buffer[0] += `<${tag}`;
106
- const propsKeys = Object.keys(props || {});
107
- for (let i = 0, len = propsKeys.length; i < len; i++) {
108
- const key = propsKeys[i];
109
- const v = props[key];
106
+ for (let [key, v] of Object.entries(props)) {
107
+ key = normalizeIntrinsicElementKey(key);
110
108
  if (key === "children") {
111
109
  } else if (key === "style" && typeof v === "object") {
112
110
  let styleStr = "";
@@ -207,7 +205,6 @@ var jsxFn = (tag, props, children) => {
207
205
  if (typeof tag === "function") {
208
206
  return new JSXFunctionNode(tag, props, children);
209
207
  } else {
210
- normalizeIntrinsicElementProps(props);
211
208
  return new JSXNode(tag, props, children);
212
209
  }
213
210
  };
@@ -38,7 +38,12 @@ var hydrateRoot = (element, reactNode, options = {}) => {
38
38
  root.render(reactNode);
39
39
  return root;
40
40
  };
41
+ var client_default = {
42
+ createRoot,
43
+ hydrateRoot
44
+ };
41
45
  export {
42
46
  createRoot,
47
+ client_default as default,
43
48
  hydrateRoot
44
49
  };
@@ -84,6 +84,7 @@ var dom_default = {
84
84
  cloneElement,
85
85
  Children,
86
86
  Fragment,
87
+ StrictMode: Fragment,
87
88
  flushSync,
88
89
  createPortal
89
90
  };
@@ -91,6 +92,7 @@ export {
91
92
  Children,
92
93
  ErrorBoundary,
93
94
  Fragment,
95
+ Fragment as StrictMode,
94
96
  Suspense,
95
97
  cloneElement,
96
98
  createContext,
@@ -1,10 +1,6 @@
1
1
  // src/jsx/dom/jsx-dev-runtime.ts
2
- import { normalizeIntrinsicElementProps } from "../utils.js";
3
2
  import { newJSXNode } from "./utils.js";
4
3
  var jsxDEV = (tag, props, key) => {
5
- if (typeof tag === "string") {
6
- normalizeIntrinsicElementProps(props);
7
- }
8
4
  return newJSXNode({
9
5
  tag,
10
6
  props,
@@ -3,7 +3,7 @@ import { toArray } from "../children.js";
3
3
  import { DOM_ERROR_HANDLER, DOM_INTERNAL_TAG, DOM_RENDERER, DOM_STASH } from "../constants.js";
4
4
  import { globalContexts as globalJSXContexts, useContext } from "../context.js";
5
5
  import { STASH_EFFECT } from "../hooks/index.js";
6
- import { styleObjectForEach } from "../utils.js";
6
+ import { normalizeIntrinsicElementKey, styleObjectForEach } from "../utils.js";
7
7
  import { createContext } from "./context.js";
8
8
  import { newJSXNode } from "./utils.js";
9
9
  var HONO_PORTAL_ELEMENT = "_hp";
@@ -12,8 +12,8 @@ var eventAliasMap = {
12
12
  DoubleClick: "DblClick"
13
13
  };
14
14
  var nameSpaceMap = {
15
- svg: "http://www.w3.org/2000/svg",
16
- math: "http://www.w3.org/1998/Math/MathML"
15
+ svg: "2000/svg",
16
+ math: "1998/Math/MathML"
17
17
  };
18
18
  var skipProps = /* @__PURE__ */ new Set(["children"]);
19
19
  var buildDataStack = [];
@@ -30,8 +30,9 @@ var getEventSpec = (key) => {
30
30
  var toAttributeName = (element, key) => element instanceof SVGElement && /[A-Z]/.test(key) && (key in element.style || key.match(/^(?:o|pai|str|u|ve)/)) ? key.replace(/([A-Z])/g, "-$1").toLowerCase() : key;
31
31
  var applyProps = (container, attributes, oldAttributes) => {
32
32
  attributes ||= {};
33
- for (const [key, value] of Object.entries(attributes)) {
33
+ for (let [key, value] of Object.entries(attributes)) {
34
34
  if (!skipProps.has(key) && (!oldAttributes || oldAttributes[key] !== value)) {
35
+ key = normalizeIntrinsicElementKey(key);
35
36
  const eventSpec = getEventSpec(key);
36
37
  if (eventSpec) {
37
38
  if (oldAttributes) {
@@ -96,8 +97,9 @@ var applyProps = (container, attributes, oldAttributes) => {
96
97
  }
97
98
  }
98
99
  if (oldAttributes) {
99
- for (const [key, value] of Object.entries(oldAttributes)) {
100
+ for (let [key, value] of Object.entries(oldAttributes)) {
100
101
  if (!skipProps.has(key) && !(key in attributes)) {
102
+ key = normalizeIntrinsicElementKey(key);
101
103
  const eventSpec = getEventSpec(key);
102
104
  if (eventSpec) {
103
105
  container.removeEventListener(eventSpec[0], value, eventSpec[1]);
@@ -357,14 +359,12 @@ var buildNode = (node) => {
357
359
  } else {
358
360
  const ns = nameSpaceMap[node.tag];
359
361
  if (ns) {
360
- ;
361
- node.n = ns;
362
362
  nameSpaceContext ||= createContext("");
363
363
  node.props.children = [
364
364
  {
365
365
  tag: nameSpaceContext.Provider,
366
366
  props: {
367
- value: ns,
367
+ value: node.n = `http://www.w3.org/${ns}`,
368
368
  children: node.props.children
369
369
  }
370
370
  }
@@ -0,0 +1,33 @@
1
+ // src/jsx/dom/server.ts
2
+ import { renderToReadableStream as renderToReadableStreamHono } from "../streaming.js";
3
+ import version from ".//index.js";
4
+ var renderToString = (element, options = {}) => {
5
+ if (Object.keys(options).length > 0) {
6
+ console.warn("options are not supported yet");
7
+ }
8
+ const res = element?.toString() ?? "";
9
+ if (typeof res !== "string") {
10
+ throw new Error("Async component is not supported in renderToString");
11
+ }
12
+ return res;
13
+ };
14
+ var renderToReadableStream = async (element, options = {}) => {
15
+ if (Object.keys(options).some((key) => key !== "onError")) {
16
+ console.warn("options are not supported yet, except onError");
17
+ }
18
+ if (!element || typeof element !== "object") {
19
+ element = element?.toString() ?? "";
20
+ }
21
+ return renderToReadableStreamHono(element, options.onError);
22
+ };
23
+ var server_default = {
24
+ renderToString,
25
+ renderToReadableStream,
26
+ version
27
+ };
28
+ export {
29
+ server_default as default,
30
+ renderToReadableStream,
31
+ renderToString,
32
+ version
33
+ };
package/dist/jsx/index.js CHANGED
@@ -30,6 +30,7 @@ var jsx_default = {
30
30
  version: reactAPICompatVersion,
31
31
  memo,
32
32
  Fragment,
33
+ StrictMode: Fragment,
33
34
  isValidElement,
34
35
  createElement: jsx,
35
36
  cloneElement,
@@ -63,6 +64,7 @@ export {
63
64
  Children,
64
65
  ErrorBoundary,
65
66
  Fragment,
67
+ Fragment as StrictMode,
66
68
  Suspense,
67
69
  cloneElement,
68
70
  createContext,
package/dist/jsx/utils.js CHANGED
@@ -1,14 +1,9 @@
1
1
  // src/jsx/utils.ts
2
- var normalizeIntrinsicElementProps = (props) => {
3
- if (props && "className" in props) {
4
- props["class"] = props["className"];
5
- delete props["className"];
6
- }
7
- if (props && "htmlFor" in props) {
8
- props["for"] = props["htmlFor"];
9
- delete props["htmlFor"];
10
- }
11
- };
2
+ var normalizeElementKeyMap = /* @__PURE__ */ new Map([
3
+ ["className", "class"],
4
+ ["htmlFor", "for"]
5
+ ]);
6
+ var normalizeIntrinsicElementKey = (key) => normalizeElementKeyMap.get(key) || key;
12
7
  var styleObjectForEach = (style, fn) => {
13
8
  for (const [k, v] of Object.entries(style)) {
14
9
  const key = k[0] === "-" || !/[A-Z]/.test(k) ? k : k.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
@@ -21,6 +16,6 @@ var styleObjectForEach = (style, fn) => {
21
16
  }
22
17
  };
23
18
  export {
24
- normalizeIntrinsicElementProps,
19
+ normalizeIntrinsicElementKey,
25
20
  styleObjectForEach
26
21
  };
@@ -28,7 +28,12 @@ var cors = (options) => {
28
28
  set("Access-Control-Allow-Origin", allowOrigin);
29
29
  }
30
30
  if (opts.origin !== "*") {
31
- set("Vary", "Origin");
31
+ const existingVary = c.req.header("Vary");
32
+ if (existingVary) {
33
+ set("Vary", existingVary);
34
+ } else {
35
+ set("Vary", "Origin");
36
+ }
32
37
  }
33
38
  if (opts.credentials) {
34
39
  set("Access-Control-Allow-Credentials", "true");
package/dist/request.js CHANGED
@@ -53,12 +53,7 @@ var HonoRequest = class {
53
53
  return headerData;
54
54
  }
55
55
  async parseBody(options) {
56
- if (this.bodyCache.parsedBody) {
57
- return this.bodyCache.parsedBody;
58
- }
59
- const parsedBody = await parseBody(this, options);
60
- this.bodyCache.parsedBody = parsedBody;
61
- return parsedBody;
56
+ return this.bodyCache.parsedBody ??= await parseBody(this, options);
62
57
  }
63
58
  cachedBody = (key) => {
64
59
  const { bodyCache, raw } = this;
@@ -66,19 +61,14 @@ var HonoRequest = class {
66
61
  if (cachedBody) {
67
62
  return cachedBody;
68
63
  }
69
- if (!bodyCache[key]) {
70
- for (const keyOfBodyCache of Object.keys(bodyCache)) {
71
- if (keyOfBodyCache === "parsedBody") {
72
- continue;
64
+ const anyCachedKey = Object.keys(bodyCache)[0];
65
+ if (anyCachedKey) {
66
+ return bodyCache[anyCachedKey].then((body) => {
67
+ if (anyCachedKey === "json") {
68
+ body = JSON.stringify(body);
73
69
  }
74
- return (async () => {
75
- let body = await bodyCache[keyOfBodyCache];
76
- if (keyOfBodyCache === "json") {
77
- body = JSON.stringify(body);
78
- }
79
- return await new Response(body)[key]();
80
- })();
81
- }
70
+ return new Response(body)[key]();
71
+ });
82
72
  }
83
73
  return bodyCache[key] = raw[key]();
84
74
  };
@@ -95,8 +95,8 @@ interface BodyRespond extends NewResponse {
95
95
  * @returns {Response & TypedResponse<T, U, 'text'>} - The response after rendering the text content, typed with the provided text and status code types.
96
96
  */
97
97
  interface TextRespond {
98
- <T extends string, U extends StatusCode>(text: T, status?: U, headers?: HeaderRecord): Response & TypedResponse<T, U, 'text'>;
99
- <T extends string, U extends StatusCode>(text: T, init?: ResponseInit): Response & TypedResponse<T, U, 'text'>;
98
+ <T extends string, U extends StatusCode = StatusCode>(text: T, status?: U, headers?: HeaderRecord): Response & TypedResponse<T, U, 'text'>;
99
+ <T extends string, U extends StatusCode = StatusCode>(text: T, init?: ResponseInit): Response & TypedResponse<T, U, 'text'>;
100
100
  }
101
101
  /**
102
102
  * Interface for responding with JSON.
@@ -112,8 +112,8 @@ interface TextRespond {
112
112
  * @returns {JSONRespondReturn<T, U>} - The response after rendering the JSON object, typed with the provided object and status code types.
113
113
  */
114
114
  interface JSONRespond {
115
- <T extends JSONValue | SimplifyDeepArray<unknown>, U extends StatusCode>(object: T, status?: U, headers?: HeaderRecord): JSONRespondReturn<T, U>;
116
- <T extends JSONValue | SimplifyDeepArray<unknown>, U extends StatusCode>(object: T, init?: ResponseInit): JSONRespondReturn<T, U>;
115
+ <T extends JSONValue | SimplifyDeepArray<unknown>, U extends StatusCode = StatusCode>(object: T, status?: U, headers?: HeaderRecord): JSONRespondReturn<T, U>;
116
+ <T extends JSONValue | SimplifyDeepArray<unknown>, U extends StatusCode = StatusCode>(object: T, init?: ResponseInit): JSONRespondReturn<T, U>;
117
117
  }
118
118
  /**
119
119
  * @template T - The type of the JSON value or simplified unknown type.
@@ -98,7 +98,7 @@ declare class Hono<E extends Env = Env, S extends Schema = {}, BasePath extends
98
98
  * app.route("/api", app2) // GET /api/user
99
99
  * ```
100
100
  */
101
- route<SubPath extends string, SubEnv extends Env, SubSchema extends Schema, SubBasePath extends string>(path: SubPath, app?: Hono<SubEnv, SubSchema, SubBasePath>): Hono<E, MergeSchemaPath<SubSchema, MergePath<BasePath, SubPath>> & S, BasePath>;
101
+ route<SubPath extends string, SubEnv extends Env, SubSchema extends Schema, SubBasePath extends string>(path: SubPath, app: Hono<SubEnv, SubSchema, SubBasePath>): Hono<E, MergeSchemaPath<SubSchema, MergePath<BasePath, SubPath>> & S, BasePath>;
102
102
  /**
103
103
  * `.basePath()` allows base paths to be specified.
104
104
  *
@@ -1,13 +1,13 @@
1
1
  import type { HtmlEscaped, HtmlEscapedString, StringBuffer } from '../utils/html';
2
2
  import type { Context } from './context';
3
- import type { Hono, IntrinsicElements as IntrinsicElementsDefined } from './intrinsic-elements';
3
+ import type { JSX as HonoJSX, IntrinsicElements as IntrinsicElementsDefined } from './intrinsic-elements';
4
4
  export type Props = Record<string, any>;
5
5
  export type FC<P = Props> = {
6
6
  (props: P): HtmlEscapedString | Promise<HtmlEscapedString>;
7
7
  defaultProps?: Partial<P> | undefined;
8
8
  displayName?: string | undefined;
9
9
  };
10
- export type DOMAttributes = Hono.HTMLAttributes;
10
+ export type DOMAttributes = HonoJSX.HTMLAttributes;
11
11
  export declare namespace JSX {
12
12
  type Element = HtmlEscapedString | Promise<HtmlEscapedString>;
13
13
  interface ElementChildrenAttribute {
@@ -24,3 +24,8 @@ export declare const createRoot: (element: HTMLElement | DocumentFragment, optio
24
24
  * @returns Root object has `render` and `unmount` methods
25
25
  */
26
26
  export declare const hydrateRoot: (element: HTMLElement | DocumentFragment, reactNode: Child, options?: RootOptions) => Root;
27
+ declare const _default: {
28
+ createRoot: (element: HTMLElement | DocumentFragment, options?: RootOptions) => Root;
29
+ hydrateRoot: (element: HTMLElement | DocumentFragment, reactNode: Child, options?: RootOptions) => Root;
30
+ };
31
+ export default _default;
@@ -14,7 +14,7 @@ import { createPortal, flushSync } from './render';
14
14
  export { render } from './render';
15
15
  declare const createElement: (tag: string | ((props: Props) => JSXNode), props: Props | null, ...children: Child[]) => JSXNode;
16
16
  declare const cloneElement: <T extends JSXNode | JSX.Element>(element: T, props: Props, ...children: Child[]) => T;
17
- export { reactAPICompatVersion as version, createElement as jsx, useState, useEffect, useRef, useCallback, use, startTransition, useTransition, useDeferredValue, startViewTransition, useViewTransition, useMemo, useLayoutEffect, useInsertionEffect, useReducer, useId, useDebugValue, createRef, forwardRef, useImperativeHandle, useSyncExternalStore, Suspense, ErrorBoundary, createContext, useContext, memo, isValidElement, createElement, cloneElement, Children, Fragment, DOMAttributes, flushSync, createPortal, };
17
+ export { reactAPICompatVersion as version, createElement as jsx, useState, useEffect, useRef, useCallback, use, startTransition, useTransition, useDeferredValue, startViewTransition, useViewTransition, useMemo, useLayoutEffect, useInsertionEffect, useReducer, useId, useDebugValue, createRef, forwardRef, useImperativeHandle, useSyncExternalStore, Suspense, ErrorBoundary, createContext, useContext, memo, isValidElement, createElement, cloneElement, Children, Fragment, Fragment as StrictMode, DOMAttributes, flushSync, createPortal, };
18
18
  declare const _default: {
19
19
  version: string;
20
20
  useState: {
@@ -23,7 +23,7 @@ declare const _default: {
23
23
  };
24
24
  useEffect: (effect: () => void | (() => void), deps?: readonly unknown[] | undefined) => void;
25
25
  useRef: <T_2>(initialValue: T_2 | null) => import("../hooks").RefObject<T_2>;
26
- useCallback: <T_3 extends (...args: unknown[]) => unknown>(callback: T_3, deps: readonly unknown[]) => T_3;
26
+ useCallback: <T_3 extends Function>(callback: T_3, deps: readonly unknown[]) => T_3;
27
27
  use: <T_4>(promise: Promise<T_4>) => T_4;
28
28
  startTransition: (callback: () => void) => void;
29
29
  useTransition: () => [boolean, (callback: () => void) => void];
@@ -64,6 +64,7 @@ declare const _default: {
64
64
  toArray: (children: Child) => Child[];
65
65
  };
66
66
  Fragment: (props: Record<string, unknown>) => JSXNode;
67
+ StrictMode: (props: Record<string, unknown>) => JSXNode;
67
68
  flushSync: (callback: () => void) => void;
68
69
  createPortal: (children: Child, container: HTMLElement, key?: string | undefined) => Child;
69
70
  };
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @module
3
+ * This module provides APIs for `hono/jsx/server`, which is compatible with `react-dom/server`.
4
+ */
5
+ import type { Child } from '../base';
6
+ import version from './';
7
+ export interface RenderToStringOptions {
8
+ identifierPrefix?: string;
9
+ }
10
+ /**
11
+ * Render JSX element to string.
12
+ * @param element JSX element to render.
13
+ * @param options Options for rendering.
14
+ * @returns Rendered string.
15
+ */
16
+ declare const renderToString: (element: Child, options?: RenderToStringOptions) => string;
17
+ export interface RenderToReadableStreamOptions {
18
+ identifierPrefix?: string;
19
+ namespaceURI?: string;
20
+ nonce?: string;
21
+ bootstrapScriptContent?: string;
22
+ bootstrapScripts?: string[];
23
+ bootstrapModules?: string[];
24
+ progressiveChunkSize?: number;
25
+ signal?: AbortSignal;
26
+ onError?: (error: unknown) => string | void;
27
+ }
28
+ /**
29
+ * Render JSX element to readable stream.
30
+ * @param element JSX element to render.
31
+ * @param options Options for rendering.
32
+ * @returns Rendered readable stream.
33
+ */
34
+ declare const renderToReadableStream: (element: Child, options?: RenderToReadableStreamOptions) => Promise<ReadableStream<Uint8Array>>;
35
+ export { renderToString, renderToReadableStream, version };
36
+ declare const _default: {
37
+ renderToString: (element: Child, options?: RenderToStringOptions) => string;
38
+ renderToReadableStream: (element: Child, options?: RenderToReadableStreamOptions) => Promise<ReadableStream<Uint8Array>>;
39
+ version: {
40
+ version: string;
41
+ useState: {
42
+ <T>(initialState: T | (() => T)): [T, (newState: T | ((currentState: T) => T)) => void];
43
+ <T_1 = undefined>(): [T_1 | undefined, (newState: T_1 | ((currentState: T_1 | undefined) => T_1 | undefined) | undefined) => void];
44
+ };
45
+ useEffect: (effect: () => void | (() => void), deps?: readonly unknown[] | undefined) => void;
46
+ useRef: <T_2>(initialValue: T_2 | null) => import("./").RefObject<T_2>;
47
+ useCallback: <T_3 extends Function>(callback: T_3, deps: readonly unknown[]) => T_3;
48
+ use: <T_4>(promise: Promise<T_4>) => T_4;
49
+ startTransition: (callback: () => void) => void;
50
+ useTransition: () => [boolean, (callback: () => void) => void];
51
+ useDeferredValue: <T_5>(value: T_5) => T_5;
52
+ startViewTransition: (callback: () => void) => void;
53
+ useViewTransition: () => [boolean, (callback: () => void) => void];
54
+ useMemo: <T_6>(factory: () => T_6, deps: readonly unknown[]) => T_6;
55
+ useLayoutEffect: (effect: () => void | (() => void), deps?: readonly unknown[] | undefined) => void;
56
+ useInsertionEffect: (effect: () => void | (() => void), deps?: readonly unknown[] | undefined) => void;
57
+ useReducer: <T_7, A>(reducer: (state: T_7, action: A) => T_7, initialArg: T_7, init?: ((initialState: T_7) => T_7) | undefined) => [T_7, (action: A) => void];
58
+ useId: () => string;
59
+ useDebugValue: (_value: unknown, _formatter?: ((value: unknown) => string) | undefined) => void;
60
+ createRef: <T_8>() => import("./").RefObject<T_8>;
61
+ forwardRef: <T_9, P = {}>(Component: (props: P, ref?: import("./").RefObject<T_9> | undefined) => import("../base").JSX.Element) => (props: P & {
62
+ ref?: import("./").RefObject<T_9> | undefined;
63
+ }) => import("../base").JSX.Element;
64
+ useImperativeHandle: <T_10>(ref: import("./").RefObject<T_10>, createHandle: () => T_10, deps: readonly unknown[]) => void;
65
+ useSyncExternalStore: <T_11>(subscribe: (callback: (value: T_11) => void) => () => void, getSnapshot: () => T_11, getServerSnapshot?: (() => T_11) | undefined) => T_11;
66
+ Suspense: import("./").FC<import("./").PropsWithChildren<{
67
+ fallback: any;
68
+ }>>;
69
+ ErrorBoundary: import("./").FC<import("./").PropsWithChildren<{
70
+ fallback?: Child;
71
+ fallbackRender?: import("../components").FallbackRender | undefined;
72
+ onError?: import("../components").ErrorHandler | undefined;
73
+ }>>;
74
+ createContext: <T_12>(defaultValue: T_12) => import("./").Context<T_12>;
75
+ useContext: <T_13>(context: import("./").Context<T_13>) => T_13;
76
+ memo: <T_14>(component: import("./").FC<T_14>, propsAreEqual?: (prevProps: Readonly<T_14>, nextProps: Readonly<T_14>) => boolean) => import("./").FC<T_14>;
77
+ isValidElement: (element: unknown) => element is import("./").JSXNode;
78
+ createElement: (tag: string | ((props: import("../base").Props) => import("./").JSXNode), props: import("../base").Props | null, ...children: Child[]) => import("./").JSXNode;
79
+ cloneElement: <T_15 extends import("./").JSXNode | import("../base").JSX.Element>(element: T_15, props: import("../base").Props, ...children: Child[]) => T_15;
80
+ Children: {
81
+ map: (children: Child[], fn: (child: Child, index: number) => Child) => Child[];
82
+ forEach: (children: Child[], fn: (child: Child, index: number) => void) => void;
83
+ count: (children: Child[]) => number;
84
+ only: (_children: Child[]) => Child;
85
+ toArray: (children: Child) => Child[];
86
+ };
87
+ Fragment: (props: Record<string, unknown>) => import("./").JSXNode;
88
+ StrictMode: (props: Record<string, unknown>) => import("./").JSXNode;
89
+ flushSync: (callback: () => void) => void;
90
+ createPortal: (children: Child, container: HTMLElement, key?: string | undefined) => Child;
91
+ };
92
+ };
93
+ export default _default;
@@ -26,7 +26,7 @@ export declare const useReducer: <T, A>(reducer: (state: T, action: A) => T, ini
26
26
  export declare const useEffect: (effect: () => void | (() => void), deps?: readonly unknown[]) => void;
27
27
  export declare const useLayoutEffect: (effect: () => void | (() => void), deps?: readonly unknown[]) => void;
28
28
  export declare const useInsertionEffect: (effect: () => void | (() => void), deps?: readonly unknown[]) => void;
29
- export declare const useCallback: <T extends (...args: unknown[]) => unknown>(callback: T, deps: readonly unknown[]) => T;
29
+ export declare const useCallback: <T extends Function>(callback: T, deps: readonly unknown[]) => T;
30
30
  export type RefObject<T> = {
31
31
  current: T | null;
32
32
  };
@@ -9,7 +9,7 @@ import { ErrorBoundary } from './components';
9
9
  import { createContext, useContext } from './context';
10
10
  import { createRef, forwardRef, startTransition, startViewTransition, use, useCallback, useDebugValue, useDeferredValue, useEffect, useId, useImperativeHandle, useInsertionEffect, useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore, useTransition, useViewTransition } from './hooks';
11
11
  import { Suspense } from './streaming';
12
- export { reactAPICompatVersion as version, jsx, memo, Fragment, isValidElement, jsx as createElement, cloneElement, ErrorBoundary, createContext, useContext, useState, useEffect, useRef, useCallback, useReducer, useId, useDebugValue, use, startTransition, useTransition, useDeferredValue, startViewTransition, useViewTransition, useMemo, useLayoutEffect, useInsertionEffect, createRef, forwardRef, useImperativeHandle, useSyncExternalStore, Suspense, Children, DOMAttributes, };
12
+ export { reactAPICompatVersion as version, jsx, memo, Fragment, Fragment as StrictMode, isValidElement, jsx as createElement, cloneElement, ErrorBoundary, createContext, useContext, useState, useEffect, useRef, useCallback, useReducer, useId, useDebugValue, use, startTransition, useTransition, useDeferredValue, startViewTransition, useViewTransition, useMemo, useLayoutEffect, useInsertionEffect, createRef, forwardRef, useImperativeHandle, useSyncExternalStore, Suspense, Children, DOMAttributes, };
13
13
  declare const _default: {
14
14
  version: string;
15
15
  memo: <T>(component: import("./base").FC<T>, propsAreEqual?: (prevProps: Readonly<T>, nextProps: Readonly<T>) => boolean) => import("./base").FC<T>;
@@ -17,6 +17,10 @@ declare const _default: {
17
17
  key?: string | undefined;
18
18
  children?: import("../utils/html").HtmlEscapedString | import("./base").Child;
19
19
  }) => import("../utils/html").HtmlEscapedString;
20
+ StrictMode: ({ children, }: {
21
+ key?: string | undefined;
22
+ children?: import("../utils/html").HtmlEscapedString | import("./base").Child;
23
+ }) => import("../utils/html").HtmlEscapedString;
20
24
  isValidElement: (element: unknown) => element is import("./base").JSXNode;
21
25
  createElement: (tag: string | Function, props: import("./base").Props | null, ...children: (string | number | import("../utils/html").HtmlEscapedString)[]) => import("./base").JSXNode;
22
26
  cloneElement: <T_1 extends import("./base").JSXNode | import("./base").JSX.Element>(element: T_1, props: Partial<import("./base").Props>, ...children: import("./base").Child[]) => T_1;
@@ -33,7 +37,7 @@ declare const _default: {
33
37
  };
34
38
  useEffect: (effect: () => void | (() => void), deps?: readonly unknown[] | undefined) => void;
35
39
  useRef: <T_6>(initialValue: T_6 | null) => import("./hooks").RefObject<T_6>;
36
- useCallback: <T_7 extends (...args: unknown[]) => unknown>(callback: T_7, deps: readonly unknown[]) => T_7;
40
+ useCallback: <T_7 extends Function>(callback: T_7, deps: readonly unknown[]) => T_7;
37
41
  useReducer: <T_8, A>(reducer: (state: T_8, action: A) => T_8, initialArg: T_8, init?: ((initialState: T_8) => T_8) | undefined) => [T_8, (action: A) => void];
38
42
  useId: () => string;
39
43
  useDebugValue: (_value: unknown, _formatter?: ((value: unknown) => string) | undefined) => void;
@@ -65,3 +69,4 @@ declare const _default: {
65
69
  };
66
70
  export default _default;
67
71
  export type * from './types';
72
+ export type { JSX } from './intrinsic-elements';
@@ -4,7 +4,7 @@
4
4
  * MIT License
5
5
  * Copyright (c) Meta Platforms, Inc. and affiliates.
6
6
  */
7
- export declare namespace Hono {
7
+ export declare namespace JSX {
8
8
  export type CrossOrigin = 'anonymous' | 'use-credentials' | '' | undefined;
9
9
  export type CSSProperties = {};
10
10
  type AnyAttributes = {
@@ -636,5 +636,5 @@ export declare namespace Hono {
636
636
  }
637
637
  export {};
638
638
  }
639
- export interface IntrinsicElements extends Hono.IntrinsicElements {
639
+ export interface IntrinsicElements extends JSX.IntrinsicElements {
640
640
  }
@@ -17,4 +17,4 @@ export declare const Suspense: FC<PropsWithChildren<{
17
17
  * `renderToReadableStream()` is an experimental feature.
18
18
  * The API might be changed.
19
19
  */
20
- export declare const renderToReadableStream: (str: HtmlEscapedString | Promise<HtmlEscapedString>, onError?: (e: unknown) => void) => ReadableStream<Uint8Array>;
20
+ export declare const renderToReadableStream: (str: HtmlEscapedString | Promise<HtmlEscapedString>, onError?: (e: unknown) => string | void) => ReadableStream<Uint8Array>;
@@ -2,14 +2,14 @@
2
2
  * All types exported from "hono/jsx" are in this file.
3
3
  */
4
4
  import type { Child, JSXNode } from './base';
5
- import type { Hono } from './intrinsic-elements';
5
+ import type { JSX } from './intrinsic-elements';
6
6
  export type { Child, JSXNode, FC } from './base';
7
7
  export type { RefObject } from './hooks';
8
8
  export type { Context } from './context';
9
9
  export type PropsWithChildren<P = unknown> = P & {
10
10
  children?: Child | undefined;
11
11
  };
12
- export type CSSProperties = Hono.CSSProperties;
12
+ export type CSSProperties = JSX.CSSProperties;
13
13
  /**
14
14
  * React types
15
15
  */
@@ -1,8 +1,2 @@
1
- /**
2
- * Normalizes intrinsic element properties by converting JSX element properties
3
- * to their corresponding HTML attributes.
4
- *
5
- * @param props - JSX element properties.
6
- */
7
- export declare const normalizeIntrinsicElementProps: (props: Record<string, unknown>) => void;
1
+ export declare const normalizeIntrinsicElementKey: (key: string) => string;
8
2
  export declare const styleObjectForEach: (style: Record<string, string | number>, fn: (key: string, value: string | null) => void) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "4.4.4",
3
+ "version": "4.5.0-rc.1",
4
4
  "description": "Ultrafast web framework for the Edges",
5
5
  "main": "dist/cjs/index.js",
6
6
  "type": "module",
@@ -178,6 +178,11 @@
178
178
  "import": "./dist/jsx/dom/css.js",
179
179
  "require": "./dist/cjs/jsx/dom/css.js"
180
180
  },
181
+ "./jsx/dom/server": {
182
+ "types": "./dist/types/jsx/dom/server.d.ts",
183
+ "import": "./dist/jsx/dom/server.js",
184
+ "require": "./dist/cjs/jsx/dom/server.js"
185
+ },
181
186
  "./jwt": {
182
187
  "types": "./dist/types/middleware/jwt/index.d.ts",
183
188
  "import": "./dist/middleware/jwt/index.js",
@@ -434,6 +439,9 @@
434
439
  "jsx/dom/css": [
435
440
  "./dist/types/jsx/dom/css.d.ts"
436
441
  ],
442
+ "jsx/dom/server": [
443
+ "./dist/types/jsx/dom/server.d.ts"
444
+ ],
437
445
  "jwt": [
438
446
  "./dist/types/middleware/jwt"
439
447
  ],