import type { PushRepository, PushTokenRow } from "../../db/repositories/push.repository"; import { type PushEvent } from "./notificationPrefs"; export declare const EXPO_PUSH_ENDPOINT = "https://exp.host/--/api/v2/push/send"; /** Expo accepts at most 100 messages per request. */ export declare const EXPO_PUSH_BATCH_SIZE = 100; export interface ExpoPushMessage { title: string; body: string; /** Delivered to the app as `notification.request.content.data`. */ data: Record; /** iOS plays nothing unless this is set — "default" is the device sound. */ sound?: "default"; /** "high" wakes an Android device immediately instead of batching. */ priority?: "default" | "normal" | "high"; /** iOS: groups one session's notifications into a single stack. */ threadId?: string; /** iOS + Android: a newer push with the same id replaces the shown one. */ collapseId?: string; /** Android: the same replacement, for an already-displayed notification. */ tag?: string; } /** A message fixed for every device, or one built per device's language. */ export type ExpoPushContent = ExpoPushMessage | ((locale: string | null) => ExpoPushMessage); export interface ExpoPushOutcome { /** Tokens the send was actually attempted for, after preferences were applied. */ attempted: number; succeeded: number; /** Tokens Expo rejected as permanently dead, now revoked locally. */ retired: number; /** Deliverable tokens skipped because their owner's preferences said not to send. */ suppressed: number; } export declare class ExpoPushSender { private readonly repo; private readonly accessToken?; /** * @param accessToken Expo access token, when the project has enhanced * security enabled. Optional on purpose: a self-hoster does not own the Expo * project and cannot obtain one, so requiring it would break the deployment * this transport exists to serve. */ constructor(repo: PushRepository, accessToken?: string | undefined); /** * Send one message to every deliverable Expo token whose preferences allow it. * * Sends are independent: Expo returns a ticket per token in one response, so * a dead device is recorded against its own row and never silences the other * devices in the batch. The same holds for preferences — they are applied per * token, so one device's quiet hours never mute another phone. * * `event` names what the push is about so the right toggle applies; leaving * it out sends to every deliverable token regardless of preferences. */ send(message: ExpoPushContent, opts?: { event?: PushEvent; now?: number; }): Promise; /** * Send to exactly these tokens, ignoring preferences. * * For a push the user asked for by name (the settings screen's test button): * muting it because their own quiet hours are on would answer "does delivery * work?" with silence. */ sendTo(rows: PushTokenRow[], message: ExpoPushContent, now?: number): Promise; private deliver; private sendChunk; } //# sourceMappingURL=expoPushSender.d.ts.map