UNPKG

frest

Version:

REST client for browser with Fetch

501 lines (482 loc) 14.8 kB
/** * @module frest */ import { Frest } from './Frest'; import { InterceptorManager } from './InterceptorManager'; /** * Supported HTTP Method * @public */ export type HttpMethod = | 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS'; export interface HeaderConfig { common: Headers; post: Headers; get: Headers; put: Headers; delete: Headers; patch: Headers; options: Headers; } export type ResponseTransformer = (raw: Response, data: any) => any; export type RequestTransformer = (req: FrestRequest, data?: any) => any; /** * Base config for Frest instance * @public */ export interface ConfigBase { /** * The base url for this instance. Defaults to empty string. * @public */ base: string; transformResponse: ResponseTransformer[]; transformRequest: RequestTransformer[]; /** * {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API | Fetch API} function implementation to use. * @remarks * Useful for example to provide custom `fetch` function or mocking in test. * By default use native browser `fetch` function and will fallback to {@link https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest | XMLHttpRequest} * if not available. * @public */ fetch: typeof fetch; /** * Default HTTP Method to use if not supplied in request. Defaults to `GET`. * @public */ method: HttpMethod; // /** // * Default {@link https://developer.mozilla.org/en-US/docs/Web/API/Headers | Headers} to include in each request. // * @remarks // * If this Headers contain key which is supplied in request, it will get overridden. // * In native `fetch` API, this can also be a key-value object, but for Frest // * it's **required** to be an instance of `Headers` class. // * @public // */ // headers: IHeaderConfig; /** * Default cache mode you want to use for each request: `default`, `no-store`, `reload`, `no-cache`, `force-cache`, or `only-if-cached`. * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ cache?: RequestCache; /** * Default request credentials you want to use for each request: `omit`, `same-origin`, or `include`. * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ credentials?: RequestCredentials; /** * The `keepalive` option can be used to allow the request to outlive the page. * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ keepalive?: boolean; /** * Default mode you want to use for each request, e.g., `cors`, `no-cors`, or `same-origin`. * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ mode?: RequestMode; /** * Default redirect mode to use for each request. * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ redirect?: RequestRedirect; /** * A {@link https://developer.mozilla.org/en-US/docs/Web/API/USVString | USVString} specifying `no-referrer`, `client`, or a URL for each request * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ referrer?: string; /** * Specifies the value of the referer HTTP header for each request. * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ referrerPolicy?: ReferrerPolicy; /** * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ signal?: AbortSignal; } export interface Config extends ConfigBase { /** * Default {@link https://developer.mozilla.org/en-US/docs/Web/API/Headers | Headers} to include in each request. * @remarks * If this Headers contain key which is supplied in request, it will get overridden. * In native `fetch` API, this can also be a key-value object, but for Frest * it's **required** to be an instance of `Headers` class. * @public */ headers: HeaderConfig; } /** * Frest configuration used in constructor and config merge. * @remarks * Frest instance contains some default configurations, so all * configuration properties are optional when used in constructor * and {@link Frest.mergeConfig}. They are basically * the same as {@link IConfig}. * @public */ export type ConfigMergeType = Partial<ConfigBase> & { headers?: Partial<HeaderConfig>; }; /** * Frest configuration used in constructor. * @remarks * It can either be a string of `base` URL or a configuration object of {@link ConfigMergeType}. * @public */ export type ConfigType = string | ConfigMergeType; /** * Request configuration object. * @remarks * The request configuration extends from native `fetch` request init options * and also accept any properties outside those. This can be useful for * debugging, interceptor, etc. to identify originating request. * * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ export interface FrestRequest { [key: string]: any; /** * Path relative to {@link IConfigBase.base}. * @remarks * The full endpoint URL to call is constructed from Frest instance's `base` * config and this `path` property. It can be a string, e.g. `/foo/bar` or * an array, e.g. `['foo', 'bar']` * @public */ path: string | string[]; /** * HTTP request method used in this request. * @remarks * Defaults to the instance's `method` configuration if not supplied. * This is ignored when calling instance's request shortcut methods, in * which the HTTP method is set according to the function name, e.g. `get` * will use `GET` HTTP method and setting this **won't** override it. * @public */ method: HttpMethod; /** * HTTP request headers used in this request. * @remarks * The request will include instance's `headers` configuration. Any existing * key defined in this request header will override the default headers. * @public */ headers: Headers; transformResponse: ResponseTransformer[]; transformRequest: RequestTransformer[]; /** * Specific action which this request called with. * @remarks * This is optional and mainly used for debugging purpose. You can provide * any value to this and use it in interceptor, logging, etc to identify * originating request. * Note that for `download` and `upload` method of Frest instance, this * is predetermined and can't be overridden * @public */ action?: string; /** * Specific base URL for this request. * @remarks * Override the instance's `base` configuration for this specific request. * @public */ base?: string; /** * Parameter for this request. * @remarks * Specify URL query with key-value object or string. This will be appended * to the final endpoint URL as query string. * @public */ query?: any; /** * `fetch` function used in this request. * @remarks * Override instance's `fetch` configuration for this request. Useful for * mocking in tests or when you want a customized native fetch function. * Note that for `download` and `upload` method of Frest instance, this will * be ignored and the request will use `XMLHTTPRequest` to support upload/download * progress. * @public */ fetch?: typeof fetch; /** * Skip processing interceptor by its id. * @remarks * This is mainly used internally by interceptors. By convention, interceptors * must honor this config and not modify request/response/error if defined * in `skip`. * @public */ skip?: string[]; /** * Body param for this request. * @remarks * Provide request body parameter which will be sent with this request. * This can be a `Blob`, `BufferSource`, `FormData`, `URLSearchParams`, * or `USVString` object, as per native `fetch` init. * * Note that a request using the GET or HEAD method cannot have a body. * Also for `upload` method of Frest instance, it's required to use * `FormData` as body. * * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ body?: any; /** * Upload progress callback for Frest instance `upload` method. * @public */ onUploadProgress?: (ev: ProgressEvent) => any; /** * Download progress callback for Frest instance `download` method. * @public */ onDownloadProgress?: (ev: ProgressEvent) => any; /** * Response type in case of client is XMLHttpRequest. * * @remarks * If using `download`, this is default to `blob`. Otherwise by default * it's `text`. */ responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text'; /** * The cache mode you want to use for the request: `default`, `no-store`, `reload`, `no-cache`, `force-cache`, or `only-if-cached`. * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ cache?: RequestCache; /** * The request credentials you want to use for the request: `omit`, `same-origin`, or `include`. * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ credentials?: RequestCredentials; /** * The `keepalive` option can be used to allow the request to outlive the page. * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ keepalive?: boolean; /** * The mode you want to use for the request, e.g., `cors`, `no-cors`, or `same-origin`. * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ mode?: RequestMode; /** * The redirect mode to use for the request. * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ redirect?: RequestRedirect; /** * A {@link https://developer.mozilla.org/en-US/docs/Web/API/USVString | USVString} specifying `no-referrer`, `client`, or a URL for the request * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ referrer?: string; /** * Specifies the value of the referer HTTP header for the request. * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ referrerPolicy?: ReferrerPolicy; /** * @remarks * See {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | fetch} * request init for more. * @public */ signal?: AbortSignal; } /** * Request configuration. * @remarks * This can be string, array of string as `path` of this request, or * a request configuration object of {@link IRequest} * @public */ export type RequestType = string | string[] | Partial<FrestRequest>; /** * Response object as a result of successful endpoint call. * @remarks * Every successful request will return a promise of this object. `T` is * type parameter of the `body` property. * * @public * @template T - The type of `body` property. Defaults to `any` */ export interface FrestResponse<T = any> { /** * Original `fetch` response. * @public */ raw: Response; /** * The body of this response, if any. * @public */ data: T; readonly headers: Headers; readonly ok: boolean; readonly redirected: boolean; readonly status: number; readonly statusText: string; readonly trailer: Promise<Headers>; readonly type: ResponseType; readonly url: string; } /** * Error object thrown in case of request failure. * @remarks * Any error happened during a request life-cycle, including non-ok HTTP status, * will have this signature. * @public */ export interface FrestErrorType { /** * The message describing this error. * @public */ message: string; /** * Frest instance used when this error happened. * @public */ frest: Frest; /** * The request config used when this error happened. * @public */ request: FrestRequest; /** * The response when this error happened, if any. * @remarks * This can be `undefined` because an error may be thrown before the request * is made. * @public */ response?: FrestResponse; } /** * Argument object passed to a request interceptor function. * @public */ export interface RequestInterceptorArg { /** * Frest instance which the request is made with. * @public */ frest: Frest; /** * The request configuration used in this request. * @public */ request: FrestRequest; } export interface ResponseInterceptorArg { /** * Frest instance which the request is made with. * @public */ frest: Frest; /** * The request configuration used in this request. * @public */ request: FrestRequest; response: FrestResponse; } /** * Request interceptor function signature. * @public */ export type RequestInterceptor = ( input: RequestInterceptorArg, ) => Promise<FrestRequest>; /** * Response interceptor function signature. * @public */ export type ResponseInterceptor = ( input: ResponseInterceptorArg, ) => Promise<FrestResponse>; /** * Error interceptor function signature. * @public */ export type ErrorInterceptor = ( error: FrestErrorType, ) => Promise<FrestResponse | undefined | null>; /** * List of interceptors by its type. * @public */ export interface Interceptors { /** * List of response interceptor; * @public */ response: InterceptorManager<ResponseInterceptor>; /** * List of request interceptor; * @public */ request: InterceptorManager<RequestInterceptor>; /** * List of error interceptor; * @public */ error: InterceptorManager<ErrorInterceptor>; }