@zhengxs/http
Version:
A lightweight cross-platform http request library
162 lines (161 loc) • 8 kB
TypeScript
/// <reference types="node" />
import { type Agent, type HeadersInit, type RequestInfo, type RequestInit } from './_shims/index';
import { APIError } from './error';
import type { APIResponseProps, DefaultQuery, Fetch, FinalRequestOptions, PromiseOrValue, ReqHeaders, RequestClient, RequestOptions } from './types';
export { maybeMultipartFormRequestOptions, multipartFormRequestOptions, createForm, type Uploadable, } from './uploads';
export declare function defaultParseResponse<T>(props: APIResponseProps): Promise<T>;
/**
* A subclass of `Promise` providing additional helper methods
* for interacting with the SDK.
*/
export declare class APIPromise<T> extends Promise<T> {
private responsePromise;
private parseResponse;
private parsedPromise;
constructor(responsePromise: Promise<APIResponseProps>, parseResponse?: (props: APIResponseProps) => PromiseOrValue<T>);
_thenUnwrap<U>(transform: (data: T) => U): APIPromise<U>;
/**
* Gets the raw `Response` instance instead of parsing the response
* data.
*
* If you want to parse the response body but still get the `Response`
* instance, you can use {@link withResponse()}.
*/
asResponse(): Promise<Response>;
/**
* Gets the parsed response data and the raw `Response` instance.
*
* If you just want to get the raw `Response` instance without parsing it,
* you can use {@link asResponse()}.
*/
withResponse(): Promise<{
data: T;
response: Response;
}>;
private parse;
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
finally(onfinally?: (() => void) | undefined | null): Promise<T>;
}
export interface APIClientOptions {
baseURL: string;
maxRetries?: number | undefined;
timeout?: number | undefined;
httpAgent?: Agent | undefined;
fetch?: Fetch | undefined;
}
export declare class APIClient {
baseURL: string;
maxRetries: number;
timeout: number;
httpAgent: Agent | undefined;
protected fetch: Fetch;
protected idempotencyHeader?: string;
constructor({ baseURL, maxRetries, timeout, // 10 minutes
httpAgent, fetch: overrideFetch, }: APIClientOptions);
/**
* Override this to add your own auth headers.
*
* ```ts
* {
* Authorization: 'Bearer 123',
* }
* ```
*/
protected authHeaders(_opts: FinalRequestOptions): PromiseOrValue<ReqHeaders>;
/**
* Override this to add your own default headers.
*/
protected defaultHeaders(opts: FinalRequestOptions): Promise<ReqHeaders>;
protected defaultQuery(): DefaultQuery | undefined;
/**
* Override this to add your own headers validation:
*/
protected validateHeaders(_headers: ReqHeaders, _customHeaders: ReqHeaders): void;
protected defaultIdempotencyKey(): string;
get<Req extends NonNullable<unknown>, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp>;
post<Req extends NonNullable<unknown>, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp>;
patch<Req extends NonNullable<unknown>, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp>;
put<Req extends NonNullable<unknown>, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp>;
delete<Req extends NonNullable<unknown>, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp>;
private methodRequest;
getAPIList<Item, PageClass extends AbstractPage<Item> = AbstractPage<Item>>(path: string, Page: new (...args: any[]) => PageClass, opts?: RequestOptions<any>): PagePromise<PageClass, Item>;
private calculateContentLength;
protected buildRequest<Req extends NonNullable<unknown>>(options: FinalRequestOptions<Req>): Promise<{
req: RequestInit;
url: string;
timeout: number;
}>;
/**
* Used as a callback for mutating the given `RequestInit` object.
*
* This is useful for cases where you want to add certain headers based off of
* the request properties, e.g. `method` or `url`.
*/
protected prepareRequest(_request: RequestInit, _config: {
url: string;
options: FinalRequestOptions;
}): Promise<void>;
protected parseHeaders(headers: HeadersInit | null | undefined): Record<string, string>;
protected makeStatusError(status: number | undefined, error: NonNullable<unknown> | undefined, message: string | undefined, headers: ReqHeaders | undefined): APIError;
request<Req extends NonNullable<unknown>, Rsp>(options: PromiseOrValue<FinalRequestOptions<Req>>, remainingRetries?: number | null): APIPromise<Rsp>;
protected makeRequest(optionsInput: PromiseOrValue<FinalRequestOptions>, retriesRemaining: number | null): Promise<APIResponseProps>;
simple<Req extends NonNullable<unknown>, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp>;
protected makeSimpleRequest(optionsInput: PromiseOrValue<FinalRequestOptions>, retriesRemaining?: number | null): Promise<APIResponseProps>;
requestAPIList<Item = unknown, PageClass extends AbstractPage<Item> = AbstractPage<Item>>(Page: new (...args: ConstructorParameters<typeof AbstractPage>) => PageClass, options: FinalRequestOptions): PagePromise<PageClass, Item>;
buildURL<Req extends Record<string, unknown>>(path: string, query: Req | null | undefined): string;
protected stringifyQuery(query: Record<string, unknown>): string;
fetchWithTimeout(url: RequestInfo, init: RequestInit | undefined, ms: number, controller: AbortController): Promise<Response>;
protected getRequestClient(): RequestClient;
private shouldRetry;
private retryRequest;
private calculateDefaultRetryTimeoutMillis;
protected getUserAgent(): string;
static create(baseURL: string, options?: Omit<APIClientOptions, 'baseURL'>): APIClient;
}
export type PageInfo = {
url: URL;
} | {
params: Record<string, unknown> | null;
};
export declare abstract class AbstractPage<Item> implements AsyncIterable<Item> {
#private;
protected options: FinalRequestOptions;
protected response: Response;
protected body: unknown;
constructor(client: APIClient, response: Response, body: unknown, options: FinalRequestOptions);
/**
* @deprecated Use nextPageInfo instead
*/
abstract nextPageParams(): Partial<Record<string, unknown>> | null;
abstract nextPageInfo(): PageInfo | null;
abstract getPaginatedItems(): Item[];
hasNextPage(): boolean;
getNextPage(): Promise<this>;
iterPages(): AsyncGenerator<AbstractPage<Item>, void, unknown>;
[Symbol.asyncIterator](): AsyncGenerator<Awaited<Item>, void, unknown>;
}
/**
* This subclass of Promise will resolve to an instantiated Page once the request completes.
*
* It also implements AsyncIterable to allow auto-paginating iteration on an unawaited list call, eg:
*
* ```ts
* for await (const item of client.items.list()) {
* console.log(item)
* }
* ```
*/
export declare class PagePromise<PageClass extends AbstractPage<Item>, Item = ReturnType<PageClass['getPaginatedItems']>[number]> extends APIPromise<PageClass> implements AsyncIterable<Item> {
constructor(client: APIClient, request: Promise<APIResponseProps>, Page: new (...args: ConstructorParameters<typeof AbstractPage>) => PageClass);
/**
* Allow auto-paginating iteration on an un awaited list call, eg:
*
* ```ts
* for await (const item of client.items.list()) {
* console.log(item)
* }
* ```
*/
[Symbol.asyncIterator](): AsyncGenerator<Awaited<Item>, void, unknown>;
}