npm package: @instant-messengers/vk-teams-bridge
Description: Библиотека реализует прослойку между клиентским приложением и мини-аппом. Главный функционал в мэтчинге запросов между клиентами
Latest version: 2.3.8

# VK teams bridge
Библиотека реализует прослойку между клиентским приложением и мини-аппом. Главный функционал в мэтчинге запросов между клиентами

Подробная инструкция о том как это работает и список доступных методов в [документации](https://biz.mail.ru/docs/on-premises/vk-teams/mini-apps/index.html#vk-teams-bridge)

## Установка
Добавляем ``@instant-messengers:registry=https://registry.npmjs.org/`` в ``.npmrc``. Далее загружаем как npm пакет.

Или добавляем скрипт на страницу, если в проекте нет сборщика:
```html
<head>
    <script src="./index.min.js"></script>
    <script>
        window.VKTBridge.send('LoadingCompleted', { ok: true })
            .then((bridgeResponse) => {
                console.log({ bridgeResponse });
            })
            .catch((bridgeError) => {
                console.log({ bridgeError });
            });
    </script>
</head>
```

### Инициализация экземпляра класса и типизация
Для правильной типизации `bridge` необходимо при инициализации класса передать в его конструктор следующие generic аргументы:

- `SUBSCRIBE_ACTION` - enum, описывающий возможные имена подписок (`TeamsSubscribeAction`)
- `SUBSCRIBE_DESCRIPTOR` - тип формата `Record<SUBSCRIBE_ACTION,TSubscribeActionDescriptor<any, any, any>>` (`TTeamsSubscribeActionsDescriptor`)
- `SEND_ACTION` - enum, описывающий возможные имена ивентов для отправки (`TeamsSendAction`)
- `SEND_DESCRIPTOR` - тип формата `Record<SUBSCRIBE_ACTION,TSendActionDescriptor<any, any, any>>` (`TTeamsSendActionsDescriptor`)

Пример: `new Bridge<SUBSCRIBE_ACTION, SUBSCRIBE_DESCRIPTOR, SEND_ACTION, SEND_DESCRIPTOR>()`

Для стандартного использования, все вышеописанные типы можно импортировать прямо из пакета:

```tsx
import {
	Bridge,
	TeamsSubscribeAction,
	TTeamsSubscribeActionsDescriptor,
	TeamsSendAction,
	TTeamsSendActionsDescriptor
} from '@instant-messengers/vk-teams-bridge';

const bridge = new Bridge<TeamsSubscribeAction, TTeamsSubscribeActionsDescriptor, TeamsSendAction, TTeamsSendActionsDescriptor>()
```

Если нужны кастомные события, можно по аналогии описать свои типы с помощью хелперов, встроенных в пакет.

## Настройка для супераппа
Настройка зависит от платформы супераппа (веб, айос, андроид, десктоп)
Для реализации в iframe достаточно слушать событие message и парсить ивент.
Подробнее о настройке [тут](https://biz.mail.ru/docs/on-premises/vk-teams/mini-apps/index.html#vk-teams-bridge).

## Настройка для мини-аппа

Описание и список доступных методов [тут](https://biz.mail.ru/docs/on-premises/vk-teams/mini-apps/index.html#vk-teams-bridge)

### Эмит событий в суперапп
Для отправки событий в супер-апп необходимо вызвать метод send экземпляра класса `Bridge`.

Метод `send` принимает в качестве аргументов 2 параметра:

- action - одно из значений enum, переданного аргументом `SEND_ACTION` в generic конструктора класса `Bridge`
- payload - аргумент, передаваемый в качестве пэйлоада с типом `TSendActionDescriptor[’input’]`

Результатом вызова метода будет Promise, который либо зарезолвится со значением типа `TSendActionDescriptor[’output’]`
либо зареджектится с ошибкой `BridgeError` и кодом ошибки с типом `TSendActionDescriptor[’errorCode’]`

```tsx
import { TeamsSendAction, isBridgeError, TErrorCode, TTeamsSendActionsDescriptor } from '@instant-messengers/vk-teams-bridge';

import { bridge } from '.../.../bridge'; // импорт из кода проекта

async function openPopUp() {
    try {
        const { feedback } = await bridge.send(TeamsSendAction.OpenPopUp, {
            title: 'Заголовок',
            text: 'Описание',
            mainButton: 'Да',
            secondaryButton: 'Отмена',
        });

        if (feedback === 'main') {
            //..
        } else {
            //..
        }
    } catch (err) {
        // Проверяем на то, что ошибка соответствует типу BridgeError
        if (isBridgeError<TErrorCode<TTeamsSendActionsDescriptor[TeamsSendAction.OpenPopUp]>>(err)) {
            switch (err.code) {
                case TeamsErrorCode.POPUP_CLOSED:
                    // обработка ошибки с кодом POPUP_CLOSED
                    break;
                case BaseBridgeErrorCode.BAD_REQUEST:
                    // обработка ошибки с кодом BAD_REQUEST
                    break;
                //...
            }
        } else {
            // обработка других ошибок
        }
    }
}
```

### Подписка на события из суперапп
Для подписки на события из суперапп необходимо воспользоваться методом subscribe экземпляра класса `Bridge`.

Метод subscribe принимает в качестве аргументов 3 параметра:

- action - одно из значений enum, переданного аргументом SUBSCRIBE_ACTION в generic конструктора класса `Bridge`
- callback - функция-обработчик, которая будет вызвана при наступлении action
- params - дополнительные параметры подписки события

Результатом вызова метода будет `Promise` который либо зарезолвится объектом со значением типа  `{ unsubscribe: () ⇒ void }`, где `unsubscribe` - метод,
вызов которого отменяет подписку, либо зареджектится с ошибкой `BridgeError` и кодом ошибки с типом `TSubscribeActionDescriptor[’errorCode’]`.

```tsx
import { TeamsSendAction, isBridgeError, TErrorCode, TTeamsSendActionsDescriptor } from '@instant-messengers/vk-teams-bridge';

import { bridge } from '.../.../bridge'; // импорт из кода проекта

async function subscribeToChangeLanguage() {
    try {
        // Для отписки от события необходимо вызвать метод unsubscribe
        const { unsubscribe } = await bridge.subscribe(TeamsSubscribeAction.Language, (data) => {
            console.log(`Язык сменился на ${data.language}`)
        });
    } catch (err) {
        // Проверяем на то, что ошибка соответствует типу BridgeError
        if (isBridgeError<TErrorCode<TTeamsSubscribeActionsDescriptor[TeamsSubscribeAction.Language]>>(err)) {
            switch (err.code) {
                case BaseBridgeErrorCode.INTERNAL_ERROR:
                    // обработка ошибки с кодом INTERNAL_ERROR
                    break;
                //... обработка других кейсов
            }
        } else {
            // обработка других ошибок
        }
    }
}
```

### Обработка ошибок
`Bridge` может выбросить ошибку в виде экземпляра класса `BridgeError`. Для явной проверки на то, что ошибка, 
которую мы словили в `catch` является экземпляром класса `BridgeError` есть хелпер `isBridgeError()`.

`isBridgeError` в качестве аргумента generic принимает `TErrorCode<{Дескриптор события, которое мы обрабатываем}>`, 
а в качестве аргумента функции принимает саму ошибку.

Примеры работы с этим хелпером описаны выше. 
Обратите внимание на то, что в качестве аргумента generic `TErrorCode` можно воспользоваться встроенными в пакет типами дескрипторов,  
которые есть на каждое стандартное действие. Так, например запись `isBridgeError<TErrorCode<TTeamsSendActionsDescriptor[TeamsSendAction.OpenPopUp]>>(err)` из примера 
работы с методом `bridge.send()` можно заменить на `isBridgeError<TErrorCode<TOpenPopUp>>(err)`, 
а запись `isBridgeError<TErrorCode<TTeamsSubscribeActionsDescriptor[TeamsSubscribeAction.Language]>>(err)` из примера работы 
с методом `bridge.subscribe()` можно заменить на `isBridgeError<TErrorCode<TLanguage>>(err)`.

`TOpenPopUp` и `TLanguage`, как и другие типы импортируются из пакета.