import { Domain, SettingsType2, Narrow } from '@palmares/core';
import { S as StatusCodes, R as RedirectionStatusCodes } from './status-RlKnv8eR.cjs';
import { FileLike } from './response/utils.cjs';

/**
 * Functional approach to creating a server adapter instead of the default class/inheritance approach.
 */
declare function serverResponseAdapter<TRedirectFunction extends ServerResponseAdapter['redirect'], TSendFunction extends ServerResponseAdapter['send'], TStreamFunction extends ServerResponseAdapter['stream'], TSendFileFunction extends ServerResponseAdapter['sendFile']>(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<any>;
    /**
     * 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<any>;
    stream(_serverAdapter: ServerAdapter | ServerlessAdapter, _serverInstance: any, _serverRequestAndResponseData: any, _status: number, _headers: {
        [key: string]: string;
    } | undefined, _body: AsyncGenerator<any, any, any> | Generator<any, any, any>, _isAsync: boolean): Promise<any>;
    sendFile(_serverAdapter: ServerAdapter | ServerlessAdapter, _serverInstance: any, _serverRequestAndResponseData: any, _status: number, _headers: {
        [key: string]: string;
    } | undefined, _filePath: Blob | ArrayBuffer): Promise<any>;
}

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<string, {
    status: 500;
    statusText: string;
    headers: {
        "Content-Type": string;
    };
}>;
declare const DEFAULT_SERVER_ERROR_INVALID_QUERY_OR_PARAMS: () => Response<string, {
    context: undefined;
    headers: object & {
        "Content-Type": "text/html";
    };
    status: 400;
}>;

type ModifiedResponsesFromMiddlewares<TFinalResponse extends Response<any, {
    context: any;
    headers: any;
    status: any;
}>, TMiddlewares extends readonly Middleware[] = []> = TMiddlewares extends [...infer TRestMiddlewares, infer TLastMiddleware] ? TLastMiddleware extends Middleware ? TLastMiddleware['response'] extends (response: Response<any, any>) => Promise<infer TResponse> | infer TResponse ? TResponse extends Response<any, any> ? ModifiedResponsesFromMiddlewares<Response<TResponse['body'] extends undefined ? TFinalResponse['body'] : TResponse['body'], {
    status: TFinalResponse['status'];
    headers: TResponse['headers'] & TFinalResponse['headers'];
    context: TResponse['context'] & TFinalResponse['context'];
}>, TRestMiddlewares extends readonly Middleware[] ? TRestMiddlewares : []> : never : never : ModifiedResponsesFromMiddlewares<TFinalResponse, TRestMiddlewares extends readonly Middleware[] ? TRestMiddlewares : []> : TFinalResponse;
type ExtractResponsesFromMiddlewaresRequestAndRouterHandlers<TRouters extends DefaultRouterType[] | Omit<DefaultRouterType, never>[]> = (ExtractAllHandlersType<TRouters> extends (request: any) => infer TResponse | Promise<infer TResponse> ? TResponse extends Response<any, any> ? TResponse : never : never) | ExtractResponsesFromMiddlewaresRequestFromRouters<TRouters> | 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<TRouters extends DefaultRouterType[] | Omit<DefaultRouterType, never>[], TFinalResponses extends Response<any, any> = never> = TRouters extends [infer TFirstRouter, ...infer TRestRouters] ? TFirstRouter extends BaseRouter<any, infer TRouterChildren, infer TMiddlewares, any, any> | Omit<BaseRouter<any, infer TRouterChildren, infer TMiddlewares, any, any>, never> ? TMiddlewares extends readonly Middleware[] ? TMiddlewares extends readonly [infer TFirstMiddie, ...infer TRestMiddlewares] ? TFirstMiddie extends {
    request: (request: Request<any, any>) => Promise<infer TResponseOrRequest> | infer TResponseOrRequest;
    response: (response: any) => Promise<infer TResponse> | infer TResponse;
} ? ExtractResponsesFromMiddlewaresRequestFromRouters<TRestRouters extends DefaultRouterType[] | Omit<DefaultRouterType, never>[] ? TRestRouters : [], (TResponseOrRequest extends Response<any, any> ? TResponseOrRequest : never) | (TResponse extends Response<any, any> ? TResponse : never)> | ExtractResponsesFromMiddlewaresRequestFromRouters<TRouterChildren extends DefaultRouterType[] | Omit<DefaultRouterType, never>[] ? TRouterChildren : [], (TResponseOrRequest extends Response<any, any> ? TResponseOrRequest : never) | (TResponse extends Response<any, any> ? TResponse : never)> | ExtractResponsesFromMiddlewaresRequestFromRouters<[
    BaseRouter<any, any, TRestMiddlewares extends readonly Middleware[] ? TRestMiddlewares : [], any, any>
], (TResponseOrRequest extends Response<any, any> ? TResponseOrRequest : never) | (TResponse extends Response<any, any> ? TResponse : never)> : ExtractResponsesFromMiddlewaresRequestFromRouters<TRestRouters extends DefaultRouterType[] | Omit<DefaultRouterType, never>[] ? TRestRouters : [], TFinalResponses> | ExtractResponsesFromMiddlewaresRequestFromRouters<TRouterChildren extends DefaultRouterType[] | Omit<DefaultRouterType, never>[] ? TRouterChildren : [], TFinalResponses> | ExtractResponsesFromMiddlewaresRequestFromRouters<[
    BaseRouter<any, any, TRestMiddlewares extends readonly Middleware[] ? TRestMiddlewares : [], any, any>
], TFinalResponses> : TFinalResponses : ExtractResponsesFromMiddlewaresRequestFromRouters<TRestRouters extends DefaultRouterType[] | Omit<DefaultRouterType, never>[] ? TRestRouters : [], TFinalResponses> | ExtractResponsesFromMiddlewaresRequestFromRouters<TRouterChildren extends DefaultRouterType[] | Omit<DefaultRouterType, never>[] ? TRouterChildren : [], TFinalResponses> : TFinalResponses : TFinalResponses;
type ExtractResponsesFromMiddlewaresRequest<TMiddlewares extends readonly Middleware[], TMiddlewaresPassed extends readonly Middleware[] = [], TFinalResponses extends Response<any, {
    context: any;
    headers: any;
    status: any;
}> = never> = TMiddlewares extends readonly [infer TFirstMiddie, ...infer TRestMiddlewares] ? TFirstMiddie extends Middleware ? TFirstMiddie['request'] extends (request: Request<any, any>) => Promise<infer TResponseOrRequest> | infer TResponseOrRequest ? Exclude<TResponseOrRequest, Request<any, any>> extends never ? ExtractResponsesFromMiddlewaresRequest<TRestMiddlewares extends readonly Middleware[] ? TRestMiddlewares : [], [
    ...TMiddlewaresPassed,
    TFirstMiddie
], TFinalResponses> : TResponseOrRequest extends Response<any, any> ? ExtractResponsesFromMiddlewaresRequest<TRestMiddlewares extends readonly Middleware[] ? TRestMiddlewares : [], [
    ...TMiddlewaresPassed,
    TFirstMiddie
], ModifiedResponsesFromMiddlewares<Exclude<TResponseOrRequest, Request<any, any>>, [
    ...TMiddlewaresPassed,
    TFirstMiddie
]> | TFinalResponses> : never : never : never : TFinalResponses;
type DefaultResponseType = Response<any, {
    status: any;
    headers: any;
    context: any;
}>;
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<ResponseHeaderTypes, string | string[]> | Record<string, string | string[]>;

declare class Response<TBody extends unknown | undefined | ArrayBuffer | Blob | FileLike | (() => AsyncGenerator<any, any, any> | Generator<any, any, any>) | string | object = undefined, TResponse extends {
    status?: StatusCodes;
    responses?: Record<string, (...args: any[]) => Response<any, any> | Promise<Response<any, any>>> | 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<TBody extends any | any[], TResponse extends {
        status?: StatusCodes;
        headers?: HeadersType;
        context?: object;
    }>(body: TBody, options?: TResponse): Response<TBody, {
        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;
    }>;
    /**
     * 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<TBody extends () => AsyncGenerator<any, any, any> | Generator<any, any, any>, TResponse extends {
        status?: StatusCodes;
        headers?: object | unknown;
        context?: object | unknown;
    } = {
        status: undefined;
        headers: undefined;
        context: undefined;
    }>(body: TBody, options?: TResponse & {
        statusText?: string;
    }): Response<ReturnType<TBody>, {
        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<TBody extends FileLike | ArrayBuffer | Blob, TResponse extends {
        status?: StatusCodes;
        headers?: object | unknown;
        context?: object | unknown;
    } = {
        status: undefined;
        headers: undefined;
        context: undefined;
    }>(body: TBody, options?: TResponse & {
        statusText?: string;
        filename?: string;
    }): Response<TBody extends FileLike ? TBody["blob"] : TBody, {
        context: TResponse["context"] extends object ? TResponse["context"] : undefined;
        headers: (TResponse["headers"] extends object ? TResponse["headers"] : object) & {
            [DEFAULT_RESPONSE_HEADERS_CONTENT_HEADER_KEY]: string;
            [DEFAULT_RESPONSE_HEADERS_CONTENT_DISPOSITION_KEY]: string;
        };
        status: TResponse["status"] extends StatusCodes ? TResponse["status"] : 200 | 201;
    }>;
    /**
     * 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<TUrl extends string, TResponse extends {
        status?: RedirectionStatusCodes;
        headers?: object | unknown;
        context?: object | unknown;
    } = {
        status: undefined;
        headers: undefined;
        context: undefined;
    }>(url: TUrl, options?: TResponse): Response<undefined, {
        context: TResponse["context"] extends object ? TResponse["context"] : undefined;
        headers: TResponse["headers"] extends object ? TResponse["headers"] : object & {
            [DEFAULT_RESPONSE_HEADERS_LOCATION_HEADER_KEY]: TUrl;
        };
        status: TResponse["status"] extends StatusCodes ? TResponse["status"] : 302;
    }>;
    /**
     * 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('<h1>Hello World</h1>');
     * });
     * ```
     *
     * @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<TResponse extends {
        status?: StatusCodes;
        headers?: object | unknown;
        context?: object | unknown;
    } = {
        status: undefined;
        headers: undefined;
        context: undefined;
    }>(htmlBody: string, options?: TResponse & {
        statusText?: string;
    }): Response<string, {
        context: TResponse["context"] extends object ? TResponse["context"] : undefined;
        headers: (TResponse["headers"] extends object ? TResponse["headers"] : object) & {
            [DEFAULT_RESPONSE_HEADERS_CONTENT_HEADER_KEY]: "text/html";
        };
        status: TResponse["status"] extends StatusCodes ? TResponse["status"] : 200 | 201;
    }>;
    /**
     * 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('<h1>Hello World</h1>');
     * });
     * ```
     *
     * @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<TResponse extends {
        status?: StatusCodes;
        headers?: object | unknown;
        context?: object | unknown;
    } = {
        status: undefined;
        headers: undefined;
        context: undefined;
    }>(text: string, options?: TResponse & {
        statusText?: string;
    }): Response<string, {
        context: TResponse["context"] extends object ? TResponse["context"] : undefined;
        headers: (TResponse["headers"] extends object ? TResponse["headers"] : object) & {
            [DEFAULT_RESPONSE_HEADERS_CONTENT_HEADER_KEY]: "plain/text";
        };
        status: TResponse["status"] extends StatusCodes ? TResponse["status"] : 200 | 201;
    }>;
    /**
     * 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<undefined, {
        status: StatusCodes;
    }>;
    /**
     * 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 extends Error = 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<TNewResponse extends {
        body?: object;
        status?: StatusCodes;
        headers?: HeadersType | unknown;
        context?: object | unknown;
    } = {
        body: never;
        status: undefined;
        headers: undefined;
        context: undefined;
    }>(args?: TNewResponse, options?: {
        inPlace: boolean;
    }): Response<TNewResponse['body'] extends never ? TBody : TNewResponse['body'], {
        status: TNewResponse['status'] extends StatusCodes ? TNewResponse['status'] : TResponse['status'];
        headers: TNewResponse['headers'] extends object ? TNewResponse['headers'] : TResponse['headers'];
        context: TNewResponse['context'] extends object ? TNewResponse['context'] & TResponse['context'] : TResponse['context'];
    }>;
    /**
     * 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>(): 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<TBody>;
    /**
     * 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<string | undefined>;
    arrayBuffer(): Promise<ArrayBuffer | undefined>;
    blob(): Promise<Blob | undefined>;
    /**
     * 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<FormDataLike | {
        $$type: string;
        proxyCallback: ConstructorParameters<{
            new (proxyCallback?: {
                getValue: (name: string) => {
                    value: string | Blob | File;
                    fileName?: string;
                }[];
                getKeys: () => string[];
            }): /*elided*/ any;
        }>[0];
        data: Record<string, {
            value: string | Blob | File;
            fileName?: string;
        }[]>;
        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<string, string | Blob | File>;
    } | undefined>;
}

