hono 4.1.0 → 4.1.2

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.
@@ -43,19 +43,33 @@ var createRequest = (event) => {
43
43
  v.forEach((header) => headers.set(k, header.value));
44
44
  });
45
45
  const requestBody = event.Records[0].cf.request.body;
46
- const body = requestBody?.encoding === "base64" && requestBody?.data ? Buffer.from(requestBody.data, "base64") : requestBody?.data;
46
+ const method = event.Records[0].cf.request.method;
47
+ const body = createBody(method, requestBody);
47
48
  return new Request(url, {
48
49
  headers,
49
- method: event.Records[0].cf.request.method,
50
+ method,
50
51
  body
51
52
  });
52
53
  };
54
+ var createBody = (method, requestBody) => {
55
+ if (!requestBody || !requestBody.data) {
56
+ return void 0;
57
+ }
58
+ if (method === "GET" || method === "HEAD") {
59
+ return void 0;
60
+ }
61
+ if (requestBody.encoding === "base64") {
62
+ return Buffer.from(requestBody.data, "base64");
63
+ }
64
+ return requestBody.data;
65
+ };
53
66
  var isContentTypeBinary = (contentType) => {
54
67
  return !/^(text\/(plain|html|css|javascript|csv).*|application\/(.*json|.*xml).*|image\/svg\+xml.*)$/.test(
55
68
  contentType
56
69
  );
57
70
  };
58
71
  export {
72
+ createBody,
59
73
  handle,
60
74
  isContentTypeBinary
61
75
  };
@@ -24,6 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
25
25
  var handler_exports = {};
26
26
  __export(handler_exports, {
27
+ createBody: () => createBody,
27
28
  handle: () => handle,
28
29
  isContentTypeBinary: () => isContentTypeBinary
29
30
  });
@@ -72,13 +73,26 @@ const createRequest = (event) => {
72
73
  v.forEach((header) => headers.set(k, header.value));
73
74
  });
74
75
  const requestBody = event.Records[0].cf.request.body;
75
- const body = requestBody?.encoding === "base64" && requestBody?.data ? Buffer.from(requestBody.data, "base64") : requestBody?.data;
76
+ const method = event.Records[0].cf.request.method;
77
+ const body = createBody(method, requestBody);
76
78
  return new Request(url, {
77
79
  headers,
78
- method: event.Records[0].cf.request.method,
80
+ method,
79
81
  body
80
82
  });
81
83
  };
