@abloatai/humans 0.65.0 → 0.66.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,7 +27,7 @@ export interface SocketEventHost<TCollaboration extends EventMap<TCollaboration>
27
27
  onConnectionEvent?: (event: string) => void;
28
28
  updateSyncStatus(updates: Partial<SyncStatus>): void;
29
29
  processDeltaWithBatching(delta: SyncDelta): void;
30
- applyDeltaFrame(deltas: SyncDelta[]): void;
30
+ applyDeltaFrame(deltas: SyncDelta[]): Promise<void>;
31
31
  handleBootstrapRequired(hint: BootstrapHint): void;
32
32
  handleBootstrapData(data: BootstrapDataEvent): void;
33
33
  performCredentialRefresh(): Promise<'refreshed' | 'session_error' | 'network_error'>;
@@ -77,7 +77,28 @@ export function wireSocketEvents<TCollaboration extends EventMap<TCollaboration>
77
77
  // A catch-up/reconnect frame is already complete — apply it as ONE
78
78
  // atomic flush so the gallery re-renders once, not once per 50-delta
79
79
  // chunk. See `applyDeltaFrame`.
80
- deps.applyDeltaFrame(deltas);
80
+ void deps.applyDeltaFrame(deltas).catch((error: unknown) => {
81
+ deps.updateSyncStatus({ state: 'error', error: error instanceof Error ? error : new Error(String(error)) });
82
+ });
83
+ });
84
+
85
+ let catchUpLane = Promise.resolve();
86
+ const onCatchUpChunk = deps.syncWebSocket.subscribe('catchup_chunk', (chunk) => {
87
+ catchUpLane = catchUpLane.then(async () => {
88
+ await deps.applyDeltaFrame(chunk.deltas);
89
+ // The raw position covers filtered rows too. Advance only after this
90
+ // chunk's visible rows are durable; replay is therefore idempotent.
91
+ deps.syncWebSocket.acknowledge(chunk.position);
92
+ });
93
+ void catchUpLane.catch((error: unknown) => {
94
+ deps.updateSyncStatus({ state: 'error', error: error instanceof Error ? error : new Error(String(error)) });
95
+ });
96
+ });
97
+ const onCatchUpEnd = deps.syncWebSocket.subscribe('catchup_end', (end) => {
98
+ void catchUpLane.then(() => {
99
+ deps.syncWebSocket.acknowledge(end.currentSyncId);
100
+ deps.syncWebSocket.completeCatchUp(end);
101
+ }).catch(() => undefined);
81
102
  });
82
103
 
83
104
  // Bootstrap events
@@ -181,7 +202,7 @@ export function wireSocketEvents<TCollaboration extends EventMap<TCollaboration>
181
202
 
182
203
  deps.disposers.push(
183
204
  onConnected, onDisconnected, onReconnecting,
184
- onDelta, onDeltaBatch, onBootstrapRequired,
205
+ onDelta, onDeltaBatch, onCatchUpChunk, onCatchUpEnd, onBootstrapRequired,
185
206
  onBootstrapData,
186
207
  onError, onSessionError, onHandshakeFailed, onReconnectFailed,
187
208
  () => { deps.areaOfInterest.dispose(); },