import { Domain, SettingsType2, Narrow } from '@palmares/core'; import { S as StatusCodes, R as RedirectionStatusCodes } from './status-RlKnv8eR.js'; import { FileLike } from './response/utils.js'; /** * Functional approach to creating a server adapter instead of the default class/inheritance approach. */ declare function serverResponseAdapter(args: { send: TSendFunction; redirect: TRedirectFunction; stream: TStreamFunction; sendFile: TSendFileFunction; }): { new (): ServerResponseAdapter & { redirect: TRedirectFunction; send: TSendFunction; stream: TStreamFunction; sendFile: TSendFileFunction; }; }; /** * This code here is responsible for translating the response from the palmares framework to the server. */ declare class ServerResponseAdapter { /** * This function is used for handling redirects. * * @param _server The {@link ServerAdapter} or {@link ServerlessAdapter} adapter. * @param _serverRequestAndResponseData The server request and response data. * @param _status The status code of the response. * @param _headers The headers of the response. * @param _redirectTo The redirect url. * * @returns - A promise that resolves with the data needed for redirection. This data is the data that * will be returned from the callback on the {@link ServerRouterAdapter.parseHandler} or * {@link ServerRouterAdapter.parseHandlers}. */ redirect(_serverAdapter: ServerAdapter | ServerlessAdapter, _serverInstance: any, _serverRequestAndResponseData: any, _status: number, _headers: { [key: string]: string; } | undefined, _redirectTo: string): Promise; /** * This function is used for handling sending data to the client. * * @param _server The {@link ServerAdapter} or {@link ServerlessAdapter} adapter. * @param _serverRequestAndResponseData The server request and response data. * @param _status The status code of the response. * @param _headers The headers of the response. * @param _body The body of the response. * * @returns A promise that resolves with the data needed for sending the response. */ send(_serverAdapter: ServerAdapter | ServerlessAdapter, _serverInstance: any, _serverRequestAndResponseData: any, _status: number, _headers: { [key: string]: string; } | undefined, _body: string): Promise; stream(_serverAdapter: ServerAdapter | ServerlessAdapter, _serverInstance: any, _serverRequestAndResponseData: any, _status: number, _headers: { [key: string]: string; } | undefined, _body: AsyncGenerator | Generator, _isAsync: boolean): Promise; sendFile(_serverAdapter: ServerAdapter | ServerlessAdapter, _serverInstance: any, _serverRequestAndResponseData: any, _status: number, _headers: { [key: string]: string; } | undefined, _filePath: Blob | ArrayBuffer): Promise; } declare const DEFAULT_RESPONSE_HEADERS_CONTENT_HEADER_KEY = "Content-Type"; declare const DEFAULT_RESPONSE_HEADERS_CONTENT_DISPOSITION_KEY = "Content-Disposition"; declare const DEFAULT_RESPONSE_CONTENT_HEADER_VALUE_JSON = "application/json"; declare const DEFAULT_RESPONSE_CONTENT_HEADER_VALUE_HTML = "text/html"; declare const DEFAULT_RESPONSE_CONTENT_HEADER_VALUE_TEXT = "plain/text"; declare const DEFAULT_RESPONSE_CONTENT_HEADER_VALUE_STREAM = "application/octet-stream"; declare const DEFAULT_RESPONSE_HEADERS_LOCATION_HEADER_KEY = "Location"; declare const DEFAULT_NOT_FOUND_STATUS_TEXT_MESSAGE = "Not Found"; declare const DEFAULT_SERVER_ERROR_STATUS_TEXT_MESSAGE = "Internal Server Error"; declare const DEFAULT_SERVER_ERROR_RESPONSE: (error: Error, settings: AllServerSettingsType, domains: Domain[]) => Response; declare const DEFAULT_SERVER_ERROR_INVALID_QUERY_OR_PARAMS: () => Response; type ModifiedResponsesFromMiddlewares, TMiddlewares extends readonly Middleware[] = []> = TMiddlewares extends [...infer TRestMiddlewares, infer TLastMiddleware] ? TLastMiddleware extends Middleware ? TLastMiddleware['response'] extends (response: Response) => Promise | infer TResponse ? TResponse extends Response ? ModifiedResponsesFromMiddlewares, TRestMiddlewares extends readonly Middleware[] ? TRestMiddlewares : []> : never : never : ModifiedResponsesFromMiddlewares : TFinalResponse; type ExtractResponsesFromMiddlewaresRequestAndRouterHandlers[]> = (ExtractAllHandlersType extends (request: any) => infer TResponse | Promise ? TResponse extends Response ? TResponse : never : never) | ExtractResponsesFromMiddlewaresRequestFromRouters | Response; /** * This will extract all of the responses from the middlewares of a tuple of routers. * You pass first a tuple of routers and then it will extract all of the responses from the `request` * function of those middlewares. It gets the children routers as well. * * @generics TRouters - A tuple of routers that will be used for extracting the responses from the * middlewares. We will traverse through the parent and all it's children. * @generics TFinalResponses - The final type of the responses, this is used for recursion and should not * be explicitly set. * * @returns - A union of {@link Response} instances */ type ExtractResponsesFromMiddlewaresRequestFromRouters[], TFinalResponses extends Response = never> = TRouters extends [infer TFirstRouter, ...infer TRestRouters] ? TFirstRouter extends BaseRouter | Omit, never> ? TMiddlewares extends readonly Middleware[] ? TMiddlewares extends readonly [infer TFirstMiddie, ...infer TRestMiddlewares] ? TFirstMiddie extends { request: (request: Request) => Promise | infer TResponseOrRequest; response: (response: any) => Promise | infer TResponse; } ? ExtractResponsesFromMiddlewaresRequestFromRouters[] ? TRestRouters : [], (TResponseOrRequest extends Response ? TResponseOrRequest : never) | (TResponse extends Response ? TResponse : never)> | ExtractResponsesFromMiddlewaresRequestFromRouters[] ? TRouterChildren : [], (TResponseOrRequest extends Response ? TResponseOrRequest : never) | (TResponse extends Response ? TResponse : never)> | ExtractResponsesFromMiddlewaresRequestFromRouters<[ BaseRouter ], (TResponseOrRequest extends Response ? TResponseOrRequest : never) | (TResponse extends Response ? TResponse : never)> : ExtractResponsesFromMiddlewaresRequestFromRouters[] ? TRestRouters : [], TFinalResponses> | ExtractResponsesFromMiddlewaresRequestFromRouters[] ? TRouterChildren : [], TFinalResponses> | ExtractResponsesFromMiddlewaresRequestFromRouters<[ BaseRouter ], TFinalResponses> : TFinalResponses : ExtractResponsesFromMiddlewaresRequestFromRouters[] ? TRestRouters : [], TFinalResponses> | ExtractResponsesFromMiddlewaresRequestFromRouters[] ? TRouterChildren : [], TFinalResponses> : TFinalResponses : TFinalResponses; type ExtractResponsesFromMiddlewaresRequest = never> = TMiddlewares extends readonly [infer TFirstMiddie, ...infer TRestMiddlewares] ? TFirstMiddie extends Middleware ? TFirstMiddie['request'] extends (request: Request) => Promise | infer TResponseOrRequest ? Exclude> extends never ? ExtractResponsesFromMiddlewaresRequest : TResponseOrRequest extends Response ? ExtractResponsesFromMiddlewaresRequest>, [ ...TMiddlewaresPassed, TFirstMiddie ]> | TFinalResponses> : never : never : never : TFinalResponses; type DefaultResponseType = Response; type ResponseTypeType = 'basic' | 'cors' | 'error' | 'opaque' | 'opaqueredirect'; type MimeTypes = 'audio/aac' | 'video/x-msvideo' | 'image/avif' | 'video/av1' | 'application/octet-stream' | 'image/bmp' | 'text/css' | 'text/csv' | 'application/vnd.ms-fontobject' | 'application/epub+zip' | 'image/gif' | 'application/gzip' | 'text/html' | 'image/x-icon' | 'text/calendar' | 'image/jpeg' | 'text/javascript' | 'application/json' | 'application/ld+json' | 'audio/x-midi' | 'audio/mpeg' | 'video/mp4' | 'video/mpeg' | 'audio/ogg' | 'video/ogg' | 'application/ogg' | 'audio/opus' | 'font/otf' | 'application/pdf' | 'image/png' | 'application/rtf' | 'image/svg+xml' | 'image/tiff' | 'video/mp2t' | 'font/ttf' | 'text/plain' | 'application/wasm' | 'video/webm' | 'audio/webm' | 'image/webp' | 'font/woff' | 'font/woff2' | 'application/xhtml+xml' | 'application/xml' | 'application/zip' | 'video/3gpp' | 'video/3gpp2' | 'model/gltf+json' | 'model/gltf-binary'; type ResponseHeaderTypes = 'Access-Control-Allow-Credentials' | 'Access-Control-Allow-Headers' | 'Access-Control-Allow-Methods' | 'Access-Control-Allow-Origin' | 'Access-Control-Expose-Headers' | 'Access-Control-Max-Age' | 'Age' | 'Allow' | 'Cache-Control' | 'Clear-Site-Data' | 'Content-Disposition' | 'Content-Encoding' | 'Content-Language' | 'Content-Length' | 'Content-Location' | 'Content-Range' | 'Content-Security-Policy' | 'Content-Security-Policy-Report-Only' | 'Content-Type' | 'Cookie' | 'Cross-Origin-Embedder-Policy' | 'Cross-Origin-Opener-Policy' | 'Cross-Origin-Resource-Policy' | 'Date' | 'ETag' | 'Expires' | 'Last-Modified' | 'Location' | 'Permissions-Policy' | 'Pragma' | 'Retry-After' | 'Save-Data' | 'Sec-CH-Prefers-Color-Scheme' | 'Sec-CH-Prefers-Reduced-Motion' | 'Sec-CH-UA' | 'Sec-CH-UA-Arch' | 'Sec-CH-UA-Bitness' | 'Sec-CH-UA-Form-Factor' | 'Sec-CH-UA-Full-Version' | 'Sec-CH-UA-Full-Version-List' | 'Sec-CH-UA-Mobile' | 'Sec-CH-UA-Model' | 'Sec-CH-UA-Platform' | 'Sec-CH-UA-Platform-Version' | 'Sec-CH-UA-WoW64' | 'Sec-Fetch-Dest' | 'Sec-Fetch-Mode' | 'Sec-Fetch-Site' | 'Sec-Fetch-User' | 'Sec-GPC' | 'Server' | 'Server-Timing' | 'Service-Worker-Navigation-Preload' | 'Set-Cookie' | 'Strict-Transport-Security' | 'Timing-Allow-Origin' | 'Trailer' | 'Transfer-Encoding' | 'Upgrade' | 'Vary' | 'WWW-Authenticate' | 'Warning' | 'X-Content-Type-Options' | 'X-DNS-Prefetch-Control' | 'X-Frame-Options' | 'X-Permitted-Cross-Domain-Policies' | 'X-Powered-By' | 'X-Robots-Tag' | 'X-XSS-Protection'; type HeadersType = Record<'Content-Type', MimeTypes> | Record | Record; declare class Response AsyncGenerator | Generator) | string | object = undefined, TResponse extends { status?: StatusCodes; responses?: Record Response | Promise>> | undefined; headers?: HeadersType | unknown; context?: object | unknown; } = { status: undefined; responses: undefined; headers: undefined; context: undefined; }> { /** * This is data sent by the server, you can use it to translate your request and response during the * lifecycle of Request/Response. * * Think like that, on express: * * ```ts * app.use((req, res, next) => { * const serverRequestAndResponseData = { req, res }; * await wrappedHandler(serverRequestAndResponseData); * }); * ``` */ protected $$type: string; private __serverRequestAndResponseData; private __serverInstance; private __error; readonly url: string; readonly ok: boolean; readonly redirected: boolean; readonly type: ResponseTypeType; readonly bodyUsed: boolean; readonly responses?: TResponse['responses']; statusText: string; status: TResponse['status'] extends StatusCodes ? TResponse['status'] : undefined; body: TBody; headers: TResponse['headers'] extends object ? TResponse['headers'] : undefined; context: TResponse['context'] extends object ? TResponse['context'] : undefined; /** * # IMPORTANT * We advise you to use the static methods instead of this constructor directly, it will not set the * headers and status correctly so it can lead to unexpected behavior. * Need to clone a response? Use the {@link Response.clone} method instead. * * @param body - The body of the response, it doesn't support FormData, but it supports Blob, ArrayBuffer, * string and object. * @param options - The options of the response. */ constructor(body?: TBody, options?: TResponse & { statusText?: string; }); /** * This method is a factory method that should be used to send a response with a json body. * * By default, it will set the status to 200 and set the content-type header to application/json. * * @example * ```ts * import { Response, path } from '@palmares/server'; * * path('/users').get(async () => { * const users = await getUsers(); * return Response.json(users); * }); * ``` * * @param body - The body to send as json. * @param options - The options to pass to the response. * * @returns - A response with the status set to 200 and the content-type header set to application/json. */ static json(body: TBody, options?: TResponse): Response; /** * Streams a response back to the client. Instead of using a ReadableStream (which is not Supported by * things like React Native.) We opted to use a generator function instead. * You just need to return a generator function that yields chunks of data, and we will stream it back to * the client. Seems easy enough, right? * * @example * ```ts * import { Response, path } from '@palmares/server'; * * path('/users').get(async () => { * const users = await getUsers(); * return Response.stream(function* () { * for (const user of users) { * yield JSON.stringify(user); * } * }); * }); * ``` * * @param body - The generator function to stream back to the client. * @param options - The options to pass to the response. * * @returns - A response with the status set to 200 and the content-type header set to application/octet-stream. */ static stream AsyncGenerator | Generator, TResponse extends { status?: StatusCodes; headers?: object | unknown; context?: object | unknown; } = { status: undefined; headers: undefined; context: undefined; }>(body: TBody, options?: TResponse & { statusText?: string; }): Response, { context: TResponse["context"] extends object ? TResponse["context"] : undefined; headers: (TResponse["headers"] extends object ? TResponse["headers"] : object) & { [DEFAULT_RESPONSE_HEADERS_CONTENT_HEADER_KEY]: string; }; status: TResponse["status"] extends StatusCodes ? TResponse["status"] : 200 | 201; }>; /** * Sends a response back to the client, by default it will set the status to 200 and we will try to * retrieve the content-type from the Blob body sent. * If you also want to send the filename, you can pass it as the second argument using the `filename` * key, OR you can send a FileLike object as the body. * * @example * ```ts * import { Response, FileLike, path } from '@palmares/server'; * * path('/users').get(async () => { * const blob = new Blob(['Hello, world!'], { type: 'text/plain;charset=utf-8' }); * return Response.file(blob, { filename: 'hello.txt' }); * }); * * // OR * * path('/users').get(async () => { * const blob = new Blob(['Hello, world!'], { type: 'text/plain;charset=utf-8' }); * return Response.file(new FileLike(blob, 'hello.txt')); * }); * ``` * * @example * ```ts * import { Response, path } from '@palmares/server'; * * path('/users').get(async () => { * const blob = new Blob(['Hello, world!'], { type: 'text/plain;charset=utf-8' }); * return Response.file(blob); * }); * ``` * * @example * ```ts * import { Response, path } from '@palmares/server'; * * path('/users').get(async () => { * const blob = new Blob(['Hello, world!'], { type: 'text/plain;charset=utf-8' }); * const arrayBuffer = await blob.arrayBuffer(); * return Response.file(arrayBuffer); * }); * ``` * * @param body - The generator function to stream back to the client. * @param options - The options to pass to the response. * * @returns - A response with the status set to 200 and the content-type header set to application/octet-stream. */ static file(body: TBody, options?: TResponse & { statusText?: string; filename?: string; }): Response; /** * This method should be used to redirect to another page. * By default, it will set the status to 302 and set the location header to the url passed as argument. * * @param url - The url to redirect to. * @param options - The options to pass to the response. * * @example * ```ts * import { Response, path } from '@palmares/server'; * * path('/login').post(async (request) => { * const { username, password } = await request.json(); * if (username === 'admin' && password === 'admin') return Response.redirect('/admin'); * return Response.redirect('/login'); * }); * ``` * * @returns - A response with the status set to 302 and the location header set to the url passed as argument. */ static redirect(url: TUrl, options?: TResponse): Response; /** * Factory method to create a response with a html body. This will set the content-type header to text/html. * * @example * ``` * import { Response, path } from '@palmares/server'; * * path('/users').get(async () => { * return Response.html('

Hello World

'); * }); * ``` * * @param htmlBody - The html body to send as a string. * @param options - The options to pass to the response object. * * @returns - A response with the status set to 200 and the content-type header set to text/html. */ static html(htmlBody: string, options?: TResponse & { statusText?: string; }): Response; /** * Factory method to create a response with a html body. This will set the content-type header to text/html. * * @example * ``` * import { Response, path } from '@palmares/server'; * * path('/users').get(async () => { * return Response.html('

Hello World

'); * }); * ``` * * @param htmlBody - The html body to send as a string. * @param options - The options to pass to the response object. * * @returns - A response with the status set to 200 and the content-type header set to text/html. */ static text(text: string, options?: TResponse & { statusText?: string; }): Response; /** * This method should be used to send a response with a 500 status code. It will NOT call the error handler. * * @example * ```ts * import { Response, path } from '@palmares/server'; * * path('/users').get(async () => { * const users = await getUsers(); * return Response.error(); * }); * ``` * * @returns - A response with the status set to 500. */ static error(): Response; /** * You know? Sometimes s*it happens, and you need to send an error back to the client. This method is u * sed so you can retrieve the error metadata. This is helpful on the `handler500` on your settings. * You can also extract errors on custom middlewares so you can properly handle them. * * @example * ```ts * import { middleware, Response, path } from '@palmares/server'; * * const validationMiddleware = middleware({ * response: (response) => { * const error = response.error(); * if (error) { * // Do something with the error. * } * return response; * } * }); * * * path('/users').get(async () => { * const users = await getUsers(); * throw new Error('Something went wrong'); * }).middlewares([validationMiddleware]); * ```` * * @returns - The error object. */ error(): TError; /** * This method should be used to throw a {@link Response}. Throwing a Response will not trigger the * `handler500` function. * * Use it when you want to throw stuff like 404, 403, 401, etc. This is a syntatic sugar for `throw * Response(response)`. * * @example * ```ts * import { Response, path, HTTP_404_NOT_FOUND } from '@palmares/server'; * * function fetchUsersOrThrow() { * const users = await getUsers(); * if (!users) Response.json({ message: 'Users not found' }, { status: HTTP_404_NOT_FOUND }).throw(); * return users; * } * * path('/users').get(async () => { * const users = await fetchUsersOrThrow(); * return Response.json(users); * }); * */ throw(): void; /** * This is similar to the {@link Request.clone()} method. By default it will modify the response in place, * but you can set the `inPlace` option to false to return a new response. * * @param args - The arguments to pass to the new response. * @param options - The options to pass to the new response. */ clone(args?: TNewResponse, options?: { inPlace: boolean; }): Response; /** * This method is used to get the underlying server data. This is similar to {@link Request.serverData()} * method. This is useful usually on middlewares, not on handlers. * This is the underlying serverData. The documentation of this should be provided by the framework you * are using underlined with Palmares. * So, the idea is simple, when a request is made, the underlying framework will call a callback we * provide passing the data it needs to handle both the request and the response. For Express.js for * example this will be an object containing both the `req` and `res` objects. If for some reason you * need some data or some functionality we do not support by default you can, at any time, call this * function and get this data. * * ### IMPORTANT * * It's not up for us to document this, ask the library author of the adapter to provide a documentation * and properly type this. * * ### IMPORTANT2 * * Understand that when you create a new instance of response we will not have the server data attached to * it, so calling this method will return undefined. * You should use the request to attach the server data to the response. This method is useful for * middlewares, and only that. * * @example * ```ts * // on settings.ts * import { ExpressServerAdapter } from '@palmares/express-adapter'; * import ServerDomain from '@palmares/server'; * * export default defineSettings({ * //...other configs, * installedDomains: [ * [ * ServerDomain, * { * servers: { * default: { * server: ExpressServerAdapter, * // ...other configs, * }, * }, * }, * ], * ], * }); * * // on controllers.ts * import { middleware, path } from '@palmares/server'; * import type { Request, Response } from 'express'; * * const request = new Request(); * request.serverData(); // undefined * * path('/test').get((request) => { * const response = Response.json({ hello: 'World' }); * response.serverData(); // undefined, we have not appended the server data just yet, you should use * // request for that. * return response * }).middlewares([ * middleware({ * response: (response) => { * response.serverData(); // { req: Request, res: Response } * } * }) * }); * ``` * * @returns - The underlying server data. */ serverData(): T; /** * This method will extract the body of the response as a json object. * If the response is not a json response, it will return undefined. * * @example * ```ts * import { Response, path } from '@palmares/server'; * * path('/users').get(async () => { * const users = await getUsers(); * const response = Response.json(users); * await response.json(); // This will return the users object. * return response; * }); * ``` * * @returns - The body of the response as a json object. */ json(): Promise; /** * This method will extract the body of the response as a string. * * @example * ```ts * import { Response, path } from '@palmares/server'; * * path('/users').get(async () => { * const users = await getUsers(); * const response = Response.json(users); * await response.text(); // This will return the users object as a string. * return response; * }); * ``` * * @returns - The body of the response as a string. */ text(): Promise; arrayBuffer(): Promise; blob(): Promise; /** * You can use this method to get the body of the response as a FormData, you cannot send FormData though, * we don't currently support it. * * @example * ```ts * import { Response, path } from '@palmares/server'; * * path('/users').post(async (request) => { * const formData = await request.formData(); * const response = new Response(formData); * * await response.formData() // This will return the formData passed as argument. * * return response; * }); * ``` * * @returns - The body of the response as a {@link FormDataLike} object. */ formData(): Promise { value: string | Blob | File; fileName?: string; }[]; getKeys: () => string[]; }): /*elided*/ any; }>[0]; data: Record; append(name: string, value: string | Blob | File, fileName?: string): void; get(name: string): string | Blob | null; getAll(name: string): any[]; has(name: string): boolean; set(name: string, value: string | Blob | File, fileName?: string): void; delete(name: string): void; toJSON(): Record; } | undefined>; } type AllServerSettingsType = SettingsType2 & ServersSettingsType; type ServerSettingsType = { server: typeof ServerAdapter | typeof ServerlessAdapter; /** * The root middlewares to be used by the server, all routes will be wrapped by those middlewares. Use case is for * cors, authentication and so on. */ middlewares?: Middleware[]; /** Defaults to 4000 */ port?: number; debug?: boolean; /** This is the settings for when initializing the server, for example custom options for express initialization or * custom options for fastify initialization */ customServerSettings?: TCustomServerSettings; prefix?: string; handler404?: NonNullable['response']; serverlessFolderLocation?: string; validation?: { handler?: (request: Request) => Response; /** * Those options are used to configure how we will validate the query and the url parameters. By default we will use * the `lazy` option. * * So let's explain what each option means: * * - `strict`: This will validate the query and the url parameters before the request is handled, if the validation * fails, the request will be rejected. * - `lazy`: This will validate the query and the url parameters only when they are used, if the validation fails, * the request will be rejected. This is the default option. * - `none`: This will not validate the query and the url parameters. * * Be aware that if you use the `strict` option we will not pass through the middlewares. Lazy option will pass * through the middlewares you passed during the request lifecycle. */ options?: { url?: 'strict' | 'lazy' | 'none'; query?: 'strict' | 'lazy' | 'none'; }; }; handler500?: NonNullable['response']; }; type DefaultRequestDefinitions = { adapter: (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter; }; type DefaultRouterDefinitions = { adapter: (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter; }; type ServersSettingsType = { servers: Record>; /** * Used for debugging purposes, it will show a error screen when an error occurs when trying to open the request. * Defaults to true. * * PLEASE, MAKE SURE TO SET THIS TO FALSE ON PRODUCTION. */ debug?: boolean; }; type ParseHandlersServer = Map ReturnType; options?: TCustomRouterOptions; }>; /** * Adapter used for translating Palmares router to the framework of choice router. * * Functional approach to creating a server adapter instead of the default class/inheritance approach. */ declare function serverRouterAdapter(args: { /** * Used for parsing each part of the route, instead of parsing the whole route all at once, the framework itself will * call this method for each part of the route. * * n this example we are parsing the route and following Express's route syntax, like /users/:id, /users/:id/posts, * /users/:id/posts/:postId, etc. So each url param will contain * a colon before the name of the param. * * @example * ```ts * parseRoute(server, partOfPath, urlParamType) { * if (urlParamType) return ':${partOfPath}`; * else return partOfPath; * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _partOfPath - The part of the path to be parsed. * @param _urlParamType - If the part of the path is a url param, this will be true, otherwise it will be false. * * @returns The parsed part of the path. */ parseRoute: TParseRouteFunction; /** * This method is used for loading a 405 handler, this will only be called if no handler is found for the requested * method. * * IMPORTANT: If you define a route handler OUTSIDE of palmares and we do not find the route, this will still be * called, because this is defined by your framework of choice. * * @example * ```ts * load404(server, handler) { * const initializedServer = servers.get(server.serverName)?.server; * if (initializedServer) { * initializedServer.use((req, res) => { * const serverRequestAndResponseData = { * req, * res, * }; * handler(serverRequestAndResponseData); * }); * } * }, * ``` * * @param _serverAdapter - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _server - The return value of the {@link ServerAdapter.load} method. * @param _handler - The handler is a simple callback function that receives a single parameter as argument. * Whatever you pass on this parameter can later be retrieved inside of {@link ServerResponseAdapter} and * {@link ServerRequestAdapter} methods. What you return on {@link ServerResponseAdapter.redirect} or * {@link ServerResponseAdapter.send} will be the return value of this method. */ load404: TLoad404Function; /** * Usually {@link parseHandlers()} is preferred, but if your framework supports all methods from the * {@link MethodTypes} enum, you can use this method instead. This method is used to parse one handler at a time. * * IMPORTANT: Don't forget to handle the `all` method, so it can be used to accept all methods. * * app.[method]() * @example * ```ts * parseHandler(server, path, method, handler, queryParams) { * const initializedServer = servers.get(server.serverName)?.server; * if (initializedServer) { * initializedServer[method](path, (req: Request, res: Response) => { * const serverRequestAndResponseData = { * req, * res, * }; * handler(serverRequestAndResponseData); * }); * } * }, * ``` * * @param _serverAdapter - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _server - The return value of the {@link ServerAdapter.load} method. * @param _path - The retrieved by calling {@link parseRoute()} method. * @param _method - The method to be used. * @param _handler - The handler is a simple callback function that receives a single parameter as argument. * Whatever you pass on this parameter can later be retrieved inside of {@link ServerResponseAdapter} and * {@link ServerRequestAdapter} methods. What you return on {@link ServerResponseAdapter.redirect} or * {@link ServerResponseAdapter.send} will be the return value of this method. * @param _queryParams - The query params so you can parse it and validate as you wish. */ parseHandler?: TParseHandlerFunction; /** * Use this method if you want to parse all handlers at once. Parse all handlers at once is ofter useful if your * framework doesn't support the same methods as us. With this method you can loop through each handler and parse * it or you can listen to all methods and parse them during the request/response lifecycle. * * Important: if this method is defined, {@link parseHandler()} will be ignored. * * @example * ```ts * parseHandlers(server, path, handlers, _, handler404) { * const initializedServer = servers.get(server.serverName)?.server; * if (initializedServer) { * const optionsHandler = handlers.get('options')?.handler; * const headHandler = handlers.get('head')?.handler; * const deleteHandler = handlers.get('delete')?.handler; * const getHandler = handlers.get('get')?.handler; * const postHandler = handlers.get('post')?.handler; * const putHandler = handlers.get('put')?.handler; * const patchHandler = handlers.get('patch')?.handler; * const allHandler = handlers.get('all')?.handler; * * // This will initialize the server routes. * initializedServer.all(path, (req: Request, res: Response) => { * const serverRequestAndResponseData = { * req, * res, * }; * if (optionsHandler && req.method === 'OPTIONS') { * optionsHandler(serverRequestAndResponseData); * return; * } else if (headHandler && req.method === 'HEAD') { * headHandler(serverRequestAndResponseData); * return; * } else if (deleteHandler && req.method === 'DELETE') { * deleteHandler(serverRequestAndResponseData); * return; * } else if (getHandler && req.method === 'GET') { * getHandler(serverRequestAndResponseData); * return; * } else if (postHandler && req.method === 'POST') { * postHandler(serverRequestAndResponseData); * return; * } else if (putHandler && req.method === 'PUT') { * putHandler(serverRequestAndResponseData); * return; * } else if (patchHandler && req.method === 'PATCH') { * patchHandler(serverRequestAndResponseData); * return; * } else if (allHandler) { * allHandler(serverRequestAndResponseData); * return; * } else handler404(serverRequestAndResponseData); * }); * } * }, * ``` * * @param _serverAdapter - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _server - The return value of the {@link ServerAdapter.load} method. * @param _path - The retrieved by calling {@link parseRoute()} method. * @param _methodsAndHandlers - A Map instance where the method is the key and the handler is the value. The handler * is a simple callback function that receives a single parameter as argument. Whatever you pass on this parameter can * later be retrieved inside of {@link ServerResponseAdapter} and {@link ServerRequestAdapter} methods. What you * return on {@link ServerResponseAdapter.redirect} or {@link ServerResponseAdapter.send} will be the return value of * the handlers callback. * @param _queryParams - The query params so you can parse it and validate as you wish. * @param _404Handler - The 404 handler. */ parseHandlers?: TParseHandlersFunction; }): { new (): ServerRouterAdapter & { parseRoute: TParseRouteFunction; parseHandler: TParseHandlerFunction; parseHandlers: TParseHandlersFunction; load404: TLoad404Function; }; }; /** * Adapter used for translating palmares router to the framework of choice router. */ declare class ServerRouterAdapter { /** * This method is used for loading a 404 handler, this will only be called if no handler is found for the requested * method. * * IMPORTANT: If you define a route handler OUTSIDE of palmares and we do not find the route, this will still be * called, because this is defined by your framework of choice. * * @example * ```ts * load404(_, server, handler) { * server.use((req, res) => { * const serverRequestAndResponseData = { * req, * res, * }; * handler(serverRequestAndResponseData); * }); * }, * ``` * * @param _serverAdapter - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _server - The return value of the {@link ServerAdapter.load} method. * @param _handler - The handler is a simple callback function that receives a single parameter as argument. * Whatever you pass on this parameter can later be retrieved inside of {@link ServerResponseAdapter} and * {@link ServerRequestAdapter} methods. What you return on {@link ServerResponseAdapter.redirect} or * {@link ServerResponseAdapter.send} will be the return value of this method. */ load404(_serverAdapter: ServerAdapter, _server: any, _handler: (serverRequestAndResponseData: any) => ReturnType): Promise; /** * Used for parsing each part of the route, instead of parsing the whole route all at once, the framework * itself will call this method for each part of the route. * * In this example we are parsing the route and following Express's route syntax, like /users/:id, /users/:id/posts, * /users/:id/posts/:postId, etc. So each url param will contain a colon before the name of the param. * * @example * ```ts * parseRoute(_, __, partOfPath, urlParamType) { * if (urlParamType) return ':${partOfPath}`; * else return partOfPath; * }, * ``` * * @param _serverAdapter - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _server - The return value of the {@link ServerAdapter.load} method. * @param _partOfPath - The part of the path to be parsed. * @param _urlParamType - If the part of the path is a url param, this will be true, otherwise it will be false. * * @returns The parsed part of the path. */ parseRoute(_serverAdapter: ServerAdapter, _server: any, _partOfPath: string, _urlParamType?: Parameters[1]): string | undefined; /** * Usually {@link parseHandlers()} is preferred, but if your framework supports all methods from the * {@link MethodTypes} enum, you can use this method instead. This method is used to parse one handler at a time. * * IMPORTANT: Don't forget to handle the `all` method, so it can be used to accept all methods. * * @example * ```ts * parseHandler(_, server, path, method, handler, queryParams) { * server[method](path, (req: Request, res: Response) => { * const serverRequestAndResponseData = { * req, * res, * }; * handler(serverRequestAndResponseData); * }); * }, * ``` * * @param _serverAdapter - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _server - The return value of the {@link ServerAdapter.load} method. * @param _path - The retrieved by calling {@link parseRoute()} method. * @param _method - The method to be used. * @param _handler - The handler is a simple callback function that receives a single parameter as argument. * Whatever you pass on this parameter can later be retrieved inside of {@link ServerResponseAdapter} and * {@link ServerRequestAdapter} methods. What you return on {@link ServerResponseAdapter.redirect} or * {@link ServerResponseAdapter.send} will be the return value of this method. * @param _queryParams - The query params so you can parse it and validate as you wish. */ parseHandler(_serverAdapter: ServerAdapter, _server: any, _path: string, _method: MethodTypes | 'all', _handler: (serverRequestAndResponseData: any) => ReturnType, _queryParams: BaseRouter['__queryParamsAndPath']['params'], _customOptions?: any): undefined; parseHandlers?(_serverAdapter: ServerAdapter, _server: any, _path: string, _methodsAndHandlers: ParseHandlersServer, _queryParams: BaseRouter['__queryParamsAndPath']['params'], _404Handler: (serverRequestAndResponseData: any) => ReturnType): undefined; } /** * Remove the optional properties from an object. * * @example * ```ts * type Test = { * a?: string; * b: number; * c?: boolean; * }; * type WithoutOptionals = RemoveOptionals; // { b: number } * ``` */ type RemoveOptionals = { [K in keyof T as undefined extends T[K] ? never : K]: T[K]; }; type Exact = (() => T extends TOne ? 1 : 0) extends () => T extends TTwo ? 1 : 0 ? TOne extends TTwo ? TTwo extends TOne ? true : false : false : false; /** * This will extract the request type by inferring the return type (when they are {@link Request}) of the `request` * function of the middlewares. * * Important: Take extra care when changing this type because it's used for inferring the request type on the handler * but also on the middleware, so it's used in a lot of places and can break things. * * @generics TPath - The path from the router, this is the full path by joining all the routers together. * @generics TMiddlewares - All the middlewares used by the router, from the root router to the handler. This will be * recursive, and it's used for inferring the request type. * @generics TMethod - The method used for the handler. Eg. 'GET' | 'POST', etc. * @generics TResponses - The responses that the handler can return. This is used for inferring the response type. * Instead of using `Response.json()` the user will be able to use `Response.json()` and the type will be inferred. * @generics TFinalRequest - This should not be defined, it's used for recursion. * * @returns - A new inferred {@link Request} instance. */ type ExtractRequestsFromMiddlewaresForServer Response | unknown; status: TKey; }>; } | undefined = undefined, TFinalRequest extends Request = Request> = TMiddlewares extends readonly [infer TFirstMiddie, ...infer TRestMiddlewares] ? TFirstMiddie extends Middleware ? ReturnType any ? TFirstMiddie['request'] : (...args: any[]) => never> extends Promise | never ? ExtractRequestsFromMiddlewaresForServer : undefined; headers: TFinalRequest['headers']; context: TFinalRequest['context']; cache: TFinalRequest['cache']; credentials: TFinalRequest['credentials']; integrity: TFinalRequest['integrity']; destination: TFinalRequest['destination']; referrer: TFinalRequest['referrer']; referrerPolicy: TFinalRequest['referrerPolicy']; redirect: TFinalRequest['redirect']; }> : TFinalRequest> : TFirstMiddie['request'] extends (request: Request) => Promise | infer TRequest ? Extract> extends Request ? ExtractRequestsFromMiddlewaresForServer>['body'] & TFinalRequest['body']; headers: Extract>['headers'] & TFinalRequest['headers']; context: Extract>['context'] & TFinalRequest['context']; responses: RemoveOptionals>['responses']> & (RemoveOptionals extends undefined ? unknown : RemoveOptionals) & (RemoveOptionals extends undefined ? unknown : RemoveOptionals); method: TMethod; mode: Extract>['mode'] extends RequestMode ? Extract>['mode'] : TFinalRequest['mode'] extends RequestMode ? TFinalRequest['mode'] : RequestMode; cache: Extract>['cache'] extends RequestCache ? Extract>['cache'] : TFinalRequest['cache'] extends RequestCache ? TFinalRequest['cache'] : RequestCache; credentials: Extract>['credentials'] extends RequestCredentials ? Extract>['credentials'] : TFinalRequest['credentials'] extends RequestCredentials ? TFinalRequest['credentials'] : RequestCredentials; integrity: Extract>['integrity'] extends string ? Extract>['integrity'] : TFinalRequest['integrity'] extends string ? TFinalRequest['integrity'] : string; destination: Extract>['destination'] extends RequestDestination ? Extract>['destination'] : TFinalRequest['destination'] extends RequestDestination ? TFinalRequest['destination'] : RequestDestination; referrer: Extract>['referrer'] extends string ? Extract>['referrer'] : TFinalRequest['referrer'] extends string ? TFinalRequest['referrer'] : string; referrerPolicy: Extract>['referrer'] extends ReferrerPolicy ? Extract>['referrer'] : TFinalRequest['referrer'] extends ReferrerPolicy ? TFinalRequest['referrer'] : ReferrerPolicy; redirect: Extract>['redirect'] extends RequestRedirect ? Extract>['redirect'] : TFinalRequest['redirect'] extends RequestRedirect ? TFinalRequest['redirect'] : RequestRedirect; }> : TFinalRequest> : ExtractRequestsFromMiddlewaresForServer : TFinalRequest> : ExtractRequestsFromMiddlewaresForServer : TFinalRequest> : ExtractRequestsFromMiddlewaresForServer : TFinalRequest> : TFinalRequest; type ExtractRequestsFromMiddlewaresForClient = Request, TFinalRequestClient extends Request = Request> = TMiddlewares extends readonly [infer TFirstMiddie, ...infer TRestMiddlewares] ? TFirstMiddie extends Middleware ? TFirstMiddie['request'] extends (request: infer TRequestClient) => Promise | infer TRequestServer ? TRequestClient extends Request ? TRequestServer extends Request ? TPreviousServerRequest extends Request ? Exact<{ method: TRequestClient['method']; headers: TRequestClient['headers']; body: TRequestClient['body']; context: TRequestClient['context']; mode: TRequestClient['mode']; cache: TRequestClient['cache']; credentials: TRequestClient['credentials']; integrity: TRequestClient['integrity']; destination: TRequestClient['destination']; referrer: TRequestClient['referrer']; referrerPolicy: TRequestClient['referrerPolicy']; redirect: TRequestClient['redirect']; }, { method: TPreviousServerRequest['method']; headers: TPreviousServerRequest['headers']; body: TPreviousServerRequest['body']; context: TPreviousServerRequest['context']; mode: TPreviousServerRequest['mode']; cache: TPreviousServerRequest['cache']; credentials: TPreviousServerRequest['credentials']; integrity: TPreviousServerRequest['integrity']; destination: TPreviousServerRequest['destination']; referrer: TPreviousServerRequest['referrer']; referrerPolicy: TRequestClient['referrerPolicy']; redirect: TPreviousServerRequest['redirect']; }> extends false ? ExtractRequestsFromMiddlewaresForClient : TFinalRequestClient> : ExtractRequestsFromMiddlewaresForClient : never : never : never : never : never : TFinalRequestClient; /** * This defines the options for the middleware, those are custom options that you pass to your middleware that will * either be available to the handler or to the {@link Request} or {@link Response} objects. */ type MiddlewareOptions = { responses?: { [TKey in StatusCodes]?: (...args: any[]) => Response | unknown; status: TKey; }>; } | undefined; customOptions?: TServerAdapter['routers']['parseHandlers'] extends (...args: any) => any ? NonNullable[3]['set']>[1]>['options'] : TServerAdapter['routers'] extends ServerRouterAdapter ? TServerAdapter['routers']['parseHandler'] extends (...args: any) => any ? Parameters[4] : never : never; }; /** * This class is used to create a new {@link Middleware} instance. * * First, it's important to understand how middlewares work: Middlewares are executed in the order they are * declared: `middlewares([middleware1, middleware2])` * * The execution lifecycle will be * _____________________________________________________________ * | V middleware1.request | //> middleware1.response | * |--||-----------------------|--||---------------------------| * | || middleware2.request | || middleware2.response | * |--||-----------------------|--||---------------------------| * | \\> handler ------------|--^ | * |-------------------------- |-------------------------------| * * In other words: * 1. middleware1.request is executed * 2. middleware2.request is executed * 3. handler is executed * 4. middleware2.response is executed * 5. middleware1.response is executed * * It works like an onion (the vegetable), we go IN the onion, the center is the handler and then we go * OUT of the onion on the reversed order. Let's say we return a {@link Response} * on middleware1.request, the handler will not be executed, and `middleware2.response` will never be executed, * just `middleware1.response`. * * Second, on the middleware, during the request lifecycle, there are two types of things you can do: * 1. You usually use a middleware to change the request until it reaches the handler * 2. OR you can use a middleware to respond to the request before it reaches the handler. * * This means the `request` can have return either a {@link Request} or a {@link Response}. * * The only usage of `response` is to make changes to {@link Response} before it is sent to the client, * like filtering out properties, adding headers, whatever. * * @example * ```ts * import { Middleware, Response, HTTP_401_UNAUTHORIZED } from '@palmares/server'; * * export class AuthenticateMiddleware extends Middleware { * request: async (request) => { * const bearerAuth = request.headers['Authorization']; * // make validation * if (isValid) { * const user = await getUserFromToken(bearerAuth); * const requestWithUser = request.clone({ * context: { user }, * }); * return requestWithUser; * } * return Response.json({ message: 'Unauthorized' }, { status: HTTP_401_UNAUTHORIZED }); * }, * response: (response) => { * const responseWithHeaders = response.clone({ * headers: { * 'X-Server': 'Palmares', * }, * }); * return responseWithHeaders; * }, * } * ``` */ declare class Middleware { /** * This function is executed during the request lifecycle. It can return a {@link Request} or a {@link Response}. * * If it returns a {@link Request}, the request will be passed to the next middleware or handler. If it's * a {@link Response}, the response will be sent to the passed middlewares until it's sent to the client. * * ### IMPORTANT * * Using `middleware` function it's nice if you explicitly define how the {@link Request} will enter the * function. This way we can correctly type the Request on the client. We will know how the data needs to * be sent to the server. * * ### IMPORTANT2 * * If you don't explicitly type the Request, at least explicitly type the returned {@link Request}. * This way we can correctly type the request on the handler. * * @example * ```ts * import { Middleware, Response, HTTP_401_UNAUTHORIZED } from '@palmares/server'; * * export class AuthenticateMiddleware extends Middleware { * request: async (request: Request { * const bearerAuth = request.headers['Authorization']; * // make validation * if (isValid) { * const user = await getUserFromToken(bearerAuth); * const requestWithUser = request.clone({ * context: { user }, * }); * return requestWithUser; * } * return Response.json({ message: 'Unauthorized' }, { status: HTTP_401_UNAUTHORIZED }); * }, * } * ``` * * @param request - An instance of {@link Request} with the data. * * @returns - A {@link Request} instance with the modified data or a {@link Response} instance if you want * to break the middleware chain. */ request: ((request: ExtractRequestsFromMiddlewaresForServer ? TInferMiddlewares extends readonly Middleware[] ? TInferMiddlewares : [] : []>) => Promise | DefaultRequestType | DefaultResponseType) | undefined; /** * This function is executed during the response lifecycle. It needs to return a {@link Response} instance. * Usually you will use this to either change the sent response entirely or to add some headers/data to * the response or filter out some properties. * * @example * ```ts * import { Middleware, Response, HTTP_401_UNAUTHORIZED } from '@palmares/server'; * * export class HelmetMiddleware extends Middleware { * response: async (response) => { * // Filter out properties * const responseWithHeaders = response.clone({ * headers: newHeaders * }); * return responseWithHeaders; * }, * }; * ``` * * @param response - An instance of {@link Response} with the data. * * @returns - A {@link Response} instance with the modified data. */ response: ((response: ExtractResponsesFromMiddlewaresRequestAndRouterHandlers<[TRouter]>) => Promise | DefaultResponseType) | undefined; options?: MiddlewareOptions | undefined; } /** * This function is used to create a new {@link Middleware} instance. It's a syntatic sugar over the inheritance/class * approach. * * First, it's important to understand how middlewares work: Middlewares are executed in the order they are * declared: `middlewares([middleware1, middleware2])` * * The execution lifecycle will be * _____________________________________________________________ * | V middleware1.request | //> middleware1.response | * |--||-----------------------|--||---------------------------| * | || middleware2.request | || middleware2.response | * |--||-----------------------|--||---------------------------| * | \\> handler ------------|--^ | * |-------------------------- |-------------------------------| * * In other words: * 1. middleware1.request is executed * 2. middleware2.request is executed * 3. handler is executed * 4. middleware2.response is executed * 5. middleware1.response is executed * * It works like an onion (the vegetable), we go IN the onion, the center is the handler and then we go OUT * of the onion on the reversed order. Let's say we return a {@link Response} on middleware1.request, the * handler will not be executed, and `middleware2.response` will never be executed, just `middleware1.response`. * * Second, on the middleware, during the request lifecycle, there are two types of things you can do: * 1. You usually use a middleware to change the request until it reaches the handler * 2. OR you can use a middleware to respond to the request before it reaches the handler. * * This means the `request` can have return either a {@link Request} or a {@link Response}. * * The only usage of `response` is to make changes to {@link Response} before it is sent to the client, like * filtering out properties, adding headers, whatever. * * @example * ```ts * import { middleware, Response, HTTP_401_UNAUTHORIZED } from '@palmares/server'; * * export const authenticateMiddleware = middleware({ * request: (request) => { * const bearerAuth = request.headers['Authorization']; * // make validation * if (isValid) { * const user = await getUserFromToken(bearerAuth); * const requestWithUser = request.clone({ * context: { user }, * }); * return requestWithUser; * } * return Response.json({ message: 'Unauthorized' }, { status: HTTP_401_UNAUTHORIZED }); * }, * response: (response) => { * const responseWithHeaders = response.clone({ * headers: { * 'X-Server': 'Palmares', * }, * }); * return responseWithHeaders; * }, * }); * ``` */ declare function middleware = never, TReturnOfRequestFunction extends Request | Response = never, TRouterMiddlewares = TRouter extends BaseRouter ? TInferMiddlewares extends readonly Middleware[] ? TInferMiddlewares : never : never>(options: { /** * This function is executed during the request lifecycle. It can return a {@link Request} or a {@link Response}. * * If it returns a {@link Request}, the request will be passed to the next middleware or handler. If it's a * {@link Response}, the response will be sent to the passed middlewares until it's sent to the client. * * ### IMPORTANT * * Using `middleware` function it's nice if you explicitly define how the {@link Request} will enter the * function. This way we can correctly type the Request on the client. We will know how the data needs to * be sent to the server. * * ### IMPORTANT2 * * If you don't explicitly type the Request, at least explicitly type the returned {@link Request}. This * way we can correctly type the request on the handler. * * @example * ```ts * import { middleware, Response, HTTP_401_UNAUTHORIZED } from '@palmares/server'; * * export const authenticateMiddleware = middleware({ * request: (request: Request { * const bearerAuth = request.headers['Authorization']; * // make validation * if (isValid) { * const user = await getUserFromToken(bearerAuth); * const requestWithUser = request.clone({ * context: { user }, * }); * return requestWithUser; * } * return Response.json({ message: 'Unauthorized' }, { status: HTTP_401_UNAUTHORIZED }); * }, * }); * ``` * * @param request - An instance of {@link Request} with the data. * * @returns - A {@link Request} instance with the modified data or a {@link Response} instance if you want * to break the middleware chain. */ request?: (request: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer : Request) => TReturnOfRequestFunction | Promise; /** * This function is executed during the response lifecycle. It needs to return a {@link Response} instance. * Usually you will use this to either change the sent response entirely or to add some headers/data to the * response or filter out some properties. * * @example * ```ts * import { middleware, Response, HTTP_401_UNAUTHORIZED } from '@palmares/server'; * * export const helmetMiddleware = middleware({ * response: (response) => { * // Filter out properties * const responseWithHeaders = response.clone({ * headers: newHeaders * }); * return responseWithHeaders; * }, * }); * ``` * * @param response - An instance of {@link Response} with the data. * * @returns - A {@link Response} instance with the modified data. */ response?: (response: (Exclude> | ExtractResponsesFromMiddlewaresRequestAndRouterHandlers<[TRouter]>) & { responses: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer['responses'] : TOptions['responses']; }) => Promise | TReturnOfResponseFunction; /** * Options are custom options that you can pass to the middleware. Usually, those options will exist on the * {@link Request} or {@link Response} instances. * * @example * ```ts * import { middleware, Response, path } from '@palmares/server'; * * export const helmetMiddleware = middleware({ * options: { * responses: { * '200': (message: string) => Response.json({ message }, { status: 200 }), * } * }, * }); * * path('/test').middlewares([helmetMiddleware]).get((request) => { * // return Response.json({ aDifferentBody: 20 }) // this will fail * return request.responses['200']('hello'); * }); * ``` * * @param options - The options passed to the middleware. * @param options.responses - The responses that the middleware can return, this will enforce that the * response returned from the handler is one of the responses defined here. */ options?: TOptions; }): Omit & { request: (request: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer : string) => TReturnOfRequestFunction | Promise; response: (response: (Exclude> | ExtractResponsesFromMiddlewaresRequestAndRouterHandlers<[TRouter]>) & { responses: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer["responses"] : TOptions["responses"]; }) => Promise | TReturnOfResponseFunction; options: TOptions extends undefined ? undefined : TOptions; }; /** * This functions is used to create a new {@link Middleware} instance. It's a syntatic sugar over the * inheritance/class approach. This function is pretty much the same as {@link middleware}, but it is * preferred over {@link middleware} when you want to create a middleware typesafe middleware for a specific router. * * See {@link middleware} for more information about how middlewares work in Palmares and it's lifecycle. * * @example * ```ts * import { nestedMiddleware, Response, HTTP_401_UNAUTHORIZED } from '@palmares/server'; * * import type { baseRouter } from './routes'; * * export const typingTestAuthenticateUserMiddleware = nestedMiddleware()({ * // This request is fully typed from the router, it contains the properties and the path of the router * request: (request) => { * const customRequest = request.clone<{ * context: { user: number }; * }>(); * return customRequest; * }, * // This response is fully typed from the router, it will contain the properties you return from the * // router handlers. * response: (response) => { * const modifiedResponse = response.clone(); * return modifiedResponse; * }, * }); * ``` */ declare function nestedMiddleware(): = never, TReturnOfRequestFunction extends Request | Response = never, TRouterMiddlewares = TRouter extends BaseRouter[], any, unknown, unknown, DefaultRouterDefinitions> ? TInferMiddlewares extends readonly Middleware[] ? TInferMiddlewares : never : never>(options: { /** * This function is executed during the request lifecycle. It can return a {@link Request} or a {@link Response}. * * If it returns a {@link Request}, the request will be passed to the next middleware or handler. If it's * a {@link Response}, the response will be sent to the passed middlewares until it's sent to the client. * * ### IMPORTANT * * Using `middleware` function it's nice if you explicitly define how the {@link Request} will enter the * function. This way we can correctly type the Request on the client. We will know how the data needs * to be sent to the server. * * ### IMPORTANT2 * * If you don't explicitly type the Request, at least explicitly type the returned {@link Request}. * This way we can correctly type the request on the handler. * * @example * ```ts * import { middleware, Response, HTTP_401_UNAUTHORIZED } from '@palmares/server'; * * export const authenticateMiddleware = middleware({ * request: (request: Request { * const bearerAuth = request.headers['Authorization']; * // make validation * if (isValid) { * const user = await getUserFromToken(bearerAuth); * const requestWithUser = request.clone({ * context: { user }, * }); * return requestWithUser; * } * return Response.json({ message: 'Unauthorized' }, { status: HTTP_401_UNAUTHORIZED }); * }, * }); * ``` * * @param request - An instance of {@link Request} with the data. * * @returns - A {@link Request} instance with the modified data or a {@link Response} instance if you * want to break the middleware chain. */ request?: (request: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer : Request) => TReturnOfRequestFunction | Promise; /** * This function is executed during the response lifecycle. It needs to return a {@link Response} instance. * Usually you will use this to either change the sent response entirely or to add some headers/data to * the response or filter out some properties. * * @example * ```ts * import { middleware, Response, HTTP_401_UNAUTHORIZED } from '@palmares/server'; * * export const helmetMiddleware = middleware({ * response: (response) => { * // Filter out properties * const responseWithHeaders = response.clone({ * headers: newHeaders * }); * return responseWithHeaders; * }, * }); * ``` * * @param response - An instance of {@link Response} with the data. * * @returns - A {@link Response} instance with the modified data. */ response?: (response: (Exclude> | ExtractResponsesFromMiddlewaresRequestAndRouterHandlers<[TRouter]>) & { responses: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer["responses"] : TOptions["responses"]; }) => Promise | TReturnOfResponseFunction; /** * Options are custom options that you can pass to the middleware. Usually, those options will exist on * the {@link Request} or {@link Response} instances. * * @example * ```ts * import { middleware, Response, path } from '@palmares/server'; * * export const helmetMiddleware = middleware({ * options: { * responses: { * '200': (message: string) => Response.json({ message }, { status: 200 }), * } * }, * }); * * path('/test').middlewares([helmetMiddleware]).get((request) => { * // return Response.json({ aDifferentBody: 20 }) // this will fail * return request.responses['200']('hello'); * }); * ``` * * @param options - The options passed to the middleware. * @param options.responses - The responses that the middleware can return, this will enforce that the * response returned from the handler is one of the responses defined here. */ options?: TOptions; }) => Omit & { options: TOptions extends undefined ? undefined : TOptions; request: (request: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer : Request) => TReturnOfRequestFunction | Promise; response: (response: ExtractResponsesFromMiddlewaresRequestAndRouterHandlers<[TRouter]>) => Promise | TReturnOfResponseFunction; }; declare function requestMiddleware, TRouter extends DefaultRouterType = DefaultRouterType>(): = never, TReturnOfRequestFunction extends Request | Response = never, TRouterMiddlewares = TRouter extends BaseRouter[], any, unknown, unknown, DefaultRouterDefinitions> ? TInferMiddlewares extends readonly Middleware[] ? TInferMiddlewares : never : never>(options: { /** * This function is executed during the request lifecycle. It can return a {@link Request} or a {@link Response}. * * If it returns a {@link Request}, the request will be passed to the next middleware or handler. If it's * a {@link Response}, the response will be sent to the passed middlewares until it's sent to the client. * * ### IMPORTANT * * Using `middleware` function it's nice if you explicitly define how the {@link Request} will enter the * function. This way we can correctly type the Request on the client. We will know how the data needs * to be sent to the server. * * ### IMPORTANT2 * * If you don't explicitly type the Request, at least explicitly type the returned {@link Request}. * This way we can correctly type the request on the handler. * * @example * ```ts * import { middleware, Response, HTTP_401_UNAUTHORIZED } from '@palmares/server'; * * export const authenticateMiddleware = middleware({ * request: (request: Request { * const bearerAuth = request.headers['Authorization']; * // make validation * if (isValid) { * const user = await getUserFromToken(bearerAuth); * const requestWithUser = request.clone({ * context: { user }, * }); * return requestWithUser; * } * return Response.json({ message: 'Unauthorized' }, { status: HTTP_401_UNAUTHORIZED }); * }, * }); * ``` * * @param request - An instance of {@link Request} with the data. * * @returns - A {@link Request} instance with the modified data or a {@link Response} instance if you * want to break the middleware chain. */ request?: (request: TRequest & ExtractRequestsFromMiddlewaresForServer) => TReturnOfRequestFunction | Promise; /** * This function is executed during the response lifecycle. It needs to return a {@link Response} instance. * Usually you will use this to either change the sent response entirely or to add some headers/data to * the response or filter out some properties. * * @example * ```ts * import { middleware, Response, HTTP_401_UNAUTHORIZED } from '@palmares/server'; * * export const helmetMiddleware = middleware({ * response: (response) => { * // Filter out properties * const responseWithHeaders = response.clone({ * headers: newHeaders * }); * return responseWithHeaders; * }, * }); * ``` * * @param response - An instance of {@link Response} with the data. * * @returns - A {@link Response} instance with the modified data. */ response?: (response: (Exclude> | ExtractResponsesFromMiddlewaresRequestAndRouterHandlers<[TRouter]>) & { responses: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer["responses"] : TOptions["responses"]; }) => Promise | TReturnOfResponseFunction; /** * Options are custom options that you can pass to the middleware. Usually, those options will exist on * the {@link Request} or {@link Response} instances. * * @example * ```ts * import { middleware, Response, path } from '@palmares/server'; * * export const helmetMiddleware = middleware({ * options: { * responses: { * '200': (message: string) => Response.json({ message }, { status: 200 }), * } * }, * }); * * path('/test').middlewares([helmetMiddleware]).get((request) => { * // return Response.json({ aDifferentBody: 20 }) // this will fail * return request.responses['200']('hello'); * }); * ``` * * @param options - The options passed to the middleware. * @param options.responses - The responses that the middleware can return, this will enforce that the * response returned from the handler is one of the responses defined here. */ options?: TOptions; }) => Omit & { options: TOptions extends undefined ? undefined : TOptions; request: (request: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer : Request) => TReturnOfRequestFunction | Promise; response: (response: ExtractResponsesFromMiddlewaresRequestAndRouterHandlers<[TRouter]>) => Promise | TReturnOfResponseFunction; }; type MethodTypes = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head' | 'options'; type MergeParentAndChildPathsType, TPathFromChild extends string> = TParentRouter extends BaseRouter ? TRootPath extends `${infer InferedRootPath}?${infer InferedQueryParams}` ? TPathFromChild extends `${infer InferedPathFromChild}?${infer InferedQueryParamsFromChild}` ? `${InferedRootPath}${InferedPathFromChild}?${InferedQueryParams}&${InferedQueryParamsFromChild}` : `${InferedRootPath}${TPathFromChild}?${InferedQueryParams}` : TPathFromChild extends `${infer InferedPathFromChild}?${infer InferedQueryParamsFromChild}` ? `${TRootPath}${InferedPathFromChild}?${InferedQueryParamsFromChild}` : `${TRootPath}${TPathFromChild}` : TPathFromChild; type ValidatedFullPathType = TMergedPath extends string | undefined ? TMergedPath : TPathFromChild; type MergeParentMiddlewaresType> = TParentRouter extends BaseRouter ? TParentMiddlewares extends readonly Middleware[] ? TParentMiddlewares['length'] extends 0 ? [] : TParentMiddlewares : [] : []; type ValidatedMiddlewaresType = TMiddlewares extends readonly Middleware[] ? TMiddlewares : []; type DefaultRouterType = BaseRouter; /** * Used for extracting the request type all the way from the root router to the handler, it knows where the request * has passed, to which middlewares. * This way we have a fully typesafe request object without writing a single type * * @generics TRootPath - The path from the router, this is the full path by joining all the routers together. * @generics TMiddlewares - All the middlewares used by the router, from the root router to the handler. This will be * recursive, and it's used for inferring the request type. * @generics TMethod - The method used for the handler. Eg. 'GET' | 'POST', etc. * @generics TResponses - The responses that the handler can return. This is used for documentation and also will exist * on the request object so you can retrieve it at any time and throw passing the parameters you want. */ type RequestOnHandlerType Response | Promise>> | undefined = undefined> = TMiddlewares['length'] extends 0 ? Request : ExtractRequestsFromMiddlewaresForServer; /** * This is used for defining the handler function. It will automatically infer the request type based on the * middlewares used. * * @generics TRootPath - The path from the router, this is the full path by joining all the routers together. * @generics TMiddlewares - All the middlewares used by the router, from the root router to the handler. This will be * recursive, and it's used for inferring the request type. * @generics TMethod - The method used for the handler. Eg. 'GET' | 'POST', etc. * @generics TResponses - The responses that the handler can return. This is used for inferring the response type. * Instead of using `Response.json()` the user will be able to use * `401: () => Response.json({ message: 'Something bad happened' }, { status: 404 })` */ type HandlerType Response | Promise>> | undefined = undefined> = (request: RequestOnHandlerType) => RequestOnHandlerType['responses'] extends never ? Promise> | Response : ExtractPossibleResponsesOfHandlerType['responses']>; /** * This is used for validating the response of the handler. If a response is defined on the handler or any * of the middlewares, if the response of the handler is not the one defined, it will error out. * * This is useful for validation. Suppose we want to guarantee that a response always follow a certain * structure, we can define it on the middlewares and the handler will be forced to follow that response. */ type ExtractPossibleResponsesOfHandlerType Response>> = ReturnType | Response extends `${infer TStatusCode extends StatusCodes}` ? TStatusCode : StatusCodes; }> | Promise extends `${infer TStatusCode extends StatusCodes}` ? TStatusCode : StatusCodes; }>>; /** * Used for appending the handlers to the router. This way we can then extract all of the handlers of a given router. * It is defined by each method it defines. * * @generics TRootPath - The path from the router, this is the full path by joining all the routers together. * @generics TMiddlewares - All the middlewares used by the router, from the root router to the handler. * This will be recursive, and it's used for inferring the request type. * * @returns - An object with all the methods defined in the router. */ type AlreadyDefinedMethodsType = { [key in MethodTypes]?: { handler: HandlerType; options?: RouterOptionsType; }; }; type DefineAlreadyDefinedMethodsType | unknown, THandler extends HandlerType, TOptions extends RouterOptionsType, TMethodType extends MethodTypes> = TAlreadyDefinedMethods extends object ? TAlreadyDefinedMethods & { [key in TMethodType]: { handler: THandler; options?: TOptions; }; } : { [key in TMethodType]: { handler: THandler; options?: TOptions; }; }; /** * This is responsible for extracting all handlers from a router, a handler is what will effectively be executed when a * request is made. This is used for knowing what type of {@link Request} is expected for the handler and what type * of {@link Response} will it return. * * @generics TRouters - A list of {@link BaseRouter} or {@link Omit} that will be used for extracting * the handlers. * @generics TFinalHandlers - The final type of the handlers, this is used for recursion and should not be used by * the user. * * @returns - The actual handler function. */ type ExtractAllHandlersType[], TFinalHandlers extends HandlerType = never> = TRouters extends [infer TFirstRouter, ...infer TRestRouters] ? TFirstRouter extends BaseRouter | Omit, never> ? (TDefinedHandlers[keyof TDefinedHandlers] extends { handler: any; options?: any; } ? TDefinedHandlers[keyof TDefinedHandlers]['handler'] : never) | TFinalHandlers | ExtractAllHandlersType[] ? TRouterChildren : [], TFinalHandlers> | ExtractAllHandlersType[] ? TRestRouters : [], TFinalHandlers> : TFinalHandlers : TFinalHandlers; /** * This will extract all the routers from a tuple of child routers, we will append those routers to the parent router. * * @generics TIncludes - A tuple of routers that will be used for extracting the routers. We will traverse through * the parent and all it's children. * @generics TRouters - The final type of the routers, this is used for recursion and SHOULD NOT be explicitly set. * * @returns - A union of {@link BaseRouter} instances */ type ExtractIncludes)[] | Narrow)[]>, TRouters extends readonly DefaultRouterType[]> = TIncludes extends readonly [infer TFirstRouter, ...infer TRestRouters] ? TRestRouters extends readonly (DefaultRouterType | Omit)[] ? TFirstRouter extends DefaultRouterType ? ExtractIncludes)[] ? TRestRouters : [], [ ...TRouters, TFirstRouter ]> : TFirstRouter extends Omit ? TRouter extends DefaultRouterType ? ExtractIncludes)[] ? TRestRouters : [], [ ...TRouters, TRouter ]> : TRouters : TRouters : TRouters : TRouters; type RouterOptionsType = MiddlewareOptions & { middlewares?: Narrow; }; type ExtractTRouteTreesFromChildren)[], TResult = unknown> = TRouters extends readonly [infer TRouterFirst, ...infer TRestRouters] ? TRouterFirst extends BaseRouter ? TRestRouters extends readonly (DefaultRouterType | Omit)[] ? ExtractTRouteTreesFromChildren : TResult & TRootTRouteTree : TResult : TResult; /** * This is the core of the types and for the application to work. * * For types: * - this class is used to keep track of all of the children as well as the parent. * - By keeping track of children and parent we can pretty much merge everything together and work nicely * with middleware, the handlers, and the path. * - Let's say for example that we defined a middleware on the parent that changes the Request, this change * should also be applied to the children routes. The same applies for the path, let's say that we defined a * custom parameter for the path on the parent, like an id. * * This should be applied to the children as well. * - Yu might ask, "but why a parent router keeping track of it's children is important?". Because of the * typing when using the router. * We want to know which routes we can "call", and what are the headers, data and basically everything else * we should send to them. * * For the application to work: * - Pretty much a router is a tree. One router is connected to another router, that is connected to another * router and so on. But basically * ALL applications will have just one route as entrypoint. * - Understand that the root router will know all the handlers, so you don't need to traverse everything everytime. */ declare class BaseRouter[] = never[], TRootPath extends string | undefined = undefined, TAlreadyDefinedHandlers extends AlreadyDefinedMethodsType | unknown = unknown, TRootRoutesTree = unknown, TDefinitions extends { adapter: (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter; } = DefaultRouterDefinitions> { path: TRootPath; protected __domain: Domain; protected __partsOfPath: { part: string; isUrlParam: boolean; }[]; protected __queryParamsAndPath: { path: string; params: Map; }; protected __urlParamsAndPath: { path: string; params: Map; }; protected __completePaths: Map; options?: RouterOptionsType; }; }; }>; protected __parentRouter?: TParentRouter; protected __wasCreatedFromNested: boolean; protected __children?: TChildren; protected __middlewares: TMiddlewares; protected __handlers: TAlreadyDefinedHandlers; constructor(path: TRootPath, children?: TChildren); static new(path: TPath): MethodsRouter; static newNested>(): , TMergedMiddlewares = MergeParentMiddlewaresType>(path: TPath) => MethodsRouter, ValidatedFullPathType, undefined, unknown, DefaultRouterDefinitions>; /** * Used for including other routers inside of this router. This way we can construct a tree of routers. And you * can use it to use the same middlewares and handlers for multiple routes. */ nested)[]>(children: ((router: ReturnType['child']>) => Narrow) | Narrow): MethodsRouter, TMiddlewares, TRootPath, TAlreadyDefinedHandlers, TRootRoutesTree & ExtractTRouteTreesFromChildren>>; protected appendChildToParentRouter(router: DefaultRouterType, child: DefaultRouterType): void; middlewares(definedMiddlewares: Narrow): MethodsRouter; private extractQueryParamsFromPath; private extractUrlParamsFromPath; /** * This works similarly to a lexer in a programming language, but it's a bit simpler. We split the * characters and then we loop through them to find what we want. * * This means the complexity will grow the bigger the path is. */ private extractUrlAndQueryParametersFromPath; } declare class IncludesRouter | undefined = undefined, TRootRoutesTree = unknown, TDefinitions extends { adapter: (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter; } = DefaultRouterDefinitions> extends BaseRouter { /** * Syntax sugar for creating a nested router inside of the `include` method when passing a function * instead of an array. * * @param path - The path of the route. * @returns - The child router. */ child(): [] ? TMiddlewares["length"] extends 0 ? [] : TMiddlewares : []>(path: TPath) => MethodsRouter, [], ValidatedMiddlewaresType, ValidatedFullPathType, undefined, unknown, DefaultRouterDefinitions>; } declare class MethodsRouter | unknown = unknown, TRootRoutesTree = unknown, TDefinitions extends { adapter: (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter; } = DefaultRouterDefinitions> extends BaseRouter { get, TOptions extends RouterOptionsType>(handler: THandler, options?: TOptions): Omit, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | "get" | "all">; post, TOptions extends RouterOptionsType>(handler: THandler, options?: TOptions): Omit, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | "post" | "all">; delete, TOptions extends RouterOptionsType>(handler: THandler, options?: TOptions): Omit, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | "delete" | "all">; options, TOptions extends RouterOptionsType>(handler: THandler, options?: TOptions): Omit, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | "options" | "all">; head, TOptions extends RouterOptionsType>(handler: THandler, options?: TOptions): Omit, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | "head" | "all">; put, TOptions extends RouterOptionsType>(handler: THandler, options?: TOptions): Omit, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | "put" | "all">; patch, TOptions extends RouterOptionsType>(handler: THandler, options?: TOptions): Omit, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | "patch" | "all">; all, TOptions extends RouterOptionsType>(handler: THandler, options?: TOptions): Omit, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | MethodTypes | "all">; } type HandlerForServerless = { writeFile: (args: { pathOfHandlerFile: string[]; /** This is the name of your current package as on package.json the import like: * `import ${name} from ${projectName}` */ projectName: string; adapter: { /** * Is it a default export? like `import ${name} from ${projectName}` or not, * like: `import { ${name} } from ${projectName}` */ isDefaultImport: boolean; /** This is the name on the import like: `import ${name} from ${projectName}` */ name: string; }; }) => Promise; appendBody: (args: { parameters: { name: string; type: string; }[] | string[]; customExport?: string; isCJSModule?: boolean; isDefaultExport?: boolean; functionName: string; adapter: string; isSpecificRoute?: boolean; isSpecificMethod?: boolean; requestAndResponseData: string; getMethodFunctionBody: string; getRouteFunctionBody: string; }) => Promise; }; type ParseHandlerServerless = Map; /** * Adapter used for translating Palmares router to the framework of choice router. * * Functional approach to creating a server adapter instead of the default class/inheritance approach. */ declare function serverlessRouterAdapter(args: { /** * Used for parsing each part of the route, instead of parsing the whole route all at once, the framework * itself will call this method for each part of the route. * * n this example we are parsing the route and following Express's route syntax, like /users/:id, /users/:id/posts, * /users/:id/posts/:postId, etc. So each url param will contain a colon before the name of the param. * * @example * ```ts * parseRoute(server, partOfPath, urlParamType) { * if (urlParamType) return ':${partOfPath}`; * else return partOfPath; * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _partOfPath - The part of the path to be parsed. * @param _urlParamType - If the part of the path is a url param, this will be true, otherwise it will be false. * * @returns The parsed part of the path. */ parseRoute: TParseRouteFunction; /** * This method is used for loading a 405 handler, this will only be called if no handler is found for the requested * method. * * IMPORTANT: If you define a route handler OUTSIDE of palmares and we do not find the route, this will still be * called, because this is defined by your framework of choice. * * @example * ```ts * load404(server, handler) { * const initializedServer = servers.get(server.serverName)?.server; * if (initializedServer) { * initializedServer.use((req, res) => { * const serverRequestAndResponseData = { * req, * res, * }; * handler(serverRequestAndResponseData); * }); * } * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _handler - The handler is a simple callback function that receives a single parameter as argument. * Whatever you pass on this parameter can later be retrieved inside of * {@link ServerResponseAdapter} and {@link ServerRequestAdapter} methods. */ load404: TLoad404Function; /** * Use this method if you want to parse all handlers at once. Parse all handlers at once is ofter useful if your * framework doesn't support the same methods as us. With this method you can loop through each handler and parse * it or you can listen to all methods and parse them during the request/response lifecycle. * * Important: if this method is defined, {@link parseHandler()} will be ignored. * * @example * ```ts * parseHandlers(server, path, handlers, _, handler404) { * const initializedServer = servers.get(server.serverName)?.server; * if (initializedServer) { * const optionsHandler = handlers.get('options')?.handler; * const headHandler = handlers.get('head')?.handler; * const deleteHandler = handlers.get('delete')?.handler; * const getHandler = handlers.get('get')?.handler; * const postHandler = handlers.get('post')?.handler; * const putHandler = handlers.get('put')?.handler; * const patchHandler = handlers.get('patch')?.handler; * const allHandler = handlers.get('all')?.handler; * * // This will initialize the server routes. * initializedServer.all(path, (req: Request, res: Response) => { * const serverRequestAndResponseData = { * req, * res, * }; * if (optionsHandler && req.method === 'OPTIONS') { * optionsHandler(serverRequestAndResponseData); * return; * } else if (headHandler && req.method === 'HEAD') { * headHandler(serverRequestAndResponseData); * return; * } else if (deleteHandler && req.method === 'DELETE') { * deleteHandler(serverRequestAndResponseData); * return; * } else if (getHandler && req.method === 'GET') { * getHandler(serverRequestAndResponseData); * return; * } else if (postHandler && req.method === 'POST') { * postHandler(serverRequestAndResponseData); * return; * } else if (putHandler && req.method === 'PUT') { * putHandler(serverRequestAndResponseData); * return; * } else if (patchHandler && req.method === 'PATCH') { * patchHandler(serverRequestAndResponseData); * return; * } else if (allHandler) { * allHandler(serverRequestAndResponseData); * return; * } else handler404(serverRequestAndResponseData); * }); * } * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _path - The retrieved by calling {@link parseRoute()} method. * @param _methodsAndHandlers - A Map instance where the method is the key and the handler is the value. The * handler is a simple callback function that receives a single parameter as argument. Whatever you pass on this * parameter can later be retrieved inside of {@link ServerResponseAdapter} and {@link ServerRequestAdapter} methods. * What you return on {@link ServerResponseAdapter.redirect} or {@link ServerResponseAdapter.send} will be the return * value of the handlers callback. * @param _queryParams - The query params so you can parse it and validate as you wish. * @param _404Handler - The 404 handler. */ parseHandlers?: TParseHandlersFunction; }): { new (): ServerlessRouterAdapter & { parseRoute: TParseRouteFunction; parseHandlers: TParseHandlersFunction; load404: TLoad404Function; }; }; /** * Adapter used for translating palmares router to the framework of choice router. */ declare class ServerlessRouterAdapter { /** * This method is used for loading a 405 handler, this will only be called if no handler is found for the requested * method. * * IMPORTANT: If you define a route handler OUTSIDE of palmares and we do not find the route, this will still be * called, because this is defined by your framework of choice. * * @example * ```ts * load404(server, handler) { * const initializedServer = servers.get(server.serverName)?.server; * if (initializedServer) { * initializedServer.use((req, res) => { * const serverRequestAndResponseData = { * req, * res, * }; * handler(serverRequestAndResponseData); * }); * } * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _handler - The handler is a simple callback function that receives a single parameter as argument. * Whatever you pass on this parameter can later be retrieved inside of {@link ServerResponseAdapter} and * {@link ServerRequestAdapter} methods. */ load404(_server: ServerlessAdapter, _handler: (serverRequestAndResponseData: any) => ReturnType): Promise; /** * This method is used for loading a 500 handler, this handler will be called when an error occurs during the * request/response lifecycle. * * IMPORTANT: If you define a route handler OUTSIDE of palmares and an error occurs in the handler, this method * will not be called. * * @example * ```ts * load500(server, handler) { * const initializedServer = servers.get(server.serverName)?.server; * if (initializedServer) { * initializedServer.use((req, res) => { * const serverRequestAndResponseData = { * req, * res, * }; * handler(serverRequestAndResponseData); * }); * } * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _handler - The handler is a simple callback function that receives a single parameter as argument. Whatever * you pass on this parameter can later be retrieved inside of {@link ServerResponseAdapter} and * {@link ServerRequestAdapter} methods. */ load500(_server: ServerlessAdapter, _handler: (serverRequestAndResponseData: any) => ReturnType): Promise; /** * Used for parsing each part of the route, instead of parsing the whole route all at once, the framework itself will * call this method for each part of the route. * * n this example we are parsing the route and following Express's route syntax, like /users/:id, /users/:id/posts, * /users/:id/posts/:postId, etc. So each url param will contain a colon before the name of the param. * * @example * ```ts * parseRoute(server, partOfPath, urlParamType) { * if (urlParamType) return ':${partOfPath}`; * else return partOfPath; * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _partOfPath - The part of the path to be parsed. * @param _urlParamType - If the part of the path is a url param, this will be true, otherwise it will be false. * * @returns The parsed part of the path. */ parseRoute(_server: ServerlessAdapter, _partOfPath: string, _urlParamType?: Parameters[1]): string | undefined; /** * Use this method if you want to parse all handlers at once. Parse all handlers at once is ofter useful if your * framework doesn't support the same methods as us. With this method you can loop through each handler and parse * it or you can listen to all methods and parse them during the request/response lifecycle. * * Important: if this method is defined, {@link parseHandler()} will be ignored. * * @param _server - The {@link ServerlessAdapter} instance. * @param _path - The retrieved by calling {@link parseRoute()} method. * @param _methodsAndHandlers - A Map instance where the method is the key and the handler is the value. The handler * is a simple callback function that receives a single parameter as argument. Whatever you pass on this parameter can * later be retrieved inside of {@link ServerResponseAdapter} and {@link ServerRequestAdapter} methods. What you * return on {@link ServerResponseAdapter.redirect} or {@link ServerResponseAdapter.send} will be the return value * of the handler callback. * @param _queryParams - The query params so you can parse it and validate as you wish. * @param _404Handler - The 404 handler. */ parseHandlers(_server: ServerlessAdapter, _rootFileSystemPath: string, _path: string, _methodsAndHandlers: ParseHandlerServerless, _queryParams: BaseRouter['__queryParamsAndPath']['params'], _404Handler: (serverRequestAndResponseData: any) => ReturnType): Promise; } /** * Functional approach to creating a server adapter instead of the default class/inheritance approach. */ declare function serverlessAdapter(args: { name: string; /** * This is the {@link ServerRequestAdapter}. The request will hold all of the request data from the server, * this way we can translate the original request to Palmares request, everything is all lazy loaded. */ request: TServerlessRequestAdapter; /** * This is the {@link ServerResponseAdapter} instance to be used by the server so we can translate Palmares's * response to the server's response. */ response: TServerlessResponseAdapter; /** * This is the {@link ServerlessRouterAdapter} instance to be used by the server so we can translate Palmares's * router to the server's router. */ routers: TServerlessRouterAdapter; customServerSettings: TCustomServerSettings; load: TLoadFunction; generate: TStartFunction; }): { customServerSettings: TCustomServerSettings; new (serverName: string): ServerlessAdapter & { request: TServerlessRequestAdapter; response: TServerlessResponseAdapter; routers: TServerlessRouterAdapter; load: TLoadFunction; }; }; declare class ServerlessAdapter { $$type: string; serverName: string; settings: ServerSettingsType; allSettings: AllServerSettingsType; domains: Domain[]; routers: ServerlessRouterAdapter; request: ServerRequestAdapter; response: ServerResponseAdapter; constructor(serverName: string, allSettings: AllServerSettingsType, settings: AllServerSettingsType['servers'][string], domains: Domain[]); load(_serverName: string, _domains: Domain[], _settings: AllServerSettingsType['servers'][string]): Promise; generate(..._args: any[]): Promise; static customServerSettings(args: AllServerSettingsType['servers'][string]['customServerSettings']): unknown; } declare class Request Response | Promise>> | undefined; context?: unknown; mode?: RequestMode; cache?: RequestCache; credentials?: RequestCredentials; integrity?: string; destination?: RequestDestination; referrer?: string; redirect?: RequestRedirect; referrerPolicy?: ReferrerPolicy; } = { method: RequestMethodTypes; headers: { [key: string]: string; } | unknown; body: unknown; context: unknown; mode: RequestMode; cache: RequestCache; credentials: RequestCredentials; integrity: string; responses: undefined; destination: RequestDestination; referrer: string; redirect: RequestRedirect; referrerPolicy: ReferrerPolicy; }, TDefinitions extends { adapter: (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter; } = DefaultRequestDefinitions> { /** * All of those private methods are not really private, we use them internally so we do a typescript * mangling to use them. * * But the intellisense on VSCODE or other editors will not show them. */ private __queryParams; private __urlParams; private __serverAdapter; private __requestAdapter; /** * This is data sent by the server, you can use it to translate your request and response during the * lifecycle of Request/Response. * * Think like that, on express: * * @example * ```ts * app.use((req, res, next) => { * const serverRequestAndResponseData = { req, res }; * await wrappedHandler(serverRequestAndResponseData); * }); * ``` */ private __serverRequestAndResponseData; private __serverInstance; private __query?; private __headers; private __destination?; private __cachedMethod; private __params?; private __body?; private __cache?; private __credentials?; private __mode?; private __redirect?; private __referrer?; private __referrerPolicy?; private __integrity?; private __signal; private __validationErrors?; private __url?; private __responses?; private __validation?; context: TRequest['context']; /** * @deprecated - DO NOT create an instance of Request directly, unless you know what you are doing. * If you want to change the request use {@link clone()} instead. */ constructor(options?: TRequest); /** * This is the method that will be used to get the url of the request, it will be lazy loaded and cached * and cannot be changed. This is because we don't want to parse the url if the user doesn't need it. * * @example * ```ts * const request = new Request({ url: '/test' }); * request.url; //'/test' * * path('/test').get((request) => { * request.url; //'http:mycustomdomain.com/test' * }); * ``` * * @returns - The url of the request. */ get url(): `${string}${TRoutePath}`; get cache(): TRequest['cache']; get credentials(): TRequest['credentials']; get mode(): TRequest['mode']; get redirect(): TRequest['redirect']; get referrer(): string | undefined; get referrerPolicy(): ReferrerPolicy | undefined; get integrity(): string | undefined; get destination(): RequestDestination | undefined; get signal(): AbortSignal | undefined; get responses(): TRequest['responses']; /** * This will show the errors that happened on the request. This way you can validate them during the * request response lifecycle. * * By default we give you the data parsed, we just parse the data when you use it. So in other words. * If the request is made and you don't use the data we just don't validate. * * This is nice to keep your application fast and don't get in your way. */ get validationErrors(): { query?: Record, { data: any; errorOn: keyof Parameters[1][]; type: Parameters[1]; }>; url?: Record, { data: any; errorOn: keyof Parameters[1][]; type: Parameters[1]; }>; }; /** * This will cancel the request lifecycle and will return an 500 error to the client. * * @example * ```ts * path('/test').get((request) => { * request.abort(); * }); * * fetch('/test'); // 500 error * ``` * * @param reason - The reason why the request was aborted. */ abort(reason?: string): void; /** * This is the method that will be used to get the method of the request, it will be lazy loaded and * cached and cannot be changed. * * @example * ```ts * const request = new Request({ method: 'GET' }); * request.method; //'GET' * * path('/test').get((request) => { * request.method; //'GET' * }); * ``` * * @returns - The method of the request. For reference, see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods */ get method(): TRequest['method']; /** * By default this will return nothing, you need to use one of the following methods {@link formData()}, * {@link json()}, {@link text()}, {@link blob()} or {@link arrayBuffer()} to get the body. * This is because we don't want to parse the body if the user doesn't need it. This will JUST have a * value if you use either use {@link clone()} passing a new body or if you create a new instance of * Request passing a body. Otherwise it will always be undefined. * * @example * ```ts * const request = new Request({ body: 'Hello World' }); * request.body; //'Hello World' * * path('/test').get((request) => { * request.body; //undefined * }) * ``` * * @returns - The body of the request. */ get body(): TRequest['body']; /** * This will lazy load the headers of the request. Instead of returning the headers directly it is a * proxy, so it's only parsed and translated when needed. * * @example * ```ts * const request = new Request({ headers: { 'Content-Type': 'application/json' } }); * request.headers; // { 'Content-Type': 'application/json' } * * path('/test').get((request) => { * request.headers; // Proxy instance * request.headers['Content-Type']; // 'application/json' * JSON.stringify(request.headers); // '{"Content-Type":"application/json"}' * }); * ``` * * @returns - Returns a proxy that will lazy load the headers of the request. */ get headers(): TRequest['headers']; /** * This is an extraction of a piece of code that repeats inside of `query` getter. * * @param target - The target to append the parsed query param. * @param key - The key of the query param. */ private __appendUrlParamParsedToTarget; /** * This is really similar to {@link headers} but it's used for url params instead. * This will lazy load and parse the url parameters of the request. Instead of returning the params * directly it is a proxy, so it's only parsed and translated when needed. * * @example * ```ts * path('/test/').get((request) => { * request.params; // Proxy instance * request.params['filter']; // string type * JSON.stringify(request.headers); // '{"filter":"string"}' * }); * ``` * * @returns - Returns a proxy that will lazy load the headers of the request. */ get params(): ExtractUrlParamsFromPathType; private __validateQueryParamsAndThrow; private __validateParamsAndThrow; /** * This is an extraction of a piece of code that repeats inside of `query` getter. * * @param target - The target to append the parsed query param. * @param key - The key of the query param. */ private __appendQueryParamParsedToTarget; /** * This is really similar to {@link headers} but it's used for query params instead. * This will lazy load and parse query parameters of the request. Instead of returning the query params * directly it is a proxy, so it's only parsed and translated when needed. * * @example * ```ts * path('/test?filter=string&world=string[]?').get((request) => { * request.query; // Proxy instance * request.query['filter']; // string type * request.query['world']; // string[] | undefined type * JSON.stringify(request.headers); // '{"filter":"string"}' * }); * ``` * * @returns - Returns a proxy that will lazy load the headers of the request. */ get query(): ExtractQueryParamsFromPathType; /** * This function is used to clone the object, it is the only and the prefered way to make changes to your * request (besides making changes to the `context`). You can use it to change the headers, body, context, * mode, cache, credentials, integrity, destination, referrer and redirect. To improve performance this * will change the values in-place. This means it will change itself and return it again, but you can do * a copy of the object using `{ options: inPlace: false }` * * @example * ```ts * const request = new Request({ headers: { 'Content-Type': 'application/json' } }); * const newRequest = request.clone({ headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); * request.headers; // { 'Content-Type': 'application/x-www-form-urlencoded' } * newRequest.headers; // { 'Content-Type': 'application/x-www-form-urlencoded' } * * const request = new Request({ headers: { 'Content-Type': 'application/json' } }); * const newRequest = request.clone( * { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }, * { inPlace: false } * ); * request.headers; // { 'Content-Type': 'application/json' } * newRequest.headers; // { 'Content-Type': 'application/x-www-form-urlencoded' } * ``` * * @param args - The new values you want to set on the request, the values you don't pass will not be overridden. * @param options - The options you want to use when cloning the request. * @param options.inPlace - If you want to clone the request or change it in-place. By default it will * change it in-place. IMPORTANT: The header will NOT be overridden you can just change an existing value * or add a new one. * * @returns - Either a new Request instance or the same instance with new values. */ clone(args?: TNewRequest, options?: { inPlace: boolean; }): Request; /** * This is the underlying serverData. The documentation of this should be provided by the framework you * are using underlined with Palmares. * So, the idea is simple, when a request is made, the underlying framework will call a callback we * provide passing the data it needs to handle both the request and the response. For Express.js for * example this will be an object containing both the `req` and `res` objects. If for some reason you need * some data or some functionality we do not support by default you can, at any time, call this function * and get this data. * * IMPORTANT: It's not up for us to document this, ask the library author of the adapter to provide a * documentation and properly type this. * * @example * ```ts * // on settings.ts * import { ExpressServerAdapter } from '@palmares/express-adapter'; * import ServerDomain from '@palmares/server'; * * export default defineSettings({ * //...other configs, * installedDomains: [ * [ * ServerDomain, * { * servers: { * default: { * server: ExpressServerAdapter, * // ...other configs, * }, * }, * }, * ], * ], * }); * * // on controllers.ts * import type { Request, Response } from 'express'; * * const request = new Request(); * request.serverData(); // undefined * * path('/test').get((request) => { * request.serverData(); // { req: Request, res: Response } * }); * ``` * * @returns - The underlying server data. */ serverData(): Parameters[2]; /** * This should return the body as an ArrayBuffer instance. If the body is not an ArrayBuffer it should * return undefined. You should search for documentation of the underlying adapter to understand WHEN * it will return an ArrayBuffer (usually might depend of 'Content-Type' header) * * @example * ```ts * const request = new Request({ body: new ArrayBuffer(10) }); * await request.arrayBuffer(); // ArrayBuffer(10) * * path('/test').post(async (request) => { * await request.arrayBuffer(); // ArrayBuffer | undefined * }); * * fetch('/test', { * method: 'POST', * headers: { * 'Content-Type': 'application/octet-stream' * }, * body: new ArrayBuffer(10) * }); * ``` * * @param options - Those options are custom options you want to pass to the underlying adapter instance * when retrieving the array buffer, see the documentation of the underlying adapter. You can retrieve * those options by: 'MyCustomFrameworkRequestAdapter.customToArrayBufferOptions?.()' if it is implemented. */ arrayBuffer(options?: Parameters[3]): Promise; /** * This SHOULD return a json body when the 'Content-Type' on the request header is `application/json`. * * @example * ```ts * const request = new Request({ body: { hello: 'world' } }); * await request.json(); // { hello: 'world' } * * path('/test').post(async (request) => { * await request.json(); // { hello: 'world' } | undefined * }); * * fetch('/test', { * method: 'POST', * headers: { * 'Content-Type': 'application/json' * }, * body: JSON.stringify({ hello: 'world' }) * }); * ``` * * @param options - Those options are custom options you want to pass to the underlying adapter instance * when retrieving the json, see the documentation of the underlying adapter. You can retrieve those * options by: 'MyCustomFrameworkRequestAdapter.customToJsonOptions?.()' if it is implemented. */ json(options?: Parameters[3]): Promise; /** * This should return the body as a Blob instance. If the body is not a Blob it should return undefined. * You should search for documentation of the underlying adapter to understand WHEN it will return a * Blob (usually might depend of 'Content-Type' header) * * @example * ```ts * const request = new Request({ body: new Blob() }); * request.blob(); // Blob * * path('/test').post((request) => { * request.blob(); // Blob | undefined * }); * * fetch('/test', { * method: 'POST', * headers: { * 'Content-Type': 'application/octet-stream' * }, * body: new Blob() * }); * ``` * * @param options - Those options are custom options you want to pass to the underlying adapter instance * when retrieving the blob, see the documentation of the underlying adapter. You can retrieve those * options by: 'MyCustomFrameworkRequestAdapter.customToBlobOptions?.()' if it is implemented. */ blob(options?: Parameters[3]): Promise; /** * This should contain data when the 'Content-Type' on the request is a `multipart/form-data` or * `application/x-www-form-urlencoded`. Otherwise it should be undefined. * * This should be used for retrieving a FormData-like instance. FormData is not available on Node.js and * might not be supported on other runtimes, * so in order to support it we have created a FormData-like class that has the same API as the original * FormData with some extensions. * * See: https://developer.mozilla.org/en-US/docs/Web/API/FormData * * @example * ```ts * const request = new Request({ body: new FormData() }); * await request.formData(); // Blob * * path('/test').post(async (request) => { * request.formData(); // FormDataLike | undefined * }); * * fetch('/test', { * method: 'POST', * headers: { * 'Content-Type': 'application/form-data' * }, * body: new FormData() * }); * ``` * * @param options - Those options are custom options you want to pass to the underlying framework instance * when retrieving the form data. * You can retrieve those options by: 'MyCustomFrameworkRequestAdapter.customToBlobOptions?.()' if it is implemented. */ formData(options?: Parameters[5]): Promise> | undefined>; /** * This should return the body as a string. If the body is not a string it should return undefined. * You should search for documentation of the underlying adapter to understand WHEN it will return a * string (usually might depend of 'Content-Type' header) * * @example * ```ts * const request = new Request({ body: 'Hello World' }); * await request.text(); // 'Hello World' * * path('/test').post(async (request) => { * await request.text(); // 'Hello World' | undefined * }); * * fetch('/test', { * method: 'POST', * headers: { * 'Content-Type': 'text/plain' * }, * body: 'Hello World' * }); * ``` * * @param options - Those options are custom options you want to pass to the underlying adapter instance * when retrieving the text, see the documentation of the underlying adapter. You can retrieve those options by: * 'MyCustomFrameworkRequestAdapter.customToTextOptions?.()' if it is implemented. */ text(options?: Parameters[3]): Promise; /** * Should return the raw data of the request, whatever you have on the request body should be returned here. * * @example * ```ts * const request = new Request({ body: 'Hello World' }); * await request.raw(); // 'Hello World' * * path('/test').post(async (request) => { * await request.raw(); // 'Hello World' | undefined * }); * ``` * * @param options - Those options are custom options you want to pass to the underlying adapter instance * when retrieving the raw data, see the documentation of the underlying adapter. You can retrieve those * options by: 'MyCustomFrameworkRequestAdapter.customToRawOptions?.()' if it is implemented. */ raw(options?: Parameters[3]): Promise; } type Whitespace = '\n' | ' '; type Trim = T extends `${Whitespace}${infer U}` ? Trim : T extends `${infer U}${Whitespace}` ? Trim : T; type GetTypeByStringType = TString extends `(${infer TUnionOrMergedTypes})` ? TUnionOrMergedTypes extends `${infer TType}|${infer TRest}` ? GetTypeByStringType<`(${TRest})`, TFinalType | GetTypeByStringType> : GetTypeByStringType : Trim extends 'number' ? TFinalType | number : Trim extends 'string' ? TFinalType | string : Trim extends 'boolean' ? TFinalType | boolean : TString; type GetLastCharacterOfString = TString extends `${string}${infer End}` ? End extends `` ? TString : GetLastCharacterOfString : TString; type GetTypeByStringForQueryParamsType = TString extends `${infer TType}[]?` | `${infer TType}[]` ? GetLastCharacterOfString extends '?' ? GetTypeByStringType[] | undefined : GetTypeByStringType[] : TString extends `${infer TType}?` | `${infer TType}` ? GetLastCharacterOfString extends '?' ? GetTypeByStringType | undefined : GetTypeByStringType : never; type ExtractStringWithoutSpacesType = TString extends ` ${infer TRest}` ? ExtractStringWithoutSpacesType<`${TRest}`> : TString extends `${infer TRest} ` ? ExtractStringWithoutSpacesType<`${TRest}`> : TString; type ExtractQueryParamsFromPathType = T extends `${string}?${infer TQueryParams}` ? ExtractUrlQueryParamsFromPathTypeRequiredAndOptional : never; /** * Used for extracting all the url parameters as an object from a path string. */ type ExtractUrlParamsFromPathType = TPath extends `${string}<${infer TParam}:${infer TType}>${infer TRest}` | `${string}<${infer TParam}:${infer TType}>` ? { [key in TParam]: GetTypeByStringType>; } & ExtractUrlParamsFromPathType : object; type ExtractUrlQueryParamsFromPathType = TPath extends `${infer TParam}=${infer TType}&${infer TRest}` ? { [key in TParam]: GetTypeByStringForQueryParamsType>; } & ExtractUrlQueryParamsFromPathType : TPath extends `${infer TParam}=${infer TType}` ? { [key in TParam]: GetTypeByStringForQueryParamsType>; } : undefined; /** * Some query parameters are obligatory and some are optional, we use this to convert * values with "undefined" in them to optional * * { * key?: value * } */ type ExtractUrlQueryParamsFromPathTypeRequiredAndOptional = { [key in keyof ExtractUrlQueryParamsFromPathType as undefined extends ExtractUrlQueryParamsFromPathType[key] ? never : key]: ExtractUrlQueryParamsFromPathType[key]; } & { [key in keyof ExtractUrlQueryParamsFromPathType as undefined extends ExtractUrlQueryParamsFromPathType[key] ? key : never]?: ExtractUrlQueryParamsFromPathType[key]; }; type DefaultRequestType = Request; type FormDataLike = { new ( /** * This should be prefered, what it does is that instead of creating a default form data like class * it'll return a proxy, this way all values are lazy loaded. Just when needed. */ proxyCallback?: { /** * This function will be called when a value is needed. It should return an array of object for the given key. * * If the key is a File or Blob, fileName should be defined. Otherwise just return on value. A File * object is prefered over a Blob object, because it can hold more information about the file. * * @example * ```ts * const formData = new FormDataLike({ * getValue: (name) => { * if (name === 'file') return [{ value: new File([''], 'file.txt'), fileName: 'file.txt' }]; * else return [{ value: 'value' }]; * }, * }); * formData.get('file'); // File { name: 'file.txt' } * ``` * * @param name - The name of the key to get the value from. */ getValue: (name: string) => { value: string | Blob; fileName?: string; }[]; /** * This function will be called for returning all keys of the form data in order to transform it to a json object. * * @example * ```ts * const formData = new FormDataLike({ * getValue: (name) => { * if (name === 'file') return [{ value: new File([''], 'file.txt'), fileName: 'file.txt' }]; * else return [{ value: 'value' }]; * }, * getKeys: () => ['file', 'key'], * }); * * formData.toJSON(); // { file: File { name: 'file.txt' }, key: 'value' } * ``` * * @returns - An array of all keys of the form data. */ getKeys: () => string[]; }): { append: (name: keyof TObject, value: string | Blob | File, fileName?: string) => void; get: (name: TName) => TName extends keyof TObject ? TObject[TName] extends (infer TType)[] ? TType : TObject[TName] : string | Blob | File; getAll: (name: TName) => TName extends keyof TObject ? TObject[TName] extends any[] ? TObject[TName] : TObject[TName][] : string | Blob | File; has: (name: keyof TObject) => boolean; set: (name: keyof TObject, value: TName extends keyof TObject ? TObject[TName] extends (infer TType)[] ? TType : TObject[TName] : string | Blob | File, fileName?: string) => void; delete: (name: keyof TObject) => void; toJSON: () => TObject; }; }; type RequestMethodTypes = Uppercase; type RequestCache = 'default' | 'force-cache' | 'no-cache' | 'no-store' | 'only-if-cached' | 'reload'; type RequestCredentials = 'include' | 'omit' | 'same-origin'; type RequestDestination = '' | 'audio' | 'audioworklet' | 'document' | 'embed' | 'font' | 'image' | 'manifest' | 'object' | 'paintworklet' | 'report' | 'script' | 'sharedworker' | 'style' | 'track' | 'video' | 'worker' | 'xslt'; type RequestMode = 'cors' | 'navigate' | 'no-cors' | 'same-origin'; type RequestRedirect = 'error' | 'follow' | 'manual'; declare class ServerRequestAdapter { /** * This should return the full concatenated url of the request, with domain and path. * * @example * ```ts * import { Request } from 'express'; * * url: (_, serverRequestAndResponseData: { req: Request }) => { * const { req } = serverRequestAndResponseData; * return `${req.protocol}://${req.get('host')}${req.originalUrl}`; * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _serverRequestAndResponseData - The server request and response data that you have defined on * {@link ServerRouterAdapter.parseHandler} or {@link ServerRouterAdapter.parseHandlers} on the router. */ url(_serverAdapter: ServerAdapter | ServerlessAdapter, _server: ReturnType, _serverRequestAndResponseData: any): string; /** * Translates the headers from the server request to the headers of the request to the API. This is lazy loaded, * so it will only parse the headers when the user actually needs it. * In other words, it is a proxy, so you just need to extract each value of the header one by one. What is expected * is the user to pass the key of the header like that: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers * * We don't make assumptions so we do not transform it to lowerCase by default. Depending of your framework * you are totally free to do this for better parsing. * * @example * ```ts * import { Request } from 'express'; * * headers: (_, serverRequestAndResponseData: { req: Request }, key) => { * const lowerCasedKey = key.toLowerCase(); * const { req } = serverRequestAndResponseData; * * return req.headers[lowerCasedKey]; * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _serverRequestAndResponseData - The server request and response data that you have defined on * {@link ServerRouterAdapter.parseHandler} or {@link ServerRouterAdapter.parseHandlers} on the router. * @param _key - The key of the header that the user wants to extract. * * @returns - The value of the header if it exists, otherwise undefined. */ headers(_serverAdapter: ServerAdapter | ServerlessAdapter, _server: ReturnType, _serverRequestAndResponseData: any, _key: string): string | undefined; /** * This should return the method of the request. Casing doesn't matter, it should just follow this guide: * https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods * * @example * ```ts * import { Request } from 'express'; * * method: (_server, serverRequestAndResponseData) => { * const { req } = serverRequestAndResponseData as { req: Request }; * return req.method; * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _serverRequestAndResponseData - The server request and response data that you have defined on * {@link ServerRouterAdapter.parseHandler} or {@link ServerRouterAdapter.parseHandlers} on the router. * * @returns - The method of the request. */ method(_serverAdapter: ServerAdapter | ServerlessAdapter, _server: ReturnType, _serverRequestAndResponseData: any): string; /** * Translates the params from the server request to the params of the request to the API. This is lazy loaded, * so it will only parse the params when the user actually needs it. In other words, it is a proxy, so you just * need to extract each value of the param one by one. What is expected is the user to pass the key of the param * like that: https://expressjs.com/en/4x/api.html#req.params * * You don't need to worry about parsing, we parse it on our side, but if you do parse, no problem, we will just * ignore parsing on our end. But please note that this might introduce unexpected behavior to users. So make sure * to document it. * * @example * ```ts * import { Request } from 'express'; * * params: (_, serverRequestAndResponseData: { req: Request }, key) => { * const { req } = serverRequestAndResponseData; * return req.params[key]; * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _serverRequestAndResponseData - The server request and response data that you have defined on * {@link ServerRouterAdapter.parseHandler} or {@link ServerRouterAdapter.parseHandlers} on the router. * @param _key - The key of the param that the user wants to extract. * * @returns - The value of the param if it exists, otherwise undefined. */ params?(_serverAdapter: ServerAdapter | ServerlessAdapter, _server: ReturnType, _serverRequestAndResponseData: any, _key: string): string | undefined; /** * Translates the query from the server request to the query of the request to the API. This is lazy loaded, * so it will only parse the query when the user actually needs it. In other words, it is a proxy, so you * just need to extract each value of the query one by one. What is expected is the user to pass the key of * the query like that: * https://expressjs.com/en/4x/api.html#req.query * * You don't need to worry about parsing, we parse it on our side, but if you do parse, no problem, we * will just ignore parsing on our end. But please note that this might introduce unexpected behavior to users. * So make sure to document it. * * @example * ```ts * import { Request } from 'express'; * * query: (_, serverRequestAndResponseData: { req: Request }, key) => { * const { req } = serverRequestAndResponseData; * return req.query[key]; * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _serverRequestAndResponseData - The server request and response data that you have defined on * {@link ServerRouterAdapter.parseHandler} or {@link ServerRouterAdapter.parseHandlers} on the router. * @param _key - The key of the query that the user wants to extract. * * @returns - The value of the query if it exists, otherwise undefined. */ query(_serverAdapter: ServerAdapter | ServerlessAdapter, _server: ReturnType, _serverRequestAndResponseData: any, _key: string): string | undefined; /** * When the request is a `application/json` request, this should return the parsed json. This is called * when the user calls the {@link Request.json} method. * * If you want to let users pass custom options to the {@link Request.json} method, you can override the * {@link customToJsonOptions} static method. * The user will then need to call this method (for intellisense) in order to pass custom options. * * @example * ```ts * import express, { Request } from 'express'; * * toJson: (_, serverRequestAndResponseData: { req: Request }, options: Parameters) => { * const { req } = serverRequestAndResponseData; * * return new Promise((resolve) => { * express.json(options)(req, undefined, () => { * resolve(req.body); * }); * }); * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _serverRequestAndResponseData - The server request and response data that you have defined on * {@link ServerRouterAdapter.parseHandler} or {@link ServerRouterAdapter.parseHandlers} on the router. * @param _options - Any type of custom options that you want to be able to pass when converting to json. If you * want to support custom options, please override the {@link customToJsonOptions} static method. * * @returns - A promise that resolves to the parsed json. */ toJson(_serverAdapter: ServerAdapter | ServerlessAdapter, _server: ReturnType, _serverRequestAndResponseData: any, _options: any): Promise; /** * This should return something when the request Content-Type is a `multipart/form-data` or * `application/x-www-form-urlencoded` request. This is lazy loaded, so it will only parse the data when you * actually need it. * Transforms the data to a FormData-like instance. FormData is not available on Node.js and other runtimes, so in * order to support it we have created a FormData-like class that follows the same api as the original FormData. * * see: https://developer.mozilla.org/en-US/docs/Web/API/FormData * * Because it's a custom class, we add some useful stuff like the ability to lazy load the data, so it will only parse * the data when you actually need it. * * @example * ```ts * import express, { Request } from 'express'; * * toFormData: (server, serverRequestAndResponseData, formDataConstructor, isUrlEncoded, options) => { * const serverInstanceAndSettings = servers.get(server.serverName); * const { req, res } = serverRequestAndResponseData as { req: Request; res: Response }; * * return new Promise((resolve) => { * let formDataOrUrlEncodedParser = isUrlEncoded * ? serverInstanceAndSettings?.urlEncodedParser * : serverInstanceAndSettings?.formDataParser; * * if (isUrlEncoded && serverInstanceAndSettings && !serverInstanceAndSettings?.urlEncodedParser) { * const urlEncodedParserSettings = serverInstanceAndSettings.settings.customServerSettings?.urlEncodedOptions; * * serverInstanceAndSettings.urlEncodedParser = express.urlencoded({ * ...urlEncodedParserSettings, * extended: true, * }); * formDataOrUrlEncodedParser = serverInstanceAndSettings.urlEncodedParser; * } else if (serverInstanceAndSettings && !serverInstanceAndSettings?.formDataParser) { * const formDataParserSettings = serverInstanceAndSettings.settings.customServerSettings?.multerOptions; * * serverInstanceAndSettings.formDataParser = multer(formDataParserSettings); * formDataOrUrlEncodedParser = serverInstanceAndSettings.formDataParser; * } * * let middleware: * | ReturnType * | ReturnType[keyof ReturnType]> * | undefined = undefined; * if (isUrlEncoded && !formDataOrUrlEncodedParser) formDataOrUrlEncodedParser = * express.urlencoded({ extended: true }); * else if (!isUrlEncoded && !formDataOrUrlEncodedParser) formDataOrUrlEncodedParser = multer(); * * const optionsOfParser = (options?.options || []) as any[]; * if (!isUrlEncoded) { * const formDataParser = formDataOrUrlEncodedParser as ReturnType; * if (options && !isUrlEncoded) middleware = * (formDataParser[options.type as keyof ReturnType] as any)(...optionsOfParser); * if (!middleware) middleware = formDataParser.any(); * } else middleware = formDataOrUrlEncodedParser as ReturnType; * * middleware(req, res, () => { * const formData = new formDataConstructor({ * getKeys: () => { * const bodyKeys = Object.keys(req.body || {}) || []; * if (req?.files) { * if (Array.isArray(req.files)) { * for (const file of req.files) bodyKeys.push(file.fieldname); * } else bodyKeys.push(...Object.keys(req.files)); * } * if (req?.file) bodyKeys.push(req.file.fieldname); * return bodyKeys; * }, * getValue: (name) => { * const bodyKeys = Object.keys(req.body || {}); * for (const key of bodyKeys) { * if (key === name) * return [ * { * value: req.body[key], * filename: undefined, * }, * ]; * } * * if (req?.files) { * if (Array.isArray(req.files)) { * const files = []; * for (const file of req.files) { * if (file.fieldname === name) * files.push({ * value: new File([file.buffer], file.originalname, { type: file.mimetype }), * filename: file.originalname, * }); * } * return files; * } else { * const files = req.files[name]; * const filesArray = []; * * for (const file of files) { * if (file.fieldname === name) * filesArray.push({ * value: new File([file.buffer], file.originalname, { type: file.mimetype }), * filename: file.originalname, * }); * } * return filesArray; * } * } * * if (req?.file) * if (req.file.fieldname === name) * return [ * { * value: new File([req.file.buffer], req.file.originalname, { type: req.file.mimetype }), * filename: req.file.originalname, * }, * ]; * return []; * }, * }); * resolve(formData); * }); * }); * } * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} adapter. * @param _serverRequestAndResponseData - The server request and response data that you have defined on * {@link ServerRouterAdapter.parseHandler} or {@link ServerRouterAdapter.parseHandlers} on the router. * @param _formDataConstructor - The constructor of the FormData-like class. It's a class so you should use * it like this: `new formDataConstructor()`. You can pass a custom proxyCallback, this will lazy load the * values when you actually need it. {@link FormDataLike} * @param _isUrlEncoded - Whether or not the request is a `application/x-www-form-urlencoded` request. If * not, it's a `multipart/form-data` request. * @param _options - Any type of custom options that you want to be able to pass when converting to FormData. * If you want to support custom options, please override the {@link customToFormDataOptions} static method. * * @returns -A promise that resolves to a FormData-like instance. */ toFormData(_serverAdapter: ServerAdapter | ServerlessAdapter, _server: ReturnType, _serverRequestAndResponseData: any, _formDataConstructor: FormDataLike, _isUrlEncoded: boolean, _options: any): Promise>>; /** * This should return the parsed ArrayBuffer of the request. This is called when the user calls the * {@link Request.arrayBuffer} method. * * If you want to let users pass custom options to the {@link Request.arrayBuffer} method, you can override * the {@link customToArrayBufferOptions} static method. The user will then need to call this method * (for intellisense) in order to pass custom options. * * @example * ```ts * import express, { Request } from 'express'; * * toArrayBuffer: (_, serverRequestAndResponseData: { req: Request }, options: Parameters) => { * const { req } = serverRequestAndResponseData; * return new Promise((resolve) => { * express.raw(options)(req, undefined, () => { * resolve(new ArrayBuffer([req.body])); * }); * }); * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _serverRequestAndResponseData - The server request and response data that you have defined on * {@link ServerRouterAdapter.parseHandler} or {@link ServerRouterAdapter.parseHandlers} on the router. * @param _options - Any type of custom options that you want to be able to pass when converting to ArrayBuffer. * If you want to support custom options, please override the {@link customToArrayBufferOptions} static method. * * @returns - A promise that resolves to the parsed ArrayBuffer. */ toArrayBuffer(_serverAdapter: ServerAdapter | ServerlessAdapter, _server: ReturnType, _serverRequestAndResponseData: any, _options: any): Promise; /** * This should return the parsed Blob of the request. This is called when the user calls the {@link Request.blob} * method. * If you want to let users pass custom options to the {@link Request.blob} method, you can override the * {@link customToBlobOptions} static method. The user will then need to call this method (for intellisense) * in order to pass custom options. A File instance can also be returned since it's generally more descriptive. * * @example * ```ts * import express, { Request } from 'express'; * * toBlob: (_, serverRequestAndResponseData: { req: Request }, options: Parameters) => { * const { req } = serverRequestAndResponseData; * return new Promise((resolve) => { * express.raw(options)(req, undefined, () => { * resolve(new Blob([req.body])); * }); * }); * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _serverRequestAndResponseData - The server request and response data that you have defined on * {@link ServerRouterAdapter.parseHandler} or {@link ServerRouterAdapter.parseHandlers} on the router. * @param _options - Any type of custom options that you want to be able to pass when converting to Blob. * If you want to support custom options, please override the {@link customToBlobOptions} static method. * * @returns - A promise that resolves to the parsed Blob. */ toBlob(_serverAdapter: ServerAdapter | ServerlessAdapter, _server: ReturnType, _serverRequestAndResponseData: any, _options: any): Promise; /** * This should return the parsed raw data of the request. This is called when the user calls the * {@link Request.raw} method. This should just return whatever you have on the body of the request. * You don't need to parse or anything like that. * * If you want to let users pass custom options to the {@link Request.raw} method, you can override the * {@link customToRawOptions} static method. The user will then need to call this method (for intellisense) * in order to pass custom options. * * @example * ```ts * import express, { Request } from 'express'; * * toRaw: (_, serverRequestAndResponseData: { req: Request }, options: Parameters) => { * const { req } = serverRequestAndResponseData; * return new Promise((resolve) => { * express.raw(options)(req, undefined, () => { * resolve(req.body); * }); * }); * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _serverRequestAndResponseData - The server request and response data that you have defined on * {@link ServerRouterAdapter.parseHandler} or {@link ServerRouterAdapter.parseHandlers} on the router. * @param _options - Any type of custom options that you want to be able to pass when converting to raw. If * you want to support custom options, please override the {@link customToRawOptions} static method. * * @returns - A promise that resolves to the parsed raw data. */ toRaw(_serverAdapter: ServerAdapter | ServerlessAdapter, _server: any, _serverRequestAndResponseData: any, _options: any): Promise; /** * Translates the request to a string. Should be used for text/plain requests. * * If you want to let users pass custom options to the {@link Request.text} method, you can override the * {@link customToTextOptions} static method. The user will then need to call this method (for intellisense) * in order to pass custom options. * * @example * ```ts * import express, { Request } from 'express'; * * toText: (_, serverRequestAndResponseData: { req: Request }, options: Parameters) => { * const { req } = serverRequestAndResponseData; * return new Promise((resolve) => { * express.text(options)(req, undefined, () => { * resolve(req.body); * }); * }); * }, * ``` * * @param _server - The {@link ServerAdapter} or {@link ServerlessAdapter} instance. * @param _serverRequestAndResponseData - The server request and response data that you have defined on * {@link ServerRouterAdapter.parseHandler} or {@link ServerRouterAdapter.parseHandlers} on the router. * @param _options - Any type of custom options that you want to be able to pass when converting to raw. If you want * to support custom options, please override the {@link customToTextOptions} static method. * * @returns A promise that resolves to a string. */ toText(_serverAdapter: ServerAdapter | ServerlessAdapter, _server: any, _serverRequestAndResponseData: any, _options: any): Promise; } /** * Functional approach to creating a server adapter instead of the default class/inheritance approach. */ declare function serverAdapter(args: { name: string; /** * This is the {@link ServerRequestAdapter}. The request will hold all of the request data from * the server, this way we can translate the original request to Palmares request, everything * is all lazy loaded. */ request: TServerRequestAdapter; /** * This is the {@link ServerResponseAdapter} instance to be used by the server so we can * translate Palmares's response to the server's response. */ response: TServerResponseAdapter; /** * This is the {@link ServerRouterAdapter} instance to be used by the server so we can translate * Palmares's router to the server's router. */ routers: TServerRouterAdapter; /** * This is the function that will be called by Palmares to load the server. Usually you add the * server constructor here. Notice that this function DOES NOT start the server, it will be used * for adding middleware, custom logic, etc. * * You can use a global Map to store the server instance, this way you can access it later on the * start function. Since this is functional and not class based. * * @example * ``` * load: async (_domains: Domain[], settings: ServerSettingsTypeExpress) => { * const server = express(); * return server; * }, * ``` * * @param domains - All of the domains of the application, usually you will not need this, but can be useful. * @param settings - The settings for the server. */ load: TLoadFunction; /** * This is the function that will be called by Palmares to start the server. Usually you start the server here. * Most servers have a `.listen`, that's what you will call here. * * Use the logServerStart function to log to the user that the server has started. * * @example * ``` * start: async (serverName, port, logServerStart) => { * const serverInstanceToStart = servers.get(serverName); * if (serverInstanceToStart) { * serverInstanceToStart.server.listen(port, () => logServerStart()); * } * }, * ``` * * @param serverName - The name of the server, by default a palmares application can contain multiple servers. * @param port - The port to start the server on. * @param logServerStart - A function that you can call to log to the user that the server has started. */ start: TStartFunction; /** * Custom function to call when we receive a SIGINT or SIGTERM signal. With that you can close the server gracefully. * * @example * ``` * close: async () => { * console.log('closing the server'); * }, * ``` */ close: TCloseFunction; }): typeof ServerAdapter & { new (serverName: string): ServerAdapter & { request: TServerRequestAdapter; response: TServerResponseAdapter; routers: TServerRouterAdapter; load: TLoadFunction; start: TStartFunction; close: TCloseFunction; }; }; declare class ServerAdapter { $$type: string; serverName: string; settings: ServerSettingsType; allSettings: AllServerSettingsType; domains: Domain[]; routers: ServerRouterAdapter; request: ServerRequestAdapter; response: ServerResponseAdapter; constructor(serverName: string, allSettings: AllServerSettingsType, settings: ServerSettingsType, domains: Domain[]); /** * This is the function that will be called by Palmares to load the server. Usually you add the * server constructor here. Notice that this function DOES NOT start the server, it will be used * for adding middleware, custom logic, etc. * * What you return here will be passed to the start function and to all the other functions from * the adapter. * * @example * ``` * load: async (_domains: Domain[], settings: ServerSettingsTypeExpress) => { * const server = express(); * return server; * }, * ``` * * @param domains - All of the domains of the application, usually you will not need this, but can be useful. * @param settings - The settings for the server. * * @returns The server instance. */ load(_serverName: string, _domains: Domain[], _settings: ServerSettingsType): Promise; /** * This is the function that will be called by Palmares to start the server. Usually you start the server here. * Most servers have a `.listen`, that's what you will call here. * * Use the logServerStart function to log to the user that the server has started. * * @example * ``` * start: async (server, port, logServerStart) => { * const serverInstanceToStart = servers.get(serverName); * if (serverInstanceToStart) { * serverInstanceToStart.server.listen(port, () => logServerStart()); * } * }, * ``` * * @param _serverName - The name of the server, by default a palmares application can contain multiple servers. * @param _server - What you returned from the `.load` function. * @param _port - The port to start the server on. * @param _logServerStart - A function that you can call to log to the user that the server has started. */ start(_serverName: string, _server: any, _port: number, _logServerStart: () => void): Promise; /** * Custom function to call when we receive a SIGINT or SIGTERM signal. With that you can close the server gracefully. * * @example * ``` * close: async (server) => { * server.stop() * console.log('closing the server'); * }, * ``` * * @param _serverName - The name of the server, by default a palmares application can contain multiple servers. * @param _server - What you returned from the `.load` function. */ close(_serverName: string, _server: any): Promise; } export { DEFAULT_RESPONSE_HEADERS_LOCATION_HEADER_KEY as $, type AllServerSettingsType as A, BaseRouter as B, type ExtractUrlParamsFromPathType as C, type DefaultRequestDefinitions as D, type ExtractResponsesFromMiddlewaresRequestAndRouterHandlers as E, type FormDataLike as F, type ExtractUrlQueryParamsFromPathType as G, type HeadersType as H, IncludesRouter as I, type ExtractUrlQueryParamsFromPathTypeRequiredAndOptional as J, type DefaultRequestType as K, type RequestMethodTypes as L, type MethodTypes as M, type RequestCache as N, type RequestCredentials as O, type ParseHandlersServer as P, type RequestDestination as Q, Response as R, ServerAdapter as S, type RequestMode as T, type RequestRedirect as U, DEFAULT_RESPONSE_HEADERS_CONTENT_HEADER_KEY as V, DEFAULT_RESPONSE_HEADERS_CONTENT_DISPOSITION_KEY as W, DEFAULT_RESPONSE_CONTENT_HEADER_VALUE_JSON as X, DEFAULT_RESPONSE_CONTENT_HEADER_VALUE_HTML as Y, DEFAULT_RESPONSE_CONTENT_HEADER_VALUE_TEXT as Z, DEFAULT_RESPONSE_CONTENT_HEADER_VALUE_STREAM as _, ServerRequestAdapter as a, DEFAULT_NOT_FOUND_STATUS_TEXT_MESSAGE as a0, DEFAULT_SERVER_ERROR_STATUS_TEXT_MESSAGE as a1, DEFAULT_SERVER_ERROR_RESPONSE as a2, DEFAULT_SERVER_ERROR_INVALID_QUERY_OR_PARAMS as a3, type HandlerType as a4, type RouterOptionsType as a5, type HandlerForServerless as a6, type DefaultRouterType as a7, type ValidatedMiddlewaresType as a8, type MergeParentMiddlewaresType as a9, type ValidatedFullPathType as aa, type MergeParentAndChildPathsType as ab, type ExtractRequestsFromMiddlewaresForServer as ac, type ExtractRequestsFromMiddlewaresForClient as ad, type MiddlewareOptions as ae, type RequestOnHandlerType as af, type AlreadyDefinedMethodsType as ag, type DefineAlreadyDefinedMethodsType as ah, type ExtractAllHandlersType as ai, type ExtractIncludes as aj, ServerResponseAdapter as b, serverResponseAdapter as c, ServerRouterAdapter as d, serverRouterAdapter as e, ServerlessRouterAdapter as f, serverlessRouterAdapter as g, type ParseHandlerServerless as h, ServerlessAdapter as i, serverlessAdapter as j, Middleware as k, Request as l, middleware as m, nestedMiddleware as n, MethodsRouter as o, type ServerSettingsType as p, type DefaultRouterDefinitions as q, requestMiddleware as r, serverAdapter as s, type ServersSettingsType as t, type ExtractResponsesFromMiddlewaresRequestFromRouters as u, type ExtractResponsesFromMiddlewaresRequest as v, type DefaultResponseType as w, type ResponseTypeType as x, type MimeTypes as y, type ExtractQueryParamsFromPathType as z };