@up-im/medotvet_sdk 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/apcheki_sdk.mdc +90 -0
- package/README.md +136 -0
- package/dist/api/abstract.d.ts +21 -0
- package/dist/api/abstract.js +125 -0
- package/dist/api/bookmarks.d.ts +28 -0
- package/dist/api/bookmarks.js +121 -0
- package/dist/api/chat.d.ts +30 -0
- package/dist/api/chat.js +118 -0
- package/dist/api/content.d.ts +154 -0
- package/dist/api/content.js +237 -0
- package/dist/api/geoIp.d.ts +8 -0
- package/dist/api/geoIp.js +14 -0
- package/dist/api/index.d.ts +27 -0
- package/dist/api/index.js +31 -0
- package/dist/api/payment.d.ts +54 -0
- package/dist/api/payment.js +90 -0
- package/dist/api/promocode.d.ts +9 -0
- package/dist/api/promocode.js +22 -0
- package/dist/api/push.d.ts +54 -0
- package/dist/api/push.js +99 -0
- package/dist/api/receipt.d.ts +34 -0
- package/dist/api/receipt.js +60 -0
- package/dist/api/stat.d.ts +21 -0
- package/dist/api/stat.js +75 -0
- package/dist/api/survey.d.ts +82 -0
- package/dist/api/survey.js +122 -0
- package/dist/api/user.d.ts +80 -0
- package/dist/api/user.js +167 -0
- package/dist/eventBus/abstract.d.ts +4 -0
- package/dist/eventBus/abstract.js +29 -0
- package/dist/eventBus/userLogin.d.ts +5 -0
- package/dist/eventBus/userLogin.js +11 -0
- package/dist/eventBus/userLogout.d.ts +4 -0
- package/dist/eventBus/userLogout.js +11 -0
- package/dist/http/apiError.d.ts +4 -0
- package/dist/http/apiError.js +10 -0
- package/dist/http/apiRoute.d.ts +98 -0
- package/dist/http/apiRoute.js +197 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +7 -0
- package/dist/interfaces/BannerType.d.ts +5 -0
- package/dist/interfaces/BannerType.js +7 -0
- package/dist/interfaces/apiStatEvents.d.ts +1 -0
- package/dist/interfaces/apiStatEvents.js +18 -0
- package/dist/interfaces/diplomaStatus.d.ts +8 -0
- package/dist/interfaces/diplomaStatus.js +9 -0
- package/dist/interfaces/iAppStore.d.ts +1 -0
- package/dist/interfaces/iAppStore.js +2 -0
- package/dist/interfaces/iAppVersionCheck.d.ts +5 -0
- package/dist/interfaces/iAppVersionCheck.js +2 -0
- package/dist/interfaces/iArticle.d.ts +15 -0
- package/dist/interfaces/iArticle.js +2 -0
- package/dist/interfaces/iBalance.d.ts +6 -0
- package/dist/interfaces/iBalance.js +2 -0
- package/dist/interfaces/iBank.d.ts +4 -0
- package/dist/interfaces/iBank.js +2 -0
- package/dist/interfaces/iBanner.d.ts +6 -0
- package/dist/interfaces/iBanner.js +2 -0
- package/dist/interfaces/iBookmark.d.ts +3 -0
- package/dist/interfaces/iBookmark.js +2 -0
- package/dist/interfaces/iBrand.d.ts +6 -0
- package/dist/interfaces/iBrand.js +2 -0
- package/dist/interfaces/iCatalog.d.ts +50 -0
- package/dist/interfaces/iCatalog.js +2 -0
- package/dist/interfaces/iCatalogNode.d.ts +3 -0
- package/dist/interfaces/iCatalogNode.js +2 -0
- package/dist/interfaces/iCatalogPreview.d.ts +17 -0
- package/dist/interfaces/iCatalogPreview.js +2 -0
- package/dist/interfaces/iCity.d.ts +4 -0
- package/dist/interfaces/iCity.js +2 -0
- package/dist/interfaces/iContentItem.d.ts +7 -0
- package/dist/interfaces/iContentItem.js +2 -0
- package/dist/interfaces/iEnv.d.ts +6 -0
- package/dist/interfaces/iEnv.js +2 -0
- package/dist/interfaces/iFilter.d.ts +11 -0
- package/dist/interfaces/iFilter.js +2 -0
- package/dist/interfaces/iGetNodeListProps.d.ts +8 -0
- package/dist/interfaces/iGetNodeListProps.js +2 -0
- package/dist/interfaces/iInstruction.d.ts +6 -0
- package/dist/interfaces/iInstruction.js +2 -0
- package/dist/interfaces/iIntro.d.ts +6 -0
- package/dist/interfaces/iIntro.js +2 -0
- package/dist/interfaces/iMessage.d.ts +25 -0
- package/dist/interfaces/iMessage.js +2 -0
- package/dist/interfaces/iNode.d.ts +26 -0
- package/dist/interfaces/iNode.js +2 -0
- package/dist/interfaces/iNodeTree.d.ts +14 -0
- package/dist/interfaces/iNodeTree.js +2 -0
- package/dist/interfaces/iPagingItems.d.ts +9 -0
- package/dist/interfaces/iPagingItems.js +2 -0
- package/dist/interfaces/iPayment.d.ts +20 -0
- package/dist/interfaces/iPayment.js +2 -0
- package/dist/interfaces/iPush.d.ts +14 -0
- package/dist/interfaces/iPush.js +2 -0
- package/dist/interfaces/iQuestion.d.ts +7 -0
- package/dist/interfaces/iQuestion.js +2 -0
- package/dist/interfaces/iReceipt.d.ts +20 -0
- package/dist/interfaces/iReceipt.js +2 -0
- package/dist/interfaces/iReceiptAddProps.d.ts +8 -0
- package/dist/interfaces/iReceiptAddProps.js +2 -0
- package/dist/interfaces/iReceiptProduct.d.ts +7 -0
- package/dist/interfaces/iReceiptProduct.js +2 -0
- package/dist/interfaces/iSearchParams.d.ts +11 -0
- package/dist/interfaces/iSearchParams.js +2 -0
- package/dist/interfaces/iShop.d.ts +6 -0
- package/dist/interfaces/iShop.js +2 -0
- package/dist/interfaces/iShopAddress.d.ts +5 -0
- package/dist/interfaces/iShopAddress.js +2 -0
- package/dist/interfaces/iSorter.d.ts +7 -0
- package/dist/interfaces/iSorter.js +2 -0
- package/dist/interfaces/iSpecialization.d.ts +4 -0
- package/dist/interfaces/iSpecialization.js +2 -0
- package/dist/interfaces/iStatView.d.ts +4 -0
- package/dist/interfaces/iStatView.js +2 -0
- package/dist/interfaces/iStorage.d.ts +5 -0
- package/dist/interfaces/iStorage.js +2 -0
- package/dist/interfaces/iStories.d.ts +13 -0
- package/dist/interfaces/iStories.js +2 -0
- package/dist/interfaces/iSubstance.d.ts +4 -0
- package/dist/interfaces/iSubstance.js +2 -0
- package/dist/interfaces/iSurvey.d.ts +36 -0
- package/dist/interfaces/iSurvey.js +2 -0
- package/dist/interfaces/iSurveyQuestion.d.ts +11 -0
- package/dist/interfaces/iSurveyQuestion.js +2 -0
- package/dist/interfaces/iSymptoms.d.ts +4 -0
- package/dist/interfaces/iSymptoms.js +2 -0
- package/dist/interfaces/iTestQuestion.d.ts +20 -0
- package/dist/interfaces/iTestQuestion.js +2 -0
- package/dist/interfaces/iTestResult.d.ts +17 -0
- package/dist/interfaces/iTestResult.js +2 -0
- package/dist/interfaces/iText.d.ts +3 -0
- package/dist/interfaces/iText.js +2 -0
- package/dist/interfaces/iUser.d.ts +35 -0
- package/dist/interfaces/iUser.js +2 -0
- package/dist/interfaces/iUserData.d.ts +10 -0
- package/dist/interfaces/iUserData.js +2 -0
- package/dist/interfaces/iUserEditProps.d.ts +20 -0
- package/dist/interfaces/iUserEditProps.js +2 -0
- package/dist/interfaces/iUserStat.d.ts +7 -0
- package/dist/interfaces/iUserStat.js +2 -0
- package/dist/interfaces/iUserSurvey.d.ts +21 -0
- package/dist/interfaces/iUserSurvey.js +11 -0
- package/dist/interfaces/iUserTokens.d.ts +4 -0
- package/dist/interfaces/iUserTokens.js +2 -0
- package/dist/interfaces/intRange.d.ts +3 -0
- package/dist/interfaces/intRange.js +2 -0
- package/dist/interfaces/itemType.d.ts +9 -0
- package/dist/interfaces/itemType.js +11 -0
- package/dist/interfaces/paymentStatus.d.ts +7 -0
- package/dist/interfaces/paymentStatus.js +9 -0
- package/dist/interfaces/paymentType.d.ts +5 -0
- package/dist/interfaces/paymentType.js +7 -0
- package/dist/interfaces/payoutType.d.ts +5 -0
- package/dist/interfaces/payoutType.js +7 -0
- package/dist/interfaces/pushStatus.d.ts +6 -0
- package/dist/interfaces/pushStatus.js +8 -0
- package/dist/interfaces/receiptStatus.d.ts +7 -0
- package/dist/interfaces/receiptStatus.js +9 -0
- package/dist/interfaces/testStatus.d.ts +6 -0
- package/dist/interfaces/testStatus.js +7 -0
- package/dist/interfaces/userRole.d.ts +6 -0
- package/dist/interfaces/userRole.js +14 -0
- package/dist/interfaces/userStatEvent.d.ts +5 -0
- package/dist/interfaces/userStatEvent.js +7 -0
- package/dist/interfaces/viewEventType.d.ts +13 -0
- package/dist/interfaces/viewEventType.js +19 -0
- package/dist/service/webSocketClient.d.ts +21 -0
- package/dist/service/webSocketClient.js +87 -0
- package/dist/storage/default.d.ts +2 -0
- package/dist/storage/default.js +8 -0
- package/dist/storage/user.d.ts +21 -0
- package/dist/storage/user.js +107 -0
- package/dist/utils/queryString.d.ts +3 -0
- package/dist/utils/queryString.js +21 -0
- package/package.json +31 -0
- package/src/api/abstract.ts +136 -0
- package/src/api/bookmarks.ts +109 -0
- package/src/api/chat.ts +127 -0
- package/src/api/content.ts +258 -0
- package/src/api/geoIp.ts +12 -0
- package/src/api/index.ts +38 -0
- package/src/api/payment.ts +105 -0
- package/src/api/promocode.ts +18 -0
- package/src/api/push.ts +102 -0
- package/src/api/stat.ts +74 -0
- package/src/api/survey.ts +164 -0
- package/src/api/user.ts +176 -0
- package/src/eventBus/abstract.ts +33 -0
- package/src/eventBus/userLogin.ts +13 -0
- package/src/eventBus/userLogout.ts +12 -0
- package/src/http/apiError.ts +9 -0
- package/src/http/apiRoute.ts +234 -0
- package/src/index.ts +2 -0
- package/src/interfaces/BannerType.ts +6 -0
- package/src/interfaces/apiStatEvents.ts +18 -0
- package/src/interfaces/diplomaStatus.ts +10 -0
- package/src/interfaces/iAppStore.ts +1 -0
- package/src/interfaces/iArticle.ts +12 -0
- package/src/interfaces/iBalance.ts +6 -0
- package/src/interfaces/iBank.ts +4 -0
- package/src/interfaces/iBanner.ts +6 -0
- package/src/interfaces/iBookmark.ts +3 -0
- package/src/interfaces/iCity.ts +4 -0
- package/src/interfaces/iContentItem.ts +6 -0
- package/src/interfaces/iEnv.ts +6 -0
- package/src/interfaces/iFilter.ts +16 -0
- package/src/interfaces/iGetNodeListProps.ts +9 -0
- package/src/interfaces/iInstruction.ts +6 -0
- package/src/interfaces/iIntro.ts +6 -0
- package/src/interfaces/iMessage.ts +25 -0
- package/src/interfaces/iNode.ts +24 -0
- package/src/interfaces/iNodeTree.ts +14 -0
- package/src/interfaces/iPagingItems.ts +8 -0
- package/src/interfaces/iPayment.ts +28 -0
- package/src/interfaces/iPush.ts +15 -0
- package/src/interfaces/iQuestion.ts +4 -0
- package/src/interfaces/iSearchParams.ts +12 -0
- package/src/interfaces/iSorter.ts +10 -0
- package/src/interfaces/iSpecialization.ts +4 -0
- package/src/interfaces/iStatView.ts +4 -0
- package/src/interfaces/iStorage.ts +5 -0
- package/src/interfaces/iStories.ts +10 -0
- package/src/interfaces/iSubstance.ts +4 -0
- package/src/interfaces/iSurvey.ts +38 -0
- package/src/interfaces/iSurveyQuestion.ts +15 -0
- package/src/interfaces/iSymptoms.ts +4 -0
- package/src/interfaces/iTestQuestion.ts +21 -0
- package/src/interfaces/iTestResult.ts +20 -0
- package/src/interfaces/iText.ts +3 -0
- package/src/interfaces/iUser.ts +37 -0
- package/src/interfaces/iUserData.ts +10 -0
- package/src/interfaces/iUserEditProps.ts +16 -0
- package/src/interfaces/iUserStat.ts +8 -0
- package/src/interfaces/iUserSurvey.ts +23 -0
- package/src/interfaces/iUserTokens.ts +4 -0
- package/src/interfaces/intRange.ts +5 -0
- package/src/interfaces/itemType.ts +10 -0
- package/src/interfaces/paymentStatus.ts +8 -0
- package/src/interfaces/paymentType.ts +6 -0
- package/src/interfaces/payoutType.ts +6 -0
- package/src/interfaces/pushStatus.ts +7 -0
- package/src/interfaces/testStatus.ts +8 -0
- package/src/interfaces/userRole.ts +13 -0
- package/src/interfaces/userStatEvent.ts +6 -0
- package/src/interfaces/viewEventType.ts +17 -0
- package/src/service/webSocketClient.ts +94 -0
- package/src/storage/default.ts +7 -0
- package/src/storage/user.ts +109 -0
- package/src/utils/queryString.ts +22 -0
- package/tsconfig.json +27 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
description:
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
# apcheki_sdk Package Overview
|
|
7
|
+
|
|
8
|
+
Этот npm пакет "@up-im/apcheki_sdk" установаться на frontend чтобы взаимодействовать с последней версией API backend
|
|
9
|
+
|
|
10
|
+
This rule describes the structure and usage of the `apcheki_sdk` npm package under the `apcheki_sdk` directory.
|
|
11
|
+
|
|
12
|
+
## Entry Point
|
|
13
|
+
|
|
14
|
+
- [src/api/index.ts](mdc:apcheki_sdk/src/api/index.ts): defines the `createClient` function
|
|
15
|
+
- Accepts configuration `{ host: string, wsHost: string, storage?: iStorage }`
|
|
16
|
+
- Returns API modules: `user`, `content`, `geoIp`, `receipt`, `payment`, `stat`, `chat`, `bookmarks`, `push`, `promocode`
|
|
17
|
+
|
|
18
|
+
## Storage
|
|
19
|
+
|
|
20
|
+
- Interface: [src/interfaces/iStorage.ts](mdc:apcheki_sdk/src/interfaces/iStorage.ts)
|
|
21
|
+
- Default implementation: [src/storage/default.ts](mdc:apcheki_sdk/src/storage/default.ts)
|
|
22
|
+
- To override storage, pass a custom object implementing `iStorage` to `createClient`
|
|
23
|
+
|
|
24
|
+
## API Modules
|
|
25
|
+
|
|
26
|
+
Each API class extends [src/api/abstract.ts](mdc:apcheki_sdk/src/api/abstract.ts) and uses `fetcher` for HTTP calls or WebSocket for `chat`.
|
|
27
|
+
|
|
28
|
+
- [src/api/user.ts](mdc:apcheki_sdk/src/api/user.ts): User authentication and profile endpoints
|
|
29
|
+
- [src/api/content.ts](mdc:apcheki_sdk/src/api/content.ts): Content retrieval and management
|
|
30
|
+
- [src/api/geoIp.ts](mdc:apcheki_sdk/src/api/geoIp.ts): Geo-IP lookup
|
|
31
|
+
- [src/api/receipt.ts](mdc:apcheki_sdk/src/api/receipt.ts): Receipt operations
|
|
32
|
+
- [src/api/payment.ts](mdc:apcheki_sdk/src/api/payment.ts): Payment processing
|
|
33
|
+
- [src/api/stat.ts](mdc:apcheki_sdk/src/api/stat.ts): Statistics endpoints
|
|
34
|
+
- [src/api/chat.ts](mdc:apcheki_sdk/src/api/chat.ts): WebSocket-based chat
|
|
35
|
+
- Handles authentication via token and message events
|
|
36
|
+
- [src/api/bookmarks.ts](mdc:apcheki_sdk/src/api/bookmarks.ts): Bookmark management
|
|
37
|
+
- [src/api/push.ts](mdc:apcheki_sdk/src/api/push.ts): Push notification registration
|
|
38
|
+
- [src/api/promocode.ts](mdc:apcheki_sdk/src/api/promocode.ts): Promo code validation and application
|
|
39
|
+
|
|
40
|
+
## Error Handling
|
|
41
|
+
|
|
42
|
+
- Uses `ApiError` from [src/http/apiError.ts](mdc:apcheki_sdk/src/http/apiError.ts) for consistent error responses
|
|
43
|
+
|
|
44
|
+
## Usage Example
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { createClient } from "apcheki_sdk"
|
|
48
|
+
|
|
49
|
+
const client = createClient({
|
|
50
|
+
host: "https://api.example.com",
|
|
51
|
+
wsHost: "wss://ws.example.com",
|
|
52
|
+
// optional: storage: customStorage
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// then use: client.user, client.chat, client.payment, etc.
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Notes
|
|
59
|
+
|
|
60
|
+
- WebSocket client lives in [src/service/webSocketClient.ts](mdc:apcheki_sdk/src/service/webSocketClient.ts)
|
|
61
|
+
- Keep API modules focused and DRY; add new endpoints by extending `ApiAbstract` and following existing patterns
|
|
62
|
+
|
|
63
|
+
## Package Update Process (команда "Опубликуй sdk")
|
|
64
|
+
|
|
65
|
+
!!! ВАЖНО при публикации новой версии SDK:
|
|
66
|
+
– Выполнять ТОЛЬКО пункты 1–5 этой инструкции, строго в указанном порядке
|
|
67
|
+
– Никаких дополнительных проверок, изменений, оптимизаций или предложений не выполнять
|
|
68
|
+
– Не добавлять, не удалять и не модифицировать шаги
|
|
69
|
+
|
|
70
|
+
1. Перейти в папку SDK:
|
|
71
|
+
```bash
|
|
72
|
+
cd /Users/oreen/MAMP/www/apcheki_sdk
|
|
73
|
+
```
|
|
74
|
+
2. Чтение и инкремент версии:
|
|
75
|
+
2.1. Прочитать текущее значение version из package.json → OLD_VERSION (например, 0.2.35)
|
|
76
|
+
2.2. Увеличить патч-номер: если версия формата X.Y.Z, то NEW_VERSION = X.Y.(Z+1) (например, 0.2.36)
|
|
77
|
+
2.3. Записать NEW_VERSION в поле version в package.json
|
|
78
|
+
3. Сборка и публикация:
|
|
79
|
+
```bash
|
|
80
|
+
npm i && npm run build && npm publish
|
|
81
|
+
git add . && git commit -m "<NEW_VERSION> <Краткое описание>"
|
|
82
|
+
```
|
|
83
|
+
4. Подготовка коммита
|
|
84
|
+
4.1. Собрать список изменённых файлов: git diff --cached --name-only
|
|
85
|
+
4.2 Проанализировать эти файлы и сформировать короткое однострочное описание важнейших изменений (например, «Добавлена поддержка X», «Исправлен баг Y», «Обновлены типы в Z»).
|
|
86
|
+
4.3 Сконструировать сообщение в формате: <NEW_VERSION> <Краткое описание>.
|
|
87
|
+
5. Создание коммита
|
|
88
|
+
```bash
|
|
89
|
+
git add . && git commit -m "<NEW_VERSION> <Краткое описание>"
|
|
90
|
+
```
|
package/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Medotvet SDK для React
|
|
2
|
+
|
|
3
|
+
Полноценный клиент для работы с backend из React/Next. Ниже перечислены
|
|
4
|
+
все методы из `src/api` и примеры интеграции.
|
|
5
|
+
|
|
6
|
+
## Установка
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
npm i @up-im/medotvet_sdk
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Инициализация клиента
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { createClient } from "@up-im/medotvet_sdk"
|
|
16
|
+
|
|
17
|
+
const client = createClient({
|
|
18
|
+
host: "https://api.example.com",
|
|
19
|
+
wsHost: "wss://ws.example.com",
|
|
20
|
+
// storage?: iStorage (опционально, по умолчанию localStorage)
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- Все запросы идут на `host/api/*` через `fetch` с `FormData`.
|
|
25
|
+
- Методы с `options.addToken` требуют авторизацию; refresh токен
|
|
26
|
+
обновляется aвтоматически.
|
|
27
|
+
- В ответах ошибки приходят как `ApiError(status, message)`.
|
|
28
|
+
|
|
29
|
+
## Модули и методы
|
|
30
|
+
|
|
31
|
+
### user
|
|
32
|
+
- `get()` — вернуть пользователя из localStorage без запроса на сервер.
|
|
33
|
+
- `getFull()` — получить профиль с backend; 401 без авторизации.
|
|
34
|
+
- `loginOrRegisterByPhone({ phone })` — старт регистрации/логина, шлёт SMS.
|
|
35
|
+
- `loginOrRegisterByPhoneConfirm({ phone, code })` — завершить вход,
|
|
36
|
+
сохранить токены, вернуть пользователя.
|
|
37
|
+
- `setRef({ ref })` — ввести реферальный код; требует токен.
|
|
38
|
+
- `editUser(data: iUserEditProps)` — обновить профиль; при смене email
|
|
39
|
+
может вернуть `false`, тогда повторить с `email_code`.
|
|
40
|
+
- `logout()` — локальный выход, чистит токены, шлёт событие logout.
|
|
41
|
+
- `logoutAllDevice()` — удаляет refresh на сервере, чистит локально,
|
|
42
|
+
рассылает logout.
|
|
43
|
+
- `onLogout` — подписка на событие выхода `client.user.onLogout(cb)`.
|
|
44
|
+
- `delete()` — удалить аккаунт и связанные сущности, затем logout.
|
|
45
|
+
- `getMyReferer()` — вернуть мой рефкод.
|
|
46
|
+
- `uploadDiploma(formData)` — отправить файлы `diploma[]`, ответ:
|
|
47
|
+
`{ success, diploma_files, diploma_status }`. Статусы экспортируются
|
|
48
|
+
как `DiplomaStatus` (числовые значения).
|
|
49
|
+
- `getDiplomaStatus()` — статус диплома (`DiplomaStatus`): 1 не
|
|
50
|
+
загружен, 2 проверка, 3 принят, 4 отклонён + `diploma_reject_reason`.
|
|
51
|
+
|
|
52
|
+
### content
|
|
53
|
+
- `getEnv()` — общие настройки/реферальные вознаграждения.
|
|
54
|
+
- `checkAppVersion({ appStore, appVersion })` — проверка актуальности
|
|
55
|
+
версии в сторе, ответ `{ isActual }`.
|
|
56
|
+
- `getCloudVersion(appStore)` — версия для обновления по воздуху (OTA).
|
|
57
|
+
- `getNodeTree(parent?)` — дерево категорий.
|
|
58
|
+
- `getArticleList({ select, page?, filters?, sorters?, perPage? })` —
|
|
59
|
+
статьи.
|
|
60
|
+
- `getArticleOne({ id })` — статья с полем `item`.
|
|
61
|
+
- `getPolicy()` / `getTerms()` / `getLoyalty()` / `getAgreement()` —
|
|
62
|
+
тексты.
|
|
63
|
+
- `getInstruction()` — шаги "Как получить деньги", до 100 элементов.
|
|
64
|
+
- `getBanks({ page, searchTitle? })` — банки для выплат.
|
|
65
|
+
- `getSpecializationList({ page, searchTitle? })` — справочник специализаций.
|
|
66
|
+
- `getCityList({ page, searchTitle? })` — города с пагинацией.
|
|
67
|
+
- `getCityOne({ id })` — один город.
|
|
68
|
+
- `getBannerRand({ type, signal? })` — баннер по типу (требует токен).
|
|
69
|
+
- `getStoriesList({ select, page?, perPage? })` — сторисы, sku сжаты в
|
|
70
|
+
`{ id, title }`.
|
|
71
|
+
- `getStoriesOne({ id })` — сторис с sku приведённым к `{ id, title }`.
|
|
72
|
+
- `getIntro()` — приветственные слайды с сортировкой.
|
|
73
|
+
|
|
74
|
+
### survey
|
|
75
|
+
- `getList({ page?, select?, bookmarks? })` — доступные опросы,
|
|
76
|
+
сортировка по приоритету.
|
|
77
|
+
- `getBookmarks({ page?, select? })` — избранные опросы, 401 без
|
|
78
|
+
авторизации.
|
|
79
|
+
- `getOne({ id })` — опрос с вопросами.
|
|
80
|
+
- `start(surveyId, signal?)` — начать прохождение, ответ
|
|
81
|
+
`{ success, userSurvey }`.
|
|
82
|
+
- `saveAnswer({ userSurveyId, questionIndex, answer, signal? })` —
|
|
83
|
+
сохранить ответ, возвращает `{ completed, next_question_index,
|
|
84
|
+
message }`.
|
|
85
|
+
- `cancel(userSurveyId, signal?)` — отменить прохождение.
|
|
86
|
+
- `getHistory({ page? })` — история прохождений.
|
|
87
|
+
|
|
88
|
+
### payment
|
|
89
|
+
- `addSBP({ sum, bank })` — заявка на выплату через СБП, вернёт
|
|
90
|
+
`iPayment`.
|
|
91
|
+
- `addCard({ sum, card_number })` — заявка на карту, вернёт `iPayment`.
|
|
92
|
+
- `getList({ page?, select })` — список выплат, сортировка `id desc`.
|
|
93
|
+
- `balance()` — баланс и суммы начислений/выплат.
|
|
94
|
+
- `getVerificationUrl()` — ссылка на KYC SolarStaff и признак `verified`.
|
|
95
|
+
- `checkVerificationStatus()` — статус KYC:
|
|
96
|
+
`not_started|pending|active|blocked` + текст.
|
|
97
|
+
|
|
98
|
+
### stat
|
|
99
|
+
- `add({ itemId, event })` — записать событие просмотра/квиза/
|
|
100
|
+
презентации; для CATALOG_SKU + PRESENTATION_SUCCESS|QUESTIONS_SUCCESS
|
|
101
|
+
пишет и начисления.
|
|
102
|
+
- `getEvent({ sku: number[] })` — получить события пользователя по акциям.
|
|
103
|
+
|
|
104
|
+
### chat (WebSocket)
|
|
105
|
+
- Подключается к `wsHost`, авторизует token при `onOpen`.
|
|
106
|
+
- `messageSubscribe(cb)` — подписка на входящие сообщения массивами;
|
|
107
|
+
вернёт функцию отписки. История последних 10 пачек приходит сразу.
|
|
108
|
+
- `sendMessage({ text, file? })` — отправка текста/файла (конвертируется
|
|
109
|
+
в base64). Доступно только пользователю с `role === 0`.
|
|
110
|
+
- `sendView({ id })` — отметить сообщение прочитанным.
|
|
111
|
+
- `getUnread()` — количество непрочитанных через HTTP.
|
|
112
|
+
- `getMessages({ page })` — запросить сообщения по страницам через WS.
|
|
113
|
+
- `disconnect()` — закрыть WebSocket вручную.
|
|
114
|
+
|
|
115
|
+
### bookmarks
|
|
116
|
+
- `inBookmarks({ skuId })` — проверить избранное. Дебаунсит запросы,
|
|
117
|
+
требует токен.
|
|
118
|
+
- `mutate({ skuId, isAdd })` — добавить/убрать из избранного и обновить
|
|
119
|
+
кэш.
|
|
120
|
+
- `getTotal()` — общее число избранных или `null`, использует кеш.
|
|
121
|
+
|
|
122
|
+
### push
|
|
123
|
+
- `getList({ page?, filters?, select })` — список пушей, сортировка
|
|
124
|
+
`id desc`.
|
|
125
|
+
- `countNew()` — количество непрочитанных.
|
|
126
|
+
- `view({ pushId })` — отметить один пуш прочитанным.
|
|
127
|
+
- `viewAll()` — отметить все пуши прочитанными.
|
|
128
|
+
- `register({ token, appStore })` — зарегистрировать push-токен.
|
|
129
|
+
- `unsubscribe()` — отписаться от пушей.
|
|
130
|
+
- `isSubscribed()` — признак активной подписки.
|
|
131
|
+
|
|
132
|
+
### promocode
|
|
133
|
+
- `activate(code)` — активировать промокод, ответ `{ sum }`; требует токен.
|
|
134
|
+
|
|
135
|
+
### geoIp
|
|
136
|
+
- `detect()` — определить город по IP.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { UserStorage } from "../storage/user";
|
|
2
|
+
export declare class ApiAbstract {
|
|
3
|
+
protected host: string;
|
|
4
|
+
protected userStorage: UserStorage;
|
|
5
|
+
private static isTokenUpdating;
|
|
6
|
+
constructor({ host, userStorage }: {
|
|
7
|
+
host: string;
|
|
8
|
+
userStorage: UserStorage;
|
|
9
|
+
});
|
|
10
|
+
protected fetcher<TResponse>({ route, postBody, options }: {
|
|
11
|
+
route: string;
|
|
12
|
+
postBody?: {
|
|
13
|
+
[key: string]: any;
|
|
14
|
+
} | null;
|
|
15
|
+
options?: RequestInit & {
|
|
16
|
+
noConsoleError?: boolean;
|
|
17
|
+
addToken?: boolean;
|
|
18
|
+
};
|
|
19
|
+
}): Promise<TResponse>;
|
|
20
|
+
protected getToken(): Promise<string | null>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiAbstract = void 0;
|
|
4
|
+
const userLogout_1 = require("../eventBus/userLogout");
|
|
5
|
+
const apiError_1 = require("../http/apiError");
|
|
6
|
+
const apiRoute_1 = require("../http/apiRoute");
|
|
7
|
+
class ApiAbstract {
|
|
8
|
+
constructor({ host, userStorage }) {
|
|
9
|
+
this.host = host;
|
|
10
|
+
this.userStorage = userStorage;
|
|
11
|
+
}
|
|
12
|
+
async fetcher({ route, postBody = null, options }) {
|
|
13
|
+
const formData = new FormData();
|
|
14
|
+
if (postBody) {
|
|
15
|
+
for (let key in postBody) {
|
|
16
|
+
if (postBody[key] instanceof FileList) {
|
|
17
|
+
for (const value of postBody[key]) {
|
|
18
|
+
formData.append(key + '[]', value);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
else if (Array.isArray(postBody[key])) {
|
|
22
|
+
for (const value of postBody[key]) {
|
|
23
|
+
if (value !== null && typeof value == "object") {
|
|
24
|
+
formData.append(key + '[]', JSON.stringify(value));
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
formData.append(key + '[]', value);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else if (typeof postBody[key] == "object") {
|
|
32
|
+
formData.append(key, JSON.stringify(postBody[key]));
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
formData.append(key, postBody[key]);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const headers = {};
|
|
40
|
+
if (options?.addToken) {
|
|
41
|
+
const token = await this.getToken();
|
|
42
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
43
|
+
}
|
|
44
|
+
else if (route.startsWith('/user') && !!postBody) {
|
|
45
|
+
headers["timestamp"] = Date.now().toString();
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const res = await fetch(this.host + "/api" + route, {
|
|
49
|
+
headers: headers,
|
|
50
|
+
method: postBody ? "POST" : "GET",
|
|
51
|
+
body: postBody ? formData : null,
|
|
52
|
+
credentials: "include",
|
|
53
|
+
...options
|
|
54
|
+
});
|
|
55
|
+
if (!res.ok) {
|
|
56
|
+
if (res.status == 413)
|
|
57
|
+
throw new apiError_1.ApiError(res.status, "Слишком большой размер файла");
|
|
58
|
+
if (res.status == 401) {
|
|
59
|
+
await this.userStorage.clearUser();
|
|
60
|
+
await userLogout_1.eventBusUserLogout.broadcast();
|
|
61
|
+
}
|
|
62
|
+
if (res.status == 404 && !postBody) {
|
|
63
|
+
if (!options?.noConsoleError)
|
|
64
|
+
console.warn(`not_found: ${this.host + "/api" + route}`);
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
//пробуем расшифровать json с ошибкой
|
|
68
|
+
const answer = await res.json();
|
|
69
|
+
const error = new apiError_1.ApiError(res.status, answer.message);
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
//ошибка расшифровки json
|
|
74
|
+
if (!options?.noConsoleError)
|
|
75
|
+
console.warn({ url: this.host + "/api" + route });
|
|
76
|
+
if (!(error instanceof apiError_1.ApiError))
|
|
77
|
+
throw new apiError_1.ApiError(res.status, res.statusText);
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return res.json();
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (error instanceof Error && error.message.toLowerCase().includes("fail"))
|
|
85
|
+
throw new apiError_1.ApiError(0, "Нет соединения с интернетом");
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async getToken() {
|
|
90
|
+
const accessToken = await this.userStorage.getAccessToken();
|
|
91
|
+
if (accessToken)
|
|
92
|
+
return accessToken;
|
|
93
|
+
const refreshToken = await this.userStorage.getRefreshToken();
|
|
94
|
+
if (refreshToken) {
|
|
95
|
+
//перевыпуск пары токенов
|
|
96
|
+
if (ApiAbstract.isTokenUpdating) { //дедубликация запросов на обновление токена
|
|
97
|
+
await new Promise(r => setTimeout(r, 100)); //sleep
|
|
98
|
+
return await this.getToken();
|
|
99
|
+
}
|
|
100
|
+
ApiAbstract.isTokenUpdating = true;
|
|
101
|
+
try {
|
|
102
|
+
const data = await this.fetcher({
|
|
103
|
+
route: apiRoute_1.apiRouteUserRefresh,
|
|
104
|
+
postBody: { refreshToken: refreshToken }
|
|
105
|
+
});
|
|
106
|
+
await this.userStorage.setUser(data.accessToken, data.refreshToken);
|
|
107
|
+
ApiAbstract.isTokenUpdating = false;
|
|
108
|
+
return data.accessToken;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.error(error);
|
|
112
|
+
if (error instanceof apiError_1.ApiError) {
|
|
113
|
+
if (error.status === 404) { //токен не найден
|
|
114
|
+
await this.userStorage.clearUser();
|
|
115
|
+
await userLogout_1.eventBusUserLogout.broadcast();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
ApiAbstract.isTokenUpdating = false;
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
exports.ApiAbstract = ApiAbstract;
|
|
125
|
+
ApiAbstract.isTokenUpdating = false;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ApiAbstract } from "./abstract";
|
|
2
|
+
export declare class ApiBookmarks extends ApiAbstract {
|
|
3
|
+
private cache;
|
|
4
|
+
private timeout;
|
|
5
|
+
private requestKeys;
|
|
6
|
+
private total;
|
|
7
|
+
/**
|
|
8
|
+
* принимает id акции (не товара) который находится в поле id метода возвращаемых товаров getCatalogList. В методе есть дебаунсер, что позволяет его вызвать для каждого товара на странице сделав только 1 запрос на сервер
|
|
9
|
+
* @param {number} props.sku - id акции (не товара)
|
|
10
|
+
*/
|
|
11
|
+
inBookmarks({ skuId }: {
|
|
12
|
+
skuId: number;
|
|
13
|
+
}): Promise<boolean>;
|
|
14
|
+
private collectKeys;
|
|
15
|
+
/**
|
|
16
|
+
* добавление \ удаление из избранного
|
|
17
|
+
* @param {number} props.sku - id акции (не товара)
|
|
18
|
+
* @param {UserStatEvent} props.isAdd - признак добавление или удаление
|
|
19
|
+
*/
|
|
20
|
+
mutate({ skuId, isAdd }: {
|
|
21
|
+
skuId: number;
|
|
22
|
+
isAdd: boolean;
|
|
23
|
+
}): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* возвращает кол-во товаров в избранном или null в случае ошибки
|
|
26
|
+
*/
|
|
27
|
+
getTotal(): Promise<number | null>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiBookmarks = void 0;
|
|
4
|
+
const abstract_1 = require("./abstract");
|
|
5
|
+
const apiRoute_1 = require("../http/apiRoute");
|
|
6
|
+
const itemType_1 = require("../interfaces/itemType");
|
|
7
|
+
const apiError_1 = require("../http/apiError");
|
|
8
|
+
class ApiBookmarks extends abstract_1.ApiAbstract {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
this.cache = new Map(); //false - если данные не получены с сервера по ключу
|
|
12
|
+
this.timeout = undefined;
|
|
13
|
+
this.requestKeys = new Set();
|
|
14
|
+
this.total = null;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* принимает id акции (не товара) который находится в поле id метода возвращаемых товаров getCatalogList. В методе есть дебаунсер, что позволяет его вызвать для каждого товара на странице сделав только 1 запрос на сервер
|
|
18
|
+
* @param {number} props.sku - id акции (не товара)
|
|
19
|
+
*/
|
|
20
|
+
async inBookmarks({ skuId }) {
|
|
21
|
+
if (!skuId || skuId <= 0)
|
|
22
|
+
return false;
|
|
23
|
+
if (!await this.userStorage.isAuth())
|
|
24
|
+
return false;
|
|
25
|
+
const key = `${itemType_1.ItemType.CATALOG_SKU}-${skuId}`;
|
|
26
|
+
return await this.collectKeys(key);
|
|
27
|
+
}
|
|
28
|
+
async collectKeys(key) {
|
|
29
|
+
//has cache
|
|
30
|
+
if (this.cache.has(key)) {
|
|
31
|
+
const val = this.cache.get(key);
|
|
32
|
+
if (val !== false)
|
|
33
|
+
return true;
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
//no cache
|
|
37
|
+
//собираем включи для 1 запроса со всех вызовов
|
|
38
|
+
if (!this.requestKeys.has(key)) {
|
|
39
|
+
if (this.timeout)
|
|
40
|
+
clearTimeout(this.timeout);
|
|
41
|
+
this.requestKeys.add(key);
|
|
42
|
+
this.timeout = setTimeout(async () => {
|
|
43
|
+
if (!this.requestKeys.size)
|
|
44
|
+
return;
|
|
45
|
+
//все компоненты отрендерены, ключи все запрошены, можно выполнять запрос
|
|
46
|
+
try {
|
|
47
|
+
const arrFromRequestKeys = Array.from(this.requestKeys);
|
|
48
|
+
const data = await this.fetcher({
|
|
49
|
+
route: apiRoute_1.apiRouteBookmarksGet,
|
|
50
|
+
postBody: { itemKeys: arrFromRequestKeys },
|
|
51
|
+
options: { addToken: true }
|
|
52
|
+
});
|
|
53
|
+
for (const requestKey of arrFromRequestKeys) {
|
|
54
|
+
const find = data.find(it => it.item_key == requestKey);
|
|
55
|
+
this.cache.set(requestKey, find?.item_key || false);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
this.cache.set(key, false);
|
|
60
|
+
console.error(error);
|
|
61
|
+
}
|
|
62
|
+
this.requestKeys.clear(); //очистка очереди запросов
|
|
63
|
+
}, 200);
|
|
64
|
+
}
|
|
65
|
+
//ждем последнего запроса
|
|
66
|
+
await new Promise(r => setTimeout(r, 300)); //sleep
|
|
67
|
+
return await this.collectKeys(key); //на следующем крузе вернется результат из кэша
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* добавление \ удаление из избранного
|
|
71
|
+
* @param {number} props.sku - id акции (не товара)
|
|
72
|
+
* @param {UserStatEvent} props.isAdd - признак добавление или удаление
|
|
73
|
+
*/
|
|
74
|
+
async mutate({ skuId, isAdd }) {
|
|
75
|
+
if (!skuId || skuId <= 0)
|
|
76
|
+
return;
|
|
77
|
+
if (!await this.userStorage.isAuth())
|
|
78
|
+
throw new apiError_1.ApiError(401, "Пользователь не авторизован");
|
|
79
|
+
try {
|
|
80
|
+
await this.fetcher({
|
|
81
|
+
route: isAdd
|
|
82
|
+
? apiRoute_1.apiRouteBookmarksAdd
|
|
83
|
+
: apiRoute_1.apiRouteBookmarksRemove,
|
|
84
|
+
postBody: {
|
|
85
|
+
itemType: itemType_1.ItemType.CATALOG_SKU,
|
|
86
|
+
itemId: skuId
|
|
87
|
+
},
|
|
88
|
+
options: {
|
|
89
|
+
addToken: true
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.error(error);
|
|
95
|
+
}
|
|
96
|
+
const key = `${itemType_1.ItemType.CATALOG_SKU}-${skuId}`;
|
|
97
|
+
this.cache.set(key, isAdd ? key : false);
|
|
98
|
+
this.total = (this.total ?? 0) + (isAdd ? 1 : -1);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* возвращает кол-во товаров в избранном или null в случае ошибки
|
|
102
|
+
*/
|
|
103
|
+
async getTotal() {
|
|
104
|
+
if (this.total !== null)
|
|
105
|
+
return this.total;
|
|
106
|
+
if (!await this.userStorage.isAuth())
|
|
107
|
+
return null;
|
|
108
|
+
try {
|
|
109
|
+
const total = await this.fetcher({
|
|
110
|
+
route: apiRoute_1.apiRouteBookmarksCount,
|
|
111
|
+
options: { addToken: true }
|
|
112
|
+
});
|
|
113
|
+
this.total = total;
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.error(error);
|
|
117
|
+
}
|
|
118
|
+
return this.total;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
exports.ApiBookmarks = ApiBookmarks;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { iMessage } from "../interfaces/iMessage";
|
|
2
|
+
import { ApiAbstract } from "./abstract";
|
|
3
|
+
import { UserStorage } from "../storage/user";
|
|
4
|
+
export declare class ApiChat extends ApiAbstract {
|
|
5
|
+
private client;
|
|
6
|
+
private messageHistory;
|
|
7
|
+
private messageSubscriptions;
|
|
8
|
+
constructor({ host, wsHost, userStorage }: {
|
|
9
|
+
host: string;
|
|
10
|
+
wsHost: string;
|
|
11
|
+
userStorage: UserStorage;
|
|
12
|
+
});
|
|
13
|
+
private auth;
|
|
14
|
+
messageSubscribe(callback: (messages: iMessage[]) => void): () => void;
|
|
15
|
+
sendMessage({ text, file }: {
|
|
16
|
+
text: string;
|
|
17
|
+
file?: FileList | File | null;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
sendView({ id }: {
|
|
20
|
+
id: number;
|
|
21
|
+
}): void;
|
|
22
|
+
/**
|
|
23
|
+
* Получить количество непрочитанных сообщений через обычное API
|
|
24
|
+
*/
|
|
25
|
+
getUnread(): Promise<number>;
|
|
26
|
+
getMessages({ page }: {
|
|
27
|
+
page: number;
|
|
28
|
+
}): void;
|
|
29
|
+
disconnect(): void;
|
|
30
|
+
}
|
package/dist/api/chat.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiChat = void 0;
|
|
4
|
+
const abstract_1 = require("./abstract");
|
|
5
|
+
const webSocketClient_1 = require("../service/webSocketClient");
|
|
6
|
+
const apiError_1 = require("../http/apiError");
|
|
7
|
+
const userLogout_1 = require("../eventBus/userLogout");
|
|
8
|
+
const apiRoute_1 = require("../http/apiRoute");
|
|
9
|
+
//import { eventBusUserLogin } from "../eventBus/userLogin"
|
|
10
|
+
class ApiChat extends abstract_1.ApiAbstract {
|
|
11
|
+
constructor({ host, wsHost, userStorage }) {
|
|
12
|
+
super({ host, userStorage });
|
|
13
|
+
this.messageHistory = [];
|
|
14
|
+
this.messageSubscriptions = new Set();
|
|
15
|
+
this.client = new webSocketClient_1.WebSocketClient(wsHost);
|
|
16
|
+
this.client.onOpen(async () => await this.auth());
|
|
17
|
+
this.client.onMessage(message => {
|
|
18
|
+
//prepare
|
|
19
|
+
const data = JSON.parse(message);
|
|
20
|
+
if (!Array.isArray(data)) {
|
|
21
|
+
console.error('Входящее сообщения должны быть массивом', data);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
for (const item of data) {
|
|
25
|
+
if ("date" in item)
|
|
26
|
+
item.date = new Date(item.date);
|
|
27
|
+
}
|
|
28
|
+
//broadcast
|
|
29
|
+
for (const callback of Array.from(this.messageSubscriptions)) {
|
|
30
|
+
callback(data);
|
|
31
|
+
}
|
|
32
|
+
//Последние 10 групп сообщений с сервера для новых подписчиков
|
|
33
|
+
this.messageHistory.push(data);
|
|
34
|
+
if (this.messageHistory.length > 10) {
|
|
35
|
+
this.messageHistory.splice(0, this.messageHistory.length - 10);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
// eventBusUserLogin.subscribe(async () => this.client.connect())
|
|
39
|
+
// this.userStorage.isAuth().then(isAuth => {
|
|
40
|
+
// if (isAuth) this.client.connect()
|
|
41
|
+
// })
|
|
42
|
+
userLogout_1.eventBusUserLogout.subscribe(async () => this.client.close());
|
|
43
|
+
}
|
|
44
|
+
async auth() {
|
|
45
|
+
const token = await this.getToken();
|
|
46
|
+
if (!token) {
|
|
47
|
+
console.error("User token for WebSocket empty");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
this.client.send(JSON.stringify({ token }), true);
|
|
51
|
+
}
|
|
52
|
+
messageSubscribe(callback) {
|
|
53
|
+
this.messageSubscriptions.add(callback);
|
|
54
|
+
//Последние 10 групп сообщений с сервера для новых подписчиков
|
|
55
|
+
for (const history of this.messageHistory)
|
|
56
|
+
callback(history);
|
|
57
|
+
return () => { this.messageSubscriptions.delete(callback); };
|
|
58
|
+
}
|
|
59
|
+
async sendMessage({ text, file }) {
|
|
60
|
+
const user = await this.userStorage?.getUser();
|
|
61
|
+
if (!user)
|
|
62
|
+
throw new apiError_1.ApiError(401, "Пользователь не авторизован");
|
|
63
|
+
if (user.role !== 0)
|
|
64
|
+
throw new apiError_1.ApiError(400, "Для тестирования чата авторизуйтесь под обычного пользователя");
|
|
65
|
+
const convertToBase64 = (file) => {
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
const reader = new FileReader();
|
|
68
|
+
reader.onload = () => resolve(reader.result);
|
|
69
|
+
reader.onerror = reject;
|
|
70
|
+
reader.readAsDataURL(file);
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
const firstFile = file instanceof FileList
|
|
74
|
+
? Array.from(file)?.pop()
|
|
75
|
+
: file;
|
|
76
|
+
const message = {
|
|
77
|
+
route: "/message",
|
|
78
|
+
text,
|
|
79
|
+
file: firstFile ? await convertToBase64(firstFile) : undefined
|
|
80
|
+
};
|
|
81
|
+
this.client.send(JSON.stringify(message));
|
|
82
|
+
}
|
|
83
|
+
sendView({ id }) {
|
|
84
|
+
const message = {
|
|
85
|
+
route: "/view",
|
|
86
|
+
message_id: id
|
|
87
|
+
};
|
|
88
|
+
this.client.send(JSON.stringify(message));
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Получить количество непрочитанных сообщений через обычное API
|
|
92
|
+
*/
|
|
93
|
+
async getUnread() {
|
|
94
|
+
if (!await this.userStorage.isAuth())
|
|
95
|
+
throw new apiError_1.ApiError(401, "Пользователь не авторизован");
|
|
96
|
+
const data = await this.fetcher({
|
|
97
|
+
route: apiRoute_1.apiRouteChatUnread,
|
|
98
|
+
options: { addToken: true }
|
|
99
|
+
});
|
|
100
|
+
return data.unread;
|
|
101
|
+
}
|
|
102
|
+
// getDialogs({page}:{page: number}) {//оставим для оптимизации если диалогов будет много
|
|
103
|
+
// this.client.send(JSON.stringify({
|
|
104
|
+
// route: "/get/dialogs",
|
|
105
|
+
// page,
|
|
106
|
+
// }))
|
|
107
|
+
// }
|
|
108
|
+
getMessages({ page }) {
|
|
109
|
+
this.client.send(JSON.stringify({
|
|
110
|
+
route: "/get/messages",
|
|
111
|
+
page,
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
114
|
+
disconnect() {
|
|
115
|
+
this.client.close();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
exports.ApiChat = ApiChat;
|