@dxos/echo-pipeline 0.6.12 → 0.6.13-main.548ca8d

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 (123) hide show
  1. package/dist/lib/browser/chunk-PESZVYAN.mjs +2050 -0
  2. package/dist/lib/browser/chunk-PESZVYAN.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +3463 -17
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +3 -4
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/node/{chunk-7HHYCGUR.cjs → chunk-6EZVIJNE.cjs} +89 -47
  9. package/dist/lib/node/chunk-6EZVIJNE.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +3440 -35
  11. package/dist/lib/node/index.cjs.map +4 -4
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/testing/index.cjs +11 -12
  14. package/dist/lib/node/testing/index.cjs.map +3 -3
  15. package/dist/lib/{browser/chunk-UKXIJW43.mjs → node-esm/chunk-4LW7MDPZ.mjs} +76 -36
  16. package/dist/lib/node-esm/chunk-4LW7MDPZ.mjs.map +7 -0
  17. package/dist/lib/{browser/chunk-MPWFDDQK.mjs → node-esm/index.mjs} +1702 -335
  18. package/dist/lib/node-esm/index.mjs.map +7 -0
  19. package/dist/lib/node-esm/meta.json +1 -0
  20. package/dist/lib/node-esm/testing/index.mjs +551 -0
  21. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  22. package/dist/types/src/automerge/automerge-host.d.ts +24 -1
  23. package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
  24. package/dist/types/src/automerge/collection-synchronizer.d.ts +2 -0
  25. package/dist/types/src/automerge/collection-synchronizer.d.ts.map +1 -1
  26. package/dist/types/src/automerge/echo-network-adapter.d.ts.map +1 -1
  27. package/dist/types/src/automerge/echo-replicator.d.ts +3 -3
  28. package/dist/types/src/automerge/echo-replicator.d.ts.map +1 -1
  29. package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts +3 -3
  30. package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts.map +1 -1
  31. package/dist/types/src/automerge/mesh-echo-replicator.d.ts.map +1 -1
  32. package/dist/types/src/automerge/space-collection.d.ts +3 -2
  33. package/dist/types/src/automerge/space-collection.d.ts.map +1 -1
  34. package/dist/types/src/db-host/automerge-metrics.d.ts +11 -0
  35. package/dist/types/src/db-host/automerge-metrics.d.ts.map +1 -0
  36. package/dist/types/src/db-host/data-service.d.ts +3 -2
  37. package/dist/types/src/db-host/data-service.d.ts.map +1 -1
  38. package/dist/types/src/db-host/database-root.d.ts +20 -0
  39. package/dist/types/src/db-host/database-root.d.ts.map +1 -0
  40. package/dist/types/src/db-host/documents-iterator.d.ts +7 -0
  41. package/dist/types/src/db-host/documents-iterator.d.ts.map +1 -0
  42. package/dist/types/src/db-host/echo-host.d.ts +73 -0
  43. package/dist/types/src/db-host/echo-host.d.ts.map +1 -0
  44. package/dist/types/src/db-host/index.d.ts +5 -0
  45. package/dist/types/src/db-host/index.d.ts.map +1 -1
  46. package/dist/types/src/db-host/migration.d.ts +8 -0
  47. package/dist/types/src/db-host/migration.d.ts.map +1 -0
  48. package/dist/types/src/db-host/query-service.d.ts +25 -0
  49. package/dist/types/src/db-host/query-service.d.ts.map +1 -0
  50. package/dist/types/src/db-host/query-state.d.ts +41 -0
  51. package/dist/types/src/db-host/query-state.d.ts.map +1 -0
  52. package/dist/types/src/db-host/space-state-manager.d.ts +23 -0
  53. package/dist/types/src/db-host/space-state-manager.d.ts.map +1 -0
  54. package/dist/types/src/edge/echo-edge-replicator.d.ts +23 -0
  55. package/dist/types/src/edge/echo-edge-replicator.d.ts.map +1 -0
  56. package/dist/types/src/edge/echo-edge-replicator.test.d.ts +2 -0
  57. package/dist/types/src/edge/echo-edge-replicator.test.d.ts.map +1 -0
  58. package/dist/types/src/edge/index.d.ts +2 -0
  59. package/dist/types/src/edge/index.d.ts.map +1 -0
  60. package/dist/types/src/index.d.ts +1 -0
  61. package/dist/types/src/index.d.ts.map +1 -1
  62. package/dist/types/src/metadata/metadata-store.d.ts +4 -1
  63. package/dist/types/src/metadata/metadata-store.d.ts.map +1 -1
  64. package/dist/types/src/testing/test-agent-builder.d.ts.map +1 -1
  65. package/dist/types/src/testing/test-replicator.d.ts +4 -4
  66. package/dist/types/src/testing/test-replicator.d.ts.map +1 -1
  67. package/package.json +40 -50
  68. package/src/automerge/automerge-host.test.ts +8 -9
  69. package/src/automerge/automerge-host.ts +46 -7
  70. package/src/automerge/automerge-repo.test.ts +18 -16
  71. package/src/automerge/collection-synchronizer.test.ts +10 -5
  72. package/src/automerge/collection-synchronizer.ts +17 -6
  73. package/src/automerge/echo-data-monitor.test.ts +1 -3
  74. package/src/automerge/echo-network-adapter.test.ts +4 -3
  75. package/src/automerge/echo-network-adapter.ts +5 -4
  76. package/src/automerge/echo-replicator.ts +3 -3
  77. package/src/automerge/mesh-echo-replicator-connection.ts +10 -9
  78. package/src/automerge/mesh-echo-replicator.ts +2 -1
  79. package/src/automerge/space-collection.ts +3 -2
  80. package/src/automerge/storage-adapter.test.ts +2 -3
  81. package/src/db-host/automerge-metrics.ts +38 -0
  82. package/src/db-host/data-service.ts +29 -14
  83. package/src/db-host/database-root.ts +86 -0
  84. package/src/db-host/documents-iterator.ts +73 -0
  85. package/src/db-host/documents-synchronizer.test.ts +2 -2
  86. package/src/db-host/echo-host.ts +257 -0
  87. package/src/db-host/index.ts +6 -1
  88. package/src/db-host/migration.ts +57 -0
  89. package/src/db-host/query-service.ts +208 -0
  90. package/src/db-host/query-state.ts +200 -0
  91. package/src/db-host/space-state-manager.ts +90 -0
  92. package/src/edge/echo-edge-replicator.test.ts +96 -0
  93. package/src/edge/echo-edge-replicator.ts +337 -0
  94. package/src/edge/index.ts +5 -0
  95. package/src/index.ts +1 -0
  96. package/src/metadata/metadata-store.ts +20 -0
  97. package/src/pipeline/pipeline-stress.test.ts +44 -47
  98. package/src/pipeline/pipeline.test.ts +3 -4
  99. package/src/space/control-pipeline.test.ts +2 -3
  100. package/src/space/control-pipeline.ts +10 -1
  101. package/src/space/replication.browser.test.ts +2 -8
  102. package/src/space/space-manager.browser.test.ts +6 -5
  103. package/src/space/space-protocol.browser.test.ts +29 -34
  104. package/src/space/space-protocol.test.ts +29 -27
  105. package/src/space/space.test.ts +28 -11
  106. package/src/testing/test-agent-builder.ts +2 -2
  107. package/src/testing/test-replicator.ts +3 -3
  108. package/dist/lib/browser/chunk-MPWFDDQK.mjs.map +0 -7
  109. package/dist/lib/browser/chunk-UKXIJW43.mjs.map +0 -7
  110. package/dist/lib/browser/chunk-XPCF2V5U.mjs +0 -31
  111. package/dist/lib/browser/chunk-XPCF2V5U.mjs.map +0 -7
  112. package/dist/lib/browser/light.mjs +0 -32
  113. package/dist/lib/browser/light.mjs.map +0 -7
  114. package/dist/lib/node/chunk-5DH4KR2S.cjs +0 -2148
  115. package/dist/lib/node/chunk-5DH4KR2S.cjs.map +0 -7
  116. package/dist/lib/node/chunk-7HHYCGUR.cjs.map +0 -7
  117. package/dist/lib/node/chunk-DZVH7HDD.cjs +0 -43
  118. package/dist/lib/node/chunk-DZVH7HDD.cjs.map +0 -7
  119. package/dist/lib/node/light.cjs +0 -52
  120. package/dist/lib/node/light.cjs.map +0 -7
  121. package/dist/types/src/light.d.ts +0 -4
  122. package/dist/types/src/light.d.ts.map +0 -1
  123. package/src/light.ts +0 -7
@@ -1,8 +1,34 @@
1
- import "@dxos/node-std/globals";
1
+ import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
  import {
3
- Buffer,
4
- createIdFromSpaceKey
5
- } from "./chunk-XPCF2V5U.mjs";
3
+ AuthExtension,
4
+ AuthStatus,
5
+ CredentialRetrieverExtension,
6
+ CredentialServerExtension,
7
+ MOCK_AUTH_PROVIDER,
8
+ MOCK_AUTH_VERIFIER,
9
+ MetadataStore,
10
+ Pipeline,
11
+ Space,
12
+ SpaceManager,
13
+ SpaceProtocol,
14
+ SpaceProtocolSession,
15
+ TimeframeClock,
16
+ codec,
17
+ createIdFromSpaceKey,
18
+ createMappedFeedWriter,
19
+ hasInvitationExpired,
20
+ mapFeedIndexesToTimeframe,
21
+ mapTimeframeToFeedIndexes,
22
+ startAfter,
23
+ valueEncoding
24
+ } from "./chunk-4LW7MDPZ.mjs";
25
+
26
+ // packages/core/echo/echo-pipeline/src/db-host/data-service.ts
27
+ import { UpdateScheduler as UpdateScheduler2 } from "@dxos/async";
28
+ import { Stream } from "@dxos/codec-protobuf/stream";
29
+ import { invariant as invariant7 } from "@dxos/invariant";
30
+ import { SpaceId as SpaceId2 } from "@dxos/keys";
31
+ import { log as log7 } from "@dxos/log";
6
32
 
7
33
  // packages/core/echo/echo-pipeline/src/db-host/documents-synchronizer.ts
8
34
  import { UpdateScheduler } from "@dxos/async";
@@ -170,11 +196,24 @@ var DocumentsSynchronizer = class extends Resource {
170
196
  }
171
197
  };
172
198
 
199
+ // packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts
200
+ import { Event as Event2, asyncTimeout } from "@dxos/async";
201
+ import { getBackend, getHeads, isAutomerge, equals as headsEquals, save } from "@dxos/automerge/automerge";
202
+ import { Repo } from "@dxos/automerge/automerge-repo";
203
+ import { Context, Resource as Resource4, cancelWithContext } from "@dxos/context";
204
+ import { invariant as invariant3 } from "@dxos/invariant";
205
+ import { PublicKey } from "@dxos/keys";
206
+ import { log as log4 } from "@dxos/log";
207
+ import { objectPointerCodec } from "@dxos/protocols";
208
+ import { trace } from "@dxos/tracing";
209
+
173
210
  // packages/core/echo/echo-pipeline/src/automerge/collection-synchronizer.ts
174
211
  import { asyncReturn, Event, scheduleTask, scheduleTaskInterval } from "@dxos/async";
175
212
  import { next as am } from "@dxos/automerge/automerge";
176
213
  import { Resource as Resource2 } from "@dxos/context";
214
+ import { log as log2 } from "@dxos/log";
177
215
  import { defaultMap } from "@dxos/util";
216
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/collection-synchronizer.ts";
178
217
  var MIN_QUERY_INTERVAL = 5e3;
179
218
  var POLL_INTERVAL = 3e4;
