UNPKG

elysia

Version:

Ergonomic Framework for Human

382 lines (381 loc) 15.1 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var dynamic_handle_exports = {}; __export(dynamic_handle_exports, { createDynamicErrorHandler: () => createDynamicErrorHandler, createDynamicHandler: () => createDynamicHandler }); module.exports = __toCommonJS(dynamic_handle_exports); var import_error = require("./error"); var import_fast_querystring = require("./fast-querystring"); var import_utils = require("./utils"); var import_cookies = require("./cookies"); var import_value = require("@sinclair/typebox/value"); const injectDefaultValues = (typeChecker, obj) => { for (const [key, keySchema] of Object.entries( // @ts-expect-error private typeChecker.schema.properties )) { obj[key] ??= keySchema.default; } }; const createDynamicHandler = (app) => { const { mapResponse, mapEarlyResponse } = app["~adapter"].handler; return async (request) => { const url = request.url, s = url.indexOf("/", 11), qi = url.indexOf("?", s + 1), path = qi === -1 ? url.substring(s) : url.substring(s, qi); const set = { cookie: {}, status: 200, headers: {} }; const context = Object.assign( {}, // @ts-expect-error app.singleton.decorator, { set, // @ts-expect-error store: app.singleton.store, request, path, qi, error: import_error.error, redirect: import_utils.redirect } ); try { if (app.event.request) for (let i = 0; i < app.event.request.length; i++) { const onRequest = app.event.request[i].fn; let response2 = onRequest(context); if (response2 instanceof Promise) response2 = await response2; response2 = mapEarlyResponse(response2, set); if (response2) return context.response = response2; } const handler = app.router.dynamic.find(request.method, path) ?? app.router.dynamic.find("ALL", path); if (!handler) throw new import_error.NotFoundError(); const { handle, hooks, validator, content, route } = handler.store; let body; if (request.method !== "GET" && request.method !== "HEAD") { if (content) { switch (content) { case "application/json": body = await request.json(); break; case "text/plain": body = await request.text(); break; case "application/x-www-form-urlencoded": body = (0, import_fast_querystring.parseQuery)(await request.text()); break; case "application/octet-stream": body = await request.arrayBuffer(); break; case "multipart/form-data": body = {}; const form = await request.formData(); for (const key of form.keys()) { if (body[key]) continue; const value = form.getAll(key); if (value.length === 1) body[key] = value[0]; else body[key] = value; } break; } } else { let contentType = request.headers.get("content-type"); if (contentType) { const index = contentType.indexOf(";"); if (index !== -1) contentType = contentType.slice(0, index); context.contentType = contentType; if (hooks.parse) for (let i = 0; i < hooks.parse.length; i++) { const hook = hooks.parse[i].fn; let temp = hook(context, contentType); if (temp instanceof Promise) temp = await temp; if (temp) { body = temp; break; } } delete context.contentType; if (body === void 0) { switch (contentType) { case "application/json": body = await request.json(); break; case "text/plain": body = await request.text(); break; case "application/x-www-form-urlencoded": body = (0, import_fast_querystring.parseQuery)(await request.text()); break; case "application/octet-stream": body = await request.arrayBuffer(); break; case "multipart/form-data": body = {}; const form = await request.formData(); for (const key of form.keys()) { if (body[key]) continue; const value = form.getAll(key); if (value.length === 1) body[key] = value[0]; else body[key] = value; } break; } } } } } context.route = route; context.body = body; context.params = handler?.params || void 0; context.query = qi === -1 ? {} : (0, import_fast_querystring.parseQuery)(url.substring(qi + 1)); context.headers = {}; for (const [key, value] of request.headers.entries()) context.headers[key] = value; const cookieMeta = Object.assign( {}, app.config?.cookie, // @ts-expect-error validator?.cookie?.config ); const cookieHeaderValue = request.headers.get("cookie"); context.cookie = await (0, import_cookies.parseCookie)( context.set, cookieHeaderValue, cookieMeta ? { secrets: cookieMeta.secrets !== void 0 ? typeof cookieMeta.secrets === "string" ? cookieMeta.secrets : cookieMeta.secrets.join(",") : void 0, sign: cookieMeta.sign === true ? true : cookieMeta.sign !== void 0 ? typeof cookieMeta.sign === "string" ? cookieMeta.sign : cookieMeta.sign.join(",") : void 0 } : void 0 ); const headerValidator = validator?.createHeaders?.(); if (headerValidator) injectDefaultValues(headerValidator, context.headers); const paramsValidator = validator?.createParams?.(); if (paramsValidator) injectDefaultValues(paramsValidator, context.params); const queryValidator = validator?.createQuery?.(); if (queryValidator) injectDefaultValues(queryValidator, context.query); if (hooks.transform) for (let i = 0; i < hooks.transform.length; i++) { const hook = hooks.transform[i]; const operation = hook.fn(context); if (hook.subType === "derive") { if (operation instanceof Promise) Object.assign(context, await operation); else Object.assign(context, operation); } else if (operation instanceof Promise) await operation; } if (validator) { if (headerValidator) { const _header = structuredClone(context.headers); for (const [key, value] of request.headers) _header[key] = value; if (validator.headers.Check(_header) === false) throw new import_error.ValidationError( "header", validator.headers, _header ); } else if (validator.headers?.Decode) context.headers = validator.headers.Decode(context.headers); if (paramsValidator?.Check(context.params) === false) { throw new import_error.ValidationError( "params", validator.params, context.params ); } else if (validator.params?.Decode) context.params = validator.params.Decode(context.params); if (queryValidator?.Check(context.query) === false) throw new import_error.ValidationError( "query", validator.query, context.query ); else if (validator.query?.Decode) context.query = validator.query.Decode(context.query); if (validator.createCookie?.()) { let cookieValue = {}; for (const [key, value] of Object.entries(context.cookie)) cookieValue[key] = value.value; if (validator.cookie.Check(cookieValue) === false) throw new import_error.ValidationError( "cookie", validator.cookie, cookieValue ); else if (validator.cookie?.Decode) cookieValue = validator.cookie.Decode( cookieValue ); } if (validator.createBody?.()?.Check(body) === false) throw new import_error.ValidationError("body", validator.body, body); else if (validator.body?.Decode) context.body = validator.body.Decode(body); } if (hooks.beforeHandle) for (let i = 0; i < hooks.beforeHandle.length; i++) { const hook = hooks.beforeHandle[i]; let response2 = hook.fn(context); if (hook.subType === "resolve") { if (response2 instanceof import_error.ElysiaCustomStatusResponse) { const result = mapEarlyResponse( response2, context.set ); if (result) return context.response = result; } if (response2 instanceof Promise) Object.assign(context, await response2); else Object.assign(context, response2); continue; } else if (response2 instanceof Promise) response2 = await response2; if (response2 !== void 0) { ; context.response = response2; if (hooks.afterHandle) for (let i2 = 0; i2 < hooks.afterHandle.length; i2++) { let newResponse = hooks.afterHandle[i2].fn( context ); if (newResponse instanceof Promise) newResponse = await newResponse; if (newResponse) response2 = newResponse; } const result = mapEarlyResponse(response2, context.set); if (result) return context.response = result; } } let response = typeof handle === "function" ? handle(context) : handle; if (response instanceof Promise) response = await response; if (hooks.afterHandle) if (!hooks.afterHandle.length) { const status = response instanceof import_error.ElysiaCustomStatusResponse ? response.code : set.status ? typeof set.status === "string" ? import_utils.StatusMap[set.status] : set.status : 200; const responseValidator = validator?.createResponse?.()?.[status]; if (responseValidator?.Check(response) === false) throw new import_error.ValidationError( "response", responseValidator, response ); else if (responseValidator?.Decode) response = responseValidator.Decode(response); } else { ; context.response = response; for (let i = 0; i < hooks.afterHandle.length; i++) { let newResponse = hooks.afterHandle[i].fn( context ); if (newResponse instanceof Promise) newResponse = await newResponse; const result = mapEarlyResponse( newResponse, context.set ); if (result !== void 0) { const responseValidator = ( // @ts-expect-error validator?.response?.[result.status] ); if (responseValidator?.Check(result) === false) throw new import_error.ValidationError( "response", responseValidator, result ); else if (responseValidator?.Decode) response = responseValidator.Decode(response); return context.response = result; } } } if (context.set.cookie && cookieMeta?.sign) { const secret = !cookieMeta.secrets ? void 0 : typeof cookieMeta.secrets === "string" ? cookieMeta.secrets : cookieMeta.secrets[0]; if (cookieMeta.sign === true) for (const [key, cookie] of Object.entries( context.set.cookie )) context.set.cookie[key].value = await (0, import_utils.signCookie)( cookie.value, "${secret}" ); else { const properties = validator?.cookie?.schema?.properties; for (const name of cookieMeta.sign) { if (!(name in properties)) continue; if (context.set.cookie[name]?.value) { context.set.cookie[name].value = await (0, import_utils.signCookie)( context.set.cookie[name].value, secret ); } } } } return mapResponse(context.response = response, context.set); } catch (error2) { const reportedError = error2 instanceof import_value.TransformDecodeError && error2.error ? error2.error : error2; return app.handleError(context, reportedError); } finally { if (app.event.afterResponse) for (const afterResponse of app.event.afterResponse) await afterResponse.fn(context); } }; }; const createDynamicErrorHandler = (app) => { const { mapResponse } = app["~adapter"].handler; return async (context, error2) => { const errorContext = Object.assign(context, { error: error2, code: error2.code }); errorContext.set = context.set; if (app.event.error) for (let i = 0; i < app.event.error.length; i++) { const hook = app.event.error[i]; let response = hook.fn(errorContext); if (response instanceof Promise) response = await response; if (response !== void 0 && response !== null) return context.response = mapResponse( response, context.set ); } return new Response( typeof error2.cause === "string" ? error2.cause : error2.message, { headers: context.set.headers, status: error2.status ?? 500 } ); }; }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { createDynamicErrorHandler, createDynamicHandler });