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

Мост

Мост — единственный выход приложения из песочницы. Объект window.pairx появляется до первого скрипта страницы; его нельзя подменить.

СвойствоЧто это
pairx.versionВерсия моста, сейчас "1.0".
pairx.call(method, params?)Вызов метода; Promise с результатом или ошибкой. Вызов вместе с параметрами — до 64 КиБ JSON.
pairx.on(event, callback)Подписка на событие; возвращает функцию, которая отписывает.
pairx.launchПараметры запуска — неизменяемый объект, см. ниже.
try {
  const { id } = await pairx.call("user.get");
} catch (error) {
  console.log(error.code, error.message);   // "unsupported", "offline", …
}
const off = pairx.on("storage.changed", ({ changes }) => { /* … */ });
off();

Имя метода — сегменты через точку, каждый начинается со строчной латинской буквы: ui.mainButton, storage.write. Неизвестный метод отклоняется с кодом unsupported; проверить заранее — app.supports.

Методы#

МетодЧто делает
app.readyИнтерфейс готов: Pairx убирает заставку.
app.closeЗакрыть приложение.
app.supportsЕсть ли метод в этой версии Pairx — для возможностей, которые появляются позже.
user.getКто открыл приложение. id — человек внутри этого приложения: в другом приложении у него другой ID; по нему нельзя узнать аккаунт Pairx.
context.getГде открыто приложение: общий экземпляр в чате, личный контекст или предпросмотр автора перед отправкой.
ui.themeТема Pairx: светлая или тёмная и её цвета.
ui.safeAreaОтступы от краёв, которые не закрывает Pairx (шапку и нативную кнопку Pairx рисует сам, их отступы уже учтены).
ui.mainButtonНативная кнопка Pairx внизу экрана.
ui.backButton«Назад» в шапке Pairx вместо «Закрыть» — для своих экранов приложения; нажатие приходит событием ui.backButton.clicked.
ui.popupНативное окно; в заголовке Pairx пишет название приложения и «код пользователя», чтобы окно нельзя было выдать за окно Pairx.
ui.toastКороткая подсказка внизу экрана.
storage.snapshotВсё состояние общих данных на одном seq — см. «Общие данные».
storage.writeОдна запись в общее хранилище; операции — в справочнике хранилища.
storage.private.setЛичные данные человека.
clipboard.writeTextСкопировать текст, до 10 000 символов; только по нажатию человека.
diagnostics.errorСообщить об ошибке приложения.

app.ready#

Интерфейс готов: Pairx убирает заставку. Вызывайте сразу, как нарисован первый экран.

Результат: true

app.close#

Закрыть приложение.

Результат: true

app.supports#

Есть ли метод в этой версии Pairx — для возможностей, которые появляются позже.

ПараметрТипЧто
namestringИмя метода.

Результат: boolean

if (await pairx.call('app.supports', { name: 'share.toChat' })) { /* … */ }

user.get#

Кто открыл приложение. id — человек внутри этого приложения: в другом приложении у него другой ID; по нему нельзя узнать аккаунт Pairx.

Результат: { id: string, locale: string }

const { id } = await pairx.call('user.get');

context.get#

Где открыто приложение: общий экземпляр в чате, личный контекст или предпросмотр автора перед отправкой.

Результат: { kind: "chat" | "personal" | "preview", preview: boolean }

ui.theme#

Тема Pairx: светлая или тёмная и её цвета. CSS prefers-color-scheme в приложении следует той же теме.

Результат: { scheme: "light" | "dark", colors: { accent, background, surface, text, muted } }

ui.safeArea#

Отступы от краёв, которые не закрывает Pairx (шапку и нативную кнопку Pairx рисует сам, их отступы уже учтены).

Результат: { top, bottom, left, right }

ui.mainButton#

Нативная кнопка Pairx внизу экрана. Нажатие приходит событием ui.mainButton.clicked.

ПараметрТипЧто
textstringНадпись, до 40 символов; пустая прячет кнопку.
visibleboolean?Показать (по умолчанию true) или спрятать.
enabledboolean?Доступна ли (по умолчанию true).
progressboolean?Индикатор вместо надписи, пока идёт запись.

Результат: true

await pairx.call('ui.mainButton', { text: 'Отправить', visible: true });
pairx.on('ui.mainButton.clicked', send);

ui.backButton#

«Назад» в шапке Pairx вместо «Закрыть» — для своих экранов приложения; нажатие приходит событием ui.backButton.clicked.

ПараметрТипЧто
visiblebooleanПоказать «Назад» (true) или вернуть «Закрыть».

Результат: true

ui.popup#

Нативное окно; в заголовке Pairx пишет название приложения и «код пользователя», чтобы окно нельзя было выдать за окно Pairx. До трёх кнопок; ответ — id нажатой.

ПараметрТипЧто
messagestringТекст, до 500 символов.
buttons{ id, text, type? }[]?Кнопки, надпись до 40 символов; type — cancel или destructive. Без кнопок — одна «OK».

Результат: string

