@dxos/echo-pipeline 0.6.3-main.9e4e207 → 0.6.3-next.2f65b78
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/lib/browser/{chunk-PEE7MYCZ.mjs → chunk-UJQ5VS5V.mjs} +1790 -3268
- package/dist/lib/browser/chunk-UJQ5VS5V.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1049 -12
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +2 -224
- package/dist/lib/browser/testing/index.mjs.map +4 -4
- package/dist/lib/node/{chunk-RLTLWNAY.cjs → chunk-RH6TDRML.cjs} +783 -2233
- package/dist/lib/node/chunk-RH6TDRML.cjs.map +7 -0
- package/dist/lib/node/index.cjs +1056 -37
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +13 -238
- package/dist/lib/node/testing/index.cjs.map +4 -4
- package/dist/types/src/automerge/automerge-host.d.ts +2 -29
- package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
- package/dist/types/src/automerge/echo-network-adapter.d.ts +2 -9
- package/dist/types/src/automerge/echo-network-adapter.d.ts.map +1 -1
- package/dist/types/src/automerge/echo-replicator.d.ts +0 -7
- package/dist/types/src/automerge/echo-replicator.d.ts.map +1 -1
- package/dist/types/src/automerge/heads-store.d.ts +1 -1
- package/dist/types/src/automerge/heads-store.d.ts.map +1 -1
- package/dist/types/src/automerge/index.d.ts +0 -2
- package/dist/types/src/automerge/index.d.ts.map +1 -1
- package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts +1 -3
- package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts.map +1 -1
- package/dist/types/src/automerge/mesh-echo-replicator.d.ts +2 -2
- package/dist/types/src/automerge/mesh-echo-replicator.d.ts.map +1 -1
- package/dist/types/src/db-host/data-service.d.ts +1 -2
- package/dist/types/src/db-host/data-service.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +0 -1
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/package.json +33 -33
- package/src/automerge/automerge-host.test.ts +14 -76
- package/src/automerge/automerge-host.ts +30 -217
- package/src/automerge/automerge-repo.test.ts +1 -2
- package/src/automerge/echo-network-adapter.test.ts +1 -5
- package/src/automerge/echo-network-adapter.ts +4 -69
- package/src/automerge/echo-replicator.ts +0 -9
- package/src/automerge/heads-store.ts +9 -6
- package/src/automerge/index.ts +0 -2
- package/src/automerge/mesh-echo-replicator-connection.ts +1 -6
- package/src/automerge/mesh-echo-replicator.ts +7 -28
- package/src/db-host/data-service.ts +12 -26
- package/src/testing/index.ts +0 -1
- package/dist/lib/browser/chunk-PEE7MYCZ.mjs.map +0 -7
- package/dist/lib/node/chunk-RLTLWNAY.cjs.map +0 -7
- package/dist/types/src/automerge/collection-synchronizer.d.ts +0 -61
- package/dist/types/src/automerge/collection-synchronizer.d.ts.map +0 -1
- package/dist/types/src/automerge/collection-synchronizer.test.d.ts +0 -2
- package/dist/types/src/automerge/collection-synchronizer.test.d.ts.map +0 -1
- package/dist/types/src/automerge/network-protocol.d.ts +0 -31
- package/dist/types/src/automerge/network-protocol.d.ts.map +0 -1
- package/dist/types/src/automerge/space-collection.d.ts +0 -4
- package/dist/types/src/automerge/space-collection.d.ts.map +0 -1
- package/dist/types/src/testing/test-replicator.d.ts +0 -46
- package/dist/types/src/testing/test-replicator.d.ts.map +0 -1
- package/src/automerge/collection-synchronizer.test.ts +0 -91
- package/src/automerge/collection-synchronizer.ts +0 -204
- package/src/automerge/network-protocol.ts +0 -45
- package/src/automerge/space-collection.ts +0 -14
- package/src/testing/test-replicator.ts +0 -194
|
@@ -103,11 +103,7 @@ describe('EchoNetworkAdapter', () => {
|
|
|
103
103
|
});
|
|
104
104
|
|
|
105
105
|
const createConnectedAdapter = async (replicator: MeshEchoReplicator) => {
|
|
106
|
-
const adapter = new EchoNetworkAdapter({
|
|
107
|
-
getContainingSpaceForDocument: async () => null,
|
|
108
|
-
onCollectionStateQueried: () => {},
|
|
109
|
-
onCollectionStateReceived: () => {},
|
|
110
|
-
});
|
|
106
|
+
const adapter = new EchoNetworkAdapter({ getContainingSpaceForDocument: async () => null });
|
|
111
107
|
adapter.connect(PEER_ID);
|
|
112
108
|
await adapter.open();
|
|
113
109
|
afterTest(() => adapter.close());
|
|
@@ -3,30 +3,16 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { synchronized, Trigger } from '@dxos/async';
|
|
6
|
-
import {
|
|
6
|
+
import { type Message, NetworkAdapter, type PeerId, type PeerMetadata } from '@dxos/automerge/automerge-repo';
|
|
7
7
|
import { LifecycleState } from '@dxos/context';
|
|
8
8
|
import { invariant } from '@dxos/invariant';
|
|
9
9
|
import { type PublicKey } from '@dxos/keys';
|
|
10
10
|
import { log } from '@dxos/log';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import {
|
|
14
|
-
type EchoReplicator,
|
|
15
|
-
type ReplicatorConnection,
|
|
16
|
-
type ShouldAdvertiseParams,
|
|
17
|
-
type ShouldSyncCollectionParams,
|
|
18
|
-
} from './echo-replicator';
|
|
19
|
-
import {
|
|
20
|
-
isCollectionQueryMessage,
|
|
21
|
-
isCollectionStateMessage,
|
|
22
|
-
type CollectionQueryMessage,
|
|
23
|
-
type CollectionStateMessage,
|
|
24
|
-
} from './network-protocol';
|
|
11
|
+
|
|
12
|
+
import { type EchoReplicator, type ReplicatorConnection, type ShouldAdvertiseParams } from './echo-replicator';
|
|
25
13
|
|
|
26
14
|
export type EchoNetworkAdapterParams = {
|
|
27
15
|
getContainingSpaceForDocument: (documentId: string) => Promise<PublicKey | null>;
|
|
28
|
-
onCollectionStateQueried: (collectionId: string, peerId: PeerId) => void;
|
|
29
|
-
onCollectionStateReceived: (collectionId: string, peerId: PeerId, state: unknown) => void;
|
|
30
16
|
};
|
|
31
17
|
|
|
32
18
|
/**
|
|
@@ -133,47 +119,6 @@ export class EchoNetworkAdapter extends NetworkAdapter {
|
|
|
133
119
|
return connection.connection.shouldAdvertise(params);
|
|
134
120
|
}
|
|
135
121
|
|
|
136
|
-
shouldSyncCollection(peerId: PeerId, params: ShouldSyncCollectionParams): boolean {
|
|
137
|
-
const connection = this._connections.get(peerId);
|
|
138
|
-
if (!connection) {
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return connection.connection.shouldSyncCollection(params);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
queryCollectionState(collectionId: string, targetId: PeerId): void {
|
|
146
|
-
const message: CollectionQueryMessage = {
|
|
147
|
-
type: 'collection-query',
|
|
148
|
-
senderId: this.peerId as PeerId,
|
|
149
|
-
targetId,
|
|
150
|
-
collectionId,
|
|
151
|
-
};
|
|
152
|
-
this.send(message);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
sendCollectionState(collectionId: string, targetId: PeerId, state: unknown): void {
|
|
156
|
-
const message: CollectionStateMessage = {
|
|
157
|
-
type: 'collection-state',
|
|
158
|
-
senderId: this.peerId as PeerId,
|
|
159
|
-
targetId,
|
|
160
|
-
collectionId,
|
|
161
|
-
state,
|
|
162
|
-
};
|
|
163
|
-
this.send(message);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// TODO(dmaretskyi): Remove.
|
|
167
|
-
getPeersInterestedInCollection(collectionId: string): PeerId[] {
|
|
168
|
-
return Array.from(this._connections.values())
|
|
169
|
-
.map((connection) => {
|
|
170
|
-
return connection.connection.shouldSyncCollection({ collectionId })
|
|
171
|
-
? (connection.connection.peerId as PeerId)
|
|
172
|
-
: null;
|
|
173
|
-
})
|
|
174
|
-
.filter(nonNullable);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
122
|
private _onConnectionOpen(connection: ReplicatorConnection) {
|
|
178
123
|
log('Connection opened', { peerId: connection.peerId });
|
|
179
124
|
invariant(!this._connections.has(connection.peerId as PeerId));
|
|
@@ -191,7 +136,7 @@ export class EchoNetworkAdapter extends NetworkAdapter {
|
|
|
191
136
|
break;
|
|
192
137
|
}
|
|
193
138
|
|
|
194
|
-
this.
|
|
139
|
+
this.emit('message', value);
|
|
195
140
|
}
|
|
196
141
|
} catch (err) {
|
|
197
142
|
if (connectionEntry.isOpen) {
|
|
@@ -204,16 +149,6 @@ export class EchoNetworkAdapter extends NetworkAdapter {
|
|
|
204
149
|
this._emitPeerCandidate(connection);
|
|
205
150
|
}
|
|
206
151
|
|
|
207
|
-
private _onMessage(message: Message) {
|
|
208
|
-
if (isCollectionQueryMessage(message)) {
|
|
209
|
-
this._params.onCollectionStateQueried(message.collectionId, message.senderId);
|
|
210
|
-
} else if (isCollectionStateMessage(message)) {
|
|
211
|
-
this._params.onCollectionStateReceived(message.collectionId, message.senderId, message.state);
|
|
212
|
-
} else {
|
|
213
|
-
this.emit('message', message);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
152
|
/**
|
|
218
153
|
* Trigger doc-synchronizer shared documents set recalculation. Happens on peer-candidate.
|
|
219
154
|
* TODO(y): replace with a proper API call when sharePolicy update becomes supported by automerge-repo
|
|
@@ -51,17 +51,8 @@ export interface ReplicatorConnection {
|
|
|
51
51
|
* The remote peer can still request the document by its id bypassing this check.
|
|
52
52
|
*/
|
|
53
53
|
shouldAdvertise(params: ShouldAdvertiseParams): Promise<boolean>;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @returns true if the collection should be synced to this peer.
|
|
57
|
-
*/
|
|
58
|
-
shouldSyncCollection(params: ShouldSyncCollectionParams): boolean;
|
|
59
54
|
}
|
|
60
55
|
|
|
61
56
|
export type ShouldAdvertiseParams = {
|
|
62
57
|
documentId: string;
|
|
63
58
|
};
|
|
64
|
-
|
|
65
|
-
export type ShouldSyncCollectionParams = {
|
|
66
|
-
collectionId: string;
|
|
67
|
-
};
|
|
@@ -26,11 +26,14 @@ export class HeadsStore {
|
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
async getHeads(documentId: DocumentId): Promise<Heads | undefined> {
|
|
30
|
+
try {
|
|
31
|
+
return await this._db.get<DocumentId, Heads>(documentId, { keyEncoding: 'utf8', valueEncoding: headsEncoding });
|
|
32
|
+
} catch (err: any) {
|
|
33
|
+
if (err.notFound) {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
throw err;
|
|
37
|
+
}
|
|
35
38
|
}
|
|
36
39
|
}
|
package/src/automerge/index.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { type PublicKey } from '@dxos/keys';
|
|
|
9
9
|
import { log } from '@dxos/log';
|
|
10
10
|
import { AutomergeReplicator, type AutomergeReplicatorFactory } from '@dxos/teleport-extension-automerge-replicator';
|
|
11
11
|
|
|
12
|
-
import type { ReplicatorConnection, ShouldAdvertiseParams
|
|
12
|
+
import type { ReplicatorConnection, ShouldAdvertiseParams } from './echo-replicator';
|
|
13
13
|
|
|
14
14
|
const DEFAULT_FACTORY: AutomergeReplicatorFactory = (params) => new AutomergeReplicator(...params);
|
|
15
15
|
|
|
@@ -18,7 +18,6 @@ export type MeshReplicatorConnectionParams = {
|
|
|
18
18
|
onRemoteConnected: () => void;
|
|
19
19
|
onRemoteDisconnected: () => void;
|
|
20
20
|
shouldAdvertise: (params: ShouldAdvertiseParams) => Promise<boolean>;
|
|
21
|
-
shouldSyncCollection: (params: ShouldSyncCollectionParams) => boolean;
|
|
22
21
|
replicatorFactory?: AutomergeReplicatorFactory;
|
|
23
22
|
};
|
|
24
23
|
|
|
@@ -113,10 +112,6 @@ export class MeshReplicatorConnection extends Resource implements ReplicatorConn
|
|
|
113
112
|
return this._params.shouldAdvertise(params);
|
|
114
113
|
}
|
|
115
114
|
|
|
116
|
-
shouldSyncCollection(params: ShouldSyncCollectionParams): boolean {
|
|
117
|
-
return this._params.shouldSyncCollection(params);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
115
|
/**
|
|
121
116
|
* Start exchanging messages with the remote peer.
|
|
122
117
|
* Call after the remote peer has connected.
|
|
@@ -3,18 +3,16 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { invariant } from '@dxos/invariant';
|
|
6
|
-
import { PublicKey
|
|
6
|
+
import { PublicKey } from '@dxos/keys';
|
|
7
7
|
import { log } from '@dxos/log';
|
|
8
8
|
import {
|
|
9
9
|
type AutomergeReplicator,
|
|
10
10
|
type AutomergeReplicatorFactory,
|
|
11
11
|
} from '@dxos/teleport-extension-automerge-replicator';
|
|
12
|
-
import { ComplexSet, defaultMap } from '@dxos/util';
|
|
12
|
+
import { ComplexMap, ComplexSet, defaultMap } from '@dxos/util';
|
|
13
13
|
|
|
14
14
|
import { type EchoReplicator, type EchoReplicatorContext, type ShouldAdvertiseParams } from './echo-replicator';
|
|
15
15
|
import { MeshReplicatorConnection } from './mesh-echo-replicator-connection';
|
|
16
|
-
import { getSpaceIdFromCollectionId } from './space-collection';
|
|
17
|
-
import { createIdFromSpaceKey } from '../space';
|
|
18
16
|
|
|
19
17
|
// TODO(dmaretskyi): Move out of @dxos/echo-pipeline.
|
|
20
18
|
|
|
@@ -29,9 +27,9 @@ export class MeshEchoReplicator implements EchoReplicator {
|
|
|
29
27
|
private readonly _connectionsPerPeer = new Map<string, MeshReplicatorConnection>();
|
|
30
28
|
|
|
31
29
|
/**
|
|
32
|
-
*
|
|
30
|
+
* spaceKey -> deviceKey[]
|
|
33
31
|
*/
|
|
34
|
-
private readonly _authorizedDevices = new
|
|
32
|
+
private readonly _authorizedDevices = new ComplexMap<PublicKey, ComplexSet<PublicKey>>(PublicKey.hash);
|
|
35
33
|
|
|
36
34
|
private _context: EchoReplicatorContext | null = null;
|
|
37
35
|
|
|
@@ -90,9 +88,7 @@ export class MeshEchoReplicator implements EchoReplicator {
|
|
|
90
88
|
return false;
|
|
91
89
|
}
|
|
92
90
|
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
const authorizedDevices = this._authorizedDevices.get(spaceId);
|
|
91
|
+
const authorizedDevices = this._authorizedDevices.get(spaceKey);
|
|
96
92
|
|
|
97
93
|
if (!connection.remoteDeviceKey) {
|
|
98
94
|
log('device key not found for share policy check', {
|
|
@@ -117,32 +113,15 @@ export class MeshEchoReplicator implements EchoReplicator {
|
|
|
117
113
|
return false;
|
|
118
114
|
}
|
|
119
115
|
},
|
|
120
|
-
shouldSyncCollection: ({ collectionId }) => {
|
|
121
|
-
const spaceId = getSpaceIdFromCollectionId(collectionId);
|
|
122
|
-
|
|
123
|
-
const authorizedDevices = this._authorizedDevices.get(spaceId);
|
|
124
|
-
|
|
125
|
-
if (!connection.remoteDeviceKey) {
|
|
126
|
-
log('device key not found for collection sync check', {
|
|
127
|
-
peerId: connection.peerId,
|
|
128
|
-
collectionId,
|
|
129
|
-
});
|
|
130
|
-
return false;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const isAuthorized = authorizedDevices?.has(connection.remoteDeviceKey) ?? false;
|
|
134
|
-
return isAuthorized;
|
|
135
|
-
},
|
|
136
116
|
});
|
|
137
117
|
this._connections.add(connection);
|
|
138
118
|
|
|
139
119
|
return connection.replicatorExtension;
|
|
140
120
|
}
|
|
141
121
|
|
|
142
|
-
|
|
122
|
+
authorizeDevice(spaceKey: PublicKey, deviceKey: PublicKey) {
|
|
143
123
|
log('authorizeDevice', { spaceKey, deviceKey });
|
|
144
|
-
|
|
145
|
-
defaultMap(this._authorizedDevices, spaceId, () => new ComplexSet(PublicKey.hash)).add(deviceKey);
|
|
124
|
+
defaultMap(this._authorizedDevices, spaceKey, () => new ComplexSet(PublicKey.hash)).add(deviceKey);
|
|
146
125
|
for (const connection of this._connections) {
|
|
147
126
|
if (connection.remoteDeviceKey && connection.remoteDeviceKey.equals(deviceKey)) {
|
|
148
127
|
if (this._connectionsPerPeer.has(connection.peerId)) {
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
import { type DocumentId } from '@dxos/automerge/automerge-repo';
|
|
6
6
|
import { type RequestOptions, Stream } from '@dxos/codec-protobuf';
|
|
7
7
|
import { invariant } from '@dxos/invariant';
|
|
8
|
-
import { SpaceId } from '@dxos/keys';
|
|
9
8
|
import { log } from '@dxos/log';
|
|
10
9
|
import {
|
|
11
10
|
type DataService,
|
|
11
|
+
type DocHeadsList,
|
|
12
12
|
type FlushRequest,
|
|
13
13
|
type SubscribeRequest,
|
|
14
14
|
type BatchedDocumentUpdates,
|
|
@@ -18,12 +18,10 @@ import {
|
|
|
18
18
|
type ReIndexHeadsRequest,
|
|
19
19
|
type WaitUntilHeadsReplicatedRequest,
|
|
20
20
|
type UpdateRequest,
|
|
21
|
-
type GetSpaceSyncStateRequest,
|
|
22
|
-
type SpaceSyncState,
|
|
23
21
|
} from '@dxos/protocols/proto/dxos/echo/service';
|
|
24
22
|
|
|
25
23
|
import { DocumentsSynchronizer } from './documents-synchronizer';
|
|
26
|
-
import {
|
|
24
|
+
import { type AutomergeHost } from '../automerge';
|
|
27
25
|
|
|
28
26
|
export type DataServiceParams = {
|
|
29
27
|
automergeHost: AutomergeHost;
|
|
@@ -93,14 +91,18 @@ export class DataServiceImpl implements DataService {
|
|
|
93
91
|
}
|
|
94
92
|
|
|
95
93
|
async getDocumentHeads(request: GetDocumentHeadsRequest): Promise<GetDocumentHeadsResponse> {
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
94
|
+
const entries = await Promise.all(
|
|
95
|
+
request.documentIds?.map(async (documentId): Promise<DocHeadsList.Entry> => {
|
|
96
|
+
const heads = await this._automergeHost.getHeads(documentId as DocumentId);
|
|
97
|
+
return {
|
|
98
|
+
documentId,
|
|
99
|
+
heads,
|
|
100
|
+
};
|
|
101
|
+
}) ?? [],
|
|
102
|
+
);
|
|
101
103
|
return {
|
|
102
104
|
heads: {
|
|
103
|
-
entries
|
|
105
|
+
entries,
|
|
104
106
|
},
|
|
105
107
|
};
|
|
106
108
|
}
|
|
@@ -119,20 +121,4 @@ export class DataServiceImpl implements DataService {
|
|
|
119
121
|
async updateIndexes() {
|
|
120
122
|
await this._updateIndexes();
|
|
121
123
|
}
|
|
122
|
-
|
|
123
|
-
async getSpaceSyncState(
|
|
124
|
-
request: GetSpaceSyncStateRequest,
|
|
125
|
-
options?: RequestOptions | undefined,
|
|
126
|
-
): Promise<SpaceSyncState> {
|
|
127
|
-
invariant(SpaceId.isValid(request.spaceId));
|
|
128
|
-
const collectionId = deriveCollectionIdFromSpaceId(request.spaceId);
|
|
129
|
-
const state = await this._automergeHost.getCollectionSyncState(collectionId);
|
|
130
|
-
|
|
131
|
-
return {
|
|
132
|
-
peers: state.peers.map((peer) => ({
|
|
133
|
-
peerId: peer.peerId,
|
|
134
|
-
documentsToReconcile: peer.differentDocuments,
|
|
135
|
-
})),
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
124
|
}
|
package/src/testing/index.ts
CHANGED