@dabble/patches 0.4.5 → 0.4.6

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 (181) hide show
  1. package/dist/algorithms/client/applyCommittedChanges.d.ts +8 -2
  2. package/dist/algorithms/client/applyCommittedChanges.js +30 -38
  3. package/dist/algorithms/client/batching.d.ts +8 -2
  4. package/dist/algorithms/client/batching.js +38 -37
  5. package/dist/algorithms/client/breakChange.d.ts +8 -2
  6. package/dist/algorithms/client/breakChange.js +191 -240
  7. package/dist/algorithms/client/createStateFromSnapshot.d.ts +8 -2
  8. package/dist/algorithms/client/createStateFromSnapshot.js +7 -8
  9. package/dist/algorithms/client/getJSONByteSize.d.ts +3 -1
  10. package/dist/algorithms/client/getJSONByteSize.js +12 -11
  11. package/dist/algorithms/client/makeChange.d.ts +8 -2
  12. package/dist/algorithms/client/makeChange.js +28 -36
  13. package/dist/algorithms/server/commitChanges.d.ts +9 -3
  14. package/dist/algorithms/server/commitChanges.js +69 -78
  15. package/dist/algorithms/server/createVersion.d.ts +9 -3
  16. package/dist/algorithms/server/createVersion.js +21 -27
  17. package/dist/algorithms/server/getSnapshotAtRevision.d.ts +9 -3
  18. package/dist/algorithms/server/getSnapshotAtRevision.js +27 -28
  19. package/dist/algorithms/server/getStateAtRevision.d.ts +9 -3
  20. package/dist/algorithms/server/getStateAtRevision.js +13 -17
  21. package/dist/algorithms/server/handleOfflineSessionsAndBatches.d.ts +9 -3
  22. package/dist/algorithms/server/handleOfflineSessionsAndBatches.js +60 -77
  23. package/dist/algorithms/server/transformIncomingChanges.d.ts +8 -2
  24. package/dist/algorithms/server/transformIncomingChanges.js +27 -39
  25. package/dist/algorithms/shared/applyChanges.d.ts +8 -2
  26. package/dist/algorithms/shared/applyChanges.js +11 -16
  27. package/dist/algorithms/shared/rebaseChanges.d.ts +8 -2
  28. package/dist/algorithms/shared/rebaseChanges.js +30 -49
  29. package/dist/chunk-IZ2YBCUP.js +56 -0
  30. package/dist/client/InMemoryStore.d.ts +9 -3
  31. package/dist/client/InMemoryStore.js +92 -101
  32. package/dist/client/IndexedDBStore.d.ts +9 -3
  33. package/dist/client/IndexedDBStore.js +378 -491
  34. package/dist/client/Patches.d.ts +18 -13
  35. package/dist/client/Patches.js +152 -207
  36. package/dist/client/PatchesDoc.d.ts +14 -8
  37. package/dist/client/PatchesDoc.js +147 -154
  38. package/dist/client/PatchesHistoryClient.d.ts +12 -5
  39. package/dist/client/PatchesHistoryClient.js +110 -117
  40. package/dist/client/PatchesStore.d.ts +9 -3
  41. package/dist/client/PatchesStore.js +0 -1
  42. package/dist/client/index.d.ts +12 -6
  43. package/dist/client/index.js +5 -5
  44. package/dist/data/change.d.ts +9 -3
  45. package/dist/data/change.js +23 -15
  46. package/dist/data/version.d.ts +9 -3
  47. package/dist/data/version.js +11 -15
  48. package/dist/event-signal.d.ts +7 -6
  49. package/dist/event-signal.js +24 -39
  50. package/dist/index-CvQws3AB.d.ts +36 -0
  51. package/dist/index.d.ts +27 -5
  52. package/dist/index.js +10 -4
  53. package/dist/json-patch/JSONPatch.d.ts +9 -5
  54. package/dist/json-patch/JSONPatch.js +175 -183
  55. package/dist/json-patch/applyPatch.d.ts +5 -2
  56. package/dist/json-patch/applyPatch.js +27 -35
  57. package/dist/json-patch/composePatch.d.ts +5 -2
  58. package/dist/json-patch/composePatch.js +34 -34
  59. package/dist/json-patch/createJSONPatch.d.ts +7 -2
  60. package/dist/json-patch/createJSONPatch.js +11 -38
  61. package/dist/json-patch/index.d.ts +14 -6
  62. package/dist/json-patch/index.js +20 -9
  63. package/dist/json-patch/invertPatch.d.ts +5 -2
  64. package/dist/json-patch/invertPatch.js +31 -30
  65. package/dist/json-patch/ops/add.d.ts +5 -2
  66. package/dist/json-patch/ops/add.js +53 -51
  67. package/dist/json-patch/ops/bitmask.d.ts +8 -5
  68. package/dist/json-patch/ops/bitmask.js +41 -44
  69. package/dist/json-patch/ops/copy.d.ts +5 -2
  70. package/dist/json-patch/ops/copy.js +32 -33
  71. package/dist/json-patch/ops/increment.d.ts +5 -2
  72. package/dist/json-patch/ops/increment.js +21 -20
  73. package/dist/json-patch/ops/index.d.ts +10 -21
  74. package/dist/json-patch/ops/index.js +34 -24
  75. package/dist/json-patch/ops/move.d.ts +5 -2
  76. package/dist/json-patch/ops/move.js +132 -198
  77. package/dist/json-patch/ops/remove.d.ts +5 -2
  78. package/dist/json-patch/ops/remove.js +33 -30
  79. package/dist/json-patch/ops/replace.d.ts +5 -2
  80. package/dist/json-patch/ops/replace.js +45 -43
  81. package/dist/json-patch/ops/test.d.ts +5 -2
  82. package/dist/json-patch/ops/test.js +25 -21
  83. package/dist/json-patch/ops/text.d.ts +5 -2
  84. package/dist/json-patch/ops/text.js +54 -54
  85. package/dist/json-patch/pathProxy.d.ts +9 -3
  86. package/dist/json-patch/pathProxy.js +27 -48
  87. package/dist/json-patch/state.d.ts +5 -2
  88. package/dist/json-patch/state.js +11 -7
  89. package/dist/json-patch/transformPatch.d.ts +6 -2
  90. package/dist/json-patch/transformPatch.js +21 -24
  91. package/dist/json-patch/types.d.ts +9 -7
  92. package/dist/json-patch/types.js +0 -1
  93. package/dist/json-patch/utils/deepEqual.d.ts +3 -1
  94. package/dist/json-patch/utils/deepEqual.js +32 -28
  95. package/dist/json-patch/utils/exit.d.ts +5 -2
  96. package/dist/json-patch/utils/exit.js +7 -3
  97. package/dist/json-patch/utils/get.d.ts +5 -2
  98. package/dist/json-patch/utils/get.js +8 -4
  99. package/dist/json-patch/utils/getOpData.d.ts +5 -2
  100. package/dist/json-patch/utils/getOpData.js +12 -9
  101. package/dist/json-patch/utils/getType.d.ts +6 -3
  102. package/dist/json-patch/utils/getType.js +9 -4
  103. package/dist/json-patch/utils/index.d.ts +15 -14
  104. package/dist/json-patch/utils/index.js +14 -14
  105. package/dist/json-patch/utils/log.d.ts +4 -2
  106. package/dist/json-patch/utils/log.js +8 -3
  107. package/dist/json-patch/utils/ops.d.ts +8 -5
  108. package/dist/json-patch/utils/ops.js +83 -100
  109. package/dist/json-patch/utils/paths.d.ts +12 -9
  110. package/dist/json-patch/utils/paths.js +54 -51
  111. package/dist/json-patch/utils/pluck.d.ts +8 -5
  112. package/dist/json-patch/utils/pluck.js +32 -26
  113. package/dist/json-patch/utils/shallowCopy.d.ts +3 -1
  114. package/dist/json-patch/utils/shallowCopy.js +22 -18
  115. package/dist/json-patch/utils/softWrites.d.ts +6 -3
  116. package/dist/json-patch/utils/softWrites.js +17 -16
  117. package/dist/json-patch/utils/toArrayIndex.d.ts +3 -1
  118. package/dist/json-patch/utils/toArrayIndex.js +14 -10
  119. package/dist/json-patch/utils/toKeys.d.ts +3 -1
  120. package/dist/json-patch/utils/toKeys.js +15 -11
  121. package/dist/json-patch/utils/updateArrayIndexes.d.ts +5 -2
  122. package/dist/json-patch/utils/updateArrayIndexes.js +33 -37
  123. package/dist/json-patch/utils/updateArrayPath.d.ts +5 -2
  124. package/dist/json-patch/utils/updateArrayPath.js +29 -42
  125. package/dist/net/PatchesClient.d.ts +128 -0
  126. package/dist/net/PatchesClient.js +161 -0
  127. package/dist/net/PatchesSync.d.ts +19 -9
  128. package/dist/net/PatchesSync.js +291 -386
  129. package/dist/net/error.d.ts +3 -1
  130. package/dist/net/error.js +9 -6
  131. package/dist/net/http/FetchTransport.d.ts +21 -0
  132. package/dist/net/http/FetchTransport.js +34 -0
  133. package/dist/net/index.d.ts +26 -12
  134. package/dist/net/index.js +12 -10
  135. package/dist/net/protocol/JSONRPCClient.d.ts +11 -4
  136. package/dist/net/protocol/JSONRPCClient.js +95 -103
  137. package/dist/net/protocol/JSONRPCServer.d.ts +15 -8
  138. package/dist/net/protocol/JSONRPCServer.js +101 -123
  139. package/dist/net/protocol/types.d.ts +21 -15
  140. package/dist/net/protocol/types.js +0 -1
  141. package/dist/net/protocol/utils.d.ts +12 -0
  142. package/dist/net/protocol/utils.js +15 -0
  143. package/dist/net/types.d.ts +4 -2
  144. package/dist/net/types.js +0 -1
  145. package/dist/net/webrtc/WebRTCAwareness.d.ts +14 -4
  146. package/dist/net/webrtc/WebRTCAwareness.js +111 -120
  147. package/dist/net/webrtc/WebRTCTransport.d.ts +16 -8
  148. package/dist/net/webrtc/WebRTCTransport.js +149 -157
  149. package/dist/net/webrtc/index.d.ts +10 -2
  150. package/dist/net/webrtc/index.js +2 -2
  151. package/dist/net/websocket/AuthorizationProvider.d.ts +7 -5
  152. package/dist/net/websocket/AuthorizationProvider.js +12 -17
  153. package/dist/net/websocket/PatchesWebSocket.d.ts +14 -109
  154. package/dist/net/websocket/PatchesWebSocket.js +37 -184
  155. package/dist/net/websocket/RPCServer.d.ts +19 -10
  156. package/dist/net/websocket/RPCServer.js +190 -192
  157. package/dist/net/websocket/SignalingService.d.ts +12 -32
  158. package/dist/net/websocket/SignalingService.js +126 -133
  159. package/dist/net/websocket/WebSocketServer.d.ts +17 -4
  160. package/dist/net/websocket/WebSocketServer.js +64 -72
  161. package/dist/net/websocket/WebSocketTransport.d.ts +13 -5
  162. package/dist/net/websocket/WebSocketTransport.js +178 -207
  163. package/dist/net/websocket/onlineState.d.ts +6 -3
  164. package/dist/net/websocket/onlineState.js +25 -21
  165. package/dist/server/PatchesBranchManager.d.ts +12 -5
  166. package/dist/server/PatchesBranchManager.js +132 -142
  167. package/dist/server/PatchesHistoryManager.d.ts +11 -3
  168. package/dist/server/PatchesHistoryManager.js +81 -84
  169. package/dist/server/PatchesServer.d.ts +16 -10
  170. package/dist/server/PatchesServer.js +131 -137
  171. package/dist/server/index.d.ts +7 -2
  172. package/dist/server/index.js +9 -3
  173. package/dist/server/types.d.ts +9 -3
  174. package/dist/server/types.js +0 -1
  175. package/dist/types.d.ts +38 -19
  176. package/dist/types.js +1 -1
  177. package/dist/utils/concurrency.d.ts +7 -5
  178. package/dist/utils/concurrency.js +43 -53
  179. package/dist/utils/deferred.d.ts +4 -2
  180. package/dist/utils/deferred.js +25 -21
  181. package/package.json +5 -7
