@dxos/echo-pipeline 0.3.11-main.cc2fe2c → 0.3.11-main.cf49a01

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.
@@ -26,8 +26,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  mod
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var chunk_GJQNRSA3_exports = {};
30
- __export(chunk_GJQNRSA3_exports, {
29
+ var chunk_WGNVVL2H_exports = {};
30
+ __export(chunk_WGNVVL2H_exports, {
31
31
  AuthExtension: () => AuthExtension,
32
32
  AuthStatus: () => AuthStatus,
33
33
  AutomergeHost: () => AutomergeHost,
@@ -54,7 +54,7 @@ __export(chunk_GJQNRSA3_exports, {
54
54
  startAfter: () => startAfter,
55
55
  valueEncoding: () => valueEncoding
56
56
  });
57
- module.exports = __toCommonJS(chunk_GJQNRSA3_exports);
57
+ module.exports = __toCommonJS(chunk_WGNVVL2H_exports);
58
58
  var import_hypercore = require("@dxos/hypercore");
59
59
  var import_protocols = require("@dxos/protocols");
60
60
  var import_invariant = require("@dxos/invariant");
@@ -147,10 +147,12 @@ var import_keys7 = require("@dxos/keys");
147
147
  var import_log12 = require("@dxos/log");
148
148
  var import_protocols7 = require("@dxos/protocols");
149
149
  var import_util9 = require("@dxos/util");
150
+ var import_async10 = require("@dxos/async");
150
151
  var import_automerge_repo = require("@dxos/automerge/automerge-repo");
151
152
  var import_automerge_repo_storage_indexeddb = require("@dxos/automerge/automerge-repo-storage-indexeddb");
152
153
  var import_codec_protobuf2 = require("@dxos/codec-protobuf");
153
154
  var import_invariant10 = require("@dxos/invariant");
155
+ var import_keys8 = require("@dxos/keys");
154
156
  var import_log13 = require("@dxos/log");
155
157
  var import_random_access_storage = require("@dxos/random-access-storage");
156
158
  var import_teleport_extension_automerge_replicator = require("@dxos/teleport-extension-automerge-replicator");
@@ -2700,7 +2702,7 @@ var SpaceManager = class {
2700
2702
  ...this._spaces.values()
2701
2703
  ].map((space) => space.close()));
2702
2704
  }
2703
- async constructSpace({ metadata, swarmIdentity, onNetworkConnection, onAuthFailure, memberKey }) {
2705
+ async constructSpace({ metadata, swarmIdentity, onAuthorizedConnection, onAuthFailure, memberKey }) {
2704
2706
  import_log12.log.trace("dxos.echo.space-manager.construct-space", import_protocols7.trace.begin({
2705
2707
  id: this._instanceId
2706
2708
  }), {
@@ -2723,7 +2725,7 @@ var SpaceManager = class {
2723
2725
  topic: spaceKey,
2724
2726
  swarmIdentity,
2725
2727
  networkManager: this._networkManager,
2726
- onSessionAuth: onNetworkConnection,
2728
+ onSessionAuth: onAuthorizedConnection,
2727
2729
  onAuthFailure,
2728
2730
  blobStore: this._blobStore
2729
2731
  });
@@ -2762,17 +2764,92 @@ SpaceManager = _ts_decorate8([
2762
2764
  var __dxlog_file14 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
2763
2765
  var AutomergeHost = class {
2764
2766
  constructor(storageDirectory) {
2767
+ this._authorizedDevices = new import_util10.ComplexMap(import_keys8.PublicKey.hash);
2765
2768
  this._meshNetwork = new MeshNetworkAdapter();
2766
2769
  this._clientNetwork = new LocalHostNetworkAdapter();
2767
2770
  this._storage = storageDirectory.type === import_random_access_storage.StorageType.IDB ? new import_automerge_repo_storage_indexeddb.IndexedDBStorageAdapter(storageDirectory.path, "data") : new AutomergeStorageAdapter(storageDirectory);
2768
2771
  this._repo = new import_automerge_repo.Repo({
2772
+ peerId: `host-${import_keys8.PublicKey.random().toHex()}`,
2769
2773
  network: [
2770
2774
  this._clientNetwork,
2771
2775
  this._meshNetwork
2772
2776
  ],
2773
2777
  storage: this._storage,
2774
2778
  // TODO(dmaretskyi): Share based on HALO permissions and space affinity.
2775
- sharePolicy: async (peerId, documentId) => true
2779
+ // Hosts, running in the worker, don't share documents unless requested by other peers.
2780
+ sharePolicy: async (peerId, documentId) => {
2781
+ if (peerId.startsWith("client-")) {
2782
+ return true;
2783
+ }
2784
+ if (!documentId) {
2785
+ return false;
2786
+ }
2787
+ const doc = this._repo.handles[documentId]?.docSync();
2788
+ if (!doc) {
2789
+ (0, import_log13.log)("doc not found for share policy check", {
2790
+ peerId,
2791
+ documentId
2792
+ }, {
2793
+ F: __dxlog_file14,
2794
+ L: 65,
2795
+ S: this,
2796
+ C: (f, a) => f(...a)
2797
+ });
2798
+ return false;
2799
+ }
2800
+ try {
2801
+ if (!doc.experimental_spaceKey) {
2802
+ import_log13.log.warn("space key not found for share policy check", {
2803
+ peerId,
2804
+ documentId
2805
+ }, {
2806
+ F: __dxlog_file14,
2807
+ L: 71,
2808
+ S: this,
2809
+ C: (f, a) => f(...a)
2810
+ });
2811
+ return false;
2812
+ }
2813
+ const spaceKey = import_keys8.PublicKey.from(doc.experimental_spaceKey);
2814
+ const authorizedDevices = this._authorizedDevices.get(spaceKey);
2815
+ const deviceKeyHex = this.repo.peerMetadataByPeerId[peerId]?.dxos_deviceKey;
2816
+ if (!deviceKeyHex) {
2817
+ import_log13.log.warn("device key not found for share policy check", {
2818
+ peerId,
2819
+ documentId
2820
+ }, {
2821
+ F: __dxlog_file14,
2822
+ L: 81,
2823
+ S: this,
2824
+ C: (f, a) => f(...a)
2825
+ });
2826
+ return false;
2827
+ }
2828
+ const deviceKey = import_keys8.PublicKey.from(deviceKeyHex);
2829
+ const isAuthorized = authorizedDevices?.has(deviceKey) ?? false;
2830
+ import_log13.log.info("share policy check", {
2831
+ peerId,
2832
+ documentId,
2833
+ deviceKey,
2834
+ spaceKey,
2835
+ isAuthorized
2836
+ }, {
2837
+ F: __dxlog_file14,
2838
+ L: 87,
2839
+ S: this,
2840
+ C: (f, a) => f(...a)
2841
+ });
2842
+ return isAuthorized;
2843
+ } catch (err) {
2844
+ import_log13.log.catch(err, void 0, {
2845
+ F: __dxlog_file14,
2846
+ L: 90,
2847
+ S: this,
2848
+ C: (f, a) => f(...a)
2849
+ });
2850
+ return false;
2851
+ }
2852
+ }
2776
2853
  });
2777
2854
  this._clientNetwork.ready();
2778
2855
  this._meshNetwork.ready();
@@ -2781,6 +2858,7 @@ var AutomergeHost = class {
2781
2858
  return this._repo;
2782
2859
  }
2783
2860
  async close() {
2861
+ this._storage instanceof AutomergeStorageAdapter && await this._storage.close();
2784
2862
  await this._clientNetwork.close();
2785
2863
  }
2786
2864
  //
@@ -2792,7 +2870,7 @@ var AutomergeHost = class {
2792
2870
  sendSyncMessage(request) {
2793
2871
  return this._clientNetwork.sendSyncMessage(request);
2794
2872
  }
2795
- getHostInfo() {
2873
+ async getHostInfo() {
2796
2874
  return this._clientNetwork.getHostInfo();
2797
2875
  }
2798
2876
  //
@@ -2801,11 +2879,15 @@ var AutomergeHost = class {
2801
2879
  createExtension() {
2802
2880
  return this._meshNetwork.createExtension();
2803
2881
  }
2882
+ authorizeDevice(spaceKey, deviceKey) {
2883
+ (0, import_util10.defaultMap)(this._authorizedDevices, spaceKey, () => new import_util10.ComplexSet(import_keys8.PublicKey.hash)).add(deviceKey);
2884
+ }
2804
2885
  };
2805
2886
  var LocalHostNetworkAdapter = class extends import_automerge_repo.NetworkAdapter {
2806
2887
  constructor() {
2807
2888
  super(...arguments);
2808
2889
  this._peers = /* @__PURE__ */ new Map();
2890
+ this._connected = new import_async10.Trigger();
2809
2891
  }
2810
2892
  /**
2811
2893
  * Emits `ready` event. That signals to `Repo` that it can start using the adapter.
@@ -2817,12 +2899,13 @@ var LocalHostNetworkAdapter = class extends import_automerge_repo.NetworkAdapter
2817
2899
  }
2818
2900
  connect(peerId) {
2819
2901
  this.peerId = peerId;
2902
+ this._connected.wake();
2820
2903
  }
2821
2904
  send(message) {
2822
2905
  const peer = this._peers.get(message.targetId);
2823
2906
  (0, import_invariant10.invariant)(peer, "Peer not found.", {
2824
2907
  F: __dxlog_file14,
2825
- L: 114,
2908
+ L: 170,
2826
2909
  S: this,
2827
2910
  A: [
2828
2911
  "peer",
@@ -2842,7 +2925,7 @@ var LocalHostNetworkAdapter = class extends import_automerge_repo.NetworkAdapter
2842
2925
  return new import_codec_protobuf2.Stream(({ next, close }) => {
2843
2926
  (0, import_invariant10.invariant)(!this._peers.has(peerId), "Peer already connected.", {
2844
2927
  F: __dxlog_file14,
2845
- L: 132,
2928
+ L: 188,
2846
2929
  S: this,
2847
2930
  A: [
2848
2931
  "!this._peers.has(peerId)",
@@ -2864,19 +2947,35 @@ var LocalHostNetworkAdapter = class extends import_automerge_repo.NetworkAdapter
2864
2947
  });
2865
2948
  }
2866
2949
  });
2867
- this.emit("peer-candidate", {
2868
- peerId
2869
- });
2950
+ this._connected.wait({
2951
+ timeout: 1e3
2952
+ }).then(() => {
2953
+ this.emit("peer-candidate", {
2954
+ peerMetadata: {},
2955
+ peerId
2956
+ });
2957
+ }).catch((err) => import_log13.log.catch(err, void 0, {
2958
+ F: __dxlog_file14,
2959
+ L: 213,
2960
+ S: this,
2961
+ C: (f, a) => f(...a)
2962
+ }));
2870
2963
  });
2871
2964
  }
2872
2965
  async sendSyncMessage({ id, syncMessage }) {
2966
+ await this._connected.wait({
2967
+ timeout: 1e3
2968
+ });
2873
2969
  const message = import_automerge_repo.cbor.decode(syncMessage);
2874
2970
  this.emit("message", message);
2875
2971
  }
2876
- getHostInfo() {
2972
+ async getHostInfo() {
2973
+ await this._connected.wait({
2974
+ timeout: 1e3
2975
+ });
2877
2976
  (0, import_invariant10.invariant)(this.peerId, "Peer id not set.", {
2878
2977
  F: __dxlog_file14,
2879
- L: 161,
2978
+ L: 225,
2880
2979
  S: this,
2881
2980
  A: [
2882
2981
  "this.peerId",
@@ -2912,7 +3011,7 @@ var MeshNetworkAdapter = class extends import_automerge_repo.NetworkAdapter {
2912
3011
  const extension = this._extensions.get(receiverId);
2913
3012
  (0, import_invariant10.invariant)(extension, "Extension not found.", {
2914
3013
  F: __dxlog_file14,
2915
- L: 196,
3014
+ L: 260,
2916
3015
  S: this,
2917
3016
  A: [
2918
3017
  "extension",
@@ -2923,7 +3022,7 @@ var MeshNetworkAdapter = class extends import_automerge_repo.NetworkAdapter {
2923
3022
  payload: import_automerge_repo.cbor.encode(message)
2924
3023
  }).catch((err) => import_log13.log.catch(err, void 0, {
2925
3024
  F: __dxlog_file14,
2926
- L: 197,
3025
+ L: 261,
2927
3026
  S: this,
2928
3027
  C: (f, a) => f(...a)
2929
3028
  }));
@@ -2933,7 +3032,7 @@ var MeshNetworkAdapter = class extends import_automerge_repo.NetworkAdapter {
2933
3032
  createExtension() {
2934
3033
  (0, import_invariant10.invariant)(this.peerId, "Peer id not set.", {
2935
3034
  F: __dxlog_file14,
2936
- L: 205,
3035
+ L: 269,
2937
3036
  S: this,
2938
3037
  A: [
2939
3038
  "this.peerId",
@@ -2944,13 +3043,17 @@ var MeshNetworkAdapter = class extends import_automerge_repo.NetworkAdapter {
2944
3043
  const extension = new import_teleport_extension_automerge_replicator.AutomergeReplicator({
2945
3044
  peerId: this.peerId
2946
3045
  }, {
2947
- onStartReplication: async (info) => {
3046
+ onStartReplication: async (info, remotePeerId) => {
2948
3047
  if (this._extensions.has(info.id)) {
2949
3048
  return;
2950
3049
  }
2951
3050
  peerInfo = info;
2952
3051
  this._extensions.set(info.id, extension);
2953
3052
  this.emit("peer-candidate", {
3053
+ // TODO(mykola): Hack, stop abusing `peerMetadata` field.
3054
+ peerMetadata: {
3055
+ dxos_deviceKey: remotePeerId.toHex()
3056
+ },
2954
3057
  peerId: info.id
2955
3058
  });
2956
3059
  },
@@ -2975,8 +3078,12 @@ var AutomergeStorageAdapter = class extends import_automerge_repo.StorageAdapter
2975
3078
  constructor(_directory) {
2976
3079
  super();
2977
3080
  this._directory = _directory;
3081
+ this._state = "opened";
2978
3082
  }
2979
3083
  async load(key) {
3084
+ if (this._state !== "opened") {
3085
+ return void 0;
3086
+ }
2980
3087
  const filename = this._getFilename(key);
2981
3088
  const file = this._directory.getOrCreateFile(filename);
2982
3089
  const { size } = await file.stat();
@@ -2987,6 +3094,9 @@ var AutomergeStorageAdapter = class extends import_automerge_repo.StorageAdapter
2987
3094
  return (0, import_util10.bufferToArray)(buffer);
2988
3095
  }
2989
3096
  async save(key, data) {
3097
+ if (this._state !== "opened") {
3098
+ return void 0;
3099
+ }
2990
3100
  const filename = this._getFilename(key);
2991
3101
  const file = this._directory.getOrCreateFile(filename);
2992
3102
  await file.write(0, (0, import_util10.arrayToBuffer)(data));
@@ -2994,11 +3104,17 @@ var AutomergeStorageAdapter = class extends import_automerge_repo.StorageAdapter
2994
3104
  await file.flush?.();
2995
3105
  }
2996
3106
  async remove(key) {
3107
+ if (this._state !== "opened") {
3108
+ return void 0;
3109
+ }
2997
3110
  const filename = this._getFilename(key);
2998
3111
  const file = this._directory.getOrCreateFile(filename);
2999
3112
  await file.destroy();
3000
3113
  }
3001
3114
  async loadRange(keyPrefix) {
3115
+ if (this._state !== "opened") {
3116
+ return [];
3117
+ }
3002
3118
  const filename = this._getFilename(keyPrefix);
3003
3119
  const entries = await this._directory.list();
3004
3120
  return Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
@@ -3012,6 +3128,9 @@ var AutomergeStorageAdapter = class extends import_automerge_repo.StorageAdapter
3012
3128
  }));
3013
3129
  }
3014
3130
  async removeRange(keyPrefix) {
3131
+ if (this._state !== "opened") {
3132
+ return void 0;
3133
+ }
3015
3134
  const filename = this._getFilename(keyPrefix);
3016
3135
  const entries = await this._directory.list();
3017
3136
  await Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
@@ -3019,6 +3138,9 @@ var AutomergeStorageAdapter = class extends import_automerge_repo.StorageAdapter
3019
3138
  await file.destroy();
3020
3139
  }));
3021
3140
  }
3141
+ async close() {
3142
+ this._state = "closed";
3143
+ }
3022
3144
  _getFilename(key) {
3023
3145
  return key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-");
3024
3146
  }
@@ -3054,4 +3176,4 @@ var AutomergeStorageAdapter = class extends import_automerge_repo.StorageAdapter
3054
3176
  startAfter,
3055
3177
  valueEncoding
3056
3178
  });
3057
- //# sourceMappingURL=chunk-GJQNRSA3.cjs.map
3179
+ //# sourceMappingURL=chunk-WGNVVL2H.cjs.map