@dxos/echo-pipeline 0.4.10-main.3e35a2f → 0.4.10-main.3f5e2d2

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 (58) hide show
  1. package/dist/lib/browser/{chunk-SYE4EK33.mjs → chunk-KMWJLYEQ.mjs} +52 -27
  2. package/dist/lib/browser/{chunk-SYE4EK33.mjs.map → chunk-KMWJLYEQ.mjs.map} +3 -3
  3. package/dist/lib/browser/index.mjs +192 -171
  4. package/dist/lib/browser/index.mjs.map +3 -3
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +4 -2
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/node/{chunk-WCTX6RNS.cjs → chunk-YZA42CKA.cjs} +55 -30
  9. package/dist/lib/node/chunk-YZA42CKA.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +221 -198
  11. package/dist/lib/node/index.cjs.map +3 -3
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/testing/index.cjs +14 -12
  14. package/dist/lib/node/testing/index.cjs.map +3 -3
  15. package/dist/types/src/automerge/automerge-doc-loader.d.ts.map +1 -1
  16. package/dist/types/src/automerge/automerge-host.d.ts +7 -14
  17. package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
  18. package/dist/types/src/automerge/automerge-repo.test.d.ts +2 -0
  19. package/dist/types/src/automerge/automerge-repo.test.d.ts.map +1 -0
  20. package/dist/types/src/automerge/index.d.ts +1 -0
  21. package/dist/types/src/automerge/index.d.ts.map +1 -1
  22. package/dist/types/src/automerge/leveldb-storage-adapter.d.ts +11 -8
  23. package/dist/types/src/automerge/leveldb-storage-adapter.d.ts.map +1 -1
  24. package/dist/types/src/automerge/local-host-network-adapter.d.ts +8 -1
  25. package/dist/types/src/automerge/local-host-network-adapter.d.ts.map +1 -1
  26. package/dist/types/src/automerge/migrations.d.ts +2 -2
  27. package/dist/types/src/automerge/reference.d.ts +1 -1
  28. package/dist/types/src/automerge/reference.d.ts.map +1 -1
  29. package/dist/types/src/automerge/types.d.ts +4 -3
  30. package/dist/types/src/automerge/types.d.ts.map +1 -1
  31. package/dist/types/src/space/control-pipeline.d.ts +3 -1
  32. package/dist/types/src/space/control-pipeline.d.ts.map +1 -1
  33. package/dist/types/src/space/space-manager.d.ts +3 -1
  34. package/dist/types/src/space/space-manager.d.ts.map +1 -1
  35. package/dist/types/src/space/space.d.ts +2 -1
  36. package/dist/types/src/space/space.d.ts.map +1 -1
  37. package/dist/types/src/testing/level.d.ts +2 -2
  38. package/dist/types/src/testing/level.d.ts.map +1 -1
  39. package/dist/types/src/testing/test-agent-builder.d.ts.map +1 -1
  40. package/package.json +30 -30
  41. package/src/automerge/automerge-doc-loader.ts +3 -0
  42. package/src/automerge/automerge-host.test.ts +26 -17
  43. package/src/automerge/automerge-host.ts +59 -98
  44. package/src/automerge/automerge-repo.test.ts +61 -0
  45. package/src/automerge/index.ts +1 -0
  46. package/src/automerge/level.test.ts +41 -2
  47. package/src/automerge/leveldb-storage-adapter.ts +36 -24
  48. package/src/automerge/local-host-network-adapter.ts +19 -13
  49. package/src/automerge/migrations.ts +2 -2
  50. package/src/automerge/reference.ts +1 -1
  51. package/src/automerge/storage-adapter.test.ts +4 -4
  52. package/src/automerge/types.ts +4 -3
  53. package/src/space/control-pipeline.ts +11 -1
  54. package/src/space/space-manager.ts +4 -0
  55. package/src/space/space.ts +11 -1
  56. package/src/testing/level.ts +3 -2
  57. package/src/testing/test-agent-builder.ts +1 -0
  58. package/dist/lib/node/chunk-WCTX6RNS.cjs.map +0 -7
@@ -22,44 +22,58 @@ import {
22
22
  mapTimeframeToFeedIndexes,
23
23
  startAfter,
24
24
  valueEncoding
25
- } from "./chunk-SYE4EK33.mjs";
25
+ } from "./chunk-KMWJLYEQ.mjs";
26
26
 
27
27
  // packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts
28
- import { next as automerge, getHeads } from "@dxos/automerge/automerge";
28
+ import { Event } from "@dxos/async";
29
+ import { next as automerge, getBackend } from "@dxos/automerge/automerge";
29
30
  import { Repo } from "@dxos/automerge/automerge-repo";
30
31
  import { Context } from "@dxos/context";
