@dxos/echo-pipeline 0.6.2-main.fb91371 → 0.6.2
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 +14 -11
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +14 -11
- package/dist/lib/node/index.cjs.map +2 -2
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/automerge/mesh-echo-replicator.d.ts.map +1 -1
- package/package.json +33 -33
- package/src/automerge/echo-network-adapter.test.ts +11 -0
- package/src/automerge/mesh-echo-replicator.ts +3 -0
|
@@ -916,6 +916,9 @@ var MeshEchoReplicator = class {
|
|
|
916
916
|
this._context = context;
|
|
917
917
|
}
|
|
918
918
|
async disconnect() {
|
|
919
|
+
for (const connection of this._connectionsPerPeer.values()) {
|
|
920
|
+
this._context?.onConnectionClosed(connection);
|
|
921
|
+
}
|
|
919
922
|
for (const connection of this._connections) {
|
|
920
923
|
await connection.close();
|
|
921
924
|
}
|
|
@@ -926,7 +929,7 @@ var MeshEchoReplicator = class {
|
|
|
926
929
|
createExtension(extensionFactory) {
|
|
927
930
|
invariant4(this._context, void 0, {
|
|
928
931
|
F: __dxlog_file4,
|
|
929
|
-
L:
|
|
932
|
+
L: 54,
|
|
930
933
|
S: this,
|
|
931
934
|
A: [
|
|
932
935
|
"this._context",
|
|
@@ -941,13 +944,13 @@ var MeshEchoReplicator = class {
|
|
|
941
944
|
peerId: connection.peerId
|
|
942
945
|
}, {
|
|
943
946
|
F: __dxlog_file4,
|
|
944
|
-
L:
|
|
947
|
+
L: 60,
|
|
945
948
|
S: this,
|
|
946
949
|
C: (f, a) => f(...a)
|
|
947
950
|
});
|
|
948
951
|
invariant4(this._context, void 0, {
|
|
949
952
|
F: __dxlog_file4,
|
|
950
|
-
L:
|
|
953
|
+
L: 61,
|
|
951
954
|
S: this,
|
|
952
955
|
A: [
|
|
953
956
|
"this._context",
|
|
@@ -967,7 +970,7 @@ var MeshEchoReplicator = class {
|
|
|
967
970
|
peerId: connection.peerId
|
|
968
971
|
}, {
|
|
969
972
|
F: __dxlog_file4,
|
|
970
|
-
L:
|
|
973
|
+
L: 72,
|
|
971
974
|
S: this,
|
|
972
975
|
C: (f, a) => f(...a)
|
|
973
976
|
});
|
|
@@ -982,13 +985,13 @@ var MeshEchoReplicator = class {
|
|
|
982
985
|
documentId: params.documentId
|
|
983
986
|
}, {
|
|
984
987
|
F: __dxlog_file4,
|
|
985
|
-
L:
|
|
988
|
+
L: 79,
|
|
986
989
|
S: this,
|
|
987
990
|
C: (f, a) => f(...a)
|
|
988
991
|
});
|
|
989
992
|
invariant4(this._context, void 0, {
|
|
990
993
|
F: __dxlog_file4,
|
|
991
|
-
L:
|
|
994
|
+
L: 80,
|
|
992
995
|
S: this,
|
|
993
996
|
A: [
|
|
994
997
|
"this._context",
|
|
@@ -1003,7 +1006,7 @@ var MeshEchoReplicator = class {
|
|
|
1003
1006
|
documentId: params.documentId
|
|
1004
1007
|
}, {
|
|
1005
1008
|
F: __dxlog_file4,
|
|
1006
|
-
L:
|
|
1009
|
+
L: 84,
|
|
1007
1010
|
S: this,
|
|
1008
1011
|
C: (f, a) => f(...a)
|
|
1009
1012
|
});
|
|
@@ -1016,7 +1019,7 @@ var MeshEchoReplicator = class {
|
|
|
1016
1019
|
documentId: params.documentId
|
|
1017
1020
|
}, {
|
|
1018
1021
|
F: __dxlog_file4,
|
|
1019
|
-
L:
|
|
1022
|
+
L: 94,
|
|
1020
1023
|
S: this,
|
|
1021
1024
|
C: (f, a) => f(...a)
|
|
1022
1025
|
});
|
|
@@ -1032,7 +1035,7 @@ var MeshEchoReplicator = class {
|
|
|
1032
1035
|
isAuthorized
|
|
1033
1036
|
}, {
|
|
1034
1037
|
F: __dxlog_file4,
|
|
1035
|
-
L:
|
|
1038
|
+
L: 102,
|
|
1036
1039
|
S: this,
|
|
1037
1040
|
C: (f, a) => f(...a)
|
|
1038
1041
|
});
|
|
@@ -1040,7 +1043,7 @@ var MeshEchoReplicator = class {
|
|
|
1040
1043
|
} catch (err) {
|
|
1041
1044
|
log4.catch(err, void 0, {
|
|
1042
1045
|
F: __dxlog_file4,
|
|
1043
|
-
L:
|
|
1046
|
+
L: 112,
|
|
1044
1047
|
S: this,
|
|
1045
1048
|
C: (f, a) => f(...a)
|
|
1046
1049
|
});
|
|
@@ -1057,7 +1060,7 @@ var MeshEchoReplicator = class {
|
|
|
1057
1060
|
deviceKey
|
|
1058
1061
|
}, {
|
|
1059
1062
|
F: __dxlog_file4,
|
|
1060
|
-
L:
|
|
1063
|
+
L: 123,
|
|
1061
1064
|
S: this,
|
|
1062
1065
|
C: (f, a) => f(...a)
|
|
1063
1066
|
});
|
|
@@ -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/heads-store.ts", "../../../src/automerge/leveldb-storage-adapter.ts", "../../../src/automerge/mesh-echo-replicator.ts", "../../../src/automerge/mesh-echo-replicator-connection.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 equals as headsEquals,\n save,\n type Doc,\n type Heads,\n} from '@dxos/automerge/automerge';\nimport {\n type DocHandleChangePayload,\n Repo,\n type AnyDocumentId,\n type DocHandle,\n type DocumentId,\n type PeerId,\n type StorageAdapterInterface,\n} from '@dxos/automerge/automerge-repo';\nimport { Context, Resource, cancelWithContext, type Lifecycle } from '@dxos/context';\nimport { type SpaceDoc } from '@dxos/echo-protocol';\nimport { type IndexMetadataStore } from '@dxos/indexing';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { type LevelDB } from '@dxos/kv-store';\nimport { log } from '@dxos/log';\nimport { objectPointerCodec } from '@dxos/protocols';\nimport { type DocHeadsList, type FlushRequest } 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 { HeadsStore } from './heads-store';\nimport { LevelDBStorageAdapter, type BeforeSaveParams } from './leveldb-storage-adapter';\n\nexport type AutomergeHostParams = {\n db: LevelDB;\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 extends Resource {\n private readonly _db: LevelDB;\n private readonly _indexMetadataStore: IndexMetadataStore;\n private readonly _echoNetworkAdapter = new EchoNetworkAdapter({\n getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this),\n });\n\n private _repo!: Repo;\n private _storage!: StorageAdapterInterface & Lifecycle;\n private readonly _headsStore: HeadsStore;\n\n @trace.info()\n private _peerId!: string;\n\n constructor({ db, indexMetadataStore }: AutomergeHostParams) {\n super();\n this._db = db;\n this._storage = new LevelDBStorageAdapter({\n db: db.sublevel('automerge'),\n callbacks: {\n beforeSave: async (params) => this._beforeSave(params),\n afterSave: async () => this._afterSave(),\n },\n });\n this._headsStore = new HeadsStore({ db: db.sublevel('heads') });\n this._indexMetadataStore = indexMetadataStore;\n }\n\n protected override 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\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 // Upstream swarm.\n this._echoNetworkAdapter,\n ],\n });\n\n await this._echoNetworkAdapter.open();\n await this._echoNetworkAdapter.whenConnected();\n }\n\n protected override async _close() {\n await this._storage.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 get loadedDocsCount(): number {\n return Object.keys(this._repo.handles).length;\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 async waitUntilHeadsReplicated(heads: DocHeadsList): Promise<void> {\n await Promise.all(\n heads.entries?.map(async ({ documentId, heads }) => {\n if (!heads || heads.length === 0) {\n return;\n }\n\n const currentHeads = this.getHeads(documentId as DocumentId);\n if (currentHeads !== null && headsEquals(currentHeads, heads)) {\n return;\n }\n\n const handle = await this.loadDoc(Context.default(), documentId as DocumentId);\n await waitForHeads(handle, heads);\n }) ?? [],\n );\n\n // Flush to disk also so that the indexer can pick up the changes.\n await this._repo.flush((heads.entries?.map((entry) => entry.documentId) ?? []) as DocumentId[]);\n }\n\n async reIndexHeads(documentIds: DocumentId[]) {\n for (const documentId of documentIds) {\n log.info('re-indexing heads for document', { documentId });\n const handle = this._repo.find(documentId);\n await handle.whenReady(['ready', 'requesting']);\n if (handle.inState(['requesting'])) {\n log.warn('document is not available locally, skipping', { documentId });\n continue; // Handle not available locally.\n }\n\n const doc = handle.docSync();\n invariant(doc);\n\n const heads = getHeads(doc);\n const batch = this._db.batch();\n this._headsStore.setHeads(documentId, heads, batch);\n await batch.write();\n }\n log.info('done re-indexing heads');\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(peerId: PeerId, documentId?: DocumentId): 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.shouldAdvertise(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 heads = getHeads(doc);\n\n this._headsStore.setHeads(handle.documentId, heads, batch);\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, heads]));\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({ documentIds }: FlushRequest = {}): Promise<void> {\n // Note: Sync protocol for client and services ensures that all handles should have all changes.\n\n await this._repo.flush(documentIds as DocumentId[] | undefined);\n }\n\n async getHeads(documentId: DocumentId): Promise<Heads | undefined> {\n const handle = this._repo.handles[documentId];\n if (handle) {\n const doc = handle.docSync();\n if (!doc) {\n return undefined;\n }\n return getHeads(doc);\n } else {\n return this._headsStore.getHeads(documentId);\n }\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 const unavailableHeads = new Set(heads);\n\n await handle.whenReady();\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 return unavailableHeads.size === 0;\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 { synchronized, Trigger } 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 ShouldAdvertiseParams } 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 if (this._lifecycleState === LifecycleState.OPEN) {\n return;\n }\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 if (this._lifecycleState === LifecycleState.CLOSED) {\n return this;\n }\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 shouldAdvertise(peerId: PeerId, params: ShouldAdvertiseParams): Promise<boolean> {\n const connection = this._connections.get(peerId);\n if (!connection) {\n return false;\n }\n\n return connection.connection.shouldAdvertise(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//\n\nimport type { Heads } from '@dxos/automerge/automerge';\nimport type { DocumentId } from '@dxos/automerge/automerge-repo';\nimport { headsEncoding } from '@dxos/indexing';\nimport type { BatchLevel, SublevelDB } from '@dxos/kv-store';\n\nexport type HeadsStoreParams = {\n db: SublevelDB;\n};\n\nexport class HeadsStore {\n private readonly _db: SublevelDB;\n\n constructor({ db }: HeadsStoreParams) {\n this._db = db;\n }\n\n setHeads(documentId: DocumentId, heads: Heads, batch: BatchLevel) {\n batch.put<DocumentId, Heads>(documentId, heads, {\n sublevel: this._db,\n keyEncoding: 'utf8',\n valueEncoding: headsEncoding,\n });\n }\n\n async getHeads(documentId: DocumentId): Promise<Heads | undefined> {\n try {\n return await this._db.get<DocumentId, Heads>(documentId, { keyEncoding: 'utf8', valueEncoding: headsEncoding });\n } catch (err: any) {\n if (err.notFound) {\n return undefined;\n }\n throw err;\n }\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n// s\n\nimport { type MixedEncoding } from 'level-transcoder';\n\nimport { type StorageAdapterInterface, type Chunk, type StorageKey } from '@dxos/automerge/automerge-repo';\nimport { LifecycleState, Resource } from '@dxos/context';\nimport { type BatchLevel, type SublevelDB } from '@dxos/kv-store';\nimport { type MaybePromise } from '@dxos/util';\n\nexport type LevelDBStorageAdapterParams = {\n db: SublevelDB;\n callbacks?: StorageCallbacks;\n};\n\nexport type BeforeSaveParams = { path: StorageKey; batch: BatchLevel };\n\nexport interface StorageCallbacks {\n beforeSave(params: BeforeSaveParams): MaybePromise<void>;\n afterSave(path: StorageKey): MaybePromise<void>;\n}\n\nexport class LevelDBStorageAdapter extends Resource implements StorageAdapterInterface {\n constructor(private readonly _params: LevelDBStorageAdapterParams) {\n super();\n }\n\n async load(keyArray: StorageKey): Promise<Uint8Array | undefined> {\n try {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n // TODO(mykola): this should be an error.\n return undefined;\n }\n return await this._params.db.get<StorageKey, Uint8Array>(keyArray, { ...encodingOptions });\n } catch (err: any) {\n if (isLevelDbNotFoundError(err)) {\n return undefined;\n }\n throw err;\n }\n }\n\n async save(keyArray: StorageKey, binary: Uint8Array): Promise<void> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return undefined;\n }\n const batch = this._params.db.batch();\n\n await this._params.callbacks?.beforeSave?.({ path: keyArray, batch });\n batch.put<StorageKey, Uint8Array>(keyArray, Buffer.from(binary), {\n ...encodingOptions,\n });\n await batch.write();\n\n await this._params.callbacks?.afterSave?.(keyArray);\n }\n\n async remove(keyArray: StorageKey): Promise<void> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return undefined;\n }\n await this._params.db.del<StorageKey>(keyArray, { ...encodingOptions });\n }\n\n async loadRange(keyPrefix: StorageKey): Promise<Chunk[]> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return [];\n }\n const result: Chunk[] = [];\n for await (const [key, value] of this._params.db.iterator<StorageKey, Uint8Array>({\n gte: keyPrefix,\n lte: [...keyPrefix, '\\uffff'],\n ...encodingOptions,\n })) {\n result.push({\n key,\n data: value,\n });\n }\n return result;\n }\n\n async removeRange(keyPrefix: StorageKey): Promise<void> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return undefined;\n }\n const batch = this._params.db.batch();\n\n for await (const [key] of this._params.db.iterator<StorageKey, Uint8Array>({\n gte: keyPrefix,\n lte: [...keyPrefix, '\\uffff'],\n ...encodingOptions,\n })) {\n batch.del<StorageKey>(key, { ...encodingOptions });\n }\n await batch.write();\n }\n}\n\nconst keyEncoder: MixedEncoding<StorageKey, Uint8Array, StorageKey> = {\n encode: (key: StorageKey): Uint8Array =>\n Buffer.from(key.map((k) => k.replaceAll('%', '%25').replaceAll('-', '%2D')).join('-')),\n decode: (key: Uint8Array): StorageKey =>\n Buffer.from(key)\n .toString()\n .split('-')\n .map((k) => k.replaceAll('%2D', '-').replaceAll('%25', '%')),\n format: 'buffer',\n};\n\nexport const encodingOptions = {\n keyEncoding: keyEncoder,\n valueEncoding: 'buffer',\n};\n\nconst isLevelDbNotFoundError = (err: any): boolean => err.code === 'LEVEL_NOT_FOUND';\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport {\n type AutomergeReplicator,\n type AutomergeReplicatorFactory,\n} from '@dxos/teleport-extension-automerge-replicator';\nimport { ComplexMap, ComplexSet, defaultMap } from '@dxos/util';\n\nimport { type EchoReplicator, type EchoReplicatorContext, type ShouldAdvertiseParams } from './echo-replicator';\nimport { MeshReplicatorConnection } from './mesh-echo-replicator-connection';\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(extensionFactory?: AutomergeReplicatorFactory): AutomergeReplicator {\n invariant(this._context);\n\n const connection: MeshReplicatorConnection = new MeshReplicatorConnection({\n ownPeerId: this._context.peerId,\n replicatorFactory: extensionFactory,\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 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 connection.disable();\n this._connections.delete(connection);\n },\n shouldAdvertise: async (params: ShouldAdvertiseParams) => {\n log('shouldAdvertise', { 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 if (this._connectionsPerPeer.has(connection.peerId)) {\n this._context?.onConnectionAuthScopeChanged(connection);\n }\n }\n }\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { cbor, type Message } from '@dxos/automerge/automerge-repo';\nimport { Resource } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { type PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { AutomergeReplicator, type AutomergeReplicatorFactory } from '@dxos/teleport-extension-automerge-replicator';\n\nimport type { ReplicatorConnection, ShouldAdvertiseParams } from './echo-replicator';\n\nconst DEFAULT_FACTORY: AutomergeReplicatorFactory = (params) => new AutomergeReplicator(...params);\n\nexport type MeshReplicatorConnectionParams = {\n ownPeerId: string;\n onRemoteConnected: () => void;\n onRemoteDisconnected: () => void;\n shouldAdvertise: (params: ShouldAdvertiseParams) => Promise<boolean>;\n replicatorFactory?: AutomergeReplicatorFactory;\n};\n\nexport class 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 invariant(this._isEnabled, 'Writing to a disabled connection');\n try {\n await this.replicatorExtension.sendSyncMessage({ payload: cbor.encode(message) });\n } catch (err) {\n controller.error(err);\n this._disconnectIfEnabled();\n }\n },\n });\n\n const createAutomergeReplicator = this._params.replicatorFactory ?? DEFAULT_FACTORY;\n this.replicatorExtension = createAutomergeReplicator([\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 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 this._disconnectIfEnabled();\n },\n },\n ]);\n }\n\n private _disconnectIfEnabled() {\n if (this._isEnabled) {\n this._params.onRemoteDisconnected();\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 shouldAdvertise(params: ShouldAdvertiseParams): Promise<boolean> {\n return this._params.shouldAdvertise(params);\n }\n\n /**\n * Start exchanging messages with the remote peer.\n * Call after the remote peer has connected.\n */\n 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 disable() {\n this._isEnabled = false;\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,SAASA,OAAOC,oBAAoB;AACpC,SACEC,QAAQC,WACRC,YACAC,UACAC,aACAC,UAAUC,aACVC,YAGK;AACP,SAEEC,YAMK;AACP,SAASC,SAASC,YAAAA,WAAUC,yBAAyC;AAGrE,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,iBAAiB;AAE1B,SAASC,OAAAA,YAAW;AACpB,SAASC,0BAA0B;AAEnC,SAASC,aAAa;AACtB,SAASC,iBAAiB;;;AC9B1B,SAASC,cAAcC,eAAe;AACtC,SAAuBC,sBAAsD;AAC7E,SAASC,sBAAsB;AAC/B,SAASC,iBAAiB;AAE1B,SAASC,WAAW;;;;;;;;;;;;AAWb,IAAMC,qBAAN,cAAiCJ,eAAAA;EAStCK,YAA6BC,SAAmC;AAC9D,UAAK;SADsBA,UAAAA;SARZC,eAAe,oBAAIC,IAAAA;SAInBC,eAAe,oBAAIC,IAAAA;SAC5BC,kBAAkCV,eAAeW;SACxCC,aAAa,IAAId,QAAAA;EAIlC;EAESe,QAAQC,QAAgBC,cAA+C;AAC9E,SAAKD,SAASA;AACd,SAAKC,eAAeA;AACpB,SAAKH,WAAWI,KAAI;EACtB;EAESC,KAAKC,SAAwB;AACpC,UAAMC,kBAAkB,KAAKX,aAAaY,IAAIF,QAAQG,QAAQ;AAC9D,QAAI,CAACF,iBAAiB;AACpB,YAAM,IAAIG,MAAM,uBAAA;IAClB;AAGAH,oBAAgBI,OAAOC,MAAMN,OAAAA,EAASO,MAAM,CAACC,QAAAA;AAC3C,UAAIP,gBAAgBQ,QAAQ;AAC1BzB,YAAIuB,MAAMC,KAAAA,QAAAA;;;;;;MACZ;IACF,CAAA;EACF;EAESE,aAAmB;EAE5B;EAEA,MACMC,OAAO;AACX,QAAI,KAAKnB,oBAAoBV,eAAe8B,MAAM;AAChD;IACF;AACA,SAAKpB,kBAAkBV,eAAe8B;AAEtC5B,QAAI,cAAA,QAAA;;;;;;AACJ,SAAK6B,KAAK,SAAS;MACjBC,SAAS;IACX,CAAA;EACF;EAEA,MACMC,QAAQ;AACZ,QAAI,KAAKvB,oBAAoBV,eAAeW,QAAQ;AAClD,aAAO;IACT;AAEA,eAAWuB,cAAc,KAAK5B,cAAc;AAC1C,YAAM4B,WAAWN,WAAU;IAC7B;AACA,SAAKtB,aAAa6B,MAAK;AAEvB,SAAKzB,kBAAkBV,eAAeW;EACxC;EAEA,MAAMyB,gBAAgB;AACpB,UAAM,KAAKxB,WAAWyB,KAAK;MAAEC,SAAS;IAAO,CAAA;EAC/C;EAEA,MACMC,cAAcL,YAA4B;AAC9CjC,cAAU,KAAKS,oBAAoBV,eAAe8B,MAAI,QAAA;;;;;;;;;AACtD7B,cAAU,KAAKa,QAAM,QAAA;;;;;;;;;AACrBb,cAAU,CAAC,KAAKK,aAAakC,IAAIN,UAAAA,GAAAA,QAAAA;;;;;;;;;AAEjC,SAAK5B,aAAamC,IAAIP,UAAAA;AACtB,UAAMA,WAAWrB,QAAQ;MACvBC,QAAQ,KAAKA;MACb4B,kBAAkB,KAAKC,kBAAkBC,KAAK,IAAI;MAClDC,oBAAoB,KAAKC,oBAAoBF,KAAK,IAAI;MACtDG,8BAA8B,KAAKC,8BAA8BJ,KAAK,IAAI;MAC1EK,+BAA+B,KAAK5C,QAAQ4C;IAC9C,CAAA;EACF;EAEA,MACMC,iBAAiBhB,YAA4B;AACjDjC,cAAU,KAAKS,oBAAoBV,eAAe8B,MAAI,QAAA;;;;;;;;;AACtD7B,cAAU,KAAKK,aAAakC,IAAIN,UAAAA,GAAAA,QAAAA;;;;;;;;;AAChC,UAAMA,WAAWN,WAAU;AAC3B,SAAKtB,aAAa6C,OAAOjB,UAAAA;EAC3B;EAEA,MAAMkB,gBAAgBtC,QAAgBuC,QAAiD;AACrF,UAAMC,aAAa,KAAK9C,aAAaY,IAAIN,MAAAA;AACzC,QAAI,CAACwC,YAAY;AACf,aAAO;IACT;AAEA,WAAOA,WAAWA,WAAWF,gBAAgBC,MAAAA;EAC/C;EAEQV,kBAAkBW,YAAkC;AAC1DpD,QAAI,qBAAqB;MAAEY,QAAQwC,WAAWxC;IAAO,GAAA;;;;;;AACrDb,cAAU,CAAC,KAAKO,aAAagC,IAAIc,WAAWxC,MAAM,GAAA,QAAA;;;;;;;;;AAClD,UAAMyC,SAASD,WAAWE,SAASC,UAAS;AAC5C,UAAMlC,SAAS+B,WAAWI,SAASC,UAAS;AAC5C,UAAMxC,kBAAmC;MAAEmC;MAAYC;MAAQhC;MAAQI,QAAQ;IAAK;AACpF,SAAKnB,aAAaoD,IAAIN,WAAWxC,QAAkBK,eAAAA;AAEnD0C,mBAAe,YAAA;AACb,UAAI;AACF,eAAO,MAAM;AAEX,gBAAM,EAAEC,MAAMC,MAAK,IAAK,MAAMR,OAAOS,KAAI;AACzC,cAAIF,MAAM;AACR;UACF;AAEA,eAAK/B,KAAK,WAAWgC,KAAAA;QACvB;MACF,SAASrC,KAAK;AACZ,YAAIP,gBAAgBQ,QAAQ;AAC1BzB,cAAIuB,MAAMC,KAAAA,QAAAA;;;;;;QACZ;MACF;IACF,CAAA;AAEAxB,QAAI,uBAAuB;MAAEY,QAAQwC,WAAWxC;IAAO,GAAA;;;;;;AACvD,SAAKmD,mBAAmBX,UAAAA;EAC1B;;;;;EAMQN,8BAA8BM,YAAkC;AACtEpD,QAAI,iCAAiC;MAAEY,QAAQwC,WAAWxC;IAAO,GAAA;;;;;;AACjE,UAAMoD,QAAQ,KAAK1D,aAAaY,IAAIkC,WAAWxC,MAAM;AACrDb,cAAUiE,OAAAA,QAAAA;;;;;;;;;AACV,SAAKnC,KAAK,qBAAqB;MAAEjB,QAAQwC,WAAWxC;IAAiB,CAAA;AACrE,SAAKmD,mBAAmBX,UAAAA;EAC1B;EAEQR,oBAAoBQ,YAAkC;AAC5DpD,QAAI,qBAAqB;MAAEY,QAAQwC,WAAWxC;IAAO,GAAA;;;;;;AACrD,UAAMoD,QAAQ,KAAK1D,aAAaY,IAAIkC,WAAWxC,MAAM;AACrDb,cAAUiE,OAAAA,QAAAA;;;;;;;;;AAEVA,UAAMvC,SAAS;AACf,SAAKI,KAAK,qBAAqB;MAAEjB,QAAQwC,WAAWxC;IAAiB,CAAA;AAErE,SAAKoD,MAAMX,OAAOY,OAAM,EAAG1C,MAAM,CAACC,QAAQxB,IAAIuB,MAAMC,KAAAA,QAAAA;;;;;;AACpD,SAAKwC,MAAM3C,OAAO6C,MAAK,EAAG3C,MAAM,CAACC,QAAQxB,IAAIuB,MAAMC,KAAAA,QAAAA;;;;;;AAEnD,SAAKlB,aAAa2C,OAAOG,WAAWxC,MAAM;EAC5C;EAEQmD,mBAAmBX,YAAkC;AAC3D,SAAKvB,KAAK,kBAAkB;MAC1BjB,QAAQwC,WAAWxC;MACnBC,cAAcsD,uBAAAA;IAChB,CAAA;EACF;AACF;;EA9HGxE;GArCUM,mBAAAA,WAAAA,QAAAA,IAAAA;;EAkDVN;GAlDUM,mBAAAA,WAAAA,SAAAA,IAAAA;;EAoEVN;GApEUM,mBAAAA,WAAAA,iBAAAA,IAAAA;;EAoFVN;GApFUM,mBAAAA,WAAAA,oBAAAA,IAAAA;AA4KN,IAAMkE,yBAAyB,OACnC;;EAECC,iBAAiB;AACnB;AAEK,IAAMC,qBAAqB,CAACC,aAChCA,UAAkBF,oBAAoB;;;ACjMzC,SAASG,qBAAqB;AAOvB,IAAMC,aAAN,MAAMA;EAGXC,YAAY,EAAEC,GAAE,GAAsB;AACpC,SAAKC,MAAMD;EACb;EAEAE,SAASC,YAAwBC,OAAcC,OAAmB;AAChEA,UAAMC,IAAuBH,YAAYC,OAAO;MAC9CG,UAAU,KAAKN;MACfO,aAAa;MACbC,eAAeC;IACjB,CAAA;EACF;EAEA,MAAMC,SAASR,YAAoD;AACjE,QAAI;AACF,aAAO,MAAM,KAAKF,IAAIW,IAAuBT,YAAY;QAAEK,aAAa;QAAQC,eAAeC;MAAc,CAAA;IAC/G,SAASG,KAAU;AACjB,UAAIA,IAAIC,UAAU;AAChB,eAAOC;MACT;AACA,YAAMF;IACR;EACF;AACF;;;AC/BA,SAASG,kBAAAA,iBAAgBC,gBAAgB;AAgBlC,IAAMC,wBAAN,cAAoCC,SAAAA;EACzCC,YAA6BC,SAAsC;AACjE,UAAK;SADsBA,UAAAA;EAE7B;EAEA,MAAMC,KAAKC,UAAuD;AAChE,QAAI;AACF,UAAI,KAAKC,oBAAoBC,gBAAeC,MAAM;AAEhD,eAAOC;MACT;AACA,aAAO,MAAM,KAAKN,QAAQO,GAAGC,IAA4BN,UAAU;QAAE,GAAGO;MAAgB,CAAA;IAC1F,SAASC,KAAU;AACjB,UAAIC,uBAAuBD,GAAAA,GAAM;AAC/B,eAAOJ;MACT;AACA,YAAMI;IACR;EACF;EAEA,MAAME,KAAKV,UAAsBW,QAAmC;AAClE,QAAI,KAAKV,oBAAoBC,gBAAeC,MAAM;AAChD,aAAOC;IACT;AACA,UAAMQ,QAAQ,KAAKd,QAAQO,GAAGO,MAAK;AAEnC,UAAM,KAAKd,QAAQe,WAAWC,aAAa;MAAEC,MAAMf;MAAUY;IAAM,CAAA;AACnEA,UAAMI,IAA4BhB,UAAUiB,OAAOC,KAAKP,MAAAA,GAAS;MAC/D,GAAGJ;IACL,CAAA;AACA,UAAMK,MAAMO,MAAK;AAEjB,UAAM,KAAKrB,QAAQe,WAAWO,YAAYpB,QAAAA;EAC5C;EAEA,MAAMqB,OAAOrB,UAAqC;AAChD,QAAI,KAAKC,oBAAoBC,gBAAeC,MAAM;AAChD,aAAOC;IACT;AACA,UAAM,KAAKN,QAAQO,GAAGiB,IAAgBtB,UAAU;MAAE,GAAGO;IAAgB,CAAA;EACvE;EAEA,MAAMgB,UAAUC,WAAyC;AACvD,QAAI,KAAKvB,oBAAoBC,gBAAeC,MAAM;AAChD,aAAO,CAAA;IACT;AACA,UAAMsB,SAAkB,CAAA;AACxB,qBAAiB,CAACC,KAAKC,KAAAA,KAAU,KAAK7B,QAAQO,GAAGuB,SAAiC;MAChFC,KAAKL;MACLM,KAAK;WAAIN;QAAW;;MACpB,GAAGjB;IACL,CAAA,GAAI;AACFkB,aAAOM,KAAK;QACVL;QACAM,MAAML;MACR,CAAA;IACF;AACA,WAAOF;EACT;EAEA,MAAMQ,YAAYT,WAAsC;AACtD,QAAI,KAAKvB,oBAAoBC,gBAAeC,MAAM;AAChD,aAAOC;IACT;AACA,UAAMQ,QAAQ,KAAKd,QAAQO,GAAGO,MAAK;AAEnC,qBAAiB,CAACc,GAAAA,KAAQ,KAAK5B,QAAQO,GAAGuB,SAAiC;MACzEC,KAAKL;MACLM,KAAK;WAAIN;QAAW;;MACpB,GAAGjB;IACL,CAAA,GAAI;AACFK,YAAMU,IAAgBI,KAAK;QAAE,GAAGnB;MAAgB,CAAA;IAClD;AACA,UAAMK,MAAMO,MAAK;EACnB;AACF;AAEA,IAAMe,aAAgE;EACpEC,QAAQ,CAACT,QACPT,OAAOC,KAAKQ,IAAIU,IAAI,CAACC,MAAMA,EAAEC,WAAW,KAAK,KAAA,EAAOA,WAAW,KAAK,KAAA,CAAA,EAAQC,KAAK,GAAA,CAAA;EACnFC,QAAQ,CAACd,QACPT,OAAOC,KAAKQ,GAAAA,EACTe,SAAQ,EACRC,MAAM,GAAA,EACNN,IAAI,CAACC,MAAMA,EAAEC,WAAW,OAAO,GAAA,EAAKA,WAAW,OAAO,GAAA,CAAA;EAC3DK,QAAQ;AACV;AAEO,IAAMpC,kBAAkB;EAC7BqC,aAAaV;EACbW,eAAe;AACjB;AAEA,IAAMpC,yBAAyB,CAACD,QAAsBA,IAAIsC,SAAS;;;;;;;;;;;;;;AHtD5D,IAAMC,gBAAN,cAA4BC,UAAAA;EAcjCC,YAAY,EAAEC,IAAIC,mBAAkB,GAAyB;AAC3D,UAAK;AAZUC,+BAAsB,IAAIC,mBAAmB;MAC5DC,+BAA+B,KAAKC,+BAA+BC,KAAK,IAAI;IAC9E,CAAA;AAWE,SAAKC,MAAMP;AACX,SAAKQ,WAAW,IAAIC,sBAAsB;MACxCT,IAAIA,GAAGU,SAAS,WAAA;MAChBC,WAAW;QACTC,YAAY,OAAOC,WAAW,KAAKC,YAAYD,MAAAA;QAC/CE,WAAW,YAAY,KAAKC,WAAU;MACxC;IACF,CAAA;AACA,SAAKC,cAAc,IAAIC,WAAW;MAAElB,IAAIA,GAAGU,SAAS,OAAA;IAAS,CAAA;AAC7D,SAAKS,sBAAsBlB;EAC7B;EAEA,MAAyBmB,QAAQ;AAE/B,SAAKC,UAAU,QAAQC,UAAUC,OAAM,EAAGC,MAAK,CAAA;AAE/C,UAAM,KAAKhB,SAASiB,OAAI;AAGxB,SAAKC,QAAQ,IAAIC,KAAK;MACpBC,QAAQ,KAAKP;MACbQ,aAAa,KAAKC,aAAaxB,KAAK,IAAI;MACxCyB,SAAS,KAAKvB;MACdwB,SAAS;;QAEP,KAAK9B;;IAET,CAAA;AAEA,UAAM,KAAKA,oBAAoBuB,KAAI;AACnC,UAAM,KAAKvB,oBAAoB+B,cAAa;EAC9C;EAEA,MAAyBC,SAAS;AAChC,UAAM,KAAK1B,SAAS2B,QAAK;AACzB,UAAM,KAAKjC,oBAAoBiC,MAAK;AACpC,UAAM,KAAKC,KAAKC,QAAO;EACzB;;;;EAKA,IAAIC,OAAa;AACf,WAAO,KAAKZ;EACd;EAEA,IAAIa,kBAA0B;AAC5B,WAAOC,OAAOC,KAAK,KAAKf,MAAMgB,OAAO,EAAEC;EACzC;EAEA,MAAMC,cAAcC,YAA4B;AAC9C,UAAM,KAAK3C,oBAAoB0C,cAAcC,UAAAA;EAC/C;EAEA,MAAMC,iBAAiBD,YAA4B;AACjD,UAAM,KAAK3C,oBAAoB4C,iBAAiBD,UAAAA;EAClD;;;;EAKA,MAAME,QAAWC,KAAcC,YAA2BC,MAA8C;AACtG,QAAIC;AACJ,QAAI,OAAOF,eAAe,UAAU;AAElCE,eAAS,KAAKzB,MAAMgB,QAAQO,UAAAA;IAC9B;AACA,QAAI,CAACE,QAAQ;AACXA,eAAS,KAAKzB,MAAM0B,KAAKH,UAAAA;IAC3B;AAGA,QAAI,CAACE,OAAOE,QAAO,GAAI;AACrB,UAAI,CAACH,MAAMI,SAAS;AAClB,cAAMC,kBAAkBP,KAAKG,OAAOK,UAAS,CAAA;MAC/C,OAAO;AACL,cAAMD,kBAAkBP,KAAKS,aAAaN,OAAOK,UAAS,GAAIN,KAAKI,OAAO,CAAA;MAC5E;IACF;AAEA,WAAOH;EACT;;;;EAKAO,UAAaC,cAA2BT,MAAuC;AAC7E,QAAIA,MAAMU,iBAAiB;AACzB,UAAI,CAACC,YAAYF,YAAAA,GAAe;AAC9B,cAAM,IAAIG,UAAU,6CAAA;MACtB;AAEA,aAAO,KAAKpC,MAAMqC,OAAOC,KAAKL,YAAAA,CAAAA;IAChC,OAAO;AACL,aAAO,KAAKjC,MAAMuC,OAAON,YAAAA;IAC3B;EACF;EAEA,MAAMO,yBAAyBC,OAAoC;AACjE,UAAMC,QAAQC,IACZF,MAAMG,SAASC,IAAI,OAAO,EAAEtB,YAAYkB,OAAAA,OAAK,MAAE;AAC7C,UAAI,CAACA,UAASA,OAAMxB,WAAW,GAAG;AAChC;MACF;AAEA,YAAM6B,eAAe,KAAKC,SAASxB,UAAAA;AACnC,UAAIuB,iBAAiB,QAAQE,YAAYF,cAAcL,MAAAA,GAAQ;AAC7D;MACF;AAEA,YAAMhB,SAAS,MAAM,KAAKJ,QAAQ4B,QAAQC,QAAO,QAAA;;;UAAI3B,UAAAA;AACrD,YAAM4B,aAAa1B,QAAQgB,MAAAA;IAC7B,CAAA,KAAM,CAAA,CAAE;AAIV,UAAM,KAAKzC,MAAMoD,MAAOX,MAAMG,SAASC,IAAI,CAACQ,UAAUA,MAAM9B,UAAU,KAAK,CAAA,CAAE;EAC/E;EAEA,MAAM+B,aAAaC,aAA2B;AAC5C,eAAWhC,cAAcgC,aAAa;AACpCC,MAAAA,KAAIC,KAAK,kCAAkC;QAAElC;MAAW,GAAA;;;;;;AACxD,YAAME,SAAS,KAAKzB,MAAM0B,KAAKH,UAAAA;AAC/B,YAAME,OAAOK,UAAU;QAAC;QAAS;OAAa;AAC9C,UAAIL,OAAOiC,QAAQ;QAAC;OAAa,GAAG;AAClCF,QAAAA,KAAIG,KAAK,+CAA+C;UAAEpC;QAAW,GAAA;;;;;;AACrE;MACF;AAEA,YAAMqC,MAAMnC,OAAOoC,QAAO;AAC1BC,MAAAA,WAAUF,KAAAA,QAAAA;;;;;;;;;AAEV,YAAMnB,QAAQM,SAASa,GAAAA;AACvB,YAAMG,QAAQ,KAAKlF,IAAIkF,MAAK;AAC5B,WAAKxE,YAAYyE,SAASzC,YAAYkB,OAAOsB,KAAAA;AAC7C,YAAMA,MAAME,MAAK;IACnB;AACAT,IAAAA,KAAIC,KAAK,0BAAA,QAAA;;;;;;EACX;;;;;EAMA,MAAcrD,aAAaF,QAAgBqB,YAA2C;AACpF,QAAIrB,OAAOgE,WAAW,SAAA,GAAY;AAChC,aAAO;IACT;AAEA,QAAI,CAAC3C,YAAY;AACf,aAAO;IACT;AAEA,UAAM4C,eAAe,KAAKvD,KAAKwD,qBAAqBlE,MAAAA;AACpD,QAAImE,mBAAmBF,YAAAA,GAAe;AACpC,aAAO,KAAK3F,oBAAoB8F,gBAAgBpE,QAAQ;QAAEqB;MAAW,CAAA;IACvE;AAEA,WAAO;EACT;EAEA,MAAcnC,YAAY,EAAEmF,MAAMR,MAAK,GAAsB;AAC3D,UAAMtC,SAAS,KAAKzB,MAAMgB,QAAQuD,KAAK,CAAA,CAAE;AACzC,QAAI,CAAC9C,QAAQ;AACX;IACF;AACA,UAAMmC,MAAMnC,OAAOoC,QAAO;AAC1B,QAAI,CAACD,KAAK;AACR;IACF;AAEA,UAAMY,WAAWC,mBAAmBb,GAAAA,KAAQc;AAE5C,UAAMjC,QAAQM,SAASa,GAAAA;AAEvB,SAAKrE,YAAYyE,SAASvC,OAAOF,YAAYkB,OAAOsB,KAAAA;AAEpD,UAAMY,YAAY7D,OAAOC,KAAK6C,IAAIgB,WAAW,CAAC,CAAA;AAC9C,UAAMC,aAAaF,UAAU9B,IAAI,CAACiC,aAChCC,mBAAmBC,OAAO;MAAEzD,YAAYE,OAAOF;MAAYuD;MAAUN;IAAS,CAAA,CAAA;AAEhF,UAAMS,eAAe,IAAIC,IAAIL,WAAWhC,IAAI,CAACsC,OAAO;MAACA;MAAI1C;KAAM,CAAA;AAC/D,SAAKhD,oBAAoB2F,UAAUH,cAAclB,KAAAA;EACnD;;;;EAKA,MAAczE,aAAa;AACzB,SAAKG,oBAAoB4F,kBAAiB;EAC5C;EAGQC,iBAAiB;AACvB,WAAOC,UAAU,KAAKvF,MAAMgB,SAAS,CAACS,YAAY;MAChD+D,OAAO/D,OAAO+D;MACdC,QAAQ,CAAC,CAAChE,OAAOoC,QAAO;MACxBpB,OAAOhB,OAAOoC,QAAO,IAAK6B,UAAU3C,SAAStB,OAAOoC,QAAO,CAAA,IAAM;MACjE8B,MACElE,OAAOoC,QAAO,KACd0B,UAAU9D,OAAOoC,QAAO,GAAI,CAAC+B,OAAOC,QAAAA;AAClC,YAAI;AACF,kBAAQA,KAAAA;YACN,KAAK;YACL,KAAK;AACH,qBAAOD;YACT,KAAK;AACH,qBAAO9E,OAAOC,KAAK6E,KAAAA;YACrB;AACE,qBAAO,GAAGA,KAAAA;UACd;QACF,SAASE,KAAK;AACZ,iBAAO,GAAGA,GAAAA;QACZ;MACF,CAAA;IACJ,EAAA;EACF;EAGQC,kBAAkB;AACxB,WAAO,KAAK/F,MAAMgG;EACpB;EAEA,MAAcrH,+BAA+B4C,YAA+C;AAC1F,UAAMqC,MAAM,KAAK5D,MAAMgB,QAAQO,UAAAA,GAAoBsC,QAAAA;AACnD,QAAI,CAACD,KAAK;AACR,aAAO;IACT;AAEA,UAAMqC,cAAcxB,mBAAmBb,GAAAA;AACvC,QAAI,CAACqC,aAAa;AAChB,aAAO;IACT;AAEA,WAAOrG,UAAUsG,KAAKD,WAAAA;EACxB;;;;EAKA,MACM7C,MAAM,EAAEG,YAAW,IAAmB,CAAC,GAAkB;AAG7D,UAAM,KAAKvD,MAAMoD,MAAMG,WAAAA;EACzB;EAEA,MAAMR,SAASxB,YAAoD;AACjE,UAAME,SAAS,KAAKzB,MAAMgB,QAAQO,UAAAA;AAClC,QAAIE,QAAQ;AACV,YAAMmC,MAAMnC,OAAOoC,QAAO;AAC1B,UAAI,CAACD,KAAK;AACR,eAAOc;MACT;AACA,aAAO3B,SAASa,GAAAA;IAClB,OAAO;AACL,aAAO,KAAKrE,YAAYwD,SAASxB,UAAAA;IACnC;EACF;AACF;;EAxQG4E,MAAM1C,KAAI;GAXAtF,cAAAA,WAAAA,WAAAA,MAAAA;;EAgNVgI,MAAM1C,KAAK;IAAE2C,OAAO;EAAK,CAAA;GAhNfjI,cAAAA,WAAAA,kBAAAA,IAAAA;;EA0OVgI,MAAM1C,KAAK;IAAE2C,OAAO;EAAK,CAAA;GA1OfjI,cAAAA,WAAAA,mBAAAA,IAAAA;;EAgQVgI,MAAME,KAAK;IAAEC,uBAAuB;EAAK,CAAA;GAhQ/BnI,cAAAA,WAAAA,SAAAA,IAAAA;AAAAA,gBAAAA,cAAAA;EADZgI,MAAMI,SAAQ;GACFpI,aAAAA;AAqRN,IAAMsG,qBAAqB,CAACb,QAAAA;AAEjC,QAAM4C,cAAc5C,IAAI6C,QAAQjC,YAAaZ,IAAY8C;AACzD,MAAIF,eAAe,MAAM;AACvB,WAAO;EACT;AAEA,SAAOG,OAAOH,WAAAA;AAChB;AAEA,IAAMrD,eAAe,OAAO1B,QAA6BgB,UAAAA;AACvD,QAAMmE,mBAAmB,IAAIC,IAAIpE,KAAAA;AAEjC,QAAMhB,OAAOK,UAAS;AACtB,QAAMgF,MAAMC,KAAuCtF,QAAQ,QAAA,EAAUuF,iBAAiB,MAAA;AAEpF,eAAWC,cAAcL,iBAAiBM,OAAM,GAAI;AAClD,UAAIC,qBAAqB1F,OAAOoC,QAAO,GAAIoD,UAAAA,GAAa;AACtDL,yBAAiBQ,OAAOH,UAAAA;MAC1B;IACF;AAEA,WAAOL,iBAAiBS,SAAS;EACnC,CAAA;AACF;AAEA,IAAMF,uBAAuB,CAACvD,KAAeqD,eAAAA;AAC3C,SAAO,CAAC,CAACK,WAAW1D,GAAAA,EAAK2D,gBAAgBN,UAAAA;AAC3C;;;AI3WA,SAASO,aAAAA,kBAAiB;AAC1B,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,OAAAA,YAAW;AAKpB,SAASC,YAAYC,YAAYC,kBAAkB;;;ACPnD,SAASC,YAA0B;AACnC,SAASC,YAAAA,iBAAgB;AACzB,SAASC,aAAAA,kBAAiB;AAE1B,SAASC,OAAAA,YAAW;AACpB,SAASC,2BAA4D;;AAIrE,IAAMC,kBAA8C,CAACC,WAAW,IAAIF,oBAAAA,GAAuBE,MAAAA;AAUpF,IAAMC,2BAAN,cAAuCN,UAAAA;EAU5CO,YAA6BC,SAAyC;AACpE,UAAK;SADsBA,UAAAA;SAPtBC,kBAAoC;SAInCC,gBAA+B;SAC/BC,aAAa;AAKnB,QAAIC;AACJ,SAAKC,WAAW,IAAIC,eAAwB;MAC1CC,OAAO,CAACC,eAAAA;AACNJ,mCAA2BI;AAC3B,aAAKC,KAAKC,UAAU,MAAMF,WAAWG,MAAK,CAAA;MAC5C;IACF,CAAA;AAEA,SAAKC,WAAW,IAAIC,eAAwB;MAC1CC,OAAO,OAAOC,SAAkBP,eAAAA;AAC9Bf,QAAAA,WAAU,KAAKU,YAAY,oCAAA;;;;;;;;;AAC3B,YAAI;AACF,gBAAM,KAAKa,oBAAoBC,gBAAgB;YAAEC,SAAS3B,KAAK4B,OAAOJ,OAAAA;UAAS,CAAA;QACjF,SAASK,KAAK;AACZZ,qBAAWa,MAAMD,GAAAA;AACjB,eAAKE,qBAAoB;QAC3B;MACF;IACF,CAAA;AAEA,UAAMC,4BAA4B,KAAKvB,QAAQwB,qBAAqB5B;AACpE,SAAKoB,sBAAsBO,0BAA0B;MACnD;QACEE,QAAQ,KAAKzB,QAAQ0B;MACvB;MACA;QACEC,oBAAoB,OAAOC,MAAMC,iBAA6B;AAa5D,eAAK5B,kBAAkB4B;AAGvB,eAAK3B,gBAAgB0B,KAAKE;AAE1BpC,UAAAA,KAAI,sBAAsB;YAAEoC,IAAIF,KAAKE;YAAIC,YAAY,KAAKN;YAAQI,cAAcA,aAAaG,MAAK;UAAG,GAAA;;;;;;AAErG,eAAKhC,QAAQiC,kBAAiB;QAChC;QACAC,eAAe,OAAO,EAAEhB,QAAO,MAAE;AAC/B,cAAI,CAAC,KAAKf,YAAY;AACpB;UACF;AACA,gBAAMY,UAAUxB,KAAK4C,OAAOjB,OAAAA;AAE5Bd,mCAAyBgC,QAAQrB,OAAAA;QACnC;QACAsB,SAAS,YAAA;AACP,eAAKf,qBAAoB;QAC3B;MACF;KACD;EACH;EAEQA,uBAAuB;AAC7B,QAAI,KAAKnB,YAAY;AACnB,WAAKH,QAAQsC,qBAAoB;IACnC;EACF;EAEA,IAAIb,SAAiB;AACnBhC,IAAAA,WAAU,KAAKS,iBAAiB,MAAM,sCAAA;;;;;;;;;AACtC,WAAO,KAAKA;EACd;EAEA,MAAMqC,gBAAgB1C,QAAiD;AACrE,WAAO,KAAKG,QAAQuC,gBAAgB1C,MAAAA;EACtC;;;;;EAMA2C,SAAS;AACP/C,IAAAA,WAAU,KAAKS,iBAAiB,MAAM,sCAAA;;;;;;;;;AACtC,SAAKC,aAAa;EACpB;;;;EAKAsC,UAAU;AACR,SAAKtC,aAAa;EACpB;AACF;;;;AD5GO,IAAMuC,qBAAN,MAAMA;EAAN;AACYC,wBAAe,oBAAIC,IAAAA;AAInBC;;;+BAAsB,oBAAIC,IAAAA;AAK1BC;;;8BAAqB,IAAIC,WAA6CC,WAAUC,IAAI;AAE7FC,oBAAyC;;EAEjD,MAAMC,QAAQC,SAA+C;AAC3D,SAAKF,WAAWE;EAClB;EAEA,MAAMC,aAAa;AACjB,eAAWC,cAAc,KAAKZ,cAAc;AAC1C,YAAMY,WAAWC,MAAK;IACxB;AACA,SAAKb,aAAac,MAAK;AACvB,SAAKZ,oBAAoBY,MAAK;AAE9B,SAAKN,WAAW;EAClB;EAEAO,gBAAgBC,kBAAoE;AAClFC,IAAAA,WAAU,KAAKT,UAAQ,QAAA;;;;;;;;;AAEvB,UAAMI,aAAuC,IAAIM,yBAAyB;MACxEC,WAAW,KAAKX,SAASY;MACzBC,mBAAmBL;MACnBM,mBAAmB,YAAA;AACjBC,QAAAA,KAAI,qBAAqB;UAAEH,QAAQR,WAAWQ;QAAO,GAAA;;;;;;AACrDH,QAAAA,WAAU,KAAKT,UAAQ,QAAA;;;;;;;;;AAEvB,YAAI,KAAKN,oBAAoBsB,IAAIZ,WAAWQ,MAAM,GAAG;AACnD,eAAKZ,SAASiB,6BAA6Bb,UAAAA;QAC7C,OAAO;AACL,eAAKV,oBAAoBwB,IAAId,WAAWQ,QAAQR,UAAAA;AAChD,eAAKJ,SAASmB,iBAAiBf,UAAAA;AAC/BA,qBAAWgB,OAAM;QACnB;MACF;MACAC,sBAAsB,YAAA;AACpBN,QAAAA,KAAI,wBAAwB;UAAEH,QAAQR,WAAWQ;QAAO,GAAA;;;;;;AACxD,aAAKZ,UAAUsB,mBAAmBlB,UAAAA;AAClC,aAAKV,oBAAoB6B,OAAOnB,WAAWQ,MAAM;AACjDR,mBAAWoB,QAAO;AAClB,aAAKhC,aAAa+B,OAAOnB,UAAAA;MAC3B;MACAqB,iBAAiB,OAAOC,WAAAA;AACtBX,QAAAA,KAAI,mBAAmB;UAAEH,QAAQR,WAAWQ;UAAQe,YAAYD,OAAOC;QAAW,GAAA;;;;;;AAClFlB,QAAAA,WAAU,KAAKT,UAAQ,QAAA;;;;;;;;;AACvB,YAAI;AACF,gBAAM4B,WAAW,MAAM,KAAK5B,SAAS6B,8BAA8BH,OAAOC,UAAU;AACpF,cAAI,CAACC,UAAU;AACbb,YAAAA,KAAI,8CAA8C;cAChDH,QAAQR,WAAWQ;cACnBe,YAAYD,OAAOC;YACrB,GAAA;;;;;;AACA,mBAAO;UACT;AAEA,gBAAMG,oBAAoB,KAAKlC,mBAAmBmC,IAAIH,QAAAA;AAEtD,cAAI,CAACxB,WAAW4B,iBAAiB;AAC/BjB,YAAAA,KAAI,+CAA+C;cACjDH,QAAQR,WAAWQ;cACnBe,YAAYD,OAAOC;YACrB,GAAA;;;;;;AACA,mBAAO;UACT;AAEA,gBAAMM,eAAeH,mBAAmBd,IAAIZ,WAAW4B,eAAe,KAAK;AAC3EjB,UAAAA,KAAI,sBAAsB;YACxBmB,WAAW,KAAKlC,SAASY;YACzBuB,YAAY/B,WAAWQ;YACvBe,YAAYD,OAAOC;YACnBS,WAAWhC,WAAW4B;YACtBJ;YACAK;UACF,GAAA;;;;;;AACA,iBAAOA;QACT,SAASI,KAAK;AACZtB,UAAAA,KAAIuB,MAAMD,KAAAA,QAAAA;;;;;;AACV,iBAAO;QACT;MACF;IACF,CAAA;AACA,SAAK7C,aAAa+C,IAAInC,UAAAA;AAEtB,WAAOA,WAAWoC;EACpB;EAEAC,gBAAgBb,UAAqBQ,WAAsB;AACzDrB,IAAAA,KAAI,mBAAmB;MAAEa;MAAUQ;IAAU,GAAA;;;;;;AAC7CM,eAAW,KAAK9C,oBAAoBgC,UAAU,MAAM,IAAIe,WAAW7C,WAAUC,IAAI,CAAA,EAAGwC,IAAIH,SAAAA;AACxF,eAAWhC,cAAc,KAAKZ,cAAc;AAC1C,UAAIY,WAAW4B,mBAAmB5B,WAAW4B,gBAAgBY,OAAOR,SAAAA,GAAY;AAC9E,YAAI,KAAK1C,oBAAoBsB,IAAIZ,WAAWQ,MAAM,GAAG;AACnD,eAAKZ,UAAUiB,6BAA6Bb,UAAAA;QAC9C;MACF;IACF;EACF;AACF;",
|
|
6
|
-
"names": ["Event", "asyncTimeout", "next", "automerge", "getBackend", "getHeads", "isAutomerge", "equals", "headsEquals", "save", "Repo", "Context", "Resource", "cancelWithContext", "invariant", "PublicKey", "log", "objectPointerCodec", "trace", "mapValues", "synchronized", "Trigger", "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", "shouldAdvertise", "params", "connection", "reader", "readable", "getReader", "writable", "getWriter", "set", "queueMicrotask", "done", "value", "read", "_emitPeerCandidate", "entry", "cancel", "abort", "createEchoPeerMetadata", "dxos_peerSource", "isEchoPeerMetadata", "metadata", "headsEncoding", "HeadsStore", "constructor", "db", "_db", "setHeads", "documentId", "heads", "batch", "put", "sublevel", "keyEncoding", "valueEncoding", "headsEncoding", "getHeads", "get", "err", "notFound", "undefined", "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", "AutomergeHost", "Resource", "constructor", "db", "indexMetadataStore", "_echoNetworkAdapter", "EchoNetworkAdapter", "getContainingSpaceForDocument", "_getContainingSpaceForDocument", "bind", "_db", "_storage", "LevelDBStorageAdapter", "sublevel", "callbacks", "beforeSave", "params", "_beforeSave", "afterSave", "_afterSave", "_headsStore", "HeadsStore", "_indexMetadataStore", "_open", "_peerId", "PublicKey", "random", "toHex", "open", "_repo", "Repo", "peerId", "sharePolicy", "_sharePolicy", "storage", "network", "whenConnected", "_close", "close", "_ctx", "dispose", "repo", "loadedDocsCount", "Object", "keys", "handles", "length", "addReplicator", "replicator", "removeReplicator", "loadDoc", "ctx", "documentId", "opts", "handle", "find", "isReady", "timeout", "cancelWithContext", "whenReady", "asyncTimeout", "createDoc", "initialValue", "preserveHistory", "isAutomerge", "TypeError", "import", "save", "create", "waitUntilHeadsReplicated", "heads", "Promise", "all", "entries", "map", "currentHeads", "getHeads", "headsEquals", "Context", "default", "waitForHeads", "flush", "entry", "reIndexHeads", "documentIds", "log", "info", "inState", "warn", "doc", "docSync", "invariant", "batch", "setHeads", "write", "startsWith", "peerMetadata", "peerMetadataByPeerId", "isEchoPeerMetadata", "shouldAdvertise", "path", "spaceKey", "getSpaceKeyFromDoc", "undefined", "objectIds", "objects", "encodedIds", "objectId", "objectPointerCodec", "encode", "idToLastHash", "Map", "id", "markDirty", "notifyMarkedDirty", "_automergeDocs", "mapValues", "state", "hasDoc", "automerge", "data", "value", "key", "err", "_automergePeers", "peers", "spaceKeyHex", "from", "trace", "depth", "span", "showInBrowserTimeline", "resource", "rawSpaceKey", "access", "experimental_spaceKey", "String", "unavailableHeads", "Set", "Event", "wrap", "waitForCondition", "changeHash", "values", "changeIsPresentInDoc", "delete", "size", "getBackend", "getChangeByHash", "invariant", "PublicKey", "log", "ComplexMap", "ComplexSet", "defaultMap", "cbor", "Resource", "invariant", "log", "AutomergeReplicator", "DEFAULT_FACTORY", "params", "MeshReplicatorConnection", "constructor", "_params", "remoteDeviceKey", "_remotePeerId", "_isEnabled", "readableStreamController", "readable", "ReadableStream", "start", "controller", "_ctx", "onDispose", "close", "writable", "WritableStream", "write", "message", "replicatorExtension", "sendSyncMessage", "payload", "encode", "err", "error", "_disconnectIfEnabled", "createAutomergeReplicator", "replicatorFactory", "peerId", "ownPeerId", "onStartReplication", "info", "remotePeerId", "id", "thisPeerId", "toHex", "onRemoteConnected", "onSyncMessage", "decode", "enqueue", "onClose", "onRemoteDisconnected", "shouldAdvertise", "enable", "disable", "MeshEchoReplicator", "_connections", "Set", "_connectionsPerPeer", "Map", "_authorizedDevices", "ComplexMap", "PublicKey", "hash", "_context", "connect", "context", "disconnect", "connection", "close", "clear", "createExtension", "extensionFactory", "invariant", "MeshReplicatorConnection", "ownPeerId", "peerId", "replicatorFactory", "onRemoteConnected", "log", "has", "onConnectionAuthScopeChanged", "set", "onConnectionOpen", "enable", "onRemoteDisconnected", "
|
|
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 equals as headsEquals,\n save,\n type Doc,\n type Heads,\n} from '@dxos/automerge/automerge';\nimport {\n type DocHandleChangePayload,\n Repo,\n type AnyDocumentId,\n type DocHandle,\n type DocumentId,\n type PeerId,\n type StorageAdapterInterface,\n} from '@dxos/automerge/automerge-repo';\nimport { Context, Resource, cancelWithContext, type Lifecycle } from '@dxos/context';\nimport { type SpaceDoc } from '@dxos/echo-protocol';\nimport { type IndexMetadataStore } from '@dxos/indexing';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { type LevelDB } from '@dxos/kv-store';\nimport { log } from '@dxos/log';\nimport { objectPointerCodec } from '@dxos/protocols';\nimport { type DocHeadsList, type FlushRequest } 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 { HeadsStore } from './heads-store';\nimport { LevelDBStorageAdapter, type BeforeSaveParams } from './leveldb-storage-adapter';\n\nexport type AutomergeHostParams = {\n db: LevelDB;\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 extends Resource {\n private readonly _db: LevelDB;\n private readonly _indexMetadataStore: IndexMetadataStore;\n private readonly _echoNetworkAdapter = new EchoNetworkAdapter({\n getContainingSpaceForDocument: this._getContainingSpaceForDocument.bind(this),\n });\n\n private _repo!: Repo;\n private _storage!: StorageAdapterInterface & Lifecycle;\n private readonly _headsStore: HeadsStore;\n\n @trace.info()\n private _peerId!: string;\n\n constructor({ db, indexMetadataStore }: AutomergeHostParams) {\n super();\n this._db = db;\n this._storage = new LevelDBStorageAdapter({\n db: db.sublevel('automerge'),\n callbacks: {\n beforeSave: async (params) => this._beforeSave(params),\n afterSave: async () => this._afterSave(),\n },\n });\n this._headsStore = new HeadsStore({ db: db.sublevel('heads') });\n this._indexMetadataStore = indexMetadataStore;\n }\n\n protected override 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\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 // Upstream swarm.\n this._echoNetworkAdapter,\n ],\n });\n\n await this._echoNetworkAdapter.open();\n await this._echoNetworkAdapter.whenConnected();\n }\n\n protected override async _close() {\n await this._storage.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 get loadedDocsCount(): number {\n return Object.keys(this._repo.handles).length;\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 async waitUntilHeadsReplicated(heads: DocHeadsList): Promise<void> {\n await Promise.all(\n heads.entries?.map(async ({ documentId, heads }) => {\n if (!heads || heads.length === 0) {\n return;\n }\n\n const currentHeads = this.getHeads(documentId as DocumentId);\n if (currentHeads !== null && headsEquals(currentHeads, heads)) {\n return;\n }\n\n const handle = await this.loadDoc(Context.default(), documentId as DocumentId);\n await waitForHeads(handle, heads);\n }) ?? [],\n );\n\n // Flush to disk also so that the indexer can pick up the changes.\n await this._repo.flush((heads.entries?.map((entry) => entry.documentId) ?? []) as DocumentId[]);\n }\n\n async reIndexHeads(documentIds: DocumentId[]) {\n for (const documentId of documentIds) {\n log.info('re-indexing heads for document', { documentId });\n const handle = this._repo.find(documentId);\n await handle.whenReady(['ready', 'requesting']);\n if (handle.inState(['requesting'])) {\n log.warn('document is not available locally, skipping', { documentId });\n continue; // Handle not available locally.\n }\n\n const doc = handle.docSync();\n invariant(doc);\n\n const heads = getHeads(doc);\n const batch = this._db.batch();\n this._headsStore.setHeads(documentId, heads, batch);\n await batch.write();\n }\n log.info('done re-indexing heads');\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(peerId: PeerId, documentId?: DocumentId): 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.shouldAdvertise(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 heads = getHeads(doc);\n\n this._headsStore.setHeads(handle.documentId, heads, batch);\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, heads]));\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({ documentIds }: FlushRequest = {}): Promise<void> {\n // Note: Sync protocol for client and services ensures that all handles should have all changes.\n\n await this._repo.flush(documentIds as DocumentId[] | undefined);\n }\n\n async getHeads(documentId: DocumentId): Promise<Heads | undefined> {\n const handle = this._repo.handles[documentId];\n if (handle) {\n const doc = handle.docSync();\n if (!doc) {\n return undefined;\n }\n return getHeads(doc);\n } else {\n return this._headsStore.getHeads(documentId);\n }\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 const unavailableHeads = new Set(heads);\n\n await handle.whenReady();\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 return unavailableHeads.size === 0;\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 { synchronized, Trigger } 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 ShouldAdvertiseParams } 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 if (this._lifecycleState === LifecycleState.OPEN) {\n return;\n }\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 if (this._lifecycleState === LifecycleState.CLOSED) {\n return this;\n }\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 shouldAdvertise(peerId: PeerId, params: ShouldAdvertiseParams): Promise<boolean> {\n const connection = this._connections.get(peerId);\n if (!connection) {\n return false;\n }\n\n return connection.connection.shouldAdvertise(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//\n\nimport type { Heads } from '@dxos/automerge/automerge';\nimport type { DocumentId } from '@dxos/automerge/automerge-repo';\nimport { headsEncoding } from '@dxos/indexing';\nimport type { BatchLevel, SublevelDB } from '@dxos/kv-store';\n\nexport type HeadsStoreParams = {\n db: SublevelDB;\n};\n\nexport class HeadsStore {\n private readonly _db: SublevelDB;\n\n constructor({ db }: HeadsStoreParams) {\n this._db = db;\n }\n\n setHeads(documentId: DocumentId, heads: Heads, batch: BatchLevel) {\n batch.put<DocumentId, Heads>(documentId, heads, {\n sublevel: this._db,\n keyEncoding: 'utf8',\n valueEncoding: headsEncoding,\n });\n }\n\n async getHeads(documentId: DocumentId): Promise<Heads | undefined> {\n try {\n return await this._db.get<DocumentId, Heads>(documentId, { keyEncoding: 'utf8', valueEncoding: headsEncoding });\n } catch (err: any) {\n if (err.notFound) {\n return undefined;\n }\n throw err;\n }\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n// s\n\nimport { type MixedEncoding } from 'level-transcoder';\n\nimport { type StorageAdapterInterface, type Chunk, type StorageKey } from '@dxos/automerge/automerge-repo';\nimport { LifecycleState, Resource } from '@dxos/context';\nimport { type BatchLevel, type SublevelDB } from '@dxos/kv-store';\nimport { type MaybePromise } from '@dxos/util';\n\nexport type LevelDBStorageAdapterParams = {\n db: SublevelDB;\n callbacks?: StorageCallbacks;\n};\n\nexport type BeforeSaveParams = { path: StorageKey; batch: BatchLevel };\n\nexport interface StorageCallbacks {\n beforeSave(params: BeforeSaveParams): MaybePromise<void>;\n afterSave(path: StorageKey): MaybePromise<void>;\n}\n\nexport class LevelDBStorageAdapter extends Resource implements StorageAdapterInterface {\n constructor(private readonly _params: LevelDBStorageAdapterParams) {\n super();\n }\n\n async load(keyArray: StorageKey): Promise<Uint8Array | undefined> {\n try {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n // TODO(mykola): this should be an error.\n return undefined;\n }\n return await this._params.db.get<StorageKey, Uint8Array>(keyArray, { ...encodingOptions });\n } catch (err: any) {\n if (isLevelDbNotFoundError(err)) {\n return undefined;\n }\n throw err;\n }\n }\n\n async save(keyArray: StorageKey, binary: Uint8Array): Promise<void> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return undefined;\n }\n const batch = this._params.db.batch();\n\n await this._params.callbacks?.beforeSave?.({ path: keyArray, batch });\n batch.put<StorageKey, Uint8Array>(keyArray, Buffer.from(binary), {\n ...encodingOptions,\n });\n await batch.write();\n\n await this._params.callbacks?.afterSave?.(keyArray);\n }\n\n async remove(keyArray: StorageKey): Promise<void> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return undefined;\n }\n await this._params.db.del<StorageKey>(keyArray, { ...encodingOptions });\n }\n\n async loadRange(keyPrefix: StorageKey): Promise<Chunk[]> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return [];\n }\n const result: Chunk[] = [];\n for await (const [key, value] of this._params.db.iterator<StorageKey, Uint8Array>({\n gte: keyPrefix,\n lte: [...keyPrefix, '\\uffff'],\n ...encodingOptions,\n })) {\n result.push({\n key,\n data: value,\n });\n }\n return result;\n }\n\n async removeRange(keyPrefix: StorageKey): Promise<void> {\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return undefined;\n }\n const batch = this._params.db.batch();\n\n for await (const [key] of this._params.db.iterator<StorageKey, Uint8Array>({\n gte: keyPrefix,\n lte: [...keyPrefix, '\\uffff'],\n ...encodingOptions,\n })) {\n batch.del<StorageKey>(key, { ...encodingOptions });\n }\n await batch.write();\n }\n}\n\nconst keyEncoder: MixedEncoding<StorageKey, Uint8Array, StorageKey> = {\n encode: (key: StorageKey): Uint8Array =>\n Buffer.from(key.map((k) => k.replaceAll('%', '%25').replaceAll('-', '%2D')).join('-')),\n decode: (key: Uint8Array): StorageKey =>\n Buffer.from(key)\n .toString()\n .split('-')\n .map((k) => k.replaceAll('%2D', '-').replaceAll('%25', '%')),\n format: 'buffer',\n};\n\nexport const encodingOptions = {\n keyEncoding: keyEncoder,\n valueEncoding: 'buffer',\n};\n\nconst isLevelDbNotFoundError = (err: any): boolean => err.code === 'LEVEL_NOT_FOUND';\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport {\n type AutomergeReplicator,\n type AutomergeReplicatorFactory,\n} from '@dxos/teleport-extension-automerge-replicator';\nimport { ComplexMap, ComplexSet, defaultMap } from '@dxos/util';\n\nimport { type EchoReplicator, type EchoReplicatorContext, type ShouldAdvertiseParams } from './echo-replicator';\nimport { MeshReplicatorConnection } from './mesh-echo-replicator-connection';\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._connectionsPerPeer.values()) {\n this._context?.onConnectionClosed(connection);\n }\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(extensionFactory?: AutomergeReplicatorFactory): AutomergeReplicator {\n invariant(this._context);\n\n const connection: MeshReplicatorConnection = new MeshReplicatorConnection({\n ownPeerId: this._context.peerId,\n replicatorFactory: extensionFactory,\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 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 connection.disable();\n this._connections.delete(connection);\n },\n shouldAdvertise: async (params: ShouldAdvertiseParams) => {\n log('shouldAdvertise', { 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 if (this._connectionsPerPeer.has(connection.peerId)) {\n this._context?.onConnectionAuthScopeChanged(connection);\n }\n }\n }\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { cbor, type Message } from '@dxos/automerge/automerge-repo';\nimport { Resource } from '@dxos/context';\nimport { invariant } from '@dxos/invariant';\nimport { type PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { AutomergeReplicator, type AutomergeReplicatorFactory } from '@dxos/teleport-extension-automerge-replicator';\n\nimport type { ReplicatorConnection, ShouldAdvertiseParams } from './echo-replicator';\n\nconst DEFAULT_FACTORY: AutomergeReplicatorFactory = (params) => new AutomergeReplicator(...params);\n\nexport type MeshReplicatorConnectionParams = {\n ownPeerId: string;\n onRemoteConnected: () => void;\n onRemoteDisconnected: () => void;\n shouldAdvertise: (params: ShouldAdvertiseParams) => Promise<boolean>;\n replicatorFactory?: AutomergeReplicatorFactory;\n};\n\nexport class 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 invariant(this._isEnabled, 'Writing to a disabled connection');\n try {\n await this.replicatorExtension.sendSyncMessage({ payload: cbor.encode(message) });\n } catch (err) {\n controller.error(err);\n this._disconnectIfEnabled();\n }\n },\n });\n\n const createAutomergeReplicator = this._params.replicatorFactory ?? DEFAULT_FACTORY;\n this.replicatorExtension = createAutomergeReplicator([\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 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 this._disconnectIfEnabled();\n },\n },\n ]);\n }\n\n private _disconnectIfEnabled() {\n if (this._isEnabled) {\n this._params.onRemoteDisconnected();\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 shouldAdvertise(params: ShouldAdvertiseParams): Promise<boolean> {\n return this._params.shouldAdvertise(params);\n }\n\n /**\n * Start exchanging messages with the remote peer.\n * Call after the remote peer has connected.\n */\n 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 disable() {\n this._isEnabled = false;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Event", "asyncTimeout", "next", "automerge", "getBackend", "getHeads", "isAutomerge", "equals", "headsEquals", "save", "Repo", "Context", "Resource", "cancelWithContext", "invariant", "PublicKey", "log", "objectPointerCodec", "trace", "mapValues", "synchronized", "Trigger", "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", "shouldAdvertise", "params", "connection", "reader", "readable", "getReader", "writable", "getWriter", "set", "queueMicrotask", "done", "value", "read", "_emitPeerCandidate", "entry", "cancel", "abort", "createEchoPeerMetadata", "dxos_peerSource", "isEchoPeerMetadata", "metadata", "headsEncoding", "HeadsStore", "constructor", "db", "_db", "setHeads", "documentId", "heads", "batch", "put", "sublevel", "keyEncoding", "valueEncoding", "headsEncoding", "getHeads", "get", "err", "notFound", "undefined", "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", "AutomergeHost", "Resource", "constructor", "db", "indexMetadataStore", "_echoNetworkAdapter", "EchoNetworkAdapter", "getContainingSpaceForDocument", "_getContainingSpaceForDocument", "bind", "_db", "_storage", "LevelDBStorageAdapter", "sublevel", "callbacks", "beforeSave", "params", "_beforeSave", "afterSave", "_afterSave", "_headsStore", "HeadsStore", "_indexMetadataStore", "_open", "_peerId", "PublicKey", "random", "toHex", "open", "_repo", "Repo", "peerId", "sharePolicy", "_sharePolicy", "storage", "network", "whenConnected", "_close", "close", "_ctx", "dispose", "repo", "loadedDocsCount", "Object", "keys", "handles", "length", "addReplicator", "replicator", "removeReplicator", "loadDoc", "ctx", "documentId", "opts", "handle", "find", "isReady", "timeout", "cancelWithContext", "whenReady", "asyncTimeout", "createDoc", "initialValue", "preserveHistory", "isAutomerge", "TypeError", "import", "save", "create", "waitUntilHeadsReplicated", "heads", "Promise", "all", "entries", "map", "currentHeads", "getHeads", "headsEquals", "Context", "default", "waitForHeads", "flush", "entry", "reIndexHeads", "documentIds", "log", "info", "inState", "warn", "doc", "docSync", "invariant", "batch", "setHeads", "write", "startsWith", "peerMetadata", "peerMetadataByPeerId", "isEchoPeerMetadata", "shouldAdvertise", "path", "spaceKey", "getSpaceKeyFromDoc", "undefined", "objectIds", "objects", "encodedIds", "objectId", "objectPointerCodec", "encode", "idToLastHash", "Map", "id", "markDirty", "notifyMarkedDirty", "_automergeDocs", "mapValues", "state", "hasDoc", "automerge", "data", "value", "key", "err", "_automergePeers", "peers", "spaceKeyHex", "from", "trace", "depth", "span", "showInBrowserTimeline", "resource", "rawSpaceKey", "access", "experimental_spaceKey", "String", "unavailableHeads", "Set", "Event", "wrap", "waitForCondition", "changeHash", "values", "changeIsPresentInDoc", "delete", "size", "getBackend", "getChangeByHash", "invariant", "PublicKey", "log", "ComplexMap", "ComplexSet", "defaultMap", "cbor", "Resource", "invariant", "log", "AutomergeReplicator", "DEFAULT_FACTORY", "params", "MeshReplicatorConnection", "constructor", "_params", "remoteDeviceKey", "_remotePeerId", "_isEnabled", "readableStreamController", "readable", "ReadableStream", "start", "controller", "_ctx", "onDispose", "close", "writable", "WritableStream", "write", "message", "replicatorExtension", "sendSyncMessage", "payload", "encode", "err", "error", "_disconnectIfEnabled", "createAutomergeReplicator", "replicatorFactory", "peerId", "ownPeerId", "onStartReplication", "info", "remotePeerId", "id", "thisPeerId", "toHex", "onRemoteConnected", "onSyncMessage", "decode", "enqueue", "onClose", "onRemoteDisconnected", "shouldAdvertise", "enable", "disable", "MeshEchoReplicator", "_connections", "Set", "_connectionsPerPeer", "Map", "_authorizedDevices", "ComplexMap", "PublicKey", "hash", "_context", "connect", "context", "disconnect", "connection", "values", "onConnectionClosed", "close", "clear", "createExtension", "extensionFactory", "invariant", "MeshReplicatorConnection", "ownPeerId", "peerId", "replicatorFactory", "onRemoteConnected", "log", "has", "onConnectionAuthScopeChanged", "set", "onConnectionOpen", "enable", "onRemoteDisconnected", "delete", "disable", "shouldAdvertise", "params", "documentId", "spaceKey", "getContainingSpaceForDocument", "authorizedDevices", "get", "remoteDeviceKey", "isAuthorized", "localPeer", "remotePeer", "deviceKey", "err", "catch", "add", "replicatorExtension", "authorizeDevice", "defaultMap", "ComplexSet", "equals"]
|
|
7
7
|
}
|