@fitzzero/quickdraw-core 5.1.1 → 5.1.2
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.
- package/README.md +533 -180
- package/dist/{admin-DKwkIh5i.d.ts → admin-DWWrT1h6.d.ts} +2 -2
- package/dist/{adminSchemas-2DUA_hZ8.d.ts → adminSchemas-D4bFKsrb.d.ts} +6 -4
- package/dist/{auth-BhWqdyb-.d.ts → auth-DXiSJZaf.d.ts} +42 -16
- package/dist/{caller-CXTFswBO.d.ts → caller-BT-Mv4bD.d.ts} +117 -22
- package/dist/{chunk-RT6OILOI.js → chunk-4D2DOGAW.js} +2 -14
- package/dist/chunk-4D2DOGAW.js.map +1 -0
- package/dist/chunk-5CGO426C.js +15 -0
- package/dist/chunk-5CGO426C.js.map +1 -0
- package/dist/{chunk-RZTP4IEW.js → chunk-6K5BY47X.js} +4594 -3481
- package/dist/chunk-6K5BY47X.js.map +1 -0
- package/dist/{chunk-VSQBHPWH.js → chunk-753VJIUP.js} +13 -15
- package/dist/chunk-753VJIUP.js.map +1 -0
- package/dist/{chunk-ZIVPHYRG.js → chunk-7QCUX4TK.js} +4 -4
- package/dist/chunk-7QCUX4TK.js.map +1 -0
- package/dist/chunk-AK23XSWD.js +16 -0
- package/dist/chunk-AK23XSWD.js.map +1 -0
- package/dist/{chunk-SHEGLZEP.js → chunk-AONAFOYU.js} +14 -5
- package/dist/{chunk-SHEGLZEP.js.map → chunk-AONAFOYU.js.map} +1 -1
- package/dist/chunk-DKE6QO26.js +136 -0
- package/dist/chunk-DKE6QO26.js.map +1 -0
- package/dist/{chunk-H23KEFBA.js → chunk-DUBU3BB3.js} +30 -1
- package/dist/chunk-DUBU3BB3.js.map +1 -0
- package/dist/{chunk-CDKG4TFA.js → chunk-GKH3LJ7N.js} +1 -1
- package/dist/chunk-GKH3LJ7N.js.map +1 -0
- package/dist/{chunk-OECZPRPW.js → chunk-GSIPUNJL.js} +49 -9
- package/dist/chunk-GSIPUNJL.js.map +1 -0
- package/dist/{chunk-DD4SKCNO.js → chunk-LCC7HNFP.js} +12 -1
- package/dist/chunk-LCC7HNFP.js.map +1 -0
- package/dist/{chunk-2PWMUVC7.js → chunk-MBH6IDSM.js} +480 -12
- package/dist/chunk-MBH6IDSM.js.map +1 -0
- package/dist/{chunk-QCHKWIRS.js → chunk-NMXYENH4.js} +10 -10
- package/dist/{chunk-QCHKWIRS.js.map → chunk-NMXYENH4.js.map} +1 -1
- package/dist/chunk-NO4M6PO5.js +101 -0
- package/dist/chunk-NO4M6PO5.js.map +1 -0
- package/dist/{chunk-TBMKJ26R.js → chunk-NW6U45HX.js} +3 -1
- package/dist/chunk-NW6U45HX.js.map +1 -0
- package/dist/{chunk-REX5YPHX.js → chunk-RJ5I2VO3.js} +74 -19
- package/dist/chunk-RJ5I2VO3.js.map +1 -0
- package/dist/{chunk-QEKVYG5F.js → chunk-RL4VKLBX.js} +1 -1
- package/dist/{chunk-QEKVYG5F.js.map → chunk-RL4VKLBX.js.map} +1 -1
- package/dist/chunk-XH2IZVLT.js +62 -0
- package/dist/chunk-XH2IZVLT.js.map +1 -0
- package/dist/{chunk-4DIQHASK.js → chunk-Z5ILULF2.js} +26 -7
- package/dist/chunk-Z5ILULF2.js.map +1 -0
- package/dist/cli/quickdraw-docs.js +5 -3
- package/dist/cli/quickdraw-docs.js.map +1 -1
- package/dist/client/index.d.ts +30 -18
- package/dist/client/index.js +8 -6
- package/dist/client/index.js.map +1 -1
- package/dist/{clientTypes-Bc-G8n-U.d.ts → clientTypes-hWcPUVS9.d.ts} +3 -3
- package/dist/{connection-Cr1BU07W.d.ts → connection-CgijdGpT.d.ts} +8 -4
- package/dist/{createServer-CP9eDHZZ.d.ts → createServer-Cp-Wk500.d.ts} +36 -14
- package/dist/{createTestApp-UKVGEmOf.d.ts → createTestApp-BB_PkqQ7.d.ts} +16 -10
- package/dist/{envelope-Cp3YcVxC.d.ts → envelope-DzWyIXjj.d.ts} +18 -4
- package/dist/{http-Djj2Inuu.d.ts → http-DotQ5bj8.d.ts} +68 -17
- package/dist/index.d.ts +7 -7
- package/dist/index.js +37 -13
- package/dist/index.js.map +1 -1
- package/dist/{infer-Teo1xpsd.d.ts → infer-BmoZsL9a.d.ts} +43 -10
- package/dist/logger-Yz93KzdV.d.ts +30 -0
- package/dist/{metrics-BdBu5o8G.d.ts → metrics-DW80Exve.d.ts} +2 -2
- package/dist/origins-kvpxnVcW.d.ts +8 -0
- package/dist/prisma/index.d.ts +5 -5
- package/dist/prisma/index.js +130 -67
- package/dist/prisma/index.js.map +1 -1
- package/dist/{rateLimit-ZMIZJUZF.js → rateLimit-5RKBFLUR.js} +2 -2
- package/dist/server/auth/index.d.ts +82 -33
- package/dist/server/auth/index.js +273 -268
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/express/index.d.ts +9 -2
- package/dist/server/express/index.js +1 -1
- package/dist/server/index.d.ts +147 -67
- package/dist/server/index.js +520 -381
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/index.d.ts +63 -17
- package/dist/server/mcp/index.js +256 -54
- package/dist/server/mcp/index.js.map +1 -1
- package/dist/server/otel.d.ts +3 -3
- package/dist/{sharing-DVa8W-yR.d.ts → sharing-UDLn1049.d.ts} +3 -3
- package/dist/testing/client.d.ts +14 -14
- package/dist/testing/client.js +9 -7
- package/dist/testing/client.js.map +1 -1
- package/dist/testing/index.d.ts +12 -12
- package/dist/testing/index.js +21 -12
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/mock.d.ts +5 -5
- package/dist/testing/mock.js +8 -6
- package/dist/{types-Cu0vmx7c.d.ts → types-CYliTP65.d.ts} +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunk-2PWMUVC7.js.map +0 -1
- package/dist/chunk-4DIQHASK.js.map +0 -1
- package/dist/chunk-CDKG4TFA.js.map +0 -1
- package/dist/chunk-DD4SKCNO.js.map +0 -1
- package/dist/chunk-H23KEFBA.js.map +0 -1
- package/dist/chunk-OECZPRPW.js.map +0 -1
- package/dist/chunk-REX5YPHX.js.map +0 -1
- package/dist/chunk-RT6OILOI.js.map +0 -1
- package/dist/chunk-RZTP4IEW.js.map +0 -1
- package/dist/chunk-TBMKJ26R.js.map +0 -1
- package/dist/chunk-VSQBHPWH.js.map +0 -1
- package/dist/chunk-YSWH776Y.js +0 -13
- package/dist/chunk-YSWH776Y.js.map +0 -1
- package/dist/chunk-ZIVPHYRG.js.map +0 -1
- package/dist/logger-BY28acW-.d.ts +0 -16
- /package/dist/{rateLimit-ZMIZJUZF.js.map → rateLimit-5RKBFLUR.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/backoff.ts","../src/client/watch.ts","../src/client/lane.ts","../src/client/reload.ts","../src/client/socket.ts","../src/client/connection.ts","../src/client/loopGuard.ts","../src/client/coordinator.ts","../src/client/additions.ts","../src/client/optimistic.ts","../src/client/session.ts","../src/client/live/collectionState.ts","../src/client/live/collectionIndex.ts","../src/client/live/collectionSnapshot.ts","../src/client/live/collectionStore.ts","../src/client/live/host.ts","../src/client/live/registry.ts","../src/client/live/streams.ts","../src/client/live/collectionLoads.ts","../src/client/live/collectionController.ts","../src/client/live/resume.ts","../src/client/live/collections.ts","../src/client/live/demux.ts","../src/client/live/entities.ts","../src/client/live/entityStore.ts","../src/client/live/events.ts","../src/client/live/presence.ts","../src/client/live/liveData.ts","../src/client/context.ts","../src/client/admin.ts","../src/client/binding.ts","../src/client/live/searchResults.ts","../src/client/live/views.ts"],"sourcesContent":["// Rate-limit backoff per kind of work (RFC 0003 section 11.1). A `RATE_LIMITED`\n// answer pauses that kind of work for its `retryAfterMs` plus random jitter,\n// so clients told to wait the same time do not all retry at the same instant.\n// Ported from 4.1's provider (4.1 `src/client/QuickdrawProvider.tsx:269-287`),\n// which paused every read for one shared window. Here each kind has its own:\n// a full query queue says nothing about mutations, and subscription events run\n// in their own per-socket lane on the server (section 8.2).\n//\n// React-free: the connection owns one and puts its windows in its state.\n\nimport type { MethodKind } from \"../contract/methods\";\nimport type { QuickdrawError } from \"../protocol/errors\";\nimport { isRecord } from \"../protocol/guards\";\n\n/** The kinds of work that back off separately: method calls by kind, and subscription events. */\nexport type BackoffKind = MethodKind | \"subscription\";\n\n/** When each kind's backoff ends, in epoch milliseconds; a kind that is not backing off is absent. */\nexport type BackoffWindows = Readonly<Partial<Record<BackoffKind, number>>>;\n\n/** The wait when a `RATE_LIMITED` answer carries no `retryAfterMs`, as in 4.1. */\nexport const DEFAULT_BACKOFF_MS = 5000;\n\n/** The shortest and longest wait, before jitter. */\nconst MIN_BACKOFF_MS = 250;\nconst MAX_BACKOFF_MS = 5 * 60 * 1000;\n\n/** Jitter adds up to this share of the wait. */\nconst JITTER_RATIO = 0.5;\n\n/** The backoff windows of one connection. */\nexport interface Backoff {\n /** Starts or extends `kind`'s window: `retryAfterMs` (or the default) plus up to half again at random. */\n report(kind: BackoffKind, retryAfterMs?: number): void;\n /** How long `kind` still backs off, in milliseconds; 0 when it does not. */\n remaining(kind: BackoffKind): number;\n /** The windows in effect. */\n windows(): BackoffWindows;\n /** Ends every window and its timer. */\n clear(): void;\n}\n\n/** The `retryAfterMs` a `RATE_LIMITED` error carries in its data, if it carries one. */\nexport function retryAfterOf(error: QuickdrawError): number | undefined {\n const retryAfterMs: unknown = isRecord(error.data) ? error.data.retryAfterMs : undefined;\n return typeof retryAfterMs === \"number\" ? retryAfterMs : undefined;\n}\n\nfunction waitFor(retryAfterMs: number | undefined): number {\n const wait =\n typeof retryAfterMs === \"number\" && Number.isFinite(retryAfterMs)\n ? retryAfterMs\n : DEFAULT_BACKOFF_MS;\n return Math.min(Math.max(wait, MIN_BACKOFF_MS), MAX_BACKOFF_MS);\n}\n\n/**\n * Creates the backoff windows of one connection. `onChange` is called with\n * the windows whenever one starts, is extended or ends.\n */\nexport function createBackoff(onChange: (windows: BackoffWindows) => void): Backoff {\n const until = new Map<BackoffKind, number>();\n const timers = new Map<BackoffKind, ReturnType<typeof setTimeout>>();\n\n const windows = (): BackoffWindows => Object.freeze(Object.fromEntries(until));\n\n function end(kind: BackoffKind): void {\n timers.delete(kind);\n until.delete(kind);\n onChange(windows());\n }\n\n return Object.freeze({\n report(kind: BackoffKind, retryAfterMs?: number): void {\n const wait = waitFor(retryAfterMs);\n const delay = wait + Math.random() * wait * JITTER_RATIO;\n const ends = Date.now() + delay;\n if (ends <= (until.get(kind) ?? 0)) {\n return;\n }\n clearTimeout(timers.get(kind));\n until.set(kind, ends);\n timers.set(\n kind,\n setTimeout(() => {\n end(kind);\n }, delay),\n );\n onChange(windows());\n },\n remaining(kind: BackoffKind): number {\n const ends = until.get(kind);\n return ends === undefined ? 0 : Math.max(0, ends - Date.now());\n },\n windows,\n clear(): void {\n for (const timer of timers.values()) {\n clearTimeout(timer);\n }\n timers.clear();\n if (until.size > 0) {\n until.clear();\n onChange(windows());\n }\n },\n });\n}\n","// The change topics a client connection watches (RFC 0003 sections 8.2 and\n// 11.3). A query whose contract declares `watch` joins the topic of the\n// collection scope it reads; the server then sends `qd:changed { s, topic,\n// rev }` once per flush that changed the topic, with no data, and the query\n// is invalidated (`hooks.ts`, through the coordinator). This replaces 4.1's\n// `invalidateOn`, which listened for hand-written event names on every hook\n// (4.1 `src/client/useServiceQuery.ts:139-166`).\n//\n// - Watches are counted per topic across everything that watches it: the\n// first sends `qd:watch`, and the topic is left (`qd:unwatch`) a tick\n// after the last ends unless another starts first, so two components\n// reading one topic join it once, and a remount joins it once too.\n// - The server forgets a socket's topics when it disconnects, so every\n// connect sends `qd:watch` again for each topic still watched.\n// - `qd:watch` runs in the socket's subscription lane on the server, and goes\n// through the connection's lane here (`lane.ts`). A `RATE_LIMITED` answer\n// starts the connection's `subscription` backoff, and the topic is joined\n// again once it ends; no topic is joined while it lasts. Any other refusal\n// (`FORBIDDEN`, `NOT_FOUND`, ...) stands until the next connect: the query\n// still works, it is just not told of changes.\n// - One `qd:changed` listener serves every topic and routes by topic.\n// Watches that share a `key` are told once per frame between them.\n// - A read can wait for its topic's join (`waitForJoin`): while the socket\n// is connected and the topic's `qd:watch` is unanswered, the query hooks\n// hold a read until the server answers it, joined or refused, so the read\n// sees every change made before the join and a watched query is read once\n// on its first mount (RFC 0003 section 17).\n// - A watch is told once (`onJoined`) when its topic is first joined after\n// the watch started, unless its key's read waited for that join: a read\n// sent before then (on a socket that was not connected yet, or a result\n// prefetched before the watch) may have missed a change made before the\n// join, so the query hooks read once more. A topic is not joined from the\n// moment the socket drops: a read of a key sent while it is not joined (it\n// waited in Socket.IO's buffer through an outage, or went out while the\n// join waited out a backoff) reaches the server before the join, so the\n// watches of that key are told again when the join is acknowledged.\n// Otherwise joining again after a reconnect tells no one: the\n// coordinator's reconnect refetch covers the queries read before it.\n//\n// React-free: the connection owns one (`connection.watch`).\n\nimport { CLIENT_EVENTS, SERVER_EVENTS } from \"../contract/names\";\nimport type { ChangedFrame } from \"../protocol/envelope\";\nimport { fromWire } from \"../protocol/errors\";\nimport { isRecord } from \"../protocol/guards\";\nimport { DEFAULT_BACKOFF_MS, retryAfterOf, type BackoffKind } from \"./backoff\";\nimport type { QuickdrawSocket } from \"./connection\";\nimport type { SubscriptionLane } from \"./lane\";\n\n/** One watch of a change topic, as `connection.watch` takes it. */\nexport interface TopicWatch {\n /** The service's name on the wire: the contract's `name`. */\n readonly service: string;\n /**\n * The topic: `{collection}:{scope}` for one scope of a collection\n * (`collectionTopic`), or `\"service\"` for the service-wide topic, which the\n * server opens only to services that declare `watchAccess`.\n */\n readonly topic: string;\n /** Called with each `qd:changed` frame of the topic while the watch lasts. */\n readonly onChanged: (frame: ChangedFrame) => void;\n /**\n * On the `\"service\"` topic, the models this watch is about (`watch: {\n * service: [models] }`): a frame whose `models` names none of them is not\n * passed to `onChanged`. A frame without `models` (an older server, or\n * the last frame of a watch the socket lost) is always passed.\n */\n readonly models?: readonly string[];\n /**\n * Called when the server first acknowledges `qd:watch` for the topic after\n * this watch started, and again when a later join (after a reconnect) is\n * acknowledged after a read of this watch's `key` went out while the topic\n * was not joined: that read may have missed a change made before the join.\n * Not called when the topic was joined already, nor when a read of the\n * `key` waited for that acknowledgement (`waitForJoin`).\n */\n readonly onJoined?: () => void;\n /**\n * Watches of one topic that share a key are told of each frame once\n * between them. The query hooks pass their query key's hash, so two\n * components reading one query cause one invalidation.\n */\n readonly key?: string;\n}\n\n/** What the topics need of their connection. */\nexport interface TopicHost {\n readonly socket: QuickdrawSocket;\n /** The connection's lane, which `qd:watch` goes through. */\n readonly lane: SubscriptionLane;\n backoffRemaining(kind: BackoffKind): number;\n reportRateLimited(kind: BackoffKind, retryAfterMs?: number): void;\n}\n\n/** A topic a read waits for, as `waitForJoin` takes it. */\nexport type JoinWait = Pick<TopicWatch, \"service\" | \"topic\" | \"key\">;\n\n/** The topics of one connection. */\nexport interface Topics {\n /** Starts a watch; returns the function that ends it. Ending it twice does nothing. */\n watch(watch: TopicWatch): () => void;\n /**\n * While the socket is connected and the topic's `qd:watch` is unanswered,\n * a promise that resolves once it is answered (joined or refused), fails,\n * or the topic is left or the connection closes; `undefined` otherwise,\n * when there is nothing to wait for. The watches with `key` are not told\n * `onJoined` for that join: the read that waited is sent after it.\n */\n waitForJoin(wait: JoinWait): Promise<void> | undefined;\n /** Joins every watched topic again: the socket has just connected. */\n rejoin(): void;\n /** Stops waiting to retry joins: the connection closed. The next connect joins again. */\n stop(): void;\n}\n\n/**\n * Where a topic stands with the server: `waiting` to be sent (not connected,\n * or backing off), `joining` until `qd:watch` is answered, `joined`, or\n * `refused` until the next connect.\n */\ntype JoinState = \"waiting\" | \"joining\" | \"joined\" | \"refused\";\n\n/** One `watch` call: the watch, and whether it was told its topic was joined. */\ninterface WatchRecord {\n readonly watch: TopicWatch;\n told: boolean;\n}\n\n/** One read waiting for a topic's join (`waitForJoin`): its key, and what lets it go. */\ninterface Hold {\n readonly key: string | undefined;\n readonly release: () => void;\n}\n\ninterface Topic {\n readonly id: string;\n readonly frame: { readonly s: string; readonly topic: string };\n /** One record per `watch` call, so the same watch object may be started twice. */\n readonly watches: Set<WatchRecord>;\n /** The reads waiting for the `qd:watch` in flight to be answered. */\n readonly holds: Set<Hold>;\n /** The keys whose reads went out while the topic was not joined, owed a telling at the next join. */\n readonly unjoinedReads: Set<string>;\n state: JoinState;\n retry: ReturnType<typeof setTimeout> | undefined;\n /**\n * Set when the last watch ended: the topic is left on the next tick\n * unless a watch starts first, so a component that remounts (React's\n * strict mode) or changes its input within one scope keeps its topic\n * instead of leaving and joining it again.\n */\n leaving: ReturnType<typeof setTimeout> | undefined;\n /** Raised by every join and by leaving, so the answer to an earlier `qd:watch` is ignored. */\n attempt: number;\n}\n\n/** The topics of one connection, by `topicId`. */\ninterface Registry {\n readonly host: TopicHost;\n readonly topics: Map<string, Topic>;\n}\n\nfunction topicId(service: string, topic: string): string {\n return `${service}\\u0000${topic}`;\n}\n\n/** Throws `error` from a microtask of its own, where it is reported without unwinding the caller. */\nfunction rethrowLater(error: unknown): void {\n queueMicrotask(() => {\n throw error;\n });\n}\n\n/** Runs `notify` for each listener, so one that throws neither stops the others nor the socket. */\nexport function notifyEach<T>(listeners: Iterable<T>, notify: (listener: T) => void): void {\n for (const listener of [...listeners]) {\n try {\n notify(listener);\n } catch (error) {\n rethrowLater(error);\n }\n }\n}\n\n/** `records` with one per key: a watch without a key is always kept. */\nfunction oncePerKey(records: Iterable<WatchRecord>): WatchRecord[] {\n const keys = new Set<string>();\n return [...records].filter(({ watch }) => {\n if (watch.key === undefined) {\n return true;\n }\n const first = !keys.has(watch.key);\n keys.add(watch.key);\n return first;\n });\n}\n\n/** The first letter lowercased, as the server names models (`modelKey`). */\nfunction modelName(model: string): string {\n return `${model.charAt(0).toLowerCase()}${model.slice(1)}`;\n}\n\n/** Whether `frame` is about a model `watch` watches: always, unless both name models and share none. */\nfunction concerns(watch: TopicWatch, frame: ChangedFrame): boolean {\n const { models } = watch;\n if (models === undefined || !Array.isArray(frame.models)) {\n return true;\n }\n const changed = new Set(frame.models.map((model) => modelName(String(model))));\n return models.some((model) => changed.has(modelName(model)));\n}\n\n/** Tells each watch of `topic` that `frame` concerns, once per key. */\nfunction tell(topic: Topic, frame: ChangedFrame): void {\n const concerned = [...topic.watches].filter(({ watch }) => concerns(watch, frame));\n notifyEach(oncePerKey(concerned), ({ watch }) => {\n watch.onChanged(frame);\n });\n}\n\n/**\n * Tells the watches of `topic` that it is joined, once per key: those not\n * told yet, and those whose key's read went out while it was not joined;\n * except those whose key's read waited for this join, which is sent after\n * it.\n */\nfunction tellJoined(topic: Topic): void {\n const waited = new Set([...topic.holds].map((hold) => hold.key));\n const unjoined = new Set(topic.unjoinedReads);\n topic.unjoinedReads.clear();\n const owed = [...topic.watches].filter(\n ({ watch, told }) => !told || (watch.key !== undefined && unjoined.has(watch.key)),\n );\n for (const record of owed) {\n record.told = true;\n }\n const toTell = owed.filter(({ watch }) => watch.key === undefined || !waited.has(watch.key));\n notifyEach(oncePerKey(toTell), ({ watch }) => {\n watch.onJoined?.();\n });\n}\n\n/**\n * Lets every read waiting for `topic`'s join go: it was answered, failed, or\n * will not be sent. Unless the topic is joined now, those reads go out\n * before its join.\n */\nfunction releaseHolds(topic: Topic): void {\n const holds = [...topic.holds];\n topic.holds.clear();\n for (const hold of holds) {\n if (topic.state !== \"joined\" && hold.key !== undefined) {\n topic.unjoinedReads.add(hold.key);\n }\n hold.release();\n }\n}\n\nfunction isChangedFrame(value: unknown): value is ChangedFrame {\n return isRecord(value) && typeof value.s === \"string\" && typeof value.topic === \"string\";\n}\n\n/** Joins `topic` again after `delayMs`, unless it is left first. */\nfunction retryIn(registry: Registry, topic: Topic, delayMs: number): void {\n clearTimeout(topic.retry);\n topic.state = \"waiting\";\n topic.retry = setTimeout(() => {\n topic.retry = undefined;\n if (registry.topics.get(topic.id) === topic) {\n join(registry, topic);\n }\n }, delayMs);\n}\n\n/** Settles a topic by a refusal of its `qd:watch`: waits out `RATE_LIMITED`, else stands refused. */\nfunction refused(registry: Registry, topic: Topic, reply: unknown): void {\n const { host } = registry;\n const failure = fromWire(isRecord(reply) ? reply.e : undefined);\n if (failure.code === \"RATE_LIMITED\") {\n host.reportRateLimited(\"subscription\", retryAfterOf(failure));\n retryIn(registry, topic, host.backoffRemaining(\"subscription\"));\n } else {\n topic.state = \"refused\";\n }\n}\n\n/**\n * Settles a topic by the answer to its `qd:watch`, or by the error that came\n * instead, and lets the reads that waited for it go: joined, they see every\n * change made before the join; otherwise they read anyway.\n */\nfunction answered(registry: Registry, topic: Topic, error: Error | null, reply: unknown): void {\n if (error !== null) {\n // No answer: a dropped connection joins again on its next connect.\n if (registry.host.socket.connected) {\n retryIn(registry, topic, DEFAULT_BACKOFF_MS);\n } else {\n topic.state = \"waiting\";\n }\n } else if (isRecord(reply) && reply.ok === true) {\n topic.state = \"joined\";\n tellJoined(topic);\n } else {\n refused(registry, topic, reply);\n }\n releaseHolds(topic);\n}\n\n/**\n * Sends `qd:watch` for `topic` when the socket is connected and\n * subscriptions are not backing off. Reads waiting for an earlier attempt\n * wait for this one; when none is sent, they go.\n */\nfunction join(registry: Registry, topic: Topic): void {\n const { host } = registry;\n clearTimeout(topic.retry);\n topic.retry = undefined;\n topic.attempt += 1;\n const wait = host.backoffRemaining(\"subscription\");\n if (!host.socket.connected) {\n topic.state = \"waiting\";\n releaseHolds(topic);\n } else if (wait > 0) {\n retryIn(registry, topic, wait);\n releaseHolds(topic);\n } else {\n topic.state = \"joining\";\n const { attempt } = topic;\n host.lane.send(CLIENT_EVENTS.watch, topic.frame, (error, reply) => {\n if (registry.topics.get(topic.id) === topic && topic.attempt === attempt) {\n answered(registry, topic, error, reply);\n }\n });\n }\n}\n\n/** Forgets `topic`, and sends `qd:unwatch` when the server may have joined it. */\nfunction leave(registry: Registry, topic: Topic): void {\n registry.topics.delete(topic.id);\n clearTimeout(topic.retry);\n clearTimeout(topic.leaving);\n topic.leaving = undefined;\n topic.attempt += 1;\n releaseHolds(topic);\n const sent = topic.state === \"joining\" || topic.state === \"joined\";\n if (sent && registry.host.socket.connected) {\n registry.host.socket.emit(CLIENT_EVENTS.unwatch, topic.frame);\n }\n}\n\n/**\n * A promise that resolves once `topic`'s `qd:watch` in flight is answered;\n * see `Topics.waitForJoin`. A read that does not wait while the topic is not\n * joined goes out before its join, and is remembered for that join.\n */\nfunction waitForJoin(registry: Registry, wait: JoinWait): Promise<void> | undefined {\n const topic = registry.topics.get(topicId(wait.service, wait.topic));\n if (topic === undefined) {\n return undefined;\n }\n if (topic.state === \"joining\" && registry.host.socket.connected) {\n return new Promise<void>((resolve) => {\n topic.holds.add({ key: wait.key, release: resolve });\n });\n }\n if (topic.state !== \"joined\" && wait.key !== undefined) {\n topic.unjoinedReads.add(wait.key);\n }\n return undefined;\n}\n\nfunction startWatch(registry: Registry, watch: TopicWatch): () => void {\n const id = topicId(watch.service, watch.topic);\n const topic = registry.topics.get(id) ?? {\n id,\n frame: Object.freeze({ s: watch.service, topic: watch.topic }),\n watches: new Set(),\n holds: new Set(),\n unjoinedReads: new Set(),\n state: \"waiting\",\n retry: undefined,\n leaving: undefined,\n attempt: 0,\n };\n registry.topics.set(id, topic);\n const kept = topic.leaving !== undefined;\n clearTimeout(topic.leaving);\n topic.leaving = undefined;\n // A topic joined already needs no telling: this watch's reads come after the join.\n const record: WatchRecord = { watch, told: topic.state === \"joined\" };\n topic.watches.add(record);\n if (topic.watches.size === 1 && !kept) {\n join(registry, topic);\n }\n return () => {\n if (topic.watches.delete(record) && topic.watches.size === 0) {\n topic.leaving = setTimeout(() => {\n if (topic.watches.size === 0 && registry.topics.get(topic.id) === topic) {\n leave(registry, topic);\n }\n }, 0);\n }\n };\n}\n\n/** Creates the topics of a connection and listens for `qd:changed` on its socket. */\nexport function createTopics(host: TopicHost): Topics {\n const registry: Registry = { host, topics: new Map() };\n host.socket.on(SERVER_EVENTS.changed, (frame: unknown) => {\n const topic = isChangedFrame(frame)\n ? registry.topics.get(topicId(frame.s, frame.topic))\n : undefined;\n if (topic !== undefined) {\n tell(topic, frame as ChangedFrame);\n }\n });\n host.socket.on(\"disconnect\", () => {\n // The server forgot the socket's topics with it.\n for (const topic of registry.topics.values()) {\n if (topic.state === \"joined\") {\n topic.state = \"waiting\";\n }\n }\n });\n return Object.freeze({\n watch: (watch: TopicWatch) => startWatch(registry, watch),\n waitForJoin: (wait: JoinWait) => waitForJoin(registry, wait),\n rejoin(): void {\n for (const topic of [...registry.topics.values()]) {\n if (topic.watches.size === 0) {\n leave(registry, topic);\n } else {\n join(registry, topic);\n }\n }\n },\n stop(): void {\n for (const topic of [...registry.topics.values()]) {\n if (topic.watches.size === 0) {\n leave(registry, topic);\n } else {\n clearTimeout(topic.retry);\n topic.retry = undefined;\n topic.attempt += 1;\n topic.state = \"waiting\";\n releaseHolds(topic);\n }\n }\n },\n });\n}\n","// The client's lane of subscription events (RFC 0003 section 8.2). The server\n// runs `qd:sub`, `qd:col:sub`, `qd:col:items`, `qd:watch` and\n// `qd:stream:sub` in a lane per socket:\n// `limits.subscriptions.maxInFlight` (8) at once and `maxQueued` (64)\n// waiting, then `RATE_LIMITED`. A page that mounts a board can ask for more\n// than that in one tick, so the client keeps a lane of its own in front of it:\n//\n// - at most `maxInFlight` events (from the server's `qd:hello`, 8 before it\n// arrives) await their acknowledgement; the others wait here, in order, so\n// the server's queue never fills;\n// - nothing is sent while the connection's `subscription` backoff lasts\n// (after a `RATE_LIMITED` answer): the lane waits it out, then goes on;\n// - nothing is sent while the socket is down: an event whose turn comes then\n// is answered at once with an error, and its sender subscribes again when\n// the socket connects (the server forgets a socket's subscriptions anyway);\n// closing the connection answers every waiting event that way at once, and\n// leaves no timer behind.\n//\n// Unsubscribe events (`qd:unsub`, `qd:col:unsub`, `qd:unwatch`,\n// `qd:stream:unsub`) are not in the server's lane, and are sent directly.\n//\n// React-free: the connection owns one; the change topics (`watch.ts`) and the\n// live data (`live/`) send through it.\n\nimport type { CLIENT_EVENTS } from \"../contract/names\";\nimport { isRecord } from \"../protocol/guards\";\nimport { MAX_SUBSCRIBE_IDS, type HelloFrame } from \"../protocol/version\";\nimport type { BackoffKind } from \"./backoff\";\nimport type { QuickdrawSocket } from \"./connection\";\nimport { notifyEach } from \"./watch\";\n\n/** How many subscription events a lane sends at once before the server's `qd:hello` says. */\nexport const DEFAULT_SUBSCRIPTION_LANE = 8;\n\n/** The events that run in the server's subscription lane. */\nexport type SubscriptionEvent =\n | typeof CLIENT_EVENTS.sub\n | typeof CLIENT_EVENTS.collectionSub\n | typeof CLIENT_EVENTS.collectionItems\n | typeof CLIENT_EVENTS.watch\n | typeof CLIENT_EVENTS.streamSub;\n\n/**\n * Receives what came back for one subscription event: an error (no answer\n * in time, the socket dropped, or it was down when the event's turn came) or\n * the server's reply.\n */\nexport type LaneCallback = (error: Error | null, reply: unknown) => void;\n\n/** What a lane needs of its connection. */\nexport interface LaneHost {\n readonly socket: QuickdrawSocket;\n /** How long to wait for an acknowledgement. */\n timeoutMs(): number;\n /** The server's `qd:hello` on the current credentials, or `null` before it arrives. */\n hello(): HelloFrame | null;\n backoffRemaining(kind: BackoffKind): number;\n}\n\n/** A connection's lane of subscription events. */\nexport interface SubscriptionLane {\n /**\n * Sends `event` with `frame` once a slot is free, and calls `done` with\n * what comes back. `done` is called exactly once, and never synchronously\n * from `send` unless the socket is down.\n */\n send(event: SubscriptionEvent, frame: object, done: LaneCallback): void;\n /** Events sent and not answered yet. */\n inFlight(): number;\n /** Events waiting for a slot. */\n waiting(): number;\n /**\n * The connection closed: answers every event waiting for a slot as if the\n * socket were down (their senders subscribe again on the next connect),\n * and stops waiting out a backoff.\n */\n stop(): void;\n}\n\n/** The subscription limits a server announced, checked: they came over the network. */\nexport interface SubscriptionLimits {\n /** Subscription events one socket may have running at once. */\n readonly maxInFlight: number;\n /** Ids one `qd:sub` may name. */\n readonly maxSubscribeIds: number;\n}\n\nfunction positiveInteger(value: unknown, fallback: number): number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value > 0 ? value : fallback;\n}\n\n/** The limits `hello` announces, or the defaults where it says nothing usable. */\nexport function subscriptionLimits(hello: HelloFrame | null): SubscriptionLimits {\n const limits: unknown = hello?.limits;\n const record = isRecord(limits) ? limits : {};\n const lane = isRecord(record.subscriptions) ? record.subscriptions : {};\n return {\n maxInFlight: positiveInteger(lane.maxInFlight, DEFAULT_SUBSCRIPTION_LANE),\n maxSubscribeIds: positiveInteger(record.maxSubscribeIds, MAX_SUBSCRIBE_IDS),\n };\n}\n\ninterface Pending {\n readonly event: SubscriptionEvent;\n readonly frame: object;\n readonly done: LaneCallback;\n}\n\n/** The untyped face of a socket's `timeout(ms)`: the lane sends four event types through one call. */\ninterface TimedEmitter {\n emit(event: string, frame: object, ack: LaneCallback): void;\n}\n\n/** The error a sender gets for an event the lane did not send because the socket was down. */\nfunction notConnected(): Error {\n return new Error(\"The socket is not connected; the event was not sent\");\n}\n\n/** Creates the subscription lane of one connection. */\nexport function createSubscriptionLane(host: LaneHost): SubscriptionLane {\n const queue: Pending[] = [];\n let inFlight = 0;\n let backoffTimer: ReturnType<typeof setTimeout> | undefined;\n\n const answer = (pending: Pending, error: Error | null, reply: unknown): void => {\n notifyEach([pending.done], (done) => {\n done(error, reply);\n });\n };\n\n function sendOne(pending: Pending): void {\n inFlight += 1;\n const emitter = host.socket.timeout(host.timeoutMs()) as unknown as TimedEmitter;\n emitter.emit(pending.event, pending.frame, (error, reply) => {\n inFlight -= 1;\n answer(pending, error, reply);\n pump();\n });\n }\n\n function waitForBackoff(wait: number): void {\n backoffTimer ??= setTimeout(() => {\n backoffTimer = undefined;\n pump();\n }, wait);\n }\n\n function dropAll(): void {\n for (const dropped of queue.splice(0)) {\n answer(dropped, notConnected(), undefined);\n }\n }\n\n function pump(): void {\n const { maxInFlight } = subscriptionLimits(host.hello());\n while (queue.length > 0 && inFlight < maxInFlight) {\n if (!host.socket.connected) {\n dropAll();\n return;\n }\n const wait = host.backoffRemaining(\"subscription\");\n if (wait > 0) {\n waitForBackoff(wait);\n return;\n }\n sendOne(queue.shift() as Pending);\n }\n }\n\n return Object.freeze({\n send(event: SubscriptionEvent, frame: object, done: LaneCallback): void {\n queue.push({ event, frame, done });\n pump();\n },\n inFlight: () => inFlight,\n waiting: () => queue.length,\n stop(): void {\n clearTimeout(backoffTimer);\n backoffTimer = undefined;\n dropAll();\n },\n });\n}\n","// What a client does by default when the server speaks another protocol\n// (RFC 0003 section 8.1): reload the page once per browser session, so a tab\n// left open across a deploy picks up the client that matches the server. A\n// second mismatch in the same session (the new bundle still speaks the old\n// protocol) does not reload again, which would loop.\n//\n// Without a DOM (React Native, Node) there is nothing to reload and this does\n// nothing; such apps pass their own `onProtocolMismatch`. Without\n// `sessionStorage` it does nothing either, since it could not stop a loop.\n\nimport type { ProtocolMismatch } from \"../protocol/version\";\n\n/** The `sessionStorage` key that records a reload for one server protocol. */\nexport const RELOAD_KEY_PREFIX = \"quickdraw:protocol-reload:\";\n\ninterface BrowserScope {\n readonly location?: { reload?: unknown };\n readonly sessionStorage?: Pick<Storage, \"getItem\" | \"setItem\">;\n}\n\n/** Records the reload in `sessionStorage`; false when one was recorded already or storage fails. */\nfunction firstReload(scope: BrowserScope, key: string): boolean {\n try {\n const storage = scope.sessionStorage;\n if (storage === undefined || storage.getItem(key) !== null) {\n return false;\n }\n storage.setItem(key, String(Date.now()));\n return true;\n } catch {\n return false;\n }\n}\n\n/** The default `onProtocolMismatch`: reloads the page once per session and server protocol. */\nexport function reloadOncePerSession(mismatch: ProtocolMismatch): void {\n const scope = globalThis as BrowserScope;\n const location = scope.location;\n if (typeof location?.reload !== \"function\") {\n return;\n }\n if (firstReload(scope, `${RELOAD_KEY_PREFIX}${mismatch.expected}`)) {\n (location as { reload(): void }).reload();\n }\n}\n","// The Socket.IO socket of a client connection (RFC 0003 sections 8.1 and\n// 8.4): created unconnected with the connection's options, typed with the v5\n// frames, encoding with the JSON-only parser unless the server sends binary,\n// and sending the v5 handshake beside the app's credentials on every\n// connect. Split from `connection.ts`, which owns the socket's state.\n//\n// React-free.\n\nimport { io, type ManagerOptions, type Socket, type SocketOptions } from \"socket.io-client\";\nimport type { ClientToServerEvents, ServerToClientEvents } from \"../protocol/envelope\";\nimport { createJsonParser } from \"../protocol/parser\";\nimport { PROTOCOL_VERSION } from \"../protocol/version\";\nimport { QUICKDRAW_VERSION } from \"../version\";\n\n/** The client's Socket.IO socket, typed with the v5 frames. */\nexport type QuickdrawSocket = Socket<ServerToClientEvents, ClientToServerEvents>;\n\n/** Socket.IO client options: `io(url, options)`. */\nexport type SocketClientOptions = Partial<ManagerOptions & SocketOptions>;\n\n/** The connection options the socket is made from. */\nexport interface SocketSettings {\n readonly url: string;\n readonly socketOptions?: SocketClientOptions;\n readonly transports?: SocketClientOptions[\"transports\"];\n readonly binary?: boolean;\n}\n\n/**\n * Creates the socket, unconnected. `credentials` is read on every connect,\n * so new credentials take effect on the next one; the handshake adds\n * `qd: { protocol: 5, client }` to them.\n */\nexport function createSocket(\n settings: SocketSettings,\n credentials: () => Readonly<Record<string, unknown>>,\n): QuickdrawSocket {\n return io(settings.url, {\n forceNew: true,\n withCredentials: true,\n transports: [\"websocket\", \"polling\"],\n ...(settings.binary === true ? {} : { parser: createJsonParser() }),\n ...settings.socketOptions,\n ...(settings.transports === undefined ? {} : { transports: settings.transports }),\n autoConnect: false,\n auth: (send: (data: object) => void) => {\n send({ ...credentials(), qd: { protocol: PROTOCOL_VERSION, client: QUICKDRAW_VERSION } });\n },\n });\n}\n","// The connection of a v5 client (RFC 0003 sections 8.1, 11.1 and 11.3): one\n// Socket.IO socket with the v5 handshake, its state as a snapshot to\n// subscribe to, the pushes a server sends a whole connection, and the change\n// topics it watches. Ported from 4.1's provider\n// (4.1 `src/client/QuickdrawProvider.tsx:295-403`), without React, so a\n// React Native or Node client uses it as it is: nothing here touches\n// `window` or `document`.\n//\n// - The handshake sends `auth.qd = { protocol: 5, client }` beside the app's\n// credentials, and keeps the server's `qd:hello`: who the socket acts for,\n// its grants, and the limits. Once it is known, a call waits the server's\n// `callTimeoutMs` plus 2 s by default, so a slow call ends with the\n// server's `TIMEOUT` rather than the client's.\n// - A refused handshake says why in its `connect_error` data: another\n// protocol (`PROTOCOL_MISMATCH`, which calls `onProtocolMismatch`) or failed\n// authentication (`UNAUTHENTICATED`). Socket.IO does not retry either.\n// - `qd:rotate` reconnects at a random moment within its window; `qd:access`\n// updates the grants in the state.\n// - `RATE_LIMITED` answers start a backoff window per kind (`backoff.ts`).\n// - A connection that drops and comes back with the same credentials (or\n// rotates) is `reconnecting` meanwhile, joins its watched topics again\n// (`watch.ts`) and tells `onReconnect` listeners, which refetch what may\n// have changed (the provider, through the coordinator).\n// - Every `qd:hello` stands for a new socket, which is in no app room until\n// a call joins it: `onHello` listeners hear each one (and the current one\n// when they start listening), to run their joining calls again\n// (`useJoin`).\n// - New credentials (`setAuth`) fail the calls waiting in Socket.IO's send\n// buffer with `CANCELLED` before reconnecting: Socket.IO would send them\n// on the next connect, as the new user.\n// - Subscription events (`qd:sub`, `qd:col:sub`, `qd:col:items`,\n// `qd:watch`) go through the connection's lane (`lane.ts`), paced by the\n// server's `limits.subscriptions`.\n//\n// 4.1 created a socket per token and hard-coded its options\n// (4.1 `src/client/QuickdrawProvider.tsx:306-312`), and cleared every\n// subscription on a disconnect (`:326-330`). Here one socket lives as long as\n// the connection (`socket.ts`): new credentials reconnect it, and\n// `socketOptions` pass through to `io()`. Caches are never cleared on a\n// disconnect.\n\nimport { SERVER_EVENTS } from \"../contract/names\";\nimport { QuickdrawError } from \"../protocol/errors\";\nimport { isRecord } from \"../protocol/guards\";\nimport {\n isAuthenticationRefused,\n isProtocolMismatch,\n type AuthenticationRefused,\n type HelloFrame,\n type ProtocolMismatch,\n} from \"../protocol/version\";\nimport { createBackoff, type Backoff, type BackoffKind, type BackoffWindows } from \"./backoff\";\nimport { createSubscriptionLane, type SubscriptionLane } from \"./lane\";\nimport { reloadOncePerSession } from \"./reload\";\nimport { createSocket, type QuickdrawSocket, type SocketClientOptions } from \"./socket\";\nimport { createTopics, notifyEach, type JoinWait, type Topics, type TopicWatch } from \"./watch\";\n\nexport type { QuickdrawSocket, SocketClientOptions };\n\n/**\n * The credentials a connection authenticates with: a token, sent as\n * `auth.token`; an object of handshake fields, sent as they are; or nothing,\n * for an anonymous connection (or one a session cookie authenticates).\n */\nexport type ConnectionAuth = string | Readonly<Record<string, unknown>> | null | undefined;\n\n/** Options of {@link createQuickdrawConnection}. */\nexport interface QuickdrawConnectionOptions {\n /** The server's URL: `\"https://api.example.com\"`. */\n readonly url: string;\n /** The credentials to connect with. `setAuth` changes them. */\n readonly auth?: ConnectionAuth;\n /**\n * Socket.IO manager and socket options, passed to `io()` over the defaults\n * (`withCredentials: true`, `forceNew: true`). The connection sets `auth`\n * and `autoConnect` itself.\n */\n readonly socketOptions?: SocketClientOptions;\n /**\n * The transports to try, in order. Default `[\"websocket\", \"polling\"]`;\n * React Native clients pass `[\"websocket\"]`.\n */\n readonly transports?: SocketClientOptions[\"transports\"];\n /**\n * `true` when the server was created with `binary: true`. By default the\n * client encodes with the JSON-only parser, as the server does (section 8.4).\n */\n readonly binary?: boolean;\n /**\n * How long a call waits for its answer before it fails with `TIMEOUT`.\n * Default: the server's `callTimeoutMs` plus 2,000 ms once its hello has\n * arrived, and 10,000 ms before.\n */\n readonly timeoutMs?: number;\n /**\n * Called when the server refuses the connection because it speaks another\n * protocol. Default: reload the page once per browser session; nothing\n * without a DOM.\n */\n readonly onProtocolMismatch?: (mismatch: ProtocolMismatch) => void;\n}\n\n/**\n * Where a connection is:\n *\n * - `idle`: not opened, or closed by the app;\n * - `connecting`: opening, or reopening after it was lost (Socket.IO retries);\n * - `connected`;\n * - `disconnected`: the server ended it, and it does not retry;\n * - `refused`: the server refused the handshake (see `refusal`).\n */\nexport type ConnectionStatus = \"idle\" | \"connecting\" | \"connected\" | \"disconnected\" | \"refused\";\n\n/** Why the server refused a handshake: another protocol, failed authentication, or something else. */\nexport type ConnectionRefusal =\n | ProtocolMismatch\n | AuthenticationRefused\n | { readonly code: \"REFUSED\"; readonly message: string };\n\n/** A snapshot of a connection's state. A new object whenever anything in it changes. */\nexport interface ConnectionState {\n readonly status: ConnectionStatus;\n /**\n * True while the connection is `connecting` again after it was connected\n * with its current credentials: the socket dropped, or the server asked it\n * to rotate. Queries keep running meanwhile (their calls wait in the send\n * buffer); `setAuth` and `close` end it.\n */\n readonly reconnecting: boolean;\n /** The server's `qd:hello` on the current credentials, or `null` before it arrives. */\n readonly hello: HelloFrame | null;\n /**\n * The principal's service grants: from the server's `qd:hello`, then from\n * every `qd:access` push; `null` before the hello on the current\n * credentials arrives.\n */\n readonly serviceAccess: HelloFrame[\"serviceAccess\"] | null;\n /** Why the last handshake was refused, while `status` is `refused`. */\n readonly refusal: ConnectionRefusal | null;\n /** When each kind's rate-limit backoff ends; a kind that is not backing off is absent. */\n readonly backoff: BackoffWindows;\n}\n\n/** A v5 client connection. */\nexport interface QuickdrawConnection {\n readonly url: string;\n /**\n * The default time limit of a call, in milliseconds: the `timeoutMs`\n * option when it was given; otherwise the server's `callTimeoutMs` plus\n * 2,000 once its hello has arrived, and 10,000 before.\n */\n readonly timeoutMs: number;\n /** The socket, created unconnected with the connection and kept for its lifetime. */\n readonly socket: QuickdrawSocket;\n /**\n * The lane every subscription event goes through (`qd:sub`, `qd:col:sub`,\n * `qd:col:items`, `qd:watch`): at most the server's\n * `limits.subscriptions.maxInFlight` of them unanswered at once, none while\n * the `subscription` backoff lasts.\n */\n readonly subscriptionLane: SubscriptionLane;\n /** The current state. The same object until something changes. */\n getState(): ConnectionState;\n /** Calls `listener` after every state change; returns the unsubscribe function. */\n subscribe(listener: () => void): () => void;\n /** Connects, unless the connection is connected or connecting. */\n open(): void;\n /**\n * Disconnects and stays idle until `open`. Calls in flight fail; calls\n * still waiting in Socket.IO's send buffer fail with `CANCELLED`. No timer\n * of the connection's is left running.\n */\n close(): void;\n /**\n * Opens the connection for one user of it (a mounted provider) and returns\n * the release. The last release closes it on the next tick, unless the\n * connection is retained again first, so React's strict mode, which mounts\n * effects twice, does not reconnect.\n */\n retain(): () => void;\n /**\n * Changes the credentials. When they differ from the current ones\n * (compared by value as they are sent: a token string is the same as\n * `{ token }` with that value), the calls still waiting in Socket.IO's send\n * buffer fail with `CANCELLED` (they were made as the last credentials,\n * and would be sent as the new ones), an open connection reconnects with\n * the new credentials, and this returns true.\n */\n setAuth(auth: ConnectionAuth): boolean;\n /** A call id, unique among this connection's calls in flight. */\n nextCallId(): number;\n /** Starts or extends `kind`'s backoff after a `RATE_LIMITED` answer. */\n reportRateLimited(kind: BackoffKind, retryAfterMs?: number): void;\n /** How long `kind` still backs off, in milliseconds; 0 when it does not. */\n backoffRemaining(kind: BackoffKind): number;\n /**\n * Calls `listener` each time the socket connects again with the same\n * credentials: after it dropped, after a `qd:rotate`, or on `open` after\n * the server ended it. Not on the first connect, nor after `setAuth` or\n * `close`. Watched topics are joined again first. Returns the unsubscribe\n * function.\n */\n onReconnect(listener: () => void): () => void;\n /**\n * Calls `listener` with every `qd:hello` the server sends: on the first\n * connect, after every reconnect (a dropped socket, a `qd:rotate`, `open`\n * after the server ended it) and after new credentials. Each hello is a\n * new socket, which is in no app room until a call joins it, so this is\n * where a client joins its rooms again (`useJoin` does it for React).\n * When the connection is connected and already has its hello, `listener`\n * is also called with it, in a microtask. Returns the unsubscribe\n * function.\n *\n * @example\n * const stop = connection.onHello(() => {\n * void call(connection, { service: \"gameService\", method: \"watchWorld\", input: { worldId } });\n * });\n */\n onHello(listener: (hello: HelloFrame) => void): () => void;\n /**\n * Watches a change topic (RFC 0003 section 11.3): the first watch of a\n * topic sends `qd:watch` (again on every connect), the last one to end\n * sends `qd:unwatch`, and `onChanged` receives the topic's `qd:changed`\n * frames meanwhile. Returns the function that ends the watch.\n *\n * @example\n * const stop = connection.watch({\n * service: \"taskService\",\n * topic: collectionTopic(\"byProject\", projectId),\n * onChanged: () => void refresh(),\n * });\n */\n watch(watch: TopicWatch): () => void;\n /**\n * While the socket is connected and a watched topic's `qd:watch` is\n * unanswered, a promise that resolves once the server answers it (joined\n * or refused), the attempt fails, the topic is left or the connection\n * closes; `undefined` when there is nothing to wait for. A read sent after\n * it sees every change made before the join, so the watches with `key`\n * are not told `onJoined` for that join. The query hooks hold a watched\n * query's read with it.\n */\n waitForJoin(wait: JoinWait): Promise<void> | undefined;\n}\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\n/** How much longer than the server's time limit a call waits, so the server's `TIMEOUT` arrives first. */\nconst HELLO_TIMEOUT_MARGIN_MS = 2_000;\n\n/** The state every connection starts in, and the one a server renders (no socket opens there). */\nexport const INITIAL_CONNECTION_STATE: ConnectionState = Object.freeze({\n status: \"idle\",\n reconnecting: false,\n hello: null,\n serviceAccess: null,\n refusal: null,\n backoff: Object.freeze({}),\n});\n\ninterface StateStore {\n get(): ConnectionState;\n set(patch: Partial<ConnectionState>): void;\n subscribe(listener: () => void): () => void;\n}\n\nfunction createStore(): StateStore {\n let state = INITIAL_CONNECTION_STATE;\n const listeners = new Set<() => void>();\n return {\n get: () => state,\n set(patch) {\n state = Object.freeze({ ...state, ...patch });\n for (const listener of [...listeners]) {\n listener();\n }\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n\nfunction credentialsOf(auth: ConnectionAuth): Readonly<Record<string, unknown>> {\n if (typeof auth === \"string\") {\n return auth === \"\" ? {} : { token: auth };\n }\n return auth ?? {};\n}\n\n/**\n * Equal credentials give equal keys, whatever the order of their fields at\n * any depth. They are compared as they are sent: a token string and\n * `{ token }` with the same value are the same credentials.\n */\nfunction authKey(auth: ConnectionAuth): string {\n const sorted = (_key: string, value: unknown): unknown =>\n isRecord(value)\n ? Object.fromEntries(Object.entries(value).sort(([a], [b]) => (a < b ? -1 : 1)))\n : value;\n return JSON.stringify(credentialsOf(auth), sorted);\n}\n\n/** An acknowledgement as Socket.IO keeps it: `withError` when it takes an error first (`timeout`). */\ntype Ack = ((...args: unknown[]) => void) & { readonly withError?: boolean };\n\n/**\n * Fails every packet waiting in Socket.IO's send buffer with `error` and\n * empties the buffer. Socket.IO sends that buffer on the next connect,\n * whatever credentials the socket then carries, so a call made as one user\n * would run as the next.\n */\nfunction failBuffered(socket: QuickdrawSocket, error: Error): void {\n const buffered = socket.sendBuffer.splice(0);\n const { acks } = socket as unknown as { readonly acks: Record<string, Ack | undefined> };\n for (const packet of buffered) {\n const id = packet.id === undefined ? undefined : String(packet.id);\n const ack = id === undefined ? undefined : acks[id];\n if (id !== undefined && ack !== undefined) {\n Reflect.deleteProperty(acks, id);\n if (ack.withError === true) {\n ack.call(socket, error);\n }\n }\n }\n}\n\nfunction refusalOf(error: Error & { readonly data?: unknown }): ConnectionRefusal {\n if (isProtocolMismatch(error.data)) {\n return { code: error.data.code, expected: error.data.expected };\n }\n if (isAuthenticationRefused(error.data)) {\n return { code: \"UNAUTHENTICATED\" };\n }\n return { code: \"REFUSED\", message: error.message };\n}\n\n/** The longest delay a timer honors (2^31 - 1 ms); a longer one fires at once. */\nconst MAX_TIMEOUT_MS = 2_147_483_647;\n\n/** True when `value` can be a call's time limit: more than 0 and at most 2^31 - 1 milliseconds. */\nexport function isTimeLimit(value: unknown): value is number {\n return typeof value === \"number\" && value > 0 && value <= MAX_TIMEOUT_MS;\n}\n\n/** The `timeoutMs` option, checked; `undefined` when it was left out. */\nfunction checkOptions(options: QuickdrawConnectionOptions): number | undefined {\n if (typeof options.url !== \"string\" || options.url === \"\") {\n throw new TypeError(\"createQuickdrawConnection: url must be the server's URL\");\n }\n const { timeoutMs } = options;\n if (timeoutMs !== undefined && !isTimeLimit(timeoutMs)) {\n throw new TypeError(\n \"createQuickdrawConnection: timeoutMs must be a number of milliseconds, above 0 and at most 2^31 - 1\",\n );\n }\n return timeoutMs;\n}\n\n/** A call's default time limit: the option, else the server's limit plus the margin, else 10 s. */\nfunction defaultTimeout(option: number | undefined, hello: HelloFrame | null): number {\n if (option !== undefined) {\n return option;\n }\n // The frame came over the network: its shape is checked, not trusted.\n const limits: unknown = hello?.limits;\n const serverMs: unknown = isRecord(limits) ? limits.callTimeoutMs : undefined;\n const fromHello = typeof serverMs === \"number\" ? serverMs + HELLO_TIMEOUT_MARGIN_MS : undefined;\n return isTimeLimit(fromHello) ? fromHello : DEFAULT_TIMEOUT_MS;\n}\n\n/**\n * Whether the socket has connected with the current credentials since the\n * connection last opened (the next connect is then a reconnect), and the\n * topics and the subscription lane, which stop retrying and waiting when the\n * connection closes.\n */\ninterface Session {\n established: boolean;\n readonly topics: Topics;\n readonly lane: SubscriptionLane;\n}\n\n/** When the socket opens and closes: the app's `open`, `close` and `retain`, new credentials, `qd:rotate`. */\ninterface Lifecycle {\n open(): void;\n close(): void;\n retain(): () => void;\n /** Reconnects an open connection, for new credentials. */\n reconnect(): void;\n /** Reconnects at a random moment within `withinMs` (`qd:rotate`). */\n rotateWithin(withinMs: number): void;\n /** The status a socket that will not retry is in: closed by the app, or ended by the server. */\n stoppedStatus(): ConnectionStatus;\n}\n\nfunction createLifecycle(\n socket: QuickdrawSocket,\n store: StateStore,\n backoff: Backoff,\n session: Session,\n): Lifecycle {\n let opened = false;\n let switching = false;\n let users = 0;\n let closeTimer: ReturnType<typeof setTimeout> | undefined;\n let rotateTimer: ReturnType<typeof setTimeout> | undefined;\n\n function connect(): void {\n socket.connect();\n store.set({ status: \"connecting\", refusal: null });\n }\n\n function reconnect(): void {\n if (!opened) {\n return;\n }\n switching = true;\n socket.disconnect();\n switching = false;\n connect();\n }\n\n function open(): void {\n clearTimeout(closeTimer);\n closeTimer = undefined;\n opened = true;\n if (!socket.connected && !socket.active) {\n connect();\n }\n }\n\n function close(): void {\n opened = false;\n session.established = false;\n session.topics.stop();\n session.lane.stop();\n clearTimeout(closeTimer);\n closeTimer = undefined;\n clearTimeout(rotateTimer);\n rotateTimer = undefined;\n backoff.clear();\n // A call waiting to be sent would go out on the next `open`, long after the app closed.\n failBuffered(\n socket,\n new QuickdrawError(\"CANCELLED\", \"The connection closed before the call was sent\"),\n );\n socket.disconnect();\n store.set({ status: \"idle\", reconnecting: false });\n }\n\n function retain(): () => void {\n users += 1;\n open();\n let released = false;\n return () => {\n if (!released) {\n released = true;\n users -= 1;\n if (users === 0) {\n closeTimer = setTimeout(close, 0);\n }\n }\n };\n }\n\n function rotateWithin(withinMs: number): void {\n if (rotateTimer === undefined) {\n rotateTimer = setTimeout(() => {\n rotateTimer = undefined;\n reconnect();\n }, Math.random() * withinMs);\n }\n }\n\n function stoppedStatus(): ConnectionStatus {\n if (switching) {\n return \"connecting\";\n }\n return opened ? \"disconnected\" : \"idle\";\n }\n\n return { open, close, retain, reconnect, rotateWithin, stoppedStatus };\n}\n\n/** One `onHello` listener, and the last hello it was given, so no hello reaches it twice. */\ninterface HelloListener {\n readonly listener: (hello: HelloFrame) => void;\n last: HelloFrame | undefined;\n}\n\n/** What the socket's own events update: the state, the session (and its topics) and the listeners. */\ninterface Wiring {\n readonly socket: QuickdrawSocket;\n readonly store: StateStore;\n readonly lifecycle: Lifecycle;\n readonly session: Session;\n readonly reconnected: Set<() => void>;\n readonly hellos: Set<HelloListener>;\n readonly onProtocolMismatch: (mismatch: ProtocolMismatch) => void;\n}\n\n/** Gives `entry` the hello, unless it was given that one already or stopped listening. */\nfunction sayHello(\n hellos: ReadonlySet<HelloListener>,\n entry: HelloListener,\n hello: HelloFrame,\n): void {\n if (hellos.has(entry) && entry.last !== hello) {\n entry.last = hello;\n entry.listener(hello);\n }\n}\n\n/** Adds `listener` to `set`; returns the function that takes it out again. */\nfunction addListener<T>(set: Set<T>, listener: T): () => void {\n set.add(listener);\n return () => {\n set.delete(listener);\n };\n}\n\n/** `connection.onHello`: every hello from now on, and the current one in a microtask. */\nfunction listenForHellos(\n wiring: Pick<Wiring, \"hellos\" | \"store\">,\n listener: (hello: HelloFrame) => void,\n): () => void {\n const { hellos, store } = wiring;\n const entry: HelloListener = { listener, last: undefined };\n hellos.add(entry);\n const { status, hello } = store.get();\n if (status === \"connected\" && hello !== null) {\n queueMicrotask(() => {\n notifyEach([entry], (current) => {\n sayHello(hellos, current, hello);\n });\n });\n }\n return () => {\n hellos.delete(entry);\n };\n}\n\n/** The socket's connects, disconnects and refusals. */\nfunction listenToSocket(wiring: Wiring): void {\n const { socket, store, lifecycle, session } = wiring;\n socket.on(\"connect\", () => {\n const again = session.established;\n session.established = true;\n store.set({ status: \"connected\", reconnecting: false, refusal: null });\n session.topics.rejoin();\n if (again) {\n notifyEach(wiring.reconnected, (listener) => {\n listener();\n });\n }\n });\n socket.on(\"disconnect\", () => {\n const status = socket.active ? \"connecting\" : lifecycle.stoppedStatus();\n store.set({ status, reconnecting: status === \"connecting\" && session.established });\n });\n socket.on(\"connect_error\", (error: Error & { readonly data?: unknown }) => {\n if (socket.active) {\n return;\n }\n const refusal = refusalOf(error);\n session.established = false;\n store.set({ status: \"refused\", reconnecting: false, refusal });\n if (refusal.code === \"PROTOCOL_MISMATCH\") {\n wiring.onProtocolMismatch(refusal);\n }\n });\n}\n\n/** The pushes a server sends the whole connection. */\nfunction listenToPushes(wiring: Wiring): void {\n const { socket, store, lifecycle } = wiring;\n socket.on(SERVER_EVENTS.hello, (frame) => {\n const grants = isRecord(frame) && isRecord(frame.serviceAccess) ? frame.serviceAccess : null;\n store.set({ hello: frame, serviceAccess: grants as HelloFrame[\"serviceAccess\"] | null });\n notifyEach(wiring.hellos, (entry) => {\n sayHello(wiring.hellos, entry, frame);\n });\n });\n socket.on(SERVER_EVENTS.access, (frame) => {\n if (isRecord(frame) && isRecord(frame.serviceAccess)) {\n store.set({ serviceAccess: frame.serviceAccess as HelloFrame[\"serviceAccess\"] });\n }\n });\n socket.on(SERVER_EVENTS.rotate, (frame) => {\n const withinMs: unknown = isRecord(frame) ? frame.withinMs : undefined;\n if (typeof withinMs === \"number\" && Number.isFinite(withinMs) && withinMs >= 0) {\n lifecycle.rotateWithin(withinMs);\n }\n });\n}\n\n/**\n * Creates a v5 client connection to `url`. It does not connect until `open`\n * or `retain`. React apps use `QuickdrawProvider`, which owns one; other\n * clients (React Native without the provider, Node scripts) use this with\n * `call`.\n *\n * @example\n * const connection = createQuickdrawConnection({ url: \"http://localhost:4000\", auth: token });\n * connection.open();\n * const reply = await call(connection, { service: \"taskService\", method: \"get\", input: { id } });\n */\nexport function createQuickdrawConnection(\n options: QuickdrawConnectionOptions,\n): QuickdrawConnection {\n const timeoutOption = checkOptions(options);\n const store = createStore();\n const backoff = createBackoff((windows) => {\n store.set({ backoff: windows });\n });\n let auth = options.auth;\n let nextId = 0;\n const socket = createSocket(options, () => credentialsOf(auth));\n const timeoutMs = (): number => defaultTimeout(timeoutOption, store.get().hello);\n const subscriptionLane = createSubscriptionLane({\n socket,\n timeoutMs,\n hello: () => store.get().hello,\n backoffRemaining: backoff.remaining,\n });\n const topics = createTopics({\n socket,\n lane: subscriptionLane,\n backoffRemaining: backoff.remaining,\n reportRateLimited: backoff.report,\n });\n const session: Session = { established: false, topics, lane: subscriptionLane };\n const lifecycle = createLifecycle(socket, store, backoff, session);\n const reconnected = new Set<() => void>();\n const wiring: Wiring = {\n socket,\n store,\n lifecycle,\n session,\n reconnected,\n hellos: new Set(),\n onProtocolMismatch: options.onProtocolMismatch ?? reloadOncePerSession,\n };\n listenToSocket(wiring);\n listenToPushes(wiring);\n\n return Object.freeze({\n url: options.url,\n get timeoutMs(): number {\n return timeoutMs();\n },\n socket,\n subscriptionLane,\n getState: store.get,\n subscribe: store.subscribe,\n open: lifecycle.open,\n close: lifecycle.close,\n retain: lifecycle.retain,\n setAuth(next: ConnectionAuth): boolean {\n if (authKey(next) === authKey(auth)) {\n return false;\n }\n auth = next;\n session.established = false;\n failBuffered(\n socket,\n new QuickdrawError(\"CANCELLED\", \"The credentials changed before the call was sent\"),\n );\n store.set({ hello: null, serviceAccess: null });\n lifecycle.reconnect();\n return true;\n },\n nextCallId(): number {\n const id = nextId;\n nextId = nextId >= Number.MAX_SAFE_INTEGER ? 0 : nextId + 1;\n return id;\n },\n reportRateLimited: backoff.report,\n backoffRemaining: backoff.remaining,\n onReconnect: (listener: () => void) => addListener(reconnected, listener),\n onHello: (listener: (hello: HelloFrame) => void) => listenForHellos(wiring, listener),\n watch: topics.watch,\n waitForJoin: topics.waitForJoin,\n });\n}\n","// Development warnings for a client caught in a loop, in the server's format\n// (`[quickdraw:<kind>] <service>.<method>: <message>`, RFC 0003 section 13):\n//\n// - `repeated-mutation`: one `useMutation` hook instance issues its mutation\n// more than 5 times within a second, as a mutation fired from an effect or\n// from render does. The warning names the component that holds the hook.\n// - `repeated-invalidation`: one cached query is asked to be invalidated\n// with `qd.invalidate` more than 20 times within a second, as an effect or\n// a render that invalidates on every run does; or the coordinator itself\n// refetches it or marks it stale more than 20 times within a second. The\n// coordinator's work is counted after its coalescing, at the refetch it\n// issues: its window turns a watched topic that changes 25 times a second\n// into a few refetches, which is the coordinator doing its job, not a loop.\n//\n// The coordinator keeps a loop from flooding the server (one read in flight\n// per key, one queued, one refetch per window), so an app's loop would\n// otherwise go unseen until the socket's rate limit answers `RATE_LIMITED`;\n// that is why what an app asks is counted as it is asked. Each warning is\n// logged once per kind and member per `QueryClient`, with the root's\n// `consoleLogger`, and only in development: never where\n// `process.env.NODE_ENV` is \"production\" or cannot be read.\n//\n// React-free: the hooks hand in a trace of where they were rendered, made\n// once per hook instance in development, whose stack names the component\n// (the frame just above React's own `react_stack_bottom_frame`).\n\nimport type { QueryClient, QueryKey } from \"@tanstack/react-query\";\nimport { consoleLogger } from \"../contract/logger\";\nimport { KEY_ROOT } from \"./keys\";\n\n/** Mutations one hook instance may issue within {@link MUTATION_WINDOW_MS}. */\nexport const MUTATION_LIMIT = 5;\nexport const MUTATION_WINDOW_MS = 1_000;\n\n/**\n * Invalidations one cached query may be asked for, and refetches (or stale\n * marks) the coordinator may issue for it, within {@link INVALIDATION_WINDOW_MS}.\n */\nexport const INVALIDATION_LIMIT = 20;\nexport const INVALIDATION_WINDOW_MS = 1_000;\n\n/** How many queries' times a guard keeps per count; the least recently counted go first. */\nconst MAX_QUERIES = 1_000;\n\n/** What one mutation hook instance counts: when it mutated, and where it was rendered. */\nexport interface MutationTrace {\n readonly times: number[];\n /** An error made where the hook was first rendered, for its stack; `undefined` outside development. */\n readonly origin: Error | undefined;\n}\n\n/** The loop warnings of one `QueryClient`. */\nexport interface LoopGuard {\n /** Counts one mutation `trace`'s hook instance issued, of `service.method`. */\n mutated(trace: MutationTrace, service: string, method: string): void;\n /** Counts one invalidation an app asked for (`qd.invalidate`) of the cached query `queryKey` (hashed `queryHash`). */\n asked(queryKey: QueryKey, queryHash: string): void;\n /** Counts one refetch or stale mark the coordinator issued for the cached query, after coalescing. */\n issued(queryKey: QueryKey, queryHash: string): void;\n}\n\n/** True in development: `process.env.NODE_ENV` can be read and is not \"production\". */\nexport function isDevelopment(): boolean {\n try {\n // Written out whole, so a bundler can inline it.\n return process.env.NODE_ENV !== \"production\";\n } catch {\n // No `process` here (a bundler that provides none): treated as production.\n return false;\n }\n}\n\n/** How many stack frames a trace keeps, where the engine lets it say (V8): enough for wrapping hooks. */\nconst TRACE_FRAMES = 40;\n\n/**\n * A hook instance's trace, made where it is first rendered (call it from the\n * hook itself, so its component is a few frames up): the origin only in\n * development.\n */\nexport function createMutationTrace(): MutationTrace {\n if (!isDevelopment()) {\n return { times: [], origin: undefined };\n }\n const limit = Error.stackTraceLimit;\n Error.stackTraceLimit = Math.max(limit, TRACE_FRAMES);\n const origin = new Error(\"quickdraw: rendered here\");\n Error.stackTraceLimit = limit;\n return { times: [], origin };\n}\n\nconst BOTTOM_FRAME = /react[-_]stack[-_]bottom[-_]frame/u;\n\n/** The function a stack frame is in: `at TaskEditor (...)` (V8) or `TaskEditor@...` (Firefox, Safari). */\nfunction frameName(frame: string): string | undefined {\n const name = /^\\s*at (?:async )?([^\\s(]+)/u.exec(frame)?.[1] ?? /^([^@\\s]+)@/u.exec(frame)?.[1];\n const bare = name?.replace(/^Object\\./u, \"\");\n return bare === undefined || bare === \"<anonymous>\" || bare === \"\" ? undefined : bare;\n}\n\n/**\n * The component a trace was made in: the frame just above React's\n * `react_stack_bottom_frame`, which calls every function component in\n * development builds; `undefined` when the stack does not say.\n */\nexport function componentOf(origin: Error | undefined): string | undefined {\n const frames = origin?.stack?.split(\"\\n\") ?? [];\n const bottom = frames.findIndex((frame) => BOTTOM_FRAME.test(frame));\n return bottom > 0 ? frameName(frames[bottom - 1] ?? \"\") : undefined;\n}\n\n/** Records one event at `at` in `times`, and says whether more than `limit` fell within `windowMs`. */\nfunction crossed(times: number[], at: number, limit: number, windowMs: number): boolean {\n times.push(at);\n while (times.length > 0 && at - (times[0] ?? at) >= windowMs) {\n times.shift();\n }\n if (times.length > limit + 1) {\n times.shift();\n }\n return times.length > limit;\n}\n\n/** `service.method` for a quickdraw method key, else the key as JSON. */\nfunction memberOf(queryKey: QueryKey): string {\n const [root, service, kind, method] = queryKey;\n if (root === KEY_ROOT && kind === \"m\" && typeof service === \"string\") {\n return `${service}.${String(method)}`;\n }\n return JSON.stringify(queryKey).slice(0, 120);\n}\n\nconst OFF: LoopGuard = Object.freeze({\n mutated: () => undefined,\n asked: () => undefined,\n issued: () => undefined,\n});\n\n/** The times kept for `queryHash` in `counts`, most recently counted last; at most {@link MAX_QUERIES} queries. */\nfunction timesOf(counts: Map<string, number[]>, queryHash: string): number[] {\n const times = counts.get(queryHash) ?? [];\n counts.delete(queryHash);\n counts.set(queryHash, times);\n if (counts.size > MAX_QUERIES) {\n const [oldest] = counts.keys();\n counts.delete(oldest ?? queryHash);\n }\n return times;\n}\n\n/** A loop guard: counts, and logs each kind of warning once per member. */\nexport function createLoopGuard(now: () => number = Date.now): LoopGuard {\n const warned = new Set<string>();\n const asked = new Map<string, number[]>();\n const issued = new Map<string, number[]>();\n const warn = (kind: string, member: string, message: string): void => {\n const key = `${kind}\\u0000${member}`;\n if (!warned.has(key)) {\n warned.add(key);\n consoleLogger.warn(`[quickdraw:${kind}] ${member}: ${message}`, {\n category: \"quickdraw.dev\",\n warning: kind,\n });\n }\n };\n const invalidated = (counts: Map<string, number[]>, queryKey: QueryKey, hash: string): void => {\n const times = timesOf(counts, hash);\n if (!crossed(times, now(), INVALIDATION_LIMIT, INVALIDATION_WINDOW_MS)) {\n return;\n }\n warn(\n \"repeated-invalidation\",\n memberOf(queryKey),\n `invalidated ${String(times.length)} times within a second: an effect or a render that invalidates it on every run loops with the read it causes. ` +\n \"Invalidate from an event handler or once a mutation settles; a scope that changes this often reads better as a collection\",\n );\n };\n return Object.freeze({\n mutated(trace: MutationTrace, service: string, method: string): void {\n if (!crossed(trace.times, now(), MUTATION_LIMIT, MUTATION_WINDOW_MS)) {\n return;\n }\n const component = componentOf(trace.origin);\n warn(\n \"repeated-mutation\",\n `${service}.${method}`,\n `mutated ${String(trace.times.length)} times within a second by one useMutation` +\n `${component === undefined ? \"\" : ` (in ${component})`}: a mutation fired from an effect or from render repeats like this, and each one writes. ` +\n \"Fire it from an event handler, or guard the effect so it runs once per change\",\n );\n },\n asked(queryKey: QueryKey, queryHash: string): void {\n invalidated(asked, queryKey, queryHash);\n },\n issued(queryKey: QueryKey, queryHash: string): void {\n invalidated(issued, queryKey, queryHash);\n },\n });\n}\n\nconst guards = new WeakMap<QueryClient, LoopGuard>();\n\n/** The loop guard of `queryClient`, made on first use; one that does nothing outside development. */\nexport function loopGuardOf(queryClient: QueryClient): LoopGuard {\n let guard = guards.get(queryClient);\n if (guard === undefined) {\n guard = isDevelopment() ? createLoopGuard() : OFF;\n guards.set(queryClient, guard);\n }\n return guard;\n}\n","// The invalidation coordinator (RFC 0003 section 11.3): one per `QueryClient`,\n// shared by every hook, `qd.invalidate`, the watched topics and non-React\n// code, so a query key has at most one read in flight and at most one queued\n// behind it however many invalidations arrive.\n//\n// 4.1 debounced each hook instance for 100 ms and then called\n// `invalidateQueries`, whose default cancels the read in flight and starts\n// another while the server keeps computing the abandoned one\n// (4.1 `src/client/useServiceQuery.ts:141-166`); a reconnect invalidated\n// every query at once (4.1 `src/client/QuickdrawProvider.tsx:320-321`).\n// Passing `cancelRefetch: false` alone is not enough: the read in flight is\n// kept, but the invalidation is lost, because a successful fetch clears\n// TanStack's `isInvalidated` flag. Here, per cached query:\n//\n// - idle and outside a window: refetch now (never cancelling), then open a\n// window (250 ms by default);\n// - inside the window: remember it (`pending`); when the window ends,\n// refetch if the query is idle, or else mark it dirty;\n// - while a read is in flight: mark it dirty. When the read settles (data\n// or error) and the query still has observers, refetch exactly once;\n// - a query without observers is only marked stale: nothing reads it, and\n// its next observer refetches it. One being read without observers (a\n// prefetch) is marked stale when that read settles, since the read's\n// success clears the mark.\n//\n// The coordinator watches the `QueryCache` only while it has keys to look\n// after, drops a key when its last observer leaves or the query leaves the\n// cache, and coordinates at most `maxKeys` keys at once; past that a key is\n// refetched without a window or a follow-up, still without cancelling. In\n// development, a key the coordinator refetches or marks stale more than 20\n// times within a second is named as a loop (`loopGuard.ts`): counted at the\n// refetch it issues, after coalescing, so a watched topic that changes many\n// times a second (a few refetches) is not; what an app asks with\n// `qd.invalidate` is counted as it is asked (`binding.ts`).\n//\n// React-free: the provider makes one per `QueryClient` and retains it while\n// mounted, so its windows and delayed refetches stop a tick after it\n// unmounts; a client without React makes its own with\n// `createInvalidationCoordinator(queryClient)` and disposes it.\n\nimport type { Query, QueryCacheNotifyEvent, QueryClient, QueryKey } from \"@tanstack/react-query\";\nimport { KEY_ROOT } from \"./keys\";\nimport { loopGuardOf, type LoopGuard } from \"./loopGuard\";\n\n/** How long after a refetch further invalidations of the key are served together, by default. */\nexport const DEFAULT_INVALIDATION_WINDOW_MS = 250;\n\n/** How many keys a coordinator looks after at once, by default. */\nexport const DEFAULT_MAX_COORDINATED_KEYS = 1000;\n\n/** The longest random delay of a refetch after a reconnect, by default. */\nexport const RECONNECT_JITTER_MS = 2000;\n\n/** Options of {@link InvalidationCoordinator.invalidate}. */\nexport interface InvalidateOptions {\n /** Match `queryKey` exactly, rather than as a prefix, which is TanStack's default. */\n readonly exact?: boolean;\n /**\n * How long after a refetch this key's further invalidations are served\n * together, as one refetch when the window ends. Default: the coordinator's.\n */\n readonly windowMs?: number;\n}\n\n/** Options of {@link createInvalidationCoordinator}. */\nexport interface CoordinatorOptions {\n /** The default window of `invalidate`. Default 250 ms. */\n readonly windowMs?: number;\n /** How many keys are coordinated at once; others are refetched without a window. Default 1,000. */\n readonly maxKeys?: number;\n}\n\n/** Options of {@link InvalidationCoordinator.refetchAfterReconnect}. */\nexport interface ReconnectRefetchOptions {\n /**\n * True for a query that watches a change topic: it missed every\n * `qd:changed` while the connection was down, so it is refetched even when\n * it is fresh.\n */\n readonly watched: (query: Query) => boolean;\n /**\n * The longest random delay before each refetch, so clients that reconnect\n * together do not refetch in one burst; `0` refetches at once. Default\n * 2,000 ms. The provider passes its `reconnectJitterMs`.\n */\n readonly jitterMs?: number;\n /** Which queries to consider: those this key prefixes. Default `[\"qd\"]`, every quickdraw query. */\n readonly queryKey?: QueryKey;\n}\n\n/** The invalidation coordinator of one `QueryClient`. */\nexport interface InvalidationCoordinator {\n readonly queryClient: QueryClient;\n /**\n * Invalidates the cached queries `queryKey` matches (a prefix, unless\n * `exact`): each is refetched without cancelling a read in flight, at most\n * one read in flight and one queued behind it. Returns at once; the\n * refetches run in the background.\n */\n invalidate(queryKey: QueryKey, options?: InvalidateOptions): void;\n /**\n * After a reconnect: refetches the active queries that are watched or\n * stale, each after its own random delay of up to `jitterMs` (at once for\n * `0`), unless by then it is reading, or it has been read since the\n * reconnect. Throws a `TypeError` for a `jitterMs` below 0.\n */\n refetchAfterReconnect(options: ReconnectRefetchOptions): void;\n /**\n * Holds the coordinator for one user of it (a mounted provider) and\n * returns the release. A tick after the last release it is disposed,\n * unless it is retained again first, as React's strict mode does when it\n * mounts effects twice; retaining a disposed coordinator takes it up again.\n */\n retain(): () => void;\n /** Stops every window and pending refetch, and lets a new coordinator be made for the client. */\n dispose(): void;\n}\n\ntype Timer = ReturnType<typeof setTimeout>;\n\n/** What the coordinator looks after for one cached query. */\ninterface Entry {\n readonly query: Query;\n /** The window the next refetch opens. */\n windowMs: number;\n /** Open after a refetch; invalidations meanwhile wait for its end. */\n window: Timer | undefined;\n /** An invalidation arrived during the window. */\n pending: boolean;\n /** An invalidation arrived during a read: refetch once when it settles. */\n dirty: boolean;\n}\n\ninterface State {\n readonly queryClient: QueryClient;\n /** Counts each refetch and stale mark issued, for the loop warning. */\n readonly loops: LoopGuard;\n readonly windowMs: number;\n readonly maxKeys: number;\n /** By query hash. */\n readonly entries: Map<string, Entry>;\n /** The delayed refetches of `refetchAfterReconnect`. */\n readonly delayed: Set<Timer>;\n /** Stops watching the cache; set while there are entries. */\n unsubscribe: (() => void) | undefined;\n disposed: boolean;\n /** How many users retain the coordinator, and the disposal a tick after the last let go. */\n users: number;\n disposeTimer: Timer | undefined;\n}\n\nconst coordinators = new WeakMap<QueryClient, InvalidationCoordinator>();\n\nfunction isReading(query: Query): boolean {\n return query.state.fetchStatus !== \"idle\";\n}\n\n/** Refetches `query` if it is active, keeping a read in flight. */\nfunction refetchNow(state: State, query: Query): void {\n state.loops.issued(query.queryKey, query.queryHash);\n void state.queryClient.invalidateQueries(\n { queryKey: query.queryKey, exact: true },\n { cancelRefetch: false },\n );\n}\n\n/** Marks `query` stale without reading it: its next observer refetches it. */\nfunction markStale(state: State, query: Query): void {\n state.loops.issued(query.queryKey, query.queryHash);\n void state.queryClient.invalidateQueries({\n queryKey: query.queryKey,\n exact: true,\n refetchType: \"none\",\n });\n}\n\n/** Stops looking after a query, and stops watching the cache when it was the last. */\nfunction drop(state: State, entry: Entry): void {\n clearTimeout(entry.window);\n if (state.entries.get(entry.query.queryHash) === entry) {\n state.entries.delete(entry.query.queryHash);\n }\n if (state.entries.size === 0) {\n state.unsubscribe?.();\n state.unsubscribe = undefined;\n }\n}\n\n/** Stops looking after a query nothing observes; an invalidation it was owed leaves it stale. */\nfunction abandon(state: State, entry: Entry): void {\n drop(state, entry);\n if (entry.pending || entry.dirty) {\n markStale(state, entry.query);\n }\n}\n\n/** Refetches now and opens the window. */\nfunction fire(state: State, entry: Entry): void {\n entry.pending = false;\n refetchNow(state, entry.query);\n entry.window = setTimeout(() => {\n windowEnded(state, entry);\n }, entry.windowMs);\n}\n\n/** Serves an invalidation owed outside a window: refetch, or wait for the read in flight. */\nfunction serve(state: State, entry: Entry): void {\n if (entry.query.getObserversCount() === 0) {\n entry.pending = true;\n abandon(state, entry);\n } else if (isReading(entry.query)) {\n entry.dirty = true;\n } else {\n fire(state, entry);\n }\n}\n\nfunction windowEnded(state: State, entry: Entry): void {\n entry.window = undefined;\n if (entry.pending) {\n entry.pending = false;\n serve(state, entry);\n } else if (!entry.dirty) {\n drop(state, entry);\n }\n}\n\n/** A read of a dirty query settled, it lost its last observer, or it left the cache. */\nfunction onCacheEvent(state: State, event: QueryCacheNotifyEvent): void {\n const entry = state.entries.get(event.query.queryHash);\n if (entry === undefined || entry.query !== event.query) {\n return;\n }\n if (event.type === \"removed\") {\n drop(state, entry);\n } else if (event.type === \"observerRemoved\" && event.query.getObserversCount() === 0) {\n abandon(state, entry);\n } else if (event.type === \"updated\" && entry.dirty && !isReading(entry.query)) {\n entry.dirty = false;\n if (entry.window === undefined) {\n serve(state, entry);\n } else {\n entry.pending = true;\n }\n }\n}\n\n/** The entry of `query`, made when there is room; watches the cache while there are entries. */\nfunction entryFor(state: State, query: Query): Entry | undefined {\n const existing = state.entries.get(query.queryHash);\n if (existing?.query === query) {\n return existing;\n }\n if (existing !== undefined) {\n drop(state, existing);\n }\n if (state.entries.size >= state.maxKeys) {\n return undefined;\n }\n const entry: Entry = {\n query,\n windowMs: state.windowMs,\n window: undefined,\n pending: false,\n dirty: false,\n };\n state.entries.set(query.queryHash, entry);\n state.unsubscribe ??= state.queryClient.getQueryCache().subscribe((event) => {\n onCacheEvent(state, event);\n });\n return entry;\n}\n\n/** One invalidation of one cached query. */\nfunction request(state: State, query: Query, windowMs: number): void {\n const observed = query.getObserversCount() > 0;\n if (!observed && !isReading(query)) {\n markStale(state, query);\n return;\n }\n const entry = state.disposed ? undefined : entryFor(state, query);\n if (entry === undefined) {\n if (observed) {\n refetchNow(state, query);\n } else {\n markStale(state, query);\n }\n return;\n }\n entry.windowMs = windowMs;\n if (!observed) {\n // A read nobody observes (a prefetch): marked stale once it settles,\n // since its success would clear the mark set now.\n entry.dirty = true;\n } else if (entry.window === undefined) {\n serve(state, entry);\n } else {\n entry.pending = true;\n }\n}\n\n/** A delayed refetch after a reconnect, unless the query was read since or no longer needs it. */\nfunction refreshAfter(state: State, query: Query, since: number): void {\n const cached = state.queryClient.getQueryCache().get(query.queryHash) === query;\n const { dataUpdatedAt, errorUpdatedAt } = query.state;\n // Strictly later: a read that landed in the reconnect's millisecond may have been sent before it.\n const readSince = Math.max(dataUpdatedAt, errorUpdatedAt) > since;\n if (cached && query.isActive() && !isReading(query) && !readSince) {\n request(state, query, state.windowMs);\n }\n}\n\n/**\n * A reconnect's jitter, checked: `value`, or 2,000 ms when it is\n * `undefined`. Throws a `TypeError` naming `owner` for anything but a finite\n * number of milliseconds, 0 or more.\n */\nexport function reconnectJitter(owner: string, value: number | undefined): number {\n const jitterMs = value ?? RECONNECT_JITTER_MS;\n if (typeof jitterMs !== \"number\" || !Number.isFinite(jitterMs) || jitterMs < 0) {\n throw new TypeError(`${owner} must be a number of milliseconds, 0 or more`);\n }\n return jitterMs;\n}\n\n/** {@link refreshAfter} after a random delay of up to `jitterMs`, or at once for 0. */\nfunction refreshLater(state: State, query: Query, since: number, jitterMs: number): void {\n if (jitterMs === 0) {\n refreshAfter(state, query, since);\n return;\n }\n const timer = setTimeout(() => {\n state.delayed.delete(timer);\n refreshAfter(state, query, since);\n }, Math.random() * jitterMs);\n state.delayed.add(timer);\n}\n\nfunction refetchAfterReconnect(state: State, options: ReconnectRefetchOptions): void {\n const since = Date.now();\n const jitterMs = reconnectJitter(\"refetchAfterReconnect: jitterMs\", options.jitterMs);\n const queries = state.queryClient\n .getQueryCache()\n .findAll({ queryKey: options.queryKey ?? [KEY_ROOT] });\n for (const query of queries) {\n if (query.isActive() && (options.watched(query) || query.isStale())) {\n refreshLater(state, query, since, jitterMs);\n }\n }\n}\n\nfunction retain(state: State, coordinator: InvalidationCoordinator): () => void {\n state.users += 1;\n clearTimeout(state.disposeTimer);\n state.disposeTimer = undefined;\n if (state.disposed) {\n state.disposed = false;\n if (!coordinators.has(state.queryClient)) {\n coordinators.set(state.queryClient, coordinator);\n }\n }\n let released = false;\n return () => {\n if (released) {\n return;\n }\n released = true;\n state.users -= 1;\n if (state.users === 0) {\n state.disposeTimer = setTimeout(() => {\n state.disposeTimer = undefined;\n dispose(state, coordinator);\n }, 0);\n }\n };\n}\n\nfunction dispose(state: State, coordinator: InvalidationCoordinator): void {\n clearTimeout(state.disposeTimer);\n state.disposeTimer = undefined;\n state.disposed = true;\n for (const entry of [...state.entries.values()]) {\n clearTimeout(entry.window);\n }\n state.entries.clear();\n for (const timer of state.delayed) {\n clearTimeout(timer);\n }\n state.delayed.clear();\n state.unsubscribe?.();\n state.unsubscribe = undefined;\n if (coordinators.get(state.queryClient) === coordinator) {\n coordinators.delete(state.queryClient);\n }\n}\n\nfunction checkCount(name: string, value: number | undefined, fallback: number): number {\n const count = value ?? fallback;\n if (typeof count !== \"number\" || !Number.isFinite(count) || count < 0) {\n throw new TypeError(`createInvalidationCoordinator: ${name} must be a number, 0 or more`);\n }\n return count;\n}\n\n/**\n * The invalidation coordinator of `queryClient`: made on the first call for\n * a client and returned again by later ones (whose options are then\n * ignored), so the provider, the hooks and non-React code share one per\n * client until it is disposed.\n *\n * @example\n * const coordinator = createInvalidationCoordinator(queryClient);\n * connection.watch({ service, topic, onChanged: () => coordinator.invalidate(key) });\n */\nexport function createInvalidationCoordinator(\n queryClient: QueryClient,\n options: CoordinatorOptions = {},\n): InvalidationCoordinator {\n const existing = coordinators.get(queryClient);\n if (existing !== undefined) {\n return existing;\n }\n const state: State = {\n queryClient,\n loops: loopGuardOf(queryClient),\n windowMs: checkCount(\"windowMs\", options.windowMs, DEFAULT_INVALIDATION_WINDOW_MS),\n maxKeys: checkCount(\"maxKeys\", options.maxKeys, DEFAULT_MAX_COORDINATED_KEYS),\n entries: new Map(),\n delayed: new Set(),\n unsubscribe: undefined,\n disposed: false,\n users: 0,\n disposeTimer: undefined,\n };\n const coordinator: InvalidationCoordinator = Object.freeze({\n queryClient,\n invalidate(queryKey: QueryKey, invalidateOptions: InvalidateOptions = {}): void {\n const windowMs = checkCount(\"windowMs\", invalidateOptions.windowMs, state.windowMs);\n const filters = { queryKey, exact: invalidateOptions.exact === true };\n for (const query of queryClient.getQueryCache().findAll(filters)) {\n request(state, query, windowMs);\n }\n },\n refetchAfterReconnect(reconnect: ReconnectRefetchOptions): void {\n refetchAfterReconnect(state, reconnect);\n },\n retain: () => retain(state, coordinator),\n dispose(): void {\n dispose(state, coordinator);\n },\n });\n coordinators.set(queryClient, coordinator);\n return coordinator;\n}\n","// The rows optimistic updates add (RFC 0003 section 11.4): `cache.addItem`\n// and `cache.addEntity` in a mutation's `optimistic` update. The overlay\n// store (`optimistic.ts`) keeps them with its layers, one per call and\n// scope, and the collection hook shows them (`live/views.ts`).\n//\n// - An addition is a provisional item of one collection scope: the fields\n// the update gave, with its own id, or a provisional `qd:new:<n>` one.\n// It shows at once, flagged `pending` while its call is in flight; a\n// refused call drops it, unless it was added with `onRefused: \"keep\"`\n// (finding F6.4 of the quickdraw-chat migration): then it leaves the\n// items and stays as a refused one, with the call's error, until the app\n// dismisses it or sends the call again (`refused`, `dismiss`).\n// - A call whose outcome is unknown (`isUnknownOutcome`: its connection\n// dropped after it was sent, or it timed out) refuses nothing yet: the\n// server may have made the write. Its additions stay, pending and flagged\n// `unknown`, until the scope's next load says: a load sent after the\n// failure that answers without the item refuses it (kept with\n// `onRefused: \"keep\"`, with the call's error), and one that holds it ends\n// it, its own copy shown instead (the final review of the release\n// candidates, item D). Only an id the client made and the server keeps\n// can be found: an item with a provisional id is refused by that load even\n// when the server made its row, under another id.\n// - The reply names the server's id (`data.id`): the item takes it, and the\n// reply's values for the fields it has. A reply that names no id drops\n// it, as does one naming an id the scope already holds.\n// - Once the scope accounts for it, it ends (`settle`): the scope's state\n// holds the id (its own copy shows instead, so the two never show\n// together), a delta named it, or a load of the scope sent after the\n// call's reply answered without it, so it is not a member. A refused or\n// unknown addition ends too once the scope holds its id, or a delta names\n// it: the server has that row. A finished addition nothing ends goes with\n// the store's expiry, as a layer does.\n//\n// React-free.\n\nimport type { QueryClient } from \"@tanstack/react-query\";\nimport type { CollectionDef } from \"../contract/collections\";\nimport type { QuickdrawError } from \"../protocol/errors\";\nimport { isRecord } from \"../protocol/guards\";\nimport { collectionKey } from \"./keys\";\n\n/** A row as additions keep it: any object with a string `id`. */\nexport type AddedRow = Readonly<Record<string, unknown>> & { readonly id: string };\n\n/** An item an optimistic update added to a scope (`OptimisticCache.addItem`). */\nexport interface AddedItem {\n /**\n * The item: the fields the update gave, with its own id (or a provisional\n * one) until the call's reply names the server's, whose values then\n * replace its own.\n */\n readonly item: AddedRow;\n /** True while the call is in flight, and while its outcome is unknown. */\n readonly pending: boolean;\n /**\n * True when the call's outcome is unknown (its connection dropped after it\n * was sent, or it timed out) until the scope's next load says.\n */\n readonly unknown: boolean;\n}\n\n/** What a refused call does with an item its update added (`cache.addItem(..., { onRefused })`). */\nexport type OnRefused = \"drop\" | \"keep\";\n\n/** Options of `cache.addItem` and `cache.addEntity`. */\nexport interface AddItemOptions {\n /**\n * `\"keep\"`: when the server refuses the call, the item leaves the scope's\n * items and stays in `useCollection().refused` with the error, until the\n * app dismisses it or sends the call again (a chat's failed message, with\n * \"retry\"). Default `\"drop\"`: it goes with the refusal.\n */\n readonly onRefused?: OnRefused;\n}\n\n/** An added item whose call was refused, kept by `onRefused: \"keep\"` (`Additions.refused`). */\nexport interface RefusedAddition {\n readonly item: AddedRow;\n /** Why the call was refused. */\n readonly error: QuickdrawError;\n /** The addition itself, for `dismiss` and to send the call again. */\n readonly addition: Addition;\n}\n\n/** What a refused call left on a kept addition: its error, and how to send the call again. */\nexport interface Refusal {\n readonly error: QuickdrawError;\n /** Sends the same call again (the update runs again and adds its items anew). */\n readonly retry: () => Promise<unknown>;\n}\n\n/** A scope of a collection of a service. */\nexport interface ScopeRef {\n readonly service: string;\n readonly collection: string;\n readonly scope: string;\n}\n\n/** A call whose outcome is unknown: how its additions are refused if their scope's next load answers without them. */\ninterface Unknown {\n readonly refusal: Refusal;\n /** The store's clock when the call failed: a load sent at or after it is the evidence. */\n readonly at: number;\n /** True once its scope was asked for a load (`Additions.unchecked`). */\n asked: boolean;\n}\n\n/** What a scope's new state says about the finished additions to it (`settleAdditions`). */\nexport interface ScopeEvidence {\n /** True when the scope's state holds member `id`. */\n readonly holds: (id: string) => boolean;\n /** The ids the deltas just applied named. */\n readonly named?: ReadonlySet<string>;\n /** The overlay store's clock when the load just applied (a snapshot or a resume) was sent. */\n readonly readAt?: number;\n}\n\n/** One optimistic addition of one mutation call: a provisional item of one scope. */\nexport interface Addition {\n /** The scope's key: `scopeKey(service, collection, scope)`. */\n readonly key: string;\n readonly service: string;\n readonly collection: string;\n readonly scope: string;\n /** The item shown: the update's fields, with the server's id and values once the reply names them. */\n item: AddedRow;\n /** The store's clock when the call succeeded; absent while it is in flight. */\n finished: number | undefined;\n /** When a finished addition is dropped if nothing ended it before (`Date.now()` time). */\n expiresAt: number | undefined;\n /** Added with `onRefused: \"keep\"`: a refused call keeps it, as refused. */\n readonly keep: boolean;\n /** Set when its call was refused and it was kept: shown in `refused`, never in the items. */\n refusal: Refusal | undefined;\n /** Set while its call's outcome is unknown: shown in the items, pending, until its scope's next load says. */\n unknown: Unknown | undefined;\n}\n\n/**\n * The additions of one overlay store. They never drop an addition on their\n * own: `finish`, `refuse` and `settle` return those to drop, and the store\n * drops them (`remove`) and tells the views of their services, so no end\n * goes unseen (finding F11.1 of the quickdraw-chat migration).\n */\nexport interface Additions {\n /** How many it holds. */\n readonly size: number;\n /** Opens an addition of a call in flight to scope `scope` of `collection`. */\n add(service: string, collection: string, scope: string, item: AddedRow, keep?: boolean): Addition;\n /**\n * The call of `additions` was refused: those added with `onRefused:\n * \"keep\"` stay, refused with `refusal`; returns the others, for the\n * caller to drop (`remove`).\n */\n refuse(additions: readonly Addition[], refusal: Refusal): Addition[];\n /**\n * The call of `additions` failed without an outcome (`isUnknownOutcome`)\n * at the store's clock `clock`: they stay, pending, until their scope's\n * next load says (`settle`), and are then refused with `refusal` if it\n * answers without them.\n */\n unknown(additions: readonly Addition[], refusal: Refusal, clock: number): void;\n /**\n * The scopes holding additions of unknown outcome that were not asked for\n * a load yet; marks them asked, so each is asked once.\n */\n unchecked(): ScopeRef[];\n /**\n * Finishes the additions of a call that succeeded with `data`, at the\n * store's clock `clock`, until `expiresAt`; returns the others, for the\n * caller to drop (`remove`): the reply names no id, or their scope holds\n * it already.\n */\n finish(\n additions: readonly Addition[],\n data: unknown,\n clock: number,\n expiresAt: number,\n ): Addition[];\n /** Drops `additions`; returns those it held. */\n remove(additions: readonly Addition[]): Addition[];\n /**\n * Weighs `evidence` against the additions to one scope: refuses those of\n * unknown outcome that a load it reports answered without, and returns\n * those it ends, for the caller to drop (`remove`), and whether any was\n * refused.\n */\n settle(\n service: string,\n collection: string,\n scope: string,\n evidence: ScopeEvidence,\n ): { readonly ending: Addition[]; readonly refused: boolean };\n /** The items added to a scope and shown in it, oldest first: not those refused. */\n added(service: string, collection: string, scope: string): readonly AddedItem[];\n /** The items added to a scope whose call was refused and that were kept, oldest first. */\n refused(service: string, collection: string, scope: string): readonly RefusedAddition[];\n /** Every addition, oldest scope first. */\n all(): Addition[];\n clear(): void;\n}\n\nconst NO_ADDITIONS: readonly AddedItem[] = Object.freeze([]);\n\nconst NO_REFUSALS: readonly RefusedAddition[] = Object.freeze([]);\n\nfunction scopeKey(service: string, collection: string, scope: string): string {\n return `${service}\\u0000${collection}\\u0000${scope}`;\n}\n\nfunction isRow(value: unknown): value is AddedRow {\n return isRecord(value) && typeof value.id === \"string\";\n}\n\n/** The number in the next provisional id: `qd:new:1`, `qd:new:2`, ... */\nlet provisional = 0;\n\n/** An id for an added item that names none: one no server id is (a colon, and the `qd:` prefix). */\nfunction provisionalId(): string {\n provisional = provisional >= Number.MAX_SAFE_INTEGER ? 1 : provisional + 1;\n return `qd:new:${String(provisional)}`;\n}\n\n/** The item an update adds: a copy of its fields, with its own id or a provisional one. */\nexport function newItem(owner: string, item: unknown): AddedRow {\n if (!isRecord(item)) {\n throw new TypeError(`${owner}: the item must be an object of its fields`);\n }\n const { id } = item;\n if (id !== undefined && (typeof id !== \"string\" || id === \"\")) {\n throw new TypeError(`${owner}: an item's id must be a non-empty string, or left out`);\n }\n return Object.freeze({ ...item, id: id ?? provisionalId() }) as AddedRow;\n}\n\n/** The scope of each collection of entity rows that `row` belongs to, by its scope column and `where`. */\nexport function entityScopes(\n collections: Readonly<Record<string, CollectionDef>>,\n row: AddedRow,\n): [collection: string, scope: string][] {\n return Object.entries(collections).flatMap(([name, def]): [string, string][] => {\n const scope = typeof def.scope === \"string\" ? row[def.scope] : undefined;\n const matches = Object.entries(def.where ?? {}).every(\n ([column, value]) => Object.hasOwn(row, column) && row[column] === value,\n );\n return def.item === \"entity\" && typeof scope === \"string\" && scope !== \"\" && matches\n ? [[name, scope]]\n : [];\n });\n}\n\n/** `item` with the server's id and the reply's values for the fields it has, when `data` is a row. */\nfunction repliedItem(item: AddedRow, data: unknown): AddedRow | undefined {\n if (!isRow(data)) {\n return undefined;\n }\n const next: Record<string, unknown> = { ...item, id: data.id };\n for (const field of Object.keys(item)) {\n if (field !== \"id\" && Object.hasOwn(data, field)) {\n next[field] = data[field];\n }\n }\n return Object.freeze(next) as AddedRow;\n}\n\n/** True when the state the cache holds for the addition's scope holds member `id`. */\nfunction scopeHolds(queryClient: QueryClient, addition: Addition, id: string): boolean {\n const entry = queryClient.getQueryData(\n collectionKey(addition.service, addition.collection, addition.scope),\n );\n const state: unknown = isRecord(entry) ? entry.state : undefined;\n if (!isRecord(state)) {\n return false;\n }\n const { revById, byId } = state;\n return (revById instanceof Map && revById.has(id)) || (byId instanceof Map && byId.has(id));\n}\n\n/** True when the scope holds the addition's id now, or a delta just named it: the server has that row. */\nfunction found(addition: Addition, evidence: ScopeEvidence): boolean {\n const { id } = addition.item;\n return evidence.holds(id) || evidence.named?.has(id) === true;\n}\n\n/** True when `evidence` accounts for a finished addition: its scope holds it, or says it is not a member. */\nfunction accounted(addition: Addition, evidence: ScopeEvidence): boolean {\n const { finished } = addition;\n const { readAt } = evidence;\n return (\n finished !== undefined &&\n (found(addition, evidence) || (readAt !== undefined && readAt >= finished))\n );\n}\n\n/** What `evidence` does to one addition: ends it, refuses it (an unknown outcome a later load answered without), or neither. */\nfunction verdict(addition: Addition, evidence: ScopeEvidence): \"end\" | \"refuse\" | undefined {\n const { unknown, refusal } = addition;\n if (unknown === undefined && refusal === undefined) {\n return accounted(addition, evidence) ? \"end\" : undefined;\n }\n if (found(addition, evidence)) {\n return \"end\";\n }\n const { readAt } = evidence;\n if (unknown !== undefined && readAt !== undefined && readAt >= unknown.at) {\n return addition.keep ? \"refuse\" : \"end\";\n }\n return undefined;\n}\n\n/** Keeps the additions made with `onRefused: \"keep\"` as refused with `refusal`; returns the others. */\nfunction refuseAdditions(additions: readonly Addition[], refusal: Refusal): Addition[] {\n const dropped: Addition[] = [];\n for (const addition of additions) {\n if (addition.keep) {\n addition.refusal = refusal;\n } else {\n dropped.push(addition);\n }\n }\n return dropped;\n}\n\n/** The items a scope's additions show: those not refused, flagged pending while their call is in flight. */\nfunction shownOf(held: readonly Addition[] | undefined): readonly AddedItem[] {\n const shown = held?.filter((addition) => addition.refusal === undefined) ?? [];\n return shown.length === 0\n ? NO_ADDITIONS\n : shown.map((addition) => ({\n item: addition.item,\n pending: addition.finished === undefined,\n unknown: addition.unknown !== undefined,\n }));\n}\n\n/** A scope's refused additions, with their errors. */\nfunction refusedOf(held: readonly Addition[] | undefined): readonly RefusedAddition[] {\n const refused = (held ?? []).flatMap((addition): RefusedAddition[] =>\n addition.refusal === undefined\n ? []\n : [{ item: addition.item, error: addition.refusal.error, addition }],\n );\n return refused.length === 0 ? NO_REFUSALS : refused;\n}\n\n/** A new addition of a call in flight. */\nfunction newAddition(\n service: string,\n collection: string,\n scope: string,\n item: AddedRow,\n keep: boolean,\n): Addition {\n return {\n key: scopeKey(service, collection, scope),\n service,\n collection,\n scope,\n item,\n finished: undefined,\n expiresAt: undefined,\n keep,\n refusal: undefined,\n unknown: undefined,\n };\n}\n\n/** The scopes of `additions` of unknown outcome not asked for a load yet; marks them asked. */\nfunction unasked(additions: readonly Addition[]): ScopeRef[] {\n const scopes = new Map<string, ScopeRef>();\n for (const addition of additions) {\n if (addition.unknown !== undefined && !addition.unknown.asked) {\n addition.unknown.asked = true;\n const { service, collection, scope } = addition;\n scopes.set(addition.key, { service, collection, scope });\n }\n }\n return [...scopes.values()];\n}\n\n/** Applies `evidence` to one scope's additions: returns those it ends, and whether it refused any. */\nfunction weigh(\n held: readonly Addition[],\n evidence: ScopeEvidence,\n): { readonly ending: Addition[]; readonly refused: boolean } {\n const ending: Addition[] = [];\n let refused = false;\n for (const addition of held) {\n const outcome = verdict(addition, evidence);\n if (outcome === \"end\") {\n ending.push(addition);\n } else if (outcome === \"refuse\" && addition.unknown !== undefined) {\n addition.refusal = addition.unknown.refusal;\n addition.unknown = undefined;\n refused = true;\n }\n }\n return { ending, refused };\n}\n\n/** Creates the additions of the overlay store of `queryClient`, whose collection states it reads. */\nexport function createAdditions(queryClient: QueryClient): Additions {\n const byScope = new Map<string, Addition[]>();\n let size = 0;\n /** Set when a call's outcome turned unknown: some scope may need asking (`unchecked`). */\n let toCheck = false;\n const all = (): Addition[] => [...byScope.values()].flat();\n const removeOne = (addition: Addition): boolean => {\n const held = byScope.get(addition.key);\n const index = held?.indexOf(addition) ?? -1;\n if (held === undefined || index < 0) {\n return false;\n }\n held.splice(index, 1);\n if (held.length === 0) {\n byScope.delete(addition.key);\n }\n size -= 1;\n return true;\n };\n const remove = (additions: readonly Addition[]): Addition[] => additions.filter(removeOne);\n return {\n get size() {\n return size;\n },\n add(service, collection, scope, item, keep = false) {\n const addition = newAddition(service, collection, scope, item, keep);\n byScope.set(addition.key, [...(byScope.get(addition.key) ?? []), addition]);\n size += 1;\n return addition;\n },\n finish(additions, data, clock, expiresAt) {\n const ended: Addition[] = [];\n for (const addition of additions) {\n const replied = repliedItem(addition.item, data);\n if (replied === undefined || scopeHolds(queryClient, addition, replied.id)) {\n ended.push(addition);\n } else {\n addition.item = replied;\n addition.finished = clock;\n addition.expiresAt = expiresAt;\n }\n }\n return ended;\n },\n remove,\n refuse: refuseAdditions,\n unknown(additions, refusal, clock) {\n for (const addition of additions) {\n addition.unknown = { refusal, at: clock, asked: false };\n toCheck = true;\n }\n },\n unchecked() {\n const scopes = toCheck ? unasked(all()) : [];\n toCheck = false;\n return scopes;\n },\n settle: (service, collection, scope, evidence) =>\n weigh(byScope.get(scopeKey(service, collection, scope)) ?? [], evidence),\n added: (service, collection, scope) =>\n shownOf(byScope.get(scopeKey(service, collection, scope))),\n refused: (service, collection, scope) =>\n refusedOf(byScope.get(scopeKey(service, collection, scope))),\n all,\n clear() {\n byScope.clear();\n size = 0;\n },\n };\n}\n","// Optimistic mutations (RFC 0003 section 11.4): a user's own edit shows at\n// once, and is undone cleanly when the server refuses it.\n//\n// An edit is an overlay, never a write into the cache: a layer of fields kept\n// per service and row id, shown over whatever the cache holds for that row\n// (`applyOverlay`). The cache keeps the server's data, so a refetch or a\n// frame never has to be reconciled with a guess, and undoing an edit is\n// dropping its layer.\n//\n// - A mutation whose input has a string `id` and whose output is `\"entity\"`\n// is optimistic by default: the input's other fields are overlaid on the\n// row with that id. `optimistic: false` turns it off; a function\n// `(input, cache) => void` writes its own layers with `cache.patchEntity`,\n// `cache.removeEntity` and `cache.patchItem`.\n// - The layers are made when the call is sent. A refused call drops them.\n// - A call that succeeds keeps them, with the values its reply holds for the\n// same fields (the server may have normalized them), for as long as cached\n// data can predate the write:\n// - data read by a request sent after the call succeeded already holds the\n// write, so a finished layer is not shown over it (`readAt`, on the\n// store's clock): the cached result of one query is refreshed without\n// taking the overlay off another that still holds the old row;\n// - a frame (`qd:e`, `qd:c`) whose revision is newer than every revision\n// of the row seen before the reply ends the layer for good (`observe`).\n// A mutation reply carries no revision, because the server flushes after\n// it answers, so that is the threshold; a frame that arrives before the\n// reply is from an earlier flush and only raises it;\n// - a reply to a read (a subscribe reply, a snapshot, a page, items by id)\n// ends the layer only when its read was sent after the call's reply: one\n// sent before may have read the row before the write, whatever its\n// revision and whenever its answer arrives;\n// - a finished layer that gets neither within 10 s is dropped, so a layer\n// on a row nothing follows (a custom one, or an unsubscribed row) cannot\n// stay forever.\n// Revisions and send order are compared, never arrival order.\n// - Only fields the row already has are overlaid, so a projection shows the\n// fields it carries and nothing else.\n// - An update can add a row too (`cache.addItem(collection, scope, item)`,\n// or `cache.addEntity(row)` for every collection of entity rows it\n// belongs to): a provisional item shown in the scope at once, in the\n// collection's order, flagged `pending` while the call is in flight, kept\n// beside the layers until the scope accounts for it (`additions.ts`,\n// `settleAdditions`). With `{ onRefused: \"keep\" }` a refused call keeps\n// it, out of the items, as a refused one with the error, until the app\n// dismisses it or sends the call again (`OverlayView.refused`).\n//\n// The query hooks apply overlays to methods whose output is a projection\n// (one row, `nullable(...)` or `listOf(...)`, `overlayRows.ts`); the\n// live-data hooks apply them to entities and collection items through the\n// same `applyOverlay`. A store keeps at most 1,000 layers and forgets the\n// oldest finished ones first. It remembers the last revision of at most\n// 1,000 rows, plus every row that has a layer, so reading a large board\n// cannot push those out. What one mutation call opens, finishes and drops is\n// `optimisticCall.ts`.\n//\n// React-free: one store per `QueryClient`.\n\nimport type { QueryClient } from \"@tanstack/react-query\";\nimport type { Revision } from \"../protocol/envelope\";\nimport { isRecord } from \"../protocol/guards\";\nimport {\n createAdditions,\n type AddedItem,\n type AddedRow,\n type AddItemOptions,\n type Addition,\n type Additions,\n type Refusal,\n type RefusedAddition,\n type ScopeEvidence,\n type ScopeRef,\n} from \"./additions\";\n\nexport type {\n AddedItem,\n AddItemOptions,\n OnRefused,\n RefusedAddition,\n ScopeEvidence,\n ScopeRef,\n} from \"./additions\";\n\n/** A row as overlays find it: any object with a string `id`. */\ntype Row = Readonly<Record<string, unknown>> & { readonly id: string };\n\n/**\n * A row an optimistic update adds: every field of `T` but `id`, which it may\n * give (an id the client made, which the server keeps) or leave to the\n * server.\n */\nexport type NewRow<T> = Omit<T, \"id\"> & { readonly id?: string };\n\n/**\n * What a custom optimistic update writes layers through, for one mutation\n * call. Every layer belongs to that call: dropped if it fails, kept after it\n * succeeds until the server's data for the row catches up.\n */\nexport interface OptimisticCache<\n Entity = Record<string, unknown>,\n Items extends Record<string, unknown> = Record<string, Record<string, unknown>>,\n Scopes extends { readonly [K in keyof Items]: unknown } = { readonly [K in keyof Items]: string },\n> {\n /** Shows `fields` over the row `id` of the mutation's service: its entity and its collection items. */\n patchEntity(id: string, fields: Partial<Entity>): void;\n /** Hides the row `id`: from lists, collections and its entity. */\n removeEntity(id: string): void;\n /** Shows `fields` over the row `id` in the items of `collection` only. */\n patchItem<K extends keyof Items & string>(\n collection: K,\n id: string,\n fields: Partial<Items[K]>,\n ): void;\n /**\n * Shows `item` in scope `scope` of `collection` at once, in the\n * collection's order (give it the `order` fields; without them it shows\n * last), flagged in `useCollection`'s `pending` while the call is in\n * flight: a create shown before the server answers. A refused call drops\n * it, or with `{ onRefused: \"keep\" }` moves it to `useCollection().refused`\n * with the error, until the app dismisses it or sends the call again; the\n * reply's `id` (the created row's) replaces its own, and the scope's own\n * copy replaces it when it arrives.\n */\n addItem<K extends keyof Items & string>(\n collection: K,\n scope: Scopes[K],\n item: NewRow<Items[K]>,\n options?: AddItemOptions,\n ): void;\n /**\n * `addItem` for every collection of the service whose items are the\n * entity (`item: \"entity\"`) and whose scope column, and every column of\n * its `where`, `row` holds with a matching value: the scope is\n * `row[scope]`. A collection of a projection, or scoped `via` a junction,\n * takes `addItem`. `options` as `addItem`'s.\n */\n addEntity(row: NewRow<Entity>, options?: AddItemOptions): void;\n}\n\n/**\n * A mutation's `optimistic` option: `false` for none, or a function that\n * writes the layers itself. Left out, the default applies (see the top of\n * this file).\n */\nexport type OptimisticUpdate<Input, Cache = OptimisticCache> = (input: Input, cache: Cache) => void;\n\n/** Where a row being shown comes from, for {@link OverlayStore.applyOverlay}. */\nexport interface OverlayOptions {\n /** The collection the row is an item of: layers written with `patchItem` for it apply too. */\n readonly collection?: string;\n /**\n * When the request that read the row was sent, as `now()` was then.\n * Layers of calls that had finished by then are in the row already and\n * are not applied again. Left out, every layer applies.\n */\n readonly readAt?: number;\n}\n\n/** The overlays of one `QueryClient`. */\nexport interface OverlayStore {\n /**\n * `row` as the overlays of `service` show it: their fields over its own,\n * or `undefined` when one hides it. Returns `row` itself when no layer\n * changes it.\n */\n applyOverlay<T>(service: string, row: T, options?: OverlayOptions): T | undefined;\n /**\n * Revision `rev` of the row arrived. Without `readAt` it came in a frame\n * (`qd:e`, `qd:c`), which ends the layers of finished calls it is newer\n * than. With `readAt` it came in the reply to a read sent then (on this\n * store's clock: a subscribe reply, a snapshot, a page, items), which ends\n * only the layers of calls that finished before the read was sent.\n */\n observe(service: string, id: string, rev: Revision, readAt?: number): void;\n /** The store's clock: take it when sending a read, and pass it as `readAt` to show what the read returned. */\n now(): number;\n /** Calls `listener` whenever a layer is added, changed or dropped; returns the unsubscribe function. */\n subscribe(listener: () => void): () => void;\n /**\n * The overlays of `service` as one object, which stays the same until one\n * of them changes: a `useSyncExternalStore` snapshot for code that renders\n * the rows of one service.\n */\n view(service: string): OverlayView;\n}\n\n/** The overlays of one service, until one of them changes (`OverlayStore.view`). */\nexport interface OverlayView {\n /** `applyOverlay` for this view's service. */\n apply<T>(row: T, options?: OverlayOptions): T | undefined;\n /** The items optimistic updates added to scope `scope` of `collection`, oldest first. */\n added(collection: string, scope: string): readonly AddedItem[];\n /**\n * The items added to scope `scope` of `collection` with `onRefused:\n * \"keep\"` whose call was refused, oldest first: shown in\n * `useCollection().refused`, not among the items.\n */\n refused(collection: string, scope: string): readonly RefusedAddition[];\n}\n\n/**\n * The overlays of nothing: what a server renders (no mutation runs there),\n * and so what the browser hydrates (`context.ts`).\n */\nexport const NO_OVERLAYS: OverlayView = Object.freeze({\n apply: <T>(row: T) => row,\n added: () => Object.freeze([]),\n refused: () => Object.freeze([]),\n});\n\n/** One layer of one mutation call. */\nexport interface Layer {\n readonly key: string;\n readonly service: string;\n readonly id: string;\n /** Applies to the items of this collection only; absent for the row everywhere. */\n readonly collection: string | undefined;\n /** Hides the row. */\n readonly removed: boolean;\n fields: Readonly<Record<string, unknown>>;\n /** The store's clock when the call succeeded; absent while it is in flight. */\n finished: number | undefined;\n /** The newest revision of the row seen before the call finished. */\n base: Revision | undefined;\n /** When a finished layer is dropped if nothing ended it before (`Date.now()` time). */\n expiresAt: number | undefined;\n}\n\n/** What one mutation call opened. */\nexport interface Opened {\n readonly layers: Layer[];\n readonly additions: Addition[];\n}\n\n/** What a mutation call does with the store: open layers, then finish or drop them. */\nexport interface StoreInternals extends OverlayStore {\n add(service: string, id: string, layer: Pick<Layer, \"collection\" | \"removed\" | \"fields\">): Layer;\n addItem(\n service: string,\n collection: string,\n scope: string,\n item: AddedRow,\n keep?: boolean,\n ): Addition;\n finish(opened: Opened, data: unknown): void;\n discard(opened: Opened): void;\n /**\n * The call was refused: drops its layers and the additions it opened,\n * except those added with `onRefused: \"keep\"`, which stay refused.\n */\n refuse(opened: Opened, refusal: Refusal): void;\n /**\n * The call failed without an outcome (`isUnknownOutcome`): drops its\n * layers, and keeps its additions shown, pending, until their scope's next\n * load says whether the server made them (`additions.ts`).\n */\n unknown(opened: Opened, refusal: Refusal): void;\n /** The scopes whose additions of unknown outcome were not asked for a load yet; marks them asked. */\n unchecked(): ScopeRef[];\n /** Drops a refused addition: the app dismissed it, or sends its call again. */\n dismiss(addition: Addition): void;\n /** Ends the finished additions to a scope that it accounts for (`settleAdditions`). */\n settle(service: string, collection: string, scope: string, evidence: ScopeEvidence): void;\n /** Drops every layer and every revision seen: the cache was emptied for another user. */\n reset(): void;\n}\n\n/** The most layers a store keeps; past it the oldest finished ones go first. */\nconst MAX_LAYERS = 1000;\n\n/** The most additions a store keeps; past it the oldest go first. */\nconst MAX_ADDITIONS = 1000;\n\n/** The most rows without a layer whose last revision a store remembers. */\nconst MAX_REVISIONS = 1000;\n\n/** How long a finished layer stays when no frame and no read after its reply ends it. */\nconst FINISHED_LAYER_MS = 10_000;\n\nconst stores = new WeakMap<QueryClient, StoreInternals>();\n\nfunction rowKey(service: string, id: string): string {\n return `${service}\\u0000${id}`;\n}\n\nfunction isRow(value: unknown): value is Row {\n return isRecord(value) && typeof value.id === \"string\";\n}\n\n/** `fields` laid over `row` where `row` has the field; `row` itself when nothing changes. */\nfunction overlay(row: Row, fields: Readonly<Record<string, unknown>>): Row {\n let next: Record<string, unknown> | undefined;\n for (const [field, value] of Object.entries(fields)) {\n if (field !== \"id\" && Object.hasOwn(row, field) && !Object.is(row[field], value)) {\n next ??= { ...row };\n next[field] = value;\n }\n }\n return (next ?? row) as Row;\n}\n\n/** The values `data` holds for the fields of `layer`, when `data` is its row. */\nfunction repliedFields(layer: Layer, data: unknown): Readonly<Record<string, unknown>> {\n if (!isRow(data) || data.id !== layer.id) {\n return layer.fields;\n }\n const fields: Record<string, unknown> = { ...layer.fields };\n for (const field of Object.keys(fields)) {\n if (Object.hasOwn(data, field)) {\n fields[field] = data[field];\n }\n }\n return fields;\n}\n\n/** The layer state of one store, and the bookkeeping its methods share. */\ninterface Layers {\n readonly byRow: Map<string, Layer[]>;\n /** The rows optimistic updates added, per scope (`additions.ts`). */\n readonly additions: Additions;\n /** The last revision of rows without a layer, the least recently seen first. */\n readonly revisions: Map<string, Revision>;\n /** The last revision of rows with a layer, kept out of `revisions` so that churn cannot evict it. */\n readonly pinned: Map<string, Revision>;\n /** Drops the finished layers that expire first. */\n expiry: ReturnType<typeof setTimeout> | undefined;\n /** The current view of each service; a change of the service's layers drops it. */\n readonly views: Map<string, OverlayView>;\n readonly listeners: Set<() => void>;\n count: number;\n clock: number;\n}\n\n/** Drops the views of `services` and tells the listeners, when there is any. */\nfunction changed(layers: Layers, services: Iterable<string>): void {\n const touched = new Set(services);\n if (touched.size === 0) {\n return;\n }\n for (const service of touched) {\n layers.views.delete(service);\n }\n for (const listener of [...layers.listeners]) {\n listener();\n }\n}\n\nfunction viewOf(layers: Layers, service: string): OverlayView {\n let view = layers.views.get(service);\n if (view === undefined) {\n view = Object.freeze({\n apply: <T>(row: T, options?: OverlayOptions) => applyOverlay(layers, service, row, options),\n added: (collection: string, scope: string) =>\n layers.additions.added(service, collection, scope),\n refused: (collection: string, scope: string) =>\n layers.additions.refused(service, collection, scope),\n });\n layers.views.set(service, view);\n }\n return view;\n}\n\nfunction remove(layers: Layers, layer: Layer): boolean {\n const row = layers.byRow.get(layer.key);\n const index = row?.indexOf(layer) ?? -1;\n if (row === undefined || index < 0) {\n return false;\n }\n row.splice(index, 1);\n if (row.length === 0) {\n layers.byRow.delete(layer.key);\n const pinned = layers.pinned.get(layer.key);\n layers.pinned.delete(layer.key);\n if (pinned !== undefined) {\n remember(layers, layer.key, pinned);\n }\n }\n layers.count -= 1;\n return true;\n}\n\n/** Drops the oldest finished layers (or else the oldest) while the store holds too many; returns them. */\nfunction trim(layers: Layers): Layer[] {\n const trimmed: Layer[] = [];\n while (layers.count > MAX_LAYERS) {\n const all = [...layers.byRow.values()].flat();\n const oldest = all.find((layer) => layer.finished !== undefined) ?? all[0];\n if (oldest === undefined || !remove(layers, oldest)) {\n break;\n }\n trimmed.push(oldest);\n }\n return trimmed;\n}\n\n/** The last revision seen of the row `key`. */\nfunction knownRevision(layers: Layers, key: string): Revision | undefined {\n return layers.pinned.get(key) ?? layers.revisions.get(key);\n}\n\nfunction remember(layers: Layers, key: string, rev: Revision): void {\n const known = knownRevision(layers, key);\n const newest = known === undefined ? rev : Math.max(known, rev);\n layers.revisions.delete(key);\n if (layers.byRow.has(key)) {\n layers.pinned.set(key, newest);\n return;\n }\n layers.revisions.set(key, newest);\n for (const old of layers.revisions.keys()) {\n if (layers.revisions.size <= MAX_REVISIONS) {\n break;\n }\n layers.revisions.delete(old);\n }\n}\n\n/**\n * Whether revision `rev` of a finished layer's row ends it: from a frame, when\n * it is newer than every revision seen before the call's reply; from the\n * reply to a read sent at `readAt`, when that read was sent after the reply.\n */\nfunction ends(layer: Layer, rev: Revision, readAt: number | undefined): boolean {\n if (readAt !== undefined) {\n return layer.finished !== undefined && readAt >= layer.finished;\n }\n return layer.base === undefined || rev > layer.base;\n}\n\nfunction observe(\n layers: Layers,\n service: string,\n id: string,\n rev: Revision,\n readAt: number | undefined,\n): void {\n if (typeof rev !== \"number\" || !Number.isFinite(rev)) {\n return;\n }\n const key = rowKey(service, id);\n remember(layers, key, rev);\n const dropped: Layer[] = [];\n for (const layer of layers.byRow.get(key) ?? []) {\n if (layer.finished === undefined) {\n // The server flushes a write after answering it, so a frame, or a read,\n // that arrives before the call's reply is from before the write.\n layer.base = layer.base === undefined ? rev : Math.max(layer.base, rev);\n } else if (ends(layer, rev, readAt)) {\n dropped.push(layer);\n }\n }\n discard(layers, dropped);\n}\n\n/** Stops the expiry of finished layers. */\nfunction stopExpiry(layers: Layers): void {\n clearTimeout(layers.expiry);\n layers.expiry = undefined;\n}\n\n/**\n * Drops `dropped` and `additions`, then tells the listeners once: for the\n * services of those it held, and of `alsoChanged` (what else the caller\n * changed). The one place additions are dropped, so none ends unseen.\n */\nfunction discard(\n layers: Layers,\n dropped: readonly Layer[],\n additions: readonly Addition[] = [],\n alsoChanged: readonly string[] = [],\n): void {\n const removed = dropped.filter((layer) => remove(layers, layer));\n const gone = layers.additions.remove(additions);\n if (layers.count === 0 && layers.additions.size === 0) {\n stopExpiry(layers);\n }\n changed(layers, [\n ...removed.map((layer) => layer.service),\n ...gone.map((addition) => addition.service),\n ...alsoChanged,\n ]);\n}\n\n/** Drops the finished layers and additions whose time is up, and waits for the next to expire. */\nfunction expire(layers: Layers): void {\n const now = Date.now();\n const isDue = (entry: { readonly expiresAt: number | undefined }): boolean =>\n entry.expiresAt !== undefined && entry.expiresAt <= now;\n discard(\n layers,\n [...layers.byRow.values()].flat().filter(isDue),\n layers.additions.all().filter(isDue),\n );\n armExpiry(layers);\n}\n\n/** Waits for the first finished layer or addition to expire, unless a wait is set already. */\nfunction armExpiry(layers: Layers): void {\n if (layers.expiry !== undefined) {\n return;\n }\n const times = [...[...layers.byRow.values()].flat(), ...layers.additions.all()].map(\n (entry) => entry.expiresAt,\n );\n const first = Math.min(...times.filter((time) => time !== undefined));\n if (Number.isFinite(first)) {\n layers.expiry = setTimeout(\n () => {\n layers.expiry = undefined;\n expire(layers);\n },\n Math.max(0, first - Date.now()),\n );\n }\n}\n\n/** Whether `layer` shows over a row read at `readAt` and shown in `collection`. */\nfunction applies(layer: Layer, options: OverlayOptions): boolean {\n const { collection, readAt } = options;\n const inRow = layer.finished === undefined || readAt === undefined || layer.finished > readAt;\n return inRow && (layer.collection === undefined || layer.collection === collection);\n}\n\nfunction applyOverlay<T>(\n layers: Layers,\n service: string,\n row: T,\n options: OverlayOptions = {},\n): T | undefined {\n if (!isRow(row)) {\n return row;\n }\n let shown: Row = row;\n for (const layer of layers.byRow.get(rowKey(service, row.id)) ?? []) {\n if (applies(layer, options)) {\n if (layer.removed) {\n return undefined;\n }\n shown = overlay(shown, layer.fields);\n }\n }\n return shown as T;\n}\n\n/** Opens a layer of a call in flight over row `id` of `service`. */\nfunction addLayer(\n layers: Layers,\n service: string,\n id: string,\n made: Pick<Layer, \"collection\" | \"removed\" | \"fields\">,\n): Layer {\n const key = rowKey(service, id);\n const base = knownRevision(layers, key);\n const layer: Layer = {\n ...made,\n key,\n service,\n id,\n finished: undefined,\n base,\n expiresAt: undefined,\n };\n layers.byRow.set(key, [...(layers.byRow.get(key) ?? []), layer]);\n if (base !== undefined) {\n // The row has a layer now: its revision leaves the memory that churn empties.\n layers.revisions.delete(key);\n layers.pinned.set(key, base);\n }\n layers.count += 1;\n // A layer trimmed past the limit may be another service's: its views change too.\n changed(layers, [service, ...trim(layers).map((trimmed) => trimmed.service)]);\n return layer;\n}\n\n/**\n * Finishes the layers and additions of a call that succeeded with `data`:\n * layers keep its values, additions take the id it names (or are dropped\n * when it names none, or when their scope holds it already), for at most 10 s.\n */\nfunction finishLayers(layers: Layers, opened: Opened, data: unknown): void {\n layers.clock += 1;\n const expiresAt = Date.now() + FINISHED_LAYER_MS;\n for (const layer of opened.layers) {\n layer.finished = layers.clock;\n layer.fields = repliedFields(layer, data);\n layer.expiresAt = expiresAt;\n }\n // Those the reply names no id for, or whose scope holds it already, go now.\n const ending = layers.additions.finish(opened.additions, data, layers.clock, expiresAt);\n discard(layers, [], ending, [\n ...opened.layers.map((layer) => layer.service),\n ...opened.additions.map((addition) => addition.service),\n ]);\n armExpiry(layers);\n}\n\n/** A call failed without an outcome: its layers go, its additions wait for their scopes' next loads. */\nfunction unknownOutcome(layers: Layers, opened: Opened, refusal: Refusal): void {\n // A load sent from now on is the evidence: it was sent after the call failed.\n layers.clock += 1;\n layers.additions.unknown(opened.additions, refusal, layers.clock);\n discard(layers, opened.layers);\n changed(\n layers,\n opened.additions.map((addition) => addition.service),\n );\n}\n\n/** What a scope's new state does to the additions to it (`settleAdditions`). */\nfunction settleScope(layers: Layers, ref: ScopeRef, evidence: ScopeEvidence): void {\n if (layers.additions.size === 0) {\n return;\n }\n const { ending, refused } = layers.additions.settle(\n ref.service,\n ref.collection,\n ref.scope,\n evidence,\n );\n // Dropped here, so the views hear of an end that leaves the scope's state as it was\n // (finding F11.1); those of unknown outcome a load answered without moved to `refused`.\n discard(layers, [], ending, refused ? [ref.service] : []);\n}\n\n/** Drops every layer and every revision seen, and tells the views of every service shown. */\nfunction resetLayers(layers: Layers): void {\n const services = new Set(layers.views.keys());\n for (const row of layers.byRow.values()) {\n for (const layer of row) {\n services.add(layer.service);\n }\n }\n for (const addition of layers.additions.all()) {\n services.add(addition.service);\n }\n stopExpiry(layers);\n layers.byRow.clear();\n layers.additions.clear();\n layers.revisions.clear();\n layers.pinned.clear();\n layers.count = 0;\n changed(layers, services);\n}\n\nfunction createStore(queryClient: QueryClient): StoreInternals {\n const layers: Layers = {\n byRow: new Map(),\n additions: createAdditions(queryClient),\n revisions: new Map(),\n pinned: new Map(),\n expiry: undefined,\n views: new Map(),\n listeners: new Set(),\n count: 0,\n clock: 0,\n };\n return Object.freeze({\n applyOverlay: <T>(service: string, row: T, options?: OverlayOptions) =>\n applyOverlay(layers, service, row, options),\n observe: (service: string, id: string, rev: Revision, readAt?: number) => {\n observe(layers, service, id, rev, readAt);\n },\n now: () => layers.clock,\n subscribe(listener: () => void): () => void {\n layers.listeners.add(listener);\n return () => {\n layers.listeners.delete(listener);\n };\n },\n view: (service: string) => viewOf(layers, service),\n add: (service: string, id: string, made: Pick<Layer, \"collection\" | \"removed\" | \"fields\">) =>\n addLayer(layers, service, id, made),\n addItem(\n service: string,\n collection: string,\n scope: string,\n item: AddedRow,\n keep = false,\n ): Addition {\n const addition = layers.additions.add(service, collection, scope, item, keep);\n // One at a time, so at most one past the limit: the oldest goes, perhaps another service's.\n const oldest = layers.additions.size > MAX_ADDITIONS ? layers.additions.all()[0] : undefined;\n discard(layers, [], oldest === undefined ? [] : [oldest], [service]);\n return addition;\n },\n finish(opened: Opened, data: unknown): void {\n finishLayers(layers, opened, data);\n },\n discard(opened: Opened): void {\n discard(layers, opened.layers, opened.additions);\n },\n refuse(opened: Opened, refusal: Refusal): void {\n const dropped = layers.additions.refuse(opened.additions, refusal);\n // The kept ones moved from the items to `refused`: their scopes' views change too.\n discard(\n layers,\n opened.layers,\n dropped,\n opened.additions.filter((addition) => addition.refusal !== undefined).map((a) => a.service),\n );\n },\n unknown(opened: Opened, refusal: Refusal): void {\n unknownOutcome(layers, opened, refusal);\n },\n unchecked: () => layers.additions.unchecked(),\n dismiss(addition: Addition): void {\n discard(layers, [], [addition]);\n },\n settle(service: string, collection: string, scope: string, evidence: ScopeEvidence): void {\n settleScope(layers, { service, collection, scope }, evidence);\n },\n reset(): void {\n resetLayers(layers);\n },\n });\n}\n\n/** The store of `queryClient`, with what a mutation call does to it (`optimisticCall.ts`). */\nexport function storeOf(queryClient: QueryClient): StoreInternals {\n let store = stores.get(queryClient);\n if (store === undefined) {\n store = createStore(queryClient);\n stores.set(queryClient, store);\n }\n return store;\n}\n\n/**\n * The overlay store of `queryClient`, made on first use. Code that shows\n * rows from somewhere other than a query hook (the live-data hooks, an app's\n * own cache) passes them through `applyOverlay`, and reports the revisions\n * it receives through `observe`.\n */\nexport function overlaysOf(queryClient: QueryClient): OverlayStore {\n return storeOf(queryClient);\n}\n\n/**\n * Drops every layer and every revision the overlay store of `queryClient`\n * holds, and tells its subscribers: the cache was emptied because another\n * user acts on the connection now (`session.ts`). A call still in flight\n * shows nothing more.\n */\nexport function resetOverlays(queryClient: QueryClient): void {\n stores.get(queryClient)?.reset();\n}\n\n/**\n * The state of scope `scope` of `collection` of `service` changed in the\n * cache of `queryClient` (`live/collectionController.ts`): its finished\n * additions end when that state accounts for them, because it holds the id\n * their reply named (the server's own copy is shown now), a delta just\n * applied named it, or the load just applied was sent after their call's\n * reply (`readAt`) and so would hold it if it were a member. Additions of\n * calls in flight stay.\n */\nexport function settleAdditions(\n queryClient: QueryClient,\n service: string,\n collection: string,\n scope: string,\n evidence: ScopeEvidence,\n): void {\n stores.get(queryClient)?.settle(service, collection, scope, evidence);\n}\n","// Which user a `QueryClient`'s cache holds data for, and what each\n// `qd:hello` does to that cache (RFC 0003 sections 6, 8.1, 11.1 and 11.5).\n// Method results, rows and items are cached as the user who read them was\n// allowed to see them (fields above that user's tier included), and the\n// server answers a version or revision the client holds \"not modified\" for\n// anyone who may read the row. So the cache of one user is never shown to,\n// nor sent on behalf of, another:\n//\n// - a hello naming another user than the cache was loaded for (`null`, an\n// anonymous socket, counts as a user) empties the cache: every quickdraw\n// query is removed (method results, entity and collection entries, held or\n// not, and the versions that come with them), the optimistic overlays are\n// dropped, and the live data drops what it holds and loads it again from\n// scratch (`live/liveData.ts`);\n// - the first hello on new credentials naming the same user (a refreshed\n// token) keeps the cache and refetches it, as the new credentials;\n// - a hello after a reconnect with the same credentials changes nothing.\n//\n// The hooks and the live stores read nothing before the hello on the current\n// credentials has arrived (`context.ts`, `query.ts`, `live/host.ts`), so no\n// version or revision of the last user's data leaves the client first, and\n// while new credentials await their hello the hooks show nothing of what is\n// cached (`awaitingHello`): no cache is removed until the hello decides, and\n// a hello naming the same user shows it again. 4.1\n// cleared nothing on a token change; 5.0's first cut refetched with the\n// versions held, which the server answered \"not modified\" for the new user.\n//\n// Pushes that say the user's access changed refetch what it may have\n// changed, through the invalidation coordinator (`refetchOnAccessChanges`):\n// new service grants (`qd:access`) every quickdraw query, and a revoked row\n// or scope (`qd:revoked`) the method queries of its service.\n//\n// React-free: the provider makes the session of its connection and\n// `QueryClient`, and the live data uses the same one.\n\nimport type { QueryClient } from \"@tanstack/react-query\";\nimport { SERVER_EVENTS } from \"../contract/names\";\nimport { isName, isRecord } from \"../protocol/guards\";\nimport type { HelloFrame } from \"../protocol/version\";\nimport type { QuickdrawConnection } from \"./connection\";\nimport type { InvalidationCoordinator } from \"./coordinator\";\nimport { KEY_ROOT, serviceKeyPrefix } from \"./keys\";\nimport { resetOverlays } from \"./optimistic\";\nimport { notifyEach } from \"./watch\";\n\n/** What a new `qd:hello` meant for the cache. */\nexport interface HelloChange {\n /** It names another user than the cache was loaded for: the cache was emptied. */\n readonly switched: boolean;\n /** No hello was held before it: the connection's first, or the first on new credentials. */\n readonly first: boolean;\n}\n\n/** The hellos of one connection, as they concern the cache of one `QueryClient`. */\nexport interface CacheSession {\n /**\n * Calls `listener` after each new hello, once the cache is settled for the\n * user it names; returns the unsubscribe function.\n */\n onHello(listener: (change: HelloChange) => void): () => void;\n}\n\n/** The user each cache was loaded for (`null`: anonymous); absent before its first hello. */\nconst loadedFor = new WeakMap<QueryClient, { readonly userId: string | null }>();\n\nconst sessions = new WeakMap<QuickdrawConnection, WeakMap<QueryClient, CacheSession>>();\n\n/**\n * True while new credentials await their hello on a connection whose cache\n * was loaded under the last ones (a hello settled it): the hooks then show\n * nothing of what is cached, since it may be another user's, until the hello\n * settles it (removed for another user, kept for the same one). False before\n * the connection's first hello, so data a server render prefetched shows.\n */\nexport function awaitingHello(connection: QuickdrawConnection, queryClient: QueryClient): boolean {\n return connection.getState().hello === null && loadedFor.has(queryClient);\n}\n\n/** The user a hello names: its `userId`, or `null` for an anonymous socket. */\nexport function userOf(hello: unknown): string | null {\n return isRecord(hello) && typeof hello.userId === \"string\" ? hello.userId : null;\n}\n\n/** Settles `queryClient`'s cache for the user `hello` names. */\nfunction settle(queryClient: QueryClient, hello: HelloFrame, first: boolean): HelloChange {\n const user = userOf(hello);\n const loaded = loadedFor.get(queryClient);\n loadedFor.set(queryClient, { userId: user });\n if (loaded !== undefined && loaded.userId !== user) {\n queryClient.removeQueries({ queryKey: [KEY_ROOT] });\n resetOverlays(queryClient);\n return { switched: true, first };\n }\n if (loaded !== undefined && first) {\n // The same user on new credentials: what is cached may stay, read again as them.\n void queryClient.invalidateQueries({ queryKey: [KEY_ROOT] });\n }\n return { switched: false, first };\n}\n\nfunction createSession(connection: QuickdrawConnection, queryClient: QueryClient): CacheSession {\n const listeners = new Set<(change: HelloChange) => void>();\n let held = connection.getState().hello;\n if (held !== null) {\n settle(queryClient, held, false);\n }\n connection.subscribe(() => {\n const next = connection.getState().hello;\n if (next === held) {\n return;\n }\n const first = held === null;\n held = next;\n if (next !== null) {\n const change = settle(queryClient, next, first);\n notifyEach(listeners, (listener) => {\n listener(change);\n });\n }\n });\n return Object.freeze({\n onHello(listener: (change: HelloChange) => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n });\n}\n\n/**\n * The session of `connection` and `queryClient`, made on first use and kept\n * as long as the connection: from then on, every `qd:hello` settles the\n * cache for the user it names. The provider makes it when it mounts; code\n * without React that caches through `queryClient` makes it before the\n * connection opens.\n */\nexport function sessionOf(connection: QuickdrawConnection, queryClient: QueryClient): CacheSession {\n let byClient = sessions.get(connection);\n if (byClient === undefined) {\n byClient = new WeakMap();\n sessions.set(connection, byClient);\n }\n let session = byClient.get(queryClient);\n if (session === undefined) {\n session = createSession(connection, queryClient);\n byClient.set(queryClient, session);\n }\n return session;\n}\n\n/**\n * Refetches, through `coordinator`, what a change of the user's access may\n * have changed: every quickdraw query when the server pushes new service\n * grants (`qd:access`), and the method queries of a service when it ends a\n * subscription of that service (`qd:revoked`: access to a row or a scope was\n * revoked, or its anchor deleted, so a method may refuse now what it served).\n * A query refused that way loses its cached result (`query.ts`). Returns the\n * function that stops; the provider runs it while it is mounted.\n */\nexport function refetchOnAccessChanges(\n connection: QuickdrawConnection,\n coordinator: InvalidationCoordinator,\n): () => void {\n const { socket } = connection;\n const onAccess = (): void => {\n coordinator.invalidate([KEY_ROOT]);\n };\n const onRevoked = (frame: unknown): void => {\n if (isRecord(frame) && isName(frame.s)) {\n coordinator.invalidate([...serviceKeyPrefix(frame.s), \"m\"]);\n }\n };\n socket.on(SERVER_EVENTS.access, onAccess);\n socket.on(SERVER_EVENTS.revoked, onRevoked);\n return () => {\n socket.off(SERVER_EVENTS.access, onAccess);\n socket.off(SERVER_EVENTS.revoked, onRevoked);\n };\n}\n","// The state of one collection scope as the cache holds it (RFC 0003 sections\n// 7.3 and 7.4), and what reading it needs: the empty state, the items loaded\n// in the order they are shown, and the items a reload left behind. Split from\n// `collectionStore.ts`, which changes it (deltas, pages, items) and documents\n// its rules, and `collectionSnapshot.ts` (snapshots).\n//\n// Pure functions, React-free.\n\nimport type { Revision } from \"../../protocol/envelope\";\nimport type { IndexRow } from \"./collectionIndex\";\n\n/** An item of a collection: any object with a string `id`. */\nexport type CollectionItem = { readonly id: string };\n\n/** What the cache holds for one collection scope. */\nexport interface CollectionState<Item extends CollectionItem = CollectionItem> {\n /** The items loaded, by id. */\n readonly byId: ReadonlyMap<string, Item>;\n /**\n * The ids of the items loaded, in order, while no index is held: the\n * server's order of the pages, then items that arrived later, in their\n * place by `order` when they carry its columns and last otherwise.\n */\n readonly order: readonly string[];\n /** The newest revision held for each member: a loaded item, or an index row. */\n readonly revById: ReadonlyMap<string, Revision>;\n /**\n * Tombstones: the revision each removed id was removed at, the latest\n * {@link MAX_TOMBSTONES} of them. A snapshot drops those it is newer than.\n */\n readonly removed: ReadonlyMap<string, Revision>;\n /** One row per member, in order, when the collection declares an index and the scope fits in it. */\n readonly index: readonly IndexRow[] | null;\n /** The scope has more members than an index holds (50,000): no index, and views run over loaded items. */\n readonly indexTruncated: boolean;\n /** The page size asked for was above the collection's `maxLimit`, and was lowered to it. */\n readonly clamped: boolean;\n /** The cursor of the next page; `null` after the last one. */\n readonly nextCursor: string | null;\n /** How many members the scope has; `null` before the first snapshot. */\n readonly totalCount: number | null;\n /** The revision of the last snapshot. */\n readonly snapshotRev: Revision;\n /** The newest revision applied to the scope: what a resume sends as `since`. */\n readonly rev: Revision;\n}\n\n/**\n * A page as the store reads it: the answer to `qd:col:sub` without `since`\n * (`CollectionSnapshot`), checked for its required fields only.\n */\nexport interface PageReply {\n readonly rev: Revision;\n readonly items: readonly unknown[];\n readonly total: number;\n readonly cursor: string | null;\n readonly clamped?: unknown;\n readonly index?: unknown;\n readonly indexTruncated?: unknown;\n}\n\n/**\n * The most tombstones a scope keeps. A tombstone keeps a frame, page or\n * items answer older than a removal from bringing the item back; those\n * arrive soon after it, so the oldest go first once a scope that is never\n * reloaded has removed this many items.\n */\nexport const MAX_TOMBSTONES = 1000;\n\n/**\n * Records that `id` was removed at `rev` in `tombstones` (a copy being\n * written), as its newest entry, and drops the oldest past\n * {@link MAX_TOMBSTONES}.\n */\nexport function addTombstone(tombstones: Map<string, Revision>, id: string, rev: Revision): void {\n tombstones.delete(id);\n tombstones.set(id, rev);\n for (const oldest of tombstones.keys()) {\n if (tombstones.size <= MAX_TOMBSTONES) {\n return;\n }\n tombstones.delete(oldest);\n }\n}\n\n/** The state of a scope nothing arrived for yet. */\nexport function emptyCollection<Item extends CollectionItem>(): CollectionState<Item> {\n return Object.freeze({\n byId: new Map(),\n order: [],\n revById: new Map(),\n removed: new Map(),\n index: null,\n indexTruncated: false,\n clamped: false,\n nextCursor: null,\n totalCount: null,\n snapshotRev: 0,\n rev: 0,\n });\n}\n\n/** The ids of the items loaded, in the order they are shown. */\nexport function loadedIds(state: CollectionState<CollectionItem>): string[] {\n if (state.index === null) {\n return [...state.order];\n }\n return state.index.map((row) => row.id).filter((id) => state.byId.has(id));\n}\n\n/** Loaded items older than the last snapshot and not refreshed by it: their data may be out of date. */\nexport function staleIds(state: CollectionState<CollectionItem>): string[] {\n return loadedIds(state).filter((id) => (state.revById.get(id) ?? 0) < state.snapshotRev);\n}\n\n/**\n * Drops the loaded items a reload did not refresh, from a scope without an\n * index whose every page was read again after its last snapshot: an item\n * older than that snapshot was on none of its pages, in no delta and in no\n * items answer since, so it is no longer a member. Each leaves a tombstone\n * at the snapshot's revision; the count stays the server's. A state with an\n * index (whose snapshot already pruned by membership) is returned as it is.\n */\nexport function pruneStale<Item extends CollectionItem>(\n state: CollectionState<Item>,\n): CollectionState<Item> {\n const stale = new Set(staleIds(state));\n if (stale.size === 0 || state.index !== null) {\n return state;\n }\n const byId = new Map(state.byId);\n const revById = new Map(state.revById);\n const removed = new Map(state.removed);\n for (const id of stale) {\n byId.delete(id);\n revById.delete(id);\n addTombstone(removed, id, state.snapshotRev);\n }\n return Object.freeze({\n ...state,\n byId,\n revById,\n removed,\n order: state.order.filter((id) => !stale.has(id)),\n });\n}\n","// The collection index on the client (RFC 0003 sections 7.4 and 7.5). The\n// first page of a collection that declares `index` carries one row per\n// member, `[id, rev, ...fields]` in the collection's `order`; the client keeps\n// those rows as objects (`{ id, status, ordinal }`), which is what a view\n// reads, and keeps them in order from deltas: every `order` column but `id`\n// is an index field (section 7.1), so a row's place can be found by its own\n// values.\n//\n// The order is the server's keyset order: each column ascending or\n// descending, nulls last ascending and first descending, `id` last. Numbers\n// compare as numbers, booleans false first, and strings by code unit, which\n// matches a database collation only for ASCII text; a snapshot brings the\n// server's own order back.\n//\n// Pure functions, React-free.\n\nimport type { OrderBy } from \"../../contract/collections\";\nimport type { WireIndexRow } from \"../../protocol/envelope\";\nimport { isRecord } from \"../../protocol/guards\";\n\n/** One member in a collection's index, as views and hooks read it: `id` and the index fields, by name. */\nexport type IndexRow = Readonly<Record<string, unknown>> & { readonly id: string };\n\n/** What the store needs of a collection's declaration (`CollectionDef`). */\nexport interface CollectionShape {\n /** The index fields, in the order the contract declares them; absent when there is no index. */\n readonly index?: readonly string[] | undefined;\n /** The sort columns, ending in `id`. */\n readonly order?: OrderBy | undefined;\n}\n\n/** True when `value` is an item or row: an object with a non-empty string `id`. */\nexport function hasId(value: unknown): value is { readonly id: string } {\n return isRecord(value) && typeof value.id === \"string\" && value.id !== \"\";\n}\n\n/** A wire index row `[id, rev, ...fields]` as an object; `undefined` when it is malformed. */\nexport function indexRowOf(shape: CollectionShape, wire: unknown): IndexRow | undefined {\n if (!Array.isArray(wire) || typeof wire[0] !== \"string\" || wire[0] === \"\") {\n return undefined;\n }\n const values: WireIndexRow | readonly unknown[] = wire;\n const row: Record<string, unknown> = { id: values[0] };\n for (const [position, field] of (shape.index ?? []).entries()) {\n row[field] = values[position + 2] ?? null;\n }\n return Object.freeze(row) as IndexRow;\n}\n\n/** The index row of an item: its index fields, which are item fields. */\nexport function indexRowFromItem(shape: CollectionShape, item: { readonly id: string }): IndexRow {\n const values = item as Readonly<Record<string, unknown>>;\n const row: Record<string, unknown> = { id: item.id };\n for (const field of shape.index ?? []) {\n row[field] = values[field] ?? null;\n }\n return Object.freeze(row) as IndexRow;\n}\n\n/** `row` with the index fields among `fields` (a patch) laid over it; `row` itself when none changes. */\nexport function patchIndexRow(shape: CollectionShape, row: IndexRow, fields: unknown): IndexRow {\n if (!isRecord(fields)) {\n return row;\n }\n let next: Record<string, unknown> | undefined;\n for (const field of shape.index ?? []) {\n if (Object.hasOwn(fields, field) && !Object.is(row[field], fields[field])) {\n next ??= { ...row };\n next[field] = fields[field];\n }\n }\n return next === undefined ? row : (Object.freeze(next) as IndexRow);\n}\n\nfunction rank(value: unknown): number {\n return value === null || value === undefined ? 1 : 0;\n}\n\n/** Compares two column values ascending: nulls last, numbers as numbers, the rest as strings. */\nfunction compareValues(a: unknown, b: unknown): number {\n if (Object.is(a, b)) {\n return 0;\n }\n if (rank(a) !== rank(b)) {\n return rank(a) - rank(b);\n }\n if (typeof a === \"number\" && typeof b === \"number\") {\n return a - b;\n }\n if (typeof a === \"boolean\" && typeof b === \"boolean\") {\n return Number(a) - Number(b);\n }\n const left = typeof a === \"string\" ? a : JSON.stringify(a);\n const right = typeof b === \"string\" ? b : JSON.stringify(b);\n if (left === right) {\n return 0;\n }\n return left < right ? -1 : 1;\n}\n\ntype Values = Readonly<Record<string, unknown>>;\n\n/** Compares two rows by `order`, as the server's keyset cursor orders them. */\nexport function compareRows(order: OrderBy, a: Values, b: Values): number {\n for (const [column, direction] of order) {\n const compared = compareValues(a[column], b[column]);\n if (compared !== 0) {\n return direction === \"desc\" ? -compared : compared;\n }\n }\n return 0;\n}\n\n/** True when `value` holds every `order` column, so its place in the order can be found. */\nexport function hasOrderValues(order: OrderBy | undefined, value: Values): boolean {\n return order !== undefined && order.every(([column]) => Object.hasOwn(value, column));\n}\n\n/**\n * Where `row` goes among `count` rows sorted by `order`, each read with\n * `rowAt(position)`: after every row that sorts before or with it. A binary\n * search, so it reads about log2(count) of them.\n */\nexport function insertionPointBy(\n order: OrderBy,\n count: number,\n rowAt: (position: number) => Values,\n row: Values,\n): number {\n let low = 0;\n let high = count;\n while (low < high) {\n const middle = Math.floor((low + high) / 2);\n if (compareRows(order, rowAt(middle), row) <= 0) {\n low = middle + 1;\n } else {\n high = middle;\n }\n }\n return low;\n}\n\n/** Where `row` goes in `rows`, which are sorted by `order`: after every row that sorts before or with it. */\nexport function insertionPoint(order: OrderBy, rows: readonly Values[], row: Values): number {\n return insertionPointBy(order, rows.length, (position) => rows[position] as Values, row);\n}\n\n/**\n * Where the row of `id`, whose values are `row`, is in `rows`: found by its\n * values in the order, else by a scan (a string order the database collates\n * differently); -1 when it is not there.\n */\nexport function positionOf(\n order: OrderBy | undefined,\n rows: readonly IndexRow[],\n row: IndexRow,\n): number {\n if (order !== undefined) {\n const after = insertionPoint(order, rows, row);\n if (after > 0 && rows[after - 1]?.id === row.id) {\n return after - 1;\n }\n }\n return rows.findIndex((candidate) => candidate.id === row.id);\n}\n","// A collection scope's snapshot (RFC 0003 sections 7.3 and 7.4): the answer\n// to `qd:col:sub` without a cursor, merged with the state held by revision.\n// Split from `collectionStore.ts`, whose header states the rules.\n//\n// Pure functions, React-free.\n\nimport type { Revision } from \"../../protocol/envelope\";\nimport {\n hasId,\n indexRowFromItem,\n indexRowOf,\n insertionPoint,\n type CollectionShape,\n type IndexRow,\n} from \"./collectionIndex\";\nimport {\n emptyCollection,\n loadedIds,\n type CollectionItem,\n type CollectionState,\n type PageReply,\n} from \"./collectionState\";\n\n/** The index row the state holds for `id`, or one made from its item. */\nfunction heldRow(\n base: CollectionState<CollectionItem>,\n held: ReadonlyMap<string, IndexRow>,\n shape: CollectionShape,\n id: string,\n): IndexRow | undefined {\n const item = base.byId.get(id);\n return held.get(id) ?? (item === undefined ? undefined : indexRowFromItem(shape, item));\n}\n\n/** The index after a snapshot, and the revision of each member in it. */\ninterface SnapshotIndex {\n readonly rows: IndexRow[];\n readonly revs: Map<string, Revision>;\n}\n\n/**\n * The snapshot's index merged with what the state holds: a member removed\n * after the snapshot was read stays out, and a member changed or added after\n * it keeps the row the state holds, in its place. `null` without an index.\n */\nfunction snapshotIndex(\n base: CollectionState<CollectionItem>,\n snapshot: PageReply,\n shape: CollectionShape,\n): SnapshotIndex | null {\n const wires: readonly unknown[] | undefined = Array.isArray(snapshot.index)\n ? (snapshot.index as readonly unknown[])\n : undefined;\n if (wires === undefined) {\n return null;\n }\n const held = new Map((base.index ?? []).map((row) => [row.id, row]));\n const newer = (id: string): boolean =>\n (base.revById.get(id) ?? Number.NEGATIVE_INFINITY) > snapshot.rev;\n const rows: IndexRow[] = [];\n const late: IndexRow[] = [];\n const revs = new Map<string, Revision>();\n // A member newer than the snapshot keeps the row the state holds; with\n // none held, the snapshot's row (`fallback`) is the best known.\n const keep = (id: string, fallback?: IndexRow): void => {\n const row = heldRow(base, held, shape, id) ?? fallback;\n if (row !== undefined) {\n late.push(row);\n revs.set(id, base.revById.get(id) ?? snapshot.rev);\n }\n };\n for (const wire of wires) {\n const row = indexRowOf(shape, wire);\n const removedAfter =\n (base.removed.get(row?.id ?? \"\") ?? Number.NEGATIVE_INFINITY) > snapshot.rev;\n if (row === undefined || revs.has(row.id) || removedAfter) {\n continue;\n }\n if (newer(row.id)) {\n keep(row.id, row);\n } else {\n rows.push(row);\n revs.set(row.id, snapshot.rev);\n }\n }\n for (const id of base.revById.keys()) {\n if (!revs.has(id) && newer(id)) {\n keep(id);\n }\n }\n const { order } = shape;\n for (const row of late) {\n rows.splice(order === undefined ? rows.length : insertionPoint(order, rows, row), 0, row);\n }\n return { rows, revs };\n}\n\n/** The items a snapshot keeps: those held that are members (or newer than it), then its page's. */\nfunction snapshotItems<Item extends CollectionItem>(\n base: CollectionState<Item>,\n snapshot: PageReply,\n members: ReadonlySet<string> | null,\n): { readonly byId: Map<string, Item>; readonly revById: Map<string, Revision> } {\n const byId = new Map<string, Item>();\n const revById = new Map<string, Revision>();\n for (const id of loadedIds(base)) {\n const rev = base.revById.get(id) ?? 0;\n const pruned = members !== null && !members.has(id) && rev <= snapshot.rev;\n if (!pruned) {\n byId.set(id, base.byId.get(id) as Item);\n revById.set(id, rev);\n }\n }\n for (const item of snapshot.items) {\n const tombstone = hasId(item) ? base.removed.get(item.id) : undefined;\n const cached = hasId(item) ? revById.get(item.id) : undefined;\n const older = (cached ?? tombstone ?? Number.NEGATIVE_INFINITY) > snapshot.rev;\n if (hasId(item) && !older && (members === null || members.has(item.id))) {\n byId.set(item.id, item as Item);\n revById.set(item.id, snapshot.rev);\n }\n }\n return { byId, revById };\n}\n\n/** The order of loaded items after a snapshot without an index: its page first, then the others as before. */\nfunction snapshotOrder(\n base: CollectionState<CollectionItem>,\n snapshot: PageReply,\n byId: ReadonlyMap<string, unknown>,\n): string[] {\n const order = new Set<string>();\n for (const item of snapshot.items) {\n if (hasId(item) && byId.has(item.id)) {\n order.add(item.id);\n }\n }\n for (const id of loadedIds(base)) {\n if (byId.has(id)) {\n order.add(id);\n }\n }\n return [...order];\n}\n\n/**\n * Applies a snapshot: the answer to `qd:col:sub` without a cursor (a first\n * load, a reload after `reset`, or a resume the server could not serve).\n *\n * - With an index, the index is the scope's membership: held items of\n * members stay, others are pruned unless a delta newer than the snapshot\n * put them there. Without one, every held item stays (pages loaded before\n * are kept), as 4.1 did when the server sent no `ids`.\n * - Page items replace held ones unless the state holds a newer item or a\n * newer tombstone for them.\n * - Tombstones older than the snapshot are dropped; newer ones stay.\n */\nexport function applySnapshot<Item extends CollectionItem>(\n prev: CollectionState<Item> | null | undefined,\n snapshot: PageReply,\n shape: CollectionShape,\n): CollectionState<Item> {\n const base = prev ?? emptyCollection<Item>();\n const index = snapshotIndex(base, snapshot, shape);\n const members = index === null ? null : new Set(index.revs.keys());\n const { byId, revById } = snapshotItems(base, snapshot, members);\n for (const [id, rev] of index?.revs ?? []) {\n if (!revById.has(id)) {\n revById.set(id, rev);\n }\n }\n return Object.freeze({\n byId,\n order: index === null ? snapshotOrder(base, snapshot, byId) : [],\n revById,\n removed: new Map([...base.removed].filter(([, rev]) => rev > snapshot.rev)),\n index: index?.rows ?? null,\n indexTruncated: snapshot.indexTruncated === true,\n clamped: snapshot.clamped === true,\n nextCursor: snapshot.cursor,\n totalCount: index === null ? snapshot.total : index.rows.length,\n snapshotRev: snapshot.rev,\n rev: Math.max(base.rev, snapshot.rev),\n });\n}\n","// How a collection scope's cached state changes (RFC 0003 sections 7.2 to\n// 7.4): the merge logic behind `useCollection`, free of React and sockets so\n// every rule is tested on its own. Ported from 4.1's collection cache\n// (4.1 `src/client/collectionCache.ts`), whose rules hold:\n//\n// - everything is keyed by id, so live deltas and pages loaded later compose;\n// - per item, the newest revision wins: a delta older than what the state\n// holds for that id is ignored, and a snapshot or page item overwrites\n// only what is not newer than the page;\n// - a removal leaves a tombstone at its revision, so an older `added` or\n// page cannot bring the item back; a snapshot at or after the tombstone\n// drops it. A scope keeps the latest 1,000 (`MAX_TOMBSTONES`), and a\n// frame that removes nothing shares them with the state before it rather\n// than copying them.\n//\n// and adds what 5.0's protocol carries:\n//\n// - one revision per frame (`qd:c { rev, deltas }`): the deltas of a frame,\n// and of a resume reply, share it and apply in the order sent, so with\n// equal revisions the later one wins;\n// - `added` for an id already held is an upsert (a touch), and changes no\n// count;\n// - the count is the server's `total`, changed only by `added` and\n// `removed`: `updated` and `patched` name members the total already holds;\n// - `patched` merges the changed fields into the item. With no item held it\n// never makes a partial one: the id is reported `missing`, for the\n// controller to load with `qd:col:items`, unless only the index holds the\n// member and the whole scope is not being loaded;\n// - without an index, a member a page has not loaded yet is beyond the items\n// shown: `updated` and `patched` for it are ignored while more pages\n// follow, unless the whole scope is being loaded, so they never put an\n// item into a paged window out of its place;\n// - the index (`collectionIndex.ts`): the snapshot's rows are the scope's\n// membership, so items of non-members are pruned as 4.1 pruned by `ids`;\n// `added` brings its row, and `patched` and `updated` change its fields\n// and its place; a row newer than the snapshot is kept over it;\n// - `clamped` and `indexTruncated` from the snapshot.\n//\n// The state's shape and the helpers that read it are in `collectionState.ts`,\n// snapshots in `collectionSnapshot.ts`; this module re-exports both, and\n// applies deltas, later pages, items loaded by id and items read outside the\n// scope (a search's results, which the scope's deltas then keep current).\n//\n// Pure functions, React-free.\n\nimport type { CollectionDelta, Revision } from \"../../protocol/envelope\";\nimport { isRecord } from \"../../protocol/guards\";\nimport {\n hasId,\n hasOrderValues,\n indexRowFromItem,\n indexRowOf,\n insertionPoint,\n insertionPointBy,\n patchIndexRow,\n positionOf,\n type CollectionShape,\n type IndexRow,\n} from \"./collectionIndex\";\nimport {\n addTombstone,\n emptyCollection,\n type CollectionItem,\n type CollectionState,\n type PageReply,\n} from \"./collectionState\";\n\nexport { applySnapshot } from \"./collectionSnapshot\";\nexport {\n MAX_TOMBSTONES,\n emptyCollection,\n loadedIds,\n pruneStale,\n staleIds,\n type CollectionItem,\n type CollectionState,\n type PageReply,\n} from \"./collectionState\";\n\n/** What applying deltas did. */\nexport interface DeltaResult<Item extends CollectionItem = CollectionItem> {\n /** The new state: the same object when nothing changed. */\n readonly state: CollectionState<Item>;\n /** A `reset` arrived: load the scope again. */\n readonly reset: boolean;\n /** Ids a `patched` delta found no item for, to load with `qd:col:items`. */\n readonly missing: readonly string[];\n}\n\n/** Options of {@link applyDeltas}. */\nexport interface DeltaOptions {\n /** True while the whole scope is loaded: a patch of a member only the index holds loads its item. */\n readonly loadAll?: boolean;\n}\n\n/** A copy of a state that one batch of changes is made on. */\ninterface Work<Item extends CollectionItem> {\n readonly shape: CollectionShape;\n readonly byId: Map<string, Item>;\n readonly order: string[];\n readonly revById: Map<string, Revision>;\n /**\n * The tombstones: the base state's own map until the batch changes one,\n * when `tombstones` copies it, so a frame that removes nothing shares it.\n */\n removed: ReadonlyMap<string, Revision>;\n /** True once `removed` is this batch's copy. */\n removedCopied: boolean;\n readonly index: IndexRow[] | null;\n /** The index's rows by id, made on first use. */\n indexById: Map<string, IndexRow> | undefined;\n totalCount: number | null;\n /** More pages follow the items loaded. */\n readonly paged: boolean;\n /**\n * Whether every item in `order` carries the `order` columns, so a new one\n * can be placed among them by its values: worked out once per batch, on\n * first use, and kept as items come and go.\n */\n placeable: boolean | undefined;\n changed: boolean;\n}\n\ntype Values = Readonly<Record<string, unknown>>;\n\nfunction workOn<Item extends CollectionItem>(\n base: CollectionState<Item>,\n shape: CollectionShape,\n): Work<Item> {\n return {\n shape,\n byId: new Map(base.byId),\n order: [...base.order],\n revById: new Map(base.revById),\n removed: base.removed,\n removedCopied: false,\n index: base.index === null ? null : [...base.index],\n indexById: undefined,\n totalCount: base.totalCount,\n paged: base.nextCursor !== null,\n placeable: undefined,\n changed: false,\n };\n}\n\n/**\n * True when a change of member `id` may bring its item in: it is loaded, the\n * index places it, the whole scope is being loaded, or no page follows the\n * items loaded. Otherwise it is beyond the paged window shown.\n */\nfunction mayBringIn(work: Work<CollectionItem>, id: string, loadAll: boolean): boolean {\n return work.byId.has(id) || work.index !== null || loadAll || !work.paged;\n}\n\n/** The state `work` made, over `base`; `base` itself when nothing changed and `extra` is empty. */\nfunction finish<Item extends CollectionItem>(\n base: CollectionState<Item>,\n work: Work<Item>,\n extra: Partial<CollectionState<Item>> = {},\n): CollectionState<Item> {\n if (!work.changed && Object.keys(extra).length === 0) {\n return base;\n }\n return Object.freeze({\n ...base,\n byId: work.byId,\n order: work.index === null ? work.order : [],\n revById: work.revById,\n removed: work.removed,\n index: work.index,\n totalCount: work.index === null ? work.totalCount : work.index.length,\n ...extra,\n });\n}\n\n/** The batch's tombstones, to change: copied from the base state on the first change. */\nfunction tombstones(work: Work<CollectionItem>): Map<string, Revision> {\n if (!work.removedCopied) {\n work.removed = new Map(work.removed);\n work.removedCopied = true;\n }\n return work.removed as Map<string, Revision>;\n}\n\n/** True when the state holds something newer for `id` than `rev`: an item, a row or a tombstone. */\nfunction isStale(work: Work<CollectionItem>, id: string, rev: Revision): boolean {\n const held = work.revById.get(id) ?? work.removed.get(id);\n return held !== undefined && rev < held;\n}\n\nfunction rowsById(work: Work<CollectionItem>): Map<string, IndexRow> {\n work.indexById ??= new Map((work.index ?? []).map((row) => [row.id, row]));\n return work.indexById;\n}\n\n/** Takes the row of `id` out of the index. */\nfunction takeIndexRow(work: Work<CollectionItem>, id: string): void {\n const index = work.index;\n const held = rowsById(work).get(id);\n if (index === null || held === undefined) {\n return;\n }\n const position = positionOf(work.shape.order, index, held);\n if (position >= 0) {\n index.splice(position, 1);\n }\n rowsById(work).delete(id);\n}\n\n/** Puts `row` in the index at its place, replacing the row of its id. */\nfunction placeIndexRow(work: Work<CollectionItem>, row: IndexRow): void {\n const index = work.index;\n if (index === null) {\n return;\n }\n takeIndexRow(work, row.id);\n const { order } = work.shape;\n index.splice(order === undefined ? index.length : insertionPoint(order, index, row), 0, row);\n rowsById(work).set(row.id, row);\n}\n\n/** True when every item in `work.order` carries the `order` columns; read once per batch. */\nfunction canPlace(work: Work<CollectionItem>): boolean {\n const { order } = work.shape;\n if (order === undefined) {\n return false;\n }\n work.placeable ??= work.order.every((id) => hasOrderValues(order, work.byId.get(id) as Values));\n return work.placeable;\n}\n\n/**\n * Adds the id of a newly loaded item to the order: in its place when its\n * values and those of every item loaded allow, found by a binary search over\n * the order, else last. A page in the server's order lands at the end, so a\n * whole scope loads in time linear in its size.\n */\nfunction placeLoaded(work: Work<CollectionItem>, item: CollectionItem): void {\n const { order } = work.shape;\n const values = item as Values;\n if (order === undefined || !canPlace(work) || !hasOrderValues(order, values)) {\n work.order.push(item.id);\n work.placeable = order === undefined ? undefined : false;\n return;\n }\n const valuesAt = (position: number): Values =>\n work.byId.get(work.order[position] as string) as Values;\n work.order.splice(insertionPointBy(order, work.order.length, valuesAt, values), 0, item.id);\n}\n\n/**\n * Upserts `item` at revision `rev`, unless something newer is held. `row` is\n * its index row when it came with one. `counts` says whether a new id is a\n * new member (a delta) rather than one the count already holds (a page).\n */\nfunction upsert(\n work: Work<CollectionItem>,\n item: CollectionItem,\n rev: Revision,\n counts: boolean,\n row?: IndexRow,\n): void {\n const { id } = item;\n if (isStale(work, id, rev)) {\n return;\n }\n const known = work.revById.has(id);\n if (work.removed.has(id)) {\n tombstones(work).delete(id);\n }\n work.byId.set(id, item);\n work.revById.set(id, rev);\n if (work.index !== null) {\n placeIndexRow(work, row ?? indexRowFromItem(work.shape, item));\n } else if (!known) {\n placeLoaded(work, item);\n } else if (work.placeable === true && !hasOrderValues(work.shape.order, item as Values)) {\n work.placeable = false;\n }\n if (!known && counts && work.totalCount !== null) {\n work.totalCount += 1;\n }\n work.changed = true;\n}\n\n/** Removes `id` at revision `rev`, leaving a tombstone, unless something newer is held. */\nfunction remove(work: Work<CollectionItem>, id: string, rev: Revision): void {\n if (isStale(work, id, rev)) {\n return;\n }\n const known = work.revById.has(id);\n work.byId.delete(id);\n work.revById.delete(id);\n takeIndexRow(work, id);\n const position = work.order.indexOf(id);\n if (position >= 0) {\n work.order.splice(position, 1);\n }\n if (position >= 0 && work.placeable === false) {\n // The item without the order's columns may be the one that left: work it out again.\n work.placeable = undefined;\n }\n addTombstone(tombstones(work), id, rev);\n if (known && work.totalCount !== null) {\n work.totalCount = Math.max(0, work.totalCount - 1);\n }\n work.changed = true;\n}\n\n/** Merges a patch of `id` at revision `rev`; reports the id when its item must be loaded instead. */\nfunction patch(\n work: Work<CollectionItem>,\n delta: { readonly id: string; readonly d: unknown },\n rev: Revision,\n loadAll: boolean,\n missing: string[],\n): void {\n const { id, d } = delta;\n if (isStale(work, id, rev)) {\n return;\n }\n if (!work.revById.has(id)) {\n // A member this state does not know, or one it removed: never a partial item.\n if (mayBringIn(work, id, loadAll)) {\n missing.push(id);\n }\n return;\n }\n work.revById.set(id, rev);\n work.changed = true;\n const row = rowsById(work).get(id);\n if (work.index !== null && row !== undefined) {\n placeIndexRow(work, patchIndexRow(work.shape, row, d));\n }\n const item = work.byId.get(id);\n if (item !== undefined) {\n work.byId.set(id, isRecord(d) ? { ...item, ...d } : item);\n } else if (work.index === null || loadAll) {\n missing.push(id);\n }\n}\n\n/** Applies one delta; returns true for a `reset`. */\nfunction applyOne(\n work: Work<CollectionItem>,\n delta: unknown,\n rev: Revision,\n loadAll: boolean,\n missing: string[],\n): boolean {\n if (!isRecord(delta)) {\n return false;\n }\n if (delta.t === \"reset\") {\n return true;\n }\n if (delta.t === \"added\" && hasId(delta.item)) {\n upsert(work, delta.item, rev, true, indexRowOf(work.shape, delta.index));\n } else if (delta.t === \"updated\" && hasId(delta.item)) {\n if (mayBringIn(work, delta.item.id, loadAll)) {\n upsert(work, delta.item, rev, false);\n }\n } else if (delta.t === \"patched\" && typeof delta.id === \"string\") {\n patch(work, { id: delta.id, d: delta.d }, rev, loadAll, missing);\n } else if (delta.t === \"removed\" && typeof delta.id === \"string\") {\n remove(work, delta.id, rev);\n }\n return false;\n}\n\n/**\n * Applies the deltas of one `qd:c` frame (or of a resume reply), all at\n * revision `rev`, in the order sent. The scope's `rev` rises to `rev`\n * unless the frame holds a `reset`.\n */\nexport function applyDeltas<Item extends CollectionItem>(\n prev: CollectionState<Item> | null | undefined,\n deltas: readonly CollectionDelta<Item>[] | readonly unknown[],\n rev: Revision,\n shape: CollectionShape,\n options: DeltaOptions = {},\n): DeltaResult<Item> {\n const base = prev ?? emptyCollection<Item>();\n const work = workOn(base, shape) as Work<CollectionItem>;\n const missing: string[] = [];\n let reset = false;\n for (const delta of deltas) {\n reset = applyOne(work, delta, rev, options.loadAll === true, missing) || reset;\n }\n const rises = !reset && rev > base.rev;\n const state = finish(base, work as Work<Item>, rises ? { rev } : {});\n return { state, reset, missing };\n}\n\n/** One frame's revision and deltas (`CollectionDelta`), not checked yet. */\nexport interface DeltaBatch {\n readonly rev: Revision;\n readonly deltas: readonly unknown[];\n}\n\n/** Applies frames in the order they arrived, each at its own revision. */\nexport function applyFrames<Item extends CollectionItem>(\n prev: CollectionState<Item> | null | undefined,\n frames: readonly DeltaBatch[],\n shape: CollectionShape,\n options: DeltaOptions = {},\n): DeltaResult<Item> {\n let state = prev ?? emptyCollection<Item>();\n let reset = false;\n const missing: string[] = [];\n for (const frame of frames) {\n const result = applyDeltas(state, frame.deltas, frame.rev, shape, options);\n state = result.state;\n reset ||= result.reset;\n missing.push(...result.missing);\n }\n return { state, reset, missing };\n}\n\n/**\n * Applies a later page (the answer to `qd:col:sub` with a cursor): items are\n * upserted unless the state holds newer ones, nothing is pruned, and new ids\n * go last (or in their place by `order`, without an index).\n */\nexport function applyPage<Item extends CollectionItem>(\n prev: CollectionState<Item> | null | undefined,\n page: PageReply,\n shape: CollectionShape,\n): CollectionState<Item> {\n const base = prev ?? emptyCollection<Item>();\n const work = workOn(base, shape) as Work<CollectionItem>;\n for (const item of page.items) {\n if (hasId(item)) {\n upsert(work, item, page.rev, false);\n }\n }\n return finish(base, work as Work<Item>, {\n nextCursor: page.cursor,\n clamped: page.clamped === true,\n ...(work.index === null ? { totalCount: page.total } : {}),\n });\n}\n\n/** What {@link applyKept} did. */\nexport interface KeptResult<Item extends CollectionItem = CollectionItem> {\n /** The new state: the same object when nothing changed. */\n readonly state: CollectionState<Item>;\n /** Index members the state holds a newer revision of but no item for, to load with `qd:col:items`. */\n readonly missing: readonly string[];\n}\n\n/** True when an item read outside the scope may be kept: a member the index holds, or one a delta could bring in. */\nfunction keepable(work: Work<CollectionItem>, id: string, loadAll: boolean): boolean {\n return work.index === null ? mayBringIn(work, id, loadAll) : rowsById(work).has(id);\n}\n\n/**\n * Applies items of the scope that were read outside it at revision `rev` (a\n * search's results, `useSearch`): each is upserted as an item loaded by id\n * is, unless the state holds something newer for it, so the scope's deltas\n * keep it current from then on. Only members the state can show are kept:\n * those its index holds, or, without an index, those a delta could bring in\n * (never one beyond a paged window). Nothing is removed and no count\n * changes.\n */\nexport function applyKept<Item extends CollectionItem>(\n prev: CollectionState<Item> | null | undefined,\n items: readonly unknown[],\n rev: Revision,\n shape: CollectionShape,\n options: DeltaOptions = {},\n): KeptResult<Item> {\n const base = prev ?? emptyCollection<Item>();\n const work = workOn(base, shape) as Work<CollectionItem>;\n const missing: string[] = [];\n for (const item of items) {\n if (hasId(item) && keepable(work, item.id, options.loadAll === true)) {\n upsert(work, item, rev, false);\n if (work.index !== null && !work.byId.has(item.id)) {\n missing.push(item.id);\n }\n }\n }\n return { state: finish(base, work as Work<Item>), missing };\n}\n\n/**\n * Applies the answer to `qd:col:items` for `requested` ids, read at `rev`:\n * items are upserted unless the state holds newer ones, and a requested id\n * the answer leaves out is not a member, so it is removed (unless the state\n * holds something newer for it).\n */\nexport function applyItems<Item extends CollectionItem>(\n prev: CollectionState<Item> | null | undefined,\n items: readonly unknown[],\n rev: Revision,\n shape: CollectionShape,\n requested: readonly string[],\n): CollectionState<Item> {\n const base = prev ?? emptyCollection<Item>();\n const work = workOn(base, shape) as Work<CollectionItem>;\n const returned = new Set<string>();\n for (const item of items) {\n if (hasId(item)) {\n returned.add(item.id);\n upsert(work, item, rev, false);\n }\n }\n for (const id of requested) {\n if (!returned.has(id)) {\n remove(work, id, rev);\n }\n }\n return finish(base, work as Work<Item>);\n}\n","// What the live data's stores share (RFC 0003 sections 6, 7, 8.2 and 11.5):\n// the connection they subscribe over, the `QueryClient` their state lives\n// in, and the overlay store of optimistic mutations, plus how they read and\n// write that state and how they send a subscription event and read what\n// came back.\n//\n// State lives in the `QueryClient`, under the entity key `[\"qd\", service,\n// \"e\", id]` and the collection key `[\"qd\", service, \"c\", collection,\n// scope]`, so the hooks read it as they read any query, and app code and\n// devtools see it. The stores are its only writers. Entries are written\n// whole and without TanStack's structural sharing: an index can hold 50,000\n// rows, and the stores already keep every unchanged object. A hook observes\n// its entry with a query that never fetches, which also keeps TanStack from\n// collecting the entry while it is shown; an entry nobody shows any more is\n// collected after `gcTime`, as any query is.\n//\n// React-free.\n\nimport type { QueryClient, QueryKey } from \"@tanstack/react-query\";\nimport type { Revision } from \"../../protocol/envelope\";\nimport { QuickdrawError, fromWire } from \"../../protocol/errors\";\nimport { isRecord } from \"../../protocol/guards\";\nimport { DEFAULT_BACKOFF_MS, retryAfterOf } from \"../backoff\";\nimport type { QuickdrawConnection } from \"../connection\";\nimport { subscriptionLimits, type SubscriptionEvent, type SubscriptionLimits } from \"../lane\";\nimport type { OverlayStore } from \"../optimistic\";\n\n/** The connection and cache one set of live stores works with. */\nexport interface LiveHost {\n readonly connection: QuickdrawConnection;\n readonly queryClient: QueryClient;\n /** The overlays of `queryClient`: told every revision that arrives, and applied to what the hooks show. */\n readonly overlays: OverlayStore;\n}\n\n/** An entry of the live data, or `undefined` when none is cached. */\nexport function readEntry<T>(host: LiveHost, queryKey: QueryKey): T | undefined {\n return host.queryClient.getQueryData<T>(queryKey);\n}\n\n/** Writes an entry of the live data, telling the hooks that show it. */\nexport function writeEntry<T>(host: LiveHost, queryKey: QueryKey, value: T): void {\n const { queryClient } = host;\n const options = queryClient.defaultQueryOptions({ queryKey, structuralSharing: false });\n queryClient.getQueryCache().build(queryClient, options).setData(value, { manual: true });\n}\n\n/** What a hook observes its entry with: a query that is never fetched, never stale, never shared structurally. */\nexport interface EntryQueryOptions<T> {\n readonly queryKey: QueryKey;\n readonly queryFn: () => T | null;\n readonly enabled: false;\n readonly staleTime: number;\n readonly structuralSharing: false;\n}\n\n/** The options of the query a hook observes the entry under `queryKey` with. */\nexport function entryQuery<T>(queryKey: QueryKey): EntryQueryOptions<T> {\n return {\n queryKey,\n // Never called: the query is disabled, and only the stores write the entry.\n queryFn: () => null,\n enabled: false,\n staleTime: Number.POSITIVE_INFINITY,\n structuralSharing: false,\n };\n}\n\n/** The subscription limits the server announced on the current connection. */\nexport function limitsOf(host: LiveHost): SubscriptionLimits {\n return subscriptionLimits(host.connection.getState().hello);\n}\n\n/** How a subscription event ended. */\nexport type Outcome =\n /** The server answered `{ ok: true, ... }`. */\n | { readonly kind: \"ok\"; readonly reply: Readonly<Record<string, unknown>> }\n /** The server refused it, for a reason other than its lane being full. */\n | { readonly kind: \"refused\"; readonly error: QuickdrawError }\n /**\n * Send it again after `delayMs`: the server's lane was full (the\n * connection now backs off, and the lane waits that out), or no answer\n * came while the socket stayed up.\n */\n | { readonly kind: \"retry\"; readonly delayMs: number }\n /** The socket is down, or its hello has not arrived: send it again once it has. */\n | { readonly kind: \"offline\" };\n\nfunction outcomeOf(host: LiveHost, error: Error | null, reply: unknown): Outcome {\n if (error !== null) {\n return host.connection.socket.connected\n ? { kind: \"retry\", delayMs: DEFAULT_BACKOFF_MS }\n : { kind: \"offline\" };\n }\n if (isRecord(reply) && reply.ok === true) {\n return { kind: \"ok\", reply };\n }\n const failure = fromWire(isRecord(reply) ? reply.e : undefined);\n if (failure.code === \"RATE_LIMITED\") {\n host.connection.reportRateLimited(\"subscription\", retryAfterOf(failure));\n return { kind: \"retry\", delayMs: 0 };\n }\n return { kind: \"refused\", error: failure };\n}\n\n/**\n * Sends a subscription event through the connection's lane, and calls `done`\n * with how it ended. Before the server's hello on the current credentials\n * has named the user, nothing is sent and `done` is told `offline` at once:\n * the revisions a request carries could belong to the last user's data, and\n * the live data asks for everything it holds once the hello arrives\n * (`liveData.ts`).\n */\nexport function request(\n host: LiveHost,\n event: SubscriptionEvent,\n frame: object,\n done: (outcome: Outcome) => void,\n): void {\n if (host.connection.getState().hello === null) {\n done({ kind: \"offline\" });\n return;\n }\n host.connection.subscriptionLane.send(event, frame, (error, reply) => {\n done(outcomeOf(host, error, reply));\n });\n}\n\n/** True when `value` is a revision: a finite number. */\nexport function isRevision(value: unknown): value is Revision {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\n/** The error a malformed reply stands for. */\nexport function malformed(what: string): QuickdrawError {\n return new QuickdrawError(\"INTERNAL\", `The server's ${what} reply is malformed`);\n}\n\n/** `items` in runs of at most `size`. */\nexport function chunks<T>(items: readonly T[], size: number): T[][] {\n const runs: T[][] = [];\n for (let start = 0; start < items.length; start += size) {\n runs.push(items.slice(start, start + size));\n }\n return runs;\n}\n","// Reference-counted live subscriptions (RFC 0003 sections 6, 7 and 11.5): one\n// record per key (a row, a collection scope) however many hooks hold it.\n// Ported from 4.1's registry (4.1 `src/client/QuickdrawProvider.tsx:25-68`)\n// with two changes:\n//\n// - the last release closes the record a tick later, unless it is acquired\n// again first, so React's strict mode (which mounts effects twice) and a\n// remount keep the subscription instead of ending and starting it;\n// - nothing is cleared when the connection drops. Records outlive a\n// disconnect, and their store subscribes them again on the next connect,\n// from the revisions it holds; 4.1 cleared every record on a disconnect\n// (4.1 `src/client/QuickdrawProvider.tsx:326-330`) and loaded\n// everything again.\n//\n// React-free.\n\n/** A record held by one user of it: the record, whether this acquisition made it, and the release. */\nexport interface Holding<Entry> {\n readonly entry: Entry;\n readonly isNew: boolean;\n /** Ends this holding. Calling it again does nothing. */\n release(): void;\n}\n\n/** The records of one store, by key. */\nexport interface Registry<Entry> {\n /** Holds the record of `key`, made with `open` when there is none. */\n acquire(key: string, open: () => Entry): Holding<Entry>;\n /** The record of `key` while it is held; `undefined` once its last holding ended. */\n get(key: string): Entry | undefined;\n /** Every record held now. */\n held(): Entry[];\n}\n\ninterface Slot<Entry> {\n readonly entry: Entry;\n refs: number;\n closing: ReturnType<typeof setTimeout> | undefined;\n}\n\n/**\n * Creates a registry. `close` runs for a record a tick after its last\n * holding ended, unless it was acquired again meanwhile.\n */\nexport function createRegistry<Entry>(close: (entry: Entry, key: string) => void): Registry<Entry> {\n const slots = new Map<string, Slot<Entry>>();\n\n function release(key: string, slot: Slot<Entry>): void {\n slot.refs -= 1;\n if (slot.refs > 0) {\n return;\n }\n slot.closing = setTimeout(() => {\n slot.closing = undefined;\n if (slot.refs === 0 && slots.get(key) === slot) {\n slots.delete(key);\n close(slot.entry, key);\n }\n }, 0);\n }\n\n return Object.freeze({\n acquire(key: string, open: () => Entry): Holding<Entry> {\n let slot = slots.get(key);\n const isNew = slot === undefined;\n if (slot === undefined) {\n slot = { entry: open(), refs: 0, closing: undefined };\n slots.set(key, slot);\n }\n clearTimeout(slot.closing);\n slot.closing = undefined;\n slot.refs += 1;\n const held = slot;\n let released = false;\n return {\n entry: held.entry,\n isNew,\n release: () => {\n if (!released) {\n released = true;\n release(key, held);\n }\n },\n };\n },\n get(key: string): Entry | undefined {\n const slot = slots.get(key);\n return slot !== undefined && slot.refs > 0 ? slot.entry : undefined;\n },\n held: () => [...slots.values()].filter((slot) => slot.refs > 0).map((slot) => slot.entry),\n });\n}\n","// The streams one connection holds (RFC 0003 section 12.5): one feed per\n// stream and scope, counted by the hooks that hold it (`registry.ts`), with\n// `qd:stream [service, stream, scope, item]` frames routed to it by their\n// service, stream and scope (`null` for a global stream).\n//\n// - Holding a feed sends `qd:stream:sub` through the connection's lane\n// (`../lane.ts`), once the server's hello names the user (`host.ts`). The\n// answer's seed (the latest items the server kept, or what the service\n// computed for this subscriber) becomes the feed's\n// items, and every frame after it is appended, oldest first, keeping at\n// most the largest `max` any holder asked for.\n// - The server joins the feed's room and reads its seed in one tick, so an\n// item pushed after the seed can arrive before the answer: frames that\n// arrive while a subscribe is unanswered are kept and appended after the\n// seed.\n// - Every connect subscribes again, and the seed then replaces what is held:\n// the server forgot the socket's feeds, and nothing says which items were\n// missed meanwhile. Another user on the connection drops every feed's items\n// first. A refusal (`FORBIDDEN`, ...) empties the feed and stands until the\n// next connect; `RATE_LIMITED` waits out the backoff and asks again. A\n// `qd:revoked { kind: \"stream\" }` (access lowered while subscribed) does\n// the same as a `FORBIDDEN` refusal: the server took the socket out of the\n// feed's room.\n// - The last holder's release unsubscribes a tick later (`qd:stream:unsub`),\n// unless the feed is held again first.\n//\n// React-free: the live data (`liveData.ts`) makes one per connection and\n// `QueryClient`.\n\nimport { CLIENT_EVENTS } from \"../../contract/names\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport { isName } from \"../../protocol/guards\";\nimport { notifyEach } from \"../watch\";\nimport { request, type LiveHost } from \"./host\";\nimport { createRegistry, type Registry } from \"./registry\";\n\n/** The most items a feed keeps, whatever `max` asks for. */\nexport const STREAM_MAX_ITEMS = 10_000;\n\n/** How many items a feed keeps when its holders ask for no `max`. */\nexport const STREAM_DEFAULT_MAX = 500;\n\n/** A hook's `max` option as a whole number from 1 to `STREAM_MAX_ITEMS`; `STREAM_DEFAULT_MAX` when absent. */\nexport function streamMaxOf(max: number | undefined): number {\n if (typeof max !== \"number\" || !Number.isFinite(max)) {\n return STREAM_DEFAULT_MAX;\n }\n return Math.min(Math.max(1, Math.floor(max)), STREAM_MAX_ITEMS);\n}\n\n/** One stream of a service, as its member and the store see it. */\nexport interface StreamTarget {\n readonly service: string;\n readonly stream: string;\n /** True for a stream with one feed per scope value; false for a global stream. */\n readonly scoped: boolean;\n}\n\n/** What a feed shows: its items, oldest first, whether its seed is still to come, and why it failed. */\nexport interface StreamState<Item = unknown> {\n readonly items: readonly Item[];\n /** True until the first answer to the feed's subscribe. */\n readonly isLoading: boolean;\n /** Why the subscribe was refused: `FORBIDDEN` for a feed the user may not read. */\n readonly error: QuickdrawError | null;\n}\n\n/** The state of a feed nobody holds yet. */\nexport const PENDING_STREAM: StreamState = Object.freeze({\n items: Object.freeze([]),\n isLoading: true,\n error: null,\n});\n\n/** The streams of one connection. */\nexport interface StreamStore {\n /**\n * Holds a feed, keeping at least `max` items, for one user of it. Returns\n * the release; the feed is unsubscribed a tick after its last release.\n */\n hold(target: StreamTarget, scope: string | undefined, max: number): () => void;\n /** The feed's state: `PENDING_STREAM` while nobody holds it. The same object until it changes. */\n state(key: string): StreamState;\n /** Calls `listener` whenever the feed of `key` changes; returns the unsubscribe function. */\n listen(key: string, listener: () => void): () => void;\n /** A `qd:stream` frame arrived. */\n receive(frame: unknown): void;\n /**\n * The server ended the subscription to a feed (`qd:revoked`): its access\n * was lowered. The feed empties and shows `FORBIDDEN`, takes no further\n * item, and stands until the next connect subscribes again.\n */\n revoked(service: string, stream: string, scope: string | undefined): void;\n /** Subscribes every held feed again: the socket connected, or the user is known. */\n resume(): void;\n /** Another user acts on the connection now: drops every feed's items and subscribes again. */\n forget(): void;\n /** The connection closed: stops every retry until the next connect. */\n stop(): void;\n}\n\n/** The key of one feed: a stream's, or one scope's of a scoped stream. */\nexport function feedKey(service: string, stream: string, scope: string | undefined): string {\n return `${service}\\u0000${stream}\\u0000${scope === undefined ? \"\\u0001\" : `\\u0002${scope}`}`;\n}\n\ninterface Feed {\n readonly key: string;\n readonly frame: { readonly s: string; readonly stream: string; readonly scope?: string };\n state: StreamState;\n /** The `max` of each holding. */\n readonly maxes: Map<object, number>;\n /** Items that arrived while a subscribe was unanswered; `undefined` otherwise. */\n pending: unknown[] | undefined;\n /** True once a subscribe was sent: the server may hold the socket in the feed's room. */\n sent: boolean;\n /** Raised by every subscribe and by `forget`, so an older answer is ignored. */\n attempt: number;\n retry: ReturnType<typeof setTimeout> | undefined;\n}\n\nfunction capOf(feed: Feed): number {\n return Math.min(Math.max(STREAM_DEFAULT_MAX, ...feed.maxes.values()), STREAM_MAX_ITEMS);\n}\n\nfunction latest(items: readonly unknown[], cap: number): readonly unknown[] {\n return items.length > cap ? items.slice(items.length - cap) : items;\n}\n\n/**\n * A `qd:stream` frame read from the network: `[service, stream, scope,\n * item]`, `scope` null for a global stream; elements after `item` are a\n * later protocol's and ignored. `undefined` for anything else.\n */\nfunction readStreamFrame(value: unknown):\n | {\n readonly s: string;\n readonly stream: string;\n readonly scope: string | undefined;\n readonly item: unknown;\n }\n | undefined {\n if (!Array.isArray(value) || value.length < 4) {\n return undefined;\n }\n const [s, stream, scope, item] = value as readonly unknown[];\n if (!isName(s) || !isName(stream) || !(scope === null || isName(scope))) {\n return undefined;\n }\n return { s, stream, scope: scope ?? undefined, item };\n}\n\n/** What the feeds of one connection share. */\ninterface Feeds {\n readonly host: LiveHost;\n readonly registry: Registry<Feed>;\n /** Per feed key, the hooks to tell when it changes; kept apart from the feeds, which come and go. */\n readonly listeners: Map<string, Set<() => void>>;\n}\n\nfunction setState(feeds: Feeds, feed: Feed, state: StreamState): void {\n feed.state = state;\n notifyEach(feeds.listeners.get(feed.key) ?? [], (listener) => {\n listener();\n });\n}\n\n/** The subscribe was answered: the seed, then what arrived meanwhile. */\nfunction answered(feeds: Feeds, feed: Feed, reply: Readonly<Record<string, unknown>>): void {\n const seed = Array.isArray(reply.seed) ? (reply.seed as readonly unknown[]) : [];\n const items = latest([...seed, ...(feed.pending ?? [])], capOf(feed));\n feed.pending = undefined;\n setState(feeds, feed, Object.freeze({ items, isLoading: false, error: null }));\n}\n\n/** Sends `qd:stream:sub` for `feed` through the connection's lane, and settles the feed by its answer. */\nfunction subscribe(feeds: Feeds, feed: Feed): void {\n const { host } = feeds;\n clearTimeout(feed.retry);\n feed.retry = undefined;\n feed.attempt += 1;\n const { attempt } = feed;\n feed.pending = [];\n request(host, CLIENT_EVENTS.streamSub, feed.frame, (outcome) => {\n if (feed.attempt !== attempt || feeds.registry.get(feed.key) !== feed) {\n return;\n }\n if (outcome.kind === \"ok\") {\n answered(feeds, feed, outcome.reply);\n } else if (outcome.kind === \"refused\") {\n feed.pending = undefined;\n setState(feeds, feed, Object.freeze({ items: [], isLoading: false, error: outcome.error }));\n } else if (outcome.kind === \"retry\") {\n feed.retry = setTimeout(() => {\n subscribe(feeds, feed);\n }, outcome.delayMs);\n } else {\n // Offline: the next connect, or the hello, subscribes again.\n feed.pending = undefined;\n }\n });\n feed.sent ||= host.connection.getState().hello !== null && host.connection.socket.connected;\n}\n\n/** The feed's last holder let go a tick ago: unsubscribe, unless it was never sent. */\nfunction closeFeed(feeds: Feeds, feed: Feed): void {\n const { socket } = feeds.host.connection;\n clearTimeout(feed.retry);\n feed.attempt += 1;\n if (feed.sent && socket.connected) {\n socket.emit(CLIENT_EVENTS.streamUnsub, feed.frame);\n }\n setState(feeds, feed, PENDING_STREAM);\n}\n\nfunction openFeed(target: StreamTarget, scope: string | undefined, key: string): Feed {\n const frame =\n scope === undefined\n ? { s: target.service, stream: target.stream }\n : { s: target.service, stream: target.stream, scope };\n return {\n key,\n frame: Object.freeze(frame),\n state: PENDING_STREAM,\n maxes: new Map(),\n pending: undefined,\n sent: false,\n attempt: 0,\n retry: undefined,\n };\n}\n\nfunction hold(\n feeds: Feeds,\n target: StreamTarget,\n scope: string | undefined,\n max: number,\n): () => void {\n const key = feedKey(target.service, target.stream, scope);\n const holding = feeds.registry.acquire(key, () => openFeed(target, scope, key));\n const feed = holding.entry;\n const token = {};\n feed.maxes.set(token, max);\n if (holding.isNew) {\n subscribe(feeds, feed);\n }\n return () => {\n feed.maxes.delete(token);\n holding.release();\n };\n}\n\n/** A `qd:stream` frame: appended to its feed, or kept until the feed's seed arrives. */\nfunction receive(feeds: Feeds, value: unknown): void {\n const frame = readStreamFrame(value);\n if (frame === undefined) {\n return;\n }\n const feed = feeds.registry.get(feedKey(frame.s, frame.stream, frame.scope));\n if (feed === undefined) {\n return;\n }\n if (feed.pending !== undefined) {\n feed.pending = [...latest(feed.pending, capOf(feed) - 1), frame.item];\n return;\n }\n if (!feed.state.isLoading && feed.state.error === null) {\n const items = latest([...feed.state.items, frame.item], capOf(feed));\n setState(feeds, feed, Object.freeze({ ...feed.state, items }));\n }\n}\n\n/** The server revoked the feed's subscription: its socket left the room. */\nfunction revoked(feeds: Feeds, key: string): void {\n const feed = feeds.registry.get(key);\n if (feed === undefined) {\n return;\n }\n clearTimeout(feed.retry);\n feed.retry = undefined;\n feed.attempt += 1;\n feed.pending = undefined;\n feed.sent = false;\n const error = new QuickdrawError(\"FORBIDDEN\", \"Access to the stream was revoked\");\n setState(feeds, feed, Object.freeze({ items: [], isLoading: false, error }));\n}\n\nfunction listen(feeds: Feeds, key: string, listener: () => void): () => void {\n const set = feeds.listeners.get(key) ?? new Set<() => void>();\n feeds.listeners.set(key, set);\n set.add(listener);\n return () => {\n set.delete(listener);\n if (set.size === 0 && feeds.listeners.get(key) === set) {\n feeds.listeners.delete(key);\n }\n };\n}\n\n/** Creates the streams of `host`'s connection. */\nexport function createStreamStore(host: LiveHost): StreamStore {\n const feeds: Feeds = {\n host,\n registry: createRegistry<Feed>((feed) => {\n closeFeed(feeds, feed);\n }),\n listeners: new Map(),\n };\n return Object.freeze({\n hold: (target: StreamTarget, scope: string | undefined, max: number) =>\n hold(feeds, target, scope, max),\n state: (key: string) => feeds.registry.get(key)?.state ?? PENDING_STREAM,\n listen: (key: string, listener: () => void) => listen(feeds, key, listener),\n receive: (frame: unknown) => {\n receive(feeds, frame);\n },\n revoked: (service: string, stream: string, scope: string | undefined) => {\n revoked(feeds, feedKey(service, stream, scope));\n },\n resume(): void {\n for (const feed of feeds.registry.held()) {\n subscribe(feeds, feed);\n }\n },\n forget(): void {\n for (const feed of feeds.registry.held()) {\n setState(feeds, feed, PENDING_STREAM);\n subscribe(feeds, feed);\n }\n },\n stop(): void {\n for (const feed of feeds.registry.held()) {\n clearTimeout(feed.retry);\n feed.retry = undefined;\n feed.attempt += 1;\n feed.pending = undefined;\n }\n },\n });\n}\n","// The requests a collection scope's pipeline makes besides loading the scope\n// (RFC 0003 sections 7.3 and 7.4): the next page by cursor (`loadMore`, and\n// every page for `load: \"all\"`), and items by id (`qd:col:items`, at most\n// 200 ids each). Split from `collectionController.ts`.\n//\n// A page is dropped when a load of the scope started after it was asked for\n// (a reset, a refresh, a resume answered with a snapshot): that load brings\n// its own first page and cursor. Items are applied by revision whenever they\n// arrive (`collectionStore.ts`), so they need no such guard.\n//\n// React-free.\n\nimport type { CollectionDef } from \"../../contract/collections\";\nimport { CLIENT_EVENTS } from \"../../contract/names\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport type { CollectionQueryKey } from \"../keys\";\nimport type { CollectionShape } from \"./collectionIndex\";\nimport {\n applyItems,\n applyPage,\n type CollectionItem,\n type CollectionState,\n} from \"./collectionStore\";\nimport { chunks, isRevision, malformed, request, type LiveHost, type Outcome } from \"./host\";\n\n/** The most ids one `qd:col:items` may name (RFC 0003 section 7.4). */\nexport const MAX_ITEM_IDS = 200;\n\n/** What the cache holds for one collection scope, under `[\"qd\", service, \"c\", collection, scope]`. */\nexport interface CollectionEntry<Item extends CollectionItem = CollectionItem> {\n /** The scope's state; `null` before its first load, and once a refusal or revocation dropped it. */\n readonly state: CollectionState<Item> | null;\n /** Why the last request failed, or why the server ended the subscription. */\n readonly error: QuickdrawError | null;\n /** True while a page is being loaded. */\n readonly loadingMore: boolean;\n}\n\n/** One collection of one service, as a controller loads it. */\nexport interface CollectionTarget {\n /** The service's name on the wire. */\n readonly service: string;\n readonly collection: string;\n /** The contract's declaration: `order`, `index`, `views` and page sizes. */\n readonly def: CollectionDef;\n}\n\n/** What the page and item requests need of a scope's pipeline. */\nexport interface LoadSteps {\n readonly host: LiveHost;\n readonly target: CollectionTarget;\n readonly scope: string;\n readonly key: CollectionQueryKey;\n readonly shape: CollectionShape;\n /** The page size the first user asked for. */\n readonly limit: number | undefined;\n /** Raised by every load of the scope: a page asked for before it is dropped. */\n generation: number;\n disposed: boolean;\n /** The page in flight, shared by everyone who asks for the next page meanwhile. */\n page: Promise<boolean> | undefined;\n /** The waits before a page or items are asked for again, each with what ends it early. */\n readonly waits: Map<ReturnType<typeof setTimeout>, () => void>;\n /** The page size to ask for now. */\n pageLimit(): number | undefined;\n currentState(): CollectionState | null;\n write(change: Partial<CollectionEntry>): void;\n /** Resolves once the server has the socket in the scope's room; rejects when loading the scope is refused. */\n whenJoined(): Promise<void>;\n}\n\n/** True when `reply` has the shape of a page: `{ rev, items, total, cursor }`. */\nexport function isPage(reply: Readonly<Record<string, unknown>>): reply is Readonly<\n Record<string, unknown>\n> & {\n readonly rev: number;\n readonly items: readonly unknown[];\n readonly total: number;\n readonly cursor: string | null;\n} {\n return (\n isRevision(reply.rev) &&\n Array.isArray(reply.items) &&\n typeof reply.total === \"number\" &&\n (reply.cursor === null || typeof reply.cursor === \"string\")\n );\n}\n\n/**\n * Reports the revision items were read at to the overlay store, by a read\n * sent at `readAt`: a reply ends an optimistic layer only when it was asked\n * for after the call's reply.\n */\nexport function observeItems(\n p: LoadSteps,\n items: readonly unknown[],\n rev: number,\n readAt: number,\n): void {\n for (const item of items) {\n const id = (item as { readonly id?: unknown } | null)?.id;\n if (typeof id === \"string\") {\n p.host.overlays.observe(p.target.service, id, rev, readAt);\n }\n }\n}\n\n/** Runs `then` after `delayMs`, unless the waits are ended first (`endWaits`), which runs `ended`. */\nfunction wait(p: LoadSteps, delayMs: number, then: () => void, ended: () => void): void {\n const timer = setTimeout(() => {\n p.waits.delete(timer);\n then();\n }, delayMs);\n p.waits.set(timer, ended);\n}\n\n/** Ends every wait before a page or items are asked for again: the scope is disposed, or the connection closed. */\nexport function endWaits(p: LoadSteps): void {\n const waits = [...p.waits];\n p.waits.clear();\n for (const [timer, ended] of waits) {\n clearTimeout(timer);\n ended();\n }\n}\n\nfunction scopeFrame(p: LoadSteps): {\n readonly s: string;\n readonly c: string;\n readonly scope: string;\n} {\n return { s: p.target.service, c: p.target.collection, scope: p.scope };\n}\n\n/** Applies the answer to a page sent at `readAt`; resolves true to go on reading pages, false to stop. */\nfunction pageLoaded(\n p: LoadSteps,\n { generation, readAt }: { readonly generation: number; readonly readAt: number },\n outcome: Outcome,\n): boolean | Promise<boolean> {\n if (generation !== p.generation) {\n p.write({ loadingMore: false });\n return false;\n }\n if (outcome.kind === \"ok\") {\n const { reply } = outcome;\n if (!isPage(reply)) {\n p.write({ loadingMore: false, error: malformed(\"qd:col:sub\") });\n return false;\n }\n observeItems(p, reply.items, reply.rev, readAt);\n p.write({\n loadingMore: false,\n error: null,\n state: applyPage(p.currentState(), reply, p.shape),\n });\n return true;\n }\n p.write(\n outcome.kind === \"refused\"\n ? { loadingMore: false, error: outcome.error }\n : { loadingMore: false },\n );\n if (outcome.kind === \"retry\") {\n return new Promise((resolve) => {\n wait(\n p,\n outcome.delayMs,\n () => {\n resolve(true);\n },\n () => {\n resolve(false);\n },\n );\n });\n }\n return false;\n}\n\n/**\n * Loads the next page by cursor, unless there is none. Resolves `true` when\n * it was applied (or should be asked for again), `false` when there was no\n * page, it failed, or a load of the scope cancelled it.\n */\nexport function loadPage(p: LoadSteps): Promise<boolean> {\n if (p.page !== undefined) {\n return p.page;\n }\n const cursor = p.currentState()?.nextCursor ?? null;\n if (cursor === null || p.disposed) {\n return Promise.resolve(false);\n }\n const sent = { generation: p.generation, readAt: p.host.overlays.now() };\n const limit = p.pageLimit();\n const frame = { ...scopeFrame(p), cursor, ...(limit === undefined ? {} : { limit }) };\n p.write({ loadingMore: true });\n let answered = false;\n const page = new Promise<boolean>((resolve) => {\n request(p.host, CLIENT_EVENTS.collectionSub, frame, (outcome) => {\n answered = true;\n p.page = undefined;\n resolve(p.disposed ? false : pageLoaded(p, sent, outcome));\n });\n });\n // With the socket down the lane answers at once, before `page` is made.\n if (!answered) {\n p.page = page;\n }\n return page;\n}\n\n/** Sends one `qd:col:items` and applies its answer. */\nfunction requestItems(p: LoadSteps, ids: readonly string[]): Promise<void> {\n const readAt = p.host.overlays.now();\n return new Promise((resolve, reject) => {\n request(p.host, CLIENT_EVENTS.collectionItems, { ...scopeFrame(p), ids }, (outcome) => {\n const state = p.currentState();\n if (p.disposed || state === null) {\n resolve();\n } else if (outcome.kind === \"ok\") {\n const { rev, items } = outcome.reply;\n if (!isRevision(rev) || !Array.isArray(items)) {\n reject(malformed(\"qd:col:items\"));\n return;\n }\n observeItems(p, items, rev, readAt);\n p.write({ state: applyItems(state, items, rev, p.shape, ids) });\n resolve();\n } else if (outcome.kind === \"retry\") {\n wait(\n p,\n outcome.delayMs,\n () => {\n requestItems(p, ids).then(resolve, reject);\n },\n () => {\n if (p.disposed) {\n resolve();\n } else {\n reject(new QuickdrawError(\"INTERNAL\", \"The connection to the server closed\"));\n }\n },\n );\n } else {\n reject(\n outcome.kind === \"refused\"\n ? outcome.error\n : new QuickdrawError(\"INTERNAL\", \"The connection to the server is down\"),\n );\n }\n });\n });\n}\n\n/**\n * Loads the items of `ids` with `qd:col:items`, at most 200 per request,\n * once the scope is joined. Rejects with the error a request was refused\n * with.\n */\nexport async function loadItems(p: LoadSteps, ids: readonly string[]): Promise<void> {\n const wanted = [...new Set(ids.filter((id) => typeof id === \"string\" && id !== \"\"))];\n if (wanted.length === 0 || p.disposed) {\n return;\n }\n await p.whenJoined();\n if (p.disposed) {\n return;\n }\n await Promise.all(chunks(wanted, MAX_ITEM_IDS).map((run) => requestItems(p, run)));\n}\n","// One collection scope's live pipeline (RFC 0003 sections 7.2 to 7.4 and\n// 11.5), shared by every hook that shows the scope, so they drive one load\n// and one page at a time. Ported from 4.1's per-key controller\n// (4.1 `src/client/useCollection.ts:136-269`), with these changes:\n//\n// - Loading the scope again resumes it: `qd:col:sub` carries `since`, the\n// newest revision applied, and a `resumed` answer brings the deltas missed\n// meanwhile, applied in the order sent. Any other answer is a snapshot,\n// applied as one; items loaded before and not on its page are then loaded\n// again by id, since they may have changed. While `load: \"all\"` reads\n// every page again instead, the items of a scope without an index that\n// none of those pages refreshed are dropped once the last page is read:\n// they left the scope while it was not followed.\n// - Frames that arrive while a load is in flight are kept and applied on top\n// of its answer, each at its own revision (4.1 did this for snapshots,\n// `:191-218`).\n// - `reset` loads the scope again after a random 100 to 2,000 ms, so the\n// clients of a bulk write do not all ask at once (4.1 waited a fixed\n// 100 ms, `:17`).\n// - `loadMore` reads the next page by cursor; a load of the scope that\n// starts meanwhile cancels it (its answer is dropped). `load: \"all\"` reads\n// pages until the cursor is `null`.\n// - `loadItems(ids)` loads items by id with `qd:col:items`, at most 200 per\n// request, once the scope is joined; a patch for an item not held loads\n// it that way.\n// - `keep(items, rev)` takes items of the scope read elsewhere (a search's\n// results) into the state by revision, as if loaded by id, so the scope's\n// deltas keep them current.\n// - `qd:revoked` drops the state: access was revoked (`FORBIDDEN`) or the\n// scope's anchor row was deleted (`NOT_FOUND`).\n// - A scope whose load was refused stays refused until a connect, or until\n// the hub learns the user's access may have changed and refreshes it\n// (`collections.ts`; finding F8.4 of the quickdraw-chat migration).\n// - Each new state tells the overlay store what it means for the items\n// optimistic updates added to the scope (`settleAdditions`): one whose\n// server id the state holds, or a delta named, or that a load sent after\n// its call's reply answered without, ends.\n// - Requests go through the connection's lane. `RATE_LIMITED` waits out the\n// subscription backoff; a request without an answer is sent again after\n// 5 s while the socket is up; with the socket down, the next connect\n// resumes the scope.\n//\n// The state lives in the cache under `[\"qd\", service, \"c\", collection,\n// scope]` (`host.ts`). React-free.\n\nimport { DEFAULT_COLLECTION_MAX_LIMIT } from \"../../contract/collections\";\nimport { CLIENT_EVENTS } from \"../../contract/names\";\nimport type { CollectionFrame, Revision, RevokeReason } from \"../../protocol/envelope\";\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport { collectionKey, type CollectionQueryKey } from \"../keys\";\nimport { settleAdditions, type ScopeEvidence } from \"../optimistic\";\nimport {\n endWaits,\n isPage,\n loadItems,\n loadPage,\n observeItems,\n type CollectionEntry,\n type CollectionTarget,\n type LoadSteps,\n} from \"./collectionLoads\";\nimport {\n applyDeltas,\n applyFrames,\n applyKept,\n applySnapshot,\n pruneStale,\n staleIds,\n type CollectionState,\n type DeltaBatch,\n type DeltaResult,\n} from \"./collectionStore\";\nimport {\n isRevision,\n malformed,\n readEntry,\n request,\n writeEntry,\n type LiveHost,\n type Outcome,\n} from \"./host\";\n\nexport type { CollectionEntry, CollectionTarget };\n\n/** The shortest and longest wait before a scope is loaded again after `reset`. */\nexport const RESET_DELAY_MS = Object.freeze({ min: 100, max: 2000 });\n\n/** Why a scope is loaded again: the socket connected, or a check (tab visible again, idle timer). */\nexport type ResumeReason = \"connect\" | \"check\";\n\n/** One collection scope's pipeline. */\nexport interface CollectionController {\n readonly key: CollectionQueryKey;\n /** Loads the scope for the first time. */\n start(): void;\n /** A `qd:c` frame of the scope arrived. */\n receive(frame: CollectionFrame): void;\n /** The server ended the subscription (`qd:revoked`). */\n revoked(reason: RevokeReason): void;\n /** Loads the scope again from the revision held: on a connect, or as a check. */\n resume(reason: ResumeReason): void;\n /** Loads the scope again from scratch; resolves once that load settled. */\n refresh(): Promise<void>;\n /** The scope's value: the id of the row it is anchored on, for a scope that has one. */\n readonly scope: string;\n /** Loads the next page, if there is one. */\n loadMore(): Promise<void>;\n /** Loads the items of `ids` by id. Rejects with the server's error when it refuses. */\n loadItems(ids: readonly string[]): Promise<void>;\n /** Loads every page of the scope while the returned release is not called. */\n loadAll(): () => void;\n /**\n * Keeps items of the scope read outside it at revision `rev` (a search's\n * results) in its state, unless it holds something newer, so its deltas\n * keep them current; a member whose newer revision it holds without an\n * item is loaded by id instead. Returns false, keeping nothing, until the\n * scope's state is loaded.\n */\n keep(items: readonly unknown[], rev: Revision): boolean;\n /** Another user acts on the connection now: drops the state and loads the scope from scratch. */\n forget(): void;\n /** The connection closed: stops every timer and wait. The next connect loads the scope again. */\n stop(): void;\n /** Ends the subscription: `qd:col:unsub`, every request in flight is dropped, and no timer is left. */\n dispose(): void;\n}\n\n/** A controller's state. */\ninterface Pipeline extends LoadSteps {\n /** The generation of the load in flight; frames are kept meanwhile. */\n loading: number | undefined;\n buffered: DeltaBatch[];\n resetTimer: ReturnType<typeof setTimeout> | undefined;\n retryTimer: ReturnType<typeof setTimeout> | undefined;\n /** True while the server has the socket in the scope's room. */\n joined: boolean;\n /** Waiting for the next load to settle: `refresh`, and `loadItems` before the scope is joined. */\n readonly settled: Set<(error: QuickdrawError | null) => void>;\n /** How many users load every page. */\n allDemand: number;\n /** True while `load: \"all\"` is reading pages. */\n allLoop: boolean;\n /** Set when the reader is asked to read again while it reads. */\n allAgain: boolean;\n /** A snapshot replaced a loaded state while every page is read: prune what the pages do not bring back. */\n pruneAfterPages: boolean;\n /** Item ids patches found missing, loaded at the next microtask. */\n readonly missing: Set<string>;\n}\n\nfunction entryOf(p: Pipeline): CollectionEntry {\n return (\n readEntry<CollectionEntry>(p.host, p.key) ?? { state: null, error: null, loadingMore: false }\n );\n}\n\n/** The scope's state holds `id`: a loaded item, or a member of its index. */\nfunction holder(state: CollectionState): (id: string) => boolean {\n return (id) => state.revById.has(id) || state.byId.has(id);\n}\n\n/** Tells the overlay store what the scope's state `state` means for the items added to it. */\nfunction tellAdditions(\n p: Pipeline,\n state: CollectionState,\n evidence: Omit<ScopeEvidence, \"holds\"> = {},\n): void {\n settleAdditions(p.host.queryClient, p.target.service, p.target.collection, p.scope, {\n ...evidence,\n holds: holder(state),\n });\n}\n\nfunction write(p: Pipeline, change: Partial<CollectionEntry>): void {\n writeEntry(p.host, p.key, Object.freeze({ ...entryOf(p), ...change }));\n if (change.state !== undefined && change.state !== null) {\n tellAdditions(p, change.state);\n }\n}\n\n/** The ids the deltas of `batches` name. */\nfunction namedIn(batches: readonly DeltaBatch[]): Set<string> {\n const named = new Set<string>();\n for (const batch of batches) {\n for (const delta of batch.deltas as readonly unknown[]) {\n const record = delta as { readonly id?: unknown; readonly item?: { readonly id?: unknown } };\n const id = record.id ?? record.item?.id;\n if (typeof id === \"string\") {\n named.add(id);\n }\n }\n }\n return named;\n}\n\n/**\n * Reports the revision of every item a delta names to the overlay store:\n * from a frame, or (with `readAt`, when the load was sent) from a resume\n * reply, which ends an optimistic layer only when it was asked for after the\n * call's reply.\n */\nfunction observeDeltas(p: Pipeline, batch: DeltaBatch, readAt?: number): void {\n for (const delta of batch.deltas as readonly unknown[]) {\n const record = delta as { readonly id?: unknown; readonly item?: { readonly id?: unknown } };\n const id = record.id ?? record.item?.id;\n if (typeof id === \"string\") {\n p.host.overlays.observe(p.target.service, id, batch.rev, readAt);\n }\n }\n}\n\nfunction settle(p: Pipeline, error: QuickdrawError | null): void {\n const waiting = [...p.settled];\n p.settled.clear();\n for (const done of waiting) {\n done(error);\n }\n}\n\n/** Loads the ids patches found missing, at the next microtask, together. */\nfunction loadMissing(p: Pipeline, ids: readonly string[]): void {\n const first = p.missing.size === 0;\n for (const id of ids) {\n p.missing.add(id);\n }\n if (first && p.missing.size > 0) {\n queueMicrotask(() => {\n const wanted = [...p.missing];\n p.missing.clear();\n loadItems(p, wanted).catch(() => undefined);\n });\n }\n}\n\nfunction scheduleReset(p: Pipeline): void {\n if (p.resetTimer !== undefined || p.disposed) {\n return;\n }\n const { min, max } = RESET_DELAY_MS;\n p.resetTimer = setTimeout(\n () => {\n p.resetTimer = undefined;\n load(p, \"snapshot\");\n },\n min + Math.random() * (max - min),\n );\n}\n\n/** What a load leaves to do once its answer is applied. */\nfunction followUp(p: Pipeline, result: DeltaResult, reloaded: boolean): void {\n if (result.reset) {\n scheduleReset(p);\n }\n if (result.missing.length > 0) {\n loadMissing(p, result.missing);\n }\n if (reloaded && p.allDemand === 0) {\n // Items loaded before a snapshot and not on its page may have changed.\n loadMissing(p, staleIds(result.state));\n } else if (reloaded) {\n // The pages that follow bring back every member: those they do not are gone.\n p.pruneAfterPages = true;\n }\n void continueLoadAll(p);\n}\n\n/**\n * After `load: \"all\"` read pages following a snapshot: once the last page is\n * read, drops the items none of them refreshed; when nobody loads every page\n * any more before then, loads those items by id instead.\n */\nfunction pruneUnseen(p: Pipeline): void {\n const state = entryOf(p).state;\n if (!p.pruneAfterPages || p.disposed || state === null) {\n return;\n }\n if (state.nextCursor === null) {\n p.pruneAfterPages = false;\n const pruned = pruneStale(state);\n if (pruned !== state) {\n write(p, { state: pruned });\n }\n } else if (p.allDemand === 0) {\n p.pruneAfterPages = false;\n loadMissing(p, staleIds(state));\n }\n}\n\n/** Applies the answer of a load sent at `readAt`, then the frames kept while it was in flight. */\nfunction applyLoad(\n p: Pipeline,\n reply: Readonly<Record<string, unknown>>,\n kept: DeltaBatch[],\n readAt: number,\n): void {\n const base = entryOf(p).state;\n const options = { loadAll: p.allDemand > 0 };\n let applied: DeltaResult;\n if (reply.resumed === true && isRevision(reply.rev) && Array.isArray(reply.deltas)) {\n const batch: DeltaBatch = { rev: reply.rev, deltas: reply.deltas as DeltaBatch[\"deltas\"] };\n observeDeltas(p, batch, readAt);\n applied = applyDeltas(base, batch.deltas, batch.rev, p.shape, options);\n } else if (isPage(reply)) {\n observeItems(p, reply.items, reply.rev, readAt);\n applied = { state: applySnapshot(base, reply, p.shape), reset: false, missing: [] };\n } else {\n refused(p, malformed(\"qd:col:sub\"));\n return;\n }\n for (const frame of kept) {\n observeDeltas(p, frame);\n }\n const after = applyFrames(applied.state, kept, p.shape, options);\n write(p, { state: after.state, error: null });\n // A load sent after an addition's reply would hold its row if it were a member.\n const resumed = reply.resumed === true && Array.isArray(reply.deltas);\n const deltas = resumed ? [{ rev: 0, deltas: reply.deltas as DeltaBatch[\"deltas\"] }] : [];\n tellAdditions(p, after.state, { readAt, named: namedIn([...deltas, ...kept]) });\n p.joined = true;\n settle(p, null);\n const reloaded = reply.resumed !== true && base !== null;\n followUp(\n p,\n {\n state: after.state,\n reset: applied.reset || after.reset,\n missing: [...applied.missing, ...after.missing],\n },\n reloaded,\n );\n}\n\n/** A load was refused: access or the scope is gone (the state is dropped), or something else (it stays). */\nfunction refused(p: Pipeline, error: QuickdrawError): void {\n p.joined = false;\n const drops = [\"FORBIDDEN\", \"NOT_FOUND\", \"UNAUTHENTICATED\"].includes(error.code);\n write(p, drops ? { state: null, error, loadingMore: false } : { error });\n settle(p, error);\n}\n\n/** What came back for a load. */\ninterface Loaded {\n readonly generation: number;\n readonly kind: LoadKind;\n /** The overlay store's clock when the load was sent. */\n readonly readAt: number;\n}\n\nfunction loaded(p: Pipeline, { generation, kind, readAt }: Loaded, outcome: Outcome): void {\n if (generation !== p.generation || p.disposed) {\n return;\n }\n p.loading = undefined;\n const kept = p.buffered;\n p.buffered = [];\n if (outcome.kind === \"ok\") {\n applyLoad(p, outcome.reply, kept, readAt);\n } else if (outcome.kind === \"refused\") {\n refused(p, outcome.error);\n } else if (outcome.kind === \"retry\") {\n p.retryTimer = setTimeout(() => {\n p.retryTimer = undefined;\n load(p, kind);\n }, outcome.delayMs);\n } else {\n // The socket is down: the next connect resumes the scope.\n p.joined = false;\n }\n}\n\ntype LoadKind = \"snapshot\" | \"resume\";\n\n/** Loads the scope: from the revision held (`resume`), or from scratch. */\nfunction load(p: Pipeline, kind: LoadKind): void {\n clearTimeout(p.retryTimer);\n p.retryTimer = undefined;\n p.generation += 1;\n const { generation } = p;\n p.loading = generation;\n p.buffered = [];\n const state = kind === \"resume\" ? entryOf(p).state : null;\n const since = state !== null && state.rev > 0 ? state.rev : undefined;\n const limit = pageLimit(p);\n const frame = {\n s: p.target.service,\n c: p.target.collection,\n scope: p.scope,\n ...(since === undefined ? {} : { since }),\n ...(limit === undefined ? {} : { limit }),\n };\n const sent: Loaded = { generation, kind, readAt: p.host.overlays.now() };\n request(p.host, CLIENT_EVENTS.collectionSub, frame, (outcome) => {\n loaded(p, sent, outcome);\n });\n}\n\n/** The page size to ask for: the hook's, else the largest while every page is loaded, else the collection's. */\nfunction pageLimit(p: Pipeline): number | undefined {\n if (p.limit !== undefined) {\n return p.limit;\n }\n return p.allDemand > 0 ? (p.target.def.maxLimit ?? DEFAULT_COLLECTION_MAX_LIMIT) : undefined;\n}\n\n/** Reads pages while some user wants every page, the scope is joined and no load is in flight. */\nasync function readPages(p: Pipeline): Promise<void> {\n while (p.allDemand > 0 && !p.disposed && p.joined && p.loading === undefined) {\n if ((entryOf(p).state?.nextCursor ?? null) === null || !(await loadPage(p))) {\n return;\n }\n }\n}\n\n/**\n * Reads every page for `load: \"all\"`. One reader at a time; asked again\n * while it reads (a load of the scope landed, which cancels the page in\n * flight), it reads again from the new cursor once it stops.\n */\nasync function continueLoadAll(p: Pipeline): Promise<void> {\n if (p.allLoop) {\n p.allAgain = true;\n return;\n }\n p.allLoop = true;\n try {\n do {\n p.allAgain = false;\n await readPages(p);\n } while (p.allAgain);\n pruneUnseen(p);\n } finally {\n p.allLoop = false;\n }\n}\n\nfunction resume(p: Pipeline, reason: ResumeReason): void {\n if (p.disposed) {\n return;\n }\n if (reason === \"connect\") {\n // The server forgot the socket's rooms with the old connection.\n p.joined = false;\n } else if (!p.joined || p.loading !== undefined) {\n return;\n }\n if (p.resetTimer !== undefined) {\n return;\n }\n const entry = entryOf(p);\n load(p, entry.state !== null && entry.error === null ? \"resume\" : \"snapshot\");\n}\n\nfunction receive(p: Pipeline, frame: CollectionFrame): void {\n if (p.disposed) {\n return;\n }\n const batch: DeltaBatch = { rev: frame.rev, deltas: frame.deltas };\n if (p.loading !== undefined) {\n p.buffered.push(batch);\n return;\n }\n const base = entryOf(p).state;\n if (base === null) {\n // Joined, but the cached state is gone (the cache was cleared): load it again.\n load(p, \"snapshot\");\n return;\n }\n observeDeltas(p, batch);\n const result = applyDeltas(base, batch.deltas, batch.rev, p.shape, { loadAll: p.allDemand > 0 });\n if (result.state !== base) {\n write(p, { state: result.state });\n }\n tellAdditions(p, result.state, { named: namedIn([batch]) });\n followUp(p, result, false);\n}\n\nfunction revoked(p: Pipeline, reason: RevokeReason): void {\n p.generation += 1;\n p.loading = undefined;\n p.buffered = [];\n clearTimeout(p.resetTimer);\n clearTimeout(p.retryTimer);\n p.resetTimer = undefined;\n p.retryTimer = undefined;\n p.joined = false;\n const error =\n reason === \"anchor-deleted\"\n ? new QuickdrawError(\"NOT_FOUND\", \"The row this scope belongs to was deleted\")\n : new QuickdrawError(\"FORBIDDEN\", \"Access to the scope was revoked\");\n write(p, { state: null, error, loadingMore: false });\n settle(p, error);\n}\n\n/** Resolves once the scope is joined; rejects with the error its next load is refused with. */\nfunction whenJoined(p: Pipeline): Promise<void> {\n if (p.joined) {\n return Promise.resolve();\n }\n return new Promise((resolve, reject) => {\n p.settled.add((error) => {\n if (error === null) {\n resolve();\n } else {\n reject(error);\n }\n });\n });\n}\n\n/** Stops the reload a `reset` scheduled, a load's retry, and the waits of pages and items. */\nfunction stopTimers(p: Pipeline): void {\n clearTimeout(p.resetTimer);\n clearTimeout(p.retryTimer);\n p.resetTimer = undefined;\n p.retryTimer = undefined;\n endWaits(p);\n}\n\nfunction dispose(p: Pipeline): void {\n p.disposed = true;\n p.generation += 1;\n stopTimers(p);\n settle(p, null);\n const { socket } = p.host.connection;\n if (socket.connected) {\n socket.emit(CLIENT_EVENTS.collectionUnsub, {\n s: p.target.service,\n c: p.target.collection,\n scope: p.scope,\n });\n }\n}\n\n/** The state of a new scope's pipeline, before its first load. */\nfunction createPipeline(\n host: LiveHost,\n target: CollectionTarget,\n scope: string,\n limit: number | undefined,\n): Pipeline {\n const p: Pipeline = {\n host,\n target,\n scope,\n key: collectionKey(target.service, target.collection, scope),\n shape: { index: target.def.index, order: target.def.order },\n limit,\n generation: 0,\n loading: undefined,\n buffered: [],\n resetTimer: undefined,\n retryTimer: undefined,\n joined: false,\n settled: new Set(),\n allDemand: 0,\n allLoop: false,\n allAgain: false,\n pruneAfterPages: false,\n missing: new Set(),\n disposed: false,\n page: undefined,\n waits: new Map(),\n pageLimit: () => pageLimit(p),\n currentState: () => entryOf(p).state,\n write: (change) => {\n write(p, change);\n },\n whenJoined: () => whenJoined(p),\n };\n return p;\n}\n\n/** Keeps items read outside the scope at `rev` in its loaded state (`CollectionController.keep`). */\nfunction keep(p: Pipeline, items: readonly unknown[], rev: Revision): boolean {\n const state = entryOf(p).state;\n if (p.disposed || state === null) {\n return false;\n }\n const kept = applyKept(state, items, rev, p.shape, { loadAll: p.allDemand > 0 });\n if (kept.state !== state) {\n write(p, { state: kept.state });\n }\n if (kept.missing.length > 0) {\n loadMissing(p, kept.missing);\n }\n return true;\n}\n\n/** Loads every page of the scope while the returned release is not called. */\nfunction holdLoadAll(p: Pipeline): () => void {\n p.allDemand += 1;\n void continueLoadAll(p);\n let released = false;\n return () => {\n if (!released) {\n released = true;\n p.allDemand -= 1;\n }\n };\n}\n\n/** Creates the pipeline of one scope; `start` loads it. `limit` is the page size asked for. */\nexport function createCollectionController(\n host: LiveHost,\n target: CollectionTarget,\n scope: string,\n limit: number | undefined,\n): CollectionController {\n const p = createPipeline(host, target, scope, limit);\n return Object.freeze({\n key: p.key,\n scope,\n start: () => {\n load(p, \"snapshot\");\n },\n receive: (frame: CollectionFrame) => {\n receive(p, frame);\n },\n revoked: (reason: RevokeReason) => {\n revoked(p, reason);\n },\n resume: (reason: ResumeReason) => {\n resume(p, reason);\n },\n refresh: () =>\n new Promise<void>((resolve) => {\n p.settled.add(() => {\n resolve();\n });\n load(p, \"snapshot\");\n }),\n loadMore: async () => {\n await loadPage(p);\n },\n loadItems: (ids: readonly string[]) => loadItems(p, ids),\n loadAll: () => holdLoadAll(p),\n keep: (items: readonly unknown[], rev: Revision) => keep(p, items, rev),\n forget: () => {\n write(p, { state: null, error: null, loadingMore: false });\n load(p, \"snapshot\");\n },\n stop: () => {\n p.joined = false;\n stopTimers(p);\n },\n dispose: () => {\n dispose(p);\n },\n });\n}\n","// When live collections check their scopes without being told to (RFC 0003\n// section 11.5). A scope stays current from its frames, but a frame can be\n// missed: a tab a browser froze, a node of a cluster that interleaved\n// flushes. So, while any scope is held:\n//\n// - when the page becomes visible after being hidden for at least 30 s, every\n// scope resumes from the revision it holds (a resume the server serves\n// from its recent deltas costs one small answer);\n// - every 5 minutes, plus or minus 20% so clients spread out, the same\n// check runs: the idle convergence check.\n//\n// A resume after a reconnect is the store's own (`liveData.ts`). Nothing here\n// needs a DOM: without `document` (React Native, Node) only the timer runs.\n// Conveyor wrote both checks around 4.1's `useCollection` by hand.\n//\n// React-free.\n\n/** How long the page must have been hidden for its scopes to be checked when it shows again. */\nexport const VISIBLE_AFTER_MS = 30_000;\n\n/** How often held scopes are checked, before jitter. */\nexport const IDLE_CHECK_MS = 5 * 60 * 1000;\n\n/** The share of {@link IDLE_CHECK_MS} the check moves by, either way, at random. */\nexport const IDLE_CHECK_JITTER = 0.2;\n\n/** The checks of one set of live collections. */\nexport interface ResumeChecks {\n /** Starts them, unless they run. */\n start(): void;\n /** Stops them. */\n stop(): void;\n}\n\n/** The page's visibility, where there is a page. */\ninterface VisibilitySource {\n readonly visibilityState: string;\n addEventListener(type: \"visibilitychange\", listener: () => void): void;\n removeEventListener(type: \"visibilitychange\", listener: () => void): void;\n}\n\n/** The document, when the code runs in a browser; `undefined` elsewhere. */\nfunction pageDocument(): VisibilitySource | undefined {\n const found: unknown = typeof document === \"undefined\" ? undefined : document;\n const usable =\n typeof found === \"object\" &&\n found !== null &&\n typeof (found as Partial<VisibilitySource>).addEventListener === \"function\";\n return usable ? (found as VisibilitySource) : undefined;\n}\n\n/** The next idle check's delay: 5 minutes, give or take 20%. */\nfunction idleDelay(): number {\n return IDLE_CHECK_MS * (1 - IDLE_CHECK_JITTER + Math.random() * 2 * IDLE_CHECK_JITTER);\n}\n\n/** Creates the checks that call `check` when the page shows again after 30 s hidden, and every 5 minutes. */\nexport function createResumeChecks(check: () => void): ResumeChecks {\n let running = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let hiddenAt: number | undefined;\n let page: VisibilitySource | undefined;\n\n const arm = (): void => {\n timer = setTimeout(() => {\n arm();\n check();\n }, idleDelay());\n };\n\n const onVisibility = (): void => {\n if (page?.visibilityState === \"hidden\") {\n hiddenAt ??= Date.now();\n return;\n }\n const hiddenFor = hiddenAt === undefined ? 0 : Date.now() - hiddenAt;\n hiddenAt = undefined;\n if (hiddenFor >= VISIBLE_AFTER_MS) {\n check();\n }\n };\n\n return Object.freeze({\n start(): void {\n if (running) {\n return;\n }\n running = true;\n arm();\n page = pageDocument();\n hiddenAt = page?.visibilityState === \"hidden\" ? Date.now() : undefined;\n page?.addEventListener(\"visibilitychange\", onVisibility);\n },\n stop(): void {\n running = false;\n clearTimeout(timer);\n timer = undefined;\n page?.removeEventListener(\"visibilitychange\", onVisibility);\n page = undefined;\n },\n });\n}\n","// The live collections of one connection and `QueryClient` (RFC 0003\n// sections 7 and 11.5): one controller per scope (`collectionController.ts`),\n// counted by the hooks that hold it (`registry.ts`), with `qd:c` and\n// `qd:revoked` frames routed to it by `service`, `collection` and `scope`.\n// While any scope is held, the visibility and idle checks run (`resume.ts`),\n// and a mutation call whose outcome is unknown has each held scope it added\n// an item to loaded again once: that load says whether the server made it\n// (`../additions.ts`). After a lost connection, the reconnect's own resume\n// does. A scope whose load was refused is loaded once more when the user's\n// access may have changed: on new service grants (`qd:access`, from\n// `liveData.ts`), and when an `added` delta of another held scope names its\n// anchor row (finding F8.4); every connect loads it again too.\n//\n// React-free: the live data (`liveData.ts`) makes one per connection and\n// `QueryClient`.\n\nimport type { CollectionFrame, Revision, RevokeReason } from \"../../protocol/envelope\";\nimport { isName, isRecord } from \"../../protocol/guards\";\nimport {\n createCollectionController,\n type CollectionController,\n type CollectionTarget,\n type ResumeReason,\n} from \"./collectionController\";\nimport { storeOf } from \"../optimistic\";\nimport type { CollectionEntry } from \"./collectionLoads\";\nimport { isRevision, readEntry, type LiveHost } from \"./host\";\nimport { createRegistry } from \"./registry\";\nimport { createResumeChecks } from \"./resume\";\n\n/** How a hook holds a scope. */\nexport interface ScopeOptions {\n /** The page size to ask for; the first holder's applies to the scope. */\n readonly limit?: number | undefined;\n /** True to load every page of the scope while held. */\n readonly loadAll?: boolean;\n}\n\n/** One holding of a scope: its controller, and the release. */\nexport interface ScopeHolding {\n readonly controller: CollectionController;\n /** Ends this holding. The scope is unsubscribed a tick after its last holding ends. */\n release(): void;\n}\n\n/** The live collections of one connection and `QueryClient`. */\nexport interface CollectionHub {\n /** Holds one scope of a collection for one user of it. */\n subscribe(target: CollectionTarget, scope: string, options?: ScopeOptions): ScopeHolding;\n /** True while a user holds `scope` of `collection`: its deltas arrive and apply to its state. */\n holds(service: string, collection: string, scope: string): boolean;\n /**\n * Keeps items of a held scope that were read outside it at revision `rev`\n * (a search's results) in its state (`CollectionController.keep`). Returns\n * false, keeping nothing, when the scope is not held or not loaded yet.\n */\n keep(\n service: string,\n collection: string,\n scope: string,\n items: readonly unknown[],\n rev: Revision,\n ): boolean;\n /** A `qd:c` frame arrived. */\n receive(frame: unknown): void;\n /** The server ended the subscription to a scope (`qd:revoked`). */\n revoked(service: string, collection: string, scope: string, reason: RevokeReason): void;\n /** Loads every held scope again from the revision it holds. */\n resume(reason: ResumeReason): void;\n /**\n * The user's access may have changed (new service grants): loads each held\n * scope whose last load was refused once more.\n */\n reopen(): void;\n /** Another user acts on the connection now: drops every scope's state and loads it again. */\n forget(): void;\n /** The connection closed: stops every scope's timers and the checks, until the next connect. */\n stop(): void;\n /** How many scopes are held. */\n size(): number;\n}\n\nfunction scopeKey(service: string, collection: string, scope: string): string {\n return `${service}\\u0000${collection}\\u0000${scope}`;\n}\n\n/** True when `value` has the shape of a `qd:c` frame. Frames come over the network: checked, not trusted. */\nfunction isCollectionFrame(value: unknown): value is CollectionFrame {\n return (\n isRecord(value) &&\n isName(value.s) &&\n isName(value.c) &&\n isName(value.scope) &&\n isRevision(value.rev) &&\n Array.isArray(value.deltas)\n );\n}\n\n/** The refusals that drop a scope's state. */\nconst REFUSALS: ReadonlySet<string> = new Set([\"FORBIDDEN\", \"NOT_FOUND\", \"UNAUTHENTICATED\"]);\n\n/** Loads `controllers`' scopes whose last load was refused once more: the user's access may have changed. */\nfunction reopen(host: LiveHost, controllers: readonly CollectionController[]): void {\n for (const controller of controllers) {\n const entry = readEntry<CollectionEntry>(host, controller.key);\n if (entry?.state === null && entry.error !== null && REFUSALS.has(entry.error.code)) {\n void controller.refresh();\n }\n }\n}\n\n/**\n * The held scopes anchored on a row `frame` adds to another scope: an invite\n * adds the chat to the user's list of chats, and the chat's messages' scope\n * is that chat's id.\n */\nfunction anchoredOn(\n controllers: readonly CollectionController[],\n frame: CollectionFrame,\n): CollectionController[] {\n const added = new Set<string>();\n for (const delta of frame.deltas as readonly unknown[]) {\n const item = isRecord(delta) && delta.t === \"added\" && isRecord(delta.item) ? delta.item : null;\n if (item !== null && typeof item.id === \"string\") {\n added.add(item.id);\n }\n }\n return added.size === 0 ? [] : controllers.filter((controller) => added.has(controller.scope));\n}\n\n/** Asks for a load of each scope that holds additions of unknown outcome, once each, while started. */\nfunction createOutcomeChecks(\n host: LiveHost,\n ask: (service: string, collection: string, scope: string) => void,\n): { start(): void; stop(): void } {\n const store = storeOf(host.queryClient);\n let unsubscribe: (() => void) | undefined;\n let queued = false;\n const check = (): void => {\n queued = false;\n for (const { service, collection, scope } of store.unchecked()) {\n ask(service, collection, scope);\n }\n };\n return {\n start() {\n // A change of the store is told inside the mutation's failure: ask after it.\n unsubscribe ??= store.subscribe(() => {\n if (!queued) {\n queued = true;\n queueMicrotask(check);\n }\n });\n },\n stop() {\n unsubscribe?.();\n unsubscribe = undefined;\n },\n };\n}\n\n/** Creates the live collections of `host`. */\nexport function createCollectionHub(host: LiveHost): CollectionHub {\n const registry = createRegistry<CollectionController>((controller) => {\n controller.dispose();\n if (registry.held().length === 0) {\n checks.stop();\n outcomes.stop();\n }\n });\n const each = (act: (controller: CollectionController) => void): void => {\n registry.held().forEach(act);\n };\n const checks = createResumeChecks(() => {\n each((controller) => controller.resume(\"check\"));\n });\n const held = (service: string, collection: string, scope: string) =>\n registry.get(scopeKey(service, collection, scope));\n const outcomes = createOutcomeChecks(host, (service, collection, scope) => {\n held(service, collection, scope)?.resume(\"check\");\n });\n return Object.freeze({\n subscribe(target: CollectionTarget, scope: string, options: ScopeOptions = {}): ScopeHolding {\n const holding = registry.acquire(scopeKey(target.service, target.collection, scope), () =>\n createCollectionController(host, target, scope, options.limit),\n );\n const { entry: controller } = holding;\n const stopAll = options.loadAll === true ? controller.loadAll() : undefined;\n if (holding.isNew) {\n controller.start();\n }\n checks.start();\n outcomes.start();\n return {\n controller,\n release: () => {\n stopAll?.();\n holding.release();\n },\n };\n },\n holds: (service: string, collection: string, scope: string) =>\n held(service, collection, scope) !== undefined,\n keep: (\n service: string,\n collection: string,\n scope: string,\n items: readonly unknown[],\n rev: Revision,\n ) => held(service, collection, scope)?.keep(items, rev) ?? false,\n receive(frame: unknown): void {\n if (isCollectionFrame(frame)) {\n held(frame.s, frame.c, frame.scope)?.receive(frame);\n reopen(host, anchoredOn(registry.held(), frame));\n }\n },\n reopen: () => {\n reopen(host, registry.held());\n },\n revoked(service: string, collection: string, scope: string, reason: RevokeReason): void {\n held(service, collection, scope)?.revoked(reason);\n },\n resume(reason: ResumeReason): void {\n const scopes = registry.held();\n for (const controller of scopes) {\n controller.resume(reason);\n }\n if (reason === \"connect\" && scopes.length > 0) {\n checks.start();\n }\n },\n forget(): void {\n each((controller) => controller.forget());\n },\n stop(): void {\n each((controller) => controller.stop());\n checks.stop();\n },\n size: () => registry.held().length,\n });\n}\n","// The live frames of a connection, received once and routed by key (RFC 0003\n// sections 8.3 and 12.5): one listener each for `qd:e`, `qd:c`,\n// `qd:revoked`, `qd:stream`, `qd:event` and `qd:presence` on the socket\n// (and `qd:access`, after which the hub loads its refused scopes again),\n// however many rows, scopes, feeds and handlers are held. The entity store\n// routes an entity frame by `service` and `id`, the collection hub a\n// collection frame by `service`, `collection` and `scope`, the stream store a\n// stream frame (`[service, stream, scope, item]`) by its first three, the\n// event bus an event by\n// service and event, and the presence store a presence frame by room. 4.1\n// put one `socket.on` per subscribed entity, collection scope and room event\n// name on the socket (4.1 `src/client/useSubscription.ts:106-129`,\n// 4.1 `src/client/useCollection.ts:260`,\n// 4.1 `src/client/useRoomEvents.ts:79-85`).\n//\n// React-free.\n\nimport { SERVER_EVENTS } from \"../../contract/names\";\nimport { isName, isRecord } from \"../../protocol/guards\";\nimport type { QuickdrawSocket } from \"../connection\";\nimport type { CollectionHub } from \"./collections\";\nimport type { EntityStore } from \"./entityStore\";\nimport type { EventBus } from \"./events\";\nimport type { PresenceStore } from \"./presence\";\nimport type { StreamStore } from \"./streams\";\n\n/** Where frames go. */\nexport interface FrameRoutes {\n readonly entities: Pick<EntityStore, \"receive\" | \"revoked\">;\n readonly collections: Pick<CollectionHub, \"receive\" | \"revoked\" | \"reopen\">;\n readonly streams: Pick<StreamStore, \"receive\" | \"revoked\">;\n readonly events: Pick<EventBus, \"receive\">;\n readonly presence: Pick<PresenceStore, \"receive\">;\n}\n\n/** Routes a `qd:revoked` frame, checked: it came over the network. */\nfunction routeRevoked(routes: FrameRoutes, frame: unknown): void {\n if (!isRecord(frame) || !isName(frame.s)) {\n return;\n }\n const reason = frame.reason === \"anchor-deleted\" ? \"anchor-deleted\" : \"access\";\n if (frame.kind === \"entity\" && isName(frame.id)) {\n routes.entities.revoked(frame.s, frame.id);\n } else if (frame.kind === \"collection\" && isName(frame.c) && isName(frame.scope)) {\n routes.collections.revoked(frame.s, frame.c, frame.scope, reason);\n } else if (\n frame.kind === \"stream\" &&\n isName(frame.stream) &&\n (frame.scope === undefined || isName(frame.scope))\n ) {\n routes.streams.revoked(frame.s, frame.stream, frame.scope);\n }\n}\n\n/** Puts one listener per live frame type on `socket`, routing each frame to `routes`. */\nexport function listenToFrames(socket: QuickdrawSocket, routes: FrameRoutes): void {\n socket.on(SERVER_EVENTS.entity, (frame: unknown) => {\n routes.entities.receive(frame);\n });\n socket.on(SERVER_EVENTS.collection, (frame: unknown) => {\n routes.collections.receive(frame);\n });\n socket.on(SERVER_EVENTS.revoked, (frame: unknown) => {\n routeRevoked(routes, frame);\n });\n socket.on(SERVER_EVENTS.stream, (frame: unknown) => {\n routes.streams.receive(frame);\n });\n socket.on(SERVER_EVENTS.event, (frame: unknown) => {\n routes.events.receive(frame);\n });\n socket.on(SERVER_EVENTS.presence, (frame: unknown) => {\n routes.presence.receive(frame);\n });\n socket.on(SERVER_EVENTS.access, () => {\n // New grants: a scope refused before may open now (finding F8.4).\n routes.collections.reopen();\n });\n}\n","// How a live entity's cached entry changes (RFC 0003 section 6): by revision\n// per row, never by arrival order. 4.1 merged every update into the cached\n// row as it arrived and carried no revision at all\n// (4.1 `src/client/useSubscription.ts:106-126`).\n//\n// - `u` (the whole row) replaces the entry unless the entry is newer.\n// - `p` (changed fields) merges into the row unless the entry is newer;\n// with no row cached there is nothing to merge into, so the row is\n// requested instead of making a partial one.\n// - `r` removes the row and leaves a tombstone at its revision, which only a\n// `u` or a subscribe reply that is not older clears.\n// - A `qd:sub` reply may carry a revision older than a frame that arrived\n// right after the join, so an entry newer than the reply keeps its row.\n// \"Not modified\" keeps the row; with none cached any more, it is requested\n// again. A row the server does not have (`NOT_FOUND`) is removed;\n// `FORBIDDEN` drops the row and keeps the error.\n//\n// \"Newer\" compares revisions; two frames with the same revision apply in the\n// order they arrive. Pure functions, React-free.\n\nimport type { EntityFrame, EntityResult, Revision } from \"../../protocol/envelope\";\nimport { QuickdrawError, fromWire } from \"../../protocol/errors\";\nimport { isName, isRecord } from \"../../protocol/guards\";\nimport { isRevision } from \"./host\";\n\n/** What the cache holds for one live row, under `[\"qd\", service, \"e\", id]`. */\nexport interface EntityEntry<Row = unknown> {\n /** The row, as the subscriber's access tier sees it; `undefined` until loaded, once removed, or after an error. */\n readonly data: Row | undefined;\n /** The revision of `data`, or of the removal; `undefined` before anything arrived. */\n readonly rev: Revision | undefined;\n /** The server removed the row (or never had it): a tombstone at `rev`. */\n readonly removed: boolean;\n /** Why the subscription failed or ended: `FORBIDDEN` when access was refused or revoked. */\n readonly error: QuickdrawError | null;\n /**\n * When the request that read `data` was sent, on the overlay store's clock\n * (`optimistic.ts`); `undefined` for a row a frame brought.\n */\n readonly readAt: number | undefined;\n}\n\n/** The entry of a row nothing arrived for yet. */\nexport const EMPTY_ENTITY: EntityEntry<never> = Object.freeze({\n data: undefined,\n rev: undefined,\n removed: false,\n error: null,\n readAt: undefined,\n});\n\n/** What applying a frame or a reply did. */\nexport interface EntityChange<Row> {\n /** The new entry: the same object when nothing changed. */\n readonly entry: EntityEntry<Row>;\n /** True when the row must be requested: a patch or \"not modified\" found no row to apply to. */\n readonly request: boolean;\n}\n\nfunction unchanged<Row>(entry: EntityEntry<Row>): EntityChange<Row> {\n return { entry, request: false };\n}\n\nfunction changed<Row>(entry: EntityEntry<Row>): EntityChange<Row> {\n return { entry: Object.freeze(entry), request: false };\n}\n\n/** True when the entry holds something newer than revision `rev`. */\nfunction isNewer(entry: EntityEntry<unknown>, rev: Revision): boolean {\n return entry.rev !== undefined && entry.rev > rev;\n}\n\n/** The row with `fields` merged in, when both are objects. */\nfunction merged<Row>(row: Row, fields: unknown): Row {\n return isRecord(row) && isRecord(fields) ? ({ ...row, ...fields } as Row) : row;\n}\n\n/** Applies one `qd:e` frame to the entry of its row (`undefined` when none is cached). */\nexport function applyEntityFrame<Row>(\n held: EntityEntry<Row> | undefined,\n frame: EntityFrame<Row>,\n): EntityChange<Row> {\n const entry = held ?? (EMPTY_ENTITY as EntityEntry<Row>);\n if (isNewer(entry, frame.rev)) {\n return unchanged(entry);\n }\n if (frame.t === \"r\") {\n return changed<Row>({ ...EMPTY_ENTITY, rev: frame.rev, removed: true });\n }\n if (frame.t === \"u\") {\n return changed({ ...EMPTY_ENTITY, data: frame.d, rev: frame.rev });\n }\n if (entry.data === undefined) {\n return { entry, request: true };\n }\n return changed({ ...entry, data: merged(entry.data, frame.d), rev: frame.rev });\n}\n\n/**\n * Applies one id's answer to `qd:sub`, read by a request sent at `readAt`\n * on the overlay store's clock.\n */\nexport function applyEntityResult<Row>(\n held: EntityEntry<Row> | undefined,\n result: EntityResult<Row>,\n readAt: number | undefined,\n): EntityChange<Row> {\n const entry = held ?? (EMPTY_ENTITY as EntityEntry<Row>);\n if (result.ok === false) {\n const error = fromWire(result.e);\n if (error.code === \"NOT_FOUND\") {\n return changed<Row>({ ...EMPTY_ENTITY, rev: entry.rev, removed: true });\n }\n return changed<Row>({ ...EMPTY_ENTITY, rev: entry.rev, error });\n }\n if (result.nm === true) {\n if (entry.data === undefined) {\n return { entry, request: true };\n }\n return entry.error === null ? unchanged(entry) : changed({ ...entry, error: null });\n }\n // Only a row or a tombstone the entry holds can be newer than the reply.\n const holds = entry.data !== undefined || entry.removed;\n if (holds && isNewer(entry, result.rev)) {\n return entry.error === null ? unchanged(entry) : changed({ ...entry, error: null });\n }\n return changed({ ...EMPTY_ENTITY, data: result.d, rev: result.rev, readAt });\n}\n\n/** The entry after the server revoked the subscription (`qd:revoked`): no row, and `FORBIDDEN`. */\nexport function revokedEntity<Row>(held: EntityEntry<Row> | undefined): EntityEntry<Row> {\n return Object.freeze({\n ...EMPTY_ENTITY,\n rev: held?.rev,\n error: new QuickdrawError(\"FORBIDDEN\", \"Access to the row was revoked\"),\n });\n}\n\n/** The entry after a whole `qd:sub` batch failed: the row stays, and the error is shown. */\nexport function failedEntity<Row>(\n held: EntityEntry<Row> | undefined,\n error: QuickdrawError,\n): EntityEntry<Row> {\n return Object.freeze({ ...(held ?? (EMPTY_ENTITY as EntityEntry<Row>)), error });\n}\n\n/** The revision to send in `qd:sub` for the entry: the row's, or `null` when no row is held. */\nexport function heldRevision(entry: EntityEntry<unknown> | undefined): Revision | null {\n return entry?.data !== undefined && entry.rev !== undefined ? entry.rev : null;\n}\n\n/** True when `value` has the shape of a `qd:e` frame. Frames come over the network: checked, not trusted. */\nexport function isEntityFrame(value: unknown): value is EntityFrame {\n if (!isRecord(value) || !isName(value.s) || !isName(value.id) || !isRevision(value.rev)) {\n return false;\n }\n if (value.t === \"r\") {\n return true;\n }\n if (value.t === \"u\") {\n return Object.hasOwn(value, \"d\");\n }\n return value.t === \"p\" && isRecord(value.d);\n}\n\n/** One id's answer to `qd:sub`, checked: a malformed answer stands for `INTERNAL`. */\nexport function entityResultOf(value: unknown): EntityResult {\n if (isRecord(value) && value.ok === false) {\n return value as unknown as EntityResult;\n }\n const answered =\n isRecord(value) &&\n value.ok === true &&\n isRevision(value.rev) &&\n (value.nm === true || Object.hasOwn(value, \"d\"));\n return answered\n ? (value as unknown as EntityResult)\n : { ok: false, e: { code: \"INTERNAL\", message: \"The server's qd:sub reply is malformed\" } };\n}\n","// The live entities of one connection and `QueryClient` (RFC 0003 sections 6\n// and 11.5): rows subscribed by id, kept current by `qd:e` frames, cached\n// under `[\"qd\", service, \"e\", id]`.\n//\n// - Subscriptions are counted per row (`registry.ts`): the first holding of\n// a row asks for it, and a tick after the last ends, `qd:unsub` is sent.\n// - The rows asked for in one tick go out together: one `qd:sub` per\n// service per microtask, carrying the revision held for each id, at most\n// the server's `maxSubscribeIds` (500) ids each, through the connection's\n// lane. Ported from 4.1's batcher\n// (4.1 `src/client/QuickdrawProvider.tsx:84-163`), which sent no\n// revisions and one event per service.\n// - Replies and frames apply by revision (`entities.ts`), and each one's\n// revision is reported to the overlay store, which ends optimistic layers.\n// - A batch refused with `RATE_LIMITED` is sent again once the\n// subscription backoff ends; one that got no answer is sent again after\n// 5 s while the socket is up, and on the next connect otherwise. Any other\n// refusal is shown on each row and stands until the next connect. Those\n// waits end when the connection closes or no row is held any more.\n// - Every connect asks for every held row again with the revision held, so\n// an unchanged row is answered \"not modified\" and keeps its data.\n// - A different user on the connection (`forget`) drops every row and asks\n// for them again without revisions.\n//\n// React-free: the live data (`liveData.ts`) makes one per connection and\n// `QueryClient`, and routes frames to it (`demux.ts`).\n\nimport { CLIENT_EVENTS } from \"../../contract/names\";\nimport type { QuickdrawError } from \"../../protocol/errors\";\nimport { entityKey } from \"../keys\";\nimport {\n EMPTY_ENTITY,\n applyEntityFrame,\n applyEntityResult,\n entityResultOf,\n failedEntity,\n heldRevision,\n isEntityFrame,\n revokedEntity,\n type EntityChange,\n type EntityEntry,\n} from \"./entities\";\nimport {\n chunks,\n limitsOf,\n malformed,\n readEntry,\n request,\n writeEntry,\n type LiveHost,\n type Outcome,\n} from \"./host\";\nimport { createRegistry, type Registry } from \"./registry\";\n\n/** The live entities of one connection and `QueryClient`. */\nexport interface EntityStore {\n /** Holds rows `ids` of `service` for one user of them; returns the release. */\n subscribe(service: string, ids: readonly string[]): () => void;\n /** A `qd:e` frame arrived. */\n receive(frame: unknown): void;\n /** The server ended the subscription to a row (`qd:revoked`). */\n revoked(service: string, id: string): void;\n /** The socket connected: asks for every held row again, with the revisions held. */\n resume(): void;\n /** Another user acts on the connection now: drops every row and asks for each again. */\n forget(): void;\n /** The connection closed: stops every retry. The next connect asks for every held row again. */\n stop(): void;\n /** How many rows are held. */\n size(): number;\n}\n\n/** A held row. */\ninterface Row {\n readonly service: string;\n readonly id: string;\n}\n\ninterface State {\n readonly host: LiveHost;\n readonly registry: Registry<Row>;\n /** The ids to ask for at the next flush, by service. */\n readonly wanted: Map<string, Set<string>>;\n /** The ids to unsubscribe at the next flush, by service. */\n readonly leaving: Map<string, Set<string>>;\n scheduled: boolean;\n /** Raised by `forget`: answers to batches sent before are dropped. */\n epoch: number;\n /** The waits before batches are sent again. */\n readonly retries: Set<ReturnType<typeof setTimeout>>;\n}\n\n/** One `qd:sub` batch in flight. */\ninterface Batch {\n readonly service: string;\n readonly ids: readonly string[];\n readonly epoch: number;\n /** The overlay clock when it was sent. */\n readonly readAt: number;\n}\n\nfunction rowKey(service: string, id: string): string {\n return `${service}\\u0000${id}`;\n}\n\nfunction add(map: Map<string, Set<string>>, service: string, id: string): void {\n const ids = map.get(service) ?? new Set<string>();\n ids.add(id);\n map.set(service, ids);\n}\n\nfunction schedule(state: State): void {\n if (!state.scheduled) {\n state.scheduled = true;\n queueMicrotask(() => {\n flush(state);\n });\n }\n}\n\n/** Asks for row `id` at the next flush. */\nfunction want(state: State, service: string, id: string): void {\n state.leaving.get(service)?.delete(id);\n add(state.wanted, service, id);\n schedule(state);\n}\n\nfunction entryOf(state: State, service: string, id: string): EntityEntry {\n return readEntry<EntityEntry>(state.host, entityKey(service, id)) ?? EMPTY_ENTITY;\n}\n\n/** Writes a change of row `id`, and asks for the row when the change says so. */\nfunction commit(state: State, row: Row, before: EntityEntry, change: EntityChange<unknown>): void {\n if (change.entry !== before) {\n writeEntry(state.host, entityKey(row.service, row.id), change.entry);\n }\n if (change.request) {\n want(state, row.service, row.id);\n }\n}\n\nfunction heldRow(state: State, service: string, id: string): Row | undefined {\n return state.registry.get(rowKey(service, id));\n}\n\n/** Shows `error` on every held row of the batch; their rows stay. */\nfunction refuse(state: State, batch: Batch, error: QuickdrawError): void {\n for (const id of batch.ids) {\n const row = heldRow(state, batch.service, id);\n if (row !== undefined) {\n const before = entryOf(state, row.service, row.id);\n commit(state, row, before, { entry: failedEntity(before, error), request: false });\n }\n }\n}\n\n/** Asks for the batch's held rows again after `delayMs`. */\nfunction retry(state: State, batch: Batch, delayMs: number): void {\n const timer = setTimeout(() => {\n state.retries.delete(timer);\n if (batch.epoch !== state.epoch) {\n return;\n }\n for (const id of batch.ids) {\n if (heldRow(state, batch.service, id) !== undefined) {\n want(state, batch.service, id);\n }\n }\n }, delayMs);\n state.retries.add(timer);\n}\n\n/** Stops every wait before a batch is sent again. */\nfunction stopRetries(state: State): void {\n for (const timer of state.retries) {\n clearTimeout(timer);\n }\n state.retries.clear();\n}\n\n/** Applies each id's answer of a batch, in request order. */\nfunction apply(state: State, batch: Batch, results: readonly unknown[]): void {\n batch.ids.forEach((id, position) => {\n const row = heldRow(state, batch.service, id);\n if (row === undefined) {\n return;\n }\n const result = entityResultOf(results[position]);\n if (result.ok) {\n // A reply: it ends an optimistic layer only when the batch was sent after the call's reply.\n state.host.overlays.observe(row.service, row.id, result.rev, batch.readAt);\n }\n const before = entryOf(state, row.service, row.id);\n commit(state, row, before, applyEntityResult(before, result, batch.readAt));\n });\n}\n\nfunction answered(state: State, batch: Batch, outcome: Outcome): void {\n if (batch.epoch !== state.epoch || outcome.kind === \"offline\") {\n // Dropped by `forget`, or sent again with every held row on the next connect.\n return;\n }\n if (outcome.kind === \"retry\") {\n retry(state, batch, outcome.delayMs);\n } else if (outcome.kind === \"refused\") {\n refuse(state, batch, outcome.error);\n } else if (Array.isArray(outcome.reply.r)) {\n apply(state, batch, outcome.reply.r as readonly unknown[]);\n } else {\n refuse(state, batch, malformed(\"qd:sub\"));\n }\n}\n\n/** Sends one `qd:sub` for `ids` of `service`, with the revision held for each. */\nfunction send(state: State, service: string, ids: readonly string[]): void {\n const revs = ids.map((id) => heldRevision(entryOf(state, service, id)));\n const batch: Batch = { service, ids, epoch: state.epoch, readAt: state.host.overlays.now() };\n const frame = revs.some((rev) => rev !== null) ? { s: service, ids, revs } : { s: service, ids };\n request(state.host, CLIENT_EVENTS.sub, frame, (outcome) => {\n answered(state, batch, outcome);\n });\n}\n\nfunction flush(state: State): void {\n state.scheduled = false;\n const { socket } = state.host.connection;\n const { maxSubscribeIds } = limitsOf(state.host);\n for (const [service, ids] of state.leaving) {\n for (const run of socket.connected ? chunks([...ids], maxSubscribeIds) : []) {\n socket.emit(CLIENT_EVENTS.unsub, { s: service, ids: run });\n }\n }\n state.leaving.clear();\n const wanted = [...state.wanted];\n state.wanted.clear();\n if (!socket.connected) {\n // Every held row is asked for on the next connect.\n return;\n }\n for (const [service, ids] of wanted) {\n const held = [...ids].filter((id) => heldRow(state, service, id) !== undefined);\n for (const run of chunks(held, maxSubscribeIds)) {\n send(state, service, run);\n }\n }\n}\n\nfunction receive(state: State, frame: unknown): void {\n if (!isEntityFrame(frame)) {\n return;\n }\n const row = heldRow(state, frame.s, frame.id);\n if (row === undefined) {\n return;\n }\n state.host.overlays.observe(row.service, row.id, frame.rev);\n const before = entryOf(state, row.service, row.id);\n commit(state, row, before, applyEntityFrame(before, frame));\n}\n\n/** Creates the live entities of `host`. */\nexport function createEntityStore(host: LiveHost): EntityStore {\n const state: State = {\n host,\n registry: createRegistry<Row>((row) => {\n state.wanted.get(row.service)?.delete(row.id);\n add(state.leaving, row.service, row.id);\n schedule(state);\n if (state.registry.held().length === 0) {\n stopRetries(state);\n }\n }),\n wanted: new Map(),\n leaving: new Map(),\n scheduled: false,\n epoch: 0,\n retries: new Set(),\n };\n return Object.freeze({\n subscribe(service: string, ids: readonly string[]): () => void {\n const holdings = [...new Set(ids)].map((id) => {\n const holding = state.registry.acquire(rowKey(service, id), () => ({ service, id }));\n if (holding.isNew) {\n want(state, service, id);\n }\n return holding;\n });\n return () => {\n for (const holding of holdings) {\n holding.release();\n }\n };\n },\n receive: (frame: unknown) => {\n receive(state, frame);\n },\n revoked(service: string, id: string): void {\n const row = heldRow(state, service, id);\n if (row !== undefined) {\n const before = entryOf(state, service, id);\n commit(state, row, before, { entry: revokedEntity(before), request: false });\n }\n },\n resume(): void {\n for (const row of state.registry.held()) {\n want(state, row.service, row.id);\n }\n },\n forget(): void {\n state.epoch += 1;\n for (const row of state.registry.held()) {\n writeEntry(state.host, entityKey(row.service, row.id), EMPTY_ENTITY);\n want(state, row.service, row.id);\n }\n },\n stop(): void {\n stopRetries(state);\n },\n size: () => state.registry.held().length,\n });\n}\n","// Typed room events on the client (RFC 0003 sections 8.3 and 12.5): one\n// `qd:event` listener per connection routes each frame, `[service, event,\n// payload]`, to the handlers registered for that service and event\n// (`useEvent`). This replaces 4.1's `useRoomEvents`, which put a socket\n// listener per event name on the socket (4.1 `src/client/useRoomEvents.ts:46`).\n// An event nobody handles when it arrives is dropped; a handler that throws\n// neither stops the others nor the socket. A frame with elements after\n// `payload` is read as its first three: a later revision of the protocol\n// may append elements, never insert them (`protocol/envelope.ts`).\n//\n// React-free: the live data (`liveData.ts`) makes one per connection and\n// `QueryClient`.\n\nimport { isName } from \"../../protocol/guards\";\nimport { notifyEach } from \"../watch\";\n\n/** A handler of one event: called with each payload. */\nexport type EventHandler = (payload: unknown) => void;\n\n/** The event handlers of one connection. */\nexport interface EventBus {\n /** Calls `handler` with the payload of each `event` of `service` until the returned function runs. */\n on(service: string, event: string, handler: EventHandler): () => void;\n /** A `qd:event` frame arrived. */\n receive(frame: unknown): void;\n}\n\nfunction eventKey(service: string, event: string): string {\n return `${service}\\u0000${event}`;\n}\n\n/** Creates the event handlers of one connection. */\nexport function createEventBus(): EventBus {\n const handlers = new Map<string, Set<EventHandler>>();\n return Object.freeze({\n on(service: string, event: string, handler: EventHandler): () => void {\n const key = eventKey(service, event);\n const set = handlers.get(key) ?? new Set<EventHandler>();\n handlers.set(key, set);\n // One entry per registration, so the same function may be registered twice.\n const entry: EventHandler = (payload) => {\n handler(payload);\n };\n set.add(entry);\n return () => {\n set.delete(entry);\n if (set.size === 0 && handlers.get(key) === set) {\n handlers.delete(key);\n }\n };\n },\n receive(frame: unknown): void {\n if (!Array.isArray(frame) || frame.length < 3) {\n return;\n }\n const [service, event, payload] = frame as readonly unknown[];\n const set =\n isName(service) && isName(event) ? handlers.get(eventKey(service, event)) : undefined;\n if (set !== undefined) {\n notifyEach(set, (handler) => {\n handler(payload);\n });\n }\n },\n });\n}\n","// Who is in the app rooms this connection's socket is in (RFC 0003 section\n// 12.5), kept from the server's `qd:presence` frames: the list a socket gets\n// as a method joins it to a room (`ctx.rooms.join`), then each user who\n// joins or leaves. A room's users are a set of user ids: a repeated `joined`\n// changes nothing. Leaving a room (`users: []`) or losing the socket (a\n// disconnect leaves every room) forgets it; the app joins again, through its\n// method, once reconnected.\n//\n// React-free: the live data (`liveData.ts`) makes one per connection and\n// `QueryClient`, before the socket connects, so no frame is missed.\n\nimport { isName, isRecord } from \"../../protocol/guards\";\nimport { notifyEach } from \"../watch\";\n\n/** The users in each app room the socket is in. */\nexport interface PresenceStore {\n /** The ids of the users in `room`, as the server last said; empty for a room the socket is not in. The same array until it changes. */\n users(room: string): readonly string[];\n /** Calls `listener` whenever the users of `room` change; returns the unsubscribe function. */\n listen(room: string, listener: () => void): () => void;\n /** A `qd:presence` frame arrived. */\n receive(frame: unknown): void;\n /** The socket disconnected, and with it left every room. */\n clear(): void;\n}\n\nconst NOBODY: readonly string[] = Object.freeze([]);\n\nfunction userList(value: unknown): readonly string[] | undefined {\n return Array.isArray(value) && value.every(isName)\n ? Object.freeze([...new Set(value as readonly string[])])\n : undefined;\n}\n\n/** The room's users after `frame`, or `undefined` for a frame that changes nothing. */\nfunction next(\n current: readonly string[],\n frame: Readonly<Record<string, unknown>>,\n): readonly string[] | undefined {\n const users = userList(frame.users);\n if (users !== undefined) {\n return users;\n }\n if (isName(frame.joined) && !current.includes(frame.joined)) {\n return Object.freeze([...current, frame.joined]);\n }\n if (isName(frame.left) && current.includes(frame.left)) {\n return Object.freeze(current.filter((user) => user !== frame.left));\n }\n return undefined;\n}\n\n/** Creates the presence of one connection's socket. */\nexport function createPresenceStore(): PresenceStore {\n const rooms = new Map<string, readonly string[]>();\n const listeners = new Map<string, Set<() => void>>();\n const changed = (room: string): void => {\n notifyEach(listeners.get(room) ?? [], (listener) => {\n listener();\n });\n };\n return Object.freeze({\n users: (room: string) => rooms.get(room) ?? NOBODY,\n listen(room: string, listener: () => void): () => void {\n const set = listeners.get(room) ?? new Set<() => void>();\n listeners.set(room, set);\n set.add(listener);\n return () => {\n set.delete(listener);\n if (set.size === 0 && listeners.get(room) === set) {\n listeners.delete(room);\n }\n };\n },\n receive(frame: unknown): void {\n if (!isRecord(frame) || !isName(frame.room)) {\n return;\n }\n const users = next(rooms.get(frame.room) ?? NOBODY, frame);\n if (users === undefined) {\n return;\n }\n if (users.length === 0) {\n rooms.delete(frame.room);\n } else {\n rooms.set(frame.room, users);\n }\n changed(frame.room);\n },\n clear(): void {\n const held = [...rooms.keys()];\n rooms.clear();\n for (const room of held) {\n changed(room);\n }\n },\n });\n}\n","// The live data of one connection and one `QueryClient` (RFC 0003 sections 6,\n// 7 and 11.5): the entity store and the collection hub, the frame listeners\n// that feed them (`demux.ts`), and what the connection's life does to them.\n//\n// - Every connect resumes what is held: rows are asked for again with the\n// revisions held, and scopes resume from the revision they hold. State is\n// kept across a disconnect (4.1 cleared it,\n// 4.1 `src/client/QuickdrawProvider.tsx:326-330`).\n// - Nothing is asked for before the server's hello on the connection's\n// current credentials has named the user (`host.ts`): on new credentials\n// the resume waits for it. When it names another user than the cache was\n// loaded for, the cache was emptied (`../session.ts`), and the state held\n// is dropped and loaded again from scratch: rows and items are shown at\n// the subscriber's access tier, and a \"not modified\" answer would keep the\n// last user's.\n//\n// Made for a connection and `QueryClient` pair when the provider mounts\n// (before its socket connects, so no `qd:presence` frame is missed), or on\n// first use by code without React, and kept as long as the connection: it\n// holds nothing once its hooks are gone, and its listeners live on the\n// connection's socket. Closing the connection stops every timer it runs\n// (retries, reloads, checks); the next connect resumes what is still held.\n//\n// React-free.\n\nimport type { QueryClient } from \"@tanstack/react-query\";\nimport type { QuickdrawConnection } from \"../connection\";\nimport { overlaysOf } from \"../optimistic\";\nimport { sessionOf } from \"../session\";\nimport { createCollectionHub, type CollectionHub } from \"./collections\";\nimport { listenToFrames } from \"./demux\";\nimport { createEntityStore, type EntityStore } from \"./entityStore\";\nimport { createEventBus, type EventBus } from \"./events\";\nimport { createPresenceStore, type PresenceStore } from \"./presence\";\nimport { createStreamStore, type StreamStore } from \"./streams\";\n\n/**\n * The live data of one connection and `QueryClient`: entities, collections,\n * stream feeds, typed event handlers, and the presence of the app rooms its\n * socket is in.\n */\nexport interface LiveData {\n readonly entities: EntityStore;\n readonly collections: CollectionHub;\n readonly streams: StreamStore;\n readonly events: EventBus;\n readonly presence: PresenceStore;\n}\n\nconst lives = new WeakMap<QuickdrawConnection, WeakMap<QueryClient, LiveData>>();\n\n/** Resumes what is held on each connect, once the user is known; reloads it all for another user. */\nfunction followConnection(\n connection: QuickdrawConnection,\n queryClient: QueryClient,\n live: LiveData,\n): void {\n const resume = (): void => {\n live.entities.resume();\n live.collections.resume(\"connect\");\n live.streams.resume();\n };\n connection.socket.on(\"connect\", () => {\n // A hello held now is from the same credentials: the state was loaded for its user.\n if (connection.getState().hello !== null) {\n resume();\n }\n });\n connection.socket.on(\"disconnect\", () => {\n // The server took the socket out of every app room with it.\n live.presence.clear();\n });\n sessionOf(connection, queryClient).onHello(({ switched, first }) => {\n if (switched) {\n live.entities.forget();\n live.collections.forget();\n live.streams.forget();\n } else if (first) {\n resume();\n }\n });\n connection.subscribe(() => {\n // Closed by the app: no retry, reload or check waits for a socket that is gone.\n if (connection.getState().status === \"idle\") {\n live.entities.stop();\n live.collections.stop();\n live.streams.stop();\n }\n });\n}\n\nfunction createLiveData(connection: QuickdrawConnection, queryClient: QueryClient): LiveData {\n const host = { connection, queryClient, overlays: overlaysOf(queryClient) };\n const live: LiveData = Object.freeze({\n entities: createEntityStore(host),\n collections: createCollectionHub(host),\n streams: createStreamStore(host),\n events: createEventBus(),\n presence: createPresenceStore(),\n });\n listenToFrames(connection.socket, live);\n followConnection(connection, queryClient, live);\n return live;\n}\n\nfunction livesOf(connection: QuickdrawConnection): WeakMap<QueryClient, LiveData> {\n let byClient = lives.get(connection);\n if (byClient === undefined) {\n byClient = new WeakMap();\n lives.set(connection, byClient);\n }\n return byClient;\n}\n\n/**\n * The live data of `connection` and `queryClient`, made on first use. The\n * hooks use it; code without React can too, holding rows and scopes through\n * its `entities` and `collections`.\n */\nexport function liveDataOf(connection: QuickdrawConnection, queryClient: QueryClient): LiveData {\n const byClient = livesOf(connection);\n let live = byClient.get(queryClient);\n if (live === undefined) {\n live = createLiveData(connection, queryClient);\n byClient.set(queryClient, live);\n }\n return live;\n}\n\n/**\n * The live data of a connection that never opens (a mock client's,\n * `../../testing/mockSession.tsx`): its stores, with no frame listener and\n * nothing following the connection, and `presence` in place of the store\n * frames feed, so `usePresence` shows what a test sets. It becomes what\n * `liveDataOf(connection, queryClient)` returns, so call it before anything\n * asks for that.\n */\nexport function inertLiveData(\n connection: QuickdrawConnection,\n queryClient: QueryClient,\n presence: PresenceStore,\n): LiveData {\n const host = { connection, queryClient, overlays: overlaysOf(queryClient) };\n const live: LiveData = Object.freeze({\n entities: createEntityStore(host),\n collections: createCollectionHub(host),\n streams: createStreamStore(host),\n events: createEventBus(),\n presence,\n });\n livesOf(connection).set(queryClient, live);\n return live;\n}\n","\"use client\";\n\n// The React context `QuickdrawProvider` fills: its connection, the\n// `QueryClient` the hooks cache in, and that client's invalidation\n// coordinator. Hooks read them from here, so they follow the provider they\n// are rendered under.\n//\n// What the hooks read of the connection, they read through React's\n// `useSyncExternalStore`, whose third argument is the snapshot a server\n// renders and the browser hydrates. It is the connection's state on a\n// server, never its live state: the state every connection starts in (no\n// socket opens on a server), or for a mock client's connection its session\n// (`serverStateOf`). A boundary that hydrates after the provider connected\n// (a Suspense boundary, a lazy route) then hydrates what the server\n// rendered, and shows the live state in the render that follows; with the\n// live state as the server snapshot, a signed-in page failed to hydrate\n// (finding F3.5).\n\nimport type { QueryClient } from \"@tanstack/react-query\";\nimport { createContext, useContext, useSyncExternalStore } from \"react\";\nimport type { HelloFrame } from \"../protocol/version\";\nimport {\n INITIAL_CONNECTION_STATE,\n type ConnectionState,\n type QuickdrawConnection,\n} from \"./connection\";\nimport type { InvalidationCoordinator } from \"./coordinator\";\nimport { awaitingHello } from \"./session\";\n\n/** What `QuickdrawProvider` provides. */\nexport interface QuickdrawContextValue {\n readonly connection: QuickdrawConnection;\n readonly queryClient: QueryClient;\n /** The coordinator of `queryClient`, which every invalidation goes through. */\n readonly coordinator: InvalidationCoordinator;\n}\n\nexport const QuickdrawContext = createContext<QuickdrawContextValue | null>(null);\n\n/** The provider's context; throws when `user` (a hook) is rendered outside a provider. */\nexport function useQuickdrawContext(user: string): QuickdrawContextValue {\n const value = useContext(QuickdrawContext);\n if (value === null) {\n throw new Error(`${user} must be rendered inside a <QuickdrawProvider>`);\n }\n return value;\n}\n\n/** The state each connection is rendered with on a server, when it is not the starting state. */\nconst serverStates = new WeakMap<QuickdrawConnection, () => ConnectionState>();\n\n/**\n * Makes `state` what `connection` is rendered with on a server and hydrated\n * with: a mock client's connection (`../testing/mockSession.tsx`), whose\n * session is the same on both sides.\n */\nexport function renderOnServerAs(\n connection: QuickdrawConnection,\n state: () => ConnectionState,\n): void {\n serverStates.set(connection, state);\n}\n\n/**\n * The connection's state as a server renders it and the browser hydrates\n * it: the state every connection starts in, unless `renderOnServerAs` gave\n * another.\n */\nexport function serverStateOf(connection: QuickdrawConnection): ConnectionState {\n return serverStates.get(connection)?.() ?? INITIAL_CONNECTION_STATE;\n}\n\n/** The connection's state, re-rendering when it changes; on a server and while hydrating, `serverStateOf`. */\nexport function useConnectionState(connection: QuickdrawConnection): ConnectionState {\n const onServer = (): ConnectionState => serverStateOf(connection);\n return useSyncExternalStore(connection.subscribe, connection.getState, onServer);\n}\n\n/**\n * The hello queries run under, or `null` while they may not run. They run\n * while the connection is connected, or reconnecting with the same\n * credentials (their calls then wait in the send buffer, and nothing\n * refetches the moment it is back: the coordinator spreads the refetches\n * after a reconnect), queries are not backing off after `RATE_LIMITED`, and\n * the server's `qd:hello` on the current credentials has arrived: until it\n * names the user, a version a query sent could be answered \"not modified\"\n * for data the last user read (`session.ts`). Re-renders when that changes\n * and on each new hello, not on every change of the connection's state, so\n * a query hook shows the emptied cache after another user's hello.\n */\nexport function useQueriesHello(connection: QuickdrawConnection): HelloFrame | null {\n const readyIn = (state: ConnectionState): HelloFrame | null => {\n const open = state.status === \"connected\" || state.reconnecting;\n return open && state.backoff.query === undefined ? state.hello : null;\n };\n return useSyncExternalStore(\n connection.subscribe,\n () => readyIn(connection.getState()),\n () => readyIn(serverStateOf(connection)),\n );\n}\n\n/**\n * The connection's `qd:hello` on its current credentials, or `null` before\n * it arrives; re-renders on each new one. A hook that shows cached data\n * reads it so that it renders again after another user's hello emptied the\n * cache (`session.ts`): a query removed from the cache tells none of its\n * observers.\n */\nexport function useHello(connection: QuickdrawConnection): HelloFrame | null {\n return useSyncExternalStore(\n connection.subscribe,\n () => connection.getState().hello,\n () => serverStateOf(connection).hello,\n );\n}\n\n/**\n * True while new credentials await their hello on a cache loaded under the\n * last ones (`session.ts`): a hook then shows nothing of what is cached.\n * Re-renders when that changes.\n */\nexport function useAwaitingHello(\n connection: QuickdrawConnection,\n queryClient: QueryClient,\n): boolean {\n const awaiting = (): boolean => awaitingHello(connection, queryClient);\n // A server renders before any hello settled a cache: nothing awaits there.\n return useSyncExternalStore(connection.subscribe, awaiting, () => false);\n}\n","\"use client\";\n\n// The admin kit's client half (RFC 0003 sections 11 and 12.4). For a\n// contract with the kit, `qd.<service>.admin` holds the members of its admin\n// methods, `qd.task.admin.adminList.useQuery({ page })`, found by what the\n// contract half marked them with, never by their names; they are the same\n// members as `qd.<service>.<method>`, gathered for admin screens. A contract\n// without the kit has no `admin` member (the name is reserved, so no method\n// or collection takes it).\n//\n// `useAdminServices(qd)` lists the client's services an admin screen can\n// show: those whose contract has the kit's `adminMeta` and whose `adminMeta`\n// answers the user, with the display name it gives. One query per service,\n// cached under the same key as `qd.<service>.admin.adminMeta.useQuery()`, so\n// the screen that follows reads the cache. It asks only the services the\n// user's grants allow (the server's hello names them): `Admin`, what the\n// kit's methods require unless the service says otherwise (`requires`\n// changes it), so a user who administers nothing sends nothing (finding\n// F3.6). 4.1 apps listed the services the user's `serviceAccess` granted\n// `Admin` on, and fetched each `adminMeta` one at a time through untyped\n// hooks.\n\nimport { useMemo } from \"react\";\nimport { ACCESS_LEVELS, type AccessLevel } from \"../contract/access\";\nimport type { AnyContract } from \"../contract/defineContract\";\nimport { adminSpecOf, type AdminMethodName, type AdminServiceMeta } from \"../contract/kits/admin\";\n\n/** One service's `adminMeta` query, as `useAdminServices` runs it. */\nexport interface AdminMetaQuery {\n /** The service's key on the client. */\n readonly key: string;\n /** The service's name on the wire. */\n readonly serviceName: string;\n /** The `adminMeta` method's name in the contract. */\n readonly method: string;\n /** Its member: a mock client answers from the member's stub. */\n readonly member: { call(): Promise<unknown> };\n}\n\n/** What one `adminMeta` query shows. */\nexport interface AdminMetaState {\n readonly data: AdminServiceMeta | undefined;\n readonly error: unknown;\n}\n\n/**\n * Runs the `adminMeta` queries of a client's services, one TanStack query\n * each, as the client's own query hooks run them (a mock client from its\n * stubs). A hook: the client that built the namespaces gives it.\n */\nexport type UseAdminMeta = (\n queries: readonly AdminMetaQuery[],\n enabled: boolean,\n) => readonly AdminMetaState[];\n\n/** The user's service-wide grants, from the hello on the current credentials; `null` before it. A hook. */\nexport type UseAdminGrants = () => Readonly<Record<string, AccessLevel>> | null;\n\n/** How a client runs its admin namespaces' hooks: the real client's, or a mock's. */\nexport interface AdminHooks {\n readonly useMeta: UseAdminMeta;\n readonly useGrants: UseAdminGrants;\n}\n\n/** What `useAdminServices` and `adminOf` read of one service's `admin` namespace. */\nexport interface AdminNamespace extends AdminHooks {\n readonly serviceName: string;\n readonly meta: { readonly method: string; readonly member: AdminMetaQuery[\"member\"] } | undefined;\n /** The namespace's members by what the kit made them for, whatever the contract named them. */\n readonly byKind: Readonly<Partial<Record<AdminMethodName, object>>>;\n}\n\nconst NAMESPACES = new WeakMap<object, AdminNamespace>();\n\n/**\n * The `admin` member of a contract's service on a client: the members of\n * the admin kit's methods, by their names in the contract; nothing for a\n * contract without the kit. `methods` are the service's method members;\n * `hooks` are how the client runs `adminMeta` and reads the user's grants\n * for `useAdminServices`.\n */\nexport function adminNamespace(\n contract: AnyContract,\n methods: Readonly<Record<string, object>>,\n hooks: AdminHooks,\n): Readonly<Record<string, object>> {\n const kit = Object.entries(contract.methods).flatMap(([name, definition]) => {\n const spec = adminSpecOf(definition);\n const member = Object.hasOwn(methods, name) ? methods[name] : undefined;\n return spec === undefined || member === undefined ? [] : [{ name, kind: spec.method, member }];\n });\n if (kit.length === 0) {\n return {};\n }\n const namespace = Object.freeze(\n Object.fromEntries(kit.map(({ name, member }) => [name, member])),\n );\n const meta = kit.find(({ kind }) => kind === \"adminMeta\");\n NAMESPACES.set(namespace, {\n serviceName: contract.name,\n meta:\n meta === undefined\n ? undefined\n : { method: meta.name, member: meta.member as AdminMetaQuery[\"member\"] },\n byKind: Object.freeze(Object.fromEntries(kit.map(({ kind, member }) => [kind, member]))),\n useMeta: hooks.useMeta,\n useGrants: hooks.useGrants,\n });\n return { admin: namespace };\n}\n\n/** The registered namespace of `client[key].admin`, or `undefined`. */\nexport function adminNamespaceOf(client: object, key: string): AdminNamespace | undefined {\n const service: unknown = Object.hasOwn(client, key) ? Reflect.get(client, key) : undefined;\n const admin: unknown = isObject(service) ? Reflect.get(service, \"admin\") : undefined;\n return isObject(admin) ? NAMESPACES.get(admin) : undefined;\n}\n\n/** The keys of a client's services that have the admin kit: those with an `admin` member. */\nexport type AdminKeysOf<Client> = {\n [Key in keyof Client & string]: Client[Key] extends { readonly admin: object } ? Key : never;\n}[keyof Client & string];\n\n/** One service `useAdminServices` lists. */\nexport interface AdminServiceInfo<Key extends string = string> {\n /** The service's key on the client: `qd[key].admin` holds its admin methods. */\n readonly key: Key;\n /** The service's name on the wire: `\"taskService\"`. */\n readonly serviceName: string;\n /** The service's name for people, as its `adminMeta` gives it: `\"Tasks\"`. */\n readonly displayName: string;\n}\n\n/** Options of `useAdminServices`. */\nexport interface UseAdminServicesOptions {\n /** `false` asks nothing and lists nothing. Default `true`. */\n readonly enabled?: boolean;\n /**\n * The service-wide grant a service's `adminMeta` needs, as the server's\n * hello names the user's grants: a service whose grant is below it is\n * left out without a call. Default `\"Admin\"`, what the admin kit's\n * methods require unless `admin.handlers(contract, { access })` gives\n * another; `null` asks every service (an `adminMeta` open to others).\n */\n readonly requires?: AccessLevel | null;\n}\n\n/** What `useAdminServices` returns. */\nexport interface UseAdminServicesResult<Key extends string = string> {\n /** The services whose `adminMeta` answered the user, in the client's order. */\n readonly services: readonly AdminServiceInfo<Key>[];\n /** True while some service's `adminMeta` has not answered. */\n readonly isLoading: boolean;\n}\n\n/** A client's `adminMeta` queries, and how the client runs them. */\ninterface AdminQueries extends AdminHooks {\n readonly queries: readonly AdminMetaQuery[];\n}\n\nconst NOTHING: readonly AdminMetaState[] = Object.freeze([]);\n\nconst NO_GRANTS: Readonly<Record<string, AccessLevel>> = Object.freeze({});\n\nconst NO_QUERIES: AdminQueries = Object.freeze({\n queries: Object.freeze([]),\n useMeta: () => NOTHING,\n useGrants: () => NO_GRANTS,\n});\n\nconst QUERIES = new WeakMap<object, AdminQueries>();\n\nfunction isObject(value: unknown): value is object {\n return typeof value === \"object\" && value !== null;\n}\n\n/** The `adminMeta` queries of the client's services with the kit: worked out once per client. */\nfunction queriesOf(client: object): AdminQueries {\n const known = QUERIES.get(client);\n if (known !== undefined) {\n return known;\n }\n const found = Object.entries(client).flatMap(([key, service]) => {\n const admin: unknown = isObject(service) ? Reflect.get(service, \"admin\") : undefined;\n const namespace = isObject(admin) ? NAMESPACES.get(admin) : undefined;\n return namespace?.meta === undefined ? [] : [{ key, namespace, meta: namespace.meta }];\n });\n const [first] = found;\n const queries: AdminQueries =\n first === undefined\n ? NO_QUERIES\n : Object.freeze({\n queries: Object.freeze(\n found.map(({ key, namespace, meta }) =>\n Object.freeze({\n key,\n serviceName: namespace.serviceName,\n method: meta.method,\n member: meta.member,\n }),\n ),\n ),\n useMeta: first.namespace.useMeta,\n useGrants: first.namespace.useGrants,\n });\n QUERIES.set(client, queries);\n return queries;\n}\n\nconst NONE: UseAdminServicesResult = Object.freeze({\n services: Object.freeze([]),\n isLoading: false,\n});\n\nconst LOADING: UseAdminServicesResult = Object.freeze({\n services: Object.freeze([]),\n isLoading: true,\n});\n\n/** True when `level` is at least `required`; no grant meets nothing. */\nfunction meets(level: AccessLevel | undefined, required: AccessLevel): boolean {\n return level !== undefined && ACCESS_LEVELS.indexOf(level) >= ACCESS_LEVELS.indexOf(required);\n}\n\n/** The queries the user's grants allow: none before the hello, every one without a requirement. */\nfunction allowed(\n queries: readonly AdminMetaQuery[],\n grants: Readonly<Record<string, AccessLevel>> | null,\n requires: AccessLevel | null,\n): readonly AdminMetaQuery[] {\n if (grants === null) {\n return NOTHING_ASKED;\n }\n return requires === null\n ? queries\n : queries.filter((query) =>\n meets(\n Object.hasOwn(grants, query.serviceName) ? grants[query.serviceName] : undefined,\n requires,\n ),\n );\n}\n\nconst NOTHING_ASKED: readonly AdminMetaQuery[] = Object.freeze([]);\n\nfunction summarize(\n queries: readonly AdminMetaQuery[],\n states: readonly AdminMetaState[],\n enabled: boolean,\n known: boolean,\n): UseAdminServicesResult {\n if (!enabled) {\n return NONE;\n }\n if (!known) {\n return LOADING;\n }\n const services = queries.flatMap((query, index) => {\n const meta = states[index]?.data;\n return meta === undefined\n ? []\n : [{ key: query.key, serviceName: query.serviceName, displayName: meta.displayName }];\n });\n // A query without a state yet (the render that adds it) has not answered either.\n const isLoading = queries.some((_query, index) => {\n const state = states[index];\n return state === undefined || (state.data === undefined && state.error === null);\n });\n return { services, isLoading };\n}\n\n/**\n * The services of `client` an admin screen can show: those whose contract\n * has the admin kit's `adminMeta`, once their `adminMeta` answers the user\n * (a service whose `adminMeta` refuses the user, `FORBIDDEN` or\n * `UNAUTHENTICATED`, is left out), with the display name it gives. It asks\n * only the services the user's grants allow (`requires`, `Admin` by\n * default), once the server's hello named them, and asks a refused one\n * again only when the user's grant on it changes. Pass the same client on\n * every render.\n *\n * @example\n * const { services, isLoading } = useAdminServices(qd);\n * services.map(({ key, displayName }) => <Link href={`/admin/${key}`}>{displayName}</Link>);\n */\nexport function useAdminServices<Client extends object>(\n client: Client,\n options: UseAdminServicesOptions = {},\n): UseAdminServicesResult<AdminKeysOf<Client>> {\n if (!isObject(client)) {\n throw new TypeError(\"useAdminServices: pass the client createQuickdrawClient made\");\n }\n const enabled = options.enabled !== false;\n const requires = options.requires === undefined ? \"Admin\" : options.requires;\n const { queries, useMeta, useGrants } = queriesOf(client);\n const grants = useGrants();\n const asked = useMemo(() => allowed(queries, grants, requires), [queries, grants, requires]);\n const states = useMeta(asked, enabled && grants !== null);\n return useMemo(\n () => summarize(asked, states, enabled, grants !== null),\n [asked, states, enabled, grants],\n ) as UseAdminServicesResult<AdminKeysOf<Client>>;\n}\n","// What a client made by `createQuickdrawClient` uses outside React: the\n// connection and the invalidation coordinator of the `QuickdrawProvider` it\n// was given to (`bindConnection`), for its members' `call` and `prefetch`\n// and for `qd.invalidate`; and which of its queries watch a change topic.\n//\n// React-free.\n\nimport type { QueryKey, Updater } from \"@tanstack/react-query\";\nimport { QuickdrawError } from \"../protocol/errors\";\nimport type { QuickdrawConnection } from \"./connection\";\nimport type { InvalidateOptions, InvalidationCoordinator } from \"./coordinator\";\nimport { KEY_ROOT, methodKey, methodKeyPrefix } from \"./keys\";\nimport { loopGuardOf } from \"./loopGuard\";\nimport type { MethodTarget } from \"./members\";\n\n/** The provider's connection and coordinator, while one is mounted, and the client's watching queries. */\nexport interface Binding {\n connection: QuickdrawConnection | null;\n coordinator: InvalidationCoordinator | null;\n /** `service\\u0000method` of every query whose contract declares `watch`. */\n readonly watched: Set<string>;\n}\n\nconst bindings = new WeakMap<object, Binding>();\n\n/** The target of each query member, so `qd.invalidate` can take a member. */\nconst queryTargets = new WeakMap<object, MethodTarget>();\n\nfunction watchedKey(service: unknown, method: unknown): string {\n return `${String(service)}\\u0000${String(method)}`;\n}\n\nfunction needsProvider(user: string): QuickdrawError {\n return new QuickdrawError(\n \"INTERNAL\",\n `${user} needs a mounted <QuickdrawProvider> for this client`,\n );\n}\n\n/** A client's binding, unbound. */\nexport function createBinding(): Binding {\n return { connection: null, coordinator: null, watched: new Set() };\n}\n\n/** Records the client object a binding belongs to. */\nexport function attachBinding(client: object, binding: Binding): void {\n bindings.set(client, binding);\n}\n\n/** Records a query member of a client: `qd.invalidate` takes it, and its watch counts after a reconnect. */\nexport function registerQuery(binding: Binding, member: object, target: MethodTarget): void {\n queryTargets.set(member, target);\n if (target.watch !== undefined) {\n binding.watched.add(watchedKey(target.service, target.method));\n }\n}\n\n/** The bound connection, for `member` of `target`; `INTERNAL` while no provider is mounted. */\nexport function connectionOf(\n binding: Binding,\n target: MethodTarget,\n member: string,\n): QuickdrawConnection {\n if (binding.connection === null) {\n throw needsProvider(`${target.service}.${target.method}.${member}`);\n }\n return binding.connection;\n}\n\n/**\n * Invalidates what `queryKey` matches through `coordinator`, counting each\n * cached query as asked for the loop warning first (`loopGuard.ts`): an app\n * that asks on every render or effect run is the loop it names, and the\n * coordinator's window would otherwise hide it.\n */\nfunction invalidateAsked(\n coordinator: InvalidationCoordinator,\n queryKey: QueryKey,\n ...options: [InvalidateOptions?]\n): void {\n const { queryClient } = coordinator;\n const loops = loopGuardOf(queryClient);\n const exact = options[0]?.exact === true;\n for (const query of queryClient.getQueryCache().findAll({ queryKey, exact })) {\n loops.asked(query.queryKey, query.queryHash);\n }\n coordinator.invalidate(queryKey, ...options);\n}\n\n/**\n * `qd.invalidate(member, input?)` or `qd.invalidate(queryKey)`, through the\n * bound coordinator: a member with `input` invalidates that one result, a\n * member alone every result of the query, a key what it prefixes.\n */\nexport function invalidateWith(binding: Binding): (target: unknown, ...input: unknown[]) => void {\n return (target, ...input) => {\n const { coordinator } = binding;\n if (coordinator === null) {\n throw needsProvider(\"qd.invalidate\");\n }\n const query =\n typeof target === \"object\" && target !== null ? queryTargets.get(target) : undefined;\n if (query !== undefined) {\n if (input[0] === undefined) {\n invalidateAsked(coordinator, methodKeyPrefix(query.service, query.method));\n } else {\n invalidateAsked(coordinator, methodKey(query.service, query.method, input[0]), {\n exact: true,\n });\n }\n } else if (Array.isArray(target)) {\n invalidateAsked(coordinator, target as QueryKey);\n } else {\n throw new TypeError(\n \"qd.invalidate: pass a query member, such as qd.task.get, or a query key\",\n );\n }\n };\n}\n\n/**\n * `qd.<service>.<query>.setData(input, updater)`: writes the cached result\n * of `input` in the bound provider's cache, as an event that carries the\n * new state does (`updater` is the result, or a function of the cached\n * one). A read of that key in flight may have read before the event, so\n * the coordinator runs one more after it settles, never cancelling it.\n * Returns what the cache holds then. `INTERNAL` while no provider is mounted.\n */\nexport function setDataWith(\n binding: Binding,\n target: MethodTarget,\n): (input: unknown, updater: Updater<unknown, unknown>) => unknown {\n return (input, updater) => {\n const { coordinator } = binding;\n if (coordinator === null) {\n throw needsProvider(`${target.service}.${target.method}.setData`);\n }\n return setCoordinated(coordinator, methodKey(target.service, target.method, input), updater);\n };\n}\n\n/**\n * Writes `queryKey`'s cached result through `coordinator`'s cache: a read in\n * flight is followed by one more (it may predate the data written).\n */\nfunction setCoordinated(\n coordinator: InvalidationCoordinator,\n queryKey: QueryKey,\n updater: Updater<unknown, unknown>,\n): unknown {\n const { queryClient } = coordinator;\n const data = queryClient.setQueryData(queryKey, updater);\n if (queryClient.getQueryState(queryKey)?.fetchStatus === \"fetching\") {\n coordinator.invalidate(queryKey, { exact: true });\n }\n return data;\n}\n\n/**\n * Makes `connection`, and `coordinator` when given, the ones `client`'s\n * `call`, `prefetch` and `invalidate` use, until the returned function runs\n * (unless another connection was bound meanwhile). `QuickdrawProvider` binds\n * its own while it is mounted.\n */\nexport function bindConnection(\n client: object,\n connection: QuickdrawConnection,\n coordinator?: InvalidationCoordinator,\n): () => void {\n const binding = bindings.get(client);\n if (binding === undefined) {\n throw new TypeError(\"QuickdrawProvider: client must be made by createQuickdrawClient\");\n }\n binding.connection = connection;\n binding.coordinator = coordinator ?? null;\n return () => {\n if (binding.connection === connection) {\n binding.connection = null;\n binding.coordinator = null;\n }\n };\n}\n\n/**\n * Whether a cached query of `client` watches a change topic: its method's\n * contract declares `watch`. Such a query missed every `qd:changed` while\n * the connection was down, so it is refetched after a reconnect even when it\n * is fresh.\n */\nexport function isWatchedQuery(client: object, queryKey: QueryKey): boolean {\n const binding = bindings.get(client);\n const [root, service, kind, method] = queryKey;\n return (\n binding !== undefined &&\n root === KEY_ROOT &&\n kind === \"m\" &&\n binding.watched.has(watchedKey(service, method))\n );\n}\n","// What `useSearch` sends and shows (RFC 0003 section 12.2), free of React.\n//\n// A method the search kit made gets `useSearch` on its member (`members.ts`)\n// with what the contract says about it: how long a query must be, and the\n// collection its results are items of, when it keeps to a collection's\n// scopes and its item is that collection's item. A page the server marks\n// with `rev` holds exactly the items that collection's subscribers receive:\n// while a hook holds that scope (`useCollection`), the results are kept in\n// its state (`CollectionHub.keep`) and shown as that state holds them, so the\n// scope's deltas keep them current, and a result the state has removed since\n// is left out. Otherwise a result shows as the page has it. Overlays of\n// optimistic mutations are laid over every result, as over a collection's\n// items.\n\nimport type { AnyContract } from \"../../contract/defineContract\";\nimport { searchSpecOf, type SearchSpec } from \"../../contract/kits/search\";\nimport type { SearchPage } from \"../../contract/kits/searchSchemas\";\nimport type { MethodDef } from \"../../contract/methods\";\nimport type { MethodTarget } from \"../members\";\nimport type { OverlayView } from \"../optimistic\";\nimport type { CollectionState } from \"./collectionState\";\n\n/** A method the search kit made, as `useSearch` runs it. */\nexport interface SearchTarget extends MethodTarget {\n /** How long a query must be, once trimmed, to be sent. */\n readonly minLength: number;\n /** The collection whose items the results are, when they are: its scopes' states keep them live. */\n readonly collection: string | undefined;\n}\n\n/** What a call of a search passes: `{ q, scope?, limit? }`. */\nexport interface SearchCall {\n readonly q: string;\n readonly scope?: string;\n readonly limit?: number;\n}\n\n/** The projection a search's results are: `\"entity\"`, a projection's name, or `undefined` for none of the contract's. */\nfunction itemName(contract: AnyContract, spec: SearchSpec): string | undefined {\n if (spec.item === undefined || spec.item === contract.entity) {\n return \"entity\";\n }\n return Object.entries(contract.projections).find(([, schema]) => schema === spec.item)?.[0];\n}\n\n/** The collection a search's results are items of: its scope collection, when its item is the search's. */\nfunction liveCollection(contract: AnyContract, spec: SearchSpec): string | undefined {\n const { scope } = spec;\n if (scope === undefined || !Object.hasOwn(contract.collections, scope)) {\n return undefined;\n }\n return contract.collections[scope]?.item === itemName(contract, spec) ? scope : undefined;\n}\n\n/** The search `target` runs, when the search kit made its method; `undefined` for any other. */\nexport function searchTargetOf(\n target: MethodTarget,\n definition: MethodDef,\n contract: AnyContract,\n): SearchTarget | undefined {\n const spec = searchSpecOf(definition);\n if (spec === undefined || target.kind !== \"query\") {\n return undefined;\n }\n return Object.freeze({\n ...target,\n minLength: spec.minLength,\n collection: liveCollection(contract, spec),\n });\n}\n\n/** The input of a search for `q`, in `scope` (none when empty), of `limit` results (the server's default when absent). */\nexport function searchCall(q: string, scope: string, limit: number | undefined): SearchCall {\n return {\n q,\n ...(scope === \"\" ? {} : { scope }),\n ...(limit === undefined ? {} : { limit }),\n };\n}\n\nconst NO_RESULTS: readonly never[] = Object.freeze([]);\n\n/** `item` as `state` holds it: its item there, `undefined` once `state` removed it, else `item` itself. */\nfunction heldItem<Item>(item: Item, state: CollectionState | null): Item | undefined {\n const id = (item as { readonly id?: unknown }).id;\n if (state === null || typeof id !== \"string\") {\n return item;\n }\n const held = state.byId.get(id);\n if (held !== undefined) {\n return held as Item;\n }\n return state.removed.has(id) ? undefined : item;\n}\n\n/**\n * The results `page` shows, in its order: as `state` holds them when the\n * page's items are its collection's (`rev`) and `state` is the held scope's\n * state, else as the page has them; each with the overlays of `view`.\n * `collection` names the collection whose `patchItem` layers apply.\n */\nexport function shownResults<Item>(\n page: SearchPage<Item> | undefined,\n state: CollectionState | null,\n view: OverlayView,\n collection: string | undefined,\n): readonly Item[] {\n if (page === undefined) {\n return NO_RESULTS;\n }\n const through = page.rev === undefined ? null : state;\n const options = through === null ? {} : { collection };\n const shown: Item[] = [];\n for (const item of page.items) {\n const row = heldItem(item, through);\n const overlaid = row === undefined ? undefined : view.apply(row, options);\n if (overlaid !== undefined) {\n shown.push(overlaid);\n }\n }\n return shown;\n}\n","// What `useCollection` shows of a scope's state (RFC 0003 sections 7.5 and\n// 11.4): the members a view selects, the items loaded among them in order,\n// with the overlays of optimistic mutations laid over both.\n//\n// A view is a named pure predicate of the contract, `(row, who) => boolean`,\n// run on the client over index rows, with `who` the connection's user from\n// `qd:hello`. The whole index is present and live, so a view needs no\n// filter on the server, and an item enters or leaves a view as soon as a\n// delta changes its index fields. A scope too large for an index\n// (`indexTruncated`) has none: its view runs over the items loaded, which\n// carry the index fields too.\n//\n// Overlays apply to index rows as to items (only fields a row has are laid\n// over it), so an optimistic edit of an index field moves the member between\n// views at once, and an optimistic removal hides it. Items an optimistic\n// update added (`OptimisticCache.addItem`) show in their place by the\n// collection's `order`, through the view like any member, until the scope\n// holds their id: then the scope's own copy shows, never both.\n//\n// Pure functions, React-free.\n\nimport type { CollectionDef, OrderBy, Viewer, ViewPredicate } from \"../../contract/collections\";\nimport {\n hasOrderValues,\n indexRowFromItem,\n insertionPoint,\n type CollectionShape,\n type IndexRow,\n} from \"./collectionIndex\";\nimport { loadedIds, type CollectionItem, type CollectionState } from \"./collectionStore\";\n\n/** A view's predicate, as the client runs it. */\nexport type RowPredicate = (row: Readonly<Record<string, unknown>>, who: Viewer) => boolean;\n\n/** A view the collection does not declare selects nothing, rather than everything. */\nconst NO_MEMBERS: RowPredicate = () => false;\n\n/**\n * The predicate of view `name` of a collection: `undefined` for no view, and\n * one that selects nothing for a name the collection does not declare (the\n * client's types refuse such a name; a caller without them gets no rows).\n */\nexport function viewPredicate(\n def: Pick<CollectionDef, \"views\">,\n name: string | undefined,\n): RowPredicate | undefined {\n if (name === undefined) {\n return undefined;\n }\n if (def.views === undefined || !Object.hasOwn(def.views, name)) {\n return NO_MEMBERS;\n }\n return def.views[name] as ViewPredicate<unknown> as RowPredicate;\n}\n\n/** Lays the overlays over a row, or hides it: `undefined`. */\nexport type Overlay = <T>(row: T) => T | undefined;\n\n/** How {@link showCollection} filters and overlays. */\nexport interface ShowOptions {\n readonly view?: RowPredicate | undefined;\n readonly who: Viewer;\n readonly overlay: Overlay;\n /**\n * Items optimistic updates added to the scope, oldest first: each shows in\n * its place by `shape.order` (last when it, or an item shown without an\n * index, lacks an `order` field), unless the scope holds its id already.\n */\n readonly added?: readonly CollectionItem[];\n /** The collection's index fields and order, which place the added items. */\n readonly shape?: CollectionShape;\n}\n\n/** What a hook shows of a scope. */\nexport interface CollectionView<Item> {\n /** The items loaded among the members shown, in order. */\n readonly items: readonly Item[];\n /** The members shown, in order; `undefined` without an index. */\n readonly index: readonly IndexRow[] | undefined;\n /** `items` by id. */\n readonly byId: ReadonlyMap<string, Item>;\n}\n\n/** `rows` overlaid, without the hidden ones and, with a view, without those it does not select. */\nfunction shown<T>(rows: Iterable<T>, options: ShowOptions): T[] {\n const kept: T[] = [];\n for (const row of rows) {\n const overlaid = options.overlay(row);\n const selected =\n overlaid !== undefined &&\n (options.view === undefined ||\n options.view(overlaid as Readonly<Record<string, unknown>>, options.who));\n if (selected) {\n kept.push(overlaid);\n }\n }\n return kept;\n}\n\ntype Values = Readonly<Record<string, unknown>>;\n\n/** Puts `added` among `items` by `order`, when it and every item hold the order's fields; else last. */\nfunction placeAdded<T>(items: T[], added: readonly T[], order: OrderBy | undefined): void {\n const placeable =\n order !== undefined && items.every((item) => hasOrderValues(order, item as Values));\n for (const item of added) {\n const at =\n placeable && hasOrderValues(order, item as Values)\n ? insertionPoint(order, items as readonly Values[], item as Values)\n : items.length;\n items.splice(at, 0, item);\n }\n}\n\n/** The added items the state does not hold yet: once it holds one, its own copy shows. */\nfunction notHeld<Item extends CollectionItem>(\n state: CollectionState<Item>,\n added: readonly CollectionItem[] | undefined,\n): readonly Item[] {\n if (added === undefined || added.length === 0) {\n return [];\n }\n return added.filter((item) => !state.revById.has(item.id) && !state.byId.has(item.id)) as Item[];\n}\n\n/** What a hook shows of `state`: its members and items, overlaid and filtered by the view. */\nexport function showCollection<Item extends CollectionItem>(\n state: CollectionState<Item>,\n options: ShowOptions,\n): CollectionView<Item> {\n const added = notHeld(state, options.added);\n const order = options.shape?.order;\n if (state.index === null) {\n const items = shown(\n loadedIds(state).map((id) => state.byId.get(id) as Item),\n options,\n );\n placeAdded(items, shown(added, options), order);\n return { items, index: undefined, byId: new Map(items.map((item) => [item.id, item])) };\n }\n const index = shown(state.index, options);\n const provisional = new Map<string, Item>();\n for (const item of added) {\n const overlaid = options.overlay(item);\n const row =\n overlaid === undefined ? undefined : indexRowFromItem(options.shape ?? {}, overlaid);\n if (row !== undefined && (options.view === undefined || options.view(row, options.who))) {\n index.splice(order === undefined ? index.length : insertionPoint(order, index, row), 0, row);\n provisional.set(row.id, overlaid as Item);\n }\n }\n const items: Item[] = [];\n for (const row of index) {\n const item = state.byId.get(row.id);\n const overlaid = item === undefined ? provisional.get(row.id) : options.overlay(item);\n if (overlaid !== undefined) {\n items.push(overlaid);\n }\n }\n return { items, index, byId: new Map(items.map((item) => [item.id, item])) };\n}\n"],"mappings":"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","names":["wait","ends","changed","hold","wait","wait","send","patch","retain","next","next","shown","refused","keep","remove","isRow","next","shown","refused","createStore","keep","loaded","next","tombstones","next","keep","remove","request","answered","request","answered","request","settle","refused","request","receive","revoked","dispose","found","scopeKey","changed","answered","rowKey","entryOf","heldRow","answered","request","receive","changed","resume","found","shown","items","provisional"]}
|