Pairxдля разработчиков

SDK

@pairx/apps-sdk — тонкая типизированная обёртка над мостом для проектов со сборкой. Без зависимостей, ESM, TypeScript. Всё, что делает SDK, можно сделать и прямыми вызовами pairx.call — SDK избавляет от рутины: порядка seq, storage.reset, повторов при conflict.

npm install https://dev.pairx.org/download/pairx-apps-sdk-0.1.0.tgz

Приложение со сборкой отправляется в Pairx одним HTML-файлом: соберите проект в один файл (для Vite — vite-plugin-singlefile).

Пример: очередь#

import { app, openStorage, ui } from "@pairx/apps-sdk";

const storage = await openStorage();
const queue = storage.log<string>("queue");

function render() {
  const people = queue.entries();
  list.textContent = people.map((e, i) => `${i + 1}. ${e.user === storage.me ? "Вы" : "Участник"}`).join("\n");
  ui.mainButton.setText(queue.mine().length ? "Выйти из очереди" : "Встать в очередь");
}

ui.mainButton.show("Встать в очередь", async () => {
  const mine = queue.mine()[0];
  ui.mainButton.setProgress(true);
  try { mine ? await queue.retract(mine.entry) : await queue.append("join"); }
  finally { ui.mainButton.setProgress(false); }
});
storage.subscribe(render);
render();
await app.ready();

Приложение и человек#

APIЧто делает
app.ready()Убрать заставку Pairx.
app.close()Закрыть приложение.
app.launch()Параметры запуска: приложение, контекст, версия, токен.
user(){ id, locale } — человек внутри этого приложения.
context(){ kind, preview } — где открыто приложение.
inPairx()Запущено ли внутри Pairx (или эмулятора) — для тестов и сборки.
call(method, params), on(event, cb)Прямой доступ к мосту с типами.

Хранилище#

openStorage() читает снимок и подписывается на ленту изменений; дальше состояние всегда текущее.

APIЧто делает
storage.meID текущего человека.
storage.subscribe(cb)Вызывается после каждого применённого изменения и после storage.reset; возвращает отписку.
storage.reload()Перечитать снимок.
storage.log(name)entries(), all() (вместе с убранными), mine(), append(value), retract(entry).
storage.slot(name)get(user?), values(), set(value), clear().
storage.doc(name)value, version, set(value, version?), update(fn) — сам повторяет при conflict.
storage.counter(name)total(key), mine(key), totals(), add(key, amount).
const board = storage.doc<{ items: string[] }>("board");
await board.update((current) => ({ items: [...(current?.items ?? []), "Новый пункт"] }));

Интерфейс#

APIЧто делает
ui.mainButton.show(text, onClick)Показать нативную кнопку; возвращает функцию, которая снимает этот обработчик.
ui.mainButton.setText, setEnabled, setProgress, hide, onClickУправление кнопкой.
ui.backButton.show(onClick), hide(), onClick«Назад» в шапке Pairx.
ui.theme(), ui.onTheme(cb)Тема Pairx и её смена.
ui.applyTheme(theme)Ставит CSS-переменные --pairx-accent, --pairx-background, --pairx-surface, --pairx-text, --pairx-muted и color-scheme.
ui.popup(message, buttons), ui.toast(text)Окна и подсказки Pairx.
clipboard.writeText(text)Копирование по нажатию человека.

Ошибки#

Методы SDK бросают PairxError с полем code — те же коды моста:

import { PairxError } from "@pairx/apps-sdk";

try { await queue.append("join"); }
catch (error) {
  if (error instanceof PairxError && error.code === "rate_limited") ui.toast("Слишком часто");
}

Тесты приложения#

inPairx() отвечает false вне Pairx: логику приложения можно тестировать без моста, подставив свой window.pairx. Сами тесты SDK идут против хозяина Pairx в памяти с правилами хранилища сервиса.