@dxos/echo-pipeline 0.5.9-main.c34beda → 0.5.9-main.c837b46

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.
@@ -28,11 +28,10 @@ import {
28
28
  } from "./chunk-HS77A4I4.mjs";
29
29
 
30
30
  // packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts
31
- import { Event } from "@dxos/async";
32
- import { next as automerge, getBackend, getHeads } from "@dxos/automerge/automerge";
31
+ import { Event, asyncTimeout } from "@dxos/async";
32
+ import { next as automerge, getBackend, getHeads, isAutomerge, save } from "@dxos/automerge/automerge";
33
33
  import { Repo } from "@dxos/automerge/automerge-repo";
34
- import { Context } from "@dxos/context";
35
- import { invariant as invariant3 } from "@dxos/invariant";
34
+ import { Context, cancelWithContext } from "@dxos/context";
36
35
  import { PublicKey } from "@dxos/keys";
37
36
  import { objectPointerCodec } from "@dxos/protocols";
38
37
  import { trace } from "@dxos/tracing";
@@ -320,10 +319,7 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
320
319
  _emitPeerCandidate(connection) {
321
320
  this.emit("peer-candidate", {
322
321
  peerId: connection.peerId,
323
- peerMetadata: {
324
- // TODO(dmaretskyi): Refactor this.
325
- dxos_peerSource: "EchoNetworkAdapter"
326
- }
322
+ peerMetadata: createEchoPeerMetadata()
327
323
  });
328
324
  }
329
325
  };
