@edryslabs/genericprovider 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +660 -0
  3. package/dist/index.d.ts +323 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +1001 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib.d.ts +36 -0
  8. package/dist/lib.d.ts.map +1 -0
  9. package/dist/lib.js +37 -0
  10. package/dist/lib.js.map +1 -0
  11. package/dist/providers/dummy/index.d.ts +226 -0
  12. package/dist/providers/dummy/index.d.ts.map +1 -0
  13. package/dist/providers/dummy/index.js +326 -0
  14. package/dist/providers/dummy/index.js.map +1 -0
  15. package/dist/providers/gun/index.d.ts +269 -0
  16. package/dist/providers/gun/index.d.ts.map +1 -0
  17. package/dist/providers/gun/index.js +683 -0
  18. package/dist/providers/gun/index.js.map +1 -0
  19. package/dist/providers/indexeddb/index.d.ts +161 -0
  20. package/dist/providers/indexeddb/index.d.ts.map +1 -0
  21. package/dist/providers/indexeddb/index.js +369 -0
  22. package/dist/providers/indexeddb/index.js.map +1 -0
  23. package/dist/providers/matrix/index.d.ts +109 -0
  24. package/dist/providers/matrix/index.d.ts.map +1 -0
  25. package/dist/providers/matrix/index.js +329 -0
  26. package/dist/providers/matrix/index.js.map +1 -0
  27. package/dist/providers/nostr/index.d.ts +172 -0
  28. package/dist/providers/nostr/index.d.ts.map +1 -0
  29. package/dist/providers/nostr/index.js +280 -0
  30. package/dist/providers/nostr/index.js.map +1 -0
  31. package/dist/providers/peerjs/index.d.ts +231 -0
  32. package/dist/providers/peerjs/index.d.ts.map +1 -0
  33. package/dist/providers/peerjs/index.js +1038 -0
  34. package/dist/providers/peerjs/index.js.map +1 -0
  35. package/dist/providers/pubnub/index.d.ts +106 -0
  36. package/dist/providers/pubnub/index.d.ts.map +1 -0
  37. package/dist/providers/pubnub/index.js +357 -0
  38. package/dist/providers/pubnub/index.js.map +1 -0
  39. package/dist/providers/simple-peer/index.d.ts +253 -0
  40. package/dist/providers/simple-peer/index.d.ts.map +1 -0
  41. package/dist/providers/simple-peer/index.js +783 -0
  42. package/dist/providers/simple-peer/index.js.map +1 -0
  43. package/dist/providers/supabase/index.d.ts +80 -0
  44. package/dist/providers/supabase/index.d.ts.map +1 -0
  45. package/dist/providers/supabase/index.js +202 -0
  46. package/dist/providers/supabase/index.js.map +1 -0
  47. package/dist/providers/trystero/index.d.ts +181 -0
  48. package/dist/providers/trystero/index.d.ts.map +1 -0
  49. package/dist/providers/trystero/index.js +187 -0
  50. package/dist/providers/trystero/index.js.map +1 -0
  51. package/dist/providers/websocket/index.d.ts +92 -0
  52. package/dist/providers/websocket/index.d.ts.map +1 -0
  53. package/dist/providers/websocket/index.js +272 -0
  54. package/dist/providers/websocket/index.js.map +1 -0
  55. package/dist/sync-monitor.d.ts +90 -0
  56. package/dist/sync-monitor.d.ts.map +1 -0
  57. package/dist/sync-monitor.js +149 -0
  58. package/dist/sync-monitor.js.map +1 -0
  59. package/dist/transport.d.ts +116 -0
  60. package/dist/transport.d.ts.map +1 -0
  61. package/dist/transport.js +2 -0
  62. package/dist/transport.js.map +1 -0
  63. package/package.json +137 -0
