Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

hono

Package Overview
Dependencies
Maintainers
1
Versions
411
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hono - npm Package Compare versions

Comparing version
4.11.10
to
4.12.0
+23
dist/adapter/aws-lambda/conninfo.js
// src/adapter/aws-lambda/conninfo.ts
var getConnInfo = (c) => {
const requestContext = c.env.requestContext;
let address;
if ("identity" in requestContext && requestContext.identity?.sourceIp) {
address = requestContext.identity.sourceIp;
} else if ("http" in requestContext && requestContext.http?.sourceIp) {
address = requestContext.http.sourceIp;
} else {
const xff = c.req.header("x-forwarded-for");
if (xff) {
address = xff.split(",")[0].trim();
}
}
return {
remote: {
address
}
};
};
export {
getConnInfo
};
// src/adapter/cloudflare-pages/conninfo.ts
var getConnInfo = (c) => ({
remote: {
address: c.req.header("cf-connecting-ip")
}
});
export {
getConnInfo
};
// src/adapter/netlify/conninfo.ts
var getConnInfo = (c) => ({
remote: {
address: c.env.context?.ip
}
});
export {
getConnInfo
};
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var conninfo_exports = {};
__export(conninfo_exports, {
getConnInfo: () => getConnInfo
});
module.exports = __toCommonJS(conninfo_exports);
const getConnInfo = (c) => {
const requestContext = c.env.requestContext;
let address;
if ("identity" in requestContext && requestContext.identity?.sourceIp) {
address = requestContext.identity.sourceIp;
} else if ("http" in requestContext && requestContext.http?.sourceIp) {
address = requestContext.http.sourceIp;
} else {
const xff = c.req.header("x-forwarded-for");
if (xff) {
address = xff.split(",")[0].trim();
}
}
return {
remote: {
address
}
};
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
getConnInfo
});
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var conninfo_exports = {};
__export(conninfo_exports, {
getConnInfo: () => getConnInfo
});
module.exports = __toCommonJS(conninfo_exports);
const getConnInfo = (c) => ({
remote: {
address: c.req.header("cf-connecting-ip")
}
});
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
getConnInfo
});
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var conninfo_exports = {};
__export(conninfo_exports, {
getConnInfo: () => getConnInfo
});
module.exports = __toCommonJS(conninfo_exports);
const getConnInfo = (c) => ({
remote: {
address: c.env.context?.ip
}
});
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
getConnInfo
});
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var plugins_exports = {};
__export(plugins_exports, {
defaultPlugin: () => defaultPlugin,
redirectPlugin: () => redirectPlugin
});
module.exports = __toCommonJS(plugins_exports);
var import_html = require("../html");
const defaultPlugin = () => {
return {
afterResponseHook: (res) => {
if (res.status !== 200) {
return false;
}
return res;
}
};
};
const REDIRECT_STATUS_CODES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
const generateRedirectHtml = (location) => {
const content = import_html.html`<!DOCTYPE html>
<title>Redirecting to: ${location}</title>
<meta http-equiv="refresh" content="0;url=${location}" />
<meta name="robots" content="noindex" />
<link rel="canonical" href="${location}" />
<body>
<a href="${location}">Redirecting to <code>${location}</code></a>
</body>
`;
return content.toString().replace(/\n/g, "");
};
const redirectPlugin = () => {
return {
afterResponseHook: (res) => {
if (REDIRECT_STATUS_CODES.has(res.status)) {
const location = res.headers.get("Location");
if (!location) {
return false;
}
const htmlBody = generateRedirectHtml(location);
return new Response(htmlBody, {
status: 200,
headers: { "Content-Type": "text/html; charset=utf-8" }
});
}
return res;
}
};
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
defaultPlugin,
redirectPlugin
});
// src/helper/ssg/plugins.ts
import { html } from "../html/index.js";
var defaultPlugin = () => {
return {
afterResponseHook: (res) => {
if (res.status !== 200) {
return false;
}
return res;
}
};
};
var REDIRECT_STATUS_CODES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
var generateRedirectHtml = (location) => {
const content = html`<!DOCTYPE html>
<title>Redirecting to: ${location}</title>
<meta http-equiv="refresh" content="0;url=${location}" />
<meta name="robots" content="noindex" />
<link rel="canonical" href="${location}" />
<body>
<a href="${location}">Redirecting to <code>${location}</code></a>
</body>
`;
return content.toString().replace(/\n/g, "");
};
var redirectPlugin = () => {
return {
afterResponseHook: (res) => {
if (REDIRECT_STATUS_CODES.has(res.status)) {
const location = res.headers.get("Location");
if (!location) {
return false;
}
const htmlBody = generateRedirectHtml(location);
return new Response(htmlBody, {
status: 200,
headers: { "Content-Type": "text/html; charset=utf-8" }
});
}
return res;
}
};
};
export {
defaultPlugin,
redirectPlugin
};
import type { GetConnInfo } from '../../helper/conninfo';
/**
* Get connection information from AWS Lambda
*
* Extracts client IP from various Lambda event sources:
* - API Gateway v1 (REST API): requestContext.identity.sourceIp
* - API Gateway v2 (HTTP API/Function URLs): requestContext.http.sourceIp
* - ALB: Falls back to x-forwarded-for header
*
* @param c - Context
* @returns Connection information including remote address
* @example
* ```ts
* import { Hono } from 'hono'
* import { handle, getConnInfo } from 'hono/aws-lambda'
*
* const app = new Hono()
*
* app.get('/', (c) => {
* const info = getConnInfo(c)
* return c.text(`Your IP: ${info.remote.address}`)
* })
*
* export const handler = handle(app)
* ```
*/
export declare const getConnInfo: GetConnInfo;
import type { GetConnInfo } from '../../helper/conninfo';
/**
* Get connection information from Cloudflare Pages
* @param c - Context
* @returns Connection information including remote address
* @example
* ```ts
* import { Hono } from 'hono'
* import { handle, getConnInfo } from 'hono/cloudflare-pages'
*
* const app = new Hono()
*
* app.get('/', (c) => {
* const info = getConnInfo(c)
* return c.text(`Your IP: ${info.remote.address}`)
* })
*
* export const onRequest = handle(app)
* ```
*/
export declare const getConnInfo: GetConnInfo;
import type { GetConnInfo } from '../../helper/conninfo';
/**
* Get connection information from Netlify
* @param c - Context
* @returns Connection information including remote address
* @example
* ```ts
* import { Hono } from 'hono'
* import { handle, getConnInfo } from 'hono/netlify'
*
* const app = new Hono()
*
* app.get('/', (c) => {
* const info = getConnInfo(c)
* return c.text(`Your IP: ${info.remote.address}`)
* })
*
* export default handle(app)
* ```
*/
export declare const getConnInfo: GetConnInfo;
import type { SSGPlugin } from './ssg';
/**
* The default plugin that defines the recommended behavior.
*
* @experimental
* `defaultPlugin` is an experimental feature.
* The API might be changed.
*/
export declare const defaultPlugin: () => SSGPlugin;
/**
* The redirect plugin that generates HTML redirect pages for HTTP redirect responses for status codes 301, 302, 303, 307 and 308.
*
* When used with `defaultPlugin`, place `redirectPlugin` before it, because `defaultPlugin` skips non-200 responses.
*
* ```ts
* // ✅ Will work as expected
* toSSG(app, fs, { plugins: [redirectPlugin(), defaultPlugin()] })
*
* // ❌ Will not work as expected
* toSSG(app, fs, { plugins: [defaultPlugin(), redirectPlugin()] })
* ```
*
* @experimental
* `redirectPlugin` is an experimental feature.
* The API might be changed.
*/
export declare const redirectPlugin: () => SSGPlugin;
+2
-0
// src/adapter/aws-lambda/index.ts
import { handle, streamHandle, defaultIsContentTypeBinary } from "./handler.js";
import { getConnInfo } from "./conninfo.js";
export {
defaultIsContentTypeBinary,
getConnInfo,
handle,
streamHandle
};
// src/adapter/cloudflare-pages/index.ts
import { handle, handleMiddleware, serveStatic } from "./handler.js";
import { getConnInfo } from "./conninfo.js";
export {
getConnInfo,
handle,

@@ -5,0 +7,0 @@ handleMiddleware,

// src/adapter/netlify/mod.ts
import { handle } from "./handler.js";
import { getConnInfo } from "./conninfo.js";
export {
getConnInfo,
handle
};

@@ -22,2 +22,3 @@ "use strict";

defaultIsContentTypeBinary: () => import_handler.defaultIsContentTypeBinary,
getConnInfo: () => import_conninfo.getConnInfo,
handle: () => import_handler.handle,

@@ -28,7 +29,9 @@ streamHandle: () => import_handler.streamHandle

var import_handler = require("./handler");
var import_conninfo = require("./conninfo");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
defaultIsContentTypeBinary,
getConnInfo,
handle,
streamHandle
});