32
+ import { invariant as invariant3 } from "@dxos/invariant";
31
33
  import { PublicKey } from "@dxos/keys";
32
- import { log as log4 } from "@dxos/log";
33
- import { idCodec } from "@dxos/protocols";
34
+ import { log as log3 } from "@dxos/log";
34
35
  import { trace } from "@dxos/tracing";
35
36
  import { ComplexMap, ComplexSet, defaultMap, mapValues } from "@dxos/util";
36
37
 
37
38
  // packages/core/echo/echo-pipeline/src/automerge/leveldb-storage-adapter.ts
38
- var LevelDBStorageAdapter = class {
39
+ import { LifecycleState, Resource } from "@dxos/context";
40
+ var LevelDBStorageAdapter = class extends Resource {
39
41
  constructor(_params) {
42
+ super();
40
43
  this._params = _params;
41
- this._state = "opened";
42
44
  }
43
45
  async load(keyArray) {
44
- if (this._state !== "opened") {
45
- return void 0;
46
+ try {
47
+ if (this._lifecycleState !== LifecycleState.OPEN) {
48
+ return void 0;
49
+ }
50
+ return await this._params.db.get(keyArray, {
51
+ ...encodingOptions
52
+ });
53
+ } catch (err) {
54
+ if (isLevelDbNotFoundError(err)) {
55
+ return void 0;
56
+ }
57
+ throw err;
46
58
  }
47
- return this._params.db.get(keyArray, {
48
- ...encodingOptions
49
- }).catch((err) => err.code === "LEVEL_NOT_FOUND" ? void 0 : Promise.reject(err));
50
59
  }
51
60
  async save(keyArray, binary) {
52
- if (this._state !== "opened") {
61
+ if (this._lifecycleState !== LifecycleState.OPEN) {
53
62
  return void 0;
54
63
  }
55
- await this._params.callbacks?.beforeSave?.(keyArray);
56
- await this._params.db.put(keyArray, Buffer.from(binary), {
64
+ const batch = this._params.db.batch();
65
+ await this._params.callbacks?.beforeSave?.({
66
+ path: keyArray,
67
+ batch
68
+ });
69
+ batch.put(keyArray, Buffer.from(binary), {
57
70
  ...encodingOptions
58
71
  });
72
+ await batch.write();
59
73
  await this._params.callbacks?.afterSave?.(keyArray);
60
74
  }
61
75
  async remove(keyArray) {
62
- if (this._state !== "opened") {
76
+ if (this._lifecycleState !== LifecycleState.OPEN) {
63
77
  return void 0;
64
78
  }
65
79
  await this._params.db.del(keyArray, {
@@ -67,7 +81,7 @@ var LevelDBStorageAdapter = class {
67
81
  });
68
82
  }
69
83
  async loadRange(keyPrefix) {
70
- if (this._state !== "opened") {
84
+ if (this._lifecycleState !== LifecycleState.OPEN) {
71
85
  return [];
72
86
  }
73
87
  const result = [];
@@ -87,7 +101,7 @@ var LevelDBStorageAdapter = class {
87
101
  return result;
88
102
  }
89
103
  async removeRange(keyPrefix) {
90
- if (this._state !== "opened") {
104
+ if (this._lifecycleState !== LifecycleState.OPEN) {
91
105
  return void 0;
92
106
  }
93
107
  const batch = this._params.db.batch();
@@ -105,9 +119,6 @@ var LevelDBStorageAdapter = class {
105
119
  }
106
120
  await batch.write();
107
121
  }
108
- close() {
109
- this._state = "closed";
110
- }
111
122
  };
112
123
  var keyEncoder = {
113
124
  encode: (key) => Buffer.from(key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-")),
@@ -117,19 +128,20 @@ var encodingOptions = {
117
128
  keyEncoding: keyEncoder,
118
129
  valueEncoding: "buffer"
119
130
  };
131
+ var isLevelDbNotFoundError = (err) => err.code === "LEVEL_NOT_FOUND";
120
132
 
121
133
  // packages/core/echo/echo-pipeline/src/automerge/local-host-network-adapter.ts
122
134
  import { Trigger } from "@dxos/async";
123
135
  import { NetworkAdapter, cbor } from "@dxos/automerge/automerge-repo";
124
136
  import { Stream } from "@dxos/codec-protobuf";
125
137
  import { invariant } from "@dxos/invariant";
126
- import { log } from "@dxos/log";
127
138
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/local-host-network-adapter.ts";
128
139
  var LocalHostNetworkAdapter = class extends NetworkAdapter {
129
140
  constructor() {
130
141
  super(...arguments);
131
142
  this._peers = /* @__PURE__ */ new Map();
132
143
  this._connected = new Trigger();
144
+ this._isConnected = false;
133
145
  }
134
146
  /**
135
147
  * Emits `ready` event. That signals to `Repo` that it can start using the adapter.
@@ -139,15 +151,21 @@ var LocalHostNetworkAdapter = class extends NetworkAdapter {
139
151
  network: this
140
152
  });
141
153
  }
154
+ /**
155
+ * Called by `Repo` to connect to the network.
156
+ *
157
+ * @param peerId Our peer Id.
158
+ */
142
159
  connect(peerId) {
143
160
  this.peerId = peerId;
161
+ this._isConnected = true;
144
162
  this._connected.wake();
145
163
  }
146
164
  send(message) {
147
165
  const peer = this._peers.get(message.targetId);
148
166
  invariant(peer, "Peer not found.", {
149
167
  F: __dxlog_file,
150
- L: 45,
168
+ L: 51,
151
169
  S: this,
152
170
  A: [
153
171
  "peer",
@@ -162,12 +180,17 @@ var LocalHostNetworkAdapter = class extends NetworkAdapter {
162
180
  }
163
181
  disconnect() {
164
182
  }
183
+ async whenConnected() {
184
+ await this._connected.wait({
185
+ timeout: 1e4
186
+ });
187
+ }
165
188
  syncRepo({ id, syncMessage }) {
166
189
  const peerId = this._getPeerId(id);
167
190
  return new Stream(({ next, close }) => {
168
191
  invariant(!this._peers.has(peerId), "Peer already connected.", {
169
192
  F: __dxlog_file,
170
- L: 63,
193
+ L: 73,
171
194
  S: this,
172
195
  A: [
173
196
  "!this._peers.has(peerId)",
@@ -189,35 +212,47 @@ var LocalHostNetworkAdapter = class extends NetworkAdapter {
189
212
  });
190
213
  }
191
214
  });
192
- this._connected.wait({
193
- timeout: 1e3
194
- }).then(() => {
195
- this.emit("peer-candidate", {
196
- peerMetadata: {},
197
- peerId
198
- });
199
- }).catch((err) => log.catch(err, void 0, {
215
+ invariant(this._isConnected, void 0, {
200
216
  F: __dxlog_file,
201
- L: 88,
217
+ L: 90,
202
218
  S: this,
203
- C: (f, a) => f(...a)
204
- }));
219
+ A: [
220
+ "this._isConnected",
221
+ ""
222
+ ]
223
+ });
224
+ this.emit("peer-candidate", {
225
+ peerMetadata: {},
226
+ peerId
227
+ });
205
228
  });
206
229
  }
207
230
  async sendSyncMessage({ id, syncMessage }) {
208
- await this._connected.wait({
209
- timeout: 1e3
231
+ invariant(this._isConnected, void 0, {
232
+ F: __dxlog_file,
233
+ L: 99,
234
+ S: this,
235
+ A: [
236
+ "this._isConnected",
237
+ ""
238
+ ]
210
239
  });
211
240
  const message = cbor.decode(syncMessage);
212
241
  this.emit("message", message);
213
242
  }
214
243
  async getHostInfo() {
215
- await this._connected.wait({
216
- timeout: 1e3
244
+ invariant(this._isConnected, void 0, {
245
+ F: __dxlog_file,
246
+ L: 105,
247
+ S: this,
248
+ A: [
249
+ "this._isConnected",
250
+ ""
251
+ ]
217
252
  });
218
253
  invariant(this.peerId, "Peer id not set.", {
219
254
  F: __dxlog_file,
220
- L: 100,
255
+ L: 106,
221
256
  S: this,
222
257
  A: [
223
258
  "this.peerId",
@@ -237,7 +272,7 @@ var LocalHostNetworkAdapter = class extends NetworkAdapter {
237
272
  import { Trigger as Trigger2 } from "@dxos/async";
238
273
  import { NetworkAdapter as NetworkAdapter2, cbor as cbor2 } from "@dxos/automerge/automerge-repo";
239
274
  import { invariant as invariant2 } from "@dxos/invariant";
240
- import { log as log2 } from "@dxos/log";
275
+ import { log } from "@dxos/log";
241
276
  import { AutomergeReplicator } from "@dxos/teleport-extension-automerge-replicator";
242
277
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-network-adapter.ts";
243
278
  var MeshNetworkAdapter = class extends NetworkAdapter2 {
@@ -272,7 +307,7 @@ var MeshNetworkAdapter = class extends NetworkAdapter2 {
272
307
  });
273
308
  extension.sendSyncMessage({
274
309
  payload: cbor2.encode(message)
275
- }).catch((err) => log2.catch(err, void 0, {
310
+ }).catch((err) => log.catch(err, void 0, {
276
311
  F: __dxlog_file2,
277
312
  L: 39,
278
313
  S: this,
@@ -297,7 +332,7 @@ var MeshNetworkAdapter = class extends NetworkAdapter2 {
297
332
  }, {
298
333
  onStartReplication: async (info, remotePeerId) => {
299
334
  await this._connected.wait();
300
- log2("onStartReplication", {
335
+ log("onStartReplication", {
301
336
  id: info.id,
302
337
  thisPeerId: this.peerId,
303
338
  remotePeerId: remotePeerId.toHex()
@@ -310,7 +345,7 @@ var MeshNetworkAdapter = class extends NetworkAdapter2 {
310
345
  if (!this._extensions.has(info.id)) {
311
346
  peerInfo = info;
312
347
  this._extensions.set(info.id, extension);
313
- log2("peer-candidate", {
348
+ log("peer-candidate", {
314
349
  id: info.id,
315
350
  thisPeerId: this.peerId,
316
351
  remotePeerId: remotePeerId.toHex()
@@ -352,7 +387,7 @@ var MeshNetworkAdapter = class extends NetworkAdapter2 {
352
387
 
353
388
  // packages/core/echo/echo-pipeline/src/automerge/migrations.ts
354
389
  import { IndexedDBStorageAdapter } from "@dxos/automerge/automerge-repo-storage-indexeddb";
355
- import { log as log3 } from "@dxos/log";
390
+ import { log as log2 } from "@dxos/log";
356
391
  import { StorageType } from "@dxos/random-access-storage";
357
392
 
358
393
  // packages/core/echo/echo-pipeline/src/automerge/automerge-storage-adapter.ts
@@ -446,7 +481,7 @@ var levelMigration = async ({ db, directory }) => {
446
481
  return;
447
482
  }
448
483
  const batch = db.batch();
449
- log3.info("found chunks on old storage adapter", {
484
+ log2.info("found chunks on old storage adapter", {
450
485
  chunks: chunks.length
451
486
  }, {
452
487
  F: __dxlog_file3,
@@ -475,29 +510,27 @@ function _ts_decorate(decorators, target, key, desc) {
475
510
  }
476
511
  var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
477
512
  var AutomergeHost = class {
478
- constructor({ directory, db, metadata }) {
513
+ constructor({ directory, db, storageCallbacks }) {
479
514
  this._ctx = new Context();
480
515
  /**
481
516
  * spaceKey -> deviceKey[]
482
517
  */
483
518
  this._authorizedDevices = new ComplexMap(PublicKey.hash);
484
- this._updatingMetadata = /* @__PURE__ */ new Map();
485
519
  this._requestedDocs = /* @__PURE__ */ new Set();
486
520
  this._directory = directory;
487
521
  this._db = db;
488
- this._metadata = metadata;
522
+ this._storageCallbacks = storageCallbacks;
489
523
  }
490
524
  async open() {
491
525
  this._directory && await levelMigration({
492
- db: await this._db,
526
+ db: this._db,
493
527
  directory: this._directory
494
528
  });
495
529
  this._storage = new LevelDBStorageAdapter({
496
- db: await this._db,
497
- callbacks: {
498
- beforeSave: (params) => this._beforeSave(params)
499
- }
530
+ db: this._db,
531
+ callbacks: this._storageCallbacks
500
532
  });
533
+ await this._storage.open?.();
501
534
  this._peerId = `host-${PublicKey.random().toHex()}`;
502
535
  this._meshNetwork = new MeshNetworkAdapter();
503
536
  this._clientNetwork = new LocalHostNetworkAdapter();
@@ -520,13 +553,13 @@ var AutomergeHost = class {
520
553
  const doc = this._repo.handles[documentId]?.docSync();
521
554
  if (!doc) {
522
555
  const isRequested = this._requestedDocs.has(`automerge:${documentId}`);
523
- log4("doc share policy check", {
556
+ log3("doc share policy check", {
524
557
  peerId,
525
558
  documentId,
526
559
  isRequested
527
560
  }, {
528
561
  F: __dxlog_file4,
529
- L: 111,
562
+ L: 108,
530
563
  S: this,
531
564
  C: (f, a) => f(...a)
532
565
  });
@@ -535,12 +568,12 @@ var AutomergeHost = class {
535
568
  try {
536
569
  const spaceKey = getSpaceKeyFromDoc(doc);
537
570
  if (!spaceKey) {
538
- log4("space key not found for share policy check", {
571
+ log3("space key not found for share policy check", {
539
572
  peerId,
540
573
  documentId
541
574
  }, {
542
575
  F: __dxlog_file4,
543
- L: 118,
576
+ L: 115,
544
577
  S: this,
545
578
  C: (f, a) => f(...a)
546
579
  });
@@ -549,12 +582,12 @@ var AutomergeHost = class {
549
582
  const authorizedDevices = this._authorizedDevices.get(PublicKey.from(spaceKey));
550
583
  const deviceKeyHex = this.repo.peerMetadataByPeerId[peerId]?.dxos_deviceKey;
551
584
  if (!deviceKeyHex) {
552
- log4("device key not found for share policy check", {
585
+ log3("device key not found for share policy check", {
553
586
  peerId,
554
587
  documentId
555
588
  }, {
556
589
  F: __dxlog_file4,
557
- L: 127,
590
+ L: 124,
558
591
  S: this,
559
592
  C: (f, a) => f(...a)
560
593
  });
@@ -562,7 +595,7 @@ var AutomergeHost = class {
562
595
  }
563
596
  const deviceKey = PublicKey.from(deviceKeyHex);
564
597
  const isAuthorized = authorizedDevices?.has(deviceKey) ?? false;
565
- log4("share policy check", {
598
+ log3("share policy check", {
566
599
  localPeer: this._peerId,
567
600
  remotePeer: peerId,
568
601
  documentId,
@@ -571,15 +604,15 @@ var AutomergeHost = class {
571
604
  isAuthorized
572
605
  }, {
573
606
  F: __dxlog_file4,
574
- L: 133,
607
+ L: 130,
575
608
  S: this,
576
609
  C: (f, a) => f(...a)
577
610
  });
578
611
  return isAuthorized;
579
612
  } catch (err) {
580
- log4.catch(err, void 0, {
613
+ log3.catch(err, void 0, {
581
614
  F: __dxlog_file4,
582
- L: 143,
615
+ L: 140,
583
616
  S: this,
584
617
  C: (f, a) => f(...a)
585
618
  });
@@ -589,66 +622,16 @@ var AutomergeHost = class {
589
622
  });
590
623
  this._clientNetwork.ready();
591
624
  this._meshNetwork.ready();
592
- {
593
- const listener = ({ handle }) => this._onDocument(handle);
594
- this._repo.on("document", listener);
595
- this._ctx.onDispose(() => {
596
- this._repo.off("document", listener);
597
- Object.values(this._repo.handles).forEach((handle) => handle.off("change"));
598
- });
599
- }
625
+ await this._clientNetwork.whenConnected();
600
626
  }
601
627
  async close() {
602
- this._storage.close?.();
628
+ await this._storage.close?.();
603
629
  await this._clientNetwork.close();
604
630
  await this._ctx.dispose();
605
631
  }
606
632
  get repo() {
607
633
  return this._repo;
608
634
  }
609
- async _beforeSave(path) {
610
- const id = path[0];
611
- if (this._updatingMetadata.has(id)) {
612
- return this._updatingMetadata.get(id);
613
- }
614
- }
615
- _onDocument(handle) {
616
- const listener = (event) => this._onUpdate(event);
617
- handle.on("change", listener);
618
- }
619
- _onUpdate(event) {
620
- if (this._metadata == null) {
621
- return;
622
- }
623
- const objectIds = getInlineChanges(event);
624
- if (objectIds.length === 0) {
625
- return;
626
- }
627
- const heads = getHeads(event.doc);
628
- const lastAvailableHash = heads.join("");
629
- if (!lastAvailableHash) {
630
- return;
631
- }
632
- const encodedIds = objectIds.map((objectId) => idCodec.encode({
633
- documentId: event.handle.documentId,
634
- objectId
635
- }));
636
- const idToLastHash = new Map(encodedIds.map((id) => [
637
- id,
638
- lastAvailableHash
639
- ]));
640
- const markingDirtyPromise = this._metadata.markDirty(idToLastHash).then(() => {
641
- this._updatingMetadata.delete(event.handle.documentId);
642
- }).catch((err) => {
643
- this._ctx.disposed && log4.catch(err, void 0, {
644
- F: __dxlog_file4,
645
- L: 207,
646
- S: this,
647
- C: (f, a) => f(...a)
648
- });
649
- });
650
- this._updatingMetadata.set(event.handle.documentId, markingDirtyPromise);
651
- }
652
635
  _automergeDocs() {
653
636
  return mapValues(this._repo.handles, (handle) => ({
654
637
  state: handle.state,
@@ -677,9 +660,21 @@ var AutomergeHost = class {
677
660
  //
678
661
  // Methods for client-services.
679
662
  //
680
- async flush({ documentIds }) {
681
- await Promise.all(documentIds?.map((id) => this._repo.find(id).whenReady()) ?? []);
682
- await this._repo.flush(documentIds);
663
+ async flush({ states }) {
664
+ await Promise.all(states?.map(async ({ heads, documentId }) => {
665
+ invariant3(heads, "heads are required for flush", {
666
+ F: __dxlog_file4,
667
+ L: 200,
668
+ S: this,
669
+ A: [
670
+ "heads",
671
+ "'heads are required for flush'"
672
+ ]
673
+ });
674
+ const handle = this.repo.handles[documentId] ?? this._repo.find(documentId);
675
+ await waitForHeads(handle, heads);
676
+ }) ?? []);
677
+ await this._repo.flush(states?.map(({ documentId }) => documentId));
683
678
  }
684
679
  syncRepo(request) {
685
680
  return this._clientNetwork.syncRepo(request);
@@ -697,12 +692,12 @@ var AutomergeHost = class {
697
692
  return this._meshNetwork.createExtension();
698
693
  }
699
694
  authorizeDevice(spaceKey, deviceKey) {
700
- log4("authorizeDevice", {
695
+ log3("authorizeDevice", {
701
696
  spaceKey,
702
697
  deviceKey
703
698
  }, {
704
699
  F: __dxlog_file4,
705
- L: 274,
700
+ L: 230,
706
701
  S: this,
707
702
  C: (f, a) => f(...a)
708
703
  });
@@ -722,27 +717,14 @@ _ts_decorate([
722
717
  depth: null
723
718
  })
724
719
  ], AutomergeHost.prototype, "_automergePeers", null);
720
+ _ts_decorate([
721
+ trace.span({
722
+ showInBrowserTimeline: true
723
+ })
724
+ ], AutomergeHost.prototype, "flush", null);
725
725
  AutomergeHost = _ts_decorate([
726
726
  trace.resource()
727
727
  ], AutomergeHost);
728
- var getInlineChanges = (event) => {
729
- const inlineChangedObjectIds = /* @__PURE__ */ new Set();
730
- for (const { path } of event.patches) {
731
- if (path.length < 2) {
732
- continue;
733
- }
734
- switch (path[0]) {
735
- case "objects":
736
- if (path.length >= 2) {
737
- inlineChangedObjectIds.add(path[1]);
738
- }
739
- break;
740
- }
741
- }
742
- return [
743
- ...inlineChangedObjectIds
744
- ];
745
- };
746
728
  var getSpaceKeyFromDoc = (doc) => {
747
729
  const rawSpaceKey = doc.access?.spaceKey ?? doc.experimental_spaceKey;
748
730
  if (rawSpaceKey == null) {
@@ -750,13 +732,42 @@ var getSpaceKeyFromDoc = (doc) => {
750
732
  }
751
733
  return String(rawSpaceKey);
752
734
  };
735
+ var waitForHeads = async (handle, heads) => {
736
+ await handle.whenReady();
737
+ const unavailableHeads = new Set(heads);
738
+ await Event.wrap(handle, "change").waitForCondition(() => {
739
+ for (const changeHash of unavailableHeads.values()) {
740
+ if (changeIsPresentInDoc(handle.docSync(), changeHash)) {
741
+ unavailableHeads.delete(changeHash);
742
+ }
743
+ }
744
+ if (unavailableHeads.size === 0) {
745
+ return true;
746
+ }
747
+ return false;
748
+ });
749
+ };
750
+ var changeIsPresentInDoc = (doc, changeHash) => {
751
+ return !!getBackend(doc).getChangeByHash(changeHash);
752
+ };
753
753
 
754
754
  // packages/core/echo/echo-pipeline/src/automerge/automerge-doc-loader.ts
755
- import { Event } from "@dxos/async";
755
+ import { Event as Event2 } from "@dxos/async";
756
756
  import { cancelWithContext } from "@dxos/context";
757
757
  import { warnAfterTimeout } from "@dxos/debug";
758
- import { invariant as invariant3 } from "@dxos/invariant";
759
- import { log as log5 } from "@dxos/log";
758
+ import { invariant as invariant4 } from "@dxos/invariant";
759
+ import { log as log4 } from "@dxos/log";
760
+ import { trace as trace2 } from "@dxos/tracing";
761
+ function _ts_decorate2(decorators, target, key, desc) {
762
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
763
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
764
+ r = Reflect.decorate(decorators, target, key, desc);
765
+ else
766
+ for (var i = decorators.length - 1; i >= 0; i--)
767
+ if (d = decorators[i])
768
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
769
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
770
+ }
760
771
  var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-doc-loader.ts";
761
772
  var AutomergeDocumentLoaderImpl = class {
762
773
  constructor(_spaceKey, _repo) {
@@ -765,7 +776,7 @@ var AutomergeDocumentLoaderImpl = class {
765
776
  this._spaceRootDocHandle = null;
766
777
  this._objectDocumentHandles = /* @__PURE__ */ new Map();
767
778
  this._objectsPendingDocumentLoad = /* @__PURE__ */ new Set();
768
- this.onObjectDocumentLoaded = new Event();
779
+ this.onObjectDocumentLoaded = new Event2();
769
780
  }
770
781
  getAllHandles() {
771
782
  return [
@@ -777,11 +788,11 @@ var AutomergeDocumentLoaderImpl = class {
777
788
  return;
778
789
  }
779
790
  if (!spaceState.rootUrl) {
780
- log5.error("Database opened with no rootUrl", {
791
+ log4.error("Database opened with no rootUrl", {
781
792
  spaceKey: this._spaceKey
782
793
  }, {
783
794
  F: __dxlog_file5,
784
- L: 66,
795
+ L: 69,
785
796
  S: this,
786
797
  C: (f, a) => f(...a)
787
798
  });
@@ -789,9 +800,9 @@ var AutomergeDocumentLoaderImpl = class {
789
800
  } else {
790
801
  const existingDocHandle = await this._initDocHandle(ctx, spaceState.rootUrl);
791
802
  const doc = existingDocHandle.docSync();
792
- invariant3(doc, void 0, {
803
+ invariant4(doc, void 0, {
793
804
  F: __dxlog_file5,
794
- L: 71,
805
+ L: 74,
795
806
  S: this,
796
807
  A: [
797
808
  "doc",
@@ -805,9 +816,9 @@ var AutomergeDocumentLoaderImpl = class {
805
816
  }
806
817
  }
807
818
  loadObjectDocument(objectId) {
808
- invariant3(this._spaceRootDocHandle, void 0, {
819
+ invariant4(this._spaceRootDocHandle, void 0, {
809
820
  F: __dxlog_file5,
810
- L: 80,
821
+ L: 83,
811
822
  S: this,
812
823
  A: [
813
824
  "this._spaceRootDocHandle",
@@ -818,9 +829,9 @@ var AutomergeDocumentLoaderImpl = class {
818
829
  return;
819
830
  }
820
831
  const spaceRootDoc = this._spaceRootDocHandle.docSync();
821
- invariant3(spaceRootDoc, void 0, {
832
+ invariant4(spaceRootDoc, void 0, {
822
833
  F: __dxlog_file5,
823
- L: 85,
834
+ L: 88,
824
835
  S: this,
825
836
  A: [
826
837
  "spaceRootDoc",
@@ -830,11 +841,11 @@ var AutomergeDocumentLoaderImpl = class {
830
841
  const documentUrl = (spaceRootDoc.links ?? {})[objectId];
831
842
  if (documentUrl == null) {
832
843
  this._objectsPendingDocumentLoad.add(objectId);
833
- log5.info("loading delayed until object links are initialized", {
844
+ log4.info("loading delayed until object links are initialized", {
834
845
  objectId
835
846
  }, {
836
847
  F: __dxlog_file5,
837
- L: 89,
848
+ L: 92,
838
849
  S: this,
839
850
  C: (f, a) => f(...a)
840
851
  });
@@ -853,9 +864,9 @@ var AutomergeDocumentLoaderImpl = class {
853
864
  linksAwaitingLoad.forEach(([objectId]) => this._objectsPendingDocumentLoad.delete(objectId));
854
865
  }
855
866
  getSpaceRootDocHandle() {
856
- invariant3(this._spaceRootDocHandle, void 0, {
867
+ invariant4(this._spaceRootDocHandle, void 0, {
857
868
  F: __dxlog_file5,
858
- L: 107,
869
+ L: 110,
859
870
  S: this,
860
871
  A: [
861
872
  "this._spaceRootDocHandle",
@@ -865,9 +876,9 @@ var AutomergeDocumentLoaderImpl = class {
865
876
  return this._spaceRootDocHandle;
866
877
  }
867
878
  createDocumentForObject(objectId) {
868
- invariant3(this._spaceRootDocHandle, void 0, {
879
+ invariant4(this._spaceRootDocHandle, void 0, {
869
880
  F: __dxlog_file5,
870
- L: 112,
881
+ L: 115,
871
882
  S: this,
872
883
  A: [
873
884
  "this._spaceRootDocHandle",
@@ -905,30 +916,30 @@ var AutomergeDocumentLoaderImpl = class {
905
916
  };
906
917
  const objectDocumentHandle = this._objectDocumentHandles.get(objectId);
907
918
  if (objectDocumentHandle != null && objectDocumentHandle.url !== automergeUrl) {
908
- log5.warn("object already inlined in a different document, ignoring the link", {
919
+ log4.warn("object already inlined in a different document, ignoring the link", {
909
920
  ...logMeta,
910
921
  actualDocumentUrl: objectDocumentHandle.url
911
922
  }, {
912
923
  F: __dxlog_file5,
913
- L: 142,
924
+ L: 145,
914
925
  S: this,
915
926
  C: (f, a) => f(...a)
916
927
  });
917
928
  continue;
918
929
  }
919
930
  if (objectDocumentHandle?.url === automergeUrl) {
920
- log5.warn("object document was already loaded", logMeta, {
931
+ log4.warn("object document was already loaded", logMeta, {
921
932
  F: __dxlog_file5,
922
- L: 149,
933
+ L: 152,
923
934
  S: this,
924
935
  C: (f, a) => f(...a)
925
936
  });
926
937
  continue;
927
938
  }
928
939
  const handle = this._repo.find(automergeUrl);
929
- log5.debug("document loading triggered", logMeta, {
940
+ log4.debug("document loading triggered", logMeta, {
930
941
  F: __dxlog_file5,
931
- L: 153,
942
+ L: 156,
932
943
  S: this,
933
944
  C: (f, a) => f(...a)
934
945
  });
@@ -946,12 +957,12 @@ var AutomergeDocumentLoaderImpl = class {
946
957
  break;
947
958
  } catch (err) {
948
959
  if (`${err}`.includes("Timeout")) {
949
- log5.info("wraparound", {
960
+ log4.info("wraparound", {
950
961
  id: docHandle.documentId,
951
962
  state: docHandle.state
952
963
  }, {
953
964
  F: __dxlog_file5,
954
- L: 169,
965
+ L: 172,
955
966
  S: this,
956
967
  C: (f, a) => f(...a)
957
968
  });
@@ -991,9 +1002,9 @@ var AutomergeDocumentLoaderImpl = class {
991
1002
  docUrl: handle.url
992
1003
  };
993
1004
  if (this.onObjectDocumentLoaded.listenerCount() === 0) {
994
- log5.info("document loaded after all listeners were removed", logMeta, {
1005
+ log4.info("document loaded after all listeners were removed", logMeta, {
995
1006
  F: __dxlog_file5,
996
- L: 205,
1007
+ L: 208,
997
1008
  S: this,
998
1009
  C: (f, a) => f(...a)
999
1010
  });
@@ -1001,9 +1012,9 @@ var AutomergeDocumentLoaderImpl = class {
1001
1012
  }
1002
1013
  const objectDocHandle = this._objectDocumentHandles.get(objectId);
1003
1014
  if (objectDocHandle?.url !== handle.url) {
1004
- log5.warn("object was rebound while a document was loading, discarding handle", logMeta, {
1015
+ log4.warn("object was rebound while a document was loading, discarding handle", logMeta, {
1005
1016
  F: __dxlog_file5,
1006
- L: 210,
1017
+ L: 213,
1007
1018
  S: this,
1008
1019
  C: (f, a) => f(...a)
1009
1020
  });
@@ -1015,14 +1026,14 @@ var AutomergeDocumentLoaderImpl = class {
1015
1026
  });
1016
1027
  } catch (err) {
1017
1028
  const shouldRetryLoading = this.onObjectDocumentLoaded.listenerCount() > 0;
1018
- log5.warn("failed to load a document", {
1029
+ log4.warn("failed to load a document", {
1019
1030
  objectId,
1020
1031
  automergeUrl: handle.url,
1021
1032
  retryLoading: shouldRetryLoading,
1022
1033
  err
1023
1034
  }, {
1024
1035
  F: __dxlog_file5,
1025
- L: 216,
1036
+ L: 219,
1026
1037
  S: this,
1027
1038
  C: (f, a) => f(...a)
1028
1039
  });
@@ -1032,9 +1043,17 @@ var AutomergeDocumentLoaderImpl = class {
1032
1043
  }
1033
1044
  }
1034
1045
  };
1046
+ _ts_decorate2([
1047
+ trace2.span({
1048
+ showInBrowserTimeline: true
1049
+ })
1050
+ ], AutomergeDocumentLoaderImpl.prototype, "loadSpaceRootDocHandle", null);
1051
+ AutomergeDocumentLoaderImpl = _ts_decorate2([
1052
+ trace2.resource()
1053
+ ], AutomergeDocumentLoaderImpl);
1035
1054
 
1036
1055
  // packages/core/echo/echo-pipeline/src/automerge/reference.ts
1037
- import { Reference } from "@dxos/echo-db";
1056
+ import { Reference } from "@dxos/echo-schema";
1038
1057
  var REFERENCE_TYPE_TAG = "dxos.echo.model.document.Reference";
1039
1058
  var encodeReference = (reference) => ({
1040
1059
  "@type": REFERENCE_TYPE_TAG,
@@ -1052,6 +1071,7 @@ export {
1052
1071
  AutomergeHost,
1053
1072
  AutomergeStorageAdapter,
1054
1073
  DataServiceImpl,
1074
+ LevelDBStorageAdapter,
1055
1075
  LocalHostNetworkAdapter,
1056
1076
  MOCK_AUTH_PROVIDER,
1057
1077
  MOCK_AUTH_VERIFIER,
@@ -1070,6 +1090,7 @@ export {
1070
1090
  createMappedFeedWriter,
1071
1091
  decodeReference,
1072
1092
  encodeReference,
1093
+ encodingOptions,
1073
1094
  getSpaceKeyFromDoc,
1074
1095
  hasInvitationExpired,
1075
1096
  isEncodedReferenceObject,