hono 4.12.15 → 4.12.17

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.
@@ -69,6 +69,8 @@ const defaultExtensionMap = {
69
69
  "text/html": "html",
70
70
  "text/xml": "xml",
71
71
  "application/xml": "xml",
72
+ "application/atom+xml": "xml",
73
+ "application/rss+xml": "xml",
72
74
  "application/yaml": "yaml"
73
75
  };
74
76
  const determineExtension = (mimeType, userExtensionMap) => {
@@ -127,6 +127,9 @@ class JSXNode {
127
127
  isEscaped = true;
128
128
  localContexts;
129
129
  constructor(tag, props, children) {
130
+ if (typeof tag !== "function" && !(0, import_utils.isValidTagName)(tag)) {
131
+ throw new Error(`Invalid JSX tag name: ${tag}`);
132
+ }
130
133
  this.tag = tag;
131
134
  this.props = props;
132
135
  this.children = children;
@@ -158,7 +161,7 @@ class JSXNode {
158
161
  const props = this.props;
159
162
  let { children } = this;
160
163
  buffer[0] += `<${tag}`;
161
- const normalizeKey = nameSpaceContext && (0, import_context.useContext)(nameSpaceContext) === "svg" ? (key) => toSVGAttributeName((0, import_utils.normalizeIntrinsicElementKey)(key)) : (key) => (0, import_utils.normalizeIntrinsicElementKey)(key);
164
+ const normalizeKey = tag === "svg" || nameSpaceContext && (0, import_context.useContext)(nameSpaceContext) === "svg" ? (key) => toSVGAttributeName((0, import_utils.normalizeIntrinsicElementKey)(key)) : (key) => (0, import_utils.normalizeIntrinsicElementKey)(key);
162
165
  for (let [key, v] of Object.entries(props)) {
163
166
  key = normalizeKey(key);
164
167
  if (!(0, import_utils.isValidAttributeName)(key)) {
@@ -18,6 +18,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
18
18
  var utils_exports = {};
19
19
  __export(utils_exports, {
20
20
  isValidAttributeName: () => isValidAttributeName,
21
+ isValidTagName: () => isValidTagName,
21
22
  normalizeIntrinsicElementKey: () => normalizeIntrinsicElementKey,
22
23
  styleObjectForEach: () => styleObjectForEach
23
24
  });
@@ -34,7 +35,37 @@ const normalizeElementKeyMap = /* @__PURE__ */ new Map([
34
35
  ]);
35
36
  const normalizeIntrinsicElementKey = (key) => normalizeElementKeyMap.get(key) || key;
36
37
  const invalidAttributeNameCharRe = /[\s"'<>/=`\\\x00-\x1f\x7f-\x9f]/;
38
+ const validAttributeNameCache = /* @__PURE__ */ new Set();
39
+ const validAttributeNameCacheMax = 1024;
40
+ const invalidTagNameCharRe = /^[!?]|[\s"'<>/=`\\\x00-\x1f\x7f-\x9f]/;
41
+ const validTagNameCache = /* @__PURE__ */ new Set();
42
+ const validTagNameCacheMax = 256;
43
+ const cacheValidName = (cache, max, name) => {
44
+ if (cache.size >= max) {
45
+ cache.clear();
46
+ }
47
+ cache.add(name);
48
+ };
49
+ const isValidTagName = (name) => {
50
+ if (validTagNameCache.has(name)) {
51
+ return true;
52
+ }
53
+ if (typeof name !== "string") {
54
+ return false;
55
+ }
56
+ if (name.length === 0) {
57
+ return true;
58
+ }
59
+ if (invalidTagNameCharRe.test(name)) {
60
+ return false;
61
+ }
62
+ cacheValidName(validTagNameCache, validTagNameCacheMax, name);
63
+ return true;
64
+ };
37
65
  const isValidAttributeName = (name) => {
66
+ if (validAttributeNameCache.has(name)) {
67
+ return true;
68
+ }
38
69
  const len = name.length;
39
70
  if (len === 0) {
40
71
  return false;
@@ -48,9 +79,15 @@ const isValidAttributeName = (name) => {
48
79
  c === 95 || // _
49
80
  c === 46 || // .
50
81
  c === 58)) {
51
- return !invalidAttributeNameCharRe.test(name);
82
+ if (!invalidAttributeNameCharRe.test(name)) {
83
+ cacheValidName(validAttributeNameCache, validAttributeNameCacheMax, name);
84
+ return true;
85
+ } else {
86
+ return false;
87
+ }
52
88
  }
53
89
  }
90
+ cacheValidName(validAttributeNameCache, validAttributeNameCacheMax, name);
54
91
  return true;
55
92
  };
56
93
  const styleObjectForEach = (style, fn) => {
@@ -67,6 +104,7 @@ const styleObjectForEach = (style, fn) => {
67
104
  // Annotate the CommonJS export names for ESM import in node:
68
105
  0 && (module.exports = {
69
106
  isValidAttributeName,
107
+ isValidTagName,
70
108
  normalizeIntrinsicElementKey,
71
109
  styleObjectForEach
72
110
  });
@@ -22,12 +22,6 @@ __export(body_limit_exports, {
22
22
  module.exports = __toCommonJS(body_limit_exports);
23
23
  var import_http_exception = require("../../http-exception");
24
24
  const ERROR_MESSAGE = "Payload Too Large";
25
- class BodyLimitError extends Error {
26
- constructor(message) {
27
- super(message);
28
- this.name = "BodyLimitError";
29
- }
30
- }
31
25
  const bodyLimit = (options) => {
32
26
  const onError = options.onError || (() => {
33
27
  const res = new Response(ERROR_MESSAGE, {
@@ -42,40 +36,37 @@ const bodyLimit = (options) => {
42
36
  }
43
37
  const hasTransferEncoding = c.req.raw.headers.has("transfer-encoding");
44
38
  const hasContentLength = c.req.raw.headers.has("content-length");
45
- if (hasTransferEncoding && hasContentLength) {
46
- }
47
39
  if (hasContentLength && !hasTransferEncoding) {
48
40
  const contentLength = parseInt(c.req.raw.headers.get("content-length") || "0", 10);
49
41
  return contentLength > maxSize ? onError(c) : next();
50
42
  }
51
43
  let size = 0;
44
+ const chunks = [];
52
45
  const rawReader = c.req.raw.body.getReader();
53
- const reader = new ReadableStream({
54
- async start(controller) {
55
- try {
56
- for (; ; ) {
57
- const { done, value } = await rawReader.read();
58
- if (done) {
59
- break;
60
- }
61
- size += value.length;
62
- if (size > maxSize) {
63
- controller.error(new BodyLimitError(ERROR_MESSAGE));
64
- break;
65
- }
66
- controller.enqueue(value);
46
+ for (; ; ) {
47
+ const { done, value } = await rawReader.read();
48
+ if (done) {
49
+ break;
50
+ }
51
+ size += value.length;
52
+ if (size > maxSize) {
53
+ return onError(c);
54
+ }
55
+ chunks.push(value);
56
+ }
57
+ const requestInit = {
58
+ body: new ReadableStream({
59
+ start(controller) {
60
+ for (const chunk of chunks) {
61
+ controller.enqueue(chunk);
67
62
  }
68
- } finally {
69
63
  controller.close();
70
64
  }
71
- }
72
- });
73
- const requestInit = { body: reader, duplex: "half" };
65
+ }),
66
+ duplex: "half"
67
+ };
74
68
  c.req.raw = new Request(c.req.raw, requestInit);
75
- await next();
76
- if (c.error instanceof BodyLimitError) {
77
- c.res = await onError(c);
78
- }
69
+ return next();
79
70
  };
80
71
  };
81
72
  // Annotate the CommonJS export names for ESM import in node:
@@ -21,14 +21,11 @@ __export(cors_exports, {
21
21
  });
22
22
  module.exports = __toCommonJS(cors_exports);
23
23
  const cors = (options) => {
24
- const defaults = {
24
+ const opts = {
25
25
  origin: "*",
26
26
  allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"],
27
27
  allowHeaders: [],
28
- exposeHeaders: []
29
- };
30
- const opts = {
31
- ...defaults,
28
+ exposeHeaders: [],
32
29
  ...options
33
30
  };
34
31
  const findAllowOrigin = ((optsOrigin) => {
@@ -49,7 +49,7 @@ const methodOverride = (options) => async function methodOverride2(c, next) {
49
49
  return app.fetch(request, c.env, getExecutionCtx(c));
50
50
  }
51
51
  }
52
- if (contentType === "application/x-www-form-urlencoded") {
52
+ if (contentType?.startsWith("application/x-www-form-urlencoded")) {
53
53
  const params = await (0, import_body.parseBody)(clonedRequest);
54
54
  const method = params[methodFormName];
55
55
  if (method) {
@@ -47,6 +47,8 @@ var defaultExtensionMap = {
47
47
  "text/html": "html",
48
48
  "text/xml": "xml",
49
49
  "application/xml": "xml",
50
+ "application/atom+xml": "xml",
51
+ "application/rss+xml": "xml",
50
52
  "application/yaml": "yaml"
51
53
  };
52
54
  var determineExtension = (mimeType, userExtensionMap) => {
package/dist/jsx/base.js CHANGED
@@ -5,7 +5,12 @@ 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";
8
- import { isValidAttributeName, normalizeIntrinsicElementKey, styleObjectForEach } from "./utils.js";
8
+ import {
9
+ isValidAttributeName,
10
+ isValidTagName,
11
+ normalizeIntrinsicElementKey,
12
+ styleObjectForEach
13
+ } from "./utils.js";
9
14
  var nameSpaceContext = void 0;
10
15
  var getNameSpaceContext = () => nameSpaceContext;
11
16
  var toSVGAttributeName = (key) => /[A-Z]/.test(key) && // Presentation attributes are findable in style object. "clip-path", "font-size", "stroke-width", etc.
@@ -85,6 +90,9 @@ var JSXNode = class {
85
90
  isEscaped = true;
86
91
  localContexts;
87
92
  constructor(tag, props, children) {
93
+ if (typeof tag !== "function" && !isValidTagName(tag)) {
94
+ throw new Error(`Invalid JSX tag name: ${tag}`);
95
+ }
88
96
  this.tag = tag;
89
97
  this.props = props;
90
98
  this.children = children;
@@ -116,7 +124,7 @@ var JSXNode = class {
116
124
  const props = this.props;
117
125
  let { children } = this;
118
126
  buffer[0] += `<${tag}`;
119
- const normalizeKey = nameSpaceContext && useContext(nameSpaceContext) === "svg" ? (key) => toSVGAttributeName(normalizeIntrinsicElementKey(key)) : (key) => normalizeIntrinsicElementKey(key);
127
+ const normalizeKey = tag === "svg" || nameSpaceContext && useContext(nameSpaceContext) === "svg" ? (key) => toSVGAttributeName(normalizeIntrinsicElementKey(key)) : (key) => normalizeIntrinsicElementKey(key);
120
128
  for (let [key, v] of Object.entries(props)) {
121
129
  key = normalizeKey(key);
122
130
  if (!isValidAttributeName(key)) {
package/dist/jsx/utils.js CHANGED
@@ -11,7 +11,37 @@ var normalizeElementKeyMap = /* @__PURE__ */ new Map([
11
11
  ]);
12
12
  var normalizeIntrinsicElementKey = (key) => normalizeElementKeyMap.get(key) || key;
13
13
  var invalidAttributeNameCharRe = /[\s"'<>/=`\\\x00-\x1f\x7f-\x9f]/;
14
+ var validAttributeNameCache = /* @__PURE__ */ new Set();
15
+ var validAttributeNameCacheMax = 1024;
16
+ var invalidTagNameCharRe = /^[!?]|[\s"'<>/=`\\\x00-\x1f\x7f-\x9f]/;
17
+ var validTagNameCache = /* @__PURE__ */ new Set();
18
+ var validTagNameCacheMax = 256;
19
+ var cacheValidName = (cache, max, name) => {
20
+ if (cache.size >= max) {
21
+ cache.clear();
22
+ }
23
+ cache.add(name);
24
+ };
25
+ var isValidTagName = (name) => {
26
+ if (validTagNameCache.has(name)) {
27
+ return true;
28
+ }
29
+ if (typeof name !== "string") {
30
+ return false;
31
+ }
32
+ if (name.length === 0) {
33
+ return true;
34
+ }
35
+ if (invalidTagNameCharRe.test(name)) {
36
+ return false;
37
+ }
38
+ cacheValidName(validTagNameCache, validTagNameCacheMax, name);
39
+ return true;
40
+ };
14
41
  var isValidAttributeName = (name) => {
42
+ if (validAttributeNameCache.has(name)) {
43
+ return true;
44
+ }
15
45
  const len = name.length;
16
46
  if (len === 0) {
17
47
  return false;
@@ -25,9 +55,15 @@ var isValidAttributeName = (name) => {
25
55
  c === 95 || // _
26
56
  c === 46 || // .
27
57
  c === 58)) {
28
- return !invalidAttributeNameCharRe.test(name);
58
+ if (!invalidAttributeNameCharRe.test(name)) {
59
+ cacheValidName(validAttributeNameCache, validAttributeNameCacheMax, name);
60
+ return true;
61
+ } else {
62
+ return false;
63
+ }
29
64
  }
30
65
  }
66
+ cacheValidName(validAttributeNameCache, validAttributeNameCacheMax, name);
31
67
  return true;
32
68
  };
33
69
  var styleObjectForEach = (style, fn) => {
@@ -43,6 +79,7 @@ var styleObjectForEach = (style, fn) => {
43
79
  };
44
80
  export {
45
81
  isValidAttributeName,
82
+ isValidTagName,
46
83
  normalizeIntrinsicElementKey,
47
84
  styleObjectForEach
48
85
  };
@@ -1,12 +1,6 @@
1
1
  // src/middleware/body-limit/index.ts
2
2
  import { HTTPException } from "../../http-exception.js";
3
3
  var ERROR_MESSAGE = "Payload Too Large";
4
- var BodyLimitError = class extends Error {
5
- constructor(message) {
6
- super(message);
7
- this.name = "BodyLimitError";
8
- }
9
- };
10
4
  var bodyLimit = (options) => {
11
5
  const onError = options.onError || (() => {
12
6
  const res = new Response(ERROR_MESSAGE, {
@@ -21,40 +15,37 @@ var bodyLimit = (options) => {
21
15
  }
22
16
  const hasTransferEncoding = c.req.raw.headers.has("transfer-encoding");
23
17
  const hasContentLength = c.req.raw.headers.has("content-length");
24
- if (hasTransferEncoding && hasContentLength) {
25
- }
26
18
  if (hasContentLength && !hasTransferEncoding) {
27
19
  const contentLength = parseInt(c.req.raw.headers.get("content-length") || "0", 10);
28
20
  return contentLength > maxSize ? onError(c) : next();
29
21
  }
30
22
  let size = 0;
23
+ const chunks = [];
31
24
  const rawReader = c.req.raw.body.getReader();
32
- const reader = new ReadableStream({
33
- async start(controller) {
34
- try {
35
- for (; ; ) {
36
- const { done, value } = await rawReader.read();
37
- if (done) {
38
- break;
39
- }
40
- size += value.length;
41
- if (size > maxSize) {
42
- controller.error(new BodyLimitError(ERROR_MESSAGE));
43
- break;
44
- }
45
- controller.enqueue(value);
25
+ for (; ; ) {
26
+ const { done, value } = await rawReader.read();
27
+ if (done) {
28
+ break;
29
+ }
30
+ size += value.length;
31
+ if (size > maxSize) {
32
+ return onError(c);
33
+ }
34
+ chunks.push(value);
35
+ }
36
+ const requestInit = {
37
+ body: new ReadableStream({
38
+ start(controller) {
39
+ for (const chunk of chunks) {
40
+ controller.enqueue(chunk);
46
41
  }
47
- } finally {
48
42
  controller.close();
49
43
  }
50
- }
51
- });
52
- const requestInit = { body: reader, duplex: "half" };
44
+ }),
45
+ duplex: "half"
46
+ };
53
47
  c.req.raw = new Request(c.req.raw, requestInit);
54
- await next();
55
- if (c.error instanceof BodyLimitError) {
56
- c.res = await onError(c);
57
- }
48
+ return next();
58
49
  };
59
50
  };
60
51
  export {
@@ -1,13 +1,10 @@
1
1
  // src/middleware/cors/index.ts
2
2
  var cors = (options) => {
3
- const defaults = {
3
+ const opts = {
4
4
  origin: "*",
5
5
  allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"],
6
6
  allowHeaders: [],
7
- exposeHeaders: []
8
- };
9
- const opts = {
10
- ...defaults,
7
+ exposeHeaders: [],
11
8
  ...options
12
9
  };
13
10
  const findAllowOrigin = ((optsOrigin) => {
@@ -28,7 +28,7 @@ var methodOverride = (options) => async function methodOverride2(c, next) {
28
28
  return app.fetch(request, c.env, getExecutionCtx(c));
29
29
  }
30
30
  }
31
- if (contentType === "application/x-www-form-urlencoded") {
31
+ if (contentType?.startsWith("application/x-www-form-urlencoded")) {
32
32
  const params = await parseBody(clonedRequest);
33
33
  const method = params[methodFormName];
34
34
  if (method) {