Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const require_compose = require("./compose.js"); const require_utils_url = require("./utils/url.js"); const require_context = require("./context.js"); const require_router = require("./router.js"); const require_utils_constants = require("./utils/constants.js"); //#region src/hono-base.ts /** * @module * This module is the base module for the Hono object. */ const notFoundHandler = (c) => { return c.text("404 Not Found", 404); }; const errorHandler = (err, c) => { if ("getResponse" in err) { const res = err.getResponse(); return c.newResponse(res.body, res); } console.error(err); return c.text("Internal Server Error", 500); }; var Hono = class Hono { get; post; put; delete; options; patch; query; all; on; use; router; getPath; _basePath = "/"; #path = "/"; routes = []; constructor(options = {}) { [...require_router.METHODS, "all"].forEach((method) => { this[method] = (args1, ...args) => { const methodName = method.toUpperCase(); if (typeof args1 === "string") this.#path = args1; else this.#addRoute(methodName, this.#path, args1); args.forEach((handler) => { this.#addRoute(methodName, this.#path, handler); }); return this; }; }); this.on = (method, path, ...handlers) => { for (const p of [path].flat()) { this.#path = p; for (const m of [method].flat()) { const methodName = m.toUpperCase(); for (const handler of handlers) this.#addRoute(methodName, this.#path, handler); } } return this; }; this.use = (arg1, ...handlers) => { if (typeof arg1 === "string") this.#path = arg1; else { this.#path = "*"; handlers.unshift(arg1); } handlers.forEach((handler) => { this.#addRoute("ALL", this.#path, handler); }); return this; }; const { strict, ...optionsWithoutStrict } = options; Object.assign(this, optionsWithoutStrict); this.getPath = strict ?? true ? options.getPath ?? require_utils_url.getPath : require_utils_url.getPathNoStrict; } #clone() { const clone = new Hono({ router: this.router, getPath: this.getPath }); clone.errorHandler = this.errorHandler; clone.#notFoundHandler = this.#notFoundHandler; clone.routes = this.routes; return clone; } #notFoundHandler = notFoundHandler; errorHandler = errorHandler; /** * `.route()` allows grouping other Hono instance in routes. * * @see {@link https://hono.dev/docs/api/routing#grouping} * * @param {string} path - base Path * @param {Hono} app - other Hono instance * @returns {Hono} routed Hono instance * * @example * ```ts * const app = new Hono() * const app2 = new Hono() * * app2.get("/user", (c) => c.text("user")) * app.route("/api", app2) // GET /api/user * ``` */ route(path, app) { const subApp = this.basePath(path); app.routes.map((r) => { let handler; if (app.errorHandler === errorHandler) handler = r.handler; else { handler = async (c, next) => (await require_compose.compose([], app.errorHandler)(c, () => r.handler(c, next))).res; handler[require_utils_constants.COMPOSED_HANDLER] = r.handler; } subApp.#addRoute(r.method, r.path, handler, r.basePath); }); return this; } /** * `.basePath()` allows base paths to be specified. * * @see {@link https://hono.dev/docs/api/routing#base-path} * * @param {string} path - base Path * @returns {Hono} changed Hono instance * * @example * ```ts * const api = new Hono().basePath('/api') * ``` */ basePath(path) { const subApp = this.#clone(); subApp._basePath = require_utils_url.mergePath(this._basePath, path); return subApp; } /** * `.onError()` handles an error and returns a customized Response. * * @see {@link https://hono.dev/docs/api/hono#error-handling} * * @param {ErrorHandler} handler - request Handler for error * @returns {Hono} changed Hono instance * * @example * ```ts * app.onError((err, c) => { * console.error(`${err}`) * return c.text('Custom Error Message', 500) * }) * ``` */ onError = (handler) => { this.errorHandler = handler; return this; }; /** * `.notFound()` allows you to customize a Not Found Response. * * @see {@link https://hono.dev/docs/api/hono#not-found} * * @param {NotFoundHandler} handler - request handler for not-found * @returns {Hono} changed Hono instance * * @example * ```ts * app.notFound((c) => { * return c.text('Custom 404 Message', 404) * }) * ``` */ notFound = (handler) => { this.#notFoundHandler = handler; return this; }; /** * `.mount()` allows you to mount applications built with other frameworks into your Hono application. * * @deprecated Use `mount()` from `hono/mount` instead. `.mount()` will be removed in v5. * * @see {@link https://hono.dev/docs/api/hono#mount} * * @param {string} path - base Path * @param {Function} applicationHandler - other Request Handler * @param {MountOptions} [options] - options of `.mount()` * @returns {Hono} mounted Hono instance * * @example * ```ts * import { Router as IttyRouter } from 'itty-router' * import { Hono } from 'hono' * // Create itty-router application * const ittyRouter = IttyRouter() * // GET /itty-router/hello * ittyRouter.get('/hello', () => new Response('Hello from itty-router')) * * const app = new Hono() * app.mount('/itty-router', ittyRouter.handle) * ``` * * @example * ```ts * const app = new Hono() * // Send the request to another application without modification. * app.mount('/app', anotherApp, { * replaceRequest: (req) => req, * }) * ``` */ mount(path, applicationHandler, options) { let replaceRequest; let optionHandler; if (options) { if (typeof options === "function") optionHandler = options; else { optionHandler = options.optionHandler; if (options.replaceRequest === false) replaceRequest = (request) => request; else replaceRequest = options.replaceRequest; } } const getOptions = optionHandler ? (c) => { const options = optionHandler(c); return Array.isArray(options) ? options : [options]; } : (c) => { let executionContext = void 0; try { executionContext = c.executionCtx; } catch {} return [c.env, executionContext]; }; replaceRequest ||= (() => { const mergedPath = require_utils_url.mergePath(this._basePath, path); const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length; return (request) => { const url = new URL(request.url); url.pathname = this.getPath(request).slice(pathPrefixLength) || "/"; return new Request(url, request); }; })(); const handler = async (c, next) => { const res = await applicationHandler(replaceRequest(c.req.raw), ...getOptions(c)); if (res) return res; await next(); }; this.#addRoute("ALL", require_utils_url.mergePath(path, "*"), handler); return this; } #addRoute(method, path, handler, baseRoutePath) { path = require_utils_url.mergePath(this._basePath, path); const r = { basePath: baseRoutePath !== void 0 ? require_utils_url.mergePath(this._basePath, baseRoutePath) : this._basePath, path, method, handler }; this.router.add(method, path, [handler, r]); this.routes.push(r); } #handleError(err, c) { if (err instanceof Error) return this.errorHandler(err, c); throw err; } #dispatch(request, executionCtx, env, method) { if (method === "HEAD") return (async () => new Response(null, await this.#dispatch(request, executionCtx, env, "GET")))(); const path = this.getPath(request, { env }); const matchResult = this.router.match(method, path); const c = new require_context.Context(request, { path, matchResult, env, executionCtx, notFoundHandler: this.#notFoundHandler }); if (matchResult[0].length === 1) { let res; try { res = matchResult[0][0][0][0](c, async () => { c.res = await this.#notFoundHandler(c); }); } catch (err) { return this.#handleError(err, c); } return res instanceof Promise ? res.then((resolved) => resolved || (c.finalized ? c.res : this.#notFoundHandler(c))).catch((err) => this.#handleError(err, c)) : res ?? this.#notFoundHandler(c); } const composed = require_compose.compose(matchResult[0], this.errorHandler, this.#notFoundHandler); return (async () => { try { const context = await composed(c); if (!context.finalized) throw new Error("Context is not finalized. Did you forget to return a Response object or `await next()`?"); return context.res; } catch (err) { return this.#handleError(err, c); } })(); } /** * `.fetch()` will be entry point of your app. * * @see {@link https://hono.dev/docs/api/hono#fetch} * * @param {Request} request - request Object of request * @param {Env} env - env Object * @param {ExecutionContext} executionCtx - context of execution * @returns {Response | Promise} response of request * */ fetch = (request, ...rest) => { return this.#dispatch(request, rest[1], rest[0], request.method); }; /** * `.request()` is a useful method for testing. * You can pass a URL or pathname to send a GET request. * app will return a Response object. * ```ts * test('GET /hello is ok', async () => { * const res = await app.request('/hello') * expect(res.status).toBe(200) * }) * ``` * @see https://hono.dev/docs/api/hono#request */ request = (input, requestInit, Env, executionCtx) => { if (input instanceof Request) return this.fetch(requestInit ? new Request(input, requestInit) : input, Env, executionCtx); input = input.toString(); return this.fetch(new Request(/^https?:\/\//.test(input) ? input : `http://localhost${require_utils_url.mergePath("/", input)}`, requestInit), Env, executionCtx); }; /** * `.fire()` automatically adds a global fetch event listener. * This can be useful for environments that adhere to the Service Worker API, such as non-ES module Cloudflare Workers. * @deprecated * Use `fire` from `hono/service-worker` instead. * ```ts * import { Hono } from 'hono' * import { fire } from 'hono/service-worker' * * const app = new Hono() * // ... * fire(app) * ``` * @see https://hono.dev/docs/api/hono#fire * @see https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API * @see https://developers.cloudflare.com/workers/reference/migrate-to-module-workers/ */ fire = () => { addEventListener("fetch", (event) => { event.respondWith(this.#dispatch(event.request, event, void 0, event.request.method)); }); }; }; //#endregion exports.HonoBase = Hono;