@dxos/echo-pipeline 0.4.8-next.06fa7e4 → 0.4.8-next.2e7285f

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 (30) hide show
  1. package/dist/lib/browser/{chunk-WAN2XUWE.mjs → chunk-3PPSCHNN.mjs} +652 -17
  2. package/dist/lib/browser/{chunk-WAN2XUWE.mjs.map → chunk-3PPSCHNN.mjs.map} +4 -4
  3. package/dist/lib/browser/index.mjs +6 -633
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +274 -2
  7. package/dist/lib/browser/testing/index.mjs.map +4 -4
  8. package/dist/lib/node/{chunk-U6J2HC4T.cjs → chunk-EVKDEZDX.cjs} +644 -19
  9. package/dist/lib/node/chunk-EVKDEZDX.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +30 -647
  11. package/dist/lib/node/index.cjs.map +4 -4
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/testing/index.cjs +282 -12
  14. package/dist/lib/node/testing/index.cjs.map +4 -4
  15. package/dist/types/src/space/control-pipeline.d.ts.map +1 -1
  16. package/dist/types/src/testing/database-test-rig.d.ts +67 -0
  17. package/dist/types/src/testing/database-test-rig.d.ts.map +1 -0
  18. package/dist/types/src/testing/index.d.ts +1 -0
  19. package/dist/types/src/testing/index.d.ts.map +1 -1
  20. package/dist/types/src/testing/util.d.ts +6 -2
  21. package/dist/types/src/testing/util.d.ts.map +1 -1
  22. package/dist/types/src/tests/database.test.d.ts +2 -0
  23. package/dist/types/src/tests/database.test.d.ts.map +1 -0
  24. package/package.json +33 -33
  25. package/src/space/control-pipeline.ts +1 -3
  26. package/src/testing/database-test-rig.ts +289 -0
  27. package/src/testing/index.ts +1 -0
  28. package/src/testing/util.ts +26 -2
  29. package/src/tests/database.test.ts +100 -0
  30. package/dist/lib/node/chunk-U6J2HC4T.cjs.map +0 -7
