| 1 | import { desktopHost } from "./desktopHost"; |
| 2 | import { releaseMockReadSnapshot } from "./mockReadSnapshot"; |
| 3 | |
| 4 | export type ReadSnapshotPage = { |
| 5 | snapshotId?: string; |
| 6 | snapshotExpiresAt?: number; |
| 7 | staleCursor?: boolean; |
| 8 | readError?: { code: string; reason: string; message: string }; |
| 9 | }; |
| 10 | |
| 11 | // Older hosts encode SessionOperationError in the message; keep that protocol |
| 12 | // compatibility at the bridge boundary rather than in individual components. |
| 13 | export function isStaleRead(error: unknown): boolean { |
| 14 | const value = error as { code?: string; data?: { sessionCode?: string }; message?: string }; |
| 15 | return value?.code === "stale_cursor" || value?.data?.sessionCode === "stale_cursor" |
| 16 | || String(value?.message ?? error).includes("stale_cursor"); |
| 17 | } |
| 18 | |
| 19 | export function assertReadPage(page: ReadSnapshotPage): void { |
| 20 | if (page.staleCursor) throw Object.assign(new Error(page.readError?.message ?? "Read snapshot expired"), { code: "stale_cursor" }); |
| 21 | if (page.readError) throw Object.assign(new Error(page.readError.message), { code: page.readError.code }); |
| 22 | } |
| 23 | |
| 24 | export function releaseReadSnapshot(id?: string): void { |
| 25 | if (!id) return; |
| 26 | const host = desktopHost(); |
| 27 | if (host.kind !== "none") void host.app?.ReleaseReadSnapshot?.(id).catch(() => {}); |
| 28 | else releaseMockReadSnapshot(id); |
| 29 | } |
| 30 |