@harrylabsj/kiwi-merchant-cloud 0.12.0 → 0.12.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.
Files changed (50) hide show
  1. package/app/cloud/bootstrap.d.ts +2 -0
  2. package/app/cloud/bootstrap.js +93 -10
  3. package/app/cloud/bootstrap.js.map +1 -1
  4. package/app/cloud/catalog-client.d.ts +2 -0
  5. package/app/cloud/catalog-client.js +5 -1
  6. package/app/cloud/catalog-client.js.map +1 -1
  7. package/app/cloud/connect-service.d.ts +153 -0
  8. package/app/cloud/connect-service.js +897 -0
  9. package/app/cloud/connect-service.js.map +1 -0
  10. package/app/cloud/file-listing-publication.d.ts +105 -0
  11. package/app/cloud/file-listing-publication.js +436 -0
  12. package/app/cloud/file-listing-publication.js.map +1 -0
  13. package/app/cloud/merchant-connect.d.ts +19 -13
  14. package/app/cloud/merchant-connect.js +43 -284
  15. package/app/cloud/merchant-connect.js.map +1 -1
  16. package/app/cloud-sample/products.json +3 -3
  17. package/app/http/merchant-management/api.d.ts +23 -1
  18. package/app/http/merchant-management/api.js +141 -1
  19. package/app/http/merchant-management/api.js.map +1 -1
  20. package/app/http/merchant-management/page.d.ts +4 -1
  21. package/app/http/merchant-management/page.js +126 -7
  22. package/app/http/merchant-management/page.js.map +1 -1
  23. package/build-manifest.json +116 -86
  24. package/node_modules/@hono/node-server/dist/early-hints.cjs +1 -1
  25. package/node_modules/@hono/node-server/dist/early-hints.mjs +1 -1
  26. package/node_modules/@hono/node-server/dist/index.cjs +41 -19
  27. package/node_modules/@hono/node-server/dist/index.mjs +42 -20
  28. package/node_modules/@hono/node-server/dist/serve-static.cjs +1 -0
  29. package/node_modules/@hono/node-server/dist/serve-static.d.cts +2 -1
  30. package/node_modules/@hono/node-server/dist/serve-static.d.mts +2 -1
  31. package/node_modules/@hono/node-server/dist/serve-static.mjs +1 -0
  32. package/node_modules/@hono/node-server/package.json +3 -2
  33. package/node_modules/hono/dist/cjs/adapter/bun/websocket.js +1 -1
  34. package/node_modules/hono/dist/cjs/jsx/utils.js +1 -1
  35. package/node_modules/hono/dist/cjs/middleware/combine/index.js +3 -1
  36. package/node_modules/hono/dist/cjs/middleware/etag/index.js +2 -2
  37. package/node_modules/hono/dist/cjs/middleware/language/language.js +1 -1
  38. package/node_modules/hono/dist/cjs/middleware/serve-static/index.js +1 -0
  39. package/node_modules/hono/dist/jsx/utils.js +1 -1
  40. package/node_modules/hono/dist/middleware/combine/index.js +3 -1
  41. package/node_modules/hono/dist/middleware/etag/index.js +2 -2
  42. package/node_modules/hono/dist/middleware/serve-static/index.js +1 -0
  43. package/node_modules/hono/package.json +2 -2
  44. package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +19 -18
  45. package/node_modules/yaml/browser/dist/nodes/Alias.js +25 -23
  46. package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +19 -18
  47. package/node_modules/yaml/dist/nodes/Alias.js +25 -23
  48. package/node_modules/yaml/package.json +1 -1
  49. package/package.json +2 -2
  50. package/runtime-package.json +2 -2
