Skip to content

Работа с данными

saasApi клиент

Все HTTP-запросы к saas-api проходят через единый синглтон saasApi (src/features/saas-api/client.ts).

Особенности клиента

  • JWT-токены хранятся в expo-secure-store
  • Автоматический refresh токена за 5 минут до истечения
  • Retry логика: при 401 — refresh токена и повтор запроса
  • Таймаут: 30 секунд (обычные запросы), 120 секунд (upload)
  • Заголовок x-request-id на каждом запросе

API-группы

ГруппаМетоды
AuthsignIn, signUp, getMe, signOut, forgotPassword, resetPassword, verifyCode, getGoogleAuthUrl, handleOAuthCallback
CompaniesgetCompanies, createCompany, updateCompany, deleteCompany, getCompanyUsers, sendInvitation, getAccessTokens
AssistantsgetAssistants, getAssistant, createAssistant, updateAssistant, deleteAssistant, duplicateAssistant, applyTemplate
KnowledgegetKnowledgeItems, createKnowledgeItem, updateKnowledgeItem, deleteKnowledgeItem
ToolsgetAssistantTools, createAssistantTool, updateAssistantTool, deleteAssistantTool
FoldersgetFolders, createFolder, updateFolder, deleteFolder
ChatsgetChats, getChat, toggleAiControl, getMessages, createMessage, deleteMessage
PhonesgetPhones, createPhone, deletePhone, attachPhone, detachPhone
IntegrationsgetIntegrations, connectIntegration, Telegram (QR/code), Instagram/Messenger OAuth, WhatsApp, Viber, ElevenLabs, Google Sheets
BillinggetTariffs, createSubscription, createPayment, setTariff, cancelSubscription
FilesuploadFile (FormData, 120s timeout)

Обработка ошибок

  • Сервисный слой возвращает null при ошибке (не бросает исключения)
  • 401: автоматический refresh + повторный запрос; при повторном 401 — принудительный логаут
  • 403: помечается isForbidden: true
  • Try-catch только для HTTP-запросов и операций сохранения

WebSocket (socket.io)

Подключение

WebSocket клиент (src/features/chat/websocket/WebSocketClient.ts) — синглтон.

ПараметрЗначение
URLEXPO_PUBLIC_WS_URL
Path/ws
Transportwebsocket only
Authtoken + companyId (headers + query)
Reconnectauto, exponential backoff (1s → 10s)

Жизненный цикл

  1. connect(companyId) — подключение с контекстом компании
  2. Автоматическое присоединение к комнате компании
  3. joinChat(chatId) — вход в комнату чата
  4. Получение событий → обновление Zustand stores
  5. leaveChat(chatId) — выход из комнаты чата
  6. disconnect() — при смене компании или логауте

Оптимизация батареи

  • WebSocket отключается при уходе приложения в фон
  • Автоматическое переподключение при возврате в foreground

События

Отправляемые (клиент → сервер):

СобытиеОписание
chat:joinВход в комнату чата
chat:leaveВыход из комнаты чата
typing:startНачало набора
typing:stopКонец набора

Получаемые (сервер → клиент):

СобытиеPayload
message:new{ message: Message }
message:updated{ message: Message }
message:deleted{ messageId, chatId }
chat:updated{ chat: Chat }
typing:start{ chatId, userId }
typing:stop{ chatId, userId }
telegram:qr-updated{ integrationId, qrCodeUrl }
telegram:qr-needs-2fa{ integrationId }
telegram:qr-completed{ integrationId }

Паттерн query + mutation

typescript
// Запрос данных
const { data, isLoading } = useQuery({
  queryKey: ['chats', companyId],
  queryFn: () => saasApi.getChats({ companyId }),
  enabled: !!companyId,
});

// Мутация с инвалидацией
const toggleAi = useMutation({
  mutationFn: ({ chatId, enabled }) =>
    saasApi.toggleAiControl(chatId, enabled),
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['chats'] });
  },
});