// .component-builds/switch/src/index.ts import componentWasm from "./component.wasm"; // .component-builds/switch/node_modules/hono/dist/compose.js var compose = (middleware, onError, onNotFound) => { return (context, next) => { let index = -1; return dispatch(0); async function dispatch(i) { if (i <= index) { throw new Error("next() called multiple times"); } index = i; let res; let isError = false; let handler; if (middleware[i]) { handler = middleware[i][0][0]; context.req.routeIndex = i; } else { handler = i === middleware.length && next || void 0; } if (handler) { try { res = await handler(context, () => dispatch(i + 1)); } catch (err) { if (err instanceof Error && onError) { context.error = err; res = await onError(err, context); isError = true; } else { throw err; } } } else { if (context.finalized === false && onNotFound) { res = await onNotFound(context); } } if (res && (context.finalized === false || isError)) { context.res = res; } return context; } }; }; // .component-builds/switch/node_modules/hono/dist/request/constants.js var GET_MATCH_RESULT = /* @__PURE__ */ Symbol(); // .component-builds/switch/node_modules/hono/dist/utils/body.js var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => { const { all = false, dot = false } = options; const headers = request instanceof HonoRequest ? request.raw.headers : request.headers; const contentType = headers.get("Content-Type"); if (contentType?.startsWith("multipart/form-data") || contentType?.startsWith("application/x-www-form-urlencoded")) { return parseFormData(request, { all, dot }); } return {}; }; async function parseFormData(request, options) { const formData = await request.formData(); if (formData) { return convertFormDataToBodyData(formData, options); } return {}; } function convertFormDataToBodyData(formData, options) { const form = /* @__PURE__ */ Object.create(null); formData.forEach((value, key) => { const shouldParseAllValues = options.all || key.endsWith("[]"); if (!shouldParseAllValues) { form[key] = value; } else { handleParsingAllValues(form, key, value); } }); if (options.dot) { Object.entries(form).forEach(([key, value]) => { const shouldParseDotValues = key.includes("."); if (shouldParseDotValues) { handleParsingNestedValues(form, key, value); delete form[key]; } }); } return form; } var handleParsingAllValues = (form, key, value) => { if (form[key] !== void 0) { if (Array.isArray(form[key])) { ; form[key].push(value); } else { form[key] = [form[key], value]; } } else { if (!key.endsWith("[]")) { form[key] = value; } else { form[key] = [value]; } } }; var handleParsingNestedValues = (form, key, value) => { if (/(?:^|\.)__proto__\./.test(key)) { return; } let nestedForm = form; const keys = key.split("."); keys.forEach((key2, index) => { if (index === keys.length - 1) { nestedForm[key2] = value; } else { if (!nestedForm[key2] || typeof nestedForm[key2] !== "object" || Array.isArray(nestedForm[key2]) || nestedForm[key2] instanceof File) { nestedForm[key2] = /* @__PURE__ */ Object.create(null); } nestedForm = nestedForm[key2]; } }); }; // .component-builds/switch/node_modules/hono/dist/utils/url.js var splitPath = (path) => { const paths = path.split("/"); if (paths[0] === "") { paths.shift(); } return paths; }; var splitRoutingPath = (routePath) => { const { groups, path } = extractGroupsFromPath(routePath); const paths = splitPath(path); return replaceGroupMarks(paths, groups); }; var extractGroupsFromPath = (path) => { const groups = []; path = path.replace(/\{[^}]+\}/g, (match2, index) => { const mark = `@${index}`; groups.push([mark, match2]); return mark; }); return { groups, path }; }; var replaceGroupMarks = (paths, groups) => { for (let i = groups.length - 1; i >= 0; i--) { const [mark] = groups[i]; for (let j = paths.length - 1; j >= 0; j--) { if (paths[j].includes(mark)) { paths[j] = paths[j].replace(mark, groups[i][1]); break; } } } return paths; }; var patternCache = {}; var getPattern = (label, next) => { if (label === "*") { return "*"; } const match2 = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/); if (match2) { const cacheKey = `${label}#${next}`; if (!patternCache[cacheKey]) { if (match2[2]) { patternCache[cacheKey] = next && next[0] !== ":" && next[0] !== "*" ? [cacheKey, match2[1], new RegExp(`^${match2[2]}(?=/${next})`)] : [label, match2[1], new RegExp(`^${match2[2]}$`)]; } else { patternCache[cacheKey] = [label, match2[1], true]; } } return patternCache[cacheKey]; } return null; }; var tryDecode = (str, decoder) => { try { return decoder(str); } catch { return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match2) => { try { return decoder(match2); } catch { return match2; } }); } }; var tryDecodeURI = (str) => tryDecode(str, decodeURI); var getPath = (request) => { const url = request.url; const start = url.indexOf("/", url.indexOf(":") + 4); let i = start; for (; i < url.length; i++) { const charCode = url.charCodeAt(i); if (charCode === 37) { const queryIndex = url.indexOf("?", i); const hashIndex = url.indexOf("#", i); const end = queryIndex === -1 ? hashIndex === -1 ? void 0 : hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex); const path = url.slice(start, end); return tryDecodeURI(path.includes("%25") ? path.replace(/%25/g, "%2525") : path); } else if (charCode === 63 || charCode === 35) { break; } } return url.slice(start, i); }; var getPathNoStrict = (request) => { const result = getPath(request); return result.length > 1 && result.at(-1) === "/" ? result.slice(0, -1) : result; }; var mergePath = (base, sub, ...rest) => { if (rest.length) { sub = mergePath(sub, ...rest); } return `${base?.[0] === "/" ? "" : "/"}${base}${sub === "/" ? "" : `${base?.at(-1) === "/" ? "" : "/"}${sub?.[0] === "/" ? sub.slice(1) : sub}`}`; }; var checkOptionalParameter = (path) => { if (path.charCodeAt(path.length - 1) !== 63 || !path.includes(":")) { return null; } const segments = path.split("/"); const results = []; let basePath = ""; segments.forEach((segment) => { if (segment !== "" && !/\:/.test(segment)) { basePath += "/" + segment; } else if (/\:/.test(segment)) { if (/\?/.test(segment)) { if (results.length === 0 && basePath === "") { results.push("/"); } else { results.push(basePath); } const optionalSegment = segment.replace("?", ""); basePath += "/" + optionalSegment; results.push(basePath); } else { basePath += "/" + segment; } } }); return results.filter((v, i, a) => a.indexOf(v) === i); }; var _decodeURI = (value) => { if (!/[%+]/.test(value)) { return value; } if (value.indexOf("+") !== -1) { value = value.replace(/\+/g, " "); } return value.indexOf("%") !== -1 ? tryDecode(value, decodeURIComponent_) : value; }; var _getQueryParam = (url, key, multiple) => { let encoded; if (!multiple && key && !/[%+]/.test(key)) { let keyIndex2 = url.indexOf("?", 8); if (keyIndex2 === -1) { return void 0; } if (!url.startsWith(key, keyIndex2 + 1)) { keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1); } while (keyIndex2 !== -1) { const trailingKeyCode = url.charCodeAt(keyIndex2 + key.length + 1); if (trailingKeyCode === 61) { const valueIndex = keyIndex2 + key.length + 2; const endIndex = url.indexOf("&", valueIndex); return _decodeURI(url.slice(valueIndex, endIndex === -1 ? void 0 : endIndex)); } else if (trailingKeyCode == 38 || isNaN(trailingKeyCode)) { return ""; } keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1); } encoded = /[%+]/.test(url); if (!encoded) { return void 0; } } const results = {}; encoded ??= /[%+]/.test(url); let keyIndex = url.indexOf("?", 8); while (keyIndex !== -1) { const nextKeyIndex = url.indexOf("&", keyIndex + 1); let valueIndex = url.indexOf("=", keyIndex); if (valueIndex > nextKeyIndex && nextKeyIndex !== -1) { valueIndex = -1; } let name = url.slice( keyIndex + 1, valueIndex === -1 ? nextKeyIndex === -1 ? void 0 : nextKeyIndex : valueIndex ); if (encoded) { name = _decodeURI(name); } keyIndex = nextKeyIndex; if (name === "") { continue; } let value; if (valueIndex === -1) { value = ""; } else { value = url.slice(valueIndex + 1, nextKeyIndex === -1 ? void 0 : nextKeyIndex); if (encoded) { value = _decodeURI(value); } } if (multiple) { if (!(results[name] && Array.isArray(results[name]))) { results[name] = []; } ; results[name].push(value); } else { results[name] ??= value; } } return key ? results[key] : results; }; var getQueryParam = _getQueryParam; var getQueryParams = (url, key) => { return _getQueryParam(url, key, true); }; var decodeURIComponent_ = decodeURIComponent; // .component-builds/switch/node_modules/hono/dist/request.js var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_); var HonoRequest = class { /** * `.raw` can get the raw Request object. * * @see {@link https://hono.dev/docs/api/request#raw} * * @example * ```ts * // For Cloudflare Workers * app.post('/', async (c) => { * const metadata = c.req.raw.cf?.hostMetadata? * ... * }) * ``` */ raw; #validatedData; // Short name of validatedData #matchResult; routeIndex = 0; /** * `.path` can get the pathname of the request. * * @see {@link https://hono.dev/docs/api/request#path} * * @example * ```ts * app.get('/about/me', (c) => { * const pathname = c.req.path // `/about/me` * }) * ``` */ path; bodyCache = {}; constructor(request, path = "/", matchResult = [[]]) { this.raw = request; this.path = path; this.#matchResult = matchResult; this.#validatedData = {}; } param(key) { return key ? this.#getDecodedParam(key) : this.#getAllDecodedParams(); } #getDecodedParam(key) { const paramKey = this.#matchResult[0][this.routeIndex][1][key]; const param = this.#getParamValue(paramKey); return param && /\%/.test(param) ? tryDecodeURIComponent(param) : param; } #getAllDecodedParams() { const decoded = {}; const keys = Object.keys(this.#matchResult[0][this.routeIndex][1]); for (const key of keys) { const value = this.#getParamValue(this.#matchResult[0][this.routeIndex][1][key]); if (value !== void 0) { decoded[key] = /\%/.test(value) ? tryDecodeURIComponent(value) : value; } } return decoded; } #getParamValue(paramKey) { return this.#matchResult[1] ? this.#matchResult[1][paramKey] : paramKey; } query(key) { return getQueryParam(this.url, key); } queries(key) { return getQueryParams(this.url, key); } header(name) { if (name) { return this.raw.headers.get(name) ?? void 0; } const headerData = {}; this.raw.headers.forEach((value, key) => { headerData[key] = value; }); return headerData; } async parseBody(options) { return parseBody(this, options); } #cachedBody = (key) => { const { bodyCache, raw: raw2 } = this; const cachedBody = bodyCache[key]; if (cachedBody) { return cachedBody; } const anyCachedKey = Object.keys(bodyCache)[0]; if (anyCachedKey) { return bodyCache[anyCachedKey].then((body) => { if (anyCachedKey === "json") { body = JSON.stringify(body); } return new Response(body)[key](); }); } return bodyCache[key] = raw2[key](); }; /** * `.json()` can parse Request body of type `application/json` * * @see {@link https://hono.dev/docs/api/request#json} * * @example * ```ts * app.post('/entry', async (c) => { * const body = await c.req.json() * }) * ``` */ json() { return this.#cachedBody("text").then((text) => JSON.parse(text)); } /** * `.text()` can parse Request body of type `text/plain` * * @see {@link https://hono.dev/docs/api/request#text} * * @example * ```ts * app.post('/entry', async (c) => { * const body = await c.req.text() * }) * ``` */ text() { return this.#cachedBody("text"); } /** * `.arrayBuffer()` parse Request body as an `ArrayBuffer` * * @see {@link https://hono.dev/docs/api/request#arraybuffer} * * @example * ```ts * app.post('/entry', async (c) => { * const body = await c.req.arrayBuffer() * }) * ``` */ arrayBuffer() { return this.#cachedBody("arrayBuffer"); } /** * Parses the request body as a `Blob`. * @example * ```ts * app.post('/entry', async (c) => { * const body = await c.req.blob(); * }); * ``` * @see https://hono.dev/docs/api/request#blob */ blob() { return this.#cachedBody("blob"); } /** * Parses the request body as `FormData`. * @example * ```ts * app.post('/entry', async (c) => { * const body = await c.req.formData(); * }); * ``` * @see https://hono.dev/docs/api/request#formdata */ formData() { return this.#cachedBody("formData"); } /** * Adds validated data to the request. * * @param target - The target of the validation. * @param data - The validated data to add. */ addValidatedData(target, data) { this.#validatedData[target] = data; } valid(target) { return this.#validatedData[target]; } /** * `.url()` can get the request url strings. * * @see {@link https://hono.dev/docs/api/request#url} * * @example * ```ts * app.get('/about/me', (c) => { * const url = c.req.url // `http://localhost:8787/about/me` * ... * }) * ``` */ get url() { return this.raw.url; } /** * `.method()` can get the method name of the request. * * @see {@link https://hono.dev/docs/api/request#method} * * @example * ```ts * app.get('/about/me', (c) => { * const method = c.req.method // `GET` * }) * ``` */ get method() { return this.raw.method; } get [GET_MATCH_RESULT]() { return this.#matchResult; } /** * `.matchedRoutes()` can return a matched route in the handler * * @deprecated * * Use matchedRoutes helper defined in "hono/route" instead. * * @see {@link https://hono.dev/docs/api/request#matchedroutes} * * @example * ```ts * app.use('*', async function logger(c, next) { * await next() * c.req.matchedRoutes.forEach(({ handler, method, path }, i) => { * const name = handler.name || (handler.length < 2 ? '[handler]' : '[middleware]') * console.log( * method, * ' ', * path, * ' '.repeat(Math.max(10 - path.length, 0)), * name, * i === c.req.routeIndex ? '<- respond from here' : '' * ) * }) * }) * ``` */ get matchedRoutes() { return this.#matchResult[0].map(([[, route]]) => route); } /** * `routePath()` can retrieve the path registered within the handler * * @deprecated * * Use routePath helper defined in "hono/route" instead. * * @see {@link https://hono.dev/docs/api/request#routepath} * * @example * ```ts * app.get('/posts/:id', (c) => { * return c.json({ path: c.req.routePath }) * }) * ``` */ get routePath() { return this.#matchResult[0].map(([[, route]]) => route)[this.routeIndex].path; } }; // .component-builds/switch/node_modules/hono/dist/utils/html.js var HtmlEscapedCallbackPhase = { Stringify: 1, BeforeStream: 2, Stream: 3 }; var raw = (value, callbacks) => { const escapedString = new String(value); escapedString.isEscaped = true; escapedString.callbacks = callbacks; return escapedString; }; var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) => { if (typeof str === "object" && !(str instanceof String)) { if (!(str instanceof Promise)) { str = str.toString(); } if (str instanceof Promise) { str = await str; } } const callbacks = str.callbacks; if (!callbacks?.length) { return Promise.resolve(str); } if (buffer) { buffer[0] += str; } else { buffer = [str]; } const resStr = Promise.all(callbacks.map((c) => c({ phase, buffer, context }))).then( (res) => Promise.all( res.filter(Boolean).map((str2) => resolveCallback(str2, phase, false, context, buffer)) ).then(() => buffer[0]) ); if (preserveCallbacks) { return raw(await resStr, callbacks); } else { return resStr; } }; // .component-builds/switch/node_modules/hono/dist/context.js var TEXT_PLAIN = "text/plain; charset=UTF-8"; var setDefaultContentType = (contentType, headers) => { return { "Content-Type": contentType, ...headers }; }; var createResponseInstance = (body, init) => new Response(body, init); var Context = class { #rawRequest; #req; /** * `.env` can get bindings (environment variables, secrets, KV namespaces, D1 database, R2 bucket etc.) in Cloudflare Workers. * * @see {@link https://hono.dev/docs/api/context#env} * * @example * ```ts * // Environment object for Cloudflare Workers * app.get('*', async c => { * const counter = c.env.COUNTER * }) * ``` */ env = {}; #var; finalized = false; /** * `.error` can get the error object from the middleware if the Handler throws an error. * * @see {@link https://hono.dev/docs/api/context#error} * * @example * ```ts * app.use('*', async (c, next) => { * await next() * if (c.error) { * // do something... * } * }) * ``` */ error; #status; #executionCtx; #res; #layout; #renderer; #notFoundHandler; #preparedHeaders; #matchResult; #path; /** * Creates an instance of the Context class. * * @param req - The Request object. * @param options - Optional configuration options for the context. */ constructor(req, options) { this.#rawRequest = req; if (options) { this.#executionCtx = options.executionCtx; this.env = options.env; this.#notFoundHandler = options.notFoundHandler; this.#path = options.path; this.#matchResult = options.matchResult; } } /** * `.req` is the instance of {@link HonoRequest}. */ get req() { this.#req ??= new HonoRequest(this.#rawRequest, this.#path, this.#matchResult); return this.#req; } /** * @see {@link https://hono.dev/docs/api/context#event} * The FetchEvent associated with the current request. * * @throws Will throw an error if the context does not have a FetchEvent. */ get event() { if (this.#executionCtx && "respondWith" in this.#executionCtx) { return this.#executionCtx; } else { throw Error("This context has no FetchEvent"); } } /** * @see {@link https://hono.dev/docs/api/context#executionctx} * The ExecutionContext associated with the current request. * * @throws Will throw an error if the context does not have an ExecutionContext. */ get executionCtx() { if (this.#executionCtx) { return this.#executionCtx; } else { throw Error("This context has no ExecutionContext"); } } /** * @see {@link https://hono.dev/docs/api/context#res} * The Response object for the current request. */ get res() { return this.#res ||= createResponseInstance(null, { headers: this.#preparedHeaders ??= new Headers() }); } /** * Sets the Response object for the current request. * * @param _res - The Response object to set. */ set res(_res) { if (this.#res && _res) { _res = createResponseInstance(_res.body, _res); for (const [k, v] of this.#res.headers.entries()) { if (k === "content-type") { continue; } if (k === "set-cookie") { const cookies = this.#res.headers.getSetCookie(); _res.headers.delete("set-cookie"); for (const cookie of cookies) { _res.headers.append("set-cookie", cookie); } } else { _res.headers.set(k, v); } } } this.#res = _res; this.finalized = true; } /** * `.render()` can create a response within a layout. * * @see {@link https://hono.dev/docs/api/context#render-setrenderer} * * @example * ```ts * app.get('/', (c) => { * return c.render('Hello!') * }) * ``` */ render = (...args) => { this.#renderer ??= (content) => this.html(content); return this.#renderer(...args); }; /** * Sets the layout for the response. * * @param layout - The layout to set. * @returns The layout function. */ setLayout = (layout) => this.#layout = layout; /** * Gets the current layout for the response. * * @returns The current layout function. */ getLayout = () => this.#layout; /** * `.setRenderer()` can set the layout in the custom middleware. * * @see {@link https://hono.dev/docs/api/context#render-setrenderer} * * @example * ```tsx * app.use('*', async (c, next) => { * c.setRenderer((content) => { * return c.html( * *
*{content}
* * * ) * }) * await next() * }) * ``` */ setRenderer = (renderer) => { this.#renderer = renderer; }; /** * `.header()` can set headers. * * @see {@link https://hono.dev/docs/api/context#header} * * @example * ```ts * app.get('/welcome', (c) => { * // Set headers * c.header('X-Message', 'Hello!') * c.header('Content-Type', 'text/plain') * * return c.body('Thank you for coming') * }) * ``` */ header = (name, value, options) => { if (this.finalized) { this.#res = createResponseInstance(this.#res.body, this.#res); } const headers = this.#res ? this.#res.headers : this.#preparedHeaders ??= new Headers(); if (value === void 0) { headers.delete(name); } else if (options?.append) { headers.append(name, value); } else { headers.set(name, value); } }; status = (status) => { this.#status = status; }; /** * `.set()` can set the value specified by the key. * * @see {@link https://hono.dev/docs/api/context#set-get} * * @example * ```ts * app.use('*', async (c, next) => { * c.set('message', 'Hono is hot!!') * await next() * }) * ``` */ set = (key, value) => { this.#var ??= /* @__PURE__ */ new Map(); this.#var.set(key, value); }; /** * `.get()` can use the value specified by the key. * * @see {@link https://hono.dev/docs/api/context#set-get} * * @example * ```ts * app.get('/', (c) => { * const message = c.get('message') * return c.text(`The message is "${message}"`) * }) * ``` */ get = (key) => { return this.#var ? this.#var.get(key) : void 0; }; /** * `.var` can access the value of a variable. * * @see {@link https://hono.dev/docs/api/context#var} * * @example * ```ts * const result = c.var.client.oneMethod() * ``` */ // c.var.propName is a read-only get var() { if (!this.#var) { return {}; } return Object.fromEntries(this.#var); } #newResponse(data, arg, headers) { const responseHeaders = this.#res ? new Headers(this.#res.headers) : this.#preparedHeaders ?? new Headers(); if (typeof arg === "object" && "headers" in arg) { const argHeaders = arg.headers instanceof Headers ? arg.headers : new Headers(arg.headers); for (const [key, value] of argHeaders) { if (key.toLowerCase() === "set-cookie") { responseHeaders.append(key, value); } else { responseHeaders.set(key, value); } } } if (headers) { for (const [k, v] of Object.entries(headers)) { if (typeof v === "string") { responseHeaders.set(k, v); } else { responseHeaders.delete(k); for (const v2 of v) { responseHeaders.append(k, v2); } } } } const status = typeof arg === "number" ? arg : arg?.status ?? this.#status; return createResponseInstance(data, { status, headers: responseHeaders }); } newResponse = (...args) => this.#newResponse(...args); /** * `.body()` can return the HTTP response. * You can set headers with `.header()` and set HTTP status code with `.status`. * This can also be set in `.text()`, `.json()` and so on. * * @see {@link https://hono.dev/docs/api/context#body} * * @example * ```ts * app.get('/welcome', (c) => { * // Set headers * c.header('X-Message', 'Hello!') * c.header('Content-Type', 'text/plain') * // Set HTTP status code * c.status(201) * * // Return the response body * return c.body('Thank you for coming') * }) * ``` */ body = (data, arg, headers) => this.#newResponse(data, arg, headers); /** * `.text()` can render text as `Content-Type:text/plain`. * * @see {@link https://hono.dev/docs/api/context#text} * * @example * ```ts * app.get('/say', (c) => { * return c.text('Hello!') * }) * ``` */ text = (text, arg, headers) => { return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized ? new Response(text) : this.#newResponse( text, arg, setDefaultContentType(TEXT_PLAIN, headers) ); }; /** * `.json()` can render JSON as `Content-Type:application/json`. * * @see {@link https://hono.dev/docs/api/context#json} * * @example * ```ts * app.get('/api', (c) => { * return c.json({ message: 'Hello!' }) * }) * ``` */ json = (object, arg, headers) => { return this.#newResponse( JSON.stringify(object), arg, setDefaultContentType("application/json", headers) ); }; html = (html, arg, headers) => { const res = (html2) => this.#newResponse(html2, arg, setDefaultContentType("text/html; charset=UTF-8", headers)); return typeof html === "object" ? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res) : res(html); }; /** * `.redirect()` can Redirect, default status code is 302. * * @see {@link https://hono.dev/docs/api/context#redirect} * * @example * ```ts * app.get('/redirect', (c) => { * return c.redirect('/') * }) * app.get('/redirect-permanently', (c) => { * return c.redirect('/', 301) * }) * ``` */ redirect = (location, status) => { const locationString = String(location); this.header( "Location", // Multibyes should be encoded // eslint-disable-next-line no-control-regex !/[^\x00-\xFF]/.test(locationString) ? locationString : encodeURI(locationString) ); return this.newResponse(null, status ?? 302); }; /** * `.notFound()` can return the Not Found Response. * * @see {@link https://hono.dev/docs/api/context#notfound} * * @example * ```ts * app.get('/notfound', (c) => { * return c.notFound() * }) * ``` */ notFound = () => { this.#notFoundHandler ??= () => createResponseInstance(); return this.#notFoundHandler(this); }; }; // .component-builds/switch/node_modules/hono/dist/router.js var METHOD_NAME_ALL = "ALL"; var METHOD_NAME_ALL_LOWERCASE = "all"; var METHODS = ["get", "post", "put", "delete", "options", "patch"]; var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built."; var UnsupportedPathError = class extends Error { }; // .component-builds/switch/node_modules/hono/dist/utils/constants.js var COMPOSED_HANDLER = "__COMPOSED_HANDLER"; // .component-builds/switch/node_modules/hono/dist/hono-base.js var notFoundHandler = (c) => { return c.text("404 Not Found", 404); }; var 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; all; on; use; /* This class is like an abstract class and does not have a router. To use it, inherit the class and implement router in the constructor. */ router; getPath; // Cannot use `#` because it requires visibility at JavaScript runtime. _basePath = "/"; #path = "/"; routes = []; constructor(options = {}) { const allMethods = [...METHODS, METHOD_NAME_ALL_LOWERCASE]; allMethods.forEach((method) => { this[method] = (args1, ...args) => { if (typeof args1 === "string") { this.#path = args1; } else { this.#addRoute(method, this.#path, args1); } args.forEach((handler) => { this.#addRoute(method, 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()) { handlers.map((handler) => { this.#addRoute(m.toUpperCase(), 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(METHOD_NAME_ALL, this.#path, handler); }); return this; }; const { strict, ...optionsWithoutStrict } = options; Object.assign(this, optionsWithoutStrict); this.getPath = strict ?? true ? options.getPath ?? getPath : 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; // Cannot use `#` because it requires visibility at JavaScript runtime. 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, app2) { const subApp = this.basePath(path); app2.routes.map((r) => { let handler; if (app2.errorHandler === errorHandler) { handler = r.handler; } else { handler = async (c, next) => (await compose([], app2.errorHandler)(c, () => r.handler(c, next))).res; handler[COMPOSED_HANDLER] = r.handler; } subApp.#addRoute(r.method, r.path, handler); }); 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 = 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. * * @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 options2 = optionHandler(c); return Array.isArray(options2) ? options2 : [options2]; } : (c) => { let executionContext = void 0; try { executionContext = c.executionCtx; } catch { } return [c.env, executionContext]; }; replaceRequest ||= (() => { const mergedPath = mergePath(this._basePath, path); const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length; return (request) => { const url = new URL(request.url); url.pathname = url.pathname.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(METHOD_NAME_ALL, mergePath(path, "*"), handler); return this; } #addRoute(method, path, handler) { method = method.toUpperCase(); path = mergePath(this._basePath, path); const r = { basePath: 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 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 = 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} - context of execution * @returns {Response | Promise