@dxos/echo-pipeline 0.8.4-main.dedc0f3 → 0.8.4-main.ead640a

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 (51) hide show
  1. package/dist/lib/browser/{chunk-MBMJB3V7.mjs → chunk-WJJXJTNS.mjs} +62 -4
  2. package/dist/lib/browser/chunk-WJJXJTNS.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-I4JBIZSN.mjs → chunk-XGG76KKU.mjs} +3 -3
  4. package/dist/lib/browser/{chunk-I4JBIZSN.mjs.map → chunk-XGG76KKU.mjs.map} +1 -1
  5. package/dist/lib/browser/filter/index.mjs +1 -1
  6. package/dist/lib/browser/index.mjs +282 -152
  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 +3 -3
  10. package/dist/lib/browser/testing/index.mjs.map +3 -3
  11. package/dist/lib/node-esm/{chunk-YOL7JY5W.mjs → chunk-CHMJJ4DG.mjs} +3 -3
  12. package/dist/lib/node-esm/{chunk-YOL7JY5W.mjs.map → chunk-CHMJJ4DG.mjs.map} +1 -1
  13. package/dist/lib/node-esm/{chunk-XJZTCD4G.mjs → chunk-LEQ77KAT.mjs} +62 -4
  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 +282 -152
  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 +3 -3
  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/edge/echo-edge-replicator.d.ts.map +1 -1
  25. package/dist/types/src/filter/filter-match.d.ts +2 -2
  26. package/dist/types/src/filter/filter-match.d.ts.map +1 -1
  27. package/dist/types/src/query/errors.d.ts +12 -9
  28. package/dist/types/src/query/errors.d.ts.map +1 -1
  29. package/dist/types/src/query/query-executor.d.ts +4 -0
  30. package/dist/types/src/query/query-executor.d.ts.map +1 -1
  31. package/dist/types/src/query/query-planner.d.ts.map +1 -1
  32. package/dist/types/src/testing/test-data.d.ts.map +1 -1
  33. package/dist/types/src/testing/test-schema.d.ts +1 -1
  34. package/dist/types/src/testing/test-schema.d.ts.map +1 -1
  35. package/dist/types/tsconfig.tsbuildinfo +1 -1
  36. package/package.json +37 -39
  37. package/src/automerge/automerge-host.ts +34 -21
  38. package/src/automerge/collection-synchronizer.test.ts +4 -3
  39. package/src/automerge/collection-synchronizer.ts +13 -9
  40. package/src/db-host/echo-host.ts +1 -1
  41. package/src/db-host/query-service.ts +1 -1
  42. package/src/edge/echo-edge-replicator.ts +30 -9
  43. package/src/filter/filter-match.test.ts +32 -12
  44. package/src/filter/filter-match.ts +88 -11
  45. package/src/query/errors.ts +2 -0
  46. package/src/query/query-executor.ts +48 -3
  47. package/src/query/query-planner.ts +42 -11
  48. package/src/testing/test-data.ts +1 -1
  49. package/src/testing/test-schema.ts +1 -1
  50. package/dist/lib/browser/chunk-MBMJB3V7.mjs.map +0 -7
  51. package/dist/lib/node-esm/chunk-XJZTCD4G.mjs.map +0 -7
@@ -3,7 +3,7 @@ import {
3
3
  filterMatchObject,
4
4
  filterMatchObjectJSON,
5
5
  filterMatchValue
6
- } from "./chunk-MBMJB3V7.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-I4JBIZSN.mjs";
29
+ } from "./chunk-XGG76KKU.mjs";
30
30
  import "./chunk-CGS2ULMK.mjs";
31
31
 
32
32
  // src/db-host/data-service.ts
@@ -39,7 +39,6 @@ import { log as log7 } from "@dxos/log";
39
39
  // src/automerge/automerge-host.ts
40
40
  import { getBackend, getHeads, equals as headsEquals, isAutomerge, save } from "@automerge/automerge";
41
41
  import { Repo, interpretAsDocumentId } from "@automerge/automerge-repo";
42
- import { exportBundle } from "@automerge/automerge-repo-bundles";
43
42
  import { DeferredTask, Event as Event2, asyncTimeout } from "@dxos/async";
44
43
  import { Context, Resource as Resource3, cancelWithContext } from "@dxos/context";
45
44
  import { DatabaseDirectory } from "@dxos/echo-protocol";
@@ -48,10 +47,12 @@ import { PublicKey } from "@dxos/keys";
48
47
  import { log as log3 } from "@dxos/log";
49
48
  import { objectPointerCodec } from "@dxos/protocols";
50
49
  import { trace as trace2 } from "@dxos/tracing";
51
- import { ComplexSet, bufferToArray, range } from "@dxos/util";
50
+ import { ComplexSet, bufferToArray, isNonNullable as isNonNullable2, range } from "@dxos/util";
52
51
 
53
52
  // src/automerge/collection-synchronizer.ts
54
- 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";
55
56
  import { Event, asyncReturn, scheduleTask, scheduleTaskInterval } from "@dxos/async";
56
57
  import { Resource } from "@dxos/context";
57
58
  import { log } from "@dxos/log";
@@ -105,7 +106,7 @@ var CollectionSynchronizer = class extends Resource {
105
106
  state
106
107
  }, {
107
108
  F: __dxlog_file,
108
- L: 76,
109
+ L: 78,
109
110
  S: this,
110
111
  C: (f, a) => f(...a)
111
112
  });
@@ -124,7 +125,7 @@ var CollectionSynchronizer = class extends Resource {
124
125
  collectionId
125
126
  }, {
126
127
  F: __dxlog_file,
127
- L: 90,
128
+ L: 92,
128
129
  S: this,
129
130
  C: (f, a) => f(...a)
130
131
  });
@@ -207,7 +208,7 @@ var CollectionSynchronizer = class extends Resource {
207
208
  state
208
209
  }, {
209
210
  F: __dxlog_file,
210
- L: 171,
211
+ L: 173,
211
212
  S: this,
212
213
  C: (f, a) => f(...a)
213
214
  });
@@ -272,19 +273,18 @@ CollectionSynchronizer = _ts_decorate([
272
273
  trace.resource()
273
274
  ], CollectionSynchronizer);
