@dxos/echo-pipeline 0.6.1-main.ff751ec → 0.6.1-next.f8e935e
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.
- package/dist/lib/browser/{chunk-O3MAK5PY.mjs → chunk-DMUP426Q.mjs} +17 -5
- package/dist/lib/browser/chunk-DMUP426Q.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +284 -184
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +1 -1
- package/dist/lib/node/{chunk-QATBVT6S.cjs → chunk-NH5WJKOW.cjs} +20 -8
- package/dist/lib/node/chunk-NH5WJKOW.cjs.map +7 -0
- package/dist/lib/node/index.cjs +327 -231
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +11 -11
- package/dist/types/src/automerge/automerge-host.d.ts +6 -2
- package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
- package/dist/types/src/automerge/echo-network-adapter.d.ts +2 -2
- package/dist/types/src/automerge/echo-network-adapter.test.d.ts +2 -0
- package/dist/types/src/automerge/echo-network-adapter.test.d.ts.map +1 -0
- package/dist/types/src/automerge/echo-replicator.d.ts +5 -6
- package/dist/types/src/automerge/echo-replicator.d.ts.map +1 -1
- package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts +35 -0
- package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts.map +1 -0
- package/dist/types/src/automerge/mesh-echo-replicator.d.ts +2 -2
- package/dist/types/src/automerge/mesh-echo-replicator.d.ts.map +1 -1
- package/dist/types/src/db-host/data-service.d.ts +11 -3
- package/dist/types/src/db-host/data-service.d.ts.map +1 -1
- package/package.json +33 -33
- package/src/automerge/automerge-host.ts +57 -11
- package/src/automerge/automerge-repo.test.ts +117 -1
- package/src/automerge/echo-network-adapter.test.ts +131 -0
- package/src/automerge/echo-network-adapter.ts +4 -4
- package/src/automerge/echo-replicator.ts +6 -9
- package/src/automerge/mesh-echo-replicator-connection.ts +130 -0
- package/src/automerge/mesh-echo-replicator.ts +15 -123
- package/src/db-host/data-service.ts +38 -5
- package/dist/lib/browser/chunk-O3MAK5PY.mjs.map +0 -7
- package/dist/lib/node/chunk-QATBVT6S.cjs.map +0 -7
|
@@ -25,20 +25,22 @@ import {
|
|
|
25
25
|
mapTimeframeToFeedIndexes,
|
|
26
26
|
startAfter,
|
|
27
27
|
valueEncoding
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-DMUP426Q.mjs";
|
|
29
29
|
|
|
30
30
|
// packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts
|
|
31
31
|
import { Event, asyncTimeout } from "@dxos/async";
|
|
32
|
-
import { next as automerge, getBackend, getHeads, isAutomerge, save } from "@dxos/automerge/automerge";
|
|
32
|
+
import { next as automerge, getBackend, getHeads, isAutomerge, save, equals as headsEquals } from "@dxos/automerge/automerge";
|
|
33
33
|
import { Repo } from "@dxos/automerge/automerge-repo";
|
|
34
|
-
import { Resource as Resource2, cancelWithContext } from "@dxos/context";
|
|
34
|
+
import { Context, Resource as Resource2, cancelWithContext } from "@dxos/context";
|
|
35
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
35
36
|
import { PublicKey } from "@dxos/keys";
|
|
37
|
+
import { log as log2 } from "@dxos/log";
|
|
36
38
|
import { objectPointerCodec } from "@dxos/protocols";
|
|
37
39
|
import { trace } from "@dxos/tracing";
|
|
38
40
|
import { mapValues } from "@dxos/util";
|
|
39
41
|
|
|
40
42
|
// packages/core/echo/echo-pipeline/src/automerge/echo-network-adapter.ts
|
|
41
|
-
import {
|
|
43
|
+
import { synchronized, Trigger } from "@dxos/async";
|
|
42
44
|
import { NetworkAdapter } from "@dxos/automerge/automerge-repo";
|
|
43
45
|
import { LifecycleState } from "@dxos/context";
|
|
44
46
|
import { invariant } from "@dxos/invariant";
|
|
@@ -175,12 +177,12 @@ var EchoNetworkAdapter = class extends NetworkAdapter {
|
|
|
175
177
|
await replicator.disconnect();
|
|
176
178
|
this._replicators.delete(replicator);
|
|
177
179
|
}
|
|
178
|
-
async
|
|
180
|
+
async shouldAdvertise(peerId, params) {
|
|
179
181
|
const connection = this._connections.get(peerId);
|
|
180
182
|
if (!connection) {
|
|
181
183
|
return false;
|
|
182
184
|
}
|
|
183
|
-
return connection.connection.
|
|
185
|
+
return connection.connection.shouldAdvertise(params);
|
|
184
186
|
}
|
|
185
187
|
_onConnectionOpen(connection) {
|
|
186
188
|
log("Connection opened", {
|
|
@@ -602,12 +604,14 @@ function _ts_decorate2(decorators, target, key, desc) {
|
|
|
602
604
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
603
605
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
604
606
|
}
|
|
607
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
|
|
605
608
|
var AutomergeHost = class extends Resource2 {
|
|
606
609
|
constructor({ db, indexMetadataStore }) {
|
|
607
610
|
super();
|
|
608
611
|
this._echoNetworkAdapter = new EchoNetworkAdapter({
|
|
609
612
|
getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this)
|
|
610
613
|
});
|
|
614
|
+
this._db = db;
|
|
611
615
|
this._storage = new LevelDBStorageAdapter({
|
|
612
616
|
db: db.sublevel("automerge"),
|
|
613
617
|
callbacks: {
|
|
@@ -652,6 +656,9 @@ var AutomergeHost = class extends Resource2 {
|
|
|
652
656
|
get repo() {
|
|
653
657
|
return this._repo;
|
|
654
658
|
}
|
|
659
|
+
get loadedDocsCount() {
|
|
660
|
+
return Object.keys(this._repo.handles).length;
|
|
661
|
+
}
|
|
655
662
|
async addReplicator(replicator) {
|
|
656
663
|
await this._echoNetworkAdapter.addReplicator(replicator);
|
|
657
664
|
}
|
|
@@ -691,6 +698,73 @@ var AutomergeHost = class extends Resource2 {
|
|
|
691
698
|
return this._repo.create(initialValue);
|
|
692
699
|
}
|
|
693
700
|
}
|
|
701
|
+
async waitUntilHeadsReplicated(heads) {
|
|
702
|
+
await Promise.all(heads.entries?.map(async ({ documentId, heads: heads2 }) => {
|
|
703
|
+
if (!heads2 || heads2.length === 0) {
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
const currentHeads = this.getHeads(documentId);
|
|
707
|
+
if (currentHeads !== null && headsEquals(currentHeads, heads2)) {
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
const handle = await this.loadDoc(Context.default(void 0, {
|
|
711
|
+
F: __dxlog_file3,
|
|
712
|
+
L: 207
|
|
713
|
+
}), documentId);
|
|
714
|
+
await waitForHeads(handle, heads2);
|
|
715
|
+
}) ?? []);
|
|
716
|
+
await this._repo.flush(heads.entries?.map((entry) => entry.documentId) ?? []);
|
|
717
|
+
}
|
|
718
|
+
async reIndexHeads(documentIds) {
|
|
719
|
+
for (const documentId of documentIds) {
|
|
720
|
+
log2.info("re-indexing heads for document", {
|
|
721
|
+
documentId
|
|
722
|
+
}, {
|
|
723
|
+
F: __dxlog_file3,
|
|
724
|
+
L: 218,
|
|
725
|
+
S: this,
|
|
726
|
+
C: (f, a) => f(...a)
|
|
727
|
+
});
|
|
728
|
+
const handle = this._repo.find(documentId);
|
|
729
|
+
await handle.whenReady([
|
|
730
|
+
"ready",
|
|
731
|
+
"requesting"
|
|
732
|
+
]);
|
|
733
|
+
if (handle.inState([
|
|
734
|
+
"requesting"
|
|
735
|
+
])) {
|
|
736
|
+
log2.warn("document is not available locally, skipping", {
|
|
737
|
+
documentId
|
|
738
|
+
}, {
|
|
739
|
+
F: __dxlog_file3,
|
|
740
|
+
L: 222,
|
|
741
|
+
S: this,
|
|
742
|
+
C: (f, a) => f(...a)
|
|
743
|
+
});
|
|
744
|
+
continue;
|
|
745
|
+
}
|
|
746
|
+
const doc = handle.docSync();
|
|
747
|
+
invariant3(doc, void 0, {
|
|
748
|
+
F: __dxlog_file3,
|
|
749
|
+
L: 227,
|
|
750
|
+
S: this,
|
|
751
|
+
A: [
|
|
752
|
+
"doc",
|
|
753
|
+
""
|
|
754
|
+
]
|
|
755
|
+
});
|
|
756
|
+
const heads = getHeads(doc);
|
|
757
|
+
const batch = this._db.batch();
|
|
758
|
+
this._headsStore.setHeads(documentId, heads, batch);
|
|
759
|
+
await batch.write();
|
|
760
|
+
}
|
|
761
|
+
log2.info("done re-indexing heads", void 0, {
|
|
762
|
+
F: __dxlog_file3,
|
|
763
|
+
L: 234,
|
|
764
|
+
S: this,
|
|
765
|
+
C: (f, a) => f(...a)
|
|
766
|
+
});
|
|
767
|
+
}
|
|
694
768
|
// TODO(dmaretskyi): Share based on HALO permissions and space affinity.
|
|
695
769
|
// Hosts, running in the worker, don't share documents unless requested by other peers.
|
|
696
770
|
// NOTE: If both peers return sharePolicy=false the replication will not happen
|
|
@@ -704,7 +778,7 @@ var AutomergeHost = class extends Resource2 {
|
|
|
704
778
|
}
|
|
705
779
|
const peerMetadata = this.repo.peerMetadataByPeerId[peerId];
|
|
706
780
|
if (isEchoPeerMetadata(peerMetadata)) {
|
|
707
|
-
return this._echoNetworkAdapter.
|
|
781
|
+
return this._echoNetworkAdapter.shouldAdvertise(peerId, {
|
|
708
782
|
documentId
|
|
709
783
|
});
|
|
710
784
|
}
|
|
@@ -851,18 +925,15 @@ var getSpaceKeyFromDoc = (doc) => {
|
|
|
851
925
|
return String(rawSpaceKey);
|
|
852
926
|
};
|
|
853
927
|
var waitForHeads = async (handle, heads) => {
|
|
854
|
-
await handle.whenReady();
|
|
855
928
|
const unavailableHeads = new Set(heads);
|
|
929
|
+
await handle.whenReady();
|
|
856
930
|
await Event.wrap(handle, "change").waitForCondition(() => {
|
|
857
931
|
for (const changeHash of unavailableHeads.values()) {
|
|
858
932
|
if (changeIsPresentInDoc(handle.docSync(), changeHash)) {
|
|
859
933
|
unavailableHeads.delete(changeHash);
|
|
860
934
|
}
|
|
861
935
|
}
|
|
862
|
-
|
|
863
|
-
return true;
|
|
864
|
-
}
|
|
865
|
-
return false;
|
|
936
|
+
return unavailableHeads.size === 0;
|
|
866
937
|
});
|
|
867
938
|
};
|
|
868
939
|
var changeIsPresentInDoc = (doc, changeHash) => {
|
|
@@ -875,8 +946,8 @@ import { interpretAsDocumentId } from "@dxos/automerge/automerge-repo";
|
|
|
875
946
|
import { cancelWithContext as cancelWithContext2 } from "@dxos/context";
|
|
876
947
|
import { warnAfterTimeout } from "@dxos/debug";
|
|
877
948
|
import { SpaceDocVersion } from "@dxos/echo-protocol";
|
|
878
|
-
import { invariant as
|
|
879
|
-
import { log as
|
|
949
|
+
import { invariant as invariant4 } from "@dxos/invariant";
|
|
950
|
+
import { log as log3 } from "@dxos/log";
|
|
880
951
|
import { trace as trace2 } from "@dxos/tracing";
|
|
881
952
|
function _ts_decorate3(decorators, target, key, desc) {
|
|
882
953
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -888,7 +959,7 @@ function _ts_decorate3(decorators, target, key, desc) {
|
|
|
888
959
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
889
960
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
890
961
|
}
|
|
891
|
-
var
|
|
962
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-doc-loader.ts";
|
|
892
963
|
var AutomergeDocumentLoaderImpl = class {
|
|
893
964
|
constructor(_spaceId, _repo, _spaceKey) {
|
|
894
965
|
this._spaceId = _spaceId;
|
|
@@ -914,8 +985,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
914
985
|
}
|
|
915
986
|
const existingDocHandle = await this._initDocHandle(ctx, spaceState.rootUrl);
|
|
916
987
|
const doc = existingDocHandle.docSync();
|
|
917
|
-
|
|
918
|
-
F:
|
|
988
|
+
invariant4(doc, void 0, {
|
|
989
|
+
F: __dxlog_file4,
|
|
919
990
|
L: 84,
|
|
920
991
|
S: this,
|
|
921
992
|
A: [
|
|
@@ -923,8 +994,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
923
994
|
""
|
|
924
995
|
]
|
|
925
996
|
});
|
|
926
|
-
|
|
927
|
-
F:
|
|
997
|
+
invariant4(doc.version === SpaceDocVersion.CURRENT, void 0, {
|
|
998
|
+
F: __dxlog_file4,
|
|
928
999
|
L: 85,
|
|
929
1000
|
S: this,
|
|
930
1001
|
A: [
|
|
@@ -944,8 +1015,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
944
1015
|
let hasUrlsToLoad = false;
|
|
945
1016
|
const urlsToLoad = {};
|
|
946
1017
|
for (const objectId of objectIds) {
|
|
947
|
-
|
|
948
|
-
F:
|
|
1018
|
+
invariant4(this._spaceRootDocHandle, void 0, {
|
|
1019
|
+
F: __dxlog_file4,
|
|
949
1020
|
L: 97,
|
|
950
1021
|
S: this,
|
|
951
1022
|
A: [
|
|
@@ -957,8 +1028,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
957
1028
|
continue;
|
|
958
1029
|
}
|
|
959
1030
|
const spaceRootDoc = this._spaceRootDocHandle.docSync();
|
|
960
|
-
|
|
961
|
-
F:
|
|
1031
|
+
invariant4(spaceRootDoc, void 0, {
|
|
1032
|
+
F: __dxlog_file4,
|
|
962
1033
|
L: 102,
|
|
963
1034
|
S: this,
|
|
964
1035
|
A: [
|
|
@@ -969,10 +1040,10 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
969
1040
|
const documentUrl = (spaceRootDoc.links ?? {})[objectId];
|
|
970
1041
|
if (documentUrl == null) {
|
|
971
1042
|
this._objectsPendingDocumentLoad.add(objectId);
|
|
972
|
-
|
|
1043
|
+
log3.info("loading delayed until object links are initialized", {
|
|
973
1044
|
objectId
|
|
974
1045
|
}, {
|
|
975
|
-
F:
|
|
1046
|
+
F: __dxlog_file4,
|
|
976
1047
|
L: 106,
|
|
977
1048
|
S: this,
|
|
978
1049
|
C: (f, a) => f(...a)
|
|
@@ -987,8 +1058,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
987
1058
|
}
|
|
988
1059
|
}
|
|
989
1060
|
getObjectDocumentId(objectId) {
|
|
990
|
-
|
|
991
|
-
F:
|
|
1061
|
+
invariant4(this._spaceRootDocHandle, void 0, {
|
|
1062
|
+
F: __dxlog_file4,
|
|
992
1063
|
L: 118,
|
|
993
1064
|
S: this,
|
|
994
1065
|
A: [
|
|
@@ -997,8 +1068,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
997
1068
|
]
|
|
998
1069
|
});
|
|
999
1070
|
const spaceRootDoc = this._spaceRootDocHandle.docSync();
|
|
1000
|
-
|
|
1001
|
-
F:
|
|
1071
|
+
invariant4(spaceRootDoc, void 0, {
|
|
1072
|
+
F: __dxlog_file4,
|
|
1002
1073
|
L: 120,
|
|
1003
1074
|
S: this,
|
|
1004
1075
|
A: [
|
|
@@ -1021,8 +1092,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1021
1092
|
linksAwaitingLoad.forEach(([objectId]) => this._objectsPendingDocumentLoad.delete(objectId));
|
|
1022
1093
|
}
|
|
1023
1094
|
getSpaceRootDocHandle() {
|
|
1024
|
-
|
|
1025
|
-
F:
|
|
1095
|
+
invariant4(this._spaceRootDocHandle, void 0, {
|
|
1096
|
+
F: __dxlog_file4,
|
|
1026
1097
|
L: 140,
|
|
1027
1098
|
S: this,
|
|
1028
1099
|
A: [
|
|
@@ -1033,8 +1104,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1033
1104
|
return this._spaceRootDocHandle;
|
|
1034
1105
|
}
|
|
1035
1106
|
createDocumentForObject(objectId) {
|
|
1036
|
-
|
|
1037
|
-
F:
|
|
1107
|
+
invariant4(this._spaceRootDocHandle, void 0, {
|
|
1108
|
+
F: __dxlog_file4,
|
|
1038
1109
|
L: 145,
|
|
1039
1110
|
S: this,
|
|
1040
1111
|
A: [
|
|
@@ -1075,11 +1146,11 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1075
1146
|
};
|
|
1076
1147
|
const objectDocumentHandle = this._objectDocumentHandles.get(objectId);
|
|
1077
1148
|
if (objectDocumentHandle != null && objectDocumentHandle.url !== automergeUrl) {
|
|
1078
|
-
|
|
1149
|
+
log3.warn("object already inlined in a different document, ignoring the link", {
|
|
1079
1150
|
...logMeta,
|
|
1080
1151
|
actualDocumentUrl: objectDocumentHandle.url
|
|
1081
1152
|
}, {
|
|
1082
|
-
F:
|
|
1153
|
+
F: __dxlog_file4,
|
|
1083
1154
|
L: 177,
|
|
1084
1155
|
S: this,
|
|
1085
1156
|
C: (f, a) => f(...a)
|
|
@@ -1087,8 +1158,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1087
1158
|
continue;
|
|
1088
1159
|
}
|
|
1089
1160
|
if (objectDocumentHandle?.url === automergeUrl) {
|
|
1090
|
-
|
|
1091
|
-
F:
|
|
1161
|
+
log3.warn("object document was already loaded", logMeta, {
|
|
1162
|
+
F: __dxlog_file4,
|
|
1092
1163
|
L: 184,
|
|
1093
1164
|
S: this,
|
|
1094
1165
|
C: (f, a) => f(...a)
|
|
@@ -1096,8 +1167,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1096
1167
|
continue;
|
|
1097
1168
|
}
|
|
1098
1169
|
const handle = this._repo.find(automergeUrl);
|
|
1099
|
-
|
|
1100
|
-
F:
|
|
1170
|
+
log3.debug("document loading triggered", logMeta, {
|
|
1171
|
+
F: __dxlog_file4,
|
|
1101
1172
|
L: 188,
|
|
1102
1173
|
S: this,
|
|
1103
1174
|
C: (f, a) => f(...a)
|
|
@@ -1116,11 +1187,11 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1116
1187
|
break;
|
|
1117
1188
|
} catch (err) {
|
|
1118
1189
|
if (`${err}`.includes("Timeout")) {
|
|
1119
|
-
|
|
1190
|
+
log3.info("wraparound", {
|
|
1120
1191
|
id: docHandle.documentId,
|
|
1121
1192
|
state: docHandle.state
|
|
1122
1193
|
}, {
|
|
1123
|
-
F:
|
|
1194
|
+
F: __dxlog_file4,
|
|
1124
1195
|
L: 204,
|
|
1125
1196
|
S: this,
|
|
1126
1197
|
C: (f, a) => f(...a)
|
|
@@ -1151,8 +1222,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1151
1222
|
docUrl: handle.url
|
|
1152
1223
|
};
|
|
1153
1224
|
if (this.onObjectDocumentLoaded.listenerCount() === 0) {
|
|
1154
|
-
|
|
1155
|
-
F:
|
|
1225
|
+
log3.info("document loaded after all listeners were removed", logMeta, {
|
|
1226
|
+
F: __dxlog_file4,
|
|
1156
1227
|
L: 231,
|
|
1157
1228
|
S: this,
|
|
1158
1229
|
C: (f, a) => f(...a)
|
|
@@ -1161,8 +1232,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1161
1232
|
}
|
|
1162
1233
|
const objectDocHandle = this._objectDocumentHandles.get(objectId);
|
|
1163
1234
|
if (objectDocHandle?.url !== handle.url) {
|
|
1164
|
-
|
|
1165
|
-
F:
|
|
1235
|
+
log3.warn("object was rebound while a document was loading, discarding handle", logMeta, {
|
|
1236
|
+
F: __dxlog_file4,
|
|
1166
1237
|
L: 236,
|
|
1167
1238
|
S: this,
|
|
1168
1239
|
C: (f, a) => f(...a)
|
|
@@ -1175,13 +1246,13 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1175
1246
|
});
|
|
1176
1247
|
} catch (err) {
|
|
1177
1248
|
const shouldRetryLoading = this.onObjectDocumentLoaded.listenerCount() > 0;
|
|
1178
|
-
|
|
1249
|
+
log3.warn("failed to load a document", {
|
|
1179
1250
|
objectId,
|
|
1180
1251
|
automergeUrl: handle.url,
|
|
1181
1252
|
retryLoading: shouldRetryLoading,
|
|
1182
1253
|
err
|
|
1183
1254
|
}, {
|
|
1184
|
-
F:
|
|
1255
|
+
F: __dxlog_file4,
|
|
1185
1256
|
L: 242,
|
|
1186
1257
|
S: this,
|
|
1187
1258
|
C: (f, a) => f(...a)
|
|
@@ -1202,14 +1273,134 @@ AutomergeDocumentLoaderImpl = _ts_decorate3([
|
|
|
1202
1273
|
], AutomergeDocumentLoaderImpl);
|
|
1203
1274
|
|
|
1204
1275
|
// packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts
|
|
1276
|
+
import { invariant as invariant6 } from "@dxos/invariant";
|
|
1277
|
+
import { PublicKey as PublicKey2 } from "@dxos/keys";
|
|
1278
|
+
import { log as log5 } from "@dxos/log";
|
|
1279
|
+
import { ComplexMap, ComplexSet, defaultMap } from "@dxos/util";
|
|
1280
|
+
|
|
1281
|
+
// packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator-connection.ts
|
|
1205
1282
|
import { cbor as cbor2 } from "@dxos/automerge/automerge-repo";
|
|
1206
1283
|
import { Resource as Resource3 } from "@dxos/context";
|
|
1207
|
-
import { invariant as
|
|
1208
|
-
import {
|
|
1209
|
-
import { log as log3 } from "@dxos/log";
|
|
1284
|
+
import { invariant as invariant5 } from "@dxos/invariant";
|
|
1285
|
+
import { log as log4 } from "@dxos/log";
|
|
1210
1286
|
import { AutomergeReplicator } from "@dxos/teleport-extension-automerge-replicator";
|
|
1211
|
-
|
|
1212
|
-
var
|
|
1287
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator-connection.ts";
|
|
1288
|
+
var DEFAULT_FACTORY = (params) => new AutomergeReplicator(...params);
|
|
1289
|
+
var MeshReplicatorConnection = class extends Resource3 {
|
|
1290
|
+
constructor(_params) {
|
|
1291
|
+
super();
|
|
1292
|
+
this._params = _params;
|
|
1293
|
+
this.remoteDeviceKey = null;
|
|
1294
|
+
this._remotePeerId = null;
|
|
1295
|
+
this._isEnabled = false;
|
|
1296
|
+
let readableStreamController;
|
|
1297
|
+
this.readable = new ReadableStream({
|
|
1298
|
+
start: (controller) => {
|
|
1299
|
+
readableStreamController = controller;
|
|
1300
|
+
this._ctx.onDispose(() => controller.close());
|
|
1301
|
+
}
|
|
1302
|
+
});
|
|
1303
|
+
this.writable = new WritableStream({
|
|
1304
|
+
write: async (message, controller) => {
|
|
1305
|
+
invariant5(this._isEnabled, "Writing to a disabled connection", {
|
|
1306
|
+
F: __dxlog_file5,
|
|
1307
|
+
L: 47,
|
|
1308
|
+
S: this,
|
|
1309
|
+
A: [
|
|
1310
|
+
"this._isEnabled",
|
|
1311
|
+
"'Writing to a disabled connection'"
|
|
1312
|
+
]
|
|
1313
|
+
});
|
|
1314
|
+
try {
|
|
1315
|
+
await this.replicatorExtension.sendSyncMessage({
|
|
1316
|
+
payload: cbor2.encode(message)
|
|
1317
|
+
});
|
|
1318
|
+
} catch (err) {
|
|
1319
|
+
controller.error(err);
|
|
1320
|
+
this._disconnectIfEnabled();
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
});
|
|
1324
|
+
const createAutomergeReplicator = this._params.replicatorFactory ?? DEFAULT_FACTORY;
|
|
1325
|
+
this.replicatorExtension = createAutomergeReplicator([
|
|
1326
|
+
{
|
|
1327
|
+
peerId: this._params.ownPeerId
|
|
1328
|
+
},
|
|
1329
|
+
{
|
|
1330
|
+
onStartReplication: async (info, remotePeerId) => {
|
|
1331
|
+
this.remoteDeviceKey = remotePeerId;
|
|
1332
|
+
this._remotePeerId = info.id;
|
|
1333
|
+
log4("onStartReplication", {
|
|
1334
|
+
id: info.id,
|
|
1335
|
+
thisPeerId: this.peerId,
|
|
1336
|
+
remotePeerId: remotePeerId.toHex()
|
|
1337
|
+
}, {
|
|
1338
|
+
F: __dxlog_file5,
|
|
1339
|
+
L: 81,
|
|
1340
|
+
S: this,
|
|
1341
|
+
C: (f, a) => f(...a)
|
|
1342
|
+
});
|
|
1343
|
+
this._params.onRemoteConnected();
|
|
1344
|
+
},
|
|
1345
|
+
onSyncMessage: async ({ payload }) => {
|
|
1346
|
+
if (!this._isEnabled) {
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
const message = cbor2.decode(payload);
|
|
1350
|
+
readableStreamController.enqueue(message);
|
|
1351
|
+
},
|
|
1352
|
+
onClose: async () => {
|
|
1353
|
+
this._disconnectIfEnabled();
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
]);
|
|
1357
|
+
}
|
|
1358
|
+
_disconnectIfEnabled() {
|
|
1359
|
+
if (this._isEnabled) {
|
|
1360
|
+
this._params.onRemoteDisconnected();
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
get peerId() {
|
|
1364
|
+
invariant5(this._remotePeerId != null, "Remote peer has not connected yet.", {
|
|
1365
|
+
F: __dxlog_file5,
|
|
1366
|
+
L: 107,
|
|
1367
|
+
S: this,
|
|
1368
|
+
A: [
|
|
1369
|
+
"this._remotePeerId != null",
|
|
1370
|
+
"'Remote peer has not connected yet.'"
|
|
1371
|
+
]
|
|
1372
|
+
});
|
|
1373
|
+
return this._remotePeerId;
|
|
1374
|
+
}
|
|
1375
|
+
async shouldAdvertise(params) {
|
|
1376
|
+
return this._params.shouldAdvertise(params);
|
|
1377
|
+
}
|
|
1378
|
+
/**
|
|
1379
|
+
* Start exchanging messages with the remote peer.
|
|
1380
|
+
* Call after the remote peer has connected.
|
|
1381
|
+
*/
|
|
1382
|
+
enable() {
|
|
1383
|
+
invariant5(this._remotePeerId != null, "Remote peer has not connected yet.", {
|
|
1384
|
+
F: __dxlog_file5,
|
|
1385
|
+
L: 120,
|
|
1386
|
+
S: this,
|
|
1387
|
+
A: [
|
|
1388
|
+
"this._remotePeerId != null",
|
|
1389
|
+
"'Remote peer has not connected yet.'"
|
|
1390
|
+
]
|
|
1391
|
+
});
|
|
1392
|
+
this._isEnabled = true;
|
|
1393
|
+
}
|
|
1394
|
+
/**
|
|
1395
|
+
* Stop exchanging messages with the remote peer.
|
|
1396
|
+
*/
|
|
1397
|
+
disable() {
|
|
1398
|
+
this._isEnabled = false;
|
|
1399
|
+
}
|
|
1400
|
+
};
|
|
1401
|
+
|
|
1402
|
+
// packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts
|
|
1403
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts";
|
|
1213
1404
|
var MeshEchoReplicator = class {
|
|
1214
1405
|
constructor() {
|
|
1215
1406
|
this._connections = /* @__PURE__ */ new Set();
|
|
@@ -1234,10 +1425,10 @@ var MeshEchoReplicator = class {
|
|
|
1234
1425
|
this._connectionsPerPeer.clear();
|
|
1235
1426
|
this._context = null;
|
|
1236
1427
|
}
|
|
1237
|
-
createExtension() {
|
|
1238
|
-
|
|
1239
|
-
F:
|
|
1240
|
-
L:
|
|
1428
|
+
createExtension(extensionFactory) {
|
|
1429
|
+
invariant6(this._context, void 0, {
|
|
1430
|
+
F: __dxlog_file6,
|
|
1431
|
+
L: 51,
|
|
1241
1432
|
S: this,
|
|
1242
1433
|
A: [
|
|
1243
1434
|
"this._context",
|
|
@@ -1246,18 +1437,19 @@ var MeshEchoReplicator = class {
|
|
|
1246
1437
|
});
|
|
1247
1438
|
const connection = new MeshReplicatorConnection({
|
|
1248
1439
|
ownPeerId: this._context.peerId,
|
|
1440
|
+
replicatorFactory: extensionFactory,
|
|
1249
1441
|
onRemoteConnected: async () => {
|
|
1250
|
-
|
|
1442
|
+
log5("onRemoteConnected", {
|
|
1251
1443
|
peerId: connection.peerId
|
|
1252
1444
|
}, {
|
|
1253
|
-
F:
|
|
1254
|
-
L:
|
|
1445
|
+
F: __dxlog_file6,
|
|
1446
|
+
L: 57,
|
|
1255
1447
|
S: this,
|
|
1256
1448
|
C: (f, a) => f(...a)
|
|
1257
1449
|
});
|
|
1258
|
-
|
|
1259
|
-
F:
|
|
1260
|
-
L:
|
|
1450
|
+
invariant6(this._context, void 0, {
|
|
1451
|
+
F: __dxlog_file6,
|
|
1452
|
+
L: 58,
|
|
1261
1453
|
S: this,
|
|
1262
1454
|
A: [
|
|
1263
1455
|
"this._context",
|
|
@@ -1269,36 +1461,36 @@ var MeshEchoReplicator = class {
|
|
|
1269
1461
|
} else {
|
|
1270
1462
|
this._connectionsPerPeer.set(connection.peerId, connection);
|
|
1271
1463
|
this._context.onConnectionOpen(connection);
|
|
1272
|
-
|
|
1464
|
+
connection.enable();
|
|
1273
1465
|
}
|
|
1274
1466
|
},
|
|
1275
1467
|
onRemoteDisconnected: async () => {
|
|
1276
|
-
|
|
1468
|
+
log5("onRemoteDisconnected", {
|
|
1277
1469
|
peerId: connection.peerId
|
|
1278
1470
|
}, {
|
|
1279
|
-
F:
|
|
1280
|
-
L:
|
|
1471
|
+
F: __dxlog_file6,
|
|
1472
|
+
L: 69,
|
|
1281
1473
|
S: this,
|
|
1282
1474
|
C: (f, a) => f(...a)
|
|
1283
1475
|
});
|
|
1284
1476
|
this._context?.onConnectionClosed(connection);
|
|
1285
1477
|
this._connectionsPerPeer.delete(connection.peerId);
|
|
1286
|
-
|
|
1478
|
+
connection.disable();
|
|
1287
1479
|
this._connections.delete(connection);
|
|
1288
1480
|
},
|
|
1289
|
-
|
|
1290
|
-
|
|
1481
|
+
shouldAdvertise: async (params) => {
|
|
1482
|
+
log5("shouldAdvertise", {
|
|
1291
1483
|
peerId: connection.peerId,
|
|
1292
1484
|
documentId: params.documentId
|
|
1293
1485
|
}, {
|
|
1294
|
-
F:
|
|
1295
|
-
L:
|
|
1486
|
+
F: __dxlog_file6,
|
|
1487
|
+
L: 76,
|
|
1296
1488
|
S: this,
|
|
1297
1489
|
C: (f, a) => f(...a)
|
|
1298
1490
|
});
|
|
1299
|
-
|
|
1300
|
-
F:
|
|
1301
|
-
L:
|
|
1491
|
+
invariant6(this._context, void 0, {
|
|
1492
|
+
F: __dxlog_file6,
|
|
1493
|
+
L: 77,
|
|
1302
1494
|
S: this,
|
|
1303
1495
|
A: [
|
|
1304
1496
|
"this._context",
|
|
@@ -1308,12 +1500,12 @@ var MeshEchoReplicator = class {
|
|
|
1308
1500
|
try {
|
|
1309
1501
|
const spaceKey = await this._context.getContainingSpaceForDocument(params.documentId);
|
|
1310
1502
|
if (!spaceKey) {
|
|
1311
|
-
|
|
1503
|
+
log5("space key not found for share policy check", {
|
|
1312
1504
|
peerId: connection.peerId,
|
|
1313
1505
|
documentId: params.documentId
|
|
1314
1506
|
}, {
|
|
1315
|
-
F:
|
|
1316
|
-
L:
|
|
1507
|
+
F: __dxlog_file6,
|
|
1508
|
+
L: 81,
|
|
1317
1509
|
S: this,
|
|
1318
1510
|
C: (f, a) => f(...a)
|
|
1319
1511
|
});
|
|
@@ -1321,19 +1513,19 @@ var MeshEchoReplicator = class {
|
|
|
1321
1513
|
}
|
|
1322
1514
|
const authorizedDevices = this._authorizedDevices.get(spaceKey);
|
|
1323
1515
|
if (!connection.remoteDeviceKey) {
|
|
1324
|
-
|
|
1516
|
+
log5("device key not found for share policy check", {
|
|
1325
1517
|
peerId: connection.peerId,
|
|
1326
1518
|
documentId: params.documentId
|
|
1327
1519
|
}, {
|
|
1328
|
-
F:
|
|
1329
|
-
L:
|
|
1520
|
+
F: __dxlog_file6,
|
|
1521
|
+
L: 91,
|
|
1330
1522
|
S: this,
|
|
1331
1523
|
C: (f, a) => f(...a)
|
|
1332
1524
|
});
|
|
1333
1525
|
return false;
|
|
1334
1526
|
}
|
|
1335
1527
|
const isAuthorized = authorizedDevices?.has(connection.remoteDeviceKey) ?? false;
|
|
1336
|
-
|
|
1528
|
+
log5("share policy check", {
|
|
1337
1529
|
localPeer: this._context.peerId,
|
|
1338
1530
|
remotePeer: connection.peerId,
|
|
1339
1531
|
documentId: params.documentId,
|
|
@@ -1341,16 +1533,16 @@ var MeshEchoReplicator = class {
|
|
|
1341
1533
|
spaceKey,
|
|
1342
1534
|
isAuthorized
|
|
1343
1535
|
}, {
|
|
1344
|
-
F:
|
|
1345
|
-
L:
|
|
1536
|
+
F: __dxlog_file6,
|
|
1537
|
+
L: 99,
|
|
1346
1538
|
S: this,
|
|
1347
1539
|
C: (f, a) => f(...a)
|
|
1348
1540
|
});
|
|
1349
1541
|
return isAuthorized;
|
|
1350
1542
|
} catch (err) {
|
|
1351
|
-
|
|
1352
|
-
F:
|
|
1353
|
-
L:
|
|
1543
|
+
log5.catch(err, void 0, {
|
|
1544
|
+
F: __dxlog_file6,
|
|
1545
|
+
L: 109,
|
|
1354
1546
|
S: this,
|
|
1355
1547
|
C: (f, a) => f(...a)
|
|
1356
1548
|
});
|
|
@@ -1362,115 +1554,23 @@ var MeshEchoReplicator = class {
|
|
|
1362
1554
|
return connection.replicatorExtension;
|
|
1363
1555
|
}
|
|
1364
1556
|
authorizeDevice(spaceKey, deviceKey) {
|
|
1365
|
-
|
|
1557
|
+
log5("authorizeDevice", {
|
|
1366
1558
|
spaceKey,
|
|
1367
1559
|
deviceKey
|
|
1368
1560
|
}, {
|
|
1369
|
-
F:
|
|
1370
|
-
L:
|
|
1561
|
+
F: __dxlog_file6,
|
|
1562
|
+
L: 120,
|
|
1371
1563
|
S: this,
|
|
1372
1564
|
C: (f, a) => f(...a)
|
|
1373
1565
|
});
|
|
1374
1566
|
defaultMap(this._authorizedDevices, spaceKey, () => new ComplexSet(PublicKey2.hash)).add(deviceKey);
|
|
1375
1567
|
for (const connection of this._connections) {
|
|
1376
1568
|
if (connection.remoteDeviceKey && connection.remoteDeviceKey.equals(deviceKey)) {
|
|
1377
|
-
this.
|
|
1378
|
-
|
|
1379
|
-
}
|
|
1380
|
-
}
|
|
1381
|
-
};
|
|
1382
|
-
var MeshReplicatorConnection = class extends Resource3 {
|
|
1383
|
-
constructor(_params) {
|
|
1384
|
-
super();
|
|
1385
|
-
this._params = _params;
|
|
1386
|
-
this.remoteDeviceKey = null;
|
|
1387
|
-
this._remotePeerId = null;
|
|
1388
|
-
this._isEnabled = false;
|
|
1389
|
-
let readableStreamController;
|
|
1390
|
-
this.readable = new ReadableStream({
|
|
1391
|
-
start: (controller) => {
|
|
1392
|
-
readableStreamController = controller;
|
|
1393
|
-
this._ctx.onDispose(() => controller.close());
|
|
1394
|
-
}
|
|
1395
|
-
});
|
|
1396
|
-
this.writable = new WritableStream({
|
|
1397
|
-
write: async (message, controller) => {
|
|
1398
|
-
this.replicatorExtension.sendSyncMessage({
|
|
1399
|
-
payload: cbor2.encode(message)
|
|
1400
|
-
}).catch((err) => {
|
|
1401
|
-
controller.error(err);
|
|
1402
|
-
});
|
|
1403
|
-
}
|
|
1404
|
-
});
|
|
1405
|
-
this.replicatorExtension = new AutomergeReplicator({
|
|
1406
|
-
peerId: this._params.ownPeerId
|
|
1407
|
-
}, {
|
|
1408
|
-
onStartReplication: async (info, remotePeerId) => {
|
|
1409
|
-
this.remoteDeviceKey = remotePeerId;
|
|
1410
|
-
this._remotePeerId = info.id;
|
|
1411
|
-
log3("onStartReplication", {
|
|
1412
|
-
id: info.id,
|
|
1413
|
-
thisPeerId: this.peerId,
|
|
1414
|
-
remotePeerId: remotePeerId.toHex()
|
|
1415
|
-
}, {
|
|
1416
|
-
F: __dxlog_file4,
|
|
1417
|
-
L: 192,
|
|
1418
|
-
S: this,
|
|
1419
|
-
C: (f, a) => f(...a)
|
|
1420
|
-
});
|
|
1421
|
-
await this._params.onRemoteConnected();
|
|
1422
|
-
},
|
|
1423
|
-
onSyncMessage: async ({ payload }) => {
|
|
1424
|
-
if (!this._isEnabled) {
|
|
1425
|
-
return;
|
|
1426
|
-
}
|
|
1427
|
-
const message = cbor2.decode(payload);
|
|
1428
|
-
readableStreamController.enqueue(message);
|
|
1429
|
-
},
|
|
1430
|
-
onClose: async () => {
|
|
1431
|
-
if (!this._isEnabled) {
|
|
1432
|
-
return;
|
|
1569
|
+
if (this._connectionsPerPeer.has(connection.peerId)) {
|
|
1570
|
+
this._context?.onConnectionAuthScopeChanged(connection);
|
|
1433
1571
|
}
|
|
1434
|
-
await this._params.onRemoteDisconnected();
|
|
1435
1572
|
}
|
|
1436
|
-
}
|
|
1437
|
-
}
|
|
1438
|
-
get peerId() {
|
|
1439
|
-
invariant4(this._remotePeerId != null, "Remote peer has not connected yet.", {
|
|
1440
|
-
F: __dxlog_file4,
|
|
1441
|
-
L: 215,
|
|
1442
|
-
S: this,
|
|
1443
|
-
A: [
|
|
1444
|
-
"this._remotePeerId != null",
|
|
1445
|
-
"'Remote peer has not connected yet.'"
|
|
1446
|
-
]
|
|
1447
|
-
});
|
|
1448
|
-
return this._remotePeerId;
|
|
1449
|
-
}
|
|
1450
|
-
async shouldAdvertize(params) {
|
|
1451
|
-
return this._params.shouldAdvertize(params);
|
|
1452
|
-
}
|
|
1453
|
-
/**
|
|
1454
|
-
* Start exchanging messages with the remote peer.
|
|
1455
|
-
* Call after the remote peer has connected.
|
|
1456
|
-
*/
|
|
1457
|
-
async enable() {
|
|
1458
|
-
invariant4(this._remotePeerId != null, "Remote peer has not connected yet.", {
|
|
1459
|
-
F: __dxlog_file4,
|
|
1460
|
-
L: 228,
|
|
1461
|
-
S: this,
|
|
1462
|
-
A: [
|
|
1463
|
-
"this._remotePeerId != null",
|
|
1464
|
-
"'Remote peer has not connected yet.'"
|
|
1465
|
-
]
|
|
1466
|
-
});
|
|
1467
|
-
this._isEnabled = true;
|
|
1468
|
-
}
|
|
1469
|
-
/**
|
|
1470
|
-
* Stop exchanging messages with the remote peer.
|
|
1471
|
-
*/
|
|
1472
|
-
async disable() {
|
|
1473
|
-
this._isEnabled = false;
|
|
1573
|
+
}
|
|
1474
1574
|
}
|
|
1475
1575
|
};
|
|
1476
1576
|
export {
|