type AllServerSettingsType<TCustomServerSettings = unknown> = SettingsType2 & ServersSettingsType<TCustomServerSettings>;
type ServerSettingsType<TCustomServerSettings = unknown> = {
    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<Middleware>['response'];
    serverlessFolderLocation?: string;
    validation?: {
        handler?: (request: Request<any, any>) => Response<any, any>;
        /**
         * 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<Middleware>['response'];
};
type DefaultRequestDefinitions = {
    adapter: (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter;
};
type DefaultRouterDefinitions = {
    adapter: (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter;
};
type ServersSettingsType<TCustomServerSettings = unknown> = {
    servers: Record<string, ServerSettingsType<TCustomServerSettings>>;
    /**
     * 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<TCustomRouterOptions = any> = Map<MethodTypes | 'all', {
    handler: (serverRequestAndResponseData: any) => ReturnType<ServerResponseAdapter['send']>;
    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<TParseRouteFunction extends ServerRouterAdapter['parseRoute'], TParseHandlerFunction extends ServerRouterAdapter['parseHandler'], TParseHandlersFunction extends ServerRouterAdapter['parseHandlers'], TLoad404Function extends ServerRouterAdapter['load404']>(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<ServerResponseAdapter['send']>): Promise<void>;
    /**
     * 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<BaseRouter['__urlParamsAndPath']['params']['set']>[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<ServerResponseAdapter['send']>, _queryParams: BaseRouter['__queryParamsAndPath']['params'], _customOptions?: any): undefined;
    parseHandlers?(_serverAdapter: ServerAdapter, _server: any, _path: string, _methodsAndHandlers: ParseHandlersServer, _queryParams: BaseRouter['__queryParamsAndPath']['params'], _404Handler: (serverRequestAndResponseData: any) => ReturnType<ServerResponseAdapter['send']>): undefined;
}

/**
 * Remove the optional properties from an object.
 *
 * @example
 * ```ts
 * type Test = {
 *   a?: string;
 *   b: number;
 *   c?: boolean;
 * };
 * type WithoutOptionals = RemoveOptionals<Test>; // { b: number }
 * ```
 */
type RemoveOptionals<T> = {
    [K in keyof T as undefined extends T[K] ? never : K]: T[K];
};
type Exact<TOne, TTwo> = (<T>() => T extends TOne ? 1 : 0) extends <T>() => 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<TPath extends string, TMiddlewares extends readonly Middleware[], TMethod extends RequestMethodTypes = RequestMethodTypes, TResponses extends {
    [TKey in StatusCodes]?: (...args: any[]) => Response<any, {
        context?: unknown;
        headers?: Record<string, string> | unknown;
        status: TKey;
    }>;
} | undefined = undefined, TFinalRequest extends Request<any, any> = Request<TPath, {
    method: TMethod;
    headers: unknown;
    body: unknown;
    context: unknown;
    mode: RequestMode;
    cache: RequestCache;
    credentials: RequestCredentials;
    integrity: string;
    responses: TResponses extends object ? TResponses : undefined;
    destination: RequestDestination;
    referrer: string;
    referrerPolicy: ReferrerPolicy;
    redirect: RequestRedirect;
}>> = TMiddlewares extends readonly [infer TFirstMiddie, ...infer TRestMiddlewares] ? TFirstMiddie extends Middleware ? ReturnType<TFirstMiddie['request'] extends (...args: any[]) => any ? TFirstMiddie['request'] : (...args: any[]) => never> extends Promise<never> | never ? ExtractRequestsFromMiddlewaresForServer<TPath, TRestMiddlewares extends readonly Middleware[] ? TRestMiddlewares : [], TMethod, TResponses, TPath extends string ? Request<TPath, {
    method: TMethod;
    mode: TFinalRequest['mode'];
    body: TFinalRequest['body'];
    responses: TFirstMiddie extends {
        options: {
            responses: infer TResponses extends MiddlewareOptions['responses'];
        };
    } ? RemoveOptionals<TResponses> : 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<any, any>) => Promise<infer TRequest> | infer TRequest ? Extract<TRequest, Request<any, any>> extends Request<any, any> ? ExtractRequestsFromMiddlewaresForServer<TPath, TRestMiddlewares extends readonly Middleware[] ? TRestMiddlewares : [], TMethod, TResponses, TPath extends string ? Request<TPath, {
    body: Extract<TRequest, Request<any, any>>['body'] & TFinalRequest['body'];
    headers: Extract<TRequest, Request<any, any>>['headers'] & TFinalRequest['headers'];
    context: Extract<TRequest, Request<any, any>>['context'] & TFinalRequest['context'];
    responses: RemoveOptionals<Extract<TRequest, Request<any, any>>['responses']> & (RemoveOptionals<TFinalRequest['responses']> extends undefined ? unknown : RemoveOptionals<TFinalRequest['responses']>) & (RemoveOptionals<TResponses> extends undefined ? unknown : RemoveOptionals<TResponses>);
    method: TMethod;
    mode: Extract<TRequest, Request<any, any>>['mode'] extends RequestMode ? Extract<TRequest, Request<any, any>>['mode'] : TFinalRequest['mode'] extends RequestMode ? TFinalRequest['mode'] : RequestMode;
    cache: Extract<TRequest, Request<any, any>>['cache'] extends RequestCache ? Extract<TRequest, Request<any, any>>['cache'] : TFinalRequest['cache'] extends RequestCache ? TFinalRequest['cache'] : RequestCache;
    credentials: Extract<TRequest, Request<any, any>>['credentials'] extends RequestCredentials ? Extract<TRequest, Request<any, any>>['credentials'] : TFinalRequest['credentials'] extends RequestCredentials ? TFinalRequest['credentials'] : RequestCredentials;
    integrity: Extract<TRequest, Request<any, any>>['integrity'] extends string ? Extract<TRequest, Request<any, any>>['integrity'] : TFinalRequest['integrity'] extends string ? TFinalRequest['integrity'] : string;
    destination: Extract<TRequest, Request<any, any>>['destination'] extends RequestDestination ? Extract<TRequest, Request<any, any>>['destination'] : TFinalRequest['destination'] extends RequestDestination ? TFinalRequest['destination'] : RequestDestination;
    referrer: Extract<TRequest, Request<any, any>>['referrer'] extends string ? Extract<TRequest, Request<any, any>>['referrer'] : TFinalRequest['referrer'] extends string ? TFinalRequest['referrer'] : string;
    referrerPolicy: Extract<TRequest, Request<any, any>>['referrer'] extends ReferrerPolicy ? Extract<TRequest, Request<any, any>>['referrer'] : TFinalRequest['referrer'] extends ReferrerPolicy ? TFinalRequest['referrer'] : ReferrerPolicy;
    redirect: Extract<TRequest, Request<any, any>>['redirect'] extends RequestRedirect ? Extract<TRequest, Request<any, any>>['redirect'] : TFinalRequest['redirect'] extends RequestRedirect ? TFinalRequest['redirect'] : RequestRedirect;
}> : TFinalRequest> : ExtractRequestsFromMiddlewaresForServer<TPath, TRestMiddlewares extends readonly Middleware[] ? TRestMiddlewares : [], TMethod, TResponses, TPath extends string ? Request<TPath, {
    method: TMethod;
    mode: TFinalRequest['mode'];
    body: TFinalRequest['body'];
    responses: undefined extends TResponses ? TFinalRequest['responses'] : undefined extends TFinalRequest['responses'] ? TResponses : TResponses & TFinalRequest['responses'];
    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> : ExtractRequestsFromMiddlewaresForServer<TPath, TRestMiddlewares extends readonly Middleware[] ? TRestMiddlewares : [], TMethod, TResponses, TPath extends string ? Request<TPath, {
    method: TMethod;
    mode: TFinalRequest['mode'];
    body: TFinalRequest['body'];
    responses: undefined extends TResponses ? TFinalRequest['responses'] : undefined extends TFinalRequest['responses'] ? TResponses : TResponses & TFinalRequest['responses'];
    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> : ExtractRequestsFromMiddlewaresForServer<TPath, TRestMiddlewares extends readonly Middleware[] ? TRestMiddlewares : [], TMethod, TResponses, TPath extends string ? Request<TPath, {
    method: TMethod;
    mode: TFinalRequest['mode'];
    body: TFinalRequest['body'];
    responses: undefined extends TResponses ? TFinalRequest['responses'] : undefined extends TFinalRequest['responses'] ? TResponses : TResponses & TFinalRequest['responses'];
    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> : TFinalRequest;
type ExtractRequestsFromMiddlewaresForClient<TPath extends string, TMiddlewares extends readonly Middleware[], TPreviousServerRequest extends Request<any, any> = Request<string, {
    method: RequestMethodTypes;
    headers: unknown;
    body: unknown;
    context: unknown;
    mode: RequestMode;
    cache: RequestCache;
    credentials: RequestCredentials;
    integrity: string;
    destination: RequestDestination;
    referrer: string;
    referrerPolicy: ReferrerPolicy;
    redirect: RequestRedirect;
}>, TFinalRequestClient extends Request<any, any> = Request<string, {
    method: RequestMethodTypes;
    headers: unknown;
    body: unknown;
    context: unknown;
    mode: RequestMode;
    cache: RequestCache;
    credentials: RequestCredentials;
    integrity: string;
    destination: RequestDestination;
    referrer: string;
    referrerPolicy: ReferrerPolicy;
    redirect: RequestRedirect;
}>> = TMiddlewares extends readonly [infer TFirstMiddie, ...infer TRestMiddlewares] ? TFirstMiddie extends Middleware ? TFirstMiddie['request'] extends (request: infer TRequestClient) => Promise<infer TRequestServer> | infer TRequestServer ? TRequestClient extends Request<any, any> ? TRequestServer extends Request<any, any> ? TPreviousServerRequest extends Request<any, any> ? 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<TPath, TRestMiddlewares extends readonly Middleware[] ? TRestMiddlewares : [], TRequestServer, TPath extends string ? Request<TPath, {
    body: TRequestClient['body'] & TFinalRequestClient['body'];
    headers: TRequestClient['headers'] & TFinalRequestClient['headers'];
    context: TRequestClient['context'] & TFinalRequestClient['context'];
    method: TRequestClient['method'] extends RequestMethodTypes ? TRequestClient['method'] : TFinalRequestClient['method'] extends RequestMethodTypes ? TFinalRequestClient['method'] : RequestMethodTypes;
    mode: TRequestClient['mode'] extends RequestMode ? TRequestClient['mode'] : TFinalRequestClient['mode'] extends RequestMode ? TFinalRequestClient['mode'] : RequestMode;
    cache: TRequestClient['cache'] extends RequestCache ? TRequestClient['cache'] : TFinalRequestClient['cache'] extends RequestCache ? TFinalRequestClient['cache'] : RequestCache;
    credentials: TRequestClient['credentials'] extends RequestCredentials ? TRequestClient['credentials'] : TFinalRequestClient['credentials'] extends RequestCredentials ? TFinalRequestClient['credentials'] : RequestCredentials;
    integrity: TRequestClient['integrity'] extends string ? TRequestClient['integrity'] : TFinalRequestClient['integrity'] extends string ? TFinalRequestClient['integrity'] : string;
    destination: TRequestClient['destination'] extends RequestDestination ? TRequestClient['destination'] : TFinalRequestClient['destination'] extends RequestDestination ? TFinalRequestClient['destination'] : RequestDestination;
    referrer: TRequestClient['referrer'] extends string ? TFinalRequestClient['referrer'] : TFinalRequestClient['referrer'] extends string ? TFinalRequestClient['referrer'] : string;
    referrerPolicy: TRequestClient['referrer'] extends ReferrerPolicy ? TRequestClient['referrer'] : TFinalRequestClient['referrer'] extends ReferrerPolicy ? TFinalRequestClient['referrer'] : ReferrerPolicy;
    redirect: TRequestClient['redirect'] extends RequestRedirect ? TRequestClient['redirect'] : TFinalRequestClient['redirect'] extends RequestRedirect ? TFinalRequestClient['redirect'] : RequestRedirect;
}> : TFinalRequestClient> : ExtractRequestsFromMiddlewaresForClient<TPath, TRestMiddlewares extends readonly Middleware[] ? TRestMiddlewares : [], TRequestServer, TFinalRequestClient> : 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<TServerAdapter extends (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter = (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter> = {
    responses?: {
        [TKey in StatusCodes]?: (...args: any[]) => Response<any, {
            context?: unknown;
            headers?: Record<string, string> | unknown;
            status: TKey;
        }>;
    } | undefined;
    customOptions?: TServerAdapter['routers']['parseHandlers'] extends (...args: any) => any ? NonNullable<Parameters<Parameters<TServerAdapter['routers']['parseHandlers']>[3]['set']>[1]>['options'] : TServerAdapter['routers'] extends ServerRouterAdapter ? TServerAdapter['routers']['parseHandler'] extends (...args: any) => any ? Parameters<TServerAdapter['routers']['parseHandler']>[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<TRouter extends DefaultRouterType = DefaultRouterType> {
    /**
     * 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<string, { headers: { 'x-string'}}) => {
     *      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<TRouter['path'], TRouter extends BaseRouter<any, any, infer TInferMiddlewares, any> ? TInferMiddlewares extends readonly Middleware[] ? TInferMiddlewares : [] : []>) => Promise<DefaultRequestType | DefaultResponseType> | 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> | 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<TRouter extends DefaultRouterType, TOptions extends MiddlewareOptions, TReturnOfResponseFunction extends Response<any, any> = never, TReturnOfRequestFunction extends Request<any, any> | Response<any, any> = never, TRouterMiddlewares = TRouter extends BaseRouter<any, any, infer TInferMiddlewares, any> ? 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<string, { headers: { 'x-string'}}) => {
     *      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<TRouter['path'], TRouterMiddlewares, RequestMethodTypes, TOptions['responses']> : Request<TRouter['path'], {
        method: RequestMethodTypes;
        headers: unknown;
        body: unknown;
        context: unknown;
        mode: RequestMode;
        cache: RequestCache;
        credentials: RequestCredentials;
        integrity: string;
        destination: RequestDestination;
        referrer: string;
        responses: TOptions['responses'];
        referrerPolicy: ReferrerPolicy;
        redirect: RequestRedirect;
    }>) => TReturnOfRequestFunction | Promise<TReturnOfRequestFunction>;
    /**
     * 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<TReturnOfRequestFunction, Request<any, any>> | ExtractResponsesFromMiddlewaresRequestAndRouterHandlers<[TRouter]>) & {
        responses: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer<TRouter['path'], TRouterMiddlewares, RequestMethodTypes, TOptions['responses']>['responses'] : TOptions['responses'];
    }) => Promise<TReturnOfResponseFunction> | 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<Middleware, "options"> & {
    request: (request: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer<TRouter["path"], TRouterMiddlewares, RequestMethodTypes, TOptions["responses"]> : string) => TReturnOfRequestFunction | Promise<TReturnOfRequestFunction>;
    response: (response: (Exclude<TReturnOfRequestFunction, Request<any, any>> | ExtractResponsesFromMiddlewaresRequestAndRouterHandlers<[TRouter]>) & {
        responses: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer<TRouter["path"], TRouterMiddlewares, RequestMethodTypes, TOptions["responses"]>["responses"] : TOptions["responses"];
    }) => Promise<TReturnOfResponseFunction> | 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<typeof baseRouter>()({
 *    // 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<TRouter extends DefaultRouterType>(): <TOptions extends MiddlewareOptions, TReturnOfResponseFunction extends Response<any, any> = never, TReturnOfRequestFunction extends Request<any, any> | Response<any, any> = never, TRouterMiddlewares = TRouter extends BaseRouter<any, any, infer TInferMiddlewares extends readonly Middleware<any>[], any, unknown, unknown, DefaultRouterDefinitions> ? TInferMiddlewares extends readonly Middleware<DefaultRouterType>[] ? 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<string, { headers: { 'x-string'}}) => {
     *      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<TRouter["path"], TRouterMiddlewares, RequestMethodTypes, TOptions["responses"]> : Request<TRouter["path"], {
        method: RequestMethodTypes;
        headers: unknown;
        body: unknown;
        context: unknown;
        mode: RequestMode;
        cache: RequestCache;
        credentials: RequestCredentials;
        integrity: string;
        destination: RequestDestination;
        referrer: string;
        responses: TOptions["responses"];
        referrerPolicy: ReferrerPolicy;
        redirect: RequestRedirect;
    }>) => TReturnOfRequestFunction | Promise<TReturnOfRequestFunction>;
    /**
     * 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<TReturnOfRequestFunction, Request<any, any>> | ExtractResponsesFromMiddlewaresRequestAndRouterHandlers<[TRouter]>) & {
        responses: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer<TRouter["path"], TRouterMiddlewares, RequestMethodTypes, TOptions["responses"]>["responses"] : TOptions["responses"];
    }) => Promise<TReturnOfResponseFunction> | 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<Middleware, "options"> & {
    options: TOptions extends undefined ? undefined : TOptions;
    request: (request: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer<TRouter["path"], TRouterMiddlewares, RequestMethodTypes, TOptions["responses"]> : Request<TRouter["path"], {
        method: RequestMethodTypes;
        headers: unknown;
        body: unknown;
        context: unknown;
        mode: RequestMode;
        cache: RequestCache;
        credentials: RequestCredentials;
        integrity: string;
        destination: RequestDestination;
        referrer: string;
        responses: TOptions["responses"];
        referrerPolicy: ReferrerPolicy;
        redirect: RequestRedirect;
    }>) => TReturnOfRequestFunction | Promise<TReturnOfRequestFunction>;
    response: (response: ExtractResponsesFromMiddlewaresRequestAndRouterHandlers<[TRouter]>) => Promise<TReturnOfResponseFunction> | TReturnOfResponseFunction;
};
declare function requestMiddleware<TRequest extends Request<any, any>, TRouter extends DefaultRouterType = DefaultRouterType>(): <TOptions extends MiddlewareOptions, TReturnOfResponseFunction extends Response<any, any> = never, TReturnOfRequestFunction extends Request<any, any> | Response<any, any> = never, TRouterMiddlewares = TRouter extends BaseRouter<any, any, infer TInferMiddlewares extends readonly Middleware<any>[], any, unknown, unknown, DefaultRouterDefinitions> ? TInferMiddlewares extends readonly Middleware<DefaultRouterType>[] ? 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<string, { headers: { 'x-string'}}) => {
     *      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<TRouter["path"], TRouterMiddlewares extends readonly Middleware[] ? TRouterMiddlewares : [], RequestMethodTypes, TOptions["responses"]>) => TReturnOfRequestFunction | Promise<TReturnOfRequestFunction>;
    /**
     * 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<TReturnOfRequestFunction, Request<any, any>> | ExtractResponsesFromMiddlewaresRequestAndRouterHandlers<[TRouter]>) & {
        responses: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer<TRouter["path"], TRouterMiddlewares, RequestMethodTypes, TOptions["responses"]>["responses"] : TOptions["responses"];
    }) => Promise<TReturnOfResponseFunction> | 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<Middleware, "options"> & {
    options: TOptions extends undefined ? undefined : TOptions;
    request: (request: TRouterMiddlewares extends readonly Middleware[] ? ExtractRequestsFromMiddlewaresForServer<TRouter["path"], TRouterMiddlewares, RequestMethodTypes, TOptions["responses"]> : Request<TRouter["path"], {
        method: RequestMethodTypes;
        headers: unknown;
        body: unknown;
        context: unknown;
        mode: RequestMode;
        cache: RequestCache;
        credentials: RequestCredentials;
        integrity: string;
        destination: RequestDestination;
        referrer: string;
        responses: TOptions["responses"];
        referrerPolicy: ReferrerPolicy;
        redirect: RequestRedirect;
    }>) => TReturnOfRequestFunction | Promise<TReturnOfRequestFunction>;
    response: (response: ExtractResponsesFromMiddlewaresRequestAndRouterHandlers<[TRouter]>) => Promise<TReturnOfResponseFunction> | TReturnOfResponseFunction;
};

type MethodTypes = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head' | 'options';
type MergeParentAndChildPathsType<TParentRouter extends BaseRouter<any, any, any, any, any>, TPathFromChild extends string> = TParentRouter extends BaseRouter<any, any, any, infer TRootPath, any> ? 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, TPathFromChild> = TMergedPath extends string | undefined ? TMergedPath : TPathFromChild;
type MergeParentMiddlewaresType<TParentRouter extends BaseRouter<any, any, any, any, any>> = TParentRouter extends BaseRouter<any, any, infer TParentMiddlewares, any, any> ? TParentMiddlewares extends readonly Middleware[] ? TParentMiddlewares['length'] extends 0 ? [] : TParentMiddlewares : [] : [];
type ValidatedMiddlewaresType<TMiddlewares> = TMiddlewares extends readonly Middleware[] ? TMiddlewares : [];
type DefaultRouterType = BaseRouter<any, any, any, any, any>;
/**
 * 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<TRootPath extends string, TMiddlewares extends readonly Middleware[], TMethod extends RequestMethodTypes = RequestMethodTypes, TResponses extends Record<string, (...args: any[]) => Response<any, any> | Promise<Response<any, any>>> | undefined = undefined> = TMiddlewares['length'] extends 0 ? Request<TRootPath, any> : ExtractRequestsFromMiddlewaresForServer<TRootPath, TMiddlewares, TMethod, TResponses>;
/**
 * 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<TRootPath extends string, TMiddlewares extends readonly (Middleware | never)[], TMethod extends RequestMethodTypes = RequestMethodTypes, TResponses extends Record<string, (...args: any[]) => Response<any, any> | Promise<Response<any, any>>> | undefined = undefined> = (request: RequestOnHandlerType<TRootPath, TMiddlewares, TMethod, TResponses>) => RequestOnHandlerType<TRootPath, TMiddlewares, TMethod, TResponses>['responses'] extends never ? Promise<Response<any, any>> | Response<any, any> : ExtractPossibleResponsesOfHandlerType<RequestOnHandlerType<TRootPath, TMiddlewares, TMethod, TResponses>['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<TPossibleResponses extends Record<string, (...args: any) => Response<any, any>>> = ReturnType<TPossibleResponses[keyof TPossibleResponses]> | Response<any, {
    context?: any;
    headers?: any;
    status?: Exclude<`${StatusCodes}`, keyof TPossibleResponses> extends `${infer TStatusCode extends StatusCodes}` ? TStatusCode : StatusCodes;
}> | Promise<Response<any, {
    context?: any;
    headers?: any;
    status?: Exclude<`${StatusCodes}`, keyof TPossibleResponses> 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<TRootPath extends string, TMiddlewares extends readonly Middleware[]> = {
    [key in MethodTypes]?: {
        handler: HandlerType<TRootPath, TMiddlewares>;
        options?: RouterOptionsType;
    };
};
type DefineAlreadyDefinedMethodsType<TRootPath extends string, TMiddlewares extends readonly Middleware[], TAlreadyDefinedMethods extends AlreadyDefinedMethodsType<TRootPath, TMiddlewares> | unknown, THandler extends HandlerType<TRootPath, any, any, any>, TOptions extends RouterOptionsType<any>, 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<BaseRouter, never>} 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<TRouters extends DefaultRouterType[] | Omit<DefaultRouterType, never>[], TFinalHandlers extends HandlerType<string, any> = never> = TRouters extends [infer TFirstRouter, ...infer TRestRouters] ? TFirstRouter extends BaseRouter<any, infer TRouterChildren, any, any, infer TDefinedHandlers> | Omit<BaseRouter<any, infer TRouterChildren, any, any, infer TDefinedHandlers>, never> ? (TDefinedHandlers[keyof TDefinedHandlers] extends {
    handler: any;
    options?: any;
} ? TDefinedHandlers[keyof TDefinedHandlers]['handler'] : never) | TFinalHandlers | ExtractAllHandlersType<TRouterChildren extends DefaultRouterType[] | Omit<DefaultRouterType, never>[] ? TRouterChildren : [], TFinalHandlers> | ExtractAllHandlersType<TRestRouters extends DefaultRouterType[] | Omit<DefaultRouterType, never>[] ? 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<TIncludes extends readonly (DefaultRouterType | Omit<DefaultRouterType, any>)[] | Narrow<readonly (DefaultRouterType | Omit<DefaultRouterType, any>)[]>, TRouters extends readonly DefaultRouterType[]> = TIncludes extends readonly [infer TFirstRouter, ...infer TRestRouters] ? TRestRouters extends readonly (DefaultRouterType | Omit<DefaultRouterType, any>)[] ? TFirstRouter extends DefaultRouterType ? ExtractIncludes<TRestRouters extends readonly (DefaultRouterType | Omit<DefaultRouterType, any>)[] ? TRestRouters : [], [
    ...TRouters,
    TFirstRouter
]> : TFirstRouter extends Omit<infer TRouter, any> ? TRouter extends DefaultRouterType ? ExtractIncludes<TRestRouters extends readonly (DefaultRouterType | Omit<DefaultRouterType, any>)[] ? TRestRouters : [], [
    ...TRouters,
    TRouter
]> : TRouters : TRouters : TRouters : TRouters;
type RouterOptionsType<TServerAdapter extends (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter = (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter> = MiddlewareOptions<TServerAdapter> & {
    middlewares?: Narrow<readonly Middleware[]>;
};

type ExtractTRouteTreesFromChildren<TRouters extends readonly (DefaultRouterType | Omit<DefaultRouterType, any>)[], TResult = unknown> = TRouters extends readonly [infer TRouterFirst, ...infer TRestRouters] ? TRouterFirst extends BaseRouter<any, any, any, any, any, infer TRootTRouteTree, any> ? TRestRouters extends readonly (DefaultRouterType | Omit<DefaultRouterType, any>)[] ? ExtractTRouteTreesFromChildren<TRestRouters, TResult & TRootTRouteTree> : 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<TParentRouter extends DefaultRouterType | undefined = undefined, TChildren extends readonly DefaultRouterType[] | undefined = undefined, TMiddlewares extends readonly Middleware<any>[] = never[], TRootPath extends string | undefined = undefined, TAlreadyDefinedHandlers extends AlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : '', readonly Middleware[]> | unknown = unknown, TRootRoutesTree = unknown, TDefinitions extends {
    adapter: (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter;
} = DefaultRouterDefinitions> {
    path: TRootPath;
    protected __domain: Domain<any>;
    protected __partsOfPath: {
        part: string;
        isUrlParam: boolean;
    }[];
    protected __queryParamsAndPath: {
        path: string;
        params: Map<string, {
            type: ('number' | 'string' | 'boolean')[];
            isOptional: boolean;
            isArray: boolean;
            regex: RegExp | undefined;
        }>;
    };
    protected __urlParamsAndPath: {
        path: string;
        params: Map<string, {
            type: ('number' | 'string' | 'boolean')[];
            regex: RegExp | undefined;
        }>;
    };
    protected __completePaths: Map<string, {
        middlewares: Middleware[];
        urlParams: BaseRouter["__urlParamsAndPath"]["params"];
        queryPath: string;
        urlPath: string;
        queryParams: BaseRouter["__queryParamsAndPath"]["params"];
        partsOfPath: {
            part: string;
            isUrlParam: boolean;
        }[];
        router: BaseRouter;
        handlers: { [method in MethodTypes]?: {
            handler: HandlerType<string, Middleware[]>;
            options?: RouterOptionsType;
        }; };
    }>;
    protected __parentRouter?: TParentRouter;
    protected __wasCreatedFromNested: boolean;
    protected __children?: TChildren;
    protected __middlewares: TMiddlewares;
    protected __handlers: TAlreadyDefinedHandlers;
    constructor(path: TRootPath, children?: TChildren);
    static new<TPath extends string | undefined = undefined>(path: TPath): MethodsRouter<undefined, [], [], TPath, undefined, unknown, DefaultRouterDefinitions>;
    static newNested<TParentRouter extends BaseRouter<any, any, any, any, any, any>>(): <TPath extends string, TFullPath = MergeParentAndChildPathsType<TParentRouter, TPath>, TMergedMiddlewares = MergeParentMiddlewaresType<TParentRouter>>(path: TPath) => MethodsRouter<TParentRouter, [], ValidatedMiddlewaresType<TMergedMiddlewares>, ValidatedFullPathType<TFullPath, TPath>, 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<const TIncludes extends readonly (DefaultRouterType | Omit<DefaultRouterType, never>)[]>(children: ((router: ReturnType<IncludesRouter<TParentRouter, TChildren, TMiddlewares, TRootPath, undefined>['child']>) => Narrow<TIncludes>) | Narrow<TIncludes>): MethodsRouter<TParentRouter, ExtractIncludes<TIncludes, []>, TMiddlewares, TRootPath, TAlreadyDefinedHandlers, TRootRoutesTree & ExtractTRouteTreesFromChildren<ExtractIncludes<TIncludes, []>>>;
    protected appendChildToParentRouter(router: DefaultRouterType, child: DefaultRouterType): void;
    middlewares<const TRouterMiddlewares extends readonly Middleware[]>(definedMiddlewares: Narrow<TRouterMiddlewares>): MethodsRouter<TParentRouter, TChildren, readonly [...(TMiddlewares['length'] extends 0 ? [] : TMiddlewares), ...TRouterMiddlewares], TRootPath, TAlreadyDefinedHandlers, TRootRoutesTree>;
    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<TParentRouter extends DefaultRouterType | undefined = undefined, TChildren extends readonly DefaultRouterType[] | undefined = undefined, TMiddlewares extends readonly Middleware[] = [], TRootPath extends string | undefined = undefined, TAlreadyDefinedMethods extends AlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : '', readonly Middleware[]> | undefined = undefined, TRootRoutesTree = unknown, TDefinitions extends {
    adapter: (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter;
} = DefaultRouterDefinitions> extends BaseRouter<TParentRouter, TChildren, TMiddlewares, TRootPath, TAlreadyDefinedMethods, TRootRoutesTree, TDefinitions> {
    /**
     * 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(): <TPath extends string, TFullPath = TRootPath extends `${infer InferedRootPath}?${infer InferedQueryParams}` ? TPath extends `${infer InferedPathFromChild}?${infer InferedQueryParamsFromChild}` ? `${InferedRootPath}${InferedPathFromChild}?${InferedQueryParams}&${InferedQueryParamsFromChild}` : `${InferedRootPath}${TPath}?${InferedQueryParams}` : TPath extends `${infer InferedPathFromChild_1}?${infer InferedQueryParamsFromChild_1}` ? `${TRootPath}${InferedPathFromChild_1}?${InferedQueryParamsFromChild_1}` : `${TRootPath}${TPath}`, TMergedMiddlewares = TMiddlewares extends readonly Middleware<DefaultRouterType>[] ? TMiddlewares["length"] extends 0 ? [] : TMiddlewares : []>(path: TPath) => MethodsRouter<BaseRouter<TParentRouter, TChildren, TMiddlewares, TRootPath, TAlreadyDefinedMethods, TRootRoutesTree, DefaultRouterDefinitions>, [], ValidatedMiddlewaresType<TMergedMiddlewares>, ValidatedFullPathType<TFullPath, TPath>, undefined, unknown, DefaultRouterDefinitions>;
}
declare class MethodsRouter<TParentRouter extends DefaultRouterType | undefined = undefined, TChildren extends readonly DefaultRouterType[] | undefined = undefined, TMiddlewares extends readonly Middleware[] = [], TRootPath extends string | undefined = undefined, TAlreadyDefinedMethods extends AlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : '', readonly Middleware[]> | unknown = unknown, TRootRoutesTree = unknown, TDefinitions extends {
    adapter: (ServerAdapter | ServerlessAdapter) & Palmares.PServerAdapter;
} = DefaultRouterDefinitions> extends BaseRouter<TParentRouter, TChildren, TMiddlewares, TRootPath, TAlreadyDefinedMethods, TRootRoutesTree, TDefinitions> {
    get<THandler extends HandlerType<TRootPath extends string ? TRootPath : string, [
        ...(TMiddlewares['length'] extends 0 ? [] : TMiddlewares),
        ...(TOptions['middlewares'] extends readonly Middleware[] ? TOptions['middlewares'] extends 0 ? [] : TOptions['middlewares'] : [])
    ], 'GET', TOptions['responses']>, TOptions extends RouterOptionsType<TDefinitions['adapter']>>(handler: THandler, options?: TOptions): Omit<MethodsRouter<TParentRouter, TChildren, TMiddlewares, TRootPath, DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, "get">, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, "get">; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | "get" | "all">;
    post<THandler extends HandlerType<TRootPath extends string ? TRootPath : string, [
        ...(TMiddlewares['length'] extends 0 ? [] : TMiddlewares),
        ...(TOptions['middlewares'] extends readonly Middleware[] ? TOptions['middlewares'] extends 0 ? [] : TOptions['middlewares'] : [])
    ], 'POST', TOptions['responses'] extends undefined ? undefined : TOptions['responses']>, TOptions extends RouterOptionsType<TDefinitions['adapter']>>(handler: THandler, options?: TOptions): Omit<MethodsRouter<TParentRouter, TChildren, TMiddlewares, TRootPath, DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, "post">, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, "post">; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | "post" | "all">;
    delete<THandler extends HandlerType<TRootPath extends string ? TRootPath : string, [
        ...(TMiddlewares['length'] extends 0 ? [] : TMiddlewares),
        ...(TOptions['middlewares'] extends readonly Middleware[] ? TOptions['middlewares'] extends 0 ? [] : TOptions['middlewares'] : [])
    ], 'DELETE', TOptions['responses'] extends undefined ? undefined : TOptions['responses']>, TOptions extends RouterOptionsType<TDefinitions['adapter']>>(handler: THandler, options?: TOptions): Omit<MethodsRouter<TParentRouter, TChildren, TMiddlewares, TRootPath, DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, "delete">, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, "delete">; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | "delete" | "all">;
    options<THandler extends HandlerType<TRootPath extends string ? TRootPath : string, [
        ...(TMiddlewares['length'] extends 0 ? [] : TMiddlewares),
        ...(TOptions['middlewares'] extends readonly Middleware[] ? TOptions['middlewares'] extends 0 ? [] : TOptions['middlewares'] : [])
    ], 'OPTIONS', TOptions['responses']>, TOptions extends RouterOptionsType<TDefinitions['adapter']>>(handler: THandler, options?: TOptions): Omit<MethodsRouter<TParentRouter, TChildren, TMiddlewares, TRootPath, DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, "options">, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, "post">; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | "options" | "all">;
    head<THandler extends HandlerType<TRootPath extends string ? TRootPath : string, [
        ...(TMiddlewares['length'] extends 0 ? [] : TMiddlewares),
        ...(TOptions['middlewares'] extends readonly Middleware[] ? TOptions['middlewares'] extends 0 ? [] : TOptions['middlewares'] : [])
    ], 'HEAD', TOptions['responses']>, TOptions extends RouterOptionsType<TDefinitions['adapter']>>(handler: THandler, options?: TOptions): Omit<MethodsRouter<TParentRouter, TChildren, TMiddlewares, TRootPath, DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, "head">, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, "head">; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | "head" | "all">;
    put<THandler extends HandlerType<TRootPath extends string ? TRootPath : string, [
        ...(TMiddlewares['length'] extends 0 ? [] : TMiddlewares),
        ...(TOptions['middlewares'] extends readonly Middleware[] ? TOptions['middlewares'] extends 0 ? [] : TOptions['middlewares'] : [])
    ], 'PUT', TOptions['responses']>, TOptions extends RouterOptionsType<TDefinitions['adapter']>>(handler: THandler, options?: TOptions): Omit<MethodsRouter<TParentRouter, TChildren, TMiddlewares, TRootPath, DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, "put">, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, "put">; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | "put" | "all">;
    patch<THandler extends HandlerType<TRootPath extends string ? TRootPath : string, [
        ...(TMiddlewares['length'] extends 0 ? [] : TMiddlewares),
        ...(TOptions['middlewares'] extends readonly Middleware[] ? TOptions['middlewares'] extends 0 ? [] : TOptions['middlewares'] : [])
    ], 'PATCH', TOptions['responses']>, TOptions extends RouterOptionsType<TDefinitions['adapter']>>(handler: THandler, options?: TOptions): Omit<MethodsRouter<TParentRouter, TChildren, TMiddlewares, TRootPath, DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, "patch">, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, "patch">; } & TRootRoutesTree>, keyof TAlreadyDefinedMethods | "patch" | "all">;
    all<THandler extends HandlerType<TRootPath extends string ? TRootPath : string, [
        ...(TMiddlewares['length'] extends 0 ? [] : TMiddlewares),
        ...(TOptions['middlewares'] extends readonly Middleware[] ? TOptions['middlewares'] extends 0 ? [] : TOptions['middlewares'] : [])
    ], RequestMethodTypes, TOptions['responses']>, TOptions extends RouterOptionsType<TDefinitions['adapter']>>(handler: THandler, options?: TOptions): Omit<MethodsRouter<TParentRouter, TChildren, TMiddlewares, TRootPath, DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, MethodTypes>, { [TKey in TRootPath as TKey extends string | number | symbol ? TKey : never]: DefineAlreadyDefinedMethodsType<TRootPath extends string ? TRootPath : string, TMiddlewares, TAlreadyDefinedMethods, THandler, TOptions, MethodTypes>; } & 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<void>;
    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<void>;
};
type ParseHandlerServerless<TCustomRouterOptions = any> = Map<MethodTypes | 'all', {
    handler: HandlerForServerless;
    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 serverlessRouterAdapter<TParseRouteFunction extends ServerlessRouterAdapter['parseRoute'], TParseHandlersFunction extends ServerlessRouterAdapter['parseHandlers'], TLoad404Function extends ServerlessRouterAdapter['load404']>(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<ServerResponseAdapter['send']>): Promise<void>;
    /**
     * 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<ServerResponseAdapter['send']>): Promise<void>;
    /**
     * 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<BaseRouter['__urlParamsAndPath']['params']['set']>[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<ServerResponseAdapter['send']>): Promise<undefined>;
}

/**
 * Functional approach to creating a server adapter instead of the default class/inheritance approach.
 */
declare function serverlessAdapter<TServerlessRequestAdapter extends ServerlessAdapter['request'], TServerlessResponseAdapter extends ServerlessAdapter['response'], TServerlessRouterAdapter extends ServerlessAdapter['routers'], TLoadFunction extends ServerlessAdapter['load'], TStartFunction extends ServerlessAdapter['generate'], TCustomServerSettings extends (typeof ServerlessAdapter)['customServerSettings']>(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<void>;
    generate(..._args: any[]): Promise<void>;
    static customServerSettings(args: AllServerSettingsType['servers'][string]['customServerSettings']): unknown;
}

declare class Request<TRoutePath extends string = string, TRequest extends {
    method?: RequestMethodTypes;
    headers?: {
        [key: string]: string;
    } | unknown;
    body?: unknown;
    responses?: Record<string, (...args: any[]) => Response<any, any> | Promise<Response<any, any>>> | 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<keyof ExtractQueryParamsFromPathType<TRoutePath>, {
            data: any;
            errorOn: keyof Parameters<BaseRouter["__queryParamsAndPath"]["params"]["set"]>[1][];
            type: Parameters<BaseRouter["__queryParamsAndPath"]["params"]["set"]>[1];
        }>;
        url?: Record<keyof ExtractUrlParamsFromPathType<TRoutePath>, {
            data: any;
            errorOn: keyof Parameters<BaseRouter["__urlParamsAndPath"]["params"]["set"]>[1][];
            type: Parameters<BaseRouter["__urlParamsAndPath"]["params"]["set"]>[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/<filter: string>').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<TRoutePath>;
    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<TRoutePath>;
    /**
     * 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<TNewRequest extends {
        headers?: object | unknown;
        body?: unknown;
        context?: object;
        mode?: RequestMode;
        cache?: RequestCache;
        credentials?: RequestCredentials;
        integrity?: string;
        destination?: RequestDestination;
        referrer?: string;
        referrerPolicy?: ReferrerPolicy;
        redirect?: RequestRedirect;
    } = {
        headers: unknown;
        body: undefined;
        context: object;
        mode: RequestMode;
        cache: RequestCache;
        credentials: RequestCredentials;
        integrity: string;
        destination: RequestDestination;
        referrer: string;
        referrerPolicy: ReferrerPolicy;
        redirect: RequestRedirect;
    }>(args?: TNewRequest, options?: {
        inPlace: boolean;
    }): Request<TRoutePath, {
        body: TNewRequest['body'] extends object | string ? TNewRequest['body'] : TRequest['body'];
        headers: TNewRequest['headers'] extends object ? TNewRequest['headers'] : TRequest['headers'];
        context: TNewRequest['context'] extends object ? TNewRequest['context'] : TRequest['context'];
        method: TRequest['method'];
        mode: TNewRequest['mode'] extends RequestMode ? TNewRequest['mode'] : TRequest['mode'] extends RequestMode ? TRequest['mode'] : RequestMode;
        cache: TNewRequest['cache'] extends RequestCache ? TNewRequest['cache'] : TRequest['cache'] extends RequestCache ? TRequest['cache'] : RequestCache;
        credentials: TNewRequest['credentials'] extends RequestCredentials ? TNewRequest['credentials'] : TRequest['credentials'] extends RequestCredentials ? TRequest['credentials'] : RequestCredentials;
        integrity: TNewRequest['integrity'] extends string ? TNewRequest['integrity'] : TRequest['integrity'] extends string ? TRequest['integrity'] : string;
        destination: TNewRequest['destination'] extends RequestDestination ? TNewRequest['destination'] : TRequest['destination'] extends RequestDestination ? TRequest['destination'] : RequestDestination;
        referrer: TNewRequest['referrer'] extends string ? TNewRequest['referrer'] : TRequest['referrer'] extends string ? TRequest['referrer'] : string;
        redirect: TNewRequest['redirect'] extends RequestRedirect ? TNewRequest['redirect'] : TRequest['redirect'] extends RequestRedirect ? TRequest['redirect'] : RequestRedirect;
        referrerPolicy: TNewRequest['referrerPolicy'] extends ReferrerPolicy ? TNewRequest['referrerPolicy'] : TRequest['referrerPolicy'] extends ReferrerPolicy ? TRequest['referrerPolicy'] : ReferrerPolicy;
        responses: TRequest['responses'];
    }, TDefinitions>;
    /**
     * 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<TDefinitions['adapter']['request']['headers']>[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<TDefinitions['adapter']['request']['toArrayBuffer']>[3]): Promise<ArrayBuffer | undefined>;
    /**
     * 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<TDefinitions['adapter']['request']['toJson']>[3]): Promise<TRequest['body'] | undefined>;
    /**
     * 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<TDefinitions['adapter']['request']['toBlob']>[3]): Promise<Blob | undefined>;
    /**
     * 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<TDefinitions['adapter']['request']['toFormData']>[5]): Promise<InstanceType<FormDataLike<TRequest['body']>> | 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<TDefinitions['adapter']['request']['toText']>[3]): Promise<string | undefined>;
    /**
     * 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<TDefinitions['adapter']['request']['toRaw']>[3]): Promise<any>;
}

type Whitespace = '\n' | ' ';
type Trim<T> = T extends `${Whitespace}${infer U}` ? Trim<U> : T extends `${infer U}${Whitespace}` ? Trim<U> : T;
type GetTypeByStringType<TString extends string, TFinalType = never> = TString extends `(${infer TUnionOrMergedTypes})` ? TUnionOrMergedTypes extends `${infer TType}|${infer TRest}` ? GetTypeByStringType<`(${TRest})`, TFinalType | GetTypeByStringType<TType>> : GetTypeByStringType<TUnionOrMergedTypes, TFinalType> : Trim<TString> extends 'number' ? TFinalType | number : Trim<TString> extends 'string' ? TFinalType | string : Trim<TString> extends 'boolean' ? TFinalType | boolean : TString;
type GetLastCharacterOfString<TString extends string> = TString extends `${string}${infer End}` ? End extends `` ? TString : GetLastCharacterOfString<End> : TString;
type GetTypeByStringForQueryParamsType<TString extends string> = TString extends `${infer TType}[]?` | `${infer TType}[]` ? GetLastCharacterOfString<TString> extends '?' ? GetTypeByStringType<TType>[] | undefined : GetTypeByStringType<TType>[] : TString extends `${infer TType}?` | `${infer TType}` ? GetLastCharacterOfString<TString> extends '?' ? GetTypeByStringType<TType> | undefined : GetTypeByStringType<TType> : never;
type ExtractStringWithoutSpacesType<TString extends string> = TString extends ` ${infer TRest}` ? ExtractStringWithoutSpacesType<`${TRest}`> : TString extends `${infer TRest} ` ? ExtractStringWithoutSpacesType<`${TRest}`> : TString;
type ExtractQueryParamsFromPathType<T extends string> = T extends `${string}?${infer TQueryParams}` ? ExtractUrlQueryParamsFromPathTypeRequiredAndOptional<TQueryParams> : never;
/**
 * Used for extracting all the url parameters as an object from a path string.
 */
type ExtractUrlParamsFromPathType<TPath extends string> = TPath extends `${string}<${infer TParam}:${infer TType}>${infer TRest}` | `${string}<${infer TParam}:${infer TType}>` ? {
    [key in TParam]: GetTypeByStringType<ExtractStringWithoutSpacesType<TType extends `${string}{${string}}:${infer TTypeOfRegex}` ? TTypeOfRegex : TType>>;
} & ExtractUrlParamsFromPathType<TRest> : object;
type ExtractUrlQueryParamsFromPathType<TPath extends string> = TPath extends `${infer TParam}=${infer TType}&${infer TRest}` ? {
    [key in TParam]: GetTypeByStringForQueryParamsType<ExtractStringWithoutSpacesType<TType extends `${string}{${string}}:${infer TTypeOfRegex}` ? TTypeOfRegex : TType>>;
} & ExtractUrlQueryParamsFromPathType<TRest> : TPath extends `${infer TParam}=${infer TType}` ? {
    [key in TParam]: GetTypeByStringForQueryParamsType<ExtractStringWithoutSpacesType<TType extends `${string}{${string}}:${infer TTypeOfRegex}` ? TTypeOfRegex : TType>>;
} : 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<TPath extends string> = {
    [key in keyof ExtractUrlQueryParamsFromPathType<TPath> as undefined extends ExtractUrlQueryParamsFromPathType<TPath>[key] ? never : key]: ExtractUrlQueryParamsFromPathType<TPath>[key];
} & {
    [key in keyof ExtractUrlQueryParamsFromPathType<TPath> as undefined extends ExtractUrlQueryParamsFromPathType<TPath>[key] ? key : never]?: ExtractUrlQueryParamsFromPathType<TPath>[key];
};
type DefaultRequestType = Request<string, {
    method: RequestMethodTypes;
    headers: unknown;
    body: unknown;
    context: unknown;
    mode: RequestMode;
    cache: RequestCache;
    credentials: RequestCredentials;
    integrity: string;
    destination: RequestDestination;
    referrer: string;
    referrerPolicy: ReferrerPolicy;
    redirect: RequestRedirect;
}>;
type FormDataLike<TObject = unknown> = {
    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: <TName extends keyof TObject>(name: TName) => TName extends keyof TObject ? TObject[TName] extends (infer TType)[] ? TType : TObject[TName] : string | Blob | File;
        getAll: <TName extends keyof TObject>(name: TName) => TName extends keyof TObject ? TObject[TName] extends any[] ? TObject[TName] : TObject[TName][] : string | Blob | File;
        has: (name: keyof TObject) => boolean;
        set: <TName extends keyof TObject>(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<MethodTypes | 'connect' | 'trace'>;
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<ServerAdapter['load']>, _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<ServerAdapter['load']>, _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<ServerAdapter['load']>, _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<ServerAdapter['load']>, _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<ServerAdapter['load']>, _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<typeof express.json>) => {
     *   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<ServerAdapter['load']>, _serverRequestAndResponseData: any, _options: any): Promise<object | undefined>;
    /**
     * 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<typeof express.urlencoded>
     *      | ReturnType<ReturnType<typeof multer>[keyof ReturnType<typeof multer>]>
     *      | 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<typeof multer>;
     *      if (options && !isUrlEncoded) middleware =
     *        (formDataParser[options.type as keyof ReturnType<typeof multer>] as any)(...optionsOfParser);
     *      if (!middleware) middleware = formDataParser.any();
     *    } else middleware = formDataOrUrlEncodedParser as ReturnType<typeof express.urlencoded>;
     *
     *    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<ServerAdapter['load']>, _serverRequestAndResponseData: any, _formDataConstructor: FormDataLike<any>, _isUrlEncoded: boolean, _options: any): Promise<InstanceType<FormDataLike<any>>>;
    /**
     * 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<typeof express.raw>) => {
     *  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<ServerAdapter['load']>, _serverRequestAndResponseData: any, _options: any): Promise<ArrayBuffer | undefined>;
    /**
     * 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<typeof express.raw>) => {
     *   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<ServerAdapter['load']>, _serverRequestAndResponseData: any, _options: any): Promise<Blob | File | undefined>;
    /**
     * 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<typeof express.raw>) => {
     *   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<any>;
    /**
     * 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<typeof express.raw>) => {
     *   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<string | undefined>;
}

/**
 * Functional approach to creating a server adapter instead of the default class/inheritance approach.
 */
declare function serverAdapter<TServerRequestAdapter extends ServerAdapter['request'], TServerResponseAdapter extends ServerAdapter['response'], TServerRouterAdapter extends ServerAdapter['routers'], TLoadFunction extends ServerAdapter['load'], TStartFunction extends ServerAdapter['start'], TCloseFunction extends ServerAdapter['close']>(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<any>;
    allSettings: AllServerSettingsType;
    domains: Domain[];
    routers: ServerRouterAdapter;
    request: ServerRequestAdapter;
    response: ServerResponseAdapter;
    constructor(serverName: string, allSettings: AllServerSettingsType, settings: ServerSettingsType<any>, 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<any>): Promise<any>;
    /**
     * 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<void>;
    /**
     * 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<void>;
}

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 };
