import type { PushRepository, PushTokenRow } from "../../db/repositories/push.repository"; import type { ApnsClient } from "./apnsClient"; import type { LiveActivityContentState } from "./liveActivityContentState"; /** iOS ends a Live Activity ~8h after it starts. */ export declare const ACTIVITY_MAX_LIFETIME_MS: number; export type LiveActivityEvent = "update" | "end"; export interface LiveActivitySendOutcome { attempted: number; succeeded: number; /** Tokens APNs rejected as permanently unusable, now expired locally. */ retired: number; } /** * The APNs `aps` envelope for an ActivityKit push. * * Key names are Apple's and are not ours to choose: `content-state`, * `stale-date`, and `dismissal-date` are hyphenated, while `timestamp` and * `event` are not. */ interface ActivityKitPayload { aps: { /** Seconds since epoch. iOS discards a push whose timestamp regresses. */ timestamp: number; event: LiveActivityEvent; "content-state": LiveActivityContentState; /** Seconds since epoch. When iOS should start showing the content as stale. */ "stale-date"?: number; "dismissal-date"?: number; }; } export declare function buildActivityKitPayload(args: { event: LiveActivityEvent; contentState: LiveActivityContentState; now: number; staleDate?: number | null; dismissalDate?: number | null; }): ActivityKitPayload; export declare class LiveActivitySender { private readonly apns; private readonly repo; constructor(apns: ApnsClient, repo: PushRepository); /** * Push to every live activity of a session. * * Sends are independent: one rejected token must not stop the others, because * a single dead device would otherwise silence every other device watching the * same session. */ send(args: { sessionId: string; event: LiveActivityEvent; contentState: LiveActivityContentState; now?: number; priority?: 5 | 10; }): Promise; /** * Push to an explicit token list. * * Renewal needs this: a replacement activity does not exist yet, so it is * started via the app-wide push-to-start token rather than any per-session * lookup. Shares one fan-out body with `send()` so failure handling cannot * drift between the two paths. */ sendToTokens(args: { tokens: PushTokenRow[]; sessionId: string; event: LiveActivityEvent; contentState: LiveActivityContentState; now?: number; priority?: 5 | 10; /** Overrides the row's own cap — renewal sets the replacement's window. */ staleDate?: number | null; }): Promise; /** * End every live activity for a session and stop tracking them. * * Expiring locally is what stops the renewal sweep from later resurrecting an * activity for a session that has already finished. */ end(args: { sessionId: string; contentState: LiveActivityContentState; now?: number; }): Promise; private sendToToken; } export {}; //# sourceMappingURL=liveActivitySender.d.ts.map