@korajs/sync 1.0.0-beta.0 → 1.0.0-beta.10

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/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as SyncScopeMap, D as DeltaCursor, a as SyncMessage, b as SerializedOperation, W as WireFormat, c as SyncTransport, T as TransportOptions, d as TransportMessageHandler, e as TransportCloseHandler, f as TransportErrorHandler, g as SyncEncryptionConfig, V as VersionedKey, Y as YjsDocUpdateMessage, Q as QueueStorage, h as SyncState, i as SyncStatusInfo, j as SyncConfig, k as SyncStatePersistence, l as SyncQuerySubset } from './transport-BMesMB6s.js';
2
- export { A as AcknowledgmentMessage, m as AwarenessStateWire, n as AwarenessUpdateMessage, E as EncryptedPayload, o as ErrorMessage, H as HandshakeMessage, p as HandshakeResponseMessage, I as InvalidScopeError, O as OperationBatchMessage, q as SYNC_STATES, r as SYNC_STATUSES, s as ScopeViolationError, t as SyncEncryptionAlgorithm, u as SyncScopeContext, v as SyncStatus, w as dedupeQuerySubsets, x as isAcknowledgmentMessage, y as isAwarenessUpdateMessage, z as isErrorMessage, B as isHandshakeMessage, C as isHandshakeResponseMessage, F as isOperationBatchMessage, G as isSyncMessage, J as isYjsDocUpdateMessage, K as operationMatchesQuerySubsets } from './transport-BMesMB6s.js';
1
+ import { S as SyncScopeMap, D as DeltaCursor, a as SyncMessage, b as SerializedOperation, W as WireFormat, c as SyncTransport, T as TransportOptions, d as TransportMessageHandler, e as TransportCloseHandler, f as TransportErrorHandler, B as BlobChunkRequestMessage, g as BlobChunkResponseMessage, h as BlobChunkPushMessage, i as SyncEncryptionConfig, V as VersionedKey, Y as YjsDocUpdateMessage, Q as QueueStorage, j as SyncState, k as SyncStatusInfo, l as SyncConfig, R as RejectedOperationStorage, m as SyncStatePersistence, n as SyncQuerySubset, o as RejectedOperation } from './transport-B2GQerqJ.js';
2
+ export { A as AcknowledgmentMessage, p as AwarenessStateWire, q as AwarenessUpdateMessage, E as EncryptedPayload, r as ErrorMessage, H as HandshakeMessage, s as HandshakeResponseMessage, I as InvalidScopeError, M as MemoryRejectedOperationStorage, O as OperationBatchMessage, t as OperationRejectedMessage, u as SYNC_STATES, v as SYNC_STATUSES, w as ScopeViolationError, x as SyncEncryptionAlgorithm, y as SyncScopeContext, z as SyncStatus, C as dedupeQuerySubsets, F as isAcknowledgmentMessage, G as isAwarenessUpdateMessage, J as isBlobChunkPushMessage, K as isBlobChunkRequestMessage, L as isBlobChunkResponseMessage, N as isErrorMessage, P as isHandshakeMessage, U as isHandshakeResponseMessage, X as isOperationBatchMessage, Z as isOperationRejectedMessage, _ as isSyncMessage, $ as isYjsDocUpdateMessage, a0 as operationMatchesQuerySubsets } from './transport-B2GQerqJ.js';
3
3
  import * as _korajs_core from '@korajs/core';
4
4
  import { Operation, VersionVector, ApplyResult, KoraEventEmitter, TimeSource, SyncError, ConnectionQuality } from '@korajs/core';
5
5
  export { ApplyFailureReason, ApplyResult } from '@korajs/core';
@@ -95,6 +95,17 @@ interface SyncStore {
95
95
  idMapping: Record<string, string>;
96
96
  rebasedCount: number;
97
97
  }>;
98
+ /**
99
+ * Optional: read a record's current materialized field values, used to backfill
100
+ * scope / query-subset fields that a partial update (or a delete) does not carry
101
+ * in its own data. Without it, such an operation would be judged out of scope by
102
+ * its changed fields alone and wrongly dropped from sync. Optional so hand-rolled
103
+ * SyncStore implementations keep working; when absent, the engine falls back to
104
+ * judging visibility from the operation's own data.
105
+ *
106
+ * @returns the record's fields, or null when it cannot be read.
107
+ */
108
+ readRecordFields?(collection: string, recordId: string): Promise<Record<string, unknown> | null>;
98
109
  }
99
110
 
