@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,187 @@
1
+ /**
2
+ * Trystero Transport Provider
3
+ *
4
+ * Serverless peer-to-peer transport using Trystero with multiple strategies.
5
+ * Trystero uses decentralized infrastructure for peer discovery while keeping
6
+ * all data transmission direct and end-to-end encrypted.
7
+ *
8
+ * Features:
9
+ * - Zero server setup required
10
+ * - Multiple strategies: Nostr, BitTorrent, MQTT, Supabase, Firebase, IPFS
11
+ * - End-to-end encrypted P2P connections
12
+ * - Automatic chunking and serialization
13
+ * - Session encryption via AES-GCM
14
+ * - Optional TURN server support
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { GenericProvider } from 'y-generic'
19
+ * import { TrysteroTransport } from 'y-generic/providers/trystero'
20
+ * import { joinRoom } from 'trystero/nostr' // or other strategy
21
+ *
22
+ * const doc = new Y.Doc()
23
+ * const transport = new TrysteroTransport({
24
+ * joinRoom,
25
+ * appId: 'my-unique-app-id'
26
+ * })
27
+ * const provider = new GenericProvider(doc, transport)
28
+ * await provider.connect({ room: 'my-room' })
29
+ * ```
30
+ */
31
+ /**
32
+ * Trystero transport implementation.
33
+ * Creates serverless P2P connections using Trystero library.
34
+ */
35
+ export class TrysteroTransport {
36
+ constructor(options) {
37
+ this._connected = false;
38
+ this._room = '';
39
+ this.room = null;
40
+ this.sendUpdate = null;
41
+ this.peers = new Set();
42
+ this.options = {
43
+ debug: false,
44
+ ...options,
45
+ };
46
+ }
47
+ log(message, level = 'info') {
48
+ if (this.options.debug) {
49
+ const prefix = '[TrysteroTransport]';
50
+ switch (level) {
51
+ case 'error':
52
+ console.error(prefix, message);
53
+ break;
54
+ case 'warn':
55
+ console.warn(prefix, message);
56
+ break;
57
+ default:
58
+ console.log(prefix, message);
59
+ }
60
+ }
61
+ }
62
+ get isConnected() {
63
+ return this._connected;
64
+ }
65
+ async connect(config) {
66
+ if (this._connected) {
67
+ this.log('Already connected, disconnecting first...');
68
+ this.disconnect();
69
+ }
70
+ const room = config.room;
71
+ if (!room) {
72
+ throw new Error('Room ID is required');
73
+ }
74
+ this._room = room;
75
+ this.log(`Connecting to room: ${room}`);
76
+ // Build Trystero config
77
+ const trysteroConfig = {
78
+ appId: this.options.appId,
79
+ };
80
+ // Add optional config
81
+ if (this.options.password)
82
+ trysteroConfig.password = this.options.password;
83
+ if (this.options.relayUrls)
84
+ trysteroConfig.relayUrls = this.options.relayUrls;
85
+ if (this.options.relayRedundancy)
86
+ trysteroConfig.relayRedundancy = this.options.relayRedundancy;
87
+ if (this.options.rtcConfig)
88
+ trysteroConfig.rtcConfig = this.options.rtcConfig;
89
+ if (this.options.turnConfig)
90
+ trysteroConfig.turnConfig = this.options.turnConfig;
91
+ if (this.options.rtcPolyfill)
92
+ trysteroConfig.rtcPolyfill = this.options.rtcPolyfill;
93
+ if (this.options.supabaseKey)
94
+ trysteroConfig.supabaseKey = this.options.supabaseKey;
95
+ if (this.options.firebaseApp)
96
+ trysteroConfig.firebaseApp = this.options.firebaseApp;
97
+ if (this.options.rootPath)
98
+ trysteroConfig.rootPath = this.options.rootPath;
99
+ if (this.options.manualRelayReconnection !== undefined) {
100
+ trysteroConfig.manualRelayReconnection =
101
+ this.options.manualRelayReconnection;
102
+ }
103
+ // Join room with error handler
104
+ this.room = this.options.joinRoom(trysteroConfig, room, (details) => {
105
+ this.log(`Join error: ${details.error}`, 'error');
106
+ if (this.onJoinErrorCallback) {
107
+ this.onJoinErrorCallback(details);
108
+ }
109
+ });
110
+ // Create action for Yjs updates
111
+ const [send, receive] = this.room.makeAction('yjs-update');
112
+ this.sendUpdate = send;
113
+ // Listen for incoming updates
114
+ receive((data, peerId) => {
115
+ this.log(`Received update from ${peerId} (${data.byteLength} bytes)`);
116
+ if (this._callback) {
117
+ // Convert ArrayBuffer to Uint8Array
118
+ this._callback(new Uint8Array(data));
119
+ }
120
+ });
121
+ // Track peers
122
+ this.room.onPeerJoin((peerId) => {
123
+ this.peers.add(peerId);
124
+ this.log(`Peer joined: ${peerId} (${this.peers.size} total)`);
125
+ });
126
+ this.room.onPeerLeave((peerId) => {
127
+ this.peers.delete(peerId);
128
+ this.log(`Peer left: ${peerId} (${this.peers.size} remaining)`);
129
+ });
130
+ this._connected = true;
131
+ this.log(`✅ Connected to room: ${room}`);
132
+ }
133
+ disconnect() {
134
+ if (!this._connected) {
135
+ return;
136
+ }
137
+ this.log('Disconnecting...');
138
+ if (this.room) {
139
+ this.room.leave();
140
+ this.room = null;
141
+ }
142
+ this.sendUpdate = null;
143
+ this._callback = undefined;
144
+ this._connected = false;
145
+ this.peers.clear();
146
+ this.log('✅ Disconnected');
147
+ }
148
+ async send(data) {
149
+ if (!this._connected || !this.sendUpdate) {
150
+ this.log('⚠️ Not connected, cannot send', 'warn');
151
+ return;
152
+ }
153
+ // Send to all peers (null = broadcast)
154
+ this.log(`Sending update (${data.byteLength} bytes) to ${this.peers.size} peers`);
155
+ await this.sendUpdate(data, null);
156
+ }
157
+ onMessage(callback) {
158
+ this._callback = callback;
159
+ this.log('Message callback registered');
160
+ return () => {
161
+ this._callback = undefined;
162
+ this.log('Message callback unregistered');
163
+ };
164
+ }
165
+ /**
166
+ * Set a callback for join errors (optional).
167
+ */
168
+ onJoinError(callback) {
169
+ this.onJoinErrorCallback = callback;
170
+ }
171
+ /**
172
+ * Get the set of connected peer IDs.
173
+ */
174
+ getPeers() {
175
+ return new Set(this.peers);
176
+ }
177
+ /**
178
+ * Ping a peer and get round-trip time in ms.
179
+ */
180
+ async ping(peerId) {
181
+ if (!this.room) {
182
+ throw new Error('Not connected to a room');
183
+ }
184
+ return await this.room.ping(peerId);
185
+ }
186
+ }
187
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/providers/trystero/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAqJH;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IAY5B,YAAY,OAAiC;QAVrC,eAAU,GAAY,KAAK,CAAA;QAC3B,UAAK,GAAW,EAAE,CAAA;QAElB,SAAI,GAAwB,IAAI,CAAA;QAChC,eAAU,GAEP,IAAI,CAAA;QACP,UAAK,GAAgB,IAAI,GAAG,EAAE,CAAA;QAIpC,IAAI,CAAC,OAAO,GAAG;YACb,KAAK,EAAE,KAAK;YACZ,GAAG,OAAO;SACX,CAAA;IACH,CAAC;IAEO,GAAG,CACT,OAAe,EACf,QAAmC,MAAM;QAEzC,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,qBAAqB,CAAA;YACpC,QAAQ,KAAK,EAAE,CAAC;gBACd,KAAK,OAAO;oBACV,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;oBAC9B,MAAK;gBACP,KAAK,MAAM;oBACT,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;oBAC7B,MAAK;gBACP;oBACE,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;YAChC,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,UAAU,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,MAAwB;QACpC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAA;YACrD,IAAI,CAAC,UAAU,EAAE,CAAA;QACnB,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAA;QACxB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;QACxC,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;QACjB,IAAI,CAAC,GAAG,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAA;QAEvC,wBAAwB;QACxB,MAAM,cAAc,GAAmB;YACrC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;SAC1B,CAAA;QAED,sBAAsB;QACtB,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ;YAAE,cAAc,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAA;QAC1E,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS;YACxB,cAAc,CAAC,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAA;QACnD,IAAI,IAAI,CAAC,OAAO,CAAC,eAAe;YAC9B,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAA;QAC/D,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS;YACxB,cAAc,CAAC,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAA;QACnD,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU;YACzB,cAAc,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAA;QACrD,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW;YAC1B,cAAc,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAA;QACvD,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW;YAC1B,cAAc,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAA;QACvD,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW;YAC1B,cAAc,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAA;QACvD,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ;YAAE,cAAc,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAA;QAC1E,IAAI,IAAI,CAAC,OAAO,CAAC,uBAAuB,KAAK,SAAS,EAAE,CAAC;YACvD,cAAc,CAAC,uBAAuB;gBACpC,IAAI,CAAC,OAAO,CAAC,uBAAuB,CAAA;QACxC,CAAC;QAED,+BAA+B;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;YAClE,IAAI,CAAC,GAAG,CAAC,eAAe,OAAO,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAA;YACjD,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAC7B,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAA;YACnC,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,gCAAgC;QAChC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAA;QAC1D,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;QAEtB,8BAA8B;QAC9B,OAAO,CAAC,CAAC,IAAiB,EAAE,MAAc,EAAE,EAAE;YAC5C,IAAI,CAAC,GAAG,CAAC,wBAAwB,MAAM,KAAK,IAAI,CAAC,UAAU,SAAS,CAAC,CAAA;YACrE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACnB,oCAAoC;gBACpC,IAAI,CAAC,SAAS,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAA;YACtC,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,cAAc;QACd,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,EAAE;YAC9B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACtB,IAAI,CAAC,GAAG,CAAC,gBAAgB,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,CAAA;QAC/D,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,EAAE;YAC/B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YACzB,IAAI,CAAC,GAAG,CAAC,cAAc,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,aAAa,CAAC,CAAA;QACjE,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;QACtB,IAAI,CAAC,GAAG,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAA;IAC1C,CAAC;IAED,UAAU;QACR,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,OAAM;QACR,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;QAE5B,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;YACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAClB,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;QACtB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAC1B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAA;QACvB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;QAElB,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAgB;QACzB,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACzC,IAAI,CAAC,GAAG,CAAC,+BAA+B,EAAE,MAAM,CAAC,CAAA;YACjD,OAAM;QACR,CAAC;QAED,uCAAuC;QACvC,IAAI,CAAC,GAAG,CACN,mBAAmB,IAAI,CAAC,UAAU,cAAc,IAAI,CAAC,KAAK,CAAC,IAAI,QAAQ,CACxE,CAAA;QACD,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IACnC,CAAC;IAED,SAAS,CAAC,QAAoC;QAC5C,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAA;QACzB,IAAI,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;QAEvC,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;YAC1B,IAAI,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAA;QAC3C,CAAC,CAAA;IACH,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,QAAgC;QAC1C,IAAI,CAAC,mBAAmB,GAAG,QAAQ,CAAA;IACrC,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC5B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI,CAAC,MAAc;QACvB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAA;QAC5C,CAAC;QACD,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACrC,CAAC;CACF"}
@@ -0,0 +1,92 @@
1
+ import type { Transport, ConnectionConfig } from '../../transport';
2
+ /**
3
+ * WebSocket transport configuration
4
+ */
5
+ export interface WebSocketConfig extends ConnectionConfig {
6
+ /** WebSocket server URL (required) e.g., 'ws://localhost:1234' or 'wss://example.com' */
7
+ serverUrl: string;
8
+ /** Enable automatic reconnection on disconnect (default: true) */
9
+ autoReconnect?: boolean;
10
+ /** Reconnection delay in milliseconds (default: 2000) */
11
+ reconnectDelay?: number;
12
+ /** Maximum reconnection attempts (0 = infinite, default: 0) */
13
+ maxReconnectAttempts?: number;
14
+ /** WebSocket protocols (optional) */
15
+ protocols?: string | string[];
16
+ /** Enable debug logging */
17
+ debug?: boolean;
18
+ }
19
+ /**
20
+ * WebSocket Transport for Yjs
21
+ *
22
+ * Provides real-time synchronization using WebSocket connections.
23
+ *
24
+ * Features:
25
+ * - Direct WebSocket connection to server
26
+ * - Room-based collaboration
27
+ * - Automatic reconnection
28
+ * - Binary message support
29
+ * - Low latency real-time sync
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * import * as Y from 'yjs'
34
+ * import { GenericProvider } from 'y-generic'
35
+ * import { WebSocketTransport } from 'y-generic/providers/websocket'
36
+ *
37
+ * const doc = new Y.Doc()
38
+ * const transport = new WebSocketTransport()
39
+ *
40
+ * const provider = new GenericProvider(doc, transport)
41
+ * await provider.connect({
42
+ * serverUrl: 'ws://localhost:1234',
43
+ * room: 'my-room'
44
+ * })
45
+ * ```
46
+ */
47
+ export declare class WebSocketTransport implements Transport {
48
+ private ws;
49
+ private config;
50
+ private messageCallback?;
51
+ private _isConnected;
52
+ private debug;
53
+ private reconnectAttempts;
54
+ private reconnectTimer?;
55
+ private intentionalDisconnect;
56
+ private messageQueue;
57
+ private receivedBuffer;
58
+ get isConnected(): boolean;
59
+ /**
60
+ * Connect to WebSocket server
61
+ */
62
+ connect(config: WebSocketConfig): Promise<void>;
63
+ /**
64
+ * Disconnect from WebSocket server
65
+ */
66
+ disconnect(): void;
67
+ /**
68
+ * Send data to server
69
+ */
70
+ send(data: Uint8Array): void;
71
+ /**
72
+ * Register message callback
73
+ */
74
+ onMessage(callback: (data: Uint8Array) => void): () => void;
75
+ /**
76
+ * Handle incoming WebSocket message
77
+ */
78
+ private handleMessage;
79
+ /**
80
+ * Flush queued messages
81
+ */
82
+ private flushMessageQueue;
83
+ /**
84
+ * Attempt to reconnect
85
+ */
86
+ private attemptReconnect;
87
+ /**
88
+ * Debug logging
89
+ */
90
+ private log;
91
+ }
92
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/websocket/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AA6ClE;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,yFAAyF;IACzF,SAAS,EAAE,MAAM,CAAA;IACjB,kEAAkE;IAClE,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,+DAA+D;IAC/D,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAC7B,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,kBAAmB,YAAW,SAAS;IAClD,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,eAAe,CAAC,CAA4B;IACpD,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,iBAAiB,CAAY;IACrC,OAAO,CAAC,cAAc,CAAC,CAA+B;IACtD,OAAO,CAAC,qBAAqB,CAAiB;IAC9C,OAAO,CAAC,YAAY,CAAmB;IACvC,OAAO,CAAC,cAAc,CAAmB;IAEzC,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;OAEG;IACG,OAAO,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAgFrD;;OAEG;IACH,UAAU,IAAI,IAAI;IAiBlB;;OAEG;IACH,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAiB5B;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI;IAmB3D;;OAEG;IACH,OAAO,CAAC,aAAa;IAwBrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAYzB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA0BxB;;OAEG;IACH,OAAO,CAAC,GAAG;CAKZ"}
@@ -0,0 +1,272 @@
1
+ // ---------------------------------------------------------------------------
2
+ // CRC32 translation helpers
3
+ //
4
+ // GenericProvider wraps every message as [CRC32 (4 bytes)][payload] before
5
+ // calling transport.send(), and expects the same format from onMessage().
6
+ // The y-websocket server however speaks plain Yjs wire format (no header).
7
+ // These helpers translate between the two worlds at the transport boundary.
8
+ // ---------------------------------------------------------------------------
9
+ const _CRC32_TABLE = (() => {
10
+ const table = new Uint32Array(256);
11
+ for (let i = 0; i < 256; i++) {
12
+ let c = i;
13
+ for (let j = 0; j < 8; j++)
14
+ c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
15
+ table[i] = c;
16
+ }
17
+ return table;
18
+ })();
19
+ function _crc32(data) {
20
+ let crc = 0xffffffff;
21
+ for (let i = 0; i < data.length; i++)
22
+ crc = (crc >>> 8) ^ _CRC32_TABLE[(crc ^ data[i]) & 0xff];
23
+ return (crc ^ 0xffffffff) >>> 0;
24
+ }
25
+ /** Strip the 4-byte CRC32 header that GenericProvider prepends. */
26
+ function stripCRC32Header(data) {
27
+ return data.length >= 4 ? data.subarray(4) : data;
28
+ }
29
+ /** Add a valid CRC32 header so GenericProvider accepts the message. */
30
+ function addCRC32Header(data) {
31
+ const crc = _crc32(data);
32
+ const wrapped = new Uint8Array(4 + data.length);
33
+ wrapped[0] = (crc >>> 24) & 0xff;
34
+ wrapped[1] = (crc >>> 16) & 0xff;
35
+ wrapped[2] = (crc >>> 8) & 0xff;
36
+ wrapped[3] = crc & 0xff;
37
+ wrapped.set(data, 4);
38
+ return wrapped;
39
+ }
40
+ /**
41
+ * WebSocket Transport for Yjs
42
+ *
43
+ * Provides real-time synchronization using WebSocket connections.
44
+ *
45
+ * Features:
46
+ * - Direct WebSocket connection to server
47
+ * - Room-based collaboration
48
+ * - Automatic reconnection
49
+ * - Binary message support
50
+ * - Low latency real-time sync
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * import * as Y from 'yjs'
55
+ * import { GenericProvider } from 'y-generic'
56
+ * import { WebSocketTransport } from 'y-generic/providers/websocket'
57
+ *
58
+ * const doc = new Y.Doc()
59
+ * const transport = new WebSocketTransport()
60
+ *
61
+ * const provider = new GenericProvider(doc, transport)
62
+ * await provider.connect({
63
+ * serverUrl: 'ws://localhost:1234',
64
+ * room: 'my-room'
65
+ * })
66
+ * ```
67
+ */
68
+ export class WebSocketTransport {
69
+ constructor() {
70
+ this.ws = null;
71
+ this.config = null;
72
+ this._isConnected = false;
73
+ this.debug = false;
74
+ this.reconnectAttempts = 0;
75
+ this.intentionalDisconnect = false;
76
+ this.messageQueue = []; // Queue messages until connected
77
+ this.receivedBuffer = []; // Buffer messages received before callback registered
78
+ }
79
+ get isConnected() {
80
+ return this._isConnected;
81
+ }
82
+ /**
83
+ * Connect to WebSocket server
84
+ */
85
+ async connect(config) {
86
+ this.config = config;
87
+ this.debug = config.debug ?? false;
88
+ this.intentionalDisconnect = false;
89
+ if (!config.serverUrl) {
90
+ throw new Error('WebSocket serverUrl is required');
91
+ }
92
+ if (!config.room) {
93
+ throw new Error('Room name is required');
94
+ }
95
+ // Build URL with room (y-websocket compatible)
96
+ let wsUrl = config.serverUrl;
97
+ // Remove trailing slash if present
98
+ if (wsUrl.endsWith('/')) {
99
+ wsUrl = wsUrl.slice(0, -1);
100
+ }
101
+ // Append room name to URL path
102
+ wsUrl = `${wsUrl}/${encodeURIComponent(config.room)}`;
103
+ this.log(`Connecting to WebSocket server: ${wsUrl}`);
104
+ return new Promise((resolve, reject) => {
105
+ try {
106
+ // Create WebSocket connection with room in URL (y-websocket style)
107
+ this.ws = new WebSocket(wsUrl, config.protocols);
108
+ this.ws.binaryType = 'arraybuffer';
109
+ const timeout = setTimeout(() => {
110
+ if (this.ws && this.ws.readyState !== WebSocket.OPEN) {
111
+ this.ws.close();
112
+ reject(new Error('WebSocket connection timeout'));
113
+ }
114
+ }, 10000);
115
+ this.ws.onopen = () => {
116
+ clearTimeout(timeout);
117
+ this._isConnected = true;
118
+ this.reconnectAttempts = 0;
119
+ this.log(`✅ WebSocket connected to room: ${config.room}`);
120
+ // Flush queued messages
121
+ this.flushMessageQueue();
122
+ resolve();
123
+ };
124
+ this.ws.onmessage = (event) => {
125
+ this.handleMessage(event.data);
126
+ };
127
+ this.ws.onerror = (error) => {
128
+ clearTimeout(timeout);
129
+ this.log('❌ WebSocket error:', error);
130
+ if (!this._isConnected) {
131
+ reject(new Error('WebSocket connection failed'));
132
+ }
133
+ };
134
+ this.ws.onclose = (event) => {
135
+ clearTimeout(timeout);
136
+ this._isConnected = false;
137
+ this.log(`WebSocket closed: code=${event.code}, reason=${event.reason || 'none'}`);
138
+ // Attempt reconnection if not intentional
139
+ if (!this.intentionalDisconnect && (config.autoReconnect ?? true)) {
140
+ this.attemptReconnect();
141
+ }
142
+ };
143
+ }
144
+ catch (error) {
145
+ reject(error);
146
+ }
147
+ });
148
+ }
149
+ /**
150
+ * Disconnect from WebSocket server
151
+ */
152
+ disconnect() {
153
+ this.intentionalDisconnect = true;
154
+ if (this.reconnectTimer) {
155
+ clearTimeout(this.reconnectTimer);
156
+ this.reconnectTimer = undefined;
157
+ }
158
+ if (this.ws) {
159
+ this.log('Disconnecting from WebSocket...');
160
+ this.ws.close(1000, 'Client disconnect');
161
+ this.ws = null;
162
+ }
163
+ this._isConnected = false;
164
+ }
165
+ /**
166
+ * Send data to server
167
+ */
168
+ send(data) {
169
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
170
+ this.log('⚠️ WebSocket not ready, queueing message');
171
+ this.messageQueue.push(data);
172
+ return;
173
+ }
174
+ try {
175
+ // Strip CRC32 header added by GenericProvider before sending to server
176
+ const raw = stripCRC32Header(data);
177
+ this.ws.send(raw);
178
+ this.log(`📤 Sent ${raw.length} bytes (${data.length} with header)`);
179
+ }
180
+ catch (error) {
181
+ this.log('❌ Send error:', error);
182
+ }
183
+ }
184
+ /**
185
+ * Register message callback
186
+ */
187
+ onMessage(callback) {
188
+ this.messageCallback = callback;
189
+ // Flush any buffered messages that arrived before callback was registered
190
+ if (this.receivedBuffer.length > 0) {
191
+ this.log(`📦 Flushing ${this.receivedBuffer.length} buffered received messages`);
192
+ for (const data of this.receivedBuffer) {
193
+ callback(data);
194
+ }
195
+ this.receivedBuffer = [];
196
+ }
197
+ return () => {
198
+ this.messageCallback = undefined;
199
+ };
200
+ }
201
+ /**
202
+ * Handle incoming WebSocket message
203
+ */
204
+ handleMessage(data) {
205
+ try {
206
+ if (typeof data === 'string') {
207
+ // Handle text messages (control messages)
208
+ this.log('📨 Received text message:', data);
209
+ return;
210
+ }
211
+ // Wrap plain y-websocket message with CRC32 header expected by GenericProvider
212
+ const uint8Data = addCRC32Header(new Uint8Array(data));
213
+ this.log(`📨 Received ${uint8Data.length - 4} bytes`);
214
+ if (this.messageCallback) {
215
+ this.messageCallback(uint8Data);
216
+ }
217
+ else {
218
+ // Buffer message if callback not registered yet (race condition)
219
+ this.log('⏳ Buffering message (callback not yet registered)');
220
+ this.receivedBuffer.push(uint8Data);
221
+ }
222
+ }
223
+ catch (error) {
224
+ this.log('❌ Error handling message:', error);
225
+ }
226
+ }
227
+ /**
228
+ * Flush queued messages
229
+ */
230
+ flushMessageQueue() {
231
+ if (this.messageQueue.length === 0)
232
+ return;
233
+ this.log(`📦 Flushing ${this.messageQueue.length} queued messages`);
234
+ for (const data of this.messageQueue) {
235
+ this.send(data);
236
+ }
237
+ this.messageQueue = [];
238
+ }
239
+ /**
240
+ * Attempt to reconnect
241
+ */
242
+ attemptReconnect() {
243
+ if (!this.config)
244
+ return;
245
+ const maxAttempts = this.config.maxReconnectAttempts ?? 0;
246
+ if (maxAttempts > 0 && this.reconnectAttempts >= maxAttempts) {
247
+ this.log(`❌ Max reconnection attempts (${maxAttempts}) reached`);
248
+ return;
249
+ }
250
+ this.reconnectAttempts++;
251
+ const delay = this.config.reconnectDelay ?? 2000;
252
+ this.log(`🔄 Attempting reconnection #${this.reconnectAttempts} in ${delay}ms...`);
253
+ this.reconnectTimer = setTimeout(async () => {
254
+ try {
255
+ await this.connect(this.config);
256
+ this.log('✅ Reconnected successfully');
257
+ }
258
+ catch (error) {
259
+ this.log('❌ Reconnection failed:', error);
260
+ }
261
+ }, delay);
262
+ }
263
+ /**
264
+ * Debug logging
265
+ */
266
+ log(message, ...args) {
267
+ if (this.debug) {
268
+ console.log(`[WebSocketTransport] ${message}`, ...args);
269
+ }
270
+ }
271
+ }
272
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/providers/websocket/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Optional sync monitoring utilities using hash-based detection.
3
+ *
4
+ * ⚠️ NOTE: For most use cases, use the BUILT-IN verification instead:
5
+ * GenericProvider with verifyUpdates: true (default)
6
+ *
7
+ * When to use SyncHealthMonitor:
8
+ * - You need to monitor sync health across ALL peers simultaneously
9
+ * - You want periodic pub/sub-based hash broadcasting for diagnostics
10
+ * - You need alerting/monitoring separate from the core sync mechanism
11
+ *
12
+ * When to use built-in verification (recommended):
13
+ * - Fast desync detection on every update (no waiting)
14
+ * - Exponential backoff and rate limiting
15
+ * - Sequence numbers for duplicate detection
16
+ * - Zero configuration (enabled by default)
17
+ *
18
+ * This utility is complementary to Yjs's built-in state vector sync.
19
+ * Use for monitoring/alerting, not as primary sync mechanism.
20
+ */
21
+ import * as Y from 'yjs';
22
+ import type { GenericProvider } from '../src/index';
23
+ /**
24
+ * Compute hash of entire Yjs document state.
25
+ */
26
+ export declare function computeDocumentHash(doc: Y.Doc): string;
27
+ /**
28
+ * Sync health monitor that detects divergence using periodic hashing.
29
+ */
30
+ export declare class SyncHealthMonitor {
31
+ private options;
32
+ private provider;
33
+ private intervalId?;
34
+ private localHash;
35
+ private peerHashes;
36
+ constructor(provider: GenericProvider, options?: {
37
+ /** How often to check sync health (ms) */
38
+ checkInterval?: number;
39
+ /** Callback when desync detected */
40
+ onDesync?: (details: DesyncDetails) => void;
41
+ });
42
+ /**
43
+ * Start monitoring sync health.
44
+ */
45
+ start(): void;
46
+ /**
47
+ * Stop monitoring.
48
+ */
49
+ stop(): void;
50
+ /**
51
+ * Perform a health check.
52
+ */
53
+ private checkHealth;
54
+ /**
55
+ * Handle hash from peer.
56
+ */
57
+ private handlePeerHash;
58
+ /**
59
+ * Detect if any peer has different hash.
60
+ */
61
+ private detectDivergence;
62
+ }
63
+ export interface DesyncDetails {
64
+ localHash: string;
65
+ peerHashes: Map<number, string>;
66
+ divergentClients: number[];
67
+ timestamp: number;
68
+ }
69
+ /**
70
+ * Example usage:
71
+ *
72
+ * ```typescript
73
+ * const provider = new GenericProvider(doc, transport)
74
+ * await provider.connect({ room: 'my-room' })
75
+ *
76
+ * // Start monitoring
77
+ * const monitor = new SyncHealthMonitor(provider, {
78
+ * checkInterval: 5000, // Check every 5 seconds
79
+ * onDesync: (details) => {
80
+ * console.error('Documents out of sync!', details)
81
+ * // Send to error tracking, show warning to user, etc.
82
+ * }
83
+ * })
84
+ * monitor.start()
85
+ *
86
+ * // Stop when done
87
+ * monitor.stop()
88
+ * ```
89
+ */
90
+ //# sourceMappingURL=sync-monitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-monitor.d.ts","sourceRoot":"","sources":["../src/sync-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AACxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAcnD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,GAAG,MAAM,CAGtD;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAQ1B,OAAO,CAAC,OAAO;IAPjB,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,UAAU,CAAC,CAAK;IACxB,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,UAAU,CAAiC;gBAGjD,QAAQ,EAAE,eAAe,EACjB,OAAO,GAAE;QACf,0CAA0C;QAC1C,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,oCAAoC;QACpC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAA;KACvC;IAMR;;OAEG;IACH,KAAK,IAAI,IAAI;IAiBb;;OAEG;IACH,IAAI,IAAI,IAAI;IAOZ;;OAEG;IACH,OAAO,CAAC,WAAW;IAiBnB;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAiCzB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG"}