@dxos/echo-pipeline 0.8.4-main.21d9917 → 0.8.4-main.2244d791bb

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 (80) hide show
  1. package/dist/lib/{browser → neutral}/index.mjs +802 -723
  2. package/dist/lib/neutral/index.mjs.map +7 -0
  3. package/dist/lib/neutral/meta.json +1 -0
  4. package/dist/lib/{browser → neutral}/testing/index.mjs +2 -2
  5. package/dist/lib/{browser → neutral}/testing/index.mjs.map +3 -3
  6. package/dist/types/src/automerge/automerge-host.d.ts +4 -7
  7. package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
  8. package/dist/types/src/automerge/echo-network-adapter.d.ts +4 -4
  9. package/dist/types/src/automerge/echo-network-adapter.d.ts.map +1 -1
  10. package/dist/types/src/automerge/echo-replicator.d.ts +8 -8
  11. package/dist/types/src/automerge/echo-replicator.d.ts.map +1 -1
  12. package/dist/types/src/automerge/heads-store.d.ts.map +1 -1
  13. package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts +2 -2
  14. package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts.map +1 -1
  15. package/dist/types/src/automerge/mesh-echo-replicator.d.ts +5 -5
  16. package/dist/types/src/automerge/mesh-echo-replicator.d.ts.map +1 -1
  17. package/dist/types/src/db-host/echo-host.d.ts +17 -23
  18. package/dist/types/src/db-host/echo-host.d.ts.map +1 -1
  19. package/dist/types/src/db-host/local-queue-service.d.ts +4 -2
  20. package/dist/types/src/db-host/local-queue-service.d.ts.map +1 -1
  21. package/dist/types/src/db-host/query-service.d.ts +8 -8
  22. package/dist/types/src/db-host/query-service.d.ts.map +1 -1
  23. package/dist/types/src/db-host/queue-data-source.d.ts.map +1 -1
  24. package/dist/types/src/db-host/stub.d.ts +2 -1
  25. package/dist/types/src/db-host/stub.d.ts.map +1 -1
  26. package/dist/types/src/edge/echo-edge-replicator.d.ts +3 -3
  27. package/dist/types/src/edge/echo-edge-replicator.d.ts.map +1 -1
  28. package/dist/types/src/query/plan.d.ts +13 -2
  29. package/dist/types/src/query/plan.d.ts.map +1 -1
  30. package/dist/types/src/query/query-executor.d.ts +34 -15
  31. package/dist/types/src/query/query-executor.d.ts.map +1 -1
  32. package/dist/types/src/query/query-planner.d.ts +1 -0
  33. package/dist/types/src/query/query-planner.d.ts.map +1 -1
  34. package/dist/types/src/testing/test-replicator.d.ts +8 -8
  35. package/dist/types/src/testing/test-replicator.d.ts.map +1 -1
  36. package/dist/types/tsconfig.tsbuildinfo +1 -1
  37. package/package.json +43 -47
  38. package/src/automerge/automerge-host.test.ts +0 -2
  39. package/src/automerge/automerge-host.ts +4 -24
  40. package/src/automerge/echo-network-adapter.ts +11 -11
  41. package/src/automerge/echo-replicator.ts +8 -8
  42. package/src/automerge/heads-store.ts +28 -1
  43. package/src/automerge/mesh-echo-replicator-connection.ts +2 -2
  44. package/src/automerge/mesh-echo-replicator.ts +12 -9
  45. package/src/db-host/automerge-data-source.test.ts +0 -2
  46. package/src/db-host/documents-synchronizer.test.ts +0 -4
  47. package/src/db-host/echo-host.ts +53 -98
  48. package/src/db-host/local-queue-service.ts +44 -46
  49. package/src/db-host/query-service.ts +18 -106
  50. package/src/db-host/queue-data-source.ts +9 -9
  51. package/src/db-host/queue-service.test.ts +15 -11
  52. package/src/db-host/stub.ts +5 -0
  53. package/src/edge/echo-edge-replicator.test.ts +4 -4
  54. package/src/edge/echo-edge-replicator.ts +9 -9
  55. package/src/query/plan.ts +16 -2
  56. package/src/query/query-executor.ts +534 -199
  57. package/src/query/query-planner.ts +19 -0
  58. package/src/testing/test-replicator.ts +11 -11
  59. package/dist/lib/browser/index.mjs.map +0 -7
  60. package/dist/lib/browser/meta.json +0 -1
  61. package/dist/lib/node-esm/chunk-7PL6UK4B.mjs +0 -2154
  62. package/dist/lib/node-esm/chunk-7PL6UK4B.mjs.map +0 -7
  63. package/dist/lib/node-esm/chunk-S5KGVQFZ.mjs +0 -235
  64. package/dist/lib/node-esm/chunk-S5KGVQFZ.mjs.map +0 -7
  65. package/dist/lib/node-esm/filter/index.mjs +0 -12
  66. package/dist/lib/node-esm/filter/index.mjs.map +0 -7
  67. package/dist/lib/node-esm/index.mjs +0 -6529
  68. package/dist/lib/node-esm/index.mjs.map +0 -7
  69. package/dist/lib/node-esm/meta.json +0 -1
  70. package/dist/lib/node-esm/testing/index.mjs +0 -591
  71. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
  72. package/dist/types/src/db-host/documents-iterator.d.ts +0 -7
  73. package/dist/types/src/db-host/documents-iterator.d.ts.map +0 -1
  74. package/src/db-host/documents-iterator.ts +0 -76
  75. /package/dist/lib/{browser → neutral}/chunk-FJPXA75J.mjs +0 -0
  76. /package/dist/lib/{browser → neutral}/chunk-FJPXA75J.mjs.map +0 -0
  77. /package/dist/lib/{browser → neutral}/chunk-WIQUYO7H.mjs +0 -0
  78. /package/dist/lib/{browser → neutral}/chunk-WIQUYO7H.mjs.map +0 -0
  79. /package/dist/lib/{browser → neutral}/filter/index.mjs +0 -0
  80. /package/dist/lib/{browser → neutral}/filter/index.mjs.map +0 -0
@@ -148,7 +148,7 @@ import { UpdateScheduler as UpdateScheduler2 } from "@dxos/async";
148
148
  import { Stream } from "@dxos/codec-protobuf/stream";
149
149
  import { invariant as invariant7 } from "@dxos/invariant";
150
150
  import { SpaceId as SpaceId2 } from "@dxos/keys";
151
- import { log as log8 } from "@dxos/log";
151
+ import { log as log9 } from "@dxos/log";
152
152
 
153
153
  // src/automerge/automerge-host.ts
154
154
  import { getBackend, getHeads, equals as headsEquals, isAutomerge, save } from "@automerge/automerge";
@@ -158,8 +158,7 @@ import { Context as Context2, Resource as Resource3, cancelWithContext } from "@
158
158
  import { DatabaseDirectory as DatabaseDirectory2 } from "@dxos/echo-protocol";
159
159
  import { invariant as invariant2 } from "@dxos/invariant";
160
160
  import { PublicKey as PublicKey2 } from "@dxos/keys";
161
- import { log as log4 } from "@dxos/log";
162
- import { objectPointerCodec } from "@dxos/protocols";
161
+ import { log as log5 } from "@dxos/log";
163
162
  import { trace as trace2 } from "@dxos/tracing";
164
163
  import { ComplexSet, bufferToArray, defaultMap as defaultMap2, isNonNullable as isNonNullable2, range } from "@dxos/util";
165
164
 