@@ -26,17 +26,21 @@ 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_U6J2HC4T_exports = {};
30
- __export(chunk_U6J2HC4T_exports, {
29
+ var chunk_EVKDEZDX_exports = {};
30
+ __export(chunk_EVKDEZDX_exports, {
31
31
  AuthExtension: () => AuthExtension,
32
32
  AuthStatus: () => AuthStatus,
33
+ AutomergeHost: () => AutomergeHost,
34
+ AutomergeStorageAdapter: () => AutomergeStorageAdapter,
33
35
  DataPipeline: () => DataPipeline,
34
36
  DataServiceHost: () => DataServiceHost,
35
37
  DataServiceImpl: () => DataServiceImpl,
36
38
  DataServiceSubscriptions: () => DataServiceSubscriptions,
37
39
  DatabaseHost: () => DatabaseHost,
40
+ LocalHostNetworkAdapter: () => LocalHostNetworkAdapter,
38
41
  MOCK_AUTH_PROVIDER: () => MOCK_AUTH_PROVIDER,
39
42
  MOCK_AUTH_VERIFIER: () => MOCK_AUTH_VERIFIER,
43
+ MeshNetworkAdapter: () => MeshNetworkAdapter,
40
44
  MetadataStore: () => MetadataStore,
41
45
  Pipeline: () => Pipeline,
42
46
  SnapshotManager: () => SnapshotManager,
@@ -48,12 +52,13 @@ __export(chunk_U6J2HC4T_exports, {
48
52
  TimeframeClock: () => TimeframeClock,
49
53
  codec: () => codec,
50
54
  createMappedFeedWriter: () => createMappedFeedWriter,
55
+ getSpaceKeyFromDoc: () => getSpaceKeyFromDoc,
51
56
  mapFeedIndexesToTimeframe: () => mapFeedIndexesToTimeframe,
52
57
  mapTimeframeToFeedIndexes: () => mapTimeframeToFeedIndexes,
53
58
  startAfter: () => startAfter,
54
59
  valueEncoding: () => valueEncoding
55
60
  });
56
- module.exports = __toCommonJS(chunk_U6J2HC4T_exports);
61
+ module.exports = __toCommonJS(chunk_EVKDEZDX_exports);
57
62
  var import_hypercore = require("@dxos/hypercore");
58
63
  var import_protocols = require("@dxos/protocols");
59
64
  var import_invariant = require("@dxos/invariant");
@@ -148,6 +153,27 @@ var import_keys7 = require("@dxos/keys");
148
153
  var import_log12 = require("@dxos/log");
149
154
  var import_protocols7 = require("@dxos/protocols");
150
155
  var import_util9 = require("@dxos/util");
156
+ var import_util10 = require("@dxos/util");
157
+ var import_async10 = require("@dxos/async");
158
+ var import_automerge_repo = require("@dxos/automerge/automerge-repo");
159
+ var import_codec_protobuf2 = require("@dxos/codec-protobuf");
160
+ var import_invariant10 = require("@dxos/invariant");
161
+ var import_log13 = require("@dxos/log");
162
+ var import_async11 = require("@dxos/async");
163
+ var import_automerge_repo2 = require("@dxos/automerge/automerge-repo");
164
+ var import_invariant11 = require("@dxos/invariant");
165
+ var import_log14 = require("@dxos/log");
166
+ var import_teleport_extension_automerge_replicator = require("@dxos/teleport-extension-automerge-replicator");
167
+ var import_automerge = require("@dxos/automerge/automerge");
168
+ var import_automerge_repo3 = require("@dxos/automerge/automerge-repo");
169
+ var import_automerge_repo_storage_indexeddb = require("@dxos/automerge/automerge-repo-storage-indexeddb");
170
+ var import_context8 = require("@dxos/context");
171
+ var import_keys8 = require("@dxos/keys");
172
+ var import_log15 = require("@dxos/log");
173
+ var import_protocols8 = require("@dxos/protocols");
174
+ var import_random_access_storage = require("@dxos/random-access-storage");
175
+ var import_tracing5 = require("@dxos/tracing");
176
+ var import_util11 = require("@dxos/util");
151
177
  var codec = import_protocols.schema.getCodecForType("dxos.echo.feed.FeedMessage");
152
178
  var valueEncoding = (0, import_hypercore.createCodecEncoding)(codec);
153
179
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/common/feeds.ts";
@@ -2015,13 +2041,11 @@ var ControlPipeline = class {
2015
2041
  queueMicrotask(async () => {
2016
2042
  try {
2017
2043
  const feed = await feedProvider(info.key);
2018
- if (!this._pipeline.hasFeed(feed.key)) {
2019
- await this._pipeline.addFeed(feed);
2020
- }
2044
+ await this._pipeline.addFeed(feed);
2021
2045
  } catch (err) {
2022
2046
  import_log10.log.catch(err, void 0, {
2023
2047
  F: __dxlog_file10,
2024
- L: 85,
2048
+ L: 83,
2025
2049
  S: this,
2026
2050
  C: (f, a) => f(...a)
2027
2051
  });
@@ -2051,7 +2075,7 @@ var ControlPipeline = class {
2051
2075
  tf: snapshot?.timeframe
2052
2076
  }, {
2053
2077
  F: __dxlog_file10,
2054
- L: 113,
2078
+ L: 111,
2055
2079
  S: this,
2056
2080
  C: (f, a) => f(...a)
2057
2081
  });
@@ -2060,7 +2084,7 @@ var ControlPipeline = class {
2060
2084
  }
2061
2085
  (0, import_log10.log)("starting...", void 0, {
2062
2086
  F: __dxlog_file10,
2063
- L: 118,
2087
+ L: 116,
2064
2088
  S: this,
2065
2089
  C: (f, a) => f(...a)
2066
2090
  });
@@ -2070,7 +2094,7 @@ var ControlPipeline = class {
2070
2094
  await this._pipeline.start();
2071
2095
  (0, import_log10.log)("started", void 0, {
2072
2096
  F: __dxlog_file10,
2073
- L: 124,
2097
+ L: 122,
2074
2098
  S: this,
2075
2099
  C: (f, a) => f(...a)
2076
2100
  });
@@ -2087,7 +2111,7 @@ var ControlPipeline = class {
2087
2111
  message
2088
2112
  }, {
2089
2113
  F: __dxlog_file10,
2090
- L: 137,
2114
+ L: 135,
2091
2115
  S: this,
2092
2116
  C: (f, a) => f(...a)
2093
2117
  });
@@ -2109,7 +2133,7 @@ var ControlPipeline = class {
2109
2133
  snapshot
2110
2134
  }, {
2111
2135
  F: __dxlog_file10,
2112
- L: 153,
2136
+ L: 151,
2113
2137
  S: this,
2114
2138
  C: (f, a) => f(...a)
2115
2139
  });
@@ -2124,7 +2148,7 @@ var ControlPipeline = class {
2124
2148
  } catch (err) {
2125
2149
  import_log10.log.catch(err, void 0, {
2126
2150
  F: __dxlog_file10,
2127
- L: 166,
2151
+ L: 164,
2128
2152
  S: this,
2129
2153
  C: (f, a) => f(...a)
2130
2154
  });
@@ -2138,7 +2162,7 @@ var ControlPipeline = class {
2138
2162
  seq: msg.seq
2139
2163
  }, {
2140
2164
  F: __dxlog_file10,
2141
- L: 176,
2165
+ L: 174,
2142
2166
  S: this,
2143
2167
  C: (f, a) => f(...a)
2144
2168
  });
@@ -2153,7 +2177,7 @@ var ControlPipeline = class {
2153
2177
  msg
2154
2178
  }, {
2155
2179
  F: __dxlog_file10,
2156
- L: 185,
2180
+ L: 183,
2157
2181
  S: this,
2158
2182
  C: (f, a) => f(...a)
2159
2183
  });
@@ -2172,7 +2196,7 @@ var ControlPipeline = class {
2172
2196
  async stop() {
2173
2197
  (0, import_log10.log)("stopping...", void 0, {
2174
2198
  F: __dxlog_file10,
2175
- L: 205,
2199
+ L: 203,
2176
2200
  S: this,
2177
2201
  C: (f, a) => f(...a)
2178
2202
  });
@@ -2181,7 +2205,7 @@ var ControlPipeline = class {
2181
2205
  await this._saveTargetTimeframe(this._pipeline.state.timeframe);
2182
2206
  (0, import_log10.log)("stopped", void 0, {
2183
2207
  F: __dxlog_file10,
2184
- L: 209,
2208
+ L: 207,
2185
2209
  S: this,
2186
2210
  C: (f, a) => f(...a)
2187
2211
  });
@@ -2194,7 +2218,7 @@ var ControlPipeline = class {
2194
2218
  } catch (err) {
2195
2219
  (0, import_log10.log)(err, void 0, {
2196
2220
  F: __dxlog_file10,
2197
- L: 218,
2221
+ L: 216,
2198
2222
  S: this,
2199
2223
  C: (f, a) => f(...a)
2200
2224
  });
@@ -2774,17 +2798,617 @@ _ts_decorate8([
2774
2798
  SpaceManager = _ts_decorate8([
2775
2799
  (0, import_async9.trackLeaks)("open", "close")
2776
2800
  ], SpaceManager);
2801
+ var AutomergeStorageAdapter = class {
2802
+ constructor(_directory) {
2803
+ this._directory = _directory;
2804
+ this._state = "opened";
2805
+ }
2806
+ async load(key) {
2807
+ if (this._state !== "opened") {
2808
+ return void 0;
2809
+ }
2810
+ const filename = this._getFilename(key);
2811
+ const file = this._directory.getOrCreateFile(filename);
2812
+ const { size } = await file.stat();
2813
+ if (!size || size === 0) {
2814
+ return void 0;
2815
+ }
2816
+ const buffer = await file.read(0, size);
2817
+ return (0, import_util10.bufferToArray)(buffer);
2818
+ }
2819
+ async save(key, data) {
2820
+ if (this._state !== "opened") {
2821
+ return void 0;
2822
+ }
2823
+ const filename = this._getFilename(key);
2824
+ const file = this._directory.getOrCreateFile(filename);
2825
+ await file.write(0, (0, import_util10.arrayToBuffer)(data));
2826
+ await file.truncate?.(data.length);
2827
+ await file.flush?.();
2828
+ }
2829
+ async remove(key) {
2830
+ if (this._state !== "opened") {
2831
+ return void 0;
2832
+ }
2833
+ const filename = this._getFilename(key);
2834
+ const file = this._directory.getOrCreateFile(filename);
2835
+ await file.destroy();
2836
+ }
2837
+ async loadRange(keyPrefix) {
2838
+ if (this._state !== "opened") {
2839
+ return [];
2840
+ }
2841
+ const filename = this._getFilename(keyPrefix);
2842
+ const entries = await this._directory.list();
2843
+ return Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
2844
+ const file = this._directory.getOrCreateFile(entry);
2845
+ const { size } = await file.stat();
2846
+ const buffer = await file.read(0, size);
2847
+ return {
2848
+ key: this._getKeyFromFilename(entry),
2849
+ data: (0, import_util10.bufferToArray)(buffer)
2850
+ };
2851
+ }));
2852
+ }
2853
+ async removeRange(keyPrefix) {
2854
+ if (this._state !== "opened") {
2855
+ return void 0;
2856
+ }
2857
+ const filename = this._getFilename(keyPrefix);
2858
+ const entries = await this._directory.list();
2859
+ await Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
2860
+ const file = this._directory.getOrCreateFile(entry);
2861
+ await file.destroy();
2862
+ }));
2863
+ }
2864
+ async close() {
2865
+ this._state = "closed";
2866
+ }
2867
+ _getFilename(key) {
2868
+ return key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-");
2869
+ }
2870
+ _getKeyFromFilename(filename) {
2871
+ return filename.split("-").map((k) => k.replaceAll("%2D", "-").replaceAll("%25", "%"));
2872
+ }
2873
+ };
2874
+ var __dxlog_file14 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/local-host-network-adapter.ts";
2875
+ var LocalHostNetworkAdapter = class extends import_automerge_repo.NetworkAdapter {
2876
+ constructor() {
2877
+ super(...arguments);
2878
+ this._peers = /* @__PURE__ */ new Map();
2879
+ this._connected = new import_async10.Trigger();
2880
+ }
2881
+ /**
2882
+ * Emits `ready` event. That signals to `Repo` that it can start using the adapter.
2883
+ */
2884
+ ready() {
2885
+ this.emit("ready", {
2886
+ network: this
2887
+ });
2888
+ }
2889
+ connect(peerId) {
2890
+ this.peerId = peerId;
2891
+ this._connected.wake();
2892
+ }
2893
+ send(message) {
2894
+ const peer = this._peers.get(message.targetId);
2895
+ (0, import_invariant10.invariant)(peer, "Peer not found.", {
2896
+ F: __dxlog_file14,
2897
+ L: 45,
2898
+ S: this,
2899
+ A: [
2900
+ "peer",
2901
+ "'Peer not found.'"
2902
+ ]
2903
+ });
2904
+ peer.send(message);
2905
+ }
2906
+ async close() {
2907
+ this._peers.forEach((peer) => peer.disconnect());
2908
+ this.emit("close");
2909
+ }
2910
+ disconnect() {
2911
+ }
2912
+ syncRepo({ id, syncMessage }) {
2913
+ const peerId = this._getPeerId(id);
2914
+ return new import_codec_protobuf2.Stream(({ next, close }) => {
2915
+ (0, import_invariant10.invariant)(!this._peers.has(peerId), "Peer already connected.", {
2916
+ F: __dxlog_file14,
2917
+ L: 63,
2918
+ S: this,
2919
+ A: [
2920
+ "!this._peers.has(peerId)",
2921
+ "'Peer already connected.'"
2922
+ ]
2923
+ });
2924
+ this._peers.set(peerId, {
2925
+ connected: true,
2926
+ send: (message) => {
2927
+ next({
2928
+ syncMessage: import_automerge_repo.cbor.encode(message)
2929
+ });
2930
+ },
2931
+ disconnect: () => {
2932
+ this._peers.delete(peerId);
2933
+ close();
2934
+ this.emit("peer-disconnected", {
2935
+ peerId
2936
+ });
2937
+ }
2938
+ });
2939
+ this._connected.wait({
2940
+ timeout: 1e3
2941
+ }).then(() => {
2942
+ this.emit("peer-candidate", {
2943
+ peerMetadata: {},
2944
+ peerId
2945
+ });
2946
+ }).catch((err) => import_log13.log.catch(err, void 0, {
2947
+ F: __dxlog_file14,
2948
+ L: 88,
2949
+ S: this,
2950
+ C: (f, a) => f(...a)
2951
+ }));
2952
+ });
2953
+ }
2954
+ async sendSyncMessage({ id, syncMessage }) {
2955
+ await this._connected.wait({
2956
+ timeout: 1e3
2957
+ });
2958
+ const message = import_automerge_repo.cbor.decode(syncMessage);
2959
+ this.emit("message", message);
2960
+ }
2961
+ async getHostInfo() {
2962
+ await this._connected.wait({
2963
+ timeout: 1e3
2964
+ });
2965
+ (0, import_invariant10.invariant)(this.peerId, "Peer id not set.", {
2966
+ F: __dxlog_file14,
2967
+ L: 100,
2968
+ S: this,
2969
+ A: [
2970
+ "this.peerId",
2971
+ "'Peer id not set.'"
2972
+ ]
2973
+ });
2974
+ return {
2975
+ peerId: this.peerId
2976
+ };
2977
+ }
2978
+ _getPeerId(id) {
2979
+ return id;
2980
+ }
2981
+ };
2982
+ var __dxlog_file15 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-network-adapter.ts";
2983
+ var MeshNetworkAdapter = class extends import_automerge_repo2.NetworkAdapter {
2984
+ constructor() {
2985
+ super(...arguments);
2986
+ this._extensions = /* @__PURE__ */ new Map();
2987
+ this._connected = new import_async11.Trigger();
2988
+ }
2989
+ /**
2990
+ * Emits `ready` event. That signals to `Repo` that it can start using the adapter.
2991
+ */
2992
+ ready() {
2993
+ this.emit("ready", {
2994
+ network: this
2995
+ });
2996
+ }
2997
+ connect(peerId) {
2998
+ this.peerId = peerId;
2999
+ this._connected.wake();
3000
+ }
3001
+ send(message) {
3002
+ const receiverId = message.targetId;
3003
+ const extension = this._extensions.get(receiverId);
3004
+ (0, import_invariant11.invariant)(extension, "Extension not found.", {
3005
+ F: __dxlog_file15,
3006
+ L: 38,
3007
+ S: this,
3008
+ A: [
3009
+ "extension",
3010
+ "'Extension not found.'"
3011
+ ]
3012
+ });
3013
+ extension.sendSyncMessage({
3014
+ payload: import_automerge_repo2.cbor.encode(message)
3015
+ }).catch((err) => import_log14.log.catch(err, void 0, {
3016
+ F: __dxlog_file15,
3017
+ L: 39,
3018
+ S: this,
3019
+ C: (f, a) => f(...a)
3020
+ }));
3021
+ }
3022
+ disconnect() {
3023
+ }
3024
+ createExtension() {
3025
+ (0, import_invariant11.invariant)(this.peerId, "Peer id not set.", {
3026
+ F: __dxlog_file15,
3027
+ L: 47,
3028
+ S: this,
3029
+ A: [
3030
+ "this.peerId",
3031
+ "'Peer id not set.'"
3032
+ ]
3033
+ });
3034
+ let peerInfo;
3035
+ const extension = new import_teleport_extension_automerge_replicator.AutomergeReplicator({
3036
+ peerId: this.peerId
3037
+ }, {
3038
+ onStartReplication: async (info, remotePeerId) => {
3039
+ await this._connected.wait();
3040
+ (0, import_log14.log)("onStartReplication", {
3041
+ id: info.id,
3042
+ thisPeerId: this.peerId,
3043
+ remotePeerId: remotePeerId.toHex()
3044
+ }, {
3045
+ F: __dxlog_file15,
3046
+ L: 70,
3047
+ S: this,
3048
+ C: (f, a) => f(...a)
3049
+ });
3050
+ if (!this._extensions.has(info.id)) {
3051
+ peerInfo = info;
3052
+ this._extensions.set(info.id, extension);
3053
+ (0, import_log14.log)("peer-candidate", {
3054
+ id: info.id,
3055
+ thisPeerId: this.peerId,
3056
+ remotePeerId: remotePeerId.toHex()
3057
+ }, {
3058
+ F: __dxlog_file15,
3059
+ L: 76,
3060
+ S: this,
3061
+ C: (f, a) => f(...a)
3062
+ });
3063
+ this.emit("peer-candidate", {
3064
+ // TODO(mykola): Hack, stop abusing `peerMetadata` field.
3065
+ peerMetadata: {
3066
+ dxos_deviceKey: remotePeerId.toHex()
3067
+ },
3068
+ peerId: info.id
3069
+ });
3070
+ }
3071
+ },
3072
+ onSyncMessage: async ({ payload }) => {
3073
+ if (!peerInfo) {
3074
+ return;
3075
+ }
3076
+ const message = import_automerge_repo2.cbor.decode(payload);
3077
+ this.emit("message", message);
3078
+ },
3079
+ onClose: async () => {
3080
+ if (!peerInfo) {
3081
+ return;
3082
+ }
3083
+ this.emit("peer-disconnected", {
3084
+ peerId: peerInfo.id
3085
+ });
3086
+ this._extensions.delete(peerInfo.id);
3087
+ }
3088
+ });
3089
+ return extension;
3090
+ }
3091
+ };
3092
+ var AutomergeStorageWrapper = class {
3093
+ constructor({ storage, callbacks }) {
3094
+ this._storage = storage;
3095
+ this._callbacks = callbacks;
3096
+ }
3097
+ async load(key) {
3098
+ return this._storage.load(key);
3099
+ }
3100
+ async save(key, value) {
3101
+ await this._callbacks.beforeSave?.(key);
3102
+ await this._storage.save(key, value);
3103
+ await this._callbacks.afterSave?.(key);
3104
+ }
3105
+ async remove(key) {
3106
+ return this._storage.remove(key);
3107
+ }
3108
+ async loadRange(keyPrefix) {
3109
+ return this._storage.loadRange(keyPrefix);
3110
+ }
3111
+ async removeRange(keyPrefix) {
3112
+ return this._storage.removeRange(keyPrefix);
3113
+ }
3114
+ async close() {
3115
+ if (this._storage instanceof AutomergeStorageAdapter) {
3116
+ return this._storage.close();
3117
+ }
3118
+ }
3119
+ };
3120
+ function _ts_decorate9(decorators, target, key, desc) {
3121
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3122
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
3123
+ r = Reflect.decorate(decorators, target, key, desc);
3124
+ else
3125
+ for (var i = decorators.length - 1; i >= 0; i--)
3126
+ if (d = decorators[i])
3127
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3128
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
3129
+ }
3130
+ var __dxlog_file16 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
3131
+ var AutomergeHost = class {
3132
+ constructor({ directory, metadata }) {
3133
+ this._ctx = new import_context8.Context();
3134
+ this._authorizedDevices = new import_util11.ComplexMap(import_keys8.PublicKey.hash);
3135
+ this._updatingMetadata = /* @__PURE__ */ new Map();
3136
+ this._requestedDocs = /* @__PURE__ */ new Set();
3137
+ this._metadata = metadata;
3138
+ this._meshNetwork = new MeshNetworkAdapter();
3139
+ this._clientNetwork = new LocalHostNetworkAdapter();
3140
+ this._storage = new AutomergeStorageWrapper({
3141
+ storage: (
3142
+ // TODO(mykola): Delete specific handling of IDB storage.
3143
+ directory.type === import_random_access_storage.StorageType.IDB ? new import_automerge_repo_storage_indexeddb.IndexedDBStorageAdapter(directory.path, "data") : new AutomergeStorageAdapter(directory)
3144
+ ),
3145
+ callbacks: {
3146
+ beforeSave: (params) => this._beforeSave(params)
3147
+ }
3148
+ });
3149
+ this._peerId = `host-${import_keys8.PublicKey.random().toHex()}`;
3150
+ this._repo = new import_automerge_repo3.Repo({
3151
+ peerId: this._peerId,
3152
+ network: [
3153
+ this._clientNetwork,
3154
+ this._meshNetwork
3155
+ ],
3156
+ storage: this._storage,
3157
+ // TODO(dmaretskyi): Share based on HALO permissions and space affinity.
3158
+ // Hosts, running in the worker, don't share documents unless requested by other peers.
3159
+ sharePolicy: async (peerId, documentId) => {
3160
+ if (peerId.startsWith("client-")) {
3161
+ return false;
3162
+ }
3163
+ if (!documentId) {
3164
+ return false;
3165
+ }
3166
+ const doc = this._repo.handles[documentId]?.docSync();
3167
+ if (!doc) {
3168
+ const isRequested = this._requestedDocs.has(`automerge:${documentId}`);
3169
+ (0, import_log15.log)("doc share policy check", {
3170
+ peerId,
3171
+ documentId,
3172
+ isRequested
3173
+ }, {
3174
+ F: __dxlog_file16,
3175
+ L: 96,
3176
+ S: this,
3177
+ C: (f, a) => f(...a)
3178
+ });
3179
+ return isRequested;
3180
+ }
3181
+ try {
3182
+ const spaceKey = getSpaceKeyFromDoc(doc);
3183
+ if (!spaceKey) {
3184
+ (0, import_log15.log)("space key not found for share policy check", {
3185
+ peerId,
3186
+ documentId
3187
+ }, {
3188
+ F: __dxlog_file16,
3189
+ L: 103,
3190
+ S: this,
3191
+ C: (f, a) => f(...a)
3192
+ });
3193
+ return false;
3194
+ }
3195
+ const authorizedDevices = this._authorizedDevices.get(import_keys8.PublicKey.from(spaceKey));
3196
+ const deviceKeyHex = this.repo.peerMetadataByPeerId[peerId]?.dxos_deviceKey;
3197
+ if (!deviceKeyHex) {
3198
+ (0, import_log15.log)("device key not found for share policy check", {
3199
+ peerId,
3200
+ documentId
3201
+ }, {
3202
+ F: __dxlog_file16,
3203
+ L: 112,
3204
+ S: this,
3205
+ C: (f, a) => f(...a)
3206
+ });
3207
+ return false;
3208
+ }
3209
+ const deviceKey = import_keys8.PublicKey.from(deviceKeyHex);
3210
+ const isAuthorized = authorizedDevices?.has(deviceKey) ?? false;
3211
+ (0, import_log15.log)("share policy check", {
3212
+ localPeer: this._peerId,
3213
+ remotePeer: peerId,
3214
+ documentId,
3215
+ deviceKey,
3216
+ spaceKey,
3217
+ isAuthorized
3218
+ }, {
3219
+ F: __dxlog_file16,
3220
+ L: 118,
3221
+ S: this,
3222
+ C: (f, a) => f(...a)
3223
+ });
3224
+ return isAuthorized;
3225
+ } catch (err) {
3226
+ import_log15.log.catch(err, void 0, {
3227
+ F: __dxlog_file16,
3228
+ L: 128,
3229
+ S: this,
3230
+ C: (f, a) => f(...a)
3231
+ });
3232
+ return false;
3233
+ }
3234
+ }
3235
+ });
3236
+ this._clientNetwork.ready();
3237
+ this._meshNetwork.ready();
3238
+ {
3239
+ const listener = ({ handle }) => this._onDocument(handle);
3240
+ this._repo.on("document", listener);
3241
+ this._ctx.onDispose(() => {
3242
+ this._repo.off("document", listener);
3243
+ });
3244
+ }
3245
+ }
3246
+ get repo() {
3247
+ return this._repo;
3248
+ }
3249
+ async _beforeSave(path) {
3250
+ const id = path[0];
3251
+ if (this._updatingMetadata.has(id)) {
3252
+ return this._updatingMetadata.get(id);
3253
+ }
3254
+ }
3255
+ _onDocument(handle) {
3256
+ const listener = (event) => this._onUpdate(event);
3257
+ handle.on("change", listener);
3258
+ this._ctx.onDispose(() => {
3259
+ handle.off("change", listener);
3260
+ });
3261
+ }
3262
+ _onUpdate(event) {
3263
+ if (this._metadata == null) {
3264
+ return;
3265
+ }
3266
+ const objectIds = getInlineChanges(event);
3267
+ if (objectIds.length === 0) {
3268
+ return;
3269
+ }
3270
+ const heads = (0, import_automerge.getHeads)(event.doc);
3271
+ const lastAvailableHash = heads.at(-1);
3272
+ if (!lastAvailableHash) {
3273
+ return;
3274
+ }
3275
+ const encodedIds = objectIds.map((objectId) => import_protocols8.idCodec.encode({
3276
+ documentId: event.handle.documentId,
3277
+ objectId
3278
+ }));
3279
+ const idToLastHash = new Map(encodedIds.map((id) => [
3280
+ id,
3281
+ lastAvailableHash
3282
+ ]));
3283
+ const markingDirtyPromise = this._metadata.markDirty(idToLastHash).then(() => {
3284
+ this._updatingMetadata.delete(event.handle.documentId);
3285
+ }).catch((err) => {
3286
+ this._ctx.disposed && import_log15.log.catch(err, void 0, {
3287
+ F: __dxlog_file16,
3288
+ L: 188,
3289
+ S: this,
3290
+ C: (f, a) => f(...a)
3291
+ });
3292
+ });
3293
+ this._updatingMetadata.set(event.handle.documentId, markingDirtyPromise);
3294
+ }
3295
+ _automergeDocs() {
3296
+ return (0, import_util11.mapValues)(this._repo.handles, (handle) => ({
3297
+ state: handle.state,
3298
+ hasDoc: !!handle.docSync(),
3299
+ heads: handle.docSync() ? import_automerge.next.getHeads(handle.docSync()) : null,
3300
+ data: handle.docSync()?.doc && (0, import_util11.mapValues)(handle.docSync()?.doc, (value, key) => {
3301
+ try {
3302
+ switch (key) {
3303
+ case "access":
3304
+ case "links":
3305
+ return value;
3306
+ case "objects":
3307
+ return Object.keys(value);
3308
+ default:
3309
+ return `${value}`;
3310
+ }
3311
+ } catch (err) {
3312
+ return `${err}`;
3313
+ }
3314
+ })
3315
+ }));
3316
+ }
3317
+ _automergePeers() {
3318
+ return this._repo.peers;
3319
+ }
3320
+ async close() {
3321
+ await this._storage.close();
3322
+ await this._clientNetwork.close();
3323
+ await this._ctx.dispose();
3324
+ }
3325
+ //
3326
+ // Methods for client-services.
3327
+ //
3328
+ syncRepo(request) {
3329
+ return this._clientNetwork.syncRepo(request);
3330
+ }
3331
+ sendSyncMessage(request) {
3332
+ return this._clientNetwork.sendSyncMessage(request);
3333
+ }
3334
+ async getHostInfo() {
3335
+ return this._clientNetwork.getHostInfo();
3336
+ }
3337
+ //
3338
+ // Mesh replication.
3339
+ //
3340
+ createExtension() {
3341
+ return this._meshNetwork.createExtension();
3342
+ }
3343
+ authorizeDevice(spaceKey, deviceKey) {
3344
+ (0, import_log15.log)("authorizeDevice", {
3345
+ spaceKey,
3346
+ deviceKey
3347
+ }, {
3348
+ F: __dxlog_file16,
3349
+ L: 255,
3350
+ S: this,
3351
+ C: (f, a) => f(...a)
3352
+ });
3353
+ (0, import_util11.defaultMap)(this._authorizedDevices, spaceKey, () => new import_util11.ComplexSet(import_keys8.PublicKey.hash)).add(deviceKey);
3354
+ }
3355
+ };
3356
+ _ts_decorate9([
3357
+ import_tracing5.trace.info()
3358
+ ], AutomergeHost.prototype, "_peerId", void 0);
3359
+ _ts_decorate9([
3360
+ import_tracing5.trace.info({
3361
+ depth: null
3362
+ })
3363
+ ], AutomergeHost.prototype, "_automergeDocs", null);
3364
+ _ts_decorate9([
3365
+ import_tracing5.trace.info({
3366
+ depth: null
3367
+ })
3368
+ ], AutomergeHost.prototype, "_automergePeers", null);
3369
+ AutomergeHost = _ts_decorate9([
3370
+ import_tracing5.trace.resource()
3371
+ ], AutomergeHost);
3372
+ var getInlineChanges = (event) => {
3373
+ const inlineChangedObjectIds = /* @__PURE__ */ new Set();
3374
+ for (const { path } of event.patches) {
3375
+ if (path.length < 2) {
3376
+ continue;
3377
+ }
3378
+ switch (path[0]) {
3379
+ case "objects":
3380
+ if (path.length >= 2) {
3381
+ inlineChangedObjectIds.add(path[1]);
3382
+ }
3383
+ break;
3384
+ }
3385
+ }
3386
+ return [
3387
+ ...inlineChangedObjectIds
3388
+ ];
3389
+ };
3390
+ var getSpaceKeyFromDoc = (doc) => {
3391
+ const rawSpaceKey = doc.access?.spaceKey ?? doc.experimental_spaceKey;
3392
+ if (rawSpaceKey == null) {
3393
+ return null;
3394
+ }
3395
+ return String(rawSpaceKey);
3396
+ };
2777
3397
  // Annotate the CommonJS export names for ESM import in node:
2778
3398
  0 && (module.exports = {
2779
3399
  AuthExtension,
2780
3400
  AuthStatus,
3401
+ AutomergeHost,
3402
+ AutomergeStorageAdapter,
2781
3403
  DataPipeline,
2782
3404
  DataServiceHost,
2783
3405
  DataServiceImpl,
2784
3406
  DataServiceSubscriptions,
2785
3407
  DatabaseHost,
3408
+ LocalHostNetworkAdapter,
2786
3409
  MOCK_AUTH_PROVIDER,
2787
3410
  MOCK_AUTH_VERIFIER,
3411
+ MeshNetworkAdapter,
2788
3412
  MetadataStore,
2789
3413
  Pipeline,
2790
3414
  SnapshotManager,
@@ -2796,9 +3420,10 @@ SpaceManager = _ts_decorate8([
2796
3420
  TimeframeClock,
2797
3421
  codec,
2798
3422
  createMappedFeedWriter,
3423
+ getSpaceKeyFromDoc,
2799
3424
  mapFeedIndexesToTimeframe,
2800
3425
  mapTimeframeToFeedIndexes,
2801
3426
  startAfter,
2802
3427
  valueEncoding
2803
3428
  });
2804
- //# sourceMappingURL=chunk-U6J2HC4T.cjs.map
3429
+ //# sourceMappingURL=chunk-EVKDEZDX.cjs.map