@dxos/echo-pipeline 0.5.9-main.a2de4fa → 0.5.9-main.af4882d
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/index.mjs +41 -29
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +51 -39
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/automerge/automerge-host.d.ts +1 -0
- package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
- package/dist/types/src/automerge/mesh-echo-replicator.d.ts.map +1 -1
- package/package.json +33 -33
- package/src/automerge/automerge-doc-loader.test.ts +3 -2
- package/src/automerge/automerge-host.ts +14 -0
- package/src/automerge/mesh-echo-replicator.ts +0 -5
|
@@ -32,6 +32,7 @@ import { Repo } from "@dxos/automerge/automerge-repo";
|
|
|
32
32
|
import { Context } from "@dxos/context";
|
|
33
33
|
import { invariant as invariant3 } from "@dxos/invariant";
|
|
34
34
|
import { PublicKey } from "@dxos/keys";
|
|
35
|
+
import { log as log2 } from "@dxos/log";
|
|
35
36
|
import { objectPointerCodec } from "@dxos/protocols";
|
|
36
37
|
import { trace } from "@dxos/tracing";
|
|
37
38
|
import { mapValues } from "@dxos/util";
|
|
@@ -590,6 +591,7 @@ var AutomergeHost = class {
|
|
|
590
591
|
this._echoNetworkAdapter = new EchoNetworkAdapter({
|
|
591
592
|
getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this)
|
|
592
593
|
});
|
|
594
|
+
this._requestedDocs = /* @__PURE__ */ new Set();
|
|
593
595
|
this._storage = new LevelDBStorageAdapter({
|
|
594
596
|
db,
|
|
595
597
|
callbacks: {
|
|
@@ -645,6 +647,21 @@ var AutomergeHost = class {
|
|
|
645
647
|
if (!documentId) {
|
|
646
648
|
return false;
|
|
647
649
|
}
|
|
650
|
+
const doc = this._repo.handles[documentId]?.docSync();
|
|
651
|
+
if (!doc) {
|
|
652
|
+
const isRequested = this._requestedDocs.has(`automerge:${documentId}`);
|
|
653
|
+
log2("doc share policy check", {
|
|
654
|
+
peerId,
|
|
655
|
+
documentId,
|
|
656
|
+
isRequested
|
|
657
|
+
}, {
|
|
658
|
+
F: __dxlog_file3,
|
|
659
|
+
L: 143,
|
|
660
|
+
S: this,
|
|
661
|
+
C: (f, a) => f(...a)
|
|
662
|
+
});
|
|
663
|
+
return isRequested;
|
|
664
|
+
}
|
|
648
665
|
const peerMetadata = this.repo.peerMetadataByPeerId[peerId];
|
|
649
666
|
if (peerMetadata?.dxos_peerSource === "EchoNetworkAdapter") {
|
|
650
667
|
return this._echoNetworkAdapter.shouldAdvertize(peerId, {
|
|
@@ -725,7 +742,7 @@ var AutomergeHost = class {
|
|
|
725
742
|
await Promise.all(states?.map(async ({ heads, documentId }) => {
|
|
726
743
|
invariant3(heads, "heads are required for flush", {
|
|
727
744
|
F: __dxlog_file3,
|
|
728
|
-
L:
|
|
745
|
+
L: 237,
|
|
729
746
|
S: this,
|
|
730
747
|
A: [
|
|
731
748
|
"heads",
|
|
@@ -800,7 +817,7 @@ import { cancelWithContext } from "@dxos/context";
|
|
|
800
817
|
import { warnAfterTimeout } from "@dxos/debug";
|
|
801
818
|
import { SpaceDocVersion } from "@dxos/echo-protocol";
|
|
802
819
|
import { invariant as invariant4 } from "@dxos/invariant";
|
|
803
|
-
import { log as
|
|
820
|
+
import { log as log3 } from "@dxos/log";
|
|
804
821
|
import { trace as trace2 } from "@dxos/tracing";
|
|
805
822
|
function _ts_decorate3(decorators, target, key, desc) {
|
|
806
823
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -834,7 +851,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
834
851
|
return;
|
|
835
852
|
}
|
|
836
853
|
if (!spaceState.rootUrl) {
|
|
837
|
-
|
|
854
|
+
log3.error("Database opened with no rootUrl", {
|
|
838
855
|
spaceId: this._spaceId
|
|
839
856
|
}, {
|
|
840
857
|
F: __dxlog_file4,
|
|
@@ -893,7 +910,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
893
910
|
const documentUrl = (spaceRootDoc.links ?? {})[objectId];
|
|
894
911
|
if (documentUrl == null) {
|
|
895
912
|
this._objectsPendingDocumentLoad.add(objectId);
|
|
896
|
-
|
|
913
|
+
log3.info("loading delayed until object links are initialized", {
|
|
897
914
|
objectId
|
|
898
915
|
}, {
|
|
899
916
|
F: __dxlog_file4,
|
|
@@ -973,7 +990,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
973
990
|
};
|
|
974
991
|
const objectDocumentHandle = this._objectDocumentHandles.get(objectId);
|
|
975
992
|
if (objectDocumentHandle != null && objectDocumentHandle.url !== automergeUrl) {
|
|
976
|
-
|
|
993
|
+
log3.warn("object already inlined in a different document, ignoring the link", {
|
|
977
994
|
...logMeta,
|
|
978
995
|
actualDocumentUrl: objectDocumentHandle.url
|
|
979
996
|
}, {
|
|
@@ -985,7 +1002,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
985
1002
|
continue;
|
|
986
1003
|
}
|
|
987
1004
|
if (objectDocumentHandle?.url === automergeUrl) {
|
|
988
|
-
|
|
1005
|
+
log3.warn("object document was already loaded", logMeta, {
|
|
989
1006
|
F: __dxlog_file4,
|
|
990
1007
|
L: 166,
|
|
991
1008
|
S: this,
|
|
@@ -994,7 +1011,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
994
1011
|
continue;
|
|
995
1012
|
}
|
|
996
1013
|
const handle = this._repo.find(automergeUrl);
|
|
997
|
-
|
|
1014
|
+
log3.debug("document loading triggered", logMeta, {
|
|
998
1015
|
F: __dxlog_file4,
|
|
999
1016
|
L: 170,
|
|
1000
1017
|
S: this,
|
|
@@ -1014,7 +1031,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1014
1031
|
break;
|
|
1015
1032
|
} catch (err) {
|
|
1016
1033
|
if (`${err}`.includes("Timeout")) {
|
|
1017
|
-
|
|
1034
|
+
log3.info("wraparound", {
|
|
1018
1035
|
id: docHandle.documentId,
|
|
1019
1036
|
state: docHandle.state
|
|
1020
1037
|
}, {
|
|
@@ -1059,7 +1076,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1059
1076
|
docUrl: handle.url
|
|
1060
1077
|
};
|
|
1061
1078
|
if (this.onObjectDocumentLoaded.listenerCount() === 0) {
|
|
1062
|
-
|
|
1079
|
+
log3.info("document loaded after all listeners were removed", logMeta, {
|
|
1063
1080
|
F: __dxlog_file4,
|
|
1064
1081
|
L: 222,
|
|
1065
1082
|
S: this,
|
|
@@ -1069,7 +1086,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1069
1086
|
}
|
|
1070
1087
|
const objectDocHandle = this._objectDocumentHandles.get(objectId);
|
|
1071
1088
|
if (objectDocHandle?.url !== handle.url) {
|
|
1072
|
-
|
|
1089
|
+
log3.warn("object was rebound while a document was loading, discarding handle", logMeta, {
|
|
1073
1090
|
F: __dxlog_file4,
|
|
1074
1091
|
L: 227,
|
|
1075
1092
|
S: this,
|
|
@@ -1083,7 +1100,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1083
1100
|
});
|
|
1084
1101
|
} catch (err) {
|
|
1085
1102
|
const shouldRetryLoading = this.onObjectDocumentLoaded.listenerCount() > 0;
|
|
1086
|
-
|
|
1103
|
+
log3.warn("failed to load a document", {
|
|
1087
1104
|
objectId,
|
|
1088
1105
|
automergeUrl: handle.url,
|
|
1089
1106
|
retryLoading: shouldRetryLoading,
|
|
@@ -1114,7 +1131,7 @@ import { cbor as cbor2 } from "@dxos/automerge/automerge-repo";
|
|
|
1114
1131
|
import { Resource as Resource2 } from "@dxos/context";
|
|
1115
1132
|
import { invariant as invariant5 } from "@dxos/invariant";
|
|
1116
1133
|
import { PublicKey as PublicKey2 } from "@dxos/keys";
|
|
1117
|
-
import { log as
|
|
1134
|
+
import { log as log4 } from "@dxos/log";
|
|
1118
1135
|
import { AutomergeReplicator } from "@dxos/teleport-extension-automerge-replicator";
|
|
1119
1136
|
import { ComplexMap, ComplexSet, defaultMap } from "@dxos/util";
|
|
1120
1137
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts";
|
|
@@ -1155,7 +1172,7 @@ var MeshEchoReplicator = class {
|
|
|
1155
1172
|
const connection = new MeshReplicatorConnection({
|
|
1156
1173
|
ownPeerId: this._context.peerId,
|
|
1157
1174
|
onRemoteConnected: async () => {
|
|
1158
|
-
|
|
1175
|
+
log4("onRemoteConnected", {
|
|
1159
1176
|
peerId: connection.peerId
|
|
1160
1177
|
}, {
|
|
1161
1178
|
F: __dxlog_file5,
|
|
@@ -1181,7 +1198,7 @@ var MeshEchoReplicator = class {
|
|
|
1181
1198
|
}
|
|
1182
1199
|
},
|
|
1183
1200
|
onRemoteDisconnected: async () => {
|
|
1184
|
-
|
|
1201
|
+
log4("onRemoteDisconnected", {
|
|
1185
1202
|
peerId: connection.peerId
|
|
1186
1203
|
}, {
|
|
1187
1204
|
F: __dxlog_file5,
|
|
@@ -1195,7 +1212,7 @@ var MeshEchoReplicator = class {
|
|
|
1195
1212
|
this._connections.delete(connection);
|
|
1196
1213
|
},
|
|
1197
1214
|
shouldAdvertize: async (params) => {
|
|
1198
|
-
|
|
1215
|
+
log4("shouldAdvertize", {
|
|
1199
1216
|
peerId: connection.peerId,
|
|
1200
1217
|
documentId: params.documentId
|
|
1201
1218
|
}, {
|
|
@@ -1216,7 +1233,7 @@ var MeshEchoReplicator = class {
|
|
|
1216
1233
|
try {
|
|
1217
1234
|
const spaceKey = await this._context.getContainingSpaceForDocument(params.documentId);
|
|
1218
1235
|
if (!spaceKey) {
|
|
1219
|
-
|
|
1236
|
+
log4("space key not found for share policy check", {
|
|
1220
1237
|
peerId: connection.peerId,
|
|
1221
1238
|
documentId: params.documentId
|
|
1222
1239
|
}, {
|
|
@@ -1229,7 +1246,7 @@ var MeshEchoReplicator = class {
|
|
|
1229
1246
|
}
|
|
1230
1247
|
const authorizedDevices = this._authorizedDevices.get(spaceKey);
|
|
1231
1248
|
if (!connection.remoteDeviceKey) {
|
|
1232
|
-
|
|
1249
|
+
log4("device key not found for share policy check", {
|
|
1233
1250
|
peerId: connection.peerId,
|
|
1234
1251
|
documentId: params.documentId
|
|
1235
1252
|
}, {
|
|
@@ -1241,7 +1258,7 @@ var MeshEchoReplicator = class {
|
|
|
1241
1258
|
return false;
|
|
1242
1259
|
}
|
|
1243
1260
|
const isAuthorized = authorizedDevices?.has(connection.remoteDeviceKey) ?? false;
|
|
1244
|
-
|
|
1261
|
+
log4("share policy check", {
|
|
1245
1262
|
localPeer: this._context.peerId,
|
|
1246
1263
|
remotePeer: connection.peerId,
|
|
1247
1264
|
documentId: params.documentId,
|
|
@@ -1256,7 +1273,7 @@ var MeshEchoReplicator = class {
|
|
|
1256
1273
|
});
|
|
1257
1274
|
return isAuthorized;
|
|
1258
1275
|
} catch (err) {
|
|
1259
|
-
|
|
1276
|
+
log4.catch(err, void 0, {
|
|
1260
1277
|
F: __dxlog_file5,
|
|
1261
1278
|
L: 111,
|
|
1262
1279
|
S: this,
|
|
@@ -1270,7 +1287,7 @@ var MeshEchoReplicator = class {
|
|
|
1270
1287
|
return connection.replicatorExtension;
|
|
1271
1288
|
}
|
|
1272
1289
|
authorizeDevice(spaceKey, deviceKey) {
|
|
1273
|
-
|
|
1290
|
+
log4("authorizeDevice", {
|
|
1274
1291
|
spaceKey,
|
|
1275
1292
|
deviceKey
|
|
1276
1293
|
}, {
|
|
@@ -1280,11 +1297,6 @@ var MeshEchoReplicator = class {
|
|
|
1280
1297
|
C: (f, a) => f(...a)
|
|
1281
1298
|
});
|
|
1282
1299
|
defaultMap(this._authorizedDevices, spaceKey, () => new ComplexSet(PublicKey2.hash)).add(deviceKey);
|
|
1283
|
-
for (const connection of this._connections) {
|
|
1284
|
-
if (connection.remoteDeviceKey && connection.remoteDeviceKey.equals(deviceKey)) {
|
|
1285
|
-
this._context?.onConnectionAuthScopeChanged(connection);
|
|
1286
|
-
}
|
|
1287
|
-
}
|
|
1288
1300
|
}
|
|
1289
1301
|
};
|
|
1290
1302
|
var MeshReplicatorConnection = class extends Resource2 {
|
|
@@ -1316,13 +1328,13 @@ var MeshReplicatorConnection = class extends Resource2 {
|
|
|
1316
1328
|
onStartReplication: async (info, remotePeerId) => {
|
|
1317
1329
|
this.remoteDeviceKey = remotePeerId;
|
|
1318
1330
|
this._remotePeerId = info.id;
|
|
1319
|
-
|
|
1331
|
+
log4("onStartReplication", {
|
|
1320
1332
|
id: info.id,
|
|
1321
1333
|
thisPeerId: this.peerId,
|
|
1322
1334
|
remotePeerId: remotePeerId.toHex()
|
|
1323
1335
|
}, {
|
|
1324
1336
|
F: __dxlog_file5,
|
|
1325
|
-
L:
|
|
1337
|
+
L: 187,
|
|
1326
1338
|
S: this,
|
|
1327
1339
|
C: (f, a) => f(...a)
|
|
1328
1340
|
});
|
|
@@ -1346,7 +1358,7 @@ var MeshReplicatorConnection = class extends Resource2 {
|
|
|
1346
1358
|
get peerId() {
|
|
1347
1359
|
invariant5(this._remotePeerId != null, "Remote peer has not connected yet.", {
|
|
1348
1360
|
F: __dxlog_file5,
|
|
1349
|
-
L:
|
|
1361
|
+
L: 210,
|
|
1350
1362
|
S: this,
|
|
1351
1363
|
A: [
|
|
1352
1364
|
"this._remotePeerId != null",
|
|
@@ -1365,7 +1377,7 @@ var MeshReplicatorConnection = class extends Resource2 {
|
|
|
1365
1377
|
async enable() {
|
|
1366
1378
|
invariant5(this._remotePeerId != null, "Remote peer has not connected yet.", {
|
|
1367
1379
|
F: __dxlog_file5,
|
|
1368
|
-
L:
|
|
1380
|
+
L: 223,
|
|
1369
1381
|
S: this,
|
|
1370
1382
|
A: [
|
|
1371
1383
|
"this._remotePeerId != null",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/automerge/automerge-host.ts", "../../../src/automerge/echo-network-adapter.ts", "../../../src/automerge/leveldb-storage-adapter.ts", "../../../src/automerge/local-host-network-adapter.ts", "../../../src/automerge/automerge-doc-loader.ts", "../../../src/automerge/mesh-echo-replicator.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Event } from '@dxos/async';\nimport { next as automerge, getBackend, getHeads, type Doc, type Heads } from '@dxos/automerge/automerge';\nimport {\n Repo,\n type DocHandle,\n type DocHandleChangePayload,\n type DocumentId,\n type PeerId,\n type StorageAdapterInterface,\n} from '@dxos/automerge/automerge-repo';\nimport { type Stream } from '@dxos/codec-protobuf';\nimport { Context, type Lifecycle } from '@dxos/context';\nimport { type SpaceDoc } from '@dxos/echo-protocol';\nimport { type IndexMetadataStore } from '@dxos/indexing';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { type SublevelDB } from '@dxos/kv-store';\nimport { objectPointerCodec } from '@dxos/protocols';\nimport {\n type FlushRequest,\n type HostInfo,\n type SyncRepoRequest,\n type SyncRepoResponse,\n} from '@dxos/protocols/proto/dxos/echo/service';\nimport { trace } from '@dxos/tracing';\nimport { mapValues } from '@dxos/util';\n\nimport { EchoNetworkAdapter } from './echo-network-adapter';\nimport { type EchoReplicator } from './echo-replicator';\nimport { LevelDBStorageAdapter, type BeforeSaveParams } from './leveldb-storage-adapter';\nimport { LocalHostNetworkAdapter } from './local-host-network-adapter';\n\n// TODO: Remove\nexport type { DocumentId };\n\nexport type AutomergeHostParams = {\n db: SublevelDB;\n\n indexMetadataStore: IndexMetadataStore;\n};\n\n@trace.resource()\nexport class AutomergeHost {\n private readonly _indexMetadataStore: IndexMetadataStore;\n private readonly _ctx = new Context();\n private readonly _echoNetworkAdapter = new EchoNetworkAdapter({\n getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this),\n });\n\n private _repo!: Repo;\n private _clientNetwork!: LocalHostNetworkAdapter;\n private _storage!: StorageAdapterInterface & Lifecycle;\n\n @trace.info()\n private _peerId!: string;\n\n constructor({ db, indexMetadataStore }: AutomergeHostParams) {\n this._storage = new LevelDBStorageAdapter({\n db,\n callbacks: {\n beforeSave: async (params) => this._beforeSave(params),\n afterSave: async () => this._afterSave(),\n },\n });\n this._indexMetadataStore = indexMetadataStore;\n }\n\n async open() {\n // TODO(burdon): Should this be stable?\n this._peerId = `host-${PublicKey.random().toHex()}` as PeerId;\n\n await this._storage.open?.();\n this._clientNetwork = new LocalHostNetworkAdapter();\n\n // Construct the automerge repo.\n this._repo = new Repo({\n peerId: this._peerId as PeerId,\n sharePolicy: this._sharePolicy.bind(this),\n storage: this._storage,\n network: [\n // Downstream client.\n this._clientNetwork,\n // Upstream swarm.\n this._echoNetworkAdapter,\n ],\n });\n\n this._clientNetwork.ready();\n await this._echoNetworkAdapter.open();\n await this._clientNetwork.whenConnected();\n await this._echoNetworkAdapter.whenConnected();\n }\n\n async close() {\n await this._storage.close?.();\n await this._clientNetwork.close();\n await this._echoNetworkAdapter.close();\n await this._ctx.dispose();\n }\n\n get repo(): Repo {\n return this._repo;\n }\n\n async addReplicator(replicator: EchoReplicator) {\n await this._echoNetworkAdapter.addReplicator(replicator);\n }\n\n async removeReplicator(replicator: EchoReplicator) {\n await this._echoNetworkAdapter.removeReplicator(replicator);\n }\n\n // TODO(dmaretskyi): Share based on HALO permissions and space affinity.\n // Hosts, running in the worker, don't share documents unless requested by other peers.\n // NOTE: If both peers return sharePolicy=false the replication will not happen\n // https://github.com/automerge/automerge-repo/pull/292\n private async _sharePolicy(\n peerId: PeerId /* device key */,\n documentId?: DocumentId /* space key */,\n ): Promise<boolean> {\n if (peerId.startsWith('client-')) {\n return false; // Only send docs to clients if they are requested.\n }\n\n if (!documentId) {\n return false;\n }\n\n const peerMetadata = this.repo.peerMetadataByPeerId[peerId];\n if ((peerMetadata as any)?.dxos_peerSource === 'EchoNetworkAdapter') {\n return this._echoNetworkAdapter.shouldAdvertize(peerId, { documentId });\n }\n\n return false;\n }\n\n private async _beforeSave({ path, batch }: BeforeSaveParams) {\n const handle = this._repo.handles[path[0] as DocumentId];\n if (!handle) {\n return;\n }\n const doc = handle.docSync();\n if (!doc) {\n return;\n }\n\n const spaceKey = getSpaceKeyFromDoc(doc) ?? undefined;\n\n const lastAvailableHash = getHeads(doc);\n\n const objectIds = Object.keys(doc.objects ?? {});\n const encodedIds = objectIds.map((objectId) =>\n objectPointerCodec.encode({ documentId: handle.documentId, objectId, spaceKey }),\n );\n const idToLastHash = new Map(encodedIds.map((id) => [id, lastAvailableHash]));\n this._indexMetadataStore.markDirty(idToLastHash, batch);\n }\n\n /**\n * Called by AutomergeStorageAdapter after levelDB batch commit.\n */\n private async _afterSave() {\n this._indexMetadataStore.notifyMarkedDirty();\n }\n\n @trace.info({ depth: null })\n private _automergeDocs() {\n return mapValues(this._repo.handles, (handle) => ({\n state: handle.state,\n hasDoc: !!handle.docSync(),\n heads: handle.docSync() ? automerge.getHeads(handle.docSync()) : null,\n data:\n handle.docSync() &&\n mapValues(handle.docSync(), (value, key) => {\n try {\n switch (key) {\n case 'access':\n case 'links':\n return value;\n case 'objects':\n return Object.keys(value as any);\n default:\n return `${value}`;\n }\n } catch (err) {\n return `${err}`;\n }\n }),\n }));\n }\n\n @trace.info({ depth: null })\n private _automergePeers() {\n return this._repo.peers;\n }\n\n private async _getContainingSpaceForDocument(documentId: string): Promise<PublicKey | null> {\n const doc = this._repo.handles[documentId as any]?.docSync();\n if (!doc) {\n return null;\n }\n\n const spaceKeyHex = getSpaceKeyFromDoc(doc);\n if (!spaceKeyHex) {\n return null;\n }\n\n return PublicKey.from(spaceKeyHex);\n }\n\n //\n // Methods for client-services.\n //\n @trace.span({ showInBrowserTimeline: true })\n async flush({ states }: FlushRequest): Promise<void> {\n // Note: Wait for all requested documents to be loaded/synced from thin-client.\n await Promise.all(\n states?.map(async ({ heads, documentId }) => {\n invariant(heads, 'heads are required for flush');\n const handle = this.repo.handles[documentId as DocumentId] ?? this._repo.find(documentId as DocumentId);\n await waitForHeads(handle, heads);\n }) ?? [],\n );\n\n await this._repo.flush(states?.map(({ documentId }) => documentId as DocumentId));\n }\n\n syncRepo(request: SyncRepoRequest): Stream<SyncRepoResponse> {\n return this._clientNetwork.syncRepo(request);\n }\n\n sendSyncMessage(request: SyncRepoRequest): Promise<void> {\n return this._clientNetwork.sendSyncMessage(request);\n }\n\n async getHostInfo(): Promise<HostInfo> {\n return this._clientNetwork.getHostInfo();\n }\n}\n\nexport const getSpaceKeyFromDoc = (doc: any): string | null => {\n // experimental_spaceKey is set on old documents, new ones are created with doc.access.spaceKey\n const rawSpaceKey = doc.access?.spaceKey ?? doc.experimental_spaceKey;\n if (rawSpaceKey == null) {\n return null;\n }\n\n return String(rawSpaceKey);\n};\n\nconst waitForHeads = async (handle: DocHandle<SpaceDoc>, heads: Heads) => {\n await handle.whenReady();\n const unavailableHeads = new Set(heads);\n\n await Event.wrap<DocHandleChangePayload<SpaceDoc>>(handle, 'change').waitForCondition(() => {\n // Check if unavailable heads became available.\n for (const changeHash of unavailableHeads.values()) {\n if (changeIsPresentInDoc(handle.docSync(), changeHash)) {\n unavailableHeads.delete(changeHash);\n }\n }\n\n if (unavailableHeads.size === 0) {\n return true;\n }\n return false;\n });\n};\n\nconst changeIsPresentInDoc = (doc: Doc<any>, changeHash: string): boolean => {\n return !!getBackend(doc).getChangeByHash(changeHash);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { Trigger, synchronized } from '@dxos/async';\nimport { type Message, NetworkAdapter, type PeerId, type PeerMetadata } from '@dxos/automerge/automerge-repo';\nimport { LifecycleState } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { type PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\n\nimport { type EchoReplicator, type ReplicatorConnection, type ShouldAdvertizeParams } from './echo-replicator';\n\nexport type EchoNetworkAdapterParams = {\n getContainingSpaceForDocument: (documentId: string) => Promise<PublicKey | null>;\n};\n\n/**\n * Manages a set of {@link EchoReplicator} instances.\n */\nexport class EchoNetworkAdapter extends NetworkAdapter {\n private readonly _replicators = new Set<EchoReplicator>();\n /**\n * Remote peer id -> connection.\n */\n private readonly _connections = new Map<PeerId, ConnectionEntry>();\n private _lifecycleState: LifecycleState = LifecycleState.CLOSED;\n private readonly _connected = new Trigger();\n\n constructor(private readonly _params: EchoNetworkAdapterParams) {\n super();\n }\n\n override connect(peerId: PeerId, peerMetadata?: PeerMetadata | undefined): void {\n this.peerId = peerId;\n this.peerMetadata = peerMetadata;\n this._connected.wake();\n }\n\n override send(message: Message): void {\n const connectionEntry = this._connections.get(message.targetId);\n if (!connectionEntry) {\n throw new Error('Connection not found.');\n }\n\n // TODO(dmaretskyi): Find a way to enforce backpressure on AM-repo.\n connectionEntry.writer.write(message).catch((err) => {\n if (connectionEntry.isOpen) {\n log.catch(err);\n }\n });\n }\n\n override disconnect(): void {\n // No-op\n }\n\n @synchronized\n async open() {\n invariant(this._lifecycleState === LifecycleState.CLOSED);\n this._lifecycleState = LifecycleState.OPEN;\n\n log('emit ready');\n this.emit('ready', {\n network: this,\n });\n }\n\n @synchronized\n async close() {\n invariant(this._lifecycleState === LifecycleState.OPEN);\n\n for (const replicator of this._replicators) {\n await replicator.disconnect();\n }\n this._replicators.clear();\n\n this._lifecycleState = LifecycleState.CLOSED;\n }\n\n async whenConnected() {\n await this._connected.wait({ timeout: 10_000 });\n }\n\n @synchronized\n async addReplicator(replicator: EchoReplicator) {\n invariant(this._lifecycleState === LifecycleState.OPEN);\n invariant(this.peerId);\n invariant(!this._replicators.has(replicator));\n\n this._replicators.add(replicator);\n await replicator.connect({\n peerId: this.peerId,\n onConnectionOpen: this._onConnectionOpen.bind(this),\n onConnectionClosed: this._onConnectionClosed.bind(this),\n onConnectionAuthScopeChanged: this._onConnectionAuthScopeChanged.bind(this),\n getContainingSpaceForDocument: this._params.getContainingSpaceForDocument,\n });\n }\n\n @synchronized\n async removeReplicator(replicator: EchoReplicator) {\n invariant(this._lifecycleState === LifecycleState.OPEN);\n invariant(this._replicators.has(replicator));\n await replicator.disconnect();\n this._replicators.delete(replicator);\n }\n\n async shouldAdvertize(peerId: PeerId, params: ShouldAdvertizeParams): Promise<boolean> {\n const connection = this._connections.get(peerId);\n if (!connection) {\n return false;\n }\n\n return connection.connection.shouldAdvertize(params);\n }\n\n private _onConnectionOpen(connection: ReplicatorConnection) {\n log('Connection opened', { peerId: connection.peerId });\n invariant(!this._connections.has(connection.peerId as PeerId));\n const reader = connection.readable.getReader();\n const writer = connection.writable.getWriter();\n const connectionEntry: ConnectionEntry = { connection, reader, writer, isOpen: true };\n this._connections.set(connection.peerId as PeerId, connectionEntry);\n\n queueMicrotask(async () => {\n try {\n while (true) {\n // TODO(dmaretskyi): Find a way to enforce backpressure on AM-repo.\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n this.emit('message', value);\n }\n } catch (err) {\n if (connectionEntry.isOpen) {\n log.catch(err);\n }\n }\n });\n\n log('emit peer-candidate', { peerId: connection.peerId });\n this._emitPeerCandidate(connection);\n }\n\n /**\n * Trigger doc-synchronizer shared documents set recalculation. Happens on peer-candidate.\n * TODO(y): replace with a proper API call when sharePolicy update becomes supported by automerge-repo\n */\n private _onConnectionAuthScopeChanged(connection: ReplicatorConnection) {\n log('Connection auth scope changed', { peerId: connection.peerId });\n const entry = this._connections.get(connection.peerId as PeerId);\n invariant(entry);\n this.emit('peer-disconnected', { peerId: connection.peerId as PeerId });\n this._emitPeerCandidate(connection);\n }\n\n private _onConnectionClosed(connection: ReplicatorConnection) {\n log('Connection closed', { peerId: connection.peerId });\n const entry = this._connections.get(connection.peerId as PeerId);\n invariant(entry);\n\n entry.isOpen = false;\n this.emit('peer-disconnected', { peerId: connection.peerId as PeerId });\n\n void entry.reader.cancel().catch((err) => log.catch(err));\n void entry.writer.abort().catch((err) => log.catch(err));\n\n this._connections.delete(connection.peerId as PeerId);\n }\n\n private _emitPeerCandidate(connection: ReplicatorConnection) {\n this.emit('peer-candidate', {\n peerId: connection.peerId as PeerId,\n peerMetadata: {\n // TODO(dmaretskyi): Refactor this.\n dxos_peerSource: 'EchoNetworkAdapter',\n } as any,\n });\n }\n}\n\ntype ConnectionEntry = {\n connection: ReplicatorConnection;\n reader: ReadableStreamDefaultReader<Message>;\n writer: WritableStreamDefaultWriter<Message>;\n isOpen: boolean;\n};\n", "//\n// Copyright 2024 DXOS.org\n// s\n\nimport { type MixedEncoding } from 'level-transcoder';\n\nimport { type StorageAdapterInterface, type Chunk, type StorageKey } from '@dxos/automerge/automerge-repo';\nimport { LifecycleState, Resource } from '@dxos/context';\nimport { type BatchLevel, type SublevelDB } from '@dxos/kv-store';\nimport { type MaybePromise } from '@dxos/util';\n\nexport type LevelDBStorageAdapterParams = {\n db: SublevelDB;\n callbacks?: StorageCallbacks;\n};\n\nexport type BeforeSaveParams = { path: StorageKey; batch: BatchLevel };\n\nexport interface StorageCallbacks {\n beforeSave(params: BeforeSaveParams): MaybePromise<void>;\n afterSave(path: StorageKey): MaybePromise<void>;\n}\n\nexport class LevelDBStorageAdapter extends Resource implements StorageAdapterInterface {\n constructor(private readonly _params: LevelDBStorageAdapterParams) {\n super();\n }\n\n async load(keyArray: StorageKey): Promise<Uint8Array | undefined> {\n try {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n // TODO(mykola): this should be an error.\n return undefined;\n }\n return await this._params.db.get<StorageKey, Uint8Array>(keyArray, { ...encodingOptions });\n } catch (err: any) {\n if (isLevelDbNotFoundError(err)) {\n return undefined;\n }\n throw err;\n }\n }\n\n async save(keyArray: StorageKey, binary: Uint8Array): Promise<void> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return undefined;\n }\n const batch = this._params.db.batch();\n\n await this._params.callbacks?.beforeSave?.({ path: keyArray, batch });\n batch.put<StorageKey, Uint8Array>(keyArray, Buffer.from(binary), {\n ...encodingOptions,\n });\n await batch.write();\n\n await this._params.callbacks?.afterSave?.(keyArray);\n }\n\n async remove(keyArray: StorageKey): Promise<void> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return undefined;\n }\n await this._params.db.del<StorageKey>(keyArray, { ...encodingOptions });\n }\n\n async loadRange(keyPrefix: StorageKey): Promise<Chunk[]> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return [];\n }\n const result: Chunk[] = [];\n for await (const [key, value] of this._params.db.iterator<StorageKey, Uint8Array>({\n gte: keyPrefix,\n lte: [...keyPrefix, '\\uffff'],\n ...encodingOptions,\n })) {\n result.push({\n key,\n data: value,\n });\n }\n return result;\n }\n\n async removeRange(keyPrefix: StorageKey): Promise<void> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return undefined;\n }\n const batch = this._params.db.batch();\n\n for await (const [key] of this._params.db.iterator<StorageKey, Uint8Array>({\n gte: keyPrefix,\n lte: [...keyPrefix, '\\uffff'],\n ...encodingOptions,\n })) {\n batch.del<StorageKey>(key, { ...encodingOptions });\n }\n await batch.write();\n }\n}\n\nconst keyEncoder: MixedEncoding<StorageKey, Uint8Array, StorageKey> = {\n encode: (key: StorageKey): Uint8Array =>\n Buffer.from(key.map((k) => k.replaceAll('%', '%25').replaceAll('-', '%2D')).join('-')),\n decode: (key: Uint8Array): StorageKey =>\n Buffer.from(key)\n .toString()\n .split('-')\n .map((k) => k.replaceAll('%2D', '-').replaceAll('%25', '%')),\n format: 'buffer',\n};\n\nexport const encodingOptions = {\n keyEncoding: keyEncoder,\n valueEncoding: 'buffer',\n};\n\nconst isLevelDbNotFoundError = (err: any): boolean => err.code === 'LEVEL_NOT_FOUND';\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { Trigger } from '@dxos/async';\nimport { NetworkAdapter, type Message, type PeerId, cbor } from '@dxos/automerge/automerge-repo';\nimport { Stream } from '@dxos/codec-protobuf';\nimport { invariant } from '@dxos/invariant';\nimport { type HostInfo, type SyncRepoRequest, type SyncRepoResponse } from '@dxos/protocols/proto/dxos/echo/service';\n\ntype ClientSyncState = {\n connected: boolean;\n send: (message: Message) => void;\n disconnect: () => void;\n};\n\n/**\n * Used to replicate with apps running on the same device.\n */\nexport class LocalHostNetworkAdapter extends NetworkAdapter {\n private readonly _peers: Map<PeerId, ClientSyncState> = new Map();\n\n /**\n * Emits `ready` event. That signals to `Repo` that it can start using the adapter.\n */\n ready() {\n // NOTE: Emitting `ready` event in NetworkAdapter`s constructor causes a race condition\n // because `Repo` waits for `ready` event (which it never receives) before it starts using the adapter.\n this.emit('ready', {\n network: this,\n });\n }\n\n private readonly _connected = new Trigger();\n private _isConnected: boolean = false;\n\n /**\n * Called by `Repo` to connect to the network.\n *\n * @param peerId Our peer Id.\n */\n override connect(peerId: PeerId): void {\n this.peerId = peerId;\n this._isConnected = true;\n this._connected.wake();\n // No-op. Client always connects first\n }\n\n override send(message: Message): void {\n const peer = this._peers.get(message.targetId);\n invariant(peer, 'Peer not found.');\n peer.send(message);\n }\n\n async close() {\n this._peers.forEach((peer) => peer.disconnect());\n this.emit('close');\n }\n\n override disconnect(): void {\n // TODO(mykola): `disconnect` is not used anywhere in `Repo` from `@automerge/automerge-repo`. Should we remove it?\n // No-op\n }\n\n async whenConnected(): Promise<void> {\n await this._connected.wait({ timeout: 10_000 });\n }\n\n syncRepo({ id, syncMessage }: SyncRepoRequest): Stream<SyncRepoResponse> {\n const peerId = this._getPeerId(id);\n\n return new Stream(({ next, close }) => {\n invariant(!this._peers.has(peerId), 'Peer already connected.');\n this._peers.set(peerId, {\n connected: true,\n send: (message) => {\n next({\n syncMessage: cbor.encode(message),\n });\n },\n disconnect: () => {\n this._peers.delete(peerId);\n close();\n this.emit('peer-disconnected', {\n peerId,\n });\n },\n });\n\n invariant(this._isConnected);\n this.emit('peer-candidate', {\n peerMetadata: {},\n peerId,\n });\n });\n }\n\n async sendSyncMessage({ id, syncMessage }: SyncRepoRequest): Promise<void> {\n invariant(this._isConnected);\n const message = cbor.decode(syncMessage!) as Message;\n this.emit('message', message);\n }\n\n async getHostInfo(): Promise<HostInfo> {\n invariant(this._isConnected);\n invariant(this.peerId, 'Peer id not set.');\n return {\n peerId: this.peerId,\n };\n }\n\n private _getPeerId(id: string): PeerId {\n return id as PeerId;\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { Event } from '@dxos/async';\nimport { type DocHandle, type AutomergeUrl, type DocumentId, type Repo } from '@dxos/automerge/automerge-repo';\nimport { cancelWithContext, type Context } from '@dxos/context';\nimport { warnAfterTimeout } from '@dxos/debug';\nimport { type SpaceState, type SpaceDoc, SpaceDocVersion } from '@dxos/echo-protocol';\nimport { invariant } from '@dxos/invariant';\nimport { type PublicKey, type SpaceId } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { trace } from '@dxos/tracing';\n\ntype SpaceDocumentLinks = SpaceDoc['links'];\n\nexport interface AutomergeDocumentLoader {\n onObjectDocumentLoaded: Event<ObjectDocumentLoaded>;\n\n getAllHandles(): DocHandle<SpaceDoc>[];\n\n loadSpaceRootDocHandle(ctx: Context, spaceState: SpaceState): Promise<void>;\n loadObjectDocument(objectId: string | string[]): void;\n getSpaceRootDocHandle(): DocHandle<SpaceDoc>;\n createDocumentForObject(objectId: string): DocHandle<SpaceDoc>;\n onObjectLinksUpdated(links: SpaceDocumentLinks): void;\n onObjectBoundToDocument(handle: DocHandle<SpaceDoc>, objectId: string): void;\n\n /**\n * @returns objectIds for which we had document handles or were loading one.\n */\n clearHandleReferences(): string[];\n}\n\n/**\n * Manages object <-> docHandle binding and automerge document loading.\n */\n@trace.resource()\nexport class AutomergeDocumentLoaderImpl implements AutomergeDocumentLoader {\n private _spaceRootDocHandle: DocHandle<SpaceDoc> | null = null;\n /**\n * An object id pointer to a handle of the document where the object is stored inline.\n */\n private readonly _objectDocumentHandles = new Map<string, DocHandle<SpaceDoc>>();\n /**\n * If object was requested via loadObjectDocument but root document links weren't updated yet\n * loading will be triggered in onObjectLinksUpdated callback.\n */\n private readonly _objectsPendingDocumentLoad = new Set<string>();\n\n public readonly onObjectDocumentLoaded = new Event<ObjectDocumentLoaded>();\n\n constructor(\n private readonly _spaceId: SpaceId,\n private readonly _repo: Repo,\n /** Legacy Id */\n private readonly _spaceKey: PublicKey,\n ) {}\n\n getAllHandles(): DocHandle<SpaceDoc>[] {\n return this._spaceRootDocHandle != null\n ? [this._spaceRootDocHandle, ...new Set(this._objectDocumentHandles.values())]\n : [];\n }\n\n @trace.span({ showInBrowserTimeline: true })\n public async loadSpaceRootDocHandle(ctx: Context, spaceState: SpaceState): Promise<void> {\n if (this._spaceRootDocHandle != null) {\n return;\n }\n if (!spaceState.rootUrl) {\n log.error('Database opened with no rootUrl', { spaceId: this._spaceId });\n this._createContextBoundSpaceRootDocument(ctx);\n } else {\n const existingDocHandle = await this._initDocHandle(ctx, spaceState.rootUrl);\n const doc = existingDocHandle.docSync();\n invariant(doc);\n if (doc.access == null) {\n this._initDocAccess(existingDocHandle);\n }\n this._spaceRootDocHandle = existingDocHandle;\n }\n }\n\n public loadObjectDocument(objectIdOrMany: string | string[]) {\n const objectIds = Array.isArray(objectIdOrMany) ? objectIdOrMany : [objectIdOrMany];\n let hasUrlsToLoad = false;\n const urlsToLoad: SpaceDoc['links'] = {};\n for (const objectId of objectIds) {\n invariant(this._spaceRootDocHandle);\n if (this._objectDocumentHandles.has(objectId) || this._objectsPendingDocumentLoad.has(objectId)) {\n continue;\n }\n const spaceRootDoc = this._spaceRootDocHandle.docSync();\n invariant(spaceRootDoc);\n const documentUrl = (spaceRootDoc.links ?? {})[objectId];\n if (documentUrl == null) {\n this._objectsPendingDocumentLoad.add(objectId);\n log.info('loading delayed until object links are initialized', { objectId });\n } else {\n urlsToLoad[objectId] = documentUrl;\n hasUrlsToLoad = true;\n }\n }\n if (hasUrlsToLoad) {\n this._loadLinkedObjects(urlsToLoad);\n }\n }\n\n public onObjectLinksUpdated(links: SpaceDocumentLinks) {\n if (!links) {\n return;\n }\n const linksAwaitingLoad = Object.entries(links).filter(([objectId]) =>\n this._objectsPendingDocumentLoad.has(objectId),\n );\n this._loadLinkedObjects(Object.fromEntries(linksAwaitingLoad));\n linksAwaitingLoad.forEach(([objectId]) => this._objectsPendingDocumentLoad.delete(objectId));\n }\n\n public getSpaceRootDocHandle(): DocHandle<SpaceDoc> {\n invariant(this._spaceRootDocHandle);\n return this._spaceRootDocHandle;\n }\n\n public createDocumentForObject(objectId: string): DocHandle<SpaceDoc> {\n invariant(this._spaceRootDocHandle);\n const spaceDocHandle = this._repo.create<SpaceDoc>({\n version: SpaceDocVersion.CURRENT,\n });\n this._initDocAccess(spaceDocHandle);\n this.onObjectBoundToDocument(spaceDocHandle, objectId);\n this._spaceRootDocHandle.change((newDoc: SpaceDoc) => {\n newDoc.links ??= {};\n newDoc.links[objectId] = spaceDocHandle.url;\n });\n return spaceDocHandle;\n }\n\n public onObjectBoundToDocument(handle: DocHandle<SpaceDoc>, objectId: string) {\n this._objectDocumentHandles.set(objectId, handle);\n }\n\n public clearHandleReferences(): string[] {\n const objectsWithHandles = [...this._objectDocumentHandles.keys()];\n this._objectDocumentHandles.clear();\n this._spaceRootDocHandle = null;\n return objectsWithHandles;\n }\n\n private _loadLinkedObjects(links: SpaceDocumentLinks) {\n if (!links) {\n return;\n }\n for (const [objectId, automergeUrl] of Object.entries(links)) {\n const logMeta = { objectId, automergeUrl };\n const objectDocumentHandle = this._objectDocumentHandles.get(objectId);\n if (objectDocumentHandle != null && objectDocumentHandle.url !== automergeUrl) {\n log.warn('object already inlined in a different document, ignoring the link', {\n ...logMeta,\n actualDocumentUrl: objectDocumentHandle.url,\n });\n continue;\n }\n if (objectDocumentHandle?.url === automergeUrl) {\n log.warn('object document was already loaded', logMeta);\n continue;\n }\n const handle = this._repo.find<SpaceDoc>(automergeUrl as DocumentId);\n log.debug('document loading triggered', logMeta);\n this._objectDocumentHandles.set(objectId, handle);\n void this._createObjectOnDocumentLoad(handle, objectId);\n }\n }\n\n private async _initDocHandle(ctx: Context, url: string) {\n const docHandle = this._repo.find<SpaceDoc>(url as DocumentId);\n while (true) {\n try {\n await warnAfterTimeout(5_000, 'Automerge root doc load timeout (CoreDatabase)', async () => {\n await cancelWithContext(ctx, docHandle.whenReady()); // TODO(dmaretskyi): Temporary 5s timeout for debugging.\n });\n break;\n } catch (err) {\n if (`${err}`.includes('Timeout')) {\n log.info('wraparound', { id: docHandle.documentId, state: docHandle.state });\n continue;\n }\n\n throw err;\n }\n }\n\n if (docHandle.state === 'unavailable') {\n throw new Error('Automerge document is unavailable');\n }\n\n return docHandle;\n }\n\n private _createContextBoundSpaceRootDocument(ctx: Context) {\n const docHandle = this._repo.create<SpaceDoc>();\n this._spaceRootDocHandle = docHandle;\n ctx.onDispose(() => {\n docHandle.delete();\n this._spaceRootDocHandle = null;\n });\n }\n\n private _initDocAccess(handle: DocHandle<SpaceDoc>) {\n handle.change((newDoc: SpaceDoc) => {\n newDoc.access ??= { spaceKey: this._spaceKey.toHex() };\n newDoc.access.spaceKey = this._spaceKey.toHex();\n });\n }\n\n private async _createObjectOnDocumentLoad(handle: DocHandle<SpaceDoc>, objectId: string) {\n try {\n await handle.doc(['ready']);\n const logMeta = { objectId, docUrl: handle.url };\n if (this.onObjectDocumentLoaded.listenerCount() === 0) {\n log.info('document loaded after all listeners were removed', logMeta);\n return;\n }\n const objectDocHandle = this._objectDocumentHandles.get(objectId);\n if (objectDocHandle?.url !== handle.url) {\n log.warn('object was rebound while a document was loading, discarding handle', logMeta);\n return;\n }\n this.onObjectDocumentLoaded.emit({ handle, objectId });\n } catch (err) {\n const shouldRetryLoading = this.onObjectDocumentLoaded.listenerCount() > 0;\n log.warn('failed to load a document', {\n objectId,\n automergeUrl: handle.url,\n retryLoading: shouldRetryLoading,\n err,\n });\n if (shouldRetryLoading) {\n await this._createObjectOnDocumentLoad(handle, objectId);\n }\n }\n }\n}\n\nexport interface ObjectDocumentLoaded {\n handle: DocHandle<SpaceDoc>;\n objectId: string;\n}\n\nexport interface DocumentChanges {\n createdObjectIds: string[];\n updatedObjectIds: string[];\n objectsToRebind: string[];\n linkedDocuments: {\n [echoId: string]: AutomergeUrl;\n };\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Message, cbor } from '@dxos/automerge/automerge-repo';\nimport { Resource } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { AutomergeReplicator } from '@dxos/teleport-extension-automerge-replicator';\nimport { ComplexMap, ComplexSet, defaultMap } from '@dxos/util';\n\nimport {\n type EchoReplicator,\n type EchoReplicatorContext,\n type ReplicatorConnection,\n type ShouldAdvertizeParams,\n} from './echo-replicator';\n\n// TODO(dmaretskyi): Move out of @dxos/echo-pipeline.\n\n/**\n * Used to replicate with other peers over the network.\n */\nexport class MeshEchoReplicator implements EchoReplicator {\n private readonly _connections = new Set<MeshReplicatorConnection>();\n /**\n * Using automerge peerId as a key.\n */\n private readonly _connectionsPerPeer = new Map<string, MeshReplicatorConnection>();\n\n /**\n * spaceKey -> deviceKey[]\n */\n private readonly _authorizedDevices = new ComplexMap<PublicKey, ComplexSet<PublicKey>>(PublicKey.hash);\n\n private _context: EchoReplicatorContext | null = null;\n\n async connect(context: EchoReplicatorContext): Promise<void> {\n this._context = context;\n }\n\n async disconnect() {\n for (const connection of this._connections) {\n await connection.close();\n }\n this._connections.clear();\n this._connectionsPerPeer.clear();\n\n this._context = null;\n }\n\n createExtension(): AutomergeReplicator {\n invariant(this._context);\n\n const connection: MeshReplicatorConnection = new MeshReplicatorConnection({\n ownPeerId: this._context.peerId,\n onRemoteConnected: async () => {\n log('onRemoteConnected', { peerId: connection.peerId });\n invariant(this._context);\n\n if (this._connectionsPerPeer.has(connection.peerId)) {\n this._context.onConnectionAuthScopeChanged(connection);\n } else {\n this._connectionsPerPeer.set(connection.peerId, connection);\n await connection.enable();\n this._context.onConnectionOpen(connection);\n }\n },\n onRemoteDisconnected: async () => {\n log('onRemoteDisconnected', { peerId: connection.peerId });\n this._context?.onConnectionClosed(connection);\n await connection.disable();\n this._connectionsPerPeer.delete(connection.peerId);\n this._connections.delete(connection);\n },\n shouldAdvertize: async (params: ShouldAdvertizeParams) => {\n log('shouldAdvertize', { peerId: connection.peerId, documentId: params.documentId });\n invariant(this._context);\n try {\n const spaceKey = await this._context.getContainingSpaceForDocument(params.documentId);\n if (!spaceKey) {\n log('space key not found for share policy check', {\n peerId: connection.peerId,\n documentId: params.documentId,\n });\n return false;\n }\n\n const authorizedDevices = this._authorizedDevices.get(spaceKey);\n\n if (!connection.remoteDeviceKey) {\n log('device key not found for share policy check', {\n peerId: connection.peerId,\n documentId: params.documentId,\n });\n return false;\n }\n\n const isAuthorized = authorizedDevices?.has(connection.remoteDeviceKey) ?? false;\n log('share policy check', {\n localPeer: this._context.peerId,\n remotePeer: connection.peerId,\n documentId: params.documentId,\n deviceKey: connection.remoteDeviceKey,\n spaceKey,\n isAuthorized,\n });\n return isAuthorized;\n } catch (err) {\n log.catch(err);\n return false;\n }\n },\n });\n this._connections.add(connection);\n\n return connection.replicatorExtension;\n }\n\n authorizeDevice(spaceKey: PublicKey, deviceKey: PublicKey) {\n log('authorizeDevice', { spaceKey, deviceKey });\n defaultMap(this._authorizedDevices, spaceKey, () => new ComplexSet(PublicKey.hash)).add(deviceKey);\n for (const connection of this._connections) {\n if (connection.remoteDeviceKey && connection.remoteDeviceKey.equals(deviceKey)) {\n this._context?.onConnectionAuthScopeChanged(connection);\n }\n }\n }\n}\n\ntype MeshReplicatorConnectionParams = {\n ownPeerId: string;\n onRemoteConnected: () => Promise<void>;\n onRemoteDisconnected: () => Promise<void>;\n shouldAdvertize: (params: ShouldAdvertizeParams) => Promise<boolean>;\n};\n\nclass MeshReplicatorConnection extends Resource implements ReplicatorConnection {\n public readable: ReadableStream<Message>;\n public writable: WritableStream<Message>;\n public remoteDeviceKey: PublicKey | null = null;\n\n public readonly replicatorExtension: AutomergeReplicator;\n\n private _remotePeerId: string | null = null;\n private _isEnabled = false;\n\n constructor(private readonly _params: MeshReplicatorConnectionParams) {\n super();\n\n let readableStreamController!: ReadableStreamDefaultController<Message>;\n this.readable = new ReadableStream<Message>({\n start: (controller) => {\n readableStreamController = controller;\n this._ctx.onDispose(() => controller.close());\n },\n });\n\n this.writable = new WritableStream<Message>({\n write: async (message: Message, controller) => {\n // TODO(dmaretskyi): Show we block on RPC completing here?\n this.replicatorExtension.sendSyncMessage({ payload: cbor.encode(message) }).catch((err) => {\n controller.error(err);\n });\n },\n });\n\n this.replicatorExtension = new AutomergeReplicator(\n {\n peerId: this._params.ownPeerId,\n },\n {\n onStartReplication: async (info, remotePeerId /** Teleport ID */) => {\n // Note: We store only one extension per peer.\n // There can be a case where two connected peers have more than one teleport connection between them\n // and each of them uses different teleport connections to send messages.\n // It works because we receive messages from all teleport connections and Automerge Repo dedup them.\n // TODO(mykola): Use only one teleport connection per peer.\n\n // TODO(dmaretskyi): Critical bug.\n // - two peers get connected via swarm 1\n // - they get connected via swarm 2\n // - swarm 1 gets disconnected\n // - automerge repo thinks that peer 2 got disconnected even though swarm 2 is still active\n\n this.remoteDeviceKey = remotePeerId;\n\n // Set automerge id.\n this._remotePeerId = info.id;\n\n log('onStartReplication', { id: info.id, thisPeerId: this.peerId, remotePeerId: remotePeerId.toHex() });\n\n await this._params.onRemoteConnected();\n },\n onSyncMessage: async ({ payload }) => {\n if (!this._isEnabled) {\n return;\n }\n const message = cbor.decode(payload) as Message;\n // Note: automerge Repo dedup messages.\n readableStreamController.enqueue(message);\n },\n onClose: async () => {\n if (!this._isEnabled) {\n return;\n }\n await this._params.onRemoteDisconnected();\n },\n },\n );\n }\n\n get peerId(): string {\n invariant(this._remotePeerId != null, 'Remote peer has not connected yet.');\n return this._remotePeerId;\n }\n\n async shouldAdvertize(params: ShouldAdvertizeParams): Promise<boolean> {\n return this._params.shouldAdvertize(params);\n }\n\n /**\n * Start exchanging messages with the remote peer.\n * Call after the remote peer has connected.\n */\n async enable() {\n invariant(this._remotePeerId != null, 'Remote peer has not connected yet.');\n this._isEnabled = true;\n }\n\n /**\n * Stop exchanging messages with the remote peer.\n */\n async disable() {\n this._isEnabled = false;\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["Event", "next", "automerge", "getBackend", "getHeads", "Repo", "Context", "invariant", "PublicKey", "objectPointerCodec", "trace", "mapValues", "Trigger", "synchronized", "NetworkAdapter", "LifecycleState", "invariant", "log", "EchoNetworkAdapter", "constructor", "_params", "_replicators", "Set", "_connections", "Map", "_lifecycleState", "CLOSED", "_connected", "connect", "peerId", "peerMetadata", "wake", "send", "message", "connectionEntry", "get", "targetId", "Error", "writer", "write", "catch", "err", "isOpen", "disconnect", "open", "OPEN", "emit", "network", "close", "replicator", "clear", "whenConnected", "wait", "timeout", "addReplicator", "has", "add", "onConnectionOpen", "_onConnectionOpen", "bind", "onConnectionClosed", "_onConnectionClosed", "onConnectionAuthScopeChanged", "_onConnectionAuthScopeChanged", "getContainingSpaceForDocument", "removeReplicator", "delete", "shouldAdvertize", "params", "connection", "reader", "readable", "getReader", "writable", "getWriter", "set", "queueMicrotask", "done", "value", "read", "_emitPeerCandidate", "entry", "cancel", "abort", "dxos_peerSource", "LifecycleState", "Resource", "LevelDBStorageAdapter", "Resource", "constructor", "_params", "load", "keyArray", "_lifecycleState", "LifecycleState", "OPEN", "undefined", "db", "get", "encodingOptions", "err", "isLevelDbNotFoundError", "save", "binary", "batch", "callbacks", "beforeSave", "path", "put", "Buffer", "from", "write", "afterSave", "remove", "del", "loadRange", "keyPrefix", "result", "key", "value", "iterator", "gte", "lte", "push", "data", "removeRange", "keyEncoder", "encode", "map", "k", "replaceAll", "join", "decode", "toString", "split", "format", "keyEncoding", "valueEncoding", "code", "Trigger", "NetworkAdapter", "cbor", "Stream", "invariant", "LocalHostNetworkAdapter", "_peers", "Map", "_connected", "_isConnected", "ready", "emit", "network", "connect", "peerId", "wake", "send", "message", "peer", "get", "targetId", "close", "forEach", "disconnect", "whenConnected", "wait", "timeout", "syncRepo", "id", "syncMessage", "_getPeerId", "next", "has", "set", "connected", "encode", "delete", "peerMetadata", "sendSyncMessage", "decode", "getHostInfo", "AutomergeHost", "constructor", "db", "indexMetadataStore", "_ctx", "Context", "_echoNetworkAdapter", "EchoNetworkAdapter", "getContainingSpaceForDocument", "_getContainingSpaceForDocument", "bind", "_storage", "LevelDBStorageAdapter", "callbacks", "beforeSave", "params", "_beforeSave", "afterSave", "_afterSave", "_indexMetadataStore", "open", "_peerId", "PublicKey", "random", "toHex", "_clientNetwork", "LocalHostNetworkAdapter", "_repo", "Repo", "peerId", "sharePolicy", "_sharePolicy", "storage", "network", "ready", "whenConnected", "close", "dispose", "repo", "addReplicator", "replicator", "removeReplicator", "documentId", "startsWith", "
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Event } from '@dxos/async';\nimport { next as automerge, getBackend, getHeads, type Doc, type Heads } from '@dxos/automerge/automerge';\nimport {\n Repo,\n type DocHandle,\n type DocHandleChangePayload,\n type DocumentId,\n type PeerId,\n type StorageAdapterInterface,\n} from '@dxos/automerge/automerge-repo';\nimport { type Stream } from '@dxos/codec-protobuf';\nimport { Context, type Lifecycle } from '@dxos/context';\nimport { type SpaceDoc } from '@dxos/echo-protocol';\nimport { type IndexMetadataStore } from '@dxos/indexing';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { type SublevelDB } from '@dxos/kv-store';\nimport { log } from '@dxos/log';\nimport { objectPointerCodec } from '@dxos/protocols';\nimport {\n type FlushRequest,\n type HostInfo,\n type SyncRepoRequest,\n type SyncRepoResponse,\n} from '@dxos/protocols/proto/dxos/echo/service';\nimport { trace } from '@dxos/tracing';\nimport { mapValues } from '@dxos/util';\n\nimport { EchoNetworkAdapter } from './echo-network-adapter';\nimport { type EchoReplicator } from './echo-replicator';\nimport { LevelDBStorageAdapter, type BeforeSaveParams } from './leveldb-storage-adapter';\nimport { LocalHostNetworkAdapter } from './local-host-network-adapter';\n\n// TODO: Remove\nexport type { DocumentId };\n\nexport type AutomergeHostParams = {\n db: SublevelDB;\n\n indexMetadataStore: IndexMetadataStore;\n};\n\n@trace.resource()\nexport class AutomergeHost {\n private readonly _indexMetadataStore: IndexMetadataStore;\n private readonly _ctx = new Context();\n private readonly _echoNetworkAdapter = new EchoNetworkAdapter({\n getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this),\n });\n\n private _repo!: Repo;\n private _clientNetwork!: LocalHostNetworkAdapter;\n private _storage!: StorageAdapterInterface & Lifecycle;\n\n @trace.info()\n private _peerId!: string;\n\n public _requestedDocs = new Set<string>();\n\n constructor({ db, indexMetadataStore }: AutomergeHostParams) {\n this._storage = new LevelDBStorageAdapter({\n db,\n callbacks: {\n beforeSave: async (params) => this._beforeSave(params),\n afterSave: async () => this._afterSave(),\n },\n });\n this._indexMetadataStore = indexMetadataStore;\n }\n\n async open() {\n // TODO(burdon): Should this be stable?\n this._peerId = `host-${PublicKey.random().toHex()}` as PeerId;\n\n await this._storage.open?.();\n this._clientNetwork = new LocalHostNetworkAdapter();\n\n // Construct the automerge repo.\n this._repo = new Repo({\n peerId: this._peerId as PeerId,\n sharePolicy: this._sharePolicy.bind(this),\n storage: this._storage,\n network: [\n // Downstream client.\n this._clientNetwork,\n // Upstream swarm.\n this._echoNetworkAdapter,\n ],\n });\n\n this._clientNetwork.ready();\n await this._echoNetworkAdapter.open();\n await this._clientNetwork.whenConnected();\n await this._echoNetworkAdapter.whenConnected();\n }\n\n async close() {\n await this._storage.close?.();\n await this._clientNetwork.close();\n await this._echoNetworkAdapter.close();\n await this._ctx.dispose();\n }\n\n get repo(): Repo {\n return this._repo;\n }\n\n async addReplicator(replicator: EchoReplicator) {\n await this._echoNetworkAdapter.addReplicator(replicator);\n }\n\n async removeReplicator(replicator: EchoReplicator) {\n await this._echoNetworkAdapter.removeReplicator(replicator);\n }\n\n // TODO(dmaretskyi): Share based on HALO permissions and space affinity.\n // Hosts, running in the worker, don't share documents unless requested by other peers.\n // NOTE: If both peers return sharePolicy=false the replication will not happen\n // https://github.com/automerge/automerge-repo/pull/292\n private async _sharePolicy(\n peerId: PeerId /* device key */,\n documentId?: DocumentId /* space key */,\n ): Promise<boolean> {\n if (peerId.startsWith('client-')) {\n return false; // Only send docs to clients if they are requested.\n }\n\n if (!documentId) {\n return false;\n }\n\n // Workaround for https://github.com/automerge/automerge-repo/pull/292\n // NOTE: This must override the per-connection policy.\n const doc = this._repo.handles[documentId]?.docSync();\n if (!doc) {\n // TODO(dmaretskyi): Verify that this works as intended.\n // TODO(dmaretskyi): Move to MESH replicator?\n const isRequested = this._requestedDocs.has(`automerge:${documentId}`);\n log('doc share policy check', { peerId, documentId, isRequested });\n return isRequested;\n }\n\n const peerMetadata = this.repo.peerMetadataByPeerId[peerId];\n if ((peerMetadata as any)?.dxos_peerSource === 'EchoNetworkAdapter') {\n return this._echoNetworkAdapter.shouldAdvertize(peerId, { documentId });\n }\n\n return false;\n }\n\n private async _beforeSave({ path, batch }: BeforeSaveParams) {\n const handle = this._repo.handles[path[0] as DocumentId];\n if (!handle) {\n return;\n }\n const doc = handle.docSync();\n if (!doc) {\n return;\n }\n\n const spaceKey = getSpaceKeyFromDoc(doc) ?? undefined;\n\n const lastAvailableHash = getHeads(doc);\n\n const objectIds = Object.keys(doc.objects ?? {});\n const encodedIds = objectIds.map((objectId) =>\n objectPointerCodec.encode({ documentId: handle.documentId, objectId, spaceKey }),\n );\n const idToLastHash = new Map(encodedIds.map((id) => [id, lastAvailableHash]));\n this._indexMetadataStore.markDirty(idToLastHash, batch);\n }\n\n /**\n * Called by AutomergeStorageAdapter after levelDB batch commit.\n */\n private async _afterSave() {\n this._indexMetadataStore.notifyMarkedDirty();\n }\n\n @trace.info({ depth: null })\n private _automergeDocs() {\n return mapValues(this._repo.handles, (handle) => ({\n state: handle.state,\n hasDoc: !!handle.docSync(),\n heads: handle.docSync() ? automerge.getHeads(handle.docSync()) : null,\n data:\n handle.docSync() &&\n mapValues(handle.docSync(), (value, key) => {\n try {\n switch (key) {\n case 'access':\n case 'links':\n return value;\n case 'objects':\n return Object.keys(value as any);\n default:\n return `${value}`;\n }\n } catch (err) {\n return `${err}`;\n }\n }),\n }));\n }\n\n @trace.info({ depth: null })\n private _automergePeers() {\n return this._repo.peers;\n }\n\n private async _getContainingSpaceForDocument(documentId: string): Promise<PublicKey | null> {\n const doc = this._repo.handles[documentId as any]?.docSync();\n if (!doc) {\n return null;\n }\n\n const spaceKeyHex = getSpaceKeyFromDoc(doc);\n if (!spaceKeyHex) {\n return null;\n }\n\n return PublicKey.from(spaceKeyHex);\n }\n\n //\n // Methods for client-services.\n //\n @trace.span({ showInBrowserTimeline: true })\n async flush({ states }: FlushRequest): Promise<void> {\n // Note: Wait for all requested documents to be loaded/synced from thin-client.\n await Promise.all(\n states?.map(async ({ heads, documentId }) => {\n invariant(heads, 'heads are required for flush');\n const handle = this.repo.handles[documentId as DocumentId] ?? this._repo.find(documentId as DocumentId);\n await waitForHeads(handle, heads);\n }) ?? [],\n );\n\n await this._repo.flush(states?.map(({ documentId }) => documentId as DocumentId));\n }\n\n syncRepo(request: SyncRepoRequest): Stream<SyncRepoResponse> {\n return this._clientNetwork.syncRepo(request);\n }\n\n sendSyncMessage(request: SyncRepoRequest): Promise<void> {\n return this._clientNetwork.sendSyncMessage(request);\n }\n\n async getHostInfo(): Promise<HostInfo> {\n return this._clientNetwork.getHostInfo();\n }\n}\n\nexport const getSpaceKeyFromDoc = (doc: any): string | null => {\n // experimental_spaceKey is set on old documents, new ones are created with doc.access.spaceKey\n const rawSpaceKey = doc.access?.spaceKey ?? doc.experimental_spaceKey;\n if (rawSpaceKey == null) {\n return null;\n }\n\n return String(rawSpaceKey);\n};\n\nconst waitForHeads = async (handle: DocHandle<SpaceDoc>, heads: Heads) => {\n await handle.whenReady();\n const unavailableHeads = new Set(heads);\n\n await Event.wrap<DocHandleChangePayload<SpaceDoc>>(handle, 'change').waitForCondition(() => {\n // Check if unavailable heads became available.\n for (const changeHash of unavailableHeads.values()) {\n if (changeIsPresentInDoc(handle.docSync(), changeHash)) {\n unavailableHeads.delete(changeHash);\n }\n }\n\n if (unavailableHeads.size === 0) {\n return true;\n }\n return false;\n });\n};\n\nconst changeIsPresentInDoc = (doc: Doc<any>, changeHash: string): boolean => {\n return !!getBackend(doc).getChangeByHash(changeHash);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { Trigger, synchronized } from '@dxos/async';\nimport { type Message, NetworkAdapter, type PeerId, type PeerMetadata } from '@dxos/automerge/automerge-repo';\nimport { LifecycleState } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { type PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\n\nimport { type EchoReplicator, type ReplicatorConnection, type ShouldAdvertizeParams } from './echo-replicator';\n\nexport type EchoNetworkAdapterParams = {\n getContainingSpaceForDocument: (documentId: string) => Promise<PublicKey | null>;\n};\n\n/**\n * Manages a set of {@link EchoReplicator} instances.\n */\nexport class EchoNetworkAdapter extends NetworkAdapter {\n private readonly _replicators = new Set<EchoReplicator>();\n /**\n * Remote peer id -> connection.\n */\n private readonly _connections = new Map<PeerId, ConnectionEntry>();\n private _lifecycleState: LifecycleState = LifecycleState.CLOSED;\n private readonly _connected = new Trigger();\n\n constructor(private readonly _params: EchoNetworkAdapterParams) {\n super();\n }\n\n override connect(peerId: PeerId, peerMetadata?: PeerMetadata | undefined): void {\n this.peerId = peerId;\n this.peerMetadata = peerMetadata;\n this._connected.wake();\n }\n\n override send(message: Message): void {\n const connectionEntry = this._connections.get(message.targetId);\n if (!connectionEntry) {\n throw new Error('Connection not found.');\n }\n\n // TODO(dmaretskyi): Find a way to enforce backpressure on AM-repo.\n connectionEntry.writer.write(message).catch((err) => {\n if (connectionEntry.isOpen) {\n log.catch(err);\n }\n });\n }\n\n override disconnect(): void {\n // No-op\n }\n\n @synchronized\n async open() {\n invariant(this._lifecycleState === LifecycleState.CLOSED);\n this._lifecycleState = LifecycleState.OPEN;\n\n log('emit ready');\n this.emit('ready', {\n network: this,\n });\n }\n\n @synchronized\n async close() {\n invariant(this._lifecycleState === LifecycleState.OPEN);\n\n for (const replicator of this._replicators) {\n await replicator.disconnect();\n }\n this._replicators.clear();\n\n this._lifecycleState = LifecycleState.CLOSED;\n }\n\n async whenConnected() {\n await this._connected.wait({ timeout: 10_000 });\n }\n\n @synchronized\n async addReplicator(replicator: EchoReplicator) {\n invariant(this._lifecycleState === LifecycleState.OPEN);\n invariant(this.peerId);\n invariant(!this._replicators.has(replicator));\n\n this._replicators.add(replicator);\n await replicator.connect({\n peerId: this.peerId,\n onConnectionOpen: this._onConnectionOpen.bind(this),\n onConnectionClosed: this._onConnectionClosed.bind(this),\n onConnectionAuthScopeChanged: this._onConnectionAuthScopeChanged.bind(this),\n getContainingSpaceForDocument: this._params.getContainingSpaceForDocument,\n });\n }\n\n @synchronized\n async removeReplicator(replicator: EchoReplicator) {\n invariant(this._lifecycleState === LifecycleState.OPEN);\n invariant(this._replicators.has(replicator));\n await replicator.disconnect();\n this._replicators.delete(replicator);\n }\n\n async shouldAdvertize(peerId: PeerId, params: ShouldAdvertizeParams): Promise<boolean> {\n const connection = this._connections.get(peerId);\n if (!connection) {\n return false;\n }\n\n return connection.connection.shouldAdvertize(params);\n }\n\n private _onConnectionOpen(connection: ReplicatorConnection) {\n log('Connection opened', { peerId: connection.peerId });\n invariant(!this._connections.has(connection.peerId as PeerId));\n const reader = connection.readable.getReader();\n const writer = connection.writable.getWriter();\n const connectionEntry: ConnectionEntry = { connection, reader, writer, isOpen: true };\n this._connections.set(connection.peerId as PeerId, connectionEntry);\n\n queueMicrotask(async () => {\n try {\n while (true) {\n // TODO(dmaretskyi): Find a way to enforce backpressure on AM-repo.\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n this.emit('message', value);\n }\n } catch (err) {\n if (connectionEntry.isOpen) {\n log.catch(err);\n }\n }\n });\n\n log('emit peer-candidate', { peerId: connection.peerId });\n this._emitPeerCandidate(connection);\n }\n\n /**\n * Trigger doc-synchronizer shared documents set recalculation. Happens on peer-candidate.\n * TODO(y): replace with a proper API call when sharePolicy update becomes supported by automerge-repo\n */\n private _onConnectionAuthScopeChanged(connection: ReplicatorConnection) {\n log('Connection auth scope changed', { peerId: connection.peerId });\n const entry = this._connections.get(connection.peerId as PeerId);\n invariant(entry);\n this.emit('peer-disconnected', { peerId: connection.peerId as PeerId });\n this._emitPeerCandidate(connection);\n }\n\n private _onConnectionClosed(connection: ReplicatorConnection) {\n log('Connection closed', { peerId: connection.peerId });\n const entry = this._connections.get(connection.peerId as PeerId);\n invariant(entry);\n\n entry.isOpen = false;\n this.emit('peer-disconnected', { peerId: connection.peerId as PeerId });\n\n void entry.reader.cancel().catch((err) => log.catch(err));\n void entry.writer.abort().catch((err) => log.catch(err));\n\n this._connections.delete(connection.peerId as PeerId);\n }\n\n private _emitPeerCandidate(connection: ReplicatorConnection) {\n this.emit('peer-candidate', {\n peerId: connection.peerId as PeerId,\n peerMetadata: {\n // TODO(dmaretskyi): Refactor this.\n dxos_peerSource: 'EchoNetworkAdapter',\n } as any,\n });\n }\n}\n\ntype ConnectionEntry = {\n connection: ReplicatorConnection;\n reader: ReadableStreamDefaultReader<Message>;\n writer: WritableStreamDefaultWriter<Message>;\n isOpen: boolean;\n};\n", "//\n// Copyright 2024 DXOS.org\n// s\n\nimport { type MixedEncoding } from 'level-transcoder';\n\nimport { type StorageAdapterInterface, type Chunk, type StorageKey } from '@dxos/automerge/automerge-repo';\nimport { LifecycleState, Resource } from '@dxos/context';\nimport { type BatchLevel, type SublevelDB } from '@dxos/kv-store';\nimport { type MaybePromise } from '@dxos/util';\n\nexport type LevelDBStorageAdapterParams = {\n db: SublevelDB;\n callbacks?: StorageCallbacks;\n};\n\nexport type BeforeSaveParams = { path: StorageKey; batch: BatchLevel };\n\nexport interface StorageCallbacks {\n beforeSave(params: BeforeSaveParams): MaybePromise<void>;\n afterSave(path: StorageKey): MaybePromise<void>;\n}\n\nexport class LevelDBStorageAdapter extends Resource implements StorageAdapterInterface {\n constructor(private readonly _params: LevelDBStorageAdapterParams) {\n super();\n }\n\n async load(keyArray: StorageKey): Promise<Uint8Array | undefined> {\n try {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n // TODO(mykola): this should be an error.\n return undefined;\n }\n return await this._params.db.get<StorageKey, Uint8Array>(keyArray, { ...encodingOptions });\n } catch (err: any) {\n if (isLevelDbNotFoundError(err)) {\n return undefined;\n }\n throw err;\n }\n }\n\n async save(keyArray: StorageKey, binary: Uint8Array): Promise<void> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return undefined;\n }\n const batch = this._params.db.batch();\n\n await this._params.callbacks?.beforeSave?.({ path: keyArray, batch });\n batch.put<StorageKey, Uint8Array>(keyArray, Buffer.from(binary), {\n ...encodingOptions,\n });\n await batch.write();\n\n await this._params.callbacks?.afterSave?.(keyArray);\n }\n\n async remove(keyArray: StorageKey): Promise<void> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return undefined;\n }\n await this._params.db.del<StorageKey>(keyArray, { ...encodingOptions });\n }\n\n async loadRange(keyPrefix: StorageKey): Promise<Chunk[]> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return [];\n }\n const result: Chunk[] = [];\n for await (const [key, value] of this._params.db.iterator<StorageKey, Uint8Array>({\n gte: keyPrefix,\n lte: [...keyPrefix, '\\uffff'],\n ...encodingOptions,\n })) {\n result.push({\n key,\n data: value,\n });\n }\n return result;\n }\n\n async removeRange(keyPrefix: StorageKey): Promise<void> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return undefined;\n }\n const batch = this._params.db.batch();\n\n for await (const [key] of this._params.db.iterator<StorageKey, Uint8Array>({\n gte: keyPrefix,\n lte: [...keyPrefix, '\\uffff'],\n ...encodingOptions,\n })) {\n batch.del<StorageKey>(key, { ...encodingOptions });\n }\n await batch.write();\n }\n}\n\nconst keyEncoder: MixedEncoding<StorageKey, Uint8Array, StorageKey> = {\n encode: (key: StorageKey): Uint8Array =>\n Buffer.from(key.map((k) => k.replaceAll('%', '%25').replaceAll('-', '%2D')).join('-')),\n decode: (key: Uint8Array): StorageKey =>\n Buffer.from(key)\n .toString()\n .split('-')\n .map((k) => k.replaceAll('%2D', '-').replaceAll('%25', '%')),\n format: 'buffer',\n};\n\nexport const encodingOptions = {\n keyEncoding: keyEncoder,\n valueEncoding: 'buffer',\n};\n\nconst isLevelDbNotFoundError = (err: any): boolean => err.code === 'LEVEL_NOT_FOUND';\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { Trigger } from '@dxos/async';\nimport { NetworkAdapter, type Message, type PeerId, cbor } from '@dxos/automerge/automerge-repo';\nimport { Stream } from '@dxos/codec-protobuf';\nimport { invariant } from '@dxos/invariant';\nimport { type HostInfo, type SyncRepoRequest, type SyncRepoResponse } from '@dxos/protocols/proto/dxos/echo/service';\n\ntype ClientSyncState = {\n connected: boolean;\n send: (message: Message) => void;\n disconnect: () => void;\n};\n\n/**\n * Used to replicate with apps running on the same device.\n */\nexport class LocalHostNetworkAdapter extends NetworkAdapter {\n private readonly _peers: Map<PeerId, ClientSyncState> = new Map();\n\n /**\n * Emits `ready` event. That signals to `Repo` that it can start using the adapter.\n */\n ready() {\n // NOTE: Emitting `ready` event in NetworkAdapter`s constructor causes a race condition\n // because `Repo` waits for `ready` event (which it never receives) before it starts using the adapter.\n this.emit('ready', {\n network: this,\n });\n }\n\n private readonly _connected = new Trigger();\n private _isConnected: boolean = false;\n\n /**\n * Called by `Repo` to connect to the network.\n *\n * @param peerId Our peer Id.\n */\n override connect(peerId: PeerId): void {\n this.peerId = peerId;\n this._isConnected = true;\n this._connected.wake();\n // No-op. Client always connects first\n }\n\n override send(message: Message): void {\n const peer = this._peers.get(message.targetId);\n invariant(peer, 'Peer not found.');\n peer.send(message);\n }\n\n async close() {\n this._peers.forEach((peer) => peer.disconnect());\n this.emit('close');\n }\n\n override disconnect(): void {\n // TODO(mykola): `disconnect` is not used anywhere in `Repo` from `@automerge/automerge-repo`. Should we remove it?\n // No-op\n }\n\n async whenConnected(): Promise<void> {\n await this._connected.wait({ timeout: 10_000 });\n }\n\n syncRepo({ id, syncMessage }: SyncRepoRequest): Stream<SyncRepoResponse> {\n const peerId = this._getPeerId(id);\n\n return new Stream(({ next, close }) => {\n invariant(!this._peers.has(peerId), 'Peer already connected.');\n this._peers.set(peerId, {\n connected: true,\n send: (message) => {\n next({\n syncMessage: cbor.encode(message),\n });\n },\n disconnect: () => {\n this._peers.delete(peerId);\n close();\n this.emit('peer-disconnected', {\n peerId,\n });\n },\n });\n\n invariant(this._isConnected);\n this.emit('peer-candidate', {\n peerMetadata: {},\n peerId,\n });\n });\n }\n\n async sendSyncMessage({ id, syncMessage }: SyncRepoRequest): Promise<void> {\n invariant(this._isConnected);\n const message = cbor.decode(syncMessage!) as Message;\n this.emit('message', message);\n }\n\n async getHostInfo(): Promise<HostInfo> {\n invariant(this._isConnected);\n invariant(this.peerId, 'Peer id not set.');\n return {\n peerId: this.peerId,\n };\n }\n\n private _getPeerId(id: string): PeerId {\n return id as PeerId;\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { Event } from '@dxos/async';\nimport { type DocHandle, type AutomergeUrl, type DocumentId, type Repo } from '@dxos/automerge/automerge-repo';\nimport { cancelWithContext, type Context } from '@dxos/context';\nimport { warnAfterTimeout } from '@dxos/debug';\nimport { type SpaceState, type SpaceDoc, SpaceDocVersion } from '@dxos/echo-protocol';\nimport { invariant } from '@dxos/invariant';\nimport { type PublicKey, type SpaceId } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { trace } from '@dxos/tracing';\n\ntype SpaceDocumentLinks = SpaceDoc['links'];\n\nexport interface AutomergeDocumentLoader {\n onObjectDocumentLoaded: Event<ObjectDocumentLoaded>;\n\n getAllHandles(): DocHandle<SpaceDoc>[];\n\n loadSpaceRootDocHandle(ctx: Context, spaceState: SpaceState): Promise<void>;\n loadObjectDocument(objectId: string | string[]): void;\n getSpaceRootDocHandle(): DocHandle<SpaceDoc>;\n createDocumentForObject(objectId: string): DocHandle<SpaceDoc>;\n onObjectLinksUpdated(links: SpaceDocumentLinks): void;\n onObjectBoundToDocument(handle: DocHandle<SpaceDoc>, objectId: string): void;\n\n /**\n * @returns objectIds for which we had document handles or were loading one.\n */\n clearHandleReferences(): string[];\n}\n\n/**\n * Manages object <-> docHandle binding and automerge document loading.\n */\n@trace.resource()\nexport class AutomergeDocumentLoaderImpl implements AutomergeDocumentLoader {\n private _spaceRootDocHandle: DocHandle<SpaceDoc> | null = null;\n /**\n * An object id pointer to a handle of the document where the object is stored inline.\n */\n private readonly _objectDocumentHandles = new Map<string, DocHandle<SpaceDoc>>();\n /**\n * If object was requested via loadObjectDocument but root document links weren't updated yet\n * loading will be triggered in onObjectLinksUpdated callback.\n */\n private readonly _objectsPendingDocumentLoad = new Set<string>();\n\n public readonly onObjectDocumentLoaded = new Event<ObjectDocumentLoaded>();\n\n constructor(\n private readonly _spaceId: SpaceId,\n private readonly _repo: Repo,\n /** Legacy Id */\n private readonly _spaceKey: PublicKey,\n ) {}\n\n getAllHandles(): DocHandle<SpaceDoc>[] {\n return this._spaceRootDocHandle != null\n ? [this._spaceRootDocHandle, ...new Set(this._objectDocumentHandles.values())]\n : [];\n }\n\n @trace.span({ showInBrowserTimeline: true })\n public async loadSpaceRootDocHandle(ctx: Context, spaceState: SpaceState): Promise<void> {\n if (this._spaceRootDocHandle != null) {\n return;\n }\n if (!spaceState.rootUrl) {\n log.error('Database opened with no rootUrl', { spaceId: this._spaceId });\n this._createContextBoundSpaceRootDocument(ctx);\n } else {\n const existingDocHandle = await this._initDocHandle(ctx, spaceState.rootUrl);\n const doc = existingDocHandle.docSync();\n invariant(doc);\n if (doc.access == null) {\n this._initDocAccess(existingDocHandle);\n }\n this._spaceRootDocHandle = existingDocHandle;\n }\n }\n\n public loadObjectDocument(objectIdOrMany: string | string[]) {\n const objectIds = Array.isArray(objectIdOrMany) ? objectIdOrMany : [objectIdOrMany];\n let hasUrlsToLoad = false;\n const urlsToLoad: SpaceDoc['links'] = {};\n for (const objectId of objectIds) {\n invariant(this._spaceRootDocHandle);\n if (this._objectDocumentHandles.has(objectId) || this._objectsPendingDocumentLoad.has(objectId)) {\n continue;\n }\n const spaceRootDoc = this._spaceRootDocHandle.docSync();\n invariant(spaceRootDoc);\n const documentUrl = (spaceRootDoc.links ?? {})[objectId];\n if (documentUrl == null) {\n this._objectsPendingDocumentLoad.add(objectId);\n log.info('loading delayed until object links are initialized', { objectId });\n } else {\n urlsToLoad[objectId] = documentUrl;\n hasUrlsToLoad = true;\n }\n }\n if (hasUrlsToLoad) {\n this._loadLinkedObjects(urlsToLoad);\n }\n }\n\n public onObjectLinksUpdated(links: SpaceDocumentLinks) {\n if (!links) {\n return;\n }\n const linksAwaitingLoad = Object.entries(links).filter(([objectId]) =>\n this._objectsPendingDocumentLoad.has(objectId),\n );\n this._loadLinkedObjects(Object.fromEntries(linksAwaitingLoad));\n linksAwaitingLoad.forEach(([objectId]) => this._objectsPendingDocumentLoad.delete(objectId));\n }\n\n public getSpaceRootDocHandle(): DocHandle<SpaceDoc> {\n invariant(this._spaceRootDocHandle);\n return this._spaceRootDocHandle;\n }\n\n public createDocumentForObject(objectId: string): DocHandle<SpaceDoc> {\n invariant(this._spaceRootDocHandle);\n const spaceDocHandle = this._repo.create<SpaceDoc>({\n version: SpaceDocVersion.CURRENT,\n });\n this._initDocAccess(spaceDocHandle);\n this.onObjectBoundToDocument(spaceDocHandle, objectId);\n this._spaceRootDocHandle.change((newDoc: SpaceDoc) => {\n newDoc.links ??= {};\n newDoc.links[objectId] = spaceDocHandle.url;\n });\n return spaceDocHandle;\n }\n\n public onObjectBoundToDocument(handle: DocHandle<SpaceDoc>, objectId: string) {\n this._objectDocumentHandles.set(objectId, handle);\n }\n\n public clearHandleReferences(): string[] {\n const objectsWithHandles = [...this._objectDocumentHandles.keys()];\n this._objectDocumentHandles.clear();\n this._spaceRootDocHandle = null;\n return objectsWithHandles;\n }\n\n private _loadLinkedObjects(links: SpaceDocumentLinks) {\n if (!links) {\n return;\n }\n for (const [objectId, automergeUrl] of Object.entries(links)) {\n const logMeta = { objectId, automergeUrl };\n const objectDocumentHandle = this._objectDocumentHandles.get(objectId);\n if (objectDocumentHandle != null && objectDocumentHandle.url !== automergeUrl) {\n log.warn('object already inlined in a different document, ignoring the link', {\n ...logMeta,\n actualDocumentUrl: objectDocumentHandle.url,\n });\n continue;\n }\n if (objectDocumentHandle?.url === automergeUrl) {\n log.warn('object document was already loaded', logMeta);\n continue;\n }\n const handle = this._repo.find<SpaceDoc>(automergeUrl as DocumentId);\n log.debug('document loading triggered', logMeta);\n this._objectDocumentHandles.set(objectId, handle);\n void this._createObjectOnDocumentLoad(handle, objectId);\n }\n }\n\n private async _initDocHandle(ctx: Context, url: string) {\n const docHandle = this._repo.find<SpaceDoc>(url as DocumentId);\n while (true) {\n try {\n await warnAfterTimeout(5_000, 'Automerge root doc load timeout (CoreDatabase)', async () => {\n await cancelWithContext(ctx, docHandle.whenReady()); // TODO(dmaretskyi): Temporary 5s timeout for debugging.\n });\n break;\n } catch (err) {\n if (`${err}`.includes('Timeout')) {\n log.info('wraparound', { id: docHandle.documentId, state: docHandle.state });\n continue;\n }\n\n throw err;\n }\n }\n\n if (docHandle.state === 'unavailable') {\n throw new Error('Automerge document is unavailable');\n }\n\n return docHandle;\n }\n\n private _createContextBoundSpaceRootDocument(ctx: Context) {\n const docHandle = this._repo.create<SpaceDoc>();\n this._spaceRootDocHandle = docHandle;\n ctx.onDispose(() => {\n docHandle.delete();\n this._spaceRootDocHandle = null;\n });\n }\n\n private _initDocAccess(handle: DocHandle<SpaceDoc>) {\n handle.change((newDoc: SpaceDoc) => {\n newDoc.access ??= { spaceKey: this._spaceKey.toHex() };\n newDoc.access.spaceKey = this._spaceKey.toHex();\n });\n }\n\n private async _createObjectOnDocumentLoad(handle: DocHandle<SpaceDoc>, objectId: string) {\n try {\n await handle.doc(['ready']);\n const logMeta = { objectId, docUrl: handle.url };\n if (this.onObjectDocumentLoaded.listenerCount() === 0) {\n log.info('document loaded after all listeners were removed', logMeta);\n return;\n }\n const objectDocHandle = this._objectDocumentHandles.get(objectId);\n if (objectDocHandle?.url !== handle.url) {\n log.warn('object was rebound while a document was loading, discarding handle', logMeta);\n return;\n }\n this.onObjectDocumentLoaded.emit({ handle, objectId });\n } catch (err) {\n const shouldRetryLoading = this.onObjectDocumentLoaded.listenerCount() > 0;\n log.warn('failed to load a document', {\n objectId,\n automergeUrl: handle.url,\n retryLoading: shouldRetryLoading,\n err,\n });\n if (shouldRetryLoading) {\n await this._createObjectOnDocumentLoad(handle, objectId);\n }\n }\n }\n}\n\nexport interface ObjectDocumentLoaded {\n handle: DocHandle<SpaceDoc>;\n objectId: string;\n}\n\nexport interface DocumentChanges {\n createdObjectIds: string[];\n updatedObjectIds: string[];\n objectsToRebind: string[];\n linkedDocuments: {\n [echoId: string]: AutomergeUrl;\n };\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Message, cbor } from '@dxos/automerge/automerge-repo';\nimport { Resource } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { AutomergeReplicator } from '@dxos/teleport-extension-automerge-replicator';\nimport { ComplexMap, ComplexSet, defaultMap } from '@dxos/util';\n\nimport {\n type EchoReplicator,\n type EchoReplicatorContext,\n type ReplicatorConnection,\n type ShouldAdvertizeParams,\n} from './echo-replicator';\n\n// TODO(dmaretskyi): Move out of @dxos/echo-pipeline.\n\n/**\n * Used to replicate with other peers over the network.\n */\nexport class MeshEchoReplicator implements EchoReplicator {\n private readonly _connections = new Set<MeshReplicatorConnection>();\n /**\n * Using automerge peerId as a key.\n */\n private readonly _connectionsPerPeer = new Map<string, MeshReplicatorConnection>();\n\n /**\n * spaceKey -> deviceKey[]\n */\n private readonly _authorizedDevices = new ComplexMap<PublicKey, ComplexSet<PublicKey>>(PublicKey.hash);\n\n private _context: EchoReplicatorContext | null = null;\n\n async connect(context: EchoReplicatorContext): Promise<void> {\n this._context = context;\n }\n\n async disconnect() {\n for (const connection of this._connections) {\n await connection.close();\n }\n this._connections.clear();\n this._connectionsPerPeer.clear();\n\n this._context = null;\n }\n\n createExtension(): AutomergeReplicator {\n invariant(this._context);\n\n const connection: MeshReplicatorConnection = new MeshReplicatorConnection({\n ownPeerId: this._context.peerId,\n onRemoteConnected: async () => {\n log('onRemoteConnected', { peerId: connection.peerId });\n invariant(this._context);\n\n if (this._connectionsPerPeer.has(connection.peerId)) {\n this._context.onConnectionAuthScopeChanged(connection);\n } else {\n this._connectionsPerPeer.set(connection.peerId, connection);\n await connection.enable();\n this._context.onConnectionOpen(connection);\n }\n },\n onRemoteDisconnected: async () => {\n log('onRemoteDisconnected', { peerId: connection.peerId });\n this._context?.onConnectionClosed(connection);\n await connection.disable();\n this._connectionsPerPeer.delete(connection.peerId);\n this._connections.delete(connection);\n },\n shouldAdvertize: async (params: ShouldAdvertizeParams) => {\n log('shouldAdvertize', { peerId: connection.peerId, documentId: params.documentId });\n invariant(this._context);\n try {\n const spaceKey = await this._context.getContainingSpaceForDocument(params.documentId);\n if (!spaceKey) {\n log('space key not found for share policy check', {\n peerId: connection.peerId,\n documentId: params.documentId,\n });\n return false;\n }\n\n const authorizedDevices = this._authorizedDevices.get(spaceKey);\n\n if (!connection.remoteDeviceKey) {\n log('device key not found for share policy check', {\n peerId: connection.peerId,\n documentId: params.documentId,\n });\n return false;\n }\n\n const isAuthorized = authorizedDevices?.has(connection.remoteDeviceKey) ?? false;\n log('share policy check', {\n localPeer: this._context.peerId,\n remotePeer: connection.peerId,\n documentId: params.documentId,\n deviceKey: connection.remoteDeviceKey,\n spaceKey,\n isAuthorized,\n });\n return isAuthorized;\n } catch (err) {\n log.catch(err);\n return false;\n }\n },\n });\n this._connections.add(connection);\n\n return connection.replicatorExtension;\n }\n\n authorizeDevice(spaceKey: PublicKey, deviceKey: PublicKey) {\n log('authorizeDevice', { spaceKey, deviceKey });\n defaultMap(this._authorizedDevices, spaceKey, () => new ComplexSet(PublicKey.hash)).add(deviceKey);\n }\n}\n\ntype MeshReplicatorConnectionParams = {\n ownPeerId: string;\n onRemoteConnected: () => Promise<void>;\n onRemoteDisconnected: () => Promise<void>;\n shouldAdvertize: (params: ShouldAdvertizeParams) => Promise<boolean>;\n};\n\nclass MeshReplicatorConnection extends Resource implements ReplicatorConnection {\n public readable: ReadableStream<Message>;\n public writable: WritableStream<Message>;\n public remoteDeviceKey: PublicKey | null = null;\n\n public readonly replicatorExtension: AutomergeReplicator;\n\n private _remotePeerId: string | null = null;\n private _isEnabled = false;\n\n constructor(private readonly _params: MeshReplicatorConnectionParams) {\n super();\n\n let readableStreamController!: ReadableStreamDefaultController<Message>;\n this.readable = new ReadableStream<Message>({\n start: (controller) => {\n readableStreamController = controller;\n this._ctx.onDispose(() => controller.close());\n },\n });\n\n this.writable = new WritableStream<Message>({\n write: async (message: Message, controller) => {\n // TODO(dmaretskyi): Show we block on RPC completing here?\n this.replicatorExtension.sendSyncMessage({ payload: cbor.encode(message) }).catch((err) => {\n controller.error(err);\n });\n },\n });\n\n this.replicatorExtension = new AutomergeReplicator(\n {\n peerId: this._params.ownPeerId,\n },\n {\n onStartReplication: async (info, remotePeerId /** Teleport ID */) => {\n // Note: We store only one extension per peer.\n // There can be a case where two connected peers have more than one teleport connection between them\n // and each of them uses different teleport connections to send messages.\n // It works because we receive messages from all teleport connections and Automerge Repo dedup them.\n // TODO(mykola): Use only one teleport connection per peer.\n\n // TODO(dmaretskyi): Critical bug.\n // - two peers get connected via swarm 1\n // - they get connected via swarm 2\n // - swarm 1 gets disconnected\n // - automerge repo thinks that peer 2 got disconnected even though swarm 2 is still active\n\n this.remoteDeviceKey = remotePeerId;\n\n // Set automerge id.\n this._remotePeerId = info.id;\n\n log('onStartReplication', { id: info.id, thisPeerId: this.peerId, remotePeerId: remotePeerId.toHex() });\n\n await this._params.onRemoteConnected();\n },\n onSyncMessage: async ({ payload }) => {\n if (!this._isEnabled) {\n return;\n }\n const message = cbor.decode(payload) as Message;\n // Note: automerge Repo dedup messages.\n readableStreamController.enqueue(message);\n },\n onClose: async () => {\n if (!this._isEnabled) {\n return;\n }\n await this._params.onRemoteDisconnected();\n },\n },\n );\n }\n\n get peerId(): string {\n invariant(this._remotePeerId != null, 'Remote peer has not connected yet.');\n return this._remotePeerId;\n }\n\n async shouldAdvertize(params: ShouldAdvertizeParams): Promise<boolean> {\n return this._params.shouldAdvertize(params);\n }\n\n /**\n * Start exchanging messages with the remote peer.\n * Call after the remote peer has connected.\n */\n async enable() {\n invariant(this._remotePeerId != null, 'Remote peer has not connected yet.');\n this._isEnabled = true;\n }\n\n /**\n * Stop exchanging messages with the remote peer.\n */\n async disable() {\n this._isEnabled = false;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Event", "next", "automerge", "getBackend", "getHeads", "Repo", "Context", "invariant", "PublicKey", "log", "objectPointerCodec", "trace", "mapValues", "Trigger", "synchronized", "NetworkAdapter", "LifecycleState", "invariant", "log", "EchoNetworkAdapter", "constructor", "_params", "_replicators", "Set", "_connections", "Map", "_lifecycleState", "CLOSED", "_connected", "connect", "peerId", "peerMetadata", "wake", "send", "message", "connectionEntry", "get", "targetId", "Error", "writer", "write", "catch", "err", "isOpen", "disconnect", "open", "OPEN", "emit", "network", "close", "replicator", "clear", "whenConnected", "wait", "timeout", "addReplicator", "has", "add", "onConnectionOpen", "_onConnectionOpen", "bind", "onConnectionClosed", "_onConnectionClosed", "onConnectionAuthScopeChanged", "_onConnectionAuthScopeChanged", "getContainingSpaceForDocument", "removeReplicator", "delete", "shouldAdvertize", "params", "connection", "reader", "readable", "getReader", "writable", "getWriter", "set", "queueMicrotask", "done", "value", "read", "_emitPeerCandidate", "entry", "cancel", "abort", "dxos_peerSource", "LifecycleState", "Resource", "LevelDBStorageAdapter", "Resource", "constructor", "_params", "load", "keyArray", "_lifecycleState", "LifecycleState", "OPEN", "undefined", "db", "get", "encodingOptions", "err", "isLevelDbNotFoundError", "save", "binary", "batch", "callbacks", "beforeSave", "path", "put", "Buffer", "from", "write", "afterSave", "remove", "del", "loadRange", "keyPrefix", "result", "key", "value", "iterator", "gte", "lte", "push", "data", "removeRange", "keyEncoder", "encode", "map", "k", "replaceAll", "join", "decode", "toString", "split", "format", "keyEncoding", "valueEncoding", "code", "Trigger", "NetworkAdapter", "cbor", "Stream", "invariant", "LocalHostNetworkAdapter", "_peers", "Map", "_connected", "_isConnected", "ready", "emit", "network", "connect", "peerId", "wake", "send", "message", "peer", "get", "targetId", "close", "forEach", "disconnect", "whenConnected", "wait", "timeout", "syncRepo", "id", "syncMessage", "_getPeerId", "next", "has", "set", "connected", "encode", "delete", "peerMetadata", "sendSyncMessage", "decode", "getHostInfo", "AutomergeHost", "constructor", "db", "indexMetadataStore", "_ctx", "Context", "_echoNetworkAdapter", "EchoNetworkAdapter", "getContainingSpaceForDocument", "_getContainingSpaceForDocument", "bind", "_requestedDocs", "Set", "_storage", "LevelDBStorageAdapter", "callbacks", "beforeSave", "params", "_beforeSave", "afterSave", "_afterSave", "_indexMetadataStore", "open", "_peerId", "PublicKey", "random", "toHex", "_clientNetwork", "LocalHostNetworkAdapter", "_repo", "Repo", "peerId", "sharePolicy", "_sharePolicy", "storage", "network", "ready", "whenConnected", "close", "dispose", "repo", "addReplicator", "replicator", "removeReplicator", "documentId", "startsWith", "doc", "handles", "docSync", "isRequested", "has", "log", "peerMetadata", "peerMetadataByPeerId", "dxos_peerSource", "shouldAdvertize", "path", "batch", "handle", "spaceKey", "getSpaceKeyFromDoc", "undefined", "lastAvailableHash", "getHeads", "objectIds", "Object", "keys", "objects", "encodedIds", "map", "objectId", "objectPointerCodec", "encode", "idToLastHash", "Map", "id", "markDirty", "notifyMarkedDirty", "_automergeDocs", "mapValues", "state", "hasDoc", "heads", "automerge", "data", "value", "key", "err", "_automergePeers", "peers", "spaceKeyHex", "from", "flush", "states", "Promise", "all", "invariant", "find", "waitForHeads", "syncRepo", "request", "sendSyncMessage", "getHostInfo", "trace", "info", "depth", "span", "showInBrowserTimeline", "resource", "rawSpaceKey", "access", "experimental_spaceKey", "String", "whenReady", "unavailableHeads", "Event", "wrap", "waitForCondition", "changeHash", "values", "changeIsPresentInDoc", "delete", "size", "getBackend", "getChangeByHash", "Event", "cancelWithContext", "warnAfterTimeout", "SpaceDocVersion", "invariant", "log", "trace", "AutomergeDocumentLoaderImpl", "constructor", "_spaceId", "_repo", "_spaceKey", "_spaceRootDocHandle", "_objectDocumentHandles", "Map", "_objectsPendingDocumentLoad", "Set", "onObjectDocumentLoaded", "getAllHandles", "values", "loadSpaceRootDocHandle", "ctx", "spaceState", "rootUrl", "error", "spaceId", "_createContextBoundSpaceRootDocument", "existingDocHandle", "_initDocHandle", "doc", "docSync", "access", "_initDocAccess", "loadObjectDocument", "objectIdOrMany", "objectIds", "Array", "isArray", "hasUrlsToLoad", "urlsToLoad", "objectId", "has", "spaceRootDoc", "documentUrl", "links", "add", "info", "_loadLinkedObjects", "onObjectLinksUpdated", "linksAwaitingLoad", "Object", "entries", "filter", "fromEntries", "forEach", "delete", "getSpaceRootDocHandle", "createDocumentForObject", "spaceDocHandle", "create", "version", "CURRENT", "onObjectBoundToDocument", "change", "newDoc", "url", "handle", "set", "clearHandleReferences", "objectsWithHandles", "keys", "clear", "automergeUrl", "logMeta", "objectDocumentHandle", "get", "warn", "actualDocumentUrl", "find", "debug", "_createObjectOnDocumentLoad", "docHandle", "whenReady", "err", "includes", "id", "documentId", "state", "Error", "onDispose", "spaceKey", "toHex", "docUrl", "listenerCount", "objectDocHandle", "emit", "shouldRetryLoading", "retryLoading", "span", "showInBrowserTimeline", "resource", "cbor", "Resource", "invariant", "PublicKey", "log", "AutomergeReplicator", "ComplexMap", "ComplexSet", "defaultMap", "MeshEchoReplicator", "_connections", "Set", "_connectionsPerPeer", "Map", "_authorizedDevices", "hash", "_context", "connect", "context", "disconnect", "connection", "close", "clear", "createExtension", "MeshReplicatorConnection", "ownPeerId", "peerId", "onRemoteConnected", "has", "onConnectionAuthScopeChanged", "set", "enable", "onConnectionOpen", "onRemoteDisconnected", "onConnectionClosed", "disable", "delete", "shouldAdvertize", "params", "documentId", "spaceKey", "getContainingSpaceForDocument", "authorizedDevices", "get", "remoteDeviceKey", "isAuthorized", "localPeer", "remotePeer", "deviceKey", "err", "catch", "add", "replicatorExtension", "authorizeDevice", "constructor", "_params", "_remotePeerId", "_isEnabled", "readableStreamController", "readable", "ReadableStream", "start", "controller", "_ctx", "onDispose", "writable", "WritableStream", "write", "message", "sendSyncMessage", "payload", "encode", "error", "onStartReplication", "info", "remotePeerId", "id", "thisPeerId", "toHex", "onSyncMessage", "decode", "enqueue", "onClose"]
|
|
7
7
|
}
|