Skip to content

Commit

Permalink
docs: api docs [WTEL-1093]
Browse files Browse the repository at this point in the history
  • Loading branch information
dlohvinov committed Apr 21, 2024
1 parent 75c93f7 commit d1842fd
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,24 +1,64 @@
# Backend API Communication

Тут ми розглянемо з теоретичної сторони, як комунікувати з бекендом у апплікейшенах.

### Чому одночасно Webitel SDK та Raw Endpoints?

Так склалось історично, але, сподіваюсь, колись це пройде і будуть тільки Webitel SDK ендпоінти.

## Webitel SDK Endpoints

Webitel SDK ендпоінти - це ендпоінти, згенеровані автоматично через Open API (aka Swagger).

Відповідно, замість того щоб самостійно будувати `url`, і все таке - ми просто передаємо параметри
у методи, які нам дає бібліотека, згідно певної сутності. Список цих сутностей та ендпоінтів можна
подивитись на [webitel swager](https://swagger.webitel.com/#/)'i.

З запитами, які мутують дані, все просто: `body` виглядає стандартно. А от з `search` ендпоінтами складнощі,
бо генерування api налаштоване так, що параметри необхідно передавати по порядку, а не одним обʼєктом.

Тобто, замість

```javascript
service.searchSmth({ page, size, search });
```

нам треба робити ось так

```javascript
service.searchSmth(page, size, search);
```

а отже, відповідно, **порядок параметрів має значення**.

Також у `service` з api методами, які ми створюємо, можна (і потрібно!) передати наш `axios instance`,
отже, всі інтерцептори і хедери, застосовувані в ньому, будуть застосовані також.

## Raw Endpoints

Тут все доволі безхитрісно і типово: ми маємо `axios instance`, ми маємо `baseUrl` групи ендпоінтів по певній
сутності, і, ми просто формуємо `url` запиту, його `body` - та й все.

Проблема в тому, що ці ендпоінти не описані у сваггері, а отже, інформація про них передається традиційно:
із уст в уста. 🫠

## Тонкощі роботи з ендпоінтами

### Falsy values

API Gateway на бекенді налаштований так, що не вертає полів, які мають falsy значення.
**API** Gateway на бекенді налаштований так, що **не вертає полів, які мають falsy значення**.

А нам-то ці поля потрібні!

Отже, ми маємо в ці поля сетати дефолтні для них значення.
Отже, ми **маємо в ці поля сетати дефолтні для них значення**.

### Чому одночасно Webitel SDK та Raw Endpoints?
## WebSocket

Так склалось історично, але, сподіваюсь, колись це пройде і будуть тільки Webitel SDK ендпоінти.
Для організації роботи з дзвінками або чатами використовується WebSocket зʼєднання.

## WebSocket
Як правило, на Webitel SDK WebSocket'i (вебсокет обгорнутий у бібліотеку, яка має методи керування ним)
працює Workspace та Supervisor. А Omni-widget - на raw WebSocket'i
(створюємо і відкриваємо коннекшен самостійно).

## А як додать апішку-то?

Expand Down
103 changes: 103 additions & 0 deletions docs/pages/docs/how-to/add-a-REST-API-module/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,95 @@
- axios interceptors: [api/interceptors](../../../webitel-ui/api/interceptors/Readme.md)
- Трансформери для даних: [api/transformers](../../../webitel-ui/api/transformers/Readme.md)

### REST API Module Interface

**Обовʼязково, подивіться у секцію Interface [api/clients](../../../webitel-ui/api/clients/Readme.md#interface).**

## Як додати Webitel SDK Endpoint модуль?

### TLDR;
Піддивіться у souce code якогось з `api/clients` 🙂

### Довгий та розумний шлях

Спершу, нам треба створити `service` з `ApiFactory`, наприклад

```javascript
import { SomeEntityApiFactory } from 'webitel-sdk';

const service = new SomeEntityApiFactory(instance, '', openAPIConfig);
```

Далі, у нас є вхідні параметри, які ми передаємо у метод апі модуля.

Це може бути `params`, `itemInstance`, `changes`, чи ше шось (знов таки, дивіться у [інтерфейси](#rest-api-module-interface))

Нам треба ці параметри якось "обробити", підготувати до відправки.

Для цього у нас є трансформери, в `api/transformers`. Вони, як пайплайн, обробляють вхідні параметри,
і повертають оброблені.

Що нам зазвичай треба обробити?

(1) Як правило, перевести дані з того, що піде як `body` у snake_case з camelCase.

(2) Почистити непотрібні поля, адже бекенд їх не прийме і викине помилку.

(3) Зробити якісь кастомні трансформації з даними, специфічні саме для цього ендпоінта.

Як це виглядає?

```javascript
const addItem = ({ itemInstance }) => {

const body = applyTransform(itemInstance, [
camelToSnake, // (1)
sanitize(fieldsToSend), // (2)
({ id, ...rest }) => ({
itemId: id,
...rest
}), // (3)
]);
}
```

Далі, ми викликаємо наш api метод

```javascript
const addItem = async ({ itemInstance }) => {
// ...

const response = await service.add(body);
}
```

Обробляємо відповідь, наприклад, дописуючи `counter: 0`

```javascript
() => {
// ...

const item = applyTransform(response, [
(item) => ({ ...item, counter: 0 }),
]);
}
```

Ну і, обробляєм потенційну помилку

```javascript
() => {
// ...
try {
// ...
} catch (err) {
throw applyTransform(err, [
log,
]);
}
}
```

### Тонкощі

#### Як знайти необхідну мені ApiFactory, та її методи?
Expand All @@ -38,7 +123,25 @@
Де замість `...` - назва сутності, з якою ми працюємо.

## Як додати Raw Endpoint модуль?

Та в принципі, те саме що і з Webitel SDK ендпоінтом, тільки тут нам треба сформувати `url`,
щоби зробити на нього запит, як

```javascript
const baseUrl = '/entity';

async (id) => {
// ...

const url = `${baseUrl}/${id}`;
const response = await instance.get(url);
}
```

### TLDR;
Піддивіться у souce code якогось з `api/clients` 🙂

### Довгий та розумний шлях

### Тонкощі
Тут - немає. Берете, формуєте `url`'ку, викликаєте http метод, обробляєте відповідь.

0 comments on commit d1842fd

Please sign in to comment.