@dxos/echo-pipeline 0.4.4-main.fcf0b00 → 0.4.4-next.75bfacc

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.
Files changed (28) hide show
  1. package/dist/lib/browser/{chunk-26G7ZQMP.mjs → chunk-WIB35LJH.mjs} +305 -254
  2. package/dist/lib/browser/{chunk-26G7ZQMP.mjs.map → chunk-WIB35LJH.mjs.map} +4 -4
  3. package/dist/lib/browser/index.mjs +5 -1
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/lib/browser/testing/index.mjs +1 -1
  6. package/dist/lib/node/{chunk-V62AY27P.cjs → chunk-37RERU2L.cjs} +295 -248
  7. package/dist/lib/node/{chunk-V62AY27P.cjs.map → chunk-37RERU2L.cjs.map} +4 -4
  8. package/dist/lib/node/index.cjs +31 -27
  9. package/dist/lib/node/index.cjs.map +2 -2
  10. package/dist/lib/node/meta.json +1 -1
  11. package/dist/lib/node/testing/index.cjs +16 -16
  12. package/dist/types/src/automerge/automerge-host.d.ts +5 -31
  13. package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
  14. package/dist/types/src/automerge/automerge-storage-adapter.d.ts +16 -0
  15. package/dist/types/src/automerge/automerge-storage-adapter.d.ts.map +1 -0
  16. package/dist/types/src/automerge/index.d.ts +4 -1
  17. package/dist/types/src/automerge/index.d.ts.map +1 -1
  18. package/dist/types/src/automerge/local-host-network-adapter.d.ts +23 -0
  19. package/dist/types/src/automerge/local-host-network-adapter.d.ts.map +1 -0
  20. package/dist/types/src/automerge/mesh-network-adapter.d.ts +18 -0
  21. package/dist/types/src/automerge/mesh-network-adapter.d.ts.map +1 -0
  22. package/package.json +34 -34
  23. package/src/automerge/automerge-host.test.ts +102 -2
  24. package/src/automerge/automerge-host.ts +27 -303
  25. package/src/automerge/automerge-storage-adapter.ts +105 -0
  26. package/src/automerge/index.ts +4 -1
  27. package/src/automerge/local-host-network-adapter.ts +109 -0
  28. package/src/automerge/mesh-network-adapter.ts +107 -0
