---
sidebar_position: 1
---

<div class="api-link">
  <div class="api-link-title">Builder</div>
  <div class="api-link-sub-title">

[Read the API Reference »](/api/Hyper-Fetch/Class/Builder.md)

  </div>
</div>

---

## Introduction

**`Builder`** 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
commands necessary to execute requests. This way the data and information flow remains locked inside a given builder; it
is isolated and does not affect other builders.

It was designed to be used as a singleton, where `Builder` 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 commands to provide global setup and environment
- Isolates builders from other builders and their events

---

## Initialization

```tsx
import { Builder } from "@hyper-fetch/core";

export const builder = new Builder({ url: "http://localhost:3000" });
```

---

## Setting defaults

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

#### Command default setup

We can use the `setCommandConfig` method to specify the defaults for every created command.

---

## Features

### Authentication

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

[Read More](/guides/01-Basic/Authentication.mdx)

### Pre-Request Interceptor

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

### Post-Request Interceptors

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

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

### Query Params

Builder 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.

{@import Hyper-Fetch QueryStringifyOptions returns}

To change the encoding function, use the `setStringifyQueryParams` method.

```tsx
builder.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 builder.

### 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

Builder has two generic types.

```tsx
class Builder<GlobalErrorType, RequestConfigType>
```

- `GlobalErrorType` defines the error type used in all the commands. It should consist of an `Error` type and your
  default `ServerErrorType`. For some command’s individual error types, you can set up a `LocalErrorType` for each
  command.

- `RequestConfigType` is the generic responsible for shaping options passed to the client. Most likely you will change
  it only when you provide your custom client.

---

## Components

### [Cache](/api/Hyper-Fetch/Class/Cache.md)

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

---

### [Client](/api/Hyper-Fetch/Function/fetchClient.md)

Handles all requests within `Builder`. Can be replaced with `setClient` method.

---

### [SubmitDispatcher](/api/Hyper-Fetch/Class/Dispatcher.md)

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

---

### [FetchDispatcher](/api/Hyper-Fetch/Class/Dispatcher.md)

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

---

### [AppManager](/api/Hyper-Fetch/Class/AppManager.md)

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

---

### [CommandManager](/api/Hyper-Fetch/Class/CommandManager.md)

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

---

### [LoggerManager](/api/Hyper-Fetch/Class/LoggerManager.md)

Handles the logging systems for debugging.

---

## Parameters

Configuration options

{@import Hyper-Fetch BuilderConfig returns}

<!-- ## Authentication

1. Adding the headers to the request during authentication

```tsx
export const builder = new Builder({ url }).onAuth((command) => {
  const state = store.getState();
  const authToken = state.auth.token;

  // Before each command with setting "auth: true" add the Bearer token
  return command.setHeaders({
    ...command.headers,
    Authorization: `Bearer ${authToken}`,
  });
});

export const getUsers = builder.createCommand<{ name: string; email: string }>()({
  method: "GET",
  endpoint: "/users",
  auth: true, // Important!
});
```

2. Refreshing the token

```tsx
export const builder = new Builder({ url }).onError(async (res, command) => {
  const status = res[2];
  const refreshToken = localStorage.getItem(REFRESH_TOKEN_STORAGE_FIELD);

  // Check if command has the used value - this will ensure you will not go into infinite loop
  if (!command.used && refreshToken && status === 401) {
    // Prepare the refresh token command
    const postRefreshToken = builder.createCommand<LoginResponse, LoginData>()({
      endpoint: "/refresh-token",
      method: "POST",
    });

    // Call the command to receive new tokens
    const [data] = await postRefreshToken.setData({ refreshToken }).exec();

    if (data) {
      // Safe the new tokens
      localStorage.setItem(TOKEN_STORAGE_FIELD, data.token);
      localStorage.setItem(REFRESH_TOKEN_STORAGE_FIELD, data.refreshToken);
      // Repeat the request
      return command.setUsed(true).send();
    }
  }
  // Return the initial response is something goes wrong
  return res;
});
``` -->

<!--

- connection graph with command and other systems

-->

<!--
## TODOS and examples

- TODO - subsection for Builder -> providing own client (other than XHR) + options
- TODO - subsection for Builder -> providing own cache.
- TODO - subsection for Builder -> section for providing own Manager implementation.
- TODO - subsection for Builder -> section for providing own queues implementation. -->
