hono 4.11.10 → 4.12.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.
Files changed (47) hide show
  1. package/dist/adapter/aws-lambda/conninfo.js +23 -0
  2. package/dist/adapter/aws-lambda/index.js +2 -0
  3. package/dist/adapter/cloudflare-pages/conninfo.js +9 -0
  4. package/dist/adapter/cloudflare-pages/index.js +2 -0
  5. package/dist/adapter/netlify/conninfo.js +9 -0
  6. package/dist/adapter/netlify/mod.js +2 -0
  7. package/dist/cjs/adapter/aws-lambda/conninfo.js +46 -0
  8. package/dist/cjs/adapter/aws-lambda/index.js +3 -0
  9. package/dist/cjs/adapter/cloudflare-pages/conninfo.js +32 -0
  10. package/dist/cjs/adapter/cloudflare-pages/index.js +3 -0
  11. package/dist/cjs/adapter/netlify/conninfo.js +32 -0
  12. package/dist/cjs/adapter/netlify/mod.js +3 -0
  13. package/dist/cjs/client/client.js +8 -2
  14. package/dist/cjs/context.js +11 -7
  15. package/dist/cjs/helper/ssg/index.js +5 -0
  16. package/dist/cjs/helper/ssg/plugins.js +71 -0
  17. package/dist/cjs/helper/ssg/ssg.js +2 -11
  18. package/dist/cjs/jsx/dom/render.js +3 -1
  19. package/dist/cjs/middleware/basic-auth/index.js +6 -0
  20. package/dist/cjs/middleware/language/language.js +13 -2
  21. package/dist/cjs/middleware/trailing-slash/index.js +18 -4
  22. package/dist/cjs/router/trie-router/node.js +33 -16
  23. package/dist/client/client.js +8 -2
  24. package/dist/context.js +11 -7
  25. package/dist/helper/ssg/index.js +3 -0
  26. package/dist/helper/ssg/plugins.js +47 -0
  27. package/dist/helper/ssg/ssg.js +2 -10
  28. package/dist/jsx/dom/render.js +3 -1
  29. package/dist/middleware/basic-auth/index.js +6 -0
  30. package/dist/middleware/language/language.js +13 -2
  31. package/dist/middleware/trailing-slash/index.js +18 -4
  32. package/dist/router/trie-router/node.js +33 -16
  33. package/dist/types/adapter/aws-lambda/conninfo.d.ts +27 -0
  34. package/dist/types/adapter/aws-lambda/index.d.ts +1 -0
  35. package/dist/types/adapter/cloudflare-pages/conninfo.d.ts +21 -0
  36. package/dist/types/adapter/cloudflare-pages/index.d.ts +1 -0
  37. package/dist/types/adapter/netlify/conninfo.d.ts +21 -0
  38. package/dist/types/adapter/netlify/mod.d.ts +1 -0
  39. package/dist/types/client/index.d.ts +1 -1
  40. package/dist/types/client/types.d.ts +39 -1
  41. package/dist/types/context.d.ts +4 -0
  42. package/dist/types/helper/ssg/index.d.ts +1 -0
  43. package/dist/types/helper/ssg/plugins.d.ts +27 -0
  44. package/dist/types/helper/ssg/ssg.d.ts +0 -8
  45. package/dist/types/middleware/basic-auth/index.d.ts +19 -0
  46. package/dist/types/middleware/trailing-slash/index.d.ts +43 -2
  47. package/package.json +1 -1
@@ -0,0 +1,23 @@
1
+ // src/adapter/aws-lambda/conninfo.ts
2
+ var getConnInfo = (c) => {
3
+ const requestContext = c.env.requestContext;
4
+ let address;
5
+ if ("identity" in requestContext && requestContext.identity?.sourceIp) {
6
+ address = requestContext.identity.sourceIp;
7
+ } else if ("http" in requestContext && requestContext.http?.sourceIp) {
8
+ address = requestContext.http.sourceIp;
9
+ } else {
10
+ const xff = c.req.header("x-forwarded-for");
11
+ if (xff) {
12
+ address = xff.split(",")[0].trim();
13
+ }
14
+ }
15
+ return {
16
+ remote: {
17
+ address
18
+ }
19
+ };
20
+ };
21
+ export {
22
+ getConnInfo
23
+ };
@@ -1,7 +1,9 @@
1
1
  // src/adapter/aws-lambda/index.ts