274
275
  var diffCollectionState = (local, remote) => {
275
- const allDocuments = /* @__PURE__ */ new Set([
276
- ...Object.keys(local.documents),
277
- ...Object.keys(remote.documents)
278
- ]);
276
+ const localDocuments = Record.filter(local.documents, (heads) => heads.length > 0);
277
+ const remoteDocuments = Record.filter(remote.documents, (heads) => heads.length > 0);
278
+ const allDocuments = Array2.union(Record.keys(localDocuments), Record.keys(remoteDocuments));
279
279
  const missingOnRemote = [];
280
280
  const missingOnLocal = [];
281
281
  const different = [];
282
282
  for (const documentId of allDocuments) {
283
- if (!local.documents[documentId] || local.documents[documentId].length === 0) {
283
+ if (!localDocuments[documentId]) {
284
284
  missingOnLocal.push(documentId);
285
- } else if (!remote.documents[documentId] || remote.documents[documentId].length === 0) {
285
+ } else if (!remoteDocuments[documentId]) {
286
286
  missingOnRemote.push(documentId);
287
- } else if (!am.equals(local.documents[documentId], remote.documents[documentId])) {
287
+ } else if (!A.equals(local.documents[documentId], remote.documents[documentId])) {
288
288
  different.push(documentId);
289
289
  }
290
290
  }
@@ -299,7 +299,7 @@ var validateCollectionState = (state) => {
299
299
  if (!isValidDocumentId(documentId)) {
300
300
  throw new Error(`Invalid documentId: ${documentId}`);
301
301
  }
302
- if (Array.isArray(heads) && heads.some((head) => typeof head !== "string")) {
302
+ if (Array2.isArray(heads) && heads.some((head) => typeof head !== "string")) {
303
303
  throw new Error(`Invalid heads: ${heads}`);
304
304
  }
305
305
  });
@@ -934,7 +934,7 @@ var AutomergeHost = class extends Resource3 {
934
934
  err
935
935
  }, {
936
936
  F: __dxlog_file3,
937
- L: 224,
937
+ L: 223,
938
938
  S: this,
939
939
  C: (f, a) => f(...a)
940
940
  });
@@ -968,7 +968,7 @@ var AutomergeHost = class extends Resource3 {
968
968
  async addReplicator(replicator) {
969
969
  invariant2(this.isOpen, "AutomergeHost is not open", {
970
970
  F: __dxlog_file3,
971
- L: 260,
971
+ L: 259,
972
972
  S: this,
973
973
  A: [
974
974
  "this.isOpen",
@@ -980,7 +980,7 @@ var AutomergeHost = class extends Resource3 {
980
980
  async removeReplicator(replicator) {
981
981
  invariant2(this.isOpen, "AutomergeHost is not open", {
982
982
  F: __dxlog_file3,
983
- L: 265,
983
+ L: 264,
984
984
  S: this,
985
985
  A: [
986
986
  "this.isOpen",
@@ -995,7 +995,7 @@ var AutomergeHost = class extends Resource3 {
995
995
  async loadDoc(ctx, documentId, opts) {
996
996
  invariant2(this.isOpen, "AutomergeHost is not open", {
997
997
  F: __dxlog_file3,
998
- L: 273,
998
+ L: 272,
999
999
  S: this,
1000
1000
  A: [
1001
1001
  "this.isOpen",
@@ -1021,7 +1021,7 @@ var AutomergeHost = class extends Resource3 {
1021
1021
  async exportDoc(ctx, id) {
1022
1022
  invariant2(this.isOpen, "AutomergeHost is not open", {
1023
1023
  F: __dxlog_file3,
1024
- L: 296,
1024
+ L: 295,
1025
1025
  S: this,
1026
1026
  A: [
1027
1027
  "this.isOpen",
@@ -1040,7 +1040,7 @@ var AutomergeHost = class extends Resource3 {
1040
1040
  createDoc(initialValue, opts) {
1041
1041
  invariant2(this.isOpen, "AutomergeHost is not open", {
1042
1042
  F: __dxlog_file3,
1043
- L: 307,
1043
+ L: 306,
1044
1044
  S: this,
1045
1045
  A: [
1046
1046
  "this.isOpen",
@@ -1065,7 +1065,7 @@ var AutomergeHost = class extends Resource3 {
1065
1065
  async waitUntilHeadsReplicated(heads) {
1066
1066
  invariant2(this.isOpen, "AutomergeHost is not open", {
1067
1067
  F: __dxlog_file3,
1068
- L: 329,
1068
+ L: 328,
1069
1069
  S: this,
1070
1070
  A: [
1071
1071
  "this.isOpen",
@@ -1087,10 +1087,10 @@ var AutomergeHost = class extends Resource3 {
1087
1087
  return !(currentHeads !== null && headsEquals(currentHeads, targetHeads));
1088
1088
  });
1089
1089
  if (headsToWait.length > 0) {
1090
- await Promise.all(headsToWait.map(async (entry, index) => {
1090
+ await Promise.all(headsToWait.map(async (entry) => {
1091
1091
  const handle = await this.loadDoc(Context.default(void 0, {
1092
1092
  F: __dxlog_file3,
1093
- L: 347
1093
+ L: 346
1094
1094
  }), entry.documentId);
1095
1095
  await waitForHeads(handle, entry.heads);
1096
1096
  }));
@@ -1100,7 +1100,7 @@ var AutomergeHost = class extends Resource3 {
1100
1100
  async reIndexHeads(documentIds) {
1101
1101
  invariant2(this.isOpen, "AutomergeHost is not open", {
1102
1102
  F: __dxlog_file3,
1103
- L: 360,
1103
+ L: 359,
1104
1104
  S: this,
1105
1105
  A: [
1106
1106
  "this.isOpen",
@@ -1112,7 +1112,7 @@ var AutomergeHost = class extends Resource3 {
1112
1112
  documentId
1113
1113
  }, {
1114
1114
  F: __dxlog_file3,
1115
- L: 362,
1115
+ L: 361,
1116
1116
  S: this,
1117
1117
  C: (f, a) => f(...a)
1118
1118
  });
@@ -1122,7 +1122,7 @@ var AutomergeHost = class extends Resource3 {
1122
1122
  documentId
1123
1123
  }, {
1124
1124
  F: __dxlog_file3,
1125
- L: 365,
1125
+ L: 364,
1126
1126
  S: this,
1127
1127
  C: (f, a) => f(...a)
1128
1128
  });
@@ -1135,7 +1135,7 @@ var AutomergeHost = class extends Resource3 {
1135
1135
  }
1136
1136
  log3("done re-indexing heads", void 0, {
1137
1137
  F: __dxlog_file3,
1138
- L: 374,
1138
+ L: 373,
1139
1139
  S: this,
1140
1140
  C: (f, a) => f(...a)
1141
1141
  });
@@ -1145,9 +1145,6 @@ var AutomergeHost = class extends Resource3 {
1145
1145
  // NOTE: If both peers return sharePolicy=false the replication will not happen
1146
1146
  // https://github.com/automerge/automerge-repo/pull/292
1147
1147
  async _sharePolicy(peerId, documentId) {
1148
- if (peerId.startsWith("client-")) {
1149
- return false;
1150
- }
1151
1148
  if (!documentId) {
1152
1149
  return false;
1153
1150
  }
@@ -1213,7 +1210,7 @@ var AutomergeHost = class extends Resource3 {
1213
1210
  this._headsUpdates.set(documentId, heads);
1214
1211
  invariant2(this._onHeadsChangedTask, "onHeadsChangedTask is not initialized", {
1215
1212
  F: __dxlog_file3,
1216
- L: 450,
1213
+ L: 445,
1217
1214
  S: this,
1218
1215
  A: [
1219
1216
  "this._onHeadsChangedTask",
@@ -1257,11 +1254,12 @@ var AutomergeHost = class extends Resource3 {
1257
1254
  * Flush documents to disk.
1258
1255
  */
1259
1256
  async flush({ documentIds } = {}) {
1260
- const loadedDocuments = documentIds?.filter((documentId) => {
1257
+ const loadedDocuments = (documentIds ?? Object.keys(this._repo.handles)).filter((documentId) => {
1261
1258
  const handle = this._repo.handles[documentId];
1262
1259
  return handle && handle.isReady();
1263
1260
  });
1264
1261
  await this._repo.flush(loadedDocuments);
1262
+ await this._onHeadsChangedTask?.runBlocking();
1265
1263
  }
1266
1264
  async getHeads(documentIds) {
1267
1265
  const result = [];
@@ -1396,7 +1394,7 @@ var AutomergeHost = class extends Resource3 {
1396
1394
  amount: missingOnRemote.length
1397
1395
  }, {
1398
1396
  F: __dxlog_file3,
1399
- L: 649,
1397
+ L: 650,
1400
1398
  S: this,
1401
1399
  C: (f, a) => f(...a)
1402
1400
  });
@@ -1409,7 +1407,7 @@ var AutomergeHost = class extends Resource3 {
1409
1407
  amount: missingOnRemote.length
1410
1408
  }, {
1411
1409
  F: __dxlog_file3,
1412
- L: 653,
1410
+ L: 654,
1413
1411
  S: this,
1414
1412
  C: (f, a) => f(...a)
1415
1413
  });
@@ -1420,7 +1418,7 @@ var AutomergeHost = class extends Resource3 {
1420
1418
  amount: missingOnLocal.length
1421
1419
  }, {
1422
1420
  F: __dxlog_file3,
1423
- L: 661,
1421
+ L: 662,
1424
1422
  S: this,
1425
1423
  C: (f, a) => f(...a)
1426
1424
  });
@@ -1433,7 +1431,7 @@ var AutomergeHost = class extends Resource3 {
1433
1431
  amount: missingOnLocal.length
1434
1432
  }, {
1435
1433
  F: __dxlog_file3,
1436
- L: 665,
1434
+ L: 666,
1437
1435
  S: this,
1438
1436
  C: (f, a) => f(...a)
1439
1437
  });
@@ -1449,7 +1447,7 @@ var AutomergeHost = class extends Resource3 {
1449
1447
  count: toReplicateWithoutBatching.length
1450
1448
  }, {
1451
1449
  F: __dxlog_file3,
1452
- L: 677,
1450
+ L: 678,
1453
1451
  S: this,
1454
1452
  C: (f, a) => f(...a)
1455
1453
  });
@@ -1477,7 +1475,7 @@ var AutomergeHost = class extends Resource3 {
1477
1475
  err
1478
1476
  }, {
1479
1477
  F: __dxlog_file3,
1480
- L: 708,
1478
+ L: 709,
1481
1479
  S: this,
1482
1480
  C: (f, a) => f(...a)
1483
1481
  });
@@ -1493,13 +1491,38 @@ var AutomergeHost = class extends Resource3 {
1493
1491
  if (this._ctx.disposed) {
1494
1492
  return;
1495
1493
  }
1496
- const handles = documentIds.map((documentId) => this._repo.handles[documentId]);
1497
- const bundle = exportBundle(this._repo, handles);
1498
- await this._echoNetworkAdapter.pushBundle(peerId, Array.from(bundle.docs.entries()).map(([documentId, doc]) => ({
1499
- documentId,
1500
- data: doc.data,
1501
- heads: doc.heads
1502
- })));
1494
+ const docs = documentIds.map((documentId) => {
1495
+ const handle = this._repo.handles[documentId];
1496
+ if (!handle || !handle.isReady()) {
1497
+ log3.warn("document not ready, skipping", {
1498
+ documentId
1499
+ }, {
1500
+ F: __dxlog_file3,
1501
+ L: 727,
1502
+ S: this,
1503
+ C: (f, a) => f(...a)
1504
+ });
1505
+ return;
1506
+ }
1507
+ const doc = handle.doc();
1508
+ if (!doc) {
1509
+ log3.warn("document not available, skipping", {
1510
+ documentId
1511
+ }, {
1512
+ F: __dxlog_file3,
1513
+ L: 732,
1514
+ S: this,
1515
+ C: (f, a) => f(...a)
1516
+ });
1517
+ return;
1518
+ }
1519
+ return {
1520
+ documentId,
1521
+ data: save(doc),
1522
+ heads: getHeads(doc)
1523
+ };
1524
+ });
1525
+ await this._echoNetworkAdapter.pushBundle(peerId, docs.filter(isNonNullable2));
1503
1526
  }
1504
1527
  async _pullInBundles(peerId, documentIds) {
1505
1528
  const documentsToPull = [
@@ -1520,7 +1543,7 @@ var AutomergeHost = class extends Resource3 {
1520
1543
  err
1521
1544
  }, {
1522
1545
  F: __dxlog_file3,
1523
- L: 752,
1546
+ L: 762,
1524
1547
  S: this,
1525
1548
  C: (f, a) => f(...a)
1526
1549
  });
@@ -1558,9 +1581,12 @@ var AutomergeHost = class extends Resource3 {
1558
1581
  const collectionsChanged = /* @__PURE__ */ new Set();
1559
1582
  for (const collectionId of this._collectionSynchronizer.getRegisteredCollectionIds()) {
1560
1583
  const state = this._collectionSynchronizer.getLocalCollectionState(collectionId);
1584
+ if (!state) {
1585
+ continue;
1586
+ }
1561
1587
  let newState;
1562
1588
  for (const [documentId, heads] of docHeads) {
1563
- if (state?.documents[documentId]) {
1589
+ if (documentId in state.documents) {
1564
1590
  if (!newState) {
1565
1591
  newState = structuredClone(state);
1566
1592
  }
@@ -1648,7 +1674,7 @@ var changeIsPresentInDoc = (doc, changeHash) => {
1648
1674
  var decodeCollectionState = (state) => {
1649
1675
  invariant2(typeof state === "object" && state !== null, "Invalid state", {
1650
1676
  F: __dxlog_file3,
1651
- L: 832,
1677
+ L: 845,
1652
1678
  S: void 0,
1653
1679
  A: [
1654
1680
  "typeof state === 'object' && state !== null",
@@ -1668,7 +1694,7 @@ import { log as log5 } from "@dxos/log";
1668
1694
  import { ComplexSet as ComplexSet2, defaultMap as defaultMap2 } from "@dxos/util";
1669
1695
 
1670
1696
  // src/automerge/mesh-echo-replicator-connection.ts
1671
- import * as A from "@automerge/automerge";
1697
+ import * as A2 from "@automerge/automerge";
1672
1698
  import { cbor } from "@automerge/automerge-repo";
1673
1699
  import { Resource as Resource4 } from "@dxos/context";
1674
1700
  import { invariant as invariant3 } from "@dxos/invariant";
@@ -1809,7 +1835,7 @@ var MeshReplicatorConnection = class extends Resource4 {
1809
1835
  };
1810
1836
  var logSendSync = (message) => {
1811
1837
  log4("sendSyncMessage", () => {
1812
- const decodedSyncMessage = message.type === "sync" && message.data ? A.decodeSyncMessage(message.data) : void 0;
1838
+ const decodedSyncMessage = message.type === "sync" && message.data ? A2.decodeSyncMessage(message.data) : void 0;
1813
1839
  return {
1814
1840
  sync: decodedSyncMessage && {
1815
1841
  headsLength: decodedSyncMessage.heads.length,
@@ -2472,7 +2498,7 @@ var getByteCount = (message) => {
2472
2498
  };
2473
2499
 
2474
2500
  // src/db-host/documents-synchronizer.ts
2475
- import { next as A2 } from "@automerge/automerge";
2501
+ import { next as A3 } from "@automerge/automerge";
2476
2502
  import { UpdateScheduler, sleep } from "@dxos/async";
2477
2503
  import { LifecycleState as LifecycleState2, Resource as Resource5, cancelWithContext as cancelWithContext2 } from "@dxos/context";
2478
2504
  import { invariant as invariant6 } from "@dxos/invariant";
@@ -2613,11 +2639,11 @@ var DocumentsSynchronizer = class extends Resource5 {
2613
2639
  return;
2614
2640
  }
2615
2641
  const doc = handle.doc();
2616
- const mutation = syncState.lastSentHead ? A2.saveSince(doc, syncState.lastSentHead) : A2.save(doc);
2642
+ const mutation = syncState.lastSentHead ? A3.saveSince(doc, syncState.lastSentHead) : A3.save(doc);
2617
2643
  if (mutation.length === 0) {
2618
2644
  return;
2619
2645
  }
2620
- syncState.lastSentHead = A2.getHeads(doc);
2646
+ syncState.lastSentHead = A3.getHeads(doc);
2621
2647
  return mutation;
2622
2648
  }
2623
2649
  _writeMutation(documentId, mutation, isNew) {
@@ -2629,7 +2655,7 @@ var DocumentsSynchronizer = class extends Resource5 {
2629
2655
  docId: documentId
2630
2656
  });
2631
2657
  const syncState = this._startSync(newHandle);
2632
- syncState.lastSentHead = A2.getHeads(newHandle.doc());
2658
+ syncState.lastSentHead = A3.getHeads(newHandle.doc());
2633
2659
  } else {
2634
2660
  const syncState = this._syncStates.get(documentId);
2635
2661
  invariant6(syncState, "Sync state for document not found", {
@@ -2641,12 +2667,12 @@ var DocumentsSynchronizer = class extends Resource5 {
2641
2667
  "'Sync state for document not found'"
2642
2668
  ]
2643
2669
  });
2644
- const headsBefore = A2.getHeads(syncState.handle.doc());
2670
+ const headsBefore = A3.getHeads(syncState.handle.doc());
2645
2671
  this._params.repo.import(mutation, {
2646
2672
  docId: documentId
2647
2673
  });
2648
- if (A2.equals(headsBefore, syncState.lastSentHead)) {
2649
- syncState.lastSentHead = A2.getHeads(syncState.handle.doc());
2674
+ if (A3.equals(headsBefore, syncState.lastSentHead)) {
2675
+ syncState.lastSentHead = A3.getHeads(syncState.handle.doc());
2650
2676
  }
2651
2677
  }
2652
2678
  }
@@ -2819,7 +2845,7 @@ import { IndexKind } from "@dxos/protocols/proto/dxos/echo/indexing";
2819
2845
  import { trace as trace5 } from "@dxos/tracing";
2820
2846
 
2821
2847
  // src/db-host/documents-iterator.ts
2822
- import * as A3 from "@automerge/automerge";
2848
+ import * as A4 from "@automerge/automerge";
2823
2849
  import { Context as Context2 } from "@dxos/context";
2824
2850
  import { DatabaseDirectory as DatabaseDirectory2, SpaceDocVersion } from "@dxos/echo-protocol";
2825
2851
  import { invariant as invariant8 } from "@dxos/invariant";
@@ -2850,10 +2876,10 @@ var createSelectedDocumentsIterator = (automergeHost) => (
2850
2876
  ""
2851
2877
  ]
2852
2878
  });
2853
- const currentHeads = A3.getHeads(doc);
2854
- if (!A3.equals(currentHeads, heads)) {
2879
+ const currentHeads = A4.getHeads(doc);
2880
+ if (!A4.equals(currentHeads, heads)) {
2855
2881
  const begin = Date.now();
2856
- doc = A3.view(doc, heads);
2882
+ doc = A4.view(doc, heads);
2857
2883
  const end = Date.now();
2858
2884
  if (end - begin > LOG_VIEW_OPERATION_THRESHOLD) {
2859
2885
  log8("Checking out document version is taking too long", {
@@ -2908,7 +2934,7 @@ var createSelectedDocumentsIterator = (automergeHost) => (
2908
2934
 
2909
2935
  // src/db-host/query-service.ts
2910
2936
  import { getHeads as getHeads3 } from "@automerge/automerge";
2911
- import { Schema } from "effect";
2937
+ import * as Schema from "effect/Schema";
2912
2938
  import { DeferredTask as DeferredTask2, scheduleMicroTask, synchronized as synchronized2 } from "@dxos/async";
2913
2939
  import { Stream as Stream2 } from "@dxos/codec-protobuf/stream";
2914
2940
  import { Context as Context4, Resource as Resource7 } from "@dxos/context";
@@ -2919,7 +2945,8 @@ import { objectPointerCodec as objectPointerCodec4 } from "@dxos/protocols";
2919
2945
  import { trace as trace4 } from "@dxos/tracing";
2920
2946
 
2921
2947
  // src/query/query-executor.ts
2922
- import { Match, Predicate } from "effect";
2948
+ import * as Match from "effect/Match";
2949
+ import * as Predicate from "effect/Predicate";
2923
2950
  import { Context as Context3, ContextDisposedError, LifecycleState as LifecycleState3, Resource as Resource6 } from "@dxos/context";
2924
2951
  import { DatabaseDirectory as DatabaseDirectory3, ObjectStructure, isEncodedReference } from "@dxos/echo-protocol";
2925
2952
  import { EscapedPropPath } from "@dxos/indexing";
@@ -2927,7 +2954,7 @@ import { invariant as invariant10 } from "@dxos/invariant";
2927
2954
  import { DXN, PublicKey as PublicKey3 } from "@dxos/keys";
2928
2955
  import { log as log9 } from "@dxos/log";
2929
2956
  import { objectPointerCodec as objectPointerCodec3 } from "@dxos/protocols";
2930
- import { getDeep, isNonNullable as isNonNullable2 } from "@dxos/util";
2957
+ import { getDeep, isNonNullable as isNonNullable3 } from "@dxos/util";
2931
2958
 
2932
2959
  // src/query/query-planner.ts
2933
2960
  import { Order } from "@dxos/echo";
@@ -2937,6 +2964,8 @@ import { invariant as invariant9 } from "@dxos/invariant";
2937
2964
  import { BaseError } from "@dxos/errors";
2938
2965
  var QueryError = class extends BaseError.extend("QUERY_ERROR") {
2939
2966
  };
2967
+ var InvalidQueryError = class extends QueryError.extend("INVALID_QUERY") {
2968
+ };
2940
2969
 
2941
2970
  // src/query/plan.ts
2942
2971
  (function(QueryPlan2) {
@@ -3011,7 +3040,8 @@ var QueryPlanner = class {
3011
3040
  case "order":
3012
3041
  return this._generateOrderClause(query, context);
3013
3042
  default:
3014
- throw new QueryError(`Unsupported query type: ${query.type}`, {
3043
+ throw new QueryError({
3044
+ message: `Unsupported query type: ${query.type}`,
3015
3045
  context: {
3016
3046
  query: context.originalQuery
3017
3047
  }
@@ -3035,10 +3065,11 @@ var QueryPlanner = class {
3035
3065
  }
3036
3066
  // TODO(dmaretskyi): This can be rewritten as a function of (filter[]) -> (selection ? undefined, rest: filter[]) that recurses onto itself.
3037
3067
  // 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.
3038
- _generateSelectionFromFilter(filter, context) {
3039
- switch (filter.type) {
3068
+ _generateSelectionFromFilter(filter2, context) {
3069
+ switch (filter2.type) {
3070
+ // Props
3040
3071
  case "object": {
3041
- if (context.selectionInverted && filter.id === void 0 && filter.typename === null && Object.keys(filter.props).length === 0) {
3072
+ if (context.selectionInverted && filter2.id === void 0 && filter2.typename === null && Object.keys(filter2.props).length === 0) {
3042
3073
  return QueryPlan.Plan.make([
3043
3074
  {
3044
3075
  _tag: "ClearWorkingSetStep"
@@ -3047,32 +3078,33 @@ var QueryPlanner = class {
3047
3078
  ]);
3048
3079
  }
3049
3080
  if (context.selectionInverted) {
3050
- throw new QueryError("Query too complex", {
3081
+ throw new QueryError({
3082
+ message: "Query too complex",
3051
3083
  context: {
3052
3084
  query: context.originalQuery
3053
3085
  }
3054
3086
  });
3055
3087
  }
3056
- if (filter.id && filter.id?.length > 0) {
3088
+ if (filter2.id && filter2.id?.length > 0) {
3057
3089
  return QueryPlan.Plan.make([
3058
3090
  {
3059
3091
  _tag: "SelectStep",
3060
3092
  spaces: context.selectionSpaces,
3061
3093
  selector: {
3062
3094
  _tag: "IdSelector",
3063
- objectIds: filter.id
3095
+ objectIds: filter2.id
3064
3096
  }
3065
3097
  },
3066
3098
  ...this._generateDeletedHandlingSteps(context),
3067
3099
  {
3068
3100
  _tag: "FilterStep",
3069
3101
  filter: {
3070
- ...filter,
3102
+ ...filter2,
3071
3103
  id: void 0
3072
3104
  }
3073
3105
  }
3074
3106
  ]);
3075
- } else if (filter.typename) {
3107
+ } else if (filter2.typename) {
3076
3108
  return QueryPlan.Plan.make([
3077
3109
  {
3078
3110
  _tag: "SelectStep",
@@ -3080,7 +3112,7 @@ var QueryPlanner = class {
3080
3112
  selector: {
3081
3113
  _tag: "TypeSelector",
3082
3114
  typename: [
3083
- filter.typename
3115
+ filter2.typename
3084
3116
  ],
3085
3117
  inverted: false
3086
3118
  }
@@ -3089,7 +3121,7 @@ var QueryPlanner = class {
3089
3121
  {
3090
3122
  _tag: "FilterStep",
3091
3123
  filter: {
3092
- ...filter,
3124
+ ...filter2,
3093
3125
  typename: null
3094
3126
  }
3095
3127
  }
@@ -3107,12 +3139,32 @@ var QueryPlanner = class {
3107
3139
  {
3108
3140
  _tag: "FilterStep",
3109
3141
  filter: {
3110
- ...filter
3142
+ ...filter2
3111
3143
  }
3112
3144
  }
3113
3145
  ]);
3114
3146
  }
3115
3147
  }
3148
+ // Tag
3149
+ case "tag": {
3150
+ return QueryPlan.Plan.make([
3151
+ {
3152
+ _tag: "SelectStep",
3153
+ spaces: context.selectionSpaces,
3154
+ selector: {
3155
+ _tag: "WildcardSelector"
3156
+ }
3157
+ },
3158
+ ...this._generateDeletedHandlingSteps(context),
3159
+ {
3160
+ _tag: "FilterStep",
3161
+ filter: {
3162
+ ...filter2
3163
+ }
3164
+ }
3165
+ ]);
3166
+ }
3167
+ // Text
3116
3168
  case "text-search": {
3117
3169
  return QueryPlan.Plan.make([
3118
3170
  {
@@ -3120,55 +3172,61 @@ var QueryPlanner = class {
3120
3172
  spaces: context.selectionSpaces,
3121
3173
  selector: {
3122
3174
  _tag: "TextSelector",
3123
- text: filter.text,
3124
- searchKind: filter.searchKind ?? this._options.defaultTextSearchKind
3175
+ text: filter2.text,
3176
+ searchKind: filter2.searchKind ?? this._options.defaultTextSearchKind
3125
3177
  }
3126
3178
  },
3127
3179
  ...this._generateDeletedHandlingSteps(context)
3128
3180
  ]);
3129
3181
  }
3182
+ // Compare
3130
3183
  case "compare":
3131
- throw new QueryError("Query too complex", {
3184
+ throw new QueryError({
3185
+ message: "Query too complex",
3132
3186
  context: {
3133
3187
  query: context.originalQuery
3134
3188
  }
3135
3189
  });
3136
3190
  case "in":
3137
- throw new QueryError("Query too complex", {
3191
+ throw new QueryError({
3192
+ message: "Query too complex",
3138
3193
  context: {
3139
3194
  query: context.originalQuery
3140
3195
  }
3141
3196
  });
3142
3197
  case "range":
3143
- throw new QueryError("Query too complex", {
3198
+ throw new QueryError({
3199
+ message: "Query too complex",
3144
3200
  context: {
3145
3201
  query: context.originalQuery
3146
3202
  }
3147
3203
  });
3204
+ // Boolean
3148
3205
  case "not":
3149
- return this._generateSelectionFromFilter(filter.filter, {
3206
+ return this._generateSelectionFromFilter(filter2.filter, {
3150
3207
  ...context,
3151
3208
  selectionInverted: !context.selectionInverted
3152
3209
  });
3153
3210
  case "and":
3154
- throw new QueryError("Query too complex", {
3211
+ throw new QueryError({
3212
+ message: "Query too complex",
3155
3213
  context: {
3156
3214
  query: context.originalQuery
3157
3215
  }
3158
3216
  });
3159
3217
  case "or":
3160
- if (filter.filters.every(isTrivialTypenameFilter)) {
3161
- const typenames = filter.filters.map((f) => {
3162
- invariant9(f.type === "object" && f.typename !== null, void 0, {
3218
+ if (filter2.filters.every(isTrivialTypenameFilter)) {
3219
+ const typenames = filter2.filters.map((filter3) => {
3220
+ invariant9(filter3.type === "object" && filter3.typename !== null, void 0, {
3163
3221
  F: __dxlog_file10,
3164
- L: 195,
3222
+ L: 224,
3165
3223
  S: this,
3166
3224
  A: [
3167
- "f.type === 'object' && f.typename !== null",
3225
+ "filter.type === 'object' && filter.typename !== null",
3168
3226
  ""
3169
3227
  ]
3170
3228
  });
3171
- return f.typename;
3229
+ return filter3.typename;
3172
3230
  });
3173
3231
  return QueryPlan.Plan.make([
3174
3232
  {
@@ -3183,14 +3241,16 @@ var QueryPlanner = class {
3183
3241
  ...this._generateDeletedHandlingSteps(context)
3184
3242
  ]);
3185
3243
  } else {
3186
- throw new QueryError("Query too complex", {
3244
+ throw new QueryError({
3245
+ message: "Query too complex",
3187
3246
  context: {
3188
3247
  query: context.originalQuery
3189
3248
  }
3190
3249
  });
3191
3250
  }
3192
3251
  default:
3193
- throw new QueryError(`Unsupported filter type: ${filter.type}`, {
3252
+ throw new QueryError({
3253
+ message: `Unsupported filter type: ${filter2.type}`,
3194
3254
  context: {
3195
3255
  query: context.originalQuery
3196
3256
  }
@@ -3456,8 +3516,8 @@ var createRelationTraversalStep = (direction) => ({
3456
3516
  direction
3457
3517
  }
3458
3518
  });
3459
- var isTrivialTypenameFilter = (filter) => {
3460
- 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);
3519
+ var isTrivialTypenameFilter = (filter2) => {
3520
+ 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);
3461
3521
  };
3462
3522
 
3463
3523
  // src/query/query-executor.ts
@@ -3475,7 +3535,7 @@ function _define_property12(obj, key, value) {
3475
3535
  return obj;
3476
3536
  }
3477
3537
  var __dxlog_file11 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/query/query-executor.ts";
3478
- var isNullable = Predicate.isNullable;
3538
+ var isNullable2 = Predicate.isNullable;
3479
3539
  var ExecutionTrace = Object.freeze({
3480
3540
  makeEmpty: () => ({
3481
3541
  name: "Empty",
@@ -3483,11 +3543,57 @@ var ExecutionTrace = Object.freeze({
3483
3543
  objectCount: 0,
3484
3544
  documentsLoaded: 0,
3485
3545
  indexHits: 0,
3546
+ beginTs: 0,
3547
+ endTs: 0,
3486
3548
  indexQueryTime: 0,
3487
3549
  documentLoadTime: 0,
3488
3550
  executionTime: 0,
3489
3551
  children: []
3490
3552
  }),
3553
+ markEnd: (trace6) => {
3554
+ trace6.endTs = performance.now();
3555
+ trace6.executionTime = trace6.endTs - trace6.beginTs;
3556
+ },
3557
+ putOnPerformanceTimeline: (trace6) => {
3558
+ performance.measure(trace6.name, {
3559
+ start: trace6.beginTs,
3560
+ end: trace6.endTs,
3561
+ detail: {
3562
+ devtools: {
3563
+ dataType: "track-entry",
3564
+ track: "Query Execution",
3565
+ trackGroup: "ECHO",
3566
+ color: "tertiary-dark",
3567
+ properties: [
3568
+ [
3569
+ "objectCount",
3570
+ trace6.objectCount
3571
+ ],
3572
+ [
3573
+ "documentsLoaded",
3574
+ trace6.documentsLoaded
3575
+ ],
3576
+ [
3577
+ "index hits",
3578
+ trace6.indexHits
3579
+ ],
3580
+ [
3581
+ "indexQueryTime",
3582
+ trace6.indexQueryTime
3583
+ ],
3584
+ [
3585
+ "documentLoadTime",
3586
+ trace6.documentLoadTime
3587
+ ]
3588
+ ],
3589
+ tooltipText: trace6.details
3590
+ }
3591
+ }
3592
+ });
3593
+ for (const child of trace6.children) {
3594
+ ExecutionTrace.putOnPerformanceTimeline(child);
3595
+ }
3596
+ },
3491
3597
  format: (trace6) => {
3492
3598
  const go = (trace7, indent) => {
3493
3599
  return [
@@ -3527,7 +3633,7 @@ var QueryExecutor = class extends Resource6 {
3527
3633
  async execQuery() {
3528
3634
  invariant10(this._lifecycleState === LifecycleState3.OPEN, void 0, {
3529
3635
  F: __dxlog_file11,
3530
- L: 176,
3636
+ L: 211,
3531
3637
  S: this,
3532
3638
  A: [
3533
3639
  "this._lifecycleState === LifecycleState.OPEN",
@@ -3562,7 +3668,7 @@ var QueryExecutor = class extends Resource6 {
3562
3668
  trace6.children.push(result.trace);
3563
3669
  }
3564
3670
  trace6.objectCount = workingSet.length;
3565
- trace6.executionTime = performance.now() - begin;
3671
+ ExecutionTrace.markEnd(trace6);
3566
3672
  return {
3567
3673
  workingSet,
3568
3674
  trace: trace6
@@ -3606,7 +3712,8 @@ var QueryExecutor = class extends Resource6 {
3606
3712
  default:
3607
3713
  throw new Error(`Unknown step type: ${step._tag}`);
3608
3714
  }
3609
- trace6.executionTime = performance.now() - begin;
3715
+ trace6.beginTs = begin;
3716
+ ExecutionTrace.markEnd(trace6);
3610
3717
  return {
3611
3718
  workingSet: newWorkingSet,
3612
3719
  trace: trace6
@@ -3619,7 +3726,8 @@ var QueryExecutor = class extends Resource6 {
3619
3726
  const trace6 = {
3620
3727
  ...ExecutionTrace.makeEmpty(),
3621
3728
  name: "Select",
3622
- details: JSON.stringify(step.selector)
3729
+ details: JSON.stringify(step.selector),
3730
+ beginTs: performance.now()
3623
3731
  };
3624
3732
  switch (step.selector._tag) {
3625
3733
  case "WildcardSelector": {
@@ -3640,7 +3748,7 @@ var QueryExecutor = class extends Resource6 {
3640
3748
  const results = await this._loadDocumentsAfterIndexQuery(indexHits);
3641
3749
  trace6.documentsLoaded += results.length;
3642
3750
  trace6.documentLoadTime += performance.now() - documentLoadStart;
3643
- workingSet.push(...results.filter(isNonNullable2).filter((item) => step.spaces.includes(item.spaceId)));
3751
+ workingSet.push(...results.filter(isNonNullable3).filter((item) => step.spaces.includes(item.spaceId)));
3644
3752
  trace6.objectCount = workingSet.length;
3645
3753
  break;
3646
3754
  }
@@ -3650,7 +3758,7 @@ var QueryExecutor = class extends Resource6 {
3650
3758
  sourceSpaceId: step.spaces[0]
3651
3759
  })));
3652
3760
  trace6.documentLoadTime += performance.now() - beginLoad;
3653
- workingSet.push(...items.filter(isNonNullable2));
3761
+ workingSet.push(...items.filter(isNonNullable3));
3654
3762
  trace6.objectCount = workingSet.length;
3655
3763
  break;
3656
3764
  }
@@ -3672,7 +3780,7 @@ var QueryExecutor = class extends Resource6 {
3672
3780
  const results = await this._loadDocumentsAfterIndexQuery(indexHits);
3673
3781
  trace6.documentsLoaded += results.length;
3674
3782
  trace6.documentLoadTime += performance.now() - documentLoadStart;
3675
- workingSet.push(...results.filter(isNonNullable2).filter((item) => step.spaces.includes(item.spaceId)));
3783
+ workingSet.push(...results.filter(isNonNullable3).filter((item) => step.spaces.includes(item.spaceId)));
3676
3784
  trace6.objectCount = workingSet.length;
3677
3785
  break;
3678
3786
  }
@@ -3697,7 +3805,7 @@ var QueryExecutor = class extends Resource6 {
3697
3805
  const results = await this._loadDocumentsAfterIndexQuery(indexHits);
3698
3806
  trace6.documentsLoaded += results.length;
3699
3807
  trace6.documentLoadTime += performance.now() - documentLoadStart;
3700
- workingSet.push(...results.filter(isNonNullable2).filter((item) => step.spaces.includes(item.spaceId)));
3808
+ workingSet.push(...results.filter(isNonNullable3).filter((item) => step.spaces.includes(item.spaceId)));
3701
3809
  trace6.objectCount = workingSet.length;
3702
3810
  break;
3703
3811
  }
@@ -3767,20 +3875,20 @@ var QueryExecutor = class extends Resource6 {
3767
3875
  ref: ref2["/"]
3768
3876
  }, {
3769
3877
  F: __dxlog_file11,
3770
- L: 432,
3878
+ L: 477,
3771
3879
  S: this,
3772
3880
  C: (f, a) => f(...a)
3773
3881
  });
3774
3882
  return null;
3775
3883
  }
3776
3884
  });
3777
- }).filter(isNonNullable2);
3885
+ }).filter(isNonNullable3);
3778
3886
  const beginLoad = performance.now();
3779
3887
  const items = await Promise.all(refs.map(({ ref, spaceId }) => this._loadFromDXN(ref, {
3780
3888
  sourceSpaceId: spaceId
3781
3889
  })));
3782
3890
  trace6.documentLoadTime += performance.now() - beginLoad;
3783
- newWorkingSet.push(...items.filter(isNonNullable2));
3891
+ newWorkingSet.push(...items.filter(isNonNullable3));
3784
3892
  trace6.objectCount = newWorkingSet.length;
3785
3893
  break;
3786
3894
  }
@@ -3799,7 +3907,7 @@ var QueryExecutor = class extends Resource6 {
3799
3907
  const results = await this._loadDocumentsAfterIndexQuery(indexHits);
3800
3908
  trace6.documentsLoaded += results.length;
3801
3909
  trace6.documentLoadTime += performance.now() - documentLoadStart;
3802
- newWorkingSet.push(...results.filter(isNonNullable2));
3910
+ newWorkingSet.push(...results.filter(isNonNullable3));
3803
3911
  trace6.objectCount = newWorkingSet.length;
3804
3912
  break;
3805
3913
  }
@@ -3825,19 +3933,19 @@ var QueryExecutor = class extends Resource6 {
3825
3933
  ref: ref["/"]
3826
3934
  }, {
3827
3935
  F: __dxlog_file11,
3828
- L: 495,
3936
+ L: 540,
3829
3937
  S: this,
3830
3938
  C: (f, a) => f(...a)
3831
3939
  });
3832
3940
  return null;
3833
3941
  }
3834
- }).filter(isNonNullable2);
3942
+ }).filter(isNonNullable3);
3835
3943
  const beginLoad = performance.now();
3836
3944
  const items = await Promise.all(refs.map(({ ref, spaceId }) => this._loadFromDXN(ref, {
3837
3945
  sourceSpaceId: spaceId
3838
3946
  })));
3839
3947
  trace6.documentLoadTime += performance.now() - beginLoad;
3840
- newWorkingSet.push(...items.filter(isNonNullable2));
3948
+ newWorkingSet.push(...items.filter(isNonNullable3));
3841
3949
  trace6.objectCount = newWorkingSet.length;
3842
3950
  break;
3843
3951
  }
@@ -3857,7 +3965,7 @@ var QueryExecutor = class extends Resource6 {
3857
3965
  const results = await this._loadDocumentsAfterIndexQuery(indexHits);
3858
3966
  trace6.documentsLoaded += results.length;
3859
3967
  trace6.documentLoadTime += performance.now() - documentLoadStart;
3860
- newWorkingSet.push(...results.filter(isNonNullable2));
3968
+ newWorkingSet.push(...results.filter(isNonNullable3));
3861
3969
  trace6.objectCount = newWorkingSet.length;
3862
3970
  break;
3863
3971
  }
@@ -3950,14 +4058,14 @@ var QueryExecutor = class extends Resource6 {
3950
4058
  return Match.type().pipe(
3951
4059
  Match.withReturnType(),
3952
4060
  Match.when({
3953
- a: isNullable,
3954
- b: isNullable
4061
+ a: isNullable2,
4062
+ b: isNullable2
3955
4063
  }, () => 0),
3956
4064
  Match.when({
3957
- a: isNullable
4065
+ a: isNullable2
3958
4066
  }, () => 1),
3959
4067
  Match.when({
3960
- b: isNullable
4068
+ b: isNullable2
3961
4069
  }, () => -1),
3962
4070
  Match.when({
3963
4071
  a: Match.string,
@@ -3991,7 +4099,7 @@ var QueryExecutor = class extends Resource6 {
3991
4099
  const { objectId, documentId, spaceKey: spaceKeyInIndex } = objectPointerCodec3.decode(hit.id);
3992
4100
  const handle = await this._automergeHost.loadDoc(Context3.default(void 0, {
3993
4101
  F: __dxlog_file11,
3994
- L: 659
4102
+ L: 704
3995
4103
  }), documentId);
3996
4104
  const doc = handle.doc();
3997
4105
  if (!doc) {
@@ -4019,7 +4127,7 @@ var QueryExecutor = class extends Resource6 {
4019
4127
  dxn
4020
4128
  }, {
4021
4129
  F: __dxlog_file11,
4022
- L: 686,
4130
+ L: 731,
4023
4131
  S: this,
4024
4132
  C: (f, a) => f(...a)
4025
4133
  });
@@ -4032,7 +4140,7 @@ var QueryExecutor = class extends Resource6 {
4032
4140
  spaceId
4033
4141
  }, {
4034
4142
  F: __dxlog_file11,
4035
- L: 694,
4143
+ L: 739,
4036
4144
  S: this,
4037
4145
  C: (f, a) => f(...a)
4038
4146
  });
@@ -4044,7 +4152,7 @@ var QueryExecutor = class extends Resource6 {
4044
4152
  spaceId
4045
4153
  }, {
4046
4154
  F: __dxlog_file11,
4047
- L: 699,
4155
+ L: 744,
4048
4156
  S: this,
4049
4157
  C: (f, a) => f(...a)
4050
4158
  });
@@ -4065,7 +4173,7 @@ var QueryExecutor = class extends Resource6 {
4065
4173
  }
4066
4174
  const handle = await this._automergeHost.loadDoc(Context3.default(void 0, {
4067
4175
  F: __dxlog_file11,
4068
- L: 718
4176
+ L: 763
4069
4177
  }), link);
4070
4178
  const doc = handle.doc();
4071
4179
  if (!doc) {
@@ -4365,17 +4473,17 @@ import { DatabaseDirectory as DatabaseDirectory5, SpaceDocVersion as SpaceDocVer
4365
4473
  import { invariant as invariant11 } from "@dxos/invariant";
4366
4474
 
4367
4475
  // src/db-host/automerge-metrics.ts
4368
- import * as A4 from "@automerge/automerge";
4476
+ import * as A5 from "@automerge/automerge";
4369
4477
  import { log as log11 } from "@dxos/log";
4370
4478
  var __dxlog_file13 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/automerge-metrics.ts";
4371
4479
  var measureDocMetrics = (doc) => {
4372
- const snapshot = A4.save(doc);
4480
+ const snapshot = A5.save(doc);
4373
4481
  const start = Date.now();
4374
- const temp = A4.load(snapshot);
4482
+ const temp = A5.load(snapshot);
4375
4483
  const end = Date.now();
4376
- A4.free(temp);
4484
+ A5.free(temp);
4377
4485
  const getAllChangesStart = Date.now();
4378
- const mutationCount = A4.getAllChanges(doc).length;
4486
+ const mutationCount = A5.getAllChanges(doc).length;
4379
4487
  const getAllChangesEnd = Date.now();
4380
4488
  if (getAllChangesEnd - getAllChangesStart > 300) {
4381
4489
  log11.warn("getAllChanges took too long", {
@@ -4658,7 +4766,7 @@ var EchoHost = class extends Resource9 {
4658
4766
  * Flush all pending writes to the underlying storage.
4659
4767
  */
4660
4768
  async flush() {
4661
- await this._automergeHost.repo.flush();
4769
+ await this._automergeHost.flush();
4662
4770
  }
4663
4771
  /**
4664
4772
  * Perform any pending index updates.
@@ -4843,6 +4951,7 @@ var EchoHost = class extends Resource9 {
4843
4951
  };
4844
4952
 
4845
4953
  // src/edge/echo-edge-replicator.ts
4954
+ import * as Automerge from "@automerge/automerge";
4846
4955
  import { cbor as cbor2 } from "@automerge/automerge-repo";
4847
4956
  import { Mutex, scheduleMicroTask as scheduleMicroTask2, scheduleTask as scheduleTask2 } from "@dxos/async";
4848
4957
  import { Context as Context6, Resource as Resource11 } from "@dxos/context";
@@ -4852,7 +4961,7 @@ import { log as log13 } from "@dxos/log";
4852
4961
  import { DocumentCodec, EdgeService } from "@dxos/protocols";
4853
4962
  import { buf } from "@dxos/protocols/buf";
4854
4963
  import { MessageSchema as RouterMessageSchema } from "@dxos/protocols/buf/dxos/edge/messenger_pb";
4855
- import { bufferToArray as bufferToArray2 } from "@dxos/util";
4964
+ import { bufferToArray as bufferToArray2, setDeep } from "@dxos/util";
4856
4965
 
4857
4966
  // src/edge/inflight-request-limiter.ts
4858
4967
  import { Trigger as Trigger2 } from "@dxos/async";
@@ -5015,14 +5124,14 @@ var EchoEdgeReplicator = class {
5015
5124
  connectedSpaces: this._connectedSpaces.size
5016
5125
  }, {
5017
5126
  F: __dxlog_file18,
5018
- L: 72,
5127
+ L: 73,
5019
5128
  S: this,
5020
5129
  C: (f, a) => f(...a)
5021
5130
  });
5022
5131
  this._context = context;
5023
5132
  this._ctx = Context6.default(void 0, {
5024
5133
  F: __dxlog_file18,
5025
- L: 74
5134
+ L: 75
5026
5135
  });
5027
5136
  this._ctx.onDispose(this._edgeConnection.onReconnected(() => {
5028
5137
  this._ctx && scheduleMicroTask2(this._ctx, () => this._handleReconnect());
@@ -5121,7 +5230,7 @@ var EchoEdgeReplicator = class {
5121
5230
  async _openConnection(spaceId, reconnects = 0) {
5122
5231
  invariant14(this._context, void 0, {
5123
5232
  F: __dxlog_file18,
5124
- L: 135,
5233
+ L: 136,
5125
5234
  S: this,
5126
5235
  A: [
5127
5236
  "this._context",
@@ -5130,7 +5239,7 @@ var EchoEdgeReplicator = class {
5130
5239
  });
5131
5240
  invariant14(!this._connections.has(spaceId), void 0, {
5132
5241
  F: __dxlog_file18,
5133
- L: 136,
5242
+ L: 137,
5134
5243
  S: this,
5135
5244
  A: [
5136
5245
  "!this._connections.has(spaceId)",
@@ -5149,7 +5258,7 @@ var EchoEdgeReplicator = class {
5149
5258
  spaceId
5150
5259
  }, {
5151
5260
  F: __dxlog_file18,
5152
- L: 147,
5261
+ L: 148,
5153
5262
  S: this,
5154
5263
  C: (f, a) => f(...a)
5155
5264
  });
@@ -5160,7 +5269,7 @@ var EchoEdgeReplicator = class {
5160
5269
  spaceId
5161
5270
  }, {
5162
5271
  F: __dxlog_file18,
5163
- L: 151,
5272
+ L: 152,
5164
5273
  S: this,
5165
5274
  C: (f, a) => f(...a)
5166
5275
  });
@@ -5177,7 +5286,7 @@ var EchoEdgeReplicator = class {
5177
5286
  restartDelay
5178
5287
  }, {
5179
5288
  F: __dxlog_file18,
5180
- L: 162,
5289
+ L: 163,
5181
5290
  S: this,
5182
5291
  C: (f, a) => f(...a)
5183
5292
  });
@@ -5205,7 +5314,7 @@ var EchoEdgeReplicator = class {
5205
5314
  restartDelay
5206
5315
  }, {
5207
5316
  F: __dxlog_file18,
5208
- L: 179,
5317
+ L: 180,
5209
5318
  S: this,
5210
5319
  C: (f, a) => f(...a)
5211
5320
  });
@@ -5242,7 +5351,7 @@ var EdgeReplicatorConnection = class extends Resource11 {
5242
5351
  async _open(ctx) {
5243
5352
  log13("opening...", void 0, {
5244
5353
  F: __dxlog_file18,
5245
- L: 270,
5354
+ L: 273,
5246
5355
  S: this,
5247
5356
  C: (f, a) => f(...a)
5248
5357
  });
@@ -5257,7 +5366,7 @@ var EdgeReplicatorConnection = class extends Resource11 {
5257
5366
  if (firstReconnect) {
5258
5367
  log13.verbose("first reconnect skipped", void 0, {
5259
5368
  F: __dxlog_file18,
5260
- L: 285,
5369
+ L: 288,
5261
5370
  S: this,
5262
5371
  C: (f, a) => f(...a)
5263
5372
  });
@@ -5272,7 +5381,7 @@ var EdgeReplicatorConnection = class extends Resource11 {
5272
5381
  async _close() {
5273
5382
  log13("closing...", void 0, {
5274
5383
  F: __dxlog_file18,
5275
- L: 298,
5384
+ L: 301,
5276
5385
  S: this,
5277
5386
  C: (f, a) => f(...a)
5278
5387
  });
@@ -5283,7 +5392,7 @@ var EdgeReplicatorConnection = class extends Resource11 {
5283
5392
  get peerId() {
5284
5393
  invariant14(this._remotePeerId, "Not connected", {
5285
5394
  F: __dxlog_file18,
5286
- L: 307,
5395
+ L: 310,
5287
5396
  S: this,
5288
5397
  A: [
5289
5398
  "this._remotePeerId",
@@ -5308,7 +5417,7 @@ var EdgeReplicatorConnection = class extends Resource11 {
5308
5417
  remoteId: this._remotePeerId
5309
5418
  }, {
5310
5419
  F: __dxlog_file18,
5311
- L: 322,
5420
+ L: 325,
5312
5421
  S: this,
5313
5422
  C: (f, a) => f(...a)
5314
5423
  });
@@ -5329,12 +5438,11 @@ var EdgeReplicatorConnection = class extends Resource11 {
5329
5438
  }
5330
5439
  const payload = cbor2.decode(message.payload.value);
5331
5440
  log13.verbose("received", {
5332
- type: payload.type,
5333
- documentId: payload.type === "sync" && payload.documentId,
5441
+ ...getMessageInfo(payload),
5334
5442
  remoteId: this._remotePeerId
5335
5443
  }, {
5336
5444
  F: __dxlog_file18,
5337
- L: 351,
5445
+ L: 354,
5338
5446
  S: this,
5339
5447
  C: (f, a) => f(...a)
5340
5448
  });
@@ -5365,7 +5473,7 @@ var EdgeReplicatorConnection = class extends Resource11 {
5365
5473
  ]));
5366
5474
  }
5367
5475
  _processMessage(message) {
5368
- if (isForbiddenErrorMessage(message)) {
5476
+ if (isErrorMessage(message)) {
5369
5477
  this._onRestartRequested();
5370
5478
  return;
5371
5479
  }
@@ -5374,13 +5482,20 @@ var EdgeReplicatorConnection = class extends Resource11 {
5374
5482
  }
5375
5483
  async _sendMessage(message) {
5376
5484
  message.targetId = this._targetServiceId;
5485
+ setDeep(message, [
5486
+ "metadata",
5487
+ "dxos_sequence"
5488
+ ], this._getSequence());
5489
+ setDeep(message, [
5490
+ "metadata",
5491
+ "dxos_connectionId"
5492
+ ], this._connectionId);
5377
5493
  log13.verbose("sending...", {
5378
- type: message.type,
5379
- documentId: message.type === "sync" && message.documentId,
5494
+ ...getMessageInfo(message),
5380
5495
  remoteId: this._remotePeerId
5381
5496
  }, {
5382
5497
  F: __dxlog_file18,
5383
- L: 401,
5498
+ L: 407,
5384
5499
  S: this,
5385
5500
  C: (f, a) => f(...a)
5386
5501
  });
@@ -5401,14 +5516,17 @@ var EdgeReplicatorConnection = class extends Resource11 {
5401
5516
  err
5402
5517
  }, {
5403
5518
  F: __dxlog_file18,
5404
- L: 421,
5519
+ L: 426,
5405
5520
  S: this,
5406
5521
  C: (f, a) => f(...a)
5407
5522
  });
5408
5523
  }
5409
5524
  }
5525
+ _getSequence() {
5526
+ return this._sequence++;
5527
+ }
5410
5528
  constructor({ edgeConnection, edgeHttpClient, spaceId, context, sharedPolicyEnabled, onRemoteConnected, onRemoteDisconnected, onRestartRequested }) {
5411
- 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({
5529
+ super(), _define_property18(this, "_connectionId", randomUUID()), _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, "_sequence", 0), _define_property18(this, "_requestLimiter", new InflightRequestLimiter({
5412
5530
  maxInflightRequests: MAX_INFLIGHT_REQUESTS,
5413
5531
  resetBalanceTimeoutMs: MAX_RATE_LIMIT_WAIT_TIME_MS
5414
5532
  })), _define_property18(this, "_readableStreamController", void 0), _define_property18(this, "readable", void 0), _define_property18(this, "writable", void 0);
@@ -5416,7 +5534,7 @@ var EdgeReplicatorConnection = class extends Resource11 {
5416
5534
  this._edgeHttpClient = edgeHttpClient;
5417
5535
  this._spaceId = spaceId;
5418
5536
  this._context = context;
5419
- this._remotePeerId = `${EdgeService.AUTOMERGE_REPLICATOR}:${spaceId}-${randomUUID()}`;
5537
+ this._remotePeerId = `${EdgeService.AUTOMERGE_REPLICATOR}:${spaceId}-${this._connectionId}`;
5420
5538
  this._targetServiceId = `${EdgeService.AUTOMERGE_REPLICATOR}:${spaceId}`;
5421
5539
  this._sharedPolicyEnabled = sharedPolicyEnabled;
5422
5540
  this._onRemoteConnected = onRemoteConnected;
@@ -5435,7 +5553,19 @@ var EdgeReplicatorConnection = class extends Resource11 {
5435
5553
  });
5436
5554
  }
5437
5555
  };
5438
- var isForbiddenErrorMessage = (message) => message.type === "error" && message.message === "Forbidden";
5556
+ var isErrorMessage = (message) => message.type === "error";
5557
+ var getMessageInfo = (msg) => {
5558
+ const { have, heads, need, changes } = msg.type === "sync" ? Automerge.decodeSyncMessage(msg.data) : {};
5559
+ return {
5560
+ type: msg.type,
5561
+ documentId: "documentId" in msg ? msg.documentId : void 0,
5562
+ have,
5563
+ heads,
5564
+ need,
5565
+ changes: changes?.length,
5566
+ sequence: msg.metadata?.dxos_sequence
5567
+ };
5568
+ };
5439
5569
 
5440
5570
  // src/util.ts
5441
5571
  import { ObjectStructure as ObjectStructure2, decodeReference } from "@dxos/echo-protocol";