import { StatusCodeMap } from './types';
export type OkStatusCode = 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 226;
type RedirectStatusCode = 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308;
type ClientErrorStatusCode = 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451;
type ServerErrorStatusCode = 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511;
export type StatusCode = OkStatusCode | RedirectStatusCode | ClientErrorStatusCode | ServerErrorStatusCode;
export type NotOkStatusCode = Exclude<StatusCode, OkStatusCode>;
export type TypedBody<TJSON, TFormData extends Record<string, FormDataEntryValue | undefined>, THeaders extends Record<string, string | undefined>> = Omit<Body, 'json' | 'formData' | 'headers'> & {
    /**
     * The `json()` method takes the stream and reads it to completion.
     * It returns a promise which resolves with the result of parsing the body text as JSON.
     *
     * Note that despite the method being named `json()`, the result is not JSON but is instead the result of taking JSON as input and parsing it to produce a JavaScript object.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/json
     */
    json(): Promise<TJSON>;
    /**
     * The formData() method takes the stream and reads it to completion. It returns a promise that resolves with a `FormData` object.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/formData
     */
    formData(): Promise<TypedFormData<TFormData>>;
    /**
     * The headers read-only property of the Response interface contains the Headers object associated with the response.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/headers
     */
    headers: TypedHeaders<THeaders>;
};
type DefaultHTTPHeaders = 'accept' | 'accept-language' | 'content-language' | 'content-type' | 'content-length';
type Maybe = undefined | null;
type UndefinedToNull<T> = T extends undefined ? Exclude<T, undefined> | null : T;
export interface TypedHeaders<TMap extends Record<string, string | undefined>> {
    append<TName extends DefaultHTTPHeaders | keyof TMap>(name: TName, value: TName extends keyof TMap ? TMap[TName] : string): void;
    delete<TName extends DefaultHTTPHeaders | keyof TMap>(name: TName): void;
    get<TName extends DefaultHTTPHeaders | keyof TMap>(name: TName): TName extends keyof TMap ? UndefinedToNull<TMap[TName]> : TName extends DefaultHTTPHeaders ? string | null : never;
    has<TName extends DefaultHTTPHeaders | keyof TMap>(name: TName): TName extends DefaultHTTPHeaders ? boolean : TName extends keyof TMap ? TMap[TName] extends Maybe ? boolean : true : never;
    set<TName extends DefaultHTTPHeaders | keyof TMap>(name: TName, value: TName extends keyof TMap ? TMap[TName] : string): void;
    forEach(callbackfn: <TName extends keyof TMap>(value: TMap[TName], key: TName, parent: TypedHeaders<TMap>) => void, thisArg?: any): void;
    entries(): IterableIterator<[keyof TMap, TMap[keyof TMap]]>;
    keys(): IterableIterator<keyof TMap>;
    values(): IterableIterator<TMap[keyof TMap]>;
    [Symbol.iterator](): IterableIterator<[keyof TMap, TMap[keyof TMap]]>;
    getSetCookie(): string[];
}
export type TypedHeadersCtor = new <TMap extends Record<string, string>>(init?: TMap) => TypedHeaders<TMap>;
export type TypedResponseInit<TStatusCode extends StatusCode = 200> = Omit<ResponseInit, 'status' | 'statusText'> & {
    /**
     * This is the status code that will be set in the response.
     * For example, 200 for success, 404 if the resource could not be found.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/status
     */
    status: TStatusCode;
    /**
     * This is the status message that will be set in the response.
     * You don't need to set this value if it's a standard message.
     * For example, this would be OK for a status code 200, Continue for 100, Not Found for 404.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/statusText
     */
    statusText?: TStatusCode extends keyof StatusTextMap ? StatusTextMap[TStatusCode] : string;
};
export type StatusTextMap = {
    100: 'Continue';
    101: 'Switching Protocols';
    102: 'Processing';
    103: 'Early Hints';
    200: 'OK';
    201: 'Created';
    202: 'Accepted';
    203: 'Non-Authoritative Information';
    204: 'No Content';
    205: 'Reset Content';
    206: 'Partial Content';
    207: 'Multi-Status';
    208: 'Already Reported';
    226: 'IM Used';
    300: 'Multiple Choices';
    301: 'Moved Permanently';
    302: 'Found';
    303: 'See Other';
    304: 'Not Modified';
    305: 'Use Proxy';
    307: 'Temporary Redirect';
    308: 'Permanent Redirect';
    400: 'Bad Request';
    401: 'Unauthorized';
    402: 'Payment Required';
    403: 'Forbidden';
    404: 'Not Found';
    405: 'Method Not Allowed';
    406: 'Not Acceptable';
    407: 'Proxy Authentication Required';
    408: 'Request Timeout';
    409: 'Conflict';
    410: 'Gone';
    411: 'Length Required';
    412: 'Precondition Failed';
    413: 'Payload Too Large';
    414: 'URI Too Long';
    415: 'Unsupported Media Type';
    416: 'Range Not Satisfiable';
    417: 'Expectation Failed';
    418: "I'm a Teapot";
    421: 'Misdirected Request';
    422: 'Unprocessable Entity';
    423: 'Locked';
    424: 'Failed Dependency';
    425: 'Too Early';
    426: 'Upgrade Required';
    428: 'Precondition Required';
    429: 'Too Many Requests';
    431: 'Request Header Fields Too Large';
    451: 'Unavailable For Legal Reasons';
    500: 'Internal Server Error';
    501: 'Not Implemented';
    502: 'Bad Gateway';
    503: 'Service Unavailable';
    504: 'Gateway Timeout';
    505: 'HTTP Version Not Supported';
    506: 'Variant Also Negotiates';
    507: 'Insufficient Storage';
    508: 'Loop Detected';
    509: 'Bandwidth Limit Exceeded';
    510: 'Not Extended';
    511: 'Network Authentication Required';
};
export type TypedResponse<TJSON = unknown, THeaders extends Record<string, string> = Record<string, string>, TStatusCode extends StatusCode = StatusCode> = Omit<Response, 'json' | 'status' | 'ok'> & Omit<TypedBody<TJSON, any, THeaders>, 'formData'> & {
    /**
     * The status read-only property of the Response interface contains the HTTP status codes of the response.
     * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/status
     *
     * You can use `Response.ok` to check if the status is in the range 200-299.
     */
    status: TStatusCode;
    /**
     * The statusText read-only property of the Response interface contains the status message corresponding to the HTTP status code in Response.status.
     * For example, this would be OK for a status code 200, Continue for 100, Not Found for 404.
     * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/statusText
     */
    statusText: TStatusCode extends keyof StatusTextMap ? StatusTextMap[TStatusCode] : string;
} & {
    /**
     * The ok read-only property of the Response interface contains a Boolean stating whether the response was successful (status in the range 200-299) or not.
     */
    ok: TStatusCode extends OkStatusCode ? true : false;
};
export type JSONofResponse<TResponse extends TypedResponse> = TResponse extends TypedResponse<infer TJSON> ? TJSON : never;
export type TypedResponseCtor<TTypedResponse extends TypedResponse = TypedResponse> = Omit<typeof Response, 'json'> & {
    new <TStatusCode extends TTypedResponse['status'] = 200>(body: BodyInit | null | undefined, init: (TypedResponseInit<TStatusCode> & {
        status: TStatusCode;
    }) | undefined): TypedResponse<any, Record<string, string>, TStatusCode>;
    new (body: BodyInit | null | undefined, init: ResponseInit | undefined): TypedResponse<any, Record<string, string>, 200>;
    new (body?: BodyInit | null | undefined): TypedResponse<any, Record<string, string>, 200>;
    /**
     * The `json()` static method of the `Response` interface returns a `Response` that contains the provided JSON data as body,
     * and a `Content-Type` header which is set to `application/json`. The response status, status message, and additional headers can also be set.
     * @param data The JSON data to be used as the response body.
     * @param options An options object containing settings for the response, including the status code, status text, and headers. This is the same as the options parameter of the `Response()` constructor.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/json_static
     */
    json<TJSON extends JSONofResponse<TTypedResponse>, TStatusCode extends TTypedResponse['status']>(data: TJSON, options: TypedResponseInit<TStatusCode>): TypedResponse<TJSON, Record<string, string>, TStatusCode>;
    /**
     * The `json()` static method of the `Response` interface returns a `Response` that contains the provided JSON data as body,
     * and a `Content-Type` header which is set to `application/json`.
     * @param data The JSON data to be used as the response body.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/json_static
     */
    json<TJSON extends JSONofResponse<TTypedResponse>>(data: TJSON): TypedResponse<TJSON, Record<string, string>, 200>;
    /**
     * The redirect() static method of the Response interface returns a Response resulting in a redirect to the specified URL.
     * @param url The URL that the new response is to originate from.
     * @param status An optional status code for the response (e.g., 302.)
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/redirect_static
     */
    redirect<TStatusCode extends TTypedResponse['status']>(url: string | URL, status: TStatusCode): TypedResponse<any, Record<string, string>, TStatusCode>;
    /**
     * The redirect() static method of the Response interface returns a Response resulting in a redirect to the specified URL.
     * @param url The URL that the new response is to originate from.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/redirect_static
     */
    redirect(url: string | URL): TypedResponse<any, Record<string, string>, 302>;
};
export type TypedResponseWithJSONStatusMap<TResponseJSONStatusMap extends StatusCodeMap<any>> = {
    [TStatusCode in keyof TResponseJSONStatusMap]: TStatusCode extends StatusCode ? TypedResponse<TResponseJSONStatusMap[TStatusCode], Record<string, string>, TStatusCode> : never;
}[keyof TResponseJSONStatusMap];
export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'CONNECT' | 'TRACE';
export type TypedRequestInit<THeaders extends Record<string, string | undefined>, TMethod extends HTTPMethod, TFormData extends Record<string, FormDataEntryValue | undefined>> = Omit<RequestInit, 'method' | 'headers' | 'body'> & {
    method: TMethod;
    headers: TypedHeaders<THeaders>;
    body?: Exclude<BodyInit, FormData> | TFormData;
};
export type TypedRequest<TJSON = any, TFormData extends Record<string, FormDataEntryValue | undefined> = Record<string, FormDataEntryValue | undefined>, THeaders extends Record<string, string | undefined> = Record<string, string | undefined>, TMethod extends HTTPMethod = HTTPMethod, TQueryParams = any, TPathParams extends Record<string, any> = Record<string, any>> = Omit<Request, 'json' | 'method' | 'headers' | 'formData'> & TypedBody<TJSON, TFormData, THeaders> & {
    parsedUrl: URL;
    method: TMethod;
    params: TPathParams;
    query: TQueryParams;
};
export type TypedRequestCtor = new <THeaders extends Record<string, string | undefined>, TMethod extends HTTPMethod, TFormData extends Record<string, FormDataEntryValue | undefined>>(input: string | URL, init?: TypedRequestInit<THeaders, TMethod, TFormData>) => TypedRequest<any, TFormData, THeaders, TMethod, any, any>;
export interface TypedFormData<TMap extends Record<string, FormDataEntryValue | undefined> = Record<string, FormDataEntryValue | undefined>> {
    append<TName extends keyof TMap>(name: TName, value: TMap[TName] extends any[] ? TMap[TName][0] : TMap[TName], fileName?: string): void;
    delete(name: keyof TMap): void;
    get<TName extends keyof TMap>(name: TName): TMap[TName] extends any[] ? TMap[TName][0] : TMap[TName];
    getAll<TName extends keyof TMap>(name: TName): TMap[TName] extends any[] ? TMap[TName] : TMap[TName][];
    has<TName extends string>(name: TName): TName extends keyof TMap ? (TMap[TName] extends Maybe ? boolean : true) : false;
    set<TName extends keyof TMap>(name: TName, value: TMap[TName] extends any[] ? TMap[TName][0] : TMap[TName], fileName?: string): void;
    forEach(callbackfn: <TName extends keyof TMap>(value: TMap[TName], key: TName, parent: this) => void, thisArg?: any): void;
    entries(): IterableIterator<[keyof TMap, TMap[keyof TMap]]>;
    keys(): IterableIterator<keyof TMap>;
    values(): IterableIterator<TMap[keyof TMap]>;
    [Symbol.iterator](): IterableIterator<[keyof TMap, TMap[keyof TMap]]>;
}
export {};