100
111
  /** Prefix for handshake rejection when client schema version is unsupported. */
@@ -272,6 +283,14 @@ interface ChaosConfig {
272
283
  maxLatency?: number;
273
284
  /** Injectable random source for deterministic testing. Returns value in [0, 1). */
274
285
  randomSource?: () => number;
286
+ /**
287
+ * Deterministic targeted drop. When it returns true for a message and direction,
288
+ * that message is dropped unconditionally (independent of `dropRate`). Enables
289
+ * reproducing an exact gap (e.g. drop one specific operation) instead of relying
290
+ * on probabilistic drops. `direction` is 'outgoing' for `send` and 'incoming' for
291
+ * messages arriving from the inner transport.
292
+ */
293
+ dropPredicate?: (message: SyncMessage, direction: 'outgoing' | 'incoming') => boolean;
275
294
  }
276
295
  /**
277
296
  * Chaos transport that wraps another transport and injects faults.
@@ -287,6 +306,7 @@ declare class ChaosTransport implements SyncTransport {
287
306
  private readonly reorderRate;
288
307
  private readonly maxLatency;
289
308
  private readonly random;
309
+ private readonly dropPredicate;
290
310
  private messageHandler;
291
311
  private reorderBuffer;
292
312
  private pending;
@@ -470,6 +490,71 @@ declare class AwarenessManager {
470
490
  private emitAwarenessEvent;
471
491
  }
472
492
 
493
+ /**
494
+ * A blob-chunk message in decoded form (chunk bytes as a `Uint8Array` rather
495
+ * than the base64 wire string). This is the shape callers of the channel work
496
+ * with; the channel handles base64 encode/decode at the wire boundary.
497
+ *
498
+ * The shape mirrors `@korajs/store`'s `ChunkMessage` so an app-layer adapter can
499
+ * bridge the two with no field translation.
500
+ */
501
+ type BlobChunkChannelMessage = {
502
+ type: 'blob-chunk-request';
503
+ requestId: string;
504
+ hash: string;
505
+ } | {
506
+ type: 'blob-chunk-response';
507
+ requestId: string;
508
+ bytes: Uint8Array | null;
509
+ } | {
510
+ type: 'blob-chunk-push';
511
+ hash: string;
512
+ bytes: Uint8Array;
513
+ };
514
+ /** Encode chunk bytes to a base64 string for the JSON wire. */
515
+ declare function encodeBlobChunkBytes(bytes: Uint8Array): string;
516
+ /** Decode base64 chunk bytes from the wire back to a `Uint8Array`. */
517
+ declare function decodeBlobChunkBytes(encoded: string): Uint8Array;
518
+ interface BlobChunkChannelOptions {
519
+ /**
520
+ * Called when a local blob-chunk message should go out on the wire. The
521
+ * caller (the sync engine) decides whether the connection is ready to send.
522
+ */
523
+ onSend?: (message: BlobChunkRequestMessage | BlobChunkResponseMessage | BlobChunkPushMessage) => void;
524
+ }
525
+ /**
526
+ * Ephemeral side channel for out-of-band blob chunk transfer over the sync
527
+ * connection. Symmetric: a peer can both request chunks it needs and answer
528
+ * requests for chunks it holds. Never persisted in the operation log — durable
529
+ * state is the `BlobRef` inside a record's fields; this channel only moves the
530
+ * referenced bytes.
531
+ *
532
+ * The channel owns the base64 wire encoding so callers work purely in
533
+ * `Uint8Array`, and its {@link BlobChunkChannelMessage} shape mirrors
534
+ * `@korajs/store`'s `ChunkMessage` so the app layer can expose it as a
535
+ * `ChunkMessagePort` without translating fields.
536
+ */
537
+ declare class BlobChunkChannel {
538
+ private readonly onSend;
539
+ private readonly handlers;
540
+ constructor(options?: BlobChunkChannelOptions);
541
+ /**
542
+ * Send a blob-chunk message to the peer. Response bytes are base64-encoded
543
+ * onto the wire here; callers pass a `Uint8Array`.
544
+ */
545
+ send(message: BlobChunkChannelMessage): void;
546
+ /**
547
+ * Register a handler for inbound blob-chunk messages. Multiple handlers are
548
+ * allowed; each receives every delivered message.
549
+ */
550
+ onMessage(handler: (message: BlobChunkChannelMessage) => void): () => void;
551
+ /**
552
+ * Deliver an inbound wire message to registered handlers, decoding response
553
+ * bytes from base64 back to a `Uint8Array` first.
554
+ */
555
+ deliver(message: BlobChunkRequestMessage | BlobChunkResponseMessage | BlobChunkPushMessage): void;
556
+ }
557
+
473
558
  /**
474
559
  * Configuration for the SyncMetricsCollector.
475
560
  */