180
219
  var CollectionSynchronizer = class extends Resource2 {
@@ -207,6 +246,15 @@ var CollectionSynchronizer = class extends Resource2 {
207
246
  return this._getPerCollectionState(collectionId).localState;
208
247
  }
209
248
  setLocalCollectionState(collectionId, state) {
249
+ log2("setLocalCollectionState", {
250
+ collectionId,
251
+ state
252
+ }, {
253
+ F: __dxlog_file2,
254
+ L: 68,
255
+ S: this,
256
+ C: (f, a) => f(...a)
257
+ });
210
258
  this._getPerCollectionState(collectionId).localState = state;
211
259
  queueMicrotask(async () => {
212
260
  if (!this._ctx.disposed) {
@@ -276,6 +324,16 @@ var CollectionSynchronizer = class extends Resource2 {
276
324
  * Callback when a peer sends the state of a collection.
277
325
  */
278
326
  onRemoteStateReceived(collectionId, peerId, state) {
327
+ log2("onRemoteStateReceived", {
328
+ collectionId,
329
+ peerId,
330
+ state
331
+ }, {
332
+ F: __dxlog_file2,
333
+ L: 148,
334
+ S: this,
335
+ C: (f, a) => f(...a)
336
+ });
279
337
  validateCollectionState(state);
280
338
  const perCollectionState = this._getPerCollectionState(collectionId);
281
339
  perCollectionState.remoteStates.set(peerId, state);
@@ -307,13 +365,21 @@ var diffCollectionState = (local, remote) => {
307
365
  ...Object.keys(local.documents),
308
366
  ...Object.keys(remote.documents)
309
367
  ]);
368
+ const missingOnRemote = [];
369
+ const missingOnLocal = [];
310
370
  const different = [];
311
371
  for (const documentId of allDocuments) {
312
- if (!local.documents[documentId] || !remote.documents[documentId] || !am.equals(local.documents[documentId], remote.documents[documentId])) {
372
+ if (!local.documents[documentId]) {
373
+ missingOnLocal.push(documentId);
374
+ } else if (!remote.documents[documentId]) {
375
+ missingOnRemote.push(documentId);
376
+ } else if (!am.equals(local.documents[documentId], remote.documents[documentId])) {
313
377
  different.push(documentId);
314
378
  }
315
379
  }
316
380
  return {
381
+ missingOnRemote,
382
+ missingOnLocal,
317
383
  different
318
384
  };
319
385
  };
@@ -331,129 +397,12 @@ var isValidDocumentId = (documentId) => {
331
397
  return typeof documentId === "string" && !documentId.includes(":");
332
398
  };
333
399
 
334
- // packages/core/echo/echo-pipeline/src/automerge/leveldb-storage-adapter.ts
335
- import { LifecycleState, Resource as Resource3 } from "@dxos/context";
336
- var LevelDBStorageAdapter = class extends Resource3 {
337
- constructor(_params) {
338
- super();
339
- this._params = _params;
340
- }
341
- async load(keyArray) {
342
- try {
343
- if (this._lifecycleState !== LifecycleState.OPEN) {
344
- return void 0;
345
- }
346
- const startMs = Date.now();
347
- const chunk = await this._params.db.get(keyArray, {
348
- ...encodingOptions
349
- });
350
- this._params.monitor?.recordBytesLoaded(chunk.byteLength);
351
- this._params.monitor?.recordLoadDuration(Date.now() - startMs);
352
- return chunk;
353
- } catch (err) {
354
- if (isLevelDbNotFoundError(err)) {
355
- return void 0;
356
- }
357
- throw err;
358
- }
359
- }
360
- async save(keyArray, binary) {
361
- if (this._lifecycleState !== LifecycleState.OPEN) {
362
- return void 0;
363
- }
364
- const startMs = Date.now();
365
- const batch = this._params.db.batch();
366
- await this._params.callbacks?.beforeSave?.({
367
- path: keyArray,
368
- batch
369
- });
370
- batch.put(keyArray, Buffer.from(binary), {
371
- ...encodingOptions
372
- });
373
- await batch.write();
374
- this._params.monitor?.recordBytesStored(binary.byteLength);
375
- await this._params.callbacks?.afterSave?.(keyArray);
376
- this._params.monitor?.recordStoreDuration(Date.now() - startMs);
377
- }
378
- async remove(keyArray) {
379
- if (this._lifecycleState !== LifecycleState.OPEN) {
380
- return void 0;
381
- }
382
- await this._params.db.del(keyArray, {
383
- ...encodingOptions
384
- });
385
- }
386
- async loadRange(keyPrefix) {
387
- if (this._lifecycleState !== LifecycleState.OPEN) {
388
- return [];
389
- }
390
- const startMs = Date.now();
391
- const result = [];
392
- for await (const [key, value] of this._params.db.iterator({
393
- gte: keyPrefix,
394
- lte: [
395
- ...keyPrefix,
396
- "\uFFFF"
397
- ],
398
- ...encodingOptions
399
- })) {
400
- result.push({
401
- key,
402
- data: value
403
- });
404
- this._params.monitor?.recordBytesLoaded(value.byteLength);
405
- }
406
- this._params.monitor?.recordLoadDuration(Date.now() - startMs);
407
- return result;
408
- }
409
- async removeRange(keyPrefix) {
410
- if (this._lifecycleState !== LifecycleState.OPEN) {
411
- return void 0;
412
- }
413
- const batch = this._params.db.batch();
414
- for await (const [key] of this._params.db.iterator({
415
- gte: keyPrefix,
416
- lte: [
417
- ...keyPrefix,
418
- "\uFFFF"
419
- ],
420
- ...encodingOptions
421
- })) {
422
- batch.del(key, {
423
- ...encodingOptions
424
- });
425
- }
426
- await batch.write();
427
- }
428
- };
429
- var keyEncoder = {
430
- encode: (key) => Buffer.from(key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-")),
431
- decode: (key) => Buffer.from(key).toString().split("-").map((k) => k.replaceAll("%2D", "-").replaceAll("%25", "%")),
432
- format: "buffer"
433
- };
434
- var encodingOptions = {
435
- keyEncoding: keyEncoder,
436
- valueEncoding: "buffer"
437
- };
438
- var isLevelDbNotFoundError = (err) => err.code === "LEVEL_NOT_FOUND";
439
-
440
- // packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts
441
- import { Event as Event2, asyncTimeout } from "@dxos/async";
442
- import { getBackend, getHeads, isAutomerge, equals as headsEquals, save } from "@dxos/automerge/automerge";
443
- import { Repo } from "@dxos/automerge/automerge-repo";
444
- import { Context, Resource as Resource4, cancelWithContext } from "@dxos/context";
445
- import { invariant as invariant3 } from "@dxos/invariant";
446
- import { PublicKey } from "@dxos/keys";
447
- import { log as log3 } from "@dxos/log";
448
- import { objectPointerCodec } from "@dxos/protocols";
449
- import { trace } from "@dxos/tracing";
450
-
451
400
  // packages/core/echo/echo-pipeline/src/automerge/echo-network-adapter.ts
452
401
  import { synchronized, Trigger } from "@dxos/async";
453
402
  import { NetworkAdapter } from "@dxos/automerge/automerge-repo";
454
- import { LifecycleState as LifecycleState2 } from "@dxos/context";
403
+ import { LifecycleState } from "@dxos/context";
455
404
  import { invariant as invariant2 } from "@dxos/invariant";
456
- import { log as log2 } from "@dxos/log";
405
+ import { log as log3 } from "@dxos/log";
457
406
  import { nonNullable } from "@dxos/util";
458
407
 
459
408
  // packages/core/echo/echo-pipeline/src/automerge/network-protocol.ts
@@ -468,14 +417,14 @@ function _ts_decorate(decorators, target, key, desc) {
468
417
  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;
469
418
  return c > 3 && r && Object.defineProperty(target, key, r), r;
470
419
  }
471
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/echo-network-adapter.ts";
420
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/echo-network-adapter.ts";
472
421
  var EchoNetworkAdapter = class extends NetworkAdapter {
473
422
  constructor(_params) {
474
423
  super();
475
424
  this._params = _params;
476
425
  this._replicators = /* @__PURE__ */ new Set();
477
426
  this._connections = /* @__PURE__ */ new Map();
478
- this._lifecycleState = LifecycleState2.CLOSED;
427
+ this._lifecycleState = LifecycleState.CLOSED;
479
428
  this._connected = new Trigger();
480
429
  }
481
430
  connect(peerId, peerMetadata) {
@@ -489,13 +438,13 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
489
438
  disconnect() {
490
439
  }
491
440
  async open() {
492
- if (this._lifecycleState === LifecycleState2.OPEN) {
441
+ if (this._lifecycleState === LifecycleState.OPEN) {
493
442
  return;
494
443
  }
495
- this._lifecycleState = LifecycleState2.OPEN;
496
- log2("emit ready", void 0, {
497
- F: __dxlog_file2,
498
- L: 81,
444
+ this._lifecycleState = LifecycleState.OPEN;
445
+ log3("emit ready", void 0, {
446
+ F: __dxlog_file3,
447
+ L: 82,
499
448
  S: this,
500
449
  C: (f, a) => f(...a)
501
450
  });
@@ -504,14 +453,14 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
504
453
  });
505
454
  }
506
455
  async close() {
507
- if (this._lifecycleState === LifecycleState2.CLOSED) {
456
+ if (this._lifecycleState === LifecycleState.CLOSED) {
508
457
  return this;
509
458
  }
510
459
  for (const replicator of this._replicators) {
511
460
  await replicator.disconnect();
512
461
  }
513
462
  this._replicators.clear();
514
- this._lifecycleState = LifecycleState2.CLOSED;
463
+ this._lifecycleState = LifecycleState.CLOSED;
515
464
  }
516
465
  async whenConnected() {
517
466
  await this._connected.wait({
@@ -519,9 +468,9 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
519
468
  });
520
469
  }
521
470
  async addReplicator(replicator) {
522
- invariant2(this._lifecycleState === LifecycleState2.OPEN, void 0, {
523
- F: __dxlog_file2,
524
- L: 107,
471
+ invariant2(this._lifecycleState === LifecycleState.OPEN, void 0, {
472
+ F: __dxlog_file3,
473
+ L: 108,
525
474
  S: this,
526
475
  A: [
527
476
  "this._lifecycleState === LifecycleState.OPEN",
@@ -529,8 +478,8 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
529
478
  ]
530
479
  });
531
480
  invariant2(this.peerId, void 0, {
532
- F: __dxlog_file2,
533
- L: 108,
481
+ F: __dxlog_file3,
482
+ L: 109,
534
483
  S: this,
535
484
  A: [
536
485
  "this.peerId",
@@ -538,8 +487,8 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
538
487
  ]
539
488
  });
540
489
  invariant2(!this._replicators.has(replicator), void 0, {
541
- F: __dxlog_file2,
542
- L: 109,
490
+ F: __dxlog_file3,
491
+ L: 110,
543
492
  S: this,
544
493
  A: [
545
494
  "!this._replicators.has(replicator)",
@@ -561,9 +510,9 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
561
510
  });
562
511
  }
563
512
  async removeReplicator(replicator) {
564
- invariant2(this._lifecycleState === LifecycleState2.OPEN, void 0, {
565
- F: __dxlog_file2,
566
- L: 128,
513
+ invariant2(this._lifecycleState === LifecycleState.OPEN, void 0, {
514
+ F: __dxlog_file3,
515
+ L: 129,
567
516
  S: this,
568
517
  A: [
569
518
  "this._lifecycleState === LifecycleState.OPEN",
@@ -571,8 +520,8 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
571
520
  ]
572
521
  });
573
522
  invariant2(this._replicators.has(replicator), void 0, {
574
- F: __dxlog_file2,
575
- L: 129,
523
+ F: __dxlog_file3,
524
+ L: 130,
576
525
  S: this,
577
526
  A: [
578
527
  "this._replicators.has(replicator)",
@@ -626,9 +575,9 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
626
575
  this._params.monitor?.recordMessageSent(message, durationMs);
627
576
  }).catch((err) => {
628
577
  if (connectionEntry.isOpen) {
629
- log2.catch(err, void 0, {
630
- F: __dxlog_file2,
631
- L: 189,
578
+ log3.catch(err, void 0, {
579
+ F: __dxlog_file3,
580
+ L: 190,
632
581
  S: this,
633
582
  C: (f, a) => f(...a)
634
583
  });
@@ -645,17 +594,17 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
645
594
  }).filter(nonNullable);
646
595
  }
647
596
  _onConnectionOpen(connection) {
648
- log2("Connection opened", {
597
+ log3("Connection opened", {
649
598
  peerId: connection.peerId
650
599
  }, {
651
- F: __dxlog_file2,
652
- L: 207,
600
+ F: __dxlog_file3,
601
+ L: 208,
653
602
  S: this,
654
603
  C: (f, a) => f(...a)
655
604
  });
656
605
  invariant2(!this._connections.has(connection.peerId), void 0, {
657
- F: __dxlog_file2,
658
- L: 208,
606
+ F: __dxlog_file3,
607
+ L: 209,
659
608
  S: this,
660
609
  A: [
661
610
  "!this._connections.has(connection.peerId as PeerId)",
@@ -682,20 +631,20 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
682
631
  }
683
632
  } catch (err) {
684
633
  if (connectionEntry.isOpen) {
685
- log2.catch(err, void 0, {
686
- F: __dxlog_file2,
687
- L: 227,
634
+ log3.catch(err, void 0, {
635
+ F: __dxlog_file3,
636
+ L: 228,
688
637
  S: this,
689
638
  C: (f, a) => f(...a)
690
639
  });
691
640
  }
692
641
  }
693
642
  });
694
- log2("emit peer-candidate", {
643
+ log3("emit peer-candidate", {
695
644
  peerId: connection.peerId
696
645
  }, {
697
- F: __dxlog_file2,
698
- L: 232,
646
+ F: __dxlog_file3,
647
+ L: 233,
699
648
  S: this,
700
649
  C: (f, a) => f(...a)
701
650
  });
@@ -717,18 +666,18 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
717
666
  * TODO(y): replace with a proper API call when sharePolicy update becomes supported by automerge-repo
718
667
  */
719
668
  _onConnectionAuthScopeChanged(connection) {
720
- log2("Connection auth scope changed", {
669
+ log3("Connection auth scope changed", {
721
670
  peerId: connection.peerId
722
671
  }, {
723
- F: __dxlog_file2,
724
- L: 253,
672
+ F: __dxlog_file3,
673
+ L: 254,
725
674
  S: this,
726
675
  C: (f, a) => f(...a)
727
676
  });
728
677
  const entry = this._connections.get(connection.peerId);
729
678
  invariant2(entry, void 0, {
730
- F: __dxlog_file2,
731
- L: 255,
679
+ F: __dxlog_file3,
680
+ L: 256,
732
681
  S: this,
733
682
  A: [
734
683
  "entry",
@@ -741,18 +690,18 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
741
690
  this._emitPeerCandidate(connection);
742
691
  }
743
692
  _onConnectionClosed(connection) {
744
- log2("Connection closed", {
693
+ log3("Connection closed", {
745
694
  peerId: connection.peerId
746
695
  }, {
747
- F: __dxlog_file2,
748
- L: 261,
696
+ F: __dxlog_file3,
697
+ L: 262,
749
698
  S: this,
750
699
  C: (f, a) => f(...a)
751
700
  });
752
701
  const entry = this._connections.get(connection.peerId);
753
702
  invariant2(entry, void 0, {
754
- F: __dxlog_file2,
755
- L: 263,
703
+ F: __dxlog_file3,
704
+ L: 264,
756
705
  S: this,
757
706
  A: [
758
707
  "entry",
@@ -764,15 +713,15 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
764
713
  peerId: connection.peerId
765
714
  });
766
715
  this._params.monitor?.recordPeerDisconnected(connection.peerId);
767
- void entry.reader.cancel().catch((err) => log2.catch(err, void 0, {
768
- F: __dxlog_file2,
769
- L: 269,
716
+ void entry.reader.cancel().catch((err) => log3.catch(err, void 0, {
717
+ F: __dxlog_file3,
718
+ L: 270,
770
719
  S: this,
771
720
  C: (f, a) => f(...a)
772
721
  }));
773
- void entry.writer.abort().catch((err) => log2.catch(err, void 0, {
774
- F: __dxlog_file2,
775
- L: 270,
722
+ void entry.writer.abort().catch((err) => log3.catch(err, void 0, {
723
+ F: __dxlog_file3,
724
+ L: 271,
776
725
  S: this,
777
726
  C: (f, a) => f(...a)
778
727
  }));
@@ -825,42 +774,149 @@ var HeadsStore = class {
825
774
  }
826
775
  };
827
776
 
828
- // packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts
829
- function _ts_decorate2(decorators, target, key, desc) {
830
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
831
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
832
- 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;
833
- return c > 3 && r && Object.defineProperty(target, key, r), r;
834
- }
835
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
836
- var AutomergeHost = class extends Resource4 {
837
- constructor({ db, indexMetadataStore, dataMonitor }) {
777
+ // packages/core/echo/echo-pipeline/src/automerge/leveldb-storage-adapter.ts
778
+ import { LifecycleState as LifecycleState2, Resource as Resource3 } from "@dxos/context";
779
+ var LevelDBStorageAdapter = class extends Resource3 {
780
+ constructor(_params) {
838
781
  super();
839
- this._collectionSynchronizer = new CollectionSynchronizer({
840
- queryCollectionState: this._queryCollectionState.bind(this),
841
- sendCollectionState: this._sendCollectionState.bind(this),
842
- shouldSyncCollection: this._shouldSyncCollection.bind(this)
843
- });
844
- this._db = db;
845
- this._storage = new LevelDBStorageAdapter({
846
- db: db.sublevel("automerge"),
847
- callbacks: {
848
- beforeSave: async (params) => this._beforeSave(params),
849
- afterSave: async (key) => this._afterSave(key)
850
- },
851
- monitor: dataMonitor
852
- });
853
- this._echoNetworkAdapter = new EchoNetworkAdapter({
854
- getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this),
855
- isDocumentInRemoteCollection: this._isDocumentInRemoteCollection.bind(this),
856
- onCollectionStateQueried: this._onCollectionStateQueried.bind(this),
857
- onCollectionStateReceived: this._onCollectionStateReceived.bind(this),
858
- monitor: dataMonitor
782
+ this._params = _params;
783
+ }
784
+ async load(keyArray) {
785
+ try {
786
+ if (this._lifecycleState !== LifecycleState2.OPEN) {
787
+ return void 0;
788
+ }
789
+ const startMs = Date.now();
790
+ const chunk = await this._params.db.get(keyArray, {
791
+ ...encodingOptions
792
+ });
793
+ this._params.monitor?.recordBytesLoaded(chunk.byteLength);
794
+ this._params.monitor?.recordLoadDuration(Date.now() - startMs);
795
+ return chunk;
796
+ } catch (err) {
797
+ if (isLevelDbNotFoundError(err)) {
798
+ return void 0;
799
+ }
800
+ throw err;
801
+ }
802
+ }
803
+ async save(keyArray, binary) {
804
+ if (this._lifecycleState !== LifecycleState2.OPEN) {
805
+ return void 0;
806
+ }
807
+ const startMs = Date.now();
808
+ const batch = this._params.db.batch();
809
+ await this._params.callbacks?.beforeSave?.({
810
+ path: keyArray,
811
+ batch
859
812
  });
860
- this._headsStore = new HeadsStore({
861
- db: db.sublevel("heads")
813
+ batch.put(keyArray, Buffer.from(binary), {
814
+ ...encodingOptions
862
815
  });
863
- this._indexMetadataStore = indexMetadataStore;
816
+ await batch.write();
817
+ this._params.monitor?.recordBytesStored(binary.byteLength);
818
+ await this._params.callbacks?.afterSave?.(keyArray);
819
+ this._params.monitor?.recordStoreDuration(Date.now() - startMs);
820
+ }
821
+ async remove(keyArray) {
822
+ if (this._lifecycleState !== LifecycleState2.OPEN) {
823
+ return void 0;
824
+ }
825
+ await this._params.db.del(keyArray, {
826
+ ...encodingOptions
827
+ });
828
+ }
829
+ async loadRange(keyPrefix) {
830
+ if (this._lifecycleState !== LifecycleState2.OPEN) {
831
+ return [];
832
+ }
833
+ const startMs = Date.now();
834
+ const result = [];
835
+ for await (const [key, value] of this._params.db.iterator({
836
+ gte: keyPrefix,
837
+ lte: [
838
+ ...keyPrefix,
839
+ "\uFFFF"
840
+ ],
841
+ ...encodingOptions
842
+ })) {
843
+ result.push({
844
+ key,
845
+ data: value
846
+ });
847
+ this._params.monitor?.recordBytesLoaded(value.byteLength);
848
+ }
849
+ this._params.monitor?.recordLoadDuration(Date.now() - startMs);
850
+ return result;
851
+ }
852
+ async removeRange(keyPrefix) {
853
+ if (this._lifecycleState !== LifecycleState2.OPEN) {
854
+ return void 0;
855
+ }
856
+ const batch = this._params.db.batch();
857
+ for await (const [key] of this._params.db.iterator({
858
+ gte: keyPrefix,
859
+ lte: [
860
+ ...keyPrefix,
861
+ "\uFFFF"
862
+ ],
863
+ ...encodingOptions
864
+ })) {
865
+ batch.del(key, {
866
+ ...encodingOptions
867
+ });
868
+ }
869
+ await batch.write();
870
+ }
871
+ };
872
+ var keyEncoder = {
873
+ encode: (key) => Buffer.from(key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-")),
874
+ decode: (key) => Buffer.from(key).toString().split("-").map((k) => k.replaceAll("%2D", "-").replaceAll("%25", "%")),
875
+ format: "buffer"
876
+ };
877
+ var encodingOptions = {
878
+ keyEncoding: keyEncoder,
879
+ valueEncoding: "buffer"
880
+ };
881
+ var isLevelDbNotFoundError = (err) => err.code === "LEVEL_NOT_FOUND";
882
+
883
+ // packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts
884
+ function _ts_decorate2(decorators, target, key, desc) {
885
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
886
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
887
+ 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;
888
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
889
+ }
890
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
891
+ var AutomergeHost = class extends Resource4 {
892
+ constructor({ db, indexMetadataStore, dataMonitor }) {
893
+ super();
894
+ this._collectionSynchronizer = new CollectionSynchronizer({
895
+ queryCollectionState: this._queryCollectionState.bind(this),
896
+ sendCollectionState: this._sendCollectionState.bind(this),
897
+ shouldSyncCollection: this._shouldSyncCollection.bind(this)
898
+ });
899
+ this.collectionStateUpdated = new Event2();
900
+ this._db = db;
901
+ this._storage = new LevelDBStorageAdapter({
902
+ db: db.sublevel("automerge"),
903
+ callbacks: {
904
+ beforeSave: async (params) => this._beforeSave(params),
905
+ afterSave: async (key) => this._afterSave(key)
906
+ },
907
+ monitor: dataMonitor
908
+ });
909
+ this._echoNetworkAdapter = new EchoNetworkAdapter({
910
+ getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this),
911
+ isDocumentInRemoteCollection: this._isDocumentInRemoteCollection.bind(this),
912
+ onCollectionStateQueried: this._onCollectionStateQueried.bind(this),
913
+ onCollectionStateReceived: this._onCollectionStateReceived.bind(this),
914
+ monitor: dataMonitor
915
+ });
916
+ this._headsStore = new HeadsStore({
917
+ db: db.sublevel("heads")
918
+ });
919
+ this._indexMetadataStore = indexMetadataStore;
864
920
  }
865
921
  async _open() {
866
922
  this._peerId = `host-${PublicKey.random().toHex()}`;
@@ -878,6 +934,9 @@ var AutomergeHost = class extends Resource4 {
878
934
  Event2.wrap(this._echoNetworkAdapter, "peer-disconnected").on(this._ctx, (e) => this._onPeerDisconnected(e.peerId));
879
935
  this._collectionSynchronizer.remoteStateUpdated.on(this._ctx, ({ collectionId, peerId }) => {
880
936
  this._onRemoteCollectionStateUpdated(collectionId, peerId);
937
+ this.collectionStateUpdated.emit({
938
+ collectionId
939
+ });
881
940
  });
882
941
  await this._echoNetworkAdapter.open();
883
942
  await this._collectionSynchronizer.open();
@@ -959,8 +1018,8 @@ var AutomergeHost = class extends Resource4 {
959
1018
  if (headsToWait.length > 0) {
960
1019
  await Promise.all(headsToWait.map(async (entry, index) => {
961
1020
  const handle = await this.loadDoc(Context.default(void 0, {
962
- F: __dxlog_file3,
963
- L: 227
1021
+ F: __dxlog_file4,
1022
+ L: 230
964
1023
  }), entry.documentId);
965
1024
  await waitForHeads(handle, entry.heads);
966
1025
  }));
@@ -969,11 +1028,11 @@ var AutomergeHost = class extends Resource4 {
969
1028
  }
970
1029
  async reIndexHeads(documentIds) {
971
1030
  for (const documentId of documentIds) {
972
- log3.info("re-indexing heads for document", {
1031
+ log4.info("re-indexing heads for document", {
973
1032
  documentId
974
1033
  }, {
975
- F: __dxlog_file3,
976
- L: 239,
1034
+ F: __dxlog_file4,
1035
+ L: 242,
977
1036
  S: this,
978
1037
  C: (f, a) => f(...a)
979
1038
  });
@@ -985,11 +1044,11 @@ var AutomergeHost = class extends Resource4 {
985
1044
  if (handle.inState([
986
1045
  "requesting"
987
1046
  ])) {
988
- log3.warn("document is not available locally, skipping", {
1047
+ log4.warn("document is not available locally, skipping", {
989
1048
  documentId
990
1049
  }, {
991
- F: __dxlog_file3,
992
- L: 243,
1050
+ F: __dxlog_file4,
1051
+ L: 246,
993
1052
  S: this,
994
1053
  C: (f, a) => f(...a)
995
1054
  });
@@ -997,8 +1056,8 @@ var AutomergeHost = class extends Resource4 {
997
1056
  }
998
1057
  const doc = handle.docSync();
999
1058
  invariant3(doc, void 0, {
1000
- F: __dxlog_file3,
1001
- L: 248,
1059
+ F: __dxlog_file4,
1060
+ L: 251,
1002
1061
  S: this,
1003
1062
  A: [
1004
1063
  "doc",
@@ -1010,9 +1069,9 @@ var AutomergeHost = class extends Resource4 {
1010
1069
  this._headsStore.setHeads(documentId, heads, batch);
1011
1070
  await batch.write();
1012
1071
  }
1013
- log3.info("done re-indexing heads", void 0, {
1014
- F: __dxlog_file3,
1015
- L: 255,
1072
+ log4.info("done re-indexing heads", void 0, {
1073
+ F: __dxlog_file4,
1074
+ L: 258,
1016
1075
  S: this,
1017
1076
  C: (f, a) => f(...a)
1018
1077
  });
@@ -1109,7 +1168,8 @@ var AutomergeHost = class extends Resource4 {
1109
1168
  * Flush documents to disk.
1110
1169
  */
1111
1170
  async flush({ documentIds } = {}) {
1112
- await this._repo.flush(documentIds);
1171
+ const loadedDocuments = documentIds?.filter((documentId) => !!this._repo.handles[documentId]);
1172
+ await this._repo.flush(loadedDocuments);
1113
1173
  }
1114
1174
  async getHeads(documentIds) {
1115
1175
  const result = [];
@@ -1158,7 +1218,11 @@ var AutomergeHost = class extends Resource4 {
1158
1218
  const diff = diffCollectionState(localState, state);
1159
1219
  result.peers.push({
1160
1220
  peerId,
1161
- differentDocuments: diff.different.length
1221
+ missingOnRemote: diff.missingOnRemote.length,
1222
+ missingOnLocal: diff.missingOnLocal.length,
1223
+ differentDocuments: diff.different.length,
1224
+ localDocumentCount: Object.keys(localState.documents).length,
1225
+ remoteDocumentCount: Object.keys(state.documents).length
1162
1226
  });
1163
1227
  }
1164
1228
  return result;
@@ -1200,31 +1264,43 @@ var AutomergeHost = class extends Resource4 {
1200
1264
  if (!localState || !remoteState) {
1201
1265
  return;
1202
1266
  }
1203
- const { different } = diffCollectionState(localState, remoteState);
1204
- if (different.length === 0) {
1267
+ const { different, missingOnLocal, missingOnRemote } = diffCollectionState(localState, remoteState);
1268
+ const toReplicate = [
1269
+ ...missingOnLocal,
1270
+ ...missingOnRemote,
1271
+ ...different
1272
+ ];
1273
+ if (toReplicate.length === 0) {
1205
1274
  return;
1206
1275
  }
1207
- log3.info("replication documents after collection sync", {
1208
- count: different.length
1276
+ log4.info("replication documents after collection sync", {
1277
+ count: toReplicate.length
1209
1278
  }, {
1210
- F: __dxlog_file3,
1211
- L: 475,
1279
+ F: __dxlog_file4,
1280
+ L: 486,
1212
1281
  S: this,
1213
1282
  C: (f, a) => f(...a)
1214
1283
  });
1215
- for (const documentId of different) {
1284
+ for (const documentId of toReplicate) {
1216
1285
  this._repo.find(documentId);
1217
1286
  }
1218
1287
  }
1219
1288
  _onHeadsChanged(documentId, heads) {
1289
+ const collectionsChanged = /* @__PURE__ */ new Set();
1220
1290
  for (const collectionId of this._collectionSynchronizer.getRegisteredCollectionIds()) {
1221
1291
  const state = this._collectionSynchronizer.getLocalCollectionState(collectionId);
1222
1292
  if (state?.documents[documentId]) {
1223
1293
  const newState = structuredClone(state);
1224
1294
  newState.documents[documentId] = heads;
1225
1295
  this._collectionSynchronizer.setLocalCollectionState(collectionId, newState);
1296
+ collectionsChanged.add(collectionId);
1226
1297
  }
1227
1298
  }
1299
+ for (const collectionId of collectionsChanged) {
1300
+ this.collectionStateUpdated.emit({
1301
+ collectionId
1302
+ });
1303
+ }
1228
1304
  }
1229
1305
  };
1230
1306
  _ts_decorate2([
@@ -1267,8 +1343,8 @@ var changeIsPresentInDoc = (doc, changeHash) => {
1267
1343
  };
1268
1344
  var decodeCollectionState = (state) => {
1269
1345
  invariant3(typeof state === "object" && state !== null, "Invalid state", {
1270
- F: __dxlog_file3,
1271
- L: 528,
1346
+ F: __dxlog_file4,
1347
+ L: 544,
1272
1348
  S: void 0,
1273
1349
  A: [
1274
1350
  "typeof state === 'object' && state !== null",
@@ -1281,37 +1357,18 @@ var encodeCollectionState = (state) => {
1281
1357
  return state;
1282
1358
  };
1283
1359
 
1284
- // packages/core/echo/echo-pipeline/src/automerge/space-collection.ts
1285
- import { invariant as invariant4 } from "@dxos/invariant";
1286
- import { SpaceId } from "@dxos/keys";
1287
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/space-collection.ts";
1288
- var deriveCollectionIdFromSpaceId = (spaceId) => `space:${spaceId}`;
1289
- var getSpaceIdFromCollectionId = (collectionId) => {
1290
- const spaceId = collectionId.replace(/^space:/, "");
1291
- invariant4(SpaceId.isValid(spaceId), void 0, {
1292
- F: __dxlog_file4,
1293
- L: 12,
1294
- S: void 0,
1295
- A: [
1296
- "SpaceId.isValid(spaceId)",
1297
- ""
1298
- ]
1299
- });
1300
- return spaceId;
1301
- };
1302
-
1303
1360
  // packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts
1304
1361
  import { invariant as invariant6 } from "@dxos/invariant";
1305
1362
  import { PublicKey as PublicKey2 } from "@dxos/keys";
1306
- import { log as log5 } from "@dxos/log";
1363
+ import { log as log6 } from "@dxos/log";
1307
1364
  import { ComplexSet, defaultMap as defaultMap2 } from "@dxos/util";
1308
1365
 
1309
1366
  // packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator-connection.ts
1310
1367
  import * as A2 from "@dxos/automerge/automerge";
1311
1368
  import { cbor } from "@dxos/automerge/automerge-repo";
1312
1369
  import { Resource as Resource5 } from "@dxos/context";
1313
- import { invariant as invariant5 } from "@dxos/invariant";
1314
- import { log as log4 } from "@dxos/log";
1370
+ import { invariant as invariant4 } from "@dxos/invariant";
1371
+ import { log as log5 } from "@dxos/log";
1315
1372
  import { AutomergeReplicator } from "@dxos/teleport-extension-automerge-replicator";
1316
1373
  var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator-connection.ts";
1317
1374
  var DEFAULT_FACTORY = (params) => new AutomergeReplicator(...params);
@@ -1331,9 +1388,9 @@ var MeshReplicatorConnection = class extends Resource5 {
1331
1388
  });
1332
1389
  this.writable = new WritableStream({
1333
1390
  write: async (message, controller) => {
1334
- invariant5(this._isEnabled, "Writing to a disabled connection", {
1391
+ invariant4(this._isEnabled, "Writing to a disabled connection", {
1335
1392
  F: __dxlog_file5,
1336
- L: 49,
1393
+ L: 50,
1337
1394
  S: this,
1338
1395
  A: [
1339
1396
  "this._isEnabled",
@@ -1360,13 +1417,13 @@ var MeshReplicatorConnection = class extends Resource5 {
1360
1417
  onStartReplication: async (info, remotePeerId) => {
1361
1418
  this.remoteDeviceKey = remotePeerId;
1362
1419
  this._remotePeerId = info.id;
1363
- log4("onStartReplication", {
1420
+ log5("onStartReplication", {
1364
1421
  id: info.id,
1365
1422
  thisPeerId: this.peerId,
1366
1423
  remotePeerId: remotePeerId.toHex()
1367
1424
  }, {
1368
1425
  F: __dxlog_file5,
1369
- L: 84,
1426
+ L: 85,
1370
1427
  S: this,
1371
1428
  C: (f, a) => f(...a)
1372
1429
  });
@@ -1391,9 +1448,9 @@ var MeshReplicatorConnection = class extends Resource5 {
1391
1448
  }
1392
1449
  }
1393
1450
  get peerId() {
1394
- invariant5(this._remotePeerId != null, "Remote peer has not connected yet.", {
1451
+ invariant4(this._remotePeerId != null, "Remote peer has not connected yet.", {
1395
1452
  F: __dxlog_file5,
1396
- L: 110,
1453
+ L: 111,
1397
1454
  S: this,
1398
1455
  A: [
1399
1456
  "this._remotePeerId != null",
@@ -1413,9 +1470,9 @@ var MeshReplicatorConnection = class extends Resource5 {
1413
1470
  * Call after the remote peer has connected.
1414
1471
  */
1415
1472
  enable() {
1416
- invariant5(this._remotePeerId != null, "Remote peer has not connected yet.", {
1473
+ invariant4(this._remotePeerId != null, "Remote peer has not connected yet.", {
1417
1474
  F: __dxlog_file5,
1418
- L: 127,
1475
+ L: 128,
1419
1476
  S: this,
1420
1477
  A: [
1421
1478
  "this._remotePeerId != null",
@@ -1432,7 +1489,7 @@ var MeshReplicatorConnection = class extends Resource5 {
1432
1489
  }
1433
1490
  };
1434
1491
  var logSendSync = (message) => {
1435
- log4("sendSyncMessage", () => {
1492
+ log5("sendSyncMessage", () => {
1436
1493
  const decodedSyncMessage = message.type === "sync" && message.data ? A2.decodeSyncMessage(message.data) : void 0;
1437
1494
  return {
1438
1495
  sync: decodedSyncMessage && {
@@ -1446,14 +1503,33 @@ var logSendSync = (message) => {
1446
1503
  };
1447
1504
  }, {
1448
1505
  F: __dxlog_file5,
1449
- L: 140,
1506
+ L: 141,
1450
1507
  S: void 0,
1451
1508
  C: (f, a) => f(...a)
1452
1509
  });
1453
1510
  };
1454
1511
 
1512
+ // packages/core/echo/echo-pipeline/src/automerge/space-collection.ts
1513
+ import { invariant as invariant5 } from "@dxos/invariant";
1514
+ import { SpaceId } from "@dxos/keys";
1515
+ var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/space-collection.ts";
1516
+ var deriveCollectionIdFromSpaceId = (spaceId) => `space:${spaceId}`;
1517
+ var getSpaceIdFromCollectionId = (collectionId) => {
1518
+ const spaceId = collectionId.replace(/^space:/, "");
1519
+ invariant5(SpaceId.isValid(spaceId), void 0, {
1520
+ F: __dxlog_file6,
1521
+ L: 13,
1522
+ S: void 0,
1523
+ A: [
1524
+ "SpaceId.isValid(spaceId)",
1525
+ ""
1526
+ ]
1527
+ });
1528
+ return spaceId;
1529
+ };
1530
+
1455
1531
  // packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts
1456
- var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts";
1532
+ var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts";
1457
1533
  var MeshEchoReplicator = class {
1458
1534
  constructor() {
1459
1535
  this._connections = /* @__PURE__ */ new Set();
@@ -1483,8 +1559,8 @@ var MeshEchoReplicator = class {
1483
1559
  }
1484
1560
  createExtension(extensionFactory) {
1485
1561
  invariant6(this._context, void 0, {
1486
- F: __dxlog_file6,
1487
- L: 56,
1562
+ F: __dxlog_file7,
1563
+ L: 57,
1488
1564
  S: this,
1489
1565
  A: [
1490
1566
  "this._context",
@@ -1495,17 +1571,17 @@ var MeshEchoReplicator = class {
1495
1571
  ownPeerId: this._context.peerId,
1496
1572
  replicatorFactory: extensionFactory,
1497
1573
  onRemoteConnected: async () => {
1498
- log5("onRemoteConnected", {
1574
+ log6("onRemoteConnected", {
1499
1575
  peerId: connection.peerId
1500
1576
  }, {
1501
- F: __dxlog_file6,
1502
- L: 62,
1577
+ F: __dxlog_file7,
1578
+ L: 63,
1503
1579
  S: this,
1504
1580
  C: (f, a) => f(...a)
1505
1581
  });
1506
1582
  invariant6(this._context, void 0, {
1507
- F: __dxlog_file6,
1508
- L: 63,
1583
+ F: __dxlog_file7,
1584
+ L: 64,
1509
1585
  S: this,
1510
1586
  A: [
1511
1587
  "this._context",
@@ -1521,11 +1597,11 @@ var MeshEchoReplicator = class {
1521
1597
  }
1522
1598
  },
1523
1599
  onRemoteDisconnected: async () => {
1524
- log5("onRemoteDisconnected", {
1600
+ log6("onRemoteDisconnected", {
1525
1601
  peerId: connection.peerId
1526
1602
  }, {
1527
- F: __dxlog_file6,
1528
- L: 74,
1603
+ F: __dxlog_file7,
1604
+ L: 75,
1529
1605
  S: this,
1530
1606
  C: (f, a) => f(...a)
1531
1607
  });
@@ -1535,18 +1611,18 @@ var MeshEchoReplicator = class {
1535
1611
  this._connections.delete(connection);
1536
1612
  },
1537
1613
  shouldAdvertise: async (params) => {
1538
- log5("shouldAdvertise", {
1614
+ log6("shouldAdvertise", {
1539
1615
  peerId: connection.peerId,
1540
1616
  documentId: params.documentId
1541
1617
  }, {
1542
- F: __dxlog_file6,
1543
- L: 81,
1618
+ F: __dxlog_file7,
1619
+ L: 82,
1544
1620
  S: this,
1545
1621
  C: (f, a) => f(...a)
1546
1622
  });
1547
1623
  invariant6(this._context, void 0, {
1548
- F: __dxlog_file6,
1549
- L: 82,
1624
+ F: __dxlog_file7,
1625
+ L: 83,
1550
1626
  S: this,
1551
1627
  A: [
1552
1628
  "this._context",
@@ -1560,13 +1636,13 @@ var MeshEchoReplicator = class {
1560
1636
  documentId: params.documentId,
1561
1637
  peerId: connection.peerId
1562
1638
  });
1563
- log5("document not found locally for share policy check, accepting the remote document", {
1639
+ log6("document not found locally for share policy check, accepting the remote document", {
1564
1640
  peerId: connection.peerId,
1565
1641
  documentId: params.documentId,
1566
1642
  remoteDocumentExists
1567
1643
  }, {
1568
- F: __dxlog_file6,
1569
- L: 90,
1644
+ F: __dxlog_file7,
1645
+ L: 91,
1570
1646
  S: this,
1571
1647
  C: (f, a) => f(...a)
1572
1648
  });
@@ -1575,19 +1651,19 @@ var MeshEchoReplicator = class {
1575
1651
  const spaceId = await createIdFromSpaceKey(spaceKey);
1576
1652
  const authorizedDevices = this._authorizedDevices.get(spaceId);
1577
1653
  if (!connection.remoteDeviceKey) {
1578
- log5("device key not found for share policy check", {
1654
+ log6("device key not found for share policy check", {
1579
1655
  peerId: connection.peerId,
1580
1656
  documentId: params.documentId
1581
1657
  }, {
1582
- F: __dxlog_file6,
1583
- L: 106,
1658
+ F: __dxlog_file7,
1659
+ L: 107,
1584
1660
  S: this,
1585
1661
  C: (f, a) => f(...a)
1586
1662
  });
1587
1663
  return false;
1588
1664
  }
1589
1665
  const isAuthorized = authorizedDevices?.has(connection.remoteDeviceKey) ?? false;
1590
- log5("share policy check", {
1666
+ log6("share policy check", {
1591
1667
  localPeer: this._context.peerId,
1592
1668
  remotePeer: connection.peerId,
1593
1669
  documentId: params.documentId,
@@ -1595,16 +1671,16 @@ var MeshEchoReplicator = class {
1595
1671
  spaceKey,
1596
1672
  isAuthorized
1597
1673
  }, {
1598
- F: __dxlog_file6,
1599
- L: 114,
1674
+ F: __dxlog_file7,
1675
+ L: 115,
1600
1676
  S: this,
1601
1677
  C: (f, a) => f(...a)
1602
1678
  });
1603
1679
  return isAuthorized;
1604
1680
  } catch (err) {
1605
- log5.catch(err, void 0, {
1606
- F: __dxlog_file6,
1607
- L: 124,
1681
+ log6.catch(err, void 0, {
1682
+ F: __dxlog_file7,
1683
+ L: 125,
1608
1684
  S: this,
1609
1685
  C: (f, a) => f(...a)
1610
1686
  });
@@ -1615,12 +1691,12 @@ var MeshEchoReplicator = class {
1615
1691
  const spaceId = getSpaceIdFromCollectionId(collectionId);
1616
1692
  const authorizedDevices = this._authorizedDevices.get(spaceId);
1617
1693
  if (!connection.remoteDeviceKey) {
1618
- log5("device key not found for collection sync check", {
1694
+ log6("device key not found for collection sync check", {
1619
1695
  peerId: connection.peerId,
1620
1696
  collectionId
1621
1697
  }, {
1622
- F: __dxlog_file6,
1623
- L: 134,
1698
+ F: __dxlog_file7,
1699
+ L: 135,
1624
1700
  S: this,
1625
1701
  C: (f, a) => f(...a)
1626
1702
  });
@@ -1634,12 +1710,12 @@ var MeshEchoReplicator = class {
1634
1710
  return connection.replicatorExtension;
1635
1711
  }
1636
1712
  async authorizeDevice(spaceKey, deviceKey) {
1637
- log5("authorizeDevice", {
1713
+ log6("authorizeDevice", {
1638
1714
  spaceKey,
1639
1715
  deviceKey
1640
1716
  }, {
1641
- F: __dxlog_file6,
1642
- L: 151,
1717
+ F: __dxlog_file7,
1718
+ L: 152,
1643
1719
  S: this,
1644
1720
  C: (f, a) => f(...a)
1645
1721
  });
@@ -2017,11 +2093,7 @@ var getByteCount = (message) => {
2017
2093
  };
2018
2094
 
2019
2095
  // packages/core/echo/echo-pipeline/src/db-host/data-service.ts
2020
- import { Stream } from "@dxos/codec-protobuf";
2021
- import { invariant as invariant7 } from "@dxos/invariant";
2022
- import { SpaceId as SpaceId2 } from "@dxos/keys";
2023
- import { log as log6 } from "@dxos/log";
2024
- var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/data-service.ts";
2096
+ var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/data-service.ts";
2025
2097
  var DataServiceImpl = class {
2026
2098
  constructor(params) {
2027
2099
  /**
@@ -2041,9 +2113,9 @@ var DataServiceImpl = class {
2041
2113
  synchronizer.open().then(() => {
2042
2114
  this._subscriptions.set(request.subscriptionId, synchronizer);
2043
2115
  ready();
2044
- }).catch((err) => log6.catch(err, void 0, {
2045
- F: __dxlog_file7,
2046
- L: 64,
2116
+ }).catch((err) => log7.catch(err, void 0, {
2117
+ F: __dxlog_file8,
2118
+ L: 66,
2047
2119
  S: this,
2048
2120
  C: (f, a) => f(...a)
2049
2121
  }));
@@ -2053,8 +2125,8 @@ var DataServiceImpl = class {
2053
2125
  async updateSubscription(request) {
2054
2126
  const synchronizer = this._subscriptions.get(request.subscriptionId);
2055
2127
  invariant7(synchronizer, "Subscription not found", {
2056
- F: __dxlog_file7,
2057
- L: 71,
2128
+ F: __dxlog_file8,
2129
+ L: 73,
2058
2130
  S: this,
2059
2131
  A: [
2060
2132
  "synchronizer",
@@ -2074,8 +2146,8 @@ var DataServiceImpl = class {
2074
2146
  }
2075
2147
  const synchronizer = this._subscriptions.get(request.subscriptionId);
2076
2148
  invariant7(synchronizer, "Subscription not found", {
2077
- F: __dxlog_file7,
2078
- L: 86,
2149
+ F: __dxlog_file8,
2150
+ L: 88,
2079
2151
  S: this,
2080
2152
  A: [
2081
2153
  "synchronizer",
@@ -2115,38 +2187,1333 @@ var DataServiceImpl = class {
2115
2187
  async updateIndexes() {
2116
2188
  await this._updateIndexes();
2117
2189
  }
2118
- async getSpaceSyncState(request, options) {
2119
- invariant7(SpaceId2.isValid(request.spaceId), void 0, {
2120
- F: __dxlog_file7,
2121
- L: 127,
2122
- S: this,
2123
- A: [
2124
- "SpaceId.isValid(request.spaceId)",
2125
- ""
2126
- ]
2190
+ subscribeSpaceSyncState(request) {
2191
+ return new Stream(({ ctx, next, ready }) => {
2192
+ invariant7(SpaceId2.isValid(request.spaceId), void 0, {
2193
+ F: __dxlog_file8,
2194
+ L: 127,
2195
+ S: this,
2196
+ A: [
2197
+ "SpaceId.isValid(request.spaceId)",
2198
+ ""
2199
+ ]
2200
+ });
2201
+ const collectionId = deriveCollectionIdFromSpaceId(request.spaceId);
2202
+ const scheduler = new UpdateScheduler2(ctx, async () => {
2203
+ const state = await this._automergeHost.getCollectionSyncState(collectionId);
2204
+ next({
2205
+ peers: state.peers.map((peer) => ({
2206
+ peerId: peer.peerId,
2207
+ missingOnRemote: peer.missingOnRemote,
2208
+ missingOnLocal: peer.missingOnLocal,
2209
+ differentDocuments: peer.differentDocuments,
2210
+ localDocumentCount: peer.localDocumentCount,
2211
+ remoteDocumentCount: peer.remoteDocumentCount
2212
+ }))
2213
+ });
2214
+ });
2215
+ this._automergeHost.collectionStateUpdated.on(ctx, (e) => {
2216
+ if (e.collectionId === collectionId) {
2217
+ scheduler.trigger();
2218
+ }
2219
+ });
2220
+ scheduler.trigger();
2127
2221
  });
2128
- const collectionId = deriveCollectionIdFromSpaceId(request.spaceId);
2129
- const state = await this._automergeHost.getCollectionSyncState(collectionId);
2222
+ }
2223
+ };
2224
+
2225
+ // packages/core/echo/echo-pipeline/src/db-host/echo-host.ts
2226
+ import { LifecycleState as LifecycleState4, Resource as Resource9 } from "@dxos/context";
2227
+ import { todo } from "@dxos/debug";
2228
+ import { createIdFromSpaceKey as createIdFromSpaceKey3, SpaceDocVersion as SpaceDocVersion3 } from "@dxos/echo-protocol";
2229
+ import { IndexMetadataStore, IndexStore, Indexer } from "@dxos/indexing";
2230
+ import { invariant as invariant11 } from "@dxos/invariant";
2231
+ import { IndexKind } from "@dxos/protocols/proto/dxos/echo/indexing";
2232
+ import { trace as trace5 } from "@dxos/tracing";
2233
+
2234
+ // packages/core/echo/echo-pipeline/src/db-host/documents-iterator.ts
2235
+ import * as A3 from "@dxos/automerge/automerge";
2236
+ import { Context as Context2 } from "@dxos/context";
2237
+ import { SpaceDocVersion } from "@dxos/echo-protocol";
2238
+ import { invariant as invariant8 } from "@dxos/invariant";
2239
+ import { log as log8 } from "@dxos/log";
2240
+ import { ObjectPointerVersion, objectPointerCodec as objectPointerCodec2 } from "@dxos/protocols";
2241
+ var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/documents-iterator.ts";
2242
+ var LOG_VIEW_OPERATION_THRESHOLD = 300;
2243
+ var createSelectedDocumentsIterator = (automergeHost) => (
2244
+ /**
2245
+ * Get object data blobs from Automerge Repo by ids.
2246
+ */
2247
+ // TODO(mykola): Unload automerge handles after usage.
2248
+ async function* loadDocuments(objects) {
2249
+ for (const [id, heads] of objects.entries()) {
2250
+ try {
2251
+ const { documentId, objectId } = objectPointerCodec2.decode(id);
2252
+ const handle = await automergeHost.loadDoc(Context2.default(void 0, {
2253
+ F: __dxlog_file9,
2254
+ L: 30
2255
+ }), documentId);
2256
+ let doc = handle.docSync();
2257
+ invariant8(doc, void 0, {
2258
+ F: __dxlog_file9,
2259
+ L: 33,
2260
+ S: this,
2261
+ A: [
2262
+ "doc",
2263
+ ""
2264
+ ]
2265
+ });
2266
+ const currentHeads = A3.getHeads(doc);
2267
+ if (!A3.equals(currentHeads, heads)) {
2268
+ const begin = Date.now();
2269
+ doc = A3.view(doc, heads);
2270
+ const end = Date.now();
2271
+ if (end - begin > LOG_VIEW_OPERATION_THRESHOLD) {
2272
+ log8.info("Checking out document version is taking too long", {
2273
+ duration: end - begin,
2274
+ requestedHeads: heads,
2275
+ originalHeads: currentHeads
2276
+ }, {
2277
+ F: __dxlog_file9,
2278
+ L: 44,
2279
+ S: this,
2280
+ C: (f, a) => f(...a)
2281
+ });
2282
+ }
2283
+ }
2284
+ if (doc.version !== SpaceDocVersion.CURRENT) {
2285
+ continue;
2286
+ }
2287
+ if (!doc.objects?.[objectId]) {
2288
+ continue;
2289
+ }
2290
+ let newId = id;
2291
+ if (objectPointerCodec2.getVersion(id) === ObjectPointerVersion.V0) {
2292
+ const spaceKey = getSpaceKeyFromDoc(doc) ?? void 0;
2293
+ newId = objectPointerCodec2.encode({
2294
+ documentId,
2295
+ objectId,
2296
+ spaceKey
2297
+ });
2298
+ }
2299
+ yield [
2300
+ {
2301
+ id: newId,
2302
+ object: doc.objects[objectId],
2303
+ heads
2304
+ }
2305
+ ];
2306
+ } catch (error) {
2307
+ log8.error("Error loading document", {
2308
+ heads,
2309
+ id,
2310
+ error
2311
+ }, {
2312
+ F: __dxlog_file9,
2313
+ L: 70,
2314
+ S: this,
2315
+ C: (f, a) => f(...a)
2316
+ });
2317
+ }
2318
+ }
2319
+ }
2320
+ );
2321
+
2322
+ // packages/core/echo/echo-pipeline/src/db-host/query-service.ts
2323
+ import { DeferredTask } from "@dxos/async";
2324
+ import { getHeads as getHeads3 } from "@dxos/automerge/automerge";
2325
+ import { Stream as Stream2 } from "@dxos/codec-protobuf";
2326
+ import { Context as Context4, Resource as Resource7 } from "@dxos/context";
2327
+ import { log as log9 } from "@dxos/log";
2328
+ import { objectPointerCodec as objectPointerCodec4 } from "@dxos/protocols";
2329
+ import { trace as trace4 } from "@dxos/tracing";
2330
+
2331
+ // packages/core/echo/echo-pipeline/src/db-host/query-state.ts
2332
+ import { Context as Context3, LifecycleState as LifecycleState3, Resource as Resource6 } from "@dxos/context";
2333
+ import { createIdFromSpaceKey as createIdFromSpaceKey2 } from "@dxos/echo-protocol";
2334
+ import { invariant as invariant9 } from "@dxos/invariant";
2335
+ import { PublicKey as PublicKey3 } from "@dxos/keys";
2336
+ import { objectPointerCodec as objectPointerCodec3 } from "@dxos/protocols";
2337
+ import { trace as trace3 } from "@dxos/tracing";
2338
+ import { nonNullable as nonNullable2 } from "@dxos/util";
2339
+ function _ts_decorate4(decorators, target, key, desc) {
2340
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2341
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2342
+ 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;
2343
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2344
+ }
2345
+ var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/query-state.ts";
2346
+ var QueryState = class extends Resource6 {
2347
+ get active() {
2348
+ return this._lifecycleState === LifecycleState3.OPEN;
2349
+ }
2350
+ constructor(_params) {
2351
+ super();
2352
+ this._params = _params;
2353
+ this._results = [];
2354
+ this._firstRun = true;
2355
+ this.metrics = {
2356
+ objectsReturned: 0,
2357
+ objectsReturnedFromIndex: 0,
2358
+ documentsLoaded: 0,
2359
+ executionTime: 0,
2360
+ indexQueryTime: 0,
2361
+ documentLoadTime: 0
2362
+ };
2363
+ this.filter = _params.request.filter;
2364
+ }
2365
+ getResults() {
2366
+ return this._results;
2367
+ }
2368
+ // https://github.com/open-telemetry/semantic-conventions/blob/main/docs/attributes-registry/db.md#generic-database-attributes
2369
+ async execQuery() {
2370
+ const filter = this._params.request.filter;
2371
+ const beginQuery = performance.now();
2372
+ const hits = filter.objectIds && filter.objectIds?.length > 0 ? [] : await this._params.indexer.execQuery(filterToIndexQuery(filter));
2373
+ if (this._firstRun) {
2374
+ this.metrics.indexQueryTime = performance.now() - beginQuery;
2375
+ }
2376
+ const beginFilter = performance.now();
2377
+ const results = (await Promise.all(hits.map(async (result) => {
2378
+ if (this._firstRun) {
2379
+ this.metrics.objectsReturnedFromIndex++;
2380
+ }
2381
+ const { objectId, documentId, spaceKey: spaceKeyInIndex } = objectPointerCodec3.decode(result.id);
2382
+ let spaceKey;
2383
+ if (spaceKeyInIndex !== void 0) {
2384
+ spaceKey = spaceKeyInIndex;
2385
+ } else {
2386
+ if (this._firstRun) {
2387
+ this.metrics.documentsLoaded++;
2388
+ }
2389
+ const handle = await this._params.automergeHost.loadDoc(Context3.default(void 0, {
2390
+ F: __dxlog_file10,
2391
+ L: 116
2392
+ }), documentId);
2393
+ if (this._ctx.disposed) {
2394
+ return;
2395
+ }
2396
+ spaceKey = getSpaceKeyFromDoc(handle.docSync());
2397
+ }
2398
+ if (!spaceKey) {
2399
+ return;
2400
+ }
2401
+ if (this._params.request.filter.options?.spaces?.length && !this._params.request.filter.options.spaces.some((key) => key.equals(spaceKey))) {
2402
+ return;
2403
+ }
2404
+ if (this._firstRun) {
2405
+ this.metrics.objectsReturned++;
2406
+ }
2407
+ return {
2408
+ id: objectId,
2409
+ documentId,
2410
+ spaceId: await createIdFromSpaceKey2(PublicKey3.from(spaceKey)),
2411
+ spaceKey: PublicKey3.from(spaceKey),
2412
+ rank: result.rank
2413
+ };
2414
+ }))).filter(nonNullable2);
2415
+ if (this._firstRun) {
2416
+ this.metrics.documentLoadTime = performance.now() - beginFilter;
2417
+ }
2418
+ if (this._ctx.disposed) {
2419
+ return {
2420
+ changed: false
2421
+ };
2422
+ }
2423
+ const areResultsUnchanged = !this._firstRun && this._results.length === results.length && this._results.every((oldResult) => results.some((result) => result.id === oldResult.id)) && results.every((result) => this._results.some((oldResult) => oldResult.id === result.id));
2424
+ if (this._firstRun) {
2425
+ this.metrics.executionTime = performance.now() - beginQuery;
2426
+ }
2427
+ this._firstRun = false;
2428
+ if (areResultsUnchanged) {
2429
+ return {
2430
+ changed: false
2431
+ };
2432
+ }
2433
+ this._results = results;
2434
+ return {
2435
+ changed: true
2436
+ };
2437
+ }
2438
+ };
2439
+ _ts_decorate4([
2440
+ trace3.info({
2441
+ depth: null
2442
+ })
2443
+ ], QueryState.prototype, "filter", void 0);
2444
+ _ts_decorate4([
2445
+ trace3.info()
2446
+ ], QueryState.prototype, "metrics", void 0);
2447
+ _ts_decorate4([
2448
+ trace3.info()
2449
+ ], QueryState.prototype, "active", null);
2450
+ _ts_decorate4([
2451
+ trace3.span({
2452
+ showInBrowserTimeline: true,
2453
+ op: "db.query",
2454
+ attributes: {
2455
+ "db.system": "echo"
2456
+ }
2457
+ })
2458
+ ], QueryState.prototype, "execQuery", null);
2459
+ QueryState = _ts_decorate4([
2460
+ trace3.resource()
2461
+ ], QueryState);
2462
+ var filterToIndexQuery = (filter) => {
2463
+ invariant9(!(filter.type && (filter.or ?? []).length > 0), "Cannot mix type and or filters.", {
2464
+ F: __dxlog_file10,
2465
+ L: 181,
2466
+ S: void 0,
2467
+ A: [
2468
+ "!(filter.type && (filter.or ?? []).length > 0)",
2469
+ "'Cannot mix type and or filters.'"
2470
+ ]
2471
+ });
2472
+ invariant9((filter.or ?? []).every((subFilter) => !(subFilter.type && (subFilter.or ?? []).length > 0)), "Cannot mix type and or filters.", {
2473
+ F: __dxlog_file10,
2474
+ L: 182,
2475
+ S: void 0,
2476
+ A: [
2477
+ "(filter.or ?? []).every((subFilter) => !(subFilter.type && (subFilter.or ?? []).length > 0))",
2478
+ "'Cannot mix type and or filters.'"
2479
+ ]
2480
+ });
2481
+ if (filter.type || (filter.or ?? []).length > 0 && (filter.or ?? []).every((subFilter) => !subFilter.not && subFilter.type)) {
2482
+ return {
2483
+ typenames: filter.type?.objectId ? [
2484
+ filter.type.objectId
2485
+ ] : (filter.or ?? []).map((f) => f.type?.objectId).filter(nonNullable2),
2486
+ inverted: filter.not
2487
+ };
2488
+ } else {
2130
2489
  return {
2131
- peers: state.peers.map((peer) => ({
2132
- peerId: peer.peerId,
2133
- documentsToReconcile: peer.differentDocuments
2134
- }))
2490
+ typenames: []
2135
2491
  };
2136
2492
  }
2137
2493
  };
2138
2494
 
2139
- export {
2140
- DocumentsSynchronizer,
2141
- diffCollectionState,
2142
- LevelDBStorageAdapter,
2143
- encodingOptions,
2495
+ // packages/core/echo/echo-pipeline/src/db-host/query-service.ts
2496
+ var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/query-service.ts";
2497
+ var QueryServiceImpl = class extends Resource7 {
2498
+ // TODO(burdon): OK for options, but not params. Pass separately and type readonly here.
2499
+ constructor(_params) {
2500
+ super();
2501
+ this._params = _params;
2502
+ this._queries = /* @__PURE__ */ new Set();
2503
+ this._updateQueries = new DeferredTask(this._ctx, async () => {
2504
+ await Promise.all(Array.from(this._queries).map(async (query) => {
2505
+ try {
2506
+ const { changed } = await query.state.execQuery();
2507
+ if (changed) {
2508
+ query.sendResults(query.state.getResults());
2509
+ }
2510
+ } catch (err) {
2511
+ log9.catch(err, void 0, {
2512
+ F: __dxlog_file11,
2513
+ L: 52,
2514
+ S: this,
2515
+ C: (f, a) => f(...a)
2516
+ });
2517
+ }
2518
+ }));
2519
+ });
2520
+ trace4.diagnostic({
2521
+ id: "active-queries",
2522
+ name: "Active Queries",
2523
+ fetch: () => {
2524
+ return Array.from(this._queries).map((query) => {
2525
+ return {
2526
+ filter: JSON.stringify(query.state.filter),
2527
+ metrics: query.state.metrics
2528
+ };
2529
+ });
2530
+ }
2531
+ });
2532
+ }
2533
+ async _open() {
2534
+ this._params.indexer.updated.on(this._ctx, () => this._updateQueries.schedule());
2535
+ }
2536
+ async _close() {
2537
+ await Promise.all(Array.from(this._queries).map((query) => query.close()));
2538
+ }
2539
+ async setConfig(config) {
2540
+ if (this._params.indexer.initialized) {
2541
+ log9.warn("Indexer already initialized.", void 0, {
2542
+ F: __dxlog_file11,
2543
+ L: 86,
2544
+ S: this,
2545
+ C: (f, a) => f(...a)
2546
+ });
2547
+ return;
2548
+ }
2549
+ this._params.indexer.setConfig(config);
2550
+ }
2551
+ execQuery(request) {
2552
+ return new Stream2(({ next, close, ctx }) => {
2553
+ const query = {
2554
+ state: new QueryState({
2555
+ indexer: this._params.indexer,
2556
+ automergeHost: this._params.automergeHost,
2557
+ request
2558
+ }),
2559
+ sendResults: (results) => {
2560
+ if (ctx.disposed) {
2561
+ return;
2562
+ }
2563
+ next({
2564
+ queryId: request.queryId,
2565
+ results
2566
+ });
2567
+ },
2568
+ close: async () => {
2569
+ close();
2570
+ await query.state.close();
2571
+ this._queries.delete(query);
2572
+ }
2573
+ };
2574
+ this._queries.add(query);
2575
+ queueMicrotask(async () => {
2576
+ await query.state.open();
2577
+ try {
2578
+ const { changed } = await query.state.execQuery();
2579
+ if (changed) {
2580
+ query.sendResults(query.state.getResults());
2581
+ }
2582
+ } catch (error) {
2583
+ log9.catch(error, void 0, {
2584
+ F: __dxlog_file11,
2585
+ L: 123,
2586
+ S: this,
2587
+ C: (f, a) => f(...a)
2588
+ });
2589
+ }
2590
+ });
2591
+ return query.close;
2592
+ });
2593
+ }
2594
+ /**
2595
+ * Re-index all loaded documents.
2596
+ */
2597
+ async reindex() {
2598
+ log9.info("Reindexing all documents...", void 0, {
2599
+ F: __dxlog_file11,
2600
+ L: 135,
2601
+ S: this,
2602
+ C: (f, a) => f(...a)
2603
+ });
2604
+ const iterator = createDocumentsIterator(this._params.automergeHost);
2605
+ const ids = /* @__PURE__ */ new Map();
2606
+ for await (const documents of iterator()) {
2607
+ for (const { id, heads } of documents) {
2608
+ ids.set(id, heads);
2609
+ }
2610
+ if (ids.size % 100 === 0) {
2611
+ log9.info("Collected documents...", {
2612
+ count: ids.size
2613
+ }, {
2614
+ F: __dxlog_file11,
2615
+ L: 143,
2616
+ S: this,
2617
+ C: (f, a) => f(...a)
2618
+ });
2619
+ }
2620
+ }
2621
+ log9.info("Marking all documents as dirty...", {
2622
+ count: ids.size
2623
+ }, {
2624
+ F: __dxlog_file11,
2625
+ L: 147,
2626
+ S: this,
2627
+ C: (f, a) => f(...a)
2628
+ });
2629
+ await this._params.indexer.reindex(ids);
2630
+ }
2631
+ };
2632
+ var createDocumentsIterator = (automergeHost) => (
2633
+ /**
2634
+ * Recursively get all object data blobs from loaded documents from Automerge Repo.
2635
+ */
2636
+ // TODO(mykola): Unload automerge handles after usage.
2637
+ async function* getAllDocuments() {
2638
+ const visited = /* @__PURE__ */ new Set();
2639
+ async function* getObjectsFromHandle(handle) {
2640
+ if (visited.has(handle.documentId)) {
2641
+ return;
2642
+ }
2643
+ const doc = handle.docSync();
2644
+ const spaceKey = getSpaceKeyFromDoc(doc) ?? void 0;
2645
+ if (doc.objects) {
2646
+ yield Object.entries(doc.objects).map(([objectId, object]) => {
2647
+ return {
2648
+ id: objectPointerCodec4.encode({
2649
+ documentId: handle.documentId,
2650
+ objectId,
2651
+ spaceKey
2652
+ }),
2653
+ object,
2654
+ heads: getHeads3(doc)
2655
+ };
2656
+ });
2657
+ }
2658
+ if (doc.links) {
2659
+ for (const id of Object.values(doc.links)) {
2660
+ if (visited.has(id)) {
2661
+ continue;
2662
+ }
2663
+ const linkHandle = await automergeHost.loadDoc(Context4.default(void 0, {
2664
+ F: __dxlog_file11,
2665
+ L: 188
2666
+ }), id);
2667
+ for await (const result of getObjectsFromHandle(linkHandle)) {
2668
+ yield result;
2669
+ }
2670
+ }
2671
+ }
2672
+ visited.add(handle.documentId);
2673
+ }
2674
+ for (const handle of Object.values(automergeHost.repo.handles)) {
2675
+ if (visited.has(handle.documentId)) {
2676
+ continue;
2677
+ }
2678
+ for await (const result of getObjectsFromHandle(handle)) {
2679
+ yield result;
2680
+ }
2681
+ visited.add(handle.documentId);
2682
+ }
2683
+ }
2684
+ );
2685
+
2686
+ // packages/core/echo/echo-pipeline/src/db-host/space-state-manager.ts
2687
+ import isEqual from "lodash.isequal";
2688
+ import { Event as Event3, UpdateScheduler as UpdateScheduler3 } from "@dxos/async";
2689
+ import { interpretAsDocumentId } from "@dxos/automerge/automerge-repo";
2690
+ import { Resource as Resource8, Context as Context5 } from "@dxos/context";
2691
+
2692
+ // packages/core/echo/echo-pipeline/src/db-host/database-root.ts
2693
+ import { SpaceDocVersion as SpaceDocVersion2 } from "@dxos/echo-protocol";
2694
+ import { invariant as invariant10 } from "@dxos/invariant";
2695
+
2696
+ // packages/core/echo/echo-pipeline/src/db-host/automerge-metrics.ts
2697
+ import * as A4 from "@dxos/automerge/automerge";
2698
+ import { log as log10 } from "@dxos/log";
2699
+ var __dxlog_file12 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/automerge-metrics.ts";
2700
+ var measureDocMetrics = (doc) => {
2701
+ const snapshot = A4.save(doc);
2702
+ const start = Date.now();
2703
+ const temp = A4.load(snapshot);
2704
+ const end = Date.now();
2705
+ A4.free(temp);
2706
+ const getAllChangesStart = Date.now();
2707
+ const mutationCount = A4.getAllChanges(doc).length;
2708
+ const getAllChangesEnd = Date.now();
2709
+ if (getAllChangesEnd - getAllChangesStart > 300) {
2710
+ log10.warn("getAllChanges took too long", {
2711
+ elapsed: getAllChangesEnd - getAllChangesStart
2712
+ }, {
2713
+ F: __dxlog_file12,
2714
+ L: 30,
2715
+ S: void 0,
2716
+ C: (f, a) => f(...a)
2717
+ });
2718
+ }
2719
+ return {
2720
+ compressedByteSize: snapshot.byteLength,
2721
+ loadTime: end - start,
2722
+ mutationCount
2723
+ };
2724
+ };
2725
+
2726
+ // packages/core/echo/echo-pipeline/src/db-host/database-root.ts
2727
+ var __dxlog_file13 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/database-root.ts";
2728
+ var DatabaseRoot = class {
2729
+ constructor(_rootHandle) {
2730
+ this._rootHandle = _rootHandle;
2731
+ }
2732
+ get documentId() {
2733
+ return this._rootHandle.documentId;
2734
+ }
2735
+ get url() {
2736
+ return this._rootHandle.url;
2737
+ }
2738
+ get isLoaded() {
2739
+ return !!this._rootHandle.docSync();
2740
+ }
2741
+ get handle() {
2742
+ return this._rootHandle;
2743
+ }
2744
+ docSync() {
2745
+ return this._rootHandle.docSync();
2746
+ }
2747
+ getVersion() {
2748
+ const doc = this.docSync();
2749
+ if (!doc) {
2750
+ return null;
2751
+ }
2752
+ return doc.version ?? SpaceDocVersion2.LEGACY;
2753
+ }
2754
+ getSpaceKey() {
2755
+ const doc = this.docSync();
2756
+ if (!doc) {
2757
+ return null;
2758
+ }
2759
+ return getSpaceKeyFromDoc(doc);
2760
+ }
2761
+ getInlineObjectCount() {
2762
+ const doc = this.docSync();
2763
+ if (!doc) {
2764
+ return null;
2765
+ }
2766
+ return Object.keys(doc.objects ?? {}).length;
2767
+ }
2768
+ getLinkedObjectCount() {
2769
+ const doc = this.docSync();
2770
+ if (!doc) {
2771
+ return null;
2772
+ }
2773
+ return Object.keys(doc.links ?? {}).length;
2774
+ }
2775
+ getAllLinkedDocuments() {
2776
+ const doc = this.docSync();
2777
+ invariant10(doc, void 0, {
2778
+ F: __dxlog_file13,
2779
+ L: 74,
2780
+ S: this,
2781
+ A: [
2782
+ "doc",
2783
+ ""
2784
+ ]
2785
+ });
2786
+ return Object.values(doc.links ?? {});
2787
+ }
2788
+ measureMetrics() {
2789
+ const doc = this.docSync();
2790
+ if (!doc) {
2791
+ return null;
2792
+ }
2793
+ return measureDocMetrics(doc);
2794
+ }
2795
+ };
2796
+
2797
+ // packages/core/echo/echo-pipeline/src/db-host/space-state-manager.ts
2798
+ var __dxlog_file14 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/space-state-manager.ts";
2799
+ var SpaceStateManager = class extends Resource8 {
2800
+ constructor() {
2801
+ super(...arguments);
2802
+ this._roots = /* @__PURE__ */ new Map();
2803
+ this._rootBySpace = /* @__PURE__ */ new Map();
2804
+ this._perRootContext = /* @__PURE__ */ new Map();
2805
+ this._lastSpaceDocumentList = /* @__PURE__ */ new Map();
2806
+ this.spaceDocumentListUpdated = new Event3();
2807
+ }
2808
+ async _close(ctx) {
2809
+ for (const [_, rootCtx] of this._perRootContext) {
2810
+ await rootCtx.dispose();
2811
+ }
2812
+ this._roots.clear();
2813
+ }
2814
+ get roots() {
2815
+ return this._roots;
2816
+ }
2817
+ getRootByDocumentId(documentId) {
2818
+ return this._roots.get(documentId);
2819
+ }
2820
+ async assignRootToSpace(spaceId, handle) {
2821
+ let root;
2822
+ if (this._roots.has(handle.documentId)) {
2823
+ root = this._roots.get(handle.documentId);
2824
+ } else {
2825
+ root = new DatabaseRoot(handle);
2826
+ this._roots.set(handle.documentId, root);
2827
+ }
2828
+ if (this._rootBySpace.get(spaceId) === root.handle.documentId) {
2829
+ return root;
2830
+ }
2831
+ const prevRootId = this._rootBySpace.get(spaceId);
2832
+ if (prevRootId) {
2833
+ void this._perRootContext.get(prevRootId)?.dispose();
2834
+ this._perRootContext.delete(prevRootId);
2835
+ }
2836
+ this._rootBySpace.set(spaceId, root.handle.documentId);
2837
+ const ctx = new Context5(void 0, {
2838
+ F: __dxlog_file14,
2839
+ L: 58
2840
+ });
2841
+ this._perRootContext.set(root.handle.documentId, ctx);
2842
+ await root.handle.whenReady();
2843
+ const documentListCheckScheduler = new UpdateScheduler3(ctx, async () => {
2844
+ const documentIds = [
2845
+ root.documentId,
2846
+ ...root.getAllLinkedDocuments().map((url) => interpretAsDocumentId(url))
2847
+ ];
2848
+ if (!isEqual(documentIds, this._lastSpaceDocumentList.get(spaceId))) {
2849
+ this._lastSpaceDocumentList.set(spaceId, documentIds);
2850
+ this.spaceDocumentListUpdated.emit(new SpaceDocumentListUpdatedEvent(spaceId, documentIds));
2851
+ }
2852
+ }, {
2853
+ maxFrequency: 50
2854
+ });
2855
+ const triggerCheckOnChange = () => documentListCheckScheduler.trigger();
2856
+ root.handle.addListener("change", triggerCheckOnChange);
2857
+ ctx.onDispose(() => root.handle.removeListener("change", triggerCheckOnChange));
2858
+ documentListCheckScheduler.trigger();
2859
+ return root;
2860
+ }
2861
+ };
2862
+ var SpaceDocumentListUpdatedEvent = class {
2863
+ constructor(spaceId, documentIds) {
2864
+ this.spaceId = spaceId;
2865
+ this.documentIds = documentIds;
2866
+ }
2867
+ };
2868
+
2869
+ // packages/core/echo/echo-pipeline/src/db-host/echo-host.ts
2870
+ var __dxlog_file15 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/db-host/echo-host.ts";
2871
+ var INDEXER_CONFIG = {
2872
+ enabled: true,
2873
+ indexes: [
2874
+ {
2875
+ kind: IndexKind.Kind.SCHEMA_MATCH
2876
+ }
2877
+ ]
2878
+ };
2879
+ var EchoHost = class extends Resource9 {
2880
+ constructor({ kv }) {
2881
+ super();
2882
+ this._spaceStateManager = new SpaceStateManager();
2883
+ this._indexMetadataStore = new IndexMetadataStore({
2884
+ db: kv.sublevel("index-metadata")
2885
+ });
2886
+ this._echoDataMonitor = new EchoDataMonitor();
2887
+ this._automergeHost = new AutomergeHost({
2888
+ db: kv,
2889
+ dataMonitor: this._echoDataMonitor,
2890
+ indexMetadataStore: this._indexMetadataStore
2891
+ });
2892
+ this._indexer = new Indexer({
2893
+ db: kv,
2894
+ indexStore: new IndexStore({
2895
+ db: kv.sublevel("index-storage")
2896
+ }),
2897
+ metadataStore: this._indexMetadataStore,
2898
+ loadDocuments: createSelectedDocumentsIterator(this._automergeHost),
2899
+ indexCooldownTime: process.env.NODE_ENV === "test" ? 0 : void 0
2900
+ });
2901
+ this._indexer.setConfig(INDEXER_CONFIG);
2902
+ this._queryService = new QueryServiceImpl({
2903
+ automergeHost: this._automergeHost,
2904
+ indexer: this._indexer
2905
+ });
2906
+ this._dataService = new DataServiceImpl({
2907
+ automergeHost: this._automergeHost,
2908
+ updateIndexes: async () => {
2909
+ await this._indexer.updateIndexes();
2910
+ }
2911
+ });
2912
+ trace5.diagnostic({
2913
+ id: "echo-stats",
2914
+ name: "Echo Stats",
2915
+ fetch: async () => {
2916
+ return {
2917
+ dataStats: this._echoDataMonitor.computeStats(),
2918
+ loadedDocsCount: this._automergeHost.loadedDocsCount
2919
+ };
2920
+ }
2921
+ });
2922
+ trace5.diagnostic({
2923
+ id: "database-roots",
2924
+ name: "Database Roots",
2925
+ fetch: async () => {
2926
+ return Array.from(this._spaceStateManager.roots.values()).map((root) => ({
2927
+ url: root.url,
2928
+ isLoaded: root.isLoaded,
2929
+ spaceKey: root.getSpaceKey(),
2930
+ inlineObjects: root.getInlineObjectCount(),
2931
+ linkedObjects: root.getLinkedObjectCount()
2932
+ }));
2933
+ }
2934
+ });
2935
+ trace5.diagnostic({
2936
+ id: "database-root-metrics",
2937
+ name: "Database Roots (with metrics)",
2938
+ fetch: async () => {
2939
+ return Array.from(this._spaceStateManager.roots.values()).map((root) => ({
2940
+ url: root.url,
2941
+ isLoaded: root.isLoaded,
2942
+ spaceKey: root.getSpaceKey(),
2943
+ inlineObjects: root.getInlineObjectCount(),
2944
+ linkedObjects: root.getLinkedObjectCount(),
2945
+ ...root.measureMetrics() ?? {}
2946
+ }));
2947
+ }
2948
+ });
2949
+ }
2950
+ get queryService() {
2951
+ return this._queryService;
2952
+ }
2953
+ get dataService() {
2954
+ return this._dataService;
2955
+ }
2956
+ /**
2957
+ * @deprecated To be abstracted away.
2958
+ */
2959
+ get automergeRepo() {
2960
+ return this._automergeHost.repo;
2961
+ }
2962
+ get roots() {
2963
+ return this._spaceStateManager.roots;
2964
+ }
2965
+ async _open(ctx) {
2966
+ await this._automergeHost.open();
2967
+ await this._indexer.open(ctx);
2968
+ await this._queryService.open(ctx);
2969
+ await this._spaceStateManager.open(ctx);
2970
+ this._spaceStateManager.spaceDocumentListUpdated.on(this._ctx, (e) => {
2971
+ void this._automergeHost.updateLocalCollectionState(deriveCollectionIdFromSpaceId(e.spaceId), e.documentIds);
2972
+ });
2973
+ }
2974
+ async _close(ctx) {
2975
+ await this._spaceStateManager.close();
2976
+ await this._queryService.close(ctx);
2977
+ await this._indexer.close(ctx);
2978
+ await this._automergeHost.close();
2979
+ }
2980
+ /**
2981
+ * Flush all pending writes to the underlying storage.
2982
+ */
2983
+ async flush() {
2984
+ await this._automergeHost.repo.flush();
2985
+ }
2986
+ /**
2987
+ * Perform any pending index updates.
2988
+ */
2989
+ async updateIndexes() {
2990
+ await this._indexer.updateIndexes();
2991
+ }
2992
+ /**
2993
+ * Loads the document handle from the repo and waits for it to be ready.
2994
+ */
2995
+ async loadDoc(ctx, documentId, opts) {
2996
+ return await this._automergeHost.loadDoc(ctx, documentId, opts);
2997
+ }
2998
+ /**
2999
+ * Create new persisted document.
3000
+ */
3001
+ createDoc(initialValue, opts) {
3002
+ return this._automergeHost.createDoc(initialValue, opts);
3003
+ }
3004
+ /**
3005
+ * Create new space root.
3006
+ */
3007
+ async createSpaceRoot(spaceKey) {
3008
+ invariant11(this._lifecycleState === LifecycleState4.OPEN, void 0, {
3009
+ F: __dxlog_file15,
3010
+ L: 206,
3011
+ S: this,
3012
+ A: [
3013
+ "this._lifecycleState === LifecycleState.OPEN",
3014
+ ""
3015
+ ]
3016
+ });
3017
+ const spaceId = await createIdFromSpaceKey3(spaceKey);
3018
+ const automergeRoot = this._automergeHost.createDoc({
3019
+ version: SpaceDocVersion3.CURRENT,
3020
+ access: {
3021
+ spaceKey: spaceKey.toHex()
3022
+ }
3023
+ });
3024
+ await this._automergeHost.flush({
3025
+ documentIds: [
3026
+ automergeRoot.documentId
3027
+ ]
3028
+ });
3029
+ return await this.openSpaceRoot(spaceId, automergeRoot.url);
3030
+ }
3031
+ // TODO(dmaretskyi): Change to document id.
3032
+ async openSpaceRoot(spaceId, automergeUrl) {
3033
+ invariant11(this._lifecycleState === LifecycleState4.OPEN, void 0, {
3034
+ F: __dxlog_file15,
3035
+ L: 221,
3036
+ S: this,
3037
+ A: [
3038
+ "this._lifecycleState === LifecycleState.OPEN",
3039
+ ""
3040
+ ]
3041
+ });
3042
+ const handle = this._automergeHost.repo.find(automergeUrl);
3043
+ return this._spaceStateManager.assignRootToSpace(spaceId, handle);
3044
+ }
3045
+ // TODO(dmaretskyi): Change to document id.
3046
+ async closeSpaceRoot(automergeUrl) {
3047
+ todo();
3048
+ }
3049
+ /**
3050
+ * Install data replicator.
3051
+ */
3052
+ async addReplicator(replicator) {
3053
+ await this._automergeHost.addReplicator(replicator);
3054
+ }
3055
+ /**
3056
+ * Remove data replicator.
3057
+ */
3058
+ async removeReplicator(replicator) {
3059
+ await this._automergeHost.removeReplicator(replicator);
3060
+ }
3061
+ async getSpaceSyncState(spaceId) {
3062
+ const collectionId = deriveCollectionIdFromSpaceId(spaceId);
3063
+ return this._automergeHost.getCollectionSyncState(collectionId);
3064
+ }
3065
+ };
3066
+
3067
+ // packages/core/echo/echo-pipeline/src/db-host/migration.ts
3068
+ import { convertLegacyReference } from "@dxos/echo-protocol";
3069
+ import { decodeReference, encodeReference, isLegacyReference, LEGACY_TYPE_PROPERTIES, Reference, SpaceDocVersion as SpaceDocVersion4 } from "@dxos/echo-protocol";
3070
+ import { TYPE_PROPERTIES } from "@dxos/echo-schema";
3071
+ import { deepMapValuesAsync } from "@dxos/util";
3072
+ var convertLegacyReferences = async (doc) => {
3073
+ const newDoc = await deepMapValuesAsync(doc, async (value, recurse) => {
3074
+ if (isLegacyReference(value)) {
3075
+ return convertLegacyReference(value);
3076
+ }
3077
+ return recurse(value);
3078
+ });
3079
+ newDoc.version = SpaceDocVersion4.CURRENT;
3080
+ return newDoc;
3081
+ };
3082
+ var convertLegacySpaceRootDoc = async (root) => {
3083
+ const newDoc = await convertLegacyReferences(root);
3084
+ const properties = findInlineObjectOfType(newDoc, LEGACY_TYPE_PROPERTIES);
3085
+ if (properties) {
3086
+ const [_, obj] = properties;
3087
+ obj.system.type = encodeReference(Reference.fromLegacyTypename(TYPE_PROPERTIES));
3088
+ }
3089
+ return newDoc;
3090
+ };
3091
+ var findInlineObjectOfType = (spaceDoc, typename) => {
3092
+ for (const id in spaceDoc.objects ?? {}) {
3093
+ const obj = spaceDoc.objects[id];
3094
+ if (obj.system.type && decodeReference(obj.system.type).objectId === typename) {
3095
+ return [
3096
+ id,
3097
+ obj
3098
+ ];
3099
+ }
3100
+ }
3101
+ return void 0;
3102
+ };
3103
+
3104
+ // packages/core/echo/echo-pipeline/src/edge/echo-edge-replicator.ts
3105
+ import { Mutex, scheduleTask as scheduleTask2 } from "@dxos/async";
3106
+ import * as A5 from "@dxos/automerge/automerge";
3107
+ import { cbor as cbor2 } from "@dxos/automerge/automerge-repo";
3108
+ import { Context as Context6, Resource as Resource10 } from "@dxos/context";
3109
+ import { randomUUID } from "@dxos/crypto";
3110
+ import { invariant as invariant12 } from "@dxos/invariant";
3111
+ import { log as log11 } from "@dxos/log";
3112
+ import { EdgeService } from "@dxos/protocols";
3113
+ import { buf } from "@dxos/protocols/buf";
3114
+ import { MessageSchema as RouterMessageSchema } from "@dxos/protocols/buf/dxos/edge/messenger_pb";
3115
+ import { bufferToArray } from "@dxos/util";
3116
+ function _using_ctx() {
3117
+ var _disposeSuppressedError = typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed) {
3118
+ var err = new Error();
3119
+ err.name = "SuppressedError";
3120
+ err.suppressed = suppressed;
3121
+ err.error = error;
3122
+ return err;
3123
+ }, empty = {}, stack = [];
3124
+ function using(isAwait, value) {
3125
+ if (value != null) {
3126
+ if (Object(value) !== value) {
3127
+ throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
3128
+ }
3129
+ if (isAwait) {
3130
+ var dispose = value[Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose")];
3131
+ }
3132
+ if (dispose == null) {
3133
+ dispose = value[Symbol.dispose || Symbol.for("Symbol.dispose")];
3134
+ }
3135
+ if (typeof dispose !== "function") {
3136
+ throw new TypeError(`Property [Symbol.dispose] is not a function.`);
3137
+ }
3138
+ stack.push({
3139
+ v: value,
3140
+ d: dispose,
3141
+ a: isAwait
3142
+ });
3143
+ } else if (isAwait) {
3144
+ stack.push({
3145
+ d: value,
3146
+ a: isAwait
3147
+ });
3148
+ }
3149
+ return value;
3150
+ }
3151
+ return {
3152
+ e: empty,
3153
+ u: using.bind(null, false),
3154
+ a: using.bind(null, true),
3155
+ d: function() {
3156
+ var error = this.e;
3157
+ function next() {
3158
+ while (resource = stack.pop()) {
3159
+ try {
3160
+ var resource, disposalResult = resource.d && resource.d.call(resource.v);
3161
+ if (resource.a) {
3162
+ return Promise.resolve(disposalResult).then(next, err);
3163
+ }
3164
+ } catch (e) {
3165
+ return err(e);
3166
+ }
3167
+ }
3168
+ if (error !== empty) throw error;
3169
+ }
3170
+ function err(e) {
3171
+ error = error !== empty ? new _disposeSuppressedError(error, e) : e;
3172
+ return next();
3173
+ }
3174
+ return next();
3175
+ }
3176
+ };
3177
+ }
3178
+ var __dxlog_file16 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/edge/echo-edge-replicator.ts";
3179
+ var RESTART_DELAY = 500;
3180
+ var EchoEdgeReplicator = class {
3181
+ constructor({ edgeConnection, disableSharePolicy }) {
3182
+ this._mutex = new Mutex();
3183
+ this._ctx = void 0;
3184
+ this._context = null;
3185
+ this._connectedSpaces = /* @__PURE__ */ new Set();
3186
+ this._connections = /* @__PURE__ */ new Map();
3187
+ this._sharePolicyEnabled = true;
3188
+ this._edgeConnection = edgeConnection;
3189
+ this._sharePolicyEnabled = !disableSharePolicy;
3190
+ }
3191
+ async connect(context) {
3192
+ log11.info("connect", {
3193
+ peerId: context.peerId,
3194
+ connectedSpaces: this._connectedSpaces.size
3195
+ }, {
3196
+ F: __dxlog_file16,
3197
+ L: 58,
3198
+ S: this,
3199
+ C: (f, a) => f(...a)
3200
+ });
3201
+ this._context = context;
3202
+ this._ctx = Context6.default(void 0, {
3203
+ F: __dxlog_file16,
3204
+ L: 61
3205
+ });
3206
+ this._edgeConnection.reconnect.on(this._ctx, async () => {
3207
+ try {
3208
+ var _usingCtx = _using_ctx();
3209
+ const _guard = _usingCtx.u(await this._mutex.acquire());
3210
+ const spaces = [
3211
+ ...this._connectedSpaces
3212
+ ];
3213
+ for (const connection of this._connections.values()) {
3214
+ await connection.close();
3215
+ }
3216
+ this._connections.clear();
3217
+ if (this._context !== null) {
3218
+ for (const spaceId of spaces) {
3219
+ await this._openConnection(spaceId);
3220
+ }
3221
+ }
3222
+ } catch (_) {
3223
+ _usingCtx.e = _;
3224
+ } finally {
3225
+ _usingCtx.d();
3226
+ }
3227
+ });
3228
+ for (const spaceId of this._connectedSpaces) {
3229
+ await this._openConnection(spaceId);
3230
+ }
3231
+ }
3232
+ async disconnect() {
3233
+ try {
3234
+ var _usingCtx = _using_ctx();
3235
+ const _guard = _usingCtx.u(await this._mutex.acquire());
3236
+ await this._ctx?.dispose();
3237
+ for (const connection of this._connections.values()) {
3238
+ await connection.close();
3239
+ }
3240
+ this._connections.clear();
3241
+ } catch (_) {
3242
+ _usingCtx.e = _;
3243
+ } finally {
3244
+ _usingCtx.d();
3245
+ }
3246
+ }
3247
+ async connectToSpace(spaceId) {
3248
+ try {
3249
+ var _usingCtx = _using_ctx();
3250
+ const _guard = _usingCtx.u(await this._mutex.acquire());
3251
+ this._connectedSpaces.add(spaceId);
3252
+ if (this._context !== null) {
3253
+ await this._openConnection(spaceId);
3254
+ }
3255
+ } catch (_) {
3256
+ _usingCtx.e = _;
3257
+ } finally {
3258
+ _usingCtx.d();
3259
+ }
3260
+ }
3261
+ async disconnectFromSpace(spaceId) {
3262
+ try {
3263
+ var _usingCtx = _using_ctx();
3264
+ const _guard = _usingCtx.u(await this._mutex.acquire());
3265
+ this._connectedSpaces.delete(spaceId);
3266
+ const connection = this._connections.get(spaceId);
3267
+ if (connection) {
3268
+ await connection.close();
3269
+ this._connections.delete(spaceId);
3270
+ }
3271
+ } catch (_) {
3272
+ _usingCtx.e = _;
3273
+ } finally {
3274
+ _usingCtx.d();
3275
+ }
3276
+ }
3277
+ async _openConnection(spaceId) {
3278
+ invariant12(this._context, void 0, {
3279
+ F: __dxlog_file16,
3280
+ L: 117,
3281
+ S: this,
3282
+ A: [
3283
+ "this._context",
3284
+ ""
3285
+ ]
3286
+ });
3287
+ invariant12(!this._connections.has(spaceId), void 0, {
3288
+ F: __dxlog_file16,
3289
+ L: 118,
3290
+ S: this,
3291
+ A: [
3292
+ "!this._connections.has(spaceId)",
3293
+ ""
3294
+ ]
3295
+ });
3296
+ const connection = new EdgeReplicatorConnection({
3297
+ edgeConnection: this._edgeConnection,
3298
+ ownPeerId: this._context.peerId,
3299
+ spaceId,
3300
+ context: this._context,
3301
+ sharedPolicyEnabled: this._sharePolicyEnabled,
3302
+ onRemoteConnected: async () => {
3303
+ this._context?.onConnectionOpen(connection);
3304
+ },
3305
+ onRemoteDisconnected: async () => {
3306
+ this._context?.onConnectionClosed(connection);
3307
+ },
3308
+ onRestartRequested: async () => {
3309
+ try {
3310
+ var _usingCtx = _using_ctx();
3311
+ const _guard = _usingCtx.u(await this._mutex.acquire());
3312
+ const ctx = this._ctx;
3313
+ await connection.close();
3314
+ this._connections.delete(spaceId);
3315
+ if (ctx?.disposed) {
3316
+ return;
3317
+ }
3318
+ await this._openConnection(spaceId);
3319
+ } catch (_) {
3320
+ _usingCtx.e = _;
3321
+ } finally {
3322
+ _usingCtx.d();
3323
+ }
3324
+ }
3325
+ });
3326
+ this._connections.set(spaceId, connection);
3327
+ await connection.open();
3328
+ }
3329
+ };
3330
+ var EdgeReplicatorConnection = class extends Resource10 {
3331
+ constructor({ edgeConnection, ownPeerId, spaceId, context, sharedPolicyEnabled, onRemoteConnected, onRemoteDisconnected, onRestartRequested }) {
3332
+ super();
3333
+ this._remotePeerId = null;
3334
+ this._restartScheduled = false;
3335
+ this._edgeConnection = edgeConnection;
3336
+ this._ownPeerId = ownPeerId;
3337
+ this._spaceId = spaceId;
3338
+ this._context = context;
3339
+ this._remotePeerId = `${EdgeService.AUTOMERGE_REPLICATOR}:${spaceId}-${randomUUID()}`;
3340
+ this._targetServiceId = `${EdgeService.AUTOMERGE_REPLICATOR}:${spaceId}`;
3341
+ this._sharedPolicyEnabled = sharedPolicyEnabled;
3342
+ this._onRemoteConnected = onRemoteConnected;
3343
+ this._onRemoteDisconnected = onRemoteDisconnected;
3344
+ this._onRestartRequested = onRestartRequested;
3345
+ this.readable = new ReadableStream({
3346
+ start: (controller) => {
3347
+ this._readableStreamController = controller;
3348
+ }
3349
+ });
3350
+ this.writable = new WritableStream({
3351
+ write: async (message, controller) => {
3352
+ await this._sendMessage(message);
3353
+ }
3354
+ });
3355
+ }
3356
+ async _open(ctx) {
3357
+ log11("open", void 0, {
3358
+ F: __dxlog_file16,
3359
+ L: 219,
3360
+ S: this,
3361
+ C: (f, a) => f(...a)
3362
+ });
3363
+ this._ctx.onDispose(this._edgeConnection.addListener((msg) => {
3364
+ this._onMessage(msg);
3365
+ }));
3366
+ await this._onRemoteConnected();
3367
+ }
3368
+ async _close() {
3369
+ log11("close", void 0, {
3370
+ F: __dxlog_file16,
3371
+ L: 231,
3372
+ S: this,
3373
+ C: (f, a) => f(...a)
3374
+ });
3375
+ this._readableStreamController.close();
3376
+ await this._onRemoteDisconnected();
3377
+ }
3378
+ get peerId() {
3379
+ invariant12(this._remotePeerId, "Not connected", {
3380
+ F: __dxlog_file16,
3381
+ L: 237,
3382
+ S: this,
3383
+ A: [
3384
+ "this._remotePeerId",
3385
+ "'Not connected'"
3386
+ ]
3387
+ });
3388
+ return this._remotePeerId;
3389
+ }
3390
+ async shouldAdvertise(params) {
3391
+ if (!this._sharedPolicyEnabled) {
3392
+ return true;
3393
+ }
3394
+ const spaceId = await this._context.getContainingSpaceIdForDocument(params.documentId);
3395
+ if (!spaceId) {
3396
+ return true;
3397
+ }
3398
+ return spaceId === this._spaceId;
3399
+ }
3400
+ shouldSyncCollection(params) {
3401
+ if (!this._sharedPolicyEnabled) {
3402
+ return true;
3403
+ }
3404
+ const spaceId = getSpaceIdFromCollectionId(params.collectionId);
3405
+ return spaceId === this._spaceId;
3406
+ }
3407
+ _onMessage(message) {
3408
+ if (message.serviceId !== this._targetServiceId) {
3409
+ return;
3410
+ }
3411
+ const payload = cbor2.decode(message.payload.value);
3412
+ log11("recv", () => {
3413
+ const decodedData = payload.type === "sync" && payload.data ? A5.decodeSyncMessage(payload.data) : payload.type === "collection-state" ? payload.state : payload;
3414
+ return {
3415
+ from: message.serviceId,
3416
+ type: payload.type,
3417
+ decodedData
3418
+ };
3419
+ }, {
3420
+ F: __dxlog_file16,
3421
+ L: 268,
3422
+ S: this,
3423
+ C: (f, a) => f(...a)
3424
+ });
3425
+ payload.senderId = this._remotePeerId;
3426
+ this._processMessage(payload);
3427
+ }
3428
+ _processMessage(message) {
3429
+ if (isForbiddenErrorMessage(message)) {
3430
+ if (!this._restartScheduled) {
3431
+ log11.warn("Forbidden error received, replicator will restart the connection", {
3432
+ spaceId: this._spaceId,
3433
+ delayMs: RESTART_DELAY,
3434
+ remotePeerId: this._remotePeerId
3435
+ }, {
3436
+ F: __dxlog_file16,
3437
+ L: 288,
3438
+ S: this,
3439
+ C: (f, a) => f(...a)
3440
+ });
3441
+ this._restartScheduled = true;
3442
+ scheduleTask2(this._ctx, async () => {
3443
+ await this._onRestartRequested();
3444
+ }, RESTART_DELAY);
3445
+ }
3446
+ return;
3447
+ }
3448
+ this._readableStreamController.enqueue(message);
3449
+ }
3450
+ async _sendMessage(message) {
3451
+ message.targetId = this._targetServiceId;
3452
+ log11("send", {
3453
+ type: message.type,
3454
+ senderId: message.senderId,
3455
+ targetId: message.targetId,
3456
+ documentId: message.documentId
3457
+ }, {
3458
+ F: __dxlog_file16,
3459
+ L: 312,
3460
+ S: this,
3461
+ C: (f, a) => f(...a)
3462
+ });
3463
+ const encoded = cbor2.encode(message);
3464
+ await this._edgeConnection.send(buf.create(RouterMessageSchema, {
3465
+ serviceId: this._targetServiceId,
3466
+ source: {
3467
+ identityKey: this._edgeConnection.identityKey,
3468
+ peerKey: this._edgeConnection.peerKey
3469
+ },
3470
+ payload: {
3471
+ value: bufferToArray(encoded)
3472
+ }
3473
+ }));
3474
+ }
3475
+ };
3476
+ var isForbiddenErrorMessage = (message) => message.type === "error" && message.message === "Forbidden";
3477
+ export {
3478
+ AuthExtension,
3479
+ AuthStatus,
2144
3480
  AutomergeHost,
2145
- getSpaceKeyFromDoc,
3481
+ CredentialRetrieverExtension,
3482
+ CredentialServerExtension,
3483
+ DataServiceImpl,
3484
+ DatabaseRoot,
3485
+ DocumentsSynchronizer,
3486
+ EchoDataMonitor,
3487
+ EchoEdgeReplicator,
3488
+ EchoHost,
3489
+ LevelDBStorageAdapter,
3490
+ MOCK_AUTH_PROVIDER,
3491
+ MOCK_AUTH_VERIFIER,
3492
+ MeshEchoReplicator,
3493
+ MetadataStore,
3494
+ Pipeline,
3495
+ QueryServiceImpl,
3496
+ QueryState,
3497
+ Space,
3498
+ SpaceManager,
3499
+ SpaceProtocol,
3500
+ SpaceProtocolSession,
3501
+ TimeframeClock,
3502
+ codec,
3503
+ convertLegacyReferences,
3504
+ convertLegacySpaceRootDoc,
3505
+ createIdFromSpaceKey,
3506
+ createMappedFeedWriter,
2146
3507
  deriveCollectionIdFromSpaceId,
3508
+ diffCollectionState,
3509
+ encodingOptions,
3510
+ findInlineObjectOfType,
2147
3511
  getSpaceIdFromCollectionId,
2148
- MeshEchoReplicator,
2149
- EchoDataMonitor,
2150
- DataServiceImpl
3512
+ getSpaceKeyFromDoc,
3513
+ hasInvitationExpired,
3514
+ mapFeedIndexesToTimeframe,
3515
+ mapTimeframeToFeedIndexes,
3516
+ startAfter,
3517
+ valueEncoding
2151
3518
  };
2152
- //# sourceMappingURL=chunk-MPWFDDQK.mjs.map
3519
+ //# sourceMappingURL=index.mjs.map