UNPKG

miniflare

Version:

Fun, full-featured, fully-local simulator for Cloudflare Workers

1,216 lines (1,201 loc) • 42.7 kB
// ../../node_modules/.pnpm/hono@4.12.5/node_modules/hono/dist/middleware/cors/index.js var cors = (options) => { let opts = { ...{ origin: "*", allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"], allowHeaders: [], exposeHeaders: [] }, ...options }, findAllowOrigin = /* @__PURE__ */ ((optsOrigin) => typeof optsOrigin == "string" ? optsOrigin === "*" ? () => optsOrigin : (origin) => optsOrigin === origin ? origin : null : typeof optsOrigin == "function" ? optsOrigin : (origin) => optsOrigin.includes(origin) ? origin : null)(opts.origin), findAllowMethods = ((optsAllowMethods) => typeof optsAllowMethods == "function" ? optsAllowMethods : Array.isArray(optsAllowMethods) ? () => optsAllowMethods : () => [])(opts.allowMethods); return async function(c, next) { function set(key, value) { c.res.headers.set(key, value); } let allowOrigin = await findAllowOrigin(c.req.header("origin") || "", c); if (allowOrigin && set("Access-Control-Allow-Origin", allowOrigin), opts.credentials && set("Access-Control-Allow-Credentials", "true"), opts.exposeHeaders?.length && set("Access-Control-Expose-Headers", opts.exposeHeaders.join(",")), c.req.method === "OPTIONS") { opts.origin !== "*" && set("Vary", "Origin"), opts.maxAge != null && set("Access-Control-Max-Age", opts.maxAge.toString()); let allowMethods = await findAllowMethods(c.req.header("origin") || "", c); allowMethods.length && set("Access-Control-Allow-Methods", allowMethods.join(",")); let headers = opts.allowHeaders; if (!headers?.length) { let requestHeaders = c.req.header("Access-Control-Request-Headers"); requestHeaders && (headers = requestHeaders.split(/\s*,\s*/)); } return headers?.length && (set("Access-Control-Allow-Headers", headers.join(",")), c.res.headers.append("Vary", "Access-Control-Request-Headers")), c.res.headers.delete("Content-Length"), c.res.headers.delete("Content-Type"), new Response(null, { headers: c.res.headers, status: 204, statusText: "No Content" }); } await next(), opts.origin !== "*" && c.header("Vary", "Origin", { append: !0 }); }; }; // ../../node_modules/.pnpm/hono@4.12.5/node_modules/hono/dist/compose.js var compose = (middleware, onError, onNotFound) => (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, isError = !1, handler; if (middleware[i] ? (handler = middleware[i][0][0], context.req.routeIndex = i) : handler = i === middleware.length && next || void 0, 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 = !0; else throw err; } else context.finalized === !1 && onNotFound && (res = await onNotFound(context)); return res && (context.finalized === !1 || isError) && (context.res = res), context; } }; // ../../node_modules/.pnpm/hono@4.12.5/node_modules/hono/dist/request/constants.js var GET_MATCH_RESULT = /* @__PURE__ */ Symbol(); // ../../node_modules/.pnpm/hono@4.12.5/node_modules/hono/dist/utils/body.js var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => { let { all = !1, dot = !1 } = options, contentType = (request instanceof HonoRequest ? request.raw.headers : request.headers).get("Content-Type"); return contentType?.startsWith("multipart/form-data") || contentType?.startsWith("application/x-www-form-urlencoded") ? parseFormData(request, { all, dot }) : {}; }; async function parseFormData(request, options) { let formData = await request.formData(); return formData ? convertFormDataToBodyData(formData, options) : {}; } function convertFormDataToBodyData(formData, options) { let form = /* @__PURE__ */ Object.create(null); return formData.forEach((value, key) => { options.all || key.endsWith("[]") ? handleParsingAllValues(form, key, value) : form[key] = value; }), options.dot && Object.entries(form).forEach(([key, value]) => { key.includes(".") && (handleParsingNestedValues(form, key, value), delete form[key]); }), form; } var handleParsingAllValues = (form, key, value) => { form[key] !== void 0 ? Array.isArray(form[key]) ? form[key].push(value) : form[key] = [form[key], value] : key.endsWith("[]") ? form[key] = [value] : form[key] = value; }, handleParsingNestedValues = (form, key, value) => { let nestedForm = form, keys = key.split("."); keys.forEach((key2, index) => { index === keys.length - 1 ? nestedForm[key2] = value : ((!nestedForm[key2] || typeof nestedForm[key2] != "object" || Array.isArray(nestedForm[key2]) || nestedForm[key2] instanceof File) && (nestedForm[key2] = /* @__PURE__ */ Object.create(null)), nestedForm = nestedForm[key2]); }); }; // ../../node_modules/.pnpm/hono@4.12.5/node_modules/hono/dist/utils/url.js var tryDecode = (str, decoder) => { try { return decoder(str); } catch { return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match) => { try { return decoder(match); } catch { return match; } }); } }, tryDecodeURI = (str) => tryDecode(str, decodeURI), getPath = (request) => { let url = request.url, start = url.indexOf("/", url.indexOf(":") + 4), i = start; for (; i < url.length; i++) { let charCode = url.charCodeAt(i); if (charCode === 37) { let queryIndex = url.indexOf("?", i), hashIndex = url.indexOf("#", i), end = queryIndex === -1 ? hashIndex === -1 ? void 0 : hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex), 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) => { let result = getPath(request); return result.length > 1 && result.at(-1) === "/" ? result.slice(0, -1) : result; }, mergePath = (base, sub, ...rest) => (rest.length && (sub = mergePath(sub, ...rest)), `${base?.[0] === "/" ? "" : "/"}${base}${sub === "/" ? "" : `${base?.at(-1) === "/" ? "" : "/"}${sub?.[0] === "/" ? sub.slice(1) : sub}`}`); var _decodeURI = (value) => /[%+]/.test(value) ? (value.indexOf("+") !== -1 && (value = value.replace(/\+/g, " ")), value.indexOf("%") !== -1 ? tryDecode(value, decodeURIComponent_) : value) : value, _getQueryParam = (url, key, multiple) => { let encoded; if (!multiple && key && !/[%+]/.test(key)) { let keyIndex2 = url.indexOf("?", 8); if (keyIndex2 === -1) return; for (url.startsWith(key, keyIndex2 + 1) || (keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1)); keyIndex2 !== -1; ) { let trailingKeyCode = url.charCodeAt(keyIndex2 + key.length + 1); if (trailingKeyCode === 61) { let valueIndex = keyIndex2 + key.length + 2, 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); } if (encoded = /[%+]/.test(url), !encoded) return; } let results = {}; encoded ??= /[%+]/.test(url); let keyIndex = url.indexOf("?", 8); for (; keyIndex !== -1; ) { let nextKeyIndex = url.indexOf("&", keyIndex + 1), valueIndex = url.indexOf("=", keyIndex); 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, name === "") continue; let value; valueIndex === -1 ? value = "" : (value = url.slice(valueIndex + 1, nextKeyIndex === -1 ? void 0 : nextKeyIndex), encoded && (value = _decodeURI(value))), multiple ? (results[name] && Array.isArray(results[name]) || (results[name] = []), results[name].push(value)) : results[name] ??= value; } return key ? results[key] : results; }, getQueryParam = _getQueryParam, getQueryParams = (url, key) => _getQueryParam(url, key, !0), decodeURIComponent_ = decodeURIComponent; // ../../node_modules/.pnpm/hono@4.12.5/node_modules/hono/dist/request.js var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_), 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) { let paramKey = this.#matchResult[0][this.routeIndex][1][key], param = this.#getParamValue(paramKey); return param && /\%/.test(param) ? tryDecodeURIComponent(param) : param; } #getAllDecodedParams() { let decoded = {}, keys = Object.keys(this.#matchResult[0][this.routeIndex][1]); for (let key of keys) { let value = this.#getParamValue(this.#matchResult[0][this.routeIndex][1][key]); 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; let headerData = {}; return this.raw.headers.forEach((value, key) => { headerData[key] = value; }), headerData; } async parseBody(options) { return this.bodyCache.parsedBody ??= await parseBody(this, options); } #cachedBody = (key) => { let { bodyCache, raw: raw2 } = this, cachedBody = bodyCache[key]; if (cachedBody) return cachedBody; let anyCachedKey = Object.keys(bodyCache)[0]; return anyCachedKey ? bodyCache[anyCachedKey].then((body) => (anyCachedKey === "json" && (body = JSON.stringify(body)), new Response(body)[key]())) : 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; } }; // ../../node_modules/.pnpm/hono@4.12.5/node_modules/hono/dist/utils/html.js var HtmlEscapedCallbackPhase = { Stringify: 1, BeforeStream: 2, Stream: 3 }, raw = (value, callbacks) => { let escapedString = new String(value); return escapedString.isEscaped = !0, escapedString.callbacks = callbacks, escapedString; }; var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) => { typeof str == "object" && !(str instanceof String) && (str instanceof Promise || (str = str.toString()), str instanceof Promise && (str = await str)); let callbacks = str.callbacks; if (!callbacks?.length) return Promise.resolve(str); buffer ? buffer[0] += str : buffer = [str]; let resStr = Promise.all(callbacks.map((c) => c({ phase, buffer, context }))).then( (res) => Promise.all( res.filter(Boolean).map((str2) => resolveCallback(str2, phase, !1, context, buffer)) ).then(() => buffer[0]) ); return preserveCallbacks ? raw(await resStr, callbacks) : resStr; }; // ../../node_modules/.pnpm/hono@4.12.5/node_modules/hono/dist/context.js var TEXT_PLAIN = "text/plain; charset=UTF-8", setDefaultContentType = (contentType, headers) => ({ "Content-Type": contentType, ...headers }), createResponseInstance = (body, init) => new Response(body, init), 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 = !1; /** * `.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, 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() { return this.#req ??= new HonoRequest(this.#rawRequest, this.#path, this.#matchResult), 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; 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; 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 (let [k, v] of this.#res.headers.entries()) if (k !== "content-type") if (k === "set-cookie") { let cookies = this.#res.headers.getSetCookie(); _res.headers.delete("set-cookie"); for (let cookie of cookies) _res.headers.append("set-cookie", cookie); } else _res.headers.set(k, v); } this.#res = _res, this.finalized = !0; } /** * `.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), 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( * <html> * <body> * <p>{content}</p> * </body> * </html> * ) * }) * 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) => { this.finalized && (this.#res = createResponseInstance(this.#res.body, this.#res)); let headers = this.#res ? this.#res.headers : this.#preparedHeaders ??= new Headers(); value === void 0 ? headers.delete(name) : options?.append ? headers.append(name, value) : 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) => 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() { return this.#var ? Object.fromEntries(this.#var) : {}; } #newResponse(data, arg, headers) { let responseHeaders = this.#res ? new Headers(this.#res.headers) : this.#preparedHeaders ?? new Headers(); if (typeof arg == "object" && "headers" in arg) { let argHeaders = arg.headers instanceof Headers ? arg.headers : new Headers(arg.headers); for (let [key, value] of argHeaders) key.toLowerCase() === "set-cookie" ? responseHeaders.append(key, value) : responseHeaders.set(key, value); } if (headers) for (let [k, v] of Object.entries(headers)) if (typeof v == "string") responseHeaders.set(k, v); else { responseHeaders.delete(k); for (let v2 of v) responseHeaders.append(k, v2); } let 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) => !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) => this.#newResponse( JSON.stringify(object), arg, setDefaultContentType("application/json", headers) ); html = (html, arg, headers) => { let res = (html2) => this.#newResponse(html2, arg, setDefaultContentType("text/html; charset=UTF-8", headers)); return typeof html == "object" ? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, !1, {}).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) => { let locationString = String(location); return this.header( "Location", // Multibyes should be encoded // eslint-disable-next-line no-control-regex /[^\x00-\xFF]/.test(locationString) ? encodeURI(locationString) : locationString ), 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(), this.#notFoundHandler(this)); }; // ../../node_modules/.pnpm/hono@4.12.5/node_modules/hono/dist/router.js var METHOD_NAME_ALL = "ALL", METHOD_NAME_ALL_LOWERCASE = "all", METHODS = ["get", "post", "put", "delete", "options", "patch"]; var UnsupportedPathError = class extends Error { }; // ../../node_modules/.pnpm/hono@4.12.5/node_modules/hono/dist/utils/constants.js var COMPOSED_HANDLER = "__COMPOSED_HANDLER"; // ../../node_modules/.pnpm/hono@4.12.5/node_modules/hono/dist/hono-base.js var notFoundHandler = (c) => c.text("404 Not Found", 404), errorHandler = (err, c) => { if ("getResponse" in err) { let res = err.getResponse(); return c.newResponse(res.body, res); } return console.error(err), c.text("Internal Server Error", 500); }, 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 = {}) { [...METHODS, METHOD_NAME_ALL_LOWERCASE].forEach((method) => { this[method] = (args1, ...args) => (typeof args1 == "string" ? this.#path = args1 : this.#addRoute(method, this.#path, args1), args.forEach((handler) => { this.#addRoute(method, this.#path, handler); }), this); }), this.on = (method, path, ...handlers) => { for (let p of [path].flat()) { this.#path = p; for (let m of [method].flat()) handlers.map((handler) => { this.#addRoute(m.toUpperCase(), this.#path, handler); }); } return this; }, this.use = (arg1, ...handlers) => (typeof arg1 == "string" ? this.#path = arg1 : (this.#path = "*", handlers.unshift(arg1)), handlers.forEach((handler) => { this.#addRoute(METHOD_NAME_ALL, this.#path, handler); }), this); let { strict, ...optionsWithoutStrict } = options; Object.assign(this, optionsWithoutStrict), this.getPath = strict ?? !0 ? options.getPath ?? getPath : getPathNoStrict; } #clone() { let clone = new _Hono({ router: this.router, getPath: this.getPath }); return clone.errorHandler = this.errorHandler, clone.#notFoundHandler = this.#notFoundHandler, clone.routes = this.routes, 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) { let subApp = this.basePath(path); return app2.routes.map((r) => { let handler; app2.errorHandler === errorHandler ? handler = r.handler : (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); }), 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) { let subApp = this.#clone(); return subApp._basePath = mergePath(this._basePath, path), 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, 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, 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, optionHandler; options && (typeof options == "function" ? optionHandler = options : (optionHandler = options.optionHandler, options.replaceRequest === !1 ? replaceRequest = (request) => request : replaceRequest = options.replaceRequest)); let getOptions = optionHandler ? (c) => { let options2 = optionHandler(c); return Array.isArray(options2) ? options2 : [options2]; } : (c) => { let executionContext; try { executionContext = c.executionCtx; } catch { } return [c.env, executionContext]; }; replaceRequest ||= (() => { let mergedPath = mergePath(this._basePath, path), pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length; return (request) => { let url = new URL(request.url); return url.pathname = url.pathname.slice(pathPrefixLength) || "/", new Request(url, request); }; })(); let handler = async (c, next) => { let res = await applicationHandler(replaceRequest(c.req.raw), ...getOptions(c)); if (res) return res; await next(); }; return this.#addRoute(METHOD_NAME_ALL, mergePath(path, "*"), handler), this; } #addRoute(method, path, handler) { method = method.toUpperCase(), path = mergePath(this._basePath, path); let 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")))(); let path = this.getPath(request, { env }), matchResult = this.router.match(method, path), 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); } let composed = compose(matchResult[0], this.errorHandler, this.#notFoundHandler); return (async () => { try { let 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<Response>} response of request * */ fetch = (request, ...rest) => 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) => input instanceof Request ? this.fetch(requestInit ? new Request(input, requestInit) : input, Env, executionCtx) : (input = input.toString(), this.fetch( new Request( /^https?:\/\//.test(input) ? input : `http://localhost${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)); }); }; }; // ../../node_modules/.pnpm/hono@4.12.5/node_modules/hono/dist/router/pattern-router/router.js var emptyParams = /* @__PURE__ */ Object.create(null), PatternRouter = class { name = "PatternRouter"; #routes = []; add(method, path, handler) { let endsWithWildcard = path.at(-1) === "*"; endsWithWildcard && (path = path.slice(0, -2)), path.at(-1) === "?" && (path = path.slice(0, -1), this.add(method, path.replace(/\/[^/]+$/, ""), handler)); let parts = (path.match(/\/?(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/?[^\/\?]+/g) || []).map( (part) => { let match = part.match(/^\/:([^{]+)(?:{(.*)})?/); return match ? `/(?<${match[1]}>${match[2] || "[^/]+"})` : part === "/*" ? "/[^/]+" : part.replace(/[.\\+*[^\]$()]/g, "\\$&"); } ); try { this.#routes.push([ new RegExp(`^${parts.join("")}${endsWithWildcard ? "" : "/?$"}`), method, handler ]); } catch { throw new UnsupportedPathError(); } } match(method, path) { let handlers = []; for (let i = 0, len = this.#routes.length; i < len; i++) { let [pattern, routeMethod, handler] = this.#routes[i]; if (routeMethod === method || routeMethod === METHOD_NAME_ALL) { let match = pattern.exec(path); match && handlers.push([handler, match.groups || emptyParams]); } } return [handlers]; } }; // ../../node_modules/.pnpm/hono@4.12.5/node_modules/hono/dist/preset/tiny.js var Hono2 = class extends Hono { constructor(options = {}) { super(options), this.router = new PatternRouter(); } }; // src/workers/core/constants.ts var CorePaths = { /** Magic proxy used by getPlatformProxy */ PLATFORM_PROXY: "/cdn-cgi/platform-proxy", /** Trigger scheduled event handlers */ SCHEDULED: "/cdn-cgi/handler/scheduled", /** Trigger email event handlers */ EMAIL: "/cdn-cgi/handler/email", /** Handler path prefix for validation */ HANDLER_PREFIX: "/cdn-cgi/handler/", /** Live reload WebSocket endpoint */ LIVE_RELOAD: "/cdn-cgi/mf/reload", /** Local explorer UI and API */ EXPLORER: "/cdn-cgi/explorer", /** Legacy way to trigger scheduled event handlers */ LEGACY_SCHEDULED: "/cdn-cgi/mf/scheduled", /** Stream video serving endpoint */ STREAM_VIDEO: "/cdn-cgi/mf/stream", /** Local image delivery endpoint for serving hosted images */ IMAGE_DELIVERY: "/cdn-cgi/mf/imagedelivery", /** Public R2 bucket object serving endpoint */ R2_PUBLIC: "/cdn-cgi/local/r2/public" }; // src/workers/r2/public.worker.ts var RANGE_HEADER = /^bytes=(?:(\d+)-(\d+)?|-(\d+))$/; function parseRangeHeader(header) { let match = RANGE_HEADER.exec(header); if (match === null) return { error: "malformed" }; let [, start, end, suffix] = match; return start === void 0 ? Number(suffix) === 0 ? { error: "unsatisfiable" } : {} : end !== void 0 && Number(start) > Number(end) ? { error: "inverted" } : { start: Number(start) }; } function objectHeaders(object) { let headers = new Headers(); return object.writeHttpMetadata(headers), headers.has("Content-Type") || headers.set("Content-Type", "application/octet-stream"), headers.set("ETag", object.httpEtag), headers.set("Last-Modified", object.uploaded.toUTCString()), headers.set("Accept-Ranges", "bytes"), headers; } var app = new Hono2().basePath(CorePaths.R2_PUBLIC); app.use( cors({ origin: "*", allowMethods: ["GET", "HEAD"], exposeHeaders: ["*"] }) ); app.on(["GET", "HEAD"], "/:bucketId/:key{.+}", async (c) => { let bucketId = c.req.param("bucketId"), key = c.req.param("key"), bucket = c.env[bucketId]; if (bucket === void 0) return c.notFound(); let rangeHeader = c.req.header("Range"), parsedRange = rangeHeader === void 0 ? void 0 : parseRangeHeader(rangeHeader); if (parsedRange !== void 0 && "error" in parsedRange) return c.body(null, parsedRange.error === "unsatisfiable" ? 416 : 400); let hasRange = rangeHeader !== void 0, object = await bucket.get(key, { onlyIf: c.req.raw.headers, range: hasRange ? c.req.raw.headers : void 0 }); if (object === null) return c.notFound(); let headers = objectHeaders(object); if (!("body" in object)) { let preconditions; for (let name of ["If-Match", "If-Unmodified-Since"]) { let value = c.req.raw.headers.get(name); value !== null && (preconditions ??= new Headers(), preconditions.set(name, value)); } if (preconditions !== void 0) { let recheck = await bucket.get(key, { onlyIf: preconditions }); if (recheck === null) return c.notFound(); if (!("body" in recheck)) return c.body(null, 412); recheck.body.cancel(); } return c.body(null, { status: 304, headers }); } let body = c.req.method === "HEAD" ? null : object.body; body === null && object.body.cancel(); let range = object.range; if (hasRange && range !== void 0) { if (object.size === 0 || parsedRange?.start !== void 0 && parsedRange.start >= object.size) return body !== null && body.cancel(), c.body(null, 416); let normalized = { ...range }, offset, length; return normalized.suffix !== void 0 ? (length = Math.min(normalized.suffix, object.size), offset = object.size - length) : (offset = normalized.offset ?? 0, length = normalized.length ?? object.size - offset), headers.set( "Content-Range", `bytes ${offset}-${offset + length - 1}/${object.size}` ), headers.set("Content-Length", `${length}`), new Response(body, { status: 206, headers }); } return headers.set("Content-Length", `${object.size}`), new Response(body, { headers }); }); app.all("/:bucketId/:key{.+}", (c) => c.body(null, 401)); var public_worker_default = app; export { public_worker_default as default }; //# sourceMappingURL=public.worker.js.map