@zimic/http
Version:
Next-gen TypeScript-first HTTP utilities
677 lines (665 loc) • 45.4 kB
TypeScript
type JSON = {
[key: string]: JSON;
} | JSON[] | string | number | boolean | null | undefined;
declare namespace JSON {
type Loose = Record<string, any> | Loose[] | string | number | boolean | null | undefined;
}
/**
* Represents or validates a type that is compatible with JSON.
*
* **IMPORTANT**: the input of `JSONValue` and all of its internal types must be declared inline or as a type aliases
* (`type`). They cannot be interfaces.
*
* @example
* import { type JSONValue } from '@zimic/http';
*
* // Can be used as a standalone type:
* const value: JSONValue = {
* name: 'example',
* tags: ['one', 'two'],
* };
*
* @example
* import { type JSONValue } from '@zimic/http';
*
* // Can be used with a type argument to validate a JSON value:
* type ValidJSON = JSONValue<{
* id: string;
* email: string;
* createdAt: string;
* }>;
*
* // This results in a type error:
* type InvalidJSON = JSONValue<{
* id: string;
* email: string;
* createdAt: Date; // `Date` is not a valid JSON value.
* save: () => Promise<void>; // Functions are not valid JSON values.
* }>;
*/
type JSONValue<Type extends JSON = JSON> = Type;
declare namespace JSONValue {
/** A loose version of the JSON value type. JSON objects are not strictly typed. */
type Loose<Type extends JSON.Loose = JSON.Loose> = Type;
}
/**
* Recursively converts a type to its JSON-serialized version. Dates are converted to strings and keys with non-JSON
* values are excluded.
*
* @example
* import { type JSONSerialized } from '@zimic/http';
*
* type SerializedUser = JSONSerialized<{
* id: string;
* email: string;
* createdAt: Date;
* save: () => Promise<void>;
* }>;
* // {
* // id: string;
* // email: string;
* // createdAt: string;
* // }
*/
type JSONSerialized<Type> = Type extends JSONValue ? Type : Type extends string | number | boolean | null | undefined ? Type : Type extends Date ? string : Type extends (...parameters: never[]) => unknown ? never : Type extends symbol ? never : Type extends Map<infer _Key, infer _Value> ? Record<string, never> : Type extends Set<infer _Value> ? Record<string, never> : Type extends (infer ArrayItem)[] ? JSONSerialized<ArrayItem>[] : Type extends object ? {
[Key in keyof Type as [JSONSerialized<Type[Key]>] extends [never] ? never : Key]: JSONSerialized<Type[Key]>;
} : never;
type Default<Type, IfEmpty = never> = [undefined | void] extends [Type] ? IfEmpty : Exclude<Type, undefined | void>;
type DefaultNoExclude<Type, IfEmpty = never> = [undefined | void] extends Type ? IfEmpty : Type;
type IfAny<Type, Yes, No = Type> = 0 extends 1 & Type ? Yes : No;
type IfNever<Type, Yes, No = Type> = [Type] extends [never] ? Yes : No;
type UnionToIntersection<Union> = (Union extends unknown ? (union: Union) => void : never) extends (intersectedUnion: infer IntersectedUnion) => void ? IntersectedUnion : never;
type UnionHasMoreThanOneType<Union> = [UnionToIntersection<Union>] extends [never] ? true : false;
type Prettify<Type> = {
[Key in keyof Type]: Type[Key];
};
type ArrayItemIfArray<Type> = Type extends (infer Item)[] ? Item : Type;
type PickArrayProperties<Type> = {
[Key in keyof Type as never[] extends Type[Key] ? Key : never]: Type[Key];
};
type ArrayKey<Type> = keyof PickArrayProperties<Type>;
type NonArrayKey<Type> = string | number extends ArrayKey<Type> ? keyof Type : Exclude<keyof Type, ArrayKey<Type>>;
type NonEmptyArray<Type> = [Type, ...Type[]];
type ReplaceBy<Type, Source, Target> = Type extends Source ? Target : Type;
declare const brand: unique symbol;
/**
* A utility type to create a branded type. This is useful for creating types that are distinct from each other even if
* they have the same underlying structure. It also helps the TypeScript compiler to reference the type in the generated
* declaration files, rather than inlining it.
*/
type Branded<Type, Brand extends string> = Type & {
[brand]?: Brand;
};
/** A schema for strict HTTP form data. */
interface HttpFormDataSchema {
[fieldName: string]: string | string[] | Blob | Blob[] | null | undefined;
}
declare namespace HttpFormDataSchema {
/** A schema for loose HTTP form data. Field values are not strictly typed. */
type Loose = Record<string, any>;
}
declare namespace HttpFormDataSchemaName {
/** Extracts the names of the form data fields defined in a {@link HttpFormDataSchema} that are arrays. */
type Array<Schema extends HttpFormDataSchema> = IfNever<Schema, never, ArrayKey<Schema> & string>;
/** Extracts the names of the form data fields defined in a {@link HttpFormDataSchema} that are not arrays. */
type NonArray<Schema extends HttpFormDataSchema> = IfNever<Schema, never, NonArrayKey<Schema> & string>;
}
/**
* Extracts the names of the form data fields defined in a {@link HttpFormDataSchema}. Each key is considered a field
* name. `HttpFormDataSchemaName.Array` can be used to extract the names of array form data fields, whereas
* `HttpFormDataSchemaName.NonArray` extracts the names of non-array form data fields.
*
* @example
* import { type HttpFormDataSchemaName } from '@zimic/http';
*
* type FormDataName = HttpFormDataSchemaName<{
* title: string;
* descriptions: string[];
* content: Blob;
* }>;
* // "title" | "descriptions" | "content"
*
* type ArrayFormDataName = HttpFormDataSchemaName.Array<{
* title: string;
* descriptions: string[];
* content: Blob;
* }>;
* // "descriptions"
*
* type NonArrayFormDataName = HttpFormDataSchemaName.NonArray<{
* title: string;
* descriptions: string[];
* content: Blob;
* }>;
* // "title" | "content"
*/
type HttpFormDataSchemaName<Schema extends HttpFormDataSchema> = IfNever<Schema, never, keyof Schema & string>;
type PrimitiveHttpFormDataSerialized<Type> = [Type] extends [never] ? never : Type extends number ? `${number}` : Type extends boolean ? `${boolean}` : Type extends null ? 'null' : Type extends symbol ? never : Type extends HttpFormDataSchema[string] ? Type : Type extends (infer ArrayItem)[] ? ArrayItem extends (infer _InternalArrayItem)[] ? never : PrimitiveHttpFormDataSerialized<ArrayItem>[] : string;
/**
* Recursively converts a schema to its {@link https://developer.mozilla.org/docs/Web/API/FormData FormData}-serialized
* version. Numbers, booleans, and null are converted to `${number}`, `${boolean}`, and 'null' respectively, and other
* values become strings.
*
* @example
* import { type HttpFormDataSerialized } from '@zimic/http';
*
* type Schema = HttpFormDataSerialized<{
* contentTitle: string;
* contentSize: number | null;
* content: Blob;
* full?: boolean;
* }>;
* // {
* // contentTitle: string;
* // contentSize? `${number}` | 'null';
* // content: Blob;
* // full?: "false" | "true";
* // }
*/
type HttpFormDataSerialized<Type> = [Type] extends [never] ? never : Type extends HttpFormDataSchema ? Type : Type extends object ? {
[Key in keyof Type as IfNever<PrimitiveHttpFormDataSerialized<Type[Key]>, never, Key>]: PrimitiveHttpFormDataSerialized<Type[Key]>;
} : never;
/** @see {@link https://zimic.dev/docs/http/api/http-form-data `HttpFormData` API reference} */
declare class HttpFormData<LooseSchema extends HttpFormDataSchema.Loose = HttpFormDataSchema.Loose> extends FormData {
readonly _schema: HttpFormDataSerialized<LooseSchema>;
/** @see {@link https://zimic.dev/docs/http/api/http-form-data#formdataset `formData.set()` API reference} */
set<Name extends HttpFormDataSchemaName<this['_schema']>>(name: Name, value: Exclude<ArrayItemIfArray<NonNullable<LooseSchema[Name]>>, Blob>): void;
set<Name extends HttpFormDataSchemaName<this['_schema']>>(name: Name, blob: Exclude<ArrayItemIfArray<NonNullable<LooseSchema[Name]>>, string>, fileName?: string): void;
/** @see {@link https://zimic.dev/docs/http/api/http-form-data#formdataappend `formData.append()` API reference} */
append<Name extends HttpFormDataSchemaName<this['_schema']>>(name: Name, value: Exclude<ArrayItemIfArray<NonNullable<LooseSchema[Name]>>, Blob>): void;
append<Name extends HttpFormDataSchemaName<this['_schema']>>(name: Name, blob: Exclude<ArrayItemIfArray<NonNullable<LooseSchema[Name]>>, string>, fileName?: string): void;
/** @see {@link https://zimic.dev/docs/http/api/http-form-data#formdataget `formData.get()` API reference} */
get<Name extends HttpFormDataSchemaName.NonArray<this['_schema']>>(name: Name): ReplaceBy<ReplaceBy<ArrayItemIfArray<this['_schema'][Name]>, undefined, null>, Blob, File>;
/** @see {@link https://zimic.dev/docs/http/api/http-form-data#formdatagetall `formData.getAll()` API reference} */
getAll<Name extends HttpFormDataSchemaName.Array<this['_schema']>>(name: Name): ReplaceBy<ArrayItemIfArray<NonNullable<this['_schema'][Name]>>, Blob, File>[];
/** @see {@link https://zimic.dev/docs/http/api/http-form-data#formdatahas `formData.has()` API reference} */
has<Name extends HttpFormDataSchemaName<this['_schema']>>(name: Name): boolean;
/** @see {@link https://zimic.dev/docs/http/api/http-form-data#formdatadelete `formData.delete()` API reference} */
delete<Name extends HttpFormDataSchemaName<this['_schema']>>(name: Name): void;
/** @see {@link https://zimic.dev/docs/http/api/http-form-data#formdataforEach `formData.forEach()` API reference} */
forEach<This extends HttpFormData<this['_schema']>>(callback: <Key extends HttpFormDataSchemaName<this['_schema']>>(value: ReplaceBy<ArrayItemIfArray<NonNullable<this['_schema'][Key]>>, Blob, File>, key: Key, formData: HttpFormData<this['_schema']>) => void, thisArg?: This): void;
/** @see {@link https://zimic.dev/docs/http/api/http-form-data#formdatakeys `formData.keys()` API reference} */
keys(): FormDataIterator<HttpFormDataSchemaName<this['_schema']>>;
/** @see {@link https://zimic.dev/docs/http/api/http-form-data#formdatavalues `formData.values()` API reference} */
values(): FormDataIterator<ReplaceBy<ArrayItemIfArray<NonNullable<this['_schema'][HttpFormDataSchemaName<this['_schema']>]>>, Blob, File>>;
/** @see {@link https://zimic.dev/docs/http/api/http-form-data#formdataentries `formData.entries()` API reference} */
entries(): FormDataIterator<[
HttpFormDataSchemaName<this['_schema']>,
ReplaceBy<ArrayItemIfArray<NonNullable<this['_schema'][HttpFormDataSchemaName<this['_schema']>]>>, Blob, File>
]>;
[Symbol.iterator](): FormDataIterator<[
HttpFormDataSchemaName<this['_schema']>,
ReplaceBy<ArrayItemIfArray<NonNullable<this['_schema'][HttpFormDataSchemaName<this['_schema']>]>>, Blob, File>
]>;
/** @see {@link https://zimic.dev/docs/http/api/http-form-data#formdataequals `formData.equals()` API reference} */
equals<OtherSchema extends LooseSchema>(otherData: HttpFormData<OtherSchema>): Promise<boolean>;
/** @see {@link https://zimic.dev/docs/http/api/http-form-data#formdatacontains `formData.contains()` API reference} */
contains<OtherSchema extends LooseSchema>(otherData: HttpFormData<OtherSchema>): Promise<boolean>;
/** @see {@link https://zimic.dev/docs/http/api/http-form-data#formdatatoobject `formData.toObject()` API reference} */
toObject(): this["_schema"];
}
interface HttpPathParamsSchema {
[paramName: string]: string | undefined;
}
declare namespace HttpPathParamsSchema {
/** A schema for loose HTTP path parameters. Parameter values are not strictly typed. */
type Loose = Record<string, any>;
}
type PrimitiveHttpPathParamsSerialized<Type> = [Type] extends [never] ? never : Type extends number ? `${number}` : Type extends boolean ? `${boolean}` : Type extends null ? 'null' : Type extends symbol ? never : Type extends HttpPathParamsSchema[string] ? Type : string;
/**
* Recursively converts a schema to its path parameters-serialized version. Numbers, booleans, and null are converted to
* `${number}`, `${boolean}`, and 'null' respectively, and other values become strings.
*
* @example
* import { type HttpPathParamsSerialized } from '@zimic/http';
*
* type Params = HttpPathParamsSerialized<{
* userId: string;
* notificationId: number | null;
* full?: boolean;
* }>;
* // {
* // userId: string;
* // notificationId: `${number}` | 'null';
* // full?: "false" | "true";
* // }
*/
type HttpPathParamsSerialized<Type> = [Type] extends [never] ? never : Type extends HttpPathParamsSchema ? Type : Type extends object ? {
[Key in keyof Type as IfNever<PrimitiveHttpPathParamsSerialized<Type[Key]>, never, Key>]: PrimitiveHttpPathParamsSerialized<Type[Key]>;
} : never;
/** A schema for strict HTTP headers. */
interface HttpHeadersSchema {
[headerName: string]: string | undefined;
}
declare namespace HttpHeadersSchema {
/** A schema for loose HTTP headers. Header values are not strictly typed. */
type Loose = Record<string, any>;
}
/** A strict tuple representation of a {@link HttpHeadersSchema}. */
type HttpHeadersSchemaTuple<Schema extends HttpHeadersSchema.Loose = HttpHeadersSchema.Loose> = {
[Key in keyof Schema & string]: [Key, NonNullable<Schema[Key]>];
}[keyof Schema & string];
/** An initialization value for {@link https://zimic.dev/docs/http/api/http-headers `HttpHeaders`}. */
type HttpHeadersInit<Schema extends HttpHeadersSchema.Loose = HttpHeadersSchema.Loose> = Headers | Schema | HttpHeaders<Schema> | HttpHeadersSchemaTuple<Schema>[];
/**
* Extracts the names of the headers defined in a {@link HttpHeadersSchema}. Each key is considered a header name.
*
* @example
* import { type HttpHeadersSchemaName } from '@zimic/http';
*
* type HeaderName = HttpHeadersSchemaName<{
* 'content-type': string;
* 'content-length'?: string;
* }>;
* // "content-type" | "content-length"
*/
type HttpHeadersSchemaName<Schema extends HttpHeadersSchema> = IfNever<Schema, never, keyof Schema & string>;
/**
* Recursively converts a schema to its
* {@link https://developer.mozilla.org/docs/Web/API/Headers HTTP headers}-serialized version. Numbers and booleans are
* converted to `${number}` and `${boolean}` respectively, null becomes undefined and not serializable values are
* excluded, such as functions and dates.
*
* @example
* import { type HttpHeadersSerialized } from '@zimic/http';
*
* type Params = HttpHeadersSerialized<{
* 'content-type': string;
* 'x-remaining-tries': number;
* 'x-full'?: boolean;
* 'x-date': Date;
* method: () => void;
* }>;
* // {
* // 'content-type': string;
* // 'x-remaining-tries': `${number}`;
* // 'x-full'?: "false" | "true";
* // }
*/
type HttpHeadersSerialized<Type> = HttpPathParamsSerialized<Type>;
/** @see {@link https://zimic.dev/docs/http/api/http-headers `HttpHeaders` API reference} */
declare class HttpHeaders<LooseSchema extends HttpHeadersSchema.Loose = HttpHeadersSchema.Loose> extends Headers {
readonly _schema: HttpHeadersSerialized<LooseSchema>;
constructor(init?: HttpHeadersInit<LooseSchema>);
/** @see {@link https://zimic.dev/docs/http/api/http-headers#headersset `headers.set()` API reference} */
set<Name extends HttpHeadersSchemaName<this['_schema']>>(name: Name, value: NonNullable<LooseSchema[Name]>): void;
/** @see {@link https://zimic.dev/docs/http/api/http-headers#headersappend `headers.append()` API reference} */
append<Name extends HttpHeadersSchemaName<this['_schema']>>(name: Name, value: NonNullable<LooseSchema[Name]>): void;
/** @see {@link https://zimic.dev/docs/http/api/http-headers#headersget `headers.get()` API reference} */
get<Name extends HttpHeadersSchemaName<this['_schema']>>(name: Name): ReplaceBy<this['_schema'][Name], undefined, null>;
/** @see {@link https://zimic.dev/docs/http/api/http-headers#headersgetSetCookie `headers.getSetCookie()` API reference} */
getSetCookie(): NonNullable<Default<this['_schema']['Set-Cookie'], string>>[];
/** @see {@link https://zimic.dev/docs/http/api/http-headers#headershas `headers.has()` API reference} */
has<Name extends HttpHeadersSchemaName<this['_schema']>>(name: Name): boolean;
/** @see {@link https://zimic.dev/docs/http/api/http-headers#headersdelete `headers.delete()` API reference} */
delete<Name extends HttpHeadersSchemaName<this['_schema']>>(name: Name): void;
/** @see {@link https://zimic.dev/docs/http/api/http-headers#headersforEach `headers.forEach()` API reference} */
forEach<This extends HttpHeaders<this['_schema']>>(callback: <Key extends HttpHeadersSchemaName<this['_schema']>>(value: NonNullable<this['_schema'][Key]> & string, key: Key, headers: Headers) => void, thisArg?: This): void;
/** @see {@link https://zimic.dev/docs/http/api/http-headers#headerskeys `headers.keys()` API reference} */
keys(): HeadersIterator<HttpHeadersSchemaName<this['_schema']>>;
/** @see {@link https://zimic.dev/docs/http/api/http-headers#headersvalues `headers.values()` API reference} */
values(): HeadersIterator<NonNullable<this['_schema'][HttpHeadersSchemaName<this['_schema']>]> & string>;
/** @see {@link https://zimic.dev/docs/http/api/http-headers#headersentries `headers.entries()` API reference} */
entries(): HeadersIterator<[
HttpHeadersSchemaName<this['_schema']>,
NonNullable<this['_schema'][HttpHeadersSchemaName<this['_schema']>]> & string
]>;
[Symbol.iterator](): HeadersIterator<[
HttpHeadersSchemaName<this['_schema']>,
NonNullable<this['_schema'][HttpHeadersSchemaName<this['_schema']>]> & string
]>;
/** @see {@link https://zimic.dev/docs/http/api/http-headers#headersequals `headers.equals()` API reference} */
equals<OtherSchema extends LooseSchema>(otherHeaders: HttpHeaders<OtherSchema>): boolean;
/** @see {@link https://zimic.dev/docs/http/api/http-headers#headerscontains `headers.contains()` API reference} */
contains<OtherSchema extends LooseSchema>(otherHeaders: HttpHeaders<OtherSchema>): boolean;
/** @see {@link https://zimic.dev/docs/http/api/http-headers#headerstoobject `headers.toObject()` API reference} */
toObject(): this['_schema'];
private splitHeaderValues;
}
/** A schema for strict HTTP URL search parameters. */
interface HttpSearchParamsSchema {
[paramName: string]: string | string[] | undefined;
}
declare namespace HttpSearchParamsSchema {
/** A schema for loose HTTP URL search parameters. Parameter values are not strictly typed. */
type Loose = Record<string, any>;
}
/** A strict tuple representation of a {@link HttpSearchParamsSchema}. */
type HttpSearchParamsSchemaTuple<Schema extends HttpSearchParamsSchema.Loose = HttpSearchParamsSchema.Loose> = {
[Key in keyof Schema & string]: [Key, ArrayItemIfArray<NonNullable<Schema[Key]>>];
}[keyof Schema & string];
/** An initialization value for {@link https://zimic.dev/docs/http/api/http-search-params `HttpSearchParams`}. */
type HttpSearchParamsInit<Schema extends HttpSearchParamsSchema.Loose = HttpSearchParamsSchema.Loose> = string | URLSearchParams | Schema | HttpSearchParams<Schema> | HttpSearchParamsSchemaTuple<Schema>[];
declare namespace HttpSearchParamsSchemaName {
/** Extracts the names of the search params defined in a {@link HttpSearchParamsSchema} that are arrays. */
type Array<Schema extends HttpSearchParamsSchema> = IfNever<Schema, never, ArrayKey<Schema> & string>;
/** Extracts the names of the search params defined in a {@link HttpSearchParamsSchema} that are not arrays. */
type NonArray<Schema extends HttpSearchParamsSchema> = IfNever<Schema, never, NonArrayKey<Schema> & string>;
}
/**
* Extracts the names of the search params defined in a {@link HttpSearchParamsSchema}. Each key is considered a search
* param name. `HttpSearchParamsSchemaName.Array` can be used to extract the names of array search params, whereas
* `HttpSearchParamsSchemaName.NonArray` extracts the names of non-array search params.
*
* @example
* import { type HttpSearchParamsSchemaName } from '@zimic/http';
*
* type SearchParamsName = HttpSearchParamsSchemaName<{
* query?: string[];
* page?: `${number}`;
* perPage?: `${number}`;
* }>;
* // "query" | "page" | "perPage"
*
* type ArraySearchParamsName = HttpSearchParamsSchemaName.Array<{
* query?: string[];
* page?: `${number}`;
* perPage?: `${number}`;
* }>;
* // "query"
*
* type NonArraySearchParamsName = HttpSearchParamsSchemaName.NonArray<{
* query?: string[];
* page?: `${number}`;
* perPage?: `${number}`;
* }>;
* // "page" | "perPage"
*/
type HttpSearchParamsSchemaName<Schema extends HttpSearchParamsSchema> = IfNever<Schema, never, keyof Schema & string>;
type PrimitiveHttpSearchParamsSerialized<Type> = [Type] extends [never] ? never : Type extends number ? `${number}` : Type extends boolean ? `${boolean}` : Type extends null ? 'null' : Type extends symbol ? never : Type extends HttpSearchParamsSchema[string] ? Type : Type extends (infer ArrayItem)[] ? ArrayItem extends (infer _InternalArrayItem)[] ? string : PrimitiveHttpSearchParamsSerialized<ArrayItem>[] : string;
/**
* Recursively converts a schema to its
* {@link https://developer.mozilla.org/docs/Web/API/URLSearchParams URLSearchParams}-serialized version. Numbers,
* booleans, and null are converted to `${number}`, `${boolean}`, and 'null' respectively, and other values become
* strings.
*
* @example
* import { type HttpSearchParamsSerialized } from '@zimic/http';
*
* type Params = HttpSearchParamsSerialized<{
* query?: string;
* order: 'asc' | 'desc' | null;
* page?: number;
* full?: boolean;
* }>;
* // {
* // query?: string;
* // order: 'asc' | 'desc' | 'null';
* // page?: `${number}`;
* // full?: "false" | "true";
* // }
*/
type HttpSearchParamsSerialized<Type> = [Type] extends [never] ? never : Type extends HttpSearchParamsSchema ? Type : Type extends object ? {
[Key in keyof Type as IfNever<PrimitiveHttpSearchParamsSerialized<Type[Key]>, never, Key>]: PrimitiveHttpSearchParamsSerialized<Type[Key]>;
} : never;
/** @see {@link https://zimic.dev/docs/http/api/http-search-params `HttpSearchParams` API reference} */
declare class HttpSearchParams<LooseSchema extends HttpSearchParamsSchema.Loose = HttpSearchParamsSchema.Loose> extends URLSearchParams {
readonly _schema: HttpSearchParamsSerialized<LooseSchema>;
constructor(init?: HttpSearchParamsInit<LooseSchema>);
private populateInitArrayProperties;
/** @see {@link https://zimic.dev/docs/http/api/http-search-params#searchparamsset `searchParams.set()` API reference} */
set<Name extends HttpSearchParamsSchemaName<this['_schema']>>(name: Name, value: ArrayItemIfArray<NonNullable<LooseSchema[Name]>>): void;
/** @see {@link https://zimic.dev/docs/http/api/http-search-params#searchparamsappend `searchParams.append()` API reference} */
append<Name extends HttpSearchParamsSchemaName<this['_schema']>>(name: Name, value: ArrayItemIfArray<NonNullable<LooseSchema[Name]>>): void;
/** @see {@link https://zimic.dev/docs/http/api/http-search-params#searchparamsget `searchParams.get()` API reference} */
get<Name extends HttpSearchParamsSchemaName.NonArray<this['_schema']>>(name: Name): ReplaceBy<ArrayItemIfArray<this['_schema'][Name]>, undefined, null>;
/** @see {@link https://zimic.dev/docs/http/api/http-search-params#searchparamsgetall `searchParams.getAll()` API reference} */
getAll<Name extends HttpSearchParamsSchemaName.Array<this['_schema']>>(name: Name): ArrayItemIfArray<NonNullable<this['_schema'][Name]>>[];
/** @see {@link https://zimic.dev/docs/http/api/http-search-params#searchparamshas `searchParams.has()` API reference} */
has<Name extends HttpSearchParamsSchemaName<this['_schema']>>(name: Name, value?: ArrayItemIfArray<NonNullable<LooseSchema[Name]>>): boolean;
/** @see {@link https://zimic.dev/docs/http/api/http-search-params#searchparamsdelete `searchParams.delete()` API reference} */
delete<Name extends HttpSearchParamsSchemaName<this['_schema']>>(name: Name, value?: ArrayItemIfArray<NonNullable<LooseSchema[Name]>>): void;
/** @see {@link https://zimic.dev/docs/http/api/http-search-params#searchparamsforEach `searchParams.forEach()` API reference} */
forEach<This extends HttpSearchParams<this['_schema']>>(callback: <Key extends HttpSearchParamsSchemaName<this['_schema']>>(value: ArrayItemIfArray<NonNullable<this['_schema'][Key]>>, key: Key, searchParams: HttpSearchParams<this['_schema']>) => void, thisArg?: This): void;
/** @see {@link https://zimic.dev/docs/http/api/http-search-params#searchparamskeys `searchParams.keys()` API reference} */
keys(): URLSearchParamsIterator<HttpSearchParamsSchemaName<this['_schema']>>;
/** @see {@link https://zimic.dev/docs/http/api/http-search-params#searchparamsvalues `searchParams.values()` API reference} */
values(): URLSearchParamsIterator<ArrayItemIfArray<NonNullable<this['_schema'][HttpSearchParamsSchemaName<this['_schema']>]>>>;
/** @see {@link https://zimic.dev/docs/http/api/http-search-params#searchparamsentries `searchParams.entries()` API reference} */
entries(): URLSearchParamsIterator<[
HttpSearchParamsSchemaName<this['_schema']>,
ArrayItemIfArray<NonNullable<this['_schema'][HttpSearchParamsSchemaName<this['_schema']>]>>
]>;
[Symbol.iterator](): URLSearchParamsIterator<[
HttpSearchParamsSchemaName<this['_schema']>,
ArrayItemIfArray<NonNullable<this['_schema'][HttpSearchParamsSchemaName<this['_schema']>]>>
]>;
/** @see {@link https://zimic.dev/docs/http/api/http-search-params#searchparamsequals `searchParams.equals()` API reference} */
equals<OtherSchema extends LooseSchema>(otherParams: HttpSearchParams<OtherSchema>): boolean;
/** @see {@link https://zimic.dev/docs/http/api/http-search-params#searchparamscontains `searchParams.contains()` API reference} */
contains<OtherSchema extends LooseSchema>(otherParams: HttpSearchParams<OtherSchema>): boolean;
/** @see {@link https://zimic.dev/docs/http/api/http-search-params#searchparamstoobject `searchParams.toObject()` API reference} */
toObject(): this["_schema"];
}
declare const HTTP_METHODS: readonly ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
/**
* A type representing the currently supported
* {@link https://developer.mozilla.org/docs/Web/HTTP/Methods `HTTP methods`}.
*/
type HttpMethod = (typeof HTTP_METHODS)[number];
/**
* A schema representing the structure of an HTTP request.
*
* @see {@link https://zimic.dev/docs/http/api/http-schema `HttpSchema` API reference}
*/
interface HttpRequestSchema {
headers?: HttpHeadersSchema.Loose;
searchParams?: HttpSearchParamsSchema.Loose;
body?: HttpBody.Loose;
}
/**
* A schema representing the structure of an HTTP response.
*
* @see {@link https://zimic.dev/docs/http/api/http-schema `HttpSchema` API reference}
*/
interface HttpResponseSchema {
headers?: HttpHeadersSchema.Loose;
body?: HttpBody.Loose;
}
/**
* The status codes used in HTTP responses, as defined by
* {@link https://httpwg.org/specs/rfc9110.html#overview.of.status.codes RFC-9110}.
*
* - `HttpStatusCode.Information`: {@link https://developer.mozilla.org/docs/Web/HTTP/Status#information_responses `1XX`}
* - `HttpStatusCode.Success`: {@link https://developer.mozilla.org/docs/Web/HTTP/Status#successful_responses `2XX`}
* - `HttpStatusCode.Redirection`: {@link https://developer.mozilla.org/docs/Web/HTTP/Status#redirection_messages `3XX`}
* - `HttpStatusCode.ClientError`: {@link https://developer.mozilla.org/docs/Web/HTTP/Status#client_error_responses `4XX`}
* - `HttpStatusCode.ServerError`: {@link https://developer.mozilla.org/docs/Web/HTTP/Status#server_error_responses `5XX`}
*/
type HttpStatusCode = HttpStatusCode.Information | HttpStatusCode.Success | HttpStatusCode.Redirection | HttpStatusCode.ClientError | HttpStatusCode.ServerError;
declare namespace HttpStatusCode {
/**
* An HTTP status code in the `1XX` range, representing an informational response.
*
* @see {@link https://developer.mozilla.org/docs/Web/HTTP/Status#information_responses `1XX`}
*/
type Information = 100 | 101 | 102 | 103;
/**
* An HTTP status code in the `2XX` range, representing a successful response.
*
* @see {@link https://developer.mozilla.org/docs/Web/HTTP/Status#successful_responses `2XX`}
*/
type Success = 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 226;
/**
* An HTTP status code in the `3XX` range, representing a redirection response.
*
* @see {@link https://developer.mozilla.org/docs/Web/HTTP/Status#redirection_messages `3XX`}
*/
type Redirection = 300 | 301 | 302 | 303 | 304 | 307 | 308;
/**
* An HTTP status code in the `4XX` range, representing a client error response.
*
* @see {@link https://developer.mozilla.org/docs/Web/HTTP/Status#client_error_responses `4XX`}
*/
type ClientError = 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;
/**
* An HTTP status code in the `5XX` range, representing a server error response.
*
* @see {@link https://developer.mozilla.org/docs/Web/HTTP/Status#server_error_responses `5XX`}
*/
type ServerError = 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511;
}
/**
* A schema representing the structure of HTTP responses by status code.
*
* @see {@link https://zimic.dev/docs/http/api/http-schema `HttpSchema` API reference}
*/
type HttpResponseSchemaByStatusCode = {
[StatusCode in HttpStatusCode]?: HttpResponseSchema;
};
/**
* Extracts the status codes used in a response schema by status code.
*
* @see {@link https://zimic.dev/docs/http/api/http-schema `HttpSchema` API reference}
*/
type HttpResponseSchemaStatusCode<ResponseSchemaByStatusCode extends HttpResponseSchemaByStatusCode> = keyof ResponseSchemaByStatusCode & HttpStatusCode;
/**
* A schema representing the structure of an HTTP request and response for a given method.
*
* @see {@link https://zimic.dev/docs/http/api/http-schema `HttpSchema` API reference}
*/
interface HttpMethodSchema {
request?: HttpRequestSchema;
response?: HttpResponseSchemaByStatusCode;
}
/**
* A schema representing the structure of HTTP request and response by method.
*
* @see {@link https://zimic.dev/docs/http/api/http-schema `HttpSchema` API reference}
*/
interface HttpMethodsSchema {
GET?: HttpMethodSchema;
POST?: HttpMethodSchema;
PUT?: HttpMethodSchema;
PATCH?: HttpMethodSchema;
DELETE?: HttpMethodSchema;
HEAD?: HttpMethodSchema;
OPTIONS?: HttpMethodSchema;
}
interface BaseHttpSchema {
[path: string]: HttpMethodsSchema;
}
/** @see {@link https://zimic.dev/docs/http/api/http-schema `HttpSchema` API reference} */
type HttpSchema<Schema extends BaseHttpSchema = BaseHttpSchema> = Branded<Schema, 'HttpSchema'>;
declare namespace HttpSchema {
/** @see {@link https://zimic.dev/docs/http/api/http-schema#httpschemamethods `HttpSchema.Methods` API reference} */
type Methods<Schema extends HttpMethodsSchema> = Schema;
/** @see {@link https://zimic.dev/docs/http/api/http-schema#httpschemamethod `HttpSchema.Method` API reference} */
type Method<Schema extends HttpMethodSchema> = Schema;
/** @see {@link https://zimic.dev/docs/http/api/http-schema#httpschemarequest `HttpSchema.Request` API reference} */
type Request<Schema extends HttpRequestSchema> = Schema;
/** @see {@link https://zimic.dev/docs/http/api/http-schema#httpschemaresponsebystatuscode `HttpSchema.ResponseByStatusCode` API reference} */
type ResponseByStatusCode<Schema extends HttpResponseSchemaByStatusCode> = Schema;
/** @see {@link https://zimic.dev/docs/http/api/http-schema#httpschemaresponse `HttpSchema.Response` API reference} */
type Response<Schema extends HttpResponseSchema> = Schema;
/** @see {@link https://zimic.dev/docs/http/api/http-schema#httpschemabody `HttpSchema.Body` API reference} */
type Body<Schema extends HttpBody.Loose> = Schema;
/** @see {@link https://zimic.dev/docs/http/api/http-schema#httpschemaheaders `HttpSchema.Headers` API reference} */
type Headers<Schema extends HttpHeadersSchema.Loose> = Schema;
/** @see {@link https://zimic.dev/docs/http/api/http-schema#httpschemasearchparams `HttpSchema.SearchParams` API reference} */
type SearchParams<Schema extends HttpSearchParamsSchema.Loose> = Schema;
/** @see {@link https://zimic.dev/docs/http/api/http-schema#httpschemapathparams `HttpSchema.PathParams` API reference} */
type PathParams<Schema extends HttpPathParamsSchema.Loose> = Schema;
/** @see {@link https://zimic.dev/docs/http/api/http-schema#httpschemaformdata `HttpSchema.FormData` API reference} */
type FormData<Schema extends HttpFormDataSchema.Loose> = Schema;
}
/**
* Extracts the methods from an HTTP service schema.
*
* @see {@link https://zimic.dev/docs/http/api/http-schema `HttpSchema` API reference}
*/
type HttpSchemaMethod<Schema extends HttpSchema> = IfAny<Schema, any, // eslint-disable-line @typescript-eslint/no-explicit-any
// eslint-disable-line @typescript-eslint/no-explicit-any
keyof UnionToIntersection<Schema[keyof Schema]> & HttpMethod>;
type AllowAnyStringInPathParams<Path extends string> = Path extends `${infer Prefix}:${string}/${infer Suffix}` ? `${Prefix}${string}/${AllowAnyStringInPathParams<Suffix>}` : Path extends `${infer Prefix}:${string}` ? `${Prefix}${string}` : Path;
/** @see {@link https://zimic.dev/docs/http/api/http-schema#httpschemapath `HttpSchemaPath` API reference} */
declare namespace HttpSchemaPath {
type LooseLiteral<Schema extends HttpSchema, Method extends HttpMethod = HttpMethod> = {
[Path in keyof Schema & string]: Method extends keyof Schema[Path] ? Path : never;
}[keyof Schema & string];
/** @see {@link https://zimic.dev/docs/http/api/http-schema#httpschemapathliteral `HttpSchemaPath.Literal` API reference} */
export type Literal<Schema extends HttpSchema, Method extends HttpSchemaMethod<Schema> = HttpSchemaMethod<Schema>> = LooseLiteral<Schema, Method>;
/** @see {@link https://zimic.dev/docs/http/api/http-schema#httpschemapathnonliteral `HttpSchemaPath.NonLiteral` API reference} */
export type NonLiteral<Schema extends HttpSchema, Method extends HttpSchemaMethod<Schema> = HttpSchemaMethod<Schema>> = AllowAnyStringInPathParams<Literal<Schema, Method>>;
export { };
}
type HttpSchemaPath<Schema extends HttpSchema, Method extends HttpSchemaMethod<Schema> = HttpSchemaMethod<Schema>> = HttpSchemaPath.Literal<Schema, Method> | HttpSchemaPath.NonLiteral<Schema, Method>;
type LargestPathPrefix<Path extends string> = Path extends `${infer Prefix}/${infer Suffix}` ? `${Prefix}/${Suffix extends `${string}/${string}` ? LargestPathPrefix<Suffix> : ''}` : Path;
type ExcludeNonLiteralPathsSupersededByLiteralPath<Path extends string> = Path extends `${LargestPathPrefix<Path>}:${string}` ? never : Path;
type PreferMostStaticLiteralPath<Path extends string> = UnionHasMoreThanOneType<Path> extends true ? ExcludeNonLiteralPathsSupersededByLiteralPath<Path> : Path;
type RecursiveInferHttpSchemaPath<Schema extends HttpSchema, Method extends HttpSchemaMethod<Schema>, NonLiteralPath extends string, LiteralPath extends HttpSchemaPath.Literal<Schema, Method>> = NonLiteralPath extends AllowAnyStringInPathParams<LiteralPath> ? NonLiteralPath extends `${AllowAnyStringInPathParams<LiteralPath>}/${string}` ? never : LiteralPath : never;
type LiteralHttpSchemaPathFromNonLiteral<Schema extends HttpSchema, Method extends HttpSchemaMethod<Schema>, NonLiteralPath extends string, LiteralPath extends HttpSchemaPath.Literal<Schema, Method> = HttpSchemaPath.Literal<Schema, Method>> = PreferMostStaticLiteralPath<LiteralPath extends LiteralPath ? RecursiveInferHttpSchemaPath<Schema, Method, NonLiteralPath, LiteralPath> : never>;
type RecursiveInferPathParams<Path extends string> = Path extends `${infer _Prefix}:${infer ParamName}/${infer Suffix}` ? {
[Name in ParamName]: string;
} & RecursiveInferPathParams<Suffix> : Path extends `${infer _Prefix}:${infer ParamName}` ? {
[Name in ParamName]: string;
} : {};
/** @see {@link https://zimic.dev/docs/http/api/http-schema#inferpathparams `InferPathParams` API reference} */
type InferPathParams<PathOrSchema extends string | HttpSchema, OptionalPath extends PathOrSchema extends HttpSchema ? HttpSchemaPath.Literal<PathOrSchema> : never = never> = Prettify<RecursiveInferPathParams<PathOrSchema extends HttpSchema ? OptionalPath : PathOrSchema extends string ? PathOrSchema : never>>;
type OmitPastHttpStatusCodes<Schema extends HttpResponseSchemaByStatusCode, PastSchemas extends HttpResponseSchemaByStatusCode[]> = PastSchemas extends NonEmptyArray<HttpResponseSchemaByStatusCode> ? Omit<Schema, keyof UnionToIntersection<PastSchemas[number]>> : Schema;
/** @see {@link https://zimic.dev/docs/http/api/http-schema#mergehttpresponsesbystatuscode `MergeHttpResponsesByStatusCode` API reference} */
type MergeHttpResponsesByStatusCode<Schemas extends HttpResponseSchemaByStatusCode[], PastSchemas extends HttpResponseSchemaByStatusCode[] = []> = Schemas extends [
infer FirstSchema extends HttpResponseSchemaByStatusCode,
...infer RestSchemas extends HttpResponseSchemaByStatusCode[]
] ? RestSchemas extends NonEmptyArray<HttpResponseSchemaByStatusCode> ? OmitPastHttpStatusCodes<FirstSchema, PastSchemas> & MergeHttpResponsesByStatusCode<RestSchemas, [...PastSchemas, FirstSchema]> : OmitPastHttpStatusCodes<FirstSchema, PastSchemas> : never;
/** The body type for HTTP requests and responses. */
type HttpBody = JSONValue | HttpFormData<any> | HttpSearchParams<any> | Blob | ArrayBuffer | ReadableStream;
declare namespace HttpBody {
/** A loose version of the HTTP body type. JSON values are not strictly typed. */
type Loose = ReplaceBy<HttpBody, JSONValue, JSONValue.Loose>;
}
/**
* An HTTP headers object with a strictly-typed schema. Fully compatible with the built-in
* {@link https://developer.mozilla.org/docs/Web/API/Headers `Headers`} class.
*/
type StrictHeaders<Schema extends HttpHeadersSchema.Loose = HttpHeadersSchema.Loose> = Pick<HttpHeaders<Schema>, keyof Headers>;
/**
* An HTTP search params object with a strictly-typed schema. Fully compatible with the built-in
* {@link https://developer.mozilla.org/docs/Web/API/URLSearchParams `URLSearchParams`} class.
*/
type StrictURLSearchParams<Schema extends HttpSearchParamsSchema.Loose = HttpSearchParamsSchema.Loose> = Pick<HttpSearchParams<Schema>, keyof URLSearchParams>;
/**
* An HTTP form data object with a strictly-typed schema. Fully compatible with the built-in
* {@link https://developer.mozilla.org/docs/Web/API/FormData `FormData`} class.
*/
type StrictFormData<Schema extends HttpFormDataSchema.Loose = HttpFormDataSchema.Loose> = Pick<HttpFormData<Schema>, keyof FormData>;
/**
* An HTTP request with a strictly-typed JSON body. Fully compatible with the built-in
* {@link https://developer.mozilla.org/docs/Web/API/Request `Request`} class.
*/
interface HttpRequest<StrictBody extends HttpBody.Loose = HttpBody.Loose, StrictHeadersSchema extends HttpHeadersSchema.Loose = HttpHeadersSchema.Loose> extends Request {
headers: StrictHeaders<StrictHeadersSchema>;
text: () => Promise<StrictBody extends string ? StrictBody : string>;
json: () => Promise<StrictBody extends string | Exclude<HttpBody, JSONValue> ? never : StrictBody>;
formData: () => Promise<StrictBody extends HttpFormData<infer HttpFormDataSchema> ? StrictFormData<HttpFormDataSchema> : StrictBody extends HttpSearchParams<infer HttpSearchParamsSchema> ? StrictFormData<HttpSearchParamsSchema> : FormData>;
clone: () => this;
}
/**
* An HTTP response with a strictly-typed JSON body and status code. Fully compatible with the built-in
* {@link https://developer.mozilla.org/docs/Web/API/Response `Response`} class.
*/
interface HttpResponse<StrictBody extends HttpBody.Loose = HttpBody.Loose, StrictHeadersSchema extends HttpHeadersSchema.Loose = HttpHeadersSchema.Loose, StatusCode extends number = number> extends Response {
ok: StatusCode extends HttpStatusCode.Information | HttpStatusCode.Success | HttpStatusCode.Redirection ? true : false;
status: StatusCode;
headers: StrictHeaders<StrictHeadersSchema>;
text: () => Promise<StrictBody extends string ? StrictBody : string>;
json: () => Promise<StrictBody extends string | Exclude<HttpBody, JSONValue> ? never : StrictBody>;
formData: () => Promise<StrictBody extends HttpFormData<infer HttpFormDataSchema> ? StrictFormData<HttpFormDataSchema> : StrictBody extends HttpSearchParams<infer HttpSearchParamsSchema> ? StrictFormData<HttpSearchParamsSchema> : FormData>;
clone: () => this;
}
type HttpRequestHeadersSchemaFromBody<RequestSchema extends HttpRequestSchema, DefaultHeadersSchema> = 'body' extends keyof RequestSchema ? [RequestSchema['body']] extends [never] ? DefaultHeadersSchema : [Extract<RequestSchema['body'], BodyInit | HttpFormData | HttpSearchParams>] extends [never] ? 'headers' extends keyof RequestSchema ? [RequestSchema['headers']] extends [never] ? DefaultHeadersSchema : 'content-type' extends keyof Default<RequestSchema['headers']> ? DefaultHeadersSchema : {
'content-type': 'application/json';
} : {
'content-type': 'application/json';
} : DefaultHeadersSchema : DefaultHeadersSchema;
type HttpRequestHeadersSchema<MethodSchema extends HttpMethodSchema> = 'headers' extends keyof MethodSchema['request'] ? [MethodSchema['request']['headers']] extends [never] ? HttpRequestHeadersSchemaFromBody<Default<MethodSchema['request']>, never> : (MethodSchema['request']['headers'] & HttpRequestHeadersSchemaFromBody<Default<MethodSchema['request']>, {}>) | Extract<MethodSchema['request']['headers'], undefined> : HttpRequestHeadersSchemaFromBody<Default<MethodSchema['request']>, never>;
type HttpRequestSearchParamsSchema<MethodSchema extends HttpMethodSchema> = 'searchParams' extends keyof MethodSchema['request'] ? Default<MethodSchema['request']>['searchParams'] : never;
type HttpRequestBodySchema<MethodSchema extends HttpMethodSchema> = ReplaceBy<IfNever<DefaultNoExclude<Default<MethodSchema['request']>['body']>, null>, undefined, null>;
type HttpResponseHeadersSchemaFromBody<ResponseSchema extends HttpResponseSchema, DefaultHeadersSchema> = 'body' extends keyof ResponseSchema ? [ResponseSchema['body']] extends [never] ? DefaultHeadersSchema : [Extract<ResponseSchema['body'], BodyInit | HttpSearchParams | HttpFormData>] extends [never] ? 'headers' extends keyof ResponseSchema ? [ResponseSchema['headers']] extends [never] ? DefaultHeadersSchema : 'content-type' extends keyof Default<ResponseSchema['headers']> ? DefaultHeadersSchema : {
'content-type': 'application/json';
} : {
'content-type': 'application/json';
} : DefaultHeadersSchema : DefaultHeadersSchema;
type HttpResponseHeadersSchema<MethodSchema extends HttpMethodSchema, StatusCode extends HttpStatusCode> = 'headers' extends keyof Default<MethodSchema['response']>[StatusCode] ? [Default<MethodSchema['response']>[StatusCode]] extends [never] ? HttpResponseHeadersSchemaFromBody<Default<Default<MethodSchema['response']>[StatusCode]>, never> : (Default<Default<MethodSchema['response']>[StatusCode]>['headers'] & HttpResponseHeadersSchemaFromBody<Default<Default<MethodSchema['response']>[StatusCode]>, {}>) | Extract<Default<Default<MethodSchema['response']>[StatusCode]>['headers'], undefined> : HttpResponseHeadersSchemaFromBody<Default<Default<MethodSchema['response']>[StatusCode]>, never>;
type HttpResponseBodySchema<MethodSchema extends HttpMethodSchema, StatusCode extends HttpStatusCode> = ReplaceBy<IfNever<DefaultNoExclude<Default<Default<MethodSchema['response']>[StatusCode]>['body']>, null>, undefined, null>;
export { type AllowAnyStringInPathParams, HTTP_METHODS, HttpBody, HttpFormData, HttpFormDataSchema, HttpFormDataSchemaName, type HttpFormDataSerialized, HttpHeaders, type HttpHeadersInit, HttpHeadersSchema, type HttpHeadersSchemaName, type HttpHeadersSchemaTuple, type HttpHeadersSerialized, type HttpMethod, type HttpMethodSchema, type HttpMethodsSchema, HttpPathParamsSchema, type HttpPathParamsSerialized, type HttpRequest, type HttpRequestBodySchema, type HttpRequestHeadersSchema, type HttpRequestSchema, type HttpRequestSearchParamsSchema, type HttpResponse, type HttpResponseBodySchema, type HttpResponseHeadersSchema, type HttpResponseSchema, type HttpResponseSchemaByStatusCode, type HttpResponseSchemaStatusCode, HttpSchema, type HttpSchemaMethod, HttpSchemaPath, HttpSearchParams, type HttpSearchParamsInit, HttpSearchParamsSchema, HttpSearchParamsSchemaName, type HttpSearchParamsSchemaTuple, type HttpSearchParamsSerialized, HttpStatusCode, type InferPathParams, type JSONSerialized, JSONValue, type LiteralHttpSchemaPathFromNonLiteral, type MergeHttpResponsesByStatusCode, type StrictFormData, type StrictHeaders, type StrictURLSearchParams };