@@ -870,7 +869,35 @@ var createEchoPeerMetadata = () => ({
870
869
  var isEchoPeerMetadata = (metadata) => metadata?.dxos_peerSource === "EchoNetworkAdapter";
871
870
 
872
871
  // src/automerge/heads-store.ts
873
- import { headsEncoding } from "@dxos/indexing";
872
+ import { log as log4 } from "@dxos/log";
873
+ import { schema } from "@dxos/protocols/proto";
874
+ var __dxlog_file4 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/heads-store.ts";
875
+ var headsCodec2;
876
+ var getHeadsCodec = () => headsCodec2 ??= schema.getCodecForType("dxos.echo.query.Heads");
877
+ var headsEncoding = {
878
+ encode: (value) => getHeadsCodec().encode({
879
+ hashes: value
880
+ }),
881
+ decode: (encodedValue) => {
882
+ try {
883
+ return getHeadsCodec().decode(encodedValue).hashes;
884
+ } catch {
885
+ log4.warn("Detected legacy encoding of heads in storage.", void 0, {
886
+ F: __dxlog_file4,
887
+ L: 26,
888
+ S: void 0,
889
+ C: (f, a) => f(...a)
890
+ });
891
+ const concatenatedHeads = Buffer.from(encodedValue).toString("utf8").replace(/"/g, "");
892
+ const heads = [];
893
+ for (let i = 0; i < concatenatedHeads.length; i += 64) {
894
+ heads.push(concatenatedHeads.slice(i, i + 64));
895
+ }
896
+ return heads;
897
+ }
898
+ },
899
+ format: "buffer"
900
+ };
874
901
  var HeadsStore = class {
875
902
  _db;
876
903
  constructor({ db }) {
@@ -1019,7 +1046,7 @@ function _ts_decorate3(decorators, target, key, desc) {
1019
1046
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1020
1047
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1021
1048
  }
1022
- var __dxlog_file4 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
1049
+ var __dxlog_file5 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
1023
1050
  var FIND_PARAMS = {
1024
1051
  allowableStates: [
1025
1052
  "ready",
@@ -1032,7 +1059,6 @@ var BUNDLE_SYNC_THRESHOLD = 50;
1032
1059
  var OPTIMIZED_SHARE_POLICY = true;
1033
1060
  var AutomergeHost = class extends Resource3 {
1034
1061
  _db;
1035
- _indexMetadataStore;
1036
1062
  _echoNetworkAdapter;
1037
1063
  _collectionSynchronizer = new CollectionSynchronizer({
1038
1064
  queryCollectionState: this._queryCollectionState.bind(this),
@@ -1074,7 +1100,7 @@ var AutomergeHost = class extends Resource3 {
1074
1100
  */
1075
1101
  _documentsRequested = /* @__PURE__ */ new Map();
1076
1102
  _sharePolicyChangedTask;
1077
- constructor({ db, indexMetadataStore, dataMonitor, peerIdProvider, getSpaceKeyByRootDocumentId }) {
1103
+ constructor({ db, dataMonitor, peerIdProvider, getSpaceKeyByRootDocumentId }) {
1078
1104
  super();
1079
1105
  this._db = db;
1080
1106
  this._storage = new LevelDBStorageAdapter({
@@ -1099,7 +1125,6 @@ var AutomergeHost = class extends Resource3 {
1099
1125
  this._headsStore = new HeadsStore({
1100
1126
  db: db.sublevel("heads")
1101
1127
  });
1102
- this._indexMetadataStore = indexMetadataStore;
1103
1128
  this._peerIdProvider = peerIdProvider;
1104
1129
  this._getSpaceKeyByRootDocumentId = getSpaceKeyByRootDocumentId;
1105
1130
  }
@@ -1146,13 +1171,13 @@ var AutomergeHost = class extends Resource3 {
1146
1171
  try {
1147
1172
  await this._handleCollectionSync(collectionId, peerId);
1148
1173
  } catch (err) {
1149
- log4.error("failed to sync collection", {
1174
+ log5.error("failed to sync collection", {
1150
1175
  collectionId,
1151
1176
  peerId,
1152
1177
  err
1153
1178
  }, {
1154
- F: __dxlog_file4,
1155
- L: 263,
1179
+ F: __dxlog_file5,
1180
+ L: 252,
1156
1181
  S: this,
1157
1182
  C: (f, a) => f(...a)
1158
1183
  });
@@ -1160,9 +1185,9 @@ var AutomergeHost = class extends Resource3 {
1160
1185
  }));
1161
1186
  });
1162
1187
  this._sharePolicyChangedTask = new DeferredTask(this._ctx, async () => {
1163
- log4("share policy changed", void 0, {
1164
- F: __dxlog_file4,
1165
- L: 270,
1188
+ log5("share policy changed", void 0, {
1189
+ F: __dxlog_file5,
1190
+ L: 259,
1166
1191
  S: this,
1167
1192
  C: (f, a) => f(...a)
1168
1193
  });
@@ -1192,8 +1217,8 @@ var AutomergeHost = class extends Resource3 {
1192
1217
  }
1193
1218
  async addReplicator(replicator) {
1194
1219
  invariant2(this.isOpen, "AutomergeHost is not open", {
1195
- F: __dxlog_file4,
1196
- L: 302,
1220
+ F: __dxlog_file5,
1221
+ L: 291,
1197
1222
  S: this,
1198
1223
  A: [
1199
1224
  "this.isOpen",
@@ -1204,8 +1229,8 @@ var AutomergeHost = class extends Resource3 {
1204
1229
  }
1205
1230
  async removeReplicator(replicator) {
1206
1231
  invariant2(this.isOpen, "AutomergeHost is not open", {
1207
- F: __dxlog_file4,
1208
- L: 307,
1232
+ F: __dxlog_file5,
1233
+ L: 296,
1209
1234
  S: this,
1210
1235
  A: [
1211
1236
  "this.isOpen",
@@ -1219,8 +1244,8 @@ var AutomergeHost = class extends Resource3 {
1219
1244
  */
1220
1245
  async loadDoc(ctx, documentId, opts) {
1221
1246
  invariant2(this.isOpen, "AutomergeHost is not open", {
1222
- F: __dxlog_file4,
1223
- L: 315,
1247
+ F: __dxlog_file5,
1248
+ L: 304,
1224
1249
  S: this,
1225
1250
  A: [
1226
1251
  "this.isOpen",
@@ -1248,12 +1273,12 @@ var AutomergeHost = class extends Resource3 {
1248
1273
  this._sharePolicyChangedTask.schedule();
1249
1274
  }
1250
1275
  } catch (err) {
1251
- log4.error("failed to load document", {
1276
+ log5.error("failed to load document", {
1252
1277
  documentId,
1253
1278
  err
1254
1279
  }, {
1255
- F: __dxlog_file4,
1256
- L: 334,
1280
+ F: __dxlog_file5,
1281
+ L: 323,
1257
1282
  S: this,
1258
1283
  C: (f, a) => f(...a)
1259
1284
  });
@@ -1272,8 +1297,8 @@ var AutomergeHost = class extends Resource3 {
1272
1297
  }
1273
1298
  async exportDoc(ctx, id) {
1274
1299
  invariant2(this.isOpen, "AutomergeHost is not open", {
1275
- F: __dxlog_file4,
1276
- L: 353,
1300
+ F: __dxlog_file5,
1301
+ L: 342,
1277
1302
  S: this,
1278
1303
  A: [
1279
1304
  "this.isOpen",
@@ -1291,8 +1316,8 @@ var AutomergeHost = class extends Resource3 {
1291
1316
  */
1292
1317
  async createDoc(initialValue, opts) {
1293
1318
  invariant2(this.isOpen, "AutomergeHost is not open", {
1294
- F: __dxlog_file4,
1295
- L: 364,
1319
+ F: __dxlog_file5,
1320
+ L: 353,
1296
1321
  S: this,
1297
1322
  A: [
1298
1323
  "this.isOpen",
@@ -1329,8 +1354,8 @@ var AutomergeHost = class extends Resource3 {
1329
1354
  }
1330
1355
  async waitUntilHeadsReplicated(heads) {
1331
1356
  invariant2(this.isOpen, "AutomergeHost is not open", {
1332
- F: __dxlog_file4,
1333
- L: 395,
1357
+ F: __dxlog_file5,
1358
+ L: 384,
1334
1359
  S: this,
1335
1360
  A: [
1336
1361
  "this.isOpen",
@@ -1354,8 +1379,8 @@ var AutomergeHost = class extends Resource3 {
1354
1379
  if (headsToWait.length > 0) {
1355
1380
  await Promise.all(headsToWait.map(async (entry) => {
1356
1381
  const handle = await this.loadDoc(Context2.default(void 0, {
1357
- F: __dxlog_file4,
1358
- L: 413
1382
+ F: __dxlog_file5,
1383
+ L: 402
1359
1384
  }), entry.documentId);
1360
1385
  await waitForHeads(handle, entry.heads);
1361
1386
  }));
@@ -1364,8 +1389,8 @@ var AutomergeHost = class extends Resource3 {
1364
1389
  }
1365
1390
  async reIndexHeads(documentIds) {
1366
1391
  invariant2(this.isOpen, "AutomergeHost is not open", {
1367
- F: __dxlog_file4,
1368
- L: 426,
1392
+ F: __dxlog_file5,
1393
+ L: 415,
1369
1394
  S: this,
1370
1395
  A: [
1371
1396
  "this.isOpen",
@@ -1373,21 +1398,21 @@ var AutomergeHost = class extends Resource3 {
1373
1398
  ]
1374
1399
  });
1375
1400
  for (const documentId of documentIds) {
1376
- log4("re-indexing heads for document", {
1401
+ log5("re-indexing heads for document", {
1377
1402
  documentId
1378
1403
  }, {
1379
- F: __dxlog_file4,
1380
- L: 428,
1404
+ F: __dxlog_file5,
1405
+ L: 417,
1381
1406
  S: this,
1382
1407
  C: (f, a) => f(...a)
1383
1408
  });
1384
1409
  const handle = await this._repo.find(documentId, FIND_PARAMS);
1385
1410
  if (!handle.isReady()) {
1386
- log4.warn("document is not available locally, skipping", {
1411
+ log5.warn("document is not available locally, skipping", {
1387
1412
  documentId
1388
1413
  }, {
1389
- F: __dxlog_file4,
1390
- L: 431,
1414
+ F: __dxlog_file5,
1415
+ L: 420,
1391
1416
  S: this,
1392
1417
  C: (f, a) => f(...a)
1393
1418
  });
@@ -1398,9 +1423,9 @@ var AutomergeHost = class extends Resource3 {
1398
1423
  this._headsStore.setHeads(documentId, heads, batch);
1399
1424
  await batch.write();
1400
1425
  }
1401
- log4("done re-indexing heads", void 0, {
1402
- F: __dxlog_file4,
1403
- L: 440,
1426
+ log5("done re-indexing heads", void 0, {
1427
+ F: __dxlog_file5,
1428
+ L: 429,
1404
1429
  S: this,
1405
1430
  C: (f, a) => f(...a)
1406
1431
  });
@@ -1443,18 +1468,6 @@ var AutomergeHost = class extends Resource3 {
1443
1468
  }
1444
1469
  const heads = getHeads(doc);
1445
1470
  this._headsStore.setHeads(handle.documentId, heads, batch);
1446
- const spaceKey = DatabaseDirectory2.getSpaceKey(doc) ?? void 0;
1447
- const objectIds = Object.keys(doc.objects ?? {});
1448
- const encodedIds = objectIds.map((objectId) => objectPointerCodec.encode({
1449
- documentId: handle.documentId,
1450
- objectId,
1451
- spaceKey
1452
- }));
1453
- const idToLastHash = new Map(encodedIds.map((id) => [
1454
- id,
1455
- heads
1456
- ]));
1457
- this._indexMetadataStore.markDirty(idToLastHash, batch);
1458
1471
  }
1459
1472
  _shouldSyncCollection(collectionId, peerId) {
1460
1473
  const peerMetadata = this._repo.peerMetadataByPeerId[peerId];
@@ -1472,7 +1485,6 @@ var AutomergeHost = class extends Resource3 {
1472
1485
  if (!this.isOpen) {
1473
1486
  return void 0;
1474
1487
  }
1475
- this._indexMetadataStore.notifyMarkedDirty();
1476
1488
  const documentId = path[0];
1477
1489
  const handle = this._repo.handles[documentId];
1478
1490
  if (!handle || !handle.isReady()) {
@@ -1485,8 +1497,8 @@ var AutomergeHost = class extends Resource3 {
1485
1497
  const heads = getHeads(document);
1486
1498
  this._headsUpdates.set(documentId, heads);
1487
1499
  invariant2(this._onHeadsChangedTask, "onHeadsChangedTask is not initialized", {
1488
- F: __dxlog_file4,
1489
- L: 530,
1500
+ F: __dxlog_file5,
1501
+ L: 510,
1490
1502
  S: this,
1491
1503
  A: [
1492
1504
  "this._onHeadsChangedTask",
@@ -1672,48 +1684,48 @@ var AutomergeHost = class extends Resource3 {
1672
1684
  ];
1673
1685
  const bundleSyncEnabled = this._echoNetworkAdapter.bundleSyncEnabledForPeer(peerId);
1674
1686
  if (bundleSyncEnabled && missingOnRemote.length >= BUNDLE_SYNC_THRESHOLD) {
1675
- log4("pushing bundle", {
1687
+ log5("pushing bundle", {
1676
1688
  amount: missingOnRemote.length
1677
1689
  }, {
1678
- F: __dxlog_file4,
1679
- L: 742,
1690
+ F: __dxlog_file5,
1691
+ L: 722,
1680
1692
  S: this,
1681
1693
  C: (f, a) => f(...a)
1682
1694
  });
1683
1695
  const { syncInteractively } = await this._pushInBundles(peerId, missingOnRemote);
1684
1696
  toReplicateWithoutBatching.push(...syncInteractively);
1685
1697
  } else {
1686
- log4.verbose("failed to push bundle, replicating interactively", {
1698
+ log5.verbose("failed to push bundle, replicating interactively", {
1687
1699
  collectionId,
1688
1700
  peerId,
1689
1701
  amount: missingOnRemote.length
1690
1702
  }, {
1691
- F: __dxlog_file4,
1692
- L: 746,
1703
+ F: __dxlog_file5,
1704
+ L: 726,
1693
1705
  S: this,
1694
1706
  C: (f, a) => f(...a)
1695
1707
  });
1696
1708
  toReplicateWithoutBatching.push(...missingOnRemote);
1697
1709
  }
1698
1710
  if (bundleSyncEnabled && missingOnLocal.length >= BUNDLE_SYNC_THRESHOLD) {
1699
- log4("pulling bundle", {
1711
+ log5("pulling bundle", {
1700
1712
  amount: missingOnLocal.length
1701
1713
  }, {
1702
- F: __dxlog_file4,
1703
- L: 754,
1714
+ F: __dxlog_file5,
1715
+ L: 734,
1704
1716
  S: this,
1705
1717
  C: (f, a) => f(...a)
1706
1718
  });
1707
1719
  const { syncInteractively } = await this._pullInBundles(peerId, missingOnLocal);
1708
1720
  toReplicateWithoutBatching.push(...syncInteractively);
1709
1721
  } else {
1710
- log4.verbose("failed to pull bundle, replicating interactively", {
1722
+ log5.verbose("failed to pull bundle, replicating interactively", {
1711
1723
  collectionId,
1712
1724
  peerId,
1713
1725
  amount: missingOnLocal.length
1714
1726
  }, {
1715
- F: __dxlog_file4,
1716
- L: 758,
1727
+ F: __dxlog_file5,
1728
+ L: 738,
1717
1729
  S: this,
1718
1730
  C: (f, a) => f(...a)
1719
1731
  });
@@ -1722,14 +1734,14 @@ var AutomergeHost = class extends Resource3 {
1722
1734
  if (toReplicateWithoutBatching.length === 0) {
1723
1735
  return;
1724
1736
  }
1725
- log4("replicating documents after collection sync", {
1737
+ log5("replicating documents after collection sync", {
1726
1738
  collectionId,
1727
1739
  peerId,
1728
1740
  toReplicateWithoutBatching,
1729
1741
  count: toReplicateWithoutBatching.length
1730
1742
  }, {
1731
- F: __dxlog_file4,
1732
- L: 770,
1743
+ F: __dxlog_file5,
1744
+ L: 750,
1733
1745
  S: this,
1734
1746
  C: (f, a) => f(...a)
1735
1747
  });
@@ -1752,13 +1764,13 @@ var AutomergeHost = class extends Resource3 {
1752
1764
  return;
1753
1765
  }
1754
1766
  await this._pushBundle(peerId, bundle).catch((err) => {
1755
- log4.warn("failed to push bundle, replicating interactively", {
1767
+ log5.warn("failed to push bundle, replicating interactively", {
1756
1768
  peerId,
1757
1769
  bundle,
1758
1770
  err
1759
1771
  }, {
1760
- F: __dxlog_file4,
1761
- L: 803,
1772
+ F: __dxlog_file5,
1773
+ L: 783,
1762
1774
  S: this,
1763
1775
  C: (f, a) => f(...a)
1764
1776
  });
@@ -1777,11 +1789,11 @@ var AutomergeHost = class extends Resource3 {
1777
1789
  const docs = documentIds.map((documentId) => {
1778
1790
  const handle = this._repo.handles[documentId];
1779
1791
  if (!handle || !handle.isReady()) {
1780
- log4.warn("document not ready, skipping", {
1792
+ log5.warn("document not ready, skipping", {
1781
1793
  documentId
1782
1794
  }, {
1783
- F: __dxlog_file4,
1784
- L: 821,
1795
+ F: __dxlog_file5,
1796
+ L: 801,
1785
1797
  S: this,
1786
1798
  C: (f, a) => f(...a)
1787
1799
  });
@@ -1789,11 +1801,11 @@ var AutomergeHost = class extends Resource3 {
1789
1801
  }
1790
1802
  const doc = handle.doc();
1791
1803
  if (!doc) {
1792
- log4.warn("document not available, skipping", {
1804
+ log5.warn("document not available, skipping", {
1793
1805
  documentId
1794
1806
  }, {
1795
- F: __dxlog_file4,
1796
- L: 826,
1807
+ F: __dxlog_file5,
1808
+ L: 806,
1797
1809
  S: this,
1798
1810
  C: (f, a) => f(...a)
1799
1811
  });
@@ -1820,13 +1832,13 @@ var AutomergeHost = class extends Resource3 {
1820
1832
  return;
1821
1833
  }
1822
1834
  const result = await this._pullBundle(peerId, bundle).catch((err) => {
1823
- log4.warn("failed to pull bundle, replicating interactively", {
1835
+ log5.warn("failed to pull bundle, replicating interactively", {
1824
1836
  peerId,
1825
1837
  bundle,
1826
1838
  err
1827
1839
  }, {
1828
- F: __dxlog_file4,
1829
- L: 856,
1840
+ F: __dxlog_file5,
1841
+ L: 836,
1830
1842
  S: this,
1831
1843
  C: (f, a) => f(...a)
1832
1844
  });
@@ -1921,8 +1933,8 @@ var changeIsPresentInDoc = (doc, changeHash) => {
1921
1933
  };
1922
1934
  var decodeCollectionState = (state) => {
1923
1935
  invariant2(typeof state === "object" && state !== null, "Invalid state", {
1924
- F: __dxlog_file4,
1925
- L: 939,
1936
+ F: __dxlog_file5,
1937
+ L: 919,
1926
1938
  S: void 0,
1927
1939
  A: [
1928
1940
  "typeof state === 'object' && state !== null",
@@ -1938,7 +1950,7 @@ var encodeCollectionState = (state) => {
1938
1950
  // src/automerge/mesh-echo-replicator.ts
1939
1951
  import { invariant as invariant5 } from "@dxos/invariant";
1940
1952
  import { PublicKey as PublicKey3 } from "@dxos/keys";
1941
- import { log as log6 } from "@dxos/log";
1953
+ import { log as log7 } from "@dxos/log";
1942
1954
  import { ComplexSet as ComplexSet2, defaultMap as defaultMap3 } from "@dxos/util";
1943
1955
 
1944
1956
  // src/automerge/mesh-echo-replicator-connection.ts
@@ -1946,9 +1958,9 @@ import * as A2 from "@automerge/automerge";
1946
1958
  import { cbor } from "@automerge/automerge-repo";
1947
1959
  import { Resource as Resource4 } from "@dxos/context";
1948
1960
  import { invariant as invariant3 } from "@dxos/invariant";
1949
- import { log as log5 } from "@dxos/log";
1961
+ import { log as log6 } from "@dxos/log";
1950
1962
  import { AutomergeReplicator } from "@dxos/teleport-extension-automerge-replicator";
1951
- var __dxlog_file5 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator-connection.ts";
1963
+ var __dxlog_file6 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator-connection.ts";
1952
1964
  var DEFAULT_FACTORY = (params) => new AutomergeReplicator(...params);
1953
1965
  var MeshReplicatorConnection = class extends Resource4 {
1954
1966
  _params;
@@ -1970,7 +1982,7 @@ var MeshReplicatorConnection = class extends Resource4 {
1970
1982
  this.writable = new WritableStream({
1971
1983
  write: async (message, controller) => {
1972
1984
  invariant3(this._isEnabled, "Writing to a disabled connection", {
1973
- F: __dxlog_file5,
1985
+ F: __dxlog_file6,
1974
1986
  L: 51,
1975
1987
  S: this,
1976
1988
  A: [
@@ -1998,12 +2010,12 @@ var MeshReplicatorConnection = class extends Resource4 {
1998
2010
  onStartReplication: async (info, remotePeerId) => {
1999
2011
  this.remoteDeviceKey = remotePeerId;
2000
2012
  this._remotePeerId = info.id;
2001
- log5("onStartReplication", {
2013
+ log6("onStartReplication", {
2002
2014
  id: info.id,
2003
2015
  thisPeerId: this.peerId,
2004
2016
  remotePeerId: remotePeerId.toHex()
2005
2017
  }, {
2006
- F: __dxlog_file5,
2018
+ F: __dxlog_file6,
2007
2019
  L: 80,
2008
2020
  S: this,
2009
2021
  C: (f, a) => f(...a)
@@ -2030,7 +2042,7 @@ var MeshReplicatorConnection = class extends Resource4 {
2030
2042
  }
2031
2043
  get peerId() {
2032
2044
  invariant3(this._remotePeerId != null, "Remote peer has not connected yet.", {
2033
- F: __dxlog_file5,
2045
+ F: __dxlog_file6,
2034
2046
  L: 106,
2035
2047
  S: this,
2036
2048
  A: [
@@ -2058,7 +2070,7 @@ var MeshReplicatorConnection = class extends Resource4 {
2058
2070
  */
2059
2071
  enable() {
2060
2072
  invariant3(this._remotePeerId != null, "Remote peer has not connected yet.", {
2061
- F: __dxlog_file5,
2073
+ F: __dxlog_file6,
2062
2074
  L: 131,
2063
2075
  S: this,
2064
2076
  A: [
@@ -2076,7 +2088,7 @@ var MeshReplicatorConnection = class extends Resource4 {
2076
2088
  }
2077
2089
  };
2078
2090
  var logSendSync = (message) => {
2079
- log5("sendSyncMessage", () => {
2091
+ log6("sendSyncMessage", () => {
2080
2092
  const decodedSyncMessage = message.type === "sync" && message.data ? A2.decodeSyncMessage(message.data) : void 0;
2081
2093
  return {
2082
2094
  sync: decodedSyncMessage && {
@@ -2089,7 +2101,7 @@ var logSendSync = (message) => {
2089
2101
  to: message.targetId
2090
2102
  };
2091
2103
  }, {
2092
- F: __dxlog_file5,
2104
+ F: __dxlog_file6,
2093
2105
  L: 144,
2094
2106
  S: void 0,
2095
2107
  C: (f, a) => f(...a)
@@ -2099,12 +2111,12 @@ var logSendSync = (message) => {
2099
2111
  // src/automerge/space-collection.ts
2100
2112
  import { invariant as invariant4 } from "@dxos/invariant";
2101
2113
  import { SpaceId } from "@dxos/keys";
2102
- var __dxlog_file6 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/space-collection.ts";
2114
+ var __dxlog_file7 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/space-collection.ts";
2103
2115
  var deriveCollectionIdFromSpaceId = (spaceId, rootDocumentId) => rootDocumentId ? `space:${spaceId}:${rootDocumentId}` : `space:${spaceId}`;
2104
2116
  var getSpaceIdFromCollectionId = (collectionId) => {
2105
2117
  const spaceId = collectionId.split(":")[1];
2106
2118
  invariant4(SpaceId.isValid(spaceId), void 0, {
2107
- F: __dxlog_file6,
2119
+ F: __dxlog_file7,
2108
2120
  L: 16,
2109
2121
  S: void 0,
2110
2122
  A: [
@@ -2116,7 +2128,7 @@ var getSpaceIdFromCollectionId = (collectionId) => {
2116
2128
  };
2117
2129
 
2118
2130
  // src/automerge/mesh-echo-replicator.ts
2119
- var __dxlog_file7 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts";
2131
+ var __dxlog_file8 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts";
2120
2132
  var MeshEchoReplicator = class {
2121
2133
  /**
2122
2134
  * We might have multiple connections open with a peer (one per space), but there'll be only one enabled
@@ -2152,8 +2164,8 @@ var MeshEchoReplicator = class {
2152
2164
  }
2153
2165
  createExtension(extensionFactory) {
2154
2166
  invariant5(this._context, void 0, {
2155
- F: __dxlog_file7,
2156
- L: 68,
2167
+ F: __dxlog_file8,
2168
+ L: 71,
2157
2169
  S: this,
2158
2170
  A: [
2159
2171
  "this._context",
@@ -2164,17 +2176,17 @@ var MeshEchoReplicator = class {
2164
2176
  ownPeerId: this._context.peerId,
2165
2177
  replicatorFactory: extensionFactory,
2166
2178
  onRemoteConnected: async () => {
2167
- log6("onRemoteConnected", {
2179
+ log7("onRemoteConnected", {
2168
2180
  peerId: connection.peerId
2169
2181
  }, {
2170
- F: __dxlog_file7,
2171
- L: 74,
2182
+ F: __dxlog_file8,
2183
+ L: 77,
2172
2184
  S: this,
2173
2185
  C: (f, a) => f(...a)
2174
2186
  });
2175
2187
  invariant5(this._context, void 0, {
2176
- F: __dxlog_file7,
2177
- L: 75,
2188
+ F: __dxlog_file8,
2189
+ L: 78,
2178
2190
  S: this,
2179
2191
  A: [
2180
2192
  "this._context",
@@ -2195,11 +2207,11 @@ var MeshEchoReplicator = class {
2195
2207
  }
2196
2208
  },
2197
2209
  onRemoteDisconnected: async () => {
2198
- log6("onRemoteDisconnected", {
2210
+ log7("onRemoteDisconnected", {
2199
2211
  peerId: connection.peerId
2200
2212
  }, {
2201
- F: __dxlog_file7,
2202
- L: 89,
2213
+ F: __dxlog_file8,
2214
+ L: 92,
2203
2215
  S: this,
2204
2216
  C: (f, a) => f(...a)
2205
2217
  });
@@ -2207,11 +2219,11 @@ var MeshEchoReplicator = class {
2207
2219
  const existingConnections = this._connectionsPerPeer.get(connection.peerId) ?? [];
2208
2220
  const index = existingConnections.indexOf(connection);
2209
2221
  if (index < 0) {
2210
- log6.warn("disconnected connection not found", {
2222
+ log7.warn("disconnected connection not found", {
2211
2223
  peerId: connection.peerId
2212
2224
  }, {
2213
- F: __dxlog_file7,
2214
- L: 97,
2225
+ F: __dxlog_file8,
2226
+ L: 100,
2215
2227
  S: this,
2216
2228
  C: (f, a) => f(...a)
2217
2229
  });
@@ -2228,18 +2240,18 @@ var MeshEchoReplicator = class {
2228
2240
  }
2229
2241
  },
2230
2242
  shouldAdvertise: async (params) => {
2231
- log6("shouldAdvertise", {
2243
+ log7("shouldAdvertise", {
2232
2244
  peerId: connection.peerId,
2233
2245
  documentId: params.documentId
2234
2246
  }, {
2235
- F: __dxlog_file7,
2236
- L: 115,
2247
+ F: __dxlog_file8,
2248
+ L: 118,
2237
2249
  S: this,
2238
2250
  C: (f, a) => f(...a)
2239
2251
  });
2240
2252
  invariant5(this._context, void 0, {
2241
- F: __dxlog_file7,
2242
- L: 116,
2253
+ F: __dxlog_file8,
2254
+ L: 119,
2243
2255
  S: this,
2244
2256
  A: [
2245
2257
  "this._context",
@@ -2253,13 +2265,13 @@ var MeshEchoReplicator = class {
2253
2265
  documentId: params.documentId,
2254
2266
  peerId: connection.peerId
2255
2267
  });
2256
- log6("document not found locally for share policy check", {
2268
+ log7("document not found locally for share policy check", {
2257
2269
  peerId: connection.peerId,
2258
2270
  documentId: params.documentId,
2259
2271
  acceptDocument: remoteDocumentExists
2260
2272
  }, {
2261
- F: __dxlog_file7,
2262
- L: 124,
2273
+ F: __dxlog_file8,
2274
+ L: 127,
2263
2275
  S: this,
2264
2276
  C: (f, a) => f(...a)
2265
2277
  });
@@ -2268,19 +2280,19 @@ var MeshEchoReplicator = class {
2268
2280
  const spaceId = await createIdFromSpaceKey(spaceKey);
2269
2281
  const authorizedDevices = this._authorizedDevices.get(spaceId);
2270
2282
  if (!connection.remoteDeviceKey) {
2271
- log6("device key not found for share policy check", {
2283
+ log7("device key not found for share policy check", {
2272
2284
  peerId: connection.peerId,
2273
2285
  documentId: params.documentId
2274
2286
  }, {
2275
- F: __dxlog_file7,
2276
- L: 141,
2287
+ F: __dxlog_file8,
2288
+ L: 144,
2277
2289
  S: this,
2278
2290
  C: (f, a) => f(...a)
2279
2291
  });
2280
2292
  return false;
2281
2293
  }
2282
2294
  const isAuthorized = authorizedDevices?.has(connection.remoteDeviceKey) ?? false;
2283
- log6("share policy check", {
2295
+ log7("share policy check", {
2284
2296
  localPeer: this._context.peerId,
2285
2297
  remotePeer: connection.peerId,
2286
2298
  documentId: params.documentId,
@@ -2288,16 +2300,16 @@ var MeshEchoReplicator = class {
2288
2300
  spaceKey,
2289
2301
  isAuthorized
2290
2302
  }, {
2291
- F: __dxlog_file7,
2292
- L: 149,
2303
+ F: __dxlog_file8,
2304
+ L: 152,
2293
2305
  S: this,
2294
2306
  C: (f, a) => f(...a)
2295
2307
  });
2296
2308
  return isAuthorized;
2297
2309
  } catch (err) {
2298
- log6.catch(err, void 0, {
2299
- F: __dxlog_file7,
2300
- L: 159,
2310
+ log7.catch(err, void 0, {
2311
+ F: __dxlog_file8,
2312
+ L: 162,
2301
2313
  S: this,
2302
2314
  C: (f, a) => f(...a)
2303
2315
  });
@@ -2308,12 +2320,12 @@ var MeshEchoReplicator = class {
2308
2320
  const spaceId = getSpaceIdFromCollectionId(collectionId);
2309
2321
  const authorizedDevices = this._authorizedDevices.get(spaceId);
2310
2322
  if (!connection.remoteDeviceKey) {
2311
- log6("device key not found for collection sync check", {
2323
+ log7("device key not found for collection sync check", {
2312
2324
  peerId: connection.peerId,
2313
2325
  collectionId
2314
2326
  }, {
2315
- F: __dxlog_file7,
2316
- L: 169,
2327
+ F: __dxlog_file8,
2328
+ L: 172,
2317
2329
  S: this,
2318
2330
  C: (f, a) => f(...a)
2319
2331
  });
@@ -2327,12 +2339,12 @@ var MeshEchoReplicator = class {
2327
2339
  return connection.replicatorExtension;
2328
2340
  }
2329
2341
  async authorizeDevice(spaceKey, deviceKey) {
2330
- log6("authorizeDevice", {
2342
+ log7("authorizeDevice", {
2331
2343
  spaceKey,
2332
2344
  deviceKey
2333
2345
  }, {
2334
- F: __dxlog_file7,
2335
- L: 186,
2346
+ F: __dxlog_file8,
2347
+ L: 189,
2336
2348
  S: this,
2337
2349
  C: (f, a) => f(...a)
2338
2350
  });
@@ -2716,9 +2728,9 @@ import { next as A3 } from "@automerge/automerge";
2716
2728
  import { UpdateScheduler } from "@dxos/async";
2717
2729
  import { Context as Context3, LifecycleState as LifecycleState2, Resource as Resource5 } from "@dxos/context";
2718
2730
  import { invariant as invariant6 } from "@dxos/invariant";
2719
- import { log as log7 } from "@dxos/log";
2731
+ import { log as log8 } from "@dxos/log";
2720
2732
  import { retry } from "@dxos/util";
2721
- var __dxlog_file8 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/documents-synchronizer.ts";
2733
+ var __dxlog_file9 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/documents-synchronizer.ts";
2722
2734
  var MAX_UPDATE_FREQ = 10;
2723
2735
  var WRAP_AROUND_RETRY_LIMIT = 3;
2724
2736
  var WRAP_AROUND_RETRY_INITIAL_DELAY = 100;
@@ -2746,16 +2758,16 @@ var DocumentsSynchronizer = class extends Resource5 {
2746
2758
  exponent: 2
2747
2759
  }, async () => {
2748
2760
  try {
2749
- log7("loading document", {
2761
+ log8("loading document", {
2750
2762
  documentId
2751
2763
  }, {
2752
- F: __dxlog_file8,
2764
+ F: __dxlog_file9,
2753
2765
  L: 62,
2754
2766
  S: this,
2755
2767
  C: (f, a) => f(...a)
2756
2768
  });
2757
2769
  const doc = await this._params.automergeHost.loadDoc(Context3.default(void 0, {
2758
- F: __dxlog_file8,
2770
+ F: __dxlog_file9,
2759
2771
  L: 64
2760
2772
  }), documentId, {
2761
2773
  fetchFromNetwork: true
@@ -2764,10 +2776,10 @@ var DocumentsSynchronizer = class extends Resource5 {
2764
2776
  this._pendingUpdates.add(doc.documentId);
2765
2777
  this._sendUpdatesJob.trigger();
2766
2778
  } catch (err) {
2767
- log7.warn("failed to load document", {
2779
+ log8.warn("failed to load document", {
2768
2780
  err
2769
2781
  }, {
2770
- F: __dxlog_file8,
2782
+ F: __dxlog_file9,
2771
2783
  L: 72,
2772
2784
  S: this,
2773
2785
  C: (f, a) => f(...a)
@@ -2776,8 +2788,8 @@ var DocumentsSynchronizer = class extends Resource5 {
2776
2788
  }
2777
2789
  });
2778
2790
  } catch (err) {
2779
- log7.catch(err, void 0, {
2780
- F: __dxlog_file8,
2791
+ log8.catch(err, void 0, {
2792
+ F: __dxlog_file9,
2781
2793
  L: 78,
2782
2794
  S: this,
2783
2795
  C: (f, a) => f(...a)
@@ -2811,10 +2823,10 @@ var DocumentsSynchronizer = class extends Resource5 {
2811
2823
  }
2812
2824
  _startSync(doc) {
2813
2825
  if (this._syncStates.has(doc.documentId)) {
2814
- log7("Document already being synced", {
2826
+ log8("Document already being synced", {
2815
2827
  documentId: doc.documentId
2816
2828
  }, {
2817
- F: __dxlog_file8,
2829
+ F: __dxlog_file9,
2818
2830
  L: 113,
2819
2831
  S: this,
2820
2832
  C: (f, a) => f(...a)
@@ -2858,7 +2870,7 @@ var DocumentsSynchronizer = class extends Resource5 {
2858
2870
  _getPendingChanges(documentId) {
2859
2871
  const syncState = this._syncStates.get(documentId);
2860
2872
  invariant6(syncState, "Sync state for document not found", {
2861
- F: __dxlog_file8,
2873
+ F: __dxlog_file9,
2862
2874
  L: 155,
2863
2875
  S: this,
2864
2876
  A: [
@@ -2882,17 +2894,17 @@ var DocumentsSynchronizer = class extends Resource5 {
2882
2894
  if (this._lifecycleState === LifecycleState2.CLOSED) {
2883
2895
  return;
2884
2896
  }
2885
- log7("write mutation", {
2897
+ log8("write mutation", {
2886
2898
  documentId
2887
2899
  }, {
2888
- F: __dxlog_file8,
2900
+ F: __dxlog_file9,
2889
2901
  L: 173,
2890
2902
  S: this,
2891
2903
  C: (f, a) => f(...a)
2892
2904
  });
2893
2905
  const syncState = this._syncStates.get(documentId);
2894
2906
  invariant6(syncState, "Sync state for document not found", {
2895
- F: __dxlog_file8,
2907
+ F: __dxlog_file9,
2896
2908
  L: 176,
2897
2909
  S: this,
2898
2910
  A: [
@@ -2912,7 +2924,7 @@ var DocumentsSynchronizer = class extends Resource5 {
2912
2924
  };
2913
2925
 
2914
2926
  // src/db-host/data-service.ts
2915
- var __dxlog_file9 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/data-service.ts";
2927
+ var __dxlog_file10 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/data-service.ts";
2916
2928
  var DataServiceImpl = class {
2917
2929
  /**
2918
2930
  * Map of subscriptions.
@@ -2936,8 +2948,8 @@ var DataServiceImpl = class {
2936
2948
  synchronizer.open().then(() => {
2937
2949
  this._subscriptions.set(request.subscriptionId, synchronizer);
2938
2950
  ready();
2939
- }).catch((err) => log8.catch(err, void 0, {
2940
- F: __dxlog_file9,
2951
+ }).catch((err) => log9.catch(err, void 0, {
2952
+ F: __dxlog_file10,
2941
2953
  L: 74,
2942
2954
  S: this,
2943
2955
  C: (f, a) => f(...a)
@@ -2948,7 +2960,7 @@ var DataServiceImpl = class {
2948
2960
  async updateSubscription(request) {
2949
2961
  const synchronizer = this._subscriptions.get(request.subscriptionId);
2950
2962
  invariant7(synchronizer, "Subscription not found", {
2951
- F: __dxlog_file9,
2963
+ F: __dxlog_file10,
2952
2964
  L: 81,
2953
2965
  S: this,
2954
2966
  A: [
@@ -2975,7 +2987,7 @@ var DataServiceImpl = class {
2975
2987
  }
2976
2988
  const synchronizer = this._subscriptions.get(request.subscriptionId);
2977
2989
  invariant7(synchronizer, "Subscription not found", {
2978
- F: __dxlog_file9,
2990
+ F: __dxlog_file10,
2979
2991
  L: 101,
2980
2992
  S: this,
2981
2993
  A: [
@@ -3020,7 +3032,7 @@ var DataServiceImpl = class {
3020
3032
  return new Stream(({ ctx, next, ready }) => {
3021
3033
  const spaceId = request.spaceId;
3022
3034
  invariant7(SpaceId2.isValid(spaceId), void 0, {
3023
- F: __dxlog_file9,
3035
+ F: __dxlog_file10,
3024
3036
  L: 141,
3025
3037
  S: this,
3026
3038
  A: [
@@ -3057,128 +3069,38 @@ var DataServiceImpl = class {
3057
3069
 
3058
3070
  // src/db-host/echo-host.ts
3059
3071
  import { DeferredTask as DeferredTask3, sleep } from "@dxos/async";
3060
- import { Context as Context8, LifecycleState as LifecycleState5, Resource as Resource9 } from "@dxos/context";
3072
+ import { Context as Context6, LifecycleState as LifecycleState5, Resource as Resource9 } from "@dxos/context";
3061
3073
  import { todo } from "@dxos/debug";
3062
- import { SpaceDocVersion as SpaceDocVersion4, createIdFromSpaceKey as createIdFromSpaceKey2 } from "@dxos/echo-protocol";
3074
+ import { SpaceDocVersion as SpaceDocVersion3, createIdFromSpaceKey as createIdFromSpaceKey2 } from "@dxos/echo-protocol";
3063
3075
  import { RuntimeProvider as RuntimeProvider3 } from "@dxos/effect";
3064
3076
  import { FeedStore } from "@dxos/feed";
3065
3077
  import { IndexEngine } from "@dxos/index-core";
3066
- import { IndexMetadataStore, IndexStore, Indexer } from "@dxos/indexing";
3067
- import { invariant as invariant14 } from "@dxos/invariant";
3078
+ import { invariant as invariant13 } from "@dxos/invariant";
3068
3079
  import { log as log14 } from "@dxos/log";
3069
- import { IndexKind } from "@dxos/protocols/proto/dxos/echo/indexing";
3070
3080
  import { trace as trace5 } from "@dxos/tracing";
3071
3081
 
3072
- // src/db-host/documents-iterator.ts
3073
- import * as A4 from "@automerge/automerge";
3074
- import { Context as Context4 } from "@dxos/context";
3075
- import { DatabaseDirectory as DatabaseDirectory3, SpaceDocVersion as SpaceDocVersion2 } from "@dxos/echo-protocol";
3076
- import { invariant as invariant8 } from "@dxos/invariant";
3077
- import { log as log9 } from "@dxos/log";
3078
- import { ObjectPointerVersion, objectPointerCodec as objectPointerCodec2 } from "@dxos/protocols";
3079
- var __dxlog_file10 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/documents-iterator.ts";
3080
- var LOG_VIEW_OPERATION_THRESHOLD = 300;
3081
- var createSelectedDocumentsIterator = (automergeHost) => (
3082
- /**
3083
- * Get object data blobs from Automerge Repo by ids.
3084
- */
3085
- // TODO(mykola): Unload automerge handles after usage.
3086
- async function* loadDocuments(objects) {
3087
- for (const [id, heads] of objects.entries()) {
3088
- try {
3089
- const { documentId, objectId } = objectPointerCodec2.decode(id);
3090
- const handle = await automergeHost.loadDoc(Context4.default(void 0, {
3091
- F: __dxlog_file10,
3092
- L: 31
3093
- }), documentId, {
3094
- fetchFromNetwork: true
3095
- });
3096
- let doc = handle.doc();
3097
- invariant8(doc, void 0, {
3098
- F: __dxlog_file10,
3099
- L: 36,
3100
- S: this,
3101
- A: [
3102
- "doc",
3103
- ""
3104
- ]
3105
- });
3106
- const currentHeads = A4.getHeads(doc);
3107
- if (!A4.equals(currentHeads, heads)) {
3108
- const begin = Date.now();
3109
- doc = A4.view(doc, heads);
3110
- const end = Date.now();
3111
- if (end - begin > LOG_VIEW_OPERATION_THRESHOLD) {
3112
- log9("Checking out document version is taking too long", {
3113
- duration: end - begin,
3114
- requestedHeads: heads,
3115
- originalHeads: currentHeads
3116
- }, {
3117
- F: __dxlog_file10,
3118
- L: 47,
3119
- S: this,
3120
- C: (f, a) => f(...a)
3121
- });
3122
- }
3123
- }
3124
- if (doc.version !== SpaceDocVersion2.CURRENT) {
3125
- continue;
3126
- }
3127
- if (!doc.objects?.[objectId]) {
3128
- continue;
3129
- }
3130
- let newId = id;
3131
- if (objectPointerCodec2.getVersion(id) === ObjectPointerVersion.V0) {
3132
- const spaceKey = DatabaseDirectory3.getSpaceKey(doc) ?? void 0;
3133
- newId = objectPointerCodec2.encode({
3134
- documentId,
3135
- objectId,
3136
- spaceKey
3137
- });
3138
- }
3139
- yield [
3140
- {
3141
- id: newId,
3142
- object: doc.objects[objectId],
3143
- heads
3144
- }
3145
- ];
3146
- } catch (error) {
3147
- log9.error("Error loading document", {
3148
- heads,
3149
- id,
3150
- error
3151
- }, {
3152
- F: __dxlog_file10,
3153
- L: 73,
3154
- S: this,
3155
- C: (f, a) => f(...a)
3156
- });
3157
- }
3158
- }
3159
- }
3160
- );
3161
-
3162
3082
  // src/db-host/local-queue-service.ts
3163
3083
  import * as Effect2 from "effect/Effect";
3164
3084
  import * as Function from "effect/Function";
3165
- import { ATTR_META } from "@dxos/echo/internal";
3085
+ import { EchoFeedCodec } from "@dxos/echo-protocol";
3166
3086
  import { RuntimeProvider } from "@dxos/effect";
3167
- import { invariant as invariant9 } from "@dxos/invariant";
3168
- import { KEY_QUEUE_POSITION } from "@dxos/protocols";
3087
+ import { assertArgument, invariant as invariant8 } from "@dxos/invariant";
3088
+ import { FeedProtocol } from "@dxos/protocols";
3169
3089
  var __dxlog_file11 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/local-queue-service.ts";
3170
3090
  var LocalQueueServiceImpl = class {
3171
3091
  #runtime;
3172
3092
  #feedStore;
3173
- constructor(runtime, feedStore) {
3093
+ #syncQueue;
3094
+ constructor(runtime, feedStore, syncQueue) {
3174
3095
  this.#runtime = runtime;
3175
3096
  this.#feedStore = feedStore;
3097
+ this.#syncQueue = syncQueue;
3176
3098
  }
3177
3099
  queryQueue(request) {
3178
3100
  const { query } = request;
3179
- invariant9(query, "query is required", {
3101
+ invariant8(query, "query is required", {
3180
3102
  F: __dxlog_file11,
3181
- L: 37,
3103
+ L: 46,
3182
3104
  S: this,
3183
3105
  A: [
3184
3106
  "query",
@@ -3190,6 +3112,7 @@ var LocalQueueServiceImpl = class {
3190
3112
  const cursor = query.after ? parseInt(query.after) : -1;
3191
3113
  const result = yield* this.#feedStore.query({
3192
3114
  requestId: crypto.randomUUID(),
3115
+ feedNamespace: request.query.queuesNamespace || FeedProtocol.WellKnownNamespaces.data,
3193
3116
  spaceId,
3194
3117
  query: {
3195
3118
  feedIds: queueIds ?? []
@@ -3197,13 +3120,7 @@ var LocalQueueServiceImpl = class {
3197
3120
  position: cursor,
3198
3121
  limit: query.limit
3199
3122
  });
3200
- const objects = result.blocks.map((block) => {
3201
- const data = JSON.parse(new TextDecoder().decode(block.data));
3202
- if (block.position !== null) {
3203
- setQueuePosition(data, block.position);
3204
- }
3205
- return data;
3206
- });
3123
+ const objects = result.blocks.map((block) => EchoFeedCodec.decode(block.data, block.position ?? void 0));
3207
3124
  const lastBlock = result.blocks[result.blocks.length - 1];
3208
3125
  const nextCursor = lastBlock && lastBlock.position != null ? String(lastBlock.position) : null;
3209
3126
  return Function.identity({
@@ -3216,85 +3133,65 @@ var LocalQueueServiceImpl = class {
3216
3133
  }
3217
3134
  insertIntoQueue(request) {
3218
3135
  const { subspaceTag, spaceId, queueId, objects } = request;
3136
+ const feedNamespace = subspaceTag ?? FeedProtocol.WellKnownNamespaces.data;
3137
+ assertArgument(FeedProtocol.isWellKnownNamespace(feedNamespace), "request.subspaceTag", "expected a well-known queue namespace");
3219
3138
  return RuntimeProvider.runPromise(this.#runtime)(Effect2.gen(this, function* () {
3220
- const messages = objects.map((obj) => {
3221
- const data = structuredClone(obj);
3222
- if (data[ATTR_META]?.keys?.find((key) => key.source === KEY_QUEUE_POSITION)) {
3223
- data[ATTR_META].keys = data[ATTR_META].keys.filter((key) => key.source !== KEY_QUEUE_POSITION);
3224
- }
3225
- return {
3226
- spaceId,
3227
- feedId: queueId,
3228
- feedNamespace: subspaceTag,
3229
- data: new TextEncoder().encode(JSON.stringify(obj))
3230
- };
3231
- });
3139
+ const messages = objects.map((obj) => ({
3140
+ spaceId,
3141
+ feedId: queueId,
3142
+ feedNamespace,
3143
+ data: EchoFeedCodec.encode(obj)
3144
+ }));
3232
3145
  yield* this.#feedStore.appendLocal(messages);
3233
3146
  }));
3234
3147
  }
3235
3148
  deleteFromQueue(request) {
3236
3149
  const { subspaceTag, spaceId, queueId, objectIds } = request;
3150
+ const feedNamespace = subspaceTag ?? FeedProtocol.WellKnownNamespaces.data;
3151
+ assertArgument(FeedProtocol.isWellKnownNamespace(feedNamespace), "request.subspaceTag", "expected a well-known queue namespace");
3237
3152
  return RuntimeProvider.runPromise(this.#runtime)(Effect2.gen(this, function* () {
3238
3153
  const messages = objectIds.map((id) => ({
3239
3154
  spaceId,
3240
3155
  feedId: queueId,
3241
- feedNamespace: subspaceTag,
3242
- data: new TextEncoder().encode(JSON.stringify({
3156
+ feedNamespace,
3157
+ data: EchoFeedCodec.encode({
3243
3158
  id,
3244
3159
  "@deleted": true
3245
- }))
3160
+ })
3246
3161
  }));
3247
3162
  yield* this.#feedStore.appendLocal(messages);
3248
3163
  }));
3249
3164
  }
3250
- };
3251
- var setQueuePosition = (obj, position) => {
3252
- obj[ATTR_META] ??= {
3253
- keys: []
3254
- };
3255
- obj[ATTR_META].keys ??= [];
3256
- for (let i = 0; i < obj[ATTR_META].keys.length; i++) {
3257
- const key = obj[ATTR_META].keys[i];
3258
- if (key.source === KEY_QUEUE_POSITION) {
3259
- obj[ATTR_META].keys.splice(i, 1);
3260
- i--;
3261
- }
3165
+ async syncQueue(request) {
3166
+ await this.#syncQueue?.(request);
3262
3167
  }
3263
- obj[ATTR_META].keys.push({
3264
- source: KEY_QUEUE_POSITION,
3265
- id: position.toString()
3266
- });
3267
3168
  };
3268
3169
 
3269
3170
  // src/db-host/query-service.ts
3270
- import { getHeads as getHeads3 } from "@automerge/automerge";
3271
3171
  import * as Schema from "effect/Schema";
3272
3172
  import { DeferredTask as DeferredTask2, scheduleMicroTask, synchronized as synchronized2 } from "@dxos/async";
3273
3173
  import { Stream as Stream2 } from "@dxos/codec-protobuf/stream";
3274
- import { Context as Context6, Resource as Resource7 } from "@dxos/context";
3174
+ import { Resource as Resource7 } from "@dxos/context";
3275
3175
  import { raise } from "@dxos/debug";
3276
- import { DatabaseDirectory as DatabaseDirectory5, QueryAST } from "@dxos/echo-protocol";
3176
+ import { QueryAST } from "@dxos/echo-protocol";
3277
3177
  import { log as log11 } from "@dxos/log";
3278
- import { objectPointerCodec as objectPointerCodec4 } from "@dxos/protocols";
3279
3178
  import { trace as trace4 } from "@dxos/tracing";
3280
3179
 
3281
3180
  // src/query/query-executor.ts
3282
- import * as Match from "effect/Match";
3283
3181
  import * as Runtime from "effect/Runtime";
3284
- import { Context as Context5, ContextDisposedError, LifecycleState as LifecycleState3, Resource as Resource6 } from "@dxos/context";
3285
- import { ATTR_RELATION_SOURCE, ATTR_RELATION_TARGET } from "@dxos/echo/internal";
3286
- import { DatabaseDirectory as DatabaseDirectory4, ObjectStructure, isEncodedReference } from "@dxos/echo-protocol";
3182
+ import { Context as Context4, ContextDisposedError, LifecycleState as LifecycleState3, Resource as Resource6 } from "@dxos/context";
3183
+ import { ATTR_PARENT, ATTR_RELATION_SOURCE, ATTR_RELATION_TARGET } from "@dxos/echo/internal";
3184
+ import { DatabaseDirectory as DatabaseDirectory3, EncodedReference, ObjectStructure, isEncodedReference } from "@dxos/echo-protocol";
3287
3185
  import { runAndForwardErrors, unwrapExit } from "@dxos/effect";
3288
- import { EscapedPropPath } from "@dxos/indexing";
3289
- import { invariant as invariant11 } from "@dxos/invariant";
3290
- import { DXN, PublicKey as PublicKey4 } from "@dxos/keys";
3186
+ import { EscapedPropPath } from "@dxos/index-core";
3187
+ import { invariant as invariant10 } from "@dxos/invariant";
3188
+ import { DXN } from "@dxos/keys";
3291
3189
  import { log as log10 } from "@dxos/log";
3292
- import { objectPointerCodec as objectPointerCodec3 } from "@dxos/protocols";
3293
3190
  import { getDeep, isNonNullable as isNonNullable3 } from "@dxos/util";
3294
3191
 
3295
3192
  // src/query/query-planner.ts
3296
3193
  import { Order } from "@dxos/echo";
3297
- import { invariant as invariant10 } from "@dxos/invariant";
3194
+ import { invariant as invariant9 } from "@dxos/invariant";
3298
3195
 
3299
3196
  // src/query/errors.ts
3300
3197
  import { BaseError } from "@dxos/errors";
@@ -3364,6 +3261,8 @@ var QueryPlanner = class {
3364
3261
  return this._generateRelationTraversalClause(query, context);
3365
3262
  case "reference-traversal":
3366
3263
  return this._generateReferenceTraversalClause(query, context);
3264
+ case "hierarchy-traversal":
3265
+ return this._generateHierarchyTraversalClause(query, context);
3367
3266
  case "union":
3368
3267
  return this._generateUnionClause(query, context);
3369
3268
  case "set-difference":
@@ -3567,9 +3466,9 @@ var QueryPlanner = class {
3567
3466
  case "or":
3568
3467
  if (filter2.filters.every(isTrivialTypenameFilter)) {
3569
3468
  const typenames = filter2.filters.map((filter3) => {
3570
- invariant10(filter3.type === "object" && filter3.typename !== null, void 0, {
3469
+ invariant9(filter3.type === "object" && filter3.typename !== null, void 0, {
3571
3470
  F: __dxlog_file12,
3572
- L: 245,
3471
+ L: 247,
3573
3472
  S: this,
3574
3473
  A: [
3575
3474
  "filter.type === 'object' && filter.typename !== null",
@@ -3781,6 +3680,19 @@ var QueryPlanner = class {
3781
3680
  }
3782
3681
  ]);
3783
3682
  }
3683
+ _generateHierarchyTraversalClause(query, context) {
3684
+ return QueryPlan.Plan.make([
3685
+ ...this._generate(query.anchor, context).steps,
3686
+ {
3687
+ _tag: "TraverseStep",
3688
+ traversal: {
3689
+ _tag: "HierarchyTraversal",
3690
+ direction: query.direction
3691
+ }
3692
+ },
3693
+ ...this._generateDeletedHandlingSteps(context)
3694
+ ]);
3695
+ }
3784
3696
  /**
3785
3697
  * Removes filter steps that have no predicates.
3786
3698
  */
@@ -3990,6 +3902,10 @@ var isTrivialTypenameFilter = (filter2) => {
3990
3902
  // src/query/query-executor.ts
3991
3903
  var __dxlog_file13 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/query/query-executor.ts";
3992
3904
  var QueryItem = Object.freeze({
3905
+ /**
3906
+ * Checks if the item is deleted.
3907
+ * Only applies to this item, not its parents.
3908
+ */
3993
3909
  isDeleted: (item) => {
3994
3910
  if (item.doc) {
3995
3911
  return ObjectStructure.isDeleted(item.doc);
@@ -4008,6 +3924,15 @@ var QueryItem = Object.freeze({
4008
3924
  throw new Error("Invalid query item");
4009
3925
  }
4010
3926
  },
3927
+ getParent: (item) => {
3928
+ if (item.doc) {
3929
+ return ObjectStructure.getParent(item.doc)?.["/"];
3930
+ } else if (item.data) {
3931
+ return item.data[ATTR_PARENT];
3932
+ } else {
3933
+ throw new Error("Invalid query item");
3934
+ }
3935
+ },
4011
3936
  getRelationSource: (item) => {
4012
3937
  if (item.doc) {
4013
3938
  return ObjectStructure.getRelationSource(item.doc)?.["/"];
@@ -4098,9 +4023,9 @@ var ExecutionTrace = Object.freeze({
4098
4023
  }
4099
4024
  });
4100
4025
  var TRACE_QUERY_EXECUTION = false;
4101
- var QueryExecutor = class extends Resource6 {
4102
- _indexer;
4103
- _indexer2;
4026
+ var MAX_DEPTH_FOR_DELETION_TRACING = 10;
4027
+ var QueryExecutor = class _QueryExecutor extends Resource6 {
4028
+ _indexEngine;
4104
4029
  _runtime;
4105
4030
  _automergeHost;
4106
4031
  _spaceStateManager;
@@ -4116,8 +4041,7 @@ var QueryExecutor = class extends Resource6 {
4116
4041
  _lastResultSet = [];
4117
4042
  constructor(options) {
4118
4043
  super();
4119
- this._indexer = options.indexer;
4120
- this._indexer2 = options.indexer2;
4044
+ this._indexEngine = options.indexEngine;
4121
4045
  this._runtime = options.runtime;
4122
4046
  this._automergeHost = options.automergeHost;
4123
4047
  this._spaceStateManager = options.spaceStateManager;
@@ -4136,10 +4060,6 @@ var QueryExecutor = class extends Resource6 {
4136
4060
  get trace() {
4137
4061
  return this._trace;
4138
4062
  }
4139
- async _open(ctx) {
4140
- }
4141
- async _close(ctx) {
4142
- }
4143
4063
  getResults() {
4144
4064
  return this._lastResultSet.map((item) => ({
4145
4065
  id: item.objectId,
@@ -4152,9 +4072,9 @@ var QueryExecutor = class extends Resource6 {
4152
4072
  }));
4153
4073
  }
4154
4074
  async execQuery() {
4155
- invariant11(this._lifecycleState === LifecycleState3.OPEN, void 0, {
4075
+ invariant10(this._lifecycleState === LifecycleState3.OPEN, void 0, {
4156
4076
  F: __dxlog_file13,
4157
- L: 288,
4077
+ L: 295,
4158
4078
  S: this,
4159
4079
  A: [
4160
4080
  "this._lifecycleState === LifecycleState.OPEN",
@@ -4166,7 +4086,8 @@ var QueryExecutor = class extends Resource6 {
4166
4086
  this._lastResultSet = workingSet;
4167
4087
  trace6.name = "Root";
4168
4088
  trace6.details = JSON.stringify({
4169
- id: this._id
4089
+ id: this._id,
4090
+ query: prettyQuery(this._query)
4170
4091
  });
4171
4092
  this._trace = trace6;
4172
4093
  const changed = prevResultSet.length !== workingSet.length || prevResultSet.some((item, index) => workingSet[index].objectId !== item.objectId || workingSet[index].spaceId !== item.spaceId || workingSet[index].documentId !== item.documentId);
@@ -4179,7 +4100,6 @@ var QueryExecutor = class extends Resource6 {
4179
4100
  }
4180
4101
  async _execPlan(plan, workingSet) {
4181
4102
  const trace6 = ExecutionTrace.makeEmpty();
4182
- const begin = performance.now();
4183
4103
  for (const step of plan.steps) {
4184
4104
  if (this._ctx.disposed) {
4185
4105
  throw new ContextDisposedError();
@@ -4256,11 +4176,8 @@ var QueryExecutor = class extends Resource6 {
4256
4176
  switch (step.selector._tag) {
4257
4177
  case "WildcardSelector": {
4258
4178
  const beginIndexQuery = performance.now();
4259
- const indexHits = await this._indexer.execQuery({
4260
- typenames: [],
4261
- inverted: false
4262
- });
4263
- trace6.indexHits = +indexHits.length;
4179
+ const metas = await this._queryAllFromSqlIndex(step.spaces);
4180
+ trace6.indexHits = metas.length;
4264
4181
  trace6.indexQueryTime += performance.now() - beginIndexQuery;
4265
4182
  if (this._ctx.disposed) {
4266
4183
  return {
@@ -4269,10 +4186,10 @@ var QueryExecutor = class extends Resource6 {
4269
4186
  };
4270
4187
  }
4271
4188
  const documentLoadStart = performance.now();
4272
- const results = await this._loadDocumentsAfterIndexQuery(indexHits);
4189
+ const results = await this._loadDocumentsAfterSqlQuery(metas);
4273
4190
  trace6.documentsLoaded += results.length;
4274
4191
  trace6.documentLoadTime += performance.now() - documentLoadStart;
4275
- workingSet.push(...results.filter(isNonNullable3).filter((item) => step.spaces.includes(item.spaceId)));
4192
+ workingSet.push(...results.filter(isNonNullable3));
4276
4193
  trace6.objectCount = workingSet.length;
4277
4194
  break;
4278
4195
  }
@@ -4288,11 +4205,8 @@ var QueryExecutor = class extends Resource6 {
4288
4205
  }
4289
4206
  case "TypeSelector": {
4290
4207
  const beginIndexQuery = performance.now();
4291
- const indexHits = await this._indexer.execQuery({
4292
- typenames: step.selector.typename,
4293
- inverted: step.selector.inverted
4294
- });
4295
- trace6.indexHits = +indexHits.length;
4208
+ const metas = await this._queryTypesFromSqlIndex(step.spaces, step.selector.typename, step.selector.inverted);
4209
+ trace6.indexHits = metas.length;
4296
4210
  trace6.indexQueryTime += performance.now() - beginIndexQuery;
4297
4211
  if (this._ctx.disposed) {
4298
4212
  return {
@@ -4301,114 +4215,97 @@ var QueryExecutor = class extends Resource6 {
4301
4215
  };
4302
4216
  }
4303
4217
  const documentLoadStart = performance.now();
4304
- const results = await this._loadDocumentsAfterIndexQuery(indexHits);
4218
+ const results = await this._loadDocumentsAfterSqlQuery(metas);
4305
4219
  trace6.documentsLoaded += results.length;
4306
4220
  trace6.documentLoadTime += performance.now() - documentLoadStart;
4307
- workingSet.push(...results.filter(isNonNullable3).filter((item) => step.spaces.includes(item.spaceId)));
4221
+ workingSet.push(...results.filter(isNonNullable3));
4308
4222
  trace6.objectCount = workingSet.length;
4309
4223
  break;
4310
4224
  }
4311
4225
  case "TextSelector": {
4312
- if (step.selector.searchKind === "full-text" && this._indexer2 && this._runtime) {
4313
- const beginIndexQuery = performance.now();
4314
- const runtime = await runAndForwardErrors(this._runtime);
4315
- invariant11(step.spaces.length <= 1, "Multiple spaces are not supported for full-text search", {
4226
+ if (step.selector.searchKind === "vector") {
4227
+ log10.warn("Vector search is not supported", void 0, {
4316
4228
  F: __dxlog_file13,
4317
- L: 461,
4229
+ L: 459,
4318
4230
  S: this,
4319
- A: [
4320
- "step.spaces.length <= 1",
4321
- "'Multiple spaces are not supported for full-text search'"
4322
- ]
4231
+ C: (f, a) => f(...a)
4323
4232
  });
4324
- const queueIds = step.queues.length > 0 ? step.queues.map((dxnStr) => DXN.parse(dxnStr).asQueueDXN()?.queueId).filter(Boolean) : null;
4325
- const textResults = await unwrapExit(await this._indexer2.queryText({
4326
- query: step.selector.text,
4327
- spaceId: step.spaces,
4328
- includeAllQueues: step.allQueuesFromSpaces,
4329
- queueIds
4330
- }).pipe(Runtime.runPromiseExit(runtime)));
4331
- trace6.indexHits = textResults.length;
4332
- trace6.indexQueryTime += performance.now() - beginIndexQuery;
4333
- if (this._ctx.disposed) {
4334
- return {
4335
- workingSet,
4336
- trace: trace6
4337
- };
4338
- }
4339
- const documentLoadStart = performance.now();
4340
- const queueResults = textResults.filter((r) => r.queueId);
4341
- const spaceResults = textResults.filter((r) => !r.queueId);
4342
- const rankMap = new Map(textResults.map((r) => [
4343
- r.recordId,
4344
- r.rank
4233
+ break;
4234
+ }
4235
+ const beginIndexQuery = performance.now();
4236
+ invariant10(step.spaces.length <= 1, "Multiple spaces are not supported for full-text search", {
4237
+ F: __dxlog_file13,
4238
+ L: 465,
4239
+ S: this,
4240
+ A: [
4241
+ "step.spaces.length <= 1",
4242
+ "'Multiple spaces are not supported for full-text search'"
4243
+ ]
4244
+ });
4245
+ const queueIds = step.queues.length > 0 ? step.queues.map((dxnStr) => DXN.parse(dxnStr).asQueueDXN()?.queueId).filter(Boolean) : null;
4246
+ const textResults = await this._runInRuntime(this._indexEngine.queryText({
4247
+ query: step.selector.text,
4248
+ spaceId: step.spaces,
4249
+ includeAllQueues: step.allQueuesFromSpaces,
4250
+ queueIds
4251
+ }));
4252
+ trace6.indexHits = textResults.length;
4253
+ trace6.indexQueryTime += performance.now() - beginIndexQuery;
4254
+ if (this._ctx.disposed) {
4255
+ return {
4256
+ workingSet,
4257
+ trace: trace6
4258
+ };
4259
+ }
4260
+ const documentLoadStart = performance.now();
4261
+ const queueResults = textResults.filter((r) => r.queueId);
4262
+ const spaceResults = textResults.filter((r) => !r.queueId);
4263
+ const rankMap = new Map(textResults.map((r) => [
4264
+ r.recordId,
4265
+ r.rank
4266
+ ]));
4267
+ let queueItems = [];
4268
+ if (queueResults.length > 0) {
4269
+ const snapshots = await this._runInRuntime(this._indexEngine.querySnapshotsJSON(queueResults.map((r) => r.recordId)));
4270
+ const snapshotMap = new Map(snapshots.map((s) => [
4271
+ s.recordId,
4272
+ s.snapshot
4345
4273
  ]));
4346
- let queueItems = [];
4347
- if (queueResults.length > 0) {
4348
- const snapshots = await unwrapExit(await this._indexer2.querySnapshotsJSON(queueResults.map((r) => r.recordId)).pipe(Runtime.runPromiseExit(runtime)));
4349
- const snapshotMap = new Map(snapshots.map((s) => [
4350
- s.recordId,
4351
- s.snapshot
4352
- ]));
4353
- queueItems = queueResults.map((result) => {
4354
- const snapshot = snapshotMap.get(result.recordId);
4355
- if (!snapshot || typeof snapshot !== "object") {
4356
- return null;
4357
- }
4358
- return {
4359
- objectId: result.objectId,
4360
- spaceId: result.spaceId,
4361
- queueId: result.queueId,
4362
- queueNamespace: "data",
4363
- documentId: null,
4364
- doc: null,
4365
- data: snapshot,
4366
- rank: rankMap.get(result.recordId) ?? 1
4367
- };
4368
- }).filter(isNonNullable3);
4369
- }
4370
- const spaceItems = await Promise.all(spaceResults.map(async (result) => {
4371
- const dxn = DXN.fromLocalObjectId(result.objectId);
4372
- const item = await this._loadFromDXN(dxn, {
4373
- sourceSpaceId: result.spaceId
4374
- });
4375
- if (item) {
4376
- item.rank = rankMap.get(result.recordId) ?? 1;
4274
+ queueItems = queueResults.map((result) => {
4275
+ const snapshot = snapshotMap.get(result.recordId);
4276
+ if (!snapshot || typeof snapshot !== "object") {
4277
+ return null;
4377
4278
  }
4378
- return item;
4379
- }));
4380
- const items = [
4381
- ...queueItems,
4382
- ...spaceItems.filter(isNonNullable3)
4383
- ];
4384
- trace6.documentsLoaded += items.length;
4385
- trace6.documentLoadTime += performance.now() - documentLoadStart;
4386
- workingSet.push(...items.filter((item) => step.spaces.includes(item.spaceId)));
4387
- trace6.objectCount = workingSet.length;
4388
- } else {
4389
- const beginIndexQuery = performance.now();
4390
- const indexHits = await this._indexer.execQuery({
4391
- typenames: [],
4392
- text: {
4393
- query: step.selector.text,
4394
- kind: Match.type().pipe(Match.withReturnType(), Match.when("full-text", () => "text"), Match.when("vector", () => "vector"), Match.orElseAbsurd)(step.selector.searchKind)
4395
- }
4396
- });
4397
- trace6.indexHits = +indexHits.length;
4398
- trace6.indexQueryTime += performance.now() - beginIndexQuery;
4399
- if (this._ctx.disposed) {
4400
4279
  return {
4401
- workingSet,
4402
- trace: trace6
4280
+ objectId: result.objectId,
4281
+ spaceId: result.spaceId,
4282
+ queueId: result.queueId,
4283
+ queueNamespace: "data",
4284
+ documentId: null,
4285
+ doc: null,
4286
+ data: snapshot,
4287
+ rank: rankMap.get(result.recordId) ?? 1
4403
4288
  };
4404
- }
4405
- const documentLoadStart = performance.now();
4406
- const results = await this._loadDocumentsAfterIndexQuery(indexHits);
4407
- trace6.documentsLoaded += results.length;
4408
- trace6.documentLoadTime += performance.now() - documentLoadStart;
4409
- workingSet.push(...results.filter(isNonNullable3).filter((item) => step.spaces.includes(item.spaceId)));
4410
- trace6.objectCount = workingSet.length;
4289
+ }).filter(isNonNullable3);
4411
4290
  }
4291
+ const spaceItems = await Promise.all(spaceResults.map(async (result) => {
4292
+ const dxn = DXN.fromLocalObjectId(result.objectId);
4293
+ const item = await this._loadFromDXN(dxn, {
4294
+ sourceSpaceId: result.spaceId
4295
+ });
4296
+ if (item) {
4297
+ item.rank = rankMap.get(result.recordId) ?? 1;
4298
+ }
4299
+ return item;
4300
+ }));
4301
+ const items = [
4302
+ ...queueItems,
4303
+ ...spaceItems.filter(isNonNullable3)
4304
+ ];
4305
+ trace6.documentsLoaded += items.length;
4306
+ trace6.documentLoadTime += performance.now() - documentLoadStart;
4307
+ workingSet.push(...items.filter((item) => step.spaces.includes(item.spaceId)));
4308
+ trace6.objectCount = workingSet.length;
4412
4309
  break;
4413
4310
  }
4414
4311
  default:
@@ -4434,6 +4331,7 @@ var QueryExecutor = class extends Resource6 {
4434
4331
  } else if (item.data) {
4435
4332
  return filterMatchObjectJSON(step.filter, item.data);
4436
4333
  } else {
4334
+ return false;
4437
4335
  }
4438
4336
  });
4439
4337
  return {
@@ -4448,7 +4346,14 @@ var QueryExecutor = class extends Resource6 {
4448
4346
  }
4449
4347
  async _execFilterDeletedStep(step, workingSet) {
4450
4348
  const expected = step.mode === "only-deleted";
4451
- const result = workingSet.filter((item) => QueryItem.isDeleted(item) === expected);
4349
+ const deletedState = workingSet.map((item) => QueryItem.isDeleted(item));
4350
+ await Promise.all(workingSet.map(async (item, index) => {
4351
+ if (deletedState[index]) {
4352
+ return;
4353
+ }
4354
+ deletedState[index] ||= await this._getTransitiveDeletionState(item, MAX_DEPTH_FOR_DELETION_TRACING);
4355
+ }));
4356
+ const result = workingSet.filter((item, index) => deletedState[index] === expected);
4452
4357
  return {
4453
4358
  workingSet: result,
4454
4359
  trace: {
@@ -4471,9 +4376,9 @@ var QueryExecutor = class extends Resource6 {
4471
4376
  case "ReferenceTraversal": {
4472
4377
  switch (step.traversal.direction) {
4473
4378
  case "outgoing": {
4474
- invariant11(step.traversal.property !== null, "Outgoing reference traversal requires a property", {
4379
+ invariant10(step.traversal.property !== null, "Outgoing reference traversal requires a property", {
4475
4380
  F: __dxlog_file13,
4476
- L: 645,
4381
+ L: 628,
4477
4382
  S: this,
4478
4383
  A: [
4479
4384
  "step.traversal.property !== null",
@@ -4497,7 +4402,7 @@ var QueryExecutor = class extends Resource6 {
4497
4402
  ref: ref2["/"]
4498
4403
  }, {
4499
4404
  F: __dxlog_file13,
4500
- L: 661,
4405
+ L: 644,
4501
4406
  S: this,
4502
4407
  C: (f, a) => f(...a)
4503
4408
  });
@@ -4515,18 +4420,12 @@ var QueryExecutor = class extends Resource6 {
4515
4420
  break;
4516
4421
  }
4517
4422
  case "incoming": {
4518
- const indexHits = await this._indexer.execQuery({
4519
- typenames: [],
4520
- inverted: false,
4521
- graph: {
4522
- kind: "inbound-reference",
4523
- property: step.traversal.property,
4524
- anchors: workingSet.map((item) => item.objectId)
4525
- }
4526
- });
4527
- trace6.indexHits += indexHits.length;
4423
+ const beginIndexQuery = performance.now();
4424
+ const metas = await this._queryIncomingReferencesFromSqlIndex(workingSet, step.traversal.property);
4425
+ trace6.indexHits += metas.length;
4426
+ trace6.indexQueryTime += performance.now() - beginIndexQuery;
4528
4427
  const documentLoadStart = performance.now();
4529
- const results = await this._loadDocumentsAfterIndexQuery(indexHits);
4428
+ const results = await this._loadDocumentsAfterSqlQuery(metas);
4530
4429
  trace6.documentsLoaded += results.length;
4531
4430
  trace6.documentLoadTime += performance.now() - documentLoadStart;
4532
4431
  newWorkingSet.push(...results.filter(isNonNullable3));
@@ -4542,6 +4441,9 @@ var QueryExecutor = class extends Resource6 {
4542
4441
  case "relation-to-target": {
4543
4442
  const refs = workingSet.map((item) => {
4544
4443
  const dxn = step.traversal.direction === "relation-to-source" ? QueryItem.getRelationSource(item) : QueryItem.getRelationTarget(item);
4444
+ if (!dxn) {
4445
+ return null;
4446
+ }
4545
4447
  try {
4546
4448
  return {
4547
4449
  ref: DXN.parse(dxn),
@@ -4552,7 +4454,7 @@ var QueryExecutor = class extends Resource6 {
4552
4454
  ref: dxn
4553
4455
  }, {
4554
4456
  F: __dxlog_file13,
4555
- L: 720,
4457
+ L: 700,
4556
4458
  S: this,
4557
4459
  C: (f, a) => f(...a)
4558
4460
  });
@@ -4570,18 +4472,12 @@ var QueryExecutor = class extends Resource6 {
4570
4472
  }
4571
4473
  case "source-to-relation":
4572
4474
  case "target-to-relation": {
4573
- const indexHits = await this._indexer.execQuery({
4574
- typenames: [],
4575
- inverted: false,
4576
- graph: {
4577
- kind: step.traversal.direction === "source-to-relation" ? "relation-source" : "relation-target",
4578
- anchors: workingSet.map((item) => item.objectId),
4579
- property: null
4580
- }
4581
- });
4582
- trace6.indexHits += indexHits.length;
4475
+ const beginIndexQuery = performance.now();
4476
+ const metas = await this._queryRelationsFromSqlIndex(workingSet, step.traversal.direction === "source-to-relation" ? "source" : "target");
4477
+ trace6.indexHits += metas.length;
4478
+ trace6.indexQueryTime += performance.now() - beginIndexQuery;
4583
4479
  const documentLoadStart = performance.now();
4584
- const results = await this._loadDocumentsAfterIndexQuery(indexHits);
4480
+ const results = await this._loadDocumentsAfterSqlQuery(metas);
4585
4481
  trace6.documentsLoaded += results.length;
4586
4482
  trace6.documentLoadTime += performance.now() - documentLoadStart;
4587
4483
  newWorkingSet.push(...results.filter(isNonNullable3));
@@ -4591,6 +4487,84 @@ var QueryExecutor = class extends Resource6 {
4591
4487
  }
4592
4488
  break;
4593
4489
  }
4490
+ case "HierarchyTraversal": {
4491
+ switch (step.traversal.direction) {
4492
+ case "to-parent": {
4493
+ const refs = workingSet.map((item) => {
4494
+ if (!item.doc) {
4495
+ return null;
4496
+ }
4497
+ const ref = ObjectStructure.getParent(item.doc);
4498
+ if (!EncodedReference.isEncodedReference(ref)) {
4499
+ return null;
4500
+ }
4501
+ try {
4502
+ return {
4503
+ ref: DXN.parse(ref["/"]),
4504
+ spaceId: item.spaceId
4505
+ };
4506
+ } catch {
4507
+ log10.warn("invalid parent reference", {
4508
+ ref: ref["/"]
4509
+ }, {
4510
+ F: __dxlog_file13,
4511
+ L: 760,
4512
+ S: this,
4513
+ C: (f, a) => f(...a)
4514
+ });
4515
+ return null;
4516
+ }
4517
+ }).filter(isNonNullable3);
4518
+ const beginLoad = performance.now();
4519
+ const items = await Promise.all(refs.map(({ ref, spaceId }) => this._loadFromDXN(ref, {
4520
+ sourceSpaceId: spaceId
4521
+ })));
4522
+ trace6.documentLoadTime += performance.now() - beginLoad;
4523
+ newWorkingSet.push(...items.filter(isNonNullable3));
4524
+ trace6.objectCount = newWorkingSet.length;
4525
+ break;
4526
+ }
4527
+ case "to-children": {
4528
+ const bySpace = /* @__PURE__ */ new Map();
4529
+ for (const item of workingSet) {
4530
+ const existing = bySpace.get(item.spaceId);
4531
+ if (existing) {
4532
+ existing.push(item.objectId);
4533
+ } else {
4534
+ bySpace.set(item.spaceId, [
4535
+ item.objectId
4536
+ ]);
4537
+ }
4538
+ }
4539
+ const allChildren = [];
4540
+ for (const [spaceId, parentIds] of bySpace) {
4541
+ const children = await this._runInRuntime(this._indexEngine.queryChildren({
4542
+ spaceId: [
4543
+ spaceId
4544
+ ],
4545
+ parentIds
4546
+ }));
4547
+ for (const child of children) {
4548
+ allChildren.push({
4549
+ spaceId,
4550
+ objectId: child.objectId
4551
+ });
4552
+ }
4553
+ }
4554
+ trace6.indexHits += allChildren.length;
4555
+ const documentLoadStart = performance.now();
4556
+ const results = await Promise.all(allChildren.map(({ spaceId, objectId }) => this._loadFromDXN(DXN.fromLocalObjectId(objectId), {
4557
+ sourceSpaceId: spaceId
4558
+ })));
4559
+ trace6.documentsLoaded += results.filter(isNonNullable3).length;
4560
+ trace6.documentLoadTime += performance.now() - documentLoadStart;
4561
+ newWorkingSet.push(...results.filter(isNonNullable3));
4562
+ trace6.objectCount = newWorkingSet.length;
4563
+ break;
4564
+ }
4565
+ }
4566
+ break;
4567
+ }
4594
4568
  default:
4595
4569
  throw new Error(`Unknown traversal type: ${step.traversal._tag}`);
4596
4570
  }
@@ -4732,49 +4706,166 @@ var QueryExecutor = class extends Resource6 {
4732
4706
  }
4733
4707
  return String(aValue).localeCompare(String(bValue));
4734
4708
  }
4735
- async _loadDocumentsAfterIndexQuery(indexHits) {
4736
- return Promise.all(indexHits.map(async (hit) => {
4737
- return this._loadFromIndexHit(hit);
4709
+ async _runInRuntime(effect) {
4710
+ const runtimeProvider = this._runtime;
4711
+ invariant10(runtimeProvider, "SQL runtime is required.", {
4712
+ F: __dxlog_file13,
4713
+ L: 983,
4714
+ S: this,
4715
+ A: [
4716
+ "runtimeProvider",
4717
+ "'SQL runtime is required.'"
4718
+ ]
4719
+ });
4720
+ const runtime = await runAndForwardErrors(runtimeProvider);
4721
+ return await unwrapExit(await effect.pipe(Runtime.runPromiseExit(runtime)));
4722
+ }
4723
+ async _queryAllFromSqlIndex(spaceIds) {
4724
+ return await this._runInRuntime(this._indexEngine.queryAll({
4725
+ spaceIds
4726
+ }));
4727
+ }
4728
+ async _queryTypesFromSqlIndex(spaceIds, typeDxns, inverted) {
4729
+ return await this._runInRuntime(this._indexEngine.queryTypes({
4730
+ spaceIds,
4731
+ typeDxns,
4732
+ inverted
4738
4733
  }));
4739
4734
  }
4735
+ async _queryIncomingReferencesFromSqlIndex(workingSet, property) {
4736
+ const anchorDxns = workingSet.map((item) => DXN.fromLocalObjectId(item.objectId).toString());
4737
+ const rows = (await Promise.all(anchorDxns.map((targetDxn) => this._runInRuntime(this._indexEngine.queryReverseRef({
4738
+ targetDxn
4739
+ }))))).flat();
4740
+ const recordIds = rows.filter((row) => {
4741
+ if (property === null) {
4742
+ return true;
4743
+ }
4744
+ const queryPath = EscapedPropPath.unescape(property);
4745
+ const rowPath = EscapedPropPath.unescape(row.propPath);
4746
+ return _QueryExecutor._matchesReferencePropertyPath(rowPath, queryPath);
4747
+ }).map((row) => row.recordId);
4748
+ const uniqueRecordIds = Array.from(new Set(recordIds));
4749
+ return await this._runInRuntime(this._indexEngine.lookupByRecordIds(uniqueRecordIds));
4750
+ }
4740
4751
  /**
4741
- * Space key hex -> SpaceId.
4752
+ * Matches a reverse-reference row path against a query property path.
4753
+ * Allows numeric segments in the row path (array indices) that are not present in the query.
4754
+ *
4755
+ * Examples:
4756
+ * - query: ['assignee'] matches row: ['assignee'] and ['assignee', '0'].
4757
+ * - query: ['items', 'assignee'] matches row: ['items', '0', 'assignee'].
4758
+ * - query: ['a', 'b'] does NOT match row: ['a'].
4759
+ * - query: ['a'] does NOT match row: ['a', 'b'].
4742
4760
  */
4743
- _spaceIdCache = /* @__PURE__ */ new Map();
4744
- async _loadFromIndexHit(hit) {
4745
- const { objectId, documentId, spaceKey: spaceKeyInIndex } = objectPointerCodec3.decode(hit.id);
4746
- const handle = await this._automergeHost.loadDoc(Context5.default(void 0, {
4761
+ static _matchesReferencePropertyPath(rowPath, queryPath) {
4762
+ const isNumericSegment = (segment) => /^[0-9]+$/.test(segment);
4763
+ let i = 0;
4764
+ let j = 0;
4765
+ while (i < queryPath.length && j < rowPath.length) {
4766
+ if (rowPath[j] === queryPath[i]) {
4767
+ i++;
4768
+ j++;
4769
+ continue;
4770
+ }
4771
+ if (isNumericSegment(rowPath[j])) {
4772
+ j++;
4773
+ continue;
4774
+ }
4775
+ return false;
4776
+ }
4777
+ if (i !== queryPath.length) {
4778
+ return false;
4779
+ }
4780
+ for (; j < rowPath.length; j++) {
4781
+ if (!isNumericSegment(rowPath[j])) {
4782
+ return false;
4783
+ }
4784
+ }
4785
+ return true;
4786
+ }
4787
+ async _queryRelationsFromSqlIndex(workingSet, endpoint) {
4788
+ const anchorDxns = workingSet.map((item) => DXN.fromLocalObjectId(item.objectId).toString());
4789
+ return await this._runInRuntime(this._indexEngine.queryRelations({
4790
+ endpoint,
4791
+ anchorDxns
4792
+ }));
4793
+ }
4794
+ async _loadDocumentsAfterSqlQuery(metas) {
4795
+ const snapshotMap = await this._loadQueueSnapshotMap(metas);
4796
+ return await Promise.all(metas.map(async (meta) => {
4797
+ if (meta.documentId) {
4798
+ return this._loadFromAutomerge(meta);
4799
+ }
4800
+ if (meta.queueId) {
4801
+ return this._loadFromQueue(meta, snapshotMap);
4802
+ }
4803
+ return null;
4804
+ }));
4805
+ }
4806
+ async _loadQueueSnapshotMap(metas) {
4807
+ const queueMetas = metas.filter((meta) => !meta.documentId && !!meta.queueId);
4808
+ if (queueMetas.length === 0) {
4809
+ return /* @__PURE__ */ new Map();
4810
+ }
4811
+ const snapshots = await this._runInRuntime(this._indexEngine.querySnapshotsJSON(queueMetas.map((meta) => meta.recordId)));
4812
+ return new Map(snapshots.map((s) => [
4813
+ s.recordId,
4814
+ s.snapshot
4815
+ ]));
4816
+ }
4817
+ /**
4818
+ * Loads a queue-backed object from an indexed snapshot (by `recordId`).
4819
+ * Returns `null` when the snapshot is missing or is not a JSON object.
4820
+ */
4821
+ _loadFromQueue(meta, snapshotMap) {
4822
+ const snapshot = snapshotMap.get(meta.recordId);
4823
+ if (!snapshot || typeof snapshot !== "object") {
4824
+ return null;
4825
+ }
4826
+ return {
4827
+ objectId: meta.objectId,
4828
+ spaceId: meta.spaceId,
4829
+ queueId: meta.queueId,
4830
+ queueNamespace: "data",
4831
+ documentId: null,
4832
+ doc: null,
4833
+ data: snapshot,
4834
+ rank: 1
4835
+ };
4836
+ }
4837
+ /**
4838
+ * Loads a document-backed object from an Automerge `DatabaseDirectory`.
4839
+ * Returns `null` if the document can't be loaded, the inline object isn't present, or if the meta does not have a
4840
+ * document id (e.g. queue-backed objects).
4841
+ */
4842
+ async _loadFromAutomerge(meta) {
4843
+ if (!meta.documentId) {
4844
+ return null;
4845
+ }
4846
+ const handle = await this._automergeHost.loadDoc(Context4.default(void 0, {
4747
4847
  F: __dxlog_file13,
4748
- L: 942
4749
- }), documentId, {
4848
+ L: 1145
4849
+ }), meta.documentId, {
4750
4850
  fetchFromNetwork: true
4751
4851
  });
4752
4852
  const doc = handle.doc();
4753
4853
  if (!doc) {
4754
4854
  return null;
4755
4855
  }
4756
- const spaceKey = spaceKeyInIndex ?? DatabaseDirectory4.getSpaceKey(doc);
4757
- if (!spaceKey) {
4758
- return null;
4759
- }
4760
- let spaceId = this._spaceIdCache.get(spaceKey);
4761
- if (!spaceId) {
4762
- spaceId = await createIdFromSpaceKey(PublicKey4.from(spaceKey));
4763
- this._spaceIdCache.set(spaceKey, spaceId);
4764
- }
4765
- const object = DatabaseDirectory4.getInlineObject(doc, objectId);
4856
+ const object = DatabaseDirectory3.getInlineObject(doc, meta.objectId);
4766
4857
  if (!object) {
4767
4858
  return null;
4768
4859
  }
4769
4860
  return {
4770
- objectId,
4771
- documentId,
4772
- spaceId,
4861
+ objectId: meta.objectId,
4862
+ documentId: meta.documentId,
4863
+ spaceId: meta.spaceId,
4773
4864
  queueId: null,
4774
4865
  queueNamespace: null,
4775
- data: null,
4776
4866
  doc: object,
4777
- rank: hit.rank
4867
+ data: null,
4868
+ rank: 1
4778
4869
  };
4779
4870
  }
4780
4871
  async _loadFromDXN(dxn, { sourceSpaceId }) {
@@ -4784,7 +4875,7 @@ var QueryExecutor = class extends Resource6 {
4784
4875
  dxn
4785
4876
  }, {
4786
4877
  F: __dxlog_file13,
4787
- L: 981,
4878
+ L: 1174,
4788
4879
  S: this,
4789
4880
  C: (f, a) => f(...a)
4790
4881
  });
@@ -4797,7 +4888,7 @@ var QueryExecutor = class extends Resource6 {
4797
4888
  spaceId
4798
4889
  }, {
4799
4890
  F: __dxlog_file13,
4800
- L: 989,
4891
+ L: 1182,
4801
4892
  S: this,
4802
4893
  C: (f, a) => f(...a)
4803
4894
  });
@@ -4809,13 +4900,13 @@ var QueryExecutor = class extends Resource6 {
4809
4900
  spaceId
4810
4901
  }, {
4811
4902
  F: __dxlog_file13,
4812
- L: 994,
4903
+ L: 1187,
4813
4904
  S: this,
4814
4905
  C: (f, a) => f(...a)
4815
4906
  });
4816
4907
  return null;
4817
4908
  }
4818
- const inlineObject = DatabaseDirectory4.getInlineObject(dbDirectory, echoDxn.echoId);
4909
+ const inlineObject = DatabaseDirectory3.getInlineObject(dbDirectory, echoDxn.echoId);
4819
4910
  if (inlineObject) {
4820
4911
  return {
4821
4912
  objectId: echoDxn.echoId,
@@ -4828,13 +4919,13 @@ var QueryExecutor = class extends Resource6 {
4828
4919
  rank: 1
4829
4920
  };
4830
4921
  }
4831
- const link = DatabaseDirectory4.getLink(dbDirectory, echoDxn.echoId);
4922
+ const link = DatabaseDirectory3.getLink(dbDirectory, echoDxn.echoId);
4832
4923
  if (!link) {
4833
4924
  return null;
4834
4925
  }
4835
- const handle = await this._automergeHost.loadDoc(Context5.default(void 0, {
4926
+ const handle = await this._automergeHost.loadDoc(Context4.default(void 0, {
4836
4927
  F: __dxlog_file13,
4837
- L: 1017
4928
+ L: 1210
4838
4929
  }), link, {
4839
4930
  fetchFromNetwork: true
4840
4931
  });
@@ -4842,7 +4933,7 @@ var QueryExecutor = class extends Resource6 {
4842
4933
  if (!doc) {
4843
4934
  return null;
4844
4935
  }
4845
- const object = DatabaseDirectory4.getInlineObject(doc, echoDxn.echoId);
4936
+ const object = DatabaseDirectory3.getInlineObject(doc, echoDxn.echoId);
4846
4937
  if (!object) {
4847
4938
  return null;
4848
4939
  }
@@ -4857,6 +4948,136 @@ var QueryExecutor = class extends Resource6 {
4857
4948
  rank: 1
4858
4949
  };
4859
4950
  }
4951
+ async _getTransitiveDeletionState(item, remainingDepth) {
4952
+ const strongDeps = [
4953
+ QueryItem.getParent(item),
4954
+ QueryItem.getRelationSource(item),
4955
+ QueryItem.getRelationTarget(item)
4956
+ ].filter((x) => x !== void 0);
4957
+ if (strongDeps.length === 0) {
4958
+ return false;
4959
+ }
4960
+ const strongDepStates = await Promise.all(strongDeps.map(async (dxn) => {
4961
+ const dep = await this._loadFromDXN(DXN.parse(dxn), {
4962
+ sourceSpaceId: item.spaceId
4963
+ });
4964
+ if (!dep) {
4965
+ return false;
4966
+ }
4967
+ if (QueryItem.isDeleted(dep)) {
4968
+ return true;
4969
+ }
4970
+ if (remainingDepth > 0) {
4971
+ return this._getTransitiveDeletionState(dep, remainingDepth - 1);
4972
+ }
4973
+ return false;
4974
+ }));
4975
+ return strongDepStates.some((x) => x);
4976
+ }
4977
+ };
4978
+ var prettyFilter = (filter2) => {
4979
+ switch (filter2.type) {
4980
+ case "object": {
4981
+ const parts = [];
4982
+ if (filter2.typename !== null) {
4983
+ parts.push(String(filter2.typename));
4984
+ }
4985
+ if (filter2.id !== void 0 && filter2.id.length > 0) {
4986
+ parts.push(`id: [${filter2.id.join(", ")}]`);
4987
+ }
4988
+ const propEntries = Object.entries(filter2.props);
4989
+ if (propEntries.length > 0) {
4990
+ const propsStr = propEntries.map(([k, v]) => `${k}: ${prettyFilter(v)}`).join(", ");
4991
+ parts.push(`{ ${propsStr} }`);
4992
+ }
4993
+ if (filter2.foreignKeys !== void 0 && filter2.foreignKeys.length > 0) {
4994
+ parts.push(`foreignKeys: [${filter2.foreignKeys.map((fk) => JSON.stringify(fk)).join(", ")}]`);
4995
+ }
4996
+ return parts.length > 0 ? `Filter.type(${parts.join(", ")})` : "Filter.everything()";
4997
+ }
4998
+ case "compare":
4999
+ return `Filter.${filter2.operator}(${JSON.stringify(filter2.value)})`;
5000
+ case "in":
5001
+ return `Filter.in([${filter2.values.map((v) => JSON.stringify(v)).join(", ")}])`;
5002
+ case "contains":
5003
+ return `Filter.contains(${JSON.stringify(filter2.value)})`;
5004
+ case "tag":
5005
+ return `Filter.tag(${JSON.stringify(filter2.tag)})`;
5006
+ case "range":
5007
+ return `Filter.range(${JSON.stringify(filter2.from)}, ${JSON.stringify(filter2.to)})`;
5008
+ case "text-search":
5009
+ return filter2.searchKind ? `Filter.textSearch(${JSON.stringify(filter2.text)}, ${JSON.stringify(filter2.searchKind)})` : `Filter.textSearch(${JSON.stringify(filter2.text)})`;
5010
+ case "not":
5011
+ return `Filter.not(${prettyFilter(filter2.filter)})`;
5012
+ case "and":
5013
+ return `Filter.and(${filter2.filters.map(prettyFilter).join(", ")})`;
5014
+ case "or":
5015
+ return `Filter.or(${filter2.filters.map(prettyFilter).join(", ")})`;
5016
+ }
5017
+ };
5018
+ var prettyQuery = (query) => {
5019
+ switch (query.type) {
5020
+ case "select":
5021
+ return `Query.select(${prettyFilter(query.filter)})`;
5022
+ case "filter":
5023
+ return `${prettyQuery(query.selection)}.select(${prettyFilter(query.filter)})`;
5024
+ case "reference-traversal":
5025
+ return `${prettyQuery(query.anchor)}.reference(${JSON.stringify(query.property)})`;
5026
+ case "incoming-references": {
5027
+ const args = [];
5028
+ if (query.typename !== null) {
5029
+ args.push(String(query.typename));
5030
+ }
5031
+ if (query.property !== null) {
5032
+ args.push(JSON.stringify(query.property));
5033
+ }
5034
+ return `${prettyQuery(query.anchor)}.referencedBy(${args.join(", ")})`;
5035
+ }
5036
+ case "relation": {
5037
+ const method = query.direction === "outgoing" ? "sourceOf" : query.direction === "incoming" ? "targetOf" : "relationOf";
5038
+ const filterStr = query.filter !== void 0 ? prettyFilter(query.filter) : "";
5039
+ return `${prettyQuery(query.anchor)}.${method}(${filterStr})`;
5040
+ }
5041
+ case "relation-traversal":
5042
+ return `${prettyQuery(query.anchor)}.${query.direction}()`;
5043
+ case "hierarchy-traversal":
5044
+ return query.direction === "to-parent" ? `${prettyQuery(query.anchor)}.parent()` : `${prettyQuery(query.anchor)}.children()`;
5045
+ case "union":
5046
+ return `Query.all(${query.queries.map(prettyQuery).join(", ")})`;
5047
+ case "set-difference":
5048
+ return `Query.without(${prettyQuery(query.source)}, ${prettyQuery(query.exclude)})`;
5049
+ case "order": {
5050
+ const orders = query.order.map((o) => {
5051
+ if (o.kind === "natural") {
5052
+ return "Order.natural()";
5053
+ } else if (o.kind === "rank") {
5054
+ return `Order.rank(${JSON.stringify(o.direction)})`;
5055
+ } else {
5056
+ return `Order.property(${JSON.stringify(o.property)}, ${JSON.stringify(o.direction)})`;
5057
+ }
5058
+ });
5059
+ return `${prettyQuery(query.query)}.orderBy(${orders.join(", ")})`;
5060
+ }
5061
+ case "options": {
5062
+ const opts = query.options;
5063
+ const parts = [];
5064
+ if (opts.spaceIds !== void 0) {
5065
+ parts.push(`spaceIds: [${opts.spaceIds.map((s) => JSON.stringify(s)).join(", ")}]`);
5066
+ }
5067
+ if (opts.queues !== void 0) {
5068
+ parts.push(`queues: [${opts.queues.map(String).join(", ")}]`);
5069
+ }
5070
+ if (opts.deleted !== void 0) {
5071
+ parts.push(`deleted: ${JSON.stringify(opts.deleted)}`);
5072
+ }
5073
+ if (opts.allQueuesFromSpaces !== void 0) {
5074
+ parts.push(`allQueuesFromSpaces: ${opts.allQueuesFromSpaces}`);
5075
+ }
5076
+ return `${prettyQuery(query.query)}.options({ ${parts.join(", ")} })`;
5077
+ }
5078
+ case "limit":
5079
+ return `${prettyQuery(query.query)}.limit(${query.limit})`;
5080
+ }
4860
5081
  };
4861
5082
 
4862
5083
  // src/db-host/query-service.ts
@@ -4890,30 +5111,30 @@ var QueryServiceImpl = class extends Resource7 {
4890
5111
  });
4891
5112
  }
4892
5113
  async _open() {
4893
- this._params.indexer.updated.on(this._ctx, () => this.invalidateQueries());
4894
5114
  this._updateQueries = new DeferredTask2(this._ctx, this._executeQueries.bind(this));
4895
5115
  }
4896
5116
  async _close() {
4897
5117
  await this._updateQueries.join();
4898
5118
  await Promise.all(Array.from(this._queries).map((query) => query.close()));
4899
5119
  }
4900
- async setConfig(config) {
4901
- await this._params.indexer.setConfig(config);
5120
+ /**
5121
+ * @deprecated No longer needed with SQL-based indexing.
5122
+ */
5123
+ async setConfig() {
5124
+ }
5125
+ /**
5126
+ * @deprecated No longer needed with SQL-based indexing.
5127
+ */
5128
+ async reindex() {
5129
+ log11.warn("reindex() is deprecated and no longer has any effect", void 0, {
5130
+ F: __dxlog_file14,
5131
+ L: 104,
5132
+ S: this,
5133
+ C: (f, a) => f(...a)
5134
+ });
4902
5135
  }
4903
5136
  execQuery(request) {
4904
5137
  return new Stream2(({ next, close, ctx }) => {
4905
- if (this._params.indexer.config?.enabled !== true) {
4906
- log11.error("indexer is disabled", {
4907
- config: this._params.indexer.config
4908
- }, {
4909
- F: __dxlog_file14,
4910
- L: 107,
4911
- S: this,
4912
- C: (f, a) => f(...a)
4913
- });
4914
- close();
4915
- return;
4916
- }
4917
5138
  const queryEntry = this._createQuery(ctx, request, next, close, close);
4918
5139
  scheduleMicroTask(ctx, async () => {
4919
5140
  await queryEntry.executor.open();
@@ -4924,43 +5145,6 @@ var QueryServiceImpl = class extends Resource7 {
4924
5145
  });
4925
5146
  }
4926
5147
  /**
4927
- * Re-index all loaded documents.
4928
- */
4929
- async reindex() {
4930
- log11("Reindexing all documents...", void 0, {
4931
- F: __dxlog_file14,
4932
- L: 126,
4933
- S: this,
4934
- C: (f, a) => f(...a)
4935
- });
4936
- const iterator = createDocumentsIterator(this._params.automergeHost);
4937
- const ids = /* @__PURE__ */ new Map();
4938
- for await (const documents of iterator()) {
4939
- for (const { id, heads } of documents) {
4940
- ids.set(id, heads);
4941
- }
4942
- if (ids.size % 100 === 0) {
4943
- log11("Collected documents...", {
4944
- count: ids.size
4945
- }, {
4946
- F: __dxlog_file14,
4947
- L: 134,
4948
- S: this,
4949
- C: (f, a) => f(...a)
4950
- });
4951
- }
4952
- }
4953
- log11("Marking all documents as dirty...", {
4954
- count: ids.size
4955
- }, {
4956
- F: __dxlog_file14,
4957
- L: 138,
4958
- S: this,
4959
- C: (f, a) => f(...a)
4960
- });
4961
- await this._params.indexer.reindex(ids);
4962
- }
4963
- /**
4964
5148
  * Schedule re-execution of all queries.
4965
5149
  */
4966
5150
  invalidateQueries() {
@@ -4973,8 +5157,7 @@ var QueryServiceImpl = class extends Resource7 {
4973
5157
  const parsedQuery = QueryAST.Query.pipe(Schema.decodeUnknownSync)(JSON.parse(request.query));
4974
5158
  const queryEntry = {
4975
5159
  executor: new QueryExecutor({
4976
- indexer: this._params.indexer,
4977
- indexer2: this._params.indexer2,
5160
+ indexEngine: this._params.indexEngine,
4978
5161
  runtime: this._params.runtime,
4979
5162
  automergeHost: this._params.automergeHost,
4980
5163
  queryId: request.queryId ?? raise(new Error("query id required")),
@@ -5022,7 +5205,7 @@ var QueryServiceImpl = class extends Resource7 {
5022
5205
  } catch (err) {
5023
5206
  log11.catch(err, void 0, {
5024
5207
  F: __dxlog_file14,
5025
- L: 211,
5208
+ L: 187,
5026
5209
  S: this,
5027
5210
  C: (f, a) => f(...a)
5028
5211
  });
@@ -5033,7 +5216,7 @@ var QueryServiceImpl = class extends Resource7 {
5033
5216
  duration: performance.now() - begin
5034
5217
  }, {
5035
5218
  F: __dxlog_file14,
5036
- L: 215,
5219
+ L: 191,
5037
5220
  S: this,
5038
5221
  C: (f, a) => f(...a)
5039
5222
  });
@@ -5050,69 +5233,14 @@ _ts_decorate5([
5050
5233
  QueryServiceImpl = _ts_decorate5([
5051
5234
  trace4.resource()
5052
5235
  ], QueryServiceImpl);
5053
- var createDocumentsIterator = (automergeHost) => (
5054
- /**
5055
- * Recursively get all object data blobs from loaded documents from Automerge Repo.
5056
- */
5057
- // TODO(mykola): Unload automerge handles after usage.
5058
- async function* getAllDocuments() {
5059
- const visited = /* @__PURE__ */ new Set();
5060
- async function* getObjectsFromHandle(handle) {
5061
- if (visited.has(handle.documentId) || !handle.isReady()) {
5062
- return;
5063
- }
5064
- const doc = handle.doc();
5065
- const spaceKey = DatabaseDirectory5.getSpaceKey(doc) ?? void 0;
5066
- if (doc.objects) {
5067
- yield Object.entries(doc.objects).map(([objectId, object]) => {
5068
- return {
5069
- id: objectPointerCodec4.encode({
5070
- documentId: handle.documentId,
5071
- objectId,
5072
- spaceKey
5073
- }),
5074
- object,
5075
- heads: getHeads3(doc)
5076
- };
5077
- });
5078
- }
5079
- if (doc.links) {
5080
- for (const id of Object.values(doc.links)) {
5081
- const urlString = id.toString();
5082
- if (visited.has(urlString)) {
5083
- continue;
5084
- }
5085
- const linkHandle = await automergeHost.loadDoc(Context6.default(void 0, {
5086
- F: __dxlog_file14,
5087
- L: 256
5088
- }), urlString, {
5089
- fetchFromNetwork: true
5090
- });
5091
- for await (const result of getObjectsFromHandle(linkHandle)) {
5092
- yield result;
5093
- }
5094
- }
5095
- }
5096
- visited.add(handle.documentId);
5097
- }
5098
- for (const handle of Object.values(automergeHost.handles)) {
5099
- if (visited.has(handle.documentId)) {
5100
- continue;
5101
- }
5102
- for await (const result of getObjectsFromHandle(handle)) {
5103
- yield result;
5104
- }
5105
- visited.add(handle.documentId);
5106
- }
5107
- }
5108
- );
5109
5236
 
5110
5237
  // src/db-host/queue-data-source.ts
5111
5238
  import * as Effect3 from "effect/Effect";
5239
+ import { EchoFeedCodec as EchoFeedCodec2 } from "@dxos/echo-protocol";
5112
5240
  import { RuntimeProvider as RuntimeProvider2 } from "@dxos/effect";
5113
- import { FeedCursor } from "@dxos/feed";
5114
5241
  import { failedInvariant } from "@dxos/invariant";
5115
5242
  import { log as log12 } from "@dxos/log";
5243
+ import { FeedProtocol as FeedProtocol2 } from "@dxos/protocols";
5116
5244
  var __dxlog_file15 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/queue-data-source.ts";
5117
5245
  var QueueDataSource = class {
5118
5246
  sourceName = "queue";
@@ -5152,21 +5280,17 @@ var QueueDataSource = class {
5152
5280
  updatedCursors.push(cursor);
5153
5281
  continue;
5154
5282
  }
5155
- const currentCursor = typeof cursor.cursor === "string" && cursor.cursor !== "" ? FeedCursor.make(cursor.cursor) : void 0;
5283
+ const currentCursor = typeof cursor.cursor === "string" && cursor.cursor !== "" ? FeedProtocol2.FeedCursor.make(cursor.cursor) : void 0;
5156
5284
  try {
5157
5285
  const result = yield* this._feedStore.query({
5158
5286
  spaceId: cursor.spaceId,
5287
+ feedNamespace: FeedProtocol2.WellKnownNamespaces.data,
5159
5288
  cursor: currentCursor,
5160
- query: {
5161
- // Query all feeds in data namespace
5162
- feedNamespace: "data"
5163
- },
5164
5289
  limit: remainingLimit
5165
5290
  });
5166
5291
  for (const block of result.blocks) {
5167
5292
  try {
5168
- const dataString = new TextDecoder().decode(block.data);
5169
- const data = JSON.parse(dataString);
5293
+ const data = EchoFeedCodec2.decode(block.data);
5170
5294
  objects.push({
5171
5295
  spaceId: cursor.spaceId,
5172
5296
  queueId: block.feedId ?? failedInvariant(),
@@ -5216,26 +5340,26 @@ var QueueDataSource = class {
5216
5340
  import { interpretAsDocumentId as interpretAsDocumentId3 } from "@automerge/automerge-repo";
5217
5341
  import isEqual from "lodash.isequal";
5218
5342
  import { Event as Event4, UpdateScheduler as UpdateScheduler3 } from "@dxos/async";
5219
- import { Context as Context7, LifecycleState as LifecycleState4, Resource as Resource8 } from "@dxos/context";
5220
- import { invariant as invariant13 } from "@dxos/invariant";
5343
+ import { Context as Context5, LifecycleState as LifecycleState4, Resource as Resource8 } from "@dxos/context";
5344
+ import { invariant as invariant12 } from "@dxos/invariant";
5221
5345
 
5222
5346
  // src/db-host/database-root.ts
5223
5347
  import { interpretAsDocumentId as interpretAsDocumentId2 } from "@automerge/automerge-repo";
5224
- import { DatabaseDirectory as DatabaseDirectory6, SpaceDocVersion as SpaceDocVersion3 } from "@dxos/echo-protocol";
5225
- import { invariant as invariant12 } from "@dxos/invariant";
5348
+ import { DatabaseDirectory as DatabaseDirectory4, SpaceDocVersion as SpaceDocVersion2 } from "@dxos/echo-protocol";
5349
+ import { invariant as invariant11 } from "@dxos/invariant";
5226
5350
 
5227
5351
  // src/db-host/automerge-metrics.ts
5228
- import * as A5 from "@automerge/automerge";
5352
+ import * as A4 from "@automerge/automerge";
5229
5353
  import { log as log13 } from "@dxos/log";
5230
5354
  var __dxlog_file16 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/automerge-metrics.ts";
5231
5355
  var measureDocMetrics = (doc) => {
5232
- const snapshot = A5.save(doc);
5356
+ const snapshot = A4.save(doc);
5233
5357
  const start = Date.now();
5234
- const temp = A5.load(snapshot);
5358
+ const temp = A4.load(snapshot);
5235
5359
  const end = Date.now();
5236
- A5.free(temp);
5360
+ A4.free(temp);
5237
5361
  const getAllChangesStart = Date.now();
5238
- const mutationCount = A5.getAllChanges(doc).length;
5362
+ const mutationCount = A4.getAllChanges(doc).length;
5239
5363
  const getAllChangesEnd = Date.now();
5240
5364
  if (getAllChangesEnd - getAllChangesStart > 300) {
5241
5365
  log13.warn("getAllChanges took too long", {
@@ -5294,14 +5418,14 @@ var DatabaseRoot = class {
5294
5418
  if (!doc) {
5295
5419
  return null;
5296
5420
  }
5297
- return doc.version ?? SpaceDocVersion3.LEGACY;
5421
+ return doc.version ?? SpaceDocVersion2.LEGACY;
5298
5422
  }
5299
5423
  getSpaceKey() {
5300
5424
  const doc = this.doc();
5301
5425
  if (!doc) {
5302
5426
  return null;
5303
5427
  }
5304
- return DatabaseDirectory6.getSpaceKey(doc);
5428
+ return DatabaseDirectory4.getSpaceKey(doc);
5305
5429
  }
5306
5430
  getInlineObjectCount() {
5307
5431
  const doc = this.doc();
@@ -5319,7 +5443,7 @@ var DatabaseRoot = class {
5319
5443
  }
5320
5444
  getAllLinkedDocuments() {
5321
5445
  const doc = this.doc();
5322
- invariant12(doc, void 0, {
5446
+ invariant11(doc, void 0, {
5323
5447
  F: __dxlog_file17,
5324
5448
  L: 88,
5325
5449
  S: this,
@@ -5366,7 +5490,7 @@ var SpaceStateManager = class extends Resource8 {
5366
5490
  return this._rootBySpace.get(spaceId);
5367
5491
  }
5368
5492
  getRootBySpaceId(spaceId) {
5369
- invariant13(this._lifecycleState === LifecycleState4.OPEN, void 0, {
5493
+ invariant12(this._lifecycleState === LifecycleState4.OPEN, void 0, {
5370
5494
  F: __dxlog_file18,
5371
5495
  L: 48,
5372
5496
  S: this,
@@ -5398,7 +5522,7 @@ var SpaceStateManager = class extends Resource8 {
5398
5522
  this._perRootContext.delete(prevRootId);
5399
5523
  }
5400
5524
  this._rootBySpace.set(spaceId, root.handle.documentId);
5401
- const ctx = new Context7(void 0, {
5525
+ const ctx = new Context5(void 0, {
5402
5526
  F: __dxlog_file18,
5403
5527
  L: 76
5404
5528
  });
@@ -5447,46 +5571,33 @@ var QueueServiceStub = class {
5447
5571
  deleteFromQueue(request) {
5448
5572
  throw new Error("Not available.");
5449
5573
  }
5574
+ syncQueue(request) {
5575
+ throw new Error("Not available.");
5576
+ }
5450
5577
  };
5451
5578
 
5452
5579
  // src/db-host/echo-host.ts
5453
5580
  var __dxlog_file19 = "/__w/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/echo-host.ts";
5454
- var DEFAULT_INDEXING_CONFIG = {
5455
- // TODO(mykola): Enable by default when SQLite indexer is stable.
5456
- fullText: false,
5457
- vector: false
5458
- };
5459
5581
  var EchoHost = class extends Resource9 {
5460
- _indexMetadataStore;
5461
- _indexer;
5462
5582
  _automergeHost;
5463
5583
  _queryService;
5464
5584
  _dataService;
5465
5585
  _spaceStateManager = new SpaceStateManager();
5466
5586
  _echoDataMonitor;
5467
5587
  _automergeDataSource;
5468
- _indexer2;
5469
- _indexConfig;
5588
+ _indexEngine;
5470
5589
  _runtime;
5471
5590
  _feedStore;
5472
5591
  _queueDataSource;
5473
5592
  _updateIndexes;
5474
5593
  _queuesService;
5475
5594
  _indexesUpToDate = false;
5476
- constructor({ kv, localQueues, indexing = {}, peerIdProvider, getSpaceKeyByRootDocumentId, runtime, assignQueuePositions = false }) {
5595
+ constructor({ kv, localQueues, peerIdProvider, getSpaceKeyByRootDocumentId, runtime, assignQueuePositions = false, syncQueue }) {
5477
5596
  super();
5478
- this._indexConfig = {
5479
- ...DEFAULT_INDEXING_CONFIG,
5480
- ...indexing
5481
- };
5482
- this._indexMetadataStore = new IndexMetadataStore({
5483
- db: kv.sublevel("index-metadata")
5484
- });
5485
5597
  this._echoDataMonitor = new EchoDataMonitor();
5486
5598
  this._automergeHost = new AutomergeHost({
5487
5599
  db: kv,
5488
5600
  dataMonitor: this._echoDataMonitor,
5489
- indexMetadataStore: this._indexMetadataStore,
5490
5601
  peerIdProvider,
5491
5602
  getSpaceKeyByRootDocumentId
5492
5603
  });
@@ -5502,54 +5613,24 @@ var EchoHost = class extends Resource9 {
5502
5613
  runtime: this._runtime,
5503
5614
  getSpaceIds: () => this._spaceStateManager.spaceIds
5504
5615
  });
5505
- this._queuesService = new LocalQueueServiceImpl(runtime, this._feedStore);
5616
+ this._queuesService = new LocalQueueServiceImpl(runtime, this._feedStore, syncQueue);
5506
5617
  } else {
5507
5618
  this._queuesService = new QueueServiceStub();
5508
5619
  }
5509
- this._indexer = new Indexer({
5510
- db: kv,
5511
- indexStore: new IndexStore({
5512
- db: kv.sublevel("index-storage")
5513
- }),
5514
- metadataStore: this._indexMetadataStore,
5515
- loadDocuments: createSelectedDocumentsIterator(this._automergeHost),
5516
- indexCooldownTime: false ? 0 : void 0
5517
- });
5518
- void this._indexer.setConfig({
5519
- enabled: true,
5520
- indexes: [
5521
- //
5522
- {
5523
- kind: IndexKind.Kind.SCHEMA_MATCH
5524
- },
5525
- {
5526
- kind: IndexKind.Kind.GRAPH
5527
- },
5528
- ...this._indexConfig.vector ? [
5529
- {
5530
- kind: IndexKind.Kind.VECTOR
5531
- }
5532
- ] : []
5533
- ]
5534
- });
5535
- this._indexer2 = new IndexEngine();
5620
+ this._indexEngine = new IndexEngine();
5536
5621
  this._queryService = new QueryServiceImpl({
5537
5622
  automergeHost: this._automergeHost,
5538
- indexer: this._indexer,
5539
- indexer2: this._indexConfig.fullText ? this._indexer2 : void 0,
5540
- runtime: this._indexConfig.fullText ? this._runtime : void 0,
5623
+ indexEngine: this._indexEngine,
5624
+ runtime: this._runtime,
5541
5625
  spaceStateManager: this._spaceStateManager
5542
5626
  });
5543
5627
  this._dataService = new DataServiceImpl({
5544
5628
  automergeHost: this._automergeHost,
5545
5629
  spaceStateManager: this._spaceStateManager,
5546
5630
  updateIndexes: async () => {
5547
- await this._indexer.updateIndexes();
5548
- if (this._indexConfig.fullText) {
5549
- do {
5550
- await this._updateIndexes.runBlocking();
5551
- } while (!this._indexesUpToDate);
5552
- }
5631
+ do {
5632
+ await this._updateIndexes.runBlocking();
5633
+ } while (!this._indexesUpToDate);
5553
5634
  }
5554
5635
  });
5555
5636
  trace5.diagnostic({
@@ -5590,6 +5671,9 @@ var EchoHost = class extends Resource9 {
5590
5671
  }
5591
5672
  });
5592
5673
  }
5674
+ get spaceIds() {
5675
+ return this._spaceStateManager.spaceIds;
5676
+ }
5593
5677
  get queryService() {
5594
5678
  return this._queryService;
5595
5679
  }
@@ -5602,30 +5686,28 @@ var EchoHost = class extends Resource9 {
5602
5686
  get roots() {
5603
5687
  return this._spaceStateManager.roots;
5604
5688
  }
5689
+ get feedStore() {
5690
+ return this._feedStore;
5691
+ }
5605
5692
  /**
5606
- * New index-core indexer for text and other queries.
5693
+ * Index engine for queries.
5607
5694
  */
5608
- get indexer2() {
5609
- return this._indexer2;
5695
+ get indexEngine() {
5696
+ return this._indexEngine;
5610
5697
  }
5611
5698
  async _open(ctx) {
5612
5699
  await this._automergeHost.open();
5613
- await this._indexer.open(ctx);
5614
5700
  await this._queryService.open(ctx);
5615
5701
  await this._spaceStateManager.open(ctx);
5616
5702
  if (this._feedStore) {
5617
5703
  await RuntimeProvider3.runPromise(this._runtime)(this._feedStore.migrate());
5618
5704
  this._feedStore.onNewBlocks.on(this._ctx, () => {
5619
5705
  this._queryService.invalidateQueries();
5620
- if (this._indexConfig.fullText) {
5621
- this._updateIndexes.schedule();
5622
- }
5706
+ this._updateIndexes.schedule();
5623
5707
  });
5624
5708
  }
5625
- if (this._indexConfig.fullText) {
5626
- await RuntimeProvider3.runPromise(this._runtime)(this._indexer2.migrate());
5627
- this._updateIndexes = new DeferredTask3(this._ctx, this._runUpdateIndexes);
5628
- }
5709
+ await RuntimeProvider3.runPromise(this._runtime)(this._indexEngine.migrate());
5710
+ this._updateIndexes = new DeferredTask3(this._ctx, this._runUpdateIndexes);
5629
5711
  this._spaceStateManager.spaceDocumentListUpdated.on(this._ctx, (e) => {
5630
5712
  if (e.previousRootId) {
5631
5713
  void this._automergeHost.clearLocalCollectionState(deriveCollectionIdFromSpaceId(e.spaceId, e.previousRootId));
@@ -5634,18 +5716,13 @@ var EchoHost = class extends Resource9 {
5634
5716
  });
5635
5717
  this._automergeHost.documentsSaved.on(this._ctx, () => {
5636
5718
  this._queryService.invalidateQueries();
5637
- if (this._indexConfig.fullText) {
5638
- this._updateIndexes.schedule();
5639
- }
5640
- });
5641
- if (this._indexConfig.fullText) {
5642
5719
  this._updateIndexes.schedule();
5643
- }
5720
+ });
5721
+ this._updateIndexes.schedule();
5644
5722
  }
5645
5723
  async _close(ctx) {
5646
5724
  await this._queryService.close(ctx);
5647
5725
  await this._spaceStateManager.close(ctx);
5648
- await this._indexer.close(ctx);
5649
5726
  await this._automergeHost.close();
5650
5727
  }
5651
5728
  /**
@@ -5658,7 +5735,9 @@ var EchoHost = class extends Resource9 {
5658
5735
  * Perform any pending index updates.
5659
5736
  */
5660
5737
  async updateIndexes() {
5661
- await this._indexer.updateIndexes();
5738
+ do {
5739
+ await this._updateIndexes.runBlocking();
5740
+ } while (!this._indexesUpToDate);
5662
5741
  }
5663
5742
  /**
5664
5743
  * Loads the document handle from the repo and waits for it to be ready.
@@ -5679,9 +5758,9 @@ var EchoHost = class extends Resource9 {
5679
5758
  * Create new space root.
5680
5759
  */
5681
5760
  async createSpaceRoot(spaceKey) {
5682
- invariant14(this._lifecycleState === LifecycleState5.OPEN, void 0, {
5761
+ invariant13(this._lifecycleState === LifecycleState5.OPEN, void 0, {
5683
5762
  F: __dxlog_file19,
5684
- L: 342,
5763
+ L: 297,
5685
5764
  S: this,
5686
5765
  A: [
5687
5766
  "this._lifecycleState === LifecycleState.OPEN",
@@ -5690,7 +5769,7 @@ var EchoHost = class extends Resource9 {
5690
5769
  });
5691
5770
  const spaceId = await createIdFromSpaceKey2(spaceKey);
5692
5771
  const automergeRoot = await this._automergeHost.createDoc({
5693
- version: SpaceDocVersion4.CURRENT,
5772
+ version: SpaceDocVersion3.CURRENT,
5694
5773
  access: {
5695
5774
  spaceKey: spaceKey.toHex()
5696
5775
  },
@@ -5707,18 +5786,18 @@ var EchoHost = class extends Resource9 {
5707
5786
  }
5708
5787
  // TODO(dmaretskyi): Change to document id.
5709
5788
  async openSpaceRoot(spaceId, automergeUrl) {
5710
- invariant14(this._lifecycleState === LifecycleState5.OPEN, void 0, {
5789
+ invariant13(this._lifecycleState === LifecycleState5.OPEN, void 0, {
5711
5790
  F: __dxlog_file19,
5712
- L: 361,
5791
+ L: 316,
5713
5792
  S: this,
5714
5793
  A: [
5715
5794
  "this._lifecycleState === LifecycleState.OPEN",
5716
5795
  ""
5717
5796
  ]
5718
5797
  });
5719
- const handle = await this._automergeHost.loadDoc(Context8.default(void 0, {
5798
+ const handle = await this._automergeHost.loadDoc(Context6.default(void 0, {
5720
5799
  F: __dxlog_file19,
5721
- L: 362
5800
+ L: 317
5722
5801
  }), automergeUrl, {
5723
5802
  fetchFromNetwork: true
5724
5803
  });
@@ -5753,21 +5832,18 @@ var EchoHost = class extends Resource9 {
5753
5832
  this._automergeHost.refreshCollection(deriveCollectionIdFromSpaceId(spaceId, root.documentId));
5754
5833
  }
5755
5834
  _runUpdateIndexes = async () => {
5756
- if (!this._indexer2) {
5757
- return;
5758
- }
5759
5835
  let totalUpdated = 0;
5760
5836
  let totalDone = true;
5761
5837
  {
5762
- performance.mark("indexer2.update.automerge:start");
5763
- const { updated, done } = await this._indexer2.update(this._automergeDataSource, {
5838
+ performance.mark("indexEngine.update.automerge:start");
5839
+ const { updated, done } = await this._indexEngine.update(this._automergeDataSource, {
5764
5840
  spaceId: null,
5765
5841
  limit: 50
5766
5842
  }).pipe(RuntimeProvider3.runPromise(this._runtime));
5767
5843
  totalUpdated += updated;
5768
5844
  totalDone &&= done;
5769
5845
  performance.measure("Index Automerge", {
5770
- start: "indexer2.update.automerge:start",
5846
+ start: "indexEngine.update.automerge:start",
5771
5847
  detail: {
5772
5848
  devtools: {
5773
5849
  dataType: "track-entry",
@@ -5785,15 +5861,15 @@ var EchoHost = class extends Resource9 {
5785
5861
  });
5786
5862
  }
5787
5863
  if (this._queueDataSource) {
5788
- performance.mark("indexer2.update.queue:start");
5789
- const { updated, done } = await this._indexer2.update(this._queueDataSource, {
5864
+ performance.mark("indexEngine.update.queue:start");
5865
+ const { updated, done } = await this._indexEngine.update(this._queueDataSource, {
5790
5866
  spaceId: null,
5791
5867
  limit: 50
5792
5868
  }).pipe(RuntimeProvider3.runPromise(this._runtime));
5793
5869
  totalUpdated += updated;
5794
5870
  totalDone &&= done;
5795
5871
  performance.measure("Index Queues", {
5796
- start: "indexer2.update.queue:start",
5872
+ start: "indexEngine.update.queue:start",
5797
5873
  detail: {
5798
5874
  devtools: {
5799
5875
  dataType: "track-entry",
@@ -5810,12 +5886,12 @@ var EchoHost = class extends Resource9 {
5810
5886
  }
5811
5887
  });
5812
5888
  }
5813
- log14.verbose("indexer2 update completed", {
5889
+ log14.verbose("indexEngine update completed", {
5814
5890
  updated: totalUpdated,
5815
5891
  done: totalDone
5816
5892
  }, {
5817
5893
  F: __dxlog_file19,
5818
- L: 452,
5894
+ L: 402,
5819
5895
  S: this,
5820
5896
  C: (f, a) => f(...a)
5821
5897
  });
@@ -5826,6 +5902,9 @@ var EchoHost = class extends Resource9 {
5826
5902
  } else {
5827
5903
  this._indexesUpToDate = true;
5828
5904
  }
5905
+ if (totalUpdated > 0) {
5906
+ this._queryService.invalidateQueries();
5907
+ }
5829
5908
  };
5830
5909
  };
5831
5910
 
@@ -5833,9 +5912,9 @@ var EchoHost = class extends Resource9 {
5833
5912
  import * as Automerge from "@automerge/automerge";
5834
5913
  import { cbor as cbor2 } from "@automerge/automerge-repo";
5835
5914
  import { Mutex, scheduleMicroTask as scheduleMicroTask2, scheduleTask as scheduleTask2 } from "@dxos/async";
5836
- import { Context as Context9, Resource as Resource11 } from "@dxos/context";
5915
+ import { Context as Context7, Resource as Resource11 } from "@dxos/context";
5837
5916
  import { randomUUID } from "@dxos/crypto";
5838
- import { invariant as invariant15 } from "@dxos/invariant";
5917
+ import { invariant as invariant14 } from "@dxos/invariant";
5839
5918
  import { log as log16 } from "@dxos/log";
5840
5919
  import { DocumentCodec, EdgeService } from "@dxos/protocols";
5841
5920
  import { buf } from "@dxos/protocols/buf";
@@ -5999,7 +6078,7 @@ var EchoEdgeReplicator = class {
5999
6078
  C: (f, a) => f(...a)
6000
6079
  });
6001
6080
  this._context = context;
6002
- this._ctx = Context9.default(void 0, {
6081
+ this._ctx = Context7.default(void 0, {
6003
6082
  F: __dxlog_file21,
6004
6083
  L: 76
6005
6084
  });
@@ -6106,7 +6185,7 @@ var EchoEdgeReplicator = class {
6106
6185
  }
6107
6186
  }
6108
6187
  async _openConnection(spaceId, reconnects = 0) {
6109
- invariant15(this._context, void 0, {
6188
+ invariant14(this._context, void 0, {
6110
6189
  F: __dxlog_file21,
6111
6190
  L: 138,
6112
6191
  S: this,
@@ -6115,7 +6194,7 @@ var EchoEdgeReplicator = class {
6115
6194
  ""
6116
6195
  ]
6117
6196
  });
6118
- invariant15(!this._connections.has(spaceId), void 0, {
6197
+ invariant14(!this._connections.has(spaceId), void 0, {
6119
6198
  F: __dxlog_file21,
6120
6199
  L: 139,
6121
6200
  S: this,
@@ -6298,7 +6377,7 @@ var EdgeReplicatorConnection = class extends Resource11 {
6298
6377
  await this._onRemoteDisconnected();
6299
6378
  }
6300
6379
  get peerId() {
6301
- invariant15(this._remotePeerId, "Not connected", {
6380
+ invariant14(this._remotePeerId, "Not connected", {
6302
6381
  F: __dxlog_file21,
6303
6382
  L: 312,
6304
6383
  S: this,
@@ -6458,13 +6537,13 @@ var getMessageInfo = (msg) => {
6458
6537
  };
6459
6538
 
6460
6539
  // src/util.ts
6461
- import { EncodedReference, ObjectStructure as ObjectStructure2 } from "@dxos/echo-protocol";
6540
+ import { EncodedReference as EncodedReference2, ObjectStructure as ObjectStructure2 } from "@dxos/echo-protocol";
6462
6541
  var findInlineObjectOfType = (spaceDoc, typename) => {
6463
6542
  for (const id in spaceDoc.objects ?? {}) {
6464
6543
  const obj = spaceDoc.objects[id];
6465
6544
  const objType = ObjectStructure2.getTypeReference(obj);
6466
6545
  if (objType) {
6467
- const typeDXN = EncodedReference.toDXN(objType);
6546
+ const typeDXN = EncodedReference2.toDXN(objType);
6468
6547
  const typeDXNInfo = typeDXN.asTypeDXN();
6469
6548
  if (typeDXNInfo?.type === typename) {
6470
6549
  return [