const choice = await pairx.call('ui.popup', {
  message: 'Удалить запись?',
  buttons: [{ id: 'no', text: 'Отмена', type: 'cancel' }, { id: 'yes', text: 'Удалить', type: 'destructive' }],
});

ui.toast#

Короткая подсказка внизу экрана.

ПараметрТипЧто
textstringДо 200 символов.

Результат: true

storage.snapshot#

Всё состояние общих данных на одном seq — см. «Общие данные».

Результат: { seq: number, private: object, stores: { [name]: Store } }

storage.write#

Одна запись в общее хранилище; операции — в справочнике хранилища. Изменение приходит всем участникам, и автору тоже, событием storage.changed на своём месте в порядке; обычно автору — до ответа на вызов, но полагаться на это нельзя.

ПараметрТипЧто
opstringОперация: log.append, log.retract, slot.set, slot.clear, doc.set, counter.add.
storestringИмя хранилища из манифеста.
…Поля операции.

Результат: { seq: number, … }

await pairx.call('storage.write', { op: 'log.append', store: 'queue', value: 'join' });

storage.private.set#

Личные данные человека. Обычно не вызывается напрямую: это делает localStorage.

ПараметрТипЧто
items{ [key]: string }Все пары ключ — строка, до 256 КиБ вместе.

Результат: { ok: true }

clipboard.writeText#

Скопировать текст, до 10 000 символов; только по нажатию человека.

ПараметрТипЧто
textstringТекст.

Результат: true

diagnostics.error#

Сообщить об ошибке приложения. Сейчас Pairx принимает вызов и никуда его не отправляет; отчёты для автора придут позже, без данных хранилища.

ПараметрТипЧто
messagestringЧто случилось.

Результат: true

События#

СобытиеДанныеКогда
storage.changed{ changes: Change[] }Изменения общих данных от всех участников, по порядку seq — см. «Формы изменений».
storage.resetnullПеречитайте снимок: кто-то удалил свои данные или изменений слишком много.
theme.changedThemeТема Pairx сменилась при открытом приложении (сейчас на iPhone; на Android тема задаётся при открытии).
ui.mainButton.clickednullНажата нативная кнопка Pairx.
ui.backButton.clickednullНажата «Назад» в шапке или системный жест «назад».

Ошибки#

Ошибка вызова — Error с полем code:

КодКогда
unsupportedМетода нет, его параметры не те или Pairx в этой версии его не знает.
forbiddenНельзя: не хватает прав (например, писать в хранилище автора) или чужая запись.
consent_requiredЧеловек ещё не дал приложению разрешение.
rate_limitedСлишком часто: больше 10 записей в секунду или 300 в минуту от человека.
too_largeСлишком большое значение, запись, вызов (больше 64 КиБ) или превышен объём хранилища.
conflictДокумент уже изменён: версия устарела — перечитайте снимок и повторите.
offlineНет соединения с Pairx; запись можно повторить с тем же write_id.
not_foundНет такой записи, хранилища или контекста (например, сообщение с приложением удалили).
internalОшибка на стороне Pairx.

Параметры запуска#

pairx.launch есть сразу, без вызова:

ПолеТипЧто
appstringID приложения, 22 символа.
context"chat" | "personal" | "preview"Где открыто: общий экземпляр в чате, личный контекст (по ссылке, из профиля) или предпросмотр автора.
versionnumberНомер версии приложения.
tokenstring?Подписанный токен запуска (Ed25519, aud — ID приложения); пригодится серверам мини-приложений.
userstring?ID человека внутри этого приложения.

Токен запуска#

pairx.launch.token — JWT, который Pairx подписывает при каждом открытии ключом Ed25519. Он нужен, когда у приложения появится свой сервер: сервер проверяет подпись по открытым ключам Pairx и узнаёт, кто и где открыл приложение, без общих секретов. Само приложение токену доверять не должно — внутри песочницы его можно только передать.

Алгоритм EdDSA, издатель pairx-apps, срок — 60 минут. Открытые ключи — https://api.pairx.org/.well-known/pairx-apps-keys.json (JWKS; ключ выбирается по kid из заголовка токена).

ПолеЧто
issВсегда pairx-apps.
audID приложения: токен одного приложения бесполезен для другого.
subID человека внутри приложения — тот же, что в user.get.
iat, expВремя выдачи и окончания, секунды Unix; токен живёт час.
jtiУникальный ID токена.
verНомер запущенной версии.
ctxКонтекст: kind (chat, personal, preview), id, can_write, author; в чате ещё chat (dm, group, self) и role (owner, admin, member).
startПараметр из ссылки pairx.org/app/<id>?start=…, если он был.
nameИмя человека — только с разрешением profile.basic.

Будет позже#

Методы, которые появятся в следующих версиях моста. Проверяйте их через app.supports, а не по версии Pairx:

  • ui.secondaryButton — Вторая нативная кнопка.
  • share.toChat — Отправить приложение с параметром в другой чат.
  • links.openApp — Открыть другое приложение Pairx.
  • context.members — Участники чата (с разрешением chat.members).
  • user.get → name — Имя человека (с разрешением profile.basic).