**`Persistence`** is possible thanks to setting the appropriate cache or queues storage - which will be able to store
between sessions in the application or its launches. To enable the persistence of data, we must replace the default
storages with the ones we choose, which will meet our requirements - we do not have many requirements here, except for
the type that we accept.

:::note

Persistence storages can handle only json data. Remember that all file objects need to be translated to base64 or other
valid format to match json requirements.

:::

---

## Cache Persistance

```ts
export const storage = new MMKV({ id: "my-key" });

const persistenceStorage: CacheStorageType = {
  set: (key, data) => {
    storage.set(key, JSON.stringify(data));
  },
  get: (key) => {
    const value = storage.getString(key);
    return value ? JSON.parse(value) : value;
  },
  keys: () => storage.getAllKeys(),
  delete: (key) => storage.delete(key),
  clear: () => storage.clearAll(),
};

export const builder = new Builder<ServerErrorType>({
  url: "localhost:3000",
  cache: (instance) =>
    new Cache(instance, {
      storage: persistenceStorage,
    }),
});
```

#### Async persistence storages

Example below shows the **`IndexedDb`** persistence storage. This way we will use the persistent data by `lazy loading`
it to our components. Every time we use the `cache.get(cacheKey)` method, we send a request to our `lazyStorage` and at
the same time return the last data we have, when our promise responds, we will receive an appropriate event that will
propagate the data in our components. This way we are NOT loading whole persistent data into our memory, but only part
of it, not to mention that it will get garbage collected when it's cacheTime expire.

```ts
import { get, set, del, keys } from "idb-keyval";

const asyncStorage: CacheAsyncStorageType = {
  set: (key, data) => set(idbValidKey, client),
  get: (key) => get(idbValidKey),
  keys: () => keys(),
  delete: (key) => del(key),
};

export const builder = new Builder<ServerErrorType>({
  url: "localhost:3000",
  cache: (instance) =>
    new Cache(instance, {
      lazyStorage: asyncStorage,
    }),
});
```

---

## Queues persistance

At the moment, they should work best in environments such as React Native with non-multi windows applications. To make
it possible to be used in browsers, we have to solve the problems of synchronization and shared dispatch of requests. In
this case we need to have synchronous data storage to avoid data corruption and duplicated requests.

:::caution

Persistent queues shouldn't be used on the browser. This is due to the many tabs/windows concurrency reasons. This way,
we will have multiple builders initialized where the **duplicated** requests will be send and it may cause major db data
damage.

:::

### Fetching request persistence

```ts
export const storage = new MMKV({ id: "my-key" });

const persistenceStorage: DispatcherStorageType = {
  set: (key, data) => {
    storage.set(key, JSON.stringify(data));
  },
  get: (key) => {
    const value = storage.getString(key);
    return value ? JSON.parse(value) : value;
  },
  keys: () => storage.getAllKeys(),
  delete: (key) => storage.delete(key),
  clear: () => storage.clearAll(),
};

export const builder = new Builder<ServerErrorType>({
  url: "localhost:3000",
  fetchDispatcher: (instance) =>
    new Dispatcher(instance, {
      storage: persistenceStorage,
    }),
});
```

### Submit request persistence

```ts
export const storage = new MMKV({ id: "my-key" });

const persistenceStorage: DispatcherStorageType = {
  set: (key, data) => {
    storage.set(key, JSON.stringify(data));
  },
  get: (key) => {
    const value = storage.getString(key);
    return value ? JSON.parse(value) : value;
  },
  keys: () => storage.getAllKeys(),
  delete: (key) => storage.delete(key),
  clear: () => storage.clearAll(),
};

export const builder = new Builder<ServerErrorType>({
  url: "localhost:3000",
  submitDispatcher: (instance) =>
    new Dispatcher(instance, {
      storage: persistenceStorage,
    }),
});
```
