elysia
Version:
Ergonomic Framework for Human
367 lines (364 loc) • 15.1 kB
JavaScript
// src/universal/utils.ts
var isBun = typeof Bun < "u";
// src/utils.ts
var hasHeaderShorthand = "toJSON" in new Headers();
var primitiveHooks = [
"start",
"request",
"parse",
"transform",
"resolve",
"beforeHandle",
"afterHandle",
"mapResponse",
"afterResponse",
"trace",
"error",
"stop",
"body",
"headers",
"params",
"query",
"response",
"type",
"detail"
], primitiveHookMap = primitiveHooks.reduce(
(acc, x) => (acc[x] = !0, acc),
{}
);
var isBun2 = typeof Bun < "u", hasBunHash = isBun2 && typeof Bun.hash == "function", checksum = (s) => {
if (hasBunHash) return Bun.hash(s);
let h = 9;
for (let i = 0; i < s.length; ) h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
return h = h ^ h >>> 9;
};
var StatusMap = {
Continue: 100,
"Switching Protocols": 101,
Processing: 102,
"Early Hints": 103,
OK: 200,
Created: 201,
Accepted: 202,
"Non-Authoritative Information": 203,
"No Content": 204,
"Reset Content": 205,
"Partial Content": 206,
"Multi-Status": 207,
"Already Reported": 208,
"Multiple Choices": 300,
"Moved Permanently": 301,
Found: 302,
"See Other": 303,
"Not Modified": 304,
"Temporary Redirect": 307,
"Permanent Redirect": 308,
"Bad Request": 400,
Unauthorized: 401,
"Payment Required": 402,
Forbidden: 403,
"Not Found": 404,
"Method Not Allowed": 405,
"Not Acceptable": 406,
"Proxy Authentication Required": 407,
"Request Timeout": 408,
Conflict: 409,
Gone: 410,
"Length Required": 411,
"Precondition Failed": 412,
"Payload Too Large": 413,
"URI Too Long": 414,
"Unsupported Media Type": 415,
"Range Not Satisfiable": 416,
"Expectation Failed": 417,
"I'm a teapot": 418,
"Misdirected Request": 421,
"Unprocessable Content": 422,
Locked: 423,
"Failed Dependency": 424,
"Too Early": 425,
"Upgrade Required": 426,
"Precondition Required": 428,
"Too Many Requests": 429,
"Request Header Fields Too Large": 431,
"Unavailable For Legal Reasons": 451,
"Internal Server Error": 500,
"Not Implemented": 501,
"Bad Gateway": 502,
"Service Unavailable": 503,
"Gateway Timeout": 504,
"HTTP Version Not Supported": 505,
"Variant Also Negotiates": 506,
"Insufficient Storage": 507,
"Loop Detected": 508,
"Not Extended": 510,
"Network Authentication Required": 511
}, InvertedStatusMap = Object.fromEntries(
Object.entries(StatusMap).map(([k, v]) => [v, k])
);
var encoder = new TextEncoder();
var ELYSIA_FORM_DATA = Symbol("ElysiaFormData"), ELYSIA_REQUEST_ID = Symbol("ElysiaRequestId");
var supportPerMethodInlineHandler = (() => {
if (typeof Bun > "u") return !0;
let semver = Bun.version.split(".");
return !(+semver[0] < 1 || +semver[1] < 2 || +semver[2] < 14);
})();
// src/sucrose.ts
var separateFunction = (code) => {
code.startsWith("async") && (code = code.slice(5)), code = code.trimStart();
let index = -1;
if (code.charCodeAt(0) === 40 && (index = code.indexOf("=>", code.indexOf(")")), index !== -1)) {
let bracketEndIndex = index;
for (; bracketEndIndex > 0 && code.charCodeAt(--bracketEndIndex) !== 41; )
;
let body = code.slice(index + 2);
return body.charCodeAt(0) === 32 && (body = body.trimStart()), [
code.slice(1, bracketEndIndex),
body,
{
isArrowReturn: body.charCodeAt(0) !== 123
}
];
}
if (/^(\w+)=>/g.test(code) && (index = code.indexOf("=>"), index !== -1)) {
let body = code.slice(index + 2);
return body.charCodeAt(0) === 32 && (body = body.trimStart()), [
code.slice(0, index),
body,
{
isArrowReturn: body.charCodeAt(0) !== 123
}
];
}
if (code.startsWith("function")) {
index = code.indexOf("(");
let end = code.indexOf(")");
return [
code.slice(index + 1, end),
code.slice(end + 2),
{
isArrowReturn: !1
}
];
}
let start = code.indexOf("(");
if (start !== -1) {
let sep = code.indexOf(`
`, 2), parameter = code.slice(0, sep), end = parameter.lastIndexOf(")") + 1, body = code.slice(sep + 1);
return [
parameter.slice(start, end),
"{" + body,
{
isArrowReturn: !1
}
];
}
let x = code.split(`
`, 2);
return [x[0], x[1], { isArrowReturn: !1 }];
}, bracketPairRange = (parameter) => {
let start = parameter.indexOf("{");
if (start === -1) return [-1, 0];
let end = start + 1, deep = 1;
for (; end < parameter.length; end++) {
let char = parameter.charCodeAt(end);
if (char === 123 ? deep++ : char === 125 && deep--, deep === 0) break;
}
return deep !== 0 ? [0, parameter.length] : [start, end + 1];
}, bracketPairRangeReverse = (parameter) => {
let end = parameter.lastIndexOf("}");
if (end === -1) return [-1, 0];
let start = end - 1, deep = 1;
for (; start >= 0; start--) {
let char = parameter.charCodeAt(start);
if (char === 125 ? deep++ : char === 123 && deep--, deep === 0) break;
}
return deep !== 0 ? [-1, 0] : [start, end + 1];
}, removeColonAlias = (parameter) => {
for (; ; ) {
let start = parameter.indexOf(":");
if (start === -1) break;
let end = parameter.indexOf(",", start);
end === -1 && (end = parameter.indexOf("}", start) - 1), end === -2 && (end = parameter.length), parameter = parameter.slice(0, start) + parameter.slice(end);
}
return parameter;
}, retrieveRootParamters = (parameter) => {
let hasParenthesis = !1;
parameter.charCodeAt(0) === 40 && (parameter = parameter.slice(1, -1)), parameter.charCodeAt(0) === 123 && (hasParenthesis = !0, parameter = parameter.slice(1, -1)), parameter = parameter.replace(/( |\t|\n)/g, "").trim();
let parameters = [];
for (; ; ) {
let [start, end] = bracketPairRange(parameter);
if (start === -1) break;
parameters.push(parameter.slice(0, start - 1)), parameter.charCodeAt(end) === 44 && end++, parameter = parameter.slice(end);
}
parameter = removeColonAlias(parameter), parameter && (parameters = parameters.concat(parameter.split(",")));
let parameterMap = /* @__PURE__ */ Object.create(null);
for (let p of parameters) {
if (p.indexOf(",") === -1) {
parameterMap[p] = !0;
continue;
}
for (let q of p.split(",")) parameterMap[q.trim()] = !0;
}
return {
hasParenthesis,
parameters: parameterMap
};
}, findParameterReference = (parameter, inference) => {
let { parameters, hasParenthesis } = retrieveRootParamters(parameter);
return parameters.query && (inference.query = !0), parameters.headers && (inference.headers = !0), parameters.body && (inference.body = !0), parameters.cookie && (inference.cookie = !0), parameters.set && (inference.set = !0), parameters.server && (inference.server = !0), parameters.route && (inference.route = !0), parameters.url && (inference.url = !0), parameters.path && (inference.path = !0), hasParenthesis ? `{ ${Object.keys(parameters).join(", ")} }` : Object.keys(parameters).join(", ");
}, findEndIndex = (type, content, index) => {
let regex = new RegExp(
`${type.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\n\\t,; ]`
);
index !== void 0 && (regex.lastIndex = index);
let match = regex.exec(content);
return match ? match.index : -1;
};
var findAlias = (type, body, depth = 0) => {
if (depth > 5) return [];
let aliases = [], content = body;
for (; ; ) {
let index = findEndIndex(" = " + type, content);
if (index === -1 && (index = findEndIndex("=" + type, content)), index === -1) {
let lastIndex = content.indexOf(" = " + type);
if (lastIndex === -1 && (lastIndex = content.indexOf("=" + type)), lastIndex + 3 + type.length !== content.length) break;
index = lastIndex;
}
let part = content.slice(0, index), lastPart = part.lastIndexOf(" "), variable = part.slice(lastPart !== -1 ? lastPart + 1 : -1);
if (variable === "}") {
let [start, end] = bracketPairRangeReverse(part);
aliases.push(removeColonAlias(content.slice(start, end))), content = content.slice(index + 3 + type.length);
continue;
}
for (; variable.charCodeAt(0) === 44; ) variable = variable.slice(1);
for (; variable.charCodeAt(0) === 9; ) variable = variable.slice(1);
variable.includes("(") || aliases.push(variable), content = content.slice(index + 3 + type.length);
}
for (let alias of aliases) {
if (alias.charCodeAt(0) === 123) continue;
let deepAlias = findAlias(alias, body);
deepAlias.length > 0 && aliases.push(...deepAlias);
}
return aliases;
}, extractMainParameter = (parameter) => {
if (!parameter) return;
if (parameter.charCodeAt(0) !== 123) return parameter;
if (parameter = parameter.slice(2, -2), !parameter.includes(","))
return parameter.indexOf("...") !== -1 ? parameter.slice(parameter.indexOf("...") + 3) : void 0;
let spreadIndex = parameter.indexOf("...");
if (spreadIndex !== -1)
return parameter.slice(spreadIndex + 3).trimEnd();
}, inferBodyReference = (code, aliases, inference) => {
let access = (type, alias) => new RegExp(
`${alias}\\.(${type})|${alias}\\["${type}"\\]|${alias}\\['${type}'\\]`
).test(code);
for (let alias of aliases)
if (alias) {
if (alias.charCodeAt(0) === 123) {
let parameters = retrieveRootParamters(alias).parameters;
parameters.query && (inference.query = !0), parameters.headers && (inference.headers = !0), parameters.body && (inference.body = !0), parameters.cookie && (inference.cookie = !0), parameters.set && (inference.set = !0), parameters.server && (inference.server = !0), parameters.url && (inference.url = !0), parameters.route && (inference.route = !0), parameters.path && (inference.path = !0);
continue;
}
if (!inference.query && (access("query", alias) || code.includes("return " + alias) || code.includes("return " + alias + ".query")) && (inference.query = !0), !inference.headers && access("headers", alias) && (inference.headers = !0), !inference.body && access("body", alias) && (inference.body = !0), !inference.cookie && access("cookie", alias) && (inference.cookie = !0), !inference.set && access("set", alias) && (inference.set = !0), !inference.server && access("server", alias) && (inference.server = !0), !inference.route && access("route", alias) && (inference.route = !0), !inference.url && access("url", alias) && (inference.url = !0), !inference.path && access("path", alias) && (inference.path = !0), inference.query && inference.headers && inference.body && inference.cookie && inference.set && inference.server && inference.route && inference.url && inference.path)
break;
}
return aliases;
}, removeDefaultParameter = (parameter) => {
for (; ; ) {
let index = parameter.indexOf("=");
if (index === -1) break;
let commaIndex = parameter.indexOf(",", index), bracketIndex = parameter.indexOf("}", index), end = [commaIndex, bracketIndex].filter((i) => i > 0).sort((a, b) => a - b)[0] || -1;
if (end === -1) {
parameter = parameter.slice(0, index);
break;
}
parameter = parameter.slice(0, index) + parameter.slice(end);
}
return parameter.split(",").map((i) => i.trim()).join(", ");
}, isContextPassToFunction = (context, body, inference) => {
try {
let captureFunction = new RegExp(`\\w\\((.*?)?${context}`, "gs");
captureFunction.test(body);
let nextChar = body.charCodeAt(captureFunction.lastIndex);
return nextChar === 41 || nextChar === 44 ? (inference.query = !0, inference.headers = !0, inference.body = !0, inference.cookie = !0, inference.set = !0, inference.server = !0, inference.url = !0, inference.route = !0, inference.path = !0, !0) : !1;
} catch {
return console.log(
"[Sucrose] warning: unexpected isContextPassToFunction error, you may continue development as usual but please report the following to maintainers:"
), console.log("--- body ---"), console.log(body), console.log("--- context ---"), console.log(context), !0;
}
}, pendingGC, caches = {}, clearSucroseCache = (delay = 0) => {
pendingGC && clearTimeout(pendingGC), pendingGC = setTimeout(() => {
caches = {}, pendingGC = void 0, isBun && Bun.gc(!1);
}, delay);
}, mergeInference = (a, b) => ({
body: a.body || b.body,
cookie: a.cookie || b.cookie,
headers: a.headers || b.headers,
query: a.query || b.query,
set: a.set || b.set,
server: a.server || b.server,
url: a.url || b.url,
route: a.route || b.route,
path: a.path || b.path
}), sucrose = (lifeCycle, inference = {
query: !1,
headers: !1,
body: !1,
cookie: !1,
set: !1,
server: !1,
url: !1,
route: !1,
path: !1
}) => {
let events = [];
lifeCycle.request?.length && events.push(...lifeCycle.request), lifeCycle.beforeHandle?.length && events.push(...lifeCycle.beforeHandle), lifeCycle.parse?.length && events.push(...lifeCycle.parse), lifeCycle.error?.length && events.push(...lifeCycle.error), lifeCycle.transform?.length && events.push(...lifeCycle.transform), lifeCycle.afterHandle?.length && events.push(...lifeCycle.afterHandle), lifeCycle.mapResponse?.length && events.push(...lifeCycle.mapResponse), lifeCycle.afterResponse?.length && events.push(...lifeCycle.afterResponse), lifeCycle.handler && typeof lifeCycle.handler == "function" && events.push(lifeCycle.handler);
for (let i = 0; i < events.length; i++) {
let e = events[i];
if (!e) continue;
let event = typeof e == "object" ? e.fn : e;
if (typeof event != "function") continue;
let content = event.toString(), key = checksum(content), cachedInference = caches[key];
if (cachedInference) {
inference = mergeInference(inference, cachedInference);
continue;
}
let fnInference = {
query: !1,
headers: !1,
body: !1,
cookie: !1,
set: !1,
server: !1,
url: !1,
route: !1,
path: !1
}, [parameter, body] = separateFunction(content), rootParameters = findParameterReference(parameter, fnInference), mainParameter = extractMainParameter(rootParameters);
if (mainParameter) {
let aliases = findAlias(mainParameter, body.slice(1, -1));
aliases.splice(0, -1, mainParameter);
let code = body;
code.charCodeAt(0) === 123 && code.charCodeAt(body.length - 1) === 125 && (code = code.slice(1, -1)), isContextPassToFunction(mainParameter, code, fnInference) || inferBodyReference(code, aliases, fnInference), !fnInference.query && code.includes("return " + mainParameter + ".query") && (fnInference.query = !0);
}
if (caches[key] || (caches[key] = fnInference), inference = mergeInference(inference, fnInference), inference.query && inference.headers && inference.body && inference.cookie && inference.set && inference.server && inference.url && inference.route && inference.path)
break;
}
return inference;
};
export {
bracketPairRange,
bracketPairRangeReverse,
clearSucroseCache,
extractMainParameter,
findAlias,
findParameterReference,
inferBodyReference,
isContextPassToFunction,
mergeInference,
removeColonAlias,
removeDefaultParameter,
retrieveRootParamters,
separateFunction,
sucrose
};