@@ -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_V62AY27P_exports = {};
30
- __export(chunk_V62AY27P_exports, {
29
+ var chunk_37RERU2L_exports = {};
30
+ __export(chunk_37RERU2L_exports, {
31
31
  AuthExtension: () => AuthExtension,
32
32
  AuthStatus: () => AuthStatus,
33
33
  AutomergeHost: () => AutomergeHost,
@@ -37,8 +37,10 @@ __export(chunk_V62AY27P_exports, {
37
37
  DataServiceImpl: () => DataServiceImpl,
38
38
  DataServiceSubscriptions: () => DataServiceSubscriptions,
39
39
  DatabaseHost: () => DatabaseHost,
40
+ LocalHostNetworkAdapter: () => LocalHostNetworkAdapter,
40
41
  MOCK_AUTH_PROVIDER: () => MOCK_AUTH_PROVIDER,
41
42
  MOCK_AUTH_VERIFIER: () => MOCK_AUTH_VERIFIER,
43
+ MeshNetworkAdapter: () => MeshNetworkAdapter,
42
44
  MetadataStore: () => MetadataStore,
43
45
  Pipeline: () => Pipeline,
44
46
  SnapshotManager: () => SnapshotManager,
@@ -55,7 +57,7 @@ __export(chunk_V62AY27P_exports, {
55
57
  startAfter: () => startAfter,
56
58
  valueEncoding: () => valueEncoding
57
59
  });
58
- module.exports = __toCommonJS(chunk_V62AY27P_exports);
60
+ module.exports = __toCommonJS(chunk_37RERU2L_exports);
59
61
  var import_hypercore = require("@dxos/hypercore");
60
62
  var import_protocols = require("@dxos/protocols");
61
63
  var import_invariant = require("@dxos/invariant");
@@ -149,18 +151,26 @@ var import_keys7 = require("@dxos/keys");
149
151
  var import_log12 = require("@dxos/log");
150
152
  var import_protocols7 = require("@dxos/protocols");
151
153
  var import_util9 = require("@dxos/util");
152
- var import_async10 = require("@dxos/async");
153
- var import_automerge = require("@dxos/automerge/automerge");
154
154
  var import_automerge_repo = require("@dxos/automerge/automerge-repo");
155
- var import_automerge_repo_storage_indexeddb = require("@dxos/automerge/automerge-repo-storage-indexeddb");
155
+ var import_util10 = require("@dxos/util");
156
+ var import_async10 = require("@dxos/async");
157
+ var import_automerge_repo2 = require("@dxos/automerge/automerge-repo");
156
158
  var import_codec_protobuf2 = require("@dxos/codec-protobuf");
157
159
  var import_invariant10 = require("@dxos/invariant");
158
- var import_keys8 = require("@dxos/keys");
159
160
  var import_log13 = require("@dxos/log");
160
- var import_random_access_storage = require("@dxos/random-access-storage");
161
+ var import_async11 = require("@dxos/async");
162
+ var import_automerge_repo3 = require("@dxos/automerge/automerge-repo");
163
+ var import_invariant11 = require("@dxos/invariant");
164
+ var import_log14 = require("@dxos/log");
161
165
  var import_teleport_extension_automerge_replicator = require("@dxos/teleport-extension-automerge-replicator");
166
+ var import_automerge = require("@dxos/automerge/automerge");
167
+ var import_automerge_repo4 = require("@dxos/automerge/automerge-repo");
168
+ var import_automerge_repo_storage_indexeddb = require("@dxos/automerge/automerge-repo-storage-indexeddb");
169
+ var import_keys8 = require("@dxos/keys");
170
+ var import_log15 = require("@dxos/log");
171
+ var import_random_access_storage = require("@dxos/random-access-storage");
162
172
  var import_tracing5 = require("@dxos/tracing");
163
- var import_util10 = require("@dxos/util");
173
+ var import_util11 = require("@dxos/util");
164
174
  var codec = import_protocols.schema.getCodecForType("dxos.echo.feed.FeedMessage");
165
175
  var valueEncoding = (0, import_hypercore.createCodecEncoding)(codec);
166
176
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/common/feeds.ts";
@@ -2782,162 +2792,82 @@ _ts_decorate8([
2782
2792
  SpaceManager = _ts_decorate8([
2783
2793
  (0, import_async9.trackLeaks)("open", "close")
2784
2794
  ], SpaceManager);
2785
- function _ts_decorate9(decorators, target, key, desc) {
2786
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2787
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
2788
- r = Reflect.decorate(decorators, target, key, desc);
2789
- else
2790
- for (var i = decorators.length - 1; i >= 0; i--)
2791
- if (d = decorators[i])
2792
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2793
- return c > 3 && r && Object.defineProperty(target, key, r), r;
2794
- }
2795
- var __dxlog_file14 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
2796
- var AutomergeHost = class {
2797
- constructor(storageDirectory) {
2798
- this._authorizedDevices = new import_util10.ComplexMap(import_keys8.PublicKey.hash);
2799
- this._meshNetwork = new MeshNetworkAdapter();
2800
- this._clientNetwork = new LocalHostNetworkAdapter();
2801
- this._storage = storageDirectory.type === import_random_access_storage.StorageType.IDB ? new import_automerge_repo_storage_indexeddb.IndexedDBStorageAdapter(storageDirectory.path, "data") : new AutomergeStorageAdapter(storageDirectory);
2802
- this._repo = new import_automerge_repo.Repo({
2803
- peerId: `host-${import_keys8.PublicKey.random().toHex()}`,
2804
- network: [
2805
- this._clientNetwork,
2806
- this._meshNetwork
2807
- ],
2808
- storage: this._storage,
2809
- // TODO(dmaretskyi): Share based on HALO permissions and space affinity.
2810
- // Hosts, running in the worker, don't share documents unless requested by other peers.
2811
- sharePolicy: async (peerId, documentId) => {
2812
- if (peerId.startsWith("client-")) {
2813
- return true;
2814
- }
2815
- if (!documentId) {
2816
- return false;
2817
- }
2818
- const doc = this._repo.handles[documentId]?.docSync();
2819
- if (!doc) {
2820
- (0, import_log13.log)("doc not found for share policy check", {
2821
- peerId,
2822
- documentId
2823
- }, {
2824
- F: __dxlog_file14,
2825
- L: 68,
2826
- S: this,
2827
- C: (f, a) => f(...a)
2828
- });
2829
- return false;
2830
- }
2831
- try {
2832
- if (!doc.experimental_spaceKey) {
2833
- (0, import_log13.log)("space key not found for share policy check", {
2834
- peerId,
2835
- documentId
2836
- }, {
2837
- F: __dxlog_file14,
2838
- L: 74,
2839
- S: this,
2840
- C: (f, a) => f(...a)
2841
- });
2842
- return false;
2843
- }
2844
- const spaceKey = import_keys8.PublicKey.from(doc.experimental_spaceKey);
2845
- const authorizedDevices = this._authorizedDevices.get(spaceKey);
2846
- const deviceKeyHex = this.repo.peerMetadataByPeerId[peerId]?.dxos_deviceKey;
2847
- if (!deviceKeyHex) {
2848
- (0, import_log13.log)("device key not found for share policy check", {
2849
- peerId,
2850
- documentId
2851
- }, {
2852
- F: __dxlog_file14,
2853
- L: 84,
2854
- S: this,
2855
- C: (f, a) => f(...a)
2856
- });
2857
- return false;
2858
- }
2859
- const deviceKey = import_keys8.PublicKey.from(deviceKeyHex);
2860
- const isAuthorized = authorizedDevices?.has(deviceKey) ?? false;
2861
- (0, import_log13.log)("share policy check", {
2862
- peerId,
2863
- documentId,
2864
- deviceKey,
2865
- spaceKey,
2866
- isAuthorized
2867
- }, {
2868
- F: __dxlog_file14,
2869
- L: 90,
2870
- S: this,
2871
- C: (f, a) => f(...a)
2872
- });
2873
- return isAuthorized;
2874
- } catch (err) {
2875
- import_log13.log.catch(err, void 0, {
2876
- F: __dxlog_file14,
2877
- L: 93,
2878
- S: this,
2879
- C: (f, a) => f(...a)
2880
- });
2881
- return false;
2882
- }
2883
- }
2884
- });
2885
- this._clientNetwork.ready();
2886
- this._meshNetwork.ready();
2887
- }
2888
- get repo() {
2889
- return this._repo;
2795
+ var AutomergeStorageAdapter = class extends import_automerge_repo.StorageAdapter {
2796
+ constructor(_directory) {
2797
+ super();
2798
+ this._directory = _directory;
2799
+ this._state = "opened";
2890
2800
  }
2891
- _automergeDocs() {
2892
- return (0, import_util10.mapValues)(this._repo.handles, (handle) => ({
2893
- state: handle.state,
2894
- hasDoc: !!handle.docSync(),
2895
- heads: handle.docSync() ? import_automerge.next.getHeads(handle.docSync()) : null
2896
- }));
2801
+ async load(key) {
2802
+ if (this._state !== "opened") {
2803
+ return void 0;
2804
+ }
2805
+ const filename = this._getFilename(key);
2806
+ const file = this._directory.getOrCreateFile(filename);
2807
+ const { size } = await file.stat();
2808
+ if (!size || size === 0) {
2809
+ return void 0;
2810
+ }
2811
+ const buffer = await file.read(0, size);
2812
+ return (0, import_util10.bufferToArray)(buffer);
2897
2813
  }
2898
- _automergePeers() {
2899
- return this._repo.peers;
2814
+ async save(key, data) {
2815
+ if (this._state !== "opened") {
2816
+ return void 0;
2817
+ }
2818
+ const filename = this._getFilename(key);
2819
+ const file = this._directory.getOrCreateFile(filename);
2820
+ await file.write(0, (0, import_util10.arrayToBuffer)(data));
2821
+ await file.truncate?.(data.length);
2822
+ await file.flush?.();
2900
2823
  }
2901
- async close() {
2902
- this._storage instanceof AutomergeStorageAdapter && await this._storage.close();
2903
- await this._clientNetwork.close();
2824
+ async remove(key) {
2825
+ if (this._state !== "opened") {
2826
+ return void 0;
2827
+ }
2828
+ const filename = this._getFilename(key);
2829
+ const file = this._directory.getOrCreateFile(filename);
2830
+ await file.destroy();
2904
2831
  }
2905
- //
2906
- // Methods for client-services.
2907
- //
2908
- syncRepo(request) {
2909
- return this._clientNetwork.syncRepo(request);
2832
+ async loadRange(keyPrefix) {
2833
+ if (this._state !== "opened") {
2834
+ return [];
2835
+ }
2836
+ const filename = this._getFilename(keyPrefix);
2837
+ const entries = await this._directory.list();
2838
+ return Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
2839
+ const file = this._directory.getOrCreateFile(entry);
2840
+ const { size } = await file.stat();
2841
+ const buffer = await file.read(0, size);
2842
+ return {
2843
+ key: this._getKeyFromFilename(entry),
2844
+ data: (0, import_util10.bufferToArray)(buffer)
2845
+ };
2846
+ }));
2910
2847
  }
2911
- sendSyncMessage(request) {
2912
- return this._clientNetwork.sendSyncMessage(request);
2848
+ async removeRange(keyPrefix) {
2849
+ if (this._state !== "opened") {
2850
+ return void 0;
2851
+ }
2852
+ const filename = this._getFilename(keyPrefix);
2853
+ const entries = await this._directory.list();
2854
+ await Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
2855
+ const file = this._directory.getOrCreateFile(entry);
2856
+ await file.destroy();
2857
+ }));
2913
2858
  }
2914
- async getHostInfo() {
2915
- return this._clientNetwork.getHostInfo();
2859
+ async close() {
2860
+ this._state = "closed";
2916
2861
  }
2917
- //
2918
- // Mesh replication.
2919
- //
2920
- createExtension() {
2921
- return this._meshNetwork.createExtension();
2862
+ _getFilename(key) {
2863
+ return key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-");
2922
2864
  }
2923
- authorizeDevice(spaceKey, deviceKey) {
2924
- (0, import_util10.defaultMap)(this._authorizedDevices, spaceKey, () => new import_util10.ComplexSet(import_keys8.PublicKey.hash)).add(deviceKey);
2865
+ _getKeyFromFilename(filename) {
2866
+ return filename.split("-").map((k) => k.replaceAll("%2D", "-").replaceAll("%25", "%"));
2925
2867
  }
2926
2868
  };
2927
- _ts_decorate9([
2928
- import_tracing5.trace.info({
2929
- depth: null
2930
- })
2931
- ], AutomergeHost.prototype, "_automergeDocs", null);
2932
- _ts_decorate9([
2933
- import_tracing5.trace.info({
2934
- depth: null
2935
- })
2936
- ], AutomergeHost.prototype, "_automergePeers", null);
2937
- AutomergeHost = _ts_decorate9([
2938
- import_tracing5.trace.resource()
2939
- ], AutomergeHost);
2940
- var LocalHostNetworkAdapter = class extends import_automerge_repo.NetworkAdapter {
2869
+ var __dxlog_file14 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/local-host-network-adapter.ts";
2870
+ var LocalHostNetworkAdapter = class extends import_automerge_repo2.NetworkAdapter {
2941
2871
  constructor() {
2942
2872
  super(...arguments);
2943
2873
  this._peers = /* @__PURE__ */ new Map();
@@ -2959,7 +2889,7 @@ var LocalHostNetworkAdapter = class extends import_automerge_repo.NetworkAdapter
2959
2889
  const peer = this._peers.get(message.targetId);
2960
2890
  (0, import_invariant10.invariant)(peer, "Peer not found.", {
2961
2891
  F: __dxlog_file14,
2962
- L: 187,
2892
+ L: 45,
2963
2893
  S: this,
2964
2894
  A: [
2965
2895
  "peer",
@@ -2979,7 +2909,7 @@ var LocalHostNetworkAdapter = class extends import_automerge_repo.NetworkAdapter
2979
2909
  return new import_codec_protobuf2.Stream(({ next, close }) => {
2980
2910
  (0, import_invariant10.invariant)(!this._peers.has(peerId), "Peer already connected.", {
2981
2911
  F: __dxlog_file14,
2982
- L: 205,
2912
+ L: 63,
2983
2913
  S: this,
2984
2914
  A: [
2985
2915
  "!this._peers.has(peerId)",
@@ -2990,7 +2920,7 @@ var LocalHostNetworkAdapter = class extends import_automerge_repo.NetworkAdapter
2990
2920
  connected: true,
2991
2921
  send: (message) => {
2992
2922
  next({
2993
- syncMessage: import_automerge_repo.cbor.encode(message)
2923
+ syncMessage: import_automerge_repo2.cbor.encode(message)
2994
2924
  });
2995
2925
  },
2996
2926
  disconnect: () => {
@@ -3010,7 +2940,7 @@ var LocalHostNetworkAdapter = class extends import_automerge_repo.NetworkAdapter
3010
2940
  });
3011
2941
  }).catch((err) => import_log13.log.catch(err, void 0, {
3012
2942
  F: __dxlog_file14,
3013
- L: 230,
2943
+ L: 88,
3014
2944
  S: this,
3015
2945
  C: (f, a) => f(...a)
3016
2946
  }));
@@ -3020,7 +2950,7 @@ var LocalHostNetworkAdapter = class extends import_automerge_repo.NetworkAdapter
3020
2950
  await this._connected.wait({
3021
2951
  timeout: 1e3
3022
2952
  });
3023
- const message = import_automerge_repo.cbor.decode(syncMessage);
2953
+ const message = import_automerge_repo2.cbor.decode(syncMessage);
3024
2954
  this.emit("message", message);
3025
2955
  }
3026
2956
  async getHostInfo() {
@@ -3029,7 +2959,7 @@ var LocalHostNetworkAdapter = class extends import_automerge_repo.NetworkAdapter
3029
2959
  });
3030
2960
  (0, import_invariant10.invariant)(this.peerId, "Peer id not set.", {
3031
2961
  F: __dxlog_file14,
3032
- L: 242,
2962
+ L: 100,
3033
2963
  S: this,
3034
2964
  A: [
3035
2965
  "this.peerId",
@@ -3044,11 +2974,12 @@ var LocalHostNetworkAdapter = class extends import_automerge_repo.NetworkAdapter
3044
2974
  return id;
3045
2975
  }
3046
2976
  };
3047
- var MeshNetworkAdapter = class extends import_automerge_repo.NetworkAdapter {
2977
+ var __dxlog_file15 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-network-adapter.ts";
2978
+ var MeshNetworkAdapter = class extends import_automerge_repo3.NetworkAdapter {
3048
2979
  constructor() {
3049
2980
  super(...arguments);
3050
2981
  this._extensions = /* @__PURE__ */ new Map();
3051
- this._connected = new import_async10.Trigger();
2982
+ this._connected = new import_async11.Trigger();
3052
2983
  }
3053
2984
  /**
3054
2985
  * Emits `ready` event. That signals to `Repo` that it can start using the adapter.
@@ -3065,9 +2996,9 @@ var MeshNetworkAdapter = class extends import_automerge_repo.NetworkAdapter {
3065
2996
  send(message) {
3066
2997
  const receiverId = message.targetId;
3067
2998
  const extension = this._extensions.get(receiverId);
3068
- (0, import_invariant10.invariant)(extension, "Extension not found.", {
3069
- F: __dxlog_file14,
3070
- L: 279,
2999
+ (0, import_invariant11.invariant)(extension, "Extension not found.", {
3000
+ F: __dxlog_file15,
3001
+ L: 38,
3071
3002
  S: this,
3072
3003
  A: [
3073
3004
  "extension",
@@ -3075,10 +3006,10 @@ var MeshNetworkAdapter = class extends import_automerge_repo.NetworkAdapter {
3075
3006
  ]
3076
3007
  });
3077
3008
  extension.sendSyncMessage({
3078
- payload: import_automerge_repo.cbor.encode(message)
3079
- }).catch((err) => import_log13.log.catch(err, void 0, {
3080
- F: __dxlog_file14,
3081
- L: 280,
3009
+ payload: import_automerge_repo3.cbor.encode(message)
3010
+ }).catch((err) => import_log14.log.catch(err, void 0, {
3011
+ F: __dxlog_file15,
3012
+ L: 39,
3082
3013
  S: this,
3083
3014
  C: (f, a) => f(...a)
3084
3015
  }));
@@ -3086,9 +3017,9 @@ var MeshNetworkAdapter = class extends import_automerge_repo.NetworkAdapter {
3086
3017
  disconnect() {
3087
3018
  }
3088
3019
  createExtension() {
3089
- (0, import_invariant10.invariant)(this.peerId, "Peer id not set.", {
3090
- F: __dxlog_file14,
3091
- L: 288,
3020
+ (0, import_invariant11.invariant)(this.peerId, "Peer id not set.", {
3021
+ F: __dxlog_file15,
3022
+ L: 47,
3092
3023
  S: this,
3093
3024
  A: [
3094
3025
  "this.peerId",
@@ -3101,24 +3032,43 @@ var MeshNetworkAdapter = class extends import_automerge_repo.NetworkAdapter {
3101
3032
  }, {
3102
3033
  onStartReplication: async (info, remotePeerId) => {
3103
3034
  await this._connected.wait();
3035
+ (0, import_log14.log)("onStartReplication", {
3036
+ id: info.id,
3037
+ thisPeerId: this.peerId,
3038
+ remotePeerId: remotePeerId.toHex()
3039
+ }, {
3040
+ F: __dxlog_file15,
3041
+ L: 70,
3042
+ S: this,
3043
+ C: (f, a) => f(...a)
3044
+ });
3104
3045
  if (!this._extensions.has(info.id)) {
3105
3046
  peerInfo = info;
3106
3047
  this._extensions.set(info.id, extension);
3107
- } else {
3108
- this.emit("peer-disconnected", {
3048
+ (0, import_log14.log)("peer-candidate", {
3049
+ id: info.id,
3050
+ thisPeerId: this.peerId,
3051
+ remotePeerId: remotePeerId.toHex()
3052
+ }, {
3053
+ F: __dxlog_file15,
3054
+ L: 76,
3055
+ S: this,
3056
+ C: (f, a) => f(...a)
3057
+ });
3058
+ this.emit("peer-candidate", {
3059
+ // TODO(mykola): Hack, stop abusing `peerMetadata` field.
3060
+ peerMetadata: {
3061
+ dxos_deviceKey: remotePeerId.toHex()
3062
+ },
3109
3063
  peerId: info.id
3110
3064
  });
3111
3065
  }
3112
- this.emit("peer-candidate", {
3113
- // TODO(mykola): Hack, stop abusing `peerMetadata` field.
3114
- peerMetadata: {
3115
- dxos_deviceKey: remotePeerId.toHex()
3116
- },
3117
- peerId: info.id
3118
- });
3119
3066
  },
3120
3067
  onSyncMessage: async ({ payload }) => {
3121
- const message = import_automerge_repo.cbor.decode(payload);
3068
+ if (!peerInfo) {
3069
+ return;
3070
+ }
3071
+ const message = import_automerge_repo3.cbor.decode(payload);
3122
3072
  this.emit("message", message);
3123
3073
  },
3124
3074
  onClose: async () => {
@@ -3134,80 +3084,175 @@ var MeshNetworkAdapter = class extends import_automerge_repo.NetworkAdapter {
3134
3084
  return extension;
3135
3085
  }
3136
3086
  };
3137
- var AutomergeStorageAdapter = class extends import_automerge_repo.StorageAdapter {
3138
- constructor(_directory) {
3139
- super();
3140
- this._directory = _directory;
3141
- this._state = "opened";
3142
- }
3143
- async load(key) {
3144
- if (this._state !== "opened") {
3145
- return void 0;
3146
- }
3147
- const filename = this._getFilename(key);
3148
- const file = this._directory.getOrCreateFile(filename);
3149
- const { size } = await file.stat();
3150
- if (!size || size === 0) {
3151
- return void 0;
3152
- }
3153
- const buffer = await file.read(0, size);
3154
- return (0, import_util10.bufferToArray)(buffer);
3155
- }
3156
- async save(key, data) {
3157
- if (this._state !== "opened") {
3158
- return void 0;
3159
- }
3160
- const filename = this._getFilename(key);
3161
- const file = this._directory.getOrCreateFile(filename);
3162
- await file.write(0, (0, import_util10.arrayToBuffer)(data));
3163
- await file.truncate?.(data.length);
3164
- await file.flush?.();
3087
+ function _ts_decorate9(decorators, target, key, desc) {
3088
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3089
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
3090
+ r = Reflect.decorate(decorators, target, key, desc);
3091
+ else
3092
+ for (var i = decorators.length - 1; i >= 0; i--)
3093
+ if (d = decorators[i])
3094
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3095
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
3096
+ }
3097
+ var __dxlog_file16 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
3098
+ var AutomergeHost = class {
3099
+ constructor(storageDirectory) {
3100
+ this._authorizedDevices = new import_util11.ComplexMap(import_keys8.PublicKey.hash);
3101
+ this._requestedDocs = /* @__PURE__ */ new Set();
3102
+ this._meshNetwork = new MeshNetworkAdapter();
3103
+ this._clientNetwork = new LocalHostNetworkAdapter();
3104
+ this._storage = storageDirectory.type === import_random_access_storage.StorageType.IDB ? new import_automerge_repo_storage_indexeddb.IndexedDBStorageAdapter(storageDirectory.path, "data") : new AutomergeStorageAdapter(storageDirectory);
3105
+ const localPeerId = `host-${import_keys8.PublicKey.random().toHex()}`;
3106
+ this._repo = new import_automerge_repo4.Repo({
3107
+ peerId: localPeerId,
3108
+ network: [
3109
+ this._clientNetwork,
3110
+ this._meshNetwork
3111
+ ],
3112
+ storage: this._storage,
3113
+ // TODO(dmaretskyi): Share based on HALO permissions and space affinity.
3114
+ // Hosts, running in the worker, don't share documents unless requested by other peers.
3115
+ sharePolicy: async (peerId, documentId) => {
3116
+ if (peerId.startsWith("client-")) {
3117
+ return true;
3118
+ }
3119
+ if (!documentId) {
3120
+ return false;
3121
+ }
3122
+ const doc = this._repo.handles[documentId]?.docSync();
3123
+ if (!doc) {
3124
+ const isRequested = this._requestedDocs.has(`automerge:${documentId}`);
3125
+ (0, import_log15.log)("doc share policy check", {
3126
+ peerId,
3127
+ documentId,
3128
+ isRequested
3129
+ }, {
3130
+ F: __dxlog_file16,
3131
+ L: 66,
3132
+ S: this,
3133
+ C: (f, a) => f(...a)
3134
+ });
3135
+ return isRequested;
3136
+ }
3137
+ try {
3138
+ if (!doc.experimental_spaceKey) {
3139
+ (0, import_log15.log)("space key not found for share policy check", {
3140
+ peerId,
3141
+ documentId
3142
+ }, {
3143
+ F: __dxlog_file16,
3144
+ L: 72,
3145
+ S: this,
3146
+ C: (f, a) => f(...a)
3147
+ });
3148
+ return false;
3149
+ }
3150
+ const spaceKey = import_keys8.PublicKey.from(doc.experimental_spaceKey);
3151
+ const authorizedDevices = this._authorizedDevices.get(spaceKey);
3152
+ const deviceKeyHex = this.repo.peerMetadataByPeerId[peerId]?.dxos_deviceKey;
3153
+ if (!deviceKeyHex) {
3154
+ (0, import_log15.log)("device key not found for share policy check", {
3155
+ peerId,
3156
+ documentId
3157
+ }, {
3158
+ F: __dxlog_file16,
3159
+ L: 82,
3160
+ S: this,
3161
+ C: (f, a) => f(...a)
3162
+ });
3163
+ return false;
3164
+ }
3165
+ const deviceKey = import_keys8.PublicKey.from(deviceKeyHex);
3166
+ const isAuthorized = authorizedDevices?.has(deviceKey) ?? false;
3167
+ (0, import_log15.log)("share policy check", {
3168
+ localPeer: localPeerId,
3169
+ remotePeer: peerId,
3170
+ documentId,
3171
+ deviceKey,
3172
+ spaceKey,
3173
+ isAuthorized
3174
+ }, {
3175
+ F: __dxlog_file16,
3176
+ L: 88,
3177
+ S: this,
3178
+ C: (f, a) => f(...a)
3179
+ });
3180
+ return isAuthorized;
3181
+ } catch (err) {
3182
+ import_log15.log.catch(err, void 0, {
3183
+ F: __dxlog_file16,
3184
+ L: 98,
3185
+ S: this,
3186
+ C: (f, a) => f(...a)
3187
+ });
3188
+ return false;
3189
+ }
3190
+ }
3191
+ });
3192
+ this._clientNetwork.ready();
3193
+ this._meshNetwork.ready();
3165
3194
  }
3166
- async remove(key) {
3167
- if (this._state !== "opened") {
3168
- return void 0;
3169
- }
3170
- const filename = this._getFilename(key);
3171
- const file = this._directory.getOrCreateFile(filename);
3172
- await file.destroy();
3195
+ get repo() {
3196
+ return this._repo;
3173
3197
  }
3174
- async loadRange(keyPrefix) {
3175
- if (this._state !== "opened") {
3176
- return [];
3177
- }
3178
- const filename = this._getFilename(keyPrefix);
3179
- const entries = await this._directory.list();
3180
- return Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
3181
- const file = this._directory.getOrCreateFile(entry);
3182
- const { size } = await file.stat();
3183
- const buffer = await file.read(0, size);
3184
- return {
3185
- key: this._getKeyFromFilename(entry),
3186
- data: (0, import_util10.bufferToArray)(buffer)
3187
- };
3198
+ _automergeDocs() {
3199
+ return (0, import_util11.mapValues)(this._repo.handles, (handle) => ({
3200
+ state: handle.state,
3201
+ hasDoc: !!handle.docSync(),
3202
+ heads: handle.docSync() ? import_automerge.next.getHeads(handle.docSync()) : null
3188
3203
  }));
3189
3204
  }
3190
- async removeRange(keyPrefix) {
3191
- if (this._state !== "opened") {
3192
- return void 0;
3193
- }
3194
- const filename = this._getFilename(keyPrefix);
3195
- const entries = await this._directory.list();
3196
- await Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
3197
- const file = this._directory.getOrCreateFile(entry);
3198
- await file.destroy();
3199
- }));
3205
+ _automergePeers() {
3206
+ return this._repo.peers;
3200
3207
  }
3201
3208
  async close() {
3202
- this._state = "closed";
3209
+ this._storage instanceof AutomergeStorageAdapter && await this._storage.close();
3210
+ await this._clientNetwork.close();
3203
3211
  }
3204
- _getFilename(key) {
3205
- return key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-");
3212
+ //
3213
+ // Methods for client-services.
3214
+ //
3215
+ syncRepo(request) {
3216
+ return this._clientNetwork.syncRepo(request);
3206
3217
  }
3207
- _getKeyFromFilename(filename) {
3208
- return filename.split("-").map((k) => k.replaceAll("%2D", "-").replaceAll("%25", "%"));
3218
+ sendSyncMessage(request) {
3219
+ return this._clientNetwork.sendSyncMessage(request);
3220
+ }
3221
+ async getHostInfo() {
3222
+ return this._clientNetwork.getHostInfo();
3223
+ }
3224
+ //
3225
+ // Mesh replication.
3226
+ //
3227
+ createExtension() {
3228
+ return this._meshNetwork.createExtension();
3229
+ }
3230
+ authorizeDevice(spaceKey, deviceKey) {
3231
+ (0, import_log15.log)("authorizeDevice", {
3232
+ spaceKey,
3233
+ deviceKey
3234
+ }, {
3235
+ F: __dxlog_file16,
3236
+ L: 155,
3237
+ S: this,
3238
+ C: (f, a) => f(...a)
3239
+ });
3240
+ (0, import_util11.defaultMap)(this._authorizedDevices, spaceKey, () => new import_util11.ComplexSet(import_keys8.PublicKey.hash)).add(deviceKey);
3209
3241
  }
3210
3242
  };
3243
+ _ts_decorate9([
3244
+ import_tracing5.trace.info({
3245
+ depth: null
3246
+ })
3247
+ ], AutomergeHost.prototype, "_automergeDocs", null);
3248
+ _ts_decorate9([
3249
+ import_tracing5.trace.info({
3250
+ depth: null
3251
+ })
3252
+ ], AutomergeHost.prototype, "_automergePeers", null);
3253
+ AutomergeHost = _ts_decorate9([
3254
+ import_tracing5.trace.resource()
3255
+ ], AutomergeHost);
3211
3256
  // Annotate the CommonJS export names for ESM import in node:
3212
3257
  0 && (module.exports = {
3213
3258
  AuthExtension,
@@ -3219,8 +3264,10 @@ var AutomergeStorageAdapter = class extends import_automerge_repo.StorageAdapter
3219
3264
  DataServiceImpl,
3220
3265
  DataServiceSubscriptions,
3221
3266
  DatabaseHost,
3267
+ LocalHostNetworkAdapter,
3222
3268
  MOCK_AUTH_PROVIDER,
3223
3269
  MOCK_AUTH_VERIFIER,
3270
+ MeshNetworkAdapter,
3224
3271
  MetadataStore,
3225
3272
  Pipeline,
3226
3273
  SnapshotManager,
@@ -3237,4 +3284,4 @@ var AutomergeStorageAdapter = class extends import_automerge_repo.StorageAdapter
3237
3284
  startAfter,
3238
3285
  valueEncoding
3239
3286
  });
3240
- //# sourceMappingURL=chunk-V62AY27P.cjs.map
3287
+ //# sourceMappingURL=chunk-37RERU2L.cjs.map