@@ -0,0 +1,323 @@
1
+ import * as Y from 'yjs';
2
+ import * as awarenessProtocol from 'y-protocols/awareness';
3
+ import { Observable } from 'lib0/observable';
4
+ import type { Transport, ConnectionConfig, ConnectionStatus } from './transport';
5
+ /**
6
+ * PubSub channel for real-time messaging alongside Yjs.
7
+ * Allows sending ephemeral messages that don't need CRDT properties.
8
+ */
9
+ export declare class PubSubChannel extends Observable<string> {
10
+ private provider;
11
+ constructor(provider: GenericProvider);
12
+ /**
13
+ * Publish a message to a topic.
14
+ *
15
+ * @param topic - Topic name (e.g., 'notifications', 'rpc', 'events')
16
+ * @param message - Any JSON-serializable data
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * provider.pubsub.publish('chat', { user: 'Alice', text: 'Hello!' })
21
+ * provider.pubsub.publish('cursor', { x: 100, y: 200 })
22
+ * ```
23
+ */
24
+ publish(topic: string, message: any): void;
25
+ /**
26
+ * Publish a message to a single target instead of broadcasting.
27
+ *
28
+ * On transports with `sendTo`, `target` is the peer's ID and delivery is
29
+ * direct. On transports without it, the message is broadcast with the
30
+ * target embedded and dropped by every provider whose `localId` differs.
31
+ *
32
+ * @param target - Recipient id (transport peerId, or a `localId`)
33
+ * @param topic - Topic name
34
+ * @param message - Any JSON-serializable data
35
+ */
36
+ publishTo(target: string, topic: string, message: any): void;
37
+ /**
38
+ * Subscribe to messages on a topic.
39
+ *
40
+ * @param topic - Topic name to listen to (use '*' for all topics)
41
+ * @param callback - Function called when message received
42
+ * @returns Unsubscribe function
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * const unsub = provider.pubsub.subscribe('chat', (msg) => {
47
+ * console.log('Chat:', msg)
48
+ * })
49
+ *
50
+ * // Later: unsub()
51
+ * ```
52
+ */
53
+ subscribe(topic: string, callback: (message: any, topic: string) => void): () => void;
54
+ /**
55
+ * Internal: Handle incoming pub/sub message
56
+ */
57
+ _handleMessage(topic: string, message: any): void;
58
+ }
59
+ /**
60
+ * Generic Yjs provider that works with any transport implementation.
61
+ *
62
+ * This provider handles all Yjs synchronization logic including:
63
+ * - Document updates (automatic sync)
64
+ * - Awareness protocol (presence, cursors, etc.)
65
+ * - State vector synchronization
66
+ * - Optional pub/sub channel for real-time messaging
67
+ *
68
+ * You only need to implement the Transport interface for your backend.
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * // Create your transport
73
+ * const transport = new MyCustomTransport()
74
+ *
75
+ * // Create provider with Yjs document
76
+ * const doc = new Y.Doc()
77
+ * const provider = new GenericProvider(doc, transport)
78
+ *
79
+ * // Connect
80
+ * await provider.connect({ room: 'my-room' })
81
+ *
82
+ * // Provider automatically syncs all changes
83
+ * const ytext = doc.getText('content')
84
+ * ytext.insert(0, 'Hello') // Automatically synced!
85
+ * ```
86
+ */
87
+ export declare class GenericProvider extends Observable<string> {
88
+ readonly doc: Y.Doc;
89
+ readonly transport: Transport;
90
+ readonly awareness: awarenessProtocol.Awareness;
91
+ readonly pubsub: PubSubChannel;
92
+ private _status;
93
+ private _synced;
94
+ private _destroying;
95
+ private _syncInterval;
96
+ private _syncIntervalId?;
97
+ private _verifyUpdates;
98
+ private _disableBc;
99
+ private _bcChannel;
100
+ private _bcConnected;
101
+ private _bcSubscriber?;
102
+ private _hashMismatchCount;
103
+ private _lastHashMismatchTime;
104
+ private _syncRequestTimes;
105
+ private _maxSyncRequestsPerWindow;
106
+ private _syncRequestWindowMs;
107
+ private _localSeqNum;
108
+ private _remoteSeqNums;
109
+ private _corruptedMessageCount;
110
+ private _lastCorruptedMessageTime;
111
+ private _batchUpdates;
112
+ private _pendingUpdate;
113
+ private _batchTimeoutId?;
114
+ private _awarenessInterval;
115
+ private _pendingAwarenessClients;
116
+ private _awarenessTimeoutId?;
117
+ private _lastAwarenessTime;
118
+ private _excludeOrigins;
119
+ private _localId?;
120
+ private _syncMode;
121
+ private _updateHandler?;
122
+ private _awarenessUpdateHandler?;
123
+ private _unsubscribeTransport?;
124
+ private _beforeUnloadHandler?;
125
+ /**
126
+ * Create a new generic provider.
127
+ *
128
+ * @param doc - The Yjs document to sync
129
+ * @param transport - Transport implementation for your backend
130
+ * @param options - Optional configuration
131
+ */
132
+ constructor(doc: Y.Doc, transport: Transport, options?: {
133
+ awareness?: awarenessProtocol.Awareness;
134
+ /**
135
+ * Interval in milliseconds for periodic sync retries.
136
+ * Helps recover from packet loss. Set to 0 to disable.
137
+ * @default 5000
138
+ */
139
+ syncInterval?: number;
140
+ /**
141
+ * Send document hash with each update for immediate desync detection.
142
+ * When enabled, mismatch triggers instant re-sync instead of waiting.
143
+ * @default true
144
+ */
145
+ verifyUpdates?: boolean;
146
+ /**
147
+ * Batch (debounce) document updates to reduce network traffic.
148
+ * Updates are collected and sent after this delay in milliseconds.
149
+ * Set to 0 to send updates immediately (no batching).
150
+ * Recommended: 50-200ms for good balance between latency and efficiency.
151
+ * @default 0 (disabled - immediate transmission)
152
+ */
153
+ batchUpdates?: number;
154
+ /**
155
+ * Disable BroadcastChannel for cross-tab communication.
156
+ * When enabled (default), updates are shared instantly between tabs
157
+ * in the same browser without going through the network transport.
158
+ * Automatically disabled in non-browser environments (e.g., Node.js).
159
+ * @default false (BroadcastChannel enabled)
160
+ */
161
+ disableBc?: boolean;
162
+ /**
163
+ * Throttle awareness updates to reduce network traffic.
164
+ * Awareness updates (cursors, presence) are batched and sent at this interval.
165
+ * Set to 0 for immediate transmission (not recommended for high-frequency updates).
166
+ * This prevents awareness from flooding document sync on limited transports.
167
+ * @default 100 (100ms between awareness broadcasts)
168
+ */
169
+ awarenessInterval?: number;
170
+ /**
171
+ * Transaction origins whose updates should not be sent to peers.
172
+ * Updates from these origins stay local (never reach the transport).
173
+ * @default [] (no origins excluded)
174
+ */
175
+ excludeOrigins?: any[];
176
+ /**
177
+ * This provider's identity for targeted pubsub (publishTo).
178
+ * On transports without sendTo, targeted messages are broadcast and
179
+ * dropped unless their target matches this id.
180
+ */
181
+ localId?: string;
182
+ /**
183
+ * Connect-time sync strategy.
184
+ * - 'push-pull' (default): push full local state to peers, then request
185
+ * remote state. Correct for P2P transports where there is no
186
+ * authoritative peer to pull from (e.g. offline edits must be pushed).
187
+ * - 'pull': only request remote state on connect (SyncStep1), never push
188
+ * full local state. Use with relay/server transports (e.g. y-websocket)
189
+ * where the server holds authoritative state and a reconnecting client
190
+ * should adopt it rather than push a competing local copy.
191
+ * @default 'push-pull'
192
+ */
193
+ syncMode?: 'push-pull' | 'pull';
194
+ });
195
+ /**
196
+ * Connect to the backend and start syncing.
197
+ *
198
+ * @param config - Connection configuration passed to transport
199
+ */
200
+ connect(config: ConnectionConfig): Promise<void>;
201
+ /**
202
+ * Disconnect from the backend.
203
+ * The provider can be reconnected later with connect().
204
+ */
205
+ disconnect(): void;
206
+ /**
207
+ * Destroy the provider permanently.
208
+ * Removes all event listeners and cleans up resources.
209
+ */
210
+ destroy(): void;
211
+ /**
212
+ * Current connection status
213
+ */
214
+ get status(): ConnectionStatus;
215
+ /**
216
+ * Whether the provider is connected to the backend
217
+ */
218
+ get connected(): boolean;
219
+ /**
220
+ * Whether BroadcastChannel is connected for cross-tab sync
221
+ */
222
+ get bcConnected(): boolean;
223
+ /**
224
+ * Whether the document is synced with remote peers
225
+ */
226
+ get synced(): boolean;
227
+ /**
228
+ * Force an immediate sync with remote peers.
229
+ * Useful after network interruptions or to manually trigger re-sync.
230
+ */
231
+ syncNow(): void;
232
+ /**
233
+ * Setup automatic document synchronization.
234
+ * Listens to document updates and sends them to the transport.
235
+ * If batchUpdates is enabled, updates are debounced/batched.
236
+ */
237
+ private _setupDocumentSync;
238
+ /**
239
+ * Batch/debounce updates to reduce network traffic.
240
+ * Merges multiple updates and sends after delay.
241
+ */
242
+ private _batchUpdate;
243
+ /**
244
+ * Setup automatic awareness synchronization.
245
+ * Listens to awareness changes and broadcasts them.
246
+ */
247
+ private _setupAwarenessSync;
248
+ /**
249
+ * Handle incoming messages from the transport.
250
+ * Verifies message integrity with CRC32 before processing.
251
+ * Corrupt messages are rejected immediately without attempting to decode.
252
+ */
253
+ private _handleIncomingMessage;
254
+ /**
255
+ * Send SyncStep1 message to request missing updates.
256
+ * This is sent when first connecting to sync with remote peers.
257
+ * Note: SyncStep1 is just a request and doesn't include hash verification.
258
+ * Rate limited to prevent spam.
259
+ */
260
+ private _sendSyncStep1;
261
+ /**
262
+ * Send a document update to the transport.
263
+ * If verifyUpdates is enabled, includes sequence number and document hash for ordering and desync detection.
264
+ */
265
+ private _sendUpdate;
266
+ /**
267
+ * Send awareness update to the transport.
268
+ */
269
+ private _sendAwarenessUpdate;
270
+ /**
271
+ * Send a pub/sub message.
272
+ * Internal method called by PubSubChannel.
273
+ */
274
+ _sendPubSub(topic: string, message: any): void;
275
+ /**
276
+ * Send a targeted pub/sub message.
277
+ * Uses transport.sendTo when available (direct delivery), otherwise
278
+ * broadcasts a targeted frame that non-target providers drop.
279
+ * Internal method called by PubSubChannel.
280
+ */
281
+ _sendPubSubTo(target: string, topic: string, message: any): void;
282
+ /**
283
+ * Broadcast awareness state for the specified clients.
284
+ * Throttled to prevent awareness updates from flooding document sync.
285
+ * Multiple rapid updates are batched together.
286
+ */
287
+ private _broadcastAwareness;
288
+ /**
289
+ * Send awareness update immediately without throttling.
290
+ */
291
+ private _sendAwarenessNow;
292
+ /**
293
+ * Setup BroadcastChannel for cross-tab communication.
294
+ * Automatically disabled in non-browser environments.
295
+ */
296
+ private _setupBroadcastChannel;
297
+ /**
298
+ * Disconnect from BroadcastChannel and mark local client as offline.
299
+ */
300
+ private _disconnectBroadcastChannel;
301
+ /**
302
+ * Send data through both BroadcastChannel (if connected) and transport.
303
+ * All messages are wrapped with CRC32 checksum for integrity verification.
304
+ * This ensures updates reach both local tabs and remote peers with corruption detection.
305
+ */
306
+ private _send;
307
+ /**
308
+ * Update connection status and emit event.
309
+ */
310
+ private _setStatus;
311
+ /**
312
+ * TEST HELPER: Set local sequence number to a specific value.
313
+ * Used for testing sequence number overflow scenarios.
314
+ * @internal
315
+ */
316
+ _testSetSequenceNumber(seqNum: number): void;
317
+ /**
318
+ * TEST HELPER: Get current local sequence number.
319
+ * @internal
320
+ */
321
+ _testGetSequenceNumber(): number;
322
+ }
323
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}