@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
@@ -1987,13 +1987,11 @@ var ControlPipeline = class {
1987
1987
  queueMicrotask(async () => {
1988
1988
  try {
1989
1989
  const feed = await feedProvider(info.key);
1990
- if (!this._pipeline.hasFeed(feed.key)) {
1991
- await this._pipeline.addFeed(feed);
1992
- }
1990
+ await this._pipeline.addFeed(feed);
1993
1991
  } catch (err) {
1994
1992
  log9.catch(err, void 0, {
1995
1993
  F: __dxlog_file10,
1996
- L: 85,
1994
+ L: 83,
1997
1995
  S: this,
1998
1996
  C: (f, a) => f(...a)
1999
1997
  });
@@ -2023,7 +2021,7 @@ var ControlPipeline = class {
2023
2021
  tf: snapshot?.timeframe
2024
2022
  }, {
2025
2023
  F: __dxlog_file10,
2026
- L: 113,
2024
+ L: 111,
2027
2025
  S: this,
2028
2026
  C: (f, a) => f(...a)
2029
2027
  });
@@ -2032,7 +2030,7 @@ var ControlPipeline = class {
2032
2030
  }
2033
2031
  log9("starting...", void 0, {
2034
2032
  F: __dxlog_file10,
2035
- L: 118,
2033
+ L: 116,
2036
2034
  S: this,
2037
2035
  C: (f, a) => f(...a)
2038
2036
  });
@@ -2042,7 +2040,7 @@ var ControlPipeline = class {
2042
2040
  await this._pipeline.start();
2043
2041
  log9("started", void 0, {
2044
2042
  F: __dxlog_file10,
2045
- L: 124,
2043
+ L: 122,
2046
2044
  S: this,
2047
2045
  C: (f, a) => f(...a)
2048
2046
  });
@@ -2059,7 +2057,7 @@ var ControlPipeline = class {
2059
2057
  message
2060
2058
  }, {
2061
2059
  F: __dxlog_file10,
2062
- L: 137,
2060
+ L: 135,
2063
2061
  S: this,
2064
2062
  C: (f, a) => f(...a)
2065
2063
  });
@@ -2081,7 +2079,7 @@ var ControlPipeline = class {
2081
2079
  snapshot
2082
2080
  }, {
2083
2081
  F: __dxlog_file10,
2084
- L: 153,
2082
+ L: 151,
2085
2083
  S: this,
2086
2084
  C: (f, a) => f(...a)
2087
2085
  });
@@ -2096,7 +2094,7 @@ var ControlPipeline = class {
2096
2094
  } catch (err) {
2097
2095
  log9.catch(err, void 0, {
2098
2096
  F: __dxlog_file10,
2099
- L: 166,
2097
+ L: 164,
2100
2098
  S: this,
2101
2099
  C: (f, a) => f(...a)
2102
2100
  });
@@ -2110,7 +2108,7 @@ var ControlPipeline = class {
2110
2108
  seq: msg.seq
2111
2109
  }, {
2112
2110
  F: __dxlog_file10,
2113
- L: 176,
2111
+ L: 174,
2114
2112
  S: this,
2115
2113
  C: (f, a) => f(...a)
2116
2114
  });
@@ -2125,7 +2123,7 @@ var ControlPipeline = class {
2125
2123
  msg
2126
2124
  }, {
2127
2125
  F: __dxlog_file10,
2128
- L: 185,
2126
+ L: 183,
2129
2127
  S: this,
2130
2128
  C: (f, a) => f(...a)
2131
2129
  });
@@ -2144,7 +2142,7 @@ var ControlPipeline = class {
2144
2142
  async stop() {
2145
2143
  log9("stopping...", void 0, {
2146
2144
  F: __dxlog_file10,
2147
- L: 205,
2145
+ L: 203,
2148
2146
  S: this,
2149
2147
  C: (f, a) => f(...a)
2150
2148
  });
@@ -2153,7 +2151,7 @@ var ControlPipeline = class {
2153
2151
  await this._saveTargetTimeframe(this._pipeline.state.timeframe);
2154
2152
  log9("stopped", void 0, {
2155
2153
  F: __dxlog_file10,
2156
- L: 209,
2154
+ L: 207,
2157
2155
  S: this,
2158
2156
  C: (f, a) => f(...a)
2159
2157
  });
@@ -2166,7 +2164,7 @@ var ControlPipeline = class {
2166
2164
  } catch (err) {
2167
2165
  log9(err, void 0, {
2168
2166
  F: __dxlog_file10,
2169
- L: 218,
2167
+ L: 216,
2170
2168
  S: this,
2171
2169
  C: (f, a) => f(...a)
2172
2170
  });
@@ -2769,6 +2767,638 @@ SpaceManager = _ts_decorate8([
2769
2767
  trackLeaks4("open", "close")
2770
2768
  ], SpaceManager);
2771
2769
 
2770
+ // packages/core/echo/echo-pipeline/src/automerge/automerge-storage-adapter.ts
2771
+ import { arrayToBuffer as arrayToBuffer2, bufferToArray } from "@dxos/util";
2772
+ var AutomergeStorageAdapter = class {
2773
+ constructor(_directory) {
2774
+ this._directory = _directory;
2775
+ this._state = "opened";
2776
+ }
2777
+ async load(key) {
2778
+ if (this._state !== "opened") {
2779
+ return void 0;
2780
+ }
2781
+ const filename = this._getFilename(key);
2782
+ const file = this._directory.getOrCreateFile(filename);
2783
+ const { size } = await file.stat();
2784
+ if (!size || size === 0) {
2785
+ return void 0;
2786
+ }
2787
+ const buffer = await file.read(0, size);
2788
+ return bufferToArray(buffer);
2789
+ }
2790
+ async save(key, data) {
2791
+ if (this._state !== "opened") {
2792
+ return void 0;
2793
+ }
2794
+ const filename = this._getFilename(key);
2795
+ const file = this._directory.getOrCreateFile(filename);
2796
+ await file.write(0, arrayToBuffer2(data));
2797
+ await file.truncate?.(data.length);
2798
+ await file.flush?.();
2799
+ }
2800
+ async remove(key) {
2801
+ if (this._state !== "opened") {
2802
+ return void 0;
2803
+ }
2804
+ const filename = this._getFilename(key);
2805
+ const file = this._directory.getOrCreateFile(filename);
2806
+ await file.destroy();
2807
+ }
2808
+ async loadRange(keyPrefix) {
2809
+ if (this._state !== "opened") {
2810
+ return [];
2811
+ }
2812
+ const filename = this._getFilename(keyPrefix);
2813
+ const entries = await this._directory.list();
2814
+ return Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
2815
+ const file = this._directory.getOrCreateFile(entry);
2816
+ const { size } = await file.stat();
2817
+ const buffer = await file.read(0, size);
2818
+ return {
2819
+ key: this._getKeyFromFilename(entry),
2820
+ data: bufferToArray(buffer)
2821
+ };
2822
+ }));
2823
+ }
2824
+ async removeRange(keyPrefix) {
2825
+ if (this._state !== "opened") {
2826
+ return void 0;
2827
+ }
2828
+ const filename = this._getFilename(keyPrefix);
2829
+ const entries = await this._directory.list();
2830
+ await Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
2831
+ const file = this._directory.getOrCreateFile(entry);
2832
+ await file.destroy();
2833
+ }));
2834
+ }
2835
+ async close() {
2836
+ this._state = "closed";
2837
+ }
2838
+ _getFilename(key) {
2839
+ return key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-");
2840
+ }
2841
+ _getKeyFromFilename(filename) {
2842
+ return filename.split("-").map((k) => k.replaceAll("%2D", "-").replaceAll("%25", "%"));
2843
+ }
2844
+ };
2845
+
2846
+ // packages/core/echo/echo-pipeline/src/automerge/local-host-network-adapter.ts
2847
+ import { Trigger as Trigger2 } from "@dxos/async";
2848
+ import { NetworkAdapter, cbor } from "@dxos/automerge/automerge-repo";
2849
+ import { Stream as Stream2 } from "@dxos/codec-protobuf";
2850
+ import { invariant as invariant10 } from "@dxos/invariant";
2851
+ import { log as log13 } from "@dxos/log";
2852
+ var __dxlog_file14 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/local-host-network-adapter.ts";
2853
+ var LocalHostNetworkAdapter = class extends NetworkAdapter {
2854
+ constructor() {
2855
+ super(...arguments);
2856
+ this._peers = /* @__PURE__ */ new Map();
2857
+ this._connected = new Trigger2();
2858
+ }
2859
+ /**
2860
+ * Emits `ready` event. That signals to `Repo` that it can start using the adapter.
2861
+ */
2862
+ ready() {
2863
+ this.emit("ready", {
2864
+ network: this
2865
+ });
2866
+ }
2867
+ connect(peerId) {
2868
+ this.peerId = peerId;
2869
+ this._connected.wake();
2870
+ }
2871
+ send(message) {
2872
+ const peer = this._peers.get(message.targetId);
2873
+ invariant10(peer, "Peer not found.", {
2874
+ F: __dxlog_file14,
2875
+ L: 45,
2876
+ S: this,
2877
+ A: [
2878
+ "peer",
2879
+ "'Peer not found.'"
2880
+ ]
2881
+ });
2882
+ peer.send(message);
2883
+ }
2884
+ async close() {
2885
+ this._peers.forEach((peer) => peer.disconnect());
2886
+ this.emit("close");
2887
+ }
2888
+ disconnect() {
2889
+ }
2890
+ syncRepo({ id, syncMessage }) {
2891
+ const peerId = this._getPeerId(id);
2892
+ return new Stream2(({ next, close }) => {
2893
+ invariant10(!this._peers.has(peerId), "Peer already connected.", {
2894
+ F: __dxlog_file14,
2895
+ L: 63,
2896
+ S: this,
2897
+ A: [
2898
+ "!this._peers.has(peerId)",
2899
+ "'Peer already connected.'"
2900
+ ]
2901
+ });
2902
+ this._peers.set(peerId, {
2903
+ connected: true,
2904
+ send: (message) => {
2905
+ next({
2906
+ syncMessage: cbor.encode(message)
2907
+ });
2908
+ },
2909
+ disconnect: () => {
2910
+ this._peers.delete(peerId);
2911
+ close();
2912
+ this.emit("peer-disconnected", {
2913
+ peerId
2914
+ });
2915
+ }
2916
+ });
2917
+ this._connected.wait({
2918
+ timeout: 1e3
2919
+ }).then(() => {
2920
+ this.emit("peer-candidate", {
2921
+ peerMetadata: {},
2922
+ peerId
2923
+ });
2924
+ }).catch((err) => log13.catch(err, void 0, {
2925
+ F: __dxlog_file14,
2926
+ L: 88,
2927
+ S: this,
2928
+ C: (f, a) => f(...a)
2929
+ }));
2930
+ });
2931
+ }
2932
+ async sendSyncMessage({ id, syncMessage }) {
2933
+ await this._connected.wait({
2934
+ timeout: 1e3
2935
+ });
2936
+ const message = cbor.decode(syncMessage);
2937
+ this.emit("message", message);
2938
+ }
2939
+ async getHostInfo() {
2940
+ await this._connected.wait({
2941
+ timeout: 1e3
2942
+ });
2943
+ invariant10(this.peerId, "Peer id not set.", {
2944
+ F: __dxlog_file14,
2945
+ L: 100,
2946
+ S: this,
2947
+ A: [
2948
+ "this.peerId",
2949
+ "'Peer id not set.'"
2950
+ ]
2951
+ });
2952
+ return {
2953
+ peerId: this.peerId
2954
+ };
2955
+ }
2956
+ _getPeerId(id) {
2957
+ return id;
2958
+ }
2959
+ };
2960
+
2961
+ // packages/core/echo/echo-pipeline/src/automerge/mesh-network-adapter.ts
2962
+ import { Trigger as Trigger3 } from "@dxos/async";
2963
+ import { NetworkAdapter as NetworkAdapter2, cbor as cbor2 } from "@dxos/automerge/automerge-repo";
2964
+ import { invariant as invariant11 } from "@dxos/invariant";
2965
+ import { log as log14 } from "@dxos/log";
2966
+ import { AutomergeReplicator } from "@dxos/teleport-extension-automerge-replicator";
2967
+ var __dxlog_file15 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/mesh-network-adapter.ts";
2968
+ var MeshNetworkAdapter = class extends NetworkAdapter2 {
2969
+ constructor() {
2970
+ super(...arguments);
2971
+ this._extensions = /* @__PURE__ */ new Map();
2972
+ this._connected = new Trigger3();
2973
+ }
2974
+ /**
2975
+ * Emits `ready` event. That signals to `Repo` that it can start using the adapter.
2976
+ */
2977
+ ready() {
2978
+ this.emit("ready", {
2979
+ network: this
2980
+ });
2981
+ }
2982
+ connect(peerId) {
2983
+ this.peerId = peerId;
2984
+ this._connected.wake();
2985
+ }
2986
+ send(message) {
2987
+ const receiverId = message.targetId;
2988
+ const extension = this._extensions.get(receiverId);
2989
+ invariant11(extension, "Extension not found.", {
2990
+ F: __dxlog_file15,
2991
+ L: 38,
2992
+ S: this,
2993
+ A: [
2994
+ "extension",
2995
+ "'Extension not found.'"
2996
+ ]
2997
+ });
2998
+ extension.sendSyncMessage({
2999
+ payload: cbor2.encode(message)
3000
+ }).catch((err) => log14.catch(err, void 0, {
3001
+ F: __dxlog_file15,
3002
+ L: 39,
3003
+ S: this,
3004
+ C: (f, a) => f(...a)
3005
+ }));
3006
+ }
3007
+ disconnect() {
3008
+ }
3009
+ createExtension() {
3010
+ invariant11(this.peerId, "Peer id not set.", {
3011
+ F: __dxlog_file15,
3012
+ L: 47,
3013
+ S: this,
3014
+ A: [
3015
+ "this.peerId",
3016
+ "'Peer id not set.'"
3017
+ ]
3018
+ });
3019
+ let peerInfo;
3020
+ const extension = new AutomergeReplicator({
3021
+ peerId: this.peerId
3022
+ }, {
3023
+ onStartReplication: async (info, remotePeerId) => {
3024
+ await this._connected.wait();
3025
+ log14("onStartReplication", {
3026
+ id: info.id,
3027
+ thisPeerId: this.peerId,
3028
+ remotePeerId: remotePeerId.toHex()
3029
+ }, {
3030
+ F: __dxlog_file15,
3031
+ L: 70,
3032
+ S: this,
3033
+ C: (f, a) => f(...a)
3034
+ });
3035
+ if (!this._extensions.has(info.id)) {
3036
+ peerInfo = info;
3037
+ this._extensions.set(info.id, extension);
3038
+ log14("peer-candidate", {
3039
+ id: info.id,
3040
+ thisPeerId: this.peerId,
3041
+ remotePeerId: remotePeerId.toHex()
3042
+ }, {
3043
+ F: __dxlog_file15,
3044
+ L: 76,
3045
+ S: this,
3046
+ C: (f, a) => f(...a)
3047
+ });
3048
+ this.emit("peer-candidate", {
3049
+ // TODO(mykola): Hack, stop abusing `peerMetadata` field.
3050
+ peerMetadata: {
3051
+ dxos_deviceKey: remotePeerId.toHex()
3052
+ },
3053
+ peerId: info.id
3054
+ });
3055
+ }
3056
+ },
3057
+ onSyncMessage: async ({ payload }) => {
3058
+ if (!peerInfo) {
3059
+ return;
3060
+ }
3061
+ const message = cbor2.decode(payload);
3062
+ this.emit("message", message);
3063
+ },
3064
+ onClose: async () => {
3065
+ if (!peerInfo) {
3066
+ return;
3067
+ }
3068
+ this.emit("peer-disconnected", {
3069
+ peerId: peerInfo.id
3070
+ });
3071
+ this._extensions.delete(peerInfo.id);
3072
+ }
3073
+ });
3074
+ return extension;
3075
+ }
3076
+ };
3077
+
3078
+ // packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts
3079
+ import { next as automerge, getHeads } from "@dxos/automerge/automerge";
3080
+ import { Repo } from "@dxos/automerge/automerge-repo";
3081
+ import { IndexedDBStorageAdapter } from "@dxos/automerge/automerge-repo-storage-indexeddb";
3082
+ import { Context as Context7 } from "@dxos/context";
3083
+ import { PublicKey as PublicKey8 } from "@dxos/keys";
3084
+ import { log as log15 } from "@dxos/log";
3085
+ import { idCodec } from "@dxos/protocols";
3086
+ import { StorageType } from "@dxos/random-access-storage";
3087
+ import { trace as trace6 } from "@dxos/tracing";
3088
+ import { ComplexMap as ComplexMap7, ComplexSet, defaultMap, mapValues } from "@dxos/util";
3089
+
3090
+ // packages/core/echo/echo-pipeline/src/automerge/automerge-storage–wrapper.ts
3091
+ var AutomergeStorageWrapper = class {
3092
+ constructor({ storage, callbacks }) {
3093
+ this._storage = storage;
3094
+ this._callbacks = callbacks;
3095
+ }
3096
+ async load(key) {
3097
+ return this._storage.load(key);
3098
+ }
3099
+ async save(key, value) {
3100
+ await this._callbacks.beforeSave?.(key);
3101
+ await this._storage.save(key, value);
3102
+ await this._callbacks.afterSave?.(key);
3103
+ }
3104
+ async remove(key) {
3105
+ return this._storage.remove(key);
3106
+ }
3107
+ async loadRange(keyPrefix) {
3108
+ return this._storage.loadRange(keyPrefix);
3109
+ }
3110
+ async removeRange(keyPrefix) {
3111
+ return this._storage.removeRange(keyPrefix);
3112
+ }
3113
+ async close() {
3114
+ if (this._storage instanceof AutomergeStorageAdapter) {
3115
+ return this._storage.close();
3116
+ }
3117
+ }
3118
+ };
3119
+
3120
+ // packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts
3121
+ function _ts_decorate9(decorators, target, key, desc) {
3122
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3123
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
3124
+ r = Reflect.decorate(decorators, target, key, desc);
3125
+ else
3126
+ for (var i = decorators.length - 1; i >= 0; i--)
3127
+ if (d = decorators[i])
3128
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3129
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
3130
+ }
3131
+ var __dxlog_file16 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
3132
+ var AutomergeHost = class {
3133
+ constructor({ directory, metadata }) {
3134
+ this._ctx = new Context7();
3135
+ /**
3136
+ * spaceKey -> deviceKey[]
3137
+ */
3138
+ this._authorizedDevices = new ComplexMap7(PublicKey8.hash);
3139
+ this._updatingMetadata = /* @__PURE__ */ new Map();
3140
+ this._requestedDocs = /* @__PURE__ */ new Set();
3141
+ this._metadata = metadata;
3142
+ this._meshNetwork = new MeshNetworkAdapter();
3143
+ this._clientNetwork = new LocalHostNetworkAdapter();
3144
+ this._storage = new AutomergeStorageWrapper({
3145
+ storage: (
3146
+ // TODO(mykola): Delete specific handling of IDB storage.
3147
+ directory.type === StorageType.IDB ? new IndexedDBStorageAdapter(directory.path, "data") : new AutomergeStorageAdapter(directory)
3148
+ ),
3149
+ callbacks: {
3150
+ beforeSave: (params) => this._beforeSave(params)
3151
+ }
3152
+ });
3153
+ this._peerId = `host-${PublicKey8.random().toHex()}`;
3154
+ this._repo = new Repo({
3155
+ peerId: this._peerId,
3156
+ network: [
3157
+ this._clientNetwork,
3158
+ this._meshNetwork
3159
+ ],
3160
+ storage: this._storage,
3161
+ // TODO(dmaretskyi): Share based on HALO permissions and space affinity.
3162
+ // Hosts, running in the worker, don't share documents unless requested by other peers.
3163
+ sharePolicy: async (peerId, documentId) => {
3164
+ if (peerId.startsWith("client-")) {
3165
+ return false;
3166
+ }
3167
+ if (!documentId) {
3168
+ return false;
3169
+ }
3170
+ const doc = this._repo.handles[documentId]?.docSync();
3171
+ if (!doc) {
3172
+ const isRequested = this._requestedDocs.has(`automerge:${documentId}`);
3173
+ log15("doc share policy check", {
3174
+ peerId,
3175
+ documentId,
3176
+ isRequested
3177
+ }, {
3178
+ F: __dxlog_file16,
3179
+ L: 96,
3180
+ S: this,
3181
+ C: (f, a) => f(...a)
3182
+ });
3183
+ return isRequested;
3184
+ }
3185
+ try {
3186
+ const spaceKey = getSpaceKeyFromDoc(doc);
3187
+ if (!spaceKey) {
3188
+ log15("space key not found for share policy check", {
3189
+ peerId,
3190
+ documentId
3191
+ }, {
3192
+ F: __dxlog_file16,
3193
+ L: 103,
3194
+ S: this,
3195
+ C: (f, a) => f(...a)
3196
+ });
3197
+ return false;
3198
+ }
3199
+ const authorizedDevices = this._authorizedDevices.get(PublicKey8.from(spaceKey));
3200
+ const deviceKeyHex = this.repo.peerMetadataByPeerId[peerId]?.dxos_deviceKey;
3201
+ if (!deviceKeyHex) {
3202
+ log15("device key not found for share policy check", {
3203
+ peerId,
3204
+ documentId
3205
+ }, {
3206
+ F: __dxlog_file16,
3207
+ L: 112,
3208
+ S: this,
3209
+ C: (f, a) => f(...a)
3210
+ });
3211
+ return false;
3212
+ }
3213
+ const deviceKey = PublicKey8.from(deviceKeyHex);
3214
+ const isAuthorized = authorizedDevices?.has(deviceKey) ?? false;
3215
+ log15("share policy check", {
3216
+ localPeer: this._peerId,
3217
+ remotePeer: peerId,
3218
+ documentId,
3219
+ deviceKey,
3220
+ spaceKey,
3221
+ isAuthorized
3222
+ }, {
3223
+ F: __dxlog_file16,
3224
+ L: 118,
3225
+ S: this,
3226
+ C: (f, a) => f(...a)
3227
+ });
3228
+ return isAuthorized;
3229
+ } catch (err) {
3230
+ log15.catch(err, void 0, {
3231
+ F: __dxlog_file16,
3232
+ L: 128,
3233
+ S: this,
3234
+ C: (f, a) => f(...a)
3235
+ });
3236
+ return false;
3237
+ }
3238
+ }
3239
+ });
3240
+ this._clientNetwork.ready();
3241
+ this._meshNetwork.ready();
3242
+ {
3243
+ const listener = ({ handle }) => this._onDocument(handle);
3244
+ this._repo.on("document", listener);
3245
+ this._ctx.onDispose(() => {
3246
+ this._repo.off("document", listener);
3247
+ });
3248
+ }
3249
+ }
3250
+ get repo() {
3251
+ return this._repo;
3252
+ }
3253
+ async _beforeSave(path) {
3254
+ const id = path[0];
3255
+ if (this._updatingMetadata.has(id)) {
3256
+ return this._updatingMetadata.get(id);
3257
+ }
3258
+ }
3259
+ _onDocument(handle) {
3260
+ const listener = (event) => this._onUpdate(event);
3261
+ handle.on("change", listener);
3262
+ this._ctx.onDispose(() => {
3263
+ handle.off("change", listener);
3264
+ });
3265
+ }
3266
+ _onUpdate(event) {
3267
+ if (this._metadata == null) {
3268
+ return;
3269
+ }
3270
+ const objectIds = getInlineChanges(event);
3271
+ if (objectIds.length === 0) {
3272
+ return;
3273
+ }
3274
+ const heads = getHeads(event.doc);
3275
+ const lastAvailableHash = heads.at(-1);
3276
+ if (!lastAvailableHash) {
3277
+ return;
3278
+ }
3279
+ const encodedIds = objectIds.map((objectId) => idCodec.encode({
3280
+ documentId: event.handle.documentId,
3281
+ objectId
3282
+ }));
3283
+ const idToLastHash = new Map(encodedIds.map((id) => [
3284
+ id,
3285
+ lastAvailableHash
3286
+ ]));
3287
+ const markingDirtyPromise = this._metadata.markDirty(idToLastHash).then(() => {
3288
+ this._updatingMetadata.delete(event.handle.documentId);
3289
+ }).catch((err) => {
3290
+ this._ctx.disposed && log15.catch(err, void 0, {
3291
+ F: __dxlog_file16,
3292
+ L: 188,
3293
+ S: this,
3294
+ C: (f, a) => f(...a)
3295
+ });
3296
+ });
3297
+ this._updatingMetadata.set(event.handle.documentId, markingDirtyPromise);
3298
+ }
3299
+ _automergeDocs() {
3300
+ return mapValues(this._repo.handles, (handle) => ({
3301
+ state: handle.state,
3302
+ hasDoc: !!handle.docSync(),
3303
+ heads: handle.docSync() ? automerge.getHeads(handle.docSync()) : null,
3304
+ data: handle.docSync()?.doc && mapValues(handle.docSync()?.doc, (value, key) => {
3305
+ try {
3306
+ switch (key) {
3307
+ case "access":
3308
+ case "links":
3309
+ return value;
3310
+ case "objects":
3311
+ return Object.keys(value);
3312
+ default:
3313
+ return `${value}`;
3314
+ }
3315
+ } catch (err) {
3316
+ return `${err}`;
3317
+ }
3318
+ })
3319
+ }));
3320
+ }
3321
+ _automergePeers() {
3322
+ return this._repo.peers;
3323
+ }
3324
+ async close() {
3325
+ await this._storage.close();
3326
+ await this._clientNetwork.close();
3327
+ await this._ctx.dispose();
3328
+ }
3329
+ //
3330
+ // Methods for client-services.
3331
+ //
3332
+ syncRepo(request) {
3333
+ return this._clientNetwork.syncRepo(request);
3334
+ }
3335
+ sendSyncMessage(request) {
3336
+ return this._clientNetwork.sendSyncMessage(request);
3337
+ }
3338
+ async getHostInfo() {
3339
+ return this._clientNetwork.getHostInfo();
3340
+ }
3341
+ //
3342
+ // Mesh replication.
3343
+ //
3344
+ createExtension() {
3345
+ return this._meshNetwork.createExtension();
3346
+ }
3347
+ authorizeDevice(spaceKey, deviceKey) {
3348
+ log15("authorizeDevice", {
3349
+ spaceKey,
3350
+ deviceKey
3351
+ }, {
3352
+ F: __dxlog_file16,
3353
+ L: 255,
3354
+ S: this,
3355
+ C: (f, a) => f(...a)
3356
+ });
3357
+ defaultMap(this._authorizedDevices, spaceKey, () => new ComplexSet(PublicKey8.hash)).add(deviceKey);
3358
+ }
3359
+ };
3360
+ _ts_decorate9([
3361
+ trace6.info()
3362
+ ], AutomergeHost.prototype, "_peerId", void 0);
3363
+ _ts_decorate9([
3364
+ trace6.info({
3365
+ depth: null
3366
+ })
3367
+ ], AutomergeHost.prototype, "_automergeDocs", null);
3368
+ _ts_decorate9([
3369
+ trace6.info({
3370
+ depth: null
3371
+ })
3372
+ ], AutomergeHost.prototype, "_automergePeers", null);
3373
+ AutomergeHost = _ts_decorate9([
3374
+ trace6.resource()
3375
+ ], AutomergeHost);
3376
+ var getInlineChanges = (event) => {
3377
+ const inlineChangedObjectIds = /* @__PURE__ */ new Set();
3378
+ for (const { path } of event.patches) {
3379
+ if (path.length < 2) {
3380
+ continue;
3381
+ }
3382
+ switch (path[0]) {
3383
+ case "objects":
3384
+ if (path.length >= 2) {
3385
+ inlineChangedObjectIds.add(path[1]);
3386
+ }
3387
+ break;
3388
+ }
3389
+ }
3390
+ return [
3391
+ ...inlineChangedObjectIds
3392
+ ];
3393
+ };
3394
+ var getSpaceKeyFromDoc = (doc) => {
3395
+ const rawSpaceKey = doc.access?.spaceKey ?? doc.experimental_spaceKey;
3396
+ if (rawSpaceKey == null) {
3397
+ return null;
3398
+ }
3399
+ return String(rawSpaceKey);
3400
+ };
3401
+
2772
3402
  export {
2773
3403
  codec,
2774
3404
  valueEncoding,
@@ -2793,6 +3423,11 @@ export {
2793
3423
  SpaceProtocol,
2794
3424
  AuthStatus,
2795
3425
  SpaceProtocolSession,
2796
- SpaceManager
3426
+ SpaceManager,
3427
+ AutomergeStorageAdapter,
3428
+ LocalHostNetworkAdapter,
3429
+ MeshNetworkAdapter,
3430
+ AutomergeHost,
3431
+ getSpaceKeyFromDoc
2797
3432
  };
2798
- //# sourceMappingURL=chunk-WAN2XUWE.mjs.map
3433
+ //# sourceMappingURL=chunk-3PPSCHNN.mjs.map