@loro-dev/streams-crdt 0.4.1 → 0.6.0
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 +2 -1
- package/dist/flock.d.ts +2 -2
- package/dist/flock.js +59 -10
- package/dist/flock.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/loro.d.ts +2 -2
- package/dist/loro.js +26 -3
- package/dist/loro.js.map +1 -1
- package/dist/{stream-id-TsPj50Jj.js → stream-id-DBym_2Mj.js} +209 -113
- package/dist/stream-id-DBym_2Mj.js.map +1 -0
- package/dist/{stream-id-CSottEoY.d.ts → stream-id-Do4h2lOD.d.ts} +71 -11
- package/package.json +1 -1
- package/dist/stream-id-TsPj50Jj.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"stream-id-TsPj50Jj.js","names":["createTransportJoinState","disposeTransportJoinState"],"sources":["../src/checkpoint.ts","../src/reconnect.ts","../src/items.ts","../src/transport-internal.ts","../src/transport-client.ts","../src/transport-cursor.ts","../src/deque.ts","../src/transport-snapshot.ts","../src/transport-room.ts","../src/transport-runtime.ts","../src/stream-id.ts"],"sourcesContent":["import type { JsonObject } from \"./types\";\n\n/**\n * Persisted replay progress for one stream.\n *\n * This is metadata only — it does **not** contain any CRDT update data.\n * A persisted cursor is only valid when the caller also restores the matching\n * local CRDT state before the next `sync()` or `join()`.\n */\nexport interface RemoteCursor<TVersion extends JsonObject = JsonObject> {\n /** Identity of the stream this cursor belongs to. */\n readonly streamUrl: string;\n /** The offset to resume reading from on the next sync/join. */\n readonly nextOffset: string;\n /** The CRDT version that the server data up to `nextOffset` represents. */\n readonly serverLowerBoundVersion: TVersion;\n /** Timestamp (ms) when this cursor was last persisted. */\n readonly updatedAtMs: number;\n}\n\n/**\n * Storage for replay progress metadata.\n *\n * A persisted cursor is only valid when the caller also restores the matching\n * local CRDT state before the next `sync()` or `join()`. Storing only the\n * cursor can make transport resume from `nextOffset` against an empty local\n * document, which is not sufficient for delta-only catchup.\n */\nexport interface RemoteCursorStore<TVersion extends JsonObject = JsonObject> {\n load(streamUrl: string): Promise<RemoteCursor<TVersion> | null>;\n save(cursor: RemoteCursor<TVersion>): Promise<void>;\n delete?(streamUrl: string): Promise<void>;\n}\n\n/**\n * Why the transport is advancing the remote cursor.\n */\nexport type RemoteCursorSaveSource = \"local\" | \"remote\" | \"bootstrap\";\n\n/**\n * Context passed to durability hooks before a remote cursor is persisted.\n *\n * Hooks should make local durable state correspond to `cursor` before this\n * cursor is stored, so a future process can restore the same CRDT state before\n * transport resumes from `cursor.nextOffset`.\n */\nexport type BeforeRemoteCursorSaveContext<\n TVersion extends JsonObject = JsonObject,\n> = {\n readonly cursor: RemoteCursor<TVersion>;\n readonly source: RemoteCursorSaveSource;\n};\n\n/**\n * Hook invoked before the transport persists replay progress.\n *\n * This is the place to persist local CRDT payloads or snapshots. If that local\n * durability step does not happen here, the remote cursor should not advance.\n */\nexport type BeforeRemoteCursorSaveHook<TVersion extends JsonObject = JsonObject> =\n (context: BeforeRemoteCursorSaveContext<TVersion>) => void | Promise<void>;\n\ntype BeforeRemoteCursorSavePredicate<\n TVersion extends JsonObject = JsonObject,\n> = (context: BeforeRemoteCursorSaveContext<TVersion>) => boolean;\n\nexport function composeBeforeRemoteCursorSaveHooks<\n TVersion extends JsonObject = JsonObject,\n>(\n ...hooks: Array<BeforeRemoteCursorSaveHook<TVersion> | null | undefined>\n): BeforeRemoteCursorSaveHook<TVersion> | undefined {\n const active = hooks.filter(\n (hook): hook is BeforeRemoteCursorSaveHook<TVersion> => hook != null,\n );\n if (active.length === 0) {\n return undefined;\n }\n return async (context) => {\n for (const hook of active) {\n await hook(context);\n }\n };\n}\n\nfunction withRemoteCursorSavePredicate<\n TVersion extends JsonObject = JsonObject,\n>(\n predicate: BeforeRemoteCursorSavePredicate<TVersion>,\n hook: BeforeRemoteCursorSaveHook<TVersion>,\n): BeforeRemoteCursorSaveHook<TVersion> {\n return async (context) => {\n if (!predicate(context)) {\n return;\n }\n await hook(context);\n };\n}\n\nexport async function persistRemoteCursor<\n TVersion extends JsonObject = JsonObject,\n>(input: {\n remoteCursorStore: RemoteCursorStore<TVersion>;\n cursor: RemoteCursor<TVersion>;\n source: RemoteCursorSaveSource;\n beforeRemoteCursorSave?: BeforeRemoteCursorSaveHook<TVersion>;\n now?: () => number;\n}): Promise<RemoteCursor<TVersion>> {\n const next: RemoteCursor<TVersion> = {\n ...input.cursor,\n updatedAtMs: (input.now ?? Date.now)(),\n };\n if (input.beforeRemoteCursorSave != null) {\n await input.beforeRemoteCursorSave({\n cursor: next,\n source: input.source,\n });\n }\n await input.remoteCursorStore.save(next);\n return next;\n}\n\n/**\n * Construction options for `IndexedDbRemoteCursorStore`.\n */\nexport interface IndexedDbRemoteCursorStoreOptions {\n readonly dbName?: string;\n readonly storeName?: string;\n readonly dbVersion?: number;\n readonly indexedDb?: IDBFactory;\n}\n\nfunction key(streamUrl: string): string {\n return streamUrl;\n}\n\nfunction isJsonObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value != null && !Array.isArray(value);\n}\n\nfunction cloneJsonValue<T>(value: T): T {\n return structuredClone(value);\n}\n\nfunction cloneRemoteCursor<TVersion extends JsonObject>(\n cursor: RemoteCursor<TVersion>,\n): RemoteCursor<TVersion> {\n return {\n ...cursor,\n serverLowerBoundVersion: cloneJsonValue(cursor.serverLowerBoundVersion),\n };\n}\n\ntype StoredRemoteCursor = {\n readonly streamUrl: string;\n readonly nextOffset: string;\n readonly serverLowerBoundVersion: JsonObject;\n readonly updatedAtMs: number;\n};\n\nfunction fromStoredRemoteCursor<TVersion extends JsonObject>(\n record: StoredRemoteCursor,\n): RemoteCursor<TVersion> {\n if (!isJsonObject(record.serverLowerBoundVersion)) {\n throw new Error(\n \"invalid remote cursor record: serverLowerBoundVersion is not a JSON object\",\n );\n }\n return {\n streamUrl: record.streamUrl,\n nextOffset: record.nextOffset,\n serverLowerBoundVersion: cloneJsonValue(\n record.serverLowerBoundVersion as TVersion,\n ),\n updatedAtMs: record.updatedAtMs,\n };\n}\n\nfunction toStoredRemoteCursor<TVersion extends JsonObject>(\n cursor: RemoteCursor<TVersion>,\n): StoredRemoteCursor {\n return {\n streamUrl: cursor.streamUrl,\n nextOffset: cursor.nextOffset,\n serverLowerBoundVersion: cloneJsonValue(cursor.serverLowerBoundVersion),\n updatedAtMs: cursor.updatedAtMs,\n };\n}\n\n/**\n * In-memory cursor store useful for tests or ephemeral runtimes.\n */\nexport class InMemoryRemoteCursorStore<\n TVersion extends JsonObject = JsonObject,\n> implements RemoteCursorStore<TVersion> {\n private readonly data = new Map<string, RemoteCursor<TVersion>>();\n\n async load(\n streamUrl: string,\n ): Promise<RemoteCursor<TVersion> | null> {\n const value = this.data.get(key(streamUrl));\n return value == null ? null : cloneRemoteCursor(value);\n }\n\n async save(cursor: RemoteCursor<TVersion>): Promise<void> {\n this.data.set(key(cursor.streamUrl), cloneRemoteCursor(cursor));\n }\n\n async delete(streamUrl: string): Promise<void> {\n this.data.delete(key(streamUrl));\n }\n}\n\nconst DEFAULT_DB_NAME = \"streams-crdt\";\nconst DEFAULT_STORE_NAME = \"remote-cursors\";\nconst DEFAULT_DB_VERSION = 1;\n\n/**\n * IndexedDB-backed cursor store for browser clients that need replay progress persistence.\n *\n * This store only persists `RemoteCursor` metadata. It does not persist CRDT\n * payloads. Use it only when the application also persists the corresponding\n * local document state and restores that state before calling `sync()` or\n * `join()` after a reload.\n */\nexport class IndexedDbRemoteCursorStore<\n TVersion extends JsonObject = JsonObject,\n> implements RemoteCursorStore<TVersion> {\n private readonly dbName: string;\n private readonly storeName: string;\n private readonly dbVersion: number;\n private readonly indexedDb: IDBFactory | undefined;\n\n private db: IDBDatabase | null = null;\n private initPromise: Promise<void> | null = null;\n\n constructor(options?: IndexedDbRemoteCursorStoreOptions) {\n this.dbName = options?.dbName ?? DEFAULT_DB_NAME;\n this.storeName = options?.storeName ?? DEFAULT_STORE_NAME;\n this.dbVersion = options?.dbVersion ?? DEFAULT_DB_VERSION;\n this.indexedDb = options?.indexedDb ?? globalThis.indexedDB;\n }\n\n async load(\n streamUrl: string,\n ): Promise<RemoteCursor<TVersion> | null> {\n const db = await this.ensureDb();\n const record = await new Promise<StoredRemoteCursor | null>((resolve, reject) => {\n const tx = db.transaction([this.storeName], \"readonly\");\n const store = tx.objectStore(this.storeName);\n const request = store.get(key(streamUrl));\n request.onsuccess = () => {\n resolve((request.result as StoredRemoteCursor | undefined) ?? null);\n };\n request.onerror = () => {\n reject(request.error ?? new Error(\"indexeddb load failed\"));\n };\n });\n return record == null ? null : fromStoredRemoteCursor<TVersion>(record);\n }\n\n async save(cursor: RemoteCursor<TVersion>): Promise<void> {\n const db = await this.ensureDb();\n const record = toStoredRemoteCursor(cursor);\n await new Promise<void>((resolve, reject) => {\n const tx = db.transaction([this.storeName], \"readwrite\");\n const store = tx.objectStore(this.storeName);\n const request = store.put(record, key(cursor.streamUrl));\n tx.oncomplete = () => resolve();\n tx.onerror = () =>\n reject(tx.error ?? request.error ?? new Error(\"indexeddb save failed\"));\n tx.onabort = () =>\n reject(\n tx.error ??\n request.error ??\n new Error(\"indexeddb save transaction aborted\"),\n );\n request.onerror = () =>\n reject(request.error ?? new Error(\"indexeddb save failed\"));\n });\n }\n\n async delete(streamUrl: string): Promise<void> {\n const db = await this.ensureDb();\n await new Promise<void>((resolve, reject) => {\n const tx = db.transaction([this.storeName], \"readwrite\");\n const store = tx.objectStore(this.storeName);\n const request = store.delete(key(streamUrl));\n tx.oncomplete = () => resolve();\n tx.onerror = () =>\n reject(\n tx.error ?? request.error ?? new Error(\"indexeddb delete failed\"),\n );\n tx.onabort = () =>\n reject(\n tx.error ??\n request.error ??\n new Error(\"indexeddb delete transaction aborted\"),\n );\n request.onerror = () =>\n reject(request.error ?? new Error(\"indexeddb delete failed\"));\n });\n }\n\n private async ensureDb(): Promise<IDBDatabase> {\n if (this.db != null) {\n return this.db;\n }\n if (this.initPromise != null) {\n await this.initPromise;\n if (this.db == null) {\n throw new Error(\"indexeddb is not available\");\n }\n return this.db;\n }\n if (this.indexedDb == null) {\n throw new Error(\"indexeddb is not available in this environment\");\n }\n\n this.initPromise = new Promise<void>((resolve, reject) => {\n const request = this.indexedDb!.open(this.dbName, this.dbVersion);\n\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName);\n }\n };\n request.onerror = () =>\n reject(request.error ?? new Error(\"indexeddb open failed\"));\n request.onsuccess = () => {\n this.db = request.result;\n this.db.onversionchange = () => {\n this.db?.close();\n this.db = null;\n };\n resolve();\n };\n }).finally(() => {\n this.initPromise = null;\n });\n\n await this.initPromise;\n if (this.db == null) {\n throw new Error(\"indexeddb open succeeded without a database handle\");\n }\n return this.db;\n }\n}\n\n/**\n * Creates a cursor value suitable for seeding a `RemoteCursorStore`.\n */\nexport function createInitialRemoteCursor<\n TVersion extends JsonObject = JsonObject,\n>(input: {\n streamUrl: string;\n nextOffset: string;\n serverLowerBoundVersion: TVersion;\n}): RemoteCursor<TVersion> {\n return {\n streamUrl: input.streamUrl,\n nextOffset: input.nextOffset,\n serverLowerBoundVersion: cloneJsonValue(input.serverLowerBoundVersion),\n updatedAtMs: Date.now(),\n };\n}\n","/**\n * Retry and timeout settings used by `StreamsCrdt`.\n */\nexport interface ReconnectConfig {\n readonly delays: readonly number[];\n readonly jitterFraction: number;\n readonly maxAttempts: number;\n readonly connectTimeoutMs: number;\n readonly pollTimeoutMs: number;\n}\n\nexport const DEFAULT_RECONNECT_CONFIG: ReconnectConfig = {\n delays: [0, 500, 1000, 2000, 4000, 8000, 15000],\n jitterFraction: 0.2,\n maxAttempts: Infinity,\n connectTimeoutMs: 10000,\n pollTimeoutMs: 30000,\n};\n\n/**\n * Apply jitter of +/- fraction to a base delay.\n * E.g. applyJitter(1000, 0.2) returns a value in [800, 1200].\n */\nexport function applyJitter(baseMs: number, fraction: number): number {\n if (baseMs === 0) return 0;\n const jitter = baseMs * fraction * (2 * Math.random() - 1);\n return Math.max(0, Math.round(baseMs + jitter));\n}\n\n/**\n * Compute the retry delay for a given attempt number.\n * Uses the delays table from config, clamping at the last entry.\n */\nexport function computeRetryDelay(attempt: number, config: ReconnectConfig = DEFAULT_RECONNECT_CONFIG): number {\n const { delays, jitterFraction } = config;\n const index = Math.min(attempt, delays.length - 1);\n const base = delays[index];\n return applyJitter(base, jitterFraction);\n}\n","export const BINARY_CONTENT_TYPE = \"application/octet-stream\";\n\nexport function encodeItems(items: ReadonlyArray<Uint8Array>): Uint8Array {\n const total = items.reduce((sum, item) => sum + 4 + item.byteLength, 0);\n const out = new Uint8Array(total);\n const view = new DataView(out.buffer, out.byteOffset, out.byteLength);\n let cursor = 0;\n for (const item of items) {\n view.setUint32(cursor, item.byteLength, false);\n cursor += 4;\n out.set(item, cursor);\n cursor += item.byteLength;\n }\n return out;\n}\n\nexport function decodeItems(payload: Uint8Array): Uint8Array[] {\n const out: Uint8Array[] = [];\n const view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);\n let cursor = 0;\n while (cursor < payload.byteLength) {\n if (cursor + 4 > payload.byteLength) {\n throw new Error(\"corrupted items payload: truncated length prefix\");\n }\n const len = view.getUint32(cursor, false);\n cursor += 4;\n if (cursor + len > payload.byteLength) {\n throw new Error(\"corrupted items payload: truncated item payload\");\n }\n out.push(payload.slice(cursor, cursor + len));\n cursor += len;\n }\n return out;\n}\n","import type { RemoteCursor } from \"./checkpoint\";\nimport { Deque } from \"./deque\";\nimport { decodeItems } from \"./items\";\nimport type { TransportSnapshotState } from \"./transport-snapshot\";\nimport type {\n CrdtUpdateBatch,\n JsonObject,\n JsonValue,\n MaybePromise,\n SnapshotCodec,\n SnapshotUploadOptions,\n StreamsAuthContext,\n StreamsAuthProvider,\n TransportError,\n TransportRoomStatus,\n} from \"./types\";\n\nexport type FetchLike = (\n input: string,\n init?: RequestInit,\n) => Promise<Response>;\n\nexport type ReadResult = {\n readonly nextOffset: string;\n readonly upToDate: boolean;\n readonly updates: Uint8Array[];\n readonly streamCursor?: string;\n};\n\nexport type BootstrapResult = {\n readonly nextOffset: string;\n readonly upToDate: boolean;\n readonly snapshot: Uint8Array;\n readonly updates: Uint8Array[];\n readonly streamCursor?: string;\n};\n\nexport type SseControlData = {\n readonly nextOffset: string;\n readonly upToDate: boolean;\n readonly streamCursor?: string;\n};\n\nexport type SseControlHandlerResult = void | \"pause\" | \"stop\";\n\nexport type SseItemsContinueResult = {\n readonly kind: \"ok\";\n readonly latestOffset: string;\n readonly latestCursor?: string;\n readonly paused: boolean;\n};\n\nexport type SseItemsReadResult =\n | {\n readonly kind: \"ok\";\n readonly latestOffset: string;\n readonly latestCursor?: string;\n }\n | { readonly kind: \"gone\" }\n | { readonly kind: \"unsupported\" }\n | { readonly kind: \"not-found\" };\n\nexport type SseItemsSession = {\n continue: (\n onControl: (\n updates: Uint8Array[],\n nextOffset: string,\n upToDate: boolean,\n streamCursor?: string,\n ) => MaybePromise<SseControlHandlerResult>,\n ) => Promise<SseItemsContinueResult>;\n cancel: () => Promise<void>;\n};\n\nexport type SseItemsOpenResult =\n | { readonly kind: \"ok\"; readonly session: SseItemsSession }\n | { readonly kind: \"gone\" }\n | { readonly kind: \"unsupported\" }\n | { readonly kind: \"not-found\" };\n\nexport type AppendResult =\n | {\n readonly kind: \"ok\";\n readonly ackEpoch: number;\n readonly ackSeq: number;\n readonly nextOffset: string;\n }\n | {\n readonly kind: \"stale-epoch\";\n readonly serverEpoch: number;\n }\n | {\n readonly kind: \"seq-gap\";\n readonly expectedSeq: number;\n };\n\nexport type ProducerSession = {\n readonly producerId: string;\n readonly producerEpoch: number;\n readonly nextProducerSeq: number;\n};\n\nexport type LiveReadMode = \"sse\" | \"long-poll\";\n\nexport type CursorSyncResult<TVersion extends JsonObject> = {\n readonly cursor: RemoteCursor<TVersion>;\n readonly streamCursor?: string;\n};\n\nexport type LocalExportResult<TVersion extends JsonObject> = {\n readonly batch?: CrdtUpdateBatch<TVersion>;\n readonly nextRefVersion: TVersion;\n};\n\nexport type SnapshotUploadRuntimeConfig = {\n readonly canUpload: () => Promise<boolean>;\n readonly debounceMs: number;\n readonly minBytesSinceRemoteSnapshot: bigint;\n};\n\nexport type SnapshotCodecRuntimeConfig = {\n readonly compress: (snapshot: Uint8Array) => Promise<Uint8Array>;\n readonly decompress: (snapshot: Uint8Array) => Promise<Uint8Array>;\n};\n\nexport type JoinState<TVersion extends JsonObject> = {\n refCount: number;\n closed: boolean;\n status: \"connecting\" | TransportRoomStatus;\n readonly statusListeners: Set<\n (status: \"connecting\" | TransportRoomStatus) => void\n >;\n readonly pendingLocal: Deque<CrdtUpdateBatch<TVersion>>;\n flushingLocal: boolean;\n retryAttempt: number;\n retrySleepController: AbortController;\n requestController?: AbortController;\n unsubscribeLocal?: () => void;\n cursor: RemoteCursor<TVersion>;\n liveMode: LiveReadMode;\n streamCursor?: string;\n snapshot: TransportSnapshotState;\n started: Promise<void>;\n};\n\nexport type JoinSyncResult<TVersion extends JsonObject> =\n CursorSyncResult<TVersion> & {\n readonly liveMode: LiveReadMode;\n readonly localExportRefVersion: TVersion;\n };\n\nexport type LastError = {\n code:\n | \"network\"\n | \"timeout\"\n | \"auth_failed\"\n | \"gone_410\"\n | \"protocol\"\n | \"internal\";\n message: string;\n retriable: boolean;\n atMs: number;\n};\n\nexport function createProducerId(): string {\n if (typeof globalThis.crypto?.randomUUID === \"function\") {\n return globalThis.crypto.randomUUID();\n }\n return `${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;\n}\n\nexport class HttpError extends Error {\n readonly status: number;\n\n constructor(message: string, status: number) {\n super(message);\n this.status = status;\n }\n}\n\nexport class TimeoutError extends Error {\n readonly timeoutType: \"connect\" | \"poll\";\n readonly timeoutMs: number;\n\n constructor(timeoutType: \"connect\" | \"poll\", timeoutMs: number) {\n super(`TIMEOUT: ${timeoutType} request exceeded ${timeoutMs}ms`);\n this.timeoutType = timeoutType;\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport class ProtocolError extends Error {\n readonly status?: number;\n\n constructor(message: string, status?: number) {\n super(message);\n this.status = status;\n }\n}\n\nexport function getHeader(\n headers: Headers,\n lowerCaseName: string,\n titleCaseName: string,\n): string | null {\n return headers.get(lowerCaseName) ?? headers.get(titleCaseName);\n}\n\nfunction visibleHeaderNames(headers: Headers): string {\n const names: string[] = [];\n headers.forEach((_value, name) => {\n names.push(name);\n });\n if (names.length === 0) {\n return \"(none)\";\n }\n names.sort();\n return names.join(\", \");\n}\n\nexport function missingRequiredHeaderError(\n context: \"read\" | \"bootstrap\" | \"append\",\n requiredHeader: string,\n headers: Headers,\n): ProtocolError {\n return new ProtocolError(\n `${context} response missing ${requiredHeader}. ` +\n `If this is cross-origin, expose it via Access-Control-Expose-Headers (${requiredHeader.toLowerCase()}). ` +\n `Visible headers: ${visibleHeaderNames(headers)}`,\n );\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value != null;\n}\n\nexport function parseHeaderU64(value: string | null): number | null {\n if (value == null) {\n return null;\n }\n const parsed = Number.parseInt(value, 10);\n if (!Number.isFinite(parsed) || parsed < 0) {\n return null;\n }\n return parsed;\n}\n\nfunction decodeBase64Bytes(encoded: string): Uint8Array {\n // specs/ds-protocol.md allows servers to split base64 payloads across\n // multiple SSE data lines, and clients must remove the inserted CR/LF\n // characters before decoding.\n const normalized = encoded.replace(/[\\r\\n]/g, \"\");\n if (typeof Buffer !== \"undefined\") {\n return new Uint8Array(Buffer.from(normalized, \"base64\"));\n }\n if (typeof atob === \"function\") {\n const binary = atob(normalized);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) {\n out[i] = binary.charCodeAt(i);\n }\n return out;\n }\n throw new Error(\"base64 decoding is unavailable\");\n}\n\nfunction normalizeSseDataEncoding(\n dataEncoding: string | null | undefined,\n): \"base64\" | undefined {\n const normalized = dataEncoding?.trim().toLowerCase();\n if (normalized == null || normalized.length === 0) {\n return undefined;\n }\n if (normalized === \"base64\") {\n return \"base64\";\n }\n throw new ProtocolError(\n `unsupported stream-sse-data-encoding '${dataEncoding}'`,\n );\n}\n\nfunction decodeSseRawPayload(\n data: string,\n dataEncoding: \"base64\" | undefined,\n): Uint8Array {\n if (dataEncoding === \"base64\") {\n return decodeBase64Bytes(data);\n }\n return new TextEncoder().encode(data);\n}\n\nexport function decodeSseItemPayloads(\n data: string,\n dataEncoding?: string | null,\n): Uint8Array[] {\n const payload = decodeSseRawPayload(\n data,\n normalizeSseDataEncoding(dataEncoding),\n );\n if (payload.byteLength === 0) {\n return [payload];\n }\n try {\n return decodeItems(payload);\n } catch {\n return [payload];\n }\n}\n\n/**\n * Decode a single multipart part body. If the payload contains\n * length-prefixed binary framed items, decode them. Otherwise\n * return the raw bytes as a single-element array. This mirrors the\n * try/fallback approach used by {@link decodeSseItemPayloads}.\n */\nexport function decodeMultipartPartItems(payload: Uint8Array): Uint8Array[] {\n if (payload.byteLength === 0) {\n return [payload];\n }\n try {\n return decodeItems(payload);\n } catch {\n return [payload];\n }\n}\n\nexport function parseSseControlData(data: string): SseControlData {\n let parsed: unknown;\n try {\n parsed = JSON.parse(data);\n } catch {\n throw new ProtocolError(\"invalid sse control event JSON\");\n }\n if (!isObject(parsed) || typeof parsed.streamNextOffset !== \"string\") {\n throw new ProtocolError(\"sse control event missing streamNextOffset\");\n }\n const streamCursor =\n typeof parsed.streamCursor === \"string\" ? parsed.streamCursor : undefined;\n return {\n nextOffset: parsed.streamNextOffset,\n upToDate: parsed.upToDate === true,\n streamCursor,\n };\n}\n\nexport function isSseUnsupportedErrorText(message: string): boolean {\n const normalized = message.trim().toLowerCase();\n if (normalized.length === 0) {\n return false;\n }\n const mentionsSse =\n normalized.includes(\"sse\") || normalized.includes(\"text/event-stream\");\n const mentionsCompatibility =\n normalized.includes(\"unsupported\") ||\n normalized.includes(\"not support\") ||\n normalized.includes(\"incompatible\") ||\n normalized.includes(\"content type\");\n return mentionsSse && mentionsCompatibility;\n}\n\nexport function withCursorQuery(url: string, cursor?: string): string {\n if (cursor == null || cursor.length === 0) {\n return url;\n }\n const target = new URL(url);\n target.searchParams.set(\"cursor\", cursor);\n return target.toString();\n}\n\nexport function bytesToArrayBuffer(bytes: Uint8Array): ArrayBuffer {\n return bytes.buffer.slice(\n bytes.byteOffset,\n bytes.byteOffset + bytes.byteLength,\n ) as ArrayBuffer;\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.resolve();\n }\n return new Promise((resolve) => {\n const timer = setTimeout(resolve, ms);\n signal?.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timer);\n resolve();\n },\n { once: true },\n );\n });\n}\n\nexport function mergeAbortSignals(\n ...signals: ReadonlyArray<AbortSignal | null | undefined>\n): AbortSignal | undefined {\n const active = signals.filter(\n (signal): signal is AbortSignal => signal != null,\n );\n if (active.length === 0) {\n return undefined;\n }\n if (active.length === 1) {\n return active[0];\n }\n if (typeof AbortSignal.any === \"function\") {\n return AbortSignal.any(active);\n }\n\n const controller = new AbortController();\n for (const signal of active) {\n if (signal.aborted) {\n controller.abort(signal.reason);\n break;\n }\n signal.addEventListener(\n \"abort\",\n () => {\n controller.abort(signal.reason);\n },\n { once: true },\n );\n }\n return controller.signal;\n}\n\nexport function classifyFetchError(err: unknown): LastError {\n const message = err instanceof Error ? err.message : String(err);\n const status = err instanceof HttpError ? err.status : undefined;\n if (status === 401 || status === 403) {\n return { code: \"auth_failed\", message, retriable: false, atMs: Date.now() };\n }\n if (status === 410) {\n return { code: \"gone_410\", message, retriable: true, atMs: Date.now() };\n }\n if (status === 400 || status === 405 || status === 409) {\n return { code: \"protocol\", message, retriable: false, atMs: Date.now() };\n }\n if (err instanceof ProtocolError) {\n return { code: \"protocol\", message, retriable: false, atMs: Date.now() };\n }\n if (err instanceof TimeoutError) {\n return { code: \"timeout\", message, retriable: true, atMs: Date.now() };\n }\n if (err instanceof TypeError) {\n return { code: \"network\", message, retriable: true, atMs: Date.now() };\n }\n return { code: \"internal\", message, retriable: false, atMs: Date.now() };\n}\n\nexport function isStreamNotFoundError(error: unknown): boolean {\n return error instanceof HttpError && error.status === 404;\n}\n\nexport function toTransportError(error: unknown): TransportError {\n if (isStreamNotFoundError(error)) {\n return { code: \"stream_not_found\", retryable: false };\n }\n if (\n error instanceof HttpError &&\n (error.status === 401 || error.status === 403)\n ) {\n return {\n code: \"auth_failed\",\n retryable: false,\n status: error.status as 401 | 403,\n message: error.message,\n };\n }\n if (error instanceof HttpError && [400, 405, 409].includes(error.status)) {\n return {\n code: \"protocol_error\",\n retryable: false,\n status: error.status,\n message: error.message,\n };\n }\n if (error instanceof ProtocolError) {\n return {\n code: \"protocol_error\",\n retryable: false,\n status: error.status,\n message: error.message,\n };\n }\n if (error instanceof TimeoutError) {\n return {\n code: \"timeout\",\n retryable: true,\n phase: error.timeoutType,\n message: error.message,\n };\n }\n if (error instanceof HttpError && error.status === 410) {\n return { code: \"gone\", retryable: true, message: error.message };\n }\n if (error instanceof TypeError) {\n return {\n code: \"network_error\",\n retryable: true,\n message: error.message,\n };\n }\n if (error instanceof Error) {\n return {\n code: \"internal_error\",\n retryable: false,\n message: error.message,\n };\n }\n return {\n code: \"unknown\",\n retryable: false,\n message: String(error),\n };\n}\n\nexport function isReadNoProgress(\n requestOffset: string,\n result: ReadResult,\n): boolean {\n return (\n !result.upToDate &&\n result.updates.length === 0 &&\n result.nextOffset === requestOffset\n );\n}\n\nexport function isAuthOrProtocolError(error: unknown): boolean {\n return (\n error instanceof ProtocolError ||\n (error instanceof HttpError &&\n [400, 401, 403, 405, 409].includes(error.status))\n );\n}\n\nexport function normalizeAuthProvider(\n auth: StreamsAuthProvider | undefined,\n): ((context?: StreamsAuthContext) => Promise<string | undefined>) | undefined {\n if (auth == null) {\n return undefined;\n }\n if (typeof auth === \"string\") {\n const token = auth.trim();\n return async () => (token.length === 0 ? undefined : token);\n }\n return async (context) => {\n const value = await auth(context);\n const token = value?.trim() ?? \"\";\n return token.length === 0 ? undefined : token;\n };\n}\n\nexport function normalizeSnapshotUploadConfig(\n config: SnapshotUploadOptions | undefined,\n): SnapshotUploadRuntimeConfig | undefined {\n if (config == null || config.enabled === false) {\n return undefined;\n }\n if (!Number.isFinite(config.debounceMs ?? 10_000)) {\n throw new Error(\"snapshotUpload.debounceMs must be a finite number\");\n }\n if (!Number.isFinite(config.minBytesSinceRemoteSnapshot ?? 100 * 1024)) {\n throw new Error(\n \"snapshotUpload.minBytesSinceRemoteSnapshot must be a finite number\",\n );\n }\n const debounceMs = Math.max(0, Math.floor(config.debounceMs ?? 10_000));\n const minBytes = config.minBytesSinceRemoteSnapshot ?? 100 * 1024;\n if (minBytes < 0) {\n throw new Error(\n \"snapshotUpload.minBytesSinceRemoteSnapshot must be non-negative\",\n );\n }\n return {\n canUpload: async () => Boolean(await config.canUpload()),\n debounceMs,\n minBytesSinceRemoteSnapshot: BigInt(Math.floor(minBytes)),\n };\n}\n\nfunction assertSnapshotBytes(\n value: unknown,\n label: \"snapshotCodec.compress\" | \"snapshotCodec.decompress\",\n): Uint8Array {\n if (value instanceof Uint8Array) {\n return value;\n }\n throw new Error(`${label} must return Uint8Array`);\n}\n\nexport function normalizeSnapshotCodec(\n codec: SnapshotCodec | undefined,\n): SnapshotCodecRuntimeConfig | undefined {\n if (codec == null) {\n return undefined;\n }\n if (\n typeof codec.compress !== \"function\" ||\n typeof codec.decompress !== \"function\"\n ) {\n throw new Error(\n \"snapshotCodec.compress and snapshotCodec.decompress must be provided together\",\n );\n }\n return {\n compress: async (snapshot) =>\n assertSnapshotBytes(\n await codec.compress(snapshot),\n \"snapshotCodec.compress\",\n ),\n decompress: async (snapshot) =>\n assertSnapshotBytes(\n await codec.decompress(snapshot),\n \"snapshotCodec.decompress\",\n ),\n };\n}\n\nfunction jsonValueEquals(a: JsonValue, b: JsonValue): boolean {\n if (a === b) {\n return true;\n }\n if (typeof a !== typeof b || a == null || b == null) {\n return false;\n }\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {\n return false;\n }\n for (let i = 0; i < a.length; i += 1) {\n if (!jsonValueEquals(a[i] as JsonValue, b[i] as JsonValue)) {\n return false;\n }\n }\n return true;\n }\n if (typeof a !== \"object\" || typeof b !== \"object\") {\n return false;\n }\n const aEntries = Object.entries(a).sort(([left], [right]) =>\n left.localeCompare(right),\n );\n const bEntries = Object.entries(b).sort(([left], [right]) =>\n left.localeCompare(right),\n );\n if (aEntries.length !== bEntries.length) {\n return false;\n }\n for (let i = 0; i < aEntries.length; i += 1) {\n const [aKey, aValue] = aEntries[i];\n const [bKey, bValue] = bEntries[i];\n if (aKey !== bKey || !jsonValueEquals(aValue as JsonValue, bValue as JsonValue)) {\n return false;\n }\n }\n return true;\n}\n\nexport function jsonObjectEquals(a: JsonObject, b: JsonObject): boolean {\n return jsonValueEquals(a, b);\n}\n\nexport function parseSnapshotByteOffset(\n offset: string | null | undefined,\n): bigint | null {\n if (offset == null || offset.length === 0 || offset === \"-1\") {\n return 0n;\n }\n if (!/^\\d+$/.test(offset)) {\n return null;\n }\n return BigInt(offset);\n}\n\nexport function resolveNextOffsetAfterConcurrentAdvance(\n requestOffset: string,\n currentOffset: string,\n responseNextOffset: string,\n): string {\n if (currentOffset === requestOffset) {\n return responseNextOffset;\n }\n if (currentOffset === responseNextOffset) {\n return currentOffset;\n }\n const current = parseSnapshotByteOffset(currentOffset);\n const incoming = parseSnapshotByteOffset(responseNextOffset);\n if (current != null && incoming != null) {\n return incoming > current ? responseNextOffset : currentOffset;\n }\n return currentOffset;\n}\n","import {\n StreamsClient,\n type StreamError,\n} from \"@loro-dev/streams-client\";\n\nimport { BINARY_CONTENT_TYPE, decodeItems, encodeItems } from \"./items\";\nimport type { ReconnectConfig } from \"./reconnect\";\nimport {\n AppendResult,\n BootstrapResult,\n decodeMultipartPartItems,\n decodeSseItemPayloads,\n FetchLike,\n HttpError,\n isSseUnsupportedErrorText,\n ProtocolError,\n parseSseControlData,\n type ProducerSession,\n ReadResult,\n type SseControlHandlerResult,\n type SseItemsOpenResult,\n type SseItemsReadResult,\n TimeoutError,\n} from \"./transport-internal\";\nimport type {\n CrdtAdapter,\n JsonObject,\n MaybePromise,\n StreamsAuthContext,\n} from \"./types\";\n\ntype StreamsTransportClientOptions<TVersion extends JsonObject> = {\n readonly streamUrl: string;\n readonly adapter: CrdtAdapter<TVersion>;\n readonly authProvider?: (context?: StreamsAuthContext) => Promise<string | undefined>;\n readonly fetchImpl: FetchLike;\n readonly reconnectConfig: ReconnectConfig;\n};\n\n/**\n * Low-level HTTP and SSE client for one stream.\n *\n * This layer owns request headers, timeouts, and response parsing. Higher-level\n * join/sync state transitions stay in `transport-runtime.ts`.\n */\nexport class StreamsTransportClient<TVersion extends JsonObject> {\n readonly streamUrl: string;\n\n private readonly adapter: CrdtAdapter<TVersion>;\n private readonly client: StreamsClient;\n private readonly reconnectConfig: ReconnectConfig;\n\n constructor(options: StreamsTransportClientOptions<TVersion>) {\n this.streamUrl = options.streamUrl;\n this.adapter = options.adapter;\n this.client = new StreamsClient({\n url: options.streamUrl,\n auth: options.authProvider,\n fetch: options.fetchImpl as typeof globalThis.fetch,\n retry: {\n maxAttempts: 0,\n },\n timeout: {\n connectTimeoutMs: options.reconnectConfig.connectTimeoutMs,\n pollTimeoutMs: options.reconnectConfig.pollTimeoutMs,\n },\n });\n this.reconnectConfig = options.reconnectConfig;\n }\n\n async createStreamRequest(): Promise<boolean> {\n const adapterHeaders = this.adapter.getCreateStreamHeaders\n ? await this.adapter.getCreateStreamHeaders()\n : undefined;\n const result = await this.client.create({\n headers: adapterHeaders,\n });\n if (result.ok) {\n return result.result.created;\n }\n throw this.toTransportFailure(result.result);\n }\n\n async deleteStreamRequest(): Promise<boolean> {\n const result = await this.client.delete();\n if (result.ok) {\n return result.result.deleted;\n }\n throw this.toTransportFailure(result.result);\n }\n\n async readFromOffsetSseItems(\n offset: string,\n cursor: string | undefined,\n onControl: (\n updates: Uint8Array[],\n nextOffset: string,\n upToDate: boolean,\n streamCursor?: string,\n ) => MaybePromise<SseControlHandlerResult>,\n onOpen?: () => void,\n signal?: AbortSignal,\n ): Promise<SseItemsReadResult> {\n return this.readItemsSse(\n offset,\n cursor,\n onControl,\n onOpen,\n signal,\n );\n }\n\n async readFromOffset(\n offset: string,\n cursor?: string,\n live?: \"long-poll\",\n signal?: AbortSignal,\n ): Promise<{ kind: \"gone\" } | { kind: \"ok\"; value: ReadResult }> {\n const result = await this.client.readOnce({\n offset,\n cursor,\n live,\n signal,\n });\n if (!result.ok) {\n if (result.result.code === \"gone\") {\n return { kind: \"gone\" };\n }\n throw this.toTransportFailure(result.result);\n }\n\n const payload = result.result.payload?.body ?? new Uint8Array();\n return {\n kind: \"ok\",\n value: {\n nextOffset: result.result.nextOffset,\n upToDate: result.result.upToDate,\n updates: payload.byteLength === 0 ? [] : decodeItems(payload),\n streamCursor: result.result.cursor,\n },\n };\n }\n\n async bootstrap(): Promise<BootstrapResult> {\n const result = await this.client.bootstrap();\n if (!result.ok) {\n throw this.toTransportFailure(result.result);\n }\n\n return {\n nextOffset: result.result.nextOffset,\n upToDate: result.result.upToDate,\n snapshot: result.result.snapshot?.body ?? new Uint8Array(),\n updates: result.result.updates.flatMap((part) =>\n decodeMultipartPartItems(part.body)\n ),\n streamCursor: result.result.cursor,\n };\n }\n\n async readSnapshotOffsetValue(): Promise<string | null> {\n const result = await this.client.head();\n if (!result.ok) {\n if (result.result.code === \"not_found\") {\n return null;\n }\n throw this.toTransportFailure(result.result);\n }\n\n const snapshotOffset = result.result.snapshotOffset;\n return snapshotOffset == null || snapshotOffset.length === 0\n ? null\n : snapshotOffset;\n }\n\n async putSnapshotAt(\n snapshotOffset: string,\n snapshot: Uint8Array,\n ): Promise<void> {\n const result = await this.client.putSnapshot({\n offset: snapshotOffset,\n part: {\n contentType: \"application/octet-stream\",\n body: snapshot,\n },\n });\n if (!result.ok) {\n throw this.toTransportFailure(result.result);\n }\n }\n\n async appendUpdates(\n updates: readonly Uint8Array[],\n producerSession: ProducerSession,\n ): Promise<AppendResult> {\n const result = await this.client.append({\n part: {\n contentType: BINARY_CONTENT_TYPE,\n body: encodeItems(updates),\n },\n producer: {\n producerId: producerSession.producerId,\n epoch: producerSession.producerEpoch,\n seq: producerSession.nextProducerSeq,\n },\n });\n if (result.ok) {\n return {\n kind: \"ok\",\n ackEpoch: result.result.producer?.epoch ?? producerSession.producerEpoch,\n ackSeq: result.result.producer?.seq ?? producerSession.nextProducerSeq,\n nextOffset: result.result.nextOffset,\n };\n }\n\n const error = result.result;\n if (\n error.code === \"conflict\" &&\n error.detail?.kind === \"producer_seq_gap\"\n ) {\n return { kind: \"seq-gap\", expectedSeq: error.detail.expectedSeq };\n }\n if (\n error.code === \"forbidden\" &&\n error.detail?.kind === \"stale_producer_epoch\"\n ) {\n return {\n kind: \"stale-epoch\",\n serverEpoch: error.detail.serverEpoch,\n };\n }\n throw this.toTransportFailure(error);\n }\n\n private toTransportFailure(error: StreamError): Error {\n switch (error.code) {\n case \"bad_request\":\n case \"unauthorized\":\n case \"forbidden\":\n case \"not_found\":\n case \"conflict\":\n case \"gone\":\n case \"rate_limited\":\n return new HttpError(error.message, error.status);\n case \"timeout\":\n return new TimeoutError(\n error.phase,\n error.phase === \"poll\"\n ? this.reconnectConfig.pollTimeoutMs\n : this.reconnectConfig.connectTimeoutMs,\n );\n case \"network_error\":\n return error.cause instanceof TypeError\n ? error.cause\n : new TypeError(error.message);\n case \"protocol_error\":\n return new ProtocolError(error.message, error.status);\n case \"unknown\":\n if (typeof error.status === \"number\") {\n return new HttpError(error.message, error.status);\n }\n if (error.cause instanceof TypeError) {\n return error.cause;\n }\n if (error.cause instanceof Error) {\n return error.cause;\n }\n return new Error(error.message);\n default: {\n const exhaustive: never = error;\n return new Error(String(exhaustive));\n }\n }\n }\n\n private async readItemsSse(\n initialOffset: string,\n cursor: string | undefined,\n onControl: (\n updates: Uint8Array[],\n nextOffset: string,\n upToDate: boolean,\n streamCursor?: string,\n ) => MaybePromise<SseControlHandlerResult>,\n onOpen?: () => void,\n signal?: AbortSignal,\n ): Promise<SseItemsReadResult> {\n const opened = await this.openItemsSseSession(\n initialOffset,\n cursor,\n onOpen,\n signal,\n );\n if (opened.kind !== \"ok\") {\n return opened;\n }\n const result = await opened.session.continue(onControl);\n if (result.paused) {\n await opened.session.cancel();\n }\n return {\n kind: \"ok\",\n latestOffset: result.latestOffset,\n latestCursor: result.latestCursor,\n };\n }\n\n private async openItemsSseSession(\n initialOffset: string,\n cursor: string | undefined,\n onOpen?: () => void,\n signal?: AbortSignal,\n ): Promise<SseItemsOpenResult> {\n const result = await this.client.openSseSession({\n offset: initialOffset,\n cursor,\n signal,\n });\n if (!result.ok) {\n if (result.result.code === \"gone\") {\n return { kind: \"gone\" };\n }\n if (result.result.code === \"not_found\") {\n return { kind: \"not-found\" };\n }\n if (\n result.result.code === \"bad_request\" &&\n isSseUnsupportedErrorText(result.result.message)\n ) {\n return { kind: \"unsupported\" };\n }\n throw this.toTransportFailure(result.result);\n }\n\n const session = result.result;\n onOpen?.();\n let pendingDataEvents: string[] = [];\n let latestOffset = session.nextOffset ?? initialOffset;\n let latestCursor = session.cursor;\n let exhausted = false;\n\n return {\n kind: \"ok\",\n session: {\n continue: async (nextOnControl) => {\n if (exhausted) {\n return {\n kind: \"ok\",\n latestOffset,\n latestCursor,\n paused: false,\n };\n }\n for await (const event of session.events) {\n if (event.event === \"data\") {\n pendingDataEvents.push(event.data);\n continue;\n }\n if (event.event !== \"control\") {\n continue;\n }\n const control = parseSseControlData(event.data);\n const updates: Uint8Array[] = [];\n for (const eventData of pendingDataEvents) {\n updates.push(\n ...decodeSseItemPayloads(eventData, session.dataEncoding),\n );\n }\n pendingDataEvents = [];\n const handlerResult = await nextOnControl(\n updates,\n control.nextOffset,\n control.upToDate,\n control.streamCursor,\n );\n latestOffset = control.nextOffset;\n if (control.streamCursor != null) {\n latestCursor = control.streamCursor;\n }\n if (handlerResult === \"stop\") {\n exhausted = true;\n await session.cancel();\n return {\n kind: \"ok\",\n latestOffset,\n latestCursor,\n paused: false,\n };\n }\n if (handlerResult === \"pause\") {\n return {\n kind: \"ok\",\n latestOffset,\n latestCursor,\n paused: true,\n };\n }\n }\n exhausted = true;\n return {\n kind: \"ok\",\n latestOffset,\n latestCursor,\n paused: false,\n };\n },\n cancel: async () => {\n if (exhausted) {\n return;\n }\n exhausted = true;\n await session.cancel();\n },\n },\n };\n }\n}\n","import type {\n RemoteCursor,\n RemoteCursorSaveSource,\n} from \"./checkpoint\";\nimport {\n resolveNextOffsetAfterConcurrentAdvance,\n type ReadResult,\n} from \"./transport-internal\";\nimport type {\n CrdtAdapter,\n JsonObject,\n MaybePromise,\n} from \"./types\";\n\ntype TransportCursorManagerOptions<TVersion extends JsonObject> = {\n readonly adapter: Pick<\n CrdtAdapter<TVersion>,\n \"applySnapshot\" | \"applyRemoteUpdates\"\n >;\n readonly decodeSnapshot?: (\n snapshot: Uint8Array,\n ) => MaybePromise<Uint8Array>;\n readonly saveRemoteCursor: (\n cursor: RemoteCursor<TVersion>,\n source: RemoteCursorSaveSource,\n ) => Promise<RemoteCursor<TVersion>>;\n};\n\nexport class TransportCursorManager<TVersion extends JsonObject> {\n private readonly adapter: Pick<\n CrdtAdapter<TVersion>,\n \"applySnapshot\" | \"applyRemoteUpdates\"\n >;\n private readonly decodeSnapshot?: (\n snapshot: Uint8Array,\n ) => MaybePromise<Uint8Array>;\n private readonly saveRemoteCursor: (\n cursor: RemoteCursor<TVersion>,\n source: RemoteCursorSaveSource,\n ) => Promise<RemoteCursor<TVersion>>;\n\n constructor(options: TransportCursorManagerOptions<TVersion>) {\n this.adapter = options.adapter;\n this.decodeSnapshot = options.decodeSnapshot;\n this.saveRemoteCursor = options.saveRemoteCursor;\n }\n\n async applyBootstrapPayload(\n cursor: RemoteCursor<TVersion>,\n snapshot: Uint8Array,\n updates: readonly Uint8Array[],\n nextOffset: string,\n ): Promise<RemoteCursor<TVersion>> {\n let nextVersion = cursor.serverLowerBoundVersion;\n if (snapshot.byteLength > 0) {\n nextVersion = await this.adapter.applySnapshot(\n this.decodeSnapshot == null\n ? snapshot\n : await this.decodeSnapshot(snapshot),\n );\n }\n if (updates.length > 0) {\n nextVersion = await this.adapter.applyRemoteUpdates(\n [...updates],\n nextVersion,\n );\n }\n return await this.saveRemoteCursor(\n {\n ...cursor,\n nextOffset,\n serverLowerBoundVersion: nextVersion,\n },\n \"bootstrap\",\n );\n }\n\n async applyBootstrapItems(\n cursor: RemoteCursor<TVersion>,\n items: readonly Uint8Array[],\n nextOffset: string,\n ): Promise<RemoteCursor<TVersion>> {\n const snapshot = items[0] ?? new Uint8Array();\n return await this.applyBootstrapPayload(\n cursor,\n snapshot,\n items.slice(1),\n nextOffset,\n );\n }\n\n async applyRemoteItems(\n cursor: RemoteCursor<TVersion>,\n items: readonly Uint8Array[],\n nextOffset: string,\n ): Promise<RemoteCursor<TVersion>> {\n return await this.applyRemotePayload(\n cursor,\n [...items],\n nextOffset,\n \"remote\",\n );\n }\n\n async applyCatchupResult(\n cursor: RemoteCursor<TVersion>,\n result: ReadResult,\n onRemoteVersionApplied?: (\n previousVersion: TVersion,\n nextVersion: TVersion,\n ) => MaybePromise<void>,\n ): Promise<RemoteCursor<TVersion>> {\n return await this.applyRemotePayload(\n cursor,\n result.updates,\n result.nextOffset,\n \"remote\",\n onRemoteVersionApplied,\n );\n }\n\n async applyLiveResult(\n cursor: RemoteCursor<TVersion>,\n requestOffset: string,\n result: {\n readonly nextOffset: string;\n readonly updates: readonly Uint8Array[];\n },\n onRemoteVersionApplied?: (\n previousVersion: TVersion,\n nextVersion: TVersion,\n ) => MaybePromise<void>,\n ): Promise<RemoteCursor<TVersion>> {\n const previousVersion = cursor.serverLowerBoundVersion;\n let nextVersion = previousVersion;\n if (result.updates.length > 0) {\n nextVersion = await this.adapter.applyRemoteUpdates(\n [...result.updates],\n nextVersion,\n );\n await onRemoteVersionApplied?.(previousVersion, nextVersion);\n }\n return await this.saveRemoteCursor(\n {\n ...cursor,\n nextOffset: resolveNextOffsetAfterConcurrentAdvance(\n requestOffset,\n cursor.nextOffset,\n result.nextOffset,\n ),\n serverLowerBoundVersion: nextVersion,\n },\n \"remote\",\n );\n }\n\n private async applyRemotePayload(\n cursor: RemoteCursor<TVersion>,\n updates: readonly Uint8Array[],\n nextOffset: string,\n source: RemoteCursorSaveSource,\n onRemoteVersionApplied?: (\n previousVersion: TVersion,\n nextVersion: TVersion,\n ) => MaybePromise<void>,\n ): Promise<RemoteCursor<TVersion>> {\n const previousVersion = cursor.serverLowerBoundVersion;\n let nextVersion = previousVersion;\n if (updates.length > 0) {\n nextVersion = await this.adapter.applyRemoteUpdates(\n [...updates],\n nextVersion,\n );\n await onRemoteVersionApplied?.(previousVersion, nextVersion);\n }\n return await this.saveRemoteCursor(\n {\n ...cursor,\n nextOffset,\n serverLowerBoundVersion: nextVersion,\n },\n source,\n );\n }\n}\n","const DEFAULT_COMPACT_THRESHOLD = 64;\nconst DEFAULT_MIN_CAPACITY = 16;\n\nexport interface DequeOptions {\n readonly compactThreshold?: number;\n readonly minCapacity?: number;\n}\n\nexport class Deque<T> implements Iterable<T> {\n private buffer: Array<T | null | undefined>;\n private head = 0;\n private tail = 0;\n private readonly compactThreshold: number;\n private readonly minCapacity: number;\n\n constructor(values?: Iterable<T>, options: DequeOptions = {}) {\n this.compactThreshold = Math.max(\n 1,\n options.compactThreshold ?? DEFAULT_COMPACT_THRESHOLD\n );\n this.minCapacity = Math.max(1, options.minCapacity ?? DEFAULT_MIN_CAPACITY);\n const seed = values == null ? [] : Array.from(values);\n this.buffer = seed.slice();\n this.tail = seed.length;\n }\n\n get length(): number {\n return this.tail - this.head;\n }\n\n isEmpty(): boolean {\n return this.length === 0;\n }\n\n clear(): void {\n this.buffer = [];\n this.head = 0;\n this.tail = 0;\n }\n\n peekFront(): T | undefined {\n if (this.length === 0) {\n return undefined;\n }\n const value = this.buffer[this.head];\n return value == null ? undefined : value;\n }\n\n peekBack(): T | undefined {\n if (this.length === 0) {\n return undefined;\n }\n const value = this.buffer[this.tail - 1];\n return value == null ? undefined : value;\n }\n\n at(index: number): T | undefined {\n const length = this.length;\n if (length === 0) {\n return undefined;\n }\n let offset = index;\n if (offset < 0) {\n offset += length;\n }\n if (offset < 0 || offset >= length) {\n return undefined;\n }\n const value = this.buffer[this.head + offset];\n return value == null ? undefined : value;\n }\n\n pushBack(value: T): number {\n this.ensureBackCapacity();\n this.buffer[this.tail] = value;\n this.tail += 1;\n return this.length;\n }\n\n pushFront(value: T): number {\n if (this.head === 0) {\n this.recenter(1, 0);\n }\n this.head -= 1;\n this.buffer[this.head] = value;\n return this.length;\n }\n\n popFront(): T | undefined {\n if (this.length === 0) {\n return undefined;\n }\n const value = this.buffer[this.head];\n // Explicitly null out removed slot to release references for GC.\n this.buffer[this.head] = null;\n this.head += 1;\n this.compactIfNeeded();\n return value == null ? undefined : value;\n }\n\n popBack(): T | undefined {\n if (this.length === 0) {\n return undefined;\n }\n this.tail -= 1;\n const value = this.buffer[this.tail];\n // Explicitly null out removed slot to release references for GC.\n this.buffer[this.tail] = null;\n this.compactIfNeeded();\n return value == null ? undefined : value;\n }\n\n toArray(): T[] {\n const out: T[] = [];\n for (let i = this.head; i < this.tail; i += 1) {\n out.push(this.buffer[i] as T);\n }\n return out;\n }\n\n *[Symbol.iterator](): IterableIterator<T> {\n for (let i = this.head; i < this.tail; i += 1) {\n yield this.buffer[i] as T;\n }\n }\n\n private ensureBackCapacity(): void {\n if (this.tail < this.buffer.length) {\n return;\n }\n if (this.head > 0) {\n this.compactToFront();\n if (this.tail < this.buffer.length) {\n return;\n }\n }\n this.recenter(0, 1);\n }\n\n private recenter(extraFront: number, extraBack: number): void {\n const length = this.length;\n const needed = length + extraFront + extraBack;\n const currentCapacity = this.buffer.length;\n let nextCapacity = Math.max(currentCapacity, this.minCapacity);\n if (nextCapacity < needed) {\n nextCapacity = Math.max(nextCapacity * 2, needed, this.minCapacity);\n }\n const free = nextCapacity - length;\n const nextHead = Math.max(extraFront, Math.floor(free / 2));\n const next = new Array<T | null | undefined>(nextCapacity);\n for (let i = 0; i < length; i += 1) {\n next[nextHead + i] = this.buffer[this.head + i];\n }\n this.buffer = next;\n this.head = nextHead;\n this.tail = nextHead + length;\n }\n\n private compactIfNeeded(): void {\n const length = this.length;\n if (length === 0) {\n this.clear();\n return;\n }\n if (this.head < this.compactThreshold || this.head < length) {\n return;\n }\n this.compactToFront();\n }\n\n private compactToFront(): void {\n const length = this.length;\n this.buffer = this.buffer.slice(this.head, this.tail);\n this.head = 0;\n this.tail = length;\n }\n}\n","import {\n jsonObjectEquals,\n parseSnapshotByteOffset,\n type JoinState,\n type SnapshotUploadRuntimeConfig,\n} from \"./transport-internal\";\nimport type { CrdtAdapter, JsonObject, MaybePromise } from \"./types\";\n\nexport type TransportSnapshotState = {\n observedForeignWriter: boolean;\n taskScheduled: boolean;\n taskNeedsRerun: boolean;\n debounceTimer?: ReturnType<typeof setTimeout>;\n};\n\nexport function createTransportSnapshotState(): TransportSnapshotState {\n return {\n observedForeignWriter: false,\n taskScheduled: false,\n taskNeedsRerun: false,\n };\n}\n\ntype TransportSnapshotManagerOptions<TVersion extends JsonObject> = {\n readonly adapter: Pick<CrdtAdapter<TVersion>, \"exportSnapshot\">;\n readonly config?: SnapshotUploadRuntimeConfig;\n readonly encodeSnapshot?: (\n snapshot: Uint8Array,\n ) => MaybePromise<Uint8Array>;\n readonly readSnapshotOffsetValue: () => Promise<string | null>;\n readonly putSnapshotAt: (\n snapshotOffset: string,\n snapshot: Uint8Array,\n ) => Promise<void>;\n readonly enqueueExclusive: <T>(task: () => MaybePromise<T>) => Promise<T>;\n readonly logDebug: (\n message: string,\n detail?: Record<string, unknown>,\n ) => void;\n readonly logError: (\n message: string,\n error?: unknown,\n detail?: Record<string, unknown>,\n ) => void;\n readonly isCurrentState: (state: JoinState<TVersion>) => boolean;\n};\n\n/**\n * Manages debounce and upload gating for remote snapshots.\n *\n * All \"is this state still current / closed / reconnecting / blocked by a\n * foreign writer?\" checks live here so the runtime does not duplicate them.\n */\nexport class TransportSnapshotManager<TVersion extends JsonObject> {\n private readonly adapter: Pick<CrdtAdapter<TVersion>, \"exportSnapshot\">;\n private readonly config?: SnapshotUploadRuntimeConfig;\n private readonly encodeSnapshot?: (\n snapshot: Uint8Array,\n ) => MaybePromise<Uint8Array>;\n private readonly readSnapshotOffsetValue: () => Promise<string | null>;\n private readonly putSnapshotAt: (\n snapshotOffset: string,\n snapshot: Uint8Array,\n ) => Promise<void>;\n private readonly enqueueExclusive: <T>(\n task: () => MaybePromise<T>,\n ) => Promise<T>;\n private readonly logDebug: (\n message: string,\n detail?: Record<string, unknown>,\n ) => void;\n private readonly logError: (\n message: string,\n error?: unknown,\n detail?: Record<string, unknown>,\n ) => void;\n private readonly isCurrentState: (state: JoinState<TVersion>) => boolean;\n\n constructor(options: TransportSnapshotManagerOptions<TVersion>) {\n this.adapter = options.adapter;\n this.config = options.config;\n this.encodeSnapshot = options.encodeSnapshot;\n this.readSnapshotOffsetValue = options.readSnapshotOffsetValue;\n this.putSnapshotAt = options.putSnapshotAt;\n this.enqueueExclusive = options.enqueueExclusive;\n this.logDebug = options.logDebug;\n this.logError = options.logError;\n this.isCurrentState = options.isCurrentState;\n }\n\n dispose(state: JoinState<TVersion>): void {\n this.clearDebounceTimer(state.snapshot);\n }\n\n observeRemoteVersion(\n state: JoinState<TVersion>,\n previousVersion: TVersion,\n nextVersion: TVersion,\n ): void {\n const snapshot = state.snapshot;\n if (snapshot.debounceTimer == null) {\n return;\n }\n if (!jsonObjectEquals(previousVersion, nextVersion)) {\n snapshot.observedForeignWriter = true;\n }\n }\n\n schedule(state: JoinState<TVersion>): void {\n const config = this.config;\n if (config == null || state.closed) {\n return;\n }\n const snapshot = state.snapshot;\n this.clearDebounceTimer(snapshot);\n snapshot.observedForeignWriter = false;\n snapshot.debounceTimer = setTimeout(() => {\n void this.handleDebounceExpiry(state);\n }, config.debounceMs);\n }\n\n private clearDebounceTimer(snapshot: TransportSnapshotState): void {\n if (snapshot.debounceTimer != null) {\n clearTimeout(snapshot.debounceTimer);\n snapshot.debounceTimer = undefined;\n }\n }\n\n private async handleDebounceExpiry(state: JoinState<TVersion>): Promise<void> {\n const snapshot = state.snapshot;\n snapshot.debounceTimer = undefined;\n if (this.getRunnableConfig(state) == null) {\n return;\n }\n if (snapshot.taskScheduled) {\n snapshot.taskNeedsRerun = true;\n return;\n }\n snapshot.taskScheduled = true;\n void this.enqueueExclusive(async () => {\n await this.maybeUpload(state);\n })\n .catch((error) => {\n this.logError(\"snapshot upload task failed\", error);\n })\n .finally(() => {\n snapshot.taskScheduled = false;\n if (snapshot.taskNeedsRerun && !state.closed) {\n snapshot.taskNeedsRerun = false;\n void this.handleDebounceExpiry(state);\n }\n });\n }\n\n private async maybeUpload(state: JoinState<TVersion>): Promise<void> {\n const config = await this.resolveUploadConfig(state);\n if (config == null) {\n return;\n }\n const tailBytes = parseSnapshotByteOffset(state.cursor.nextOffset);\n if (tailBytes == null) {\n this.logDebug(\"skip snapshot upload: non-numeric offset token\", {\n offset: state.cursor.nextOffset,\n });\n return;\n }\n try {\n const remoteSnapshotOffset = await this.readSnapshotOffsetValue();\n const snapshotBytes = parseSnapshotByteOffset(remoteSnapshotOffset);\n if (snapshotBytes == null) {\n this.logDebug(\"skip snapshot upload: non-numeric snapshot offset\", {\n offset: remoteSnapshotOffset,\n });\n return;\n }\n if (tailBytes <= snapshotBytes) {\n return;\n }\n if (tailBytes - snapshotBytes < config.minBytesSinceRemoteSnapshot) {\n return;\n }\n const snapshot = this.adapter.exportSnapshot();\n await this.putSnapshotAt(\n state.cursor.nextOffset,\n this.encodeSnapshot == null\n ? snapshot\n : await this.encodeSnapshot(snapshot),\n );\n } catch (error) {\n this.logError(\"snapshot upload failed\", error);\n }\n }\n\n private getRunnableConfig(\n state: JoinState<TVersion>,\n ): SnapshotUploadRuntimeConfig | undefined {\n const config = this.config;\n if (config == null || state.closed || !this.isCurrentState(state)) {\n return undefined;\n }\n if (\n state.snapshot.observedForeignWriter ||\n state.status === \"reconnecting\" ||\n state.status === \"disconnected\" ||\n state.status === \"error\"\n ) {\n return undefined;\n }\n return config;\n }\n\n private async resolveUploadConfig(\n state: JoinState<TVersion>,\n ): Promise<SnapshotUploadRuntimeConfig | undefined> {\n const config = this.getRunnableConfig(state);\n if (config == null) {\n return undefined;\n }\n if (!(await this.canUpload(config))) {\n return undefined;\n }\n return config;\n }\n\n private async canUpload(\n config: SnapshotUploadRuntimeConfig,\n ): Promise<boolean> {\n try {\n return Boolean(await config.canUpload());\n } catch (error) {\n this.logError(\"snapshot upload permission check failed\", error);\n return false;\n }\n }\n}\n","import { Deque } from \"./deque\";\nimport type { RemoteCursor } from \"./checkpoint\";\nimport type { JoinState, LiveReadMode } from \"./transport-internal\";\nimport {\n createTransportSnapshotState,\n type TransportSnapshotManager,\n} from \"./transport-snapshot\";\nimport type { JsonObject } from \"./types\";\n\nexport function createJoinState<TVersion extends JsonObject>(\n cursor: RemoteCursor<TVersion>,\n liveMode: LiveReadMode = \"sse\",\n): JoinState<TVersion> {\n return {\n refCount: 0,\n closed: false,\n status: \"connecting\",\n statusListeners: new Set(),\n pendingLocal: new Deque(),\n flushingLocal: false,\n retryAttempt: 0,\n retrySleepController: new AbortController(),\n cursor,\n liveMode,\n snapshot: createTransportSnapshotState(),\n started: Promise.resolve(),\n };\n}\n\ntype DisposeJoinStateOptions<TVersion extends JsonObject> = {\n readonly snapshotManager: Pick<TransportSnapshotManager<TVersion>, \"dispose\">;\n readonly onDisposed?: () => void;\n};\n\nexport async function disposeJoinState<TVersion extends JsonObject>(\n state: JoinState<TVersion>,\n options: DisposeJoinStateOptions<TVersion>,\n): Promise<void> {\n state.closed = true;\n options.snapshotManager.dispose(state);\n const requestController = state.requestController;\n state.requestController = undefined;\n const unsubscribeLocal = state.unsubscribeLocal;\n state.unsubscribeLocal = undefined;\n requestController?.abort();\n unsubscribeLocal?.();\n options.onDisposed?.();\n}\n","import {\n composeBeforeRemoteCursorSaveHooks,\n createInitialRemoteCursor,\n InMemoryRemoteCursorStore,\n persistRemoteCursor,\n type BeforeRemoteCursorSaveHook,\n type RemoteCursor,\n type RemoteCursorSaveSource,\n type RemoteCursorStore,\n} from \"./checkpoint\";\nimport {\n computeRetryDelay,\n DEFAULT_RECONNECT_CONFIG,\n type ReconnectConfig,\n} from \"./reconnect\";\nimport { StreamsTransportClient } from \"./transport-client\";\nimport { TransportCursorManager } from \"./transport-cursor\";\nimport {\n createJoinState as createTransportJoinState,\n disposeJoinState as disposeTransportJoinState,\n} from \"./transport-room\";\nimport { TransportSnapshotManager } from \"./transport-snapshot\";\nimport {\n classifyFetchError,\n createProducerId,\n HttpError,\n isAuthOrProtocolError,\n isReadNoProgress,\n isStreamNotFoundError,\n normalizeAuthProvider,\n normalizeSnapshotCodec,\n normalizeSnapshotUploadConfig,\n sleep,\n toTransportError,\n type AppendResult,\n type BootstrapResult,\n type CursorSyncResult,\n type JoinState,\n type JoinSyncResult,\n type LiveReadMode,\n type LocalExportResult,\n type ProducerSession,\n type ReadResult,\n type SseControlHandlerResult,\n type SseItemsReadResult,\n} from \"./transport-internal\";\nimport type {\n CrdtAdapter,\n CrdtUpdateBatch,\n StreamsCrdtLike,\n StreamsCrdtOptions,\n JsonObject,\n MaybePromise,\n Result,\n TransportCreateStreamSuccess,\n TransportDeleteStreamSuccess,\n TransportError,\n TransportJoinParams,\n TransportRoomStatus,\n TransportSubscription,\n TransportSyncSuccess,\n} from \"./types\";\n\n/**\n * Durable Streams transport runtime bound to one stream URL and one local CRDT adapter.\n */\nexport class StreamsCrdt<\n TVersion extends JsonObject,\n> implements StreamsCrdtLike<TVersion> {\n readonly streamUrl: string;\n readonly adapter: CrdtAdapter<TVersion>;\n readonly remoteCursorStore: RemoteCursorStore<TVersion>;\n\n private readonly createStreamIfMissing: boolean;\n private readonly client: StreamsTransportClient<TVersion>;\n private readonly cursorManager: TransportCursorManager<TVersion>;\n private readonly reconnectConfig: ReconnectConfig;\n private readonly debug: boolean;\n private readonly beforeRemoteCursorSave?: BeforeRemoteCursorSaveHook<TVersion>;\n private readonly snapshotManager: TransportSnapshotManager<TVersion>;\n private readonly producerId = createProducerId();\n private producerEpoch = 0;\n private nextProducerSeq = 0;\n private joinState?: JoinState<TVersion>;\n private opQueue: Promise<void> = Promise.resolve();\n\n /**\n * Creates a transport for one stream URL and one local adapter instance.\n */\n constructor(options: StreamsCrdtOptions<TVersion>) {\n this.streamUrl = options.streamUrl;\n this.adapter = options.adapter;\n const authProvider = normalizeAuthProvider(options.auth);\n this.createStreamIfMissing = options.createStreamIfMissing ?? false;\n const fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);\n this.remoteCursorStore =\n options.remoteCursorStore ?? new InMemoryRemoteCursorStore<TVersion>();\n this.reconnectConfig = {\n ...DEFAULT_RECONNECT_CONFIG,\n ...options.reconnectConfig,\n };\n this.debug = options.debug ?? false;\n this.beforeRemoteCursorSave = composeBeforeRemoteCursorSaveHooks(\n options.beforeRemoteCursorSave,\n ...(options.beforeRemoteCursorSaveHooks ?? []),\n );\n const snapshotCodec = normalizeSnapshotCodec(options.snapshotCodec);\n const snapshotUploadConfig = normalizeSnapshotUploadConfig(\n options.snapshotUpload,\n );\n this.client = new StreamsTransportClient({\n streamUrl: this.streamUrl,\n adapter: this.adapter,\n authProvider,\n fetchImpl,\n reconnectConfig: this.reconnectConfig,\n });\n this.cursorManager = new TransportCursorManager({\n adapter: this.adapter,\n decodeSnapshot: snapshotCodec?.decompress,\n saveRemoteCursor: (cursor, source) =>\n this.saveRemoteCursor(cursor, source),\n });\n this.snapshotManager = new TransportSnapshotManager({\n adapter: this.adapter,\n config: snapshotUploadConfig,\n encodeSnapshot: snapshotCodec?.compress,\n readSnapshotOffsetValue: () => this.readSnapshotOffsetValue(),\n putSnapshotAt: (snapshotOffset, snapshot) =>\n this.putSnapshotAt(snapshotOffset, snapshot),\n enqueueExclusive: (task) => this.enqueueExclusive(task),\n logDebug: (message, detail) => this.logDebug(message, detail),\n logError: (message, error, detail) =>\n this.logError(message, error, detail),\n isCurrentState: (state) => this.joinState === state,\n });\n }\n\n /**\n * Stops any active live join and releases transport-owned state.\n */\n async close(): Promise<void> {\n const state = this.joinState;\n if (state != null) {\n await this.disposeJoinState(state);\n }\n }\n\n /**\n * Resets the retry counter and immediately attempts to reconnect.\n *\n * Use this after device wake or network recovery to skip any pending\n * backoff delay. No-op when the room is already joined or no join is active.\n *\n * If the room reached `\"disconnected\"` status (only possible with a finite\n * `maxAttempts` config), this restarts the read loop.\n */\n rejoin(): void {\n const state = this.joinState;\n if (state == null || state.closed || state.status === \"joined\") {\n return;\n }\n const wasDisconnected = state.status === \"disconnected\";\n state.retryAttempt = 0;\n state.retrySleepController.abort();\n state.retrySleepController = new AbortController();\n if (wasDisconnected) {\n this.setJoinStatus(state, \"reconnecting\");\n void this.runReadLoop(state);\n }\n }\n\n /**\n * Reads the latest remote snapshot offset, if the server exposes one.\n */\n async getSnapshotOffset(): Promise<Result<string | null, TransportError>> {\n try {\n return {\n ok: true,\n value: await this.readSnapshotOffsetValue(),\n };\n } catch (error) {\n return { ok: false, error: toTransportError(error) };\n }\n }\n\n /**\n * Explicitly creates the target stream.\n */\n async createStream(): Promise<\n Result<TransportCreateStreamSuccess, TransportError>\n > {\n try {\n const created = await this.createStreamRequest();\n return { ok: true, value: { created } };\n } catch (error) {\n return { ok: false, error: toTransportError(error) };\n }\n }\n\n /**\n * Deletes the target stream and clears persisted replay state when supported by the cursor store.\n */\n async deleteStream(): Promise<\n Result<TransportDeleteStreamSuccess, TransportError>\n > {\n try {\n await this.close();\n const deleted = await this.enqueueExclusive(async () => {\n const deleted = await this.deleteStreamRequest();\n await this.remoteCursorStore.delete?.(this.streamUrl);\n this.producerEpoch = 0;\n this.nextProducerSeq = 0;\n return deleted;\n });\n return { ok: true, value: { deleted } };\n } catch (error) {\n return { ok: false, error: toTransportError(error) };\n }\n }\n\n /**\n * Runs one bootstrap/catch-up cycle without entering live mode.\n */\n async sync(): Promise<\n Result<TransportSyncSuccess<TVersion>, TransportError>\n > {\n try {\n const cursor = await this.syncOnce();\n return { ok: true, value: { cursor } };\n } catch (error) {\n return { ok: false, error: toTransportError(error) };\n }\n }\n\n /**\n * Replays remote state, flushes queued local updates, then enters live read mode.\n */\n async join(\n params?: TransportJoinParams,\n ): Promise<Result<TransportSubscription, TransportError>> {\n const existing = this.joinState;\n if (existing != null) {\n try {\n await existing.started;\n return { ok: true, value: this.createSubscription(existing, params) };\n } catch (error) {\n return { ok: false, error: toTransportError(error) };\n }\n }\n\n const initialCursor = createInitialRemoteCursor<TVersion>({\n streamUrl: this.streamUrl,\n nextOffset: \"-1\",\n serverLowerBoundVersion: this.adapter.emptyVersion(),\n });\n const state = createTransportJoinState(initialCursor);\n state.started = this.startJoin(state);\n this.joinState = state;\n try {\n await state.started;\n return { ok: true, value: this.createSubscription(state, params) };\n } catch (error) {\n await this.disposeJoinState(state);\n return { ok: false, error: toTransportError(error) };\n }\n }\n\n private createSubscription(\n state: JoinState<TVersion>,\n params?: TransportJoinParams,\n ): TransportSubscription {\n state.refCount += 1;\n const statusListener = params?.onStatusChange;\n if (statusListener != null) {\n state.statusListeners.add(statusListener);\n statusListener(state.status as TransportRoomStatus);\n }\n let unsubscribed = false;\n return {\n unsubscribe: () => {\n if (unsubscribed) {\n return;\n }\n unsubscribed = true;\n if (statusListener != null) {\n state.statusListeners.delete(statusListener);\n }\n state.refCount = Math.max(0, state.refCount - 1);\n if (state.refCount !== 0 || state.closed) {\n return;\n }\n void this.disposeJoinState(state);\n },\n get connected() {\n return state.status === \"joined\";\n },\n get status() {\n return state.status as TransportRoomStatus;\n },\n onStatusChange: (listener) => {\n state.statusListeners.add(listener);\n listener(state.status as TransportRoomStatus);\n return () => {\n state.statusListeners.delete(listener);\n };\n },\n };\n }\n\n private async disposeJoinState(state: JoinState<TVersion>): Promise<void> {\n await disposeTransportJoinState(state, {\n snapshotManager: this.snapshotManager,\n onDisposed: () => {\n if (this.joinState === state) {\n this.joinState = undefined;\n }\n },\n });\n }\n\n private async startJoin(state: JoinState<TVersion>): Promise<void> {\n try {\n state.requestController ??= new AbortController();\n const joined = await this.performInitialJoinSync(state.liveMode);\n state.cursor = joined.cursor;\n state.streamCursor = joined.streamCursor;\n state.liveMode = joined.liveMode;\n const pendingLocal = this.exportUpdates(\n joined.localExportRefVersion,\n );\n const hasQueuedPreSubscribeBatch = pendingLocal.batch != null;\n if (pendingLocal.batch != null) {\n state.pendingLocal.pushBack(pendingLocal.batch);\n }\n if (state.closed) {\n return;\n }\n state.unsubscribeLocal = this.adapter.subscribeLocalUpdates((batch) => {\n state.pendingLocal.pushBack(batch);\n void this.flushPendingLocal(state);\n });\n if (hasQueuedPreSubscribeBatch) {\n await this.flushPendingLocal(state);\n if (state.status === \"error\" || state.status === \"disconnected\") {\n throw new Error(\"join local sync failed before subscription became ready\");\n }\n }\n if (state.closed) {\n return;\n }\n this.setJoinStatus(state, \"joined\");\n void this.runReadLoop(state);\n } catch (error) {\n if (state.closed) {\n return;\n }\n this.snapshotManager.dispose(state);\n this.logError(\"join first sync failed\", error, {\n streamUrl: this.streamUrl,\n });\n this.setJoinStatus(state, \"error\");\n throw error;\n }\n }\n\n private async syncOnce(): Promise<RemoteCursor<TVersion>> {\n const loaded = await this.remoteCursorStore.load(this.streamUrl);\n let cursor =\n loaded ??\n createInitialRemoteCursor<TVersion>({\n streamUrl: this.streamUrl,\n nextOffset: \"-1\",\n serverLowerBoundVersion: this.adapter.emptyVersion(),\n });\n\n try {\n // When a cursor already exists, transport resumes from `nextOffset`\n // instead of bootstrapping. That requires the caller to have already\n // restored the matching local CRDT state for `serverLowerBoundVersion`.\n if (loaded == null) {\n cursor = await this.bootstrapIntoState(cursor);\n } else {\n cursor = (await this.catchup(cursor)).cursor;\n }\n } catch (error) {\n if (!isStreamNotFoundError(error) || !this.createStreamIfMissing) {\n throw error;\n }\n await this.createStreamRequest();\n cursor = await this.bootstrapIntoState({\n ...cursor,\n nextOffset: \"-1\",\n serverLowerBoundVersion: this.adapter.emptyVersion(),\n });\n }\n\n const localBatch = this.exportUpdates(\n cursor.serverLowerBoundVersion,\n );\n if (localBatch.batch != null) {\n cursor = await this.appendLocalBatch(cursor, localBatch.batch);\n cursor = (await this.catchup(cursor)).cursor;\n }\n return cursor;\n }\n\n private async performInitialJoinSync(\n preferredLiveMode: LiveReadMode,\n ): Promise<JoinSyncResult<TVersion>> {\n const loaded = await this.remoteCursorStore.load(this.streamUrl);\n let cursor =\n loaded ??\n createInitialRemoteCursor<TVersion>({\n streamUrl: this.streamUrl,\n nextOffset: \"-1\",\n serverLowerBoundVersion: this.adapter.emptyVersion(),\n });\n let localExportRefVersion = cursor.serverLowerBoundVersion;\n let streamCursor: string | undefined;\n let liveMode = preferredLiveMode;\n\n try {\n // Same contract as `syncOnce()`: a persisted cursor only works when the\n // caller restored the corresponding local CRDT state before joining.\n if (loaded == null) {\n cursor = await this.bootstrapIntoState(cursor);\n } else {\n const caughtUp = await this.catchup(cursor);\n cursor = caughtUp.cursor;\n streamCursor = caughtUp.streamCursor;\n }\n } catch (error) {\n if (!isStreamNotFoundError(error) || !this.createStreamIfMissing) {\n throw error;\n }\n await this.createStreamRequest();\n cursor = await this.bootstrapIntoState({\n ...cursor,\n nextOffset: \"-1\",\n serverLowerBoundVersion: this.adapter.emptyVersion(),\n });\n }\n\n localExportRefVersion = cursor.serverLowerBoundVersion;\n const exportedLocal = this.exportUpdates(localExportRefVersion);\n localExportRefVersion = exportedLocal.nextRefVersion;\n if (exportedLocal.batch != null) {\n cursor = await this.appendLocalBatch(cursor, exportedLocal.batch);\n const caughtUp = await this.catchup(cursor);\n cursor = caughtUp.cursor;\n streamCursor = caughtUp.streamCursor;\n }\n localExportRefVersion = cursor.serverLowerBoundVersion;\n\n return {\n cursor,\n streamCursor,\n liveMode,\n localExportRefVersion,\n };\n }\n\n private async bootstrapIntoState(\n cursor: RemoteCursor<TVersion>,\n ): Promise<RemoteCursor<TVersion>> {\n const result = await this.bootstrap(this.streamUrl);\n const saved = await this.cursorManager.applyBootstrapPayload(\n cursor,\n result.snapshot,\n result.updates,\n result.nextOffset,\n );\n if (!result.upToDate) {\n return (await this.catchup(saved)).cursor;\n }\n return saved;\n }\n\n private async catchup(\n cursor: RemoteCursor<TVersion>,\n live?: \"long-poll\",\n streamCursor?: string,\n onRemoteVersionApplied?: (\n previousVersion: TVersion,\n nextVersion: TVersion,\n ) => MaybePromise<void>,\n ): Promise<CursorSyncResult<TVersion>> {\n let current = cursor;\n let currentStreamCursor = streamCursor;\n while (true) {\n const requestOffset = current.nextOffset;\n const response = await this.readFromOffset(\n this.streamUrl,\n requestOffset,\n currentStreamCursor,\n live,\n );\n if (response.kind === \"gone\") {\n return {\n cursor: await this.bootstrapIntoState({\n ...current,\n nextOffset: \"-1\",\n serverLowerBoundVersion: this.adapter.emptyVersion(),\n }),\n };\n }\n const result = response.value;\n if (isReadNoProgress(requestOffset, result)) {\n throw new Error(\n `catch-up made no progress at offset ${requestOffset}; server returned empty updates and unchanged next offset with up_to_date=false`,\n );\n }\n current = await this.cursorManager.applyCatchupResult(\n current,\n result,\n onRemoteVersionApplied,\n );\n currentStreamCursor = result.streamCursor;\n if (result.upToDate) {\n return { cursor: current, streamCursor: currentStreamCursor };\n }\n }\n }\n\n private async appendLocalBatch(\n cursor: RemoteCursor<TVersion>,\n batch: CrdtUpdateBatch<TVersion>,\n ): Promise<RemoteCursor<TVersion>> {\n let producerSession: ProducerSession = {\n producerId: this.producerId,\n producerEpoch: this.producerEpoch,\n nextProducerSeq: this.nextProducerSeq,\n };\n for (let attempt = 0; attempt < 3; attempt += 1) {\n const result = await this.appendUpdates(\n this.streamUrl,\n batch.updates,\n producerSession,\n );\n if (result.kind === \"ok\") {\n this.producerEpoch = result.ackEpoch;\n this.nextProducerSeq = result.ackSeq + 1;\n const next: RemoteCursor<TVersion> = {\n ...cursor,\n nextOffset: result.nextOffset,\n serverLowerBoundVersion: this.adapter.mergeVersions(\n cursor.serverLowerBoundVersion,\n batch.version,\n ),\n };\n return await this.saveRemoteCursor(next, \"local\");\n }\n if (result.kind === \"seq-gap\") {\n producerSession = {\n ...producerSession,\n nextProducerSeq: result.expectedSeq,\n };\n continue;\n }\n producerSession = {\n ...producerSession,\n producerEpoch: result.serverEpoch + 1,\n nextProducerSeq: 0,\n };\n }\n throw new Error(\"append retry budget exhausted\");\n }\n\n private exportUpdates(fromVersion: TVersion): LocalExportResult<TVersion> {\n const exported = this.adapter.exportUpdates(fromVersion);\n if (exported == null) {\n return { nextRefVersion: fromVersion };\n }\n const nextRefVersion = this.adapter.mergeVersions(\n fromVersion,\n exported.version,\n );\n if (exported.updates.length === 0) {\n return { nextRefVersion };\n }\n return {\n batch: exported,\n nextRefVersion,\n };\n }\n\n private async applyBootstrapItems(\n cursor: RemoteCursor<TVersion>,\n items: readonly Uint8Array[],\n nextOffset: string,\n ): Promise<RemoteCursor<TVersion>> {\n return await this.cursorManager.applyBootstrapItems(\n cursor,\n items,\n nextOffset,\n );\n }\n\n private async applyRemoteItems(\n cursor: RemoteCursor<TVersion>,\n items: readonly Uint8Array[],\n nextOffset: string,\n ): Promise<RemoteCursor<TVersion>> {\n return await this.cursorManager.applyRemoteItems(cursor, items, nextOffset);\n }\n\n private async runReadLoop(state: JoinState<TVersion>): Promise<void> {\n state.requestController ??= new AbortController();\n while (!state.closed) {\n try {\n if (state.liveMode === \"long-poll\") {\n const requestOffset = state.cursor.nextOffset;\n const response = await this.readFromOffset(\n this.streamUrl,\n requestOffset,\n state.streamCursor,\n \"long-poll\",\n state.requestController?.signal,\n );\n if (response.kind === \"gone\") {\n state.cursor = await this.bootstrapIntoState({\n ...state.cursor,\n nextOffset: \"-1\",\n serverLowerBoundVersion: this.adapter.emptyVersion(),\n });\n state.streamCursor = undefined;\n state.retryAttempt = 0;\n continue;\n }\n\n const result = response.value;\n if (isReadNoProgress(requestOffset, result)) {\n throw new Error(\n `catch-up made no progress at offset ${requestOffset}; server returned empty updates and unchanged next offset with up_to_date=false`,\n );\n }\n\n await this.enqueueExclusive(async () => {\n if (state.closed) {\n return;\n }\n state.cursor = await this.cursorManager.applyLiveResult(\n state.cursor,\n requestOffset,\n result,\n (previousVersion, nextVersion) => {\n this.snapshotManager.observeRemoteVersion(\n state,\n previousVersion,\n nextVersion,\n );\n },\n );\n if (result.streamCursor != null) {\n state.streamCursor = result.streamCursor;\n }\n });\n if (state.closed) {\n return;\n }\n state.retryAttempt = 0;\n this.setJoinStatus(state, \"joined\");\n await sleep(0);\n continue;\n }\n\n const sseRequestOffset = state.cursor.nextOffset;\n const sseResult = await this.readFromOffsetSseItems(\n this.streamUrl,\n sseRequestOffset,\n state.streamCursor,\n async (updates, nextOffset, _upToDate, streamCursor) => {\n await this.enqueueExclusive(async () => {\n if (state.closed) {\n return;\n }\n state.cursor = await this.cursorManager.applyLiveResult(\n state.cursor,\n sseRequestOffset,\n { nextOffset, updates },\n (previousVersion, nextVersion) => {\n this.snapshotManager.observeRemoteVersion(\n state,\n previousVersion,\n nextVersion,\n );\n },\n );\n if (streamCursor != null) {\n state.streamCursor = streamCursor;\n }\n });\n this.setJoinStatus(state, \"joined\");\n },\n () => {\n this.setJoinStatus(state, \"joined\");\n },\n state.requestController?.signal,\n );\n if (state.closed) {\n return;\n }\n if (sseResult.kind === \"ok\") {\n state.retryAttempt = 0;\n state.streamCursor = sseResult.latestCursor;\n await sleep(0);\n continue;\n }\n if (sseResult.kind === \"unsupported\") {\n state.liveMode = \"long-poll\";\n await sleep(0);\n continue;\n }\n if (sseResult.kind === \"not-found\") {\n this.logError(\n \"live read failed\",\n new HttpError(\"stream not found\", 404),\n {\n streamUrl: this.streamUrl,\n code: \"stream_not_found\",\n },\n );\n this.setJoinStatus(state, \"error\");\n return;\n }\n state.cursor = await this.bootstrapIntoState({\n ...state.cursor,\n nextOffset: \"-1\",\n serverLowerBoundVersion: this.adapter.emptyVersion(),\n });\n state.streamCursor = undefined;\n state.retryAttempt = 0;\n } catch (error) {\n if (state.closed) {\n return;\n }\n const classified = classifyFetchError(error);\n if (!classified.retriable || isAuthOrProtocolError(error)) {\n this.logError(\"live read failed\", error, {\n streamUrl: this.streamUrl,\n code: classified.code,\n });\n this.setJoinStatus(state, \"error\");\n return;\n }\n this.setJoinStatus(state, \"reconnecting\");\n const maxAttempts = this.reconnectConfig.maxAttempts;\n if (state.retryAttempt >= maxAttempts) {\n this.logError(\"live read reconnect exhausted\", error, {\n streamUrl: this.streamUrl,\n attempts: state.retryAttempt,\n });\n this.setJoinStatus(state, \"disconnected\");\n return;\n }\n const delay = computeRetryDelay(\n state.retryAttempt,\n this.reconnectConfig,\n );\n state.retryAttempt += 1;\n await sleep(delay, state.retrySleepController.signal);\n }\n }\n }\n\n /** Maximum encoded size (bytes) for a single batched append. */\n private static readonly MAX_BATCH_BYTES = 256 * 1024;\n\n /**\n * Drain up to `MAX_BATCH_BYTES` worth of queued batches from the front of\n * `pendingLocal` and merge them into a single `CrdtUpdateBatch`.\n *\n * Returns `undefined` when the queue is empty.\n */\n private drainPendingBatch(\n state: JoinState<TVersion>,\n ): { batch: CrdtUpdateBatch<TVersion>; count: number } | undefined {\n const first = state.pendingLocal.peekFront();\n if (first == null) {\n return undefined;\n }\n\n const maxBytes = StreamsCrdt.MAX_BATCH_BYTES;\n let totalBytes = first.updates.reduce(\n (sum, u) => sum + 4 + u.byteLength,\n 0,\n );\n let mergedVersion = first.version;\n const allUpdates: Uint8Array[] = Array.from(first.updates);\n let count = 1;\n\n while (count < state.pendingLocal.length) {\n const next = state.pendingLocal.at(count)!;\n const nextBytes = next.updates.reduce(\n (sum, u) => sum + 4 + u.byteLength,\n 0,\n );\n if (totalBytes + nextBytes > maxBytes) {\n break;\n }\n allUpdates.push(...next.updates);\n totalBytes += nextBytes;\n mergedVersion = this.adapter.mergeVersions(mergedVersion, next.version);\n count += 1;\n }\n\n if (count === 1) {\n return { batch: first, count: 1 };\n }\n return { batch: { updates: allUpdates, version: mergedVersion }, count };\n }\n\n private async flushPendingLocal(state: JoinState<TVersion>): Promise<void> {\n if (state.flushingLocal || state.closed) {\n return;\n }\n state.flushingLocal = true;\n try {\n while (!state.closed) {\n const drained = this.drainPendingBatch(state);\n if (drained == null) {\n return;\n }\n let attempts = 0;\n while (!state.closed) {\n try {\n state.cursor = await this.enqueueExclusive(async () =>\n this.appendLocalBatch(state.cursor, drained.batch),\n );\n for (let i = 0; i < drained.count; i += 1) {\n state.pendingLocal.popFront();\n }\n this.setJoinStatus(state, \"joined\");\n this.snapshotManager.schedule(state);\n break;\n } catch (error) {\n const classified = classifyFetchError(error);\n if (!classified.retriable || isAuthOrProtocolError(error)) {\n this.logError(\"local append failed\", error, {\n streamUrl: this.streamUrl,\n code: classified.code,\n });\n this.setJoinStatus(state, \"error\");\n return;\n }\n const maxAttempts = this.reconnectConfig.maxAttempts;\n if (attempts >= maxAttempts) {\n this.setJoinStatus(state, \"error\");\n return;\n }\n this.setJoinStatus(state, \"reconnecting\");\n const delay = computeRetryDelay(attempts, this.reconnectConfig);\n attempts += 1;\n await sleep(delay, state.retrySleepController.signal);\n }\n }\n }\n } finally {\n state.flushingLocal = false;\n }\n }\n\n private async saveRemoteCursor(\n cursor: RemoteCursor<TVersion>,\n source: RemoteCursorSaveSource,\n ): Promise<RemoteCursor<TVersion>> {\n return await persistRemoteCursor({\n remoteCursorStore: this.remoteCursorStore,\n cursor,\n source,\n beforeRemoteCursorSave: this.beforeRemoteCursorSave,\n });\n }\n\n private setJoinStatus(\n state: JoinState<TVersion>,\n status: TransportRoomStatus,\n ): void {\n if (state.status === status) {\n return;\n }\n state.status = status;\n for (const listener of state.statusListeners) {\n listener(status);\n }\n }\n\n private async createStreamRequest(): Promise<boolean> {\n return await this.client.createStreamRequest();\n }\n\n private async deleteStreamRequest(): Promise<boolean> {\n return await this.client.deleteStreamRequest();\n }\n\n private async readFromOffsetSseItems(\n _streamUrl: string,\n offset: string,\n cursor: string | undefined,\n onControl: (\n updates: Uint8Array[],\n nextOffset: string,\n upToDate: boolean,\n streamCursor?: string,\n ) => MaybePromise<SseControlHandlerResult>,\n onOpen?: () => void,\n signal?: AbortSignal,\n ): Promise<SseItemsReadResult> {\n return await this.client.readFromOffsetSseItems(\n offset,\n cursor,\n onControl,\n onOpen,\n signal,\n );\n }\n\n private async readFromOffset(\n _streamUrl: string,\n offset: string,\n cursor?: string,\n live?: \"long-poll\",\n signal?: AbortSignal,\n ): Promise<{ kind: \"gone\" } | { kind: \"ok\"; value: ReadResult }> {\n return await this.client.readFromOffset(offset, cursor, live, signal);\n }\n\n private async bootstrap(_streamUrl: string): Promise<BootstrapResult> {\n return await this.client.bootstrap();\n }\n\n private async readSnapshotOffsetValue(): Promise<string | null> {\n return await this.client.readSnapshotOffsetValue();\n }\n\n private async putSnapshotAt(\n snapshotOffset: string,\n snapshot: Uint8Array,\n ): Promise<void> {\n await this.client.putSnapshotAt(snapshotOffset, snapshot);\n }\n\n private async appendUpdates(\n _streamUrl: string,\n updates: readonly Uint8Array[],\n producerSession: ProducerSession,\n ): Promise<AppendResult> {\n return await this.client.appendUpdates(updates, producerSession);\n }\n\n private enqueueExclusive<T>(task: () => MaybePromise<T>): Promise<T> {\n const run = this.opQueue.then(task, task);\n this.opQueue = run.then(\n () => undefined,\n () => undefined,\n );\n return run;\n }\n\n private logDebug(message: string, detail?: Record<string, unknown>): void {\n if (!this.debug) {\n return;\n }\n if (detail == null) {\n console.debug(`[streams-crdt] ${message}`);\n return;\n }\n console.debug(`[streams-crdt] ${message}`, detail);\n }\n\n private logError(\n message: string,\n error?: unknown,\n detail?: Record<string, unknown>,\n ): void {\n const payload =\n error == null\n ? detail\n : {\n ...detail,\n error: error instanceof Error ? error.message : String(error),\n };\n if (payload == null) {\n console.error(`[streams-crdt] ${message}`);\n return;\n }\n console.error(`[streams-crdt] ${message}`, payload);\n }\n}\n","const MAX_STREAM_ID_BYTES = 512;\nconst textEncoder = new TextEncoder();\nconst DEFAULT_BASE_URL = \"https://streams-api.loro.dev\";\n\nfunction utf8ByteLength(value: string): number {\n return textEncoder.encode(value).byteLength;\n}\n\n/**\n * Validates a stream id accepted by `createStreamUrl()`.\n */\nexport function isValidRillId(id: string): boolean {\n return (\n id.length > 0 &&\n utf8ByteLength(id) <= MAX_STREAM_ID_BYTES &&\n !id.includes(\"/\") &&\n !id.includes(\"\\0\") &&\n !id.includes(\"..\")\n );\n}\n\n/**\n * Validates a bucket id accepted by `createStreamUrl()`.\n */\nexport function isValidBucketId(id: string): boolean {\n return isValidRillId(id);\n}\n\n/**\n * Builds a Durable Streams HTTP URL for one `(bucketId, streamId)` pair.\n */\nexport function createStreamUrl(input: {\n bucketId: string;\n streamId: string;\n baseUrl?: string;\n}): string {\n const baseUrl = (input.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/g, \"\");\n if (!isValidBucketId(input.bucketId)) {\n throw new Error(\n `invalid bucketId: ${JSON.stringify(input.bucketId)} ` +\n `(must be non-empty UTF-8, <= ${MAX_STREAM_ID_BYTES} bytes, and exclude \"/\", \"\\\\0\", \"..\")`,\n );\n }\n if (!isValidRillId(input.streamId)) {\n throw new Error(\n `invalid streamId: ${JSON.stringify(input.streamId)} ` +\n `(must be non-empty UTF-8, <= ${MAX_STREAM_ID_BYTES} bytes, and exclude \"/\", \"\\\\0\", \"..\")`,\n );\n }\n const streamId = input.streamId;\n return `${baseUrl}/ds/${encodeURIComponent(input.bucketId)}/${encodeURIComponent(streamId)}`;\n}\n"],"mappings":"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"}
|