@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,124 +1,115 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
transport;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
import "../../chunk-IZ2YBCUP.js";
|
|
2
|
+
import { signal } from "../../event-signal.js";
|
|
3
|
+
class WebRTCAwareness {
|
|
4
|
+
/**
|
|
5
|
+
* Creates a new WebRTC awareness instance.
|
|
6
|
+
* @param transport - The WebRTC transport to use for awareness communication
|
|
7
|
+
*/
|
|
8
|
+
constructor(transport) {
|
|
9
|
+
this.transport = transport;
|
|
10
|
+
this.transport.onPeerConnect(this._addPeer.bind(this));
|
|
11
|
+
this.transport.onPeerDisconnect(this._removePeer.bind(this));
|
|
12
|
+
this.transport.onMessage(this._receiveData.bind(this));
|
|
13
|
+
}
|
|
14
|
+
_states = [];
|
|
15
|
+
_localState = {};
|
|
16
|
+
/**
|
|
17
|
+
* Signal that emits when the awareness state is updated.
|
|
18
|
+
* Subscribers receive the complete new awareness state array.
|
|
19
|
+
*/
|
|
20
|
+
onUpdate = signal();
|
|
21
|
+
/**
|
|
22
|
+
* The peer ID of this client, obtained from the WebRTC transport.
|
|
23
|
+
*/
|
|
24
|
+
myId;
|
|
25
|
+
/**
|
|
26
|
+
* Connects to the WebRTC network to start synchronizing awareness states.
|
|
27
|
+
* @returns A promise that resolves when the connection is established
|
|
28
|
+
*/
|
|
29
|
+
async connect() {
|
|
30
|
+
await this.transport.connect();
|
|
31
|
+
this.myId = this.transport.id;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Disconnects from the WebRTC network and stops awareness synchronization.
|
|
35
|
+
*/
|
|
36
|
+
disconnect() {
|
|
37
|
+
this.transport.disconnect();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Gets the current combined awareness state of all peers.
|
|
41
|
+
* @returns An array of awareness states from all connected peers
|
|
42
|
+
*/
|
|
43
|
+
get states() {
|
|
44
|
+
return this._states;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Sets the combined awareness state and emits an update event.
|
|
48
|
+
* This method is protected and typically used internally.
|
|
49
|
+
* @param state - The new combined awareness state array
|
|
50
|
+
*/
|
|
51
|
+
set states(state) {
|
|
52
|
+
this._states = state;
|
|
53
|
+
this.onUpdate.emit(this._states);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Gets this peer's local awareness state.
|
|
57
|
+
* @returns The current local awareness state
|
|
58
|
+
*/
|
|
59
|
+
get localState() {
|
|
60
|
+
return this._localState;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Sets this peer's local awareness state and broadcasts it to all connected peers.
|
|
64
|
+
* @param value - The new local awareness state to set and broadcast
|
|
65
|
+
*/
|
|
66
|
+
set localState(value) {
|
|
67
|
+
value.id = this.myId;
|
|
68
|
+
this._localState = value;
|
|
69
|
+
this.transport.send(JSON.stringify(value));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Handles a new peer connection by sending the local state to the new peer.
|
|
73
|
+
* @private
|
|
74
|
+
* @param peerId - ID of the newly connected peer
|
|
75
|
+
*/
|
|
76
|
+
_addPeer(peerId) {
|
|
77
|
+
if (this._localState.id) {
|
|
78
|
+
this.transport.send(JSON.stringify(this._localState), peerId);
|
|
31
79
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Handles a peer disconnection by removing their state from the awareness state.
|
|
83
|
+
* @private
|
|
84
|
+
* @param peerId - ID of the disconnected peer
|
|
85
|
+
*/
|
|
86
|
+
_removePeer(peerId) {
|
|
87
|
+
this.states = this.states.filter((s) => s.id !== peerId);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Processes incoming awareness data from other peers.
|
|
91
|
+
* @private
|
|
92
|
+
* @param data - The serialized awareness state data received from a peer
|
|
93
|
+
*/
|
|
94
|
+
_receiveData(data) {
|
|
95
|
+
let peerState;
|
|
96
|
+
try {
|
|
97
|
+
peerState = JSON.parse(data);
|
|
98
|
+
if (!peerState?.id) return;
|
|
99
|
+
} catch (err) {
|
|
100
|
+
console.error("Invalid peer data:", err);
|
|
101
|
+
return;
|
|
40
102
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Gets the current combined awareness state of all peers.
|
|
49
|
-
* @returns An array of awareness states from all connected peers
|
|
50
|
-
*/
|
|
51
|
-
get states() {
|
|
52
|
-
return this._states;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Sets the combined awareness state and emits an update event.
|
|
56
|
-
* This method is protected and typically used internally.
|
|
57
|
-
* @param state - The new combined awareness state array
|
|
58
|
-
*/
|
|
59
|
-
set states(state) {
|
|
60
|
-
this._states = state;
|
|
61
|
-
this.onUpdate.emit(this._states);
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Gets this peer's local awareness state.
|
|
65
|
-
* @returns The current local awareness state
|
|
66
|
-
*/
|
|
67
|
-
get localState() {
|
|
68
|
-
return this._localState;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Sets this peer's local awareness state and broadcasts it to all connected peers.
|
|
72
|
-
* @param value - The new local awareness state to set and broadcast
|
|
73
|
-
*/
|
|
74
|
-
set localState(value) {
|
|
75
|
-
value.id = this.myId;
|
|
76
|
-
this._localState = value;
|
|
77
|
-
this.transport.send(JSON.stringify(value));
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Handles a new peer connection by sending the local state to the new peer.
|
|
81
|
-
* @private
|
|
82
|
-
* @param peerId - ID of the newly connected peer
|
|
83
|
-
*/
|
|
84
|
-
_addPeer(peerId) {
|
|
85
|
-
// If localState has been set (id will exist once set)
|
|
86
|
-
if (this._localState.id) {
|
|
87
|
-
this.transport.send(JSON.stringify(this._localState), peerId);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Handles a peer disconnection by removing their state from the awareness state.
|
|
92
|
-
* @private
|
|
93
|
-
* @param peerId - ID of the disconnected peer
|
|
94
|
-
*/
|
|
95
|
-
_removePeer(peerId) {
|
|
96
|
-
this.states = this.states.filter(s => s.id !== peerId);
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Processes incoming awareness data from other peers.
|
|
100
|
-
* @private
|
|
101
|
-
* @param data - The serialized awareness state data received from a peer
|
|
102
|
-
*/
|
|
103
|
-
_receiveData(data) {
|
|
104
|
-
let peerState;
|
|
105
|
-
try {
|
|
106
|
-
peerState = JSON.parse(data);
|
|
107
|
-
if (!peerState?.id)
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
catch (err) {
|
|
111
|
-
console.error('Invalid peer data:', err);
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
const update = [...this.states];
|
|
115
|
-
const existingIndex = update.findIndex(s => s.id === peerState.id);
|
|
116
|
-
if (existingIndex !== -1) {
|
|
117
|
-
update.splice(existingIndex, 1, { ...update[existingIndex], ...peerState });
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
update.push(peerState);
|
|
121
|
-
}
|
|
122
|
-
this.states = update;
|
|
103
|
+
const update = [...this.states];
|
|
104
|
+
const existingIndex = update.findIndex((s) => s.id === peerState.id);
|
|
105
|
+
if (existingIndex !== -1) {
|
|
106
|
+
update.splice(existingIndex, 1, { ...update[existingIndex], ...peerState });
|
|
107
|
+
} else {
|
|
108
|
+
update.push(peerState);
|
|
123
109
|
}
|
|
110
|
+
this.states = update;
|
|
111
|
+
}
|
|
124
112
|
}
|
|
113
|
+
export {
|
|
114
|
+
WebRTCAwareness
|
|
115
|
+
};
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
+
import { ClientTransport, ConnectionState } from '../protocol/types.js';
|
|
2
|
+
import { Signal } from '../../event-signal.js';
|
|
1
3
|
import Peer from 'simple-peer';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
+
import { WebSocketTransport } from '../websocket/WebSocketTransport.js';
|
|
5
|
+
import '../../types.js';
|
|
6
|
+
import '../../json-patch/JSONPatch.js';
|
|
7
|
+
import '@dabble/delta';
|
|
8
|
+
import '../../json-patch/types.js';
|
|
9
|
+
|
|
4
10
|
/**
|
|
5
11
|
* WebRTC-based transport implementation that enables direct peer-to-peer communication.
|
|
6
12
|
* Uses a WebSocket transport as a signaling channel to establish WebRTC connections.
|
|
7
13
|
* Once connections are established, data flows directly between peers without going through a server.
|
|
8
14
|
*/
|
|
9
|
-
|
|
15
|
+
declare class WebRTCTransport implements ClientTransport {
|
|
10
16
|
private transport;
|
|
11
17
|
private rpc;
|
|
12
18
|
private peers;
|
|
@@ -16,22 +22,22 @@ export declare class WebRTCTransport implements ClientTransport {
|
|
|
16
22
|
* Signal that emits when a message is received from a peer.
|
|
17
23
|
* Provides the message data, peer ID, and peer instance.
|
|
18
24
|
*/
|
|
19
|
-
readonly onMessage:
|
|
25
|
+
readonly onMessage: Signal<(data: string, peerId: string, peer: Peer.Instance) => void>;
|
|
20
26
|
/**
|
|
21
27
|
* Signal that emits when a new peer connection is established.
|
|
22
28
|
* Provides the peer ID and peer instance.
|
|
23
29
|
*/
|
|
24
|
-
readonly onPeerConnect:
|
|
30
|
+
readonly onPeerConnect: Signal<(peerId: string, peer: Peer.Instance) => void>;
|
|
25
31
|
/**
|
|
26
32
|
* Signal that emits when a peer disconnects.
|
|
27
33
|
* Provides the peer ID and peer instance.
|
|
28
34
|
*/
|
|
29
|
-
readonly onPeerDisconnect:
|
|
35
|
+
readonly onPeerDisconnect: Signal<(peerId: string, peer: Peer.Instance) => void>;
|
|
30
36
|
/**
|
|
31
37
|
* Signal that emits when the underlying signaling transport's state changes.
|
|
32
38
|
* This is delegated directly from the WebSocketTransport.
|
|
33
39
|
*/
|
|
34
|
-
get onStateChange():
|
|
40
|
+
get onStateChange(): Signal<(state: ConnectionState) => void>;
|
|
35
41
|
/**
|
|
36
42
|
* Creates a new WebRTC transport instance.
|
|
37
43
|
* @param transport - The WebSocket transport to use for signaling
|
|
@@ -46,7 +52,7 @@ export declare class WebRTCTransport implements ClientTransport {
|
|
|
46
52
|
* Gets the current connection state of the underlying signaling transport.
|
|
47
53
|
* @returns The current connection state
|
|
48
54
|
*/
|
|
49
|
-
get state():
|
|
55
|
+
get state(): ConnectionState;
|
|
50
56
|
/**
|
|
51
57
|
* Establishes the connection by connecting to the signaling server.
|
|
52
58
|
* Peer connections will be established automatically after this.
|
|
@@ -78,3 +84,5 @@ export declare class WebRTCTransport implements ClientTransport {
|
|
|
78
84
|
*/
|
|
79
85
|
private _removePeer;
|
|
80
86
|
}
|
|
87
|
+
|
|
88
|
+
export { WebRTCTransport };
|
|
@@ -1,161 +1,153 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
subscriptions
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Signal that emits when a peer disconnects.
|
|
27
|
-
* Provides the peer ID and peer instance.
|
|
28
|
-
*/
|
|
29
|
-
onPeerDisconnect = signal();
|
|
30
|
-
/**
|
|
31
|
-
* Signal that emits when the underlying signaling transport's state changes.
|
|
32
|
-
* This is delegated directly from the WebSocketTransport.
|
|
33
|
-
*/
|
|
34
|
-
get onStateChange() {
|
|
35
|
-
return this.transport.onStateChange;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Creates a new WebRTC transport instance.
|
|
39
|
-
* @param transport - The WebSocket transport to use for signaling
|
|
40
|
-
*/
|
|
41
|
-
constructor(transport) {
|
|
42
|
-
this.transport = transport;
|
|
43
|
-
this.rpc = new JSONRPCClient(transport);
|
|
44
|
-
this.subscriptions = [
|
|
45
|
-
this.rpc.on('peer-welcome', ({ id, peers }) => {
|
|
46
|
-
this._id = id;
|
|
47
|
-
peers.forEach((peerId) => this._connectToPeer(peerId, true));
|
|
48
|
-
}),
|
|
49
|
-
this.rpc.on('peer-disconnected', ({ id }) => {
|
|
50
|
-
this._removePeer(id);
|
|
51
|
-
}),
|
|
52
|
-
this.rpc.on('peer-signal', ({ from, data }) => {
|
|
53
|
-
if (!this.peers.has(from)) {
|
|
54
|
-
this._connectToPeer(from, false);
|
|
55
|
-
}
|
|
56
|
-
this.peers.get(from)?.peer.signal(data);
|
|
57
|
-
}),
|
|
58
|
-
];
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Gets the unique ID assigned to this peer by the signaling server.
|
|
62
|
-
* @returns The peer ID, or undefined if not yet connected
|
|
63
|
-
*/
|
|
64
|
-
get id() {
|
|
65
|
-
return this._id;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Gets the current connection state of the underlying signaling transport.
|
|
69
|
-
* @returns The current connection state
|
|
70
|
-
*/
|
|
71
|
-
get state() {
|
|
72
|
-
return this.transport.state;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Establishes the connection by connecting to the signaling server.
|
|
76
|
-
* Peer connections will be established automatically after this.
|
|
77
|
-
* @returns A promise that resolves when connected to the signaling server
|
|
78
|
-
*/
|
|
79
|
-
async connect() {
|
|
80
|
-
await this.transport.connect();
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Terminates the connection for this transport.
|
|
84
|
-
* Must be implemented by concrete subclasses.
|
|
85
|
-
*/
|
|
86
|
-
disconnect() {
|
|
87
|
-
this.subscriptions.forEach(u => u());
|
|
88
|
-
this.subscriptions.length = 0;
|
|
89
|
-
// Call _removePeer for each peer, which handles destroy()
|
|
90
|
-
const peerIds = Array.from(this.peers.keys());
|
|
91
|
-
peerIds.forEach(peerId => this._removePeer(peerId));
|
|
92
|
-
// Ensure the map is clear after removal
|
|
93
|
-
this.peers.clear();
|
|
94
|
-
// Disconnect the underlying transport if needed (optional, depends on desired behavior)
|
|
95
|
-
// this.transport.disconnect();
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Sends data to one or all connected peers.
|
|
99
|
-
* @param data - The string data to send
|
|
100
|
-
* @param peerId - Optional ID of specific peer to send to; if omitted, sends to all peers
|
|
101
|
-
*/
|
|
102
|
-
send(data, peerId) {
|
|
103
|
-
for (const info of this.peers.values()) {
|
|
104
|
-
if (peerId && info.id !== peerId)
|
|
105
|
-
continue;
|
|
106
|
-
if (info.connected) {
|
|
107
|
-
try {
|
|
108
|
-
info.peer.send(data);
|
|
109
|
-
}
|
|
110
|
-
catch (e) {
|
|
111
|
-
console.warn('Failed to send to peer:', e);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
1
|
+
import "../../chunk-IZ2YBCUP.js";
|
|
2
|
+
import Peer from "simple-peer";
|
|
3
|
+
import { signal } from "../../event-signal.js";
|
|
4
|
+
import { JSONRPCClient } from "../../net/protocol/JSONRPCClient.js";
|
|
5
|
+
import { rpcError } from "../protocol/utils.js";
|
|
6
|
+
class WebRTCTransport {
|
|
7
|
+
/**
|
|
8
|
+
* Creates a new WebRTC transport instance.
|
|
9
|
+
* @param transport - The WebSocket transport to use for signaling
|
|
10
|
+
*/
|
|
11
|
+
constructor(transport) {
|
|
12
|
+
this.transport = transport;
|
|
13
|
+
this.rpc = new JSONRPCClient(transport);
|
|
14
|
+
this.subscriptions = [
|
|
15
|
+
this.rpc.on("peer-welcome", ({ id, peers }) => {
|
|
16
|
+
this._id = id;
|
|
17
|
+
peers.forEach((peerId) => this._connectToPeer(peerId, true));
|
|
18
|
+
}),
|
|
19
|
+
this.rpc.on("peer-disconnected", ({ id }) => {
|
|
20
|
+
this._removePeer(id);
|
|
21
|
+
}),
|
|
22
|
+
this.rpc.on("peer-signal", ({ from, data }) => {
|
|
23
|
+
if (!this.peers.has(from)) {
|
|
24
|
+
this._connectToPeer(from, false);
|
|
114
25
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
26
|
+
this.peers.get(from)?.peer.signal(data);
|
|
27
|
+
})
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
rpc;
|
|
31
|
+
peers = /* @__PURE__ */ new Map();
|
|
32
|
+
_id;
|
|
33
|
+
subscriptions;
|
|
34
|
+
/**
|
|
35
|
+
* Signal that emits when a message is received from a peer.
|
|
36
|
+
* Provides the message data, peer ID, and peer instance.
|
|
37
|
+
*/
|
|
38
|
+
onMessage = signal();
|
|
39
|
+
/**
|
|
40
|
+
* Signal that emits when a new peer connection is established.
|
|
41
|
+
* Provides the peer ID and peer instance.
|
|
42
|
+
*/
|
|
43
|
+
onPeerConnect = signal();
|
|
44
|
+
/**
|
|
45
|
+
* Signal that emits when a peer disconnects.
|
|
46
|
+
* Provides the peer ID and peer instance.
|
|
47
|
+
*/
|
|
48
|
+
onPeerDisconnect = signal();
|
|
49
|
+
/**
|
|
50
|
+
* Signal that emits when the underlying signaling transport's state changes.
|
|
51
|
+
* This is delegated directly from the WebSocketTransport.
|
|
52
|
+
*/
|
|
53
|
+
get onStateChange() {
|
|
54
|
+
return this.transport.onStateChange;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Gets the unique ID assigned to this peer by the signaling server.
|
|
58
|
+
* @returns The peer ID, or undefined if not yet connected
|
|
59
|
+
*/
|
|
60
|
+
get id() {
|
|
61
|
+
return this._id;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Gets the current connection state of the underlying signaling transport.
|
|
65
|
+
* @returns The current connection state
|
|
66
|
+
*/
|
|
67
|
+
get state() {
|
|
68
|
+
return this.transport.state;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Establishes the connection by connecting to the signaling server.
|
|
72
|
+
* Peer connections will be established automatically after this.
|
|
73
|
+
* @returns A promise that resolves when connected to the signaling server
|
|
74
|
+
*/
|
|
75
|
+
async connect() {
|
|
76
|
+
await this.transport.connect();
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Terminates the connection for this transport.
|
|
80
|
+
* Must be implemented by concrete subclasses.
|
|
81
|
+
*/
|
|
82
|
+
disconnect() {
|
|
83
|
+
this.subscriptions.forEach((u) => u());
|
|
84
|
+
this.subscriptions.length = 0;
|
|
85
|
+
const peerIds = Array.from(this.peers.keys());
|
|
86
|
+
peerIds.forEach((peerId) => this._removePeer(peerId));
|
|
87
|
+
this.peers.clear();
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Sends data to one or all connected peers.
|
|
91
|
+
* @param data - The string data to send
|
|
92
|
+
* @param peerId - Optional ID of specific peer to send to; if omitted, sends to all peers
|
|
93
|
+
*/
|
|
94
|
+
send(data, peerId) {
|
|
95
|
+
for (const info of this.peers.values()) {
|
|
96
|
+
if (peerId && info.id !== peerId) continue;
|
|
97
|
+
if (info.connected) {
|
|
98
|
+
try {
|
|
99
|
+
info.peer.send(data);
|
|
100
|
+
} catch (e) {
|
|
101
|
+
this.onMessage.emit(JSON.stringify(rpcError(-32e3, e.message)), peerId, info.peer);
|
|
159
102
|
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Establishes a WebRTC connection to a peer.
|
|
108
|
+
* @private
|
|
109
|
+
* @param peerId - ID of the peer to connect to
|
|
110
|
+
* @param initiator - Whether this peer is initiating the connection
|
|
111
|
+
*/
|
|
112
|
+
_connectToPeer(peerId, initiator) {
|
|
113
|
+
const peer = new Peer({ initiator, trickle: false });
|
|
114
|
+
peer.on("signal", (data) => {
|
|
115
|
+
this.rpc.call("peer-signal", { to: peerId, data });
|
|
116
|
+
});
|
|
117
|
+
peer.on("connect", () => {
|
|
118
|
+
this.peers.set(peerId, { id: peerId, peer, connected: true });
|
|
119
|
+
this.onPeerConnect.emit(peerId, peer);
|
|
120
|
+
});
|
|
121
|
+
peer.on("data", (raw) => {
|
|
122
|
+
try {
|
|
123
|
+
this.onMessage.emit(raw, peerId, peer);
|
|
124
|
+
} catch (e) {
|
|
125
|
+
this.onMessage.emit(JSON.stringify(rpcError(-32700, "Parse error", e)), peerId, peer);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
peer.on("close", () => {
|
|
129
|
+
this._removePeer(peerId);
|
|
130
|
+
});
|
|
131
|
+
peer.on("error", (err) => {
|
|
132
|
+
this.onMessage.emit(JSON.stringify(rpcError(-32e3, err.message)), peerId, peer);
|
|
133
|
+
this._removePeer(peerId);
|
|
134
|
+
});
|
|
135
|
+
this.peers.set(peerId, { id: peerId, peer, connected: false });
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Removes a peer from the connection pool and cleans up resources.
|
|
139
|
+
* @private
|
|
140
|
+
* @param peerId - ID of the peer to remove
|
|
141
|
+
*/
|
|
142
|
+
_removePeer(peerId) {
|
|
143
|
+
const info = this.peers.get(peerId);
|
|
144
|
+
if (info) {
|
|
145
|
+
this.peers.delete(peerId);
|
|
146
|
+
this.onPeerDisconnect.emit(peerId, info.peer);
|
|
147
|
+
info.peer.destroy();
|
|
160
148
|
}
|
|
149
|
+
}
|
|
161
150
|
}
|
|
151
|
+
export {
|
|
152
|
+
WebRTCTransport
|
|
153
|
+
};
|
|
@@ -1,2 +1,10 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
1
|
+
export { WebRTCAwareness } from './WebRTCAwareness.js';
|
|
2
|
+
export { WebRTCTransport } from './WebRTCTransport.js';
|
|
3
|
+
import '../../event-signal.js';
|
|
4
|
+
import '../protocol/types.js';
|
|
5
|
+
import '../../types.js';
|
|
6
|
+
import '../../json-patch/JSONPatch.js';
|
|
7
|
+
import '@dabble/delta';
|
|
8
|
+
import '../../json-patch/types.js';
|
|
9
|
+
import 'simple-peer';
|
|
10
|
+
import '../websocket/WebSocketTransport.js';
|
package/dist/net/webrtc/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
1
|
+
export * from "./WebRTCAwareness.js";
|
|
2
|
+
export * from "./WebRTCTransport.js";
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
* "read" – non-mutating operations (subscribe, getDoc, listVersions, …)
|
|
5
5
|
* "write" – mutating operations (commitChanges, deleteDoc, …)
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
type Access = 'read' | 'write';
|
|
8
8
|
/**
|
|
9
9
|
* Context object for authorization providers.
|
|
10
10
|
* @property {string} clientId - The ID of the client making the request.
|
|
11
11
|
* @property {any} [data] - Additional data associated with the request.
|
|
12
12
|
*/
|
|
13
|
-
|
|
13
|
+
interface AuthContext {
|
|
14
14
|
clientId?: string;
|
|
15
15
|
[k: string]: any;
|
|
16
16
|
}
|
|
@@ -20,7 +20,7 @@ export interface AuthContext {
|
|
|
20
20
|
* specific – they may look at a JWT decoded during the WebSocket handshake,
|
|
21
21
|
* consult an ACL service, inspect the actual RPC method, etc.
|
|
22
22
|
*/
|
|
23
|
-
|
|
23
|
+
interface AuthorizationProvider<T extends AuthContext = AuthContext> {
|
|
24
24
|
/**
|
|
25
25
|
* General-purpose hook executed for every JSON-RPC call that targets a
|
|
26
26
|
* document. Implementations are free to look only at the first three
|
|
@@ -44,10 +44,12 @@ export interface AuthorizationProvider<T extends AuthContext = AuthContext> {
|
|
|
44
44
|
* WARNING: This should only be used for development/testing purposes.
|
|
45
45
|
* Never use this in production as it allows unrestricted access.
|
|
46
46
|
*/
|
|
47
|
-
|
|
47
|
+
declare const allowAll: AuthorizationProvider;
|
|
48
48
|
/**
|
|
49
49
|
* A secure default provider that denies all access.
|
|
50
50
|
* This forces developers to explicitly implement proper authorization.
|
|
51
51
|
* Use this as the default to ensure security by default.
|
|
52
52
|
*/
|
|
53
|
-
|
|
53
|
+
declare const denyAll: AuthorizationProvider;
|
|
54
|
+
|
|
55
|
+
export { type Access, type AuthContext, type AuthorizationProvider, allowAll, denyAll };
|