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