@dxos/echo-pipeline 0.5.3-main.3456876 → 0.5.3-main.3b535c7

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.
@@ -29,12 +29,12 @@ import { Event } from "@dxos/async";
29
29
  import { next as automerge, getBackend, getHeads } from "@dxos/automerge/automerge";
30
30
  import { Repo } from "@dxos/automerge/automerge-repo";
31
31
  import { Context } from "@dxos/context";
32
- import { invariant as invariant3 } from "@dxos/invariant";
32
+ import { invariant as invariant4 } from "@dxos/invariant";
33
33
  import { PublicKey } from "@dxos/keys";
34
- import { log as log3 } from "@dxos/log";
34
+ import { log as log4 } from "@dxos/log";
35
35
  import { idCodec } from "@dxos/protocols";
36
36
  import { trace } from "@dxos/tracing";
37
- import { mapValues } from "@dxos/util";
37
+ import { ComplexMap, ComplexSet, defaultMap, mapValues } from "@dxos/util";
38
38
 
39
39
  // packages/core/echo/echo-pipeline/src/automerge/echo-network-adapter.ts
40
40
  import { Trigger, synchronized } from "@dxos/async";
@@ -54,10 +54,12 @@ function _ts_decorate(decorators, target, key, desc) {
54
54
  }
55
55
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/echo-network-adapter.ts";
56
56
  var EchoNetworkAdapter = class extends NetworkAdapter {
57
- constructor(_params) {
58
- super();
59
- this._params = _params;
57
+ constructor() {
58
+ super(...arguments);
60
59
  this._replicators = /* @__PURE__ */ new Set();
60
+ /**
61
+ * Remote peer id -> connection.
62
+ */
61
63
  this._connections = /* @__PURE__ */ new Map();
62
64
  this._lifecycleState = LifecycleState.CLOSED;
63
65
  this._connected = new Trigger();
@@ -76,7 +78,7 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
76
78
  if (connectionEntry.isOpen) {
77
79
  log.catch(err, void 0, {
78
80
  F: __dxlog_file,
79
- L: 49,
81
+ L: 40,
80
82
  S: this,
81
83
  C: (f, a) => f(...a)
82
84
  });
@@ -88,7 +90,7 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
88
90
  async open() {
89
91
  invariant(this._lifecycleState === LifecycleState.CLOSED, void 0, {
90
92
  F: __dxlog_file,
91
- L: 60,
93
+ L: 51,
92
94
  S: this,
93
95
  A: [
94
96
  "this._lifecycleState === LifecycleState.CLOSED",
@@ -96,12 +98,6 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
96
98
  ]
97
99
  });
98
100
  this._lifecycleState = LifecycleState.OPEN;
99
- log("emit ready", void 0, {
100
- F: __dxlog_file,
101
- L: 63,
102
- S: this,
103
- C: (f, a) => f(...a)
104
- });
105
101
  this.emit("ready", {
106
102
  network: this
107
103
  });
@@ -109,7 +105,7 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
109
105
  async close() {
110
106
  invariant(this._lifecycleState === LifecycleState.OPEN, void 0, {
111
107
  F: __dxlog_file,
112
- L: 71,
108
+ L: 61,
113
109
  S: this,
114
110
  A: [
115
111
  "this._lifecycleState === LifecycleState.OPEN",
@@ -128,18 +124,9 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
128
124
  });
129
125
  }
130
126
  async addReplicator(replicator) {
131
- invariant(this._lifecycleState === LifecycleState.OPEN, void 0, {
132
- F: __dxlog_file,
133
- L: 87,
134
- S: this,
135
- A: [
136
- "this._lifecycleState === LifecycleState.OPEN",
137
- ""
138
- ]
139
- });
140
127
  invariant(this.peerId, void 0, {
141
128
  F: __dxlog_file,
142
- L: 88,
129
+ L: 77,
143
130
  S: this,
144
131
  A: [
145
132
  "this.peerId",
@@ -148,43 +135,30 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
148
135
  });
149
136
  invariant(!this._replicators.has(replicator), void 0, {
150
137
  F: __dxlog_file,
151
- L: 89,
138
+ L: 78,
152
139
  S: this,
153
140
  A: [
154
141
  "!this._replicators.has(replicator)",
155
142
  ""
156
143
  ]
157
144
  });
158
- this._replicators.add(replicator);
159
145
  await replicator.connect({
160
146
  peerId: this.peerId,
161
147
  onConnectionOpen: this._onConnectionOpen.bind(this),
162
- onConnectionClosed: this._onConnectionClosed.bind(this),
163
- getContainingSpaceForDocument: this._params.getContainingSpaceForDocument
148
+ onConnectionClosed: this._onConnectionClosed.bind(this)
164
149
  });
165
150
  }
166
151
  async removeReplicator(replicator) {
167
- invariant(this._lifecycleState === LifecycleState.OPEN, void 0, {
168
- F: __dxlog_file,
169
- L: 102,
170
- S: this,
171
- A: [
172
- "this._lifecycleState === LifecycleState.OPEN",
173
- ""
174
- ]
175
- });
176
152
  invariant(this._replicators.has(replicator), void 0, {
177
153
  F: __dxlog_file,
178
- L: 103,
154
+ L: 89,
179
155
  S: this,
180
156
  A: [
181
157
  "this._replicators.has(replicator)",
182
158
  ""
183
159
  ]
184
160
  });
185
- "";
186
161
  await replicator.disconnect();
187
- this._replicators.delete(replicator);
188
162
  }
189
163
  async shouldAdvertize(peerId, params) {
190
164
  const connection = this._connections.get(peerId);
@@ -194,17 +168,9 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
194
168
  return connection.connection.shouldAdvertize(params);
195
169
  }
196
170
  _onConnectionOpen(connection) {
197
- log("Connection opened", {
198
- peerId: connection.peerId
199
- }, {
200
- F: __dxlog_file,
201
- L: 119,
202
- S: this,
203
- C: (f, a) => f(...a)
204
- });
205
171
  invariant(!this._connections.has(connection.peerId), void 0, {
206
172
  F: __dxlog_file,
207
- L: 120,
173
+ L: 103,
208
174
  S: this,
209
175
  A: [
210
176
  "!this._connections.has(connection.peerId as PeerId)",
@@ -233,21 +199,13 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
233
199
  if (connectionEntry.isOpen) {
234
200
  log.catch(err, void 0, {
235
201
  F: __dxlog_file,
236
- L: 139,
202
+ L: 122,
237
203
  S: this,
238
204
  C: (f, a) => f(...a)
239
205
  });
240
206
  }
241
207
  }
242
208
  });
243
- log("emit peer-candidate", {
244
- peerId: connection.peerId
245
- }, {
246
- F: __dxlog_file,
247
- L: 144,
248
- S: this,
249
- C: (f, a) => f(...a)
250
- });
251
209
  this.emit("peer-candidate", {
252
210
  peerId: connection.peerId,
253
211
  peerMetadata: {
@@ -257,18 +215,10 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
257
215
  });
258
216
  }
259
217
  _onConnectionClosed(connection) {
260
- log("Connection closed", {
261
- peerId: connection.peerId
262
- }, {
263
- F: __dxlog_file,
264
- L: 155,
265
- S: this,
266
- C: (f, a) => f(...a)
267
- });
268
218
  const entry = this._connections.get(connection.peerId);
269
219
  invariant(entry, void 0, {
270
220
  F: __dxlog_file,
271
- L: 157,
221
+ L: 138,
272
222
  S: this,
273
223
  A: [
274
224
  "entry",
@@ -281,13 +231,13 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
281
231
  });
282
232
  void entry.reader.cancel().catch((err) => log.catch(err, void 0, {
283
233
  F: __dxlog_file,
284
- L: 162,
234
+ L: 143,
285
235
  S: this,
286
236
  C: (f, a) => f(...a)
287
237
  }));
288
238
  void entry.writer.abort().catch((err) => log.catch(err, void 0, {
289
239
  F: __dxlog_file,
290
- L: 163,
240
+ L: 144,
291
241
  S: this,
292
242
  C: (f, a) => f(...a)
293
243
  }));
@@ -541,9 +491,126 @@ var LocalHostNetworkAdapter = class extends NetworkAdapter2 {
541
491
  }
542
492
  };
543
493
 
494
+ // packages/core/echo/echo-pipeline/src/automerge/mesh-network-adapter.ts
495
+ import { Trigger as Trigger3 } from "@dxos/async";
496
+ import { NetworkAdapter as NetworkAdapter3, cbor as cbor2 } from "@dxos/automerge/automerge-repo";
497
+ import { invariant as invariant3 } from "@dxos/invariant";
498
+ import { log as log2 } from "@dxos/log";
499
+ import { AutomergeReplicator } from "@dxos/teleport-extension-automerge-replicator";
500
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-network-adapter.ts";
501
+ var MeshNetworkAdapter = class extends NetworkAdapter3 {
502
+ constructor() {
503
+ super(...arguments);
504
+ this._extensions = /* @__PURE__ */ new Map();
505
+ this._connected = new Trigger3();
506
+ }
507
+ /**
508
+ * Emits `ready` event. That signals to `Repo` that it can start using the adapter.
509
+ */
510
+ ready() {
511
+ this.emit("ready", {
512
+ network: this
513
+ });
514
+ }
515
+ connect(peerId) {
516
+ this.peerId = peerId;
517
+ this._connected.wake();
518
+ }
519
+ send(message) {
520
+ const receiverId = message.targetId;
521
+ const extension = this._extensions.get(receiverId);
522
+ invariant3(extension, "Extension not found.", {
523
+ F: __dxlog_file3,
524
+ L: 38,
525
+ S: this,
526
+ A: [
527
+ "extension",
528
+ "'Extension not found.'"
529
+ ]
530
+ });
531
+ extension.sendSyncMessage({
532
+ payload: cbor2.encode(message)
533
+ }).catch((err) => log2.catch(err, void 0, {
534
+ F: __dxlog_file3,
535
+ L: 39,
536
+ S: this,
537
+ C: (f, a) => f(...a)
538
+ }));
539
+ }
540
+ disconnect() {
541
+ }
542
+ createExtension() {
543
+ invariant3(this.peerId, "Peer id not set.", {
544
+ F: __dxlog_file3,
545
+ L: 47,
546
+ S: this,
547
+ A: [
548
+ "this.peerId",
549
+ "'Peer id not set.'"
550
+ ]
551
+ });
552
+ let peerInfo;
553
+ const extension = new AutomergeReplicator({
554
+ peerId: this.peerId
555
+ }, {
556
+ onStartReplication: async (info, remotePeerId) => {
557
+ await this._connected.wait();
558
+ log2("onStartReplication", {
559
+ id: info.id,
560
+ thisPeerId: this.peerId,
561
+ remotePeerId: remotePeerId.toHex()
562
+ }, {
563
+ F: __dxlog_file3,
564
+ L: 70,
565
+ S: this,
566
+ C: (f, a) => f(...a)
567
+ });
568
+ if (!this._extensions.has(info.id)) {
569
+ peerInfo = info;
570
+ this._extensions.set(info.id, extension);
571
+ log2("peer-candidate", {
572
+ id: info.id,
573
+ thisPeerId: this.peerId,
574
+ remotePeerId: remotePeerId.toHex()
575
+ }, {
576
+ F: __dxlog_file3,
577
+ L: 76,
578
+ S: this,
579
+ C: (f, a) => f(...a)
580
+ });
581
+ this.emit("peer-candidate", {
582
+ // TODO(mykola): Hack, stop abusing `peerMetadata` field.
583
+ peerMetadata: {
584
+ dxos_deviceKey: remotePeerId.toHex()
585
+ },
586
+ peerId: info.id
587
+ });
588
+ }
589
+ },
590
+ onSyncMessage: async ({ payload }) => {
591
+ if (!peerInfo) {
592
+ return;
593
+ }
594
+ const message = cbor2.decode(payload);
595
+ this.emit("message", message);
596
+ },
597
+ onClose: async () => {
598
+ if (!peerInfo) {
599
+ return;
600
+ }
601
+ this.emit("peer-disconnected", {
602
+ peerId: peerInfo.id
603
+ });
604
+ this._extensions.delete(peerInfo.id);
605
+ }
606
+ });
607
+ return extension;
608
+ }
609
+ };
610
+
544
611
  // packages/core/echo/echo-pipeline/src/automerge/migrations.ts
545
612
  import { IndexedDBStorageAdapter } from "@dxos/automerge/automerge-repo-storage-indexeddb";
546
- import { log as log2 } from "@dxos/log";
613
+ import { log as log3 } from "@dxos/log";
547
614
  import { StorageType } from "@dxos/random-access-storage";
548
615
 
549
616
  // packages/core/echo/echo-pipeline/src/automerge/automerge-storage-adapter.ts
@@ -623,7 +690,7 @@ var AutomergeStorageAdapter = class {
623
690
  };
624
691
 
625
692
  // packages/core/echo/echo-pipeline/src/automerge/migrations.ts
626
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/migrations.ts";
693
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/migrations.ts";
627
694
  var levelMigration = async ({ db, directory }) => {
628
695
  const isNewLevel = !await db.iterator({
629
696
  ...encodingOptions
@@ -637,10 +704,10 @@ var levelMigration = async ({ db, directory }) => {
637
704
  return;
638
705
  }
639
706
  const batch = db.batch();
640
- log2.info("found chunks on old storage adapter", {
707
+ log3.info("found chunks on old storage adapter", {
641
708
  chunks: chunks.length
642
709
  }, {
643
- F: __dxlog_file3,
710
+ F: __dxlog_file4,
644
711
  L: 36,
645
712
  S: void 0,
646
713
  C: (f, a) => f(...a)
@@ -664,13 +731,15 @@ function _ts_decorate2(decorators, target, key, desc) {
664
731
  r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
665
732
  return c > 3 && r && Object.defineProperty(target, key, r), r;
666
733
  }
667
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
734
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
668
735
  var AutomergeHost = class {
669
736
  constructor({ directory, db, indexMetadataStore }) {
670
737
  this._ctx = new Context();
671
- this._echoNetworkAdapter = new EchoNetworkAdapter({
672
- getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this)
673
- });
738
+ this._echoNetworkAdapter = new EchoNetworkAdapter();
739
+ /**
740
+ * spaceKey -> deviceKey[]
741
+ */
742
+ this._authorizedDevices = new ComplexMap(PublicKey.hash);
674
743
  this._requestedDocs = /* @__PURE__ */ new Set();
675
744
  this._directory = directory;
676
745
  this._db = db;
@@ -690,17 +759,103 @@ var AutomergeHost = class {
690
759
  });
691
760
  await this._storage.open?.();
692
761
  this._peerId = `host-${PublicKey.random().toHex()}`;
762
+ this._meshNetwork = new MeshNetworkAdapter();
693
763
  this._clientNetwork = new LocalHostNetworkAdapter();
694
764
  this._repo = new Repo({
695
765
  peerId: this._peerId,
696
766
  network: [
697
767
  this._clientNetwork,
768
+ this._meshNetwork,
698
769
  this._echoNetworkAdapter
699
770
  ],
700
771
  storage: this._storage,
701
- sharePolicy: this._sharePolicy.bind(this)
772
+ // TODO(dmaretskyi): Share based on HALO permissions and space affinity.
773
+ // Hosts, running in the worker, don't share documents unless requested by other peers.
774
+ sharePolicy: async (peerId, documentId) => {
775
+ if (peerId.startsWith("client-")) {
776
+ return false;
777
+ }
778
+ if (!documentId) {
779
+ return false;
780
+ }
781
+ const peerMetadata = this.repo.peerMetadataByPeerId[peerId];
782
+ if (peerMetadata?.dxos_peerSource === "EchoNetworkAdapter") {
783
+ return this._echoNetworkAdapter.shouldAdvertize(peerId, {
784
+ documentId
785
+ });
786
+ }
787
+ const doc = this._repo.handles[documentId]?.docSync();
788
+ if (!doc) {
789
+ const isRequested = this._requestedDocs.has(`automerge:${documentId}`);
790
+ log4("doc share policy check", {
791
+ peerId,
792
+ documentId,
793
+ isRequested
794
+ }, {
795
+ F: __dxlog_file5,
796
+ L: 124,
797
+ S: this,
798
+ C: (f, a) => f(...a)
799
+ });
800
+ return isRequested;
801
+ }
802
+ try {
803
+ const spaceKey = getSpaceKeyFromDoc(doc);
804
+ if (!spaceKey) {
805
+ log4("space key not found for share policy check", {
806
+ peerId,
807
+ documentId
808
+ }, {
809
+ F: __dxlog_file5,
810
+ L: 131,
811
+ S: this,
812
+ C: (f, a) => f(...a)
813
+ });
814
+ return false;
815
+ }
816
+ const authorizedDevices = this._authorizedDevices.get(PublicKey.from(spaceKey));
817
+ const deviceKeyHex = peerMetadata?.dxos_deviceKey;
818
+ if (!deviceKeyHex) {
819
+ log4("device key not found for share policy check", {
820
+ peerId,
821
+ documentId
822
+ }, {
823
+ F: __dxlog_file5,
824
+ L: 140,
825
+ S: this,
826
+ C: (f, a) => f(...a)
827
+ });
828
+ return false;
829
+ }
830
+ const deviceKey = PublicKey.from(deviceKeyHex);
831
+ const isAuthorized = authorizedDevices?.has(deviceKey) ?? false;
832
+ log4("share policy check", {
833
+ localPeer: this._peerId,
834
+ remotePeer: peerId,
835
+ documentId,
836
+ deviceKey,
837
+ spaceKey,
838
+ isAuthorized
839
+ }, {
840
+ F: __dxlog_file5,
841
+ L: 146,
842
+ S: this,
843
+ C: (f, a) => f(...a)
844
+ });
845
+ return isAuthorized;
846
+ } catch (err) {
847
+ log4.catch(err, void 0, {
848
+ F: __dxlog_file5,
849
+ L: 156,
850
+ S: this,
851
+ C: (f, a) => f(...a)
852
+ });
853
+ return false;
854
+ }
855
+ }
702
856
  });
703
857
  this._clientNetwork.ready();
858
+ this._meshNetwork.ready();
704
859
  await this._echoNetworkAdapter.open();
705
860
  await this._clientNetwork.whenConnected();
706
861
  await this._echoNetworkAdapter.whenConnected();
@@ -720,40 +875,6 @@ var AutomergeHost = class {
720
875
  async removeReplicator(replicator) {
721
876
  await this._echoNetworkAdapter.removeReplicator(replicator);
722
877
  }
723
- // TODO(dmaretskyi): Share based on HALO permissions and space affinity.
724
- // Hosts, running in the worker, don't share documents unless requested by other peers.
725
- // NOTE: If both peers return sharePolicy=false the replication will not happen
726
- // https://github.com/automerge/automerge-repo/pull/292
727
- async _sharePolicy(peerId, documentId) {
728
- if (peerId.startsWith("client-")) {
729
- return false;
730
- }
731
- if (!documentId) {
732
- return false;
733
- }
734
- const doc = this._repo.handles[documentId]?.docSync();
735
- if (!doc) {
736
- const isRequested = this._requestedDocs.has(`automerge:${documentId}`);
737
- log3("doc share policy check", {
738
- peerId,
739
- documentId,
740
- isRequested
741
- }, {
742
- F: __dxlog_file4,
743
- L: 149,
744
- S: this,
745
- C: (f, a) => f(...a)
746
- });
747
- return isRequested;
748
- }
749
- const peerMetadata = this.repo.peerMetadataByPeerId[peerId];
750
- if (peerMetadata?.dxos_peerSource === "EchoNetworkAdapter") {
751
- return this._echoNetworkAdapter.shouldAdvertize(peerId, {
752
- documentId
753
- });
754
- }
755
- return false;
756
- }
757
878
  async _beforeSave({ path, batch }) {
758
879
  const handle = this._repo.handles[path[0]];
759
880
  if (!handle) {
@@ -806,25 +927,14 @@ var AutomergeHost = class {
806
927
  _automergePeers() {
807
928
  return this._repo.peers;
808
929
  }
809
- async _getContainingSpaceForDocument(documentId) {
810
- const doc = this._repo.handles[documentId]?.docSync();
811
- if (!doc) {
812
- return null;
813
- }
814
- const spaceKeyHex = getSpaceKeyFromDoc(doc);
815
- if (!spaceKeyHex) {
816
- return null;
817
- }
818
- return PublicKey.from(spaceKeyHex);
819
- }
820
930
  //
821
931
  // Methods for client-services.
822
932
  //
823
933
  async flush({ states }) {
824
934
  await Promise.all(states?.map(async ({ heads, documentId }) => {
825
- invariant3(heads, "heads are required for flush", {
826
- F: __dxlog_file4,
827
- L: 239,
935
+ invariant4(heads, "heads are required for flush", {
936
+ F: __dxlog_file5,
937
+ L: 252,
828
938
  S: this,
829
939
  A: [
830
940
  "heads",
@@ -845,6 +955,24 @@ var AutomergeHost = class {
845
955
  async getHostInfo() {
846
956
  return this._clientNetwork.getHostInfo();
847
957
  }
958
+ //
959
+ // Mesh replication.
960
+ //
961
+ createExtension() {
962
+ return this._meshNetwork.createExtension();
963
+ }
964
+ authorizeDevice(spaceKey, deviceKey) {
965
+ log4("authorizeDevice", {
966
+ spaceKey,
967
+ deviceKey
968
+ }, {
969
+ F: __dxlog_file5,
970
+ L: 282,
971
+ S: this,
972
+ C: (f, a) => f(...a)
973
+ });
974
+ defaultMap(this._authorizedDevices, spaceKey, () => new ComplexSet(PublicKey.hash)).add(deviceKey);
975
+ }
848
976
  };
849
977
  _ts_decorate2([
850
978
  trace.info()
@@ -897,8 +1025,8 @@ var changeIsPresentInDoc = (doc, changeHash) => {
897
1025
  import { Event as Event2 } from "@dxos/async";
898
1026
  import { cancelWithContext } from "@dxos/context";
899
1027
  import { warnAfterTimeout } from "@dxos/debug";
900
- import { invariant as invariant4 } from "@dxos/invariant";
901
- import { log as log4 } from "@dxos/log";
1028
+ import { invariant as invariant5 } from "@dxos/invariant";
1029
+ import { log as log5 } from "@dxos/log";
902
1030
  import { trace as trace2 } from "@dxos/tracing";
903
1031
  function _ts_decorate3(decorators, target, key, desc) {
904
1032
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -910,7 +1038,7 @@ function _ts_decorate3(decorators, target, key, desc) {
910
1038
  r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
911
1039
  return c > 3 && r && Object.defineProperty(target, key, r), r;
912
1040
  }
913
- var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-doc-loader.ts";
1041
+ var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-doc-loader.ts";
914
1042
  var AutomergeDocumentLoaderImpl = class {
915
1043
  constructor(_spaceKey, _repo) {
916
1044
  this._spaceKey = _spaceKey;
@@ -931,10 +1059,10 @@ var AutomergeDocumentLoaderImpl = class {
931
1059
  return;
932
1060
  }
933
1061
  if (!spaceState.rootUrl) {
934
- log4.error("Database opened with no rootUrl", {
1062
+ log5.error("Database opened with no rootUrl", {
935
1063
  spaceKey: this._spaceKey
936
1064
  }, {
937
- F: __dxlog_file5,
1065
+ F: __dxlog_file6,
938
1066
  L: 70,
939
1067
  S: this,
940
1068
  C: (f, a) => f(...a)
@@ -943,8 +1071,8 @@ var AutomergeDocumentLoaderImpl = class {
943
1071
  } else {
944
1072
  const existingDocHandle = await this._initDocHandle(ctx, spaceState.rootUrl);
945
1073
  const doc = existingDocHandle.docSync();
946
- invariant4(doc, void 0, {
947
- F: __dxlog_file5,
1074
+ invariant5(doc, void 0, {
1075
+ F: __dxlog_file6,
948
1076
  L: 75,
949
1077
  S: this,
950
1078
  A: [
@@ -965,8 +1093,8 @@ var AutomergeDocumentLoaderImpl = class {
965
1093
  let hasUrlsToLoad = false;
966
1094
  const urlsToLoad = {};
967
1095
  for (const objectId of objectIds) {
968
- invariant4(this._spaceRootDocHandle, void 0, {
969
- F: __dxlog_file5,
1096
+ invariant5(this._spaceRootDocHandle, void 0, {
1097
+ F: __dxlog_file6,
970
1098
  L: 88,
971
1099
  S: this,
972
1100
  A: [
@@ -978,8 +1106,8 @@ var AutomergeDocumentLoaderImpl = class {
978
1106
  continue;
979
1107
  }
980
1108
  const spaceRootDoc = this._spaceRootDocHandle.docSync();
981
- invariant4(spaceRootDoc, void 0, {
982
- F: __dxlog_file5,
1109
+ invariant5(spaceRootDoc, void 0, {
1110
+ F: __dxlog_file6,
983
1111
  L: 93,
984
1112
  S: this,
985
1113
  A: [
@@ -990,10 +1118,10 @@ var AutomergeDocumentLoaderImpl = class {
990
1118
  const documentUrl = (spaceRootDoc.links ?? {})[objectId];
991
1119
  if (documentUrl == null) {
992
1120
  this._objectsPendingDocumentLoad.add(objectId);
993
- log4.info("loading delayed until object links are initialized", {
1121
+ log5.info("loading delayed until object links are initialized", {
994
1122
  objectId
995
1123
  }, {
996
- F: __dxlog_file5,
1124
+ F: __dxlog_file6,
997
1125
  L: 97,
998
1126
  S: this,
999
1127
  C: (f, a) => f(...a)
@@ -1016,8 +1144,8 @@ var AutomergeDocumentLoaderImpl = class {
1016
1144
  linksAwaitingLoad.forEach(([objectId]) => this._objectsPendingDocumentLoad.delete(objectId));
1017
1145
  }
1018
1146
  getSpaceRootDocHandle() {
1019
- invariant4(this._spaceRootDocHandle, void 0, {
1020
- F: __dxlog_file5,
1147
+ invariant5(this._spaceRootDocHandle, void 0, {
1148
+ F: __dxlog_file6,
1021
1149
  L: 120,
1022
1150
  S: this,
1023
1151
  A: [
@@ -1028,8 +1156,8 @@ var AutomergeDocumentLoaderImpl = class {
1028
1156
  return this._spaceRootDocHandle;
1029
1157
  }
1030
1158
  createDocumentForObject(objectId) {
1031
- invariant4(this._spaceRootDocHandle, void 0, {
1032
- F: __dxlog_file5,
1159
+ invariant5(this._spaceRootDocHandle, void 0, {
1160
+ F: __dxlog_file6,
1033
1161
  L: 125,
1034
1162
  S: this,
1035
1163
  A: [
@@ -1068,11 +1196,11 @@ var AutomergeDocumentLoaderImpl = class {
1068
1196
  };
1069
1197
  const objectDocumentHandle = this._objectDocumentHandles.get(objectId);
1070
1198
  if (objectDocumentHandle != null && objectDocumentHandle.url !== automergeUrl) {
1071
- log4.warn("object already inlined in a different document, ignoring the link", {
1199
+ log5.warn("object already inlined in a different document, ignoring the link", {
1072
1200
  ...logMeta,
1073
1201
  actualDocumentUrl: objectDocumentHandle.url
1074
1202
  }, {
1075
- F: __dxlog_file5,
1203
+ F: __dxlog_file6,
1076
1204
  L: 155,
1077
1205
  S: this,
1078
1206
  C: (f, a) => f(...a)
@@ -1080,8 +1208,8 @@ var AutomergeDocumentLoaderImpl = class {
1080
1208
  continue;
1081
1209
  }
1082
1210
  if (objectDocumentHandle?.url === automergeUrl) {
1083
- log4.warn("object document was already loaded", logMeta, {
1084
- F: __dxlog_file5,
1211
+ log5.warn("object document was already loaded", logMeta, {
1212
+ F: __dxlog_file6,
1085
1213
  L: 162,
1086
1214
  S: this,
1087
1215
  C: (f, a) => f(...a)
@@ -1089,8 +1217,8 @@ var AutomergeDocumentLoaderImpl = class {
1089
1217
  continue;
1090
1218
  }
1091
1219
  const handle = this._repo.find(automergeUrl);
1092
- log4.debug("document loading triggered", logMeta, {
1093
- F: __dxlog_file5,
1220
+ log5.debug("document loading triggered", logMeta, {
1221
+ F: __dxlog_file6,
1094
1222
  L: 166,
1095
1223
  S: this,
1096
1224
  C: (f, a) => f(...a)
@@ -1109,11 +1237,11 @@ var AutomergeDocumentLoaderImpl = class {
1109
1237
  break;
1110
1238
  } catch (err) {
1111
1239
  if (`${err}`.includes("Timeout")) {
1112
- log4.info("wraparound", {
1240
+ log5.info("wraparound", {
1113
1241
  id: docHandle.documentId,
1114
1242
  state: docHandle.state
1115
1243
  }, {
1116
- F: __dxlog_file5,
1244
+ F: __dxlog_file6,
1117
1245
  L: 182,
1118
1246
  S: this,
1119
1247
  C: (f, a) => f(...a)
@@ -1154,8 +1282,8 @@ var AutomergeDocumentLoaderImpl = class {
1154
1282
  docUrl: handle.url
1155
1283
  };
1156
1284
  if (this.onObjectDocumentLoaded.listenerCount() === 0) {
1157
- log4.info("document loaded after all listeners were removed", logMeta, {
1158
- F: __dxlog_file5,
1285
+ log5.info("document loaded after all listeners were removed", logMeta, {
1286
+ F: __dxlog_file6,
1159
1287
  L: 218,
1160
1288
  S: this,
1161
1289
  C: (f, a) => f(...a)
@@ -1164,8 +1292,8 @@ var AutomergeDocumentLoaderImpl = class {
1164
1292
  }
1165
1293
  const objectDocHandle = this._objectDocumentHandles.get(objectId);
1166
1294
  if (objectDocHandle?.url !== handle.url) {
1167
- log4.warn("object was rebound while a document was loading, discarding handle", logMeta, {
1168
- F: __dxlog_file5,
1295
+ log5.warn("object was rebound while a document was loading, discarding handle", logMeta, {
1296
+ F: __dxlog_file6,
1169
1297
  L: 223,
1170
1298
  S: this,
1171
1299
  C: (f, a) => f(...a)
@@ -1178,13 +1306,13 @@ var AutomergeDocumentLoaderImpl = class {
1178
1306
  });
1179
1307
  } catch (err) {
1180
1308
  const shouldRetryLoading = this.onObjectDocumentLoaded.listenerCount() > 0;
1181
- log4.warn("failed to load a document", {
1309
+ log5.warn("failed to load a document", {
1182
1310
  objectId,
1183
1311
  automergeUrl: handle.url,
1184
1312
  retryLoading: shouldRetryLoading,
1185
1313
  err
1186
1314
  }, {
1187
- F: __dxlog_file5,
1315
+ F: __dxlog_file6,
1188
1316
  L: 229,
1189
1317
  S: this,
1190
1318
  C: (f, a) => f(...a)
@@ -1203,281 +1331,6 @@ _ts_decorate3([
1203
1331
  AutomergeDocumentLoaderImpl = _ts_decorate3([
1204
1332
  trace2.resource()
1205
1333
  ], AutomergeDocumentLoaderImpl);
1206
-
1207
- // packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts
1208
- import { cbor as cbor2 } from "@dxos/automerge/automerge-repo";
1209
- import { Resource as Resource2 } from "@dxos/context";
1210
- import { invariant as invariant5 } from "@dxos/invariant";
1211
- import { PublicKey as PublicKey2 } from "@dxos/keys";
1212
- import { log as log5 } from "@dxos/log";
1213
- import { AutomergeReplicator } from "@dxos/teleport-extension-automerge-replicator";
1214
- import { ComplexMap, ComplexSet, defaultMap } from "@dxos/util";
1215
- var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts";
1216
- var MeshEchoReplicator = class {
1217
- constructor() {
1218
- this._connections = /* @__PURE__ */ new Set();
1219
- /**
1220
- * Using automerge peerId as a key.
1221
- */
1222
- this._connectionsPerPeer = /* @__PURE__ */ new Map();
1223
- /**
1224
- * spaceKey -> deviceKey[]
1225
- */
1226
- this._authorizedDevices = new ComplexMap(PublicKey2.hash);
1227
- this._context = null;
1228
- }
1229
- async connect(context) {
1230
- this._context = context;
1231
- }
1232
- async disconnect() {
1233
- for (const connection of this._connections) {
1234
- await connection.close();
1235
- }
1236
- this._connections.clear();
1237
- this._connectionsPerPeer.clear();
1238
- this._context = null;
1239
- }
1240
- createExtension() {
1241
- invariant5(this._context, void 0, {
1242
- F: __dxlog_file6,
1243
- L: 54,
1244
- S: this,
1245
- A: [
1246
- "this._context",
1247
- ""
1248
- ]
1249
- });
1250
- const connection = new MeshReplicatorConnection({
1251
- ownPeerId: this._context.peerId,
1252
- onRemoteConnected: async () => {
1253
- log5("onRemoteConnected", {
1254
- peerId: connection.peerId
1255
- }, {
1256
- F: __dxlog_file6,
1257
- L: 59,
1258
- S: this,
1259
- C: (f, a) => f(...a)
1260
- });
1261
- invariant5(this._context, void 0, {
1262
- F: __dxlog_file6,
1263
- L: 60,
1264
- S: this,
1265
- A: [
1266
- "this._context",
1267
- ""
1268
- ]
1269
- });
1270
- if (!this._connectionsPerPeer.has(connection.peerId)) {
1271
- this._connectionsPerPeer.set(connection.peerId, connection);
1272
- await connection.enable();
1273
- this._context.onConnectionOpen(connection);
1274
- }
1275
- },
1276
- onRemoteDisconnected: async () => {
1277
- log5("onRemoteDisconnected", {
1278
- peerId: connection.peerId
1279
- }, {
1280
- F: __dxlog_file6,
1281
- L: 69,
1282
- S: this,
1283
- C: (f, a) => f(...a)
1284
- });
1285
- invariant5(this._context, void 0, {
1286
- F: __dxlog_file6,
1287
- L: 70,
1288
- S: this,
1289
- A: [
1290
- "this._context",
1291
- ""
1292
- ]
1293
- });
1294
- this._context.onConnectionClosed(connection);
1295
- await connection.disable();
1296
- this._connectionsPerPeer.delete(connection.peerId);
1297
- this._connections.delete(connection);
1298
- },
1299
- shouldAdvertize: async (params) => {
1300
- log5("shouldAdvertize", {
1301
- peerId: connection.peerId,
1302
- documentId: params.documentId
1303
- }, {
1304
- F: __dxlog_file6,
1305
- L: 77,
1306
- S: this,
1307
- C: (f, a) => f(...a)
1308
- });
1309
- invariant5(this._context, void 0, {
1310
- F: __dxlog_file6,
1311
- L: 78,
1312
- S: this,
1313
- A: [
1314
- "this._context",
1315
- ""
1316
- ]
1317
- });
1318
- try {
1319
- const spaceKey = await this._context.getContainingSpaceForDocument(params.documentId);
1320
- if (!spaceKey) {
1321
- log5("space key not found for share policy check", {
1322
- peerId: connection.peerId,
1323
- documentId: params.documentId
1324
- }, {
1325
- F: __dxlog_file6,
1326
- L: 82,
1327
- S: this,
1328
- C: (f, a) => f(...a)
1329
- });
1330
- return false;
1331
- }
1332
- const authorizedDevices = this._authorizedDevices.get(spaceKey);
1333
- if (!connection.remoteDeviceKey) {
1334
- log5("device key not found for share policy check", {
1335
- peerId: connection.peerId,
1336
- documentId: params.documentId
1337
- }, {
1338
- F: __dxlog_file6,
1339
- L: 94,
1340
- S: this,
1341
- C: (f, a) => f(...a)
1342
- });
1343
- return false;
1344
- }
1345
- const isAuthorized = authorizedDevices?.has(connection.remoteDeviceKey) ?? false;
1346
- log5("share policy check", {
1347
- localPeer: this._context.peerId,
1348
- remotePeer: connection.peerId,
1349
- documentId: params.documentId,
1350
- deviceKey: connection.remoteDeviceKey,
1351
- spaceKey,
1352
- isAuthorized
1353
- }, {
1354
- F: __dxlog_file6,
1355
- L: 103,
1356
- S: this,
1357
- C: (f, a) => f(...a)
1358
- });
1359
- return isAuthorized;
1360
- } catch (err) {
1361
- log5.catch(err, void 0, {
1362
- F: __dxlog_file6,
1363
- L: 113,
1364
- S: this,
1365
- C: (f, a) => f(...a)
1366
- });
1367
- return false;
1368
- }
1369
- }
1370
- });
1371
- this._connections.add(connection);
1372
- return connection.replicatorExtension;
1373
- }
1374
- authorizeDevice(spaceKey, deviceKey) {
1375
- log5("authorizeDevice", {
1376
- spaceKey,
1377
- deviceKey
1378
- }, {
1379
- F: __dxlog_file6,
1380
- L: 124,
1381
- S: this,
1382
- C: (f, a) => f(...a)
1383
- });
1384
- defaultMap(this._authorizedDevices, spaceKey, () => new ComplexSet(PublicKey2.hash)).add(deviceKey);
1385
- }
1386
- };
1387
- var MeshReplicatorConnection = class extends Resource2 {
1388
- constructor(_params) {
1389
- super();
1390
- this._params = _params;
1391
- this.remoteDeviceKey = null;
1392
- this._remotePeerId = null;
1393
- this._isEnabled = false;
1394
- let readableStreamController;
1395
- this.readable = new ReadableStream({
1396
- start: (controller) => {
1397
- readableStreamController = controller;
1398
- this._ctx.onDispose(() => controller.close());
1399
- }
1400
- });
1401
- this.writable = new WritableStream({
1402
- write: async (message, controller) => {
1403
- this.replicatorExtension.sendSyncMessage({
1404
- payload: cbor2.encode(message)
1405
- }).catch((err) => {
1406
- controller.error(err);
1407
- });
1408
- }
1409
- });
1410
- this.replicatorExtension = new AutomergeReplicator({
1411
- peerId: this._params.ownPeerId
1412
- }, {
1413
- onStartReplication: async (info, remotePeerId) => {
1414
- this.remoteDeviceKey = remotePeerId;
1415
- this._remotePeerId = info.id;
1416
- log5("onStartReplication", {
1417
- id: info.id,
1418
- thisPeerId: this.peerId,
1419
- remotePeerId: remotePeerId.toHex()
1420
- }, {
1421
- F: __dxlog_file6,
1422
- L: 189,
1423
- S: this,
1424
- C: (f, a) => f(...a)
1425
- });
1426
- await this._params.onRemoteConnected();
1427
- },
1428
- onSyncMessage: async ({ payload }) => {
1429
- if (!this._isEnabled) {
1430
- return;
1431
- }
1432
- const message = cbor2.decode(payload);
1433
- readableStreamController.enqueue(message);
1434
- },
1435
- onClose: async () => {
1436
- if (!this._isEnabled) {
1437
- return;
1438
- }
1439
- await this._params.onRemoteDisconnected();
1440
- }
1441
- });
1442
- }
1443
- get peerId() {
1444
- invariant5(this._remotePeerId != null, "Remote peer has not connected yet.", {
1445
- F: __dxlog_file6,
1446
- L: 212,
1447
- S: this,
1448
- A: [
1449
- "this._remotePeerId != null",
1450
- "'Remote peer has not connected yet.'"
1451
- ]
1452
- });
1453
- return this._remotePeerId;
1454
- }
1455
- async shouldAdvertize(params) {
1456
- return this._params.shouldAdvertize(params);
1457
- }
1458
- /**
1459
- * Start exchanging messages with the remote peer.
1460
- * Call after the remote peer has connected.
1461
- */
1462
- async enable() {
1463
- invariant5(this._remotePeerId != null, "Remote peer has not connected yet.", {
1464
- F: __dxlog_file6,
1465
- L: 225,
1466
- S: this,
1467
- A: [
1468
- "this._remotePeerId != null",
1469
- "'Remote peer has not connected yet.'"
1470
- ]
1471
- });
1472
- this._isEnabled = true;
1473
- }
1474
- /**
1475
- * Stop exchanging messages with the remote peer.
1476
- */
1477
- async disable() {
1478
- this._isEnabled = false;
1479
- }
1480
- };
1481
1334
  export {
1482
1335
  AuthExtension,
1483
1336
  AuthStatus,
@@ -1489,7 +1342,7 @@ export {
1489
1342
  LocalHostNetworkAdapter,
1490
1343
  MOCK_AUTH_PROVIDER,
1491
1344
  MOCK_AUTH_VERIFIER,
1492
- MeshEchoReplicator,
1345
+ MeshNetworkAdapter,
1493
1346
  MetadataStore,
1494
1347
  Pipeline,
1495
1348
  SnapshotManager,