UNPKG

elysia

Version:

Ergonomic Framework for Human

1,263 lines (1,253 loc) 303 kB
// node_modules/memoirist/dist/index.mjs var createNode = (part, inert) => { let inertMap = inert?.length ? {} : null; if (inertMap) for (let child of inert) inertMap[child.part.charCodeAt(0)] = child; return { part, store: null, inert: inertMap, params: null, wildcardStore: null }; }, cloneNode = (node, part) => ({ ...node, part }), createParamNode = (name) => ({ name, store: null, inert: null }), Memoirist = class _Memoirist { constructor(config = {}) { this.config = config, config.lazy && (this.find = this.lazyFind); } root = {}; history = []; deferred = []; static regex = { static: /:.+?(?=\/|$)/, params: /:.+?(?=\/|$)/g, optionalParams: /(\/:\w+\?)/g }; lazyFind = (method, url) => this.config.lazy ? (this.build(), this.find(method, url)) : this.find; build() { if (this.config.lazy) { for (let [method, path, store] of this.deferred) this.add(method, path, store, { lazy: !1, ignoreHistory: !0 }); this.deferred = [], this.find = (method, url) => { let root = this.root[method]; return root ? matchRoute(url, url.length, root, 0) : null; }; } } add(method, path, store, { ignoreError = !1, ignoreHistory = !1, lazy = this.config.lazy } = {}) { if (lazy) return this.find = this.lazyFind, this.deferred.push([method, path, store]), store; if (typeof path != "string") throw new TypeError("Route path must be a string"); path === "" ? path = "/" : path[0] !== "/" && (path = `/${path}`); let isWildcard = path[path.length - 1] === "*", optionalParams = path.match(_Memoirist.regex.optionalParams); if (optionalParams) { let originalPath = path.replaceAll("?", ""); this.add(method, originalPath, store, { ignoreError, ignoreHistory, lazy }); for (let i = 0; i < optionalParams.length; i++) { let newPath = path.replace(optionalParams[i], ""); this.add(method, newPath, store, { ignoreError: !0, ignoreHistory, lazy }); } return store; } if (optionalParams && (path = path.replaceAll("?", "")), this.history.find(([m, p, s]) => m === method && p === path)) return store; (isWildcard || optionalParams && path.charCodeAt(path.length - 1) === 63) && (path = path.slice(0, -1)), ignoreHistory || this.history.push([method, path, store]); let inertParts = path.split(_Memoirist.regex.static), paramParts = path.match(_Memoirist.regex.params) || []; inertParts[inertParts.length - 1] === "" && inertParts.pop(); let node; this.root[method] ? node = this.root[method] : node = this.root[method] = createNode("/"); let paramPartsIndex = 0; for (let i = 0; i < inertParts.length; ++i) { let part = inertParts[i]; if (i > 0) { let param = paramParts[paramPartsIndex++].slice(1); if (node.params === null) node.params = createParamNode(param); else if (node.params.name !== param) { if (ignoreError) return store; throw new Error( `Cannot create route "${path}" with parameter "${param}" because a route already exists with a different parameter name ("${node.params.name}") in the same location` ); } let params = node.params; if (params.inert === null) { node = params.inert = createNode(part); continue; } node = params.inert; } for (let j = 0; ; ) { if (j === part.length) { if (j < node.part.length) { let childNode = cloneNode(node, node.part.slice(j)); Object.assign(node, createNode(part, [childNode])); } break; } if (j === node.part.length) { node.inert === null && (node.inert = {}); let inert = node.inert[part.charCodeAt(j)]; if (inert) { node = inert, part = part.slice(j), j = 0; continue; } let childNode = createNode(part.slice(j)); node.inert[part.charCodeAt(j)] = childNode, node = childNode; break; } if (part[j] !== node.part[j]) { let existingChild = cloneNode(node, node.part.slice(j)), newChild = createNode(part.slice(j)); Object.assign( node, createNode(node.part.slice(0, j), [ existingChild, newChild ]) ), node = newChild; break; } ++j; } } if (paramPartsIndex < paramParts.length) { let name = paramParts[paramPartsIndex].slice(1); if (node.params === null) node.params = createParamNode(name); else if (node.params.name !== name) { if (ignoreError) return store; throw new Error( `Cannot create route "${path}" with parameter "${name}" because a route already exists with a different parameter name ("${node.params.name}") in the same location` ); } return node.params.store === null && (node.params.store = store), node.params.store; } return isWildcard ? (node.wildcardStore === null && (node.wildcardStore = store), node.wildcardStore) : (node.store === null && (node.store = store), node.store); } find(method, url) { let root = this.root[method]; return root ? matchRoute(url, url.length, root, 0) : null; } }, matchRoute = (url, urlLength, node, startIndex) => { let part = node.part, length = part.length, endIndex = startIndex + length; if (length > 1) { if (endIndex > urlLength) return null; if (length < 15) { for (let i = 1, j = startIndex + 1; i < length; ++i, ++j) if (part.charCodeAt(i) !== url.charCodeAt(j)) return null; } else if (url.slice(startIndex, endIndex) !== part) return null; } if (endIndex === urlLength) return node.store !== null ? { store: node.store, params: {} } : node.wildcardStore !== null ? { store: node.wildcardStore, params: { "*": "" } } : null; if (node.inert !== null) { let inert = node.inert[url.charCodeAt(endIndex)]; if (inert !== void 0) { let route = matchRoute(url, urlLength, inert, endIndex); if (route !== null) return route; } } if (node.params !== null) { let { store, name, inert } = node.params, slashIndex = url.indexOf("/", endIndex); if (slashIndex !== endIndex) { if (slashIndex === -1 || slashIndex >= urlLength) { if (store !== null) { let params = {}; return params[name] = url.substring(endIndex, urlLength), { store, params }; } } else if (inert !== null) { let route = matchRoute(url, urlLength, inert, slashIndex); if (route !== null) return route.params[name] = url.substring(endIndex, slashIndex), route; } } } return node.wildcardStore !== null ? { store: node.wildcardStore, params: { "*": url.substring(endIndex, urlLength) } } : null; }; // src/index.ts import { Kind as Kind5 } from "@sinclair/typebox"; // src/type-system/index.ts import { Type, Kind as Kind2 } from "@sinclair/typebox"; // src/type-system/format.ts import { FormatRegistry } from "@sinclair/typebox"; var fullFormats = { // date: http://tools.ietf.org/html/rfc3339#section-5.6 date, // date-time: http://tools.ietf.org/html/rfc3339#section-5.6 time: getTime(!0), "date-time": getDateTime(!0), "iso-time": getTime(!1), "iso-date-time": getDateTime(!1), // duration: https://tools.ietf.org/html/rfc3339#appendix-A duration: /^P(?!$)((\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?|(\d+W)?)$/, uri, "uri-reference": /^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i, // uri-template: https://tools.ietf.org/html/rfc6570 "uri-template": /^(?:(?:[^\x00-\x20"'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i, // For the source: https://gist.github.com/dperini/729294 // For test cases: https://mathiasbynens.be/demo/url-regex url: /^(?:https?|ftp):\/\/(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)(?:\.(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu, email: /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i, hostname: /^(?=.{1,253}\.?$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*\.?$/i, // optimized https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html ipv4: /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/, ipv6: /^((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))$/i, regex, // uuid: http://tools.ietf.org/html/rfc4122 uuid: /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i, // JSON-pointer: https://tools.ietf.org/html/rfc6901 // uri fragment: https://tools.ietf.org/html/rfc3986#appendix-A "json-pointer": /^(?:\/(?:[^~/]|~0|~1)*)*$/, "json-pointer-uri-fragment": /^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i, // relative JSON-pointer: http://tools.ietf.org/html/draft-luff-relative-json-pointer-00 "relative-json-pointer": /^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/, // the following formats are used by the openapi specification: https://spec.openapis.org/oas/v3.0.0#data-types // byte: https://github.com/miguelmota/is-base64 byte, // signed 32 bit integer int32: { type: "number", validate: validateInt32 }, // signed 64 bit integer int64: { type: "number", validate: validateInt64 }, // C-type float float: { type: "number", validate: validateNumber }, // C-type double double: { type: "number", validate: validateNumber }, // hint to the UI to hide input strings password: !0, // unchecked string payload binary: !0 }; function isLeapYear(year) { return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); } var DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/, DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; function date(str) { let matches = DATE.exec(str); if (!matches) return !1; let year = +matches[1], month = +matches[2], day = +matches[3]; return month >= 1 && month <= 12 && day >= 1 && day <= (month === 2 && isLeapYear(year) ? 29 : DAYS[month]); } var TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i; function getTime(strictTimeZone) { return function(str) { let matches = TIME.exec(str); if (!matches) return !1; let hr = +matches[1], min = +matches[2], sec = +matches[3], tz = matches[4], tzSign = matches[5] === "-" ? -1 : 1, tzH = +(matches[6] || 0), tzM = +(matches[7] || 0); if (tzH > 23 || tzM > 59 || strictTimeZone && !tz) return !1; if (hr <= 23 && min <= 59 && sec < 60) return !0; let utcMin = min - tzM * tzSign, utcHr = hr - tzH * tzSign - (utcMin < 0 ? 1 : 0); return (utcHr === 23 || utcHr === -1) && (utcMin === 59 || utcMin === -1) && sec < 61; }; } var parseDateTimeEmptySpace = (str) => str.charCodeAt(str.length - 6) === 32 ? str.slice(0, -6) + "+" + str.slice(-5) : str, DATE_TIME_SEPARATOR = /t|\s/i; function getDateTime(strictTimeZone) { let time = getTime(strictTimeZone); return function(str) { let dateTime = str.split(DATE_TIME_SEPARATOR); return dateTime.length === 2 && date(dateTime[0]) && time(dateTime[1]); }; } var NOT_URI_FRAGMENT = /\/|:/, URI = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i; function uri(str) { return NOT_URI_FRAGMENT.test(str) && URI.test(str); } var BYTE = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/gm; function byte(str) { return BYTE.lastIndex = 0, BYTE.test(str); } var MIN_INT32 = -(2 ** 31), MAX_INT32 = 2 ** 31 - 1; function validateInt32(value) { return Number.isInteger(value) && value <= MAX_INT32 && value >= MIN_INT32; } function validateInt64(value) { return Number.isInteger(value); } function validateNumber() { return !0; } var Z_ANCHOR = /[^\\]\\Z/; function regex(str) { if (Z_ANCHOR.test(str)) return !1; try { return new RegExp(str), !0; } catch { return !1; } } var isISO8601 = /(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/, isFormalDate = /(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{2}\s\d{4}\s\d{2}:\d{2}:\d{2}\sGMT(?:\+|-)\d{4}\s\([^)]+\)/, isShortenDate = /^(?:(?:(?:(?:0?[1-9]|[12][0-9]|3[01])[/\s-](?:0?[1-9]|1[0-2])[/\s-](?:19|20)\d{2})|(?:(?:19|20)\d{2}[/\s-](?:0?[1-9]|1[0-2])[/\s-](?:0?[1-9]|[12][0-9]|3[01]))))(?:\s(?:1[012]|0?[1-9]):[0-5][0-9](?::[0-5][0-9])?(?:\s[AP]M)?)?$/, _validateDate = fullFormats.date, _validateDateTime = fullFormats["date-time"]; FormatRegistry.Has("date") || FormatRegistry.Set("date", (value) => { let temp = parseDateTimeEmptySpace(value).replace(/"/g, ""); if (isISO8601.test(temp) || isFormalDate.test(temp) || isShortenDate.test(temp) || _validateDate(temp)) { let date2 = new Date(temp); if (!Number.isNaN(date2.getTime())) return !0; } return !1; }); FormatRegistry.Has("date-time") || FormatRegistry.Set("date-time", (value) => { let temp = value.replace(/"/g, ""); if (isISO8601.test(temp) || isFormalDate.test(temp) || isShortenDate.test(temp) || _validateDateTime(temp)) { let date2 = new Date(temp); if (!Number.isNaN(date2.getTime())) return !0; } return !1; }); Object.entries(fullFormats).forEach((formatEntry) => { let [formatName, formatValue] = formatEntry; FormatRegistry.Has(formatName) || (formatValue instanceof RegExp ? FormatRegistry.Set(formatName, (value) => formatValue.test(value)) : typeof formatValue == "function" && FormatRegistry.Set(formatName, formatValue)); }); FormatRegistry.Has("numeric") || FormatRegistry.Set("numeric", (value) => !!value && !isNaN(+value)); FormatRegistry.Has("integer") || FormatRegistry.Set( "integer", (value) => !!value && Number.isInteger(+value) ); FormatRegistry.Has("boolean") || FormatRegistry.Set( "boolean", (value) => value === "true" || value === "false" ); FormatRegistry.Has("ObjectString") || FormatRegistry.Set("ObjectString", (value) => { let start = value.charCodeAt(0); if ((start === 9 || start === 10 || start === 32) && (start = value.trimStart().charCodeAt(0)), start !== 123 && start !== 91) return !1; try { return JSON.parse(value), !0; } catch { return !1; } }); FormatRegistry.Has("ArrayString") || FormatRegistry.Set("ArrayString", (value) => { let start = value.charCodeAt(0); if ((start === 9 || start === 10 || start === 32) && (start = value.trimStart().charCodeAt(0)), start !== 123 && start !== 91) return !1; try { return JSON.parse(value), !0; } catch { return !1; } }); // src/type-system/utils.ts import { Kind, TypeRegistry, Unsafe } from "@sinclair/typebox"; import { Value as Value2 } from "@sinclair/typebox/value"; import { TypeCompiler } from "@sinclair/typebox/compiler"; // src/universal/utils.ts var isBun = typeof Bun < "u"; // src/universal/file.ts var mime2 = { aac: "audio/aac", abw: "application/x-abiword", ai: "application/postscript", arc: "application/octet-stream", avi: "video/x-msvideo", azw: "application/vnd.amazon.ebook", bin: "application/octet-stream", bz: "application/x-bzip", bz2: "application/x-bzip2", csh: "application/x-csh", css: "text/css", csv: "text/csv", doc: "application/msword", dll: "application/octet-stream", eot: "application/vnd.ms-fontobject", epub: "application/epub+zip", gif: "image/gif", htm: "text/html", html: "text/html", ico: "image/x-icon", ics: "text/calendar", jar: "application/java-archive", jpeg: "image/jpeg", jpg: "image/jpeg", js: "application/javascript", json: "application/json", mid: "audio/midi", midi: "audio/midi", mp2: "audio/mpeg", mp3: "audio/mpeg", mp4: "video/mp4", mpa: "video/mpeg", mpe: "video/mpeg", mpeg: "video/mpeg", mpkg: "application/vnd.apple.installer+xml", odp: "application/vnd.oasis.opendocument.presentation", ods: "application/vnd.oasis.opendocument.spreadsheet", odt: "application/vnd.oasis.opendocument.text", oga: "audio/ogg", ogv: "video/ogg", ogx: "application/ogg", otf: "font/otf", png: "image/png", pdf: "application/pdf", ppt: "application/vnd.ms-powerpoint", rar: "application/x-rar-compressed", rtf: "application/rtf", sh: "application/x-sh", svg: "image/svg+xml", swf: "application/x-shockwave-flash", tar: "application/x-tar", tif: "image/tiff", tiff: "image/tiff", ts: "application/typescript", ttf: "font/ttf", txt: "text/plain", vsd: "application/vnd.visio", wav: "audio/x-wav", weba: "audio/webm", webm: "video/webm", webp: "image/webp", woff: "font/woff", woff2: "font/woff2", xhtml: "application/xhtml+xml", xls: "application/vnd.ms-excel", xlsx: "application/vnd.ms-excel", xlsx_OLD: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", xml: "application/xml", xul: "application/vnd.mozilla.xul+xml", zip: "application/zip", "3gp": "video/3gpp", "3gp_DOES_NOT_CONTAIN_VIDEO": "audio/3gpp", "3gp2": "video/3gpp2", "3gp2_DOES_NOT_CONTAIN_VIDEO": "audio/3gpp2", "7z": "application/x-7z-compressed" }, getFileExtension = (path) => { let index = path.lastIndexOf("."); return index === -1 ? "" : path.slice(index + 1); }, file = (path) => new ElysiaFile(path), createReadStream, stat, ElysiaFile = class { constructor(path) { this.path = path; if (isBun) this.value = Bun.file(path); else if (typeof window < "u") console.warn("Browser environment does not support file"); else if (!createReadStream || !stat) try { this.value = import("fs").then((fs) => (createReadStream = fs.createReadStream, fs.createReadStream(path))), this.stats = import("fs/promises").then((fs) => (stat = fs.stat, fs.stat(path))); } catch { } else this.value = createReadStream(path), this.stats = stat(path); } get type() { return ( // @ts-ignore mime2[getFileExtension(this.path)] || "application/octet-stream" ); } get length() { return isBun ? this.value.size : this.stats?.then((x) => x.size) ?? 0; } }; // src/error.ts import { Value } from "@sinclair/typebox/value"; // src/utils.ts var hasHeaderShorthand = "toJSON" in new Headers(), replaceUrlPath = (url, pathname) => { let urlObject = new URL(url); return urlObject.pathname = pathname, urlObject.toString(); }, isClass = (v) => typeof v == "function" && /^\s*class\s+/.test(v.toString()) || // Handle Object.create(null) v.toString && // Handle import * as Sentry from '@sentry/bun' // This also handle [object Date], [object Array] // and FFI value like [object Prisma] v.toString().startsWith("[object ") && v.toString() !== "[object Object]" || // If object prototype is not pure, then probably a class-like object isNotEmpty(Object.getPrototypeOf(v)), isObject = (item) => item && typeof item == "object" && !Array.isArray(item), mergeDeep = (target, source, options) => { let skipKeys = options?.skipKeys, override = options?.override ?? !0; if (!isObject(target) || !isObject(source)) return target; for (let [key, value] of Object.entries(source)) if (!skipKeys?.includes(key)) { if (!isObject(value) || !(key in target) || isClass(value)) { (override || !(key in target)) && (target[key] = value); continue; } target[key] = mergeDeep( target[key], value, { skipKeys, override } ); } return target; }, mergeCookie = (a, b) => { let v = mergeDeep(Object.assign({}, a), b, { skipKeys: ["properties"] }); return v.properties && delete v.properties, v; }, mergeObjectArray = (a, b) => { if (!b) return a; let array = [], checksums = []; if (a) { Array.isArray(a) || (a = [a]); for (let item of a) array.push(item), item.checksum && checksums.push(item.checksum); } if (b) { Array.isArray(b) || (b = [b]); for (let item of b) checksums.includes(item.checksum) || array.push(item); } return array; }, 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), {} ), mergeResponse = (a, b) => { let isRecordNumber = (x) => typeof x == "object" && Object.keys(x).every(isNumericString); return isRecordNumber(a) && isRecordNumber(b) ? Object.assign(a, b) : a && !isRecordNumber(a) && isRecordNumber(b) ? Object.assign({ 200: a }, b) : b ?? a; }, mergeSchemaValidator = (a, b) => !a && !b ? { body: void 0, headers: void 0, params: void 0, query: void 0, cookie: void 0, response: void 0 } : { body: b?.body ?? a?.body, headers: b?.headers ?? a?.headers, params: b?.params ?? a?.params, query: b?.query ?? a?.query, cookie: b?.cookie ?? a?.cookie, // @ts-ignore ? This order is correct - SaltyAom response: mergeResponse( // @ts-ignore a?.response, // @ts-ignore b?.response ) }, mergeHook = (a, b) => { if (!Object.values(b).find((x) => x != null)) return { ...a }; let hook = { ...a, ...b, // Merge local hook first // @ts-ignore body: b?.body ?? a?.body, // @ts-ignore headers: b?.headers ?? a?.headers, // @ts-ignore params: b?.params ?? a?.params, // @ts-ignore query: b?.query ?? a?.query, // @ts-ignore cookie: b?.cookie ?? a?.cookie, // ? This order is correct - SaltyAom response: mergeResponse( // @ts-ignore a?.response, // @ts-ignore b?.response ), type: a?.type || b?.type, detail: mergeDeep( // @ts-ignore b?.detail ?? {}, // @ts-ignore a?.detail ?? {} ), parse: mergeObjectArray(a?.parse, b?.parse), transform: mergeObjectArray(a?.transform, b?.transform), beforeHandle: mergeObjectArray( mergeObjectArray( // @ts-ignore fnToContainer(a?.resolve, "resolve"), a?.beforeHandle ), mergeObjectArray( fnToContainer(b.resolve, "resolve"), b?.beforeHandle ) ), afterHandle: mergeObjectArray(a?.afterHandle, b?.afterHandle), mapResponse: mergeObjectArray(a?.mapResponse, b?.mapResponse), afterResponse: mergeObjectArray( a?.afterResponse, b?.afterResponse ), trace: mergeObjectArray(a?.trace, b?.trace), error: mergeObjectArray(a?.error, b?.error) }; return hook.resolve && delete hook.resolve, hook; }, lifeCycleToArray = (a) => { a.parse && !Array.isArray(a.parse) && (a.parse = [a.parse]), a.transform && !Array.isArray(a.transform) && (a.transform = [a.transform]), a.afterHandle && !Array.isArray(a.afterHandle) && (a.afterHandle = [a.afterHandle]), a.mapResponse && !Array.isArray(a.mapResponse) && (a.mapResponse = [a.mapResponse]), a.afterResponse && !Array.isArray(a.afterResponse) && (a.afterResponse = [a.afterResponse]), a.trace && !Array.isArray(a.trace) && (a.trace = [a.trace]), a.error && !Array.isArray(a.error) && (a.error = [a.error]); let beforeHandle = []; return a.resolve && (beforeHandle = fnToContainer( // @ts-expect-error Array.isArray(a.resolve) ? a.resolve : [a.resolve], "resolve" ), delete a.resolve), a.beforeHandle && (beforeHandle.length ? beforeHandle = beforeHandle.concat( Array.isArray(a.beforeHandle) ? a.beforeHandle : [a.beforeHandle] ) : beforeHandle = Array.isArray(a.beforeHandle) ? a.beforeHandle : [a.beforeHandle]), beforeHandle.length && (a.beforeHandle = beforeHandle), a; }, 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; }, injectChecksum = (checksum2, x) => { if (!x) return; if (!Array.isArray(x)) { let fn = x; return checksum2 && !fn.checksum && (fn.checksum = checksum2), fn.scope === "scoped" && (fn.scope = "local"), fn; } let fns = [...x]; for (let fn of fns) checksum2 && !fn.checksum && (fn.checksum = checksum2), fn.scope === "scoped" && (fn.scope = "local"); return fns; }, mergeLifeCycle = (a, b, checksum2) => ({ start: mergeObjectArray( a.start, injectChecksum(checksum2, b?.start) ), request: mergeObjectArray( a.request, injectChecksum(checksum2, b?.request) ), parse: mergeObjectArray( a.parse, injectChecksum(checksum2, b?.parse) ), transform: mergeObjectArray( a.transform, injectChecksum(checksum2, b?.transform) ), beforeHandle: mergeObjectArray( mergeObjectArray( // @ts-ignore fnToContainer(a.resolve, "resolve"), a.beforeHandle ), injectChecksum( checksum2, mergeObjectArray( fnToContainer(b?.resolve, "resolve"), b?.beforeHandle ) ) ), afterHandle: mergeObjectArray( a.afterHandle, injectChecksum(checksum2, b?.afterHandle) ), mapResponse: mergeObjectArray( a.mapResponse, injectChecksum(checksum2, b?.mapResponse) ), afterResponse: mergeObjectArray( a.afterResponse, injectChecksum(checksum2, b?.afterResponse) ), // Already merged on Elysia._use, also logic is more complicated, can't directly merge trace: mergeObjectArray( a.trace, injectChecksum(checksum2, b?.trace) ), error: mergeObjectArray( a.error, injectChecksum(checksum2, b?.error) ), stop: mergeObjectArray( a.stop, injectChecksum(checksum2, b?.stop) ) }), asHookType = (fn, inject, { skipIfHasType = !1 }) => { if (!fn) return fn; if (!Array.isArray(fn)) return skipIfHasType ? fn.scope ??= inject : fn.scope = inject, fn; for (let x of fn) skipIfHasType ? x.scope ??= inject : x.scope = inject; return fn; }, filterGlobal = (fn) => { if (!fn) return fn; if (!Array.isArray(fn)) switch (fn.scope) { case "global": case "scoped": return { ...fn }; default: return { fn }; } let array = []; for (let x of fn) switch (x.scope) { case "global": case "scoped": array.push({ ...x }); break; } return array; }, filterGlobalHook = (hook) => ({ // rest is validator ...hook, type: hook?.type, detail: hook?.detail, parse: filterGlobal(hook?.parse), transform: filterGlobal(hook?.transform), beforeHandle: filterGlobal(hook?.beforeHandle), afterHandle: filterGlobal(hook?.afterHandle), mapResponse: filterGlobal(hook?.mapResponse), afterResponse: filterGlobal(hook?.afterResponse), error: filterGlobal(hook?.error), trace: filterGlobal(hook?.trace) }), 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]) ); function removeTrailingEquals(digest) { let trimmedDigest = digest; for (; trimmedDigest.endsWith("="); ) trimmedDigest = trimmedDigest.slice(0, -1); return trimmedDigest; } var encoder = new TextEncoder(), signCookie = async (val, secret) => { if (typeof val != "string") throw new TypeError("Cookie value must be provided as a string."); if (secret === null) throw new TypeError("Secret key must be provided."); let secretKey = await crypto.subtle.importKey( "raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, !1, ["sign"] ), hmacBuffer = await crypto.subtle.sign( "HMAC", secretKey, encoder.encode(val) ); return val + "." + removeTrailingEquals(Buffer.from(hmacBuffer).toString("base64")); }, unsignCookie = async (input, secret) => { if (typeof input != "string") throw new TypeError("Signed cookie string must be provided."); if (secret === null) throw new TypeError("Secret key must be provided."); let tentativeValue = input.slice(0, input.lastIndexOf(".")); return await signCookie(tentativeValue, secret) === input ? tentativeValue : !1; }, traceBackMacro = (extension, property, manage) => { if (!(!extension || typeof extension != "object" || !property)) for (let [key, value] of Object.entries(property)) { if (primitiveHookMap[key] || !(key in extension)) continue; let v = extension[key]; if (typeof v == "function") { let hook = v(value); if (typeof hook == "object") for (let [k, v2] of Object.entries(hook)) manage(k)({ fn: v2 }); } delete property[key]; } }, createMacroManager = ({ globalHook, localHook }) => (stackName) => (type, fn) => { if (typeof type == "function" && (type = { fn: type }), stackName === "resolve" && (type = { ...type, subType: "resolve" }), localHook[stackName] || (localHook[stackName] = []), typeof localHook[stackName] == "function" && (localHook[stackName] = [localHook[stackName]]), Array.isArray(localHook[stackName]) || (localHook[stackName] = [localHook[stackName]]), "fn" in type || Array.isArray(type)) { Array.isArray(type) ? localHook[stackName] = localHook[stackName].concat(type) : localHook[stackName].push(type); return; } let { insert = "after", stack = "local" } = type; typeof fn == "function" && (fn = { fn }), stack === "global" ? Array.isArray(fn) ? insert === "before" ? globalHook[stackName] = fn.concat( globalHook[stackName] ) : globalHook[stackName] = globalHook[stackName].concat(fn) : insert === "before" ? globalHook[stackName].unshift(fn) : globalHook[stackName].push(fn) : Array.isArray(fn) ? insert === "before" ? localHook[stackName] = fn.concat(localHook[stackName]) : localHook[stackName] = localHook[stackName].concat(fn) : insert === "before" ? localHook[stackName].unshift(fn) : localHook[stackName].push(fn); }, parseNumericString = (message) => { if (typeof message == "number") return message; if (message.length < 16) { if (message.trim().length === 0) return null; let length = Number(message); return Number.isNaN(length) ? null : length; } if (message.length === 16) { if (message.trim().length === 0) return null; let number = Number(message); return Number.isNaN(number) || number.toString() !== message ? null : number; } return null; }, isNumericString = (message) => parseNumericString(message) !== null, PromiseGroup = class { constructor(onError = console.error, onFinally = () => { }) { this.onError = onError; this.onFinally = onFinally; this.root = null; this.promises = []; } /** * The number of promises still being awaited. */ get size() { return this.promises.length; } /** * Add a promise to the group. * @returns The promise that was added. */ add(promise) { return this.promises.push(promise), this.root ||= this.drain(), this.promises.length === 1 && this.then(this.onFinally), promise; } async drain() { for (; this.promises.length > 0; ) { try { await this.promises[0]; } catch (error2) { this.onError(error2); } this.promises.shift(); } this.root = null; } // Allow the group to be awaited. then(onfulfilled, onrejected) { return (this.root ?? Promise.resolve()).then(onfulfilled, onrejected); } }, fnToContainer = (fn, subType) => { if (!fn) return fn; if (!Array.isArray(fn)) { if (typeof fn == "function" || typeof fn == "string") return subType ? { fn, subType } : { fn }; if ("fn" in fn) return fn; } let fns = []; for (let x of fn) typeof x == "function" || typeof x == "string" ? fns.push(subType ? { fn: x, subType } : { fn: x }) : "fn" in x && fns.push(x); return fns; }, localHookToLifeCycleStore = (a) => (a.start && (a.start = fnToContainer(a.start)), a.request && (a.request = fnToContainer(a.request)), a.parse && (a.parse = fnToContainer(a.parse)), a.transform && (a.transform = fnToContainer(a.transform)), a.beforeHandle && (a.beforeHandle = fnToContainer(a.beforeHandle)), a.afterHandle && (a.afterHandle = fnToContainer(a.afterHandle)), a.mapResponse && (a.mapResponse = fnToContainer(a.mapResponse)), a.afterResponse && (a.afterResponse = fnToContainer(a.afterResponse)), a.trace && (a.trace = fnToContainer(a.trace)), a.error && (a.error = fnToContainer(a.error)), a.stop && (a.stop = fnToContainer(a.stop)), a), lifeCycleToFn = (a) => { let lifecycle = /* @__PURE__ */ Object.create(null); return a.start?.map && (lifecycle.start = a.start.map((x) => x.fn)), a.request?.map && (lifecycle.request = a.request.map((x) => x.fn)), a.parse?.map && (lifecycle.parse = a.parse.map((x) => x.fn)), a.transform?.map && (lifecycle.transform = a.transform.map((x) => x.fn)), a.beforeHandle?.map && (lifecycle.beforeHandle = a.beforeHandle.map((x) => x.fn)), a.afterHandle?.map && (lifecycle.afterHandle = a.afterHandle.map((x) => x.fn)), a.mapResponse?.map && (lifecycle.mapResponse = a.mapResponse.map((x) => x.fn)), a.afterResponse?.map && (lifecycle.afterResponse = a.afterResponse.map((x) => x.fn)), a.error?.map && (lifecycle.error = a.error.map((x) => x.fn)), a.stop?.map && (lifecycle.stop = a.stop.map((x) => x.fn)), a.trace?.map ? lifecycle.trace = a.trace.map((x) => x.fn) : lifecycle.trace = [], lifecycle; }, cloneInference = (inference) => ({ body: inference.body, cookie: inference.cookie, headers: inference.headers, query: inference.query, set: inference.set, server: inference.server, path: inference.path, route: inference.route, url: inference.url }), redirect = (url, status2 = 302) => Response.redirect(url, status2), ELYSIA_FORM_DATA = Symbol("ElysiaFormData"), ELYSIA_REQUEST_ID = Symbol("ElysiaRequestId"), form = (items) => { let formData = new FormData(); if (formData[ELYSIA_FORM_DATA] = {}, items) for (let [key, value] of Object.entries(items)) { if (Array.isArray(value)) { formData[ELYSIA_FORM_DATA][key] = []; for (let v of value) value instanceof File ? formData.append(key, value, value.name) : value instanceof ElysiaFile ? formData.append(key, value.value, value.value?.name) : formData.append(key, value), formData[ELYSIA_FORM_DATA][key].push(value); continue; } value instanceof File ? formData.append(key, value, value.name) : value instanceof ElysiaFile ? formData.append(key, value.value, value.value?.name) : formData.append(key, value), formData[ELYSIA_FORM_DATA][key] = value; } return formData; }, randomId = () => { let uuid = crypto.randomUUID(); return uuid.slice(0, 8) + uuid.slice(24, 32); }, deduplicateChecksum = (array) => { if (!array.length) return []; let hashes = []; for (let i = 0; i < array.length; i++) { let item = array[i]; item.checksum && (hashes.includes(item.checksum) && (array.splice(i, 1), i--), hashes.push(item.checksum)); } return array; }, promoteEvent = (events, as = "scoped") => { if (events) { if (as === "scoped") { for (let event of events) "scope" in event && event.scope === "local" && (event.scope = "scoped"); return; } for (let event of events) "scope" in event && (event.scope = "global"); } }, getLoosePath = (path) => path.charCodeAt(path.length - 1) === 47 ? path.slice(0, path.length - 1) : path + "/", isNotEmpty = (obj) => { if (!obj) return !1; for (let _ in obj) return !0; return !1; }, encodePath = (path, { dynamic = !1 } = {}) => { let encoded = encodeURIComponent(path).replace(/%2F/g, "/"); return dynamic && (encoded = encoded.replace(/%3A/g, ":").replace(/%3F/g, "?")), encoded; }, supportPerMethodInlineHandler = (() => { if (typeof Bun > "u") return !0; let semver = Bun.version.split("."); return !(+semver[0] < 1 || +semver[1] < 2 || +semver[2] < 14); })(), sse = (payload) => (typeof payload == "string" && (payload = { data: payload }), payload.id === void 0 && (payload.id = randomId()), payload.toStream = () => { let payloadString = ""; return payload.id !== void 0 && payload.id !== null && (payloadString += `id: ${payload.id} `), payload.event && (payloadString += `event: ${payload.event} `), payload.retry !== void 0 && (payloadString += `retry: ${payload.retry} `), payload.data === null ? payloadString += `data: null ` : typeof payload.data == "string" ? payloadString += `data: ${payload.data} ` : typeof payload.data == "object" && (payloadString += `data: ${JSON.stringify(payload.data)} `), payloadString && (payloadString += ` `), payloadString; }, payload); // src/error.ts var env = typeof Bun < "u" ? Bun.env : typeof process < "u" ? process?.env : void 0, ERROR_CODE = Symbol("ElysiaErrorCode"), isProduction = (env?.NODE_ENV ?? env?.ENV) === "production", emptyHttpStatus = { 101: void 0, 204: void 0, 205: void 0, 304: void 0, 307: void 0, 308: void 0 }, ElysiaCustomStatusResponse = class { constructor(code, response) { let res = response ?? (code in InvertedStatusMap ? ( // @ts-expect-error Always correct InvertedStatusMap[code] ) : code); this.code = StatusMap[code] ?? code, code in emptyHttpStatus ? this.response = void 0 : this.response = res; } }, status = (code, response) => new ElysiaCustomStatusResponse(code, response), error = status, InternalServerError = class extends Error { constructor(message) { super(message ?? "INTERNAL_SERVER_ERROR"); this.code = "INTERNAL_SERVER_ERROR"; this.status = 500; } }, NotFoundError = class extends Error { constructor(message) { super(message ?? "NOT_FOUND"); this.code = "NOT_FOUND"; this.status = 404; } }, ParseError = class extends Error { constructor(cause) { super("Bad Request", { cause }); this.code = "PARSE"; this.status = 400; } }, InvalidCookieSignature = class extends Error { constructor(key, message) { super(message ?? `"${key}" has invalid cookie signature`); this.key = key; this.code = "INVALID_COOKIE_SIGNATURE"; this.status = 400; } }, mapValueError = (error2) => { if (!error2) return { summary: void 0 }; let { message, path, value, type } = error2, property = path.slice(1).replaceAll("/", "."), isRoot = path === ""; switch (type) { case 42: return { ...error2, summary: isRoot ? "Value should not be provided" : `Property '${property}' should not be provided` }; case 45: return { ...error2, summary: isRoot ? "Value is missing" : `Property '${property}' is missing` }; case 50: let quoteIndex = message.indexOf("'"), format = message.slice( quoteIndex + 1, message.indexOf("'", quoteIndex + 1) ); return { ...error2, summary: isRoot ? "Value should be an email" : `Property '${property}' should be ${format}` }; case 54: return { ...error2, summary: `${message.slice(0, 9).trim()} property '${property}' to be ${message.slice(8).trim()} but found: ${value}` }; case 62: let union = error2.schema.anyOf.map((x) => `'${x?.format ?? x.type}'`).join(", "); return { ...error2, summary: isRoot ? `Value should be one of ${union}` : `Property '${property}' should be one of: ${union}` }; default: return { summary: message, ...error2 }; } }, InvalidFileType = class _InvalidFileType extends Error { constructor(property, expected, message = `"${property}" has invalid file type`) { super(message); this.property = property; this.expected = expected; this.message = message; this.code = "INVALID_FILE_TYPE"; this.status = 422; Object.setPrototypeOf(this, _InvalidFileType.prototype); } toResponse(headers) { return isProduction ? new Response( JSON.stringify({ type: "validation", on: "body" }), { status: 422, headers: { ...headers, "content-type": "application/json" } } ) : new Response( JSON.stringify({ type: "validation", on: "body", summary: "Invalid file type", message: this.message, property: this.property, expected: this.expected }), { status: 422, headers: { ...headers, "content-type": "application/json" } } ); } }, ValidationError = class _ValidationError extends Error { constructor(type, validator, value, errors) { value && typeof value == "object" && value instanceof ElysiaCustomStatusResponse && (value = value.response); let error2 = errors?.First() || (isProduction ? void 0 : "Errors" in validator ? validator.Errors(value).First() : Value.Errors(validator, value).First()), customError = error2?.schema?.message || error2?.schema?.error !== void 0 ? typeof error2.schema.error == "function" ? error2.schema.error({ type, validator, value, get errors() { return [...validator.Errors(value)].map( mapValueError ); } }) : error2.schema.error : void 0, accessor = error2?.path || "root", message = ""; if (customError !== void 0) message = typeof customError == "object" ? JSON.stringify(customError) : customError + ""; else if (isProduction) message = JSON.stringify({ type: "validation", on: type, summary: mapValueError(error2).summary, message: error2?.message, found: value }); else { let schema = validator?.schema ?? validator, errors2 = "Errors" in validator ? [...validator.Errors(value)].map(mapValueError) : [...Value.Errors(validator, value)].map(mapValueError), expected; try { expected = Value.Create(schema); } catch (error3) { expected = { type: "Could not create expected value", // @ts-expect-error message: error3?.message, error: error3 }; } message = JSON.stringify( { type: "validation", on: type, summary: mapValueError(error2).summary, property: accessor, message: error2?.message, expected, found: value, errors: errors2 }, null, 2 ); } super(message); this.type = type; this.validator = validator; this.value = value; this.code = "VALIDATION"; this.status = 422; Object.setPrototypeOf(this, _ValidationError.prototype); } get all() { return "Errors" in this.validator ? [...this.validator.Errors(this.value)].map(mapValueError) : ( // @ts-ignore [...Value.Errors(this.validator, this.value)].map(mapValueError) ); } static simplifyModel(validator) { let model = "schema" in validator ? validator.schema : validator; try { return Value.Create(model); } catch { return model; } } get model() { return _ValidationError.simplifyModel(this.validator); } toResponse(headers) { return new Response(this.message, { status: 400, headers: { ...headers, "content-type": "application/json" } }); } }; // src/type-system/utils.ts var tryParse = (v, schema) => { try { return JSON.parse(v); } catch { throw new ValidationError("property", schema, v); } }; function createType(kind, func) { return TypeRegistry.Has(kind) || TypeRegistry.Set(kind, func), (options = {}) => Unsafe({ ...options, [Kind]: kind }); } var compile = (schema) => { try { let compiler = TypeCompiler.Compile(schema); return compiler.Create = () => Value2.Create(schema), compiler.Error = (v) => new ValidationError("property", schema, v, compiler.Errors(v)), compiler; } catch { return { Check: (v) => Value2.Check(schema, v), CheckThrow: (v) => { if (!Value2.Check(schema, v)) throw new ValidationError( "property", schema, v, Value2.Errors(schema, v) ); }, Decode: (v) => Value2.Decode(schema, v), Create: () => Value2.Create(schema), Error: (v) => new ValidationError( "property", schema, v, Value2.Errors(schema, v) ) }; } }, parseFileUnit = (size) => { if (typeof size == "string") switch (size.slice(-1)) { case "k": return +size.slice(0, size.length - 1) * 1024; case "m": return +size.slice(0, size.length -