@dxos/echo-pipeline 0.8.2-staging.7ac8446 → 0.8.2

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 (182) hide show
  1. package/dist/lib/browser/{chunk-32WDI3LB.mjs → chunk-3XSXS5EX.mjs} +15 -21
  2. package/dist/lib/browser/chunk-3XSXS5EX.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-CGS2ULMK.mjs +11 -0
  4. package/dist/lib/browser/chunk-CGS2ULMK.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-TQJTKNMS.mjs +126 -0
  6. package/dist/lib/browser/chunk-TQJTKNMS.mjs.map +7 -0
  7. package/dist/lib/browser/filter/index.mjs +11 -0
  8. package/dist/lib/browser/filter/index.mjs.map +7 -0
  9. package/dist/lib/browser/index.mjs +1380 -516
  10. package/dist/lib/browser/index.mjs.map +4 -4
  11. package/dist/lib/browser/meta.json +1 -1
  12. package/dist/lib/browser/testing/index.mjs +202 -22
  13. package/dist/lib/browser/testing/index.mjs.map +4 -4
  14. package/dist/lib/node/chunk-HOPOFWAL.cjs +147 -0
  15. package/dist/lib/node/chunk-HOPOFWAL.cjs.map +7 -0
  16. package/dist/lib/node/chunk-Q7SFCCGT.cjs +33 -0
  17. package/dist/lib/node/chunk-Q7SFCCGT.cjs.map +7 -0
  18. package/dist/lib/node/{chunk-TC2PRBEU.cjs → chunk-SG2PL5RH.cjs} +18 -24
  19. package/dist/lib/node/chunk-SG2PL5RH.cjs.map +7 -0
  20. package/dist/lib/node/filter/index.cjs +32 -0
  21. package/dist/lib/node/filter/index.cjs.map +7 -0
  22. package/dist/lib/node/index.cjs +1381 -525
  23. package/dist/lib/node/index.cjs.map +4 -4
  24. package/dist/lib/node/meta.json +1 -1
  25. package/dist/lib/node/testing/index.cjs +207 -31
  26. package/dist/lib/node/testing/index.cjs.map +4 -4
  27. package/dist/lib/node-esm/{chunk-UKOLB3LW.mjs → chunk-3BZP75TJ.mjs} +15 -21
  28. package/dist/lib/node-esm/chunk-3BZP75TJ.mjs.map +7 -0
  29. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  30. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
  31. package/dist/lib/node-esm/chunk-RVK35BS7.mjs +126 -0
  32. package/dist/lib/node-esm/chunk-RVK35BS7.mjs.map +7 -0
  33. package/dist/lib/node-esm/filter/index.mjs +11 -0
  34. package/dist/lib/node-esm/filter/index.mjs.map +7 -0
  35. package/dist/lib/node-esm/index.mjs +1380 -516
  36. package/dist/lib/node-esm/index.mjs.map +4 -4
  37. package/dist/lib/node-esm/meta.json +1 -1
  38. package/dist/lib/node-esm/testing/index.mjs +202 -22
  39. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  40. package/dist/types/src/automerge/automerge-host.d.ts +6 -4
  41. package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
  42. package/dist/types/src/automerge/collection-synchronizer.d.ts +1 -1
  43. package/dist/types/src/automerge/collection-synchronizer.d.ts.map +1 -1
  44. package/dist/types/src/automerge/echo-data-monitor.d.ts +6 -6
  45. package/dist/types/src/automerge/echo-data-monitor.d.ts.map +1 -1
  46. package/dist/types/src/automerge/echo-network-adapter.d.ts +4 -1
  47. package/dist/types/src/automerge/echo-network-adapter.d.ts.map +1 -1
  48. package/dist/types/src/automerge/heads-store.d.ts +2 -2
  49. package/dist/types/src/automerge/heads-store.d.ts.map +1 -1
  50. package/dist/types/src/automerge/leveldb-storage-adapter.d.ts +1 -1
  51. package/dist/types/src/automerge/leveldb-storage-adapter.d.ts.map +1 -1
  52. package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts.map +1 -1
  53. package/dist/types/src/automerge/mesh-echo-replicator.d.ts.map +1 -1
  54. package/dist/types/src/automerge/network-protocol.d.ts +1 -1
  55. package/dist/types/src/automerge/network-protocol.d.ts.map +1 -1
  56. package/dist/types/src/automerge/space-collection.d.ts +1 -1
  57. package/dist/types/src/automerge/space-collection.d.ts.map +1 -1
  58. package/dist/types/src/common/feeds.d.ts.map +1 -1
  59. package/dist/types/src/common/space-id.d.ts.map +1 -1
  60. package/dist/types/src/db-host/automerge-metrics.d.ts +1 -1
  61. package/dist/types/src/db-host/automerge-metrics.d.ts.map +1 -1
  62. package/dist/types/src/db-host/data-service.d.ts.map +1 -1
  63. package/dist/types/src/db-host/database-root.d.ts +7 -7
  64. package/dist/types/src/db-host/database-root.d.ts.map +1 -1
  65. package/dist/types/src/db-host/documents-iterator.d.ts +1 -1
  66. package/dist/types/src/db-host/documents-iterator.d.ts.map +1 -1
  67. package/dist/types/src/db-host/documents-synchronizer.d.ts +4 -4
  68. package/dist/types/src/db-host/documents-synchronizer.d.ts.map +1 -1
  69. package/dist/types/src/db-host/echo-host.d.ts +13 -2
  70. package/dist/types/src/db-host/echo-host.d.ts.map +1 -1
  71. package/dist/types/src/db-host/index.d.ts +0 -1
  72. package/dist/types/src/db-host/index.d.ts.map +1 -1
  73. package/dist/types/src/db-host/query-service.d.ts +2 -0
  74. package/dist/types/src/db-host/query-service.d.ts.map +1 -1
  75. package/dist/types/src/db-host/space-state-manager.d.ts +4 -3
  76. package/dist/types/src/db-host/space-state-manager.d.ts.map +1 -1
  77. package/dist/types/src/edge/echo-edge-replicator.d.ts.map +1 -1
  78. package/dist/types/src/edge/inflight-request-limiter.d.ts.map +1 -1
  79. package/dist/types/src/filter/filter-match.d.ts +13 -0
  80. package/dist/types/src/filter/filter-match.d.ts.map +1 -0
  81. package/dist/types/src/filter/filter-match.test.d.ts +2 -0
  82. package/dist/types/src/filter/filter-match.test.d.ts.map +1 -0
  83. package/dist/types/src/filter/index.d.ts +2 -0
  84. package/dist/types/src/filter/index.d.ts.map +1 -0
  85. package/dist/types/src/index.d.ts +1 -0
  86. package/dist/types/src/index.d.ts.map +1 -1
  87. package/dist/types/src/metadata/metadata-store.d.ts.map +1 -1
  88. package/dist/types/src/pipeline/message-selector.d.ts.map +1 -1
  89. package/dist/types/src/pipeline/pipeline.d.ts.map +1 -1
  90. package/dist/types/src/pipeline/timeframe-clock.d.ts.map +1 -1
  91. package/dist/types/src/query/errors.d.ts +23 -0
  92. package/dist/types/src/query/errors.d.ts.map +1 -0
  93. package/dist/types/src/query/index.d.ts +5 -0
  94. package/dist/types/src/query/index.d.ts.map +1 -0
  95. package/dist/types/src/query/plan.d.ts +132 -0
  96. package/dist/types/src/query/plan.d.ts.map +1 -0
  97. package/dist/types/src/query/query-executor.d.ts +83 -0
  98. package/dist/types/src/query/query-executor.d.ts.map +1 -0
  99. package/dist/types/src/query/query-planner.d.ts +33 -0
  100. package/dist/types/src/query/query-planner.d.ts.map +1 -0
  101. package/dist/types/src/query/query-planner.test.d.ts +2 -0
  102. package/dist/types/src/query/query-planner.test.d.ts.map +1 -0
  103. package/dist/types/src/space/admission-discovery-extension.d.ts.map +1 -1
  104. package/dist/types/src/space/control-pipeline.d.ts.map +1 -1
  105. package/dist/types/src/space/space-manager.d.ts.map +1 -1
  106. package/dist/types/src/space/space-protocol.d.ts.map +1 -1
  107. package/dist/types/src/space/space.d.ts.map +1 -1
  108. package/dist/types/src/testing/change-metadata.d.ts.map +1 -1
  109. package/dist/types/src/testing/index.d.ts +2 -0
  110. package/dist/types/src/testing/index.d.ts.map +1 -1
  111. package/dist/types/src/testing/test-agent-builder.d.ts.map +1 -1
  112. package/dist/types/src/testing/test-data.d.ts +18 -0
  113. package/dist/types/src/testing/test-data.d.ts.map +1 -0
  114. package/dist/types/src/testing/test-network-adapter.d.ts +3 -2
  115. package/dist/types/src/testing/test-network-adapter.d.ts.map +1 -1
  116. package/dist/types/src/testing/test-schema.d.ts +39 -0
  117. package/dist/types/src/testing/test-schema.d.ts.map +1 -0
  118. package/dist/types/src/util.d.ts +2 -2
  119. package/dist/types/src/util.d.ts.map +1 -1
  120. package/dist/types/tsconfig.tsbuildinfo +1 -1
  121. package/package.json +43 -34
  122. package/src/automerge/automerge-host.test.ts +7 -7
  123. package/src/automerge/automerge-host.ts +58 -60
  124. package/src/automerge/automerge-repo.test.ts +65 -65
  125. package/src/automerge/collection-synchronizer.test.ts +1 -1
  126. package/src/automerge/collection-synchronizer.ts +11 -10
  127. package/src/automerge/echo-data-monitor.ts +21 -20
  128. package/src/automerge/echo-network-adapter.test.ts +1 -1
  129. package/src/automerge/echo-network-adapter.ts +25 -18
  130. package/src/automerge/heads-store.ts +4 -3
  131. package/src/automerge/leveldb-storage-adapter.ts +1 -1
  132. package/src/automerge/mesh-echo-replicator-connection.ts +6 -5
  133. package/src/automerge/mesh-echo-replicator.ts +2 -2
  134. package/src/automerge/network-protocol.ts +2 -1
  135. package/src/automerge/space-collection.ts +2 -1
  136. package/src/db-host/automerge-metrics.ts +2 -1
  137. package/src/db-host/data-service.ts +4 -3
  138. package/src/db-host/database-root.ts +17 -22
  139. package/src/db-host/documents-iterator.ts +9 -8
  140. package/src/db-host/documents-synchronizer.test.ts +2 -2
  141. package/src/db-host/documents-synchronizer.ts +20 -18
  142. package/src/db-host/echo-host.ts +44 -15
  143. package/src/db-host/index.ts +0 -1
  144. package/src/db-host/query-service.ts +43 -37
  145. package/src/db-host/space-state-manager.ts +14 -4
  146. package/src/edge/echo-edge-replicator.test.ts +3 -3
  147. package/src/edge/echo-edge-replicator.ts +9 -8
  148. package/src/edge/inflight-request-limiter.ts +4 -4
  149. package/src/filter/filter-match.test.ts +101 -0
  150. package/src/filter/filter-match.ts +174 -0
  151. package/src/filter/index.ts +5 -0
  152. package/src/index.ts +1 -0
  153. package/src/metadata/metadata-store.ts +13 -13
  154. package/src/pipeline/pipeline-stress.test.ts +9 -9
  155. package/src/pipeline/pipeline.ts +13 -13
  156. package/src/pipeline/timeframe-clock.ts +5 -5
  157. package/src/query/errors.ts +7 -0
  158. package/src/query/index.ts +8 -0
  159. package/src/query/plan.ts +179 -0
  160. package/src/query/query-executor.ts +648 -0
  161. package/src/query/query-planner.test.ts +613 -0
  162. package/src/query/query-planner.ts +470 -0
  163. package/src/space/admission-discovery-extension.ts +2 -2
  164. package/src/space/control-pipeline.ts +8 -8
  165. package/src/space/space-manager.ts +5 -4
  166. package/src/space/space-protocol.browser.test.ts +1 -0
  167. package/src/space/space-protocol.test.ts +1 -0
  168. package/src/space/space-protocol.ts +4 -4
  169. package/src/space/space.ts +5 -5
  170. package/src/testing/index.ts +2 -0
  171. package/src/testing/test-agent-builder.ts +6 -6
  172. package/src/testing/test-data.ts +127 -0
  173. package/src/testing/test-network-adapter.ts +15 -12
  174. package/src/testing/test-replicator.ts +2 -2
  175. package/src/testing/test-schema.ts +53 -0
  176. package/src/util.ts +7 -3
  177. package/dist/lib/browser/chunk-32WDI3LB.mjs.map +0 -7
  178. package/dist/lib/node/chunk-TC2PRBEU.cjs.map +0 -7
  179. package/dist/lib/node-esm/chunk-UKOLB3LW.mjs.map +0 -7
  180. package/dist/types/src/db-host/query-state.d.ts +0 -41
  181. package/dist/types/src/db-host/query-state.d.ts.map +0 -1
  182. package/src/db-host/query-state.ts +0 -217