2
2
  import { handle, streamHandle, defaultIsContentTypeBinary } from "./handler.js";
3
+ import { getConnInfo } from "./conninfo.js";
3
4
  export {
4
5
  defaultIsContentTypeBinary,
6
+ getConnInfo,
5
7
  handle,
6
8
  streamHandle
7
9
  };
@@ -0,0 +1,9 @@
1
+ // src/adapter/cloudflare-pages/conninfo.ts
2
+ var getConnInfo = (c) => ({
3
+ remote: {
4
+ address: c.req.header("cf-connecting-ip")
5
+ }
6
+ });
7
+ export {
8
+ getConnInfo
9
+ };
@@ -1,6 +1,8 @@
1
1
  // src/adapter/cloudflare-pages/index.ts
2
2
  import { handle, handleMiddleware, serveStatic } from "./handler.js";
3
+ import { getConnInfo } from "./conninfo.js";
3
4
  export {
5
+ getConnInfo,
4
6
  handle,
5
7
  handleMiddleware,
6
8
  serveStatic
@@ -0,0 +1,9 @@
1
+ // src/adapter/netlify/conninfo.ts
2
+ var getConnInfo = (c) => ({
3
+ remote: {
4
+ address: c.env.context?.ip
5
+ }
6
+ });
7
+ export {
8
+ getConnInfo
9
+ };
@@ -1,5 +1,7 @@
1
1
  // src/adapter/netlify/mod.ts
2
2
  import { handle } from "./handler.js";
3
+ import { getConnInfo } from "./conninfo.js";
3
4
  export {
5
+ getConnInfo,
4
6
  handle
5
7
  };
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var conninfo_exports = {};
20
+ __export(conninfo_exports, {
21
+ getConnInfo: () => getConnInfo
22
+ });
23
+ module.exports = __toCommonJS(conninfo_exports);
24
+ const getConnInfo = (c) => {
25
+ const requestContext = c.env.requestContext;
26
+ let address;
27
+ if ("identity" in requestContext && requestContext.identity?.sourceIp) {
28
+ address = requestContext.identity.sourceIp;
29
+ } else if ("http" in requestContext && requestContext.http?.sourceIp) {
30
+ address = requestContext.http.sourceIp;
31
+ } else {
32
+ const xff = c.req.header("x-forwarded-for");
33
+ if (xff) {
34
+ address = xff.split(",")[0].trim();
35
+ }
36
+ }
37
+ return {
38
+ remote: {
39
+ address
40
+ }
41
+ };
42
+ };
43
+ // Annotate the CommonJS export names for ESM import in node:
44
+ 0 && (module.exports = {
45
+ getConnInfo
46
+ });
@@ -19,14 +19,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var aws_lambda_exports = {};
20
20
  __export(aws_lambda_exports, {
21
21
  defaultIsContentTypeBinary: () => import_handler.defaultIsContentTypeBinary,
22
+ getConnInfo: () => import_conninfo.getConnInfo,
22
23
  handle: () => import_handler.handle,
23
24
  streamHandle: () => import_handler.streamHandle
24
25
  });
25
26
  module.exports = __toCommonJS(aws_lambda_exports);
26
27
  var import_handler = require("./handler");
28
+ var import_conninfo = require("./conninfo");
27
29
  // Annotate the CommonJS export names for ESM import in node:
28
30
  0 && (module.exports = {
29
31
  defaultIsContentTypeBinary,
32
+ getConnInfo,
30
33
  handle,
31
34
  streamHandle
32
35
  });
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var conninfo_exports = {};
20
+ __export(conninfo_exports, {
21
+ getConnInfo: () => getConnInfo
22
+ });
23
+ module.exports = __toCommonJS(conninfo_exports);
24
+ const getConnInfo = (c) => ({
25
+ remote: {
26
+ address: c.req.header("cf-connecting-ip")
27
+ }
28
+ });
29
+ // Annotate the CommonJS export names for ESM import in node:
30
+ 0 && (module.exports = {
31
+ getConnInfo
32
+ });
@@ -18,14 +18,17 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var cloudflare_pages_exports = {};
20
20
  __export(cloudflare_pages_exports, {
21
+ getConnInfo: () => import_conninfo.getConnInfo,
21
22
  handle: () => import_handler.handle,
22
23
  handleMiddleware: () => import_handler.handleMiddleware,
23
24
  serveStatic: () => import_handler.serveStatic
24
25
  });
25
26
  module.exports = __toCommonJS(cloudflare_pages_exports);
26
27
  var import_handler = require("./handler");
28
+ var import_conninfo = require("./conninfo");
27
29
  // Annotate the CommonJS export names for ESM import in node:
28
30
  0 && (module.exports = {
31
+ getConnInfo,
29
32
  handle,
30
33
  handleMiddleware,
31
34
  serveStatic
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var conninfo_exports = {};
20
+ __export(conninfo_exports, {
21
+ getConnInfo: () => getConnInfo
22
+ });
23
+ module.exports = __toCommonJS(conninfo_exports);
24
+ const getConnInfo = (c) => ({
25
+ remote: {
26
+ address: c.env.context?.ip
27
+ }
28
+ });
29
+ // Annotate the CommonJS export names for ESM import in node:
30
+ 0 && (module.exports = {
31
+ getConnInfo
32
+ });
@@ -18,11 +18,14 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var mod_exports = {};
20
20
  __export(mod_exports, {
21
+ getConnInfo: () => import_conninfo.getConnInfo,
21
22
  handle: () => import_handler.handle
22
23
  });
23
24
  module.exports = __toCommonJS(mod_exports);
24
25
  var import_handler = require("./handler");
26
+ var import_conninfo = require("./conninfo");
25
27
  // Annotate the CommonJS export names for ESM import in node:
26
28
  0 && (module.exports = {
29
+ getConnInfo,
27
30
  handle
28
31
  });
@@ -62,6 +62,9 @@ class ClientRequestImpl {
62
62
  if (args.form) {
63
63
  const form = new FormData();
64
64
  for (const [k, v] of Object.entries(args.form)) {
65
+ if (v === void 0) {
66
+ continue;
67
+ }
65
68
  if (Array.isArray(v)) {
66
69
  for (const v2 of v) {
67
70
  form.append(k, v2);
@@ -137,7 +140,7 @@ const hc = (baseUrl, options) => createProxy(function proxyCallback(opts) {
137
140
  }
138
141
  const path = parts.join("/");
139
142
  const url = (0, import_utils.mergePath)(baseUrl, path);
140
- if (method === "url") {
143
+ if (method === "url" || method === "path") {
141
144
  let result = url;
142
145
  if (opts.args[0]) {
143
146
  if (opts.args[0].param) {
@@ -148,7 +151,10 @@ const hc = (baseUrl, options) => createProxy(function proxyCallback(opts) {
148
151
  }
149
152
  }
150
153
  result = (0, import_utils.removeIndexString)(result);
151
- return new URL(result);
154
+ if (method === "url") {
155
+ return new URL(result);
156
+ }
157
+ return result.slice(baseUrl.replace(/\/+$/, "").length).replace(/^\/?/, "/");
152
158
  }
153
159
  if (method === "ws") {
154
160
  const webSocketUrl = (0, import_utils.replaceUrlProtocol)(
@@ -31,6 +31,7 @@ const setDefaultContentType = (contentType, headers) => {
31
31
  ...headers
32
32
  };
33
33
  };
34
+ const createResponseInstance = (body, init) => new Response(body, init);
34
35
  class Context {
35
36
  #rawRequest;
36
37
  #req;
@@ -129,7 +130,7 @@ class Context {
129
130
  * The Response object for the current request.
130
131
  */
131
132
  get res() {
132
- return this.#res ||= new Response(null, {
133
+ return this.#res ||= createResponseInstance(null, {
133
134
  headers: this.#preparedHeaders ??= new Headers()
134
135
  });
135
136
  }
@@ -140,7 +141,7 @@ class Context {
140
141
  */
141
142
  set res(_res) {
142
143
  if (this.#res && _res) {
143
- _res = new Response(_res.body, _res);
144
+ _res = createResponseInstance(_res.body, _res);
144
145
  for (const [k, v] of this.#res.headers.entries()) {
145
146
  if (k === "content-type") {
146
147
  continue;
@@ -230,7 +231,7 @@ class Context {
230
231
  */
231
232
  header = (name, value, options) => {
232
233
  if (this.finalized) {
233
- this.#res = new Response(this.#res.body, this.#res);
234
+ this.#res = createResponseInstance(this.#res.body, this.#res);
234
235
  }
235
236
  const headers = this.#res ? this.#res.headers : this.#preparedHeaders ??= new Headers();
236
237
  if (value === void 0) {
@@ -319,7 +320,7 @@ class Context {
319
320
  }
320
321
  }
321
322
  const status = typeof arg === "number" ? arg : arg?.status ?? this.#status;
322
- return new Response(data, { status, headers: responseHeaders });
323
+ return createResponseInstance(data, { status, headers: responseHeaders });
323
324
  }
324
325
  newResponse = (...args) => this.#newResponse(...args);
325
326
  /**
@@ -344,6 +345,9 @@ class Context {
344
345
  * ```
345
346
  */
346
347
  body = (data, arg, headers) => this.#newResponse(data, arg, headers);
348
+ #useFastPath() {
349
+ return !this.#preparedHeaders && !this.#status && !this.finalized;
350
+ }
347
351
  /**
348
352
  * `.text()` can render text as `Content-Type:text/plain`.
349
353
  *
@@ -357,7 +361,7 @@ class Context {
357
361
  * ```
358
362
  */
359
363
  text = (text, arg, headers) => {
360
- return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized ? new Response(text) : this.#newResponse(
364
+ return this.#useFastPath() && !arg && !headers ? createResponseInstance(text) : this.#newResponse(
361
365
  text,
362
366
  arg,
363
367
  setDefaultContentType(TEXT_PLAIN, headers)
@@ -376,7 +380,7 @@ class Context {
376
380
  * ```
377
381
  */
378
382
  json = (object, arg, headers) => {
379
- return this.#newResponse(
383
+ return this.#useFastPath() && !arg && !headers ? Response.json(object) : this.#newResponse(
380
384
  JSON.stringify(object),
381
385
  arg,
382
386
  setDefaultContentType("application/json", headers)
@@ -424,7 +428,7 @@ class Context {
424
428
  * ```
425
429
  */
426
430
  notFound = () => {
427
- this.#notFoundHandler ??= () => new Response();
431
+ this.#notFoundHandler ??= () => createResponseInstance();
428
432
  return this.#notFoundHandler(this);
429
433
  };
430
434
  }
@@ -20,20 +20,25 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  var ssg_exports = {};
21
21
  __export(ssg_exports, {
22
22
  X_HONO_DISABLE_SSG_HEADER_KEY: () => import_middleware.X_HONO_DISABLE_SSG_HEADER_KEY,
23
+ defaultPlugin: () => import_plugins.defaultPlugin,
23
24
  disableSSG: () => import_middleware.disableSSG,
24
25
  isSSGContext: () => import_middleware.isSSGContext,
25
26
  onlySSG: () => import_middleware.onlySSG,
27
+ redirectPlugin: () => import_plugins.redirectPlugin,
26
28
  ssgParams: () => import_middleware.ssgParams
27
29
  });
28
30
  module.exports = __toCommonJS(ssg_exports);
29
31
  __reExport(ssg_exports, require("./ssg"), module.exports);
30
32
  var import_middleware = require("./middleware");
33
+ var import_plugins = require("./plugins");
31
34
  // Annotate the CommonJS export names for ESM import in node:
32
35
  0 && (module.exports = {
33
36
  X_HONO_DISABLE_SSG_HEADER_KEY,
37
+ defaultPlugin,
34
38
  disableSSG,
35
39
  isSSGContext,
36
40
  onlySSG,
41
+ redirectPlugin,
37
42
  ssgParams,
38
43
  ...require("./ssg")
39
44
  });
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var plugins_exports = {};
20
+ __export(plugins_exports, {
21
+ defaultPlugin: () => defaultPlugin,
22
+ redirectPlugin: () => redirectPlugin
23
+ });
24
+ module.exports = __toCommonJS(plugins_exports);
25
+ var import_html = require("../html");
26
+ const defaultPlugin = () => {
27
+ return {
28
+ afterResponseHook: (res) => {
29
+ if (res.status !== 200) {
30
+ return false;
31
+ }
32
+ return res;
33
+ }
34
+ };
35
+ };
36
+ const REDIRECT_STATUS_CODES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
37
+ const generateRedirectHtml = (location) => {
38
+ const content = import_html.html`<!DOCTYPE html>
39
+ <title>Redirecting to: ${location}</title>
40
+ <meta http-equiv="refresh" content="0;url=${location}" />
41
+ <meta name="robots" content="noindex" />
42
+ <link rel="canonical" href="${location}" />
43
+ <body>
44
+ <a href="${location}">Redirecting to <code>${location}</code></a>
45
+ </body>
46
+ `;
47
+ return content.toString().replace(/\n/g, "");
48
+ };
49
+ const redirectPlugin = () => {
50
+ return {
51
+ afterResponseHook: (res) => {
52
+ if (REDIRECT_STATUS_CODES.has(res.status)) {
53
+ const location = res.headers.get("Location");
54
+ if (!location) {
55
+ return false;
56
+ }
57
+ const htmlBody = generateRedirectHtml(location);
58
+ return new Response(htmlBody, {
59
+ status: 200,
60
+ headers: { "Content-Type": "text/html; charset=utf-8" }
61
+ });
62
+ }
63
+ return res;
64
+ }
65
+ };
66
+ };
67
+ // Annotate the CommonJS export names for ESM import in node:
68
+ 0 && (module.exports = {
69
+ defaultPlugin,
70
+ redirectPlugin
71
+ });
@@ -23,7 +23,6 @@ __export(ssg_exports, {
23
23
  combineAfterResponseHooks: () => combineAfterResponseHooks,
24
24
  combineBeforeRequestHooks: () => combineBeforeRequestHooks,
25
25
  defaultExtensionMap: () => defaultExtensionMap,
26
- defaultPlugin: () => defaultPlugin,
27
26
  fetchRoutesContent: () => fetchRoutesContent,
28
27
  saveContentToFile: () => saveContentToFile,
29
28
  toSSG: () => toSSG
@@ -33,6 +32,7 @@ var import_utils = require("../../client/utils");
33
32
  var import_concurrent = require("../../utils/concurrent");
34
33
  var import_mime = require("../../utils/mime");
35
34
  var import_middleware = require("./middleware");
35
+ var import_plugins = require("./plugins");
36
36
  var import_utils2 = require("./utils");
37
37
  const DEFAULT_CONCURRENCY = 2;
38
38
  const DEFAULT_CONTENT_TYPE = "text/plain";
@@ -214,19 +214,11 @@ const saveContentToFile = async (data, fsModule, outDir, extensionMap) => {
214
214
  }
215
215
  return filePath;
216
216
  };
217
- const defaultPlugin = {
218
- afterResponseHook: (res) => {
219
- if (res.status !== 200) {
220
- return false;
221
- }
222
- return res;
223
- }
224
- };
225
217
  const toSSG = async (app, fs, options) => {
226
218
  let result;
227
219
  const getInfoPromises = [];
228
220
  const savePromises = [];
229
- const plugins = options?.plugins || [defaultPlugin];
221
+ const plugins = options?.plugins || [(0, import_plugins.defaultPlugin)()];
230
222
  const beforeRequestHooks = [];
231
223
  const afterResponseHooks = [];
232
224
  const afterGenerateHooks = [];
@@ -319,7 +311,6 @@ const toSSG = async (app, fs, options) => {
319
311
  combineAfterResponseHooks,
320
312
  combineBeforeRequestHooks,
321
313
  defaultExtensionMap,
322
- defaultPlugin,
323
314
  fetchRoutesContent,
324
315
  saveContentToFile,
325
316
  toSSG
@@ -350,7 +350,9 @@ const build = (context, node, children) => {
350
350
  let prevNode;
351
351
  for (let i = 0; i < children.length; i++) {
352
352
  if (Array.isArray(children[i])) {
353
- children.splice(i, 1, ...children[i].flat());
353
+ children.splice(i, 1, ...children[i].flat(Infinity));
354
+ i--;
355
+ continue;
354
356
  }
355
357
  let child = buildNode(children[i]);
356
358
  if (child) {
@@ -46,6 +46,9 @@ const basicAuth = (options, ...users) => {
46
46
  if (requestUser) {
47
47
  if (verifyUserInOptions) {
48
48
  if (await options.verifyUser(requestUser.username, requestUser.password, ctx)) {
49
+ if (options.onAuthSuccess) {
50
+ await options.onAuthSuccess(ctx, requestUser.username);
51
+ }
49
52
  await next();
50
53
  return;
51
54
  }
@@ -56,6 +59,9 @@ const basicAuth = (options, ...users) => {
56
59
  (0, import_buffer.timingSafeEqual)(user.password, requestUser.password, options.hashFunction)
57
60
  ]);
58
61
  if (usernameEqual && passwordEqual) {
62
+ if (options.onAuthSuccess) {
63
+ await options.onAuthSuccess(ctx, requestUser.username);
64
+ }
59
65
  await next();
60
66
  return;
61
67
  }
@@ -66,8 +66,19 @@ const normalizeLanguage = (lang, options) => {
66
66
  const compSupported = options.supportedLanguages.map(
67
67
  (l) => options.ignoreCase ? l.toLowerCase() : l
68
68
  );
69
- const matchedLang = compSupported.find((l) => l === compLang);
70
- return matchedLang ? options.supportedLanguages[compSupported.indexOf(matchedLang)] : void 0;
69
+ const exactIndex = compSupported.indexOf(compLang);
70
+ if (exactIndex !== -1) {
71
+ return options.supportedLanguages[exactIndex];
72
+ }
73
+ const parts = compLang.split("-");
74
+ for (let i = parts.length - 1; i > 0; i--) {
75
+ const candidate = parts.slice(0, i).join("-");
76
+ const prefixIndex = compSupported.indexOf(candidate);
77
+ if (prefixIndex !== -1) {
78
+ return options.supportedLanguages[prefixIndex];
79
+ }
80
+ }
81
+ return void 0;
71
82
  } catch {
72
83
  return void 0;
73
84
  }
@@ -22,20 +22,34 @@ __export(trailing_slash_exports, {
22
22
  trimTrailingSlash: () => trimTrailingSlash
23
23
  });
24
24
  module.exports = __toCommonJS(trailing_slash_exports);
25
- const trimTrailingSlash = () => {
25
+ const trimTrailingSlash = (options) => {
26
26
  return async function trimTrailingSlash2(c, next) {
27
+ if (options?.alwaysRedirect) {
28
+ if ((c.req.method === "GET" || c.req.method === "HEAD") && c.req.path !== "/" && c.req.path.at(-1) === "/") {
29
+ const url = new URL(c.req.url);
30
+ url.pathname = url.pathname.substring(0, url.pathname.length - 1);
31
+ return c.redirect(url.toString(), 301);
32
+ }
33
+ }
27
34
  await next();
28
- if (c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path !== "/" && c.req.path.at(-1) === "/") {
35
+ if (!options?.alwaysRedirect && c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path !== "/" && c.req.path.at(-1) === "/") {
29
36
  const url = new URL(c.req.url);
30
37
  url.pathname = url.pathname.substring(0, url.pathname.length - 1);
31
38
  c.res = c.redirect(url.toString(), 301);
32
39
  }
33
40
  };
34
41
  };
35
- const appendTrailingSlash = () => {
42
+ const appendTrailingSlash = (options) => {
36
43
  return async function appendTrailingSlash2(c, next) {
44
+ if (options?.alwaysRedirect) {
45
+ if ((c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/") {
46
+ const url = new URL(c.req.url);
47
+ url.pathname += "/";
48
+ return c.redirect(url.toString(), 301);
49
+ }
50
+ }
37
51
  await next();
38
- if (c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/") {
52
+ if (!options?.alwaysRedirect && c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/") {
39
53
  const url = new URL(c.req.url);
40
54
  url.pathname += "/";
41
55
  c.res = c.redirect(url.toString(), 301);