@@ -740,6 +825,13 @@ declare class OutboundQueue {
740
825
  * Acknowledge a batch, removing its operations permanently.
741
826
  */
742
827
  acknowledge(batchId: string): Promise<void>;
828
+ /**
829
+ * Acknowledge only operations in an in-flight batch whose local sequence number is
830
+ * covered by the server's ack. Any later operations return to the front of the
831
+ * queue for retry. This is required when the server accepts a prefix but rejects a
832
+ * later operation retriably (for example a stale-scope push after auth changed).
833
+ */
834
+ acknowledgeThrough(batchId: string, lastSequenceNumber: number): Promise<void>;
743
835
  /**
744
836
  * Return a failed batch to the front of the queue for retry.
745
837
  * Prepends the operations to maintain priority.
@@ -779,6 +871,14 @@ declare class OutboundQueue {
779
871
  * Whether initialize() has been called.
780
872
  */
781
873
  get isInitialized(): boolean;
874
+ /**
875
+ * Remove a single operation the server permanently rejected — from the queue,
876
+ * from any in-flight batch, and from durable storage — so a later batch ack or
877
+ * a reconnect `returnBatch` can never resend or resurrect it. Returns the
878
+ * removed operation so the caller can record it in a durable rejected store,
879
+ * or null if it was not present (already acknowledged and removed).
880
+ */
881
+ reject(opId: string): Promise<Operation | null>;
782
882
  /**
783
883
  * Remove operations by id from queue and persistent storage.
784
884
  * Used when ops were already sent during handshake delta exchange.
@@ -802,6 +902,11 @@ interface SyncEngineOptions {
802
902
  emitter?: KoraEventEmitter;
803
903
  /** Queue storage for persistent outbound queue. Defaults to in-memory. */
804
904
  queueStorage?: QueueStorage;
905
+ /**
906
+ * Durable storage for operations the server rejected. Defaults to in-memory.
907
+ * Provide a store-backed implementation so rejections survive a page refresh.
908
+ */
909
+ rejectedStorage?: RejectedOperationStorage;
805
910
  /**
806
911
  * Optional encryptor for end-to-end encryption.
807
912
  * When provided, `data` and `previousData` fields of operations are encrypted
@@ -829,6 +934,8 @@ interface SyncDiagnostics {
829
934
  pendingOperations: number;
830
935
  hasInFlightBatch: boolean;
831
936
  reconnecting: boolean;
937
+ deliveryWatermark: number;
938
+ deliveryGapRepeatCount: number;
832
939
  timestamp: number;
833
940
  }
834
941
  /**
@@ -846,10 +953,13 @@ declare class SyncEngine {
846
953
  private readonly serializer;
847
954
  private readonly emitter;
848
955
  private readonly outboundQueue;
956
+ private readonly rejectedStorage;
849
957
  private readonly batchSize;
958
+ private readonly outboundAckTimeoutMs;
850
959
  private readonly encryptor;
851
960
  private readonly awarenessManager;
852
961
  private readonly richtextDocChannel;
962
+ private readonly blobChunkChannel;
853
963
  private readonly metricsCollector;
854
964
  private readonly syncState;
855
965
  private remoteVector;
@@ -860,10 +970,16 @@ declare class SyncEngine {
860
970
  private lastSuccessfulPull;
861
971
  private conflictCount;
862
972
  private currentBatch;
973
+ private currentBatchRequiresPartialAck;
863
974
  private reconnecting;
864
975
  private schemaBlocked;
865
976
  private clockBlocked;
866
977
  private clockSkewMs;
978
+ private blobStorageEnabled;
979
+ private outboundAckTimer;
980
+ private startPromise;
981
+ private stopPromise;
982
+ private reconnectPromise;
867
983
  private deltaBatchesReceived;
868
984
  private deltaReceiveComplete;
869
985
  private deltaSendComplete;
@@ -883,15 +999,38 @@ declare class SyncEngine {
883
999
  /** Resume cursor for paginated initial sync (persisted across reconnects) */
884
1000
  private resumeDeltaCursor;
885
1001
  private initialSyncTotalBatches;
1002
+ /**
1003
+ * The delivery watermark for the CURRENT sync view: the highest server delivery
1004
+ * sequence up to which every operation in the current view (scope + active query
1005
+ * subscriptions) has been contiguously applied. Advanced only through the server's
1006
+ * gap-free delivery stream (never through live relay), so it is a durable lower bound
1007
+ * on what this client holds for this view. Reported at handshake to resume the stream.
1008
+ *
1009
+ * The watermark is keyed by view: switching views (a scope or subscription change)
1010
+ * saves the current view's watermark and loads the target view's, so returning to a
1011
+ * previously-synced view resumes exactly where it left off instead of re-syncing. This
1012
+ * is correct because a view's watermark is a lower bound specific to that view's
1013
+ * filter; a widened view is simply a different (initially unsynced) view.
1014
+ */
1015
+ private deliveryWatermark;
1016
+ /**
1017
+ * In-memory cache of watermark per view signature, preloaded from persistence at start
1018
+ * so a view switch resolves synchronously (no race with the reconnect it triggers).
1019
+ */
1020
+ private readonly deliverySignatureWatermarks;
1021
+ private deliveryGapRepeatCount;
1022
+ private lastDeliveryGapKey;
886
1023
  constructor(options: SyncEngineOptions);
887
1024
  /**
888
1025
  * Start the sync engine: connect → handshake → delta exchange → streaming.
889
1026
  */
890
1027
  start(): Promise<void>;
1028
+ private startInternal;
891
1029
  /**
892
1030
  * Stop the sync engine. Disconnects the transport.
893
1031
  */
894
1032
  stop(): Promise<void>;
1033
+ private stopInternal;
895
1034
  private ensureDisconnected;
896
1035
  /**
897
1036
  * Push a local operation to the outbound queue.
@@ -949,6 +1088,13 @@ declare class SyncEngine {
949
1088
  * or in error state, restarts the sync. If already connected, no-op.
950
1089
  */
951
1090
  retryNow(): Promise<void>;
1091
+ /**
1092
+ * Atomically refresh the transport session. Overlapping callers share one
1093
+ * reconnect, in-flight outbound batches are returned to the queue by stop(), and the
1094
+ * next start handshakes with the latest auth token, sync scope, and query subsets.
1095
+ */
1096
+ reconnect(): Promise<void>;
1097
+ private reconnectInternal;
952
1098
  /**
953
1099
  * Export a diagnostics snapshot for debugging and support tickets.
954
1100
  * Contains connection state, timing info, and queue metrics.
@@ -975,6 +1121,41 @@ declare class SyncEngine {
975
1121
  * @param scopeMap - New per-collection scope filters, or undefined to remove scope
976
1122
  */
977
1123
  updateScope(scopeMap: SyncScopeMap | undefined): void;
1124
+ /**
1125
+ * A stable identifier for the current sync view: the auth/tenant scope plus the set of
1126
+ * active query subscriptions, canonicalized so the same view always produces the same
1127
+ * string. The delivery watermark is keyed by this, so each distinct view resumes from
1128
+ * its own last position.
1129
+ */
1130
+ private deliverySignature;
1131
+ /**
1132
+ * Switch the active delivery watermark to the current view after a scope or subscription
1133
+ * change. The prior view's watermark is saved so returning to it resumes; the new view's
1134
+ * watermark is restored from the in-memory cache (0 for a never-synced view, which then
1135
+ * does a one-time resync under that view). No data is lost: a view's watermark is a lower
1136
+ * bound for that specific view's filter.
1137
+ */
1138
+ private switchDeliveryView;
1139
+ /**
1140
+ * Record a view's watermark in the in-memory cache as the most-recently-used entry (the
1141
+ * Map preserves insertion order, so re-inserting moves it to the tail), then evict cold
1142
+ * views past the retention cap. This is the single place the cache is written, so LRU
1143
+ * order and the size bound are always maintained together.
1144
+ */
1145
+ private setViewWatermark;
1146
+ /**
1147
+ * Trim the per-view watermark cache to `MAX_DELIVERY_VIEW_WATERMARKS`, evicting the
1148
+ * least-recently-used views. The default view ('') and the live view are never evicted
1149
+ * (evicting the live view would force an immediate re-scan of what we are actively
1150
+ * syncing). Each eviction also removes the persisted row, bounding storage. Safe by
1151
+ * construction: an evicted view simply back-fills from 0 (deduplicated) when next seen.
1152
+ */
1153
+ private evictColdViewWatermarks;
1154
+ /**
1155
+ * Remove a view's persisted watermark row (best-effort; a persistence layer that omits
1156
+ * the delete simply keeps the row, which is harmless).
1157
+ */
1158
+ private deleteDeliveryWatermark;
978
1159
  /**
979
1160
  * Get the currently active scope map. Returns undefined if no scope is configured.
980
1161
  */
@@ -998,6 +1179,22 @@ declare class SyncEngine {
998
1179
  * Optional side channel for incremental Yjs updates on large richtext fields.
999
1180
  */
1000
1181
  getRichtextDocChannel(): RichtextDocChannel;
1182
+ /**
1183
+ * Side channel for out-of-band blob chunk transfer over the sync connection.
1184
+ * The app layer bridges this to a `ChunkMessagePort` to pull/serve blob bytes.
1185
+ */
1186
+ getBlobChunkChannel(): BlobChunkChannel;
1187
+ /**
1188
+ * Whether the connected server persists blob bytes centrally (learned from the
1189
+ * handshake response). When true, the app uploads the bytes behind `blob`
1190
+ * fields so they stay available after the authoring device goes offline.
1191
+ */
1192
+ isBlobStorageEnabled(): boolean;
1193
+ /**
1194
+ * Upload a blob chunk (or manifest) to the server for central persistence.
1195
+ * A no-op unless connected and the server advertised blob storage.
1196
+ */
1197
+ uploadBlobChunk(hash: string, bytes: Uint8Array): void;
1001
1198
  private messageChain;
1002
1199
  private enqueueMessage;
1003
1200
  private handleMessageAsync;
@@ -1022,8 +1219,29 @@ declare class SyncEngine {
1022
1219
  private markDeltaSendCompleteIfReady;
1023
1220
  private collectDelta;
1024
1221
  private handleOperationBatch;
1222
+ /** Acknowledge a delivery batch (used for duplicates) without re-applying it. */
1223
+ private sendDeliveryAck;
1025
1224
  private handleAcknowledgment;
1026
1225
  private handleError;
1226
+ /**
1227
+ * Handle a per-operation rejection: divert the op out of the pending outbound
1228
+ * queue (so it is never retried or resurrected on reconnect), record it in the
1229
+ * durable rejected store (so it is kept and explainable), and emit an event so
1230
+ * the app can reconcile. Unlike {@link handleError}, this is a normal per-op
1231
+ * signal, so the connection stays up.
1232
+ */
1233
+ private handleOperationRejected;
1234
+ /**
1235
+ * Every operation the server rejected that has not yet been reconciled. The app
1236
+ * uses this (alongside the `sync:operation-rejected` event) to surface failed
1237
+ * submissions and decide whether to roll back or resubmit.
1238
+ */
1239
+ getRejectedOperations(): Promise<RejectedOperation[]>;
1240
+ /**
1241
+ * Forget rejected operations by id once the app has reconciled them (rolled the
1242
+ * optimistic write back or resubmitted a corrected op).
1243
+ */
1244
+ clearRejectedOperations(operationIds: string[]): Promise<void>;
1027
1245
  private checkDeltaComplete;
1028
1246
  /**
1029
1247
  * Effective server vector: persisted last-ack merged with live handshake remote vector.
@@ -1044,13 +1262,20 @@ declare class SyncEngine {
1044
1262
  */
1045
1263
  private reconcileOutboundFromOpLog;
1046
1264
  private flushQueue;
1265
+ private startOutboundAckTimer;
1266
+ private clearOutboundAckTimer;
1267
+ private handleOutboundAckTimeout;
1047
1268
  private handleAwarenessUpdate;
1048
1269
  private handleTransportClose;
1049
1270
  private handleTransportError;
1050
1271
  private transitionTo;
1051
1272
  private setSerializerWireFormat;
1052
1273
  private operationAllowedForSync;
1274
+ private matchesScopeAndSubsets;
1275
+ private readRecordForBackfill;
1276
+ private filterAllowedForSync;
1053
1277
  private persistDeltaCursor;
1278
+ private persistDeliveryWatermark;
1054
1279
  private scheduleQuerySubsetReconnect;
1055
1280
  private reconnectForQuerySubsets;
1056
1281
  }
@@ -1292,4 +1517,4 @@ declare function getRemoteAwarenessStates(awareness: AwarenessManager): Awarenes
1292
1517
  */
1293
1518
  declare function subscribeRemoteAwarenessStates(awareness: AwarenessManager, listener: (states: AwarenessState[]) => void): () => void;
1294
1519
 
1295
- export { type AwarenessChange, type AwarenessCursor, AwarenessManager, type AwarenessMessage, type AwarenessState, type AwarenessUser, type ChaosConfig, ChaosTransport, ConnectionMonitor, type ConnectionMonitorConfig, type CursorInfo, DEFAULT_RICHTEXT_DOC_CHANNEL_THRESHOLD, DecryptionError, DeltaCursor, EncryptionError, HttpLongPollingTransport, type HttpLongPollingTransportOptions, JsonMessageSerializer, KeyDerivationError, type MessageSerializer, NegotiatedMessageSerializer, OFFLINE_SYNC_STATUS, type OutboundBatch, OutboundQueue, ProtobufMessageSerializer, QueueStorage, type ReconnectionConfig, ReconnectionManager, RichtextDocChannel, type RichtextDocChannelOptions, type RichtextDocListener, SCHEMA_MISMATCH_PREFIX, SerializedOperation, SyncConfig, type SyncDiagnostics, SyncEncryptionConfig, SyncEncryptor, SyncEngine, type SyncEngineOptions, SyncMessage, SyncQuerySubset, SyncScopeMap, SyncState, SyncStatePersistence, type SyncStatusController, type SyncStatusControllerOptions, SyncStatusInfo, type SyncStore, SyncTransport, TransportCloseHandler, TransportErrorHandler, TransportMessageHandler, TransportOptions, VersionedKey, type WebSocketConstructor, type WebSocketLike, WebSocketTransport, type WebSocketTransportOptions, WireFormat, YjsDocUpdateMessage, createDeltaCursorFromBatch, createSyncStatusController, decodeDeltaCursor, decodeYjsUpdate, deriveKey, deriveVersionedKey, encodeDeltaCursor, encodeYjsUpdate, filterOperationsByScope, generateSalt, getRemoteAwarenessStates, isClientSchemaVersionSupported, isEncryptedPayload, isSchemaMismatchReject, operationMatchesScope, richtextDocKey, sliceOperationsAfterCursor, subscribeRemoteAwarenessStates, versionVectorToWire, wireToVersionVector };
1520
+ export { type AwarenessChange, type AwarenessCursor, AwarenessManager, type AwarenessMessage, type AwarenessState, type AwarenessUser, BlobChunkChannel, type BlobChunkChannelMessage, type BlobChunkChannelOptions, BlobChunkPushMessage, BlobChunkRequestMessage, BlobChunkResponseMessage, type ChaosConfig, ChaosTransport, ConnectionMonitor, type ConnectionMonitorConfig, type CursorInfo, DEFAULT_RICHTEXT_DOC_CHANNEL_THRESHOLD, DecryptionError, DeltaCursor, EncryptionError, HttpLongPollingTransport, type HttpLongPollingTransportOptions, JsonMessageSerializer, KeyDerivationError, type MessageSerializer, NegotiatedMessageSerializer, OFFLINE_SYNC_STATUS, type OutboundBatch, OutboundQueue, ProtobufMessageSerializer, QueueStorage, type ReconnectionConfig, ReconnectionManager, RejectedOperation, RejectedOperationStorage, RichtextDocChannel, type RichtextDocChannelOptions, type RichtextDocListener, SCHEMA_MISMATCH_PREFIX, SerializedOperation, SyncConfig, type SyncDiagnostics, SyncEncryptionConfig, SyncEncryptor, SyncEngine, type SyncEngineOptions, SyncMessage, SyncQuerySubset, SyncScopeMap, SyncState, SyncStatePersistence, type SyncStatusController, type SyncStatusControllerOptions, SyncStatusInfo, type SyncStore, SyncTransport, TransportCloseHandler, TransportErrorHandler, TransportMessageHandler, TransportOptions, VersionedKey, type WebSocketConstructor, type WebSocketLike, WebSocketTransport, type WebSocketTransportOptions, WireFormat, YjsDocUpdateMessage, createDeltaCursorFromBatch, createSyncStatusController, decodeBlobChunkBytes, decodeDeltaCursor, decodeYjsUpdate, deriveKey, deriveVersionedKey, encodeBlobChunkBytes, encodeDeltaCursor, encodeYjsUpdate, filterOperationsByScope, generateSalt, getRemoteAwarenessStates, isClientSchemaVersionSupported, isEncryptedPayload, isSchemaMismatchReject, operationMatchesScope, richtextDocKey, sliceOperationsAfterCursor, subscribeRemoteAwarenessStates, versionVectorToWire, wireToVersionVector };