npm package: @md_team/api-factory
Description: axios-based api factory
Author: puppuppuppup
Latest version: 0.1.7

## Содержание
- [Содержание](#содержание)
- [О проекте](#о-проекте)
- [Быстрый старт](#быстрый-старт)
- [Инициализация](#инициализация)
  - [`httpConfig`](#httpconfig)
  - [`apisConfig`](#apisconfig)
- [Создание api](#создание-api)
- [Типизация](#типизация)
  - [Шаблонная типизация](#шаблонная-типизация)
  - [Кастомная типизация](#кастомная-типизация)
- [Расширение api](#расширение-api)

## О проекте
Данный проект предоставляет к использованию универсальное средство для создания API-сущностей с базовым наборов методов

Сделано на базе [`axios`](https://www.npmjs.com/package/axios)

## Быстрый старт
```ts
import { Api, ApiFactory, ApiBaseTypes } from '@md_team/api-factory'

type MyType = {
    id: number;
    name: string;
    email: string;
};

// apis - хранилище всех указанных API
const { apis } = new ApiFactory({
    httpConfig: {
        baseURL: 'base_url',
    },
    apisConfig: {
        myApi: {
            apiClass: Api<ApiBaseTypes<MyType>>,
            endpoint: 'my-endpoint',
        },
    },
});
```
## Инициализация

### `httpConfig`
Данное поле отвечает за настройку http-сущности, на базе которой будут строиться запросы API. Можно передать все стандартные свойства, доступные при использовании `axios.create(...options)`, и дополнительные:
- `interceptors`: настройка заготовленных (`presets`) и кастомных (`custom`) интерцепторов для axios-сущности

**Рекомендуемые к настройке параметры:**
- `baseUrl`: общая часть ссылки для всех API в пределах данной `ApiFactory` (например, домен)

**Заготовленные интерцепторы: (рекомендуется к использованию ТОЛЬКО в веб-среде)**
- `tokenName`: название токена, которое используется в cookies в вашем веб-приложении. На его основании будут работать интерцепторы, основанные на авторизации
- `authorize`: автоматически заполняет или удаляет заголовок `Authorization`, заполняя его Bearer-токеном из cookies
- `unauthorize`: удаляет из cookies токен при получении 401-ой ошибки

### `apisConfig`

В данное поле мы передаем объект с настройками нужных нам API. Ключи объекта будут использованы, как названия соответствующих API, В него входят:
- `apiClass`: сущность, которая наследует класс `Api` и которая будет лежать в основе настройки методов и типов определенной API-сущности. Если отсутствует необходимость в типизации, можно передать `Api` без типов, но тогда для базовых методов будет применен `any`
- `endpoint`: эндпоинт, на который будет настроен API относительно `baseURL` из `httpConfig` вашей `ApiFactory`

## Создание api
```ts
const { apis } = new ApiFactory({
    httpConfig: {
        baseURL: 'base_url',
    },
    apisConfig: {
        myApi: {
            apiClass: Api,
            endpoint: 'endpoint',
        },
    },
});
```
Теперь мы имеем api-сущность `myApi`, предоставляющую методы:
- `findOne`
- `findMany`
- `create`
- `update`
- `delete`

Данные методы имеют предустановленный `endpoint`, который мы указали при создании сущности.

Также все методы поддерживают передачу последним параметром `AxiosRequestConfig`

## Типизация
Базовое использование `Api` в поле `apiClass` вернет нам сущность с методами, работающими с `any`, но мы можем протипизировать её.

Типизация разделена на:
- `single`
- `many`
- `create`
- `update`

Базовый набор функций используют типизацию следующим образом:
- `findOne` - возвращает `single`
- `findMany` - возвращает `many`
- `create` - принимает `create` и возвращает `single`
- `update` - принимает `update` и возвращает `single`
- `delete` - возвращает `single`

### Шаблонная типизация
```ts
import { ApiBaseTypes, ApiFactory, Api } from "@md_team/api-factory";

type User = {
    id: number;
    name: string;
    email: string;
}

// Использование утилиты для шаблонной типизации
type ApiTypes = ApiBaseTypes<User>;

const { apis } = new ApiFactory({
    httpConfig: {
        baseURL: 'base_url',
    },
    apisConfig: {
        usersApi: {
            apiClass: Api<ApiTypes>,
            endpoint: 'users',
        },
    },
});
```
При использовании шаблона `ApiBaseTypes`, мы получаем базовую типизацию следующего вида:
```ts
export type ApiBaseTypes<BaseType> = ApiCustomTypes<{
    single: BaseType;
    many: BaseType[];
    create: Omit<BaseType, 'id'>;
    update: Partial<Omit<BaseType, 'id'>>;
}>;
```
### Кастомная типизация
Если необходимо переписать типы под определенные задачи, можно воспользоваться утилитой `ApiCustomTypes`, передав в неё необходимые типы
```ts
import { ApiCustomTypes, ApiFactory, Api } from "@md_team/api-factory";

type User = {
    id: number;
    name: string;
    email: string;
}

// Использование утилиты для кастомной типизации
type ApiTypes = ApiCustomTypes<{
    single: Pick<User, 'id'>,
    many: ApiTypes['single'][],
    create: Pick<User, 'email'>,
    update: Partial<User>,
}>;

const { apis } = new ApiFactory({
    httpConfig: {
        baseURL: 'base_url',
    },
    apisConfig: {
        usersApi: {
            apiClass: Api<ApiTypes>,
            endpoint: 'users',
        },
    },
});
```
Также мы можем воспользоваться `ApiCustomTypes` на базе существующего типа для API, доработав его
```ts
import { ApiBaseTypes, ApiCustomTypes, ApiFactory, Api } from "@md_team/api-factory";

type User = {
    id: number;
    name: string;
    email: string;
}

// Базовые типы
type ApiTypes = ApiBaseTypes<User>;

// Модифицированные типы
type ApiModifiedTypes = ApiCustomTypes<ApiTypes, {
    create: Pick<User, 'id'>;
}>

const { apis } = new ApiFactory({
    httpConfig: {
        baseURL: 'base_url',
    },
    apisConfig: {
        usersApi: {
            apiClass: Api<ApiTypes>,
            endpoint: 'users',
        },
        usersModifiedApi: {
            apiClass: Api<ApiModifiedTypes>,
            endpoint: 'users',
        },
    },
});
```
## Расширение api
Если нам необходимо добавить свои методы, не входящие в стандартный набор, мы можем расширить существующий api
```ts
import { Api, ApiBaseTypes, ApiFactory } from "@md_team/api-factory";

type User = {
    id: number;
    name: string;
    email: string;
}

class UsersExtendedApi extends Api<ApiBaseTypes<User>> {
    getMe() {
        return this.httpInstance.get(this.endpoint + '/me');
    }
}

const { apis } = new ApiFactory({
    httpConfig: {
        baseURL: 'base_url',
    },
    apisConfig: {
        usersExtendedApi: {
            apiClass: UsersExtendedApi,
            endpoint: 'users',
        },
    },
});

apis.usersExtendedApi.getMe();
```