@dxos/echo-pipeline 0.5.3-main.59db342 → 0.5.3-main.61bbff4
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-VUJXFVSK.mjs} +49 -30
- package/dist/lib/browser/{chunk-VQQD32DM.mjs.map → chunk-VUJXFVSK.mjs.map} +3 -3
- package/dist/lib/browser/index.mjs +435 -288
- 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-6733E3WM.cjs} +50 -32
- package/dist/lib/node/{chunk-P7L7ICAH.cjs.map → chunk-6733E3WM.cjs.map} +3 -3
- package/dist/lib/node/index.cjs +446 -299
- 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/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 +62 -88
- 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 +232 -0
- package/src/automerge/migrations.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/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-VUJXFVSK.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
|
|
34
|
+
import { log as log3 } from "@dxos/log";
|
|
35
35
|
import { idCodec } 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) {
|
|
@@ -927,14 +806,25 @@ var AutomergeHost = class {
|
|
|
927
806
|
_automergePeers() {
|
|
928
807
|
return this._repo.peers;
|
|
929
808
|
}
|
|
809
|
+
async _getContainingSpaceForDocument(documentId) {
|
|
810
|
+
const doc = this._repo.handles[documentId]?.docSync();
|
|
811
|
+
if (!doc) {
|
|
812
|
+
return null;
|
|
813
|
+
}
|
|
814
|
+
const spaceKeyHex = getSpaceKeyFromDoc(doc);
|
|
815
|
+
if (!spaceKeyHex) {
|
|
816
|
+
return null;
|
|
817
|
+
}
|
|
818
|
+
return PublicKey.from(spaceKeyHex);
|
|
819
|
+
}
|
|
930
820
|
//
|
|
931
821
|
// Methods for client-services.
|
|
932
822
|
//
|
|
933
823
|
async flush({ states }) {
|
|
934
824
|
await Promise.all(states?.map(async ({ heads, documentId }) => {
|
|
935
|
-
|
|
936
|
-
F:
|
|
937
|
-
L:
|
|
825
|
+
invariant3(heads, "heads are required for flush", {
|
|
826
|
+
F: __dxlog_file4,
|
|
827
|
+
L: 239,
|
|
938
828
|
S: this,
|
|
939
829
|
A: [
|
|
940
830
|
"heads",
|
|
@@ -955,24 +845,6 @@ var AutomergeHost = class {
|
|
|
955
845
|
async getHostInfo() {
|
|
956
846
|
return this._clientNetwork.getHostInfo();
|
|
957
847
|
}
|
|
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
848
|
};
|
|
977
849
|
_ts_decorate2([
|
|
978
850
|
trace.info()
|
|
@@ -1025,8 +897,8 @@ var changeIsPresentInDoc = (doc, changeHash) => {
|
|
|
1025
897
|
import { Event as Event2 } from "@dxos/async";
|
|
1026
898
|
import { cancelWithContext } from "@dxos/context";
|
|
1027
899
|
import { warnAfterTimeout } from "@dxos/debug";
|
|
1028
|
-
import { invariant as
|
|
1029
|
-
import { log as
|
|
900
|
+
import { invariant as invariant4 } from "@dxos/invariant";
|
|
901
|
+
import { log as log4 } from "@dxos/log";
|
|
1030
902
|
import { trace as trace2 } from "@dxos/tracing";
|
|
1031
903
|
function _ts_decorate3(decorators, target, key, desc) {
|
|
1032
904
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -1038,7 +910,7 @@ function _ts_decorate3(decorators, target, key, desc) {
|
|
|
1038
910
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1039
911
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1040
912
|
}
|
|
1041
|
-
var
|
|
913
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-doc-loader.ts";
|
|
1042
914
|
var AutomergeDocumentLoaderImpl = class {
|
|
1043
915
|
constructor(_spaceKey, _repo) {
|
|
1044
916
|
this._spaceKey = _spaceKey;
|
|
@@ -1059,10 +931,10 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1059
931
|
return;
|
|
1060
932
|
}
|
|
1061
933
|
if (!spaceState.rootUrl) {
|
|
1062
|
-
|
|
934
|
+
log4.error("Database opened with no rootUrl", {
|
|
1063
935
|
spaceKey: this._spaceKey
|
|
1064
936
|
}, {
|
|
1065
|
-
F:
|
|
937
|
+
F: __dxlog_file5,
|
|
1066
938
|
L: 70,
|
|
1067
939
|
S: this,
|
|
1068
940
|
C: (f, a) => f(...a)
|
|
@@ -1071,8 +943,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1071
943
|
} else {
|
|
1072
944
|
const existingDocHandle = await this._initDocHandle(ctx, spaceState.rootUrl);
|
|
1073
945
|
const doc = existingDocHandle.docSync();
|
|
1074
|
-
|
|
1075
|
-
F:
|
|
946
|
+
invariant4(doc, void 0, {
|
|
947
|
+
F: __dxlog_file5,
|
|
1076
948
|
L: 75,
|
|
1077
949
|
S: this,
|
|
1078
950
|
A: [
|
|
@@ -1093,8 +965,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1093
965
|
let hasUrlsToLoad = false;
|
|
1094
966
|
const urlsToLoad = {};
|
|
1095
967
|
for (const objectId of objectIds) {
|
|
1096
|
-
|
|
1097
|
-
F:
|
|
968
|
+
invariant4(this._spaceRootDocHandle, void 0, {
|
|
969
|
+
F: __dxlog_file5,
|
|
1098
970
|
L: 88,
|
|
1099
971
|
S: this,
|
|
1100
972
|
A: [
|
|
@@ -1106,8 +978,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1106
978
|
continue;
|
|
1107
979
|
}
|
|
1108
980
|
const spaceRootDoc = this._spaceRootDocHandle.docSync();
|
|
1109
|
-
|
|
1110
|
-
F:
|
|
981
|
+
invariant4(spaceRootDoc, void 0, {
|
|
982
|
+
F: __dxlog_file5,
|
|
1111
983
|
L: 93,
|
|
1112
984
|
S: this,
|
|
1113
985
|
A: [
|
|
@@ -1118,10 +990,10 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1118
990
|
const documentUrl = (spaceRootDoc.links ?? {})[objectId];
|
|
1119
991
|
if (documentUrl == null) {
|
|
1120
992
|
this._objectsPendingDocumentLoad.add(objectId);
|
|
1121
|
-
|
|
993
|
+
log4.info("loading delayed until object links are initialized", {
|
|
1122
994
|
objectId
|
|
1123
995
|
}, {
|
|
1124
|
-
F:
|
|
996
|
+
F: __dxlog_file5,
|
|
1125
997
|
L: 97,
|
|
1126
998
|
S: this,
|
|
1127
999
|
C: (f, a) => f(...a)
|
|
@@ -1144,8 +1016,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1144
1016
|
linksAwaitingLoad.forEach(([objectId]) => this._objectsPendingDocumentLoad.delete(objectId));
|
|
1145
1017
|
}
|
|
1146
1018
|
getSpaceRootDocHandle() {
|
|
1147
|
-
|
|
1148
|
-
F:
|
|
1019
|
+
invariant4(this._spaceRootDocHandle, void 0, {
|
|
1020
|
+
F: __dxlog_file5,
|
|
1149
1021
|
L: 120,
|
|
1150
1022
|
S: this,
|
|
1151
1023
|
A: [
|
|
@@ -1156,8 +1028,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1156
1028
|
return this._spaceRootDocHandle;
|
|
1157
1029
|
}
|
|
1158
1030
|
createDocumentForObject(objectId) {
|
|
1159
|
-
|
|
1160
|
-
F:
|
|
1031
|
+
invariant4(this._spaceRootDocHandle, void 0, {
|
|
1032
|
+
F: __dxlog_file5,
|
|
1161
1033
|
L: 125,
|
|
1162
1034
|
S: this,
|
|
1163
1035
|
A: [
|
|
@@ -1196,11 +1068,11 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1196
1068
|
};
|
|
1197
1069
|
const objectDocumentHandle = this._objectDocumentHandles.get(objectId);
|
|
1198
1070
|
if (objectDocumentHandle != null && objectDocumentHandle.url !== automergeUrl) {
|
|
1199
|
-
|
|
1071
|
+
log4.warn("object already inlined in a different document, ignoring the link", {
|
|
1200
1072
|
...logMeta,
|
|
1201
1073
|
actualDocumentUrl: objectDocumentHandle.url
|
|
1202
1074
|
}, {
|
|
1203
|
-
F:
|
|
1075
|
+
F: __dxlog_file5,
|
|
1204
1076
|
L: 155,
|
|
1205
1077
|
S: this,
|
|
1206
1078
|
C: (f, a) => f(...a)
|
|
@@ -1208,8 +1080,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1208
1080
|
continue;
|
|
1209
1081
|
}
|
|
1210
1082
|
if (objectDocumentHandle?.url === automergeUrl) {
|
|
1211
|
-
|
|
1212
|
-
F:
|
|
1083
|
+
log4.warn("object document was already loaded", logMeta, {
|
|
1084
|
+
F: __dxlog_file5,
|
|
1213
1085
|
L: 162,
|
|
1214
1086
|
S: this,
|
|
1215
1087
|
C: (f, a) => f(...a)
|
|
@@ -1217,8 +1089,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1217
1089
|
continue;
|
|
1218
1090
|
}
|
|
1219
1091
|
const handle = this._repo.find(automergeUrl);
|
|
1220
|
-
|
|
1221
|
-
F:
|
|
1092
|
+
log4.debug("document loading triggered", logMeta, {
|
|
1093
|
+
F: __dxlog_file5,
|
|
1222
1094
|
L: 166,
|
|
1223
1095
|
S: this,
|
|
1224
1096
|
C: (f, a) => f(...a)
|
|
@@ -1237,11 +1109,11 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1237
1109
|
break;
|
|
1238
1110
|
} catch (err) {
|
|
1239
1111
|
if (`${err}`.includes("Timeout")) {
|
|
1240
|
-
|
|
1112
|
+
log4.info("wraparound", {
|
|
1241
1113
|
id: docHandle.documentId,
|
|
1242
1114
|
state: docHandle.state
|
|
1243
1115
|
}, {
|
|
1244
|
-
F:
|
|
1116
|
+
F: __dxlog_file5,
|
|
1245
1117
|
L: 182,
|
|
1246
1118
|
S: this,
|
|
1247
1119
|
C: (f, a) => f(...a)
|
|
@@ -1282,8 +1154,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1282
1154
|
docUrl: handle.url
|
|
1283
1155
|
};
|
|
1284
1156
|
if (this.onObjectDocumentLoaded.listenerCount() === 0) {
|
|
1285
|
-
|
|
1286
|
-
F:
|
|
1157
|
+
log4.info("document loaded after all listeners were removed", logMeta, {
|
|
1158
|
+
F: __dxlog_file5,
|
|
1287
1159
|
L: 218,
|
|
1288
1160
|
S: this,
|
|
1289
1161
|
C: (f, a) => f(...a)
|
|
@@ -1292,8 +1164,8 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1292
1164
|
}
|
|
1293
1165
|
const objectDocHandle = this._objectDocumentHandles.get(objectId);
|
|
1294
1166
|
if (objectDocHandle?.url !== handle.url) {
|
|
1295
|
-
|
|
1296
|
-
F:
|
|
1167
|
+
log4.warn("object was rebound while a document was loading, discarding handle", logMeta, {
|
|
1168
|
+
F: __dxlog_file5,
|
|
1297
1169
|
L: 223,
|
|
1298
1170
|
S: this,
|
|
1299
1171
|
C: (f, a) => f(...a)
|
|
@@ -1306,13 +1178,13 @@ var AutomergeDocumentLoaderImpl = class {
|
|
|
1306
1178
|
});
|
|
1307
1179
|
} catch (err) {
|
|
1308
1180
|
const shouldRetryLoading = this.onObjectDocumentLoaded.listenerCount() > 0;
|
|
1309
|
-
|
|
1181
|
+
log4.warn("failed to load a document", {
|
|
1310
1182
|
objectId,
|
|
1311
1183
|
automergeUrl: handle.url,
|
|
1312
1184
|
retryLoading: shouldRetryLoading,
|
|
1313
1185
|
err
|
|
1314
1186
|
}, {
|
|
1315
|
-
F:
|
|
1187
|
+
F: __dxlog_file5,
|
|
1316
1188
|
L: 229,
|
|
1317
1189
|
S: this,
|
|
1318
1190
|
C: (f, a) => f(...a)
|
|
@@ -1331,6 +1203,281 @@ _ts_decorate3([
|
|
|
1331
1203
|
AutomergeDocumentLoaderImpl = _ts_decorate3([
|
|
1332
1204
|
trace2.resource()
|
|
1333
1205
|
], AutomergeDocumentLoaderImpl);
|
|
1206
|
+
|
|
1207
|
+
// packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts
|
|
1208
|
+
import { cbor as cbor2 } from "@dxos/automerge/automerge-repo";
|
|
1209
|
+
import { Resource as Resource2 } from "@dxos/context";
|
|
1210
|
+
import { invariant as invariant5 } from "@dxos/invariant";
|
|
1211
|
+
import { PublicKey as PublicKey2 } from "@dxos/keys";
|
|
1212
|
+
import { log as log5 } from "@dxos/log";
|
|
1213
|
+
import { AutomergeReplicator } from "@dxos/teleport-extension-automerge-replicator";
|
|
1214
|
+
import { ComplexMap, ComplexSet, defaultMap } from "@dxos/util";
|
|
1215
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-echo-replicator.ts";
|
|
1216
|
+
var MeshEchoReplicator = class {
|
|
1217
|
+
constructor() {
|
|
1218
|
+
this._connections = /* @__PURE__ */ new Set();
|
|
1219
|
+
/**
|
|
1220
|
+
* Using automerge peerId as a key.
|
|
1221
|
+
*/
|
|
1222
|
+
this._connectionsPerPeer = /* @__PURE__ */ new Map();
|
|
1223
|
+
/**
|
|
1224
|
+
* spaceKey -> deviceKey[]
|
|
1225
|
+
*/
|
|
1226
|
+
this._authorizedDevices = new ComplexMap(PublicKey2.hash);
|
|
1227
|
+
this._context = null;
|
|
1228
|
+
}
|
|
1229
|
+
async connect(context) {
|
|
1230
|
+
this._context = context;
|
|
1231
|
+
}
|
|
1232
|
+
async disconnect() {
|
|
1233
|
+
for (const connection of this._connections) {
|
|
1234
|
+
await connection.close();
|
|
1235
|
+
}
|
|
1236
|
+
this._connections.clear();
|
|
1237
|
+
this._connectionsPerPeer.clear();
|
|
1238
|
+
this._context = null;
|
|
1239
|
+
}
|
|
1240
|
+
createExtension() {
|
|
1241
|
+
invariant5(this._context, void 0, {
|
|
1242
|
+
F: __dxlog_file6,
|
|
1243
|
+
L: 54,
|
|
1244
|
+
S: this,
|
|
1245
|
+
A: [
|
|
1246
|
+
"this._context",
|
|
1247
|
+
""
|
|
1248
|
+
]
|
|
1249
|
+
});
|
|
1250
|
+
const connection = new MeshReplicatorConnection({
|
|
1251
|
+
ownPeerId: this._context.peerId,
|
|
1252
|
+
onRemoteConnected: async () => {
|
|
1253
|
+
log5("onRemoteConnected", {
|
|
1254
|
+
peerId: connection.peerId
|
|
1255
|
+
}, {
|
|
1256
|
+
F: __dxlog_file6,
|
|
1257
|
+
L: 59,
|
|
1258
|
+
S: this,
|
|
1259
|
+
C: (f, a) => f(...a)
|
|
1260
|
+
});
|
|
1261
|
+
invariant5(this._context, void 0, {
|
|
1262
|
+
F: __dxlog_file6,
|
|
1263
|
+
L: 60,
|
|
1264
|
+
S: this,
|
|
1265
|
+
A: [
|
|
1266
|
+
"this._context",
|
|
1267
|
+
""
|
|
1268
|
+
]
|
|
1269
|
+
});
|
|
1270
|
+
if (!this._connectionsPerPeer.has(connection.peerId)) {
|
|
1271
|
+
this._connectionsPerPeer.set(connection.peerId, connection);
|
|
1272
|
+
await connection.enable();
|
|
1273
|
+
this._context.onConnectionOpen(connection);
|
|
1274
|
+
}
|
|
1275
|
+
},
|
|
1276
|
+
onRemoteDisconnected: async () => {
|
|
1277
|
+
log5("onRemoteDisconnected", {
|
|
1278
|
+
peerId: connection.peerId
|
|
1279
|
+
}, {
|
|
1280
|
+
F: __dxlog_file6,
|
|
1281
|
+
L: 69,
|
|
1282
|
+
S: this,
|
|
1283
|
+
C: (f, a) => f(...a)
|
|
1284
|
+
});
|
|
1285
|
+
invariant5(this._context, void 0, {
|
|
1286
|
+
F: __dxlog_file6,
|
|
1287
|
+
L: 70,
|
|
1288
|
+
S: this,
|
|
1289
|
+
A: [
|
|
1290
|
+
"this._context",
|
|
1291
|
+
""
|
|
1292
|
+
]
|
|
1293
|
+
});
|
|
1294
|
+
this._context.onConnectionClosed(connection);
|
|
1295
|
+
await connection.disable();
|
|
1296
|
+
this._connectionsPerPeer.delete(connection.peerId);
|
|
1297
|
+
this._connections.delete(connection);
|
|
1298
|
+
},
|
|
1299
|
+
shouldAdvertize: async (params) => {
|
|
1300
|
+
log5("shouldAdvertize", {
|
|
1301
|
+
peerId: connection.peerId,
|
|
1302
|
+
documentId: params.documentId
|
|
1303
|
+
}, {
|
|
1304
|
+
F: __dxlog_file6,
|
|
1305
|
+
L: 77,
|
|
1306
|
+
S: this,
|
|
1307
|
+
C: (f, a) => f(...a)
|
|
1308
|
+
});
|
|
1309
|
+
invariant5(this._context, void 0, {
|
|
1310
|
+
F: __dxlog_file6,
|
|
1311
|
+
L: 78,
|
|
1312
|
+
S: this,
|
|
1313
|
+
A: [
|
|
1314
|
+
"this._context",
|
|
1315
|
+
""
|
|
1316
|
+
]
|
|
1317
|
+
});
|
|
1318
|
+
try {
|
|
1319
|
+
const spaceKey = await this._context.getContainingSpaceForDocument(params.documentId);
|
|
1320
|
+
if (!spaceKey) {
|
|
1321
|
+
log5("space key not found for share policy check", {
|
|
1322
|
+
peerId: connection.peerId,
|
|
1323
|
+
documentId: params.documentId
|
|
1324
|
+
}, {
|
|
1325
|
+
F: __dxlog_file6,
|
|
1326
|
+
L: 82,
|
|
1327
|
+
S: this,
|
|
1328
|
+
C: (f, a) => f(...a)
|
|
1329
|
+
});
|
|
1330
|
+
return false;
|
|
1331
|
+
}
|
|
1332
|
+
const authorizedDevices = this._authorizedDevices.get(spaceKey);
|
|
1333
|
+
if (!connection.remoteDeviceKey) {
|
|
1334
|
+
log5("device key not found for share policy check", {
|
|
1335
|
+
peerId: connection.peerId,
|
|
1336
|
+
documentId: params.documentId
|
|
1337
|
+
}, {
|
|
1338
|
+
F: __dxlog_file6,
|
|
1339
|
+
L: 92,
|
|
1340
|
+
S: this,
|
|
1341
|
+
C: (f, a) => f(...a)
|
|
1342
|
+
});
|
|
1343
|
+
return false;
|
|
1344
|
+
}
|
|
1345
|
+
const isAuthorized = authorizedDevices?.has(connection.remoteDeviceKey) ?? false;
|
|
1346
|
+
log5("share policy check", {
|
|
1347
|
+
localPeer: this._context.peerId,
|
|
1348
|
+
remotePeer: connection.peerId,
|
|
1349
|
+
documentId: params.documentId,
|
|
1350
|
+
deviceKey: connection.remoteDeviceKey,
|
|
1351
|
+
spaceKey,
|
|
1352
|
+
isAuthorized
|
|
1353
|
+
}, {
|
|
1354
|
+
F: __dxlog_file6,
|
|
1355
|
+
L: 100,
|
|
1356
|
+
S: this,
|
|
1357
|
+
C: (f, a) => f(...a)
|
|
1358
|
+
});
|
|
1359
|
+
return isAuthorized;
|
|
1360
|
+
} catch (err) {
|
|
1361
|
+
log5.catch(err, void 0, {
|
|
1362
|
+
F: __dxlog_file6,
|
|
1363
|
+
L: 110,
|
|
1364
|
+
S: this,
|
|
1365
|
+
C: (f, a) => f(...a)
|
|
1366
|
+
});
|
|
1367
|
+
return false;
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
});
|
|
1371
|
+
this._connections.add(connection);
|
|
1372
|
+
return connection.replicatorExtension;
|
|
1373
|
+
}
|
|
1374
|
+
authorizeDevice(spaceKey, deviceKey) {
|
|
1375
|
+
log5("authorizeDevice", {
|
|
1376
|
+
spaceKey,
|
|
1377
|
+
deviceKey
|
|
1378
|
+
}, {
|
|
1379
|
+
F: __dxlog_file6,
|
|
1380
|
+
L: 121,
|
|
1381
|
+
S: this,
|
|
1382
|
+
C: (f, a) => f(...a)
|
|
1383
|
+
});
|
|
1384
|
+
defaultMap(this._authorizedDevices, spaceKey, () => new ComplexSet(PublicKey2.hash)).add(deviceKey);
|
|
1385
|
+
}
|
|
1386
|
+
};
|
|
1387
|
+
var MeshReplicatorConnection = class extends Resource2 {
|
|
1388
|
+
constructor(_params) {
|
|
1389
|
+
super();
|
|
1390
|
+
this._params = _params;
|
|
1391
|
+
this.remoteDeviceKey = null;
|
|
1392
|
+
this._remotePeerId = null;
|
|
1393
|
+
this._isEnabled = false;
|
|
1394
|
+
let readableStreamController;
|
|
1395
|
+
this.readable = new ReadableStream({
|
|
1396
|
+
start: (controller) => {
|
|
1397
|
+
readableStreamController = controller;
|
|
1398
|
+
this._ctx.onDispose(() => controller.close());
|
|
1399
|
+
}
|
|
1400
|
+
});
|
|
1401
|
+
this.writable = new WritableStream({
|
|
1402
|
+
write: async (message, controller) => {
|
|
1403
|
+
this.replicatorExtension.sendSyncMessage({
|
|
1404
|
+
payload: cbor2.encode(message)
|
|
1405
|
+
}).catch((err) => {
|
|
1406
|
+
controller.error(err);
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1409
|
+
});
|
|
1410
|
+
this.replicatorExtension = new AutomergeReplicator({
|
|
1411
|
+
peerId: this._params.ownPeerId
|
|
1412
|
+
}, {
|
|
1413
|
+
onStartReplication: async (info, remotePeerId) => {
|
|
1414
|
+
this.remoteDeviceKey = remotePeerId;
|
|
1415
|
+
this._remotePeerId = info.id;
|
|
1416
|
+
log5("onStartReplication", {
|
|
1417
|
+
id: info.id,
|
|
1418
|
+
thisPeerId: this.peerId,
|
|
1419
|
+
remotePeerId: remotePeerId.toHex()
|
|
1420
|
+
}, {
|
|
1421
|
+
F: __dxlog_file6,
|
|
1422
|
+
L: 186,
|
|
1423
|
+
S: this,
|
|
1424
|
+
C: (f, a) => f(...a)
|
|
1425
|
+
});
|
|
1426
|
+
await this._params.onRemoteConnected();
|
|
1427
|
+
},
|
|
1428
|
+
onSyncMessage: async ({ payload }) => {
|
|
1429
|
+
if (!this._isEnabled) {
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
const message = cbor2.decode(payload);
|
|
1433
|
+
readableStreamController.enqueue(message);
|
|
1434
|
+
},
|
|
1435
|
+
onClose: async () => {
|
|
1436
|
+
if (!this._isEnabled) {
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1439
|
+
await this._params.onRemoteDisconnected();
|
|
1440
|
+
}
|
|
1441
|
+
});
|
|
1442
|
+
}
|
|
1443
|
+
get peerId() {
|
|
1444
|
+
invariant5(this._remotePeerId != null, "Remote peer has not connected yet.", {
|
|
1445
|
+
F: __dxlog_file6,
|
|
1446
|
+
L: 209,
|
|
1447
|
+
S: this,
|
|
1448
|
+
A: [
|
|
1449
|
+
"this._remotePeerId != null",
|
|
1450
|
+
"'Remote peer has not connected yet.'"
|
|
1451
|
+
]
|
|
1452
|
+
});
|
|
1453
|
+
return this._remotePeerId;
|
|
1454
|
+
}
|
|
1455
|
+
async shouldAdvertize(params) {
|
|
1456
|
+
return this._params.shouldAdvertize(params);
|
|
1457
|
+
}
|
|
1458
|
+
/**
|
|
1459
|
+
* Start exchanging messages with the remote peer.
|
|
1460
|
+
* Call after the remote peer has connected.
|
|
1461
|
+
*/
|
|
1462
|
+
async enable() {
|
|
1463
|
+
invariant5(this._remotePeerId != null, "Remote peer has not connected yet.", {
|
|
1464
|
+
F: __dxlog_file6,
|
|
1465
|
+
L: 222,
|
|
1466
|
+
S: this,
|
|
1467
|
+
A: [
|
|
1468
|
+
"this._remotePeerId != null",
|
|
1469
|
+
"'Remote peer has not connected yet.'"
|
|
1470
|
+
]
|
|
1471
|
+
});
|
|
1472
|
+
this._isEnabled = true;
|
|
1473
|
+
}
|
|
1474
|
+
/**
|
|
1475
|
+
* Stop exchanging messages with the remote peer.
|
|
1476
|
+
*/
|
|
1477
|
+
async disable() {
|
|
1478
|
+
this._isEnabled = false;
|
|
1479
|
+
}
|
|
1480
|
+
};
|
|
1334
1481
|
export {
|
|
1335
1482
|
AuthExtension,
|
|
1336
1483
|
AuthStatus,
|
|
@@ -1342,7 +1489,7 @@ export {
|
|
|
1342
1489
|
LocalHostNetworkAdapter,
|
|
1343
1490
|
MOCK_AUTH_PROVIDER,
|
|
1344
1491
|
MOCK_AUTH_VERIFIER,
|
|
1345
|
-
|
|
1492
|
+
MeshEchoReplicator,
|
|
1346
1493
|
MetadataStore,
|
|
1347
1494
|
Pipeline,
|
|
1348
1495
|
SnapshotManager,
|