@weavix/tracker-plugin-sdk
v0.0.6
Published
Core package for Tracker plugin SDK
Readme
@weavix/tracker-plugin-sdk
Core package for Tracker plugins (Weavix / npm). API surface matches @yandex-data-ui/tracker-plugin-sdk-core without yateamApi.
External flavor. Internal (Yandex):
@yandex-data-ui/tracker-plugin-sdk-core.
Низкоуровневое API для взаимодействия с хостом и вызова Tracker Public API.
Установка
npm install @weavix/tracker-plugin-sdkИспользование
import { hostApi, trackerApi } from '@weavix/tracker-plugin-sdk';
// Инициализация плагина (чтение параметров из URL, настройка моста)
hostApi.init({ autoResize: true });
// Получение текущей темы
const theme = await hostApi.getTheme(); // 'light' | 'light-hc' | 'dark' | 'dark-hc' | 'system' | undefined
// Получение текущего языка
const language = await hostApi.getLanguage(); // 'ru' | 'en' | undefined
// Получение контекста слота (например, текущей задачи для слота 'issue.action')
const context = await hostApi.getContext();
// Уведомление хоста о готовности плагина
await hostApi.notifyReady();
// Обновление высоты контейнера плагина
await hostApi.updateContentSize({ height: 500 });Tracker API
Все вызовы Tracker Public API выполняются через trackerApi.v3 — типизированный прокси над HTTP-методами. Ключи — пути эндпоинтов из OpenAPI (@weavix/tracker-api-types); IDE предоставляет автодополнение и JSDoc.
Подробное описание методов и форматов ответов: Tracker API Reference.
import { trackerApi } from '@weavix/tracker-plugin-sdk';
// GET — возвращает { data, headers }
const { data: issue } = await trackerApi.v3.get['/issues/{id}']({
pathParams: { id: 'QUEUE-123' },
queryParams: { expand: ['COMMENTS'] },
});
// POST
await trackerApi.v3.post['/v2/issues']({
bodyParams: { queue: { key: 'TASK' }, summary: 'Новая задача' },
});
// PATCH
await trackerApi.v3.patch['/v2/issues/{id}']({
pathParams: { id: 'QUEUE-123' },
bodyParams: { summary: 'Обновлённое название' },
});
// DELETE
await trackerApi.v3.delete['/v2/issues/{id}']({
pathParams: { id: 'QUEUE-123' },
});Очереди
// Получение списка очередей
const { data: queues } = await trackerApi.v3.get['/v2/queues']({
queryParams: { page: 1, perPage: 100 },
});
// Получение конкретной очереди
const { data: queue } = await trackerApi.v3.get['/v2/queues/{id}']({
pathParams: { id: 'MYQUEUE' },
});Задачи
// Получение задачи по ключу
const { data: issue } = await trackerApi.v3.get['/issues/{id}']({
pathParams: { id: 'QUEUE-123' },
});
// Создание задачи
const { data: newIssue } = await trackerApi.v3.post['/v2/issues']({
bodyParams: {
queue: { key: 'QUEUE' },
summary: 'Название задачи',
},
});
// Поиск задач
const { data: issues } = await trackerApi.v3.post['/v2/issues/_search']({
bodyParams: { filter: { queue: 'QUEUE' } },
});Тосты (Toast notifications)
Плагины могут показывать toast-уведомления в хост-приложении через uiApi.toaster. API максимально приближен к gravity-ui useToaster.
Permission: Требуется
"toaster"вpermissions.uiманифеста плагина (хост преобразует в scopetracker:ui:toaster).
import { uiApi } from '@weavix/tracker-plugin-sdk';
// Простой тост
uiApi.toaster.add({
title: 'Сохранено',
theme: 'success',
});
// Тост с текстовым содержимым и кастомным временем показа
uiApi.toaster.add({
title: 'Ошибка',
theme: 'danger',
content: 'Не удалось загрузить данные',
autoHiding: 10000,
});
// Тост с кнопкой действия
uiApi.toaster.add({
title: 'Элемент удалён',
theme: 'info',
content: 'QUEUE-123',
actions: [
{
label: 'Отменить',
onClick: () => {
// обработка нажатия
},
},
],
});uiApi.toaster.add(options)
| Параметр | Тип | По умолчанию | Описание |
|----------|-----|--------------|----------|
| title | string | — | Заголовок тоста (обязательный) |
| name | string | auto | Уникальный ключ для дедупликации. Генерируется автоматически, если не передан |
| theme | 'success' \| 'danger' \| 'warning' \| 'info' | 'info' | Тема (цвет и иконка) |
| content | string | — | Текстовое содержимое под заголовком |
| autoHiding | number | 5000 | Время показа в мс (от 1000 до 30000) |
| isClosable | boolean | true | Показывать кнопку закрытия |
| actions | ToastAction[] | — | Кнопки действий (макс. 2) |
ToastAction:
| Поле | Тип | Описание |
|------|-----|----------|
| label | string | Текст кнопки (макс. 50 символов) |
| onClick | () => void | Callback при нажатии |
Возвращает: Promise<{ name: string }> — имя тоста (для идентификации).
Ограничения:
title— макс. 200 символовcontent— макс. 500 символовactions— макс. 2 кнопки- Rate limit — 5 тостов за 10 секунд на плагин
Навигация в хосте
Плагин может открыть путь в хост-приложении или внешний URL через uiApi.navigate:
import { uiApi } from '@weavix/tracker-plugin-sdk';
await uiApi.navigate({
path: '/queues/MYQUEUE',
params: { tab: 'settings' },
options: { newTab: true },
});| Поле | Тип | Описание |
|------|-----|----------|
| path | string | Путь или URL (обязательный) |
| params | Record<string, string \| number \| boolean \| null \| undefined \| (string \| number \| boolean \| null \| undefined)[]> | Query-параметры |
| options.newTab | boolean | Открыть в новой вкладке |
TrackerPluginProvider (react) перехватывает клики по внешним ссылкам в iframe и вызывает uiApi.navigate.
Storage API
storageApi — JSON-хранилище уровня организации, опосредованное хостом. Запись общая на всю организацию: её видят все пользователи плагина, право на запись определяет хост (отдаёт его в поле canWrite каждой прочитанной записи).
На сегодня доступен единственный контекст — storageApi.orgShared.
import { storageApi } from '@weavix/tracker-plugin-sdk';
// Чтение
const record = await storageApi.orgShared.get('settings');
// record: { data: { theme: 'dark' }, version: 5, canWrite: true, ... } | null
// Создание новой записи (на пустом бакете)
await storageApi.orgShared.patch({
bucket: 'settings',
data: { theme: 'dark', notifications: true },
version: 0,
});
// Обновление без знания текущей версии — SDK сам вычитает её и поретраит конфликты
await storageApi.orgShared.patch({
bucket: 'settings',
data: { count: 42 },
});
// Удаление отдельного поля — передайте `null`
await storageApi.orgShared.patch({
bucket: 'settings',
data: { theme: null },
});storageApi.orgShared.get(bucket?)
Возвращает Promise<StorageRecord | null> — текущую запись или null, если её ещё нет.
| Параметр | Тип | По умолчанию | Описание |
|----------|-----|--------------|----------|
| bucket | string \| undefined | хост подставляет 'default' | Ключ записи внутри контекста |
storageApi.orgShared.patch(options)
Merge-patch: поля из data накладываются на текущую запись поверх, значение null удаляет ключ. Возвращает полный смерженный StorageRecord с новой версией (включая поля, дописанные параллельными писателями).
| Параметр | Тип | По умолчанию | Описание |
|----------|-----|--------------|----------|
| bucket | string | хост подставляет 'default' | Ключ записи |
| data | Record<string, unknown> | — | Merge-doc; null удаляет поле |
| version | number \| undefined | auto-resolve | Ожидаемая текущая версия |
Версионирование.
- С явным
version— отправляется один запрос. Любая ошибка, включаяVERSION_CONFLICT, пробрасывается вызывающему. Используйте, если приложение само держит актуальную версию и должно реагировать на конфликт (например, показать пользователю «данные изменились, перечитайте»). Для создания записи на пустом бакете передавайтеversion: 0. - Без
version— SDK сначала читает текущую версию черезget(для пустого бакета берётся0), затем выполняетpatch. НаVERSION_CONFLICTцикл повторяется до двух раз, каждый ретрай заново читает версию. Любая другая ошибка пробрасывается мгновенно. В худшем случае — 6 round-trip-ов (3 пары GET + PATCH); на каждом ретрае в консоль пишетсяconsole.warn.
Ошибки
Все ошибки storage-методов — экземпляры PluginActionError с числовыми кодами:
| Код | Константа | Когда |
|-----|-----------|-------|
| 1010 | VERSION_CONFLICT | Переданный version не совпал с текущим |
| 1011 | DATA_TOO_LARGE | Размер записи после операции превысил 256 KiB |
| 1012 | BAD_KEY | bucket не прошёл валидацию формата или длины |
import { PluginActionError, VERSION_CONFLICT, storageApi } from '@weavix/tracker-plugin-sdk';
try {
await storageApi.orgShared.patch({ bucket: 'settings', data: { x: 1 }, version: 0 });
} catch (e) {
if (e instanceof PluginActionError && e.code === VERSION_CONFLICT) {
// показать пользователю, что версия устарела
}
}Типы
import type {
StorageContextType, // 'orgShared' (расширяемое в будущем)
StorageRecord, // { key, version, data, canWrite, createdAt, updatedAt }
StorageGetPayload, // wire-payload для storage.get
StoragePatchPayload, // wire-payload для storage.patch
} from '@weavix/tracker-plugin-sdk';Вызов внешних API
Методы hostApi для работы с внешними API через прокси хоста: проверка и запрос учётных данных пользователя по доменам из манифеста и выполнение HTTP-запросов от имени плагина.
Домены и схемы авторизации задаются в манифесте плагина в permissions.external.
import { hostApi } from '@weavix/tracker-plugin-sdk';
// Проверить, указал ли пользователь авторизационные данные для доменов, и при необходимости запросить их через диалог
const { success } = await hostApi.externalApiAuthCheckAndRequest({
domains: ['api.example.com'],
});
if (!success) {
// пользователь отменил диалог или истёк таймаут ожидания
return;
}
// Прокси-вызов внешнего API (учётные данные подставляет хост)
const { status, body } = await hostApi.externalApiCall({
url: 'https://api.example.com/v1/items',
method: 'GET',
});Типичный сценарий: externalApiAuthCheckAndRequest (или пара externalApiAuthGetStatus + externalApiAuthRequest) → externalApiCall. Отзыв сохранённых данных — externalApiAuthRevoke.
hostApi.externalApiAuthGetStatus(payload)
Возвращает статус учётных данных пользователя по доменам.
| Параметр | Тип | По умолчанию | Описание |
|----------|-----|--------------|----------|
| domains | string[] \| undefined | все домены плагина | Список доменов для проверки |
| contextType | 'user' \| 'organization' \| undefined | — | Тип контекста учётных данных (в контракте payload) |
Возвращает: Promise<{ domains: ExternalApiAuthGetStatusDomain[] }>.
Если domains не передан или пуст, хост запрашивает статус по всем доменам плагина.
hostApi.externalApiAuthRequest(payload)
Показывает пользователю диалог ввода учётных данных для указанных доменов. При успешном подтверждении хост сохраняет credentials.
| Параметр | Тип | По умолчанию | Описание |
|----------|-----|--------------|----------|
| domains | ExternalApiDomainInfo[] | — | Домены (обязательно, минимум один) |
ExternalApiDomainInfo:
| Поле | Тип | Описание |
|------|-----|----------|
| domain | string | Домен из манифеста |
| instructions | string \| { en?: string; ru?: string } | Подсказка в диалоге (опционально) |
Возвращает: Promise<{ success: boolean }>. success: false — пользователь закрыл диалог или не завершил авторизацию. Ожидание ответа пользователя ограничено по времени (около 5 минут).
hostApi.externalApiAuthRevoke(payload)
Отзывает сохранённую аутентификацию для указанных доменов.
| Параметр | Тип | По умолчанию | Описание |
|----------|-----|--------------|----------|
| domains | string[] | — | Домены для отзыва (обязательно, минимум один) |
| contextType | 'user' \| 'organization' \| undefined | — | Тип контекста учётных данных (в контракте payload) |
Возвращает: Promise<{ success: boolean }>. success: true, если отзыв прошёл для всех переданных доменов.
hostApi.externalApiAuthCheckAndRequest(payload)
Комбинирует проверку статуса и запрос credentials только для неаутентифицированных доменов. Payload совпадает с externalApiAuthGetStatus.
| Параметр | Тип | По умолчанию | Описание |
|----------|-----|--------------|----------|
| domains | string[] \| undefined | все домены плагина | Домены для проверки |
| contextType | 'user' \| 'organization' \| undefined | — | Тип контекста (в контракте payload) |
Возвращает: Promise<{ success: boolean }>. Если все домены уже аутентифицированы — сразу { success: true } без диалога. Иначе показывается тот же диалог, что и у externalApiAuthRequest; при успехе credentials сохраняются.
hostApi.externalApiCall(payload)
Выполняет HTTP-запрос к внешнему API через прокси платформы. URL должен относиться к домену, разрешённому в permissions.external; заголовки авторизации подставляет хост.
| Параметр | Тип | По умолчанию | Описание |
|----------|-----|--------------|----------|
| url | string | — | Полный URL запроса (обязательный) |
| method | 'GET' \| 'POST' \| 'PUT' \| 'PATCH' \| 'DELETE' | — | HTTP-метод (обязательный) |
| headers | Record<string, string> | — | Дополнительные заголовки |
| body | Record<string, unknown> | — | Тело запроса (для методов с телом) |
| timeoutMs | number | — | Таймаут запроса в миллисекундах |
| contextType | 'user' \| 'organization' \| undefined | — | Контекст учётных данных для прокси |
Возвращает: Promise<{ status: number; headers?: Record<string, string>; body?: Record<string, unknown> }>.
При ошибке прокси-запроса (ответ платформы с status, code, message) метод бросает PluginActionError с кодом EXTERNAL_API_CALL_ERROR (1013); детали — в errorData (status, message, code, title).
Ошибки
| Код | Константа | Когда |
|-----|-----------|-------|
| 1013 | EXTERNAL_API_CALL_ERROR | Прокси-вызов externalApiCall завершился ошибкой |
import {
EXTERNAL_API_CALL_ERROR,
PluginActionError,
hostApi,
} from '@weavix/tracker-plugin-sdk';
try {
await hostApi.externalApiCall({ url: 'https://api.example.com/x', method: 'GET' });
} catch (e) {
if (e instanceof PluginActionError && e.code === EXTERNAL_API_CALL_ERROR) {
console.log(e.errorData);
}
}Типы
import type {
AuthContextType,
ExternalApiAuthGetStatusPayload,
ExternalApiAuthGetStatusResult,
ExternalApiAuthGetStatusDomain,
ExternalApiAuthRequestPayload,
ExternalApiAuthRequestResult,
ExternalApiAuthRevokePayload,
ExternalApiAuthRevokeResult,
ExternalApiAuthCheckAndRequestPayload,
ExternalApiAuthCheckAndRequestResult,
ExternalApiCallPayload,
ExternalApiCallResult,
ExternalApiDomainInfo,
PluginProxyMethod,
} from '@weavix/tracker-plugin-sdk';Обработка ошибок
import { trackerApi, PluginActionError } from '@weavix/tracker-plugin-sdk';
try {
await trackerApi.v3.get['/issues/{id}']({ pathParams: { id: 'BAD' } });
} catch (e) {
if (e instanceof PluginActionError) {
console.log(e.code, e.message, e.errorData);
}
}API
hostApi
init(options?)— инициализация плагина (чтение параметров из URL, настройка моста). Вызывать один раз перед использованием остальных методов.getTheme()— текущая тема ('light' | 'light-hc' | 'dark' | 'dark-hc' | 'system')getLanguage()— текущий код языка ('ru','en'и др.)getContext()— контекст слота (тип зависит от слота, см.SlotContextMap)getSlot()— имя текущего слота (вызывать послеinit())updateContentSize(request)— обновление высоты контейнера плагинаnotifyReady()— уведомление хоста о готовности плагинаdisableAutoResize()— отключение автоматического изменения размераexternalApiAuthGetStatus(payload)— статус аутентификации по доменамexternalApiAuthRequest(payload)— диалог запроса учётных данныхexternalApiAuthRevoke(payload)— отзыв аутентификацииexternalApiAuthCheckAndRequest(payload)— проверка и запрос credentials для неаутентифицированных доменовexternalApiCall(payload)— прокси HTTP к внешнему API
uiApi
UI-методы хоста (навигация, тосты, confirm и др.).
uiApi.navigate(request)— навигация в хост-приложении. Подробности — выше.uiApi.toaster.add(options)— показать toast-уведомление в хост-приложении. Подробности — выше.uiApi.confirm.show(options)— диалог подтверждения (permissionconfirmв манифесте).
trackerApi.v3
Типизированный прокси над эндпоинтами Tracker Public API v3:
trackerApi.v3.get[path](payload)— GET-запрос;payload:pathParams, опциональноqueryParamstrackerApi.v3.post[path](payload)— POST-запрос;payload:bodyParams, опциональноpathParams,queryParamstrackerApi.v3.put[path](payload)— PUT-запросtrackerApi.v3.patch[path](payload)— PATCH-запросtrackerApi.v3.delete[path](payload)— DELETE-запрос;payload:pathParams, опциональноqueryParams
Все методы возвращают Promise<{ data, headers }>, где data типизирован согласно ответу эндпоинта.
Типы
SlotContextMap, контексты слотов,LocalizedStringи связанные типы (Issueв контексте слота,Attachmentи т.д.) — из@weavix/tracker-core, реэкспортируются из этого пакета.- Типы запросов и ответов HTTP эндпоинтов Tracker Public API (
trackerApi.v3) — из@weavix/tracker-api-types.
import type {
Theme,
ApiCallResult,
ApiCallPayload,
TrackerApiCallOptions,
ContentSizeUpdateRequest,
SlotContextMap,
} from '@weavix/tracker-plugin-sdk';React-интеграция
Для React-приложений используйте @weavix/tracker-plugin-sdk-react — TrackerPluginProvider, useTrackerPluginContext, useLocalizedString.
Полная документация
📖 AGENTS.md — краткий вход для агентов.
📖 COOKBOOK — типовые сценарии.
📖 API Reference — hostApi, trackerApi.v3, типы, ошибки.
Лицензия
UNLICENSED
