Начало работы
Это руководство проведёт вас от нуля до зарегистрированного модуля Tango Vision.
Что вам понадобится
- Учётная запись разработчика — зарегистрируйтесь здесь (самостоятельно)
- Node 22+ и npm
- Доступ к приватному реестру
https://npm.k8s.tangovision.dev/ - API-ключ песочницы — см. Учётная запись → Получить API-ключ песочницы
Установка SDK
npm install @tv/extension-sdk.npmrc:
@tv:registry=https://npm.k8s.tangovision.dev/SDK поставляет всё одним пакетом, доступным через подпути:
| Подпуть | Что он даёт |
|---|---|
@tv/extension-sdk | Типы ModuleManifest + Zod-валидатор + типы PlatformContext |
@tv/extension-sdk/manifest | Схема манифеста, валидатор, JSON Schema |
@tv/extension-sdk/context | Типы контекста времени выполнения |
@tv/extension-sdk/react | <PlatformProvider>, usePlatformContext(), useBuilding(), useCurrentUser() |
@tv/extension-sdk/nestjs | Декораторы @ModuleCapability(), @RequiresLicense() |
@tv/extension-sdk/testing | createMockPlatformContext() |
tv-sdk (bin) | CLI-валидатор |
Анатомия модуля
my-module/
├── module-manifest.json ← контракт
├── frontend/ ← React, экспортирует федеративный "Shell"
│ └── src/App.tsx
└── backend/ ← опциональный сервис NestJS
└── src/Манифест — это сердце модуля. Он объявляет идентификатор модуля, нужные ему разрешения, события, на которых он «говорит», и место монтирования его UI. Платформа читает его три раза:
- В вашем CI —
tv-sdk validate module-manifest.json - При публикации — реестр отклоняет недопустимый манифест
- Во время выполнения — оболочка Building OS собирает ваш модуль на его основе
Золотое правило
Ваш модуль общается с платформой только через
PlatformContext.
Никакого localStorage. Никаких ручных токенов. Никаких собранных вручную URL API. Контекст даёт вам предварительно аутентифицированный HTTP-клиент, ограниченный областью арендатора. Именно это позволяет одному и тому же коду без изменений работать и в вашей песочнице, и в продакшен-арендаторе клиента.
import { usePlatformContext, useBuilding } from '@tv/extension-sdk/react';
export function WorkOrderList() {
const { api } = usePlatformContext(); // уже аутентифицирован + ограничен областью
const building = useBuilding(); // активное здание
return useQuery({
queryKey: ['work-orders', building.id],
queryFn: () => api.get(`/api/v1/buildings/${building.id}/work-orders`),
});
}Далее
→ Ваш первый модуль собирает рабочий hello-world от начала до конца.