@dxos/echo-pipeline 0.8.4-main.a4bbb77 → 0.8.4-main.ae835ea

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 (46) hide show
  1. package/dist/lib/browser/{chunk-XGG76KKU.mjs → chunk-FR6GJ4S4.mjs} +339 -425
  2. package/dist/lib/{node-esm/chunk-CHMJJ4DG.mjs.map → browser/chunk-FR6GJ4S4.mjs.map} +2 -2
  3. package/dist/lib/browser/{chunk-BVR7OOZK.mjs → chunk-WJJXJTNS.mjs} +7 -18
  4. package/dist/lib/browser/chunk-WJJXJTNS.mjs.map +7 -0
  5. package/dist/lib/browser/filter/index.mjs +1 -1
  6. package/dist/lib/browser/index.mjs +682 -750
  7. package/dist/lib/browser/index.mjs.map +3 -3
  8. package/dist/lib/browser/meta.json +1 -1
  9. package/dist/lib/browser/testing/index.mjs +65 -106
  10. package/dist/lib/browser/testing/index.mjs.map +3 -3
  11. package/dist/lib/node-esm/{chunk-CHMJJ4DG.mjs → chunk-JQCCVDLT.mjs} +339 -425
  12. package/dist/lib/{browser/chunk-XGG76KKU.mjs.map → node-esm/chunk-JQCCVDLT.mjs.map} +2 -2
  13. package/dist/lib/node-esm/{chunk-L3ZEKVDR.mjs → chunk-LEQ77KAT.mjs} +7 -18
  14. package/dist/lib/node-esm/chunk-LEQ77KAT.mjs.map +7 -0
  15. package/dist/lib/node-esm/filter/index.mjs +1 -1
  16. package/dist/lib/node-esm/index.mjs +682 -750
  17. package/dist/lib/node-esm/index.mjs.map +3 -3
  18. package/dist/lib/node-esm/meta.json +1 -1
  19. package/dist/lib/node-esm/testing/index.mjs +65 -106
  20. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  21. package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
  22. package/dist/types/src/automerge/collection-synchronizer.d.ts +2 -1
  23. package/dist/types/src/automerge/collection-synchronizer.d.ts.map +1 -1
  24. package/dist/types/src/db-host/query-service.d.ts.map +1 -1
  25. package/dist/types/src/edge/echo-edge-replicator.d.ts.map +1 -1
  26. package/dist/types/src/filter/filter-match.d.ts +2 -2
  27. package/dist/types/src/filter/filter-match.d.ts.map +1 -1
  28. package/dist/types/src/query/query-executor.d.ts +9 -0
  29. package/dist/types/src/query/query-executor.d.ts.map +1 -1
  30. package/dist/types/src/testing/test-data.d.ts.map +1 -1
  31. package/dist/types/src/testing/test-schema.d.ts +1 -1
  32. package/dist/types/src/testing/test-schema.d.ts.map +1 -1
  33. package/dist/types/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +35 -36
  35. package/src/automerge/automerge-host.ts +8 -5
  36. package/src/automerge/collection-synchronizer.test.ts +4 -3
  37. package/src/automerge/collection-synchronizer.ts +14 -9
  38. package/src/db-host/query-service.ts +2 -1
  39. package/src/edge/echo-edge-replicator.ts +30 -9
  40. package/src/filter/filter-match.test.ts +1 -1
  41. package/src/filter/filter-match.ts +6 -19
  42. package/src/query/query-executor.ts +116 -36
  43. package/src/testing/test-data.ts +1 -1
  44. package/src/testing/test-schema.ts +1 -1
  45. package/dist/lib/browser/chunk-BVR7OOZK.mjs.map +0 -7
  46. package/dist/lib/node-esm/chunk-L3ZEKVDR.mjs.map +0 -7
@@ -3,7 +3,7 @@ import {
3
3
  filterMatchObject,
4
4
  filterMatchObjectJSON,
5
5
  filterMatchValue
6
- } from "./chunk-BVR7OOZK.mjs";
6
+ } from "./chunk-WJJXJTNS.mjs";
7
7
  import {
8
8
  AuthExtension,
9
9
  AuthStatus,
@@ -26,7 +26,7 @@ import {
26
26
  mapTimeframeToFeedIndexes,
27
27
  startAfter,
28
28
  valueEncoding
29
- } from "./chunk-XGG76KKU.mjs";
29
+ } from "./chunk-FR6GJ4S4.mjs";
30
30
  import "./chunk-CGS2ULMK.mjs";
31
31
 
32
32
  // src/db-host/data-service.ts
@@ -50,25 +50,14 @@ import { trace as trace2 } from "@dxos/tracing";
50
50
  import { ComplexSet, bufferToArray, isNonNullable as isNonNullable2, range } from "@dxos/util";
51
51
 
52
52
  // src/automerge/collection-synchronizer.ts
53
- import { next as am } from "@automerge/automerge";
53
+ import { next as A } from "@automerge/automerge";
54
+ import * as Array2 from "effect/Array";
55
+ import * as Record from "effect/Record";
54
56
  import { Event, asyncReturn, scheduleTask, scheduleTaskInterval } from "@dxos/async";
55
57
  import { Resource } from "@dxos/context";
56
58
  import { log } from "@dxos/log";
57
59
  import { trace } from "@dxos/tracing";
58
60
  import { defaultMap } from "@dxos/util";
59
- function _define_property(obj, key, value) {
60
- if (key in obj) {
61
- Object.defineProperty(obj, key, {
62
- value,
63
- enumerable: true,
64
- configurable: true,
65
- writable: true
66
- });
67
- } else {
68
- obj[key] = value;
69
- }
70
- return obj;
71
- }
72
61
  function _ts_decorate(decorators, target, key, desc) {
73
62
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
74
63
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -79,6 +68,22 @@ var __dxlog_file = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/automerg
79
68
  var MIN_QUERY_INTERVAL = 5e3;
80
69
  var POLL_INTERVAL = 3e4;
81
70
  var CollectionSynchronizer = class extends Resource {
71
+ _sendCollectionState;
72
+ _queryCollectionState;
73
+ _shouldSyncCollection;
74
+ /**
75
+ * CollectionId -> State.
76
+ */
77
+ _perCollectionStates = /* @__PURE__ */ new Map();
78
+ _activeCollections = /* @__PURE__ */ new Set();
79
+ _connectedPeers = /* @__PURE__ */ new Set();
80
+ remoteStateUpdated = new Event();
81
+ constructor(params) {
82
+ super();
83
+ this._sendCollectionState = params.sendCollectionState;
84
+ this._queryCollectionState = params.queryCollectionState;
85
+ this._shouldSyncCollection = params.shouldSyncCollection;
86
+ }
82
87
  async _open(ctx) {
83
88
  scheduleTaskInterval(this._ctx, async () => {
84
89
  for (const collectionId of this._perCollectionStates.keys()) {
@@ -104,7 +109,7 @@ var CollectionSynchronizer = class extends Resource {
104
109
  state
105
110
  }, {
106
111
  F: __dxlog_file,
107
- L: 76,
112
+ L: 78,
108
113
  S: this,
109
114
  C: (f, a) => f(...a)
110
115
  });
@@ -123,7 +128,7 @@ var CollectionSynchronizer = class extends Resource {
123
128
  collectionId
124
129
  }, {
125
130
  F: __dxlog_file,
126
- L: 90,
131
+ L: 92,
127
132
  S: this,
128
133
  C: (f, a) => f(...a)
129
134
  });
@@ -206,7 +211,7 @@ var CollectionSynchronizer = class extends Resource {
206
211
  state
207
212
  }, {
208
213
  F: __dxlog_file,
209
- L: 171,
214
+ L: 173,
210
215
  S: this,
211
216
  C: (f, a) => f(...a)
212
217
  });
@@ -257,33 +262,28 @@ var CollectionSynchronizer = class extends Resource {
257
262
  }
258
263
  }
259
264
  }
260
- constructor(params) {
261
- super(), _define_property(this, "_sendCollectionState", void 0), _define_property(this, "_queryCollectionState", void 0), _define_property(this, "_shouldSyncCollection", void 0), /**
262
- * CollectionId -> State.
263
- */
264
- _define_property(this, "_perCollectionStates", /* @__PURE__ */ new Map()), _define_property(this, "_activeCollections", /* @__PURE__ */ new Set()), _define_property(this, "_connectedPeers", /* @__PURE__ */ new Set()), _define_property(this, "remoteStateUpdated", new Event());
265
- this._sendCollectionState = params.sendCollectionState;
266
- this._queryCollectionState = params.queryCollectionState;
267
- this._shouldSyncCollection = params.shouldSyncCollection;
268
- }
269
265
  };
270
266
  CollectionSynchronizer = _ts_decorate([
271
267
  trace.resource()
272
268
  ], CollectionSynchronizer);
273
269
  var diffCollectionState = (local, remote) => {
274
- const allDocuments = /* @__PURE__ */ new Set([
275
- ...Object.keys(local.documents),
276
- ...Object.keys(remote.documents)
277
- ]);
270
+ const localDocuments = Record.filter(local.documents, (heads) => heads.length > 0);
271
+ const remoteDocuments = Record.filter(remote.documents, (heads) => heads.length > 0);
272
+ const allDocuments = [
273
+ .../* @__PURE__ */ new Set([
274
+ ...Record.keys(localDocuments),
275
+ ...Record.keys(remoteDocuments)
276
+ ])
277
+ ];
278
278
  const missingOnRemote = [];
279
279
  const missingOnLocal = [];
280
280
  const different = [];
281
281
  for (const documentId of allDocuments) {
282
- if (!local.documents[documentId] || local.documents[documentId].length === 0) {
282
+ if (!localDocuments[documentId]) {
283
283
  missingOnLocal.push(documentId);
284
- } else if (!remote.documents[documentId] || remote.documents[documentId].length === 0) {
284
+ } else if (!remoteDocuments[documentId]) {
285
285
  missingOnRemote.push(documentId);
286
- } else if (!am.equals(local.documents[documentId], remote.documents[documentId])) {
286
+ } else if (!A.equals(local.documents[documentId], remote.documents[documentId])) {
287
287
  different.push(documentId);
288
288
  }
289
289
  }
@@ -298,7 +298,7 @@ var validateCollectionState = (state) => {
298
298
  if (!isValidDocumentId(documentId)) {
299
299
  throw new Error(`Invalid documentId: ${documentId}`);
300
300
  }
301
- if (Array.isArray(heads) && heads.some((head) => typeof head !== "string")) {
301
+ if (Array2.isArray(heads) && heads.some((head) => typeof head !== "string")) {
302
302
  throw new Error(`Invalid heads: ${heads}`);
303
303
  }
304
304
  });
@@ -324,19 +324,6 @@ var isCollectionQueryMessage = (message) => message.type === MESSAGE_TYPE_COLLEC
324
324
  var isCollectionStateMessage = (message) => message.type === MESSAGE_TYPE_COLLECTION_STATE;
325
325
 
326
326
  // src/automerge/echo-network-adapter.ts
327
- function _define_property2(obj, key, value) {
328
- if (key in obj) {
329
- Object.defineProperty(obj, key, {
330
- value,
331
- enumerable: true,
332
- configurable: true,
333
- writable: true
334
- });
335
- } else {
336
- obj[key] = value;
337
- }
338
- return obj;
339
- }
340
327
  function _ts_decorate2(decorators, target, key, desc) {
341
328
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
342
329
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -345,6 +332,18 @@ function _ts_decorate2(decorators, target, key, desc) {
345
332
  }
346
333
  var __dxlog_file2 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/echo-network-adapter.ts";
347
334
  var EchoNetworkAdapter = class extends NetworkAdapter {
335
+ _params;
336
+ _replicators = /* @__PURE__ */ new Set();
337
+ /**
338
+ * Remote peer id -> connection.
339
+ */
340
+ _connections = /* @__PURE__ */ new Map();
341
+ _lifecycleState = LifecycleState.CLOSED;
342
+ _connected = new Trigger();
343
+ _ready = new Trigger();
344
+ constructor(_params) {
345
+ super(), this._params = _params;
346
+ }
348
347
  isReady() {
349
348
  return this._lifecycleState === LifecycleState.OPEN;
350
349
  }
@@ -674,12 +673,6 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
674
673
  peerMetadata: createEchoPeerMetadata()
675
674
  });
676
675
  }
677
- constructor(_params) {
678
- super(), _define_property2(this, "_params", void 0), _define_property2(this, "_replicators", void 0), /**
679
- * Remote peer id -> connection.
680
- */
681
- _define_property2(this, "_connections", void 0), _define_property2(this, "_lifecycleState", void 0), _define_property2(this, "_connected", void 0), _define_property2(this, "_ready", void 0), this._params = _params, this._replicators = /* @__PURE__ */ new Set(), this._connections = /* @__PURE__ */ new Map(), this._lifecycleState = LifecycleState.CLOSED, this._connected = new Trigger(), this._ready = new Trigger();
682
- }
683
676
  };
