LeCodesdocs

Push

Удалённые push-уведомления. Как и Geolocation, это сервисный плагин — типизированная обёртка над зарегистрированным хостом сервисом "push" — но большая часть механики живёт вне твоего приложения: хост владеет системным токеном, запросом разрешения и регистрацией на бэкенде le.codes; le.codes ретранслирует твои отправки в APNs/FCM, так что в схеме по умолчанию (приложение LeCodes) ты вообще не касаешься учётных данных Apple/Google. Опционален по хосту — всегда проверяй Push.isSupported.

Обзор

TypeScript
if (Push.isSupported) {
  const { address } = await Push.register({ user: 'u42' })
  // отдай `address` своему бэкенду — или пропусти его вовсе и таргетируй по id `user`
}
Push.addEventListener('message', p => toast(p.title))   // пришло, пока приложение открыто

Дальше твой сервер (или curl) отправляет через реле:

TypeScript
POST https://le.codes/api/projects/<projectUuid>/push/send
Authorization: Bearer lecodes_pk_…        ← a project push key le.codes minted for you (see below)
{ "title": "Order shipped", "users": ["u42"], "url": "myapp://orders/42" }

API

TypeScript
Push.isSupported: boolean                   // зарегистрировал ли этот хост сервис?

Push.getStatus(): Promise<PushStatus>       // никогда не показывает запрос разрешения
Push.register(options?: { user?: string }): Promise<{ address: string }>
Push.unregister(): Promise<void>
Push.getLaunch(): Promise<PushPayload | null>
Push.addEventListener('message' | 'tap', cb: (p: PushPayload) => void): void
Push.removeEventListener('message' | 'tap', cb): void

interface PushPayload {
  title: string
  body?: string
  url?: string                    // deep link — также приходит через app.launchUrl / событие "url"
  data?: Record<string, any>      // твой JSON, ≤ 2 КБ в сериализованном виде
  badge?: number
}
interface PushStatus {
  permission: 'granted' | 'denied' | 'prompt'
  registered: boolean
}
  • Системный запрос разрешения происходит внутри register() — и никогда раньше. register() идемпотентен (безопасен на каждом запуске) и отклоняется с "denied" / "unavailable". На хостах без сервиса каждый метод отклоняется сразу, до любого пути с разрешением.
  • Когда приходит push, твоё приложение не запущено — уведомление показывает ОС. Приложение видит ровно три пути доставки: событие "message" (пришло, пока приложение было открыто — без баннера), событие "tap" (тапнули, пока приложение работало) и Push.getLaunch() (уведомление, холодным стартом запустившее этот сеанс).
  • url в полезной нагрузке — одновременно deep link: он доставляется и через app.launchUrl / событие приложения "url", так что приложения с маршрутизацией по ссылкам получают маршрутизацию уведомлений, не трогая Push.

Идентификация ТВОИХ пользователей

register({ user }) помечает устройство собственным id пользователя твоего приложения, а API отправки принимает users: ["u42"] — один пользователь разворачивается во все его устройства, и твой бэкенд никогда не хранит адреса. Повторная регистрация без user снимает метку (логаут).

Note

id пользователя утверждается клиентом — любое устройство с твоим приложением может заявить любой id и заодно получать уведомления этого пользователя. Годится для «заказ отправлен»; никогда не таргетируй секреты по id пользователя.

Отправка

Во время разработки учётные данные не нужны вовсе — CLI отправляет от твоего логина:

TypeScript
lecodes pn devices                                  # did the device actually register?
lecodes pn send --title "Order shipped" --user u42

Для собственного сервера используй проектный push-ключ (lecodes_pk_…). le.codes его генерирует — выбрать свой нельзя, и показывается он ровно один раз, так что сохрани его при создании:

TypeScript
lecodes pn keys new "prod server" --env             # writes LECODES_PUSH_KEY= into .env

или настройки проекта → Push notificationsNew key (только владелец; панель заодно даёт готовый запрос). Ключ может отправлять push-уведомления ТОЛЬКО для своего проекта — намеренно бесполезен для чего-либо ещё, в отличие от персонального токена доступа, поэтому деплоить нужно именно его. Потерянные ключи не восстанавливаются: выпусти новый и отзови старый. Персональные токены с доступом разработчика тоже работают на этом маршруте (именно их использует lecodes pn send).

Таргетинг: to: [address…], users: [id…] или оба сразу — ответ { sent, failed: [{address, reason}] }. Неизвестные адреса отклоняют весь батч; пользователь без устройств — просто ноль отправок.

Note

push нужен атрибутированный мир — приложение LeCodes знает, какой проект оно запускает, только когда это объявил доверенный лончер (запуски опубликованных проектов по QR / ссылке / из онбординга). Бандлы lecodes dev не атрибутированы, поэтому Push.register() там отклоняется с "unavailable" — тестируй push через опубликованный проект, открытый по QR.

Собственное приложение (standalone-оболочка)

Тот же бандл и тот же код работают в оболочке lecodes app: оболочка регистрирует тот же сервис "push" со своим bundle id и твоим собственным ключом APNs (загруженным в настройки проекта), а твой сервер шлёт точно такой же запрос — реле подбирает учётные данные по регистрации.

Смотрите также