@@ -1,138 +1,131 @@
1
- import { createId } from 'crypto-id';
2
- /**
3
- * Service that facilitates WebRTC connection establishment by relaying signaling messages.
4
- * Acts as a central hub for WebRTC peers to exchange connection information.
5
- */
6
- export class SignalingService {
7
- clients = new Map();
8
- /**
9
- * Registers a new client connection with the signaling service.
10
- * Assigns a unique ID to the client and informs them of other connected peers.
11
- *
12
- * @param send - Function to send messages to this client
13
- * @param id - Optional client ID (generated if not provided)
14
- * @returns The client's assigned ID
15
- */
16
- onClientConnected(send, id = createId(14)) {
17
- this.clients.set(id, { send });
18
- const welcome = {
19
- jsonrpc: '2.0',
20
- method: 'peer-welcome',
21
- params: {
22
- id,
23
- peers: Array.from(this.clients.keys()).filter(pid => pid !== id),
24
- },
25
- };
26
- send(welcome);
27
- return id;
1
+ import "../../chunk-IZ2YBCUP.js";
2
+ import { createId } from "crypto-id";
3
+ class SignalingService {
4
+ clients = /* @__PURE__ */ new Map();
5
+ /**
6
+ * Registers a new client connection with the signaling service.
7
+ * Assigns a unique ID to the client and informs them of other connected peers.
8
+ *
9
+ * @param send - Function to send messages to this client
10
+ * @param id - Optional client ID (generated if not provided)
11
+ * @returns The client's assigned ID
12
+ */
13
+ onClientConnected(send, id = createId(14)) {
14
+ this.clients.set(id, { send });
15
+ const welcome = {
16
+ jsonrpc: "2.0",
17
+ method: "peer-welcome",
18
+ params: {
19
+ id,
20
+ peers: Array.from(this.clients.keys()).filter((pid) => pid !== id)
21
+ }
22
+ };
23
+ send(welcome);
24
+ return id;
25
+ }
26
+ /**
27
+ * Handles a client disconnection by removing them from the registry
28
+ * and notifying all other connected clients.
29
+ *
30
+ * @param id - ID of the disconnected client
31
+ */
32
+ onClientDisconnected(id) {
33
+ this.clients.delete(id);
34
+ this.broadcast({
35
+ jsonrpc: "2.0",
36
+ method: "peer-disconnected",
37
+ params: { id }
38
+ });
39
+ }
40
+ /**
41
+ * Handles a signaling message from a client, relaying WebRTC session data
42
+ * between peers to facilitate connection establishment.
43
+ *
44
+ * @param fromId - ID of the client sending the message
45
+ * @param message - The JSON-RPC message or its string representation
46
+ * @returns True if the message was a valid signaling message and was handled, false otherwise
47
+ */
48
+ handleClientMessage(fromId, message) {
49
+ let parsed;
50
+ try {
51
+ parsed = typeof message === "string" ? JSON.parse(message) : message;
52
+ } catch {
53
+ return false;
28
54
  }
29
- /**
30
- * Handles a client disconnection by removing them from the registry
31
- * and notifying all other connected clients.
32
- *
33
- * @param id - ID of the disconnected client
34
- */
35
- onClientDisconnected(id) {
36
- this.clients.delete(id);
37
- // Broadcast to all others
38
- this.broadcast({
39
- jsonrpc: '2.0',
40
- method: 'peer-disconnected',
41
- params: { id },
42
- });
55
+ if (parsed.jsonrpc !== "2.0" || parsed.method !== "peer-signal" || !parsed.params?.to) return false;
56
+ const { params, id } = parsed;
57
+ const { to, data } = params;
58
+ const target = this.clients.get(to);
59
+ if (!target) {
60
+ this.respondError(fromId, id, "Target not connected");
61
+ return true;
43
62
  }
44
- /**
45
- * Handles a signaling message from a client, relaying WebRTC session data
46
- * between peers to facilitate connection establishment.
47
- *
48
- * @param fromId - ID of the client sending the message
49
- * @param message - The JSON-RPC message or its string representation
50
- * @returns True if the message was a valid signaling message and was handled, false otherwise
51
- */
52
- handleClientMessage(fromId, message) {
53
- let parsed;
54
- try {
55
- parsed = typeof message === 'string' ? JSON.parse(message) : message;
56
- }
57
- catch {
58
- return false;
59
- }
60
- if (parsed.jsonrpc !== '2.0' || parsed.method !== 'peer-signal' || !parsed.params?.to)
61
- return false;
62
- const { params, id } = parsed;
63
- const { to, data } = params;
64
- const target = this.clients.get(to);
65
- if (!target) {
66
- this.respondError(fromId, id, 'Target not connected');
67
- // Was a signaling message, even if the target is not connected
68
- return true;
69
- }
70
- const outbound = {
71
- jsonrpc: '2.0',
72
- method: 'signal',
73
- params: {
74
- from: fromId,
75
- data,
76
- },
77
- };
78
- target.send(outbound);
79
- if (id !== undefined) {
80
- this.respond(fromId, id, 'ok');
81
- }
82
- return true;
63
+ const outbound = {
64
+ jsonrpc: "2.0",
65
+ method: "signal",
66
+ params: {
67
+ from: fromId,
68
+ data
69
+ }
70
+ };
71
+ target.send(outbound);
72
+ if (id !== void 0) {
73
+ this.respond(fromId, id, "ok");
83
74
  }
84
- /**
85
- * Sends a successful JSON-RPC response to a client.
86
- *
87
- * @private
88
- * @param toId - ID of the client to send the response to
89
- * @param id - Request ID to match in the response
90
- * @param result - Result data to include in the response
91
- */
92
- respond(toId, id, result) {
93
- const client = this.clients.get(toId);
94
- if (!client)
95
- return;
96
- const response = {
97
- jsonrpc: '2.0',
98
- result,
99
- id,
100
- };
101
- client.send(response);
102
- }
103
- /**
104
- * Sends an error JSON-RPC response to a client.
105
- *
106
- * @private
107
- * @param toId - ID of the client to send the error response to
108
- * @param id - Request ID to match in the response, or undefined for notifications
109
- * @param message - Error message to include
110
- */
111
- respondError(toId, id, message) {
112
- if (id === undefined)
113
- return;
114
- const client = this.clients.get(toId);
115
- if (!client)
116
- return;
117
- const response = {
118
- jsonrpc: '2.0',
119
- error: { code: -32000, message },
120
- id,
121
- };
122
- client.send(response);
123
- }
124
- /**
125
- * Broadcasts a message to all connected clients, optionally excluding one.
126
- *
127
- * @private
128
- * @param message - The message to broadcast
129
- * @param excludeId - Optional ID of a client to exclude from the broadcast
130
- */
131
- broadcast(message, excludeId) {
132
- for (const [id, client] of this.clients.entries()) {
133
- if (id !== excludeId) {
134
- client.send(message);
135
- }
136
- }
75
+ return true;
76
+ }
77
+ /**
78
+ * Sends a successful JSON-RPC response to a client.
79
+ *
80
+ * @private
81
+ * @param toId - ID of the client to send the response to
82
+ * @param id - Request ID to match in the response
83
+ * @param result - Result data to include in the response
84
+ */
85
+ respond(toId, id, result) {
86
+ const client = this.clients.get(toId);
87
+ if (!client) return;
88
+ const response = {
89
+ jsonrpc: "2.0",
90
+ result,
91
+ id
92
+ };
93
+ client.send(response);
94
+ }
95
+ /**
96
+ * Sends an error JSON-RPC response to a client.
97
+ *
98
+ * @private
99
+ * @param toId - ID of the client to send the error response to
100
+ * @param id - Request ID to match in the response, or undefined for notifications
101
+ * @param message - Error message to include
102
+ */
103
+ respondError(toId, id, message) {
104
+ if (id === void 0) return;
105
+ const client = this.clients.get(toId);
106
+ if (!client) return;
107
+ const response = {
108
+ jsonrpc: "2.0",
109
+ error: { code: -32e3, message },
110
+ id
111
+ };
112
+ client.send(response);
113
+ }
114
+ /**
115
+ * Broadcasts a message to all connected clients, optionally excluding one.
116
+ *
117
+ * @private
118
+ * @param message - The message to broadcast
119
+ * @param excludeId - Optional ID of a client to exclude from the broadcast
120
+ */
121
+ broadcast(message, excludeId) {
122
+ for (const [id, client] of this.clients.entries()) {
123
+ if (id !== excludeId) {
124
+ client.send(message);
125
+ }
137
126
  }
127
+ }
138
128
  }
129
+ export {
130
+ SignalingService
131
+ };
@@ -1,12 +1,23 @@
1
- import type { ServerTransport } from '../protocol/types.js';
2
- import { type AuthContext, type AuthorizationProvider } from './AuthorizationProvider.js';
3
- import type { RPCServer } from './RPCServer.js';
1
+ import { ServerTransport } from '../protocol/types.js';
2
+ import { AuthorizationProvider, AuthContext } from './AuthorizationProvider.js';
3
+ import { RPCServer } from './RPCServer.js';
4
+ import '../../event-signal.js';
5
+ import '../../types.js';
6
+ import '../../json-patch/JSONPatch.js';
7
+ import '@dabble/delta';
8
+ import '../../json-patch/types.js';
9
+ import '../../server/PatchesBranchManager.js';
10
+ import '../../server/PatchesServer.js';
11
+ import '../../server/types.js';
12
+ import '../../server/PatchesHistoryManager.js';
13
+ import '../protocol/JSONRPCServer.js';
14
+
4
15
  /**
5
16
  * High-level client for the Patches real-time collaboration service.
6
17
  * This class provides document subscription, patch notification handling,
7
18
  * versioning, and other OT-specific functionality over a WebSocket connection.
8
19
  */
9
- export declare class WebSocketServer {
20
+ declare class WebSocketServer {
10
21
  protected transport: ServerTransport;
11
22
  protected auth: AuthorizationProvider;
12
23
  /**
@@ -34,3 +45,5 @@ export declare class WebSocketServer {
34
45
  ids: string | string[];
35
46
  }, ctx?: AuthContext): Promise<string[]>;
36
47
  }
48
+
49
+ export { WebSocketServer };
@@ -1,75 +1,67 @@
1
- import { denyAll } from './AuthorizationProvider.js';
2
- /**
3
- * High-level client for the Patches real-time collaboration service.
4
- * This class provides document subscription, patch notification handling,
5
- * versioning, and other OT-specific functionality over a WebSocket connection.
6
- */
7
- export class WebSocketServer {
8
- transport;
9
- auth;
10
- /**
11
- * Creates a new Patches WebSocket client instance.
12
- *
13
- * @param transport - The transport layer implementation that will be used for sending/receiving messages
14
- */
15
- constructor(transport, rpcServer) {
16
- this.transport = transport;
17
- const { rpc, auth } = rpcServer;
18
- this.auth = auth || denyAll;
19
- // Subscription operations
20
- rpc.registerMethod('subscribe', this.subscribe.bind(this));
21
- rpc.registerMethod('unsubscribe', this.unsubscribe.bind(this));
22
- rpc.onNotify(async (msg) => {
23
- if (!msg.params?.docId)
24
- return;
25
- const { docId } = msg.params;
26
- const msgString = JSON.stringify(msg);
27
- const clientIds = await this.transport.listSubscriptions(docId);
28
- clientIds.forEach(clientId => {
29
- this.transport.send(clientId, msgString);
30
- });
31
- });
32
- }
33
- /**
34
- * Subscribes the client to one or more documents to receive real-time updates.
35
- * @param connectionId - The ID of the connection making the request
36
- * @param params - The subscription parameters
37
- * @param params.ids - Document ID or IDs to subscribe to
38
- */
39
- async subscribe(params, ctx) {
40
- if (!ctx?.clientId)
41
- return [];
42
- const { ids } = params;
43
- const allIds = Array.isArray(ids) ? ids : [ids];
44
- const allowed = [];
45
- await Promise.all(allIds.map(async (id) => {
46
- try {
47
- if (await this.auth.canAccess(ctx, id, 'read', 'subscribe', params)) {
48
- allowed.push(id);
49
- }
50
- }
51
- catch {
52
- // Treat exceptions from the provider as a denial for this doc
53
- }
54
- }));
55
- if (allowed.length === 0) {
56
- return [];
1
+ import "../../chunk-IZ2YBCUP.js";
2
+ import { denyAll } from "./AuthorizationProvider.js";
3
+ class WebSocketServer {
4
+ transport;
5
+ auth;
6
+ /**
7
+ * Creates a new Patches WebSocket client instance.
8
+ *
9
+ * @param transport - The transport layer implementation that will be used for sending/receiving messages
10
+ */
11
+ constructor(transport, rpcServer) {
12
+ this.transport = transport;
13
+ const { rpc, auth } = rpcServer;
14
+ this.auth = auth || denyAll;
15
+ rpc.registerMethod("subscribe", this.subscribe.bind(this));
16
+ rpc.registerMethod("unsubscribe", this.unsubscribe.bind(this));
17
+ rpc.onNotify(async (msg) => {
18
+ if (!msg.params?.docId) return;
19
+ const { docId } = msg.params;
20
+ const msgString = JSON.stringify(msg);
21
+ const clientIds = await this.transport.listSubscriptions(docId);
22
+ clientIds.forEach((clientId) => {
23
+ this.transport.send(clientId, msgString);
24
+ });
25
+ });
26
+ }
27
+ /**
28
+ * Subscribes the client to one or more documents to receive real-time updates.
29
+ * @param connectionId - The ID of the connection making the request
30
+ * @param params - The subscription parameters
31
+ * @param params.ids - Document ID or IDs to subscribe to
32
+ */
33
+ async subscribe(params, ctx) {
34
+ if (!ctx?.clientId) return [];
35
+ const { ids } = params;
36
+ const allIds = Array.isArray(ids) ? ids : [ids];
37
+ const allowed = [];
38
+ await Promise.all(
39
+ allIds.map(async (id) => {
40
+ try {
41
+ if (await this.auth.canAccess(ctx, id, "read", "subscribe", params)) {
42
+ allowed.push(id);
43
+ }
44
+ } catch {
57
45
  }
58
- return this.transport.addSubscription(ctx.clientId, allowed);
59
- }
60
- /**
61
- * Unsubscribes the client from one or more documents.
62
- * @param connectionId - The ID of the connection making the request
63
- * @param params - The unsubscription parameters
64
- * @param params.ids - Document ID or IDs to unsubscribe from
65
- */
66
- async unsubscribe(params, ctx) {
67
- if (!ctx?.clientId)
68
- return [];
69
- const { ids } = params;
70
- // We deliberately do **not** enforce authorization here –
71
- // removing a subscription doesn't leak information and helps
72
- // clean up server-side state if a client has lost access mid-session.
73
- return this.transport.removeSubscription(ctx?.clientId, Array.isArray(ids) ? ids : [ids]);
46
+ })
47
+ );
48
+ if (allowed.length === 0) {
49
+ return [];
74
50
  }
51
+ return this.transport.addSubscription(ctx.clientId, allowed);
52
+ }
53
+ /**
54
+ * Unsubscribes the client from one or more documents.
55
+ * @param connectionId - The ID of the connection making the request
56
+ * @param params - The unsubscription parameters
57
+ * @param params.ids - Document ID or IDs to unsubscribe from
58
+ */
59
+ async unsubscribe(params, ctx) {
60
+ if (!ctx?.clientId) return [];
61
+ const { ids } = params;
62
+ return this.transport.removeSubscription(ctx?.clientId, Array.isArray(ids) ? ids : [ids]);
63
+ }
75
64
  }
65
+ export {
66
+ WebSocketServer
67
+ };
@@ -1,13 +1,19 @@
1
- import type { ClientTransport, ConnectionState } from '../protocol/types.js';
1
+ import { Signal } from '../../event-signal.js';
2
+ import { ClientTransport, ConnectionState } from '../protocol/types.js';
3
+ import '../../types.js';
4
+ import '../../json-patch/JSONPatch.js';
5
+ import '@dabble/delta';
6
+ import '../../json-patch/types.js';
7
+
2
8
  /** WebSocket constructor options (subset) */
3
- export interface WebSocketOptions {
9
+ interface WebSocketOptions {
4
10
  protocol?: string | string[];
5
11
  }
6
12
  /**
7
13
  * WebSocket-based transport implementation that provides communication over the WebSocket protocol.
8
14
  * Includes automatic reconnection with exponential backoff.
9
15
  */
10
- export declare class WebSocketTransport implements ClientTransport {
16
+ declare class WebSocketTransport implements ClientTransport {
11
17
  private url;
12
18
  private wsOptions?;
13
19
  private _state;
@@ -23,12 +29,12 @@ export declare class WebSocketTransport implements ClientTransport {
23
29
  * Signal that emits when the connection state changes.
24
30
  * Subscribers will receive the new connection state as an argument.
25
31
  */
26
- readonly onStateChange: import("../../event-signal.js").Signal<(state: ConnectionState) => void>;
32
+ readonly onStateChange: Signal<(state: ConnectionState) => void>;
27
33
  /**
28
34
  * Signal that emits when a message is received from the transport.
29
35
  * Subscribers will receive the message data as a string.
30
36
  */
31
- readonly onMessage: import("../../event-signal.js").Signal<(data: string) => void>;
37
+ readonly onMessage: Signal<(data: string) => void>;
32
38
  /**
33
39
  * Creates a new WebSocket transport instance.
34
40
  * @param url - The WebSocket server URL to connect to
@@ -78,3 +84,5 @@ export declare class WebSocketTransport implements ClientTransport {
78
84
  /** Removes previously registered online/offline listeners (if any) */
79
85
  private _removeOnlineOfflineListeners;
80
86
  }
87
+
88
+ export { type WebSocketOptions, WebSocketTransport };