@dxos/echo-pipeline 0.5.9-main.a75fa71 → 0.5.9-main.ac938b0
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 +65 -46
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +68 -49
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/automerge/automerge-doc-loader.d.ts +2 -1
- package/dist/types/src/automerge/automerge-doc-loader.d.ts.map +1 -1
- package/package.json +33 -33
- package/src/automerge/automerge-doc-loader.test.ts +6 -2
- package/src/automerge/automerge-doc-loader.ts +29 -20
- package/src/automerge/mesh-echo-replicator.ts +1 -1
|
@@ -843,6 +843,7 @@ var changeIsPresentInDoc = (doc, changeHash) => {
|
|
|
843
843
|
|
|
844
844
|
// packages/core/echo/echo-pipeline/src/automerge/automerge-doc-loader.ts
|
|
845
845
|
import { Event as Event2 } from "@dxos/async";
|
|
846
|
+
import { interpretAsDocumentId } from "@dxos/automerge/automerge-repo";
|
|
846
847
|
import { cancelWithContext as cancelWithContext2 } from "@dxos/context";
|
|
847
848
|
import { warnAfterTimeout } from "@dxos/debug";
|
|
848
849
|
import { SpaceDocVersion } from "@dxos/echo-protocol";
|
|
@@ -881,32 +882,32 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
881
882
|
return;
|
|
882
883
|
}
|
|
883
884
|
if (!spaceState.rootUrl) {
|
|
884
|
-
|
|
885
|
-
spaceId: this._spaceId
|
|
886
|
-
}, {
|
|
887
|
-
F: __dxlog_file4,
|
|
888
|
-
L: 72,
|
|
889
|
-
S: this,
|
|
890
|
-
C: (f, a) => f(...a)
|
|
891
|
-
});
|
|
892
|
-
this._createContextBoundSpaceRootDocument(ctx);
|
|
893
|
-
} else {
|
|
894
|
-
const existingDocHandle = await this._initDocHandle(ctx, spaceState.rootUrl);
|
|
895
|
-
const doc = existingDocHandle.docSync();
|
|
896
|
-
invariant3(doc, void 0, {
|
|
897
|
-
F: __dxlog_file4,
|
|
898
|
-
L: 77,
|
|
899
|
-
S: this,
|
|
900
|
-
A: [
|
|
901
|
-
"doc",
|
|
902
|
-
""
|
|
903
|
-
]
|
|
904
|
-
});
|
|
905
|
-
if (doc.access == null) {
|
|
906
|
-
this._initDocAccess(existingDocHandle);
|
|
907
|
-
}
|
|
908
|
-
this._spaceRootDocHandle = existingDocHandle;
|
|
885
|
+
throw new Error("Database opened with no rootUrl");
|
|
909
886
|
}
|
|
887
|
+
const existingDocHandle = await this._initDocHandle(ctx, spaceState.rootUrl);
|
|
888
|
+
const doc = existingDocHandle.docSync();
|
|
889
|
+
invariant3(doc, void 0, {
|
|
890
|
+
F: __dxlog_file4,
|
|
891
|
+
L: 84,
|
|
892
|
+
S: this,
|
|
893
|
+
A: [
|
|
894
|
+
"doc",
|
|
895
|
+
""
|
|
896
|
+
]
|
|
897
|
+
});
|
|
898
|
+
invariant3(doc.version === SpaceDocVersion.CURRENT, void 0, {
|
|
899
|
+
F: __dxlog_file4,
|
|
900
|
+
L: 85,
|
|
901
|
+
S: this,
|
|
902
|
+
A: [
|
|
903
|
+
"doc.version === SpaceDocVersion.CURRENT",
|
|
904
|
+
""
|
|
905
|
+
]
|
|
906
|
+
});
|
|
907
|
+
if (doc.access == null) {
|
|
908
|
+
this._initDocAccess(existingDocHandle);
|
|
909
|
+
}
|
|
910
|
+
this._spaceRootDocHandle = existingDocHandle;
|
|
910
911
|
}
|
|
911
912
|
loadObjectDocument(objectIdOrMany) {
|
|
912
913
|
const objectIds = Array.isArray(objectIdOrMany) ? objectIdOrMany : [
|
|
@@ -917,7 +918,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
917
918
|
for (const objectId of objectIds) {
|
|
918
919
|
invariant3(this._spaceRootDocHandle, void 0, {
|
|
919
920
|
F: __dxlog_file4,
|
|
920
|
-
L:
|
|
921
|
+
L: 97,
|
|
921
922
|
S: this,
|
|
922
923
|
A: [
|
|
923
924
|
"this._spaceRootDocHandle",
|
|
@@ -930,7 +931,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
930
931
|
const spaceRootDoc = this._spaceRootDocHandle.docSync();
|
|
931
932
|
invariant3(spaceRootDoc, void 0, {
|
|
932
933
|
F: __dxlog_file4,
|
|
933
|
-
L:
|
|
934
|
+
L: 102,
|
|
934
935
|
S: this,
|
|
935
936
|
A: [
|
|
936
937
|
"spaceRootDoc",
|
|
@@ -944,7 +945,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
944
945
|
objectId
|
|
945
946
|
}, {
|
|
946
947
|
F: __dxlog_file4,
|
|
947
|
-
L:
|
|
948
|
+
L: 106,
|
|
948
949
|
S: this,
|
|
949
950
|
C: (f, a) => f(...a)
|
|
950
951
|
});
|
|
@@ -957,6 +958,32 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
957
958
|
this._loadLinkedObjects(urlsToLoad);
|
|
958
959
|
}
|
|
959
960
|
}
|
|
961
|
+
getObjectDocumentId(objectId) {
|
|
962
|
+
invariant3(this._spaceRootDocHandle, void 0, {
|
|
963
|
+
F: __dxlog_file4,
|
|
964
|
+
L: 118,
|
|
965
|
+
S: this,
|
|
966
|
+
A: [
|
|
967
|
+
"this._spaceRootDocHandle",
|
|
968
|
+
""
|
|
969
|
+
]
|
|
970
|
+
});
|
|
971
|
+
const spaceRootDoc = this._spaceRootDocHandle.docSync();
|
|
972
|
+
invariant3(spaceRootDoc, void 0, {
|
|
973
|
+
F: __dxlog_file4,
|
|
974
|
+
L: 120,
|
|
975
|
+
S: this,
|
|
976
|
+
A: [
|
|
977
|
+
"spaceRootDoc",
|
|
978
|
+
""
|
|
979
|
+
]
|
|
980
|
+
});
|
|
981
|
+
if (spaceRootDoc.objects?.[objectId]) {
|
|
982
|
+
return this._spaceRootDocHandle.documentId;
|
|
983
|
+
}
|
|
984
|
+
const documentUrl = (spaceRootDoc.links ?? {})[objectId];
|
|
985
|
+
return documentUrl && interpretAsDocumentId(documentUrl);
|
|
986
|
+
}
|
|
960
987
|
onObjectLinksUpdated(links) {
|
|
961
988
|
if (!links) {
|
|
962
989
|
return;
|
|
@@ -968,7 +995,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
968
995
|
getSpaceRootDocHandle() {
|
|
969
996
|
invariant3(this._spaceRootDocHandle, void 0, {
|
|
970
997
|
F: __dxlog_file4,
|
|
971
|
-
L:
|
|
998
|
+
L: 140,
|
|
972
999
|
S: this,
|
|
973
1000
|
A: [
|
|
974
1001
|
"this._spaceRootDocHandle",
|
|
@@ -980,7 +1007,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
980
1007
|
createDocumentForObject(objectId) {
|
|
981
1008
|
invariant3(this._spaceRootDocHandle, void 0, {
|
|
982
1009
|
F: __dxlog_file4,
|
|
983
|
-
L:
|
|
1010
|
+
L: 145,
|
|
984
1011
|
S: this,
|
|
985
1012
|
A: [
|
|
986
1013
|
"this._spaceRootDocHandle",
|
|
@@ -1025,7 +1052,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1025
1052
|
actualDocumentUrl: objectDocumentHandle.url
|
|
1026
1053
|
}, {
|
|
1027
1054
|
F: __dxlog_file4,
|
|
1028
|
-
L:
|
|
1055
|
+
L: 177,
|
|
1029
1056
|
S: this,
|
|
1030
1057
|
C: (f, a) => f(...a)
|
|
1031
1058
|
});
|
|
@@ -1034,7 +1061,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1034
1061
|
if (objectDocumentHandle?.url === automergeUrl) {
|
|
1035
1062
|
log2.warn("object document was already loaded", logMeta, {
|
|
1036
1063
|
F: __dxlog_file4,
|
|
1037
|
-
L:
|
|
1064
|
+
L: 184,
|
|
1038
1065
|
S: this,
|
|
1039
1066
|
C: (f, a) => f(...a)
|
|
1040
1067
|
});
|
|
@@ -1043,7 +1070,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1043
1070
|
const handle = this._repo.find(automergeUrl);
|
|
1044
1071
|
log2.debug("document loading triggered", logMeta, {
|
|
1045
1072
|
F: __dxlog_file4,
|
|
1046
|
-
L:
|
|
1073
|
+
L: 188,
|
|
1047
1074
|
S: this,
|
|
1048
1075
|
C: (f, a) => f(...a)
|
|
1049
1076
|
});
|
|
@@ -1066,7 +1093,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1066
1093
|
state: docHandle.state
|
|
1067
1094
|
}, {
|
|
1068
1095
|
F: __dxlog_file4,
|
|
1069
|
-
L:
|
|
1096
|
+
L: 204,
|
|
1070
1097
|
S: this,
|
|
1071
1098
|
C: (f, a) => f(...a)
|
|
1072
1099
|
});
|
|
@@ -1080,14 +1107,6 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1080
1107
|
}
|
|
1081
1108
|
return docHandle;
|
|
1082
1109
|
}
|
|
1083
|
-
_createContextBoundSpaceRootDocument(ctx) {
|
|
1084
|
-
const docHandle = this._repo.create();
|
|
1085
|
-
this._spaceRootDocHandle = docHandle;
|
|
1086
|
-
ctx.onDispose(() => {
|
|
1087
|
-
docHandle.delete();
|
|
1088
|
-
this._spaceRootDocHandle = null;
|
|
1089
|
-
});
|
|
1090
|
-
}
|
|
1091
1110
|
_initDocAccess(handle) {
|
|
1092
1111
|
handle.change((newDoc) => {
|
|
1093
1112
|
newDoc.access ??= {
|
|
@@ -1108,7 +1127,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1108
1127
|
if (this.onObjectDocumentLoaded.listenerCount() === 0) {
|
|
1109
1128
|
log2.info("document loaded after all listeners were removed", logMeta, {
|
|
1110
1129
|
F: __dxlog_file4,
|
|
1111
|
-
L:
|
|
1130
|
+
L: 231,
|
|
1112
1131
|
S: this,
|
|
1113
1132
|
C: (f, a) => f(...a)
|
|
1114
1133
|
});
|
|
@@ -1118,7 +1137,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1118
1137
|
if (objectDocHandle?.url !== handle.url) {
|
|
1119
1138
|
log2.warn("object was rebound while a document was loading, discarding handle", logMeta, {
|
|
1120
1139
|
F: __dxlog_file4,
|
|
1121
|
-
L:
|
|
1140
|
+
L: 236,
|
|
1122
1141
|
S: this,
|
|
1123
1142
|
C: (f, a) => f(...a)
|
|
1124
1143
|
});
|
|
@@ -1137,7 +1156,7 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1137
1156
|
err
|
|
1138
1157
|
}, {
|
|
1139
1158
|
F: __dxlog_file4,
|
|
1140
|
-
L:
|
|
1159
|
+
L: 242,
|
|
1141
1160
|
S: this,
|
|
1142
1161
|
C: (f, a) => f(...a)
|
|
1143
1162
|
});
|
|
@@ -1223,8 +1242,8 @@ var MeshEchoReplicator = class {
|
|
|
1223
1242
|
this._context.onConnectionAuthScopeChanged(connection);
|
|
1224
1243
|
} else {
|
|
1225
1244
|
this._connectionsPerPeer.set(connection.peerId, connection);
|
|
1226
|
-
await connection.enable();
|
|
1227
1245
|
this._context.onConnectionOpen(connection);
|
|
1246
|
+
await connection.enable();
|
|
1228
1247
|
}
|
|
1229
1248
|
},
|
|
1230
1249
|
onRemoteDisconnected: async () => {
|
|
@@ -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, asyncTimeout } from '@dxos/async';\nimport {\n next as automerge,\n getBackend,\n getHeads,\n isAutomerge,\n save,\n type Doc,\n type Heads,\n} from '@dxos/automerge/automerge';\nimport {\n Repo,\n type AnyDocumentId,\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, cancelWithContext, type Lifecycle } from '@dxos/context';\nimport { type SpaceDoc } from '@dxos/echo-protocol';\nimport { type IndexMetadataStore } from '@dxos/indexing';\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, isEchoPeerMetadata } 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\nexport type LoadDocOptions = {\n timeout?: number;\n};\n\nexport type CreateDocOptions = {\n /**\n * Import the document together with its history.\n */\n preserveHistory?: boolean;\n};\n\n/**\n * Abstracts over the AutomergeRepo.\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 /**\n * @deprecated To be abstracted away.\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 /**\n * Loads the document handle from the repo and waits for it to be ready.\n */\n async loadDoc<T>(ctx: Context, documentId: AnyDocumentId, opts?: LoadDocOptions): Promise<DocHandle<T>> {\n let handle: DocHandle<T> | undefined;\n if (typeof documentId === 'string') {\n // NOTE: documentId might also be a URL, in which case this lookup will fail.\n handle = this._repo.handles[documentId as DocumentId];\n }\n if (!handle) {\n handle = this._repo.find(documentId as DocumentId);\n }\n\n // `whenReady` creates a timeout so we guard it with an if to skip it if the handle is already ready.\n if (!handle.isReady()) {\n if (!opts?.timeout) {\n await cancelWithContext(ctx, handle.whenReady());\n } else {\n await cancelWithContext(ctx, asyncTimeout(handle.whenReady(), opts.timeout));\n }\n }\n\n return handle;\n }\n\n /**\n * Create new persisted document.\n */\n createDoc<T>(initialValue?: T | Doc<T>, opts?: CreateDocOptions): DocHandle<T> {\n if (opts?.preserveHistory) {\n if (!isAutomerge(initialValue)) {\n throw new TypeError('Initial value must be an Automerge document');\n }\n // TODO(dmaretskyi): There's a more efficient way.\n return this._repo.import(save(initialValue as Doc<T>));\n } else {\n return this._repo.create(initialValue);\n }\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 (isEchoPeerMetadata(peerMetadata)) {\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 * Flush documents to disk.\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 if (states) {\n await Promise.all(\n states.map(async ({ heads, documentId }) => {\n if (!heads) {\n return;\n }\n const handle = this.repo.handles[documentId as DocumentId] ?? this._repo.find(documentId as DocumentId);\n await waitForHeads(handle, heads);\n }) ?? [],\n );\n }\n\n await this._repo.flush(states?.map(({ documentId }) => documentId as DocumentId));\n }\n\n /**\n * Host <-> Client sync.\n */\n syncRepo(request: SyncRepoRequest): Stream<SyncRepoResponse> {\n return this._clientNetwork.syncRepo(request);\n }\n\n /**\n * Host <-> Client sync.\n */\n sendSyncMessage(request: SyncRepoRequest): Promise<void> {\n return this._clientNetwork.sendSyncMessage(request);\n }\n\n /**\n * Host <-> Client sync.\n */\n async getHostInfo(): Promise<HostInfo> {\n return this._clientNetwork.getHostInfo();\n }\n}\n\nexport const getSpaceKeyFromDoc = (doc: Doc<SpaceDoc>): 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 as any).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: createEchoPeerMetadata(),\n });\n }\n}\n\ntype ConnectionEntry = {\n connection: ReplicatorConnection;\n reader: ReadableStreamDefaultReader<Message>;\n writer: WritableStreamDefaultWriter<Message>;\n isOpen: boolean;\n};\n\nexport const createEchoPeerMetadata = (): PeerMetadata =>\n ({\n // TODO(dmaretskyi): Refactor this.\n dxos_peerSource: 'EchoNetworkAdapter',\n }) as any;\n\nexport const isEchoPeerMetadata = (metadata: PeerMetadata): boolean =>\n (metadata as any)?.dxos_peerSource === 'EchoNetworkAdapter';\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 this._connectionsPerPeer.delete(connection.peerId);\n await connection.disable();\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", "asyncTimeout", "next", "automerge", "getBackend", "getHeads", "isAutomerge", "save", "Repo", "Context", "cancelWithContext", "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", "createEchoPeerMetadata", "dxos_peerSource", "isEchoPeerMetadata", "metadata", "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", "loadDoc", "ctx", "documentId", "opts", "handle", "handles", "find", "isReady", "timeout", "cancelWithContext", "whenReady", "asyncTimeout", "createDoc", "initialValue", "preserveHistory", "isAutomerge", "TypeError", "import", "save", "create", "startsWith", "peerMetadata", "peerMetadataByPeerId", "isEchoPeerMetadata", "shouldAdvertize", "path", "batch", "doc", "docSync", "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", "waitForHeads", "syncRepo", "request", "sendSyncMessage", "getHostInfo", "trace", "info", "depth", "span", "showInBrowserTimeline", "resource", "rawSpaceKey", "access", "experimental_spaceKey", "String", "unavailableHeads", "Set", "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", "
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Event, asyncTimeout } from '@dxos/async';\nimport {\n next as automerge,\n getBackend,\n getHeads,\n isAutomerge,\n save,\n type Doc,\n type Heads,\n} from '@dxos/automerge/automerge';\nimport {\n Repo,\n type AnyDocumentId,\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, cancelWithContext, type Lifecycle } from '@dxos/context';\nimport { type SpaceDoc } from '@dxos/echo-protocol';\nimport { type IndexMetadataStore } from '@dxos/indexing';\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, isEchoPeerMetadata } 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\nexport type LoadDocOptions = {\n timeout?: number;\n};\n\nexport type CreateDocOptions = {\n /**\n * Import the document together with its history.\n */\n preserveHistory?: boolean;\n};\n\n/**\n * Abstracts over the AutomergeRepo.\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 /**\n * @deprecated To be abstracted away.\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 /**\n * Loads the document handle from the repo and waits for it to be ready.\n */\n async loadDoc<T>(ctx: Context, documentId: AnyDocumentId, opts?: LoadDocOptions): Promise<DocHandle<T>> {\n let handle: DocHandle<T> | undefined;\n if (typeof documentId === 'string') {\n // NOTE: documentId might also be a URL, in which case this lookup will fail.\n handle = this._repo.handles[documentId as DocumentId];\n }\n if (!handle) {\n handle = this._repo.find(documentId as DocumentId);\n }\n\n // `whenReady` creates a timeout so we guard it with an if to skip it if the handle is already ready.\n if (!handle.isReady()) {\n if (!opts?.timeout) {\n await cancelWithContext(ctx, handle.whenReady());\n } else {\n await cancelWithContext(ctx, asyncTimeout(handle.whenReady(), opts.timeout));\n }\n }\n\n return handle;\n }\n\n /**\n * Create new persisted document.\n */\n createDoc<T>(initialValue?: T | Doc<T>, opts?: CreateDocOptions): DocHandle<T> {\n if (opts?.preserveHistory) {\n if (!isAutomerge(initialValue)) {\n throw new TypeError('Initial value must be an Automerge document');\n }\n // TODO(dmaretskyi): There's a more efficient way.\n return this._repo.import(save(initialValue as Doc<T>));\n } else {\n return this._repo.create(initialValue);\n }\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 (isEchoPeerMetadata(peerMetadata)) {\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 * Flush documents to disk.\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 if (states) {\n await Promise.all(\n states.map(async ({ heads, documentId }) => {\n if (!heads) {\n return;\n }\n const handle = this.repo.handles[documentId as DocumentId] ?? this._repo.find(documentId as DocumentId);\n await waitForHeads(handle, heads);\n }) ?? [],\n );\n }\n\n await this._repo.flush(states?.map(({ documentId }) => documentId as DocumentId));\n }\n\n /**\n * Host <-> Client sync.\n */\n syncRepo(request: SyncRepoRequest): Stream<SyncRepoResponse> {\n return this._clientNetwork.syncRepo(request);\n }\n\n /**\n * Host <-> Client sync.\n */\n sendSyncMessage(request: SyncRepoRequest): Promise<void> {\n return this._clientNetwork.sendSyncMessage(request);\n }\n\n /**\n * Host <-> Client sync.\n */\n async getHostInfo(): Promise<HostInfo> {\n return this._clientNetwork.getHostInfo();\n }\n}\n\nexport const getSpaceKeyFromDoc = (doc: Doc<SpaceDoc>): 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 as any).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: createEchoPeerMetadata(),\n });\n }\n}\n\ntype ConnectionEntry = {\n connection: ReplicatorConnection;\n reader: ReadableStreamDefaultReader<Message>;\n writer: WritableStreamDefaultWriter<Message>;\n isOpen: boolean;\n};\n\nexport const createEchoPeerMetadata = (): PeerMetadata =>\n ({\n // TODO(dmaretskyi): Refactor this.\n dxos_peerSource: 'EchoNetworkAdapter',\n }) as any;\n\nexport const isEchoPeerMetadata = (metadata: PeerMetadata): boolean =>\n (metadata as any)?.dxos_peerSource === 'EchoNetworkAdapter';\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 {\n type DocHandle,\n type AutomergeUrl,\n type DocumentId,\n type Repo,\n interpretAsDocumentId,\n} 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 getObjectDocumentId(objectId: string): string | undefined;\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 throw new Error('Database opened with no rootUrl');\n }\n\n const existingDocHandle = await this._initDocHandle(ctx, spaceState.rootUrl);\n const doc = existingDocHandle.docSync();\n invariant(doc);\n invariant(doc.version === SpaceDocVersion.CURRENT);\n if (doc.access == null) {\n this._initDocAccess(existingDocHandle);\n }\n this._spaceRootDocHandle = existingDocHandle;\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 getObjectDocumentId(objectId: string): string | undefined {\n invariant(this._spaceRootDocHandle);\n const spaceRootDoc = this._spaceRootDocHandle.docSync();\n invariant(spaceRootDoc);\n if (spaceRootDoc.objects?.[objectId]) {\n return this._spaceRootDocHandle.documentId;\n }\n const documentUrl = (spaceRootDoc.links ?? {})[objectId];\n return documentUrl && interpretAsDocumentId(documentUrl);\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 _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 this._context.onConnectionOpen(connection);\n await connection.enable();\n }\n },\n onRemoteDisconnected: async () => {\n log('onRemoteDisconnected', { peerId: connection.peerId });\n this._context?.onConnectionClosed(connection);\n this._connectionsPerPeer.delete(connection.peerId);\n await connection.disable();\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", "asyncTimeout", "next", "automerge", "getBackend", "getHeads", "isAutomerge", "save", "Repo", "Context", "cancelWithContext", "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", "createEchoPeerMetadata", "dxos_peerSource", "isEchoPeerMetadata", "metadata", "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", "loadDoc", "ctx", "documentId", "opts", "handle", "handles", "find", "isReady", "timeout", "cancelWithContext", "whenReady", "asyncTimeout", "createDoc", "initialValue", "preserveHistory", "isAutomerge", "TypeError", "import", "save", "create", "startsWith", "peerMetadata", "peerMetadataByPeerId", "isEchoPeerMetadata", "shouldAdvertize", "path", "batch", "doc", "docSync", "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", "waitForHeads", "syncRepo", "request", "sendSyncMessage", "getHostInfo", "trace", "info", "depth", "span", "showInBrowserTimeline", "resource", "rawSpaceKey", "access", "experimental_spaceKey", "String", "unavailableHeads", "Set", "Event", "wrap", "waitForCondition", "changeHash", "values", "changeIsPresentInDoc", "delete", "size", "getBackend", "getChangeByHash", "Event", "interpretAsDocumentId", "cancelWithContext", "warnAfterTimeout", "SpaceDocVersion", "invariant", "log", "trace", "AutomergeDocumentLoaderImpl", "constructor", "_spaceId", "_repo", "_spaceKey", "_spaceRootDocHandle", "_objectDocumentHandles", "Map", "_objectsPendingDocumentLoad", "Set", "onObjectDocumentLoaded", "getAllHandles", "values", "loadSpaceRootDocHandle", "ctx", "spaceState", "rootUrl", "Error", "existingDocHandle", "_initDocHandle", "doc", "docSync", "version", "CURRENT", "access", "_initDocAccess", "loadObjectDocument", "objectIdOrMany", "objectIds", "Array", "isArray", "hasUrlsToLoad", "urlsToLoad", "objectId", "has", "spaceRootDoc", "documentUrl", "links", "add", "info", "_loadLinkedObjects", "getObjectDocumentId", "objects", "documentId", "onObjectLinksUpdated", "linksAwaitingLoad", "Object", "entries", "filter", "fromEntries", "forEach", "delete", "getSpaceRootDocHandle", "createDocumentForObject", "spaceDocHandle", "create", "onObjectBoundToDocument", "change", "newDoc", "url", "handle", "set", "clearHandleReferences", "objectsWithHandles", "keys", "clear", "automergeUrl", "logMeta", "objectDocumentHandle", "get", "warn", "actualDocumentUrl", "find", "debug", "_createObjectOnDocumentLoad", "docHandle", "whenReady", "err", "includes", "id", "state", "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", "onConnectionOpen", "enable", "onRemoteDisconnected", "onConnectionClosed", "delete", "disable", "shouldAdvertize", "params", "documentId", "spaceKey", "getContainingSpaceForDocument", "authorizedDevices", "get", "remoteDeviceKey", "isAuthorized", "localPeer", "remotePeer", "deviceKey", "err", "catch", "add", "replicatorExtension", "authorizeDevice", "equals", "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
|
}
|