<!-- Canonical: https://docs.shopstory.live/docs/guide/web-sdk-reference -->

# Web SDK: методы и lifecycle

Для первого подключения используйте [Web SDK](<https://docs.shopstory.live/docs/guide/web-sdk>). Здесь собран контракт методов основного bundle.

## Методы основного SDK

Параметр SDK `clientId` принимает тот же идентификатор проекта, который в Public API называется `applicationId`. Используйте значение, выданное ShopStory, без преобразований. Общие правила: [Идентификаторы](<https://docs.shopstory.live/docs/guide/architecture#%D0%B8%D0%B4%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D1%80%D1%8B>).

### show

Монтирует каталог в контейнер сайта. Возвращает `undefined` (тип `void`), не предоставляет Promise загрузки каталога.

| Параметр | Обязательно | Назначение |
| --- | --- | --- |
| `containerElement` | Да | Существующий DOM-элемент, который сайт сохраняет на время работы SDK |
| `config.clientId` | Да | Строковый идентификатор проекта, выданный ShopStory |
| `actions` | Нет | Обработчики [добавления товара в корзину](<https://docs.shopstory.live/docs/guide/add-to-cart#web-sdk-callback>) и [проверки наличия](<https://docs.shopstory.live/docs/guide/product-availability#%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%B0%D0%BA%D1%82-%D0%BE%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%B0>) для этого экземпляра |
| `cartUrl` | Нет | Адрес корзины для повторного клика по состоянию «В корзине»; относительный путь разрешается от origin сайта |

`await ShopStorySDK.show(...)` не ждёт каталог. Ограничения повторной инициализации описаны в разделе [SPA и lifecycle](<https://docs.shopstory.live/docs/guide/web-sdk-reference#spa-%D0%B8-lifecycle>).

### showPlayer

Открывает указанную трансляцию в собственном контейнере в `document.body`. При первом вызове SDK создаёт контейнер, при следующих использует его повторно. Оба параметра обязательны:

| Параметр | Тип | Назначение |
| --- | --- | --- |
| `clientId` | `string` | Идентификатор проекта |
| `streamId` | `string` | Идентификатор трансляции из API |

Возвращает `Promise<void>`. Promise завершается после внутренней инициализации SDK, ещё до подтверждения загрузки данных эфира и воспроизведения видео. Использовать его как сигнал «видео готово» нельзя.

show-player.js

```javascript
async function openShopStoryPlayer(streamId) {
  const sdk = window.ShopStorySDK;
  if (!sdk) {
    console.error('Основной bundle ShopStory не загружен');
    return;
  }

  try {
    await sdk.showPlayer({
      clientId: 'assigned-application-id',
      streamId,
    });
  } catch (error) {
    console.error('Не удалось вызвать плеер ShopStory', error);
  }
}
```

Передавайте идентификаторы строками. Список трансляций для собственного интерфейса получайте через [`GET /v3/streams`](<https://docs.shopstory.live/docs/guide/catalog-streams>).

`showPlayer()` не принимает `actions` и `cartUrl` и не наследует их из ранее вызванного `show()`. Для прямой корзины используйте плеер внутри каталога, созданного через `show({ actions, ... })`, либо согласованный commerce-контракт.

### Готовность и ошибки

У основного SDK нет публичных событий или параметров `onReady` / `onError` для загрузки каталога и плеера. Событие `load` у `<script>` позволяет начать инициализацию; готовность каталога или видео оно не подтверждает.

| Что произошло | Что получает код сайта |
| --- | --- |
| Основной bundle не загрузился или не выполнился | `window.ShopStorySDK` отсутствует; проверьте загрузку скрипта до вызова методов |
| `show()` вернулся | Только завершение вызова монтирования; данные загружаются отдельно |
| `showPlayer()` завершил Promise | Внутренняя инициализация завершена; данные эфира и видео ещё могут загружаться |
| Вызов метода выбросил исключение или его Promise отклонён | Исключение можно обработать через `try/catch` |
| Ошибка обработана внутри SDK при загрузке или отрисовке | Публичного callback для сайта нет; возможны сообщение внутри SDK или отсутствие его интерфейса |

`try/catch` в примере не перехватывает все ошибки загрузки и воспроизведения. При сбое до завершения инициализации Promise `showPlayer()` может остаться незавершённым. Не связывайте с ним разблокировку страницы, корзины или других функций сайта.

Состояние страницы без SDK и отключение loader через feature flag остаются на стороне клиента. Если вашему интерфейсу нужны собственные состояния загрузки, пустой выдачи и ошибки каталога, используйте [Public API](<https://docs.shopstory.live/docs/guide/quickstart>).

### Типы для TypeScript

Для подключения через `<script>` добавьте локальный файл деклараций в каталог, включённый в `tsconfig.json`. Он описывает поддерживаемые на этой странице методы и параметры; сам SDK по-прежнему загружается скриптом.

shopstory-sdk.d.ts

```typescript
type ProductAvailabilityMap = Record<string, boolean>;

type ClientActions = {
  addProductToCartById?: (
    feedProductId: string,
    callback: (success: boolean) => void,
  ) => void;
  addProductToCart?: (
    vendorCode: string,
    callback: (success: boolean) => void,
  ) => void;
  resolveProductsAvailability?: (
    feedProductIds: string[],
    callback: (availability: ProductAvailabilityMap) => void,
  ) => void;
};

type ShopStoryShowOptions = {
  containerElement: Element;
  config: { clientId: string };
  actions?: ClientActions;
  cartUrl?: string;
};

type ShopStoryPlayerParams = {
  clientId: string;
  streamId: string;
};

declare global {
  interface Window {
    ShopStorySDK?: {
      show(options: ShopStoryShowOptions): void;
      showPlayer(params: ShopStoryPlayerParams): Promise<void>;
      refreshProductsAvailability?(): void;
    };
  }
}

export {};
```

Поле `ShopStorySDK` намеренно необязательное: до выполнения bundle объекта нет. По той же причине необязателен `refreshProductsAvailability` — вызывайте его только через проверку существования. Результат корзины и приоритет обработчиков описаны в разделе [Добавление в корзину](<https://docs.shopstory.live/docs/guide/add-to-cart>), карта наличия — в разделе [Наличие и остатки](<https://docs.shopstory.live/docs/guide/product-availability>).

## SPA и lifecycle

Текущий публичный контракт основного SDK рассчитан на один вызов `show()` для одного стабильного container. Публичного `destroy()` нет. В SPA сохраняйте container между route transitions и не вызывайте `show()` из каждого render/effect без собственной защиты от повторной инициализации.

PiP bundle читает согласованный PDP-шаблон и идентификатор товара во время своего lifecycle. До оценки SPA-интеграции передайте ShopStory используемый router, список PDP routes, способ смены SKU и момент замены DOM. Проверка должна охватывать прямой вход, client-side переход между товарами, back/forward и уход с PDP.

## Что включить в оценку

| Work package | Работа клиента | Нужный вход |
| --- | --- | --- |
| Bootstrap | Подключить нужный bundle; для основного SDK передать `clientId`; исключить повторную инициализацию | Выбранная поверхность, MPA/SPA topology и routes |
| Каталог | Создать стабильный container и состояние страницы без SDK | URL каталога и test `applicationId` |
| Product PDP | Сохранить строковый `feedProductId` в согласованном месте | Все PDP/SKU templates и test products |
| Commerce | Выбрать переход на PDP, callback основного SDK или custom PiP flow | Cart API, variant/store context и fallback |
| Наличие | Реализовать обработчик наличия и вызывать `refreshProductsAvailability()` при смене магазина | Пакетный stock API, источник выбранного магазина и семантика `available` в фиде |
| Security | Обновить действующую CSP и проверить registered origins | CSP, media origins и browser matrix |
| Release | Добавить feature flag, acceptance и client-side rollback | Test/live/VOD fixtures и порядок включения |

Если неизвестны SPA lifecycle, целевые браузеры или cart contract, оценка этих частей остаётся discovery scope. Базовый MPA-каталог с переходом на PDP можно оценивать отдельно.
