@dxos/echo-pipeline 0.3.11-main.c8e9429 → 0.3.11-main.cb8120f
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-44D2XTQP.mjs → chunk-PB5T4DLC.mjs} +151 -23
- package/dist/lib/browser/{chunk-44D2XTQP.mjs.map → chunk-PB5T4DLC.mjs.map} +3 -3
- package/dist/lib/browser/index.mjs +1 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +2 -2
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-PZONK23P.cjs → chunk-WGNVVL2H.cjs} +149 -25
- package/dist/lib/node/{chunk-PZONK23P.cjs.map → chunk-WGNVVL2H.cjs.map} +3 -3
- package/dist/lib/node/index.cjs +26 -28
- package/dist/lib/node/index.cjs.map +2 -2
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +17 -17
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/types/src/automerge/automerge-host.d.ts +24 -2
- package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
- package/dist/types/src/automerge/index.d.ts +1 -1
- package/dist/types/src/automerge/index.d.ts.map +1 -1
- package/dist/types/src/space/space-manager.d.ts +2 -2
- package/dist/types/src/space/space-manager.d.ts.map +1 -1
- package/package.json +33 -33
- package/src/automerge/automerge-host.test.ts +291 -34
- package/src/automerge/automerge-host.ts +110 -16
- package/src/automerge/index.ts +1 -1
- package/src/space/space-manager.ts +3 -3
- package/src/testing/test-agent-builder.ts +1 -1
|
@@ -2685,7 +2685,7 @@ var SpaceManager = class {
|
|
|
2685
2685
|
...this._spaces.values()
|
|
2686
2686
|
].map((space) => space.close()));
|
|
2687
2687
|
}
|
|
2688
|
-
async constructSpace({ metadata, swarmIdentity,
|
|
2688
|
+
async constructSpace({ metadata, swarmIdentity, onAuthorizedConnection, onAuthFailure, memberKey }) {
|
|
2689
2689
|
log12.trace("dxos.echo.space-manager.construct-space", trace4.begin({
|
|
2690
2690
|
id: this._instanceId
|
|
2691
2691
|
}), {
|
|
@@ -2708,7 +2708,7 @@ var SpaceManager = class {
|
|
|
2708
2708
|
topic: spaceKey,
|
|
2709
2709
|
swarmIdentity,
|
|
2710
2710
|
networkManager: this._networkManager,
|
|
2711
|
-
onSessionAuth:
|
|
2711
|
+
onSessionAuth: onAuthorizedConnection,
|
|
2712
2712
|
onAuthFailure,
|
|
2713
2713
|
blobStore: this._blobStore
|
|
2714
2714
|
});
|
|
@@ -2746,28 +2746,108 @@ SpaceManager = _ts_decorate8([
|
|
|
2746
2746
|
], SpaceManager);
|
|
2747
2747
|
|
|
2748
2748
|
// packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts
|
|
2749
|
+
import { Trigger as Trigger2 } from "@dxos/async";
|
|
2749
2750
|
import { Repo, NetworkAdapter, StorageAdapter, cbor } from "@dxos/automerge/automerge-repo";
|
|
2750
2751
|
import { IndexedDBStorageAdapter } from "@dxos/automerge/automerge-repo-storage-indexeddb";
|
|
2751
2752
|
import { Stream as Stream2 } from "@dxos/codec-protobuf";
|
|
2752
2753
|
import { invariant as invariant10 } from "@dxos/invariant";
|
|
2754
|
+
import { PublicKey as PublicKey8 } from "@dxos/keys";
|
|
2753
2755
|
import { log as log13 } from "@dxos/log";
|
|
2754
2756
|
import { StorageType } from "@dxos/random-access-storage";
|
|
2755
2757
|
import { AutomergeReplicator } from "@dxos/teleport-extension-automerge-replicator";
|
|
2756
|
-
import { arrayToBuffer as arrayToBuffer2, bufferToArray } from "@dxos/util";
|
|
2758
|
+
import { ComplexMap as ComplexMap7, ComplexSet, arrayToBuffer as arrayToBuffer2, bufferToArray, defaultMap } from "@dxos/util";
|
|
2757
2759
|
var __dxlog_file14 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
|
|
2758
2760
|
var AutomergeHost = class {
|
|
2759
2761
|
constructor(storageDirectory) {
|
|
2762
|
+
/**
|
|
2763
|
+
* spaceKey -> deviceKey[]
|
|
2764
|
+
*/
|
|
2765
|
+
this._authorizedDevices = new ComplexMap7(PublicKey8.hash);
|
|
2760
2766
|
this._meshNetwork = new MeshNetworkAdapter();
|
|
2761
2767
|
this._clientNetwork = new LocalHostNetworkAdapter();
|
|
2762
2768
|
this._storage = storageDirectory.type === StorageType.IDB ? new IndexedDBStorageAdapter(storageDirectory.path, "data") : new AutomergeStorageAdapter(storageDirectory);
|
|
2763
2769
|
this._repo = new Repo({
|
|
2770
|
+
peerId: `host-${PublicKey8.random().toHex()}`,
|
|
2764
2771
|
network: [
|
|
2765
2772
|
this._clientNetwork,
|
|
2766
2773
|
this._meshNetwork
|
|
2767
2774
|
],
|
|
2768
2775
|
storage: this._storage,
|
|
2769
2776
|
// TODO(dmaretskyi): Share based on HALO permissions and space affinity.
|
|
2770
|
-
|
|
2777
|
+
// Hosts, running in the worker, don't share documents unless requested by other peers.
|
|
2778
|
+
sharePolicy: async (peerId, documentId) => {
|
|
2779
|
+
if (peerId.startsWith("client-")) {
|
|
2780
|
+
return true;
|
|
2781
|
+
}
|
|
2782
|
+
if (!documentId) {
|
|
2783
|
+
return false;
|
|
2784
|
+
}
|
|
2785
|
+
const doc = this._repo.handles[documentId]?.docSync();
|
|
2786
|
+
if (!doc) {
|
|
2787
|
+
log13("doc not found for share policy check", {
|
|
2788
|
+
peerId,
|
|
2789
|
+
documentId
|
|
2790
|
+
}, {
|
|
2791
|
+
F: __dxlog_file14,
|
|
2792
|
+
L: 65,
|
|
2793
|
+
S: this,
|
|
2794
|
+
C: (f, a) => f(...a)
|
|
2795
|
+
});
|
|
2796
|
+
return false;
|
|
2797
|
+
}
|
|
2798
|
+
try {
|
|
2799
|
+
if (!doc.experimental_spaceKey) {
|
|
2800
|
+
log13.warn("space key not found for share policy check", {
|
|
2801
|
+
peerId,
|
|
2802
|
+
documentId
|
|
2803
|
+
}, {
|
|
2804
|
+
F: __dxlog_file14,
|
|
2805
|
+
L: 71,
|
|
2806
|
+
S: this,
|
|
2807
|
+
C: (f, a) => f(...a)
|
|
2808
|
+
});
|
|
2809
|
+
return false;
|
|
2810
|
+
}
|
|
2811
|
+
const spaceKey = PublicKey8.from(doc.experimental_spaceKey);
|
|
2812
|
+
const authorizedDevices = this._authorizedDevices.get(spaceKey);
|
|
2813
|
+
const deviceKeyHex = this.repo.peerMetadataByPeerId[peerId]?.dxos_deviceKey;
|
|
2814
|
+
if (!deviceKeyHex) {
|
|
2815
|
+
log13.warn("device key not found for share policy check", {
|
|
2816
|
+
peerId,
|
|
2817
|
+
documentId
|
|
2818
|
+
}, {
|
|
2819
|
+
F: __dxlog_file14,
|
|
2820
|
+
L: 81,
|
|
2821
|
+
S: this,
|
|
2822
|
+
C: (f, a) => f(...a)
|
|
2823
|
+
});
|
|
2824
|
+
return false;
|
|
2825
|
+
}
|
|
2826
|
+
const deviceKey = PublicKey8.from(deviceKeyHex);
|
|
2827
|
+
const isAuthorized = authorizedDevices?.has(deviceKey) ?? false;
|
|
2828
|
+
log13.info("share policy check", {
|
|
2829
|
+
peerId,
|
|
2830
|
+
documentId,
|
|
2831
|
+
deviceKey,
|
|
2832
|
+
spaceKey,
|
|
2833
|
+
isAuthorized
|
|
2834
|
+
}, {
|
|
2835
|
+
F: __dxlog_file14,
|
|
2836
|
+
L: 87,
|
|
2837
|
+
S: this,
|
|
2838
|
+
C: (f, a) => f(...a)
|
|
2839
|
+
});
|
|
2840
|
+
return isAuthorized;
|
|
2841
|
+
} catch (err) {
|
|
2842
|
+
log13.catch(err, void 0, {
|
|
2843
|
+
F: __dxlog_file14,
|
|
2844
|
+
L: 90,
|
|
2845
|
+
S: this,
|
|
2846
|
+
C: (f, a) => f(...a)
|
|
2847
|
+
});
|
|
2848
|
+
return false;
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2771
2851
|
});
|
|
2772
2852
|
this._clientNetwork.ready();
|
|
2773
2853
|
this._meshNetwork.ready();
|
|
@@ -2776,6 +2856,7 @@ var AutomergeHost = class {
|
|
|
2776
2856
|
return this._repo;
|
|
2777
2857
|
}
|
|
2778
2858
|
async close() {
|
|
2859
|
+
this._storage instanceof AutomergeStorageAdapter && await this._storage.close();
|
|
2779
2860
|
await this._clientNetwork.close();
|
|
2780
2861
|
}
|
|
2781
2862
|
//
|
|
@@ -2787,7 +2868,7 @@ var AutomergeHost = class {
|
|
|
2787
2868
|
sendSyncMessage(request) {
|
|
2788
2869
|
return this._clientNetwork.sendSyncMessage(request);
|
|
2789
2870
|
}
|
|
2790
|
-
getHostInfo() {
|
|
2871
|
+
async getHostInfo() {
|
|
2791
2872
|
return this._clientNetwork.getHostInfo();
|
|
2792
2873
|
}
|
|
2793
2874
|
//
|
|
@@ -2796,11 +2877,15 @@ var AutomergeHost = class {
|
|
|
2796
2877
|
createExtension() {
|
|
2797
2878
|
return this._meshNetwork.createExtension();
|
|
2798
2879
|
}
|
|
2880
|
+
authorizeDevice(spaceKey, deviceKey) {
|
|
2881
|
+
defaultMap(this._authorizedDevices, spaceKey, () => new ComplexSet(PublicKey8.hash)).add(deviceKey);
|
|
2882
|
+
}
|
|
2799
2883
|
};
|
|
2800
2884
|
var LocalHostNetworkAdapter = class extends NetworkAdapter {
|
|
2801
2885
|
constructor() {
|
|
2802
2886
|
super(...arguments);
|
|
2803
2887
|
this._peers = /* @__PURE__ */ new Map();
|
|
2888
|
+
this._connected = new Trigger2();
|
|
2804
2889
|
}
|
|
2805
2890
|
/**
|
|
2806
2891
|
* Emits `ready` event. That signals to `Repo` that it can start using the adapter.
|
|
@@ -2812,12 +2897,13 @@ var LocalHostNetworkAdapter = class extends NetworkAdapter {
|
|
|
2812
2897
|
}
|
|
2813
2898
|
connect(peerId) {
|
|
2814
2899
|
this.peerId = peerId;
|
|
2900
|
+
this._connected.wake();
|
|
2815
2901
|
}
|
|
2816
2902
|
send(message) {
|
|
2817
2903
|
const peer = this._peers.get(message.targetId);
|
|
2818
2904
|
invariant10(peer, "Peer not found.", {
|
|
2819
2905
|
F: __dxlog_file14,
|
|
2820
|
-
L:
|
|
2906
|
+
L: 170,
|
|
2821
2907
|
S: this,
|
|
2822
2908
|
A: [
|
|
2823
2909
|
"peer",
|
|
@@ -2837,7 +2923,7 @@ var LocalHostNetworkAdapter = class extends NetworkAdapter {
|
|
|
2837
2923
|
return new Stream2(({ next, close }) => {
|
|
2838
2924
|
invariant10(!this._peers.has(peerId), "Peer already connected.", {
|
|
2839
2925
|
F: __dxlog_file14,
|
|
2840
|
-
L:
|
|
2926
|
+
L: 188,
|
|
2841
2927
|
S: this,
|
|
2842
2928
|
A: [
|
|
2843
2929
|
"!this._peers.has(peerId)",
|
|
@@ -2859,19 +2945,35 @@ var LocalHostNetworkAdapter = class extends NetworkAdapter {
|
|
|
2859
2945
|
});
|
|
2860
2946
|
}
|
|
2861
2947
|
});
|
|
2862
|
-
this.
|
|
2863
|
-
|
|
2864
|
-
})
|
|
2948
|
+
this._connected.wait({
|
|
2949
|
+
timeout: 1e3
|
|
2950
|
+
}).then(() => {
|
|
2951
|
+
this.emit("peer-candidate", {
|
|
2952
|
+
peerMetadata: {},
|
|
2953
|
+
peerId
|
|
2954
|
+
});
|
|
2955
|
+
}).catch((err) => log13.catch(err, void 0, {
|
|
2956
|
+
F: __dxlog_file14,
|
|
2957
|
+
L: 213,
|
|
2958
|
+
S: this,
|
|
2959
|
+
C: (f, a) => f(...a)
|
|
2960
|
+
}));
|
|
2865
2961
|
});
|
|
2866
2962
|
}
|
|
2867
2963
|
async sendSyncMessage({ id, syncMessage }) {
|
|
2964
|
+
await this._connected.wait({
|
|
2965
|
+
timeout: 1e3
|
|
2966
|
+
});
|
|
2868
2967
|
const message = cbor.decode(syncMessage);
|
|
2869
2968
|
this.emit("message", message);
|
|
2870
2969
|
}
|
|
2871
|
-
getHostInfo() {
|
|
2970
|
+
async getHostInfo() {
|
|
2971
|
+
await this._connected.wait({
|
|
2972
|
+
timeout: 1e3
|
|
2973
|
+
});
|
|
2872
2974
|
invariant10(this.peerId, "Peer id not set.", {
|
|
2873
2975
|
F: __dxlog_file14,
|
|
2874
|
-
L:
|
|
2976
|
+
L: 225,
|
|
2875
2977
|
S: this,
|
|
2876
2978
|
A: [
|
|
2877
2979
|
"this.peerId",
|
|
@@ -2907,7 +3009,7 @@ var MeshNetworkAdapter = class extends NetworkAdapter {
|
|
|
2907
3009
|
const extension = this._extensions.get(receiverId);
|
|
2908
3010
|
invariant10(extension, "Extension not found.", {
|
|
2909
3011
|
F: __dxlog_file14,
|
|
2910
|
-
L:
|
|
3012
|
+
L: 260,
|
|
2911
3013
|
S: this,
|
|
2912
3014
|
A: [
|
|
2913
3015
|
"extension",
|
|
@@ -2918,7 +3020,7 @@ var MeshNetworkAdapter = class extends NetworkAdapter {
|
|
|
2918
3020
|
payload: cbor.encode(message)
|
|
2919
3021
|
}).catch((err) => log13.catch(err, void 0, {
|
|
2920
3022
|
F: __dxlog_file14,
|
|
2921
|
-
L:
|
|
3023
|
+
L: 261,
|
|
2922
3024
|
S: this,
|
|
2923
3025
|
C: (f, a) => f(...a)
|
|
2924
3026
|
}));
|
|
@@ -2928,7 +3030,7 @@ var MeshNetworkAdapter = class extends NetworkAdapter {
|
|
|
2928
3030
|
createExtension() {
|
|
2929
3031
|
invariant10(this.peerId, "Peer id not set.", {
|
|
2930
3032
|
F: __dxlog_file14,
|
|
2931
|
-
L:
|
|
3033
|
+
L: 269,
|
|
2932
3034
|
S: this,
|
|
2933
3035
|
A: [
|
|
2934
3036
|
"this.peerId",
|
|
@@ -2939,13 +3041,17 @@ var MeshNetworkAdapter = class extends NetworkAdapter {
|
|
|
2939
3041
|
const extension = new AutomergeReplicator({
|
|
2940
3042
|
peerId: this.peerId
|
|
2941
3043
|
}, {
|
|
2942
|
-
onStartReplication: async (info) => {
|
|
3044
|
+
onStartReplication: async (info, remotePeerId) => {
|
|
2943
3045
|
if (this._extensions.has(info.id)) {
|
|
2944
3046
|
return;
|
|
2945
3047
|
}
|
|
2946
3048
|
peerInfo = info;
|
|
2947
3049
|
this._extensions.set(info.id, extension);
|
|
2948
3050
|
this.emit("peer-candidate", {
|
|
3051
|
+
// TODO(mykola): Hack, stop abusing `peerMetadata` field.
|
|
3052
|
+
peerMetadata: {
|
|
3053
|
+
dxos_deviceKey: remotePeerId.toHex()
|
|
3054
|
+
},
|
|
2949
3055
|
peerId: info.id
|
|
2950
3056
|
});
|
|
2951
3057
|
},
|
|
@@ -2954,9 +3060,13 @@ var MeshNetworkAdapter = class extends NetworkAdapter {
|
|
|
2954
3060
|
this.emit("message", message);
|
|
2955
3061
|
},
|
|
2956
3062
|
onClose: async () => {
|
|
2957
|
-
|
|
3063
|
+
if (!peerInfo) {
|
|
3064
|
+
return;
|
|
3065
|
+
}
|
|
3066
|
+
this.emit("peer-disconnected", {
|
|
2958
3067
|
peerId: peerInfo.id
|
|
2959
3068
|
});
|
|
3069
|
+
this._extensions.delete(peerInfo.id);
|
|
2960
3070
|
}
|
|
2961
3071
|
});
|
|
2962
3072
|
return extension;
|
|
@@ -2966,8 +3076,12 @@ var AutomergeStorageAdapter = class extends StorageAdapter {
|
|
|
2966
3076
|
constructor(_directory) {
|
|
2967
3077
|
super();
|
|
2968
3078
|
this._directory = _directory;
|
|
3079
|
+
this._state = "opened";
|
|
2969
3080
|
}
|
|
2970
3081
|
async load(key) {
|
|
3082
|
+
if (this._state !== "opened") {
|
|
3083
|
+
return void 0;
|
|
3084
|
+
}
|
|
2971
3085
|
const filename = this._getFilename(key);
|
|
2972
3086
|
const file = this._directory.getOrCreateFile(filename);
|
|
2973
3087
|
const { size } = await file.stat();
|
|
@@ -2978,6 +3092,9 @@ var AutomergeStorageAdapter = class extends StorageAdapter {
|
|
|
2978
3092
|
return bufferToArray(buffer);
|
|
2979
3093
|
}
|
|
2980
3094
|
async save(key, data) {
|
|
3095
|
+
if (this._state !== "opened") {
|
|
3096
|
+
return void 0;
|
|
3097
|
+
}
|
|
2981
3098
|
const filename = this._getFilename(key);
|
|
2982
3099
|
const file = this._directory.getOrCreateFile(filename);
|
|
2983
3100
|
await file.write(0, arrayToBuffer2(data));
|
|
@@ -2985,11 +3102,17 @@ var AutomergeStorageAdapter = class extends StorageAdapter {
|
|
|
2985
3102
|
await file.flush?.();
|
|
2986
3103
|
}
|
|
2987
3104
|
async remove(key) {
|
|
3105
|
+
if (this._state !== "opened") {
|
|
3106
|
+
return void 0;
|
|
3107
|
+
}
|
|
2988
3108
|
const filename = this._getFilename(key);
|
|
2989
3109
|
const file = this._directory.getOrCreateFile(filename);
|
|
2990
|
-
await file.
|
|
3110
|
+
await file.destroy();
|
|
2991
3111
|
}
|
|
2992
3112
|
async loadRange(keyPrefix) {
|
|
3113
|
+
if (this._state !== "opened") {
|
|
3114
|
+
return [];
|
|
3115
|
+
}
|
|
2993
3116
|
const filename = this._getFilename(keyPrefix);
|
|
2994
3117
|
const entries = await this._directory.list();
|
|
2995
3118
|
return Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
|
|
@@ -3003,13 +3126,19 @@ var AutomergeStorageAdapter = class extends StorageAdapter {
|
|
|
3003
3126
|
}));
|
|
3004
3127
|
}
|
|
3005
3128
|
async removeRange(keyPrefix) {
|
|
3129
|
+
if (this._state !== "opened") {
|
|
3130
|
+
return void 0;
|
|
3131
|
+
}
|
|
3006
3132
|
const filename = this._getFilename(keyPrefix);
|
|
3007
3133
|
const entries = await this._directory.list();
|
|
3008
3134
|
await Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
|
|
3009
|
-
const file = this._directory.getOrCreateFile(
|
|
3010
|
-
await file.
|
|
3135
|
+
const file = this._directory.getOrCreateFile(entry);
|
|
3136
|
+
await file.destroy();
|
|
3011
3137
|
}));
|
|
3012
3138
|
}
|
|
3139
|
+
async close() {
|
|
3140
|
+
this._state = "closed";
|
|
3141
|
+
}
|
|
3013
3142
|
_getFilename(key) {
|
|
3014
3143
|
return key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-");
|
|
3015
3144
|
}
|
|
@@ -3043,7 +3172,6 @@ export {
|
|
|
3043
3172
|
AuthStatus,
|
|
3044
3173
|
SpaceProtocolSession,
|
|
3045
3174
|
SpaceManager,
|
|
3046
|
-
AutomergeHost
|
|
3047
|
-
AutomergeStorageAdapter
|
|
3175
|
+
AutomergeHost
|
|
3048
3176
|
};
|
|
3049
|
-
//# sourceMappingURL=chunk-
|
|
3177
|
+
//# sourceMappingURL=chunk-PB5T4DLC.mjs.map
|