@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.
Files changed (62) hide show
  1. package/dist/lib/browser/{chunk-PEE7MYCZ.mjs → chunk-UJQ5VS5V.mjs} +1790 -3268
  2. package/dist/lib/browser/chunk-UJQ5VS5V.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +1049 -12
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +2 -224
  7. package/dist/lib/browser/testing/index.mjs.map +4 -4
  8. package/dist/lib/node/{chunk-RLTLWNAY.cjs → chunk-RH6TDRML.cjs} +783 -2233
  9. package/dist/lib/node/chunk-RH6TDRML.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +1056 -37
  11. package/dist/lib/node/index.cjs.map +4 -4
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/testing/index.cjs +13 -238
  14. package/dist/lib/node/testing/index.cjs.map +4 -4
  15. package/dist/types/src/automerge/automerge-host.d.ts +2 -29
  16. package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
  17. package/dist/types/src/automerge/echo-network-adapter.d.ts +2 -9
  18. package/dist/types/src/automerge/echo-network-adapter.d.ts.map +1 -1
  19. package/dist/types/src/automerge/echo-replicator.d.ts +0 -7
  20. package/dist/types/src/automerge/echo-replicator.d.ts.map +1 -1
  21. package/dist/types/src/automerge/heads-store.d.ts +1 -1
  22. package/dist/types/src/automerge/heads-store.d.ts.map +1 -1
  23. package/dist/types/src/automerge/index.d.ts +0 -2
  24. package/dist/types/src/automerge/index.d.ts.map +1 -1
  25. package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts +1 -3
  26. package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts.map +1 -1
  27. package/dist/types/src/automerge/mesh-echo-replicator.d.ts +2 -2
  28. package/dist/types/src/automerge/mesh-echo-replicator.d.ts.map +1 -1
  29. package/dist/types/src/db-host/data-service.d.ts +1 -2
  30. package/dist/types/src/db-host/data-service.d.ts.map +1 -1
  31. package/dist/types/src/testing/index.d.ts +0 -1
  32. package/dist/types/src/testing/index.d.ts.map +1 -1
  33. package/package.json +33 -33
  34. package/src/automerge/automerge-host.test.ts +14 -76
  35. package/src/automerge/automerge-host.ts +30 -217
  36. package/src/automerge/automerge-repo.test.ts +1 -2
  37. package/src/automerge/echo-network-adapter.test.ts +1 -5
  38. package/src/automerge/echo-network-adapter.ts +4 -69
  39. package/src/automerge/echo-replicator.ts +0 -9
  40. package/src/automerge/heads-store.ts +9 -6
  41. package/src/automerge/index.ts +0 -2
  42. package/src/automerge/mesh-echo-replicator-connection.ts +1 -6
  43. package/src/automerge/mesh-echo-replicator.ts +7 -28
  44. package/src/db-host/data-service.ts +12 -26
  45. package/src/testing/index.ts +0 -1
  46. package/dist/lib/browser/chunk-PEE7MYCZ.mjs.map +0 -7
  47. package/dist/lib/node/chunk-RLTLWNAY.cjs.map +0 -7
  48. package/dist/types/src/automerge/collection-synchronizer.d.ts +0 -61
  49. package/dist/types/src/automerge/collection-synchronizer.d.ts.map +0 -1
  50. package/dist/types/src/automerge/collection-synchronizer.test.d.ts +0 -2
  51. package/dist/types/src/automerge/collection-synchronizer.test.d.ts.map +0 -1
  52. package/dist/types/src/automerge/network-protocol.d.ts +0 -31
  53. package/dist/types/src/automerge/network-protocol.d.ts.map +0 -1
  54. package/dist/types/src/automerge/space-collection.d.ts +0 -4
  55. package/dist/types/src/automerge/space-collection.d.ts.map +0 -1
  56. package/dist/types/src/testing/test-replicator.d.ts +0 -46
  57. package/dist/types/src/testing/test-replicator.d.ts.map +0 -1
  58. package/src/automerge/collection-synchronizer.test.ts +0 -91
  59. package/src/automerge/collection-synchronizer.ts +0 -204
  60. package/src/automerge/network-protocol.ts +0 -45
  61. package/src/automerge/space-collection.ts +0 -14
  62. 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 { NetworkAdapter, type Message, type PeerId, type PeerMetadata } from '@dxos/automerge/automerge-repo';
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
- import { nonNullable } from '@dxos/util';
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._onMessage(value);
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
- // TODO(dmaretskyi): Make batched.
30
- async getHeads(documentIds: DocumentId[]): Promise<Array<Heads | undefined>> {
31
- return this._db.getMany<DocumentId, Heads>(documentIds, {
32
- keyEncoding: 'utf8',
33
- valueEncoding: headsEncoding,
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
  }
@@ -6,5 +6,3 @@ export * from './automerge-host';
6
6
  export * from './leveldb-storage-adapter';
7
7
  export * from './mesh-echo-replicator';
8
8
  export * from './echo-replicator';
9
- export { diffCollectionState } from './collection-synchronizer';
10
- export * from './space-collection';
@@ -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, ShouldSyncCollectionParams } from './echo-replicator';
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, type SpaceId } from '@dxos/keys';
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
- * spaceId -> deviceKey[]
30
+ * spaceKey -> deviceKey[]
33
31
  */
34
- private readonly _authorizedDevices = new Map<SpaceId, ComplexSet<PublicKey>>();
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 spaceId = await createIdFromSpaceKey(spaceKey);
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
- async authorizeDevice(spaceKey: PublicKey, deviceKey: PublicKey) {
122
+ authorizeDevice(spaceKey: PublicKey, deviceKey: PublicKey) {
143
123
  log('authorizeDevice', { spaceKey, deviceKey });
144
- const spaceId = await createIdFromSpaceKey(spaceKey);
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 { deriveCollectionIdFromSpaceId, type AutomergeHost } from '../automerge';
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 documentIds = request.documentIds;
97
- if (!documentIds) {
98
- return { heads: { entries: [] } };
99
- }
100
- const heads = await this._automergeHost.getHeads(documentIds as DocumentId[]);
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: heads.map((heads, idx) => ({ documentId: documentIds[idx], heads })),
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
  }
@@ -6,4 +6,3 @@ export * from './change-metadata';
6
6
  export * from './test-agent-builder';
7
7
  export * from './test-feed-builder';
8
8
  export * from './test-network-adapter';
9
- export * from './test-replicator';