84
+ const createBody = (method, requestBody) => {
85
+ if (!requestBody || !requestBody.data) {
86
+ return void 0;
87
+ }
88
+ if (method === "GET" || method === "HEAD") {
89
+ return void 0;
90
+ }
91
+ if (requestBody.encoding === "base64") {
92
+ return Buffer.from(requestBody.data, "base64");
93
+ }
94
+ return requestBody.data;
95
+ };
82
96
  const isContentTypeBinary = (contentType) => {
83
97
  return !/^(text\/(plain|html|css|javascript|csv).*|application\/(.*json|.*xml).*|image\/svg\+xml.*)$/.test(
84
98
  contentType
@@ -86,6 +100,7 @@ const isContentTypeBinary = (contentType) => {
86
100
  };
87
101
  // Annotate the CommonJS export names for ESM import in node:
88
102
  0 && (module.exports = {
103
+ createBody,
89
104
  handle,
90
105
  isContentTypeBinary
91
106
  });
@@ -38,7 +38,7 @@ const replaceUrlParam = (urlString, params) => {
38
38
  return urlString;
39
39
  };
40
40
  const removeIndexString = (urlSting) => {
41
- return urlSting.replace(/\/index$/, "/");
41
+ return urlSting.replace(/\/index$/, "");
42
42
  };
43
43
  function isObject(item) {
44
44
  return typeof item === "object" && item !== null && !Array.isArray(item);
@@ -152,7 +152,13 @@ class Context {
152
152
  });
153
153
  }
154
154
  if (arg && typeof arg !== "number") {
155
- const headers2 = setHeaders(new Headers(arg.headers), this.#preparedHeaders);
155
+ const header = new Headers(arg.headers);
156
+ if (this.#headers) {
157
+ this.#headers.forEach((v, k) => {
158
+ header.set(k, v);
159
+ });
160
+ }
161
+ const headers2 = setHeaders(header, this.#preparedHeaders);
156
162
  return new Response(data, {
157
163
  headers: headers2,
158
164
  status: arg.status ?? this.#status
@@ -40,29 +40,29 @@ class SSEStreamingApi extends import_stream.StreamingApi {
40
40
  await this.write(sseData);
41
41
  }
42
42
  }
43
- const setSSEHeaders = (context) => {
44
- context.header("Transfer-Encoding", "chunked");
45
- context.header("Content-Type", "text/event-stream");
46
- context.header("Cache-Control", "no-cache");
47
- context.header("Connection", "keep-alive");
43
+ const run = async (stream, cb, onError) => {
44
+ try {
45
+ await cb(stream);
46
+ } catch (e) {
47
+ if (e instanceof Error && onError) {
48
+ await onError(e, stream);
49
+ await stream.writeSSE({
50
+ event: "error",
51
+ data: e.message
52
+ });
53
+ } else {
54
+ console.error(e);
55
+ }
56
+ }
48
57
  };
49
58
  const streamSSE = (c, cb, onError) => {
50
59
  const { readable, writable } = new TransformStream();
51
60
  const stream = new SSEStreamingApi(writable, readable);
52
- (async () => {
53
- try {
54
- await cb(stream);
55
- } catch (e) {
56
- if (e instanceof Error && onError) {
57
- await onError(e, stream);
58
- } else {
59
- console.error(e);
60
- }
61
- } finally {
62
- stream.close();
63
- }
64
- })();
65
- setSSEHeaders(c);
61
+ c.header("Transfer-Encoding", "chunked");
62
+ c.header("Content-Type", "text/event-stream");
63
+ c.header("Cache-Control", "no-cache");
64
+ c.header("Connection", "keep-alive");
65
+ run(stream, cb, onError);
66
66
  return c.newResponse(stream.responseReadable);
67
67
  };
68
68
  // Annotate the CommonJS export names for ESM import in node:
@@ -42,12 +42,15 @@ const createRenderer = (c, Layout, component, options) => (children, props) => {
42
42
  currentLayout
43
43
  )}`;
44
44
  if (options?.stream) {
45
- return c.body((0, import_streaming.renderToReadableStream)(body), {
46
- headers: options.stream === true ? {
47
- "Transfer-Encoding": "chunked",
48
- "Content-Type": "text/html; charset=UTF-8"
49
- } : options.stream
50
- });
45
+ if (options.stream === true) {
46
+ c.header("Transfer-Encoding", "chunked");
47
+ c.header("Content-Type", "text/html; charset=UTF-8");
48
+ } else {
49
+ for (const [key, value] of Object.entries(options.stream)) {
50
+ c.header(key, value);
51
+ }
52
+ }
53
+ return c.body((0, import_streaming.renderToReadableStream)(body));
51
54
  } else {
52
55
  return c.html(body);
53
56
  }
@@ -23,7 +23,7 @@ __export(router_exports, {
23
23
  module.exports = __toCommonJS(router_exports);
24
24
  var import_router = require("../../router");
25
25
  var import_url = require("../../utils/url");
26
- const emptyParams = {};
26
+ const emptyParams = /* @__PURE__ */ Object.create(null);
27
27
  const splitPathRe = /\/(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/[^\/\?]+|(\?)/g;
28
28
  const splitByStarRe = /\*/;
29
29
  class LinearRouter {
@@ -78,7 +78,7 @@ class LinearRouter {
78
78
  }
79
79
  handlers.push([handler, emptyParams]);
80
80
  } else if (hasLabel && !hasStar) {
81
- const params = {};
81
+ const params = /* @__PURE__ */ Object.create(null);
82
82
  const parts = routePath.match(splitPathRe);
83
83
  const lastIndex = parts.length - 1;
84
84
  for (let j = 0, pos = 0, len2 = parts.length; j < len2; j++) {
@@ -30,19 +30,16 @@ class PatternRouter {
30
30
  if (endsWithWildcard) {
31
31
  path = path.slice(0, -2);
32
32
  }
33
- const parts = path.match(/\/?(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/?[^\/\?]+|(\?)/g) || [];
34
- if (parts[parts.length - 1] === "?") {
35
- this.add(method, parts.slice(0, parts.length - 2).join(""), handler);
36
- parts.pop();
33
+ if (path.at(-1) === "?") {
34
+ path = path.slice(0, -1);
35
+ this.add(method, path.replace(/\/[^/]+$/, ""), handler);
37
36
  }
38
- for (let i = 0, len = parts.length; i < len; i++) {
39
- const match = parts[i].match(/^\/:([^{]+)(?:{(.*)})?/);
40
- if (match) {
41
- parts[i] = `/(?<${match[1]}>${match[2] || "[^/]+"})`;
42
- } else if (parts[i] === "/*") {
43
- parts[i] = "/[^/]+";
37
+ const parts = (path.match(/\/?(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/?[^\/\?]+/g) || []).map(
38
+ (part) => {
39
+ const match = part.match(/^\/:([^{]+)(?:{(.*)})?/);
40
+ return match ? `/(?<${match[1]}>${match[2] || "[^/]+"})` : part === "/*" ? "/[^/]+" : part.replace(/[.\\+*[^\]$()]/g, "\\$&");
44
41
  }
45
- }
42
+ );
46
43
  let re;
47
44
  try {
48
45
  re = new RegExp(`^${parts.join("")}${endsWithWildcard ? "" : "/?$"}`);
@@ -57,7 +54,7 @@ class PatternRouter {
57
54
  if (routeMethod === import_router.METHOD_NAME_ALL || routeMethod === method) {
58
55
  const match = pattern.exec(path);
59
56
  if (match) {
60
- handlers.push([handler, match.groups || {}]);
57
+ handlers.push([handler, match.groups || /* @__PURE__ */ Object.create(null)]);
61
58
  }
62
59
  }
63
60
  }
@@ -26,6 +26,7 @@ const LABEL_REG_EXP_STR = "[^/]+";
26
26
  const ONLY_WILDCARD_REG_EXP_STR = ".*";
27
27
  const TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
28
28
  const PATH_ERROR = Symbol();
29
+ const regExpMetaChars = new Set(".\\+*[^]$()");
29
30
  function compareKey(a, b) {
30
31
  if (a.length === 1) {
31
32
  return b.length === 1 ? a < b ? -1 : 1 : -1;
@@ -48,7 +49,7 @@ function compareKey(a, b) {
48
49
  class Node {
49
50
  index;
50
51
  varIndex;
51
- children = {};
52
+ children = /* @__PURE__ */ Object.create(null);
52
53
  insert(tokens, index, paramMap, context, pathErrorCheckOnly) {
53
54
  if (tokens.length === 0) {
54
55
  if (this.index !== void 0) {
@@ -110,7 +111,7 @@ class Node {
110
111
  const childKeys = Object.keys(this.children).sort(compareKey);
111
112
  const strList = childKeys.map((k) => {
112
113
  const c = this.children[k];
113
- return (typeof c.varIndex === "number" ? `(${k})@${c.varIndex}` : k) + c.buildRegExpStr();
114
+ return (typeof c.varIndex === "number" ? `(${k})@${c.varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c.buildRegExpStr();
114
115
  });
115
116
  if (typeof this.index === "number") {
116
117
  strList.unshift(`#${this.index}`);
@@ -26,15 +26,15 @@ var import_url = require("../../utils/url");
26
26
  var import_node = require("./node");
27
27
  var import_trie = require("./trie");
28
28
  const emptyParam = [];
29
- const nullMatcher = [/^$/, [], {}];
30
- let wildcardRegExpCache = {};
29
+ const nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
30
+ let wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
31
31
  function buildWildcardRegExp(path) {
32
32
  return wildcardRegExpCache[path] ??= new RegExp(
33
33
  path === "*" ? "" : `^${path.replace(/\/\*/, "(?:|/.*)")}$`
34
34
  );
35
35
  }
36
36
  function clearWildcardRegExpCache() {
37
- wildcardRegExpCache = {};
37
+ wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
38
38
  }
39
39
  function buildMatcherFromPreprocessedRoutes(routes) {
40
40
  const trie = new import_trie.Trie();
@@ -47,11 +47,11 @@ function buildMatcherFromPreprocessedRoutes(routes) {
47
47
  ).sort(
48
48
  ([isStaticA, pathA], [isStaticB, pathB]) => isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length
49
49
  );
50
- const staticMap = {};
50
+ const staticMap = /* @__PURE__ */ Object.create(null);
51
51
  for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
52
52
  const [pathErrorCheckOnly, path, handlers] = routesWithStaticPathFlag[i];
53
53
  if (pathErrorCheckOnly) {
54
- staticMap[path] = [handlers.map(([h]) => [h, {}]), emptyParam];
54
+ staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
55
55
  } else {
56
56
  j++;
57
57
  }
@@ -65,7 +65,7 @@ function buildMatcherFromPreprocessedRoutes(routes) {
65
65
  continue;
66
66
  }
67
67
  handlerData[j] = handlers.map(([h, paramCount]) => {
68
- const paramIndexMap = {};
68
+ const paramIndexMap = /* @__PURE__ */ Object.create(null);
69
69
  paramCount -= 1;
70
70
  for (; paramCount >= 0; paramCount--) {
71
71
  const [key, value] = paramAssoc[paramCount];
@@ -109,8 +109,8 @@ class RegExpRouter {
109
109
  middleware;
110
110
  routes;
111
111
  constructor() {
112
- this.middleware = { [import_router.METHOD_NAME_ALL]: {} };
113
- this.routes = { [import_router.METHOD_NAME_ALL]: {} };
112
+ this.middleware = { [import_router.METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
113
+ this.routes = { [import_router.METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
114
114
  }
115
115
  add(method, path, handler) {
116
116
  const { middleware, routes } = this;
@@ -120,7 +120,7 @@ class RegExpRouter {
120
120
  if (!middleware[method]) {
121
121
  ;
122
122
  [middleware, routes].forEach((handlerMap) => {
123
- handlerMap[method] = {};
123
+ handlerMap[method] = /* @__PURE__ */ Object.create(null);
124
124
  Object.keys(handlerMap[import_router.METHOD_NAME_ALL]).forEach((p) => {
125
125
  handlerMap[method][p] = [...handlerMap[import_router.METHOD_NAME_ALL][p]];
126
126
  });
@@ -187,7 +187,7 @@ class RegExpRouter {
187
187
  return this.match(method, path);
188
188
  }
189
189
  buildAllMatchers() {
190
- const matchers = {};
190
+ const matchers = /* @__PURE__ */ Object.create(null);
191
191
  [...Object.keys(this.routes), ...Object.keys(this.middleware)].forEach((method) => {
192
192
  matchers[method] ||= this.buildMatcher(method);
193
193
  });
@@ -29,13 +29,13 @@ class Node {
29
29
  patterns;
30
30
  order = 0;
31
31
  name;
32
- params = {};
32
+ params = /* @__PURE__ */ Object.create(null);
33
33
  constructor(method, handler, children) {
34
- this.children = children || {};
34
+ this.children = children || /* @__PURE__ */ Object.create(null);
35
35
  this.methods = [];
36
36
  this.name = "";
37
37
  if (method && handler) {
38
- const m = {};
38
+ const m = /* @__PURE__ */ Object.create(null);
39
39
  m[method] = { handler, possibleKeys: [], score: 0, name: this.name };
40
40
  this.methods = [m];
41
41
  }
@@ -72,7 +72,7 @@ class Node {
72
72
  if (!curNode.methods.length) {
73
73
  curNode.methods = [];
74
74
  }
75
- const m = {};
75
+ const m = /* @__PURE__ */ Object.create(null);
76
76
  const handlerSet = {
77
77
  handler,
78
78
  possibleKeys: possibleKeys.filter((v, i, a) => a.indexOf(v) === i),
@@ -88,9 +88,9 @@ class Node {
88
88
  for (let i = 0, len = node.methods.length; i < len; i++) {
89
89
  const m = node.methods[i];
90
90
  const handlerSet = m[method] || m[import_router.METHOD_NAME_ALL];
91
- const processedSet = {};
91
+ const processedSet = /* @__PURE__ */ Object.create(null);
92
92
  if (handlerSet !== void 0) {
93
- handlerSet.params = {};
93
+ handlerSet.params = /* @__PURE__ */ Object.create(null);
94
94
  handlerSet.possibleKeys.forEach((key) => {
95
95
  const processed = processedSet[handlerSet.name];
96
96
  handlerSet.params[key] = params[key] && !processed ? params[key] : nodeParams[key] ?? params[key];
@@ -103,7 +103,7 @@ class Node {
103
103
  }
104
104
  search(method, path) {
105
105
  const handlerSets = [];
106
- this.params = {};
106
+ this.params = /* @__PURE__ */ Object.create(null);
107
107
  const curNode = this;
108
108
  let curNodes = [curNode];
109
109
  const parts = (0, import_url.splitPath)(path);
@@ -118,9 +118,11 @@ class Node {
118
118
  nextNode.params = node.params;
119
119
  if (isLast === true) {
120
120
  if (nextNode.children["*"]) {
121
- handlerSets.push(...this.gHSets(nextNode.children["*"], method, node.params, {}));
121
+ handlerSets.push(
122
+ ...this.gHSets(nextNode.children["*"], method, node.params, /* @__PURE__ */ Object.create(null))
123
+ );
122
124
  }
123
- handlerSets.push(...this.gHSets(nextNode, method, node.params, {}));
125
+ handlerSets.push(...this.gHSets(nextNode, method, node.params, /* @__PURE__ */ Object.create(null)));
124
126
  } else {
125
127
  tempNodes.push(nextNode);
126
128
  }
@@ -131,7 +133,7 @@ class Node {
131
133
  if (pattern === "*") {
132
134
  const astNode = node.children["*"];
133
135
  if (astNode) {
134
- handlerSets.push(...this.gHSets(astNode, method, node.params, {}));
136
+ handlerSets.push(...this.gHSets(astNode, method, node.params, /* @__PURE__ */ Object.create(null)));
135
137
  tempNodes.push(astNode);
136
138
  }
137
139
  continue;
@@ -144,7 +144,7 @@ const _serialize = (name, value, opt = {}) => {
144
144
  }
145
145
  return cookie;
146
146
  };
147
- const serialize = (name, value, opt = {}) => {
147
+ const serialize = (name, value, opt) => {
148
148
  value = encodeURIComponent(value);
149
149
  return _serialize(name, value, opt);
150
150
  };
@@ -83,8 +83,9 @@ const getPattern = (label) => {
83
83
  return null;
84
84
  };
85
85
  const getPath = (request) => {
86
- const match = request.url.match(/^https?:\/\/[^/]+(\/[^?]*)/);
87
- return match ? match[1] : "";
86
+ const url = request.url;
87
+ const queryIndex = url.indexOf("?", 8);
88
+ return url.slice(url.indexOf("/", 8), queryIndex === -1 ? void 0 : queryIndex);
88
89
  };
89
90
  const getQueryStrings = (url) => {
90
91
  const queryIndex = url.indexOf("?", 8);
@@ -13,7 +13,7 @@ var replaceUrlParam = (urlString, params) => {
13
13
  return urlString;
14
14
  };
15
15
  var removeIndexString = (urlSting) => {
16
- return urlSting.replace(/\/index$/, "/");
16
+ return urlSting.replace(/\/index$/, "");
17
17
  };
18
18
  function isObject(item) {
19
19
  return typeof item === "object" && item !== null && !Array.isArray(item);
package/dist/context.js CHANGED
@@ -129,7 +129,13 @@ var Context = class {
129
129
  });
130
130
  }
131
131
  if (arg && typeof arg !== "number") {
132
- const headers2 = setHeaders(new Headers(arg.headers), this.#preparedHeaders);
132
+ const header = new Headers(arg.headers);
133
+ if (this.#headers) {
134
+ this.#headers.forEach((v, k) => {
135
+ header.set(k, v);
136
+ });
137
+ }
138
+ const headers2 = setHeaders(header, this.#preparedHeaders);
133
139
  return new Response(data, {
134
140
  headers: headers2,
135
141
  status: arg.status ?? this.#status
@@ -17,29 +17,29 @@ var SSEStreamingApi = class extends StreamingApi {
17
17
  await this.write(sseData);
18
18
  }
19
19
  };
20
- var setSSEHeaders = (context) => {
21
- context.header("Transfer-Encoding", "chunked");
22
- context.header("Content-Type", "text/event-stream");
23
- context.header("Cache-Control", "no-cache");
24
- context.header("Connection", "keep-alive");
20
+ var run = async (stream, cb, onError) => {
21
+ try {
22
+ await cb(stream);
23
+ } catch (e) {
24
+ if (e instanceof Error && onError) {
25
+ await onError(e, stream);
26
+ await stream.writeSSE({
27
+ event: "error",
28
+ data: e.message
29
+ });
30
+ } else {
31
+ console.error(e);
32
+ }
33
+ }
25
34
  };
26
35
  var streamSSE = (c, cb, onError) => {
27
36
  const { readable, writable } = new TransformStream();
28
37
  const stream = new SSEStreamingApi(writable, readable);
29
- (async () => {
30
- try {
31
- await cb(stream);
32
- } catch (e) {
33
- if (e instanceof Error && onError) {
34
- await onError(e, stream);
35
- } else {
36
- console.error(e);
37
- }
38
- } finally {
39
- stream.close();
40
- }
41
- })();
42
- setSSEHeaders(c);
38
+ c.header("Transfer-Encoding", "chunked");
39
+ c.header("Content-Type", "text/event-stream");
40
+ c.header("Cache-Control", "no-cache");
41
+ c.header("Connection", "keep-alive");
42
+ run(stream, cb, onError);
43
43
  return c.newResponse(stream.responseReadable);
44
44
  };
45
45
  export {
@@ -18,12 +18,15 @@ var createRenderer = (c, Layout, component, options) => (children, props) => {
18
18
  currentLayout
19
19
  )}`;
20
20
  if (options?.stream) {
21
- return c.body(renderToReadableStream(body), {
22
- headers: options.stream === true ? {
23
- "Transfer-Encoding": "chunked",
24
- "Content-Type": "text/html; charset=UTF-8"
25
- } : options.stream
26
- });
21
+ if (options.stream === true) {
22
+ c.header("Transfer-Encoding", "chunked");
23
+ c.header("Content-Type", "text/html; charset=UTF-8");
24
+ } else {
25
+ for (const [key, value] of Object.entries(options.stream)) {
26
+ c.header(key, value);
27
+ }
28
+ }
29
+ return c.body(renderToReadableStream(body));
27
30
  } else {
28
31
  return c.html(body);
29
32
  }
@@ -1,7 +1,7 @@
1
1
  // src/router/linear-router/router.ts
2
2
  import { METHOD_NAME_ALL, UnsupportedPathError } from "../../router.js";
3
3
  import { checkOptionalParameter } from "../../utils/url.js";
4
- var emptyParams = {};
4
+ var emptyParams = /* @__PURE__ */ Object.create(null);
5
5
  var splitPathRe = /\/(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/[^\/\?]+|(\?)/g;
6
6
  var splitByStarRe = /\*/;
7
7
  var LinearRouter = class {
@@ -56,7 +56,7 @@ var LinearRouter = class {
56
56
  }
57
57
  handlers.push([handler, emptyParams]);
58
58
  } else if (hasLabel && !hasStar) {
59
- const params = {};
59
+ const params = /* @__PURE__ */ Object.create(null);
60
60
  const parts = routePath.match(splitPathRe);
61
61
  const lastIndex = parts.length - 1;
62
62
  for (let j = 0, pos = 0, len2 = parts.length; j < len2; j++) {
@@ -8,19 +8,16 @@ var PatternRouter = class {
8
8
  if (endsWithWildcard) {
9
9
  path = path.slice(0, -2);
10
10
  }
11
- const parts = path.match(/\/?(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/?[^\/\?]+|(\?)/g) || [];
12
- if (parts[parts.length - 1] === "?") {
13
- this.add(method, parts.slice(0, parts.length - 2).join(""), handler);
14
- parts.pop();
11
+ if (path.at(-1) === "?") {
12
+ path = path.slice(0, -1);
13
+ this.add(method, path.replace(/\/[^/]+$/, ""), handler);
15
14
  }
16
- for (let i = 0, len = parts.length; i < len; i++) {
17
- const match = parts[i].match(/^\/:([^{]+)(?:{(.*)})?/);
18
- if (match) {
19
- parts[i] = `/(?<${match[1]}>${match[2] || "[^/]+"})`;
20
- } else if (parts[i] === "/*") {
21
- parts[i] = "/[^/]+";
15
+ const parts = (path.match(/\/?(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/?[^\/\?]+/g) || []).map(
16
+ (part) => {
17
+ const match = part.match(/^\/:([^{]+)(?:{(.*)})?/);
18
+ return match ? `/(?<${match[1]}>${match[2] || "[^/]+"})` : part === "/*" ? "/[^/]+" : part.replace(/[.\\+*[^\]$()]/g, "\\$&");
22
19
  }
23
- }
20
+ );
24
21
  let re;
25
22
  try {
26
23
  re = new RegExp(`^${parts.join("")}${endsWithWildcard ? "" : "/?$"}`);
@@ -35,7 +32,7 @@ var PatternRouter = class {
35
32
  if (routeMethod === METHOD_NAME_ALL || routeMethod === method) {
36
33
  const match = pattern.exec(path);
37
34
  if (match) {
38
- handlers.push([handler, match.groups || {}]);
35
+ handlers.push([handler, match.groups || /* @__PURE__ */ Object.create(null)]);
39
36
  }
40
37
  }
41
38
  }
@@ -3,6 +3,7 @@ var LABEL_REG_EXP_STR = "[^/]+";
3
3
  var ONLY_WILDCARD_REG_EXP_STR = ".*";
4
4
  var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
5
5
  var PATH_ERROR = Symbol();
6
+ var regExpMetaChars = new Set(".\\+*[^]$()");
6
7
  function compareKey(a, b) {
7
8
  if (a.length === 1) {
8
9
  return b.length === 1 ? a < b ? -1 : 1 : -1;
@@ -25,7 +26,7 @@ function compareKey(a, b) {
25
26
  var Node = class {
26
27
  index;
27
28
  varIndex;
28
- children = {};
29
+ children = /* @__PURE__ */ Object.create(null);
29
30
  insert(tokens, index, paramMap, context, pathErrorCheckOnly) {
30
31
  if (tokens.length === 0) {
31
32
  if (this.index !== void 0) {
@@ -87,7 +88,7 @@ var Node = class {
87
88
  const childKeys = Object.keys(this.children).sort(compareKey);
88
89
  const strList = childKeys.map((k) => {
89
90
  const c = this.children[k];
90
- return (typeof c.varIndex === "number" ? `(${k})@${c.varIndex}` : k) + c.buildRegExpStr();
91
+ return (typeof c.varIndex === "number" ? `(${k})@${c.varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c.buildRegExpStr();
91
92
  });
92
93
  if (typeof this.index === "number") {
93
94
  strList.unshift(`#${this.index}`);
@@ -8,15 +8,15 @@ import { checkOptionalParameter } from "../../utils/url.js";
8
8
  import { PATH_ERROR } from "./node.js";
9
9
  import { Trie } from "./trie.js";
10
10
  var emptyParam = [];
11
- var nullMatcher = [/^$/, [], {}];
12
- var wildcardRegExpCache = {};
11
+ var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
12
+ var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
13
13
  function buildWildcardRegExp(path) {
14
14
  return wildcardRegExpCache[path] ??= new RegExp(
15
15
  path === "*" ? "" : `^${path.replace(/\/\*/, "(?:|/.*)")}$`
16
16
  );
17
17
  }
18
18
  function clearWildcardRegExpCache() {
19
- wildcardRegExpCache = {};
19
+ wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
20
20
  }
21
21
  function buildMatcherFromPreprocessedRoutes(routes) {
22
22
  const trie = new Trie();
@@ -29,11 +29,11 @@ function buildMatcherFromPreprocessedRoutes(routes) {
29
29
  ).sort(
30
30
  ([isStaticA, pathA], [isStaticB, pathB]) => isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length
31
31
  );
32
- const staticMap = {};
32
+ const staticMap = /* @__PURE__ */ Object.create(null);
33
33
  for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
34
34
  const [pathErrorCheckOnly, path, handlers] = routesWithStaticPathFlag[i];
35
35
  if (pathErrorCheckOnly) {
36
- staticMap[path] = [handlers.map(([h]) => [h, {}]), emptyParam];
36
+ staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
37
37
  } else {
38
38
  j++;
39
39
  }
@@ -47,7 +47,7 @@ function buildMatcherFromPreprocessedRoutes(routes) {
47
47
  continue;
48
48
  }
49
49
  handlerData[j] = handlers.map(([h, paramCount]) => {
50
- const paramIndexMap = {};
50
+ const paramIndexMap = /* @__PURE__ */ Object.create(null);
51
51
  paramCount -= 1;
52
52
  for (; paramCount >= 0; paramCount--) {
53
53
  const [key, value] = paramAssoc[paramCount];
@@ -91,8 +91,8 @@ var RegExpRouter = class {
91
91
  middleware;
92
92
  routes;
93
93
  constructor() {
94
- this.middleware = { [METHOD_NAME_ALL]: {} };
95
- this.routes = { [METHOD_NAME_ALL]: {} };
94
+ this.middleware = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
95
+ this.routes = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
96
96
  }
97
97
  add(method, path, handler) {
98
98
  const { middleware, routes } = this;
@@ -102,7 +102,7 @@ var RegExpRouter = class {
102
102
  if (!middleware[method]) {
103
103
  ;
104
104
  [middleware, routes].forEach((handlerMap) => {
105
- handlerMap[method] = {};
105
+ handlerMap[method] = /* @__PURE__ */ Object.create(null);
106
106
  Object.keys(handlerMap[METHOD_NAME_ALL]).forEach((p) => {
107
107
  handlerMap[method][p] = [...handlerMap[METHOD_NAME_ALL][p]];
108
108
  });
@@ -169,7 +169,7 @@ var RegExpRouter = class {
169
169
  return this.match(method, path);
170
170
  }
171
171
  buildAllMatchers() {
172
- const matchers = {};
172
+ const matchers = /* @__PURE__ */ Object.create(null);
173
173
  [...Object.keys(this.routes), ...Object.keys(this.middleware)].forEach((method) => {
174
174
  matchers[method] ||= this.buildMatcher(method);
175
175
  });
@@ -7,13 +7,13 @@ var Node = class {
7
7
  patterns;
8
8
  order = 0;
9
9
  name;
10
- params = {};
10
+ params = /* @__PURE__ */ Object.create(null);
11
11
  constructor(method, handler, children) {
12
- this.children = children || {};
12
+ this.children = children || /* @__PURE__ */ Object.create(null);
13
13
  this.methods = [];
14
14
  this.name = "";
15
15
  if (method && handler) {
16
- const m = {};
16
+ const m = /* @__PURE__ */ Object.create(null);
17
17
  m[method] = { handler, possibleKeys: [], score: 0, name: this.name };
18
18
  this.methods = [m];
19
19
  }
@@ -50,7 +50,7 @@ var Node = class {
50
50
  if (!curNode.methods.length) {
51
51
  curNode.methods = [];
52
52
  }
53
- const m = {};
53
+ const m = /* @__PURE__ */ Object.create(null);
54
54
  const handlerSet = {
55
55
  handler,
56
56
  possibleKeys: possibleKeys.filter((v, i, a) => a.indexOf(v) === i),
@@ -66,9 +66,9 @@ var Node = class {
66
66
  for (let i = 0, len = node.methods.length; i < len; i++) {
67
67
  const m = node.methods[i];
68
68
  const handlerSet = m[method] || m[METHOD_NAME_ALL];
69
- const processedSet = {};
69
+ const processedSet = /* @__PURE__ */ Object.create(null);
70
70
  if (handlerSet !== void 0) {
71
- handlerSet.params = {};
71
+ handlerSet.params = /* @__PURE__ */ Object.create(null);
72
72
  handlerSet.possibleKeys.forEach((key) => {
73
73
  const processed = processedSet[handlerSet.name];
74
74
  handlerSet.params[key] = params[key] && !processed ? params[key] : nodeParams[key] ?? params[key];
@@ -81,7 +81,7 @@ var Node = class {
81
81
  }
82
82
  search(method, path) {
83
83
  const handlerSets = [];
84
- this.params = {};
84
+ this.params = /* @__PURE__ */ Object.create(null);
85
85
  const curNode = this;
86
86
  let curNodes = [curNode];
87
87
  const parts = splitPath(path);
@@ -96,9 +96,11 @@ var Node = class {
96
96
  nextNode.params = node.params;
97
97
  if (isLast === true) {
98
98
  if (nextNode.children["*"]) {
99
- handlerSets.push(...this.gHSets(nextNode.children["*"], method, node.params, {}));
99
+ handlerSets.push(
100
+ ...this.gHSets(nextNode.children["*"], method, node.params, /* @__PURE__ */ Object.create(null))
101
+ );
100
102
  }
101
- handlerSets.push(...this.gHSets(nextNode, method, node.params, {}));
103
+ handlerSets.push(...this.gHSets(nextNode, method, node.params, /* @__PURE__ */ Object.create(null)));
102
104
  } else {
103
105
  tempNodes.push(nextNode);
104
106
  }
@@ -109,7 +111,7 @@ var Node = class {
109
111
  if (pattern === "*") {
110
112
  const astNode = node.children["*"];
111
113
  if (astNode) {
112
- handlerSets.push(...this.gHSets(astNode, method, node.params, {}));
114
+ handlerSets.push(...this.gHSets(astNode, method, node.params, /* @__PURE__ */ Object.create(null)));
113
115
  tempNodes.push(astNode);
114
116
  }
115
117
  continue;
@@ -1,3 +1,4 @@
1
+ /// <reference types="node" />
1
2
  import type { Hono } from '../../hono';
2
3
  interface CloudFrontHeader {
3
4
  key: string;
@@ -82,5 +83,6 @@ interface CloudFrontResult {
82
83
  bodyEncoding?: 'text' | 'base64';
83
84
  }
84
85
  export declare const handle: (app: Hono<any>) => (event: CloudFrontEdgeEvent, context?: CloudFrontContext, callback?: Callback) => Promise<CloudFrontResult>;
86
+ export declare const createBody: (method: string, requestBody: CloudFrontRequest['body']) => string | Buffer | undefined;
85
87
  export declare const isContentTypeBinary: (contentType: string) => boolean;
86
88
  export {};
@@ -1,6 +1,6 @@
1
1
  import { Hono } from './hono';
2
2
  export type { Env, ErrorHandler, Handler, MiddlewareHandler, Next, NotFoundHandler, ValidationTargets, Input, Schema, ToSchema, TypedResponse, } from './types';
3
- export type { Context, ContextVariableMap, ContextRenderer } from './context';
3
+ export type { Context, ContextVariableMap, ContextRenderer, ExecutionContext } from './context';
4
4
  export type { HonoRequest } from './request';
5
5
  export type { InferRequestType, InferResponseType, ClientRequestOptions } from './client';
6
6
  export { Hono };
@@ -412,7 +412,7 @@ export type AddParam<I, P extends string> = ParamKeys<P> extends never ? I : I e
412
412
  param: UnionToIntersection<ParamKeyToRecord<ParamKeys<P>>>;
413
413
  };
414
414
  type AddDollar<T extends string> = `$${Lowercase<T>}`;
415
- export type MergePath<A extends string, B extends string> = A extends '' ? B : A extends '/' ? B : A extends `${infer P}/` ? B extends `/${infer Q}` ? `${P}/${Q}` : `${P}/${B}` : B extends `/${infer Q}` ? Q extends '' ? A : `${A}/${Q}` : `${A}/${B}`;
415
+ export type MergePath<A extends string, B extends string> = B extends '' ? MergePath<A, '/'> : A extends '' ? B : A extends '/' ? B : A extends `${infer P}/` ? B extends `/${infer Q}` ? `${P}/${Q}` : `${P}/${B}` : B extends `/${infer Q}` ? Q extends '' ? A : `${A}/${Q}` : `${A}/${B}`;
416
416
  export type TypedResponse<T = unknown> = {
417
417
  data: T;
418
418
  format: 'json';
@@ -1,5 +1,20 @@
1
1
  export type Cookie = Record<string, string>;
2
2
  export type SignedCookie = Record<string, string | false>;
3
+ type PartitionCookieConstraint = {
4
+ partition: true;
5
+ secure: true;
6
+ } | {
7
+ partition?: boolean;
8
+ secure?: boolean;
9
+ };
10
+ type SecureCookieConstraint = {
11
+ secure: true;
12
+ };
13
+ type HostCookieConstraint = {
14
+ secure: true;
15
+ path: '/';
16
+ domain?: undefined;
17
+ };
3
18
  export type CookieOptions = {
4
19
  domain?: string;
5
20
  expires?: Date;
@@ -11,9 +26,11 @@ export type CookieOptions = {
11
26
  sameSite?: 'Strict' | 'Lax' | 'None';
12
27
  partitioned?: boolean;
13
28
  prefix?: CookiePrefixOptions;
14
- };
29
+ } & PartitionCookieConstraint;
15
30
  export type CookiePrefixOptions = 'host' | 'secure';
31
+ export type CookieConstraint<Name> = Name extends `__Secure-${string}` ? CookieOptions & SecureCookieConstraint : Name extends `__Host-${string}` ? CookieOptions & HostCookieConstraint : CookieOptions;
16
32
  export declare const parse: (cookie: string, name?: string) => Cookie;
17
33
  export declare const parseSigned: (cookie: string, secret: string | BufferSource, name?: string) => Promise<SignedCookie>;
18
- export declare const serialize: (name: string, value: string, opt?: CookieOptions) => string;
34
+ export declare const serialize: <Name extends string>(name: Name, value: string, opt?: CookieConstraint<Name> | undefined) => string;
19
35
  export declare const serializeSigned: (name: string, value: string, secret: string | BufferSource, opt?: CookieOptions) => Promise<string>;
36
+ export {};
@@ -119,7 +119,7 @@ var _serialize = (name, value, opt = {}) => {
119
119
  }
120
120
  return cookie;
121
121
  };
122
- var serialize = (name, value, opt = {}) => {
122
+ var serialize = (name, value, opt) => {
123
123
  value = encodeURIComponent(value);
124
124
  return _serialize(name, value, opt);
125
125
  };
package/dist/utils/url.js CHANGED
@@ -51,8 +51,9 @@ var getPattern = (label) => {
51
51
  return null;
52
52
  };
53
53
  var getPath = (request) => {
54
- const match = request.url.match(/^https?:\/\/[^/]+(\/[^?]*)/);
55
- return match ? match[1] : "";
54
+ const url = request.url;
55
+ const queryIndex = url.indexOf("?", 8);
56
+ return url.slice(url.indexOf("/", 8), queryIndex === -1 ? void 0 : queryIndex);
56
57
  };
57
58
  var getQueryStrings = (url) => {
58
59
  const queryIndex = url.indexOf("?", 8);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "4.1.0",
3
+ "version": "4.1.2",
4
4
  "description": "Ultrafast web framework for the Edges",
5
5
  "main": "dist/cjs/index.js",
6
6
  "type": "module",