@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.
- package/dist/algorithms/client/applyCommittedChanges.d.ts +8 -2
- package/dist/algorithms/client/applyCommittedChanges.js +30 -38
- package/dist/algorithms/client/batching.d.ts +8 -2
- package/dist/algorithms/client/batching.js +38 -37
- package/dist/algorithms/client/breakChange.d.ts +8 -2
- package/dist/algorithms/client/breakChange.js +191 -240
- package/dist/algorithms/client/createStateFromSnapshot.d.ts +8 -2
- package/dist/algorithms/client/createStateFromSnapshot.js +7 -8
- package/dist/algorithms/client/getJSONByteSize.d.ts +3 -1
- package/dist/algorithms/client/getJSONByteSize.js +12 -11
- package/dist/algorithms/client/makeChange.d.ts +8 -2
- package/dist/algorithms/client/makeChange.js +28 -36
- package/dist/algorithms/server/commitChanges.d.ts +9 -3
- package/dist/algorithms/server/commitChanges.js +69 -78
- package/dist/algorithms/server/createVersion.d.ts +9 -3
- package/dist/algorithms/server/createVersion.js +21 -27
- package/dist/algorithms/server/getSnapshotAtRevision.d.ts +9 -3
- package/dist/algorithms/server/getSnapshotAtRevision.js +27 -28
- package/dist/algorithms/server/getStateAtRevision.d.ts +9 -3
- package/dist/algorithms/server/getStateAtRevision.js +13 -17
- package/dist/algorithms/server/handleOfflineSessionsAndBatches.d.ts +9 -3
- package/dist/algorithms/server/handleOfflineSessionsAndBatches.js +60 -77
- package/dist/algorithms/server/transformIncomingChanges.d.ts +8 -2
- package/dist/algorithms/server/transformIncomingChanges.js +27 -39
- package/dist/algorithms/shared/applyChanges.d.ts +8 -2
- package/dist/algorithms/shared/applyChanges.js +11 -16
- package/dist/algorithms/shared/rebaseChanges.d.ts +8 -2
- package/dist/algorithms/shared/rebaseChanges.js +30 -49
- package/dist/chunk-IZ2YBCUP.js +56 -0
- package/dist/client/InMemoryStore.d.ts +9 -3
- package/dist/client/InMemoryStore.js +92 -101
- package/dist/client/IndexedDBStore.d.ts +9 -3
- package/dist/client/IndexedDBStore.js +378 -491
- package/dist/client/Patches.d.ts +18 -13
- package/dist/client/Patches.js +152 -207
- package/dist/client/PatchesDoc.d.ts +14 -8
- package/dist/client/PatchesDoc.js +147 -154
- package/dist/client/PatchesHistoryClient.d.ts +12 -5
- package/dist/client/PatchesHistoryClient.js +110 -117
- package/dist/client/PatchesStore.d.ts +9 -3
- package/dist/client/PatchesStore.js +0 -1
- package/dist/client/index.d.ts +12 -6
- package/dist/client/index.js +5 -5
- package/dist/data/change.d.ts +9 -3
- package/dist/data/change.js +23 -15
- package/dist/data/version.d.ts +9 -3
- package/dist/data/version.js +11 -15
- package/dist/event-signal.d.ts +7 -6
- package/dist/event-signal.js +24 -39
- package/dist/index-CvQws3AB.d.ts +36 -0
- package/dist/index.d.ts +27 -5
- package/dist/index.js +10 -4
- package/dist/json-patch/JSONPatch.d.ts +9 -5
- package/dist/json-patch/JSONPatch.js +175 -183
- package/dist/json-patch/applyPatch.d.ts +5 -2
- package/dist/json-patch/applyPatch.js +27 -35
- package/dist/json-patch/composePatch.d.ts +5 -2
- package/dist/json-patch/composePatch.js +34 -34
- package/dist/json-patch/createJSONPatch.d.ts +7 -2
- package/dist/json-patch/createJSONPatch.js +11 -38
- package/dist/json-patch/index.d.ts +14 -6
- package/dist/json-patch/index.js +20 -9
- package/dist/json-patch/invertPatch.d.ts +5 -2
- package/dist/json-patch/invertPatch.js +31 -30
- package/dist/json-patch/ops/add.d.ts +5 -2
- package/dist/json-patch/ops/add.js +53 -51
- package/dist/json-patch/ops/bitmask.d.ts +8 -5
- package/dist/json-patch/ops/bitmask.js +41 -44
- package/dist/json-patch/ops/copy.d.ts +5 -2
- package/dist/json-patch/ops/copy.js +32 -33
- package/dist/json-patch/ops/increment.d.ts +5 -2
- package/dist/json-patch/ops/increment.js +21 -20
- package/dist/json-patch/ops/index.d.ts +10 -21
- package/dist/json-patch/ops/index.js +34 -24
- package/dist/json-patch/ops/move.d.ts +5 -2
- package/dist/json-patch/ops/move.js +132 -198
- package/dist/json-patch/ops/remove.d.ts +5 -2
- package/dist/json-patch/ops/remove.js +33 -30
- package/dist/json-patch/ops/replace.d.ts +5 -2
- package/dist/json-patch/ops/replace.js +45 -43
- package/dist/json-patch/ops/test.d.ts +5 -2
- package/dist/json-patch/ops/test.js +25 -21
- package/dist/json-patch/ops/text.d.ts +5 -2
- package/dist/json-patch/ops/text.js +54 -54
- package/dist/json-patch/pathProxy.d.ts +9 -3
- package/dist/json-patch/pathProxy.js +27 -48
- package/dist/json-patch/state.d.ts +5 -2
- package/dist/json-patch/state.js +11 -7
- package/dist/json-patch/transformPatch.d.ts +6 -2
- package/dist/json-patch/transformPatch.js +21 -24
- package/dist/json-patch/types.d.ts +9 -7
- package/dist/json-patch/types.js +0 -1
- package/dist/json-patch/utils/deepEqual.d.ts +3 -1
- package/dist/json-patch/utils/deepEqual.js +32 -28
- package/dist/json-patch/utils/exit.d.ts +5 -2
- package/dist/json-patch/utils/exit.js +7 -3
- package/dist/json-patch/utils/get.d.ts +5 -2
- package/dist/json-patch/utils/get.js +8 -4
- package/dist/json-patch/utils/getOpData.d.ts +5 -2
- package/dist/json-patch/utils/getOpData.js +12 -9
- package/dist/json-patch/utils/getType.d.ts +6 -3
- package/dist/json-patch/utils/getType.js +9 -4
- package/dist/json-patch/utils/index.d.ts +15 -14
- package/dist/json-patch/utils/index.js +14 -14
- package/dist/json-patch/utils/log.d.ts +4 -2
- package/dist/json-patch/utils/log.js +8 -3
- package/dist/json-patch/utils/ops.d.ts +8 -5
- package/dist/json-patch/utils/ops.js +83 -100
- package/dist/json-patch/utils/paths.d.ts +12 -9
- package/dist/json-patch/utils/paths.js +54 -51
- package/dist/json-patch/utils/pluck.d.ts +8 -5
- package/dist/json-patch/utils/pluck.js +32 -26
- package/dist/json-patch/utils/shallowCopy.d.ts +3 -1
- package/dist/json-patch/utils/shallowCopy.js +22 -18
- package/dist/json-patch/utils/softWrites.d.ts +6 -3
- package/dist/json-patch/utils/softWrites.js +17 -16
- package/dist/json-patch/utils/toArrayIndex.d.ts +3 -1
- package/dist/json-patch/utils/toArrayIndex.js +14 -10
- package/dist/json-patch/utils/toKeys.d.ts +3 -1
- package/dist/json-patch/utils/toKeys.js +15 -11
- package/dist/json-patch/utils/updateArrayIndexes.d.ts +5 -2
- package/dist/json-patch/utils/updateArrayIndexes.js +33 -37
- package/dist/json-patch/utils/updateArrayPath.d.ts +5 -2
- package/dist/json-patch/utils/updateArrayPath.js +29 -42
- package/dist/net/PatchesClient.d.ts +128 -0
- package/dist/net/PatchesClient.js +161 -0
- package/dist/net/PatchesSync.d.ts +19 -9
- package/dist/net/PatchesSync.js +291 -386
- package/dist/net/error.d.ts +3 -1
- package/dist/net/error.js +9 -6
- package/dist/net/http/FetchTransport.d.ts +21 -0
- package/dist/net/http/FetchTransport.js +34 -0
- package/dist/net/index.d.ts +26 -12
- package/dist/net/index.js +12 -10
- package/dist/net/protocol/JSONRPCClient.d.ts +11 -4
- package/dist/net/protocol/JSONRPCClient.js +95 -103
- package/dist/net/protocol/JSONRPCServer.d.ts +15 -8
- package/dist/net/protocol/JSONRPCServer.js +101 -123
- package/dist/net/protocol/types.d.ts +21 -15
- package/dist/net/protocol/types.js +0 -1
- package/dist/net/protocol/utils.d.ts +12 -0
- package/dist/net/protocol/utils.js +15 -0
- package/dist/net/types.d.ts +4 -2
- package/dist/net/types.js +0 -1
- package/dist/net/webrtc/WebRTCAwareness.d.ts +14 -4
- package/dist/net/webrtc/WebRTCAwareness.js +111 -120
- package/dist/net/webrtc/WebRTCTransport.d.ts +16 -8
- package/dist/net/webrtc/WebRTCTransport.js +149 -157
- package/dist/net/webrtc/index.d.ts +10 -2
- package/dist/net/webrtc/index.js +2 -2
- package/dist/net/websocket/AuthorizationProvider.d.ts +7 -5
- package/dist/net/websocket/AuthorizationProvider.js +12 -17
- package/dist/net/websocket/PatchesWebSocket.d.ts +14 -109
- package/dist/net/websocket/PatchesWebSocket.js +37 -184
- package/dist/net/websocket/RPCServer.d.ts +19 -10
- package/dist/net/websocket/RPCServer.js +190 -192
- package/dist/net/websocket/SignalingService.d.ts +12 -32
- package/dist/net/websocket/SignalingService.js +126 -133
- package/dist/net/websocket/WebSocketServer.d.ts +17 -4
- package/dist/net/websocket/WebSocketServer.js +64 -72
- package/dist/net/websocket/WebSocketTransport.d.ts +13 -5
- package/dist/net/websocket/WebSocketTransport.js +178 -207
- package/dist/net/websocket/onlineState.d.ts +6 -3
- package/dist/net/websocket/onlineState.js +25 -21
- package/dist/server/PatchesBranchManager.d.ts +12 -5
- package/dist/server/PatchesBranchManager.js +132 -142
- package/dist/server/PatchesHistoryManager.d.ts +11 -3
- package/dist/server/PatchesHistoryManager.js +81 -84
- package/dist/server/PatchesServer.d.ts +16 -10
- package/dist/server/PatchesServer.js +131 -137
- package/dist/server/index.d.ts +7 -2
- package/dist/server/index.js +9 -3
- package/dist/server/types.d.ts +9 -3
- package/dist/server/types.js +0 -1
- package/dist/types.d.ts +38 -19
- package/dist/types.js +1 -1
- package/dist/utils/concurrency.d.ts +7 -5
- package/dist/utils/concurrency.js +43 -53
- package/dist/utils/deferred.d.ts +4 -2
- package/dist/utils/deferred.js +25 -21
- package/package.json +5 -7
|
@@ -1,138 +1,131 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
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
|
-
|
|
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
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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 };
|