@@ -15,7 +15,7 @@ const earlyHints = (options) => {
15
15
  const dest = c.req.header("Sec-Fetch-Dest");
16
16
  if (mode && mode !== "navigate" || dest && dest !== "document") return next();
17
17
  const env = c.env || {};
18
- const outgoing = (env.server ? env.server : env)?.outgoing;
18
+ const outgoing = ("server" in env ? env.server : env)?.outgoing;
19
19
  if (typeof outgoing?.writeEarlyHints !== "function") {
20
20
  if (!warned) {
21
21
  console.warn("Early Hints Middleware is not supported because writeEarlyHints is not defined.");
@@ -13,7 +13,7 @@ const earlyHints = (options) => {
13
13
  const dest = c.req.header("Sec-Fetch-Dest");
14
14
  if (mode && mode !== "navigate" || dest && dest !== "document") return next();
15
15
  const env = c.env || {};
16
- const outgoing = (env.server ? env.server : env)?.outgoing;
16
+ const outgoing = ("server" in env ? env.server : env)?.outgoing;
17
17
  if (typeof outgoing?.writeEarlyHints !== "function") {
18
18
  if (!warned) {
19
19
  console.warn("Early Hints Middleware is not supported because writeEarlyHints is not defined.");
@@ -868,7 +868,10 @@ const handleResponseError = (e, outgoing) => {
868
868
  if (err.code === "ERR_STREAM_PREMATURE_CLOSE") console.info("The user aborted a request.");
869
869
  else {
870
870
  console.error(e);
871
- if (!outgoing.headersSent) outgoing.writeHead(500, { "Content-Type": "text/plain" });
871
+ if (!outgoing.headersSent) {
872
+ if (outgoing instanceof node_http.ServerResponse) outgoing._contentLength = null;
873
+ outgoing.writeHead(500, { "Content-Type": "text/plain" });
874
+ }
872
875
  outgoing.end(`Error: ${err.message}`);
873
876
  outgoing.destroy(err);
874
877
  }
@@ -876,6 +879,21 @@ const handleResponseError = (e, outgoing) => {
876
879
  const flushHeaders = (outgoing) => {
877
880
  if ("flushHeaders" in outgoing && outgoing.writable) outgoing.flushHeaders();
878
881
  };
882
+ const trySetContentLength = (outgoing, status, length) => {
883
+ const http1 = outgoing;
884
+ if (http1._contentLength === null && http1._hasBody && http1.useChunkedEncodingByDefault && !http1._removedContLen && status >= 200 && status !== 204 && status !== 304 && !outgoing.hasHeader("content-length") && !outgoing.hasHeader("transfer-encoding") && !outgoing.hasHeader("trailer")) {
885
+ http1._contentLength = length;
886
+ return true;
887
+ }
888
+ return false;
889
+ };
890
+ const writeDefaultHeaders = (outgoing, status, length) => {
891
+ if (trySetContentLength(outgoing, status, length)) outgoing.writeHead(status, { "Content-Type": defaultContentType });
892
+ else outgoing.writeHead(status, {
893
+ "Content-Type": defaultContentType,
894
+ "Content-Length": length
895
+ });
896
+ };
879
897
  const responseViaCache = async (res, outgoing) => {
880
898
  let [status, body, header] = res[cacheKey];
881
899
  if (!header) {
@@ -883,22 +901,13 @@ const responseViaCache = async (res, outgoing) => {
883
901
  outgoing.writeHead(status);
884
902
  outgoing.end();
885
903
  } else if (typeof body === "string") {
886
- outgoing.writeHead(status, {
887
- "Content-Type": defaultContentType,
888
- "Content-Length": Buffer.byteLength(body)
889
- });
904
+ writeDefaultHeaders(outgoing, status, Buffer.byteLength(body));
890
905
  outgoing.end(body);
891
906
  } else if (body instanceof Uint8Array) {
892
- outgoing.writeHead(status, {
893
- "Content-Type": defaultContentType,
894
- "Content-Length": body.byteLength
895
- });
907
+ writeDefaultHeaders(outgoing, status, body.byteLength);
896
908
  outgoing.end(body);
897
909
  } else if (body instanceof Blob) {
898
- outgoing.writeHead(status, {
899
- "Content-Type": defaultContentType,
900
- "Content-Length": body.size
901
- });
910
+ writeDefaultHeaders(outgoing, status, body.size);
902
911
  outgoing.end(new Uint8Array(await body.arrayBuffer()));
903
912
  } else {
904
913
  outgoing.writeHead(status, { "Content-Type": defaultContentType });
@@ -909,6 +918,8 @@ const responseViaCache = async (res, outgoing) => {
909
918
  return;
910
919
  }
911
920
  let hasContentLength = false;
921
+ let plainHeaders = false;
922
+ let canAutoLength = true;
912
923
  if (header instanceof Headers) {
913
924
  hasContentLength = header.has("content-length");
914
925
  header = buildOutgoingHttpHeaders(header, body === null ? void 0 : defaultContentType);
@@ -916,14 +927,25 @@ const responseViaCache = async (res, outgoing) => {
916
927
  const headerObj = new Headers(header);
917
928
  hasContentLength = headerObj.has("content-length");
918
929
  header = buildOutgoingHttpHeaders(headerObj, body === null ? void 0 : defaultContentType);
919
- } else for (const key in header) if (key.length === 14 && key.toLowerCase() === "content-length") {
920
- hasContentLength = true;
921
- break;
930
+ } else {
931
+ plainHeaders = true;
932
+ for (const key in header) {
933
+ if (key.length === 14 && key.toLowerCase() === "content-length") {
934
+ hasContentLength = true;
935
+ break;
936
+ }
937
+ if (key.length === 17 && key.toLowerCase() === "transfer-encoding" || key.length === 7 && key.toLowerCase() === "trailer") canAutoLength = false;
938
+ }
922
939
  }
923
940
  if (!hasContentLength) {
924
- if (typeof body === "string") header["Content-Length"] = Buffer.byteLength(body);
925
- else if (body instanceof Uint8Array) header["Content-Length"] = body.byteLength;
926
- else if (body instanceof Blob) header["Content-Length"] = body.size;
941
+ let length;
942
+ if (typeof body === "string") length = Buffer.byteLength(body);
943
+ else if (body instanceof Uint8Array) length = body.byteLength;
944
+ else if (body instanceof Blob) length = body.size;
945
+ if (length !== void 0 && (!plainHeaders || !canAutoLength || !trySetContentLength(outgoing, status, length))) {
946
+ if (plainHeaders) header = { ...header };
947
+ header["Content-Length"] = length;
948
+ }
927
949
  }
928
950
  outgoing.writeHead(status, header);
929
951
  if (body == null) outgoing.end();
@@ -1,5 +1,5 @@
1
1
  import { t as X_ALREADY_SENT } from "./constants-BLSFu_RU.mjs";
2
- import { STATUS_CODES, createServer } from "node:http";
2
+ import { STATUS_CODES, ServerResponse, createServer } from "node:http";
3
3
  import { Http2ServerRequest, constants } from "node:http2";
4
4
  import { Readable } from "node:stream";
5
5
  import { defineWebSocketHelper } from "hono/ws";
@@ -867,7 +867,10 @@ const handleResponseError = (e, outgoing) => {
867
867
  if (err.code === "ERR_STREAM_PREMATURE_CLOSE") console.info("The user aborted a request.");
868
868
  else {
869
869
  console.error(e);
870
- if (!outgoing.headersSent) outgoing.writeHead(500, { "Content-Type": "text/plain" });
870
+ if (!outgoing.headersSent) {
871
+ if (outgoing instanceof ServerResponse) outgoing._contentLength = null;
872
+ outgoing.writeHead(500, { "Content-Type": "text/plain" });
873
+ }
871
874
  outgoing.end(`Error: ${err.message}`);
872
875
  outgoing.destroy(err);
873
876
  }
@@ -875,6 +878,21 @@ const handleResponseError = (e, outgoing) => {
875
878
  const flushHeaders = (outgoing) => {
876
879
  if ("flushHeaders" in outgoing && outgoing.writable) outgoing.flushHeaders();
877
880
  };
881
+ const trySetContentLength = (outgoing, status, length) => {
882
+ const http1 = outgoing;
883
+ if (http1._contentLength === null && http1._hasBody && http1.useChunkedEncodingByDefault && !http1._removedContLen && status >= 200 && status !== 204 && status !== 304 && !outgoing.hasHeader("content-length") && !outgoing.hasHeader("transfer-encoding") && !outgoing.hasHeader("trailer")) {
884
+ http1._contentLength = length;
885
+ return true;
886
+ }
887
+ return false;
888
+ };
889
+ const writeDefaultHeaders = (outgoing, status, length) => {
890
+ if (trySetContentLength(outgoing, status, length)) outgoing.writeHead(status, { "Content-Type": defaultContentType });
891
+ else outgoing.writeHead(status, {
892
+ "Content-Type": defaultContentType,
893
+ "Content-Length": length
894
+ });
895
+ };
878
896
  const responseViaCache = async (res, outgoing) => {
879
897
  let [status, body, header] = res[cacheKey];
880
898
  if (!header) {
@@ -882,22 +900,13 @@ const responseViaCache = async (res, outgoing) => {
882
900
  outgoing.writeHead(status);
883
901
  outgoing.end();
884
902
  } else if (typeof body === "string") {
885
- outgoing.writeHead(status, {
886
- "Content-Type": defaultContentType,
887
- "Content-Length": Buffer.byteLength(body)
888
- });
903
+ writeDefaultHeaders(outgoing, status, Buffer.byteLength(body));
889
904
  outgoing.end(body);
890
905
  } else if (body instanceof Uint8Array) {
891
- outgoing.writeHead(status, {
892
- "Content-Type": defaultContentType,
893
- "Content-Length": body.byteLength
894
- });
906
+ writeDefaultHeaders(outgoing, status, body.byteLength);
895
907
  outgoing.end(body);
896
908
  } else if (body instanceof Blob) {
897
- outgoing.writeHead(status, {
898
- "Content-Type": defaultContentType,
899
- "Content-Length": body.size
900
- });
909
+ writeDefaultHeaders(outgoing, status, body.size);
901
910
  outgoing.end(new Uint8Array(await body.arrayBuffer()));
902
911
  } else {
903
912
  outgoing.writeHead(status, { "Content-Type": defaultContentType });
@@ -908,6 +917,8 @@ const responseViaCache = async (res, outgoing) => {
908
917
  return;
909
918
  }
910
919
  let hasContentLength = false;
920
+ let plainHeaders = false;
921
+ let canAutoLength = true;
911
922
  if (header instanceof Headers) {
912
923
  hasContentLength = header.has("content-length");
913
924
  header = buildOutgoingHttpHeaders(header, body === null ? void 0 : defaultContentType);
@@ -915,14 +926,25 @@ const responseViaCache = async (res, outgoing) => {
915
926
  const headerObj = new Headers(header);
916
927
  hasContentLength = headerObj.has("content-length");
917
928
  header = buildOutgoingHttpHeaders(headerObj, body === null ? void 0 : defaultContentType);
918
- } else for (const key in header) if (key.length === 14 && key.toLowerCase() === "content-length") {
919
- hasContentLength = true;
920
- break;
929
+ } else {
930
+ plainHeaders = true;
931
+ for (const key in header) {
932
+ if (key.length === 14 && key.toLowerCase() === "content-length") {
933
+ hasContentLength = true;
934
+ break;
935
+ }
936
+ if (key.length === 17 && key.toLowerCase() === "transfer-encoding" || key.length === 7 && key.toLowerCase() === "trailer") canAutoLength = false;
937
+ }
921
938
  }
922
939
  if (!hasContentLength) {
923
- if (typeof body === "string") header["Content-Length"] = Buffer.byteLength(body);
924
- else if (body instanceof Uint8Array) header["Content-Length"] = body.byteLength;
925
- else if (body instanceof Blob) header["Content-Length"] = body.size;
940
+ let length;
941
+ if (typeof body === "string") length = Buffer.byteLength(body);
942
+ else if (body instanceof Uint8Array) length = body.byteLength;
943
+ else if (body instanceof Blob) length = body.size;
944
+ if (length !== void 0 && (!plainHeaders || !canAutoLength || !trySetContentLength(outgoing, status, length))) {
945
+ if (plainHeaders) header = { ...header };
946
+ header["Content-Length"] = length;
947
+ }
926
948
  }
927
949
  outgoing.writeHead(status, header);
928
950
  if (body == null) outgoing.end();
@@ -77,6 +77,7 @@ const serveStatic = (options = { root: "" }) => {
77
77
  let filename;
78
78
  if (optionPath) filename = optionPath;
79
79
  else try {
80
+ if (!options.allowPercentInPath && c.req.path.includes("%")) throw new Error();
80
81
  filename = tryDecodeURI(c.req.path);
81
82
  if (/(?:^|[\/\\])\.{1,2}(?:$|[\/\\])|[\/\\]{2,}|\\/.test(filename)) throw new Error();
82
83
  } catch {
@@ -8,7 +8,8 @@ type ServeStaticOptions<E extends Env = Env> = {
8
8
  root?: string;
9
9
  path?: string;
10
10
  index?: string;
11
- precompressed?: boolean;
11
+ precompressed?: boolean; /** Allow percent signs in the routed request path. Defaults to false. */
12
+ allowPercentInPath?: boolean;
12
13
  rewriteRequestPath?: (path: string, c: Context<E>) => string;
13
14
  onFound?: (path: string, c: Context<E>) => void | Promise<void>;
14
15
  onNotFound?: (path: string, c: Context<E>) => void | Promise<void>;
@@ -8,7 +8,8 @@ type ServeStaticOptions<E extends Env = Env> = {
8
8
  root?: string;
9
9
  path?: string;
10
10
  index?: string;
11
- precompressed?: boolean;
11
+ precompressed?: boolean; /** Allow percent signs in the routed request path. Defaults to false. */
12
+ allowPercentInPath?: boolean;
12
13
  rewriteRequestPath?: (path: string, c: Context<E>) => string;
13
14
  onFound?: (path: string, c: Context<E>) => void | Promise<void>;
14
15
  onNotFound?: (path: string, c: Context<E>) => void | Promise<void>;
@@ -76,6 +76,7 @@ const serveStatic = (options = { root: "" }) => {
76
76
  let filename;
77
77
  if (optionPath) filename = optionPath;
78
78
  else try {
79
+ if (!options.allowPercentInPath && c.req.path.includes("%")) throw new Error();
79
80
  filename = tryDecodeURI(c.req.path);
80
81
  if (/(?:^|[\/\\])\.{1,2}(?:$|[\/\\])|[\/\\]{2,}|\\/.test(filename)) throw new Error();
81
82
  } catch {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hono/node-server",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "Node.js Adapter for Hono",
5
5
  "main": "dist/index.mjs",
6
6
  "type": "module",
@@ -100,7 +100,7 @@
100
100
  "@types/ws": "^8.18.1",
101
101
  "@whatwg-node/fetch": "^0.9.14",
102
102
  "eslint": "^9.10.0",
103
- "hono": "^4.12.8",
103
+ "hono": "^4.13.9",
104
104
  "np": "^11.2.1",
105
105
  "prettier": "^3.2.4",
106
106
  "publint": "^0.3.18",
@@ -119,6 +119,7 @@
119
119
  "postbuild": "publint",
120
120
  "prerelease": "pnpm run build && pnpm run test --run",
121
121
  "release": "np --no-publish",
122
+ "typecheck": "tsc --noEmit",
122
123
  "lint": "eslint src test",
123
124
  "lint:fix": "eslint src test --fix",
124
125
  "format": "prettier --check \"src/**/*.{js,ts}\" \"test/**/*.{js,ts}\"",
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_helper_websocket_index = require("../../helper/websocket/index.js");
3
2
  const require_adapter_bun_server = require("./server.js");
3
+ const require_helper_websocket_index = require("../../helper/websocket/index.js");
4
4
  //#region src/adapter/bun/websocket.ts
5
5
  /**
6
6
  * @internal
@@ -101,7 +101,7 @@ const styleObjectForEach = (style, fn) => {
101
101
  continue;
102
102
  }
103
103
  let value;
104
- if (typeof v === "number") value = !key.match(/^(?:a|border-im|column(?:-c|s)|flex(?:$|-[^b])|grid-(?:ar|[^a])|font-w|li|or|sca|st|ta|wido|z)|ty$/) ? `${v}px` : `${v}`;
104
+ if (typeof v === "number") value = !key.match(/^(?:a|border-im|column(?:-c|s)|flex(?:$|-[^b])|grid-(?!.*gap)(?:ar|[^a])|font-w|li|or|sca|st|ta|wido|z)|ty$/) ? `${v}px` : `${v}`;
105
105
  else if (typeof v === "string") {
106
106
  if (hasUnsafeStyleValue(v)) continue;
107
107
  value = v;
@@ -40,13 +40,14 @@ const some = (...middleware) => {
40
40
  return next();
41
41
  };
42
42
  let lastError;
43
+ let response;
43
44
  for (const handler of middleware) try {
44
45
  const result = await handler(c, wrappedNext);
45
46
  if (result === true && !c.finalized) await wrappedNext();
46
47
  else if (result === false) {
47
48
  lastError = /* @__PURE__ */ new Error("No successful middleware found");
48
49
  continue;
49
- }
50
+ } else if (result && result !== true) response = result;
50
51
  lastError = void 0;
51
52
  break;
52
53
  } catch (error) {
@@ -54,6 +55,7 @@ const some = (...middleware) => {
54
55
  if (isNextCalled) break;
55
56
  }
56
57
  if (lastError) throw lastError;
58
+ return response;
57
59
  };
58
60
  };
59
61
  /**
@@ -49,7 +49,7 @@ function initializeGenerator(generator) {
49
49
  * ```
50
50
  */
51
51
  const etag = (options) => {
52
- const retainedHeaders = options?.retainedHeaders ?? RETAINED_304_HEADERS;
52
+ const retainedHeaders = new Set((options?.retainedHeaders ?? RETAINED_304_HEADERS).map((header) => header.toLowerCase()));
53
53
  const weak = options?.weak ?? false;
54
54
  const generator = initializeGenerator(options?.generateDigest);
55
55
  return async function etag(c, next) {
@@ -70,7 +70,7 @@ const etag = (options) => {
70
70
  statusText: "Not Modified",
71
71
  headers: { ETag: etag }
72
72
  });
73
- for (const key of Array.from(c.res.headers.keys())) if (retainedHeaders.indexOf(key.toLowerCase()) === -1) c.res.headers.delete(key);
73
+ for (const key of Array.from(c.res.headers.keys())) if (!retainedHeaders.has(key.toLowerCase())) c.res.headers.delete(key);
74
74
  } else c.res.headers.set("ETag", etag);
75
75
  };
76
76
  };
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_utils_accept = require("../../utils/accept.js");
3
2
  const require_helper_cookie_index = require("../../helper/cookie/index.js");
3
+ const require_utils_accept = require("../../utils/accept.js");
4
4
  //#region src/middleware/language/language.ts
5
5
  const DEFAULT_OPTIONS = {
6
6
  order: [
@@ -23,6 +23,7 @@ const serveStatic = (options) => {
23
23
  let filename;
24
24
  if (options.path) filename = options.path;
25
25
  else try {
26
+ if (!options.allowPercentInPath && c.req.path.includes("%")) throw new Error();
26
27
  filename = require_utils_url.tryDecodeURI(c.req.path);
27
28
  if (/(?:^|[\/\\])\.{1,2}(?:$|[\/\\])|[\/\\]{2,}|\\/.test(filename)) throw new Error();
28
29
  } catch {
@@ -100,7 +100,7 @@ const styleObjectForEach = (style, fn) => {
100
100
  continue;
101
101
  }
102
102
  let value;
103
- if (typeof v === "number") value = !key.match(/^(?:a|border-im|column(?:-c|s)|flex(?:$|-[^b])|grid-(?:ar|[^a])|font-w|li|or|sca|st|ta|wido|z)|ty$/) ? `${v}px` : `${v}`;
103
+ if (typeof v === "number") value = !key.match(/^(?:a|border-im|column(?:-c|s)|flex(?:$|-[^b])|grid-(?!.*gap)(?:ar|[^a])|font-w|li|or|sca|st|ta|wido|z)|ty$/) ? `${v}px` : `${v}`;
104
104
  else if (typeof v === "string") {
105
105
  if (hasUnsafeStyleValue(v)) continue;
106
106
  value = v;
@@ -39,13 +39,14 @@ const some = (...middleware) => {
39
39
  return next();
40
40
  };
41
41
  let lastError;
42
+ let response;
42
43
  for (const handler of middleware) try {
43
44
  const result = await handler(c, wrappedNext);
44
45
  if (result === true && !c.finalized) await wrappedNext();
45
46
  else if (result === false) {
46
47
  lastError = /* @__PURE__ */ new Error("No successful middleware found");
47
48
  continue;
48
- }
49
+ } else if (result && result !== true) response = result;
49
50
  lastError = void 0;
50
51
  break;
51
52
  } catch (error) {
@@ -53,6 +54,7 @@ const some = (...middleware) => {
53
54
  if (isNextCalled) break;
54
55
  }
55
56
  if (lastError) throw lastError;
57
+ return response;
56
58
  };
57
59
  };
58
60
  /**
@@ -48,7 +48,7 @@ function initializeGenerator(generator) {
48
48
  * ```
49
49
  */
50
50
  const etag = (options) => {
51
- const retainedHeaders = options?.retainedHeaders ?? RETAINED_304_HEADERS;
51
+ const retainedHeaders = new Set((options?.retainedHeaders ?? RETAINED_304_HEADERS).map((header) => header.toLowerCase()));
52
52
  const weak = options?.weak ?? false;
53
53
  const generator = initializeGenerator(options?.generateDigest);
54
54
  return async function etag(c, next) {
@@ -69,7 +69,7 @@ const etag = (options) => {
69
69
  statusText: "Not Modified",
70
70
  headers: { ETag: etag }
71
71
  });
72
- for (const key of Array.from(c.res.headers.keys())) if (retainedHeaders.indexOf(key.toLowerCase()) === -1) c.res.headers.delete(key);
72
+ for (const key of Array.from(c.res.headers.keys())) if (!retainedHeaders.has(key.toLowerCase())) c.res.headers.delete(key);
73
73
  } else c.res.headers.set("ETag", etag);
74
74
  };
75
75
  };
@@ -22,6 +22,7 @@ const serveStatic = (options) => {
22
22
  let filename;
23
23
  if (options.path) filename = options.path;
24
24
  else try {
25
+ if (!options.allowPercentInPath && c.req.path.includes("%")) throw new Error();
25
26
  filename = tryDecodeURI(c.req.path);
26
27
  if (/(?:^|[\/\\])\.{1,2}(?:$|[\/\\])|[\/\\]{2,}|\\/.test(filename)) throw new Error();
27
28
  } catch {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "4.13.10",
3
+ "version": "4.13.12",
4
4
  "description": "Web framework built on Web Standards",
5
5
  "main": "dist/cjs/index.js",
6
6
  "type": "module",
@@ -693,7 +693,7 @@
693
693
  "rolldown": "^1.2.10",
694
694
  "typescript": "^6.0.3",
695
695
  "vite-plugin-fastly-js-compute": "^0.4.2",
696
- "vite-plus": "1.0.0-rc.1",
696
+ "vite-plus": "1.0.0",
697
697
  "vitest": "5.0.1",
698
698
  "wrangler": "4.107.0",
699
699
  "ws": "^8.21.0",
@@ -64,46 +64,47 @@ function plainValue(source, onError) {
64
64
  }
65
65
  if (badChar)
66
66
  onError(0, 'BAD_SCALAR_START', `Plain value cannot start with ${badChar}`);
67
- return foldLines(source);
67
+ return unfoldLines(source);
68
68
  }
69
69
  function singleQuotedValue(source, onError) {
70
70
  if (source[source.length - 1] !== "'" || source.length === 1)
71
71
  onError(source.length, 'MISSING_CHAR', "Missing closing 'quote");
72
- return foldLines(source.slice(1, -1)).replace(/''/g, "'");
72
+ return unfoldLines(source.slice(1, -1)).replace(/''/g, "'");
73
73
  }
74
- function foldLines(source) {
74
+ function unfoldLines(source) {
75
+ const line = /(.*?)\r?\n/sy;
76
+ let match = line.exec(source);
77
+ if (!match)
78
+ return source;
75
79
  /**
76
- * The negative lookbehind here and in the `re` RegExp is to
80
+ * The negative lookbehinds in these RegExps are to
77
81
  * prevent causing a polynomial search time in certain cases.
78
82
  *
79
- * The try-catch is for Safari, which doesn't support this yet:
83
+ * The try-catch is for Safari < 16.4 and other old browsers:
80
84
  * https://caniuse.com/js-regexp-lookbehind
81
85
  */
82
- let first, line;
86
+ let trimEnd, trimBoth;
83
87
  try {
84
- first = new RegExp('(.*?)(?<![ \t])[ \t]*\r?\n', 'sy');
85
- line = new RegExp('[ \t]*(.*?)(?:(?<![ \t])[ \t]*)?\r?\n', 'sy');
88
+ trimEnd = new RegExp('(?<![ \t])[ \t]+$');
89
+ trimBoth = new RegExp('^[ \t]+|(?<![ \t])[ \t]+$', 'g');
86
90
  }
87
91
  catch {
88
- first = /(.*?)[ \t]*\r?\n/sy;
89
- line = /[ \t]*(.*?)[ \t]*\r?\n/sy;
92
+ trimEnd = /[ \t]+$/;
93
+ trimBoth = /^[ \t]+|[ \t]+$/g;
90
94
  }
91
- let match = first.exec(source);
92
- if (!match)
93
- return source;
94
- let res = match[1];
95
+ let res = match[1].replace(trimEnd, '');
95
96
  let sep = ' ';
96
- let pos = first.lastIndex;
97
- line.lastIndex = pos;
97
+ let pos = line.lastIndex;
98
98
  while ((match = line.exec(source))) {
99
- if (match[1] === '') {
99
+ const lm = match[1].replace(trimBoth, '');
100
+ if (lm === '') {
100
101
  if (sep === '\n')
101
102
  res += sep;
102
103
  else
103
104
  sep = '\n';
104
105
  }
105
106
  else {
106
- res += sep + match[1];
107
+ res += sep + lm;
107
108
  sep = ' ';
108
109
  }
109
110
  pos = line.lastIndex;
@@ -43,38 +43,40 @@ class Alias extends NodeBase {
43
43
  if (node.anchor === this.source)
44
44
  found = node;
45
45
  }
46
+ if (found && ctx) {
47
+ const { anchors, doc, maxAliasCount } = ctx;
48
+ let data = anchors.get(found);
49
+ if (!data) {
50
+ // Resolve anchors for Node.prototype.toJS()
51
+ toJS(found, null, ctx);
52
+ data = anchors.get(found);
53
+ }
54
+ /* istanbul ignore if */
55
+ if (data?.res === undefined) {
56
+ const msg = 'This should not happen: Alias anchor was not resolved?';
57
+ throw new ReferenceError(msg);
58
+ }
59
+ if (maxAliasCount >= 0) {
60
+ data.count += 1;
61
+ if (data.aliasCount === 0)
62
+ data.aliasCount = getAliasCount(doc, found, anchors);
63
+ if (data.count * data.aliasCount > maxAliasCount) {
64
+ const msg = 'Excessive alias count indicates a resource exhaustion attack';
65
+ throw new ReferenceError(msg);
66
+ }
67
+ }
68
+ }
46
69
  return found;
47
70
  }
48
71
  toJSON(_arg, ctx) {
49
72
  if (!ctx)
50
73
  return { source: this.source };
51
- const { anchors, doc, maxAliasCount } = ctx;
52
- const source = this.resolve(doc, ctx);
74
+ const source = this.resolve(ctx.doc, ctx);
53
75
  if (!source) {
54
76
  const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
55
77
  throw new ReferenceError(msg);
56
78
  }
57
- let data = anchors.get(source);
58
- if (!data) {
59
- // Resolve anchors for Node.prototype.toJS()
60
- toJS(source, null, ctx);
61
- data = anchors.get(source);
62
- }
63
- /* istanbul ignore if */
64
- if (data?.res === undefined) {
65
- const msg = 'This should not happen: Alias anchor was not resolved?';
66
- throw new ReferenceError(msg);
67
- }
68
- if (maxAliasCount >= 0) {
69
- data.count += 1;
70
- if (data.aliasCount === 0)
71
- data.aliasCount = getAliasCount(doc, source, anchors);
72
- if (data.count * data.aliasCount > maxAliasCount) {
73
- const msg = 'Excessive alias count indicates a resource exhaustion attack';
74
- throw new ReferenceError(msg);
75
- }
76
- }
77
- return data.res;
79
+ return ctx.anchors.get(source).res;
78
80
  }
79
81
  toString(ctx, _onComment, _onChompKeep) {
80
82
  const src = `*${this.source}`;
@@ -66,46 +66,47 @@ function plainValue(source, onError) {
66
66
  }
67
67
  if (badChar)
68
68
  onError(0, 'BAD_SCALAR_START', `Plain value cannot start with ${badChar}`);
69
- return foldLines(source);
69
+ return unfoldLines(source);
70
70
  }
71
71
  function singleQuotedValue(source, onError) {
72
72
  if (source[source.length - 1] !== "'" || source.length === 1)
73
73
  onError(source.length, 'MISSING_CHAR', "Missing closing 'quote");
74
- return foldLines(source.slice(1, -1)).replace(/''/g, "'");
74
+ return unfoldLines(source.slice(1, -1)).replace(/''/g, "'");
75
75
  }
76
- function foldLines(source) {
76
+ function unfoldLines(source) {
77
+ const line = /(.*?)\r?\n/sy;
78
+ let match = line.exec(source);
79
+ if (!match)
80
+ return source;
77
81
  /**
78
- * The negative lookbehind here and in the `re` RegExp is to
82
+ * The negative lookbehinds in these RegExps are to
79
83
  * prevent causing a polynomial search time in certain cases.
80
84
  *
81
- * The try-catch is for Safari, which doesn't support this yet:
85
+ * The try-catch is for Safari < 16.4 and other old browsers:
82
86
  * https://caniuse.com/js-regexp-lookbehind
83
87
  */
84
- let first, line;
88
+ let trimEnd, trimBoth;
85
89
  try {
86
- first = new RegExp('(.*?)(?<![ \t])[ \t]*\r?\n', 'sy');
87
- line = new RegExp('[ \t]*(.*?)(?:(?<![ \t])[ \t]*)?\r?\n', 'sy');
90
+ trimEnd = new RegExp('(?<![ \t])[ \t]+$');
91
+ trimBoth = new RegExp('^[ \t]+|(?<![ \t])[ \t]+$', 'g');
88
92
  }
89
93
  catch {
90
- first = /(.*?)[ \t]*\r?\n/sy;
91
- line = /[ \t]*(.*?)[ \t]*\r?\n/sy;
94
+ trimEnd = /[ \t]+$/;
95
+ trimBoth = /^[ \t]+|[ \t]+$/g;
92
96
  }
93
- let match = first.exec(source);
94
- if (!match)
95
- return source;
96
- let res = match[1];
97
+ let res = match[1].replace(trimEnd, '');
97
98
  let sep = ' ';
98
- let pos = first.lastIndex;
99
- line.lastIndex = pos;
99
+ let pos = line.lastIndex;
100
100
  while ((match = line.exec(source))) {
101
- if (match[1] === '') {
101
+ const lm = match[1].replace(trimBoth, '');
102
+ if (lm === '') {
102
103
  if (sep === '\n')
103
104
  res += sep;
104
105
  else
105
106
  sep = '\n';
106
107
  }
107
108
  else {
108
- res += sep + match[1];
109
+ res += sep + lm;
109
110
  sep = ' ';
110
111
  }
111
112
  pos = line.lastIndex;