684
677
  _ts_decorate2([
685
678
  synchronized
@@ -701,20 +694,11 @@ var isEchoPeerMetadata = (metadata) => metadata?.dxos_peerSource === "EchoNetwor
701
694
 
702
695
  // src/automerge/heads-store.ts
703
696
  import { headsEncoding } from "@dxos/indexing";
704
- function _define_property3(obj, key, value) {
705
- if (key in obj) {
706
- Object.defineProperty(obj, key, {
707
- value,
708
- enumerable: true,
709
- configurable: true,
710
- writable: true
711
- });
712
- } else {
713
- obj[key] = value;
714
- }
715
- return obj;
716
- }
717
697
  var HeadsStore = class {
698
+ _db;
699
+ constructor({ db }) {
700
+ this._db = db;
701
+ }
718
702
  setHeads(documentId, heads, batch) {
719
703
  batch.put(documentId, heads, {
720
704
  sublevel: this._db,
@@ -729,28 +713,15 @@ var HeadsStore = class {
729
713
  valueEncoding: headsEncoding
730
714
  });
731
715
  }
732
- constructor({ db }) {
733
- _define_property3(this, "_db", void 0);
734
- this._db = db;
735
- }
736
716
  };
737
717
 
738
718
  // src/automerge/leveldb-storage-adapter.ts
739
719
  import { Resource as Resource2 } from "@dxos/context";
740
- function _define_property4(obj, key, value) {
741
- if (key in obj) {
742
- Object.defineProperty(obj, key, {
743
- value,
744
- enumerable: true,
745
- configurable: true,
746
- writable: true
747
- });
748
- } else {
749
- obj[key] = value;
750
- }
751
- return obj;
752
- }
753
720
  var LevelDBStorageAdapter = class extends Resource2 {
721
+ _params;
722
+ constructor(_params) {
723
+ super(), this._params = _params;
724
+ }
754
725
  async load(keyArray) {
755
726
  try {
756
727
  if (!this.isOpen) {
@@ -838,9 +809,6 @@ var LevelDBStorageAdapter = class extends Resource2 {
838
809
  }
839
810
  await batch.write();
840
811
  }
841
- constructor(_params) {
842
- super(), _define_property4(this, "_params", void 0), this._params = _params;
843
- }
844
812
  };
845
813
  var keyEncoder = {
846
814
  encode: (key) => Buffer.from(key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-")),
@@ -854,19 +822,6 @@ var encodingOptions = {
854
822
  var isLevelDbNotFoundError = (err) => err.code === "LEVEL_NOT_FOUND";
855
823
 
856
824
  // src/automerge/automerge-host.ts
857
- function _define_property5(obj, key, value) {
858
- if (key in obj) {
859
- Object.defineProperty(obj, key, {
860
- value,
861
- enumerable: true,
862
- configurable: true,
863
- writable: true
864
- });
865
- } else {
866
- obj[key] = value;
867
- }
868
- return obj;
869
- }
870
825
  function _ts_decorate3(decorators, target, key, desc) {
871
826
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
872
827
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -884,6 +839,57 @@ var BUNDLE_SIZE = 100;
884
839
  var BUNDLE_SYNC_CONCURRENCY = 2;
885
840
  var BUNDLE_SYNC_THRESHOLD = 50;
886
841
  var AutomergeHost = class extends Resource3 {
842
+ _db;
843
+ _indexMetadataStore;
844
+ _echoNetworkAdapter;
845
+ _collectionSynchronizer = new CollectionSynchronizer({
846
+ queryCollectionState: this._queryCollectionState.bind(this),
847
+ sendCollectionState: this._sendCollectionState.bind(this),
848
+ shouldSyncCollection: this._shouldSyncCollection.bind(this)
849
+ });
850
+ _repo;
851
+ _storage;
852
+ _headsStore;
853
+ _syncTask = void 0;
854
+ /**
855
+ * Cache of collections that would be synced on next sync task run.
856
+ */
857
+ _collectionsToSync = new ComplexSet(({ collectionId, peerId }) => `${collectionId}|${peerId}`);
858
+ _peerId;
859
+ _peerIdProvider;
860
+ _getSpaceKeyByRootDocumentId;
861
+ collectionStateUpdated = new Event2();
862
+ /**
863
+ * Fired after a batch of documents was saved to disk.
864
+ */
865
+ documentsSaved = new Event2();
866
+ _headsUpdates = /* @__PURE__ */ new Map();
867
+ _onHeadsChangedTask;
868
+ constructor({ db, indexMetadataStore, dataMonitor, peerIdProvider, getSpaceKeyByRootDocumentId }) {
869
+ super();
870
+ this._db = db;
871
+ this._storage = new LevelDBStorageAdapter({
872
+ db: db.sublevel("automerge"),
873
+ callbacks: {
874
+ beforeSave: async (params) => this._beforeSave(params),
875
+ afterSave: async (key) => this._afterSave(key)
876
+ },
877
+ monitor: dataMonitor
878
+ });
879
+ this._echoNetworkAdapter = new EchoNetworkAdapter({
880
+ getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this),
881
+ isDocumentInRemoteCollection: this._isDocumentInRemoteCollection.bind(this),
882
+ onCollectionStateQueried: this._onCollectionStateQueried.bind(this),
883
+ onCollectionStateReceived: this._onCollectionStateReceived.bind(this),
884
+ monitor: dataMonitor
885
+ });
886
+ this._headsStore = new HeadsStore({
887
+ db: db.sublevel("heads")
888
+ });
889
+ this._indexMetadataStore = indexMetadataStore;
890
+ this._peerIdProvider = peerIdProvider;
891
+ this._getSpaceKeyByRootDocumentId = getSpaceKeyByRootDocumentId;
892
+ }
887
893
  async _open() {
888
894
  this._peerId = `host-${this._peerIdProvider?.() ?? PublicKey.random().toHex()}`;
889
895
  this._onHeadsChangedTask = new DeferredTask(this._ctx, async () => {
@@ -1144,9 +1150,6 @@ var AutomergeHost = class extends Resource3 {
1144
1150
  // NOTE: If both peers return sharePolicy=false the replication will not happen
1145
1151
  // https://github.com/automerge/automerge-repo/pull/292
1146
1152
  async _sharePolicy(peerId, documentId) {
1147
- if (peerId.startsWith("client-")) {
1148
- return false;
1149
- }
1150
1153
  if (!documentId) {
1151
1154
  return false;
1152
1155
  }
@@ -1212,7 +1215,7 @@ var AutomergeHost = class extends Resource3 {
1212
1215
  this._headsUpdates.set(documentId, heads);
1213
1216
  invariant2(this._onHeadsChangedTask, "onHeadsChangedTask is not initialized", {
1214
1217
  F: __dxlog_file3,
1215
- L: 449,
1218
+ L: 445,
1216
1219
  S: this,
1217
1220
  A: [
1218
1221
  "this._onHeadsChangedTask",
@@ -1261,6 +1264,7 @@ var AutomergeHost = class extends Resource3 {
1261
1264
  return handle && handle.isReady();
1262
1265
  });
1263
1266
  await this._repo.flush(loadedDocuments);
1267
+ await this._onHeadsChangedTask?.runBlocking();
1264
1268
  }
1265
1269
  async getHeads(documentIds) {
1266
1270
  const result = [];
@@ -1582,9 +1586,12 @@ var AutomergeHost = class extends Resource3 {
1582
1586
  const collectionsChanged = /* @__PURE__ */ new Set();
1583
1587
  for (const collectionId of this._collectionSynchronizer.getRegisteredCollectionIds()) {
1584
1588
  const state = this._collectionSynchronizer.getLocalCollectionState(collectionId);
1589
+ if (!state) {
1590
+ continue;
1591
+ }
1585
1592
  let newState;
1586
1593
  for (const [documentId, heads] of docHeads) {
1587
- if (state?.documents[documentId]) {
1594
+ if (documentId in state.documents) {
1588
1595
  if (!newState) {
1589
1596
  newState = structuredClone(state);
1590
1597
  }
@@ -1602,41 +1609,6 @@ var AutomergeHost = class extends Resource3 {
1602
1609
  });
1603
1610
  }
1604
1611
  }
1605
- constructor({ db, indexMetadataStore, dataMonitor, peerIdProvider, getSpaceKeyByRootDocumentId }) {
1606
- super(), _define_property5(this, "_db", void 0), _define_property5(this, "_indexMetadataStore", void 0), _define_property5(this, "_echoNetworkAdapter", void 0), _define_property5(this, "_collectionSynchronizer", new CollectionSynchronizer({
1607
- queryCollectionState: this._queryCollectionState.bind(this),
1608
- sendCollectionState: this._sendCollectionState.bind(this),
1609
- shouldSyncCollection: this._shouldSyncCollection.bind(this)
1610
- })), _define_property5(this, "_repo", void 0), _define_property5(this, "_storage", void 0), _define_property5(this, "_headsStore", void 0), _define_property5(this, "_syncTask", void 0), /**
1611
- * Cache of collections that would be synced on next sync task run.
1612
- */
1613
- _define_property5(this, "_collectionsToSync", new ComplexSet(({ collectionId, peerId }) => `${collectionId}|${peerId}`)), _define_property5(this, "_peerId", void 0), _define_property5(this, "_peerIdProvider", void 0), _define_property5(this, "_getSpaceKeyByRootDocumentId", void 0), _define_property5(this, "collectionStateUpdated", new Event2()), /**
1614
- * Fired after a batch of documents was saved to disk.
1615
- */
1616
- _define_property5(this, "documentsSaved", new Event2()), _define_property5(this, "_headsUpdates", /* @__PURE__ */ new Map()), _define_property5(this, "_onHeadsChangedTask", void 0);
1617
- this._db = db;
1618
- this._storage = new LevelDBStorageAdapter({
1619
- db: db.sublevel("automerge"),
1620
- callbacks: {
1621
- beforeSave: async (params) => this._beforeSave(params),
1622
- afterSave: async (key) => this._afterSave(key)
1623
- },
1624
- monitor: dataMonitor
1625
- });
1626
- this._echoNetworkAdapter = new EchoNetworkAdapter({
1627
- getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this),
1628
- isDocumentInRemoteCollection: this._isDocumentInRemoteCollection.bind(this),
1629
- onCollectionStateQueried: this._onCollectionStateQueried.bind(this),
1630
- onCollectionStateReceived: this._onCollectionStateReceived.bind(this),
1631
- monitor: dataMonitor
1632
- });
1633
- this._headsStore = new HeadsStore({
1634
- db: db.sublevel("heads")
1635
- });
1636
- this._indexMetadataStore = indexMetadataStore;
1637
- this._peerIdProvider = peerIdProvider;
1638
- this._getSpaceKeyByRootDocumentId = getSpaceKeyByRootDocumentId;
1639
- }
1640
1612
  };
1641
1613
  _ts_decorate3([
1642
1614
  trace2.info()
@@ -1672,7 +1644,7 @@ var changeIsPresentInDoc = (doc, changeHash) => {
1672
1644
  var decodeCollectionState = (state) => {
1673
1645
  invariant2(typeof state === "object" && state !== null, "Invalid state", {
1674
1646
  F: __dxlog_file3,
1675
- L: 842,
1647
+ L: 845,
1676
1648
  S: void 0,
1677
1649
  A: [
1678
1650
  "typeof state === 'object' && state !== null",
@@ -1692,81 +1664,24 @@ import { log as log5 } from "@dxos/log";
1692
1664
  import { ComplexSet as ComplexSet2, defaultMap as defaultMap2 } from "@dxos/util";
1693
1665
 
1694
1666
  // src/automerge/mesh-echo-replicator-connection.ts
1695
- import * as A from "@automerge/automerge";
1667
+ import * as A2 from "@automerge/automerge";
1696
1668
  import { cbor } from "@automerge/automerge-repo";
1697
1669
  import { Resource as Resource4 } from "@dxos/context";
1698
1670
  import { invariant as invariant3 } from "@dxos/invariant";
1699
1671
  import { log as log4 } from "@dxos/log";
1700
1672
  import { AutomergeReplicator } from "@dxos/teleport-extension-automerge-replicator";
1701
- function _define_property6(obj, key, value) {
1702
- if (key in obj) {
1703
- Object.defineProperty(obj, key, {
1704
- value,
1705
- enumerable: true,
1706
- configurable: true,
1707
- writable: true
1708
- });
1709
- } else {
1710
- obj[key] = value;
1711
- }
1712
- return obj;
1713
- }
1714
1673
  var __dxlog_file4 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator-connection.ts";
1715
1674
  var DEFAULT_FACTORY = (params) => new AutomergeReplicator(...params);
1716
1675
  var MeshReplicatorConnection = class extends Resource4 {
1717
- _disconnectIfEnabled() {
1718
- if (this._isEnabled) {
1719
- this._params.onRemoteDisconnected();
1720
- }
1721
- }
1722
- get peerId() {
1723
- invariant3(this._remotePeerId != null, "Remote peer has not connected yet.", {
1724
- F: __dxlog_file4,
1725
- L: 106,
1726
- S: this,
1727
- A: [
1728
- "this._remotePeerId != null",
1729
- "'Remote peer has not connected yet.'"
1730
- ]
1731
- });
1732
- return this._remotePeerId;
1733
- }
1734
- get isEnabled() {
1735
- return this._isEnabled;
1736
- }
1737
- get bundleSyncEnabled() {
1738
- return false;
1739
- }
1740
- async shouldAdvertise(params) {
1741
- return this._params.shouldAdvertise(params);
1742
- }
1743
- shouldSyncCollection(params) {
1744
- return this._params.shouldSyncCollection(params);
1745
- }
1746
- /**
1747
- * Start exchanging messages with the remote peer.
1748
- * Call after the remote peer has connected.
1749
- */
1750
- enable() {
1751
- invariant3(this._remotePeerId != null, "Remote peer has not connected yet.", {
1752
- F: __dxlog_file4,
1753
- L: 131,
1754
- S: this,
1755
- A: [
1756
- "this._remotePeerId != null",
1757
- "'Remote peer has not connected yet.'"
1758
- ]
1759
- });
1760
- this._isEnabled = true;
1761
- }
1762
- /**
1763
- * Stop exchanging messages with the remote peer.
1764
- */
1765
- disable() {
1766
- this._isEnabled = false;
1767
- }
1676
+ _params;
1677
+ readable;
1678
+ writable;
1679
+ remoteDeviceKey = null;
1680
+ replicatorExtension;
1681
+ _remotePeerId = null;
1682
+ _isEnabled = false;
1768
1683
  constructor(_params) {
1769
- super(), _define_property6(this, "_params", void 0), _define_property6(this, "readable", void 0), _define_property6(this, "writable", void 0), _define_property6(this, "remoteDeviceKey", void 0), _define_property6(this, "replicatorExtension", void 0), _define_property6(this, "_remotePeerId", void 0), _define_property6(this, "_isEnabled", void 0), this._params = _params, this.remoteDeviceKey = null, this._remotePeerId = null, this._isEnabled = false;
1684
+ super(), this._params = _params;
1770
1685
  let readableStreamController;
1771
1686
  this.readable = new ReadableStream({
1772
1687
  start: (controller) => {
@@ -1830,10 +1745,61 @@ var MeshReplicatorConnection = class extends Resource4 {
1830
1745
  }
1831
1746
  ]);
1832
1747
  }
1748
+ _disconnectIfEnabled() {
1749
+ if (this._isEnabled) {
1750
+ this._params.onRemoteDisconnected();
1751
+ }
1752
+ }
1753
+ get peerId() {
1754
+ invariant3(this._remotePeerId != null, "Remote peer has not connected yet.", {
1755
+ F: __dxlog_file4,
1756
+ L: 106,
1757
+ S: this,
1758
+ A: [
1759
+ "this._remotePeerId != null",
1760
+ "'Remote peer has not connected yet.'"
1761
+ ]
1762
+ });
1763
+ return this._remotePeerId;
1764
+ }
1765
+ get isEnabled() {
1766
+ return this._isEnabled;
1767
+ }
1768
+ get bundleSyncEnabled() {
1769
+ return false;
1770
+ }
1771
+ async shouldAdvertise(params) {
1772
+ return this._params.shouldAdvertise(params);
1773
+ }
1774
+ shouldSyncCollection(params) {
1775
+ return this._params.shouldSyncCollection(params);
1776
+ }
1777
+ /**
1778
+ * Start exchanging messages with the remote peer.
1779
+ * Call after the remote peer has connected.
1780
+ */
1781
+ enable() {
1782
+ invariant3(this._remotePeerId != null, "Remote peer has not connected yet.", {
1783
+ F: __dxlog_file4,
1784
+ L: 131,
1785
+ S: this,
1786
+ A: [
1787
+ "this._remotePeerId != null",
1788
+ "'Remote peer has not connected yet.'"
1789
+ ]
1790
+ });
1791
+ this._isEnabled = true;
1792
+ }
1793
+ /**
1794
+ * Stop exchanging messages with the remote peer.
1795
+ */
1796
+ disable() {
1797
+ this._isEnabled = false;
1798
+ }
1833
1799
  };
1834
1800
  var logSendSync = (message) => {
1835
1801
  log4("sendSyncMessage", () => {
1836
- const decodedSyncMessage = message.type === "sync" && message.data ? A.decodeSyncMessage(message.data) : void 0;
1802
+ const decodedSyncMessage = message.type === "sync" && message.data ? A2.decodeSyncMessage(message.data) : void 0;
1837
1803
  return {
1838
1804
  sync: decodedSyncMessage && {
1839
1805
  headsLength: decodedSyncMessage.heads.length,
@@ -1872,21 +1838,24 @@ var getSpaceIdFromCollectionId = (collectionId) => {
1872
1838
  };
1873
1839
 
1874
1840
  // src/automerge/mesh-echo-replicator.ts
1875
- function _define_property7(obj, key, value) {
1876
- if (key in obj) {
1877
- Object.defineProperty(obj, key, {
1878
- value,
1879
- enumerable: true,
1880
- configurable: true,
1881
- writable: true
1882
- });
1883
- } else {
1884
- obj[key] = value;
1885
- }
1886
- return obj;
1887
- }
1888
1841
  var __dxlog_file6 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts";
1889
1842
  var MeshEchoReplicator = class {
1843
+ /**
1844
+ * We might have multiple connections open with a peer (one per space), but there'll be only one enabled
1845
+ * connection at any given moment, because there's a single repo for all the spaces.
1846
+ * When a connection closes (space was closed) it gets removed from the list and the next connection
1847
+ * in the line gets enabled.
1848
+ */
1849
+ _connectionsPerPeer = /* @__PURE__ */ new Map();
1850
+ /**
1851
+ * A set of all connections (enabled and disabled).
1852
+ */
1853
+ _connections = /* @__PURE__ */ new Set();
1854
+ /**
1855
+ * spaceId -> deviceKey[]
1856
+ */
1857
+ _authorizedDevices = /* @__PURE__ */ new Map();
1858
+ _context = null;
1890
1859
  async connect(context) {
1891
1860
  this._context = context;
1892
1861
  }
@@ -2099,30 +2068,11 @@ var MeshEchoReplicator = class {
2099
2068
  }
2100
2069
  }
2101
2070
  }
2102
- constructor() {
2103
- _define_property7(this, "_connectionsPerPeer", /* @__PURE__ */ new Map());
2104
- _define_property7(this, "_connections", /* @__PURE__ */ new Set());
2105
- _define_property7(this, "_authorizedDevices", /* @__PURE__ */ new Map());
2106
- _define_property7(this, "_context", null);
2107
- }
2108
2071
  };
2109
2072
 
2110
2073
  // src/automerge/echo-data-monitor.ts
2111
2074
  import { trace as trace3 } from "@dxos/tracing";
2112
2075
  import { CircularBuffer, SlidingWindowSummary, mapValues } from "@dxos/util";
2113
- function _define_property8(obj, key, value) {
2114
- if (key in obj) {
2115
- Object.defineProperty(obj, key, {
2116
- value,
2117
- enumerable: true,
2118
- configurable: true,
2119
- writable: true
2120
- });
2121
- } else {
2122
- obj[key] = value;
2123
- }
2124
- return obj;
2125
- }
2126
2076
  function _ts_decorate4(decorators, target, key, desc) {
2127
2077
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2128
2078
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -2132,6 +2082,22 @@ function _ts_decorate4(decorators, target, key, desc) {
2132
2082
  var PER_SECOND_RATE_AVG_WINDOW_SIZE = 5;
2133
2083
  var DEFAULT_AVG_WINDOW_SIZE = 25;
2134
2084
  var EchoDataMonitor = class {
2085
+ _params;
2086
+ _lastTick = 0;
2087
+ _activeCounters = createLocalCounters();
2088
+ _lastCompleteCounters;
2089
+ _localTimeSeries = createLocalTimeSeries();
2090
+ _storageAverages = createStorageAverages();
2091
+ _replicationAverages = createNetworkAverages();
2092
+ _sizeByMessage = {};
2093
+ _lastReceivedMessages = new CircularBuffer(100);
2094
+ _lastSentMessages = new CircularBuffer(100);
2095
+ _connectionsCount = 0;
2096
+ constructor(_params = {
2097
+ timeSeriesLength: 30
2098
+ }) {
2099
+ this._params = _params;
2100
+ }
2135
2101
  tick(timeMs) {
2136
2102
  this._advanceTimeWindow(timeMs - this._lastTick);
2137
2103
  this._lastTick = timeMs;
@@ -2371,9 +2337,8 @@ var EchoDataMonitor = class {
2371
2337
  messageCounts.failed++;
2372
2338
  }
2373
2339
  _getStatsForType(message) {
2374
- var _this__sizeByMessage, _message_type, _this__activeCounters_byType, _message_type1;
2375
- const messageSize = (_this__sizeByMessage = this._sizeByMessage)[_message_type = message.type] ?? (_this__sizeByMessage[_message_type] = createSlidingWindow());
2376
- const messageCounts = (_this__activeCounters_byType = this._activeCounters.byType)[_message_type1 = message.type] ?? (_this__activeCounters_byType[_message_type1] = createMessageCounter());
2340
+ const messageSize = this._sizeByMessage[message.type] ??= createSlidingWindow();
2341
+ const messageCounts = this._activeCounters.byType[message.type] ??= createMessageCounter();
2377
2342
  return {
2378
2343
  messageCounts,
2379
2344
  messageSize
@@ -2382,48 +2347,21 @@ var EchoDataMonitor = class {
2382
2347
  _computeMessageHistogram(groupKey) {
2383
2348
  const result = {};
2384
2349
  for (const receivedMessage of this._lastReceivedMessages) {
2385
- var _result, _receivedMessage_groupKey;
2386
- const counters = (_result = result)[_receivedMessage_groupKey = receivedMessage[groupKey]] ?? (_result[_receivedMessage_groupKey] = {
2350
+ const counters = result[receivedMessage[groupKey]] ??= {
2387
2351
  received: 0,
2388
2352
  sent: 0
2389
- });
2353
+ };
2390
2354
  counters.received++;
2391
2355
  }
2392
2356
  for (const receivedMessage of this._lastSentMessages) {
2393
- var _result1, _receivedMessage_groupKey1;
2394
- const counters = (_result1 = result)[_receivedMessage_groupKey1 = receivedMessage[groupKey]] ?? (_result1[_receivedMessage_groupKey1] = {
2357
+ const counters = result[receivedMessage[groupKey]] ??= {
2395
2358
  received: 0,
2396
2359
  sent: 0
2397
- });
2360
+ };
2398
2361
  counters.sent++;
2399
2362
  }
2400
2363
  return result;
2401
2364
  }
2402
- constructor(_params = {
2403
- timeSeriesLength: 30
2404
- }) {
2405
- _define_property8(this, "_params", void 0);
2406
- _define_property8(this, "_lastTick", void 0);
2407
- _define_property8(this, "_activeCounters", void 0);
2408
- _define_property8(this, "_lastCompleteCounters", void 0);
2409
- _define_property8(this, "_localTimeSeries", void 0);
2410
- _define_property8(this, "_storageAverages", void 0);
2411
- _define_property8(this, "_replicationAverages", void 0);
2412
- _define_property8(this, "_sizeByMessage", void 0);
2413
- _define_property8(this, "_lastReceivedMessages", void 0);
2414
- _define_property8(this, "_lastSentMessages", void 0);
2415
- _define_property8(this, "_connectionsCount", void 0);
2416
- this._params = _params;
2417
- this._lastTick = 0;
2418
- this._activeCounters = createLocalCounters();
2419
- this._localTimeSeries = createLocalTimeSeries();
2420
- this._storageAverages = createStorageAverages();
2421
- this._replicationAverages = createNetworkAverages();
2422
- this._sizeByMessage = {};
2423
- this._lastReceivedMessages = new CircularBuffer(100);
2424
- this._lastSentMessages = new CircularBuffer(100);
2425
- this._connectionsCount = 0;
2426
- }
2427
2365
  };
2428
2366
  EchoDataMonitor = _ts_decorate4([
2429
2367
  trace3.resource()
@@ -2496,29 +2434,30 @@ var getByteCount = (message) => {
2496
2434
  };
2497
2435
 
2498
2436
  // src/db-host/documents-synchronizer.ts
2499
- import { next as A2 } from "@automerge/automerge";
2437
+ import { next as A3 } from "@automerge/automerge";
2500
2438
  import { UpdateScheduler, sleep } from "@dxos/async";
2501
2439
  import { LifecycleState as LifecycleState2, Resource as Resource5, cancelWithContext as cancelWithContext2 } from "@dxos/context";
2502
2440
  import { invariant as invariant6 } from "@dxos/invariant";
2503
2441
  import { log as log6 } from "@dxos/log";
2504
- function _define_property9(obj, key, value) {
2505
- if (key in obj) {
2506
- Object.defineProperty(obj, key, {
2507
- value,
2508
- enumerable: true,
2509
- configurable: true,
2510
- writable: true
2511
- });
2512
- } else {
2513
- obj[key] = value;
2514
- }
2515
- return obj;
2516
- }
2517
2442
  var __dxlog_file7 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/documents-synchronizer.ts";
2518
2443
  var MAX_UPDATE_FREQ = 10;
2519
2444
  var WRAP_AROUND_RETRY_LIMIT = 3;
2520
2445
  var WRAP_AROUND_RETRY_INITIAL_DELAY = 100;
2521
2446
  var DocumentsSynchronizer = class extends Resource5 {
2447
+ _params;
2448
+ _syncStates = /* @__PURE__ */ new Map();
2449
+ /**
2450
+ * Documents that have pending updates.
2451
+ * Used to batch updates.
2452
+ */
2453
+ _pendingUpdates = /* @__PURE__ */ new Set();
2454
+ /**
2455
+ * Job that schedules if there are pending updates.
2456
+ */
2457
+ _sendUpdatesJob = void 0;
2458
+ constructor(_params) {
2459
+ super(), this._params = _params;
2460
+ }
2522
2461
  addDocuments(documentIds, retryCounter = 0, wrapAroundRetryDelay = WRAP_AROUND_RETRY_INITIAL_DELAY) {
2523
2462
  if (retryCounter > WRAP_AROUND_RETRY_LIMIT) {
2524
2463
  log6.warn("Failed to load document, retry limit reached", {
@@ -2637,11 +2576,11 @@ var DocumentsSynchronizer = class extends Resource5 {
2637
2576
  return;
2638
2577
  }
2639
2578
  const doc = handle.doc();
2640
- const mutation = syncState.lastSentHead ? A2.saveSince(doc, syncState.lastSentHead) : A2.save(doc);
2579
+ const mutation = syncState.lastSentHead ? A3.saveSince(doc, syncState.lastSentHead) : A3.save(doc);
2641
2580
  if (mutation.length === 0) {
2642
2581
  return;
2643
2582
  }
2644
- syncState.lastSentHead = A2.getHeads(doc);
2583
+ syncState.lastSentHead = A3.getHeads(doc);
2645
2584
  return mutation;
2646
2585
  }
2647
2586
  _writeMutation(documentId, mutation, isNew) {
@@ -2653,7 +2592,7 @@ var DocumentsSynchronizer = class extends Resource5 {
2653
2592
  docId: documentId
2654
2593
  });
2655
2594
  const syncState = this._startSync(newHandle);
2656
- syncState.lastSentHead = A2.getHeads(newHandle.doc());
2595
+ syncState.lastSentHead = A3.getHeads(newHandle.doc());
2657
2596
  } else {
2658
2597
  const syncState = this._syncStates.get(documentId);
2659
2598
  invariant6(syncState, "Sync state for document not found", {
@@ -2665,43 +2604,33 @@ var DocumentsSynchronizer = class extends Resource5 {
2665
2604
  "'Sync state for document not found'"
2666
2605
  ]
2667
2606
  });
2668
- const headsBefore = A2.getHeads(syncState.handle.doc());
2607
+ const headsBefore = A3.getHeads(syncState.handle.doc());
2669
2608
  this._params.repo.import(mutation, {
2670
2609
  docId: documentId
2671
2610
  });
2672
- if (A2.equals(headsBefore, syncState.lastSentHead)) {
2673
- syncState.lastSentHead = A2.getHeads(syncState.handle.doc());
2611
+ if (A3.equals(headsBefore, syncState.lastSentHead)) {
2612
+ syncState.lastSentHead = A3.getHeads(syncState.handle.doc());
2674
2613
  }
2675
2614
  }
2676
2615
  }
2677
- constructor(_params) {
2678
- super(), _define_property9(this, "_params", void 0), _define_property9(this, "_syncStates", void 0), /**
2679
- * Documents that have pending updates.
2680
- * Used to batch updates.
2681
- */
2682
- _define_property9(this, "_pendingUpdates", void 0), /**
2683
- * Job that schedules if there are pending updates.
2684
- */
2685
- _define_property9(this, "_sendUpdatesJob", void 0), this._params = _params, this._syncStates = /* @__PURE__ */ new Map(), this._pendingUpdates = /* @__PURE__ */ new Set(), this._sendUpdatesJob = void 0;
2686
- }
2687
2616
  };
2688
2617
 
2689
2618
  // src/db-host/data-service.ts
2690
- function _define_property10(obj, key, value) {
2691
- if (key in obj) {
2692
- Object.defineProperty(obj, key, {
2693
- value,
2694
- enumerable: true,
2695
- configurable: true,
2696
- writable: true
2697
- });
2698
- } else {
2699
- obj[key] = value;
2700
- }
2701
- return obj;
2702
- }
2703
2619
  var __dxlog_file8 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/data-service.ts";
2704
2620
  var DataServiceImpl = class {
2621
+ /**
2622
+ * Map of subscriptions.
2623
+ * subscriptionId -> DocumentsSynchronizer
2624
+ */
2625
+ _subscriptions = /* @__PURE__ */ new Map();
2626
+ _automergeHost;
2627
+ _spaceStateManager;
2628
+ _updateIndexes;
2629
+ constructor(params) {
2630
+ this._automergeHost = params.automergeHost;
2631
+ this._spaceStateManager = params.spaceStateManager;
2632
+ this._updateIndexes = params.updateIndexes;
2633
+ }
2705
2634
  subscribe(request) {
2706
2635
  return new Stream(({ next, ready }) => {
2707
2636
  const synchronizer = new DocumentsSynchronizer({
@@ -2822,15 +2751,6 @@ var DataServiceImpl = class {
2822
2751
  scheduler.trigger();
2823
2752
  });
2824
2753
  }
2825
- constructor(params) {
2826
- _define_property10(this, "_subscriptions", /* @__PURE__ */ new Map());
2827
- _define_property10(this, "_automergeHost", void 0);
2828
- _define_property10(this, "_spaceStateManager", void 0);
2829
- _define_property10(this, "_updateIndexes", void 0);
2830
- this._automergeHost = params.automergeHost;
2831
- this._spaceStateManager = params.spaceStateManager;
2832
- this._updateIndexes = params.updateIndexes;
2833
- }
2834
2754
  };
2835
2755
 
2836
2756
  // src/db-host/echo-host.ts
@@ -2843,7 +2763,7 @@ import { IndexKind } from "@dxos/protocols/proto/dxos/echo/indexing";
2843
2763
  import { trace as trace5 } from "@dxos/tracing";
2844
2764
 
2845
2765
  // src/db-host/documents-iterator.ts
2846
- import * as A3 from "@automerge/automerge";
2766
+ import * as A4 from "@automerge/automerge";
2847
2767
  import { Context as Context2 } from "@dxos/context";
2848
2768
  import { DatabaseDirectory as DatabaseDirectory2, SpaceDocVersion } from "@dxos/echo-protocol";
2849
2769
  import { invariant as invariant8 } from "@dxos/invariant";
@@ -2874,10 +2794,10 @@ var createSelectedDocumentsIterator = (automergeHost) => (
2874
2794
  ""
2875
2795
  ]
2876
2796
  });
2877
- const currentHeads = A3.getHeads(doc);
2878
- if (!A3.equals(currentHeads, heads)) {
2797
+ const currentHeads = A4.getHeads(doc);
2798
+ if (!A4.equals(currentHeads, heads)) {
2879
2799
  const begin = Date.now();
2880
- doc = A3.view(doc, heads);
2800
+ doc = A4.view(doc, heads);
2881
2801
  const end = Date.now();
2882
2802
  if (end - begin > LOG_VIEW_OPERATION_THRESHOLD) {
2883
2803
  log8("Checking out document version is taking too long", {
@@ -2932,7 +2852,7 @@ var createSelectedDocumentsIterator = (automergeHost) => (
2932
2852
 
2933
2853
  // src/db-host/query-service.ts
2934
2854
  import { getHeads as getHeads3 } from "@automerge/automerge";
2935
- import { Schema } from "effect";
2855
+ import * as Schema from "effect/Schema";
2936
2856
  import { DeferredTask as DeferredTask2, scheduleMicroTask, synchronized as synchronized2 } from "@dxos/async";
2937
2857
  import { Stream as Stream2 } from "@dxos/codec-protobuf/stream";
2938
2858
  import { Context as Context4, Resource as Resource7 } from "@dxos/context";
@@ -2943,7 +2863,8 @@ import { objectPointerCodec as objectPointerCodec4 } from "@dxos/protocols";
2943
2863
  import { trace as trace4 } from "@dxos/tracing";
2944
2864
 
2945
2865
  // src/query/query-executor.ts
2946
- import { Match, Predicate } from "effect";
2866
+ import * as Match from "effect/Match";
2867
+ import * as Predicate from "effect/Predicate";
2947
2868
  import { Context as Context3, ContextDisposedError, LifecycleState as LifecycleState3, Resource as Resource6 } from "@dxos/context";
2948
2869
  import { DatabaseDirectory as DatabaseDirectory3, ObjectStructure, isEncodedReference } from "@dxos/echo-protocol";
2949
2870
  import { EscapedPropPath } from "@dxos/indexing";
@@ -2986,24 +2907,18 @@ var InvalidQueryError = class extends QueryError.extend("INVALID_QUERY") {
2986
2907
  var QueryPlan;
2987
2908
 
2988
2909
  // src/query/query-planner.ts
2989
- function _define_property11(obj, key, value) {
2990
- if (key in obj) {
2991
- Object.defineProperty(obj, key, {
2992
- value,
2993
- enumerable: true,
2994
- configurable: true,
2995
- writable: true
2996
- });
2997
- } else {
2998
- obj[key] = value;
2999
- }
3000
- return obj;
3001
- }
3002
2910
  var __dxlog_file10 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/query/query-planner.ts";
3003
2911
  var DEFAULT_OPTIONS = {
3004
2912
  defaultTextSearchKind: "full-text"
3005
2913
  };
3006
2914
  var QueryPlanner = class {
2915
+ _options;
2916
+ constructor(options) {
2917
+ this._options = {
2918
+ ...DEFAULT_OPTIONS,
2919
+ ...options
2920
+ };
2921
+ }
3007
2922
  createPlan(query) {
3008
2923
  let plan = this._generate(query, {
3009
2924
  ...DEFAULT_CONTEXT,
@@ -3062,11 +2977,11 @@ var QueryPlanner = class {
3062
2977
  }
3063
2978
  // TODO(dmaretskyi): This can be rewritten as a function of (filter[]) -> (selection ? undefined, rest: filter[]) that recurses onto itself.
3064
2979
  // TODO(dmaretskyi): If the tip of the query ast is a [select, ...filter] shape we can reorder the filters so the query is most efficient.
3065
- _generateSelectionFromFilter(filter, context) {
3066
- switch (filter.type) {
2980
+ _generateSelectionFromFilter(filter2, context) {
2981
+ switch (filter2.type) {
3067
2982
  // Props
3068
2983
  case "object": {
3069
- if (context.selectionInverted && filter.id === void 0 && filter.typename === null && Object.keys(filter.props).length === 0) {
2984
+ if (context.selectionInverted && filter2.id === void 0 && filter2.typename === null && Object.keys(filter2.props).length === 0) {
3070
2985
  return QueryPlan.Plan.make([
3071
2986
  {
3072
2987
  _tag: "ClearWorkingSetStep"
@@ -3082,26 +2997,26 @@ var QueryPlanner = class {
3082
2997
  }
3083
2998
  });
3084
2999
  }
3085
- if (filter.id && filter.id?.length > 0) {
3000
+ if (filter2.id && filter2.id?.length > 0) {
3086
3001
  return QueryPlan.Plan.make([
3087
3002
  {
3088
3003
  _tag: "SelectStep",
3089
3004
  spaces: context.selectionSpaces,
3090
3005
  selector: {
3091
3006
  _tag: "IdSelector",
3092
- objectIds: filter.id
3007
+ objectIds: filter2.id
3093
3008
  }
3094
3009
  },
3095
3010
  ...this._generateDeletedHandlingSteps(context),
3096
3011
  {
3097
3012
  _tag: "FilterStep",
3098
3013
  filter: {
3099
- ...filter,
3014
+ ...filter2,
3100
3015
  id: void 0
3101
3016
  }
3102
3017
  }
3103
3018
  ]);
3104
- } else if (filter.typename) {
3019
+ } else if (filter2.typename) {
3105
3020
  return QueryPlan.Plan.make([
3106
3021
  {
3107
3022
  _tag: "SelectStep",
@@ -3109,7 +3024,7 @@ var QueryPlanner = class {
3109
3024
  selector: {
3110
3025
  _tag: "TypeSelector",
3111
3026
  typename: [
3112
- filter.typename
3027
+ filter2.typename
3113
3028
  ],
3114
3029
  inverted: false
3115
3030
  }
@@ -3118,7 +3033,7 @@ var QueryPlanner = class {
3118
3033
  {
3119
3034
  _tag: "FilterStep",
3120
3035
  filter: {
3121
- ...filter,
3036
+ ...filter2,
3122
3037
  typename: null
3123
3038
  }
3124
3039
  }
@@ -3136,7 +3051,7 @@ var QueryPlanner = class {
3136
3051
  {
3137
3052
  _tag: "FilterStep",
3138
3053
  filter: {
3139
- ...filter
3054
+ ...filter2
3140
3055
  }
3141
3056
  }
3142
3057
  ]);
@@ -3156,7 +3071,7 @@ var QueryPlanner = class {
3156
3071
  {
3157
3072
  _tag: "FilterStep",
3158
3073
  filter: {
3159
- ...filter
3074
+ ...filter2
3160
3075
  }
3161
3076
  }
3162
3077
  ]);
@@ -3169,8 +3084,8 @@ var QueryPlanner = class {
3169
3084
  spaces: context.selectionSpaces,
3170
3085
  selector: {
3171
3086
  _tag: "TextSelector",
3172
- text: filter.text,
3173
- searchKind: filter.searchKind ?? this._options.defaultTextSearchKind
3087
+ text: filter2.text,
3088
+ searchKind: filter2.searchKind ?? this._options.defaultTextSearchKind
3174
3089
  }
3175
3090
  },
3176
3091
  ...this._generateDeletedHandlingSteps(context)
@@ -3200,7 +3115,7 @@ var QueryPlanner = class {
3200
3115
  });
3201
3116
  // Boolean
3202
3117
  case "not":
3203
- return this._generateSelectionFromFilter(filter.filter, {
3118
+ return this._generateSelectionFromFilter(filter2.filter, {
3204
3119
  ...context,
3205
3120
  selectionInverted: !context.selectionInverted
3206
3121
  });
@@ -3212,9 +3127,9 @@ var QueryPlanner = class {
3212
3127
  }
3213
3128
  });
3214
3129
  case "or":
3215
- if (filter.filters.every(isTrivialTypenameFilter)) {
3216
- const typenames = filter.filters.map((filter2) => {
3217
- invariant9(filter2.type === "object" && filter2.typename !== null, void 0, {
3130
+ if (filter2.filters.every(isTrivialTypenameFilter)) {
3131
+ const typenames = filter2.filters.map((filter3) => {
3132
+ invariant9(filter3.type === "object" && filter3.typename !== null, void 0, {
3218
3133
  F: __dxlog_file10,
3219
3134
  L: 224,
3220
3135
  S: this,
@@ -3223,7 +3138,7 @@ var QueryPlanner = class {
3223
3138
  ""
3224
3139
  ]
3225
3140
  });
3226
- return filter2.typename;
3141
+ return filter3.typename;
3227
3142
  });
3228
3143
  return QueryPlan.Plan.make([
3229
3144
  {
@@ -3247,7 +3162,7 @@ var QueryPlanner = class {
3247
3162
  }
3248
3163
  default:
3249
3164
  throw new QueryError({
3250
- message: `Unsupported filter type: ${filter.type}`,
3165
+ message: `Unsupported filter type: ${filter2.type}`,
3251
3166
  context: {
3252
3167
  query: context.originalQuery
3253
3168
  }
@@ -3486,13 +3401,6 @@ var QueryPlanner = class {
3486
3401
  }
3487
3402
  ]);
3488
3403
  }
3489
- constructor(options) {
3490
- _define_property11(this, "_options", void 0);
3491
- this._options = {
3492
- ...DEFAULT_OPTIONS,
3493
- ...options
3494
- };
3495
- }
3496
3404
  };
3497
3405
  var DEFAULT_CONTEXT = {
3498
3406
  originalQuery: null,
@@ -3513,26 +3421,12 @@ var createRelationTraversalStep = (direction) => ({
3513
3421
  direction
3514
3422
  }
3515
3423
  });
3516
- var isTrivialTypenameFilter = (filter) => {
3517
- return filter.type === "object" && filter.typename !== null && Object.keys(filter.props).length === 0 && (filter.id === void 0 || filter.id.length === 0) && (filter.foreignKeys === void 0 || filter.foreignKeys.length === 0);
3424
+ var isTrivialTypenameFilter = (filter2) => {
3425
+ return filter2.type === "object" && filter2.typename !== null && Object.keys(filter2.props).length === 0 && (filter2.id === void 0 || filter2.id.length === 0) && (filter2.foreignKeys === void 0 || filter2.foreignKeys.length === 0);
3518
3426
  };
3519
3427
 
3520
3428
  // src/query/query-executor.ts
3521
- function _define_property12(obj, key, value) {
3522
- if (key in obj) {
3523
- Object.defineProperty(obj, key, {
3524
- value,
3525
- enumerable: true,
3526
- configurable: true,
3527
- writable: true
3528
- });
3529
- } else {
3530
- obj[key] = value;
3531
- }
3532
- return obj;
3533
- }
3534
3429
  var __dxlog_file11 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/query/query-executor.ts";
3535
- var isNullable = Predicate.isNullable;
3536
3430
  var ExecutionTrace = Object.freeze({
3537
3431
  makeEmpty: () => ({
3538
3432
  name: "Empty",
@@ -3540,11 +3434,57 @@ var ExecutionTrace = Object.freeze({
3540
3434
  objectCount: 0,
3541
3435
  documentsLoaded: 0,
3542
3436
  indexHits: 0,
3437
+ beginTs: 0,
3438
+ endTs: 0,
3543
3439
  indexQueryTime: 0,
3544
3440
  documentLoadTime: 0,
3545
3441
  executionTime: 0,
3546
3442
  children: []
3547
3443
  }),
3444
+ markEnd: (trace6) => {
3445
+ trace6.endTs = performance.now();
3446
+ trace6.executionTime = trace6.endTs - trace6.beginTs;
3447
+ },
3448
+ putOnPerformanceTimeline: (trace6) => {
3449
+ performance.measure(trace6.name, {
3450
+ start: trace6.beginTs,
3451
+ end: trace6.endTs,
3452
+ detail: {
3453
+ devtools: {
3454
+ dataType: "track-entry",
3455
+ track: "Query Execution",
3456
+ trackGroup: "ECHO",
3457
+ color: "tertiary-dark",
3458
+ properties: [
3459
+ [
3460
+ "objectCount",
3461
+ trace6.objectCount
3462
+ ],
3463
+ [
3464
+ "documentsLoaded",
3465
+ trace6.documentsLoaded
3466
+ ],
3467
+ [
3468
+ "index hits",
3469
+ trace6.indexHits
3470
+ ],
3471
+ [
3472
+ "indexQueryTime",
3473
+ trace6.indexQueryTime
3474
+ ],
3475
+ [
3476
+ "documentLoadTime",
3477
+ trace6.documentLoadTime
3478
+ ]
3479
+ ],
3480
+ tooltipText: trace6.details
3481
+ }
3482
+ }
3483
+ });
3484
+ for (const child of trace6.children) {
3485
+ ExecutionTrace.putOnPerformanceTimeline(child);
3486
+ }
3487
+ },
3548
3488
  format: (trace6) => {
3549
3489
  const go = (trace7, indent) => {
3550
3490
  return [
@@ -3559,6 +3499,30 @@ var ExecutionTrace = Object.freeze({
3559
3499
  });
3560
3500
  var TRACE_QUERY_EXECUTION = false;
3561
3501
  var QueryExecutor = class extends Resource6 {
3502
+ _indexer;
3503
+ _automergeHost;
3504
+ _spaceStateManager;
3505
+ /**
3506
+ * Id of this query.
3507
+ */
3508
+ _id;
3509
+ _query;
3510
+ // TODO(dmaretskyi): Might be used in the future.
3511
+ _reactivity;
3512
+ _plan;
3513
+ _trace = ExecutionTrace.makeEmpty();
3514
+ _lastResultSet = [];
3515
+ constructor(options) {
3516
+ super();
3517
+ this._indexer = options.indexer;
3518
+ this._automergeHost = options.automergeHost;
3519
+ this._spaceStateManager = options.spaceStateManager;
3520
+ this._id = options.queryId;
3521
+ this._query = options.query;
3522
+ this._reactivity = options.reactivity;
3523
+ const queryPlanner = new QueryPlanner();
3524
+ this._plan = queryPlanner.createPlan(this._query);
3525
+ }
3562
3526
  get query() {
3563
3527
  return this._query;
3564
3528
  }
@@ -3584,7 +3548,7 @@ var QueryExecutor = class extends Resource6 {
3584
3548
  async execQuery() {
3585
3549
  invariant10(this._lifecycleState === LifecycleState3.OPEN, void 0, {
3586
3550
  F: __dxlog_file11,
3587
- L: 176,
3551
+ L: 211,
3588
3552
  S: this,
3589
3553
  A: [
3590
3554
  "this._lifecycleState === LifecycleState.OPEN",
@@ -3619,7 +3583,7 @@ var QueryExecutor = class extends Resource6 {
3619
3583
  trace6.children.push(result.trace);
3620
3584
  }
3621
3585
  trace6.objectCount = workingSet.length;
3622
- trace6.executionTime = performance.now() - begin;
3586
+ ExecutionTrace.markEnd(trace6);
3623
3587
  return {
3624
3588
  workingSet,
3625
3589
  trace: trace6
@@ -3663,7 +3627,8 @@ var QueryExecutor = class extends Resource6 {
3663
3627
  default:
3664
3628
  throw new Error(`Unknown step type: ${step._tag}`);
3665
3629
  }
3666
- trace6.executionTime = performance.now() - begin;
3630
+ trace6.beginTs = begin;
3631
+ ExecutionTrace.markEnd(trace6);
3667
3632
  return {
3668
3633
  workingSet: newWorkingSet,
3669
3634
  trace: trace6
@@ -3676,7 +3641,8 @@ var QueryExecutor = class extends Resource6 {
3676
3641
  const trace6 = {
3677
3642
  ...ExecutionTrace.makeEmpty(),
3678
3643
  name: "Select",
3679
- details: JSON.stringify(step.selector)
3644
+ details: JSON.stringify(step.selector),
3645
+ beginTs: performance.now()
3680
3646
  };
3681
3647
  switch (step.selector._tag) {
3682
3648
  case "WildcardSelector": {
@@ -3824,7 +3790,7 @@ var QueryExecutor = class extends Resource6 {
3824
3790
  ref: ref2["/"]
3825
3791
  }, {
3826
3792
  F: __dxlog_file11,
3827
- L: 437,
3793
+ L: 477,
3828
3794
  S: this,
3829
3795
  C: (f, a) => f(...a)
3830
3796
  });
@@ -3882,7 +3848,7 @@ var QueryExecutor = class extends Resource6 {
3882
3848
  ref: ref["/"]
3883
3849
  }, {
3884
3850
  F: __dxlog_file11,
3885
- L: 500,
3851
+ L: 540,
3886
3852
  S: this,
3887
3853
  C: (f, a) => f(...a)
3888
3854
  });
@@ -3972,15 +3938,9 @@ var QueryExecutor = class extends Resource6 {
3972
3938
  };
3973
3939
  }
3974
3940
  async _execOrderStep(step, workingSet) {
3975
- const compareItems = (a, b) => step.order.reduce((comparison, order) => {
3976
- if (comparison !== 0) {
3977
- return comparison;
3978
- }
3979
- return this._compareByOrder(a, b, order);
3980
- }, 0);
3981
3941
  const sortedWorkingSet = [
3982
3942
  ...workingSet
3983
- ].sort(compareItems);
3943
+ ].sort((a, b) => this._compareMultiOrder(a, b, step.order));
3984
3944
  return {
3985
3945
  workingSet: sortedWorkingSet,
3986
3946
  trace: {
@@ -3991,64 +3951,69 @@ var QueryExecutor = class extends Resource6 {
3991
3951
  }
3992
3952
  };
3993
3953
  }
3954
+ _compareMultiOrder(a, b, orders) {
3955
+ if (orders.length === 0) {
3956
+ return 0;
3957
+ } else if (orders.length === 1) {
3958
+ return this._compareByOrder(a, b, orders[0]);
3959
+ }
3960
+ for (const order of orders) {
3961
+ const comparison = this._compareByOrder(a, b, order);
3962
+ if (comparison !== 0) {
3963
+ return comparison;
3964
+ }
3965
+ }
3966
+ return 0;
3967
+ }
3994
3968
  _compareByOrder(a, b, order) {
3995
- return Match.type().pipe(Match.withReturnType(), Match.when({
3996
- kind: "natural"
3997
- }, () => a.objectId.localeCompare(b.objectId)), Match.when({
3998
- kind: "property"
3999
- }, ({ property, direction }) => {
4000
- const comparison = this._compareByProperty(a, b, property);
4001
- return direction === "desc" ? -comparison : comparison;
4002
- }), Match.exhaustive)(order);
3969
+ switch (order.kind) {
3970
+ case "natural":
3971
+ return a.objectId.localeCompare(b.objectId);
3972
+ case "property": {
3973
+ const comparison = this._compareByProperty(a, b, order.property);
3974
+ return order.direction === "desc" ? -comparison : comparison;
3975
+ }
3976
+ default:
3977
+ return 0;
3978
+ }
4003
3979
  }
4004
3980
  _compareByProperty(a, b, property) {
4005
3981
  const aValue = a.doc.data[property];
4006
3982
  const bValue = b.doc.data[property];
4007
- return Match.type().pipe(
4008
- Match.withReturnType(),
4009
- Match.when({
4010
- a: isNullable,
4011
- b: isNullable
4012
- }, () => 0),
4013
- Match.when({
4014
- a: isNullable
4015
- }, () => 1),
4016
- Match.when({
4017
- b: isNullable
4018
- }, () => -1),
4019
- Match.when({
4020
- a: Match.string,
4021
- b: Match.string
4022
- }, ({ a: a2, b: b2 }) => a2.localeCompare(b2)),
4023
- Match.when({
4024
- a: Match.number,
4025
- b: Match.number
4026
- }, ({ a: a2, b: b2 }) => a2 - b2),
4027
- Match.when({
4028
- a: Match.boolean,
4029
- b: Match.boolean
4030
- }, ({ a: a2, b: b2 }) => a2 === b2 ? 0 : a2 ? 1 : -1),
4031
- Match.when({
4032
- a: Match.defined,
4033
- b: Match.defined
4034
- }, ({ a: a2, b: b2 }) => String(a2).localeCompare(String(b2))),
4035
- // TODO(wittjosiah): Why does Match.exhaustive fail here?
4036
- Match.orElse(() => 0)
4037
- )({
4038
- a: aValue,
4039
- b: bValue
4040
- });
3983
+ if (aValue == null && bValue == null) {
3984
+ return 0;
3985
+ }
3986
+ if (aValue == null) {
3987
+ return 1;
3988
+ }
3989
+ if (bValue == null) {
3990
+ return -1;
3991
+ }
3992
+ if (typeof aValue === "string" && typeof bValue === "string") {
3993
+ return aValue.localeCompare(bValue);
3994
+ }
3995
+ if (typeof aValue === "number" && typeof bValue === "number") {
3996
+ return aValue - bValue;
3997
+ }
3998
+ if (typeof aValue === "boolean" && typeof bValue === "boolean") {
3999
+ return aValue === bValue ? 0 : aValue ? 1 : -1;
4000
+ }
4001
+ return String(aValue).localeCompare(String(bValue));
4041
4002
  }
4042
4003
  async _loadDocumentsAfterIndexQuery(indexHits) {
4043
4004
  return Promise.all(indexHits.map(async (hit) => {
4044
4005
  return this._loadFromIndexHit(hit);
4045
4006
  }));
4046
4007
  }
4008
+ /**
4009
+ * Space key hex -> SpaceId.
4010
+ */
4011
+ _spaceIdCache = /* @__PURE__ */ new Map();
4047
4012
  async _loadFromIndexHit(hit) {
4048
4013
  const { objectId, documentId, spaceKey: spaceKeyInIndex } = objectPointerCodec3.decode(hit.id);
4049
4014
  const handle = await this._automergeHost.loadDoc(Context3.default(void 0, {
4050
4015
  F: __dxlog_file11,
4051
- L: 664
4016
+ L: 738
4052
4017
  }), documentId);
4053
4018
  const doc = handle.doc();
4054
4019
  if (!doc) {
@@ -4058,6 +4023,11 @@ var QueryExecutor = class extends Resource6 {
4058
4023
  if (!spaceKey) {
4059
4024
  return null;
4060
4025
  }
4026
+ let spaceId = this._spaceIdCache.get(spaceKey);
4027
+ if (!spaceId) {
4028
+ spaceId = await createIdFromSpaceKey(PublicKey3.from(spaceKey));
4029
+ this._spaceIdCache.set(spaceKey, spaceId);
4030
+ }
4061
4031
  const object = DatabaseDirectory3.getInlineObject(doc, objectId);
4062
4032
  if (!object) {
4063
4033
  return null;
@@ -4065,7 +4035,7 @@ var QueryExecutor = class extends Resource6 {
4065
4035
  return {
4066
4036
  objectId,
4067
4037
  documentId,
4068
- spaceId: await createIdFromSpaceKey(PublicKey3.from(spaceKey)),
4038
+ spaceId,
4069
4039
  doc: object
4070
4040
  };
4071
4041
  }
@@ -4076,7 +4046,7 @@ var QueryExecutor = class extends Resource6 {
4076
4046
  dxn
4077
4047
  }, {
4078
4048
  F: __dxlog_file11,
4079
- L: 691,
4049
+ L: 771,
4080
4050
  S: this,
4081
4051
  C: (f, a) => f(...a)
4082
4052
  });
@@ -4089,7 +4059,7 @@ var QueryExecutor = class extends Resource6 {
4089
4059
  spaceId
4090
4060
  }, {
4091
4061
  F: __dxlog_file11,
4092
- L: 699,
4062
+ L: 779,
4093
4063
  S: this,
4094
4064
  C: (f, a) => f(...a)
4095
4065
  });
@@ -4101,7 +4071,7 @@ var QueryExecutor = class extends Resource6 {
4101
4071
  spaceId
4102
4072
  }, {
4103
4073
  F: __dxlog_file11,
4104
- L: 704,
4074
+ L: 784,
4105
4075
  S: this,
4106
4076
  C: (f, a) => f(...a)
4107
4077
  });
@@ -4122,7 +4092,7 @@ var QueryExecutor = class extends Resource6 {
4122
4092
  }
4123
4093
  const handle = await this._automergeHost.loadDoc(Context3.default(void 0, {
4124
4094
  F: __dxlog_file11,
4125
- L: 723
4095
+ L: 803
4126
4096
  }), link);
4127
4097
  const doc = handle.doc();
4128
4098
  if (!doc) {
@@ -4139,37 +4109,9 @@ var QueryExecutor = class extends Resource6 {
4139
4109
  doc: object
4140
4110
  };
4141
4111
  }
4142
- constructor(options) {
4143
- super(), _define_property12(this, "_indexer", void 0), _define_property12(this, "_automergeHost", void 0), _define_property12(this, "_spaceStateManager", void 0), /**
4144
- * Id of this query.
4145
- */
4146
- _define_property12(this, "_id", void 0), _define_property12(this, "_query", void 0), // TODO(dmaretskyi): Might be used in the future.
4147
- _define_property12(this, "_reactivity", void 0), _define_property12(this, "_plan", void 0), _define_property12(this, "_trace", ExecutionTrace.makeEmpty()), _define_property12(this, "_lastResultSet", []);
4148
- this._indexer = options.indexer;
4149
- this._automergeHost = options.automergeHost;
4150
- this._spaceStateManager = options.spaceStateManager;
4151
- this._id = options.queryId;
4152
- this._query = options.query;
4153
- this._reactivity = options.reactivity;
4154
- const queryPlanner = new QueryPlanner();
4155
- this._plan = queryPlanner.createPlan(this._query);
4156
- }
4157
4112
  };
4158
4113
 
4159
4114
  // src/db-host/query-service.ts
4160
- function _define_property13(obj, key, value) {
4161
- if (key in obj) {
4162
- Object.defineProperty(obj, key, {
4163
- value,
4164
- enumerable: true,
4165
- configurable: true,
4166
- writable: true
4167
- });
4168
- } else {
4169
- obj[key] = value;
4170
- }
4171
- return obj;
4172
- }
4173
4115
  function _ts_decorate5(decorators, target, key, desc) {
4174
4116
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4175
4117
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -4178,6 +4120,27 @@ function _ts_decorate5(decorators, target, key, desc) {
4178
4120
  }
4179
4121
  var __dxlog_file12 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/query-service.ts";
4180
4122
  var QueryServiceImpl = class extends Resource7 {
4123
+ _params;
4124
+ // TODO(dmaretskyi): We need to implement query deduping. Idle composer has 80 queries with only 10 being unique.
4125
+ _queries = /* @__PURE__ */ new Set();
4126
+ _updateQueries;
4127
+ // TODO(burdon): OK for options, but not params. Pass separately and type readonly here.
4128
+ constructor(_params) {
4129
+ super(), this._params = _params;
4130
+ trace4.diagnostic({
4131
+ id: "active-queries",
4132
+ name: "Active Queries",
4133
+ fetch: () => {
4134
+ return Array.from(this._queries).map((query) => {
4135
+ return {
4136
+ query: JSON.stringify(query.executor.query),
4137
+ plan: JSON.stringify(query.executor.plan),
4138
+ trace: JSON.stringify(query.executor.trace)
4139
+ };
4140
+ });
4141
+ }
4142
+ });
4143
+ }
4181
4144
  async _open() {
4182
4145
  this._params.indexer.updated.on(this._ctx, () => this.invalidateQueries());
4183
4146
  this._updateQueries = new DeferredTask2(this._ctx, this._executeQueries.bind(this));
@@ -4196,7 +4159,7 @@ var QueryServiceImpl = class extends Resource7 {
4196
4159
  config: this._params.indexer.config
4197
4160
  }, {
4198
4161
  F: __dxlog_file12,
4199
- L: 101,
4162
+ L: 102,
4200
4163
  S: this,
4201
4164
  C: (f, a) => f(...a)
4202
4165
  });
@@ -4218,7 +4181,7 @@ var QueryServiceImpl = class extends Resource7 {
4218
4181
  async reindex() {
4219
4182
  log10("Reindexing all documents...", void 0, {
4220
4183
  F: __dxlog_file12,
4221
- L: 120,
4184
+ L: 121,
4222
4185
  S: this,
4223
4186
  C: (f, a) => f(...a)
4224
4187
  });
@@ -4233,7 +4196,7 @@ var QueryServiceImpl = class extends Resource7 {
4233
4196
  count: ids.size
4234
4197
  }, {
4235
4198
  F: __dxlog_file12,
4236
- L: 128,
4199
+ L: 129,
4237
4200
  S: this,
4238
4201
  C: (f, a) => f(...a)
4239
4202
  });
@@ -4243,7 +4206,7 @@ var QueryServiceImpl = class extends Resource7 {
4243
4206
  count: ids.size
4244
4207
  }, {
4245
4208
  F: __dxlog_file12,
4246
- L: 132,
4209
+ L: 133,
4247
4210
  S: this,
4248
4211
  C: (f, a) => f(...a)
4249
4212
  });
@@ -4309,7 +4272,7 @@ var QueryServiceImpl = class extends Resource7 {
4309
4272
  } catch (err) {
4310
4273
  log10.catch(err, void 0, {
4311
4274
  F: __dxlog_file12,
4312
- L: 203,
4275
+ L: 204,
4313
4276
  S: this,
4314
4277
  C: (f, a) => f(...a)
4315
4278
  });
@@ -4320,28 +4283,11 @@ var QueryServiceImpl = class extends Resource7 {
4320
4283
  duration: performance.now() - begin
4321
4284
  }, {
4322
4285
  F: __dxlog_file12,
4323
- L: 207,
4286
+ L: 208,
4324
4287
  S: this,
4325
4288
  C: (f, a) => f(...a)
4326
4289
  });
4327
4290
  }
4328
- // TODO(burdon): OK for options, but not params. Pass separately and type readonly here.
4329
- constructor(_params) {
4330
- super(), _define_property13(this, "_params", void 0), _define_property13(this, "_queries", void 0), _define_property13(this, "_updateQueries", void 0), this._params = _params, this._queries = /* @__PURE__ */ new Set();
4331
- trace4.diagnostic({
4332
- id: "active-queries",
4333
- name: "Active Queries",
4334
- fetch: () => {
4335
- return Array.from(this._queries).map((query) => {
4336
- return {
4337
- query: JSON.stringify(query.executor.query),
4338
- plan: JSON.stringify(query.executor.plan),
4339
- trace: JSON.stringify(query.executor.trace)
4340
- };
4341
- });
4342
- }
4343
- });
4344
- }
4345
4291
  };
4346
4292
  _ts_decorate5([
4347
4293
  synchronized2
@@ -4388,7 +4334,7 @@ var createDocumentsIterator = (automergeHost) => (
4388
4334
  }
4389
4335
  const linkHandle = await automergeHost.loadDoc(Context4.default(void 0, {
4390
4336
  F: __dxlog_file12,
4391
- L: 247
4337
+ L: 248
4392
4338
  }), urlString);
4393
4339
  for await (const result of getObjectsFromHandle(linkHandle)) {
4394
4340
  yield result;
@@ -4422,17 +4368,17 @@ import { DatabaseDirectory as DatabaseDirectory5, SpaceDocVersion as SpaceDocVer
4422
4368
  import { invariant as invariant11 } from "@dxos/invariant";
4423
4369
 
4424
4370
  // src/db-host/automerge-metrics.ts
4425
- import * as A4 from "@automerge/automerge";
4371
+ import * as A5 from "@automerge/automerge";
4426
4372
  import { log as log11 } from "@dxos/log";
4427
4373
  var __dxlog_file13 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/automerge-metrics.ts";
4428
4374
  var measureDocMetrics = (doc) => {
4429
- const snapshot = A4.save(doc);
4375
+ const snapshot = A5.save(doc);
4430
4376
  const start = Date.now();
4431
- const temp = A4.load(snapshot);
4377
+ const temp = A5.load(snapshot);
4432
4378
  const end = Date.now();
4433
- A4.free(temp);
4379
+ A5.free(temp);
4434
4380
  const getAllChangesStart = Date.now();
4435
- const mutationCount = A4.getAllChanges(doc).length;
4381
+ const mutationCount = A5.getAllChanges(doc).length;
4436
4382
  const getAllChangesEnd = Date.now();
4437
4383
  if (getAllChangesEnd - getAllChangesStart > 300) {
4438
4384
  log11.warn("getAllChanges took too long", {
@@ -4452,21 +4398,9 @@ var measureDocMetrics = (doc) => {
4452
4398
  };
4453
4399
 
4454
4400
  // src/db-host/database-root.ts
4455
- function _define_property14(obj, key, value) {
4456
- if (key in obj) {
4457
- Object.defineProperty(obj, key, {
4458
- value,
4459
- enumerable: true,
4460
- configurable: true,
4461
- writable: true
4462
- });
4463
- } else {
4464
- obj[key] = value;
4465
- }
4466
- return obj;
4467
- }
4468
4401
  var __dxlog_file14 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/database-root.ts";
4469
4402
  var DatabaseRoot = class {
4403
+ _rootHandle;
4470
4404
  static mapLinks(doc, mapping) {
4471
4405
  doc.change((d) => {
4472
4406
  if (!d.links) {
@@ -4480,6 +4414,9 @@ var DatabaseRoot = class {
4480
4414
  }
4481
4415
  });
4482
4416
  }
4417
+ constructor(_rootHandle) {
4418
+ this._rootHandle = _rootHandle;
4419
+ }
4483
4420
  get documentId() {
4484
4421
  return this._rootHandle.documentId;
4485
4422
  }
@@ -4543,28 +4480,16 @@ var DatabaseRoot = class {
4543
4480
  }
4544
4481
  return measureDocMetrics(doc);
4545
4482
  }
4546
- constructor(_rootHandle) {
4547
- _define_property14(this, "_rootHandle", void 0);
4548
- this._rootHandle = _rootHandle;
4549
- }
4550
4483
  };
4551
4484
 
4552
4485
  // src/db-host/space-state-manager.ts
4553
- function _define_property15(obj, key, value) {
4554
- if (key in obj) {
4555
- Object.defineProperty(obj, key, {
4556
- value,
4557
- enumerable: true,
4558
- configurable: true,
4559
- writable: true
4560
- });
4561
- } else {
4562
- obj[key] = value;
4563
- }
4564
- return obj;
4565
- }
4566
4486
  var __dxlog_file15 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/space-state-manager.ts";
4567
4487
  var SpaceStateManager = class extends Resource8 {
4488
+ _roots = /* @__PURE__ */ new Map();
4489
+ _rootBySpace = /* @__PURE__ */ new Map();
4490
+ _perRootContext = /* @__PURE__ */ new Map();
4491
+ _lastSpaceDocumentList = /* @__PURE__ */ new Map();
4492
+ spaceDocumentListUpdated = new Event3();
4568
4493
  async _close(ctx) {
4569
4494
  for (const [_, rootCtx] of this._perRootContext) {
4570
4495
  await rootCtx.dispose();
@@ -4637,16 +4562,13 @@ var SpaceStateManager = class extends Resource8 {
4637
4562
  documentListCheckScheduler.trigger();
4638
4563
  return root;
4639
4564
  }
4640
- constructor(...args) {
4641
- super(...args), _define_property15(this, "_roots", /* @__PURE__ */ new Map()), _define_property15(this, "_rootBySpace", /* @__PURE__ */ new Map()), _define_property15(this, "_perRootContext", /* @__PURE__ */ new Map()), _define_property15(this, "_lastSpaceDocumentList", /* @__PURE__ */ new Map()), _define_property15(this, "spaceDocumentListUpdated", new Event3());
4642
- }
4643
4565
  };
4644
4566
  var SpaceDocumentListUpdatedEvent = class {
4567
+ spaceId;
4568
+ spaceRootId;
4569
+ previousRootId;
4570
+ documentIds;
4645
4571
  constructor(spaceId, spaceRootId, previousRootId, documentIds) {
4646
- _define_property15(this, "spaceId", void 0);
4647
- _define_property15(this, "spaceRootId", void 0);
4648
- _define_property15(this, "previousRootId", void 0);
4649
- _define_property15(this, "documentIds", void 0);
4650
4572
  this.spaceId = spaceId;
4651
4573
  this.spaceRootId = spaceRootId;
4652
4574
  this.previousRootId = previousRootId;
@@ -4655,19 +4577,6 @@ var SpaceDocumentListUpdatedEvent = class {
4655
4577
  };
4656
4578
 
4657
4579
  // src/db-host/echo-host.ts
4658
- function _define_property16(obj, key, value) {
4659
- if (key in obj) {
4660
- Object.defineProperty(obj, key, {
4661
- value,
4662
- enumerable: true,
4663
- configurable: true,
4664
- writable: true
4665
- });
4666
- } else {
4667
- obj[key] = value;
4668
- }
4669
- return obj;
4670
- }
4671
4580
  var __dxlog_file16 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/echo-host.ts";
4672
4581
  var DEFAULT_INDEXING_CONFIG = {
4673
4582
  // TODO(dmaretskyi): Disabled by default since embedding generation is expensive.
@@ -4675,6 +4584,111 @@ var DEFAULT_INDEXING_CONFIG = {
4675
4584
  vector: false
4676
4585
  };
4677
4586
  var EchoHost = class extends Resource9 {
4587
+ _indexMetadataStore;
4588
+ _indexer;
4589
+ _automergeHost;
4590
+ _queryService;
4591
+ _dataService;
4592
+ _spaceStateManager = new SpaceStateManager();
4593
+ _echoDataMonitor;
4594
+ constructor({ kv, indexing = {}, peerIdProvider, getSpaceKeyByRootDocumentId }) {
4595
+ super();
4596
+ const indexingConfig = {
4597
+ ...DEFAULT_INDEXING_CONFIG,
4598
+ ...indexing
4599
+ };
4600
+ this._indexMetadataStore = new IndexMetadataStore({
4601
+ db: kv.sublevel("index-metadata")
4602
+ });
4603
+ this._echoDataMonitor = new EchoDataMonitor();
4604
+ this._automergeHost = new AutomergeHost({
4605
+ db: kv,
4606
+ dataMonitor: this._echoDataMonitor,
4607
+ indexMetadataStore: this._indexMetadataStore,
4608
+ peerIdProvider,
4609
+ getSpaceKeyByRootDocumentId
4610
+ });
4611
+ this._indexer = new Indexer({
4612
+ db: kv,
4613
+ indexStore: new IndexStore({
4614
+ db: kv.sublevel("index-storage")
4615
+ }),
4616
+ metadataStore: this._indexMetadataStore,
4617
+ loadDocuments: createSelectedDocumentsIterator(this._automergeHost),
4618
+ indexCooldownTime: false ? 0 : void 0
4619
+ });
4620
+ void this._indexer.setConfig({
4621
+ enabled: true,
4622
+ indexes: [
4623
+ //
4624
+ {
4625
+ kind: IndexKind.Kind.SCHEMA_MATCH
4626
+ },
4627
+ {
4628
+ kind: IndexKind.Kind.GRAPH
4629
+ },
4630
+ ...indexingConfig.fullText ? [
4631
+ {
4632
+ kind: IndexKind.Kind.FULL_TEXT
4633
+ }
4634
+ ] : [],
4635
+ ...indexingConfig.vector ? [
4636
+ {
4637
+ kind: IndexKind.Kind.VECTOR
4638
+ }
4639
+ ] : []
4640
+ ]
4641
+ });
4642
+ this._queryService = new QueryServiceImpl({
4643
+ automergeHost: this._automergeHost,
4644
+ indexer: this._indexer,
4645
+ spaceStateManager: this._spaceStateManager
4646
+ });
4647
+ this._dataService = new DataServiceImpl({
4648
+ automergeHost: this._automergeHost,
4649
+ spaceStateManager: this._spaceStateManager,
4650
+ updateIndexes: async () => {
4651
+ await this._indexer.updateIndexes();
4652
+ }
4653
+ });
4654
+ trace5.diagnostic({
4655
+ id: "echo-stats",
4656
+ name: "Echo Stats",
4657
+ fetch: async () => {
4658
+ return {
4659
+ dataStats: this._echoDataMonitor.computeStats(),
4660
+ loadedDocsCount: this._automergeHost.loadedDocsCount
4661
+ };
4662
+ }
4663
+ });
4664
+ trace5.diagnostic({
4665
+ id: "database-roots",
4666
+ name: "Database Roots",
4667
+ fetch: async () => {
4668
+ return Array.from(this._spaceStateManager.roots.values()).map((root) => ({
4669
+ url: root.url,
4670
+ isLoaded: root.isLoaded,
4671
+ spaceKey: root.getSpaceKey(),
4672
+ inlineObjects: root.getInlineObjectCount(),
4673
+ linkedObjects: root.getLinkedObjectCount()
4674
+ }));
4675
+ }
4676
+ });
4677
+ trace5.diagnostic({
4678
+ id: "database-root-metrics",
4679
+ name: "Database Roots (with metrics)",
4680
+ fetch: async () => {
4681
+ return Array.from(this._spaceStateManager.roots.values()).map((root) => ({
4682
+ url: root.url,
4683
+ isLoaded: root.isLoaded,
4684
+ spaceKey: root.getSpaceKey(),
4685
+ inlineObjects: root.getInlineObjectCount(),
4686
+ linkedObjects: root.getLinkedObjectCount(),
4687
+ ...root.measureMetrics() ?? {}
4688
+ }));
4689
+ }
4690
+ });
4691
+ }
4678
4692
  get queryService() {
4679
4693
  return this._queryService;
4680
4694
  }
@@ -4799,107 +4813,10 @@ var EchoHost = class extends Resource9 {
4799
4813
  async removeReplicator(replicator) {
4800
4814
  await this._automergeHost.removeReplicator(replicator);
4801
4815
  }
4802
- constructor({ kv, indexing = {}, peerIdProvider, getSpaceKeyByRootDocumentId }) {
4803
- super(), _define_property16(this, "_indexMetadataStore", void 0), _define_property16(this, "_indexer", void 0), _define_property16(this, "_automergeHost", void 0), _define_property16(this, "_queryService", void 0), _define_property16(this, "_dataService", void 0), _define_property16(this, "_spaceStateManager", new SpaceStateManager()), _define_property16(this, "_echoDataMonitor", void 0);
4804
- const indexingConfig = {
4805
- ...DEFAULT_INDEXING_CONFIG,
4806
- ...indexing
4807
- };
4808
- this._indexMetadataStore = new IndexMetadataStore({
4809
- db: kv.sublevel("index-metadata")
4810
- });
4811
- this._echoDataMonitor = new EchoDataMonitor();
4812
- this._automergeHost = new AutomergeHost({
4813
- db: kv,
4814
- dataMonitor: this._echoDataMonitor,
4815
- indexMetadataStore: this._indexMetadataStore,
4816
- peerIdProvider,
4817
- getSpaceKeyByRootDocumentId
4818
- });
4819
- this._indexer = new Indexer({
4820
- db: kv,
4821
- indexStore: new IndexStore({
4822
- db: kv.sublevel("index-storage")
4823
- }),
4824
- metadataStore: this._indexMetadataStore,
4825
- loadDocuments: createSelectedDocumentsIterator(this._automergeHost),
4826
- indexCooldownTime: false ? 0 : void 0
4827
- });
4828
- void this._indexer.setConfig({
4829
- enabled: true,
4830
- indexes: [
4831
- //
4832
- {
4833
- kind: IndexKind.Kind.SCHEMA_MATCH
4834
- },
4835
- {
4836
- kind: IndexKind.Kind.GRAPH
4837
- },
4838
- ...indexingConfig.fullText ? [
4839
- {
4840
- kind: IndexKind.Kind.FULL_TEXT
4841
- }
4842
- ] : [],
4843
- ...indexingConfig.vector ? [
4844
- {
4845
- kind: IndexKind.Kind.VECTOR
4846
- }
4847
- ] : []
4848
- ]
4849
- });
4850
- this._queryService = new QueryServiceImpl({
4851
- automergeHost: this._automergeHost,
4852
- indexer: this._indexer,
4853
- spaceStateManager: this._spaceStateManager
4854
- });
4855
- this._dataService = new DataServiceImpl({
4856
- automergeHost: this._automergeHost,
4857
- spaceStateManager: this._spaceStateManager,
4858
- updateIndexes: async () => {
4859
- await this._indexer.updateIndexes();
4860
- }
4861
- });
4862
- trace5.diagnostic({
4863
- id: "echo-stats",
4864
- name: "Echo Stats",
4865
- fetch: async () => {
4866
- return {
4867
- dataStats: this._echoDataMonitor.computeStats(),
4868
- loadedDocsCount: this._automergeHost.loadedDocsCount
4869
- };
4870
- }
4871
- });
4872
- trace5.diagnostic({
4873
- id: "database-roots",
4874
- name: "Database Roots",
4875
- fetch: async () => {
4876
- return Array.from(this._spaceStateManager.roots.values()).map((root) => ({
4877
- url: root.url,
4878
- isLoaded: root.isLoaded,
4879
- spaceKey: root.getSpaceKey(),
4880
- inlineObjects: root.getInlineObjectCount(),
4881
- linkedObjects: root.getLinkedObjectCount()
4882
- }));
4883
- }
4884
- });
4885
- trace5.diagnostic({
4886
- id: "database-root-metrics",
4887
- name: "Database Roots (with metrics)",
4888
- fetch: async () => {
4889
- return Array.from(this._spaceStateManager.roots.values()).map((root) => ({
4890
- url: root.url,
4891
- isLoaded: root.isLoaded,
4892
- spaceKey: root.getSpaceKey(),
4893
- inlineObjects: root.getInlineObjectCount(),
4894
- linkedObjects: root.getLinkedObjectCount(),
4895
- ...root.measureMetrics() ?? {}
4896
- }));
4897
- }
4898
- });
4899
- }
4900
4816
  };
4901
4817
 
4902
4818
  // src/edge/echo-edge-replicator.ts
4819
+ import * as Automerge from "@automerge/automerge";
4903
4820
  import { cbor as cbor2 } from "@automerge/automerge-repo";
4904
4821
  import { Mutex, scheduleMicroTask as scheduleMicroTask2, scheduleTask as scheduleTask2 } from "@dxos/async";
4905
4822
  import { Context as Context6, Resource as Resource11 } from "@dxos/context";
@@ -4909,27 +4826,26 @@ import { log as log13 } from "@dxos/log";
4909
4826
  import { DocumentCodec, EdgeService } from "@dxos/protocols";
4910
4827
  import { buf } from "@dxos/protocols/buf";
4911
4828
  import { MessageSchema as RouterMessageSchema } from "@dxos/protocols/buf/dxos/edge/messenger_pb";
4912
- import { bufferToArray as bufferToArray2 } from "@dxos/util";
4829
+ import { bufferToArray as bufferToArray2, setDeep } from "@dxos/util";
4913
4830
 
4914
4831
  // src/edge/inflight-request-limiter.ts
4915
4832
  import { Trigger as Trigger2 } from "@dxos/async";
4916
4833
  import { Resource as Resource10 } from "@dxos/context";
4917
4834
  import { log as log12 } from "@dxos/log";
4918
- function _define_property17(obj, key, value) {
4919
- if (key in obj) {
4920
- Object.defineProperty(obj, key, {
4921
- value,
4922
- enumerable: true,
4923
- configurable: true,
4924
- writable: true
4925
- });
4926
- } else {
4927
- obj[key] = value;
4928
- }
4929
- return obj;
4930
- }
4931
4835
  var __dxlog_file17 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/edge/inflight-request-limiter.ts";
4932
4836
  var InflightRequestLimiter = class extends Resource10 {
4837
+ _config;
4838
+ /**
4839
+ * Decrement when we receive a sync message, increment when we send one.
4840
+ * Can't exceed _config.maxInflightRequests.
4841
+ * Resets after timeout to avoid replicator being stuck.
4842
+ */
4843
+ _inflightRequestBalance = 0;
4844
+ _requestBarrier = new Trigger2();
4845
+ _resetBalanceTimeout;
4846
+ constructor(_config) {
4847
+ super(), this._config = _config;
4848
+ }
4933
4849
  async _open() {
4934
4850
  this._inflightRequestBalance = 0;
4935
4851
  this._requestBarrier.reset();
@@ -4972,30 +4888,9 @@ var InflightRequestLimiter = class extends Resource10 {
4972
4888
  clearInterval(this._resetBalanceTimeout);
4973
4889
  }
4974
4890
  }
4975
- constructor(_config) {
4976
- super(), _define_property17(this, "_config", void 0), /**
4977
- * Decrement when we receive a sync message, increment when we send one.
4978
- * Can't exceed _config.maxInflightRequests.
4979
- * Resets after timeout to avoid replicator being stuck.
4980
- */
4981
- _define_property17(this, "_inflightRequestBalance", void 0), _define_property17(this, "_requestBarrier", void 0), _define_property17(this, "_resetBalanceTimeout", void 0), this._config = _config, this._inflightRequestBalance = 0, this._requestBarrier = new Trigger2();
4982
- }
4983
4891
  };
4984
4892
 
4985
4893
  // src/edge/echo-edge-replicator.ts
4986
- function _define_property18(obj, key, value) {
4987
- if (key in obj) {
4988
- Object.defineProperty(obj, key, {
4989
- value,
4990
- enumerable: true,
4991
- configurable: true,
4992
- writable: true
4993
- });
4994
- } else {
4995
- obj[key] = value;
4996
- }
4997
- return obj;
4998
- }
4999
4894
  function _ts_add_disposable_resource(env, value, async) {
5000
4895
  if (value !== null && value !== void 0) {
5001
4896
  if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
@@ -5066,20 +4961,33 @@ var INITIAL_RESTART_DELAY = 500;
5066
4961
  var RESTART_DELAY_JITTER = 250;
5067
4962
  var MAX_RESTART_DELAY = 5e3;
5068
4963
  var EchoEdgeReplicator = class {
4964
+ _edgeConnection;
4965
+ _edgeHttpClient;
4966
+ _mutex = new Mutex();
4967
+ _ctx = void 0;
4968
+ _context = null;
4969
+ _connectedSpaces = /* @__PURE__ */ new Set();
4970
+ _connections = /* @__PURE__ */ new Map();
4971
+ _sharePolicyEnabled = true;
4972
+ constructor({ edgeConnection, edgeHttpClient, disableSharePolicy }) {
4973
+ this._edgeConnection = edgeConnection;
4974
+ this._edgeHttpClient = edgeHttpClient;
4975
+ this._sharePolicyEnabled = !disableSharePolicy;
4976
+ }
5069
4977
  async connect(context) {
5070
4978
  log13("connecting...", {
5071
4979
  peerId: context.peerId,
5072
4980
  connectedSpaces: this._connectedSpaces.size
5073
4981
  }, {
5074
4982
  F: __dxlog_file18,
5075
- L: 72,
4983
+ L: 73,
5076
4984
  S: this,
5077
4985
  C: (f, a) => f(...a)
5078
4986
  });
5079
4987
  this._context = context;
5080
4988
  this._ctx = Context6.default(void 0, {
5081
4989
  F: __dxlog_file18,
5082
- L: 74
4990
+ L: 75
5083
4991
  });
5084
4992
  this._ctx.onDispose(this._edgeConnection.onReconnected(() => {
5085
4993
  this._ctx && scheduleMicroTask2(this._ctx, () => this._handleReconnect());
@@ -5178,7 +5086,7 @@ var EchoEdgeReplicator = class {
5178
5086
  async _openConnection(spaceId, reconnects = 0) {
5179
5087
  invariant14(this._context, void 0, {
5180
5088
  F: __dxlog_file18,
5181
- L: 135,
5089
+ L: 136,
5182
5090
  S: this,
5183
5091
  A: [
5184
5092
  "this._context",
@@ -5187,7 +5095,7 @@ var EchoEdgeReplicator = class {
5187
5095
  });
5188
5096
  invariant14(!this._connections.has(spaceId), void 0, {
5189
5097
  F: __dxlog_file18,
5190
- L: 136,
5098
+ L: 137,
5191
5099
  S: this,
5192
5100
  A: [
5193
5101
  "!this._connections.has(spaceId)",
@@ -5206,7 +5114,7 @@ var EchoEdgeReplicator = class {
5206
5114
  spaceId
5207
5115
  }, {
5208
5116
  F: __dxlog_file18,
5209
- L: 147,
5117
+ L: 148,
5210
5118
  S: this,
5211
5119
  C: (f, a) => f(...a)
5212
5120
  });
@@ -5217,7 +5125,7 @@ var EchoEdgeReplicator = class {
5217
5125
  spaceId
5218
5126
  }, {
5219
5127
  F: __dxlog_file18,
5220
- L: 151,
5128
+ L: 152,
5221
5129
  S: this,
5222
5130
  C: (f, a) => f(...a)
5223
5131
  });
@@ -5234,7 +5142,7 @@ var EchoEdgeReplicator = class {
5234
5142
  restartDelay
5235
5143
  }, {
5236
5144
  F: __dxlog_file18,
5237
- L: 162,
5145
+ L: 163,
5238
5146
  S: this,
5239
5147
  C: (f, a) => f(...a)
5240
5148
  });
@@ -5262,7 +5170,7 @@ var EchoEdgeReplicator = class {
5262
5170
  restartDelay
5263
5171
  }, {
5264
5172
  F: __dxlog_file18,
5265
- L: 179,
5173
+ L: 180,
5266
5174
  S: this,
5267
5175
  C: (f, a) => f(...a)
5268
5176
  });
@@ -5279,27 +5187,57 @@ var EchoEdgeReplicator = class {
5279
5187
  this._connections.set(spaceId, connection);
5280
5188
  await connection.open();
5281
5189
  }
5282
- constructor({ edgeConnection, edgeHttpClient, disableSharePolicy }) {
5283
- _define_property18(this, "_edgeConnection", void 0);
5284
- _define_property18(this, "_edgeHttpClient", void 0);
5285
- _define_property18(this, "_mutex", new Mutex());
5286
- _define_property18(this, "_ctx", void 0);
5287
- _define_property18(this, "_context", null);
5288
- _define_property18(this, "_connectedSpaces", /* @__PURE__ */ new Set());
5289
- _define_property18(this, "_connections", /* @__PURE__ */ new Map());
5290
- _define_property18(this, "_sharePolicyEnabled", true);
5291
- this._edgeConnection = edgeConnection;
5292
- this._edgeHttpClient = edgeHttpClient;
5293
- this._sharePolicyEnabled = !disableSharePolicy;
5294
- }
5295
5190
  };
5296
5191
  var MAX_INFLIGHT_REQUESTS = 5;
5297
5192
  var MAX_RATE_LIMIT_WAIT_TIME_MS = 3e3;
5298
5193
  var EdgeReplicatorConnection = class extends Resource11 {
5194
+ _connectionId = randomUUID();
5195
+ _edgeConnection;
5196
+ _edgeHttpClient;
5197
+ _remotePeerId = null;
5198
+ _targetServiceId;
5199
+ _spaceId;
5200
+ _context;
5201
+ _sharedPolicyEnabled;
5202
+ _onRemoteConnected;
5203
+ _onRemoteDisconnected;
5204
+ _onRestartRequested;
5205
+ _sequence = 0;
5206
+ _requestLimiter = new InflightRequestLimiter({
5207
+ maxInflightRequests: MAX_INFLIGHT_REQUESTS,
5208
+ resetBalanceTimeoutMs: MAX_RATE_LIMIT_WAIT_TIME_MS
5209
+ });
5210
+ _readableStreamController;
5211
+ readable;
5212
+ writable;
5213
+ constructor({ edgeConnection, edgeHttpClient, spaceId, context, sharedPolicyEnabled, onRemoteConnected, onRemoteDisconnected, onRestartRequested }) {
5214
+ super();
5215
+ this._edgeConnection = edgeConnection;
5216
+ this._edgeHttpClient = edgeHttpClient;
5217
+ this._spaceId = spaceId;
5218
+ this._context = context;
5219
+ this._remotePeerId = `${EdgeService.AUTOMERGE_REPLICATOR}:${spaceId}-${this._connectionId}`;
5220
+ this._targetServiceId = `${EdgeService.AUTOMERGE_REPLICATOR}:${spaceId}`;
5221
+ this._sharedPolicyEnabled = sharedPolicyEnabled;
5222
+ this._onRemoteConnected = onRemoteConnected;
5223
+ this._onRemoteDisconnected = onRemoteDisconnected;
5224
+ this._onRestartRequested = onRestartRequested;
5225
+ this.readable = new ReadableStream({
5226
+ start: (controller) => {
5227
+ this._readableStreamController = controller;
5228
+ }
5229
+ });
5230
+ this.writable = new WritableStream({
5231
+ write: async (message, controller) => {
5232
+ await this._requestLimiter.rateLimit(message);
5233
+ await this._sendMessage(message);
5234
+ }
5235
+ });
5236
+ }
5299
5237
  async _open(ctx) {
5300
5238
  log13("opening...", void 0, {
5301
5239
  F: __dxlog_file18,
5302
- L: 270,
5240
+ L: 273,
5303
5241
  S: this,
5304
5242
  C: (f, a) => f(...a)
5305
5243
  });
@@ -5314,7 +5252,7 @@ var EdgeReplicatorConnection = class extends Resource11 {
5314
5252
  if (firstReconnect) {
5315
5253
  log13.verbose("first reconnect skipped", void 0, {
5316
5254
  F: __dxlog_file18,
5317
- L: 285,
5255
+ L: 288,
5318
5256
  S: this,
5319
5257
  C: (f, a) => f(...a)
5320
5258
  });
@@ -5329,7 +5267,7 @@ var EdgeReplicatorConnection = class extends Resource11 {
5329
5267
  async _close() {
5330
5268
  log13("closing...", void 0, {
5331
5269
  F: __dxlog_file18,
5332
- L: 298,
5270
+ L: 301,
5333
5271
  S: this,
5334
5272
  C: (f, a) => f(...a)
5335
5273
  });
@@ -5340,7 +5278,7 @@ var EdgeReplicatorConnection = class extends Resource11 {
5340
5278
  get peerId() {
5341
5279
  invariant14(this._remotePeerId, "Not connected", {
5342
5280
  F: __dxlog_file18,
5343
- L: 307,
5281
+ L: 310,
5344
5282
  S: this,
5345
5283
  A: [
5346
5284
  "this._remotePeerId",
@@ -5365,7 +5303,7 @@ var EdgeReplicatorConnection = class extends Resource11 {
5365
5303
  remoteId: this._remotePeerId
5366
5304
  }, {
5367
5305
  F: __dxlog_file18,
5368
- L: 322,
5306
+ L: 325,
5369
5307
  S: this,
5370
5308
  C: (f, a) => f(...a)
5371
5309
  });
@@ -5386,12 +5324,11 @@ var EdgeReplicatorConnection = class extends Resource11 {
5386
5324
  }
5387
5325
  const payload = cbor2.decode(message.payload.value);
5388
5326
  log13.verbose("received", {
5389
- type: payload.type,
5390
- documentId: payload.type === "sync" && payload.documentId,
5327
+ ...getMessageInfo(payload),
5391
5328
  remoteId: this._remotePeerId
5392
5329
  }, {
5393
5330
  F: __dxlog_file18,
5394
- L: 351,
5331
+ L: 354,
5395
5332
  S: this,
5396
5333
  C: (f, a) => f(...a)
5397
5334
  });
@@ -5422,7 +5359,7 @@ var EdgeReplicatorConnection = class extends Resource11 {
5422
5359
  ]));
5423
5360
  }
5424
5361
  _processMessage(message) {
5425
- if (isForbiddenErrorMessage(message)) {
5362
+ if (isErrorMessage(message)) {
5426
5363
  this._onRestartRequested();
5427
5364
  return;
5428
5365
  }
@@ -5431,13 +5368,20 @@ var EdgeReplicatorConnection = class extends Resource11 {
5431
5368
  }
5432
5369
  async _sendMessage(message) {
5433
5370
  message.targetId = this._targetServiceId;
5371
+ setDeep(message, [
5372
+ "metadata",
5373
+ "dxos_sequence"
5374
+ ], this._getSequence());
5375
+ setDeep(message, [
5376
+ "metadata",
5377
+ "dxos_connectionId"
5378
+ ], this._connectionId);
5434
5379
  log13.verbose("sending...", {
5435
- type: message.type,
5436
- documentId: message.type === "sync" && message.documentId,
5380
+ ...getMessageInfo(message),
5437
5381
  remoteId: this._remotePeerId
5438
5382
  }, {
5439
5383
  F: __dxlog_file18,
5440
- L: 401,
5384
+ L: 407,
5441
5385
  S: this,
5442
5386
  C: (f, a) => f(...a)
5443
5387
  });
@@ -5458,41 +5402,29 @@ var EdgeReplicatorConnection = class extends Resource11 {
5458
5402
  err
5459
5403
  }, {
5460
5404
  F: __dxlog_file18,
5461
- L: 421,
5405
+ L: 426,
5462
5406
  S: this,
5463
5407
  C: (f, a) => f(...a)
5464
5408
  });
5465
5409
  }
5466
5410
  }
5467
- constructor({ edgeConnection, edgeHttpClient, spaceId, context, sharedPolicyEnabled, onRemoteConnected, onRemoteDisconnected, onRestartRequested }) {
5468
- super(), _define_property18(this, "_edgeConnection", void 0), _define_property18(this, "_edgeHttpClient", void 0), _define_property18(this, "_remotePeerId", null), _define_property18(this, "_targetServiceId", void 0), _define_property18(this, "_spaceId", void 0), _define_property18(this, "_context", void 0), _define_property18(this, "_sharedPolicyEnabled", void 0), _define_property18(this, "_onRemoteConnected", void 0), _define_property18(this, "_onRemoteDisconnected", void 0), _define_property18(this, "_onRestartRequested", void 0), _define_property18(this, "_requestLimiter", new InflightRequestLimiter({
5469
- maxInflightRequests: MAX_INFLIGHT_REQUESTS,
5470
- resetBalanceTimeoutMs: MAX_RATE_LIMIT_WAIT_TIME_MS
5471
- })), _define_property18(this, "_readableStreamController", void 0), _define_property18(this, "readable", void 0), _define_property18(this, "writable", void 0);
5472
- this._edgeConnection = edgeConnection;
5473
- this._edgeHttpClient = edgeHttpClient;
5474
- this._spaceId = spaceId;
5475
- this._context = context;
5476
- this._remotePeerId = `${EdgeService.AUTOMERGE_REPLICATOR}:${spaceId}-${randomUUID()}`;
5477
- this._targetServiceId = `${EdgeService.AUTOMERGE_REPLICATOR}:${spaceId}`;
5478
- this._sharedPolicyEnabled = sharedPolicyEnabled;
5479
- this._onRemoteConnected = onRemoteConnected;
5480
- this._onRemoteDisconnected = onRemoteDisconnected;
5481
- this._onRestartRequested = onRestartRequested;
5482
- this.readable = new ReadableStream({
5483
- start: (controller) => {
5484
- this._readableStreamController = controller;
5485
- }
5486
- });
5487
- this.writable = new WritableStream({
5488
- write: async (message, controller) => {
5489
- await this._requestLimiter.rateLimit(message);
5490
- await this._sendMessage(message);
5491
- }
5492
- });
5411
+ _getSequence() {
5412
+ return this._sequence++;
5493
5413
  }
5494
5414
  };
5495
- var isForbiddenErrorMessage = (message) => message.type === "error" && message.message === "Forbidden";
5415
+ var isErrorMessage = (message) => message.type === "error";
5416
+ var getMessageInfo = (msg) => {
5417
+ const { have, heads, need, changes } = msg.type === "sync" ? Automerge.decodeSyncMessage(msg.data) : {};
5418
+ return {
5419
+ type: msg.type,
5420
+ documentId: "documentId" in msg ? msg.documentId : void 0,
5421
+ have,
5422
+ heads,
5423
+ need,
5424
+ changes: changes?.length,
5425
+ sequence: msg.metadata?.dxos_sequence
5426
+ };
5427
+ };
5496
5428
 
5497
5429
  // src/util.ts
5498
5430
  import { ObjectStructure as ObjectStructure2, decodeReference } from "@dxos/echo-protocol";