experimental-a2 0.17.0 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +1 -1
  3. package/dist/{actor-DBbe5xeE.d.ts → actor-C7b-1arn.d.ts} +5 -5
  4. package/dist/{actor-DBbe5xeE.d.ts.map → actor-C7b-1arn.d.ts.map} +1 -1
  5. package/dist/actor-client.d.ts +1 -1
  6. package/dist/actor-react.d.ts +3 -3
  7. package/dist/actor-react.js +1 -1
  8. package/dist/actor.d.ts +1 -1
  9. package/dist/actor.js +2 -2
  10. package/dist/{ai-vpGtcaCB.d.ts → ai-BMLlI2Ff.d.ts} +3 -3
  11. package/dist/{ai-vpGtcaCB.d.ts.map → ai-BMLlI2Ff.d.ts.map} +1 -1
  12. package/dist/{ai-UrWfKeuv.js → ai-D6mGlO8j.js} +2 -2
  13. package/dist/{ai-UrWfKeuv.js.map → ai-D6mGlO8j.js.map} +1 -1
  14. package/dist/ai-client.d.ts +2 -2
  15. package/dist/ai-client.js +2 -2
  16. package/dist/ai-fx.browser.d.ts +1 -0
  17. package/dist/ai-fx.browser.js +6 -0
  18. package/dist/ai-fx.browser.js.map +1 -0
  19. package/dist/ai-fx.d.ts +10 -0
  20. package/dist/ai-fx.d.ts.map +1 -0
  21. package/dist/ai-fx.js +692 -0
  22. package/dist/ai-fx.js.map +1 -0
  23. package/dist/ai-harness-B2suP2Qh.d.ts +26 -0
  24. package/dist/ai-harness-B2suP2Qh.d.ts.map +1 -0
  25. package/dist/ai-harness-BuLh_EYi.js +273 -0
  26. package/dist/ai-harness-BuLh_EYi.js.map +1 -0
  27. package/dist/ai-pi.browser.d.ts +1 -0
  28. package/dist/ai-pi.browser.js +6 -0
  29. package/dist/ai-pi.browser.js.map +1 -0
  30. package/dist/ai-pi.d.ts +17 -0
  31. package/dist/ai-pi.d.ts.map +1 -0
  32. package/dist/ai-pi.js +950 -0
  33. package/dist/ai-pi.js.map +1 -0
  34. package/dist/ai-react.d.ts +5 -5
  35. package/dist/ai-react.js +2 -2
  36. package/dist/ai-server.d.ts +47 -25
  37. package/dist/ai-server.d.ts.map +1 -1
  38. package/dist/ai-server.js +113 -40
  39. package/dist/ai-server.js.map +1 -1
  40. package/dist/ai-tool-input-DmSqMUQi.js +40 -0
  41. package/dist/ai-tool-input-DmSqMUQi.js.map +1 -0
  42. package/dist/ai.d.ts +1 -1
  43. package/dist/ai.js +1 -1
  44. package/dist/bounded-cache-CPHWF-8h.js +41 -0
  45. package/dist/bounded-cache-CPHWF-8h.js.map +1 -0
  46. package/dist/{client-COaiaDub.js → client-BhHLoNKF.js} +3 -3
  47. package/dist/{client-COaiaDub.js.map → client-BhHLoNKF.js.map} +1 -1
  48. package/dist/{client-qRnRUzBS.d.ts → client-h_DKFAjj.d.ts} +3 -3
  49. package/dist/{client-qRnRUzBS.d.ts.map → client-h_DKFAjj.d.ts.map} +1 -1
  50. package/dist/client.d.ts +3 -3
  51. package/dist/client.js +1 -1
  52. package/dist/index.d.ts +5 -5
  53. package/dist/{initial-snapshot-BrLso5x_.d.ts → initial-snapshot-Bx-c0pDP.d.ts} +2 -2
  54. package/dist/{initial-snapshot-BrLso5x_.d.ts.map → initial-snapshot-Bx-c0pDP.d.ts.map} +1 -1
  55. package/dist/{internal-CbVvEwad.js → internal-CscSY7K_.js} +11 -3
  56. package/dist/internal-CscSY7K_.js.map +1 -0
  57. package/dist/otel.d.ts +1 -1
  58. package/dist/{react-BbJ-g6Uu.d.ts → react-BBXgHWFc.d.ts} +4 -4
  59. package/dist/{react-BbJ-g6Uu.d.ts.map → react-BBXgHWFc.d.ts.map} +1 -1
  60. package/dist/react.d.ts +1 -1
  61. package/dist/react.js +1 -1
  62. package/dist/reducer-BAXc8JyF.js.map +1 -1
  63. package/dist/{reducer-BYu6DT7h.d.ts → reducer-CqA59Q6U.d.ts} +2 -2
  64. package/dist/{reducer-BYu6DT7h.d.ts.map → reducer-CqA59Q6U.d.ts.map} +1 -1
  65. package/dist/scheduler-qstash.d.ts +2 -2
  66. package/dist/scheduler-qstash.js +3 -3
  67. package/dist/scheduler-qstash.js.map +1 -1
  68. package/dist/scheduler-vercel.d.ts +7 -7
  69. package/dist/scheduler-vercel.d.ts.map +1 -1
  70. package/dist/scheduler-vercel.js +9 -10
  71. package/dist/scheduler-vercel.js.map +1 -1
  72. package/dist/{server-Rj64fNvX.js → server-D-Y4pqwu.js} +126 -67
  73. package/dist/server-D-Y4pqwu.js.map +1 -0
  74. package/dist/{server-CGM8WzRG.d.ts → server-DYAATFuT.d.ts} +42 -7
  75. package/dist/server-DYAATFuT.d.ts.map +1 -0
  76. package/dist/server.d.ts +4 -4
  77. package/dist/server.js +1 -1
  78. package/dist/{session-clear-Dshpuhff.d.ts → session-clear-C-QwTXV1.d.ts} +2 -2
  79. package/dist/session-clear-C-QwTXV1.d.ts.map +1 -0
  80. package/dist/{store-Gpkq7WBo.d.ts → store-CyLUy86v.d.ts} +53 -5
  81. package/dist/store-CyLUy86v.d.ts.map +1 -0
  82. package/dist/store-N8PXxDAS.js.map +1 -1
  83. package/dist/store-memory.d.ts +1 -1
  84. package/dist/store-memory.js +56 -11
  85. package/dist/store-memory.js.map +1 -1
  86. package/dist/{store-polling-4_y8lETm.js → store-polling-7WJV0YWP.js} +2 -2
  87. package/dist/{store-polling-4_y8lETm.js.map → store-polling-7WJV0YWP.js.map} +1 -1
  88. package/dist/store-postgres.d.ts +1 -1
  89. package/dist/store-postgres.d.ts.map +1 -1
  90. package/dist/store-postgres.js +106 -25
  91. package/dist/store-postgres.js.map +1 -1
  92. package/dist/{store-presence-polling-Q1C-k2dd.js → store-presence-polling-B1ixeqIS.js} +3 -3
  93. package/dist/{store-presence-polling-Q1C-k2dd.js.map → store-presence-polling-B1ixeqIS.js.map} +1 -1
  94. package/dist/store-redis-http.d.ts +1 -1
  95. package/dist/store-redis-http.js +3 -3
  96. package/dist/{store-redis-notify-tqWNnMRu.js → store-redis-notify-CM0AfLY0.js} +271 -101
  97. package/dist/store-redis-notify-CM0AfLY0.js.map +1 -0
  98. package/dist/store-redis.d.ts +1 -1
  99. package/dist/store-redis.js +1 -1
  100. package/dist/store-sqlite.d.ts +1 -1
  101. package/dist/store-sqlite.js +66 -21
  102. package/dist/store-sqlite.js.map +1 -1
  103. package/dist/{telemetry-cZH-cibj.d.ts → telemetry-Cyfqo6Qt.d.ts} +2 -2
  104. package/dist/telemetry-Cyfqo6Qt.d.ts.map +1 -0
  105. package/dist/{wire-DjfHOvdW.js → wire-BKxH1vbP.js} +2 -2
  106. package/dist/{wire-DjfHOvdW.js.map → wire-BKxH1vbP.js.map} +1 -1
  107. package/docs/01-quickstart.mdx +49 -83
  108. package/docs/{guides/07-examples.mdx → 02-examples.mdx} +10 -20
  109. package/docs/actors/01-introduction.mdx +48 -86
  110. package/docs/actors/02-concurrency.mdx +43 -70
  111. package/docs/actors/03-timers.mdx +28 -42
  112. package/docs/actors/04-routes.mdx +110 -150
  113. package/docs/actors/meta.ts +1 -1
  114. package/docs/agents/01-introduction.mdx +257 -0
  115. package/docs/agents/02-tools.mdx +247 -0
  116. package/docs/agents/03-conversations.mdx +538 -0
  117. package/docs/agents/04-harnesses.mdx +136 -0
  118. package/docs/agents/meta.ts +1 -0
  119. package/docs/client/01-react.mdx +294 -0
  120. package/docs/client/02-transports.mdx +86 -0
  121. package/docs/client/03-presence.mdx +224 -0
  122. package/docs/client/meta.ts +1 -0
  123. package/docs/contract/01-events.mdx +57 -0
  124. package/docs/contract/02-state.mdx +142 -0
  125. package/docs/contract/03-sessions.mdx +175 -0
  126. package/docs/index.mdx +109 -145
  127. package/docs/reference/01-core.mdx +139 -0
  128. package/docs/reference/02-server.mdx +860 -0
  129. package/docs/reference/03-client.mdx +301 -0
  130. package/docs/reference/04-ai.mdx +731 -0
  131. package/docs/reference/05-adapters.mdx +351 -0
  132. package/docs/reference/06-errors.mdx +138 -0
  133. package/docs/reference/meta.ts +1 -1
  134. package/docs/server/01-handlers.mdx +200 -0
  135. package/docs/server/02-timers.mdx +130 -0
  136. package/docs/server/03-cancellation.mdx +142 -0
  137. package/docs/server/04-routes.mdx +243 -0
  138. package/docs/server/05-production.mdx +323 -0
  139. package/docs/server/06-guarantees.mdx +132 -0
  140. package/examples/playground/DEPLOY.md +3 -5
  141. package/examples/playground/app/a0/[appId]/page.tsx +12 -13
  142. package/examples/playground/app/a0/app-list.tsx +9 -2
  143. package/examples/playground/app/a0/app-view.tsx +9 -1
  144. package/examples/playground/app/a0/apps/[appId]/route.ts +10 -5
  145. package/examples/playground/app/a0/apps.test.ts +12 -0
  146. package/examples/playground/app/a0/apps.ts +22 -7
  147. package/examples/playground/app/a0/chat.tsx +47 -1
  148. package/examples/playground/app/a0/devtools.tsx +2 -8
  149. package/examples/playground/app/a0/fx/events/route.ts +9 -0
  150. package/examples/playground/app/a0/fx/scheduler/route.ts +7 -0
  151. package/examples/playground/app/a0/fx/short/events/route.ts +11 -0
  152. package/examples/playground/app/a0/model.test.ts +18 -1
  153. package/examples/playground/app/a0/model.ts +47 -10
  154. package/examples/playground/app/a0/no-photon.cjs +4 -0
  155. package/examples/playground/app/a0/no-quickjs.cjs +3 -0
  156. package/examples/playground/app/a0/pi/events/route.ts +9 -0
  157. package/examples/playground/app/a0/pi/scheduler/route.ts +7 -0
  158. package/examples/playground/app/a0/pi/short/events/route.ts +11 -0
  159. package/examples/playground/app/a0/sandbox-log.ts +10 -4
  160. package/examples/playground/app/a0/sandbox-session.ts +152 -0
  161. package/examples/playground/app/a0/scheduler/route.ts +2 -2
  162. package/examples/playground/app/a0/server.ts +98 -54
  163. package/examples/playground/app/a0/session.ts +17 -5
  164. package/examples/playground/app/a0/shell.tsx +11 -3
  165. package/examples/playground/app/agent/ingress.test.ts +6 -3
  166. package/examples/playground/app/agent/server.ts +9 -6
  167. package/examples/playground/app/agent/telemetry.test.ts +71 -50
  168. package/examples/playground/app/canvas/[canvasId]/canvas-client.tsx +1 -1
  169. package/examples/playground/app/chat/server.test.ts +30 -26
  170. package/examples/playground/app/chat/server.ts +46 -46
  171. package/examples/playground/next.config.ts +17 -5
  172. package/examples/playground/package.json +4 -1
  173. package/examples/playground/vercel.json +18 -0
  174. package/package.json +27 -3
  175. package/src/ai-agent.ts +271 -90
  176. package/src/ai-fx.browser.ts +5 -0
  177. package/src/ai-fx.ts +912 -0
  178. package/src/ai-harness.ts +518 -0
  179. package/src/ai-model-metadata.ts +11 -6
  180. package/src/ai-pi.browser.ts +5 -0
  181. package/src/ai-pi.ts +1322 -0
  182. package/src/ai-sdk-step.ts +2 -2
  183. package/src/ai-server.ts +3 -1
  184. package/src/ai-tool-input.ts +45 -0
  185. package/src/internal.ts +13 -0
  186. package/src/libfx.d.ts +34 -0
  187. package/src/reducer.ts +1 -1
  188. package/src/scheduler-qstash.ts +5 -5
  189. package/src/scheduler-vercel.ts +14 -15
  190. package/src/server.ts +233 -29
  191. package/src/store-memory.ts +92 -16
  192. package/src/store-postgres.ts +156 -25
  193. package/src/store-redis-core.ts +322 -110
  194. package/src/store-redis-notify.ts +2 -0
  195. package/src/store-sqlite.ts +121 -28
  196. package/src/store.ts +55 -3
  197. package/src/telemetry.ts +1 -0
  198. package/dist/internal-CbVvEwad.js.map +0 -1
  199. package/dist/server-CGM8WzRG.d.ts.map +0 -1
  200. package/dist/server-Rj64fNvX.js.map +0 -1
  201. package/dist/session-clear-Dshpuhff.d.ts.map +0 -1
  202. package/dist/store-Gpkq7WBo.d.ts.map +0 -1
  203. package/dist/store-redis-notify-tqWNnMRu.js.map +0 -1
  204. package/dist/telemetry-cZH-cibj.d.ts.map +0 -1
  205. package/docs/concepts/01-contracts.mdx +0 -237
  206. package/docs/concepts/02-handlers.mdx +0 -284
  207. package/docs/concepts/03-durability.mdx +0 -314
  208. package/docs/concepts/04-state.mdx +0 -209
  209. package/docs/guides/01-timers.mdx +0 -193
  210. package/docs/guides/02-cancellation.mdx +0 -161
  211. package/docs/guides/03-react.mdx +0 -324
  212. package/docs/guides/04-local-first.mdx +0 -47
  213. package/docs/guides/05-production.mdx +0 -534
  214. package/docs/guides/06-ai-agents.mdx +0 -1408
  215. package/docs/guides/08-application-data.mdx +0 -113
  216. package/docs/guides/09-presence.mdx +0 -262
  217. package/docs/guides/10-transports.mdx +0 -221
  218. package/docs/reference/01-api.mdx +0 -2358
  219. package/docs/reference/02-errors.mdx +0 -150
  220. /package/docs/{concepts → contract}/meta.ts +0 -0
  221. /package/docs/{guides → server}/meta.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"client-COaiaDub.js","names":[],"sources":["../src/client-errors.ts","../src/initial-snapshot.ts","../src/client-render-session.ts","../src/client.ts"],"sourcesContent":["import { A2Error, type A2ErrorCode } from './errors.ts'\n\nexport type A2ClientErrorOptions = {\n details?: unknown\n cause?: unknown\n status?: number\n closeCode?: number\n closeReason?: string\n phase?: 'stream' | 'subscribe'\n timeoutMs?: number\n}\n\nexport class A2ClientError extends A2Error {\n readonly status: number | undefined\n readonly closeCode: number | undefined\n readonly closeReason: string | undefined\n readonly phase: 'stream' | 'subscribe' | undefined\n readonly timeoutMs: number | undefined\n\n constructor(\n code: A2ErrorCode,\n message: string,\n options?: A2ClientErrorOptions,\n ) {\n super(code, message, options)\n this.name = 'A2ClientError'\n this.status = options?.status\n this.closeCode = options?.closeCode\n this.closeReason = options?.closeReason\n this.phase = options?.phase\n this.timeoutMs = options?.timeoutMs\n }\n}\n\nexport function asClientError(\n error: unknown,\n options?: { code?: A2ErrorCode },\n): A2ClientError {\n if (error instanceof A2ClientError) return error\n if (error instanceof A2Error) {\n return new A2ClientError(error.code, error.message, {\n details: error.details,\n cause: error,\n })\n }\n return new A2ClientError(\n options?.code ?? 'UNKNOWN',\n error instanceof Error ? error.message : 'client operation failed',\n { cause: error },\n )\n}\n","import type { StateSnapshot } from './reducer.ts'\n\nexport type InitialSnapshot<S> =\n | StateSnapshot<S>\n | null\n | undefined\n | Promise<StateSnapshot<S> | null | undefined>\n\nexport function isInitialPromise<S>(\n initial: InitialSnapshot<S>,\n): initial is Promise<StateSnapshot<S> | null | undefined> {\n return (\n initial !== null &&\n typeof initial === 'object' &&\n 'then' in initial &&\n typeof initial.then === 'function'\n )\n}\n\nexport function observeInitial<S>(options: {\n promise: Promise<StateSnapshot<S> | null | undefined>\n settled(\n result: { value: StateSnapshot<S> | null | undefined } | { error: unknown },\n ): void\n}): () => void {\n let listener: typeof options.settled | undefined = options.settled\n const deliver = (result: Parameters<typeof options.settled>[0]): void => {\n const current = listener\n listener = undefined\n current?.(result)\n }\n void Promise.resolve(options.promise).then(\n (value) => deliver({ value }),\n (error: unknown) => deliver({ error }),\n )\n return () => {\n listener = undefined\n }\n}\n","import type { A2Client, SessionClient, SessionOptions } from './client.ts'\nimport type { EventDefs, PresenceDefs } from './contract.ts'\n\ntype Factory = (sessionId: string, options: unknown) => unknown\ntype ClientReact = {\n factory: Factory\n resolveInitial(options: {\n session: object\n source: object\n value: unknown\n }): void\n}\nconst factories = new WeakMap<object, ClientReact>()\n\nexport function registerRenderSessionFactory(options: {\n client: object\n factory: Factory\n resolveInitial: ClientReact['resolveInitial']\n}): void {\n factories.set(options.client, options)\n}\n\nexport function resolveInitialForReact(options: {\n client: object\n session: object\n source: object\n value: unknown\n}): void {\n factories.get(options.client)?.resolveInitial(options)\n}\n\nexport function createRenderSession<\n D extends EventDefs,\n S,\n P extends PresenceDefs,\n>(options: {\n client: A2Client<D, S, P>\n sessionId: string\n settings: SessionOptions<D, S>\n}): SessionClient<D, S, P> {\n const factory = factories.get(options.client)\n if (!factory)\n throw new TypeError('React requires a client returned by createClient')\n return factory.factory(options.sessionId, options.settings) as SessionClient<\n D,\n S,\n P\n >\n}\n","/**\n * experimental-a2/client — the framework-agnostic session client.\n *\n * Everything the browser needs to read a session live and push\n * optimistically, with no framework attached: the SSE subscription with\n * frontier resume and reconnection, the optimistic push queue with\n * ack/rollback, and the local fold through the same reducer the server\n * uses. `experimental-a2/react`'s `createReact` is a thin binding over it, and the\n * store contract (`subscribe`/`getSnapshot`) is exactly what\n * `useSyncExternalStore` wants.\n *\n * The client is a replica, never an access path — the routes it talks\n * to authorize every read and write.\n */\n\n// oxlint-disable no-await-in-loop -- retry/backoff/stream loops are sequential by nature\nimport { decodeState, projectClientState } from './reducer-runtime.ts'\nimport { A2ClientError, asClientError } from './client-errors.ts'\nimport {\n isInitialPromise,\n observeInitial,\n type InitialSnapshot,\n} from './initial-snapshot.ts'\nimport { registerRenderSessionFactory } from './client-render-session.ts'\nimport {\n PRESENCE_TIMINGS,\n RESERVED_PARTICIPANT_IDS,\n STREAM_TIMINGS,\n nullProtoRecord,\n} from './internal.ts'\nimport type {\n AppendInput,\n Contract,\n ContractEvent,\n EventDefs,\n PresenceDefs,\n PresenceMap,\n PresencePatch,\n WithPresence,\n} from './contract.ts'\nimport { foldEvent, type Reducer, type StateSnapshot } from './reducer.ts'\nimport { isSessionCleared } from './session-clear.ts'\nimport { validateSync } from './validate.ts'\nimport {\n isStateSnapshotFrame,\n type StateSnapshotFrame,\n type SubscriptionStart,\n errorFromWire,\n eventFromCompactWire,\n eventFromWire,\n isCompactWireEvent,\n isWireEvent,\n isWirePresencePatch,\n isWirePresenceSnapshot,\n parseSocketFrame,\n presencePatchFromWire,\n presenceSnapshotFromWire,\n type SocketDownFrame,\n type SocketPresenceFrame,\n type SocketPushFrame,\n type SocketSubscribeFrame,\n type SocketUnsubscribeFrame,\n type WireEvent,\n type WirePresencePatch,\n type WirePresenceSnapshot,\n} from './wire.ts'\nimport type { Event } from './store.ts'\n\nexport { A2ClientError } from './client-errors.ts'\nexport type { StateSnapshot } from './reducer.ts'\nexport type { InitialSnapshot } from './initial-snapshot.ts'\nexport type { A2ClientErrorOptions } from './client-errors.ts'\n\nexport type ReconnectPolicy = (failure: {\n sessionId: string\n error: A2ClientError | null\n attempt: number\n}) => number | false\n\nexport type ConnectionStatus =\n 'idle' | 'connecting' | 'paused' | 'live' | 'closed'\n\n/**\n * The connection, as a discriminated union — impossible states are\n * unrepresentable: an error only exists while disconnected,\n * `reconnects` only once a connection has been attempted.\n * \"Reconnecting…\" is `status === 'connecting' && reconnects > 0`.\n */\nexport type Connection =\n | { status: 'idle' }\n | {\n status: 'connecting'\n /** Stream restarts so far. `0` = first connect. */\n reconnects: number\n /** Why the last connection ended; `null` on the first connect. */\n error: A2ClientError | null\n }\n | { status: 'paused'; reconnects: number; error: A2ClientError | null }\n | { status: 'live'; reconnects: number }\n | { status: 'closed' }\n\n/**\n * What `push` returns: resolves at the server ack (exactly like a\n * plain promise — `await push(...)` gives the acked events), and\n * carries `confirmed` for the later moment when the live stream has\n * delivered the whole batch back and the optimistic overlay entry\n * retired — the view now shows server truth. `confirmed` is lazy:\n * never accessed, never created. A rejected push rejects both.\n */\nexport type PushResult<D extends EventDefs> = Promise<ContractEvent<D>[]> & {\n readonly confirmed: Promise<ContractEvent<D>[]>\n}\n\nexport type LoadHistoryOptions = {\n /**\n * Exclusive upper bound for the fetch. Defaults to the oldest\n * already-loaded index — successive calls page backward — or one\n * past the hydration frontier while nothing is loaded yet.\n */\n before?: number\n /** Page size; defaults to 50. */\n limit?: number\n}\n\n/** Backscroll progress, derived from the raw event feed. */\nexport type HistoryState = {\n /** A `loadHistory` fetch is in flight. */\n loading: boolean\n /** The feed reaches index 1 — nothing older remains to fetch. */\n complete: boolean\n /** The oldest loaded index; `null` while nothing is loaded. */\n oldestLoaded: number | null\n}\n\n/** One immutable view of the session — stable identity between changes. */\nexport type SessionSnapshot<\n D extends EventDefs,\n S,\n P extends PresenceDefs = Record<never, never>,\n> = WithPresence<\n P,\n {\n /** The replicated presence map, this client included (local echo). */\n presence: PresenceMap<P>\n }\n> & {\n /** The live view: server events folded, optimistic pushes applied. */\n state: S\n /** A state/index snapshot has been applied; independent of connection status. */\n hydrated: boolean\n /** The raw event feed: server truth — observed, seeded, or\n * backscrolled via `loadHistory` — plus pending optimistic events\n * (provisional indexes past the frontier). `state` never folds\n * backscrolled events; they are display data below the frontier. */\n events: ContractEvent<D>[]\n /** The latest server-confirmed state index. This is the\n * `lastSeenIndex` cancellation wants. */\n index: number\n /** Backscroll progress — `loadHistory` moves it. */\n history: HistoryState\n connection: Connection\n}\n\n/**\n * The presence member of a client session — intersected in via\n * `WithPresence`, so it exists exactly when the contract declares\n * presence fields.\n */\nexport type SessionClientPresence<P extends PresenceDefs> = {\n /**\n * Fire-and-forget presence: validates locally against the reducer's\n * presence schemas, merges into the local map immediately (the\n * echo), and coalesces on the wire to a fixed cadence — a leading\n * send immediately, then at most one merged send per interval,\n * later values winning field-wise. `null` clears a field. No ack,\n * no retry, no rollback: a lost patch is repainted by the next one.\n * Requires the session's `participant`.\n */\n setPresence(values: PresencePatch<P>['values']): void\n}\n\nexport type SessionClient<\n D extends EventDefs,\n S,\n P extends PresenceDefs = Record<never, never>,\n> = WithPresence<P, SessionClientPresence<P>> & {\n readonly sessionId: string\n subscribe(listener: () => void): () => void\n getSnapshot(): SessionSnapshot<D, S, P>\n /**\n * Optimistic append: validates locally against the reducer's event\n * schemas (instant `INVALID_PAYLOAD`, no flicker), applies to the\n * local fold, POSTs, swaps in the ack, rolls back on rejection.\n * Auto-retries `STORE_UNAVAILABLE` and transport failures. Resolves with the appended\n * events as the server recorded them. Overlapping calls on this\n * handle enter the transport in invocation order without delaying\n * their optimistic folds.\n */\n push(...events: AppendInput<D>[]): PushResult<D>\n /**\n * Backscroll: fetch a bounded slice of events from below the\n * frontier and merge it into `events` — deduped, ordered, shared by\n * every handle of this session. Folded state and the optimistic\n * overlay are never touched. Calls serialize per session and skip\n * already-loaded ranges, so overlapping backscrolls never fetch the\n * same range twice. Resolves with the events in the requested range.\n * Requires an http api; the `ws` transport has no history lane and\n * this throws a TypeError there.\n */\n loadHistory(options?: LoadHistoryOptions): Promise<ContractEvent<D>[]>\n /**\n * Take a lease on the live stream and return its release. Leases\n * refcount per handle — the first connects, releasing the last\n * closes — so independent consumers of one identity-mapped handle\n * (two hooks, a hook plus vanilla code) never fight over the\n * stream. Releasing twice is a no-op. While any lease is held the\n * stream follows the client's reconnection policy and resumes after\n * its last streamed event.\n */\n connect(): () => void\n /** Restart a leased subscription immediately after its last streamed event.\n * Preserves state, pending writes, and leases. No-op without a lease. */\n reconnect(): void\n /**\n * The hard stop: drops every outstanding lease and closes the\n * stream now. Not terminal — a later `connect()` starts fresh from\n * the last streamed event.\n */\n close(): void\n}\n\nexport type SessionOptions<D extends EventDefs, S> = {\n initial?: InitialSnapshot<S>\n /** Server-rendered history through `initial.index`. Seeds the event feed. */\n initialEvents?: ContractEvent<D>[]\n /** Overrides the client's `participant` for this session handle.\n * Bound once per handle. */\n participant?: string\n}\n\nfunction assertSessionSeed(options: { initial?: unknown } | undefined): void {\n const initial = options?.initial\n if (initial == null || isInitialPromise(initial as InitialSnapshot<unknown>))\n return\n if (\n initial === null ||\n typeof initial !== 'object' ||\n !Object.hasOwn(initial, 'state') ||\n !Object.hasOwn(initial, 'index') ||\n !('index' in initial) ||\n typeof initial.index !== 'number' ||\n !Number.isSafeInteger(initial.index) ||\n initial.index < 0\n )\n throw new TypeError(\n 'initial must contain state and a non-negative safe integer index',\n )\n const clearIndex = (initial as { clearIndex?: unknown }).clearIndex\n if (\n clearIndex !== undefined &&\n (typeof clearIndex !== 'number' ||\n !Number.isSafeInteger(clearIndex) ||\n clearIndex < 0 ||\n clearIndex > initial.index)\n )\n throw new TypeError(\n 'initial.clearIndex must be a non-negative safe integer no greater than its index',\n )\n}\n\nexport type A2Client<\n D extends EventDefs,\n S,\n P extends PresenceDefs = Record<never, never>,\n> = {\n session(\n sessionId: string,\n options?: SessionOptions<D, S>,\n ): SessionClient<D, S, P>\n}\n\n/**\n * The wire the client rides. The first form is one route serving GET\n * (SSE stream) + POST (push). `http` splits the verbs across two\n * routes, for when platform duration limits differ per verb. `ws`\n * rides everything over WebSocket, one socket per session by default.\n * Multiplexing every session of the client is an explicit opt-in.\n */\nexport type SessionUrl = string | ((sessionId: string) => string)\n\nexport type ClientApi =\n | SessionUrl // one route: GET SSE stream + POST push\n | { type: 'http'; push: SessionUrl; stream: SessionUrl } // split routes\n /** One socket per session. */\n | { type: 'ws'; url: SessionUrl; multiplex?: false }\n /** One socket for every session of this client. */\n | { type: 'ws'; url: string; multiplex: true }\n\n/**\n * The socket surface the `ws` transport drives — satisfied structurally\n * by the DOM `WebSocket` and Node's alike, and small enough to fake in\n * tests.\n */\nexport type ClientWebSocket = {\n readonly readyState: number\n send(data: string): void\n close(code?: number, reason?: string): void\n addEventListener(type: 'open', listener: () => void): void\n addEventListener(\n type: 'message',\n listener: (event: { data: unknown }) => void,\n ): void\n addEventListener(\n type: 'close',\n listener: (event: { code: number; reason: string }) => void,\n ): void\n addEventListener(type: 'error', listener: () => void): void\n}\n\nexport type ClientWebSocketConstructor = new (url: string) => ClientWebSocket\n\nexport type CreateClientOptions<\n D extends EventDefs,\n S,\n P extends PresenceDefs = Record<never, never>,\n> = {\n contract: Contract<D, P, Reducer<D, S, P>>\n /** The route (or routes) the client speaks — see `ClientApi`. */\n api: ClientApi\n /** Delay the next connection attempt in milliseconds, or pause with false. */\n reconnect?: ReconnectPolicy\n /** Injectable fetch — defaults to the global. */\n fetch?: typeof globalThis.fetch\n /** Injectable WebSocket constructor for the `ws` api — defaults to\n * the global. The http transports never touch it. */\n webSocket?: ClientWebSocketConstructor\n /** How long an idle session keeps its in-memory identity, in\n * milliseconds. Defaults to five minutes; `Infinity` disables GC. */\n gcTime?: number\n /**\n * This client's presence identity — required to call `setPresence`.\n * Caller-supplied (a user id, a tab nonce, a guest name): A2 does\n * not invent an identity story; the app states it once here. The\n * default for every session handle this client creates;\n * `session(id, { participant })` overrides it per handle.\n */\n participant?: string\n}\n\nconst PUSH_ATTEMPTS = 3\nconst RETRYABLE_PUSH_CODES = new Set([\n 'STORE_UNAVAILABLE',\n 'TIMEOUT',\n 'HTTP_ERROR',\n 'CONNECTION_FAILED',\n 'UNKNOWN',\n])\nconst DEFAULT_GC_TIME_MS = 5 * 60 * 1_000\nconst DEFAULT_HISTORY_LIMIT = 50\n\n// ── the transport seam ───────────────────────────────────────────────\n// Everything above it — optimistic queue, retry loop, presence\n// throttle, reconnect/backoff, stall watchdog — is transport-agnostic.\n\n/** The parsed frame lanes every transport yields: the SSE frame\n * discrimination today, the ws `kind` discriminant tomorrow. `ping`\n * carries no data — it exists so the watchdog sees liveness. */\ntype TransportFrame =\n | StateSnapshotFrame\n | { kind: 'event'; event: WireEvent }\n | { kind: 'events'; events: Event[] }\n | { kind: 'presence'; patch: WirePresencePatch }\n | { kind: 'presence-snapshot'; snapshot: WirePresenceSnapshot }\n | { kind: 'activity'; idle: boolean }\n | { kind: 'ping' }\n\ntype TransportPushBody = {\n sessionId: string\n events: Array<{ id: string; type: string; payload: unknown }>\n}\n\ntype TransportPresenceEnvelope = {\n sessionId: string\n presence: {\n participant: string\n values: Record<string, unknown>\n seen: number\n at: number\n }\n}\n\ntype Transport = {\n /**\n * One live read: the first frame means the stream is established\n * (any kind — a bare `ping` when no data is pending), the iterable\n * ending or throwing is the disconnect. The caller owns\n * reconnect/backoff and counts every frame as liveness.\n */\n connect(opts: {\n sessionId: string\n startAfter: number | undefined\n reducer: string\n signal: AbortSignal\n }): AsyncIterable<TransportFrame>\n /** One attempt (the retry loop lives above the seam): resolves with\n * the acked wire events, throws A2ClientError. */\n push(body: TransportPushBody): Promise<WireEvent[]>\n /** One bounded cold read of the log, oldest first — the lane\n * `loadHistory` rides. Absent on transports without a\n * request/response wire (ws), where `loadHistory` fails fast. */\n history?(opts: {\n sessionId: string\n gte: number\n lte: number\n }): Promise<{ events: WireEvent[]; clearIndex?: number }>\n /** Fire-and-forget; failures are dropped (presence repaints). */\n sendPresence(envelope: TransportPresenceEnvelope): void\n /**\n * Resolve when the session's wire can carry a push again, or after\n * `maxWaitMs` — whichever comes first; never rejects. Transports\n * whose pushes are connection-bound (ws) implement it so the retry\n * loop waits for the wire instead of a fixed clock; HTTP pushes are\n * stream-independent and omit it.\n */\n awaitReady?(sessionId: string, maxWaitMs: number): Promise<void>\n}\n\nconst sessionUrl = (url: SessionUrl, sessionId: string): string => {\n const resolved = typeof url === 'function' ? url(sessionId) : url\n if (typeof resolved !== 'string') {\n throw new TypeError('a session URL function must return a string')\n }\n return resolved\n}\n\nconst httpError = async (response: Response): Promise<A2ClientError> => {\n const error = errorFromWire(await response.json().catch(() => null))\n return error === null\n ? new A2ClientError(\n 'HTTP_ERROR',\n `request failed with ${response.status}`,\n {\n status: response.status,\n },\n )\n : new A2ClientError(error.code, error.message, {\n details: error.details,\n status: response.status,\n cause: error,\n })\n}\n\nconst httpTransport = (\n routes: { push: SessionUrl; stream: SessionUrl },\n fetchImpl: typeof globalThis.fetch,\n // Contracts that declare no presence skip presence frames unparsed,\n // exactly like unknown named frames.\n presence: boolean,\n): Transport => ({\n async *connect({ sessionId, startAfter, reducer: reducerName, signal }) {\n const streamUrl = sessionUrl(routes.stream, sessionId)\n const sep = streamUrl.includes('?') ? '&' : '?'\n const res = await fetchImpl(\n `${streamUrl}${sep}${new URLSearchParams({ sessionId, reducer: reducerName, wire: '2', ...(startAfter === undefined ? { bootstrap: '1' } : { index: String(startAfter) }) })}`,\n { headers: { accept: 'text/event-stream' }, signal },\n )\n if (!res.ok) throw await httpError(res)\n if (!res.body) {\n throw new A2ClientError('UNKNOWN', 'stream response has no body', {\n status: res.status,\n })\n }\n yield { kind: 'ping' } // connected — headers in hand, before any bytes\n const decoder = new TextDecoder()\n const reader = res.body.getReader()\n let buffer = ''\n try {\n for (;;) {\n // oxlint-disable-next-line no-await-in-loop -- stream read loop\n const { done, value } = await reader.read()\n if (done) return\n // Any bytes count — heartbeat comments included. Liveness is\n // about the connection, not about events.\n yield { kind: 'ping' }\n buffer += decoder.decode(value, { stream: true })\n for (;;) {\n const boundary = buffer.indexOf('\\n\\n')\n if (boundary === -1) break\n const frame = buffer.slice(0, boundary)\n buffer = buffer.slice(boundary + 2)\n let eventName: string | undefined\n const dataLines: string[] = []\n for (const line of frame.split('\\n')) {\n if (line.startsWith('data:')) {\n dataLines.push(line.slice(5).trimStart())\n } else if (line.startsWith('event:')) {\n eventName = line.slice(6).trim()\n }\n }\n const data = dataLines.join('\\n')\n if (!data) continue\n if (eventName === undefined) {\n const parsed: unknown = JSON.parse(data)\n // A version 2 server batches events; an older one sends one.\n if (Array.isArray(parsed)) {\n // Dropping a batch would leave a gap the frontier then skips past.\n if (!parsed.every(isCompactWireEvent))\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n 'invalid event batch',\n )\n yield {\n kind: 'events',\n events: parsed.map((row) =>\n eventFromCompactWire(row, sessionId),\n ),\n }\n } else if (isWireEvent(parsed))\n yield { kind: 'event', event: parsed }\n } else if (eventName === 'a2-snapshot') {\n const parsed: unknown = JSON.parse(data)\n if (!isStateSnapshotFrame(parsed))\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n 'invalid bootstrap snapshot',\n )\n yield parsed\n } else if (presence && eventName === 'presence-snapshot') {\n const parsed: unknown = JSON.parse(data)\n if (isWirePresenceSnapshot(parsed)) {\n yield { kind: 'presence-snapshot', snapshot: parsed }\n }\n } else if (presence && eventName === 'presence') {\n const parsed: unknown = JSON.parse(data)\n if (isWirePresencePatch(parsed)) {\n yield { kind: 'presence', patch: parsed }\n }\n } else if (\n eventName === 'a2-activity' &&\n (data === 'idle' || data === 'active')\n ) {\n yield { kind: 'activity', idle: data === 'idle' }\n }\n // Other named frames: skipped — old clients stay compatible\n // with future lanes the same way.\n }\n }\n } finally {\n reader.cancel().catch(() => {})\n }\n },\n\n async push(body) {\n const res = await fetchImpl(sessionUrl(routes.push, body.sessionId), {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n })\n if (res.ok) {\n const rows = (await res.json()) as unknown\n if (!Array.isArray(rows) || !rows.every(isWireEvent)) {\n throw new A2ClientError(\n 'STORE_UNAVAILABLE',\n 'push ack was not a list of events',\n )\n }\n return rows\n }\n throw await httpError(res)\n },\n\n async history({ sessionId, gte, lte }) {\n const streamUrl = sessionUrl(routes.stream, sessionId)\n const sep = streamUrl.includes('?') ? '&' : '?'\n const res = await fetchImpl(\n `${streamUrl}${sep}sessionId=${encodeURIComponent(sessionId)}&gte=${gte}&lte=${lte}`,\n { headers: { accept: 'application/json' } },\n )\n if (!res.ok) {\n throw await httpError(res)\n }\n const rows = (await res.json()) as unknown\n if (!Array.isArray(rows) || !rows.every(isWireEvent)) {\n throw new A2ClientError(\n 'STORE_UNAVAILABLE',\n 'history response was not a list of events',\n )\n }\n const clearIndex = Number(res.headers.get('a2-clear-index') ?? Number.NaN)\n return Number.isSafeInteger(clearIndex) && clearIndex > 0\n ? { events: rows, clearIndex }\n : { events: rows }\n },\n\n sendPresence(envelope) {\n void (async () => {\n try {\n const res = await fetchImpl(\n sessionUrl(routes.push, envelope.sessionId),\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(envelope),\n },\n )\n await res.arrayBuffer()\n } catch {\n // Dropped by design — nothing was ever true.\n }\n })()\n },\n})\n\n/** `WebSocket.OPEN` — fixed by the spec, identical in every runtime. */\nconst WS_OPEN = 1\n\ntype PendingAck = {\n resolve: (events: WireEvent[]) => void\n reject: (error: A2ClientError) => void\n}\n\nconst webSocketUrl = (value: string): URL => {\n let resolved: URL\n if (/^(https?|wss?):\\/\\//i.test(value)) {\n resolved = new URL(value)\n } else {\n const base = (globalThis as { location?: { href: string } }).location?.href\n if (base === undefined) {\n throw new TypeError(\n `cannot resolve the relative ws url '${value}' without a browser location — pass an absolute ws:// or wss:// url`,\n )\n }\n resolved = new URL(value, base)\n }\n if (resolved.protocol === 'http:') resolved.protocol = 'ws:'\n else if (resolved.protocol === 'https:') resolved.protocol = 'wss:'\n return resolved\n}\n\nconst socketReadyWaiters = () => {\n const sessions = new Map<string, Set<() => void>>()\n\n const notify = (sessionId: string): void => {\n const waiters = sessions.get(sessionId)\n if (!waiters) return\n sessions.delete(sessionId)\n for (const waiter of waiters) waiter()\n }\n\n const wait = (sessionId: string, maxWaitMs: number): Promise<void> =>\n new Promise((resolve) => {\n let waiters = sessions.get(sessionId)\n if (!waiters) {\n waiters = new Set()\n sessions.set(sessionId, waiters)\n }\n let settled = false\n const done = (): void => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n waiters.delete(done)\n if (waiters.size === 0) sessions.delete(sessionId)\n // oxlint-disable-next-line promise/no-multiple-resolved -- `settled` guards the timer and notification callers\n resolve()\n }\n const timer = setTimeout(done, maxWaitMs)\n ;(timer as { unref?: () => void }).unref?.()\n waiters.add(done)\n })\n\n return { notify, wait }\n}\n\nconst rejectPendingAcks = (pending: Map<number, PendingAck>): void => {\n if (pending.size === 0) return\n const error = new A2ClientError(\n 'STORE_UNAVAILABLE',\n 'socket closed with the ack outstanding',\n )\n for (const waiter of pending.values()) waiter.reject(error)\n pending.clear()\n}\n\nconst sessionWsTransport = (\n url: SessionUrl,\n webSocketImpl: ClientWebSocketConstructor | undefined,\n presence: boolean,\n): Transport => {\n type SocketConnection = {\n socket: ClientWebSocket\n pending: Map<number, PendingAck>\n }\n\n const connections = new Map<string, SocketConnection>()\n const ready = socketReadyWaiters()\n let nextReq = 1\n\n const socketUrl = (\n sessionId: string,\n startAfter: number | undefined,\n reducerName: string,\n ): string => {\n const resolved = webSocketUrl(sessionUrl(url, sessionId))\n resolved.searchParams.set('sessionId', sessionId)\n resolved.searchParams.delete('index')\n resolved.searchParams.delete('bootstrap')\n resolved.searchParams.set('reducer', reducerName)\n resolved.searchParams.set('wire', '2')\n if (startAfter === undefined) resolved.searchParams.set('bootstrap', '1')\n else resolved.searchParams.set('index', String(startAfter))\n return resolved.href\n }\n\n return {\n async *connect({ sessionId, startAfter, reducer: reducerName, signal }) {\n if (webSocketImpl === undefined) {\n throw new TypeError(\n 'no WebSocket implementation available — pass one via createClient({ webSocket }) where the global is missing',\n )\n }\n const socket = new webSocketImpl(\n socketUrl(sessionId, startAfter, reducerName),\n )\n const connection: SocketConnection = { socket, pending: new Map() }\n connections.set(sessionId, connection)\n\n const queue: TransportFrame[] = []\n let ended = false\n let failure: Error | null = null\n let wake: (() => void) | null = null\n const notify = (): void => {\n wake?.()\n wake = null\n }\n const finish = (error: Error | null): void => {\n if (ended) return\n ended = true\n failure = error\n if (connections.get(sessionId) === connection) {\n connections.delete(sessionId)\n ready.notify(sessionId)\n }\n rejectPendingAcks(connection.pending)\n notify()\n }\n\n socket.addEventListener('open', () => {\n if (connections.get(sessionId) !== connection || ended) return\n queue.push({ kind: 'ping' })\n notify()\n ready.notify(sessionId)\n })\n socket.addEventListener('message', (event) => {\n if (connections.get(sessionId) !== connection || ended) return\n if (typeof event.data !== 'string') return\n let frame: SocketDownFrame | null\n try {\n frame = parseSocketFrame(event.data)\n } catch (error) {\n finish(asClientError(error))\n return\n }\n if (frame === null) return\n switch (frame.kind) {\n case 'snapshot':\n queue.push(frame)\n break\n case 'ack': {\n const waiter = connection.pending.get(frame.req)\n if (waiter === undefined) return\n connection.pending.delete(frame.req)\n if (\n frame.sessionId !== undefined ||\n ('events' in frame &&\n frame.events.some((row) => row.sessionId !== sessionId))\n ) {\n waiter.reject(\n new A2ClientError(\n 'STORE_UNAVAILABLE',\n 'ack does not belong to the socket session',\n ),\n )\n return\n }\n if ('events' in frame) waiter.resolve(frame.events)\n else waiter.reject(asClientError(frame.error))\n return\n }\n case 'event':\n if (frame.event.sessionId !== sessionId) return\n queue.push({ kind: 'event', event: frame.event })\n break\n case 'events':\n if (frame.sessionId !== undefined) return\n queue.push({\n kind: 'events',\n events: frame.events.map((row) =>\n eventFromCompactWire(row, sessionId),\n ),\n })\n break\n case 'presence':\n if (presence && frame.sessionId === undefined) {\n queue.push({ kind: 'presence', patch: frame.patch })\n }\n break\n case 'presence-snapshot':\n if (presence && frame.sessionId === undefined) {\n queue.push({\n kind: 'presence-snapshot',\n snapshot: frame.snapshot,\n })\n }\n break\n case 'ping':\n queue.push(frame)\n break\n case 'subscribed':\n case 'unsubscribed':\n return\n }\n notify()\n })\n socket.addEventListener('close', (event) => {\n finish(\n event.code === 1000\n ? null\n : new A2ClientError(\n 'CONNECTION_FAILED',\n `socket closed (${event.code}${event.reason ? `: ${event.reason}` : ''})`,\n { closeCode: event.code, closeReason: event.reason },\n ),\n )\n })\n socket.addEventListener('error', () => {\n finish(new A2ClientError('CONNECTION_FAILED', 'socket error'))\n })\n\n const onAbort = (): void => {\n finish(\n signal.reason instanceof Error\n ? signal.reason\n : new Error('stream aborted'),\n )\n try {\n socket.close(1000)\n } catch {\n // Already closed.\n }\n }\n if (signal.aborted) onAbort()\n else signal.addEventListener('abort', onAbort, { once: true })\n\n try {\n for (;;) {\n while (queue.length > 0) yield queue.shift()!\n if (ended) {\n if (failure) throw failure\n return\n }\n await new Promise<void>((resolve) => {\n wake = resolve\n })\n }\n } finally {\n signal.removeEventListener('abort', onAbort)\n finish(null)\n try {\n socket.close(1000)\n } catch {\n // Already closed.\n }\n }\n },\n\n async push(body) {\n const connection = connections.get(body.sessionId)\n if (\n connection === undefined ||\n connection.socket.readyState !== WS_OPEN\n ) {\n throw new A2ClientError(\n 'STORE_UNAVAILABLE',\n 'no open socket for the session',\n )\n }\n const req = nextReq\n nextReq += 1\n return await new Promise<WireEvent[]>((resolve, reject) => {\n connection.pending.set(req, { resolve, reject })\n const frame: SocketPushFrame = {\n kind: 'push',\n req,\n events: body.events,\n }\n try {\n connection.socket.send(JSON.stringify(frame))\n } catch (cause) {\n connection.pending.delete(req)\n reject(\n new A2ClientError('STORE_UNAVAILABLE', 'socket send failed', {\n cause,\n }),\n )\n }\n })\n },\n\n awaitReady(sessionId, maxWaitMs) {\n const connection = connections.get(sessionId)\n if (connection?.socket.readyState === WS_OPEN) return Promise.resolve()\n return ready.wait(sessionId, maxWaitMs)\n },\n\n sendPresence(envelope) {\n const connection = connections.get(envelope.sessionId)\n if (\n connection === undefined ||\n connection.socket.readyState !== WS_OPEN\n ) {\n return\n }\n const frame: SocketPresenceFrame = {\n kind: 'presence',\n ...envelope.presence,\n }\n try {\n connection.socket.send(JSON.stringify(frame))\n } catch {\n return\n }\n },\n }\n}\n\n/** One session's lane on the shared ws socket — created per `connect`\n * attempt, so `startAfter` is that attempt's resume frontier. */\ntype WsChannel = {\n sessionId: string\n /** Echoed on this lane's subscribe answers. An answer to an earlier\n * attempt for the same session must not confirm or end this one;\n * data frames from that attempt precede this attempt's confirmation. */\n attempt: number\n startAfter: number | undefined\n reducer: string\n queue: TransportFrame[]\n /** The server confirmed the subscribe — pushes and presence ride. */\n live: boolean\n /** The server already dropped it — no unsubscribe frame owed. */\n dropped: boolean\n ended: boolean\n failure: Error | null\n wake: (() => void) | null\n}\n\nconst wakeChannel = (channel: WsChannel): void => {\n channel.wake?.()\n channel.wake = null\n}\n\nconst answersAttempt = (\n frame: { attempt?: number },\n channel: WsChannel,\n): boolean => frame.attempt === undefined || frame.attempt === channel.attempt\n\nconst subscriptionStart = (\n index: number | undefined,\n reducer: string,\n): SubscriptionStart =>\n index === undefined ? { bootstrap: true, reducer } : { index, reducer }\n\nconst subscribeFrame = (sessions: SocketSubscribeFrame['sessions']): string => {\n const frame: SocketSubscribeFrame = { kind: 'subscribe', sessions }\n return JSON.stringify(frame)\n}\n\nconst multiplexedWsTransport = (\n url: string,\n webSocketImpl: ClientWebSocketConstructor | undefined,\n presence: boolean,\n): Transport => {\n // ONE socket serves every session of this client (specs §13's\n // multiplexed superset): channels subscribe on it at their own\n // frontiers, down frames route back by sessionId, acks by req.\n const channels = new Map<string, WsChannel>()\n const pending = new Map<number, PendingAck>()\n /** Push retries parked in `awaitReady`, flushed per session on its\n * subscribe confirmation. */\n const ready = socketReadyWaiters()\n let socket: ClientWebSocket | null = null\n let socketOpen = false\n let watchdog: ReturnType<typeof setTimeout> | undefined\n let nextReq = 1\n let nextAttempt = 1\n\n const trySend = (data: string): void => {\n if (socket === null || !socketOpen) return\n try {\n socket.send(data)\n } catch {\n // Dropped — the socket is going down and its close event settles\n // everything that depended on this frame.\n }\n }\n\n const deliver = (channel: WsChannel, frame: TransportFrame): void => {\n channel.queue.push(frame)\n wakeChannel(channel)\n }\n\n const settleChannel = (channel: WsChannel, failure: Error | null): void => {\n if (channel.ended) return\n channel.ended = true\n channel.failure = failure\n wakeChannel(channel)\n }\n\n // Unhook the socket from the transport state and reject every\n // outstanding ack — nothing was acked, and the client-generated ids\n // make the retries idempotent (§13).\n const releaseSocket = (): ClientWebSocket | null => {\n const current = socket\n socket = null\n socketOpen = false\n clearTimeout(watchdog)\n watchdog = undefined\n rejectPendingAcks(pending)\n return current\n }\n\n // Idempotent from every direction (close event, error event, stall):\n // every channel ends — each session's reconnect loop re-subscribes at\n // its own current frontier.\n const failSocket = (failure: Error | null): void => {\n const current = releaseSocket()\n for (const channel of channels.values()) settleChannel(channel, failure)\n try {\n current?.close(1000)\n } catch {\n // Already closed — it is down either way.\n }\n }\n\n const detach = (channel: WsChannel): void => {\n if (channels.get(channel.sessionId) !== channel) return\n channels.delete(channel.sessionId)\n ready.notify(channel.sessionId)\n if (!channel.dropped) {\n const frame: SocketUnsubscribeFrame = {\n kind: 'unsubscribe',\n sessions: [channel.sessionId],\n }\n trySend(JSON.stringify(frame))\n }\n if (channels.size === 0) {\n // The last session left — the shared socket has no reason to live.\n const current = releaseSocket()\n try {\n current?.close(1000)\n } catch {\n // Already closed — it is down either way.\n }\n }\n }\n\n // One heartbeat watchdog per socket: any frame is liveness, and\n // silence past the stall timeout means the connection is dead in a\n // way the socket won't report.\n const armWatchdog = (created: ClientWebSocket): void => {\n clearTimeout(watchdog)\n watchdog = setTimeout(() => {\n if (socket !== created) return\n failSocket(\n new A2ClientError(\n 'TIMEOUT',\n `socket stalled: no data for ${STREAM_TIMINGS.stallTimeoutMs}ms`,\n { phase: 'stream', timeoutMs: STREAM_TIMINGS.stallTimeoutMs },\n ),\n )\n }, STREAM_TIMINGS.stallTimeoutMs)\n ;(watchdog as { unref?: () => void }).unref?.()\n }\n\n const route = (frame: SocketDownFrame): void => {\n switch (frame.kind) {\n case 'snapshot': {\n const channel = channels.get(frame.sessionId)\n if (channel && channel.live && !channel.ended) deliver(channel, frame)\n return\n }\n case 'ping': {\n // Global liveness — every live channel's stall watchdog feeds\n // on it, the way each SSE stream feeds on its own heartbeat.\n for (const channel of channels.values()) {\n if (channel.live && !channel.ended) {\n deliver(channel, { kind: 'ping' })\n }\n }\n return\n }\n case 'subscribed': {\n const channel = channels.get(frame.sessionId)\n if (\n channel === undefined ||\n channel.ended ||\n channel.live ||\n !answersAttempt(frame, channel)\n )\n return\n channel.live = true\n deliver(channel, { kind: 'ping' }) // the connected signal\n ready.notify(frame.sessionId)\n return\n }\n case 'unsubscribed': {\n const channel = channels.get(frame.sessionId)\n if (channel === undefined || !answersAttempt(frame, channel)) return\n channel.dropped = true\n settleChannel(\n channel,\n frame.error\n ? asClientError(frame.error)\n : frame.reason === undefined\n ? null\n : new A2ClientError('CONNECTION_FAILED', frame.reason),\n )\n return\n }\n case 'ack': {\n const waiter = pending.get(frame.req)\n if (waiter === undefined) return\n pending.delete(frame.req)\n if ('events' in frame) waiter.resolve(frame.events)\n else waiter.reject(asClientError(frame.error))\n return\n }\n case 'event': {\n // Pre-confirmation frames are safe to drop: the subscription\n // being confirmed replays from this channel's own frontier.\n const channel = channels.get(frame.event.sessionId)\n if (channel !== undefined && channel.live && !channel.ended) {\n deliver(channel, { kind: 'event', event: frame.event })\n }\n return\n }\n case 'events': {\n const { sessionId } = frame\n if (sessionId === undefined) return\n const channel = channels.get(sessionId)\n if (channel !== undefined && channel.live && !channel.ended) {\n deliver(channel, {\n kind: 'events',\n events: frame.events.map((row) =>\n eventFromCompactWire(row, sessionId),\n ),\n })\n }\n return\n }\n case 'presence': {\n // Contracts that declare no presence skip presence frames,\n // exactly like the http transport.\n if (!presence || frame.sessionId === undefined) return\n const channel = channels.get(frame.sessionId)\n if (channel !== undefined && channel.live && !channel.ended) {\n deliver(channel, { kind: 'presence', patch: frame.patch })\n }\n return\n }\n case 'presence-snapshot': {\n if (!presence || frame.sessionId === undefined) return\n const channel = channels.get(frame.sessionId)\n if (channel !== undefined && channel.live && !channel.ended) {\n deliver(channel, {\n kind: 'presence-snapshot',\n snapshot: frame.snapshot,\n })\n }\n return\n }\n }\n }\n\n const ensureSocket = (): void => {\n if (socket !== null) return\n if (webSocketImpl === undefined) {\n throw new TypeError(\n 'no WebSocket implementation available — pass one via createClient({ webSocket }) where the global is missing',\n )\n }\n const target = webSocketUrl(url)\n target.searchParams.set('wire', '2')\n const created = new webSocketImpl(target.href)\n socket = created\n socketOpen = false\n armWatchdog(created)\n created.addEventListener('open', () => {\n if (socket !== created) return\n socketOpen = true\n armWatchdog(created)\n const sessions = [...channels.values()]\n .filter((channel) => !channel.ended)\n .map((channel) => ({\n id: channel.sessionId,\n attempt: channel.attempt,\n ...subscriptionStart(channel.startAfter, channel.reducer),\n }))\n if (sessions.length > 0) trySend(subscribeFrame(sessions))\n })\n created.addEventListener('message', (event) => {\n if (socket !== created) return\n if (typeof event.data !== 'string') return\n armWatchdog(created)\n let frame: SocketDownFrame | null\n try {\n frame = parseSocketFrame(event.data)\n } catch (error) {\n failSocket(asClientError(error))\n return\n }\n if (frame === null) return\n route(frame)\n })\n created.addEventListener('close', (event) => {\n if (socket !== created) return\n failSocket(\n event.code === 1000\n ? null // deliberate server close — reconnect, but not an error\n : new A2ClientError(\n 'CONNECTION_FAILED',\n `socket closed (${event.code}${event.reason ? `: ${event.reason}` : ''})`,\n { closeCode: event.code, closeReason: event.reason },\n ),\n )\n })\n created.addEventListener('error', () => {\n if (socket !== created) return\n failSocket(new A2ClientError('CONNECTION_FAILED', 'socket error'))\n })\n }\n\n return {\n async *connect({ sessionId, startAfter, reducer: reducerName, signal }) {\n const channel: WsChannel = {\n sessionId,\n attempt: nextAttempt++,\n startAfter,\n reducer: reducerName,\n queue: [],\n live: false,\n dropped: false,\n ended: false,\n failure: null,\n wake: null,\n }\n channels.set(sessionId, channel)\n try {\n ensureSocket()\n if (socketOpen) {\n trySend(\n subscribeFrame([\n {\n id: sessionId,\n attempt: channel.attempt,\n ...subscriptionStart(startAfter, reducerName),\n },\n ]),\n )\n }\n } catch (error) {\n if (channels.get(sessionId) === channel) channels.delete(sessionId)\n throw error\n }\n\n const onAbort = (): void => {\n settleChannel(\n channel,\n signal.reason instanceof Error\n ? signal.reason\n : new Error('stream aborted'),\n )\n // Synchronously, not from the pump's finally: the watchdog and\n // close() must not leave a dead subscription behind.\n detach(channel)\n }\n if (signal.aborted) onAbort()\n else signal.addEventListener('abort', onAbort, { once: true })\n\n // An unconfirmed subscribe receives no frames at all (global\n // pings only feed live channels), so a server that never answers\n // — a single-session route, say — would hang this session\n // silently. Fail it loudly instead; the reconnect loop retries.\n const pendingSubscribe = setTimeout(() => {\n if (channel.live) return\n settleChannel(\n channel,\n new A2ClientError(\n 'TIMEOUT',\n 'subscribe not confirmed: is the ws route calling server.fetch with upgradeWebSocket?',\n { phase: 'subscribe', timeoutMs: STREAM_TIMINGS.stallTimeoutMs },\n ),\n )\n }, STREAM_TIMINGS.stallTimeoutMs)\n ;(pendingSubscribe as { unref?: () => void }).unref?.()\n\n try {\n for (;;) {\n while (channel.queue.length > 0) yield channel.queue.shift()!\n if (channel.ended) {\n if (channel.failure) throw channel.failure\n return\n }\n // oxlint-disable-next-line no-await-in-loop -- frame pump\n await new Promise<void>((resolve) => {\n channel.wake = resolve\n })\n }\n } finally {\n clearTimeout(pendingSubscribe)\n signal.removeEventListener('abort', onAbort)\n settleChannel(channel, null)\n detach(channel)\n }\n },\n\n async push(body) {\n const channel = channels.get(body.sessionId)\n const target = socket\n if (\n channel === undefined ||\n !channel.live ||\n channel.ended ||\n target === null ||\n !socketOpen ||\n target.readyState !== WS_OPEN\n ) {\n // Retryable by contract: the reconnect loop restores the\n // socket and the retry rides the same event ids.\n throw new A2ClientError(\n 'STORE_UNAVAILABLE',\n 'no open socket for the session',\n )\n }\n const req = nextReq\n nextReq += 1\n return await new Promise<WireEvent[]>((resolve, reject) => {\n pending.set(req, { resolve, reject })\n const frame: SocketPushFrame = {\n kind: 'push',\n req,\n sessionId: body.sessionId,\n events: body.events,\n }\n try {\n target.send(JSON.stringify(frame))\n } catch (cause) {\n pending.delete(req)\n reject(\n new A2ClientError('STORE_UNAVAILABLE', 'socket send failed', {\n cause,\n }),\n )\n }\n })\n },\n\n awaitReady(sessionId, maxWaitMs) {\n const channel = channels.get(sessionId)\n if (\n channel !== undefined &&\n channel.live &&\n !channel.ended &&\n socketOpen\n ) {\n return Promise.resolve()\n }\n return ready.wait(sessionId, maxWaitMs)\n },\n sendPresence(envelope) {\n const channel = channels.get(envelope.sessionId)\n if (channel === undefined || !channel.live || channel.ended) {\n return // dropped by design — the reconnect re-send covers the gap\n }\n const frame: SocketPresenceFrame = {\n kind: 'presence',\n sessionId: envelope.sessionId,\n ...envelope.presence,\n }\n trySend(JSON.stringify(frame))\n },\n }\n}\n\nconst transportFor = (\n api: ClientApi,\n fetchImpl: typeof globalThis.fetch,\n webSocketImpl: ClientWebSocketConstructor | undefined,\n presence: boolean,\n): Transport => {\n if (typeof api === 'string' || typeof api === 'function') {\n return httpTransport({ push: api, stream: api }, fetchImpl, presence)\n }\n if (api.type === 'http') {\n return httpTransport(\n { push: api.push, stream: api.stream },\n fetchImpl,\n presence,\n )\n }\n if (api.multiplex === true) {\n if (typeof api.url !== 'string') {\n throw new TypeError('a multiplexed WebSocket URL must be a string')\n }\n return multiplexedWsTransport(api.url, webSocketImpl, presence)\n }\n return sessionWsTransport(api.url, webSocketImpl, presence)\n}\n\ntype Pending<D extends EventDefs> = {\n id: string\n type: string\n payload: unknown\n createdAt: Date\n /** Set once the POST ack returns; the entry leaves the overlay when\n * the stream delivers its index. */\n acked?: ContractEvent<D>\n sent?: true\n /** Sent before the current baseline was adopted and not yet acked:\n * the baseline may already contain it, so only its ack index can\n * place it in the overlay. */\n heldUntilAck?: true\n}\n\ntype ResolvedSessionOptions<D extends EventDefs, S> = Omit<\n SessionOptions<D, S>,\n 'initial'\n> & {\n initial?: StateSnapshot<S> | null | undefined\n}\n\ntype PendingInitial<D extends EventDefs, S> = {\n source: Promise<StateSnapshot<S> | null | undefined>\n version: number\n settings: Omit<SessionOptions<D, S>, 'initial'>\n cancel(): void\n error?: A2ClientError\n}\n\ntype SessionRuntime<\n D extends EventDefs,\n S,\n P extends PresenceDefs,\n> = SessionClient<D, S, P> & {\n hydrate(options?: SessionOptions<D, S>): void\n resolveInitial(options: { source: object; value: unknown }): void\n canEvict(): boolean\n}\n\ntype CachedSession<D extends EventDefs, S, P extends PresenceDefs> = {\n runtime: SessionRuntime<D, S, P>\n timer?: ReturnType<typeof setTimeout>\n}\n\nexport function createClient<\n D extends EventDefs,\n S,\n P extends PresenceDefs = Record<never, never>,\n>(options: CreateClientOptions<D, S, P>): A2Client<D, S, P> {\n const { contract, api } = options\n const reducer = contract?.reducer\n if (!reducer)\n throw new TypeError(\n 'createClient requires a contract with a public reducer',\n )\n const presenceDefs: Readonly<PresenceDefs> = contract.presence\n const declaresPresence = Object.keys(presenceDefs).length > 0\n const fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis)\n const clientFetch: typeof globalThis.fetch = async (input, init) => {\n try {\n return await fetchImpl(input, init)\n } catch (error) {\n throw asClientError(error, { code: 'CONNECTION_FAILED' })\n }\n }\n const webSocketImpl =\n options.webSocket ??\n (globalThis as { WebSocket?: ClientWebSocketConstructor }).WebSocket\n const transport = transportFor(\n api,\n clientFetch,\n webSocketImpl,\n declaresPresence,\n )\n const gcTime = options.gcTime ?? DEFAULT_GC_TIME_MS\n if (Number.isNaN(gcTime) || gcTime < 0) {\n throw new RangeError('gcTime must be a non-negative number or Infinity')\n }\n const sessions = new Map<string, CachedSession<D, S, P>>()\n\n const scheduleGc = (sessionId: string, delay = gcTime): void => {\n const entry = sessions.get(sessionId)\n if (!entry) return\n clearTimeout(entry.timer)\n if (gcTime === Infinity) return\n entry.timer = setTimeout(() => {\n const current = sessions.get(sessionId)\n if (current !== entry) return\n if (entry.runtime.canEvict()) {\n entry.runtime.close()\n clearTimeout(entry.timer)\n sessions.delete(sessionId)\n return\n }\n // `gcTime: 0` is useful for tests and explicit no-cache clients,\n // but must not spin while a session is mounted or a push is in flight.\n scheduleGc(sessionId, Math.max(gcTime, 1_000))\n }, delay)\n ;(entry.timer as { unref?: () => void }).unref?.()\n }\n\n const touch = (sessionId: string): void => {\n scheduleGc(sessionId)\n }\n\n const makeSession = (\n sessionId: string,\n sessionOptions?: SessionOptions<D, S>,\n ): SessionRuntime<D, S, P> => {\n assertSessionSeed(sessionOptions)\n // ── server truth ─────────────────────────────────────────────\n const supplied = sessionOptions?.initial\n const initial = isInitialPromise(supplied) ? undefined : supplied\n let hydrated = initial != null\n let bootstrapGeneration: number | undefined\n let stateIndex = initial?.index ?? 0\n let streamIndex = initial?.index\n let foldedState: S = initial == null ? reducer.initialState : initial.state\n /** The latest clear marker this session has learned of, or 0. */\n let clearIndex = initial?.clearIndex ?? 0\n let initialVersion = 0\n const seenInitials = new WeakSet<object>()\n if (initial != null) seenInitials.add(initial)\n let preload: PendingInitial<D, S> | undefined\n const serverEvents: ContractEvent<D>[] = (\n sessionOptions?.initialEvents ?? []\n )\n .filter((event) => event.index <= stateIndex && event.index > clearIndex)\n .toSorted((a, b) => a.index - b.index)\n\n // ── optimistic overlay ───────────────────────────────────────\n let pending: Pending<D>[] = []\n\n // ── the presence plane ───────────────────────────────────────\n // Never cached, never folded. Foreign entries replicate from the\n // stream; the own entry is the local echo — server copies of self\n // are ignored (the echo is at least as new, and comparing it to\n // server stamps would put two clocks in one order).\n let participant = sessionOptions?.participant ?? options.participant\n // Participant and field keys arrive off the wire, so the map and\n // every entry are built null-prototype — see `nullProtoRecord`.\n let presenceState: PresenceMap = nullProtoRecord()\n let presenceLastSentAt = 0\n /** The last LWW stamp issued — see `nextPresenceAt`. */\n let presenceLastAt = 0\n /** Values awaiting the trailing send — non-null exactly while\n * `presenceTimer` is armed. */\n let presenceBuffer: Record<string, unknown> | null = null\n let presenceTimer: ReturnType<typeof setTimeout> | undefined\n /** Own fields set while the stream was down — re-sent once on\n * reconnect (their POSTs may have been lost with the network). */\n let presenceResend: Record<string, unknown> | null = null\n\n // ── store plumbing ───────────────────────────────────────────\n const listeners = new Set<() => void>()\n let snapshot: SessionSnapshot<D, S, P> | null = null\n let status: ConnectionStatus = 'idle'\n let reconnects = 0\n let lastError: A2ClientError | null = null\n let inFlightPushes = 0\n let pushWireTail: Promise<void> = Promise.resolve()\n let deferredHydration:\n { settings: ResolvedSessionOptions<D, S>; version?: number } | undefined\n let resumeInitialError: A2ClientError | undefined\n let hydrationNotification: ReturnType<typeof setTimeout> | undefined\n\n const emit = (): void => {\n // copy: a listener may unsubscribe (or subscribe) mid-notify\n // oxlint-disable-next-line no-useless-spread\n for (const listener of [...listeners]) listener()\n }\n\n const notify = (): void => {\n snapshot = null\n emit()\n }\n\n const notifyHydrated = (resume?: A2ClientError): void => {\n resumeInitialError ??= resume\n // `session(id, serverFold)` is also called while a destination\n // provider renders. Its own snapshot must advance synchronously,\n // but notifying an outgoing provider during that render would be a\n // React setState-in-render violation.\n snapshot = null\n clearTimeout(hydrationNotification)\n hydrationNotification = setTimeout(() => {\n const failure = resumeInitialError\n resumeInitialError = undefined\n if (failure && active && status === 'paused' && lastError === failure)\n reconnectStream()\n else emit()\n }, 0)\n ;(hydrationNotification as { unref?: () => void }).unref?.()\n }\n\n const mergeServerEvents = (\n events: ContractEvent<D>[] | undefined,\n throughIndex: number,\n ): boolean => {\n if (!events || events.length === 0) return false\n const byIndex = new Map(serverEvents.map((event) => [event.index, event]))\n let changed = false\n for (const event of events) {\n // Also drops rows from responses that began before a newer clear.\n if (event.index > throughIndex || event.index <= clearIndex) continue\n const existing = byIndex.get(event.index)\n if (existing?.id === event.id) continue\n byIndex.set(event.index, event)\n changed = true\n }\n if (!changed) return false\n serverEvents.splice(\n 0,\n serverEvents.length,\n ...[...byIndex.values()].toSorted((a, b) => a.index - b.index),\n )\n return true\n }\n\n /**\n * Raise the latest known clear marker (a2-implementation.md §17.4):\n * drop the served history it ended and every push acked below it.\n * The boundary never moves backward.\n */\n const applyClearBoundary = (index: number): boolean => {\n if (index <= clearIndex) return false\n clearIndex = index\n const kept = serverEvents.filter((event) => event.index > index)\n serverEvents.splice(0, serverEvents.length, ...kept)\n pending = pending.filter(\n (entry) => entry.acked === undefined || entry.acked.index > index,\n )\n return true\n }\n\n const overlayEvents = (): ContractEvent<D>[] => {\n // Acked entries first (they have a server-assigned order), then\n // unacked in push order with provisional indexes.\n const acked = pending\n .filter((p) => p.acked)\n .map((p) => p.acked!)\n .toSorted((a, b) => a.index - b.index)\n const maxKnown = Math.max(stateIndex, acked.at(-1)?.index ?? stateIndex)\n const waiting = pending.filter((p) => !p.acked)\n const held = waiting.findIndex((p) => p.heldUntilAck)\n // Later pushes may depend on a held one, so they stay hidden with it.\n const unacked = (held === -1 ? waiting : waiting.slice(0, held)).map(\n (p, i) =>\n ({\n id: p.id,\n type: p.type,\n payload: p.payload,\n index: maxKnown + 1 + i, // provisional\n sessionId,\n createdAt: p.createdAt,\n }) as ContractEvent<D>,\n )\n return [...acked, ...unacked]\n }\n\n const connection = (): Connection => {\n switch (status) {\n case 'idle':\n return { status: 'idle' }\n case 'closed':\n return { status: 'closed' }\n case 'live':\n return { status: 'live', reconnects }\n case 'connecting':\n case 'paused':\n return { status, reconnects, error: lastError }\n }\n }\n\n const historyState = (): HistoryState => {\n const oldestLoaded = serverEvents[0]?.index ?? null\n return {\n loading: historyLoads > 0,\n // The first event of the lifetime loaded — or a state index at\n // its start, an empty lifetime as far as this client knows —\n // means nothing older is left to fetch.\n complete:\n hydrated &&\n (oldestLoaded === clearIndex + 1 || stateIndex === clearIndex),\n oldestLoaded,\n }\n }\n\n const buildSnapshot = (): SessionSnapshot<D, S, P> => {\n const overlay = overlayEvents()\n let state = foldedState\n for (const event of hydrated ? overlay : []) {\n if (event.index > stateIndex) state = reducer.fold(state, event)\n }\n const displayedOverlay = overlay.filter((event) => {\n if (event.index > stateIndex) return true\n let low = 0\n let high = serverEvents.length - 1\n while (low <= high) {\n const middle = Math.floor((low + high) / 2)\n const observed = serverEvents[middle]!\n if (observed.index === event.index) return observed.id !== event.id\n if (observed.index < event.index) low = middle + 1\n else high = middle - 1\n }\n return true\n })\n return {\n state: projectClientState({ reducer, state }),\n hydrated,\n events: [...serverEvents, ...displayedOverlay],\n index: stateIndex,\n history: historyState(),\n connection: connection(),\n ...(declaresPresence\n ? { presence: presenceState as PresenceMap<P> }\n : {}),\n } as SessionSnapshot<D, S, P>\n }\n\n // ── presence ─────────────────────────────────────────────────\n /**\n * The per-session monotonic LWW stamp: wall-seeded, guarded\n * `max(now, last + 1)`, so overlapping sends can never invert —\n * the wall clock seeds it because it is the only monotonic state\n * that survives a reload without A2 owning persistence.\n */\n const nextPresenceAt = (): number => {\n presenceLastAt = Math.max(Date.now(), presenceLastAt + 1)\n return presenceLastAt\n }\n\n // Copy-on-write throughout: snapshots alias `presenceState`, so\n // every change replaces the map and the touched entry instead of\n // mutating them.\n const applyPresencePatch = (patch: PresencePatch): void => {\n if (patch.participant === participant) return // the echo is self truth\n const entry: PresenceMap[string] = Object.assign(\n nullProtoRecord<PresenceMap[string]>(),\n presenceState[patch.participant],\n )\n let changed = false\n for (const [field, value] of Object.entries(patch.values)) {\n if (value === undefined) continue\n const existing = entry[field]\n // Field-wise LWW: an older stamp loses, a tie goes to the wire.\n if (existing && existing.at.getTime() > patch.at.getTime()) continue\n if (value === null) {\n if (existing) {\n delete entry[field]\n changed = true\n }\n } else {\n entry[field] = { value, seen: patch.seen, at: patch.at }\n changed = true\n }\n }\n if (!changed) return\n const next = Object.assign(nullProtoRecord<PresenceMap>(), presenceState)\n if (Object.keys(entry).length === 0) delete next[patch.participant]\n else next[patch.participant] = entry\n presenceState = next\n notify()\n }\n\n const applyPresenceSnapshot = (incoming: PresenceMap): void => {\n const next: PresenceMap = nullProtoRecord()\n for (const [id, fields] of Object.entries(incoming)) {\n if (id === participant) continue\n next[id] = fields\n }\n // Foreign entries replaced wholesale; the own echo survives.\n const own =\n participant === undefined ? undefined : presenceState[participant]\n if (participant !== undefined && own !== undefined)\n next[participant] = own\n presenceState = next\n notify()\n }\n\n const echoPresence = (\n id: string,\n values: Record<string, unknown>,\n atMs: number,\n ): void => {\n const entry: PresenceMap[string] = Object.assign(\n nullProtoRecord<PresenceMap[string]>(),\n presenceState[id],\n )\n const at = new Date(atMs)\n for (const [field, value] of Object.entries(values)) {\n if (value === null) delete entry[field]\n else entry[field] = { value, seen: stateIndex, at }\n }\n const next = Object.assign(nullProtoRecord<PresenceMap>(), presenceState)\n if (Object.keys(entry).length === 0) delete next[id]\n else next[id] = entry\n presenceState = next\n notify()\n }\n\n // One send, fire-and-forget: no retry, no rollback, failures\n // dropped silently — the next send repaints. Sends are NOT\n // serialized on the ack and may overlap in flight: safe, because\n // merges are LWW by `at` per (participant, field) and one\n // sender's stamps are monotonic. `seen` is the state index at send\n // time, not at set time; `at` is the sender's monotonic stamp.\n const sendPresence = (\n values: Record<string, unknown>,\n at: number,\n ): void => {\n presenceLastSentAt = Date.now()\n transport.sendPresence({\n sessionId,\n // Every path here starts at setPresence, which requires the\n // participant.\n presence: { participant: participant!, values, seen: stateIndex, at },\n })\n touch(sessionId)\n }\n\n // The fixed-cadence throttle: a set outside the interval sends on\n // the leading edge; within it, values merge field-wise into one\n // trailing send at the boundary. The cadence never couples to RTT\n // — waiting on the ack served no purpose on this plane and\n // stretched remote motion on slow links.\n const queuePresenceSend = (\n values: Record<string, unknown>,\n at?: number,\n ): void => {\n if (presenceTimer !== undefined) {\n presenceBuffer = { ...presenceBuffer, ...values }\n return\n }\n const wait =\n presenceLastSentAt + PRESENCE_TIMINGS.sendIntervalMs - Date.now()\n if (wait <= 0) {\n sendPresence(values, at ?? nextPresenceAt())\n return\n }\n presenceBuffer = { ...presenceBuffer, ...values }\n presenceTimer = setTimeout(() => {\n presenceTimer = undefined\n const buffered = presenceBuffer\n presenceBuffer = null\n // The trailing send stamps at fire time — always past every\n // stamp its merged values echoed with.\n if (buffered) sendPresence(buffered, nextPresenceAt())\n }, wait)\n ;(presenceTimer as { unref?: () => void }).unref?.()\n }\n\n const setPresence = (values: PresencePatch<P>['values']): void => {\n if (participant === undefined) {\n throw new TypeError(\n 'setPresence requires a participant — pass one to createClient({ participant }) or in the session options (the SessionProvider/useSession participant prop)',\n )\n }\n const validated: Record<string, unknown> = nullProtoRecord()\n for (const [field, value] of Object.entries(values)) {\n if (value === undefined) continue\n // '*' is a catch-all vocabulary entry: any field name (bar\n // object-plumbing names) validates against it. The actor\n // module's follower reducer declares it — the browser cannot\n // know a server-defined vocabulary, so the server stays the\n // authority.\n const schema = Object.hasOwn(presenceDefs, field)\n ? presenceDefs[field]\n : RESERVED_PARTICIPANT_IDS.has(field)\n ? undefined\n : presenceDefs['*']\n if (!schema) {\n throw new A2ClientError(\n 'UNKNOWN_PRESENCE_FIELD',\n `no presence field '${field}' in the reducer's vocabulary`,\n )\n }\n if (value === null) {\n validated[field] = null\n continue\n }\n const result = validateSync(schema, value, `presence field '${field}'`)\n if (result.issues) {\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n `invalid value for presence field '${field}'`,\n { details: result.issues },\n )\n }\n validated[field] = result.value\n }\n if (Object.keys(validated).length === 0) return\n // One stamp per set: the echo and a leading send share it, so\n // the local map and the wire agree on this write's LWW position.\n const at = nextPresenceAt()\n echoPresence(participant, validated, at)\n if (status !== 'live') {\n presenceResend = { ...presenceResend, ...validated }\n }\n queuePresenceSend(validated, at)\n touch(sessionId)\n }\n\n /** Pushes awaiting stream confirmation — resolved the moment the\n * stream, by event or bootstrap snapshot, passes their batch. */\n let confirmWatchers: Array<{\n index: number\n resolve: () => void\n lease?: true\n }> = []\n\n const resolveConfirmed = (): void => {\n const delivered = streamIndex ?? 0\n const due = confirmWatchers.filter(\n (watcher) => watcher.index <= delivered,\n )\n if (due.length === 0) return\n confirmWatchers = confirmWatchers.filter(\n (watcher) => watcher.index > delivered,\n )\n for (const watcher of due) watcher.resolve()\n }\n\n // State hydration does not subsume delivery: unobserved ACKs still\n // keep an idle stream catching up even when their state is covered.\n const retireCoveredPending = (): void => {\n pending = pending.filter(\n (entry) =>\n !entry.acked ||\n entry.acked.index > Math.min(stateIndex, streamIndex ?? stateIndex),\n )\n }\n\n const adoptBaseline = (baseline: StateSnapshot<S>): void => {\n hydrated = true\n stateIndex = baseline.index\n foldedState = baseline.state\n for (const entry of pending)\n if (entry.sent && !entry.acked) entry.heldUntilAck = true\n retireCoveredPending()\n }\n\n const bootstrapState = (frame: StateSnapshotFrame): S => {\n let state: S\n try {\n state = decodeState({\n reducer,\n state: frame.stateUndefined ? undefined : frame.state,\n }) as S\n } catch (error) {\n throw asClientError(error, { code: 'INVALID_PAYLOAD' })\n }\n if (!reducer.stateSchema) return state\n const result = validateSync(\n reducer.stateSchema,\n state,\n 'bootstrap stateSchema',\n )\n if (result.issues)\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n 'bootstrap state failed stateSchema',\n { details: result.issues },\n )\n return result.value\n }\n\n /** The single ingest point: every server-confirmed event, in log\n * order, from the stream. */\n // A batch is folded whole before listeners hear about it, once.\n const ingest = (events: readonly ContractEvent<D>[]): void => {\n let delivered = false\n for (const event of events) {\n if (event.index <= (streamIndex ?? 0)) continue\n delivered = true\n streamIndex = event.index\n const cleared = isSessionCleared(event)\n // A marker at or below a newer hydrated fold is already reflected in it.\n if (event.index > stateIndex) {\n stateIndex = event.index\n if (!cleared) serverEvents.push(event)\n foldedState = foldEvent(reducer, foldedState, event)\n } else if (!cleared) {\n mergeServerEvents([event], stateIndex)\n }\n if (cleared) applyClearBoundary(event.index)\n pending = pending.filter((p) => p.id !== event.id)\n }\n if (!delivered) return\n resolveConfirmed()\n notify()\n touch(sessionId)\n }\n\n // ── push ─────────────────────────────────────────────────────\n const validated = (\n events: AppendInput<D>[],\n ): Array<{ id: string; type: string; payload: unknown }> =>\n events.map((event) => {\n const schema = Object.hasOwn(contract.events, event.type)\n ? contract.events[event.type]\n : undefined\n if (!schema) {\n throw new A2ClientError(\n 'UNKNOWN_EVENT_TYPE',\n `no event type '${String(event.type)}' in the reducer's vocabulary`,\n )\n }\n const result = validateSync(\n schema,\n event.payload,\n `event '${String(event.type)}'`,\n )\n if (result.issues) {\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n `invalid payload for event '${String(event.type)}'`,\n { details: result.issues },\n )\n }\n return {\n id: event.id ?? crypto.randomUUID(),\n type: event.type,\n payload: result.value,\n }\n })\n\n const post = async (\n body: TransportPushBody,\n ): Promise<ContractEvent<D>[]> => {\n let lastPushError: A2ClientError = new A2ClientError(\n 'STORE_UNAVAILABLE',\n 'push failed',\n )\n for (let attempt = 1; attempt <= PUSH_ATTEMPTS; attempt += 1) {\n try {\n const rows = await transport.push(body)\n return rows.map((row) => eventFromWire(row) as ContractEvent<D>)\n } catch (err) {\n lastPushError = asClientError(err)\n }\n if (!RETRYABLE_PUSH_CODES.has(lastPushError.code)) throw lastPushError\n if (attempt < PUSH_ATTEMPTS) {\n const sleepMs = 250 * attempt\n // Wait for the clock AND, when the transport can tell us,\n // the wire. The pacing sleep is a floor: a failure acked\n // over a healthy socket (a shedding store) must not re-fire\n // at wire speed. A push caught in a routine reconnect blip\n // additionally parks until the subscription is confirmed;\n // that cap scales with the reconnect backoff so an\n // unreachable server still exhausts attempts promptly.\n await Promise.all([\n new Promise((resolve) => setTimeout(resolve, sleepMs)),\n transport.awaitReady?.(\n sessionId,\n sleepMs + STREAM_TIMINGS.reconnectBaseMs * attempt,\n ),\n ])\n }\n }\n throw lastPushError\n }\n\n /**\n * Decorate the ack promise into a PushResult. `confirmed` is a\n * lazy getter — materialized on first access, so callers that\n * ignore it can't leak an unhandled rejection.\n */\n const withConfirmed = (ack: Promise<ContractEvent<D>[]>): PushResult<D> => {\n let confirmed: Promise<ContractEvent<D>[]> | undefined\n return Object.defineProperty(ack as PushResult<D>, 'confirmed', {\n get(): Promise<ContractEvent<D>[]> {\n confirmed ??= ack.then(\n (acked) =>\n new Promise<ContractEvent<D>[]>((resolve) => {\n const last = acked.at(-1)?.index ?? 0\n if ((streamIndex ?? 0) >= last) {\n resolve(acked)\n return\n }\n confirmWatchers.push({\n index: last,\n resolve: () => resolve(acked),\n })\n }),\n )\n return confirmed\n },\n })\n }\n\n // A cold socket opens only after a pending initial Promise settles.\n const initialSettled = (epoch: number): Promise<void> =>\n new Promise((resolve, reject) => {\n const check = (): void => {\n const failure =\n leaseEpoch !== epoch || status === 'closed'\n ? new DOMException('session closed', 'AbortError')\n : !hydrated && preload?.error\n if (failure) {\n listeners.delete(check)\n reject(failure)\n } else if (hydrated || !preload) {\n listeners.delete(check)\n resolve()\n }\n }\n listeners.add(check)\n check()\n })\n\n const push = (...events: AppendInput<D>[]): PushResult<D> => {\n touch(sessionId)\n return withConfirmed(\n (async () => {\n if (events.length === 0) {\n throw new TypeError('push requires at least one event')\n }\n const entries: Pending<D>[] = validated(events).map((e) => ({\n id: e.id,\n type: e.type,\n payload: e.payload,\n createdAt: new Date(),\n }))\n // Reserve before notifying: a subscriber may reenter push(),\n // and that work must follow the call whose state it observed.\n const waitForPriorPush = pushWireTail\n let releasePush!: () => void\n pushWireTail = new Promise<void>((resolve) => {\n releasePush = resolve\n })\n pending.push(...entries)\n inFlightPushes += 1\n let acknowledgedIndex: number | undefined\n const pushEpoch = leaseEpoch\n const releaseConnection =\n !hydrated || transport.awaitReady || active\n ? runtime.connect()\n : undefined\n\n try {\n refreshIdleStream()\n notify() // optimistic — the view updates before the network moves\n await waitForPriorPush\n if (transport.awaitReady) {\n await initialSettled(pushEpoch)\n await transport.awaitReady(\n sessionId,\n STREAM_TIMINGS.stallTimeoutMs,\n )\n }\n if (leaseEpoch !== pushEpoch)\n throw new DOMException('session closed', 'AbortError')\n for (const entry of entries) entry.sent = true\n const acked = await post({\n sessionId,\n events: entries.map(({ id, type, payload }) => ({\n id,\n type,\n payload,\n })),\n })\n acknowledgedIndex = acked.at(-1)?.index\n for (const event of acked) {\n const entry = pending.find((p) => p.id === event.id)\n if (entry) entry.acked = event // stream retires it at its index\n }\n retireCoveredPending()\n if ((acked.at(-1)?.index ?? 0) > (streamIndex ?? stateIndex))\n refreshIdleStream()\n notify()\n return acked\n } catch (err) {\n // Rollback: refold without the rejected events.\n const ids = new Set(entries.map((e) => e.id))\n pending = pending.filter((p) => !ids.has(p.id))\n notify()\n throw err\n } finally {\n if (\n releaseConnection &&\n pushEpoch === leaseEpoch &&\n acknowledgedIndex !== undefined &&\n acknowledgedIndex > (streamIndex ?? 0)\n ) {\n confirmWatchers.push({\n index: acknowledgedIndex,\n resolve: releaseConnection,\n lease: true,\n })\n } else releaseConnection?.()\n releasePush()\n inFlightPushes -= 1\n if (inFlightPushes === 0 && deferredHydration) {\n const next = deferredHydration\n deferredHydration = undefined\n if (next.version === undefined || next.version === initialVersion)\n if (applyInitial(next)) notifyHydrated()\n }\n touch(sessionId)\n }\n })(),\n )\n }\n\n // ── backscroll ───────────────────────────────────────────────\n // Cold reads of the log below the state index. Fetched events merge\n // into `serverEvents` only — never the fold, never the overlay.\n let historyLoads = 0\n /** Calls chain per session: each resolves its bounds after the\n * prior call's merge, so overlapping backscrolls page backward\n * instead of re-fetching the same range. */\n let historyTail: Promise<unknown> = Promise.resolve()\n\n const eventsBetween = (gte: number, lte: number): ContractEvent<D>[] =>\n serverEvents.filter((event) => event.index >= gte && event.index <= lte)\n\n /** The narrowest sub-range of [gte, lte] missing from the feed, or\n * null when the range is fully loaded (nothing to fetch). */\n const missingBetween = (\n gte: number,\n lte: number,\n ): { gte: number; lte: number } | null => {\n const present = new Set(eventsBetween(gte, lte).map((e) => e.index))\n let lo = gte\n while (lo <= lte && present.has(lo)) lo += 1\n if (lo > lte) return null\n let hi = lte\n while (hi > lo && present.has(hi)) hi -= 1\n return { gte: lo, lte: hi }\n }\n\n const loadHistory = (\n loadOptions?: LoadHistoryOptions,\n ): Promise<ContractEvent<D>[]> => {\n const readHistory = transport.history\n if (readHistory === undefined) {\n throw new TypeError(\n 'loadHistory requires an http api — the ws transport has no history lane; serve the session with server.fetch and pass its route url as the string or { type: \"http\" } api',\n )\n }\n const before = loadOptions?.before\n const limit = loadOptions?.limit\n if (\n before !== undefined &&\n (!Number.isSafeInteger(before) || before < 1)\n ) {\n throw new TypeError(\n 'loadHistory before must be a positive safe integer',\n )\n }\n if (limit !== undefined && (!Number.isSafeInteger(limit) || limit < 1)) {\n throw new TypeError('loadHistory limit must be a positive safe integer')\n }\n touch(sessionId)\n const run = historyTail.then(async () => {\n const upper = before ?? serverEvents[0]?.index ?? stateIndex + 1\n // Strictly at or below the state index: the live stream owns\n // everything above it, and the optimistic overlay must never\n // collide with a backscrolled row.\n const lte = Math.min(upper - 1, stateIndex)\n const gte = Math.max(\n clearIndex + 1,\n upper - (limit ?? DEFAULT_HISTORY_LIMIT),\n )\n if (gte > lte) return []\n const missing = missingBetween(gte, lte)\n if (missing === null) return eventsBetween(gte, lte)\n historyLoads += 1\n notify()\n try {\n const page = await readHistory({ sessionId, ...missing })\n if (page.clearIndex !== undefined) applyClearBoundary(page.clearIndex)\n mergeServerEvents(\n page.events.map((row) => eventFromWire(row) as ContractEvent<D>),\n stateIndex,\n )\n return eventsBetween(gte, lte)\n } catch (error) {\n throw asClientError(error)\n } finally {\n historyLoads -= 1\n notify()\n touch(sessionId)\n }\n })\n // Failures reject the caller, never the chain.\n historyTail = run.catch(() => {})\n return run\n }\n\n // ── the live stream ──────────────────────────────────────────\n // A run-generation model instead of a terminal `closed` flag:\n // stopping bumps the generation (the running loop notices and\n // exits), connect() starts a fresh one. Reentrant by design.\n // Consumers hold leases: connect() counts one and returns its\n // release, the last release stops the stream, and close() is the\n // hard stop — it drops every lease and stops now (bumping\n // `leaseEpoch` makes the outstanding releases inert).\n let generation = 0\n let active = false\n let streamIdle = false\n let abort: AbortController | null = null\n let leases = 0\n let leaseEpoch = 0\n\n const stopStream = (): void => {\n touch(sessionId)\n if (!active) return\n active = false\n streamIdle = false\n generation += 1 // the running loop notices and exits\n abort?.abort()\n abort = null\n // A pending trailing send dies with the stream — losing one is\n // fine by definition; sets made while closed accumulate in\n // `presenceResend` and repaint after the next connect.\n clearTimeout(presenceTimer)\n presenceTimer = undefined\n presenceBuffer = null\n status = 'closed'\n notify()\n }\n\n const runStream = async (run: number): Promise<void> => {\n let backoff = STREAM_TIMINGS.reconnectBaseMs\n let attempt = 0\n // oxlint-disable no-await-in-loop -- sequential reconnect loop\n // oxlint-disable-next-line no-unmodified-loop-condition -- close() bumps `generation`\n while (generation === run) {\n streamIdle = false\n const controller = new AbortController()\n abort = controller\n // The stall watchdog: the server heartbeats the stream, so a\n // healthy connection is never silent for long. Silence past the\n // timeout means the connection is dead in a way the socket\n // won't report (an offline browser's established SSE socket\n // neither errors nor receives) — abort it and let the normal\n // reconnect path run. This is what keeps `status: 'live'`\n // honest.\n let stall: ReturnType<typeof setTimeout> | undefined\n let stalled = false\n const armStall = (): void => {\n clearTimeout(stall)\n stall = setTimeout(() => {\n stalled = true\n controller.abort()\n }, STREAM_TIMINGS.stallTimeoutMs)\n ;(stall as { unref?: () => void }).unref?.()\n }\n let wasLive = false\n try {\n // oxlint-disable-next-line no-unmodified-loop-condition -- hydration changes while this connection waits\n while (!hydrated && preload && !preload.error)\n await waitForInitial(controller.signal)\n if (generation !== run || controller.signal.aborted) break\n if (!hydrated && preload?.error) {\n lastError = preload.error\n status = 'paused'\n notify()\n return\n }\n if (hydrated && streamIndex === undefined) streamIndex = stateIndex\n // Acks at or before this start are covered by the baseline and\n // are never streamed.\n resolveConfirmed()\n if (generation !== run) break\n bootstrapGeneration = streamIndex === undefined ? run : undefined\n const frames = transport.connect({\n sessionId,\n startAfter: streamIndex,\n reducer: reducer.name,\n signal: controller.signal,\n })\n for await (const frame of frames) {\n if (generation !== run) break\n // Every frame counts — heartbeats included. Liveness is\n // about the connection, not about events.\n armStall()\n if (frame.kind === 'snapshot') {\n if (\n frame.sessionId !== sessionId ||\n frame.name !== reducer.name ||\n !isStateSnapshotFrame(frame)\n )\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n 'bootstrap snapshot belongs to another session or reducer',\n )\n if (bootstrapGeneration !== run)\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n 'unexpected bootstrap snapshot',\n )\n const baseline =\n !hydrated || frame.index >= stateIndex\n ? { state: bootstrapState(frame), index: frame.index }\n : undefined\n streamIndex = frame.index\n bootstrapGeneration = undefined\n applyClearBoundary(frame.clearIndex ?? 0)\n if (baseline) adoptBaseline(baseline)\n resolveConfirmed()\n notify()\n if (generation !== run) break\n }\n if (!hydrated || streamIndex === undefined) {\n if (frame.kind === 'event' || frame.kind === 'events')\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n 'received an event before the bootstrap snapshot',\n )\n continue\n }\n if (!wasLive) {\n // The first frame is the connection signal: the transport\n // yields it the moment the stream is established.\n backoff = STREAM_TIMINGS.reconnectBaseMs\n attempt = 0\n wasLive = true\n status = 'live'\n lastError = null\n notify()\n if (generation !== run) break\n if (presenceResend) {\n const values = presenceResend\n presenceResend = null\n queuePresenceSend(values)\n }\n }\n if (frame.kind === 'event') {\n streamIdle = false\n ingest([eventFromWire(frame.event) as ContractEvent<D>])\n } else if (frame.kind === 'events') {\n streamIdle = false\n ingest(frame.events as ContractEvent<D>[])\n } else if (frame.kind === 'activity') {\n streamIdle = frame.idle\n if (\n streamIdle &&\n (inFlightPushes > 0 ||\n pending.some(\n (entry) =>\n (entry.acked?.index ?? 0) > (streamIndex ?? stateIndex),\n ))\n ) {\n refreshIdleStream()\n }\n } else if (frame.kind === 'presence') {\n applyPresencePatch(presencePatchFromWire(frame.patch))\n } else if (frame.kind === 'presence-snapshot') {\n applyPresenceSnapshot(\n presenceSnapshotFromWire(frame.snapshot).snapshot,\n )\n }\n }\n // The transport ended the stream cleanly — reconnect, but it\n // isn't an error.\n if (generation === run) {\n lastError = null\n }\n } catch (err) {\n if (generation === run) {\n lastError = stalled\n ? new A2ClientError(\n 'TIMEOUT',\n `stream stalled: no data for ${STREAM_TIMINGS.stallTimeoutMs}ms`,\n {\n phase: 'stream',\n timeoutMs: STREAM_TIMINGS.stallTimeoutMs,\n },\n )\n : asClientError(err)\n }\n } finally {\n if (bootstrapGeneration === run) bootstrapGeneration = undefined\n clearTimeout(stall)\n }\n if (generation !== run) break\n streamIdle = false\n if (wasLive) reconnects += 1\n attempt += 1\n let delay: number | false\n try {\n delay = options.reconnect\n ? options.reconnect({ sessionId, error: lastError, attempt })\n : backoff\n if (\n delay !== false &&\n (!Number.isFinite(delay) || delay < 0 || delay > 2_147_483_647)\n ) {\n throw new RangeError(\n 'reconnect must return false or a delay from 0 to 2147483647 ms',\n )\n }\n } catch (error) {\n if (generation !== run) break\n lastError = asClientError(error)\n delay = false\n }\n if (generation !== run) break\n if (delay === false) {\n abort = null\n status = 'paused'\n notify()\n return\n }\n const waiting = new AbortController()\n abort = waiting\n status = 'connecting'\n notify()\n if (generation !== run) break\n await new Promise<void>((resolve) => {\n let settled = false\n const finish = (): void => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n waiting.signal.removeEventListener('abort', finish)\n // oxlint-disable-next-line no-multiple-resolved -- guarded above\n resolve()\n }\n const timer = setTimeout(finish, delay)\n ;(timer as { unref?: () => void }).unref?.()\n if (waiting.signal.aborted) finish()\n else waiting.signal.addEventListener('abort', finish, { once: true })\n })\n backoff = Math.min(backoff * 2, STREAM_TIMINGS.reconnectMaxMs)\n }\n // oxlint-enable no-await-in-loop\n }\n\n const refreshIdleStream = (): void => {\n if (streamIdle && status !== 'paused') reconnectStream()\n }\n\n const reconnectStream = (): void => {\n touch(sessionId)\n if (!active) return\n streamIdle = false\n generation += 1\n const run = generation\n const previous = abort\n abort = null\n reconnects += 1\n status = 'connecting'\n lastError = null\n notify()\n // Replace the lane before aborting so a multiplexed session keeps its socket.\n if (active && generation === run) void runStream(run)\n previous?.abort()\n }\n\n const applyInitial = ({\n settings: next,\n version,\n }: {\n settings: ResolvedSessionOptions<D, S>\n version?: number\n }): boolean => {\n const nextIndex = next.initial?.index ?? 0\n if (hydrated && nextIndex > stateIndex && inFlightPushes > 0) {\n if (\n !deferredHydration ||\n nextIndex > (deferredHydration.settings.initial?.index ?? 0)\n ) {\n deferredHydration = {\n settings: next,\n ...(version === undefined ? {} : { version }),\n }\n }\n return false\n }\n\n // The boundary applies even to an older fold: it only removes history.\n const boundaryChanged = applyClearBoundary(next.initial?.clearIndex ?? 0)\n const historyChanged =\n mergeServerEvents(\n next.initialEvents,\n Math.min(nextIndex, stateIndex),\n ) || boundaryChanged\n if (next.initial != null && bootstrapGeneration === undefined)\n streamIndex ??= nextIndex\n if (next.initial == null || (hydrated && nextIndex <= stateIndex)) {\n return historyChanged\n }\n\n adoptBaseline(next.initial)\n mergeServerEvents(next.initialEvents, stateIndex)\n return true\n }\n\n const invalidateInitial = (): void => {\n initialVersion++\n preload?.cancel()\n preload = undefined\n if (deferredHydration?.version !== undefined)\n deferredHydration = undefined\n }\n\n const settleInitial = (\n result:\n { source: object; value: unknown } | { source: object; error: unknown },\n ): void => {\n const entry = preload\n if (\n !entry ||\n entry.source !== result.source ||\n entry.version !== initialVersion\n )\n return\n entry.cancel()\n const cold = !hydrated\n let changed = false\n if ('error' in result) {\n if (cold) entry.error = asClientError(result.error)\n else preload = undefined\n } else {\n try {\n assertSessionSeed({ initial: result.value })\n if (isInitialPromise(result.value as InitialSnapshot<unknown>))\n throw new TypeError('an initial Promise must resolve to a snapshot')\n preload = undefined\n changed = applyInitial({\n settings: {\n ...entry.settings,\n initial: result.value as StateSnapshot<S> | null | undefined,\n },\n version: entry.version,\n })\n } catch (error) {\n if (cold) {\n preload = entry\n entry.error = asClientError(error, { code: 'INVALID_PAYLOAD' })\n } else preload = undefined\n }\n }\n if (cold || changed) notifyHydrated()\n }\n\n const waitForInitial = (signal: AbortSignal): Promise<void> =>\n new Promise((resolve, reject) => {\n let settled = false\n const finish = (): void => {\n if (\n settled ||\n (!signal.aborted && !hydrated && preload && !preload.error)\n )\n return\n settled = true\n listeners.delete(finish)\n signal.removeEventListener('abort', finish)\n if (signal.aborted) reject(signal.reason)\n else resolve()\n }\n listeners.add(finish)\n signal.addEventListener('abort', finish, { once: true })\n finish()\n })\n\n const runtime: SessionRuntime<D, S, P> = {\n sessionId,\n // Only on presence-declaring contracts — the type surface\n // promises no runtime-inert members (a2-api.md §12).\n ...(declaresPresence ? { setPresence } : {}),\n subscribe(listener) {\n touch(sessionId)\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n touch(sessionId)\n }\n },\n getSnapshot() {\n snapshot ??= buildSnapshot()\n return snapshot\n },\n push,\n loadHistory,\n reconnect: reconnectStream,\n connect() {\n touch(sessionId)\n leases += 1\n const epoch = leaseEpoch\n if (!active) {\n active = true\n status = 'connecting'\n lastError = null\n const run = generation\n notify()\n if (active && generation === run) void runStream(run)\n }\n let released = false\n return () => {\n // Idempotent, and inert after a hard close() — a stale\n // release must not touch leases taken since.\n if (released || leaseEpoch !== epoch) return\n released = true\n touch(sessionId)\n leases -= 1\n if (leases === 0) stopStream()\n }\n },\n close() {\n invalidateInitial()\n resumeInitialError = undefined\n leases = 0\n leaseEpoch += 1\n confirmWatchers = confirmWatchers.filter((watcher) => !watcher.lease)\n stopStream()\n },\n resolveInitial: settleInitial,\n hydrate(next) {\n assertSessionSeed(next)\n touch(sessionId)\n if (!next) return\n participant ??= next.participant\n const input = next.initial\n const resume =\n !hydrated && status === 'paused' && preload?.error === lastError\n ? preload.error\n : undefined\n if (isInitialPromise(input)) {\n if (seenInitials.has(input)) {\n if (preload?.source === input && next.initialEvents !== undefined)\n preload.settings.initialEvents = next.initialEvents\n if (mergeServerEvents(next.initialEvents, stateIndex))\n notifyHydrated()\n return\n }\n invalidateInitial()\n seenInitials.add(input)\n const { initial: _initial, ...settings } = next\n const entry: PendingInitial<D, S> = {\n source: input,\n version: initialVersion,\n settings,\n cancel() {},\n }\n preload = entry\n entry.cancel = observeInitial({\n promise: input,\n settled: (result) => settleInitial({ source: input, ...result }),\n })\n if (resume) notifyHydrated(resume)\n return\n }\n if (input != null) {\n const repeated = seenInitials.has(input)\n seenInitials.add(input)\n if (repeated || (hydrated && input.index <= stateIndex)) {\n if (\n deferredHydration?.settings.initial === input &&\n next.initialEvents !== undefined\n )\n deferredHydration.settings.initialEvents = next.initialEvents\n const boundaryChanged = applyClearBoundary(input.clearIndex ?? 0)\n if (\n mergeServerEvents(\n next.initialEvents,\n Math.min(input.index, stateIndex),\n ) ||\n boundaryChanged\n )\n notifyHydrated()\n return\n }\n }\n if (input !== undefined) invalidateInitial()\n if (\n applyInitial({ settings: { ...next, initial: input } }) ||\n resume ||\n input === null\n )\n notifyHydrated(resume)\n },\n canEvict() {\n return (\n listeners.size === 0 &&\n !active &&\n inFlightPushes === 0 &&\n historyLoads === 0 &&\n confirmWatchers.length === 0 &&\n presenceTimer === undefined\n )\n },\n } as SessionRuntime<D, S, P>\n\n if (isInitialPromise(supplied)) runtime.hydrate(sessionOptions)\n return runtime\n }\n\n const client: A2Client<D, S, P> = {\n session(sessionId, sessionOptions) {\n const existing = sessions.get(sessionId)\n if (existing) {\n existing.runtime.hydrate(sessionOptions)\n touch(sessionId)\n return existing.runtime\n }\n\n const runtime = makeSession(sessionId, sessionOptions)\n sessions.set(sessionId, { runtime })\n touch(sessionId)\n return runtime\n },\n }\n registerRenderSessionFactory({\n client,\n factory: (sessionId, settings) =>\n makeSession(sessionId, settings as SessionOptions<D, S>),\n resolveInitial: ({ session, source, value }) => {\n ;(session as SessionRuntime<D, S, P>).resolveInitial({ source, value })\n },\n })\n return client\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client-BhHLoNKF.js","names":[],"sources":["../src/client-errors.ts","../src/initial-snapshot.ts","../src/client-render-session.ts","../src/client.ts"],"sourcesContent":["import { A2Error, type A2ErrorCode } from './errors.ts'\n\nexport type A2ClientErrorOptions = {\n details?: unknown\n cause?: unknown\n status?: number\n closeCode?: number\n closeReason?: string\n phase?: 'stream' | 'subscribe'\n timeoutMs?: number\n}\n\nexport class A2ClientError extends A2Error {\n readonly status: number | undefined\n readonly closeCode: number | undefined\n readonly closeReason: string | undefined\n readonly phase: 'stream' | 'subscribe' | undefined\n readonly timeoutMs: number | undefined\n\n constructor(\n code: A2ErrorCode,\n message: string,\n options?: A2ClientErrorOptions,\n ) {\n super(code, message, options)\n this.name = 'A2ClientError'\n this.status = options?.status\n this.closeCode = options?.closeCode\n this.closeReason = options?.closeReason\n this.phase = options?.phase\n this.timeoutMs = options?.timeoutMs\n }\n}\n\nexport function asClientError(\n error: unknown,\n options?: { code?: A2ErrorCode },\n): A2ClientError {\n if (error instanceof A2ClientError) return error\n if (error instanceof A2Error) {\n return new A2ClientError(error.code, error.message, {\n details: error.details,\n cause: error,\n })\n }\n return new A2ClientError(\n options?.code ?? 'UNKNOWN',\n error instanceof Error ? error.message : 'client operation failed',\n { cause: error },\n )\n}\n","import type { StateSnapshot } from './reducer.ts'\n\nexport type InitialSnapshot<S> =\n | StateSnapshot<S>\n | null\n | undefined\n | Promise<StateSnapshot<S> | null | undefined>\n\nexport function isInitialPromise<S>(\n initial: InitialSnapshot<S>,\n): initial is Promise<StateSnapshot<S> | null | undefined> {\n return (\n initial !== null &&\n typeof initial === 'object' &&\n 'then' in initial &&\n typeof initial.then === 'function'\n )\n}\n\nexport function observeInitial<S>(options: {\n promise: Promise<StateSnapshot<S> | null | undefined>\n settled(\n result: { value: StateSnapshot<S> | null | undefined } | { error: unknown },\n ): void\n}): () => void {\n let listener: typeof options.settled | undefined = options.settled\n const deliver = (result: Parameters<typeof options.settled>[0]): void => {\n const current = listener\n listener = undefined\n current?.(result)\n }\n void Promise.resolve(options.promise).then(\n (value) => deliver({ value }),\n (error: unknown) => deliver({ error }),\n )\n return () => {\n listener = undefined\n }\n}\n","import type { A2Client, SessionClient, SessionOptions } from './client.ts'\nimport type { EventDefs, PresenceDefs } from './contract.ts'\n\ntype Factory = (sessionId: string, options: unknown) => unknown\ntype ClientReact = {\n factory: Factory\n resolveInitial(options: {\n session: object\n source: object\n value: unknown\n }): void\n}\nconst factories = new WeakMap<object, ClientReact>()\n\nexport function registerRenderSessionFactory(options: {\n client: object\n factory: Factory\n resolveInitial: ClientReact['resolveInitial']\n}): void {\n factories.set(options.client, options)\n}\n\nexport function resolveInitialForReact(options: {\n client: object\n session: object\n source: object\n value: unknown\n}): void {\n factories.get(options.client)?.resolveInitial(options)\n}\n\nexport function createRenderSession<\n D extends EventDefs,\n S,\n P extends PresenceDefs,\n>(options: {\n client: A2Client<D, S, P>\n sessionId: string\n settings: SessionOptions<D, S>\n}): SessionClient<D, S, P> {\n const factory = factories.get(options.client)\n if (!factory)\n throw new TypeError('React requires a client returned by createClient')\n return factory.factory(options.sessionId, options.settings) as SessionClient<\n D,\n S,\n P\n >\n}\n","/**\n * experimental-a2/client — the framework-agnostic session client.\n *\n * Everything the browser needs to read a session live and push\n * optimistically, with no framework attached: the SSE subscription with\n * frontier resume and reconnection, the optimistic push queue with\n * ack/rollback, and the local fold through the same reducer the server\n * uses. `experimental-a2/react`'s `createReact` is a thin binding over it, and the\n * store contract (`subscribe`/`getSnapshot`) is exactly what\n * `useSyncExternalStore` wants.\n *\n * The client is a replica, never an access path — the routes it talks\n * to authorize every read and write.\n */\n\n// oxlint-disable no-await-in-loop -- retry/backoff/stream loops are sequential by nature\nimport { decodeState, projectClientState } from './reducer-runtime.ts'\nimport { A2ClientError, asClientError } from './client-errors.ts'\nimport {\n isInitialPromise,\n observeInitial,\n type InitialSnapshot,\n} from './initial-snapshot.ts'\nimport { registerRenderSessionFactory } from './client-render-session.ts'\nimport {\n PRESENCE_TIMINGS,\n RESERVED_PARTICIPANT_IDS,\n STREAM_TIMINGS,\n nullProtoRecord,\n} from './internal.ts'\nimport type {\n AppendInput,\n Contract,\n ContractEvent,\n EventDefs,\n PresenceDefs,\n PresenceMap,\n PresencePatch,\n WithPresence,\n} from './contract.ts'\nimport { foldEvent, type Reducer, type StateSnapshot } from './reducer.ts'\nimport { isSessionCleared } from './session-clear.ts'\nimport { validateSync } from './validate.ts'\nimport {\n isStateSnapshotFrame,\n type StateSnapshotFrame,\n type SubscriptionStart,\n errorFromWire,\n eventFromCompactWire,\n eventFromWire,\n isCompactWireEvent,\n isWireEvent,\n isWirePresencePatch,\n isWirePresenceSnapshot,\n parseSocketFrame,\n presencePatchFromWire,\n presenceSnapshotFromWire,\n type SocketDownFrame,\n type SocketPresenceFrame,\n type SocketPushFrame,\n type SocketSubscribeFrame,\n type SocketUnsubscribeFrame,\n type WireEvent,\n type WirePresencePatch,\n type WirePresenceSnapshot,\n} from './wire.ts'\nimport type { Event } from './store.ts'\n\nexport { A2ClientError } from './client-errors.ts'\nexport type { StateSnapshot } from './reducer.ts'\nexport type { InitialSnapshot } from './initial-snapshot.ts'\nexport type { A2ClientErrorOptions } from './client-errors.ts'\n\nexport type ReconnectPolicy = (failure: {\n sessionId: string\n error: A2ClientError | null\n attempt: number\n}) => number | false\n\nexport type ConnectionStatus =\n 'idle' | 'connecting' | 'paused' | 'live' | 'closed'\n\n/**\n * The connection, as a discriminated union — impossible states are\n * unrepresentable: an error only exists while disconnected,\n * `reconnects` only once a connection has been attempted.\n * \"Reconnecting…\" is `status === 'connecting' && reconnects > 0`.\n */\nexport type Connection =\n | { status: 'idle' }\n | {\n status: 'connecting'\n /** Stream restarts so far. `0` = first connect. */\n reconnects: number\n /** Why the last connection ended; `null` on the first connect. */\n error: A2ClientError | null\n }\n | { status: 'paused'; reconnects: number; error: A2ClientError | null }\n | { status: 'live'; reconnects: number }\n | { status: 'closed' }\n\n/**\n * What `push` returns: resolves at the server ack (exactly like a\n * plain promise — `await push(...)` gives the acked events), and\n * carries `confirmed` for the later moment when the live stream has\n * delivered the whole batch back and the optimistic overlay entry\n * retired — the view now shows server truth. `confirmed` is lazy:\n * never accessed, never created. A rejected push rejects both.\n */\nexport type PushResult<D extends EventDefs> = Promise<ContractEvent<D>[]> & {\n readonly confirmed: Promise<ContractEvent<D>[]>\n}\n\nexport type LoadHistoryOptions = {\n /**\n * Exclusive upper bound for the fetch. Defaults to the oldest\n * already-loaded index — successive calls page backward — or one\n * past the hydration frontier while nothing is loaded yet.\n */\n before?: number\n /** Page size; defaults to 50. */\n limit?: number\n}\n\n/** Backscroll progress, derived from the raw event feed. */\nexport type HistoryState = {\n /** A `loadHistory` fetch is in flight. */\n loading: boolean\n /** The feed reaches index 1 — nothing older remains to fetch. */\n complete: boolean\n /** The oldest loaded index; `null` while nothing is loaded. */\n oldestLoaded: number | null\n}\n\n/** One immutable view of the session — stable identity between changes. */\nexport type SessionSnapshot<\n D extends EventDefs,\n S,\n P extends PresenceDefs = Record<never, never>,\n> = WithPresence<\n P,\n {\n /** The replicated presence map, this client included (local echo). */\n presence: PresenceMap<P>\n }\n> & {\n /** The live view: server events folded, optimistic pushes applied. */\n state: S\n /** A state/index snapshot has been applied; independent of connection status. */\n hydrated: boolean\n /** The raw event feed: server truth — observed, seeded, or\n * backscrolled via `loadHistory` — plus pending optimistic events\n * (provisional indexes past the frontier). `state` never folds\n * backscrolled events; they are display data below the frontier. */\n events: ContractEvent<D>[]\n /** The latest server-confirmed state index. This is the\n * `lastSeenIndex` cancellation wants. */\n index: number\n /** Backscroll progress — `loadHistory` moves it. */\n history: HistoryState\n connection: Connection\n}\n\n/**\n * The presence member of a client session — intersected in via\n * `WithPresence`, so it exists exactly when the contract declares\n * presence fields.\n */\nexport type SessionClientPresence<P extends PresenceDefs> = {\n /**\n * Fire-and-forget presence: validates locally against the reducer's\n * presence schemas, merges into the local map immediately (the\n * echo), and coalesces on the wire to a fixed cadence — a leading\n * send immediately, then at most one merged send per interval,\n * later values winning field-wise. `null` clears a field. No ack,\n * no retry, no rollback: a lost patch is repainted by the next one.\n * Requires the session's `participant`.\n */\n setPresence(values: PresencePatch<P>['values']): void\n}\n\nexport type SessionClient<\n D extends EventDefs,\n S,\n P extends PresenceDefs = Record<never, never>,\n> = WithPresence<P, SessionClientPresence<P>> & {\n readonly sessionId: string\n subscribe(listener: () => void): () => void\n getSnapshot(): SessionSnapshot<D, S, P>\n /**\n * Optimistic append: validates locally against the reducer's event\n * schemas (instant `INVALID_PAYLOAD`, no flicker), applies to the\n * local fold, POSTs, swaps in the ack, rolls back on rejection.\n * Auto-retries `STORE_UNAVAILABLE` and transport failures. Resolves with the appended\n * events as the server recorded them. Overlapping calls on this\n * handle enter the transport in invocation order without delaying\n * their optimistic folds.\n */\n push(...events: AppendInput<D>[]): PushResult<D>\n /**\n * Backscroll: fetch a bounded slice of events from below the\n * frontier and merge it into `events` — deduped, ordered, shared by\n * every handle of this session. Folded state and the optimistic\n * overlay are never touched. Calls serialize per session and skip\n * already-loaded ranges, so overlapping backscrolls never fetch the\n * same range twice. Resolves with the events in the requested range.\n * Requires an http api; the `ws` transport has no history lane and\n * this throws a TypeError there.\n */\n loadHistory(options?: LoadHistoryOptions): Promise<ContractEvent<D>[]>\n /**\n * Take a lease on the live stream and return its release. Leases\n * refcount per handle — the first connects, releasing the last\n * closes — so independent consumers of one identity-mapped handle\n * (two hooks, a hook plus vanilla code) never fight over the\n * stream. Releasing twice is a no-op. While any lease is held the\n * stream follows the client's reconnection policy and resumes after\n * its last streamed event.\n */\n connect(): () => void\n /** Restart a leased subscription immediately after its last streamed event.\n * Preserves state, pending writes, and leases. No-op without a lease. */\n reconnect(): void\n /**\n * The hard stop: drops every outstanding lease and closes the\n * stream now. Not terminal — a later `connect()` starts fresh from\n * the last streamed event.\n */\n close(): void\n}\n\nexport type SessionOptions<D extends EventDefs, S> = {\n initial?: InitialSnapshot<S>\n /** Server-rendered history through `initial.index`. Seeds the event feed. */\n initialEvents?: ContractEvent<D>[]\n /** Overrides the client's `participant` for this session handle.\n * Bound once per handle. */\n participant?: string\n}\n\nfunction assertSessionSeed(options: { initial?: unknown } | undefined): void {\n const initial = options?.initial\n if (initial == null || isInitialPromise(initial as InitialSnapshot<unknown>))\n return\n if (\n initial === null ||\n typeof initial !== 'object' ||\n !Object.hasOwn(initial, 'state') ||\n !Object.hasOwn(initial, 'index') ||\n !('index' in initial) ||\n typeof initial.index !== 'number' ||\n !Number.isSafeInteger(initial.index) ||\n initial.index < 0\n )\n throw new TypeError(\n 'initial must contain state and a non-negative safe integer index',\n )\n const clearIndex = (initial as { clearIndex?: unknown }).clearIndex\n if (\n clearIndex !== undefined &&\n (typeof clearIndex !== 'number' ||\n !Number.isSafeInteger(clearIndex) ||\n clearIndex < 0 ||\n clearIndex > initial.index)\n )\n throw new TypeError(\n 'initial.clearIndex must be a non-negative safe integer no greater than its index',\n )\n}\n\nexport type A2Client<\n D extends EventDefs,\n S,\n P extends PresenceDefs = Record<never, never>,\n> = {\n session(\n sessionId: string,\n options?: SessionOptions<D, S>,\n ): SessionClient<D, S, P>\n}\n\n/**\n * The wire the client rides. The first form is one route serving GET\n * (SSE stream) + POST (push). `http` splits the verbs across two\n * routes, for when platform duration limits differ per verb. `ws`\n * rides everything over WebSocket, one socket per session by default.\n * Multiplexing every session of the client is an explicit opt-in.\n */\nexport type SessionUrl = string | ((sessionId: string) => string)\n\nexport type ClientApi =\n | SessionUrl // one route: GET SSE stream + POST push\n | { type: 'http'; push: SessionUrl; stream: SessionUrl } // split routes\n /** One socket per session. */\n | { type: 'ws'; url: SessionUrl; multiplex?: false }\n /** One socket for every session of this client. */\n | { type: 'ws'; url: string; multiplex: true }\n\n/**\n * The socket surface the `ws` transport drives — satisfied structurally\n * by the DOM `WebSocket` and Node's alike, and small enough to fake in\n * tests.\n */\nexport type ClientWebSocket = {\n readonly readyState: number\n send(data: string): void\n close(code?: number, reason?: string): void\n addEventListener(type: 'open', listener: () => void): void\n addEventListener(\n type: 'message',\n listener: (event: { data: unknown }) => void,\n ): void\n addEventListener(\n type: 'close',\n listener: (event: { code: number; reason: string }) => void,\n ): void\n addEventListener(type: 'error', listener: () => void): void\n}\n\nexport type ClientWebSocketConstructor = new (url: string) => ClientWebSocket\n\nexport type CreateClientOptions<\n D extends EventDefs,\n S,\n P extends PresenceDefs = Record<never, never>,\n> = {\n contract: Contract<D, P, Reducer<D, S, P>>\n /** The route (or routes) the client speaks — see `ClientApi`. */\n api: ClientApi\n /** Delay the next connection attempt in milliseconds, or pause with false. */\n reconnect?: ReconnectPolicy\n /** Injectable fetch — defaults to the global. */\n fetch?: typeof globalThis.fetch\n /** Injectable WebSocket constructor for the `ws` api — defaults to\n * the global. The http transports never touch it. */\n webSocket?: ClientWebSocketConstructor\n /** How long an idle session keeps its in-memory identity, in\n * milliseconds. Defaults to five minutes; `Infinity` disables GC. */\n gcTime?: number\n /**\n * This client's presence identity — required to call `setPresence`.\n * Caller-supplied (a user id, a tab nonce, a guest name): A2 does\n * not invent an identity story; the app states it once here. The\n * default for every session handle this client creates;\n * `session(id, { participant })` overrides it per handle.\n */\n participant?: string\n}\n\nconst PUSH_ATTEMPTS = 3\nconst RETRYABLE_PUSH_CODES = new Set([\n 'STORE_UNAVAILABLE',\n 'TIMEOUT',\n 'HTTP_ERROR',\n 'CONNECTION_FAILED',\n 'UNKNOWN',\n])\nconst DEFAULT_GC_TIME_MS = 5 * 60 * 1_000\nconst DEFAULT_HISTORY_LIMIT = 50\n\n// ── the transport seam ───────────────────────────────────────────────\n// Everything above it — optimistic queue, retry loop, presence\n// throttle, reconnect/backoff, stall watchdog — is transport-agnostic.\n\n/** The parsed frame lanes every transport yields: the SSE frame\n * discrimination today, the ws `kind` discriminant tomorrow. `ping`\n * carries no data — it exists so the watchdog sees liveness. */\ntype TransportFrame =\n | StateSnapshotFrame\n | { kind: 'event'; event: WireEvent }\n | { kind: 'events'; events: Event[] }\n | { kind: 'presence'; patch: WirePresencePatch }\n | { kind: 'presence-snapshot'; snapshot: WirePresenceSnapshot }\n | { kind: 'activity'; idle: boolean }\n | { kind: 'ping' }\n\ntype TransportPushBody = {\n sessionId: string\n events: Array<{ id: string; type: string; payload: unknown }>\n}\n\ntype TransportPresenceEnvelope = {\n sessionId: string\n presence: {\n participant: string\n values: Record<string, unknown>\n seen: number\n at: number\n }\n}\n\ntype Transport = {\n /**\n * One live read: the first frame means the stream is established\n * (any kind — a bare `ping` when no data is pending), the iterable\n * ending or throwing is the disconnect. The caller owns\n * reconnect/backoff and counts every frame as liveness.\n */\n connect(opts: {\n sessionId: string\n startAfter: number | undefined\n reducer: string\n signal: AbortSignal\n }): AsyncIterable<TransportFrame>\n /** One attempt (the retry loop lives above the seam): resolves with\n * the acked wire events, throws A2ClientError. */\n push(body: TransportPushBody): Promise<WireEvent[]>\n /** One bounded cold read of the log, oldest first — the lane\n * `loadHistory` rides. Absent on transports without a\n * request/response wire (ws), where `loadHistory` fails fast. */\n history?(opts: {\n sessionId: string\n gte: number\n lte: number\n }): Promise<{ events: WireEvent[]; clearIndex?: number }>\n /** Fire-and-forget; failures are dropped (presence repaints). */\n sendPresence(envelope: TransportPresenceEnvelope): void\n /**\n * Resolve when the session's wire can carry a push again, or after\n * `maxWaitMs` — whichever comes first; never rejects. Transports\n * whose pushes are connection-bound (ws) implement it so the retry\n * loop waits for the wire instead of a fixed clock; HTTP pushes are\n * stream-independent and omit it.\n */\n awaitReady?(sessionId: string, maxWaitMs: number): Promise<void>\n}\n\nconst sessionUrl = (url: SessionUrl, sessionId: string): string => {\n const resolved = typeof url === 'function' ? url(sessionId) : url\n if (typeof resolved !== 'string') {\n throw new TypeError('a session URL function must return a string')\n }\n return resolved\n}\n\nconst httpError = async (response: Response): Promise<A2ClientError> => {\n const error = errorFromWire(await response.json().catch(() => null))\n return error === null\n ? new A2ClientError(\n 'HTTP_ERROR',\n `request failed with ${response.status}`,\n {\n status: response.status,\n },\n )\n : new A2ClientError(error.code, error.message, {\n details: error.details,\n status: response.status,\n cause: error,\n })\n}\n\nconst httpTransport = (\n routes: { push: SessionUrl; stream: SessionUrl },\n fetchImpl: typeof globalThis.fetch,\n // Contracts that declare no presence skip presence frames unparsed,\n // exactly like unknown named frames.\n presence: boolean,\n): Transport => ({\n async *connect({ sessionId, startAfter, reducer: reducerName, signal }) {\n const streamUrl = sessionUrl(routes.stream, sessionId)\n const sep = streamUrl.includes('?') ? '&' : '?'\n const res = await fetchImpl(\n `${streamUrl}${sep}${new URLSearchParams({ sessionId, reducer: reducerName, wire: '2', ...(startAfter === undefined ? { bootstrap: '1' } : { index: String(startAfter) }) })}`,\n { headers: { accept: 'text/event-stream' }, signal },\n )\n if (!res.ok) throw await httpError(res)\n if (!res.body) {\n throw new A2ClientError('UNKNOWN', 'stream response has no body', {\n status: res.status,\n })\n }\n yield { kind: 'ping' } // connected — headers in hand, before any bytes\n const decoder = new TextDecoder()\n const reader = res.body.getReader()\n let buffer = ''\n try {\n for (;;) {\n // oxlint-disable-next-line no-await-in-loop -- stream read loop\n const { done, value } = await reader.read()\n if (done) return\n // Any bytes count — heartbeat comments included. Liveness is\n // about the connection, not about events.\n yield { kind: 'ping' }\n buffer += decoder.decode(value, { stream: true })\n for (;;) {\n const boundary = buffer.indexOf('\\n\\n')\n if (boundary === -1) break\n const frame = buffer.slice(0, boundary)\n buffer = buffer.slice(boundary + 2)\n let eventName: string | undefined\n const dataLines: string[] = []\n for (const line of frame.split('\\n')) {\n if (line.startsWith('data:')) {\n dataLines.push(line.slice(5).trimStart())\n } else if (line.startsWith('event:')) {\n eventName = line.slice(6).trim()\n }\n }\n const data = dataLines.join('\\n')\n if (!data) continue\n if (eventName === undefined) {\n const parsed: unknown = JSON.parse(data)\n // A version 2 server batches events; an older one sends one.\n if (Array.isArray(parsed)) {\n // Dropping a batch would leave a gap the frontier then skips past.\n if (!parsed.every(isCompactWireEvent))\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n 'invalid event batch',\n )\n yield {\n kind: 'events',\n events: parsed.map((row) =>\n eventFromCompactWire(row, sessionId),\n ),\n }\n } else if (isWireEvent(parsed))\n yield { kind: 'event', event: parsed }\n } else if (eventName === 'a2-snapshot') {\n const parsed: unknown = JSON.parse(data)\n if (!isStateSnapshotFrame(parsed))\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n 'invalid bootstrap snapshot',\n )\n yield parsed\n } else if (presence && eventName === 'presence-snapshot') {\n const parsed: unknown = JSON.parse(data)\n if (isWirePresenceSnapshot(parsed)) {\n yield { kind: 'presence-snapshot', snapshot: parsed }\n }\n } else if (presence && eventName === 'presence') {\n const parsed: unknown = JSON.parse(data)\n if (isWirePresencePatch(parsed)) {\n yield { kind: 'presence', patch: parsed }\n }\n } else if (\n eventName === 'a2-activity' &&\n (data === 'idle' || data === 'active')\n ) {\n yield { kind: 'activity', idle: data === 'idle' }\n }\n // Other named frames: skipped — old clients stay compatible\n // with future lanes the same way.\n }\n }\n } finally {\n reader.cancel().catch(() => {})\n }\n },\n\n async push(body) {\n const res = await fetchImpl(sessionUrl(routes.push, body.sessionId), {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n })\n if (res.ok) {\n const rows = (await res.json()) as unknown\n if (!Array.isArray(rows) || !rows.every(isWireEvent)) {\n throw new A2ClientError(\n 'STORE_UNAVAILABLE',\n 'push ack was not a list of events',\n )\n }\n return rows\n }\n throw await httpError(res)\n },\n\n async history({ sessionId, gte, lte }) {\n const streamUrl = sessionUrl(routes.stream, sessionId)\n const sep = streamUrl.includes('?') ? '&' : '?'\n const res = await fetchImpl(\n `${streamUrl}${sep}sessionId=${encodeURIComponent(sessionId)}&gte=${gte}&lte=${lte}`,\n { headers: { accept: 'application/json' } },\n )\n if (!res.ok) {\n throw await httpError(res)\n }\n const rows = (await res.json()) as unknown\n if (!Array.isArray(rows) || !rows.every(isWireEvent)) {\n throw new A2ClientError(\n 'STORE_UNAVAILABLE',\n 'history response was not a list of events',\n )\n }\n const clearIndex = Number(res.headers.get('a2-clear-index') ?? Number.NaN)\n return Number.isSafeInteger(clearIndex) && clearIndex > 0\n ? { events: rows, clearIndex }\n : { events: rows }\n },\n\n sendPresence(envelope) {\n void (async () => {\n try {\n const res = await fetchImpl(\n sessionUrl(routes.push, envelope.sessionId),\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(envelope),\n },\n )\n await res.arrayBuffer()\n } catch {\n // Dropped by design — nothing was ever true.\n }\n })()\n },\n})\n\n/** `WebSocket.OPEN` — fixed by the spec, identical in every runtime. */\nconst WS_OPEN = 1\n\ntype PendingAck = {\n resolve: (events: WireEvent[]) => void\n reject: (error: A2ClientError) => void\n}\n\nconst webSocketUrl = (value: string): URL => {\n let resolved: URL\n if (/^(https?|wss?):\\/\\//i.test(value)) {\n resolved = new URL(value)\n } else {\n const base = (globalThis as { location?: { href: string } }).location?.href\n if (base === undefined) {\n throw new TypeError(\n `cannot resolve the relative ws url '${value}' without a browser location — pass an absolute ws:// or wss:// url`,\n )\n }\n resolved = new URL(value, base)\n }\n if (resolved.protocol === 'http:') resolved.protocol = 'ws:'\n else if (resolved.protocol === 'https:') resolved.protocol = 'wss:'\n return resolved\n}\n\nconst socketReadyWaiters = () => {\n const sessions = new Map<string, Set<() => void>>()\n\n const notify = (sessionId: string): void => {\n const waiters = sessions.get(sessionId)\n if (!waiters) return\n sessions.delete(sessionId)\n for (const waiter of waiters) waiter()\n }\n\n const wait = (sessionId: string, maxWaitMs: number): Promise<void> =>\n new Promise((resolve) => {\n let waiters = sessions.get(sessionId)\n if (!waiters) {\n waiters = new Set()\n sessions.set(sessionId, waiters)\n }\n let settled = false\n const done = (): void => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n waiters.delete(done)\n if (waiters.size === 0) sessions.delete(sessionId)\n // oxlint-disable-next-line promise/no-multiple-resolved -- `settled` guards the timer and notification callers\n resolve()\n }\n const timer = setTimeout(done, maxWaitMs)\n ;(timer as { unref?: () => void }).unref?.()\n waiters.add(done)\n })\n\n return { notify, wait }\n}\n\nconst rejectPendingAcks = (pending: Map<number, PendingAck>): void => {\n if (pending.size === 0) return\n const error = new A2ClientError(\n 'STORE_UNAVAILABLE',\n 'socket closed with the ack outstanding',\n )\n for (const waiter of pending.values()) waiter.reject(error)\n pending.clear()\n}\n\nconst sessionWsTransport = (\n url: SessionUrl,\n webSocketImpl: ClientWebSocketConstructor | undefined,\n presence: boolean,\n): Transport => {\n type SocketConnection = {\n socket: ClientWebSocket\n pending: Map<number, PendingAck>\n }\n\n const connections = new Map<string, SocketConnection>()\n const ready = socketReadyWaiters()\n let nextReq = 1\n\n const socketUrl = (\n sessionId: string,\n startAfter: number | undefined,\n reducerName: string,\n ): string => {\n const resolved = webSocketUrl(sessionUrl(url, sessionId))\n resolved.searchParams.set('sessionId', sessionId)\n resolved.searchParams.delete('index')\n resolved.searchParams.delete('bootstrap')\n resolved.searchParams.set('reducer', reducerName)\n resolved.searchParams.set('wire', '2')\n if (startAfter === undefined) resolved.searchParams.set('bootstrap', '1')\n else resolved.searchParams.set('index', String(startAfter))\n return resolved.href\n }\n\n return {\n async *connect({ sessionId, startAfter, reducer: reducerName, signal }) {\n if (webSocketImpl === undefined) {\n throw new TypeError(\n 'no WebSocket implementation available — pass one via createClient({ webSocket }) where the global is missing',\n )\n }\n const socket = new webSocketImpl(\n socketUrl(sessionId, startAfter, reducerName),\n )\n const connection: SocketConnection = { socket, pending: new Map() }\n connections.set(sessionId, connection)\n\n const queue: TransportFrame[] = []\n let ended = false\n let failure: Error | null = null\n let wake: (() => void) | null = null\n const notify = (): void => {\n wake?.()\n wake = null\n }\n const finish = (error: Error | null): void => {\n if (ended) return\n ended = true\n failure = error\n if (connections.get(sessionId) === connection) {\n connections.delete(sessionId)\n ready.notify(sessionId)\n }\n rejectPendingAcks(connection.pending)\n notify()\n }\n\n socket.addEventListener('open', () => {\n if (connections.get(sessionId) !== connection || ended) return\n queue.push({ kind: 'ping' })\n notify()\n ready.notify(sessionId)\n })\n socket.addEventListener('message', (event) => {\n if (connections.get(sessionId) !== connection || ended) return\n if (typeof event.data !== 'string') return\n let frame: SocketDownFrame | null\n try {\n frame = parseSocketFrame(event.data)\n } catch (error) {\n finish(asClientError(error))\n return\n }\n if (frame === null) return\n switch (frame.kind) {\n case 'snapshot':\n queue.push(frame)\n break\n case 'ack': {\n const waiter = connection.pending.get(frame.req)\n if (waiter === undefined) return\n connection.pending.delete(frame.req)\n if (\n frame.sessionId !== undefined ||\n ('events' in frame &&\n frame.events.some((row) => row.sessionId !== sessionId))\n ) {\n waiter.reject(\n new A2ClientError(\n 'STORE_UNAVAILABLE',\n 'ack does not belong to the socket session',\n ),\n )\n return\n }\n if ('events' in frame) waiter.resolve(frame.events)\n else waiter.reject(asClientError(frame.error))\n return\n }\n case 'event':\n if (frame.event.sessionId !== sessionId) return\n queue.push({ kind: 'event', event: frame.event })\n break\n case 'events':\n if (frame.sessionId !== undefined) return\n queue.push({\n kind: 'events',\n events: frame.events.map((row) =>\n eventFromCompactWire(row, sessionId),\n ),\n })\n break\n case 'presence':\n if (presence && frame.sessionId === undefined) {\n queue.push({ kind: 'presence', patch: frame.patch })\n }\n break\n case 'presence-snapshot':\n if (presence && frame.sessionId === undefined) {\n queue.push({\n kind: 'presence-snapshot',\n snapshot: frame.snapshot,\n })\n }\n break\n case 'ping':\n queue.push(frame)\n break\n case 'subscribed':\n case 'unsubscribed':\n return\n }\n notify()\n })\n socket.addEventListener('close', (event) => {\n finish(\n event.code === 1000\n ? null\n : new A2ClientError(\n 'CONNECTION_FAILED',\n `socket closed (${event.code}${event.reason ? `: ${event.reason}` : ''})`,\n { closeCode: event.code, closeReason: event.reason },\n ),\n )\n })\n socket.addEventListener('error', () => {\n finish(new A2ClientError('CONNECTION_FAILED', 'socket error'))\n })\n\n const onAbort = (): void => {\n finish(\n signal.reason instanceof Error\n ? signal.reason\n : new Error('stream aborted'),\n )\n try {\n socket.close(1000)\n } catch {\n // Already closed.\n }\n }\n if (signal.aborted) onAbort()\n else signal.addEventListener('abort', onAbort, { once: true })\n\n try {\n for (;;) {\n while (queue.length > 0) yield queue.shift()!\n if (ended) {\n if (failure) throw failure\n return\n }\n await new Promise<void>((resolve) => {\n wake = resolve\n })\n }\n } finally {\n signal.removeEventListener('abort', onAbort)\n finish(null)\n try {\n socket.close(1000)\n } catch {\n // Already closed.\n }\n }\n },\n\n async push(body) {\n const connection = connections.get(body.sessionId)\n if (\n connection === undefined ||\n connection.socket.readyState !== WS_OPEN\n ) {\n throw new A2ClientError(\n 'STORE_UNAVAILABLE',\n 'no open socket for the session',\n )\n }\n const req = nextReq\n nextReq += 1\n return await new Promise<WireEvent[]>((resolve, reject) => {\n connection.pending.set(req, { resolve, reject })\n const frame: SocketPushFrame = {\n kind: 'push',\n req,\n events: body.events,\n }\n try {\n connection.socket.send(JSON.stringify(frame))\n } catch (cause) {\n connection.pending.delete(req)\n reject(\n new A2ClientError('STORE_UNAVAILABLE', 'socket send failed', {\n cause,\n }),\n )\n }\n })\n },\n\n awaitReady(sessionId, maxWaitMs) {\n const connection = connections.get(sessionId)\n if (connection?.socket.readyState === WS_OPEN) return Promise.resolve()\n return ready.wait(sessionId, maxWaitMs)\n },\n\n sendPresence(envelope) {\n const connection = connections.get(envelope.sessionId)\n if (\n connection === undefined ||\n connection.socket.readyState !== WS_OPEN\n ) {\n return\n }\n const frame: SocketPresenceFrame = {\n kind: 'presence',\n ...envelope.presence,\n }\n try {\n connection.socket.send(JSON.stringify(frame))\n } catch {\n return\n }\n },\n }\n}\n\n/** One session's lane on the shared ws socket — created per `connect`\n * attempt, so `startAfter` is that attempt's resume frontier. */\ntype WsChannel = {\n sessionId: string\n /** Echoed on this lane's subscribe answers. An answer to an earlier\n * attempt for the same session must not confirm or end this one;\n * data frames from that attempt precede this attempt's confirmation. */\n attempt: number\n startAfter: number | undefined\n reducer: string\n queue: TransportFrame[]\n /** The server confirmed the subscribe — pushes and presence ride. */\n live: boolean\n /** The server already dropped it — no unsubscribe frame owed. */\n dropped: boolean\n ended: boolean\n failure: Error | null\n wake: (() => void) | null\n}\n\nconst wakeChannel = (channel: WsChannel): void => {\n channel.wake?.()\n channel.wake = null\n}\n\nconst answersAttempt = (\n frame: { attempt?: number },\n channel: WsChannel,\n): boolean => frame.attempt === undefined || frame.attempt === channel.attempt\n\nconst subscriptionStart = (\n index: number | undefined,\n reducer: string,\n): SubscriptionStart =>\n index === undefined ? { bootstrap: true, reducer } : { index, reducer }\n\nconst subscribeFrame = (sessions: SocketSubscribeFrame['sessions']): string => {\n const frame: SocketSubscribeFrame = { kind: 'subscribe', sessions }\n return JSON.stringify(frame)\n}\n\nconst multiplexedWsTransport = (\n url: string,\n webSocketImpl: ClientWebSocketConstructor | undefined,\n presence: boolean,\n): Transport => {\n // ONE socket serves every session of this client (specs §13's\n // multiplexed superset): channels subscribe on it at their own\n // frontiers, down frames route back by sessionId, acks by req.\n const channels = new Map<string, WsChannel>()\n const pending = new Map<number, PendingAck>()\n /** Push retries parked in `awaitReady`, flushed per session on its\n * subscribe confirmation. */\n const ready = socketReadyWaiters()\n let socket: ClientWebSocket | null = null\n let socketOpen = false\n let watchdog: ReturnType<typeof setTimeout> | undefined\n let nextReq = 1\n let nextAttempt = 1\n\n const trySend = (data: string): void => {\n if (socket === null || !socketOpen) return\n try {\n socket.send(data)\n } catch {\n // Dropped — the socket is going down and its close event settles\n // everything that depended on this frame.\n }\n }\n\n const deliver = (channel: WsChannel, frame: TransportFrame): void => {\n channel.queue.push(frame)\n wakeChannel(channel)\n }\n\n const settleChannel = (channel: WsChannel, failure: Error | null): void => {\n if (channel.ended) return\n channel.ended = true\n channel.failure = failure\n wakeChannel(channel)\n }\n\n // Unhook the socket from the transport state and reject every\n // outstanding ack — nothing was acked, and the client-generated ids\n // make the retries idempotent (§13).\n const releaseSocket = (): ClientWebSocket | null => {\n const current = socket\n socket = null\n socketOpen = false\n clearTimeout(watchdog)\n watchdog = undefined\n rejectPendingAcks(pending)\n return current\n }\n\n // Idempotent from every direction (close event, error event, stall):\n // every channel ends — each session's reconnect loop re-subscribes at\n // its own current frontier.\n const failSocket = (failure: Error | null): void => {\n const current = releaseSocket()\n for (const channel of channels.values()) settleChannel(channel, failure)\n try {\n current?.close(1000)\n } catch {\n // Already closed — it is down either way.\n }\n }\n\n const detach = (channel: WsChannel): void => {\n if (channels.get(channel.sessionId) !== channel) return\n channels.delete(channel.sessionId)\n ready.notify(channel.sessionId)\n if (!channel.dropped) {\n const frame: SocketUnsubscribeFrame = {\n kind: 'unsubscribe',\n sessions: [channel.sessionId],\n }\n trySend(JSON.stringify(frame))\n }\n if (channels.size === 0) {\n // The last session left — the shared socket has no reason to live.\n const current = releaseSocket()\n try {\n current?.close(1000)\n } catch {\n // Already closed — it is down either way.\n }\n }\n }\n\n // One heartbeat watchdog per socket: any frame is liveness, and\n // silence past the stall timeout means the connection is dead in a\n // way the socket won't report.\n const armWatchdog = (created: ClientWebSocket): void => {\n clearTimeout(watchdog)\n watchdog = setTimeout(() => {\n if (socket !== created) return\n failSocket(\n new A2ClientError(\n 'TIMEOUT',\n `socket stalled: no data for ${STREAM_TIMINGS.stallTimeoutMs}ms`,\n { phase: 'stream', timeoutMs: STREAM_TIMINGS.stallTimeoutMs },\n ),\n )\n }, STREAM_TIMINGS.stallTimeoutMs)\n ;(watchdog as { unref?: () => void }).unref?.()\n }\n\n const route = (frame: SocketDownFrame): void => {\n switch (frame.kind) {\n case 'snapshot': {\n const channel = channels.get(frame.sessionId)\n if (channel && channel.live && !channel.ended) deliver(channel, frame)\n return\n }\n case 'ping': {\n // Global liveness — every live channel's stall watchdog feeds\n // on it, the way each SSE stream feeds on its own heartbeat.\n for (const channel of channels.values()) {\n if (channel.live && !channel.ended) {\n deliver(channel, { kind: 'ping' })\n }\n }\n return\n }\n case 'subscribed': {\n const channel = channels.get(frame.sessionId)\n if (\n channel === undefined ||\n channel.ended ||\n channel.live ||\n !answersAttempt(frame, channel)\n )\n return\n channel.live = true\n deliver(channel, { kind: 'ping' }) // the connected signal\n ready.notify(frame.sessionId)\n return\n }\n case 'unsubscribed': {\n const channel = channels.get(frame.sessionId)\n if (channel === undefined || !answersAttempt(frame, channel)) return\n channel.dropped = true\n settleChannel(\n channel,\n frame.error\n ? asClientError(frame.error)\n : frame.reason === undefined\n ? null\n : new A2ClientError('CONNECTION_FAILED', frame.reason),\n )\n return\n }\n case 'ack': {\n const waiter = pending.get(frame.req)\n if (waiter === undefined) return\n pending.delete(frame.req)\n if ('events' in frame) waiter.resolve(frame.events)\n else waiter.reject(asClientError(frame.error))\n return\n }\n case 'event': {\n // Pre-confirmation frames are safe to drop: the subscription\n // being confirmed replays from this channel's own frontier.\n const channel = channels.get(frame.event.sessionId)\n if (channel !== undefined && channel.live && !channel.ended) {\n deliver(channel, { kind: 'event', event: frame.event })\n }\n return\n }\n case 'events': {\n const { sessionId } = frame\n if (sessionId === undefined) return\n const channel = channels.get(sessionId)\n if (channel !== undefined && channel.live && !channel.ended) {\n deliver(channel, {\n kind: 'events',\n events: frame.events.map((row) =>\n eventFromCompactWire(row, sessionId),\n ),\n })\n }\n return\n }\n case 'presence': {\n // Contracts that declare no presence skip presence frames,\n // exactly like the http transport.\n if (!presence || frame.sessionId === undefined) return\n const channel = channels.get(frame.sessionId)\n if (channel !== undefined && channel.live && !channel.ended) {\n deliver(channel, { kind: 'presence', patch: frame.patch })\n }\n return\n }\n case 'presence-snapshot': {\n if (!presence || frame.sessionId === undefined) return\n const channel = channels.get(frame.sessionId)\n if (channel !== undefined && channel.live && !channel.ended) {\n deliver(channel, {\n kind: 'presence-snapshot',\n snapshot: frame.snapshot,\n })\n }\n return\n }\n }\n }\n\n const ensureSocket = (): void => {\n if (socket !== null) return\n if (webSocketImpl === undefined) {\n throw new TypeError(\n 'no WebSocket implementation available — pass one via createClient({ webSocket }) where the global is missing',\n )\n }\n const target = webSocketUrl(url)\n target.searchParams.set('wire', '2')\n const created = new webSocketImpl(target.href)\n socket = created\n socketOpen = false\n armWatchdog(created)\n created.addEventListener('open', () => {\n if (socket !== created) return\n socketOpen = true\n armWatchdog(created)\n const sessions = [...channels.values()]\n .filter((channel) => !channel.ended)\n .map((channel) => ({\n id: channel.sessionId,\n attempt: channel.attempt,\n ...subscriptionStart(channel.startAfter, channel.reducer),\n }))\n if (sessions.length > 0) trySend(subscribeFrame(sessions))\n })\n created.addEventListener('message', (event) => {\n if (socket !== created) return\n if (typeof event.data !== 'string') return\n armWatchdog(created)\n let frame: SocketDownFrame | null\n try {\n frame = parseSocketFrame(event.data)\n } catch (error) {\n failSocket(asClientError(error))\n return\n }\n if (frame === null) return\n route(frame)\n })\n created.addEventListener('close', (event) => {\n if (socket !== created) return\n failSocket(\n event.code === 1000\n ? null // deliberate server close — reconnect, but not an error\n : new A2ClientError(\n 'CONNECTION_FAILED',\n `socket closed (${event.code}${event.reason ? `: ${event.reason}` : ''})`,\n { closeCode: event.code, closeReason: event.reason },\n ),\n )\n })\n created.addEventListener('error', () => {\n if (socket !== created) return\n failSocket(new A2ClientError('CONNECTION_FAILED', 'socket error'))\n })\n }\n\n return {\n async *connect({ sessionId, startAfter, reducer: reducerName, signal }) {\n const channel: WsChannel = {\n sessionId,\n attempt: nextAttempt++,\n startAfter,\n reducer: reducerName,\n queue: [],\n live: false,\n dropped: false,\n ended: false,\n failure: null,\n wake: null,\n }\n channels.set(sessionId, channel)\n try {\n ensureSocket()\n if (socketOpen) {\n trySend(\n subscribeFrame([\n {\n id: sessionId,\n attempt: channel.attempt,\n ...subscriptionStart(startAfter, reducerName),\n },\n ]),\n )\n }\n } catch (error) {\n if (channels.get(sessionId) === channel) channels.delete(sessionId)\n throw error\n }\n\n const onAbort = (): void => {\n settleChannel(\n channel,\n signal.reason instanceof Error\n ? signal.reason\n : new Error('stream aborted'),\n )\n // Synchronously, not from the pump's finally: the watchdog and\n // close() must not leave a dead subscription behind.\n detach(channel)\n }\n if (signal.aborted) onAbort()\n else signal.addEventListener('abort', onAbort, { once: true })\n\n // An unconfirmed subscribe receives no frames at all (global\n // pings only feed live channels), so a server that never answers\n // — a single-session route, say — would hang this session\n // silently. Fail it loudly instead; the reconnect loop retries.\n const pendingSubscribe = setTimeout(() => {\n if (channel.live) return\n settleChannel(\n channel,\n new A2ClientError(\n 'TIMEOUT',\n 'subscribe not confirmed: is the ws route calling server.fetch with upgradeWebSocket?',\n { phase: 'subscribe', timeoutMs: STREAM_TIMINGS.stallTimeoutMs },\n ),\n )\n }, STREAM_TIMINGS.stallTimeoutMs)\n ;(pendingSubscribe as { unref?: () => void }).unref?.()\n\n try {\n for (;;) {\n while (channel.queue.length > 0) yield channel.queue.shift()!\n if (channel.ended) {\n if (channel.failure) throw channel.failure\n return\n }\n // oxlint-disable-next-line no-await-in-loop -- frame pump\n await new Promise<void>((resolve) => {\n channel.wake = resolve\n })\n }\n } finally {\n clearTimeout(pendingSubscribe)\n signal.removeEventListener('abort', onAbort)\n settleChannel(channel, null)\n detach(channel)\n }\n },\n\n async push(body) {\n const channel = channels.get(body.sessionId)\n const target = socket\n if (\n channel === undefined ||\n !channel.live ||\n channel.ended ||\n target === null ||\n !socketOpen ||\n target.readyState !== WS_OPEN\n ) {\n // Retryable by contract: the reconnect loop restores the\n // socket and the retry rides the same event ids.\n throw new A2ClientError(\n 'STORE_UNAVAILABLE',\n 'no open socket for the session',\n )\n }\n const req = nextReq\n nextReq += 1\n return await new Promise<WireEvent[]>((resolve, reject) => {\n pending.set(req, { resolve, reject })\n const frame: SocketPushFrame = {\n kind: 'push',\n req,\n sessionId: body.sessionId,\n events: body.events,\n }\n try {\n target.send(JSON.stringify(frame))\n } catch (cause) {\n pending.delete(req)\n reject(\n new A2ClientError('STORE_UNAVAILABLE', 'socket send failed', {\n cause,\n }),\n )\n }\n })\n },\n\n awaitReady(sessionId, maxWaitMs) {\n const channel = channels.get(sessionId)\n if (\n channel !== undefined &&\n channel.live &&\n !channel.ended &&\n socketOpen\n ) {\n return Promise.resolve()\n }\n return ready.wait(sessionId, maxWaitMs)\n },\n sendPresence(envelope) {\n const channel = channels.get(envelope.sessionId)\n if (channel === undefined || !channel.live || channel.ended) {\n return // dropped by design — the reconnect re-send covers the gap\n }\n const frame: SocketPresenceFrame = {\n kind: 'presence',\n sessionId: envelope.sessionId,\n ...envelope.presence,\n }\n trySend(JSON.stringify(frame))\n },\n }\n}\n\nconst transportFor = (\n api: ClientApi,\n fetchImpl: typeof globalThis.fetch,\n webSocketImpl: ClientWebSocketConstructor | undefined,\n presence: boolean,\n): Transport => {\n if (typeof api === 'string' || typeof api === 'function') {\n return httpTransport({ push: api, stream: api }, fetchImpl, presence)\n }\n if (api.type === 'http') {\n return httpTransport(\n { push: api.push, stream: api.stream },\n fetchImpl,\n presence,\n )\n }\n if (api.multiplex === true) {\n if (typeof api.url !== 'string') {\n throw new TypeError('a multiplexed WebSocket URL must be a string')\n }\n return multiplexedWsTransport(api.url, webSocketImpl, presence)\n }\n return sessionWsTransport(api.url, webSocketImpl, presence)\n}\n\ntype Pending<D extends EventDefs> = {\n id: string\n type: string\n payload: unknown\n createdAt: Date\n /** Set once the POST ack returns; the entry leaves the overlay when\n * the stream delivers its index. */\n acked?: ContractEvent<D>\n sent?: true\n /** Sent before the current baseline was adopted and not yet acked:\n * the baseline may already contain it, so only its ack index can\n * place it in the overlay. */\n heldUntilAck?: true\n}\n\ntype ResolvedSessionOptions<D extends EventDefs, S> = Omit<\n SessionOptions<D, S>,\n 'initial'\n> & {\n initial?: StateSnapshot<S> | null | undefined\n}\n\ntype PendingInitial<D extends EventDefs, S> = {\n source: Promise<StateSnapshot<S> | null | undefined>\n version: number\n settings: Omit<SessionOptions<D, S>, 'initial'>\n cancel(): void\n error?: A2ClientError\n}\n\ntype SessionRuntime<\n D extends EventDefs,\n S,\n P extends PresenceDefs,\n> = SessionClient<D, S, P> & {\n hydrate(options?: SessionOptions<D, S>): void\n resolveInitial(options: { source: object; value: unknown }): void\n canEvict(): boolean\n}\n\ntype CachedSession<D extends EventDefs, S, P extends PresenceDefs> = {\n runtime: SessionRuntime<D, S, P>\n timer?: ReturnType<typeof setTimeout>\n}\n\nexport function createClient<\n D extends EventDefs,\n S,\n P extends PresenceDefs = Record<never, never>,\n>(options: CreateClientOptions<D, S, P>): A2Client<D, S, P> {\n const { contract, api } = options\n const reducer = contract?.reducer\n if (!reducer)\n throw new TypeError(\n 'createClient requires a contract with a public reducer',\n )\n const presenceDefs: Readonly<PresenceDefs> = contract.presence\n const declaresPresence = Object.keys(presenceDefs).length > 0\n const fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis)\n const clientFetch: typeof globalThis.fetch = async (input, init) => {\n try {\n return await fetchImpl(input, init)\n } catch (error) {\n throw asClientError(error, { code: 'CONNECTION_FAILED' })\n }\n }\n const webSocketImpl =\n options.webSocket ??\n (globalThis as { WebSocket?: ClientWebSocketConstructor }).WebSocket\n const transport = transportFor(\n api,\n clientFetch,\n webSocketImpl,\n declaresPresence,\n )\n const gcTime = options.gcTime ?? DEFAULT_GC_TIME_MS\n if (Number.isNaN(gcTime) || gcTime < 0) {\n throw new RangeError('gcTime must be a non-negative number or Infinity')\n }\n const sessions = new Map<string, CachedSession<D, S, P>>()\n\n const scheduleGc = (sessionId: string, delay = gcTime): void => {\n const entry = sessions.get(sessionId)\n if (!entry) return\n clearTimeout(entry.timer)\n if (gcTime === Infinity) return\n entry.timer = setTimeout(() => {\n const current = sessions.get(sessionId)\n if (current !== entry) return\n if (entry.runtime.canEvict()) {\n entry.runtime.close()\n clearTimeout(entry.timer)\n sessions.delete(sessionId)\n return\n }\n // `gcTime: 0` is useful for tests and explicit no-cache clients,\n // but must not spin while a session is mounted or a push is in flight.\n scheduleGc(sessionId, Math.max(gcTime, 1_000))\n }, delay)\n ;(entry.timer as { unref?: () => void }).unref?.()\n }\n\n const touch = (sessionId: string): void => {\n scheduleGc(sessionId)\n }\n\n const makeSession = (\n sessionId: string,\n sessionOptions?: SessionOptions<D, S>,\n ): SessionRuntime<D, S, P> => {\n assertSessionSeed(sessionOptions)\n // ── server truth ─────────────────────────────────────────────\n const supplied = sessionOptions?.initial\n const initial = isInitialPromise(supplied) ? undefined : supplied\n let hydrated = initial != null\n let bootstrapGeneration: number | undefined\n let stateIndex = initial?.index ?? 0\n let streamIndex = initial?.index\n let foldedState: S = initial == null ? reducer.initialState : initial.state\n /** The latest clear marker this session has learned of, or 0. */\n let clearIndex = initial?.clearIndex ?? 0\n let initialVersion = 0\n const seenInitials = new WeakSet<object>()\n if (initial != null) seenInitials.add(initial)\n let preload: PendingInitial<D, S> | undefined\n const serverEvents: ContractEvent<D>[] = (\n sessionOptions?.initialEvents ?? []\n )\n .filter((event) => event.index <= stateIndex && event.index > clearIndex)\n .toSorted((a, b) => a.index - b.index)\n\n // ── optimistic overlay ───────────────────────────────────────\n let pending: Pending<D>[] = []\n\n // ── the presence plane ───────────────────────────────────────\n // Never cached, never folded. Foreign entries replicate from the\n // stream; the own entry is the local echo — server copies of self\n // are ignored (the echo is at least as new, and comparing it to\n // server stamps would put two clocks in one order).\n let participant = sessionOptions?.participant ?? options.participant\n // Participant and field keys arrive off the wire, so the map and\n // every entry are built null-prototype — see `nullProtoRecord`.\n let presenceState: PresenceMap = nullProtoRecord()\n let presenceLastSentAt = 0\n /** The last LWW stamp issued — see `nextPresenceAt`. */\n let presenceLastAt = 0\n /** Values awaiting the trailing send — non-null exactly while\n * `presenceTimer` is armed. */\n let presenceBuffer: Record<string, unknown> | null = null\n let presenceTimer: ReturnType<typeof setTimeout> | undefined\n /** Own fields set while the stream was down — re-sent once on\n * reconnect (their POSTs may have been lost with the network). */\n let presenceResend: Record<string, unknown> | null = null\n\n // ── store plumbing ───────────────────────────────────────────\n const listeners = new Set<() => void>()\n let snapshot: SessionSnapshot<D, S, P> | null = null\n let status: ConnectionStatus = 'idle'\n let reconnects = 0\n let lastError: A2ClientError | null = null\n let inFlightPushes = 0\n let pushWireTail: Promise<void> = Promise.resolve()\n let deferredHydration:\n { settings: ResolvedSessionOptions<D, S>; version?: number } | undefined\n let resumeInitialError: A2ClientError | undefined\n let hydrationNotification: ReturnType<typeof setTimeout> | undefined\n\n const emit = (): void => {\n // copy: a listener may unsubscribe (or subscribe) mid-notify\n // oxlint-disable-next-line no-useless-spread\n for (const listener of [...listeners]) listener()\n }\n\n const notify = (): void => {\n snapshot = null\n emit()\n }\n\n const notifyHydrated = (resume?: A2ClientError): void => {\n resumeInitialError ??= resume\n // `session(id, serverFold)` is also called while a destination\n // provider renders. Its own snapshot must advance synchronously,\n // but notifying an outgoing provider during that render would be a\n // React setState-in-render violation.\n snapshot = null\n clearTimeout(hydrationNotification)\n hydrationNotification = setTimeout(() => {\n const failure = resumeInitialError\n resumeInitialError = undefined\n if (failure && active && status === 'paused' && lastError === failure)\n reconnectStream()\n else emit()\n }, 0)\n ;(hydrationNotification as { unref?: () => void }).unref?.()\n }\n\n const mergeServerEvents = (\n events: ContractEvent<D>[] | undefined,\n throughIndex: number,\n ): boolean => {\n if (!events || events.length === 0) return false\n const byIndex = new Map(serverEvents.map((event) => [event.index, event]))\n let changed = false\n for (const event of events) {\n // Also drops rows from responses that began before a newer clear.\n if (event.index > throughIndex || event.index <= clearIndex) continue\n const existing = byIndex.get(event.index)\n if (existing?.id === event.id) continue\n byIndex.set(event.index, event)\n changed = true\n }\n if (!changed) return false\n serverEvents.splice(\n 0,\n serverEvents.length,\n ...[...byIndex.values()].toSorted((a, b) => a.index - b.index),\n )\n return true\n }\n\n /**\n * Raise the latest known clear marker (a2-implementation.md §17.4):\n * drop the served history it ended and every push acked below it.\n * The boundary never moves backward.\n */\n const applyClearBoundary = (index: number): boolean => {\n if (index <= clearIndex) return false\n clearIndex = index\n const kept = serverEvents.filter((event) => event.index > index)\n serverEvents.splice(0, serverEvents.length, ...kept)\n pending = pending.filter(\n (entry) => entry.acked === undefined || entry.acked.index > index,\n )\n return true\n }\n\n const overlayEvents = (): ContractEvent<D>[] => {\n // Acked entries first (they have a server-assigned order), then\n // unacked in push order with provisional indexes.\n const acked = pending\n .filter((p) => p.acked)\n .map((p) => p.acked!)\n .toSorted((a, b) => a.index - b.index)\n const maxKnown = Math.max(stateIndex, acked.at(-1)?.index ?? stateIndex)\n const waiting = pending.filter((p) => !p.acked)\n const held = waiting.findIndex((p) => p.heldUntilAck)\n // Later pushes may depend on a held one, so they stay hidden with it.\n const unacked = (held === -1 ? waiting : waiting.slice(0, held)).map(\n (p, i) =>\n ({\n id: p.id,\n type: p.type,\n payload: p.payload,\n index: maxKnown + 1 + i, // provisional\n sessionId,\n createdAt: p.createdAt,\n }) as ContractEvent<D>,\n )\n return [...acked, ...unacked]\n }\n\n const connection = (): Connection => {\n switch (status) {\n case 'idle':\n return { status: 'idle' }\n case 'closed':\n return { status: 'closed' }\n case 'live':\n return { status: 'live', reconnects }\n case 'connecting':\n case 'paused':\n return { status, reconnects, error: lastError }\n }\n }\n\n const historyState = (): HistoryState => {\n const oldestLoaded = serverEvents[0]?.index ?? null\n return {\n loading: historyLoads > 0,\n // The first event of the lifetime loaded — or a state index at\n // its start, an empty lifetime as far as this client knows —\n // means nothing older is left to fetch.\n complete:\n hydrated &&\n (oldestLoaded === clearIndex + 1 || stateIndex === clearIndex),\n oldestLoaded,\n }\n }\n\n const buildSnapshot = (): SessionSnapshot<D, S, P> => {\n const overlay = overlayEvents()\n let state = foldedState\n for (const event of hydrated ? overlay : []) {\n if (event.index > stateIndex) state = reducer.fold(state, event)\n }\n const displayedOverlay = overlay.filter((event) => {\n if (event.index > stateIndex) return true\n let low = 0\n let high = serverEvents.length - 1\n while (low <= high) {\n const middle = Math.floor((low + high) / 2)\n const observed = serverEvents[middle]!\n if (observed.index === event.index) return observed.id !== event.id\n if (observed.index < event.index) low = middle + 1\n else high = middle - 1\n }\n return true\n })\n return {\n state: projectClientState({ reducer, state }),\n hydrated,\n events: [...serverEvents, ...displayedOverlay],\n index: stateIndex,\n history: historyState(),\n connection: connection(),\n ...(declaresPresence\n ? { presence: presenceState as PresenceMap<P> }\n : {}),\n } as SessionSnapshot<D, S, P>\n }\n\n // ── presence ─────────────────────────────────────────────────\n /**\n * The per-session monotonic LWW stamp: wall-seeded, guarded\n * `max(now, last + 1)`, so overlapping sends can never invert —\n * the wall clock seeds it because it is the only monotonic state\n * that survives a reload without A2 owning persistence.\n */\n const nextPresenceAt = (): number => {\n presenceLastAt = Math.max(Date.now(), presenceLastAt + 1)\n return presenceLastAt\n }\n\n // Copy-on-write throughout: snapshots alias `presenceState`, so\n // every change replaces the map and the touched entry instead of\n // mutating them.\n const applyPresencePatch = (patch: PresencePatch): void => {\n if (patch.participant === participant) return // the echo is self truth\n const entry: PresenceMap[string] = Object.assign(\n nullProtoRecord<PresenceMap[string]>(),\n presenceState[patch.participant],\n )\n let changed = false\n for (const [field, value] of Object.entries(patch.values)) {\n if (value === undefined) continue\n const existing = entry[field]\n // Field-wise LWW: an older stamp loses, a tie goes to the wire.\n if (existing && existing.at.getTime() > patch.at.getTime()) continue\n if (value === null) {\n if (existing) {\n delete entry[field]\n changed = true\n }\n } else {\n entry[field] = { value, seen: patch.seen, at: patch.at }\n changed = true\n }\n }\n if (!changed) return\n const next = Object.assign(nullProtoRecord<PresenceMap>(), presenceState)\n if (Object.keys(entry).length === 0) delete next[patch.participant]\n else next[patch.participant] = entry\n presenceState = next\n notify()\n }\n\n const applyPresenceSnapshot = (incoming: PresenceMap): void => {\n const next: PresenceMap = nullProtoRecord()\n for (const [id, fields] of Object.entries(incoming)) {\n if (id === participant) continue\n next[id] = fields\n }\n // Foreign entries replaced wholesale; the own echo survives.\n const own =\n participant === undefined ? undefined : presenceState[participant]\n if (participant !== undefined && own !== undefined)\n next[participant] = own\n presenceState = next\n notify()\n }\n\n const echoPresence = (\n id: string,\n values: Record<string, unknown>,\n atMs: number,\n ): void => {\n const entry: PresenceMap[string] = Object.assign(\n nullProtoRecord<PresenceMap[string]>(),\n presenceState[id],\n )\n const at = new Date(atMs)\n for (const [field, value] of Object.entries(values)) {\n if (value === null) delete entry[field]\n else entry[field] = { value, seen: stateIndex, at }\n }\n const next = Object.assign(nullProtoRecord<PresenceMap>(), presenceState)\n if (Object.keys(entry).length === 0) delete next[id]\n else next[id] = entry\n presenceState = next\n notify()\n }\n\n // One send, fire-and-forget: no retry, no rollback, failures\n // dropped silently — the next send repaints. Sends are NOT\n // serialized on the ack and may overlap in flight: safe, because\n // merges are LWW by `at` per (participant, field) and one\n // sender's stamps are monotonic. `seen` is the state index at send\n // time, not at set time; `at` is the sender's monotonic stamp.\n const sendPresence = (\n values: Record<string, unknown>,\n at: number,\n ): void => {\n presenceLastSentAt = Date.now()\n transport.sendPresence({\n sessionId,\n // Every path here starts at setPresence, which requires the\n // participant.\n presence: { participant: participant!, values, seen: stateIndex, at },\n })\n touch(sessionId)\n }\n\n // The fixed-cadence throttle: a set outside the interval sends on\n // the leading edge; within it, values merge field-wise into one\n // trailing send at the boundary. The cadence never couples to RTT\n // — waiting on the ack served no purpose on this plane and\n // stretched remote motion on slow links.\n const queuePresenceSend = (\n values: Record<string, unknown>,\n at?: number,\n ): void => {\n if (presenceTimer !== undefined) {\n presenceBuffer = { ...presenceBuffer, ...values }\n return\n }\n const wait =\n presenceLastSentAt + PRESENCE_TIMINGS.sendIntervalMs - Date.now()\n if (wait <= 0) {\n sendPresence(values, at ?? nextPresenceAt())\n return\n }\n presenceBuffer = { ...presenceBuffer, ...values }\n presenceTimer = setTimeout(() => {\n presenceTimer = undefined\n const buffered = presenceBuffer\n presenceBuffer = null\n // The trailing send stamps at fire time — always past every\n // stamp its merged values echoed with.\n if (buffered) sendPresence(buffered, nextPresenceAt())\n }, wait)\n ;(presenceTimer as { unref?: () => void }).unref?.()\n }\n\n const setPresence = (values: PresencePatch<P>['values']): void => {\n if (participant === undefined) {\n throw new TypeError(\n 'setPresence requires a participant — pass one to createClient({ participant }) or in the session options (the SessionProvider/useSession participant prop)',\n )\n }\n const validated: Record<string, unknown> = nullProtoRecord()\n for (const [field, value] of Object.entries(values)) {\n if (value === undefined) continue\n // '*' is a catch-all vocabulary entry: any field name (bar\n // object-plumbing names) validates against it. The actor\n // module's follower reducer declares it — the browser cannot\n // know a server-defined vocabulary, so the server stays the\n // authority.\n const schema = Object.hasOwn(presenceDefs, field)\n ? presenceDefs[field]\n : RESERVED_PARTICIPANT_IDS.has(field)\n ? undefined\n : presenceDefs['*']\n if (!schema) {\n throw new A2ClientError(\n 'UNKNOWN_PRESENCE_FIELD',\n `no presence field '${field}' in the reducer's vocabulary`,\n )\n }\n if (value === null) {\n validated[field] = null\n continue\n }\n const result = validateSync(schema, value, `presence field '${field}'`)\n if (result.issues) {\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n `invalid value for presence field '${field}'`,\n { details: result.issues },\n )\n }\n validated[field] = result.value\n }\n if (Object.keys(validated).length === 0) return\n // One stamp per set: the echo and a leading send share it, so\n // the local map and the wire agree on this write's LWW position.\n const at = nextPresenceAt()\n echoPresence(participant, validated, at)\n if (status !== 'live') {\n presenceResend = { ...presenceResend, ...validated }\n }\n queuePresenceSend(validated, at)\n touch(sessionId)\n }\n\n /** Pushes awaiting stream confirmation — resolved the moment the\n * stream, by event or bootstrap snapshot, passes their batch. */\n let confirmWatchers: Array<{\n index: number\n resolve: () => void\n lease?: true\n }> = []\n\n const resolveConfirmed = (): void => {\n const delivered = streamIndex ?? 0\n const due = confirmWatchers.filter(\n (watcher) => watcher.index <= delivered,\n )\n if (due.length === 0) return\n confirmWatchers = confirmWatchers.filter(\n (watcher) => watcher.index > delivered,\n )\n for (const watcher of due) watcher.resolve()\n }\n\n // State hydration does not subsume delivery: unobserved ACKs still\n // keep an idle stream catching up even when their state is covered.\n const retireCoveredPending = (): void => {\n pending = pending.filter(\n (entry) =>\n !entry.acked ||\n entry.acked.index > Math.min(stateIndex, streamIndex ?? stateIndex),\n )\n }\n\n const adoptBaseline = (baseline: StateSnapshot<S>): void => {\n hydrated = true\n stateIndex = baseline.index\n foldedState = baseline.state\n for (const entry of pending)\n if (entry.sent && !entry.acked) entry.heldUntilAck = true\n retireCoveredPending()\n }\n\n const bootstrapState = (frame: StateSnapshotFrame): S => {\n let state: S\n try {\n state = decodeState({\n reducer,\n state: frame.stateUndefined ? undefined : frame.state,\n }) as S\n } catch (error) {\n throw asClientError(error, { code: 'INVALID_PAYLOAD' })\n }\n if (!reducer.stateSchema) return state\n const result = validateSync(\n reducer.stateSchema,\n state,\n 'bootstrap stateSchema',\n )\n if (result.issues)\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n 'bootstrap state failed stateSchema',\n { details: result.issues },\n )\n return result.value\n }\n\n /** The single ingest point: every server-confirmed event, in log\n * order, from the stream. */\n // A batch is folded whole before listeners hear about it, once.\n const ingest = (events: readonly ContractEvent<D>[]): void => {\n let delivered = false\n for (const event of events) {\n if (event.index <= (streamIndex ?? 0)) continue\n delivered = true\n streamIndex = event.index\n const cleared = isSessionCleared(event)\n // A marker at or below a newer hydrated fold is already reflected in it.\n if (event.index > stateIndex) {\n stateIndex = event.index\n if (!cleared) serverEvents.push(event)\n foldedState = foldEvent(reducer, foldedState, event)\n } else if (!cleared) {\n mergeServerEvents([event], stateIndex)\n }\n if (cleared) applyClearBoundary(event.index)\n pending = pending.filter((p) => p.id !== event.id)\n }\n if (!delivered) return\n resolveConfirmed()\n notify()\n touch(sessionId)\n }\n\n // ── push ─────────────────────────────────────────────────────\n const validated = (\n events: AppendInput<D>[],\n ): Array<{ id: string; type: string; payload: unknown }> =>\n events.map((event) => {\n const schema = Object.hasOwn(contract.events, event.type)\n ? contract.events[event.type]\n : undefined\n if (!schema) {\n throw new A2ClientError(\n 'UNKNOWN_EVENT_TYPE',\n `no event type '${String(event.type)}' in the reducer's vocabulary`,\n )\n }\n const result = validateSync(\n schema,\n event.payload,\n `event '${String(event.type)}'`,\n )\n if (result.issues) {\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n `invalid payload for event '${String(event.type)}'`,\n { details: result.issues },\n )\n }\n return {\n id: event.id ?? crypto.randomUUID(),\n type: event.type,\n payload: result.value,\n }\n })\n\n const post = async (\n body: TransportPushBody,\n ): Promise<ContractEvent<D>[]> => {\n let lastPushError: A2ClientError = new A2ClientError(\n 'STORE_UNAVAILABLE',\n 'push failed',\n )\n for (let attempt = 1; attempt <= PUSH_ATTEMPTS; attempt += 1) {\n try {\n const rows = await transport.push(body)\n return rows.map((row) => eventFromWire(row) as ContractEvent<D>)\n } catch (err) {\n lastPushError = asClientError(err)\n }\n if (!RETRYABLE_PUSH_CODES.has(lastPushError.code)) throw lastPushError\n if (attempt < PUSH_ATTEMPTS) {\n const sleepMs = 250 * attempt\n // Wait for the clock AND, when the transport can tell us,\n // the wire. The pacing sleep is a floor: a failure acked\n // over a healthy socket (a shedding store) must not re-fire\n // at wire speed. A push caught in a routine reconnect blip\n // additionally parks until the subscription is confirmed;\n // that cap scales with the reconnect backoff so an\n // unreachable server still exhausts attempts promptly.\n await Promise.all([\n new Promise((resolve) => setTimeout(resolve, sleepMs)),\n transport.awaitReady?.(\n sessionId,\n sleepMs + STREAM_TIMINGS.reconnectBaseMs * attempt,\n ),\n ])\n }\n }\n throw lastPushError\n }\n\n /**\n * Decorate the ack promise into a PushResult. `confirmed` is a\n * lazy getter — materialized on first access, so callers that\n * ignore it can't leak an unhandled rejection.\n */\n const withConfirmed = (ack: Promise<ContractEvent<D>[]>): PushResult<D> => {\n let confirmed: Promise<ContractEvent<D>[]> | undefined\n return Object.defineProperty(ack as PushResult<D>, 'confirmed', {\n get(): Promise<ContractEvent<D>[]> {\n confirmed ??= ack.then(\n (acked) =>\n new Promise<ContractEvent<D>[]>((resolve) => {\n const last = acked.at(-1)?.index ?? 0\n if ((streamIndex ?? 0) >= last) {\n resolve(acked)\n return\n }\n confirmWatchers.push({\n index: last,\n resolve: () => resolve(acked),\n })\n }),\n )\n return confirmed\n },\n })\n }\n\n // A cold socket opens only after a pending initial Promise settles.\n const initialSettled = (epoch: number): Promise<void> =>\n new Promise((resolve, reject) => {\n const check = (): void => {\n const failure =\n leaseEpoch !== epoch || status === 'closed'\n ? new DOMException('session closed', 'AbortError')\n : !hydrated && preload?.error\n if (failure) {\n listeners.delete(check)\n reject(failure)\n } else if (hydrated || !preload) {\n listeners.delete(check)\n resolve()\n }\n }\n listeners.add(check)\n check()\n })\n\n const push = (...events: AppendInput<D>[]): PushResult<D> => {\n touch(sessionId)\n return withConfirmed(\n (async () => {\n if (events.length === 0) {\n throw new TypeError('push requires at least one event')\n }\n const entries: Pending<D>[] = validated(events).map((e) => ({\n id: e.id,\n type: e.type,\n payload: e.payload,\n createdAt: new Date(),\n }))\n // Reserve before notifying: a subscriber may reenter push(),\n // and that work must follow the call whose state it observed.\n const waitForPriorPush = pushWireTail\n let releasePush!: () => void\n pushWireTail = new Promise<void>((resolve) => {\n releasePush = resolve\n })\n pending.push(...entries)\n inFlightPushes += 1\n let acknowledgedIndex: number | undefined\n const pushEpoch = leaseEpoch\n const releaseConnection =\n !hydrated || transport.awaitReady || active\n ? runtime.connect()\n : undefined\n\n try {\n refreshIdleStream()\n notify() // optimistic — the view updates before the network moves\n await waitForPriorPush\n if (transport.awaitReady) {\n await initialSettled(pushEpoch)\n await transport.awaitReady(\n sessionId,\n STREAM_TIMINGS.stallTimeoutMs,\n )\n }\n if (leaseEpoch !== pushEpoch)\n throw new DOMException('session closed', 'AbortError')\n for (const entry of entries) entry.sent = true\n const acked = await post({\n sessionId,\n events: entries.map(({ id, type, payload }) => ({\n id,\n type,\n payload,\n })),\n })\n acknowledgedIndex = acked.at(-1)?.index\n for (const event of acked) {\n const entry = pending.find((p) => p.id === event.id)\n if (entry) entry.acked = event // stream retires it at its index\n }\n retireCoveredPending()\n if ((acked.at(-1)?.index ?? 0) > (streamIndex ?? stateIndex))\n refreshIdleStream()\n notify()\n return acked\n } catch (err) {\n // Rollback: refold without the rejected events.\n const ids = new Set(entries.map((e) => e.id))\n pending = pending.filter((p) => !ids.has(p.id))\n notify()\n throw err\n } finally {\n if (\n releaseConnection &&\n pushEpoch === leaseEpoch &&\n acknowledgedIndex !== undefined &&\n acknowledgedIndex > (streamIndex ?? 0)\n ) {\n confirmWatchers.push({\n index: acknowledgedIndex,\n resolve: releaseConnection,\n lease: true,\n })\n } else releaseConnection?.()\n releasePush()\n inFlightPushes -= 1\n if (inFlightPushes === 0 && deferredHydration) {\n const next = deferredHydration\n deferredHydration = undefined\n if (next.version === undefined || next.version === initialVersion)\n if (applyInitial(next)) notifyHydrated()\n }\n touch(sessionId)\n }\n })(),\n )\n }\n\n // ── backscroll ───────────────────────────────────────────────\n // Cold reads of the log below the state index. Fetched events merge\n // into `serverEvents` only — never the fold, never the overlay.\n let historyLoads = 0\n /** Calls chain per session: each resolves its bounds after the\n * prior call's merge, so overlapping backscrolls page backward\n * instead of re-fetching the same range. */\n let historyTail: Promise<unknown> = Promise.resolve()\n\n const eventsBetween = (gte: number, lte: number): ContractEvent<D>[] =>\n serverEvents.filter((event) => event.index >= gte && event.index <= lte)\n\n /** The narrowest sub-range of [gte, lte] missing from the feed, or\n * null when the range is fully loaded (nothing to fetch). */\n const missingBetween = (\n gte: number,\n lte: number,\n ): { gte: number; lte: number } | null => {\n const present = new Set(eventsBetween(gte, lte).map((e) => e.index))\n let lo = gte\n while (lo <= lte && present.has(lo)) lo += 1\n if (lo > lte) return null\n let hi = lte\n while (hi > lo && present.has(hi)) hi -= 1\n return { gte: lo, lte: hi }\n }\n\n const loadHistory = (\n loadOptions?: LoadHistoryOptions,\n ): Promise<ContractEvent<D>[]> => {\n const readHistory = transport.history\n if (readHistory === undefined) {\n throw new TypeError(\n 'loadHistory requires an http api — the ws transport has no history lane; serve the session with server.fetch and pass its route url as the string or { type: \"http\" } api',\n )\n }\n const before = loadOptions?.before\n const limit = loadOptions?.limit\n if (\n before !== undefined &&\n (!Number.isSafeInteger(before) || before < 1)\n ) {\n throw new TypeError(\n 'loadHistory before must be a positive safe integer',\n )\n }\n if (limit !== undefined && (!Number.isSafeInteger(limit) || limit < 1)) {\n throw new TypeError('loadHistory limit must be a positive safe integer')\n }\n touch(sessionId)\n const run = historyTail.then(async () => {\n const upper = before ?? serverEvents[0]?.index ?? stateIndex + 1\n // Strictly at or below the state index: the live stream owns\n // everything above it, and the optimistic overlay must never\n // collide with a backscrolled row.\n const lte = Math.min(upper - 1, stateIndex)\n const gte = Math.max(\n clearIndex + 1,\n upper - (limit ?? DEFAULT_HISTORY_LIMIT),\n )\n if (gte > lte) return []\n const missing = missingBetween(gte, lte)\n if (missing === null) return eventsBetween(gte, lte)\n historyLoads += 1\n notify()\n try {\n const page = await readHistory({ sessionId, ...missing })\n if (page.clearIndex !== undefined) applyClearBoundary(page.clearIndex)\n mergeServerEvents(\n page.events.map((row) => eventFromWire(row) as ContractEvent<D>),\n stateIndex,\n )\n return eventsBetween(gte, lte)\n } catch (error) {\n throw asClientError(error)\n } finally {\n historyLoads -= 1\n notify()\n touch(sessionId)\n }\n })\n // Failures reject the caller, never the chain.\n historyTail = run.catch(() => {})\n return run\n }\n\n // ── the live stream ──────────────────────────────────────────\n // A run-generation model instead of a terminal `closed` flag:\n // stopping bumps the generation (the running loop notices and\n // exits), connect() starts a fresh one. Reentrant by design.\n // Consumers hold leases: connect() counts one and returns its\n // release, the last release stops the stream, and close() is the\n // hard stop — it drops every lease and stops now (bumping\n // `leaseEpoch` makes the outstanding releases inert).\n let generation = 0\n let active = false\n let streamIdle = false\n let abort: AbortController | null = null\n let leases = 0\n let leaseEpoch = 0\n\n const stopStream = (): void => {\n touch(sessionId)\n if (!active) return\n active = false\n streamIdle = false\n generation += 1 // the running loop notices and exits\n abort?.abort()\n abort = null\n // A pending trailing send dies with the stream — losing one is\n // fine by definition; sets made while closed accumulate in\n // `presenceResend` and repaint after the next connect.\n clearTimeout(presenceTimer)\n presenceTimer = undefined\n presenceBuffer = null\n status = 'closed'\n notify()\n }\n\n const runStream = async (run: number): Promise<void> => {\n let backoff = STREAM_TIMINGS.reconnectBaseMs\n let attempt = 0\n // oxlint-disable no-await-in-loop -- sequential reconnect loop\n // oxlint-disable-next-line no-unmodified-loop-condition -- close() bumps `generation`\n while (generation === run) {\n streamIdle = false\n const controller = new AbortController()\n abort = controller\n // The stall watchdog: the server heartbeats the stream, so a\n // healthy connection is never silent for long. Silence past the\n // timeout means the connection is dead in a way the socket\n // won't report (an offline browser's established SSE socket\n // neither errors nor receives) — abort it and let the normal\n // reconnect path run. This is what keeps `status: 'live'`\n // honest.\n let stall: ReturnType<typeof setTimeout> | undefined\n let stalled = false\n const armStall = (): void => {\n clearTimeout(stall)\n stall = setTimeout(() => {\n stalled = true\n controller.abort()\n }, STREAM_TIMINGS.stallTimeoutMs)\n ;(stall as { unref?: () => void }).unref?.()\n }\n let wasLive = false\n try {\n // oxlint-disable-next-line no-unmodified-loop-condition -- hydration changes while this connection waits\n while (!hydrated && preload && !preload.error)\n await waitForInitial(controller.signal)\n if (generation !== run || controller.signal.aborted) break\n if (!hydrated && preload?.error) {\n lastError = preload.error\n status = 'paused'\n notify()\n return\n }\n if (hydrated && streamIndex === undefined) streamIndex = stateIndex\n // Acks at or before this start are covered by the baseline and\n // are never streamed.\n resolveConfirmed()\n if (generation !== run) break\n bootstrapGeneration = streamIndex === undefined ? run : undefined\n const frames = transport.connect({\n sessionId,\n startAfter: streamIndex,\n reducer: reducer.name,\n signal: controller.signal,\n })\n for await (const frame of frames) {\n if (generation !== run) break\n // Every frame counts — heartbeats included. Liveness is\n // about the connection, not about events.\n armStall()\n if (frame.kind === 'snapshot') {\n if (\n frame.sessionId !== sessionId ||\n frame.name !== reducer.name ||\n !isStateSnapshotFrame(frame)\n )\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n 'bootstrap snapshot belongs to another session or reducer',\n )\n if (bootstrapGeneration !== run)\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n 'unexpected bootstrap snapshot',\n )\n const baseline =\n !hydrated || frame.index >= stateIndex\n ? { state: bootstrapState(frame), index: frame.index }\n : undefined\n streamIndex = frame.index\n bootstrapGeneration = undefined\n applyClearBoundary(frame.clearIndex ?? 0)\n if (baseline) adoptBaseline(baseline)\n resolveConfirmed()\n notify()\n if (generation !== run) break\n }\n if (!hydrated || streamIndex === undefined) {\n if (frame.kind === 'event' || frame.kind === 'events')\n throw new A2ClientError(\n 'INVALID_PAYLOAD',\n 'received an event before the bootstrap snapshot',\n )\n continue\n }\n if (!wasLive) {\n // The first frame is the connection signal: the transport\n // yields it the moment the stream is established.\n backoff = STREAM_TIMINGS.reconnectBaseMs\n attempt = 0\n wasLive = true\n status = 'live'\n lastError = null\n notify()\n if (generation !== run) break\n if (presenceResend) {\n const values = presenceResend\n presenceResend = null\n queuePresenceSend(values)\n }\n }\n if (frame.kind === 'event') {\n streamIdle = false\n ingest([eventFromWire(frame.event) as ContractEvent<D>])\n } else if (frame.kind === 'events') {\n streamIdle = false\n ingest(frame.events as ContractEvent<D>[])\n } else if (frame.kind === 'activity') {\n streamIdle = frame.idle\n if (\n streamIdle &&\n (inFlightPushes > 0 ||\n pending.some(\n (entry) =>\n (entry.acked?.index ?? 0) > (streamIndex ?? stateIndex),\n ))\n ) {\n refreshIdleStream()\n }\n } else if (frame.kind === 'presence') {\n applyPresencePatch(presencePatchFromWire(frame.patch))\n } else if (frame.kind === 'presence-snapshot') {\n applyPresenceSnapshot(\n presenceSnapshotFromWire(frame.snapshot).snapshot,\n )\n }\n }\n // The transport ended the stream cleanly — reconnect, but it\n // isn't an error.\n if (generation === run) {\n lastError = null\n }\n } catch (err) {\n if (generation === run) {\n lastError = stalled\n ? new A2ClientError(\n 'TIMEOUT',\n `stream stalled: no data for ${STREAM_TIMINGS.stallTimeoutMs}ms`,\n {\n phase: 'stream',\n timeoutMs: STREAM_TIMINGS.stallTimeoutMs,\n },\n )\n : asClientError(err)\n }\n } finally {\n if (bootstrapGeneration === run) bootstrapGeneration = undefined\n clearTimeout(stall)\n }\n if (generation !== run) break\n streamIdle = false\n if (wasLive) reconnects += 1\n attempt += 1\n let delay: number | false\n try {\n delay = options.reconnect\n ? options.reconnect({ sessionId, error: lastError, attempt })\n : backoff\n if (\n delay !== false &&\n (!Number.isFinite(delay) || delay < 0 || delay > 2_147_483_647)\n ) {\n throw new RangeError(\n 'reconnect must return false or a delay from 0 to 2147483647 ms',\n )\n }\n } catch (error) {\n if (generation !== run) break\n lastError = asClientError(error)\n delay = false\n }\n if (generation !== run) break\n if (delay === false) {\n abort = null\n status = 'paused'\n notify()\n return\n }\n const waiting = new AbortController()\n abort = waiting\n status = 'connecting'\n notify()\n if (generation !== run) break\n await new Promise<void>((resolve) => {\n let settled = false\n const finish = (): void => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n waiting.signal.removeEventListener('abort', finish)\n // oxlint-disable-next-line no-multiple-resolved -- guarded above\n resolve()\n }\n const timer = setTimeout(finish, delay)\n ;(timer as { unref?: () => void }).unref?.()\n if (waiting.signal.aborted) finish()\n else waiting.signal.addEventListener('abort', finish, { once: true })\n })\n backoff = Math.min(backoff * 2, STREAM_TIMINGS.reconnectMaxMs)\n }\n // oxlint-enable no-await-in-loop\n }\n\n const refreshIdleStream = (): void => {\n if (streamIdle && status !== 'paused') reconnectStream()\n }\n\n const reconnectStream = (): void => {\n touch(sessionId)\n if (!active) return\n streamIdle = false\n generation += 1\n const run = generation\n const previous = abort\n abort = null\n reconnects += 1\n status = 'connecting'\n lastError = null\n notify()\n // Replace the lane before aborting so a multiplexed session keeps its socket.\n if (active && generation === run) void runStream(run)\n previous?.abort()\n }\n\n const applyInitial = ({\n settings: next,\n version,\n }: {\n settings: ResolvedSessionOptions<D, S>\n version?: number\n }): boolean => {\n const nextIndex = next.initial?.index ?? 0\n if (hydrated && nextIndex > stateIndex && inFlightPushes > 0) {\n if (\n !deferredHydration ||\n nextIndex > (deferredHydration.settings.initial?.index ?? 0)\n ) {\n deferredHydration = {\n settings: next,\n ...(version === undefined ? {} : { version }),\n }\n }\n return false\n }\n\n // The boundary applies even to an older fold: it only removes history.\n const boundaryChanged = applyClearBoundary(next.initial?.clearIndex ?? 0)\n const historyChanged =\n mergeServerEvents(\n next.initialEvents,\n Math.min(nextIndex, stateIndex),\n ) || boundaryChanged\n if (next.initial != null && bootstrapGeneration === undefined)\n streamIndex ??= nextIndex\n if (next.initial == null || (hydrated && nextIndex <= stateIndex)) {\n return historyChanged\n }\n\n adoptBaseline(next.initial)\n mergeServerEvents(next.initialEvents, stateIndex)\n return true\n }\n\n const invalidateInitial = (): void => {\n initialVersion++\n preload?.cancel()\n preload = undefined\n if (deferredHydration?.version !== undefined)\n deferredHydration = undefined\n }\n\n const settleInitial = (\n result:\n { source: object; value: unknown } | { source: object; error: unknown },\n ): void => {\n const entry = preload\n if (\n !entry ||\n entry.source !== result.source ||\n entry.version !== initialVersion\n )\n return\n entry.cancel()\n const cold = !hydrated\n let changed = false\n if ('error' in result) {\n if (cold) entry.error = asClientError(result.error)\n else preload = undefined\n } else {\n try {\n assertSessionSeed({ initial: result.value })\n if (isInitialPromise(result.value as InitialSnapshot<unknown>))\n throw new TypeError('an initial Promise must resolve to a snapshot')\n preload = undefined\n changed = applyInitial({\n settings: {\n ...entry.settings,\n initial: result.value as StateSnapshot<S> | null | undefined,\n },\n version: entry.version,\n })\n } catch (error) {\n if (cold) {\n preload = entry\n entry.error = asClientError(error, { code: 'INVALID_PAYLOAD' })\n } else preload = undefined\n }\n }\n if (cold || changed) notifyHydrated()\n }\n\n const waitForInitial = (signal: AbortSignal): Promise<void> =>\n new Promise((resolve, reject) => {\n let settled = false\n const finish = (): void => {\n if (\n settled ||\n (!signal.aborted && !hydrated && preload && !preload.error)\n )\n return\n settled = true\n listeners.delete(finish)\n signal.removeEventListener('abort', finish)\n if (signal.aborted) reject(signal.reason)\n else resolve()\n }\n listeners.add(finish)\n signal.addEventListener('abort', finish, { once: true })\n finish()\n })\n\n const runtime: SessionRuntime<D, S, P> = {\n sessionId,\n // Only on presence-declaring contracts — the type surface\n // promises no runtime-inert members (a2-api.md §12).\n ...(declaresPresence ? { setPresence } : {}),\n subscribe(listener) {\n touch(sessionId)\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n touch(sessionId)\n }\n },\n getSnapshot() {\n snapshot ??= buildSnapshot()\n return snapshot\n },\n push,\n loadHistory,\n reconnect: reconnectStream,\n connect() {\n touch(sessionId)\n leases += 1\n const epoch = leaseEpoch\n if (!active) {\n active = true\n status = 'connecting'\n lastError = null\n const run = generation\n notify()\n if (active && generation === run) void runStream(run)\n }\n let released = false\n return () => {\n // Idempotent, and inert after a hard close() — a stale\n // release must not touch leases taken since.\n if (released || leaseEpoch !== epoch) return\n released = true\n touch(sessionId)\n leases -= 1\n if (leases === 0) stopStream()\n }\n },\n close() {\n invalidateInitial()\n resumeInitialError = undefined\n leases = 0\n leaseEpoch += 1\n confirmWatchers = confirmWatchers.filter((watcher) => !watcher.lease)\n stopStream()\n },\n resolveInitial: settleInitial,\n hydrate(next) {\n assertSessionSeed(next)\n touch(sessionId)\n if (!next) return\n participant ??= next.participant\n const input = next.initial\n const resume =\n !hydrated && status === 'paused' && preload?.error === lastError\n ? preload.error\n : undefined\n if (isInitialPromise(input)) {\n if (seenInitials.has(input)) {\n if (preload?.source === input && next.initialEvents !== undefined)\n preload.settings.initialEvents = next.initialEvents\n if (mergeServerEvents(next.initialEvents, stateIndex))\n notifyHydrated()\n return\n }\n invalidateInitial()\n seenInitials.add(input)\n const { initial: _initial, ...settings } = next\n const entry: PendingInitial<D, S> = {\n source: input,\n version: initialVersion,\n settings,\n cancel() {},\n }\n preload = entry\n entry.cancel = observeInitial({\n promise: input,\n settled: (result) => settleInitial({ source: input, ...result }),\n })\n if (resume) notifyHydrated(resume)\n return\n }\n if (input != null) {\n const repeated = seenInitials.has(input)\n seenInitials.add(input)\n if (repeated || (hydrated && input.index <= stateIndex)) {\n if (\n deferredHydration?.settings.initial === input &&\n next.initialEvents !== undefined\n )\n deferredHydration.settings.initialEvents = next.initialEvents\n const boundaryChanged = applyClearBoundary(input.clearIndex ?? 0)\n if (\n mergeServerEvents(\n next.initialEvents,\n Math.min(input.index, stateIndex),\n ) ||\n boundaryChanged\n )\n notifyHydrated()\n return\n }\n }\n if (input !== undefined) invalidateInitial()\n if (\n applyInitial({ settings: { ...next, initial: input } }) ||\n resume ||\n input === null\n )\n notifyHydrated(resume)\n },\n canEvict() {\n return (\n listeners.size === 0 &&\n !active &&\n inFlightPushes === 0 &&\n historyLoads === 0 &&\n confirmWatchers.length === 0 &&\n presenceTimer === undefined\n )\n },\n } as SessionRuntime<D, S, P>\n\n if (isInitialPromise(supplied)) runtime.hydrate(sessionOptions)\n return runtime\n }\n\n const client: A2Client<D, S, P> = {\n session(sessionId, sessionOptions) {\n const existing = sessions.get(sessionId)\n if (existing) {\n existing.runtime.hydrate(sessionOptions)\n touch(sessionId)\n return existing.runtime\n }\n\n const runtime = makeSession(sessionId, sessionOptions)\n sessions.set(sessionId, { runtime })\n touch(sessionId)\n return runtime\n },\n }\n registerRenderSessionFactory({\n client,\n factory: (sessionId, settings) =>\n makeSession(sessionId, settings as SessionOptions<D, S>),\n resolveInitial: ({ session, source, value }) => {\n ;(session as SessionRuntime<D, S, P>).resolveInitial({ source, value })\n },\n })\n return client\n}\n"],"mappings":"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"}