blade
Version:
React at the edge.
499 lines (494 loc) • 16.1 kB
JavaScript
import { n as resolveCallback, t as HtmlEscapedCallbackPhase } from "./html-BHm7adlz.js";
//#region ../../node_modules/hono/dist/utils/body.js
var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
const { all = false, dot = false } = options;
const contentType = (request instanceof HonoRequest ? request.raw.headers : request.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) => {
if (!(options.all || key.endsWith("[]"))) form[key] = value;
else handleParsingAllValues(form, key, value);
});
if (options.dot) Object.entries(form).forEach(([key, value]) => {
if (key.includes(".")) {
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 form[key] = value;
};
var handleParsingNestedValues = (form, key, value) => {
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];
}
});
};
//#endregion
//#region ../../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);
return replaceGroupMarks(splitPath(path), groups);
};
var extractGroupsFromPath = (path) => {
const groups = [];
path = path.replace(/\{[^}]+\}/g, (match, index) => {
const mark = `@${index}`;
groups.push([mark, match]);
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 match = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
if (match) {
const cacheKey = `${label}#${next}`;
if (!patternCache[cacheKey]) if (match[2]) patternCache[cacheKey] = next && next[0] !== ":" && next[0] !== "*" ? [
cacheKey,
match[1],
/* @__PURE__ */ new RegExp(`^${match[2]}(?=/${next})`)
] : [
label,
match[1],
/* @__PURE__ */ new RegExp(`^${match[2]}$`)
];
else patternCache[cacheKey] = [
label,
match[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, (match) => {
try {
return decoder(match);
} catch {
return match;
}
});
}
};
var tryDecodeURI = (str) => tryDecode(str, decodeURI);
var getPath = (request) => {
const url = request.url;
const start = url.indexOf("/", 8);
let i = start;
for (; i < url.length; i++) {
const charCode = url.charCodeAt(i);
if (charCode === 37) {
const queryIndex = url.indexOf("?", i);
const path = url.slice(start, queryIndex === -1 ? void 0 : queryIndex);
return tryDecodeURI(path.includes("%25") ? path.replace(/%25/g, "%2525") : path);
} else if (charCode === 63) 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 ? decodeURIComponent_(value) : value;
};
var _getQueryParam = (url, key, multiple) => {
let encoded;
if (!multiple && key && !/[%+]/.test(key)) {
let keyIndex2 = url.indexOf(`?${key}`, 8);
if (keyIndex2 === -1) keyIndex2 = url.indexOf(`&${key}`, 8);
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;
}
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;
//#endregion
//#region ../../node_modules/hono/dist/request.js
var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_);
var HonoRequest = class {
raw;
#validatedData;
#matchResult;
routeIndex = 0;
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 : void 0;
}
#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 && typeof value === "string") 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 this.bodyCache.parsedBody ??= await parseBody(this, options);
}
#cachedBody = (key) => {
const { bodyCache, raw } = 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] = raw[key]();
};
json() {
return this.#cachedBody("json");
}
text() {
return this.#cachedBody("text");
}
arrayBuffer() {
return this.#cachedBody("arrayBuffer");
}
blob() {
return this.#cachedBody("blob");
}
formData() {
return this.#cachedBody("formData");
}
addValidatedData(target, data) {
this.#validatedData[target] = data;
}
valid(target) {
return this.#validatedData[target];
}
get url() {
return this.raw.url;
}
get method() {
return this.raw.method;
}
get matchedRoutes() {
return this.#matchResult[0].map(([[, route]]) => route);
}
get routePath() {
return this.#matchResult[0].map(([[, route]]) => route)[this.routeIndex].path;
}
};
//#endregion
//#region ../../node_modules/hono/dist/context.js
var TEXT_PLAIN = "text/plain; charset=UTF-8";
var setHeaders = (headers, map = {}) => {
for (const key of Object.keys(map)) headers.set(key, map[key]);
return headers;
};
var Context = class {
#rawRequest;
#req;
env = {};
#var;
finalized = false;
error;
#status = 200;
#executionCtx;
#headers;
#preparedHeaders;
#res;
#isFresh = true;
#layout;
#renderer;
#notFoundHandler;
#matchResult;
#path;
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;
}
}
get req() {
this.#req ??= new HonoRequest(this.#rawRequest, this.#path, this.#matchResult);
return this.#req;
}
get event() {
if (this.#executionCtx && "respondWith" in this.#executionCtx) return this.#executionCtx;
else throw Error("This context has no FetchEvent");
}
get executionCtx() {
if (this.#executionCtx) return this.#executionCtx;
else throw Error("This context has no ExecutionContext");
}
get res() {
this.#isFresh = false;
return this.#res ||= new Response("404 Not Found", { status: 404 });
}
set res(_res) {
this.#isFresh = false;
if (this.#res && _res) {
_res = new Response(_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 = (...args) => {
this.#renderer ??= (content) => this.html(content);
return this.#renderer(...args);
};
setLayout = (layout) => this.#layout = layout;
getLayout = () => this.#layout;
setRenderer = (renderer) => {
this.#renderer = renderer;
};
header = (name, value, options) => {
if (this.finalized) this.#res = new Response(this.#res.body, this.#res);
if (value === void 0) {
if (this.#headers) this.#headers.delete(name);
else if (this.#preparedHeaders) delete this.#preparedHeaders[name.toLocaleLowerCase()];
if (this.finalized) this.res.headers.delete(name);
return;
}
if (options?.append) {
if (!this.#headers) {
this.#isFresh = false;
this.#headers = new Headers(this.#preparedHeaders);
this.#preparedHeaders = {};
}
this.#headers.append(name, value);
} else if (this.#headers) this.#headers.set(name, value);
else {
this.#preparedHeaders ??= {};
this.#preparedHeaders[name.toLowerCase()] = value;
}
if (this.finalized) if (options?.append) this.res.headers.append(name, value);
else this.res.headers.set(name, value);
};
status = (status) => {
this.#isFresh = false;
this.#status = status;
};
set = (key, value) => {
this.#var ??= /* @__PURE__ */ new Map();
this.#var.set(key, value);
};
get = (key) => {
return this.#var ? this.#var.get(key) : void 0;
};
get var() {
if (!this.#var) return {};
return Object.fromEntries(this.#var);
}
#newResponse(data, arg, headers) {
if (this.#isFresh && !headers && !arg && this.#status === 200) return new Response(data, { headers: this.#preparedHeaders });
if (arg && typeof arg !== "number") {
const header = new Headers(arg.headers);
if (this.#headers) this.#headers.forEach((v, k) => {
if (k === "set-cookie") header.append(k, v);
else header.set(k, v);
});
const headers2 = setHeaders(header, this.#preparedHeaders);
return new Response(data, {
headers: headers2,
status: arg.status ?? this.#status
});
}
const status = typeof arg === "number" ? arg : this.#status;
this.#preparedHeaders ??= {};
this.#headers ??= new Headers();
setHeaders(this.#headers, this.#preparedHeaders);
if (this.#res) {
this.#res.headers.forEach((v, k) => {
if (k === "set-cookie") this.#headers?.append(k, v);
else this.#headers?.set(k, v);
});
setHeaders(this.#headers, this.#preparedHeaders);
}
headers ??= {};
for (const [k, v] of Object.entries(headers)) if (typeof v === "string") this.#headers.set(k, v);
else {
this.#headers.delete(k);
for (const v2 of v) this.#headers.append(k, v2);
}
return new Response(data, {
status,
headers: this.#headers
});
}
newResponse = (...args) => this.#newResponse(...args);
body = (data, arg, headers) => {
return typeof arg === "number" ? this.#newResponse(data, arg, headers) : this.#newResponse(data, arg);
};
text = (text, arg, headers) => {
if (!this.#preparedHeaders) {
if (this.#isFresh && !headers && !arg) return new Response(text);
this.#preparedHeaders = {};
}
this.#preparedHeaders["content-type"] = TEXT_PLAIN;
if (typeof arg === "number") return this.#newResponse(text, arg, headers);
return this.#newResponse(text, arg);
};
json = (object, arg, headers) => {
const body = JSON.stringify(object);
this.#preparedHeaders ??= {};
this.#preparedHeaders["content-type"] = "application/json";
return typeof arg === "number" ? this.#newResponse(body, arg, headers) : this.#newResponse(body, arg);
};
html = (html, arg, headers) => {
this.#preparedHeaders ??= {};
this.#preparedHeaders["content-type"] = "text/html; charset=UTF-8";
if (typeof html === "object") return resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then((html2) => {
return typeof arg === "number" ? this.#newResponse(html2, arg, headers) : this.#newResponse(html2, arg);
});
return typeof arg === "number" ? this.#newResponse(html, arg, headers) : this.#newResponse(html, arg);
};
redirect = (location, status) => {
this.#headers ??= new Headers();
this.#headers.set("Location", String(location));
return this.newResponse(null, status ?? 302);
};
notFound = () => {
this.#notFoundHandler ??= () => new Response();
return this.#notFoundHandler(this);
};
};
//#endregion
export { getPathNoStrict as a, splitPath as c, getPath as i, splitRoutingPath as l, checkOptionalParameter as n, getPattern as o, decodeURIComponent_ as r, mergePath as s, Context as t };