@@ -21,2 +21,3 @@ "use strict";

__export(cloudflare_pages_exports, {
getConnInfo: () => import_conninfo.getConnInfo,
handle: () => import_handler.handle,

@@ -28,4 +29,6 @@ handleMiddleware: () => import_handler.handleMiddleware,

var import_handler = require("./handler");
var import_conninfo = require("./conninfo");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
getConnInfo,
handle,

@@ -32,0 +35,0 @@ handleMiddleware,

@@ -21,2 +21,3 @@ "use strict";

__export(mod_exports, {
getConnInfo: () => import_conninfo.getConnInfo,
handle: () => import_handler.handle

@@ -26,5 +27,7 @@ });

var import_handler = require("./handler");
var import_conninfo = require("./conninfo");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
getConnInfo,
handle
});
+8
-2

@@ -65,2 +65,5 @@ "use strict";

for (const [k, v] of Object.entries(args.form)) {
if (v === void 0) {
continue;
}
if (Array.isArray(v)) {

@@ -141,3 +144,3 @@ for (const v2 of v) {

const url = (0, import_utils.mergePath)(baseUrl, path);
if (method === "url") {
if (method === "url" || method === "path") {
let result = url;

@@ -153,3 +156,6 @@ if (opts.args[0]) {

result = (0, import_utils.removeIndexString)(result);
return new URL(result);
if (method === "url") {
return new URL(result);
}
return result.slice(baseUrl.replace(/\/+$/, "").length).replace(/^\/?/, "/");
}

@@ -156,0 +162,0 @@ if (method === "ws") {

@@ -34,2 +34,3 @@ "use strict";

};
const createResponseInstance = (body, init) => new Response(body, init);
class Context {

@@ -133,3 +134,3 @@ #rawRequest;

get res() {
return this.#res ||= new Response(null, {
return this.#res ||= createResponseInstance(null, {
headers: this.#preparedHeaders ??= new Headers()

@@ -145,3 +146,3 @@ });

if (this.#res && _res) {
_res = new Response(_res.body, _res);
_res = createResponseInstance(_res.body, _res);
for (const [k, v] of this.#res.headers.entries()) {

@@ -236,3 +237,3 @@ if (k === "content-type") {

if (this.finalized) {
this.#res = new Response(this.#res.body, this.#res);
this.#res = createResponseInstance(this.#res.body, this.#res);
}

@@ -326,3 +327,3 @@ const headers = this.#res ? this.#res.headers : this.#preparedHeaders ??= new Headers();

const status = typeof arg === "number" ? arg : arg?.status ?? this.#status;
return new Response(data, { status, headers: responseHeaders });
return createResponseInstance(data, { status, headers: responseHeaders });
}

@@ -352,2 +353,5 @@ newResponse = (...args) => this.#newResponse(...args);

body = (data, arg, headers) => this.#newResponse(data, arg, headers);
#useFastPath() {
return !this.#preparedHeaders && !this.#status && !this.finalized;
}
/**

@@ -366,3 +370,3 @@ * `.text()` can render text as `Content-Type:text/plain`.

text = (text, arg, headers) => {
return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized ? new Response(text) : this.#newResponse(
return this.#useFastPath() && !arg && !headers ? createResponseInstance(text) : this.#newResponse(
text,

@@ -386,3 +390,3 @@ arg,

json = (object, arg, headers) => {
return this.#newResponse(
return this.#useFastPath() && !arg && !headers ? Response.json(object) : this.#newResponse(
JSON.stringify(object),

@@ -435,3 +439,3 @@ arg,

notFound = () => {
this.#notFoundHandler ??= () => new Response();
this.#notFoundHandler ??= () => createResponseInstance();
return this.#notFoundHandler(this);

@@ -438,0 +442,0 @@ };

@@ -23,5 +23,7 @@ "use strict";

X_HONO_DISABLE_SSG_HEADER_KEY: () => import_middleware.X_HONO_DISABLE_SSG_HEADER_KEY,
defaultPlugin: () => import_plugins.defaultPlugin,
disableSSG: () => import_middleware.disableSSG,
isSSGContext: () => import_middleware.isSSGContext,
onlySSG: () => import_middleware.onlySSG,
redirectPlugin: () => import_plugins.redirectPlugin,
ssgParams: () => import_middleware.ssgParams

@@ -32,10 +34,13 @@ });

var import_middleware = require("./middleware");
var import_plugins = require("./plugins");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
X_HONO_DISABLE_SSG_HEADER_KEY,
defaultPlugin,
disableSSG,
isSSGContext,
onlySSG,
redirectPlugin,
ssgParams,
...require("./ssg")
});

@@ -26,3 +26,2 @@ "use strict";

defaultExtensionMap: () => defaultExtensionMap,
defaultPlugin: () => defaultPlugin,
fetchRoutesContent: () => fetchRoutesContent,

@@ -37,2 +36,3 @@ saveContentToFile: () => saveContentToFile,

var import_middleware = require("./middleware");
var import_plugins = require("./plugins");
var import_utils2 = require("./utils");

@@ -219,10 +219,2 @@ const DEFAULT_CONCURRENCY = 2;

};
const defaultPlugin = {
afterResponseHook: (res) => {
if (res.status !== 200) {
return false;
}
return res;
}
};
const toSSG = async (app, fs, options) => {

@@ -232,3 +224,3 @@ let result;

const savePromises = [];
const plugins = options?.plugins || [defaultPlugin];
const plugins = options?.plugins || [(0, import_plugins.defaultPlugin)()];
const beforeRequestHooks = [];

@@ -326,3 +318,2 @@ const afterResponseHooks = [];

defaultExtensionMap,
defaultPlugin,
fetchRoutesContent,

@@ -329,0 +320,0 @@ saveContentToFile,

@@ -353,3 +353,5 @@ "use strict";

if (Array.isArray(children[i])) {
children.splice(i, 1, ...children[i].flat());
children.splice(i, 1, ...children[i].flat(Infinity));
i--;
continue;
}

@@ -356,0 +358,0 @@ let child = buildNode(children[i]);

@@ -49,2 +49,5 @@ "use strict";

if (await options.verifyUser(requestUser.username, requestUser.password, ctx)) {
if (options.onAuthSuccess) {
await options.onAuthSuccess(ctx, requestUser.username);
}
await next();

@@ -60,2 +63,5 @@ return;

if (usernameEqual && passwordEqual) {
if (options.onAuthSuccess) {
await options.onAuthSuccess(ctx, requestUser.username);
}
await next();

@@ -62,0 +68,0 @@ return;

@@ -69,4 +69,15 @@ "use strict";

);
const matchedLang = compSupported.find((l) => l === compLang);
return matchedLang ? options.supportedLanguages[compSupported.indexOf(matchedLang)] : void 0;
const exactIndex = compSupported.indexOf(compLang);
if (exactIndex !== -1) {
return options.supportedLanguages[exactIndex];
}
const parts = compLang.split("-");
for (let i = parts.length - 1; i > 0; i--) {
const candidate = parts.slice(0, i).join("-");
const prefixIndex = compSupported.indexOf(candidate);
if (prefixIndex !== -1) {
return options.supportedLanguages[prefixIndex];
}
}
return void 0;
} catch {

@@ -73,0 +84,0 @@ return void 0;

@@ -25,6 +25,13 @@ "use strict";

module.exports = __toCommonJS(trailing_slash_exports);
const trimTrailingSlash = () => {
const trimTrailingSlash = (options) => {
return async function trimTrailingSlash2(c, next) {
if (options?.alwaysRedirect) {
if ((c.req.method === "GET" || c.req.method === "HEAD") && c.req.path !== "/" && c.req.path.at(-1) === "/") {
const url = new URL(c.req.url);
url.pathname = url.pathname.substring(0, url.pathname.length - 1);
return c.redirect(url.toString(), 301);
}
}
await next();
if (c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path !== "/" && c.req.path.at(-1) === "/") {
if (!options?.alwaysRedirect && c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path !== "/" && c.req.path.at(-1) === "/") {
const url = new URL(c.req.url);

@@ -36,6 +43,13 @@ url.pathname = url.pathname.substring(0, url.pathname.length - 1);

};
const appendTrailingSlash = () => {
const appendTrailingSlash = (options) => {
return async function appendTrailingSlash2(c, next) {
if (options?.alwaysRedirect) {
if ((c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/") {
const url = new URL(c.req.url);
url.pathname += "/";
return c.redirect(url.toString(), 301);
}
}
await next();
if (c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/") {
if (!options?.alwaysRedirect && c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/") {
const url = new URL(c.req.url);

@@ -42,0 +56,0 @@ url.pathname += "/";

@@ -27,2 +27,8 @@ "use strict";

const emptyParams = /* @__PURE__ */ Object.create(null);
const hasChildren = (children) => {
for (const _ in children) {
return true;
}
return false;
};
class Node {

@@ -77,4 +83,3 @@ #methods;

}
#getHandlerSets(node, method, nodeParams, params) {
const handlerSets = [];
#pushHandlerSets(handlerSets, node, method, nodeParams, params) {
for (let i = 0, len = node.#methods.length; i < len; i++) {

@@ -97,3 +102,2 @@ const m = node.#methods[i];

}
return handlerSets;
}

@@ -107,3 +111,5 @@ search(method, path) {

const curNodesQueue = [];
for (let i = 0, len = parts.length; i < len; i++) {
const len = parts.length;
let partOffsets = null;
for (let i = 0; i < len; i++) {
const part = parts[i];

@@ -119,7 +125,5 @@ const isLast = i === len - 1;

if (nextNode.#children["*"]) {
handlerSets.push(
...this.#getHandlerSets(nextNode.#children["*"], method, node.#params)
);
this.#pushHandlerSets(handlerSets, nextNode.#children["*"], method, node.#params);
}
handlerSets.push(...this.#getHandlerSets(nextNode, method, node.#params));
this.#pushHandlerSets(handlerSets, nextNode, method, node.#params);
} else {

@@ -135,3 +139,3 @@ tempNodes.push(nextNode);

if (astNode) {
handlerSets.push(...this.#getHandlerSets(astNode, method, node.#params));
this.#pushHandlerSets(handlerSets, astNode, method, node.#params);
astNode.#params = params;

@@ -147,9 +151,17 @@ tempNodes.push(astNode);

const child = node.#children[key];
const restPathString = parts.slice(i).join("/");
if (matcher instanceof RegExp) {
if (partOffsets === null) {
partOffsets = new Array(len);
let offset = path[0] === "/" ? 1 : 0;
for (let p = 0; p < len; p++) {
partOffsets[p] = offset;
offset += parts[p].length + 1;
}
}
const restPathString = path.substring(partOffsets[i]);
const m = matcher.exec(restPathString);
if (m) {
params[name] = m[0];
handlerSets.push(...this.#getHandlerSets(child, method, node.#params, params));
if (Object.keys(child.#children).length) {
this.#pushHandlerSets(handlerSets, child, method, node.#params, params);
if (hasChildren(child.#children)) {
child.#params = params;

@@ -166,6 +178,10 @@ const componentCount = m[0].match(/\//)?.length ?? 0;

if (isLast) {
handlerSets.push(...this.#getHandlerSets(child, method, params, node.#params));
this.#pushHandlerSets(handlerSets, child, method, params, node.#params);
if (child.#children["*"]) {
handlerSets.push(
...this.#getHandlerSets(child.#children["*"], method, params, node.#params)
this.#pushHandlerSets(
handlerSets,
child.#children["*"],
method,
params,
node.#params
);

@@ -180,3 +196,4 @@ }

}
curNodes = tempNodes.concat(curNodesQueue.shift() ?? []);
const shifted = curNodesQueue.shift();
curNodes = shifted ? tempNodes.concat(shifted) : tempNodes;
}

@@ -183,0 +200,0 @@ if (handlerSets.length > 1) {

@@ -50,2 +50,5 @@ // src/client/client.ts

for (const [k, v] of Object.entries(args.form)) {
if (v === void 0) {
continue;
}
if (Array.isArray(v)) {

@@ -126,3 +129,3 @@ for (const v2 of v) {

const url = mergePath(baseUrl, path);
if (method === "url") {
if (method === "url" || method === "path") {
let result = url;

@@ -138,3 +141,6 @@ if (opts.args[0]) {

result = removeIndexString(result);
return new URL(result);
if (method === "url") {
return new URL(result);
}
return result.slice(baseUrl.replace(/\/+$/, "").length).replace(/^\/?/, "/");
}

@@ -141,0 +147,0 @@ if (method === "ws") {

@@ -11,2 +11,3 @@ // src/context.ts

};
var createResponseInstance = (body, init) => new Response(body, init);
var Context = class {

@@ -110,3 +111,3 @@ #rawRequest;

get res() {
return this.#res ||= new Response(null, {
return this.#res ||= createResponseInstance(null, {
headers: this.#preparedHeaders ??= new Headers()

@@ -122,3 +123,3 @@ });

if (this.#res && _res) {
_res = new Response(_res.body, _res);
_res = createResponseInstance(_res.body, _res);
for (const [k, v] of this.#res.headers.entries()) {

@@ -213,3 +214,3 @@ if (k === "content-type") {

if (this.finalized) {
this.#res = new Response(this.#res.body, this.#res);
this.#res = createResponseInstance(this.#res.body, this.#res);
}

@@ -303,3 +304,3 @@ const headers = this.#res ? this.#res.headers : this.#preparedHeaders ??= new Headers();

const status = typeof arg === "number" ? arg : arg?.status ?? this.#status;
return new Response(data, { status, headers: responseHeaders });
return createResponseInstance(data, { status, headers: responseHeaders });
}

@@ -329,2 +330,5 @@ newResponse = (...args) => this.#newResponse(...args);

body = (data, arg, headers) => this.#newResponse(data, arg, headers);
#useFastPath() {
return !this.#preparedHeaders && !this.#status && !this.finalized;
}
/**

@@ -343,3 +347,3 @@ * `.text()` can render text as `Content-Type:text/plain`.

text = (text, arg, headers) => {
return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized ? new Response(text) : this.#newResponse(
return this.#useFastPath() && !arg && !headers ? createResponseInstance(text) : this.#newResponse(
text,

@@ -363,3 +367,3 @@ arg,

json = (object, arg, headers) => {
return this.#newResponse(
return this.#useFastPath() && !arg && !headers ? Response.json(object) : this.#newResponse(
JSON.stringify(object),

@@ -412,3 +416,3 @@ arg,

notFound = () => {
this.#notFoundHandler ??= () => new Response();
this.#notFoundHandler ??= () => createResponseInstance();
return this.#notFoundHandler(this);

@@ -415,0 +419,0 @@ };

@@ -10,8 +10,11 @@ // src/helper/ssg/index.ts

} from "./middleware.js";
import { defaultPlugin, redirectPlugin } from "./plugins.js";
export {
X_HONO_DISABLE_SSG_HEADER_KEY,
defaultPlugin,
disableSSG,
isSSGContext,
onlySSG,
redirectPlugin,
ssgParams
};

@@ -6,2 +6,3 @@ // src/helper/ssg/ssg.ts

import { SSG_CONTEXT, X_HONO_DISABLE_SSG_HEADER_KEY } from "./middleware.js";
import { defaultPlugin } from "./plugins.js";
import { dirname, filterStaticGenerateRoutes, isDynamicRoute, joinPaths } from "./utils.js";

@@ -188,10 +189,2 @@ var DEFAULT_CONCURRENCY = 2;

};
var defaultPlugin = {
afterResponseHook: (res) => {
if (res.status !== 200) {
return false;
}
return res;
}
};
var toSSG = async (app, fs, options) => {

@@ -201,3 +194,3 @@ let result;

const savePromises = [];
const plugins = options?.plugins || [defaultPlugin];
const plugins = options?.plugins || [defaultPlugin()];
const beforeRequestHooks = [];

@@ -294,3 +287,2 @@ const afterResponseHooks = [];

defaultExtensionMap,
defaultPlugin,
fetchRoutesContent,

@@ -297,0 +289,0 @@ saveContentToFile,

@@ -329,3 +329,5 @@ // src/jsx/dom/render.ts

if (Array.isArray(children[i])) {
children.splice(i, 1, ...children[i].flat());
children.splice(i, 1, ...children[i].flat(Infinity));
i--;
continue;
}

@@ -332,0 +334,0 @@ let child = buildNode(children[i]);

@@ -27,2 +27,5 @@ // src/middleware/basic-auth/index.ts

if (await options.verifyUser(requestUser.username, requestUser.password, ctx)) {
if (options.onAuthSuccess) {
await options.onAuthSuccess(ctx, requestUser.username);
}
await next();

@@ -38,2 +41,5 @@ return;

if (usernameEqual && passwordEqual) {
if (options.onAuthSuccess) {
await options.onAuthSuccess(ctx, requestUser.username);
}
await next();

@@ -40,0 +46,0 @@ return;

@@ -38,4 +38,15 @@ // src/middleware/language/language.ts

);
const matchedLang = compSupported.find((l) => l === compLang);
return matchedLang ? options.supportedLanguages[compSupported.indexOf(matchedLang)] : void 0;
const exactIndex = compSupported.indexOf(compLang);
if (exactIndex !== -1) {
return options.supportedLanguages[exactIndex];
}
const parts = compLang.split("-");
for (let i = parts.length - 1; i > 0; i--) {
const candidate = parts.slice(0, i).join("-");
const prefixIndex = compSupported.indexOf(candidate);
if (prefixIndex !== -1) {
return options.supportedLanguages[prefixIndex];
}
}
return void 0;
} catch {

@@ -42,0 +53,0 @@ return void 0;

// src/middleware/trailing-slash/index.ts
var trimTrailingSlash = () => {
var trimTrailingSlash = (options) => {
return async function trimTrailingSlash2(c, next) {
if (options?.alwaysRedirect) {
if ((c.req.method === "GET" || c.req.method === "HEAD") && c.req.path !== "/" && c.req.path.at(-1) === "/") {
const url = new URL(c.req.url);
url.pathname = url.pathname.substring(0, url.pathname.length - 1);
return c.redirect(url.toString(), 301);
}
}
await next();
if (c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path !== "/" && c.req.path.at(-1) === "/") {
if (!options?.alwaysRedirect && c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path !== "/" && c.req.path.at(-1) === "/") {
const url = new URL(c.req.url);

@@ -12,6 +19,13 @@ url.pathname = url.pathname.substring(0, url.pathname.length - 1);

};
var appendTrailingSlash = () => {
var appendTrailingSlash = (options) => {
return async function appendTrailingSlash2(c, next) {
if (options?.alwaysRedirect) {
if ((c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/") {
const url = new URL(c.req.url);
url.pathname += "/";
return c.redirect(url.toString(), 301);
}
}
await next();
if (c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/") {
if (!options?.alwaysRedirect && c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/") {
const url = new URL(c.req.url);

@@ -18,0 +32,0 @@ url.pathname += "/";

@@ -5,2 +5,8 @@ // src/router/trie-router/node.ts

var emptyParams = /* @__PURE__ */ Object.create(null);
var hasChildren = (children) => {
for (const _ in children) {
return true;
}
return false;
};
var Node = class _Node {

@@ -55,4 +61,3 @@ #methods;

}
#getHandlerSets(node, method, nodeParams, params) {
const handlerSets = [];
#pushHandlerSets(handlerSets, node, method, nodeParams, params) {
for (let i = 0, len = node.#methods.length; i < len; i++) {

@@ -75,3 +80,2 @@ const m = node.#methods[i];

}
return handlerSets;
}

@@ -85,3 +89,5 @@ search(method, path) {

const curNodesQueue = [];
for (let i = 0, len = parts.length; i < len; i++) {
const len = parts.length;
let partOffsets = null;
for (let i = 0; i < len; i++) {
const part = parts[i];

@@ -97,7 +103,5 @@ const isLast = i === len - 1;

if (nextNode.#children["*"]) {
handlerSets.push(
...this.#getHandlerSets(nextNode.#children["*"], method, node.#params)
);
this.#pushHandlerSets(handlerSets, nextNode.#children["*"], method, node.#params);
}
handlerSets.push(...this.#getHandlerSets(nextNode, method, node.#params));
this.#pushHandlerSets(handlerSets, nextNode, method, node.#params);
} else {

@@ -113,3 +117,3 @@ tempNodes.push(nextNode);

if (astNode) {
handlerSets.push(...this.#getHandlerSets(astNode, method, node.#params));
this.#pushHandlerSets(handlerSets, astNode, method, node.#params);
astNode.#params = params;

@@ -125,9 +129,17 @@ tempNodes.push(astNode);

const child = node.#children[key];
const restPathString = parts.slice(i).join("/");
if (matcher instanceof RegExp) {
if (partOffsets === null) {
partOffsets = new Array(len);
let offset = path[0] === "/" ? 1 : 0;
for (let p = 0; p < len; p++) {
partOffsets[p] = offset;
offset += parts[p].length + 1;
}
}
const restPathString = path.substring(partOffsets[i]);
const m = matcher.exec(restPathString);
if (m) {
params[name] = m[0];
handlerSets.push(...this.#getHandlerSets(child, method, node.#params, params));
if (Object.keys(child.#children).length) {
this.#pushHandlerSets(handlerSets, child, method, node.#params, params);
if (hasChildren(child.#children)) {
child.#params = params;

@@ -144,6 +156,10 @@ const componentCount = m[0].match(/\//)?.length ?? 0;

if (isLast) {
handlerSets.push(...this.#getHandlerSets(child, method, params, node.#params));
this.#pushHandlerSets(handlerSets, child, method, params, node.#params);
if (child.#children["*"]) {
handlerSets.push(
...this.#getHandlerSets(child.#children["*"], method, params, node.#params)
this.#pushHandlerSets(
handlerSets,
child.#children["*"],
method,
params,
node.#params
);

@@ -158,3 +174,4 @@ }

}
curNodes = tempNodes.concat(curNodesQueue.shift() ?? []);
const shifted = curNodesQueue.shift();
curNodes = shifted ? tempNodes.concat(shifted) : tempNodes;
}

@@ -161,0 +178,0 @@ if (handlerSets.length > 1) {

@@ -6,3 +6,4 @@ /**

export { handle, streamHandle, defaultIsContentTypeBinary } from './handler';
export { getConnInfo } from './conninfo';
export type { APIGatewayProxyResult, LambdaEvent } from './handler';
export type { ApiGatewayRequestContext, ApiGatewayRequestContextV2, ALBRequestContext, LambdaContext, } from './types';

@@ -6,2 +6,3 @@ /**

export { handle, handleMiddleware, serveStatic } from './handler';
export { getConnInfo } from './conninfo';
export type { EventContext } from './handler';
export { handle } from './handler';
export { getConnInfo } from './conninfo';
import type { Hono } from '../hono';
import type { HonoBase } from '../hono-base';
import type { METHODS, METHOD_NAME_ALL_LOWERCASE } from '../router';
import type { Endpoint, ResponseFormat, Schema } from '../types';
import type { Endpoint, KnownResponseFormat, ResponseFormat, Schema } from '../types';
import type { StatusCode, SuccessStatusCode } from '../utils/http-status';

@@ -77,2 +77,18 @@ import type { HasRequiredKeys } from '../utils/types';

} : {} : {}) | undefined = undefined>(arg?: Arg) => HonoURL<Prefix, Path, Arg>;
$path: <const Arg extends (S[keyof S] extends {
input: infer R;
} ? R extends {
param: infer P;
} ? R extends {
query: infer Q;
} ? {
param: P;
query: Q;
} : {
param: P;
} : R extends {
query: infer Q;
} ? {
query: Q;
} : {} : {}) | undefined = undefined>(arg?: Arg) => BuildPath<Path, Arg>;
} & (S['$get'] extends {

@@ -112,2 +128,3 @@ outputFormat: 'ws';

} ? `${ApplyParam<TrimStartSlash<P>, Param>}` : `/${TrimStartSlash<P>}`;
type BuildPath<P extends string, Arg> = `${BuildPathname<P, Arg>}${BuildSearch<Arg, 'query'>}`;
type BuildTypedURL<Protocol extends string, Host extends string, Port extends string, P extends string, Arg> = TypedURL<`${Protocol}:`, Host, Port, BuildPathname<P, Arg>, BuildSearch<Arg, 'query'>>;

@@ -170,2 +187,23 @@ type HonoURL<Prefix extends string, Path extends string, Arg> = IsLiteral<Prefix> extends true ? TrimEndSlash<Prefix> extends `${infer Protocol}://${infer Rest}` ? Rest extends `${infer Hostname}/${infer P}` ? ParseHostName<Hostname> extends [infer Host extends string, infer Port extends string] ? BuildTypedURL<Protocol, Host, Port, P, Arg> : never : ParseHostName<Rest> extends [infer Host extends string, infer Port extends string] ? BuildTypedURL<Protocol, Host, Port, Path, Arg> : never : URL : URL;

};
type GlobalResponseDefinition = {
[S in StatusCode]?: {
[F in KnownResponseFormat]?: unknown;
};
};
type ToEndpoints<Def extends GlobalResponseDefinition, R> = {
[S in keyof Def & StatusCode]: {
[F in keyof Def[S] & KnownResponseFormat]: Omit<R, 'output' | 'status' | 'outputFormat'> & {
output: Def[S][F];
status: S;
outputFormat: F;
};
}[keyof Def[S] & KnownResponseFormat];
}[keyof Def & StatusCode];
type ModRoute<R, Def extends GlobalResponseDefinition> = R extends Endpoint ? R | ToEndpoints<Def, R> : R;
type ModSchema<D, Def extends GlobalResponseDefinition> = {
[K in keyof D]: {
[M in keyof D[K]]: ModRoute<D[K][M], Def>;
};
};
export type ApplyGlobalResponse<App, Def extends GlobalResponseDefinition> = App extends HonoBase<infer E, infer D extends Schema, infer B> ? Hono<E, ModSchema<D, Def> extends Schema ? ModSchema<D, Def> : never, B> : never;
export {};

@@ -31,2 +31,6 @@ import { HonoRequest } from './request';

props: any;
/**
* For compatibility with Wrangler 4.x.
*/
exports?: any;
}

@@ -33,0 +37,0 @@ /**

@@ -7,1 +7,2 @@ /**

export { X_HONO_DISABLE_SSG_HEADER_KEY, ssgParams, isSSGContext, disableSSG, onlySSG, } from './middleware';
export { defaultPlugin, redirectPlugin } from './plugins';

@@ -87,11 +87,3 @@ import type { Hono } from '../../hono';

/**
* The default plugin that defines the recommended behavior.
*
* @experimental
* `defaultPlugin` is an experimental feature.
* The API might be changed.
*/
export declare const defaultPlugin: SSGPlugin;
/**
* @experimental
* `toSSG` is an experimental feature.

@@ -98,0 +90,0 @@ * The API might be changed.

@@ -14,2 +14,3 @@ /**

invalidUserMessage?: string | object | MessageFunction;
onAuthSuccess?: (c: Context, username: string) => void | Promise<void>;
} | {

@@ -20,2 +21,3 @@ verifyUser: (username: string, password: string, c: Context) => boolean | Promise<boolean>;

invalidUserMessage?: string | object | MessageFunction;
onAuthSuccess?: (c: Context, username: string) => void | Promise<void>;
};

@@ -34,2 +36,3 @@ /**

* @param {string | object | MessageFunction} [options.invalidUserMessage="Unauthorized"] - The invalid user message.
* @param {Function} [options.onAuthSuccess] - Callback function called on successful authentication.
* @returns {MiddlewareHandler} The middleware handler function.

@@ -54,2 +57,18 @@ * @throws {HTTPException} If neither "username and password" nor "verifyUser" options are provided.

* ```
*
* @example
* ```ts
* // With onAuthSuccess callback
* app.use(
* '/auth/*',
* basicAuth({
* username: 'hono',
* password: 'ahotproject',
* onAuthSuccess: (c, username) => {
* c.set('user', { name: username, role: 'admin' })
* console.log(`User ${username} authenticated`)
* },
* })
* )
* ```
*/

@@ -56,0 +75,0 @@ export declare const basicAuth: (options: BasicAuthOptions, ...users: {

@@ -6,2 +6,12 @@ /**

import type { MiddlewareHandler } from '../../types';
type TrimTrailingSlashOptions = {
/**
* If `true`, the middleware will always redirect requests with a trailing slash
* before executing handlers.
* This is useful for routes with wildcards (`*`).
* If `false` (default), it will only redirect when the route is not found (404).
* @default false
*/
alwaysRedirect?: boolean;
};
/**

@@ -12,2 +22,3 @@ * Trailing Slash Middleware for Hono.

*
* @param {TrimTrailingSlashOptions} options - The options for the middleware.
* @returns {MiddlewareHandler} The middleware handler function.

@@ -22,4 +33,23 @@ *

* ```
*
* @example
* ```ts
* // With alwaysRedirect option for wildcard routes
* const app = new Hono()
*
* app.use(trimTrailingSlash({ alwaysRedirect: true }))
* app.get('/my-path/*', (c) => c.text('Wildcard route'))
* ```
*/
export declare const trimTrailingSlash: () => MiddlewareHandler;
export declare const trimTrailingSlash: (options?: TrimTrailingSlashOptions) => MiddlewareHandler;
type AppendTrailingSlashOptions = {
/**
* If `true`, the middleware will always redirect requests without a trailing slash
* before executing handlers.
* This is useful for routes with wildcards (`*`).
* If `false` (default), it will only redirect when the route is not found (404).
* @default false
*/
alwaysRedirect?: boolean;
};
/**

@@ -31,2 +61,3 @@ * Append trailing slash middleware for Hono.

*
* @param {AppendTrailingSlashOptions} options - The options for the middleware.
* @returns {MiddlewareHandler} The middleware handler function.

@@ -40,3 +71,13 @@ *

* ```
*
* @example
* ```ts
* // With alwaysRedirect option for wildcard routes
* const app = new Hono()
*
* app.use(appendTrailingSlash({ alwaysRedirect: true }))
* app.get('/my-path/*', (c) => c.text('Wildcard route'))
* ```
*/
export declare const appendTrailingSlash: () => MiddlewareHandler;
export declare const appendTrailingSlash: (options?: AppendTrailingSlashOptions) => MiddlewareHandler;
export {};
{
"name": "hono",
"version": "4.11.10",
"version": "4.12.0",
"description": "Web framework built on Web Standards",

@@ -5,0 +5,0 @@ "main": "dist/cjs/index.js",