@@ -2,8 +2,9 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
+ import { NetworkAdapter, type Message, type PeerId, type PeerMetadata } from '@automerge/automerge-repo';
6
+
5
7
  import { synchronized, Trigger } from '@dxos/async';
6
- import { NetworkAdapter, type Message, type PeerId, type PeerMetadata } from '@dxos/automerge/automerge-repo';
7
8
  import { LifecycleState } from '@dxos/context';
8
9
  import { invariant } from '@dxos/invariant';
9
10
  import { type PublicKey } from '@dxos/keys';
@@ -53,11 +54,20 @@ export class EchoNetworkAdapter extends NetworkAdapter {
53
54
  private readonly _connections = new Map<PeerId, ConnectionEntry>();
54
55
  private _lifecycleState: LifecycleState = LifecycleState.CLOSED;
55
56
  private readonly _connected = new Trigger();
57
+ private readonly _ready = new Trigger();
56
58
 
57
59
  constructor(private readonly _params: EchoNetworkAdapterParams) {
58
60
  super();
59
61
  }
60
62
 
63
+ override isReady(): boolean {
64
+ return this._lifecycleState === LifecycleState.OPEN;
65
+ }
66
+
67
+ override whenReady(): Promise<void> {
68
+ return this._ready.wait();
69
+ }
70
+
61
71
  override connect(peerId: PeerId, peerMetadata?: PeerMetadata | undefined): void {
62
72
  this.peerId = peerId;
63
73
  this.peerMetadata = peerMetadata;
@@ -73,20 +83,16 @@ export class EchoNetworkAdapter extends NetworkAdapter {
73
83
  }
74
84
 
75
85
  @synchronized
76
- async open() {
86
+ async open(): Promise<void> {
77
87
  if (this._lifecycleState === LifecycleState.OPEN) {
78
88
  return;
79
89
  }
80
90
  this._lifecycleState = LifecycleState.OPEN;
81
-
82
- log('emit ready');
83
- this.emit('ready', {
84
- network: this,
85
- });
91
+ this._ready.wake();
86
92
  }
87
93
 
88
94
  @synchronized
89
- async close() {
95
+ async close(): Promise<this | undefined> {
90
96
  if (this._lifecycleState === LifecycleState.CLOSED) {
91
97
  return this;
92
98
  }
@@ -96,15 +102,16 @@ export class EchoNetworkAdapter extends NetworkAdapter {
96
102
  }
97
103
  this._replicators.clear();
98
104
 
105
+ this._ready.reset();
99
106
  this._lifecycleState = LifecycleState.CLOSED;
100
107
  }
101
108
 
102
- async whenConnected() {
109
+ async whenConnected(): Promise<void> {
103
110
  await this._connected.wait({ timeout: 10_000 });
104
111
  }
105
112
 
106
113
  @synchronized
107
- async addReplicator(replicator: EchoReplicator) {
114
+ async addReplicator(replicator: EchoReplicator): Promise<void> {
108
115
  invariant(this._lifecycleState === LifecycleState.OPEN);
109
116
  invariant(this.peerId);
110
117
  invariant(!this._replicators.has(replicator));
@@ -125,7 +132,7 @@ export class EchoNetworkAdapter extends NetworkAdapter {
125
132
  }
126
133
 
127
134
  @synchronized
128
- async removeReplicator(replicator: EchoReplicator) {
135
+ async removeReplicator(replicator: EchoReplicator): Promise<void> {
129
136
  invariant(this._lifecycleState === LifecycleState.OPEN);
130
137
  invariant(this._replicators.has(replicator));
131
138
  await replicator.disconnect();
@@ -171,7 +178,7 @@ export class EchoNetworkAdapter extends NetworkAdapter {
171
178
  this._send(message);
172
179
  }
173
180
 
174
- private _send(message: Message) {
181
+ private _send(message: Message): void {
175
182
  const connectionEntry = this._connections.get(message.targetId);
176
183
  if (!connectionEntry) {
177
184
  throw new Error('Connection not found.');
@@ -204,7 +211,7 @@ export class EchoNetworkAdapter extends NetworkAdapter {
204
211
  .filter(isNonNullable);
205
212
  }
206
213
 
207
- private _onConnectionOpen(connection: ReplicatorConnection) {
214
+ private _onConnectionOpen(connection: ReplicatorConnection): void {
208
215
  log('Connection opened', { peerId: connection.peerId });
209
216
  invariant(!this._connections.has(connection.peerId as PeerId));
210
217
  const reader = connection.readable.getReader();
@@ -235,7 +242,7 @@ export class EchoNetworkAdapter extends NetworkAdapter {
235
242
  this._params.monitor?.recordPeerConnected(connection.peerId);
236
243
  }
237
244
 
238
- private _onMessage(message: Message) {
245
+ private _onMessage(message: Message): void {
239
246
  if (isCollectionQueryMessage(message)) {
240
247
  this._params.onCollectionStateQueried(message.collectionId, message.senderId);
241
248
  } else if (isCollectionStateMessage(message)) {
@@ -246,7 +253,7 @@ export class EchoNetworkAdapter extends NetworkAdapter {
246
253
  this._params.monitor?.recordMessageReceived(message);
247
254
  }
248
255
 
249
- public onConnectionAuthScopeChanged(peer: PeerId) {
256
+ public onConnectionAuthScopeChanged(peer: PeerId): void {
250
257
  const entry = this._connections.get(peer);
251
258
  if (entry) {
252
259
  this._onConnectionAuthScopeChanged(entry.connection);
@@ -257,7 +264,7 @@ export class EchoNetworkAdapter extends NetworkAdapter {
257
264
  * Trigger doc-synchronizer shared documents set recalculation. Happens on peer-candidate.
258
265
  * TODO(y): replace with a proper API call when sharePolicy update becomes supported by automerge-repo
259
266
  */
260
- private _onConnectionAuthScopeChanged(connection: ReplicatorConnection) {
267
+ private _onConnectionAuthScopeChanged(connection: ReplicatorConnection): void {
261
268
  log('Connection auth scope changed', { peerId: connection.peerId });
262
269
  const entry = this._connections.get(connection.peerId as PeerId);
263
270
  invariant(entry);
@@ -265,7 +272,7 @@ export class EchoNetworkAdapter extends NetworkAdapter {
265
272
  this._emitPeerCandidate(connection);
266
273
  }
267
274
 
268
- private _onConnectionClosed(connection: ReplicatorConnection) {
275
+ private _onConnectionClosed(connection: ReplicatorConnection): void {
269
276
  log('Connection closed', { peerId: connection.peerId });
270
277
  const entry = this._connections.get(connection.peerId as PeerId);
271
278
  invariant(entry);
@@ -280,7 +287,7 @@ export class EchoNetworkAdapter extends NetworkAdapter {
280
287
  this._connections.delete(connection.peerId as PeerId);
281
288
  }
282
289
 
283
- private _emitPeerCandidate(connection: ReplicatorConnection) {
290
+ private _emitPeerCandidate(connection: ReplicatorConnection): void {
284
291
  this.emit('peer-candidate', {
285
292
  peerId: connection.peerId as PeerId,
286
293
  peerMetadata: createEchoPeerMetadata(),
@@ -2,8 +2,9 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import type { Heads } from '@dxos/automerge/automerge';
6
- import type { DocumentId } from '@dxos/automerge/automerge-repo';
5
+ import type { Heads } from '@automerge/automerge';
6
+ import type { DocumentId } from '@automerge/automerge-repo';
7
+
7
8
  import { headsEncoding } from '@dxos/indexing';
8
9
  import type { BatchLevel, SublevelDB } from '@dxos/kv-store';
9
10
 
@@ -18,7 +19,7 @@ export class HeadsStore {
18
19
  this._db = db;
19
20
  }
20
21
 
21
- setHeads(documentId: DocumentId, heads: Heads, batch: BatchLevel) {
22
+ setHeads(documentId: DocumentId, heads: Heads, batch: BatchLevel): void {
22
23
  batch.put<DocumentId, Heads>(documentId, heads, {
23
24
  sublevel: this._db,
24
25
  keyEncoding: 'utf8',
@@ -2,9 +2,9 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  // s
4
4
 
5
+ import { type StorageAdapterInterface, type Chunk, type StorageKey } from '@automerge/automerge-repo';
5
6
  import { type MixedEncoding } from 'level-transcoder';
6
7
 
7
- import { type StorageAdapterInterface, type Chunk, type StorageKey } from '@dxos/automerge/automerge-repo';
8
8
  import { LifecycleState, Resource } from '@dxos/context';
9
9
  import { type BatchLevel, type SublevelDB } from '@dxos/kv-store';
10
10
  import { type MaybePromise } from '@dxos/util';
@@ -2,8 +2,9 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import * as A from '@dxos/automerge/automerge';
6
- import { cbor } from '@dxos/automerge/automerge-repo';
5
+ import * as A from '@automerge/automerge';
6
+ import { cbor } from '@automerge/automerge-repo';
7
+
7
8
  import { Resource } from '@dxos/context';
8
9
  import { invariant } from '@dxos/invariant';
9
10
  import { type PublicKey } from '@dxos/keys';
@@ -95,7 +96,7 @@ export class MeshReplicatorConnection extends Resource implements ReplicatorConn
95
96
  ]);
96
97
  }
97
98
 
98
- private _disconnectIfEnabled() {
99
+ private _disconnectIfEnabled(): void {
99
100
  if (this._isEnabled) {
100
101
  this._params.onRemoteDisconnected();
101
102
  }
@@ -122,7 +123,7 @@ export class MeshReplicatorConnection extends Resource implements ReplicatorConn
122
123
  * Start exchanging messages with the remote peer.
123
124
  * Call after the remote peer has connected.
124
125
  */
125
- enable() {
126
+ enable(): void {
126
127
  invariant(this._remotePeerId != null, 'Remote peer has not connected yet.');
127
128
  this._isEnabled = true;
128
129
  }
@@ -130,7 +131,7 @@ export class MeshReplicatorConnection extends Resource implements ReplicatorConn
130
131
  /**
131
132
  * Stop exchanging messages with the remote peer.
132
133
  */
133
- disable() {
134
+ disable(): void {
134
135
  this._isEnabled = false;
135
136
  }
136
137
  }
@@ -46,7 +46,7 @@ export class MeshEchoReplicator implements EchoReplicator {
46
46
  this._context = context;
47
47
  }
48
48
 
49
- async disconnect() {
49
+ async disconnect(): Promise<void> {
50
50
  for (const connection of this._connections) {
51
51
  if (connection.isEnabled) {
52
52
  this._context?.onConnectionClosed(connection);
@@ -180,7 +180,7 @@ export class MeshEchoReplicator implements EchoReplicator {
180
180
  return connection.replicatorExtension;
181
181
  }
182
182
 
183
- async authorizeDevice(spaceKey: PublicKey, deviceKey: PublicKey) {
183
+ async authorizeDevice(spaceKey: PublicKey, deviceKey: PublicKey): Promise<void> {
184
184
  log('authorizeDevice', { spaceKey, deviceKey });
185
185
  const spaceId = await createIdFromSpaceKey(spaceKey);
186
186
  defaultMap(this._authorizedDevices, spaceId, () => new ComplexSet(PublicKey.hash)).add(deviceKey);
@@ -2,7 +2,8 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import type { Message } from '@dxos/automerge/automerge-repo';
5
+ import type { Message } from '@automerge/automerge-repo';
6
+
6
7
  import {
7
8
  type CollectionQueryMessage,
8
9
  type CollectionStateMessage,
@@ -2,7 +2,8 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { type DocumentId } from '@dxos/automerge/automerge-repo';
5
+ import { type DocumentId } from '@automerge/automerge-repo';
6
+
6
7
  import type { CollectionId } from '@dxos/echo-protocol';
7
8
  import { invariant } from '@dxos/invariant';
8
9
  import { SpaceId } from '@dxos/keys';
@@ -2,7 +2,8 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import * as A from '@dxos/automerge/automerge';
5
+ import * as A from '@automerge/automerge';
6
+
6
7
  import { log } from '@dxos/log';
7
8
 
8
9
  export type DocMetrics = {
@@ -2,8 +2,9 @@
2
2
  // Copyright 2021 DXOS.org
3
3
  //
4
4
 
5
+ import { type DocumentId } from '@automerge/automerge-repo';
6
+
5
7
  import { UpdateScheduler } from '@dxos/async';
6
- import { type DocumentId } from '@dxos/automerge/automerge-repo';
7
8
  import { type RequestOptions } from '@dxos/codec-protobuf';
8
9
  import { Stream } from '@dxos/codec-protobuf/stream';
9
10
  import { invariant } from '@dxos/invariant';
@@ -72,7 +73,7 @@ export class DataServiceImpl implements DataService {
72
73
  });
73
74
  }
74
75
 
75
- async updateSubscription(request: UpdateSubscriptionRequest) {
76
+ async updateSubscription(request: UpdateSubscriptionRequest): Promise<void> {
76
77
  const synchronizer = this._subscriptions.get(request.subscriptionId);
77
78
  invariant(synchronizer, 'Subscription not found');
78
79
 
@@ -122,7 +123,7 @@ export class DataServiceImpl implements DataService {
122
123
  await this._automergeHost.reIndexHeads((request.documentIds ?? []) as DocumentId[]);
123
124
  }
124
125
 
125
- async updateIndexes() {
126
+ async updateIndexes(): Promise<void> {
126
127
  await this._updateIndexes();
127
128
  }
128
129
 
@@ -2,21 +2,16 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import type * as A from '@dxos/automerge/automerge';
6
- import {
7
- interpretAsDocumentId,
8
- type AutomergeUrl,
9
- type DocHandle,
10
- type DocumentId,
11
- } from '@dxos/automerge/automerge-repo';
12
- import { type SpaceDoc, SpaceDocVersion } from '@dxos/echo-protocol';
5
+ import type * as A from '@automerge/automerge';
6
+ import { interpretAsDocumentId, type AutomergeUrl, type DocHandle, type DocumentId } from '@automerge/automerge-repo';
7
+
8
+ import { DatabaseDirectory, SpaceDocVersion } from '@dxos/echo-protocol';
13
9
  import { invariant } from '@dxos/invariant';
14
10
 
15
11
  import { measureDocMetrics, type DocMetrics } from './automerge-metrics';
16
- import { getSpaceKeyFromDoc } from '../automerge';
17
12
 
18
13
  export class DatabaseRoot {
19
- static mapLinks(doc: DocHandle<SpaceDoc>, mapping: Record<DocumentId, DocumentId>): void {
14
+ static mapLinks(doc: DocHandle<DatabaseDirectory>, mapping: Record<DocumentId, DocumentId>): void {
20
15
  doc.change((d) => {
21
16
  if (!d.links) {
22
17
  return;
@@ -30,7 +25,7 @@ export class DatabaseRoot {
30
25
  });
31
26
  }
32
27
 
33
- constructor(private readonly _rootHandle: DocHandle<SpaceDoc>) {}
28
+ constructor(private readonly _rootHandle: DocHandle<DatabaseDirectory>) {}
34
29
 
35
30
  get documentId(): DocumentId {
36
31
  return this._rootHandle.documentId;
@@ -41,19 +36,19 @@ export class DatabaseRoot {
41
36
  }
42
37
 
43
38
  get isLoaded(): boolean {
44
- return !!this._rootHandle.docSync();
39
+ return this._rootHandle.isReady();
45
40
  }
46
41
 
47
- get handle(): DocHandle<SpaceDoc> {
42
+ get handle(): DocHandle<DatabaseDirectory> {
48
43
  return this._rootHandle;
49
44
  }
50
45
 
51
- docSync(): A.Doc<SpaceDoc> | null {
52
- return this._rootHandle.docSync() ?? null;
46
+ doc(): A.Doc<DatabaseDirectory> | null {
47
+ return this._rootHandle.isReady() ? this._rootHandle.doc() : null;
53
48
  }
54
49
 
55
50
  getVersion(): SpaceDocVersion | null {
56
- const doc = this.docSync();
51
+ const doc = this.doc();
57
52
  if (!doc) {
58
53
  return null;
59
54
  }
@@ -62,16 +57,16 @@ export class DatabaseRoot {
62
57
  }
63
58
 
64
59
  getSpaceKey(): string | null {
65
- const doc = this.docSync();
60
+ const doc = this.doc();
66
61
  if (!doc) {
67
62
  return null;
68
63
  }
69
64
 
70
- return getSpaceKeyFromDoc(doc);
65
+ return DatabaseDirectory.getSpaceKey(doc);
71
66
  }
72
67
 
73
68
  getInlineObjectCount(): number | null {
74
- const doc = this.docSync();
69
+ const doc = this.doc();
75
70
  if (!doc) {
76
71
  return null;
77
72
  }
@@ -80,7 +75,7 @@ export class DatabaseRoot {
80
75
  }
81
76
 
82
77
  getLinkedObjectCount(): number | null {
83
- const doc = this.docSync();
78
+ const doc = this.doc();
84
79
  if (!doc) {
85
80
  return null;
86
81
  }
@@ -89,7 +84,7 @@ export class DatabaseRoot {
89
84
  }
90
85
 
91
86
  getAllLinkedDocuments(): AutomergeUrl[] {
92
- const doc = this.docSync();
87
+ const doc = this.doc();
93
88
  invariant(doc);
94
89
 
95
90
  // .toString() to handle RawString.
@@ -97,7 +92,7 @@ export class DatabaseRoot {
97
92
  }
98
93
 
99
94
  measureMetrics(): DocMetrics | null {
100
- const doc = this.docSync();
95
+ const doc = this.doc();
101
96
  if (!doc) {
102
97
  return null;
103
98
  }
@@ -2,16 +2,17 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import * as A from '@dxos/automerge/automerge';
6
- import { type DocumentId } from '@dxos/automerge/automerge-repo';
5
+ import * as A from '@automerge/automerge';
6
+ import { type DocumentId } from '@automerge/automerge-repo';
7
+
7
8
  import { Context } from '@dxos/context';
8
- import { SpaceDocVersion, type SpaceDoc } from '@dxos/echo-protocol';
9
- import { type ObjectSnapshot, type IdToHeads } from '@dxos/indexing';
9
+ import { DatabaseDirectory, SpaceDocVersion } from '@dxos/echo-protocol';
10
+ import { type IdToHeads, type ObjectSnapshot } from '@dxos/indexing';
10
11
  import { invariant } from '@dxos/invariant';
11
12
  import { log } from '@dxos/log';
12
13
  import { ObjectPointerVersion, objectPointerCodec } from '@dxos/protocols';
13
14
 
14
- import { type AutomergeHost, getSpaceKeyFromDoc } from '../automerge';
15
+ import { type AutomergeHost } from '../automerge';
15
16
 
16
17
  const LOG_VIEW_OPERATION_THRESHOLD = 300;
17
18
 
@@ -27,9 +28,9 @@ export const createSelectedDocumentsIterator = (automergeHost: AutomergeHost) =>
27
28
  for (const [id, heads] of objects.entries()) {
28
29
  try {
29
30
  const { documentId, objectId } = objectPointerCodec.decode(id);
30
- const handle = await automergeHost.loadDoc<SpaceDoc>(Context.default(), documentId as DocumentId);
31
+ const handle = await automergeHost.loadDoc<DatabaseDirectory>(Context.default(), documentId as DocumentId);
31
32
 
32
- let doc = handle.docSync();
33
+ let doc = handle.doc();
33
34
  invariant(doc);
34
35
 
35
36
  const currentHeads = A.getHeads(doc);
@@ -61,7 +62,7 @@ export const createSelectedDocumentsIterator = (automergeHost: AutomergeHost) =>
61
62
  // Upgrade V0 object pointers to V1.
62
63
  let newId = id;
63
64
  if (objectPointerCodec.getVersion(id) === ObjectPointerVersion.V0) {
64
- const spaceKey = getSpaceKeyFromDoc(doc) ?? undefined;
65
+ const spaceKey = DatabaseDirectory.getSpaceKey(doc) ?? undefined;
65
66
  newId = objectPointerCodec.encode({ documentId, objectId, spaceKey });
66
67
  }
67
68
 
@@ -2,11 +2,11 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
+ import { next as A } from '@automerge/automerge';
6
+ import { generateAutomergeUrl, parseAutomergeUrl, Repo } from '@automerge/automerge-repo';
5
7
  import { describe, expect, test } from 'vitest';
6
8
 
7
9
  import { sleep } from '@dxos/async';
8
- import { next as A } from '@dxos/automerge/automerge';
9
- import { generateAutomergeUrl, parseAutomergeUrl, Repo } from '@dxos/automerge/automerge-repo';
10
10
  import { openAndClose } from '@dxos/test-utils';
11
11
 
12
12
  import { DocumentsSynchronizer } from './documents-synchronizer';
@@ -2,11 +2,12 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
+ import { next as A, type Heads } from '@automerge/automerge';
6
+ import { type Repo, type DocHandle, type DocumentId } from '@automerge/automerge-repo';
7
+
5
8
  import { UpdateScheduler } from '@dxos/async';
6
- import { next as A, type Heads } from '@dxos/automerge/automerge';
7
- import { type Repo, type DocHandle, type DocumentId } from '@dxos/automerge/automerge-repo';
8
9
  import { Resource } from '@dxos/context';
9
- import { type SpaceDoc } from '@dxos/echo-protocol';
10
+ import { type DatabaseDirectory } from '@dxos/echo-protocol';
10
11
  import { invariant } from '@dxos/invariant';
11
12
  import { log } from '@dxos/log';
12
13
  import { type BatchedDocumentUpdates, type DocumentUpdate } from '@dxos/protocols/proto/dxos/echo/service';
@@ -19,7 +20,7 @@ export type DocumentsSynchronizerParams = {
19
20
  };
20
21
 
21
22
  interface DocSyncState {
22
- handle: DocHandle<SpaceDoc>;
23
+ handle: DocHandle<DatabaseDirectory>;
23
24
  lastSentHead?: Heads;
24
25
  clearSubscriptions?: () => void;
25
26
  }
@@ -44,17 +45,17 @@ export class DocumentsSynchronizer extends Resource {
44
45
  super();
45
46
  }
46
47
 
47
- addDocuments(documentIds: DocumentId[], retryCounter = 0) {
48
+ addDocuments(documentIds: DocumentId[], retryCounter = 0): void {
48
49
  if (retryCounter > 3) {
49
50
  log.warn('Failed to load document, retry limit reached', { documentIds });
50
51
  return;
51
52
  }
52
53
 
53
54
  for (const documentId of documentIds) {
54
- const doc = this._params.repo.find<SpaceDoc>(documentId as DocumentId);
55
- doc
56
- .whenReady()
57
- .then(() => {
55
+ this._params.repo
56
+ .find<DatabaseDirectory>(documentId as DocumentId)
57
+ .then(async (doc) => {
58
+ await doc.whenReady();
58
59
  this._startSync(doc);
59
60
  this._pendingUpdates.add(doc.documentId);
60
61
  this._sendUpdatesJob!.trigger();
@@ -66,7 +67,7 @@ export class DocumentsSynchronizer extends Resource {
66
67
  }
67
68
  }
68
69
 
69
- removeDocuments(documentIds: DocumentId[]) {
70
+ removeDocuments(documentIds: DocumentId[]): void {
70
71
  for (const documentId of documentIds) {
71
72
  this._syncStates.get(documentId)?.clearSubscriptions?.();
72
73
  this._syncStates.delete(documentId);
@@ -85,10 +86,10 @@ export class DocumentsSynchronizer extends Resource {
85
86
  this._syncStates.clear();
86
87
  }
87
88
 
88
- update(updates: DocumentUpdate[]) {
89
+ update(updates: DocumentUpdate[]): void {
89
90
  for (const { documentId, mutation, isNew } of updates) {
90
91
  if (isNew) {
91
- const doc = this._params.repo.find<SpaceDoc>(documentId as DocumentId);
92
+ const { handle: doc } = this._params.repo.findWithProgress<DatabaseDirectory>(documentId as DocumentId);
92
93
  doc.update((doc) => A.loadIncremental(doc, mutation));
93
94
  this._startSync(doc);
94
95
  } else {
@@ -97,7 +98,7 @@ export class DocumentsSynchronizer extends Resource {
97
98
  }
98
99
  }
99
100
 
100
- private _startSync(doc: DocHandle<SpaceDoc>) {
101
+ private _startSync(doc: DocHandle<DatabaseDirectory>): void {
101
102
  if (this._syncStates.has(doc.documentId)) {
102
103
  log.info('Document already being synced', { documentId: doc.documentId });
103
104
  return;
@@ -108,7 +109,7 @@ export class DocumentsSynchronizer extends Resource {
108
109
  this._syncStates.set(doc.documentId, syncState);
109
110
  }
110
111
 
111
- _subscribeForChanges(syncState: DocSyncState) {
112
+ _subscribeForChanges(syncState: DocSyncState): void {
112
113
  const handler = () => {
113
114
  this._pendingUpdates.add(syncState.handle.documentId);
114
115
  this._sendUpdatesJob!.trigger();
@@ -117,7 +118,7 @@ export class DocumentsSynchronizer extends Resource {
117
118
  syncState.clearSubscriptions = () => syncState.handle.off('heads-changed', handler);
118
119
  }
119
120
 
120
- private async _checkAndSendUpdates() {
121
+ private async _checkAndSendUpdates(): Promise<void> {
121
122
  const updates: DocumentUpdate[] = [];
122
123
 
123
124
  const docsWithPendingUpdates = Array.from(this._pendingUpdates);
@@ -141,10 +142,11 @@ export class DocumentsSynchronizer extends Resource {
141
142
  private _getPendingChanges(documentId: DocumentId): Uint8Array | void {
142
143
  const syncState = this._syncStates.get(documentId);
143
144
  invariant(syncState, 'Sync state for document not found');
144
- const doc = syncState.handle.docSync();
145
- if (!doc) {
145
+ const handle = syncState.handle;
146
+ if (!handle || !handle.isReady() || !handle.doc()) {
146
147
  return;
147
148
  }
149
+ const doc = handle.doc();
148
150
  const mutation = syncState.lastSentHead ? A.saveSince(doc, syncState.lastSentHead) : A.save(doc);
149
151
  if (mutation.length === 0) {
150
152
  return;
@@ -153,7 +155,7 @@ export class DocumentsSynchronizer extends Resource {
153
155
  return mutation;
154
156
  }
155
157
 
156
- private _writeMutation(documentId: DocumentId, mutation: Uint8Array) {
158
+ private _writeMutation(documentId: DocumentId, mutation: Uint8Array): void {
157
159
  const syncState = this._syncStates.get(documentId);
158
160
  invariant(syncState, 'Sync state for document not found');
159
161
  syncState.handle.update((doc) => {