Skip to main content
Version: 5.x.x

Client


Introduction

Client is a class that allows you to configure the server connection. It initializes the entire library’s subsystems, such as queues, caches, and interceptors. It also allows you to create (based on its settings) the requests necessary to execute requests. This way the data and information flow remains locked inside a given client; it is isolated and does not affect other clients.

It was designed to be used as a singleton, where Client helps us create a global structure for making server requests without duplicating logic in different parts of the application. In this approach, we can easily create a solid structure and architecture for an application. This also facilitates test maintenance by dividing the necessary configurations and types.


Purpose

  • Orchestrates the components and flow of the library
  • Creates requests to provide global setup and environment
  • Isolates clients from other clients and their events


Initialization

import { Client } from "@hyper-fetch/core";

export const client = new Client({ url: "http://localhost:3000" });

Setting defaults

Because Hyper Fetch components are created inside Client, you can set global or default system values on it.

Request default setup

We can use the setRequestDefaultOptions method to specify the defaults for every created request.

type RequestOptionsType<GenericEndpoint,AdapterOptions,RequestMethods> = {
abortKey: string;
auth: boolean;
cache: boolean;
cacheKey: string;
cacheTime: number;
cancelable: boolean;
deduplicate: boolean;
deduplicateTime: number;
disableRequestInterceptors: boolean;
disableResponseInterceptors: boolean;
effectKey: string;
endpoint: GenericEndpoint;
garbageCollection: number;
headers: HeadersInit;
method: RequestMethods;
offline: boolean;
options: AdapterOptions;
queueKey: string;
queued: boolean;
retry: number;
retryTime: number;
}

Add them by:

const request = client.setRequestDefaultOptions((options) => {
if (options.method === "POST") {
return { timeout: 1000, withCredentials: true };
} else {
return options;
}
});

Adapter defaults setup

info

Adapter options may vary depending on the adapter you use.

We can use the setAdapterDefaultOptions method to specify the defaults for every request.

Default HTTP adapter options:

{
timeout: number;
withCredentials: boolean;
responseType: "text" | "document" | "arraybuffer" | "blob" | "json";
}

Add them by:

const request = client.setAdapterDefaultOptions({ timeout: 1000, withCredentials: true });

Features

Authentication

To send authenticated requests, set up the onAuth interceptor. Set up the request with the auth option set to true. Read more about authentication here.

Read More

Pre-Request Interceptor

Use the onRequest client method if you need to use the pre-request interceptor to modify the request before it’s sent.

Post-Request Interceptors

There are several methods for intercepting a response from a request:

  • onError which is triggered on request error response.
  • onSuccess which is triggered on request success response.
  • onResponse which is triggered on any response.

We can modify received data with these interceptors before it will be emitted to other sub-systems.

Query Params

Client has a built-in query params encoding function; you can modify its options or provide your own function. Use the setQueryParamsConfig method and the options listed below.

{
arrayFormat: bracket | index | comma | separator | bracket-separator | none;
arraySeparator: string;
dateParser: (value: QueryParamType) => string;
encode: boolean;
objectParser: (value: QueryParamType) => string;
skipEmptyString: boolean;
skipNull: boolean;
strict: boolean;
}

To change the encoding function, use the setStringifyQueryParams method.

client.setStringifyQueryParams((value: string) => encode(value));

Header Mapper

By default, the header mapper behaves very simply: it checks if the content is FormData or JSON, and provides correct headers to the request. You can create much more advanced setups with the setHeaderMapper. It allows you to define custom logic that will be triggered before every request made in the client.

Payload Mapper

The payload mapper’s default responsibility is to check if data is an instance of FormData or not. Based on this, you can stringify non-FormData values or just pass the FormData to the request to be made. This allows file upload to be supported out of the box.


Typescript

Client has two generic types.

class Client<GlobalErrorType, AdapterOptions>
  • GlobalErrorType defines the error type used in all the requests. It should consist of an Error type and your default ServerErrorType. For some request’s individual error types, you can set up a LocalErrorType for each request.

  • AdapterOptions is the generic responsible for shaping options passed to the adapter. Most likely you will change it only when you provide your custom adapter.


Components

Cache

Handles data storages and persistence. Can be adjusted with options when initializing Client.


Adapter

Handles all requests within Client. Can be replaced with setAdapter method.


SubmitDispatcher

Handles the mutation requests and queueing. Can be adjusted with options when initializing the client.


FetchDispatcher

Handles the fetching requests and queueing. Can be adjusted with options when initializing the client.


AppManager

Handles the app focus and online state. Can be adjusted with options when initializing the client.


RequestManager

Handles additional events and cancellation of requests. Can be adjusted with options when initializing the client.


LoggerManager

Handles the logging systems for debugging.


Parameters

Configuration options

{
adapter: (request: RequestInstance, requestId: string, DO_NOT_USE?: [object Object]) => Promise<ResponseReturnType<any, any, any>>;
appManager: (client: C) => C[appManager];
cache: (client: C) => C[cache];
fetchDispatcher: (client: C) => C[submitDispatcher];
submitDispatcher: (client: C) => C[fetchDispatcher];
url: string;
}