@@ -339,6 +335,11 @@ _ts_decorate([
339
335
  _ts_decorate([
340
336
  synchronized
341
337
  ], EchoNetworkAdapter.prototype, "removeReplicator", null);
338
+ var createEchoPeerMetadata = () => ({
339
+ // TODO(dmaretskyi): Refactor this.
340
+ dxos_peerSource: "EchoNetworkAdapter"
341
+ });
342
+ var isEchoPeerMetadata = (metadata) => metadata?.dxos_peerSource === "EchoNetworkAdapter";
342
343
 
343
344
  // packages/core/echo/echo-pipeline/src/automerge/leveldb-storage-adapter.ts
344
345
  import { LifecycleState as LifecycleState2, Resource } from "@dxos/context";
@@ -590,7 +591,7 @@ var AutomergeHost = class {
590
591
  constructor({ db, indexMetadataStore }) {
591
592
  this._ctx = new Context(void 0, {
592
593
  F: __dxlog_file3,
593
- L: 49
594
+ L: 71
594
595
  });
595
596
  this._echoNetworkAdapter = new EchoNetworkAdapter({
596
597
  getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this)
@@ -630,6 +631,9 @@ var AutomergeHost = class {
630
631
  await this._echoNetworkAdapter.close();
631
632
  await this._ctx.dispose();
632
633
  }
634
+ /**
635
+ * @deprecated To be abstracted away.
636
+ */
633
637
  get repo() {
634
638
  return this._repo;
635
639
  }
@@ -639,6 +643,39 @@ var AutomergeHost = class {
639
643
  async removeReplicator(replicator) {
640
644
  await this._echoNetworkAdapter.removeReplicator(replicator);
641
645
  }
646
+ /**
647
+ * Loads the document handle from the repo and waits for it to be ready.
648
+ */
649
+ async loadDoc(ctx, documentId, opts) {
650
+ let handle;
651
+ if (typeof documentId === "string") {
652
+ handle = this._repo.handles[documentId];
653
+ }
654
+ if (!handle) {
655
+ handle = this._repo.find(documentId);
656
+ }
657
+ if (!handle.isReady()) {
658
+ if (!opts?.timeout) {
659
+ await cancelWithContext(ctx, handle.whenReady());
660
+ } else {
661
+ await cancelWithContext(ctx, asyncTimeout(handle.whenReady(), opts.timeout));
662
+ }
663
+ }
664
+ return handle;
665
+ }
666
+ /**
667
+ * Create new persisted document.
668
+ */
669
+ createDoc(initialValue, opts) {
670
+ if (opts?.preserveHistory) {
671
+ if (!isAutomerge(initialValue)) {
672
+ throw new TypeError("Initial value must be an Automerge document");
673
+ }
674
+ return this._repo.import(save(initialValue));
675
+ } else {
676
+ return this._repo.create(initialValue);
677
+ }
678
+ }
642
679
  // TODO(dmaretskyi): Share based on HALO permissions and space affinity.
643
680
  // Hosts, running in the worker, don't share documents unless requested by other peers.
644
681
  // NOTE: If both peers return sharePolicy=false the replication will not happen
@@ -651,7 +688,7 @@ var AutomergeHost = class {
651
688
  return false;
652
689
  }
653
690
  const peerMetadata = this.repo.peerMetadataByPeerId[peerId];
654
- if (peerMetadata?.dxos_peerSource === "EchoNetworkAdapter") {
691
+ if (isEchoPeerMetadata(peerMetadata)) {
655
692
  return this._echoNetworkAdapter.shouldAdvertize(peerId, {
656
693
  documentId
657
694
  });
@@ -723,31 +760,36 @@ var AutomergeHost = class {
723
760
  }
724
761
  return PublicKey.from(spaceKeyHex);
725
762
  }
726
- //
727
- // Methods for client-services.
728
- //
763
+ /**
764
+ * Flush documents to disk.
765
+ */
729
766
  async flush({ states }) {
730
- await Promise.all(states?.map(async ({ heads, documentId }) => {
731
- invariant3(heads, "heads are required for flush", {
732
- F: __dxlog_file3,
733
- L: 223,
734
- S: this,
735
- A: [
736
- "heads",
737
- "'heads are required for flush'"
738
- ]
739
- });
740
- const handle = this.repo.handles[documentId] ?? this._repo.find(documentId);
741
- await waitForHeads(handle, heads);
742
- }) ?? []);
767
+ if (states) {
768
+ await Promise.all(states.map(async ({ heads, documentId }) => {
769
+ if (!heads) {
770
+ return;
771
+ }
772
+ const handle = this.repo.handles[documentId] ?? this._repo.find(documentId);
773
+ await waitForHeads(handle, heads);
774
+ }) ?? []);
775
+ }
743
776
  await this._repo.flush(states?.map(({ documentId }) => documentId));
744
777
  }
778
+ /**
779
+ * Host <-> Client sync.
780
+ */
745
781
  syncRepo(request) {
746
782
  return this._clientNetwork.syncRepo(request);
747
783
  }
784
+ /**
785
+ * Host <-> Client sync.
786
+ */
748
787
  sendSyncMessage(request) {
749
788
  return this._clientNetwork.sendSyncMessage(request);
750
789
  }
790
+ /**
791
+ * Host <-> Client sync.
792
+ */
751
793
  async getHostInfo() {
752
794
  return this._clientNetwork.getHostInfo();
753
795
  }
@@ -801,10 +843,11 @@ var changeIsPresentInDoc = (doc, changeHash) => {
801
843
 
802
844
  // packages/core/echo/echo-pipeline/src/automerge/automerge-doc-loader.ts
803
845
  import { Event as Event2 } from "@dxos/async";
804
- import { cancelWithContext } from "@dxos/context";
846
+ import { interpretAsDocumentId } from "@dxos/automerge/automerge-repo";
847
+ import { cancelWithContext as cancelWithContext2 } from "@dxos/context";
805
848
  import { warnAfterTimeout } from "@dxos/debug";
806
849
  import { SpaceDocVersion } from "@dxos/echo-protocol";
807
- import { invariant as invariant4 } from "@dxos/invariant";
850
+ import { invariant as invariant3 } from "@dxos/invariant";
808
851
  import { log as log2 } from "@dxos/log";
809
852
  import { trace as trace2 } from "@dxos/tracing";
810
853
  function _ts_decorate3(decorators, target, key, desc) {
@@ -839,32 +882,32 @@ var AutomergeDocumentLoaderImpl = class {
839
882
  return;
840
883
  }
841
884
  if (!spaceState.rootUrl) {
842
- log2.error("Database opened with no rootUrl", {
843
- spaceId: this._spaceId
844
- }, {
845
- F: __dxlog_file4,
846
- L: 72,
847
- S: this,
848
- C: (f, a) => f(...a)
849
- });
850
- this._createContextBoundSpaceRootDocument(ctx);
851
- } else {
852
- const existingDocHandle = await this._initDocHandle(ctx, spaceState.rootUrl);
853
- const doc = existingDocHandle.docSync();
854
- invariant4(doc, void 0, {
855
- F: __dxlog_file4,
856
- L: 77,
857
- S: this,
858
- A: [
859
- "doc",
860
- ""
861
- ]
862
- });
863
- if (doc.access == null) {
864
- this._initDocAccess(existingDocHandle);
865
- }
866
- this._spaceRootDocHandle = existingDocHandle;
885
+ throw new Error("Database opened with no rootUrl");
867
886
  }
887
+ const existingDocHandle = await this._initDocHandle(ctx, spaceState.rootUrl);
888
+ const doc = existingDocHandle.docSync();
889
+ invariant3(doc, void 0, {
890
+ F: __dxlog_file4,
891
+ L: 84,
892
+ S: this,
893
+ A: [
894
+ "doc",
895
+ ""
896
+ ]
897
+ });
898
+ invariant3(doc.version === SpaceDocVersion.CURRENT, void 0, {
899
+ F: __dxlog_file4,
900
+ L: 85,
901
+ S: this,
902
+ A: [
903
+ "doc.version === SpaceDocVersion.CURRENT",
904
+ ""
905
+ ]
906
+ });
907
+ if (doc.access == null) {
908
+ this._initDocAccess(existingDocHandle);
909
+ }
910
+ this._spaceRootDocHandle = existingDocHandle;
868
911
  }
869
912
  loadObjectDocument(objectIdOrMany) {
870
913
  const objectIds = Array.isArray(objectIdOrMany) ? objectIdOrMany : [
@@ -873,9 +916,9 @@ var AutomergeDocumentLoaderImpl = class {
873
916
  let hasUrlsToLoad = false;
874
917
  const urlsToLoad = {};
875
918
  for (const objectId of objectIds) {
876
- invariant4(this._spaceRootDocHandle, void 0, {
919
+ invariant3(this._spaceRootDocHandle, void 0, {
877
920
  F: __dxlog_file4,
878
- L: 90,
921
+ L: 97,
879
922
  S: this,
880
923
  A: [
881
924
  "this._spaceRootDocHandle",
@@ -886,9 +929,9 @@ var AutomergeDocumentLoaderImpl = class {
886
929
  continue;
887
930
  }
888
931
  const spaceRootDoc = this._spaceRootDocHandle.docSync();
889
- invariant4(spaceRootDoc, void 0, {
932
+ invariant3(spaceRootDoc, void 0, {
890
933
  F: __dxlog_file4,
891
- L: 95,
934
+ L: 102,
892
935
  S: this,
893
936
  A: [
894
937
  "spaceRootDoc",
@@ -902,7 +945,7 @@ var AutomergeDocumentLoaderImpl = class {
902
945
  objectId
903
946
  }, {
904
947
  F: __dxlog_file4,
905
- L: 99,
948
+ L: 106,
906
949
  S: this,
907
950
  C: (f, a) => f(...a)
908
951
  });
@@ -915,6 +958,32 @@ var AutomergeDocumentLoaderImpl = class {
915
958
  this._loadLinkedObjects(urlsToLoad);
916
959
  }
917
960
  }
961
+ getObjectDocumentId(objectId) {
962
+ invariant3(this._spaceRootDocHandle, void 0, {
963
+ F: __dxlog_file4,
964
+ L: 118,
965
+ S: this,
966
+ A: [
967
+ "this._spaceRootDocHandle",
968
+ ""
969
+ ]
970
+ });
971
+ const spaceRootDoc = this._spaceRootDocHandle.docSync();
972
+ invariant3(spaceRootDoc, void 0, {
973
+ F: __dxlog_file4,
974
+ L: 120,
975
+ S: this,
976
+ A: [
977
+ "spaceRootDoc",
978
+ ""
979
+ ]
980
+ });
981
+ if (spaceRootDoc.objects?.[objectId]) {
982
+ return this._spaceRootDocHandle.documentId;
983
+ }
984
+ const documentUrl = (spaceRootDoc.links ?? {})[objectId];
985
+ return documentUrl && interpretAsDocumentId(documentUrl);
986
+ }
918
987
  onObjectLinksUpdated(links) {
919
988
  if (!links) {
920
989
  return;
@@ -924,9 +993,9 @@ var AutomergeDocumentLoaderImpl = class {
924
993
  linksAwaitingLoad.forEach(([objectId]) => this._objectsPendingDocumentLoad.delete(objectId));
925
994
  }
926
995
  getSpaceRootDocHandle() {
927
- invariant4(this._spaceRootDocHandle, void 0, {
996
+ invariant3(this._spaceRootDocHandle, void 0, {
928
997
  F: __dxlog_file4,
929
- L: 122,
998
+ L: 140,
930
999
  S: this,
931
1000
  A: [
932
1001
  "this._spaceRootDocHandle",
@@ -936,9 +1005,9 @@ var AutomergeDocumentLoaderImpl = class {
936
1005
  return this._spaceRootDocHandle;
937
1006
  }
938
1007
  createDocumentForObject(objectId) {
939
- invariant4(this._spaceRootDocHandle, void 0, {
1008
+ invariant3(this._spaceRootDocHandle, void 0, {
940
1009
  F: __dxlog_file4,
941
- L: 127,
1010
+ L: 145,
942
1011
  S: this,
943
1012
  A: [
944
1013
  "this._spaceRootDocHandle",
@@ -983,7 +1052,7 @@ var AutomergeDocumentLoaderImpl = class {
983
1052
  actualDocumentUrl: objectDocumentHandle.url
984
1053
  }, {
985
1054
  F: __dxlog_file4,
986
- L: 159,
1055
+ L: 177,
987
1056
  S: this,
988
1057
  C: (f, a) => f(...a)
989
1058
  });
@@ -992,7 +1061,7 @@ var AutomergeDocumentLoaderImpl = class {
992
1061
  if (objectDocumentHandle?.url === automergeUrl) {
993
1062
  log2.warn("object document was already loaded", logMeta, {
994
1063
  F: __dxlog_file4,
995
- L: 166,
1064
+ L: 184,
996
1065
  S: this,
997
1066
  C: (f, a) => f(...a)
998
1067
  });
@@ -1001,7 +1070,7 @@ var AutomergeDocumentLoaderImpl = class {
1001
1070
  const handle = this._repo.find(automergeUrl);
1002
1071
  log2.debug("document loading triggered", logMeta, {
1003
1072
  F: __dxlog_file4,
1004
- L: 170,
1073
+ L: 188,
1005
1074
  S: this,
1006
1075
  C: (f, a) => f(...a)
1007
1076
  });
@@ -1014,7 +1083,7 @@ var AutomergeDocumentLoaderImpl = class {
1014
1083
  while (true) {
1015
1084
  try {
1016
1085
  await warnAfterTimeout(5e3, "Automerge root doc load timeout (CoreDatabase)", async () => {
1017
- await cancelWithContext(ctx, docHandle.whenReady());
1086
+ await cancelWithContext2(ctx, docHandle.whenReady());
1018
1087
  });
1019
1088
  break;
1020
1089
  } catch (err) {
@@ -1024,7 +1093,7 @@ var AutomergeDocumentLoaderImpl = class {
1024
1093
  state: docHandle.state
1025
1094
  }, {
1026
1095
  F: __dxlog_file4,
1027
- L: 186,
1096
+ L: 204,
1028
1097
  S: this,
1029
1098
  C: (f, a) => f(...a)
1030
1099
  });
@@ -1038,14 +1107,6 @@ var AutomergeDocumentLoaderImpl = class {
1038
1107
  }
1039
1108
  return docHandle;
1040
1109
  }
1041
- _createContextBoundSpaceRootDocument(ctx) {
1042
- const docHandle = this._repo.create();
1043
- this._spaceRootDocHandle = docHandle;
1044
- ctx.onDispose(() => {
1045
- docHandle.delete();
1046
- this._spaceRootDocHandle = null;
1047
- });
1048
- }
1049
1110
  _initDocAccess(handle) {
1050
1111
  handle.change((newDoc) => {
1051
1112
  newDoc.access ??= {
@@ -1066,7 +1127,7 @@ var AutomergeDocumentLoaderImpl = class {
1066
1127
  if (this.onObjectDocumentLoaded.listenerCount() === 0) {
1067
1128
  log2.info("document loaded after all listeners were removed", logMeta, {
1068
1129
  F: __dxlog_file4,
1069
- L: 222,
1130
+ L: 231,
1070
1131
  S: this,
1071
1132
  C: (f, a) => f(...a)
1072
1133
  });
@@ -1076,7 +1137,7 @@ var AutomergeDocumentLoaderImpl = class {
1076
1137
  if (objectDocHandle?.url !== handle.url) {
1077
1138
  log2.warn("object was rebound while a document was loading, discarding handle", logMeta, {
1078
1139
  F: __dxlog_file4,
1079
- L: 227,
1140
+ L: 236,
1080
1141
  S: this,
1081
1142
  C: (f, a) => f(...a)
1082
1143
  });
@@ -1095,7 +1156,7 @@ var AutomergeDocumentLoaderImpl = class {
1095
1156
  err
1096
1157
  }, {
1097
1158
  F: __dxlog_file4,
1098
- L: 233,
1159
+ L: 242,
1099
1160
  S: this,
1100
1161
  C: (f, a) => f(...a)
1101
1162
  });
@@ -1117,7 +1178,7 @@ AutomergeDocumentLoaderImpl = _ts_decorate3([
1117
1178
  // packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts
1118
1179
  import { cbor as cbor2 } from "@dxos/automerge/automerge-repo";
1119
1180
  import { Resource as Resource2 } from "@dxos/context";
1120
- import { invariant as invariant5 } from "@dxos/invariant";
1181
+ import { invariant as invariant4 } from "@dxos/invariant";
1121
1182
  import { PublicKey as PublicKey2 } from "@dxos/keys";
1122
1183
  import { log as log3 } from "@dxos/log";
1123
1184
  import { AutomergeReplicator } from "@dxos/teleport-extension-automerge-replicator";
@@ -1148,7 +1209,7 @@ var MeshEchoReplicator = class {
1148
1209
  this._context = null;
1149
1210
  }
1150
1211
  createExtension() {
1151
- invariant5(this._context, void 0, {
1212
+ invariant4(this._context, void 0, {
1152
1213
  F: __dxlog_file5,
1153
1214
  L: 54,
1154
1215
  S: this,
@@ -1168,7 +1229,7 @@ var MeshEchoReplicator = class {
1168
1229
  S: this,
1169
1230
  C: (f, a) => f(...a)
1170
1231
  });
1171
- invariant5(this._context, void 0, {
1232
+ invariant4(this._context, void 0, {
1172
1233
  F: __dxlog_file5,
1173
1234
  L: 60,
1174
1235
  S: this,
@@ -1181,8 +1242,8 @@ var MeshEchoReplicator = class {
1181
1242
  this._context.onConnectionAuthScopeChanged(connection);
1182
1243
  } else {
1183
1244
  this._connectionsPerPeer.set(connection.peerId, connection);
1184
- await connection.enable();
1185
1245
  this._context.onConnectionOpen(connection);
1246
+ await connection.enable();
1186
1247
  }
1187
1248
  },
1188
1249
  onRemoteDisconnected: async () => {
@@ -1209,7 +1270,7 @@ var MeshEchoReplicator = class {
1209
1270
  S: this,
1210
1271
  C: (f, a) => f(...a)
1211
1272
  });
1212
- invariant5(this._context, void 0, {
1273
+ invariant4(this._context, void 0, {
1213
1274
  F: __dxlog_file5,
1214
1275
  L: 79,
1215
1276
  S: this,
@@ -1349,7 +1410,7 @@ var MeshReplicatorConnection = class extends Resource2 {
1349
1410
  });
1350
1411
  }
1351
1412
  get peerId() {
1352
- invariant5(this._remotePeerId != null, "Remote peer has not connected yet.", {
1413
+ invariant4(this._remotePeerId != null, "Remote peer has not connected yet.", {
1353
1414
  F: __dxlog_file5,
1354
1415
  L: 215,
1355
1416
  S: this,
@@ -1368,7 +1429,7 @@ var MeshReplicatorConnection = class extends Resource2 {
1368
1429
  * Call after the remote peer has connected.
1369
1430
  */
1370
1431
  async enable() {
1371
- invariant5(this._remotePeerId != null, "Remote peer has not connected yet.", {
1432
+ invariant4(this._remotePeerId != null, "Remote peer has not connected yet.", {
1372
1433
  F: __dxlog_file5,
1373
1434
  L: 228,
1374
1435
  S: this,