iac/apps/documentations/frontend.ENDPOINTS.md

225 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Эндпоинты, с которыми взаимодействует documentation-frontend
Документ описывает все HTTP-эндпоинты внешних сервисов, к которым обращается модуль (микрофронтенд `documentation-frontend`, образ `documentation-frontend-app`, деплой `frontend`). Модуль публикуется как remote для Module Federation (`webpack.config.js`, имя `srx_documentations`).
## Как устроено взаимодействие
Все запросы описаны декларативно в реестре `module/api/endpoints.ts` (объект `endpoints`). Каждый эндпоинт задаётся структурой `Endpoint`:
- `service` — логическое имя сервиса (см. таблицу хостов ниже);
- `method` — HTTP-метод (`GET`/`POST`/`PUT`/`PATCH`/`DELETE`);
- `path(args)` — функция, возвращающая путь запроса (с подстановкой параметров/query);
- `body(args)` — опционально, формирование тела запроса;
- `responseType` — опционально, тип ответа (напр. `blob`);
- `accessToken(args)` — опционально, явная передача access-токена в заголовки;
- `cache`, `queryOptions` — опции кеширования/повторов;
- `showErrorNotification` — показывать ли уведомление об ошибке (по умолчанию `true`).
Запрос выполняется единой функцией `fetch(endpoint, params, controller)` (`module/api/endpoints.ts`), которая через `httpService` (`module/api/http-service.ts`, обёртка `createHttpService` из `@sarex-team/sdk-js` поверх `axios`) отправляет запрос на базовый хост сервиса. Базовый хост выбирается по паре «`service` + окружение»: `httpService` создаётся с картой хостов `apiHosts` и текущим `buildEnv`, и разрешает хост внутри себя. Тот же алгоритм продублирован в экспортируемом хелпере `resolveHost(service)` из `module/api/hosts.ts`. Итоговый URL = `<базовый хост сервиса>` + `path` эндпоинта.
Окружение определяется глобальной константой `BUILD_ENV`, которую webpack подставляет в бандл через `DefinePlugin` (`webpack.config.js`) из переменной сборки `process.env.BUILD_ENV`. Допустимые значения проверяются в `env.js`: `local`/`stage`/`preprod`/`prod`/`contour`. В режиме `local` тип http-сервиса переключается на `"original"` (`module/api/http-service.ts`).
Ошибки маппируются в человекочитаемые сообщения в `module/api/errors.ts` (`resolveNetworkErrorByCode`, `resolveNetworkError`).
## Базовые хосты по сервисам и окружениям
Значения из `module/api/hosts.ts` (объект `apiHosts`). Итоговый URL = `<базовый хост сервиса>` + `path` эндпоинта.
| Сервис (`service`) | Назначение | `local` | `stage` | `preprod` | `prod` | `contour` |
| --- | --- | --- | --- | --- | --- | --- |
| `sarex` | Локальный сервис данных (`/api/core`, `/api/client`) | `/sarex-backend` | `/` | `/` | `/` | `/` |
| `documentations` | Сервис документации (документы, бандлы, файлы) | `https://stage-api.sarex.io/documentations` | `https://stage-api.sarex.io/documentations` | `https://api.preprod.sarex.io/documentations` | `https://api.sarex.io/documentations` | `/documentations` |
| `sarexApi` | Gateway/API Sarex (`/gateway`, `/eav`, `/cde`, `/transmittals`, `/flows`, `/issues`) | `https://stage-api.sarex.io` | `https://stage-api.sarex.io` | `https://api.preprod.sarex.io` | `https://api.sarex.io` | `/` |
| `workspaces` | Сервис рабочих областей | `https://stage-api.sarex.io/workspaces` | `https://stage-api.sarex.io/workspaces` | `https://api.preprod.sarex.io/workspaces` | `https://api.sarex.io/workspaces` | `/workspaces` |
| `workflows` | Сервис обработки документов | `https://stage-api.sarex.io/workflows` | `https://stage-api.sarex.io/workflows` | `https://api.preprod.sarex.io/workflows` | `https://api.sarex.io/workflows` | `/workflows` |
| `processes` | Сервис рабочих процессов (flows, reviews) | `https://stage-api.sarex.io/flows` | `https://stage-api.sarex.io/flows` | `https://api.preprod.sarex.io/flows` | `https://api.sarex.io/flows` | `/flows` |
| `remarks` | Сервис замечаний | `https://stage-api.sarex.io/remarks` | `https://stage-api.sarex.io/remarks` | `https://api.preprod.sarex.io/remarks` | `https://api.sarex.io/remarks` | `/remarks` |
| `files` | Сервис файлов | `https://stage-api.sarex.io/files` | `https://stage-api.sarex.io/files` | `https://api.preprod.sarex.io/files` | `https://api.sarex.io/files` | `/files` |
| `google` | Временное хранилище (GCS) | `https://storage.googleapis.com/srx-tmp` | `https://storage.googleapis.com/srx-tmp` | `https://storage.googleapis.com/srx-tmp` | `https://storage.googleapis.com/srx-tmp` | `https://storage.googleapis.com/srx-tmp` |
| `bim` | BIM-API | `https://stage-bim-api.sarex.io` | `https://stage-bim-api.sarex.io` | `https://bim-api.preprod.sarex.io` | `https://bim-api.sarex.io` | `""` |
| `zitadel` | IdP (аутентификация) | `https://idp.dev.stage.sarex.io` | `https://idp.dev.stage.sarex.io` | `https://login.preprod.sarex.io` | `https://login.sarex.io` | `""` |
> Хосты `google`, `bim` и `zitadel` заданы в карте хостов, но напрямую в реестре `endpoints` не используются — они задействованы через SDK/вьюер (`@sarex-team/sdk-js`) и механизм аутентификации. В окружении `local` сервис `sarex` проксируется на `/sarex-backend`, в `stage`/`preprod`/`prod` — на `/` (относительные пути), в `contour` все сервисы работают по относительным путям изолированного контура. Отдельного `module-hosts.ts` (карты хостов удалённых модулей) в репозитории нет.
## Эндпоинты по сервисам
### `sarex` — Локальный сервис данных
| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getSettings` | GET | `/api/client/settings/` | Клиентские настройки (кешируется, `stateTime: 5`) |
| `getUser` | GET | `/api/core/users/{userId}/` | Пользователь по id |
| `getUsersByCompanyId` | GET | `/api/core/users/?company={companyId}&limit={limit}&offset={offset}` | Пользователи компании (пагинация) |
| `getTargets` | GET | `/api/core/targets/` | Список таргетов |
| `getCompanies` | GET | `/api/core/companies/` | Список компаний |
| `getDepartmentById` | GET | `/api/core/admin/departments?company={companyId}` | Отделы компании |
| `getUsersPositionById` | GET | `/api/core/admin/positions/?company={companyId}` | Должности компании |
| `getMrpaList` | POST | `/api/core/mrpa/list/` | Список МЧД (фильтр по пользователю/компании) |
| `getByFullUrl` | GET | `{url}` | Запрос по произвольному URL |
### `documentations` — Сервис документации
| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getDisks` | GET | `/api/v1/disks` | Список дисков |
| `getDocumentTypes` | GET | `/api/v1/documents/types` | Справочник типов документов |
| `getAllPermmission` | GET | `/api/v1/permissions` | Все права доступа |
| `getDocPermission` | GET | `/api/v1/documents/{id}/permissions` | Права доступа документа |
| `postPermission` | POST | `/api/v1/documents/{id}/permissions` | Выдать права сервисному аккаунту |
| `postBundle` | POST | `/api/v1/bundles` | Создать бандл |
| `postFile` | POST | `/api/v1/bundles/{bundleId}/{fileKey}?single_upload=1` | Загрузить файл (single upload) |
| `uploadFileStart` | POST | `/api/v1/bundles/{bundleId}/{key}/upload_multipart` | Начать multipart-загрузку файла |
| `uploadFolderStart` | POST | `/api/v1/bundles/{bundleId}/{key}/upload_multipart?upload_path={folderPath}` | Начать multipart-загрузку с указанием пути |
| `uploadPart` | PUT | `/api/v1/bundles/{bundleId}/{bundleKey}?part_number={partNumber}` | Загрузить часть файла |
| `bundleComplite` | POST | `/api/v1/bundles/{bundleId}/upload_finish` | Завершить загрузку бандла |
| `bundleCompleteUpload` | POST | `/api/v1/bundles/{bundleId}/upload_finish` | Завершить загрузку бандла (дубль ключа) |
| `getFile` | GET | `/api/v1/bundles/{bundleId}/{bundleKey}` | Получить файл бандла |
| `updateComment` | PATCH | `/api/v1/bundles/{bundleId}/comment` | Обновить комментарий бандла |
| `getBundles` | GET | `/api/v1/documents/{id}/bundles` | Бандлы документа |
| `addBundle` | POST | `/api/v1/documents/{documentId}/add_bundle` | Привязать бандл к документу |
| `moveBundles` | PATCH | `/api/v1/documents/{documentId}/move_bundles` | Переместить бандлы |
| `removeBundle` | DELETE | `/api/v1/bundles/{id}` | Удалить бандл |
| `postWorkspace` | POST | `/api/v1/workspaces` | Создать рабочую область |
| `getDocumentById` | GET | `/api/v1/documents/{id}` | Документ по id |
| `getDocumentWithBundles` | GET | `/api/v1/documents/{id}?extend=bundles` | Документ с бандлами |
| `changeDocument` | PATCH | `/api/v1/documents/{documentId}` | Переименовать документ |
| `changeDocumentName` | PATCH | `/api/v1/documents/{id}` | Переименовать документ |
| `updatePath` | PATCH | `/api/v1/documents/{id}/update-path` | Сменить родителя документа |
| `updateDocumentsPaths` | PATCH | `/api/v1/documents/update-path` | Массовая смена родителя |
| `deleteDocument` | DELETE | `/api/v1/documents/{id}` | Удалить документ |
| `deleteDocuments` | DELETE | `/api/v1/documents?document_ids={ids}` | Удалить несколько документов |
| `getFolderChildrenWithActiveProcesses` | POST | `/api/v1/documents/flows` | Дети папки с активными процессами |
| `downloadFile` | GET | `/api/v1/bundles/{lastBundleId}/{key}/download` | Скачать файл (с флагами `include_original_pdf`/`include_printable_pdf`) |
| `downloadFiles` | GET | `/api/v1/download_url/documents?document_ids={documentIds}` | Получить ссылку на скачивание документов |
| `downloadAllFiles` | GET | `/api/v1/bundles/{lastBundleId}/download` | Скачать все файлы бандла |
| `downloadFolder` | GET | `/api/v1/documents/{docId}/download?depth={depth}` | Скачать папку |
| `getFoldersDownloadUrl` | GET | `/api/v1/documents/get_folders_download_url?document_ids={ids}` | Ссылка на скачивание папок |
| `conversionFile` | POST | `/api/v1/conversion` | Конвертация документа (в IFC) |
| `addMarks` | PUT | `/api/v1/bundles/{bundleId}/marks` | Добавить штампы/QR/подписи |
| `sign` | POST | `/api/v1/bundles/{bundleId}/sign` | Подписать бандл |
| `cancelQrCode` | PATCH | `/api/v1/bundles/{bundleId}/cancel_qr` | Отменить QR-код |
| `restartWorkflow` | POST | `/api/v1/bundles/{bundleId}/restart` | Перезапустить workflow бандла |
| `getPublicLink` | GET | `/api/v1/public/documents/public_link/{public_link_id}` | Получить публичную ссылку |
| `createPublicLink` | POST | `/api/v1/documents/public_link` | Создать публичную ссылку |
| `updatePublicLink` | PATCH | `/api/v1/documents/public_link/{public_link_id}` | Обновить публичную ссылку |
| `deletePublicLink` | DELETE | `/api/v1/documents/public_link/{public_link_id}` | Удалить публичную ссылку |
| `removeDoc` | DELETE | `/api/v1/documents/bin?parent_id={id}` | Переместить в корзину |
| `recoveryDocument` | PATCH | `/api/v1/documents/bin/restore?parent_id={id}` | Восстановить из корзины |
| `copyFolderStructure` | POST | `/api/v1/documents/copy_structure` | Копировать структуру папок |
| `getTemplateJSON` | GET | `/api/v1/templates/{bundleId}` | JSON-шаблон бандла |
| `uploadSingleTemplate` | POST | `/api/v1/bundles/{bundleId}/{key}/upload_single` | Загрузить файл шаблона |
| `createReport` | POST | `/api/v1/documents/create_report` | Сформировать отчёт по документам |
| `updateChangelog` | PATCH | `api/v1/changelogs/{bundleId}` | Обновить запись журнала изменений |
| `createChangelog` | POST | `api/v1/changelogs/create` | Создать запись журнала изменений |
| `getFavorites` | GET | `/api/v1/favorite_documents?company_id={companyId}` | Избранные документы |
| `createFavoriteDocument` | POST | `/api/v1/favorite_documents` | Добавить документ в избранное |
| `deleteFavoriteDocument` | DELETE | `/api/v1/favorite_documents/{documentId}` | Убрать документ из избранного |
| `getNearestNameTemplate` | GET | `/api/v1/documents/{documentId}/name_template` | Ближайший шаблон именования (без уведомления об ошибке) |
| `getDocumentNameTemplate` | GET | `/api/v1/name_templates/{documentId}` | Шаблон именования документа (без уведомления об ошибке) |
| `createNameTemplate` | POST | `/api/v1/name_templates/create` | Создать шаблон именования |
| `updateNameTemplate` | PATCH | `/api/v1/name_templates/{documentId}` | Обновить шаблон именования |
| `deleteNameTemplate` | DELETE | `/api/v1/name_templates/{documentId}` | Удалить шаблон именования |
| `createLink` | POST | `/api/v1/links` | Создать ярлык (ссылку на документ) |
| `getBundleMrpas` | GET | `/api/v1/bundles/{bundleId}/mrpas` | МЧД бандла |
### `sarexApi` — Gateway/API Sarex
Через этот сервис проходят запросы к `/gateway`, `/eav`, `/cde`, а также к сабпутям других доменов, доступным через общий шлюз: `/transmittals`, `/flows`, `/issues`.
| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getDocuments` | GET | `/gateway/api/v1/disks/{id}/documents?parent_id={parentId}&child_id={childId}` | Документы диска (по родителю/потомку) |
| `getFolderChildren` | GET | `/gateway/api/v1/disks/{diskId}/documents?parent_id={documentId}` | Дети папки |
| `getSearch` | GET | `/gateway/api/v4/disks/{diskId}/documents?...` | Поиск/фильтрация документов (root_document, limit, filters, bookmark) |
| `createDocument` | POST | `/gateway/api/v1/documents` | Создать документ/папку/проект |
| `fetchDocumentPaths` | POST | `/gateway/api/v1/documents/ancestors` | Предки документов |
| `getAttributesByDocument` | GET | `/gateway/api/v1/documents/{id}/attributes` | Атрибуты документа |
| `updateAttributes` | PUT | `/gateway/api/v1/documents/{id}/attributes` | Обновить атрибуты документа |
| `addAttributes` | POST | `/gateway/eav/api/v0/entity/` | Создать сущность атрибутов (EAV) |
| `getDefaultAttributes` | GET | `/eav/api/v0/schema/?model=document&company_id={companyId}&type_identifier={docType}` | Схема атрибутов по типу |
| `getAttributes` | GET | `/eav/api/v0/attribute/?company_id={params}` | Атрибуты компании |
| `getAttributesWithParams` | GET | `/eav/api/v0/schema/?model=document&{params}` | Схема атрибутов с параметрами |
| `updateSubscription` | POST | `/gateway/api/v1/subscription/` | Создать/обновить подписку |
| `deleteSubscription` | DELETE | `/gateway/api/v1/documents/{documentId}/subscription/` | Удалить подписку |
| `getActivityLog` | GET | `/gateway/api/v1/system_log/?model_names=document&...` | Журнал активности документа |
| `fetchResourceByDocumentId` | GET | `/gateway/api/v1/resources-rpc/resource-by-document-id/{id}/` | Ресурс по id документа |
| `getUsersWithTransmittalProjectPermissions` | GET | `/gateway/api/v2/users/?limit=5000&offset=0&resource_id={projectId}&permissions={permissions}` | Пользователи с правами в проекте |
| `getRemovedDocuments` | GET | `/gateway/api/v1/documents/bin?parent_id={id}{params}` | Удалённые документы в папке |
| `getRemovedFilteredDocuments` | GET | `/gateway/api/v1/documents/bin{params}` | Удалённые документы (фильтр) |
| `getTemplates` | GET | `/gateway/api/v1/disks/{diskId}/flat_documents?type={type}` | Плоский список документов по типу |
| `getFileSize` | GET | `/gateway/api/v1/documents/size?disk_id={diskId}&document_id={documentId}` | Размер документа |
| `completeUpload` | POST | `{uploadUrl}/complete` | Завершение загрузки (по переданному URL) |
| `createTransmittal` | POST | `/transmittals/api/v1/transmittals/create` | Создать трансмиттал |
| `getTransmittalById` | GET | `/transmittals/api/v1/transmittals/{transmittalId}` | Трансмиттал по id |
| `getTransmittalsByBundleId` | POST | `/transmittals/internal/v1/transmittals/by_bundle_ids` | Трансмитталы по id бандлов |
| `getTemplateListForSelect` | GET | `/transmittals/api/v1/transmittal_templates/select?resource={resourceId}` | Список шаблонов трансмитталов для выбора |
| `getSingleTemplate` | GET | `/transmittals/api/v1/transmittal_templates/{templateId}?resource={resourceId}` | Шаблон трансмиттала по id |
| `createPrescriptionDocument` | POST | `/issues/api/prescriptions/{prescriptionId}/generate/` | Сгенерировать документ по предписанию |
| `loadReviewData` | GET | `/flows/api/v1/documents/?bundle_ids={ids}&limit=10000&full=true` | Данные согласований по бандлам (с явным access-токеном) |
| `searchAssets` | POST | `eav/api/v4/assets/search/` | Поиск активов по id |
| `getProjectAssets` | GET | `eav/api/v4/assets/?linkable_to_project={resourceId}&parentId=null` | Активы проекта |
| `getAssetsList` | GET | `eav/api/v4/assets/?tenant_id={tenantId}&linkable_to_project={resourceId}&depth=0&...` | Список активов (поиск/пагинация) |
| `getAssets` | GET | `eav/api/v4/assets/?{params}` | Активы по произвольным параметрам |
| `getAssetLevels` | GET | `eav/api/v4/assets/?tenant_id={tenantId}&parent_id={parentAssetId}&path_contains={id}` | Уровни активов |
| `getBindings` | GET | `/cde/app/v1/bundles/{bundleId}/bindings` | Привязки бандла |
| `createSession` | POST | `/cde/app/v1/s32d/sessions/` | Создать S32D-сессию |
| `getSessionList` | GET | `/cde/app/v1/s32d/sessions/` | Список S32D-сессий |
| `uploadS32DSingle` | PUT | `/cde/app/v1/s32d/sessions/{sessionId}/archive` | Загрузить архив S32D (single) |
| `s32dMultipartInit` | POST | `/cde/app/v1/s32d/sessions/{sessionId}/archive/multipart` | Начать multipart-загрузку архива S32D |
| `s32dMultipartUploadPart` | PUT | `/cde/app/v1/s32d/sessions/{sessionId}/archive/multipart/{uploadId}/parts/{partNumber}` | Загрузить часть архива S32D |
| `s32dMultipartComplete` | POST | `/cde/app/v1/s32d/sessions/{sessionId}/archive/multipart/{uploadId}/complete` | Завершить multipart-загрузку S32D |
| `startS32DProcess` | POST | `/cde/app/v1/s32d/sessions/{sessionId}/process` | Запустить обработку S32D |
### `processes` — Сервис рабочих процессов (flows)
| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getProcesses` | GET | `/api/v1/flows/?{query}` | Список процессов (flows) |
| `createReview` | POST | `/api/v1/reviews/` | Создать review |
| `deleteReview` | DELETE | `/api/v1/reviews/{id}/` | Удалить review |
| `activateReview` | PATCH | `/api/v1/reviews/{id}/approve/` | Активировать/утвердить review |
| `createReviewDocuments` | POST | `/api/v1/documents/` | Добавить документы в review |
### `workflows` — Сервис обработки документов
| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getWorkflow` | GET | `/api/v1/workflows/{workflowId}` | Workflow по id |
| `getWorkflows` | POST | `/api/v1/workflows/batch` | Пакетное получение workflow |
### `workspaces` — Сервис рабочих областей
| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getWorkspaces` | GET | `/api/v1/workspaces/{uuid}` | Рабочая область по uuid |
### `remarks` — Сервис замечаний
| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `getRemarksTotalCount` | GET | `/api/v1/total_count` | Общее число замечаний |
### `files` — Сервис файлов
| Ключ | Метод | Путь | Назначение |
| --- | --- | --- | --- |
| `downloadBundlesMrpas` | POST | `/api/v1/bundles_mrpas/` | Скачать МЧД бандлов (ответ `blob`) |
## Обработка ошибок
Маппинг ошибок выполняется в `module/api/errors.ts`. Функция `fetch` (`module/api/endpoints.ts`) перехватывает `AxiosError` и вызывает:
- `resolveNetworkErrorByCode(service, code, endpoint, method, data)` — при HTTP-ответе с кодом ≥ 400 и при отмене запроса (`CanceledError`/`ERR_CANCELED`, внутренний код `-1` → «Запрос был отменен»);
- `resolveNetworkError(service, error)` — при сетевой ошибке без ответа сервера.
Базовый маппинг кодов (`httpCodeToError`): `400` — «некорректный формат запроса», `401` — «ошибка авторизации», `403` — «доступ запрещен», `404` — «ресурс не найден», `500` — «ошибка сервера». Для неизвестного кода подбирается ближайший (`4xx` → `400`, иначе → `500`). К сообщению добавляется человекочитаемое имя сервиса из `getServiceToName()` (напр. `documentations`/`sarexApi` → «Сервис документации», `sarex` → «Локальный сервис данных», `processes` → «Сервис рабочих процессов», `workflows` → «Сервис обработки документов», `remarks` → «Сервис замечаний», `workspaces` → «Сервис рабочих областей», `files` → «Сервис файлов»).
Для части кодов сообщение уточняется по эндпоинту и методу:
- `401` — набор сообщений `error401Messages` (истёкшая/невалидная сессия, завершённая сессия); по умолчанию — «Ваш токен невалиден, обновите страницу».
- `403` — тип определяется `determine403ErrorType(endpoint, method)` (напр. чтение/создание/редактирование/удаление/перемещение документа, скачивание, загрузка файла, управление доступом, изменение атрибутов, создание review/трансмиттала, доступ к диску/проекту), сообщения — `error403Messages`.
- `400` — тип определяется `determine400ErrorType(endpoint, method, data)` с анализом текста `data.message` (конфликт имени, дубликат, отсутствие/некорректность расширения, некорректный формат), сообщения — `error400Messages`.
- `409` — тип определяется `determine409ErrorType(endpoint, method, data)` (дубликаты имён документов/папок/ярлыков, конфликт при `copy_structure`), сообщения — `error409Messages`.
По умолчанию у запросов включён показ уведомления об ошибке (`showErrorNotification !== false`); отдельные эндпоинты отключают его (`getNearestNameTemplate`, `getDocumentNameTemplate`). Типы кодов ошибок описаны в `module/api/types.ts`.