@dxos/echo-pipeline 0.4.9 → 0.4.10-main.05b9ab6

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 (77) hide show
  1. package/dist/lib/browser/{chunk-RTEEJ723.mjs → chunk-KMWJLYEQ.mjs} +77 -57
  2. package/dist/lib/browser/chunk-KMWJLYEQ.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +617 -217
  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 +10 -2
  7. package/dist/lib/browser/testing/index.mjs.map +4 -4
  8. package/dist/lib/node/{chunk-7VZVCCNF.cjs → chunk-YZA42CKA.cjs} +82 -62
  9. package/dist/lib/node/chunk-YZA42CKA.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +635 -237
  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 +20 -13
  14. package/dist/lib/node/testing/index.cjs.map +4 -4
  15. package/dist/types/src/automerge/automerge-doc-loader.d.ts +66 -0
  16. package/dist/types/src/automerge/automerge-doc-loader.d.ts.map +1 -0
  17. package/dist/types/src/automerge/automerge-doc-loader.test.d.ts +2 -0
  18. package/dist/types/src/automerge/automerge-doc-loader.test.d.ts.map +1 -0
  19. package/dist/types/src/automerge/automerge-host.d.ts +21 -18
  20. package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
  21. package/dist/types/src/automerge/automerge-repo.test.d.ts +2 -0
  22. package/dist/types/src/automerge/automerge-repo.test.d.ts.map +1 -0
  23. package/dist/types/src/automerge/index.d.ts +4 -0
  24. package/dist/types/src/automerge/index.d.ts.map +1 -1
  25. package/dist/types/src/automerge/level.test.d.ts +2 -0
  26. package/dist/types/src/automerge/level.test.d.ts.map +1 -0
  27. package/dist/types/src/automerge/leveldb-storage-adapter.d.ts +30 -0
  28. package/dist/types/src/automerge/leveldb-storage-adapter.d.ts.map +1 -0
  29. package/dist/types/src/automerge/local-host-network-adapter.d.ts +8 -1
  30. package/dist/types/src/automerge/local-host-network-adapter.d.ts.map +1 -1
  31. package/dist/types/src/automerge/migrations.d.ts +7 -0
  32. package/dist/types/src/automerge/migrations.d.ts.map +1 -0
  33. package/dist/types/src/automerge/reference.d.ts +15 -0
  34. package/dist/types/src/automerge/reference.d.ts.map +1 -0
  35. package/dist/types/src/automerge/storage-adapter.test.d.ts +2 -0
  36. package/dist/types/src/automerge/storage-adapter.test.d.ts.map +1 -0
  37. package/dist/types/src/automerge/types.d.ts +73 -0
  38. package/dist/types/src/automerge/types.d.ts.map +1 -0
  39. package/dist/types/src/metadata/metadata-store.d.ts +2 -1
  40. package/dist/types/src/metadata/metadata-store.d.ts.map +1 -1
  41. package/dist/types/src/space/control-pipeline.d.ts +3 -1
  42. package/dist/types/src/space/control-pipeline.d.ts.map +1 -1
  43. package/dist/types/src/space/space-manager.d.ts +3 -1
  44. package/dist/types/src/space/space-manager.d.ts.map +1 -1
  45. package/dist/types/src/space/space.d.ts +6 -9
  46. package/dist/types/src/space/space.d.ts.map +1 -1
  47. package/dist/types/src/testing/index.d.ts +1 -0
  48. package/dist/types/src/testing/index.d.ts.map +1 -1
  49. package/dist/types/src/testing/level.d.ts +3 -0
  50. package/dist/types/src/testing/level.d.ts.map +1 -0
  51. package/dist/types/src/testing/test-agent-builder.d.ts +2 -2
  52. package/dist/types/src/testing/test-agent-builder.d.ts.map +1 -1
  53. package/package.json +33 -30
  54. package/src/automerge/automerge-doc-loader.test.ts +97 -0
  55. package/src/automerge/automerge-doc-loader.ts +244 -0
  56. package/src/automerge/automerge-host.test.ts +22 -8
  57. package/src/automerge/automerge-host.ts +66 -118
  58. package/src/automerge/automerge-repo.test.ts +29 -0
  59. package/src/automerge/index.ts +4 -0
  60. package/src/automerge/level.test.ts +82 -0
  61. package/src/automerge/leveldb-storage-adapter.ts +117 -0
  62. package/src/automerge/local-host-network-adapter.ts +19 -13
  63. package/src/automerge/migrations.ts +41 -0
  64. package/src/automerge/reference.ts +31 -0
  65. package/src/automerge/storage-adapter.test.ts +90 -0
  66. package/src/automerge/types.ts +86 -0
  67. package/src/db-host/data-service.ts +1 -1
  68. package/src/metadata/metadata-store.ts +17 -8
  69. package/src/space/control-pipeline.ts +11 -1
  70. package/src/space/space-manager.ts +4 -0
  71. package/src/space/space.test.ts +7 -7
  72. package/src/space/space.ts +17 -22
  73. package/src/testing/index.ts +1 -0
  74. package/src/testing/level.ts +11 -0
  75. package/src/testing/test-agent-builder.ts +1 -0
  76. package/dist/lib/browser/chunk-RTEEJ723.mjs.map +0 -7
  77. package/dist/lib/node/chunk-7VZVCCNF.cjs.map +0 -7
@@ -18,162 +18,170 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var node_exports = {};
20
20
  __export(node_exports, {
21
- AuthExtension: () => import_chunk_7VZVCCNF.AuthExtension,
22
- AuthStatus: () => import_chunk_7VZVCCNF.AuthStatus,
21
+ AuthExtension: () => import_chunk_YZA42CKA.AuthExtension,
22
+ AuthStatus: () => import_chunk_YZA42CKA.AuthStatus,
23
+ AutomergeDocumentLoaderImpl: () => AutomergeDocumentLoaderImpl,
23
24
  AutomergeHost: () => AutomergeHost,
24
25
  AutomergeStorageAdapter: () => AutomergeStorageAdapter,
25
- DataServiceImpl: () => import_chunk_7VZVCCNF.DataServiceImpl,
26
+ DataServiceImpl: () => import_chunk_YZA42CKA.DataServiceImpl,
27
+ LevelDBStorageAdapter: () => LevelDBStorageAdapter,
26
28
  LocalHostNetworkAdapter: () => LocalHostNetworkAdapter,
27
- MOCK_AUTH_PROVIDER: () => import_chunk_7VZVCCNF.MOCK_AUTH_PROVIDER,
28
- MOCK_AUTH_VERIFIER: () => import_chunk_7VZVCCNF.MOCK_AUTH_VERIFIER,
29
+ MOCK_AUTH_PROVIDER: () => import_chunk_YZA42CKA.MOCK_AUTH_PROVIDER,
30
+ MOCK_AUTH_VERIFIER: () => import_chunk_YZA42CKA.MOCK_AUTH_VERIFIER,
29
31
  MeshNetworkAdapter: () => MeshNetworkAdapter,
30
- MetadataStore: () => import_chunk_7VZVCCNF.MetadataStore,
31
- Pipeline: () => import_chunk_7VZVCCNF.Pipeline,
32
- SnapshotManager: () => import_chunk_7VZVCCNF.SnapshotManager,
33
- SnapshotStore: () => import_chunk_7VZVCCNF.SnapshotStore,
34
- Space: () => import_chunk_7VZVCCNF.Space,
35
- SpaceManager: () => import_chunk_7VZVCCNF.SpaceManager,
36
- SpaceProtocol: () => import_chunk_7VZVCCNF.SpaceProtocol,
37
- SpaceProtocolSession: () => import_chunk_7VZVCCNF.SpaceProtocolSession,
38
- TimeframeClock: () => import_chunk_7VZVCCNF.TimeframeClock,
39
- codec: () => import_chunk_7VZVCCNF.codec,
40
- createMappedFeedWriter: () => import_chunk_7VZVCCNF.createMappedFeedWriter,
32
+ MetadataStore: () => import_chunk_YZA42CKA.MetadataStore,
33
+ Pipeline: () => import_chunk_YZA42CKA.Pipeline,
34
+ REFERENCE_TYPE_TAG: () => REFERENCE_TYPE_TAG,
35
+ SnapshotManager: () => import_chunk_YZA42CKA.SnapshotManager,
36
+ SnapshotStore: () => import_chunk_YZA42CKA.SnapshotStore,
37
+ Space: () => import_chunk_YZA42CKA.Space,
38
+ SpaceManager: () => import_chunk_YZA42CKA.SpaceManager,
39
+ SpaceProtocol: () => import_chunk_YZA42CKA.SpaceProtocol,
40
+ SpaceProtocolSession: () => import_chunk_YZA42CKA.SpaceProtocolSession,
41
+ TimeframeClock: () => import_chunk_YZA42CKA.TimeframeClock,
42
+ codec: () => import_chunk_YZA42CKA.codec,
43
+ createMappedFeedWriter: () => import_chunk_YZA42CKA.createMappedFeedWriter,
44
+ decodeReference: () => decodeReference,
45
+ encodeReference: () => encodeReference,
46
+ encodingOptions: () => encodingOptions,
41
47
  getSpaceKeyFromDoc: () => getSpaceKeyFromDoc,
42
- mapFeedIndexesToTimeframe: () => import_chunk_7VZVCCNF.mapFeedIndexesToTimeframe,
43
- mapTimeframeToFeedIndexes: () => import_chunk_7VZVCCNF.mapTimeframeToFeedIndexes,
44
- startAfter: () => import_chunk_7VZVCCNF.startAfter,
45
- valueEncoding: () => import_chunk_7VZVCCNF.valueEncoding
48
+ hasInvitationExpired: () => import_chunk_YZA42CKA.hasInvitationExpired,
49
+ isEncodedReferenceObject: () => isEncodedReferenceObject,
50
+ mapFeedIndexesToTimeframe: () => import_chunk_YZA42CKA.mapFeedIndexesToTimeframe,
51
+ mapTimeframeToFeedIndexes: () => import_chunk_YZA42CKA.mapTimeframeToFeedIndexes,
52
+ startAfter: () => import_chunk_YZA42CKA.startAfter,
53
+ valueEncoding: () => import_chunk_YZA42CKA.valueEncoding
46
54
  });
47
55
  module.exports = __toCommonJS(node_exports);
48
- var import_chunk_7VZVCCNF = require("./chunk-7VZVCCNF.cjs");
56
+ var import_chunk_YZA42CKA = require("./chunk-YZA42CKA.cjs");
57
+ var import_async = require("@dxos/async");
49
58
  var import_automerge = require("@dxos/automerge/automerge");
50
59
  var import_automerge_repo = require("@dxos/automerge/automerge-repo");
51
- var import_automerge_repo_storage_indexeddb = require("@dxos/automerge/automerge-repo-storage-indexeddb");
52
60
  var import_context = require("@dxos/context");
53
61
  var import_keys = require("@dxos/keys");
54
62
  var import_log = require("@dxos/log");
55
- var import_protocols = require("@dxos/protocols");
56
- var import_random_access_storage = require("@dxos/random-access-storage");
57
63
  var import_tracing = require("@dxos/tracing");
58
64
  var import_util = require("@dxos/util");
59
- var import_util2 = require("@dxos/util");
60
- var import_async = require("@dxos/async");
65
+ var import_context2 = require("@dxos/context");
66
+ var import_async2 = require("@dxos/async");
61
67
  var import_automerge_repo2 = require("@dxos/automerge/automerge-repo");
62
68
  var import_codec_protobuf = require("@dxos/codec-protobuf");
63
69
  var import_invariant = require("@dxos/invariant");
64
- var import_log2 = require("@dxos/log");
65
- var import_async2 = require("@dxos/async");
70
+ var import_async3 = require("@dxos/async");
66
71
  var import_automerge_repo3 = require("@dxos/automerge/automerge-repo");
67
72
  var import_invariant2 = require("@dxos/invariant");
68
- var import_log3 = require("@dxos/log");
73
+ var import_log2 = require("@dxos/log");
69
74
  var import_teleport_extension_automerge_replicator = require("@dxos/teleport-extension-automerge-replicator");
70
- var AutomergeStorageAdapter = class {
71
- constructor(_directory) {
72
- this._directory = _directory;
73
- this._state = "opened";
75
+ var import_automerge_repo_storage_indexeddb = require("@dxos/automerge/automerge-repo-storage-indexeddb");
76
+ var import_log3 = require("@dxos/log");
77
+ var import_random_access_storage = require("@dxos/random-access-storage");
78
+ var import_util2 = require("@dxos/util");
79
+ var import_async4 = require("@dxos/async");
80
+ var import_context3 = require("@dxos/context");
81
+ var import_debug = require("@dxos/debug");
82
+ var import_invariant3 = require("@dxos/invariant");
83
+ var import_log4 = require("@dxos/log");
84
+ var import_tracing2 = require("@dxos/tracing");
85
+ var import_echo_schema = require("@dxos/echo-schema");
86
+ var LevelDBStorageAdapter = class extends import_context2.Resource {
87
+ constructor(_params) {
88
+ super();
89
+ this._params = _params;
74
90
  }
75
- async load(key) {
76
- if (this._state !== "opened") {
77
- return void 0;
78
- }
79
- const filename = this._getFilename(key);
80
- const file = this._directory.getOrCreateFile(filename);
81
- const { size } = await file.stat();
82
- if (!size || size === 0) {
83
- return void 0;
91
+ async load(keyArray) {
92
+ try {
93
+ if (this._lifecycleState !== import_context2.LifecycleState.OPEN) {
94
+ return void 0;
95
+ }
96
+ return await this._params.db.get(keyArray, {
97
+ ...encodingOptions
98
+ });
99
+ } catch (err) {
100
+ if (isLevelDbNotFoundError(err)) {
101
+ return void 0;
102
+ }
103
+ throw err;
84
104
  }
85
- const buffer = await file.read(0, size);
86
- return (0, import_util2.bufferToArray)(buffer);
87
105
  }
88
- async save(key, data) {
89
- if (this._state !== "opened") {
106
+ async save(keyArray, binary) {
107
+ if (this._lifecycleState !== import_context2.LifecycleState.OPEN) {
90
108
  return void 0;
91
109
  }
92
- const filename = this._getFilename(key);
93
- const file = this._directory.getOrCreateFile(filename);
94
- await file.write(0, (0, import_util2.arrayToBuffer)(data));
95
- await file.truncate?.(data.length);
96
- await file.flush?.();
110
+ const batch = this._params.db.batch();
111
+ await this._params.callbacks?.beforeSave?.({
112
+ path: keyArray,
113
+ batch
114
+ });
115
+ batch.put(keyArray, Buffer.from(binary), {
116
+ ...encodingOptions
117
+ });
118
+ await batch.write();
119
+ await this._params.callbacks?.afterSave?.(keyArray);
97
120
  }
98
- async remove(key) {
99
- if (this._state !== "opened") {
121
+ async remove(keyArray) {
122
+ if (this._lifecycleState !== import_context2.LifecycleState.OPEN) {
100
123
  return void 0;
101
124
  }
102
- const filename = this._getFilename(key);
103
- const file = this._directory.getOrCreateFile(filename);
104
- await file.destroy();
125
+ await this._params.db.del(keyArray, {
126
+ ...encodingOptions
127
+ });
105
128
  }
106
129
  async loadRange(keyPrefix) {
107
- if (this._state !== "opened") {
130
+ if (this._lifecycleState !== import_context2.LifecycleState.OPEN) {
108
131
  return [];
109
132
  }
110
- const filename = this._getFilename(keyPrefix);
111
- const entries = await this._directory.list();
112
- return Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
113
- const file = this._directory.getOrCreateFile(entry);
114
- const { size } = await file.stat();
115
- const buffer = await file.read(0, size);
116
- return {
117
- key: this._getKeyFromFilename(entry),
118
- data: (0, import_util2.bufferToArray)(buffer)
119
- };
120
- }));
133
+ const result = [];
134
+ for await (const [key, value] of this._params.db.iterator({
135
+ gte: keyPrefix,
136
+ lte: [
137
+ ...keyPrefix,
138
+ "\uFFFF"
139
+ ],
140
+ ...encodingOptions
141
+ })) {
142
+ result.push({
143
+ key,
144
+ data: value
145
+ });
146
+ }
147
+ return result;
121
148
  }
122
149
  async removeRange(keyPrefix) {
123
- if (this._state !== "opened") {
150
+ if (this._lifecycleState !== import_context2.LifecycleState.OPEN) {
124
151
  return void 0;
125
152
  }
126
- const filename = this._getFilename(keyPrefix);
127
- const entries = await this._directory.list();
128
- await Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
129
- const file = this._directory.getOrCreateFile(entry);
130
- await file.destroy();
131
- }));
132
- }
133
- async close() {
134
- this._state = "closed";
135
- }
136
- _getFilename(key) {
137
- return key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-");
138
- }
139
- _getKeyFromFilename(filename) {
140
- return filename.split("-").map((k) => k.replaceAll("%2D", "-").replaceAll("%25", "%"));
141
- }
142
- };
143
- var AutomergeStorageWrapper = class {
144
- constructor({ storage, callbacks }) {
145
- this._storage = storage;
146
- this._callbacks = callbacks;
147
- }
148
- async load(key) {
149
- return this._storage.load(key);
150
- }
151
- async save(key, value) {
152
- await this._callbacks.beforeSave?.(key);
153
- await this._storage.save(key, value);
154
- await this._callbacks.afterSave?.(key);
155
- }
156
- async remove(key) {
157
- return this._storage.remove(key);
158
- }
159
- async loadRange(keyPrefix) {
160
- return this._storage.loadRange(keyPrefix);
161
- }
162
- async removeRange(keyPrefix) {
163
- return this._storage.removeRange(keyPrefix);
164
- }
165
- async close() {
166
- if (this._storage instanceof AutomergeStorageAdapter) {
167
- return this._storage.close();
153
+ const batch = this._params.db.batch();
154
+ for await (const [key] of this._params.db.iterator({
155
+ gte: keyPrefix,
156
+ lte: [
157
+ ...keyPrefix,
158
+ "\uFFFF"
159
+ ],
160
+ ...encodingOptions
161
+ })) {
162
+ batch.del(key, {
163
+ ...encodingOptions
164
+ });
168
165
  }
166
+ await batch.write();
169
167
  }
170
168
  };
169
+ var keyEncoder = {
170
+ encode: (key) => Buffer.from(key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-")),
171
+ decode: (key) => Buffer.from(key).toString().split("-").map((k) => k.replaceAll("%2D", "-").replaceAll("%25", "%"))
172
+ };
173
+ var encodingOptions = {
174
+ keyEncoding: keyEncoder,
175
+ valueEncoding: "buffer"
176
+ };
177
+ var isLevelDbNotFoundError = (err) => err.code === "LEVEL_NOT_FOUND";
171
178
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/local-host-network-adapter.ts";
172
179
  var LocalHostNetworkAdapter = class extends import_automerge_repo2.NetworkAdapter {
173
180
  constructor() {
174
181
  super(...arguments);
175
182
  this._peers = /* @__PURE__ */ new Map();
176
- this._connected = new import_async.Trigger();
183
+ this._connected = new import_async2.Trigger();
184
+ this._isConnected = false;
177
185
  }
178
186
  /**
179
187
  * Emits `ready` event. That signals to `Repo` that it can start using the adapter.
@@ -183,15 +191,21 @@ var LocalHostNetworkAdapter = class extends import_automerge_repo2.NetworkAdapte
183
191
  network: this
184
192
  });
185
193
  }
194
+ /**
195
+ * Called by `Repo` to connect to the network.
196
+ *
197
+ * @param peerId Our peer Id.
198
+ */
186
199
  connect(peerId) {
187
200
  this.peerId = peerId;
201
+ this._isConnected = true;
188
202
  this._connected.wake();
189
203
  }
190
204
  send(message) {
191
205
  const peer = this._peers.get(message.targetId);
192
206
  (0, import_invariant.invariant)(peer, "Peer not found.", {
193
207
  F: __dxlog_file,
194
- L: 45,
208
+ L: 51,
195
209
  S: this,
196
210
  A: [
197
211
  "peer",
@@ -206,12 +220,17 @@ var LocalHostNetworkAdapter = class extends import_automerge_repo2.NetworkAdapte
206
220
  }
207
221
  disconnect() {
208
222
  }
223
+ async whenConnected() {
224
+ await this._connected.wait({
225
+ timeout: 1e4
226
+ });
227
+ }
209
228
  syncRepo({ id, syncMessage }) {
210
229
  const peerId = this._getPeerId(id);
211
230
  return new import_codec_protobuf.Stream(({ next, close }) => {
212
231
  (0, import_invariant.invariant)(!this._peers.has(peerId), "Peer already connected.", {
213
232
  F: __dxlog_file,
214
- L: 63,
233
+ L: 73,
215
234
  S: this,
216
235
  A: [
217
236
  "!this._peers.has(peerId)",
@@ -233,35 +252,47 @@ var LocalHostNetworkAdapter = class extends import_automerge_repo2.NetworkAdapte
233
252
  });
234
253
  }
235
254
  });
236
- this._connected.wait({
237
- timeout: 1e3
238
- }).then(() => {
239
- this.emit("peer-candidate", {
240
- peerMetadata: {},
241
- peerId
242
- });
243
- }).catch((err) => import_log2.log.catch(err, void 0, {
255
+ (0, import_invariant.invariant)(this._isConnected, void 0, {
244
256
  F: __dxlog_file,
245
- L: 88,
257
+ L: 90,
246
258
  S: this,
247
- C: (f, a) => f(...a)
248
- }));
259
+ A: [
260
+ "this._isConnected",
261
+ ""
262
+ ]
263
+ });
264
+ this.emit("peer-candidate", {
265
+ peerMetadata: {},
266
+ peerId
267
+ });
249
268
  });
250
269
  }
251
270
  async sendSyncMessage({ id, syncMessage }) {
252
- await this._connected.wait({
253
- timeout: 1e3
271
+ (0, import_invariant.invariant)(this._isConnected, void 0, {
272
+ F: __dxlog_file,
273
+ L: 99,
274
+ S: this,
275
+ A: [
276
+ "this._isConnected",
277
+ ""
278
+ ]
254
279
  });
255
280
  const message = import_automerge_repo2.cbor.decode(syncMessage);
256
281
  this.emit("message", message);
257
282
  }
258
283
  async getHostInfo() {
259
- await this._connected.wait({
260
- timeout: 1e3
284
+ (0, import_invariant.invariant)(this._isConnected, void 0, {
285
+ F: __dxlog_file,
286
+ L: 105,
287
+ S: this,
288
+ A: [
289
+ "this._isConnected",
290
+ ""
291
+ ]
261
292
  });
262
293
  (0, import_invariant.invariant)(this.peerId, "Peer id not set.", {
263
294
  F: __dxlog_file,
264
- L: 100,
295
+ L: 106,
265
296
  S: this,
266
297
  A: [
267
298
  "this.peerId",
@@ -281,7 +312,7 @@ var MeshNetworkAdapter = class extends import_automerge_repo3.NetworkAdapter {
281
312
  constructor() {
282
313
  super(...arguments);
283
314
  this._extensions = /* @__PURE__ */ new Map();
284
- this._connected = new import_async2.Trigger();
315
+ this._connected = new import_async3.Trigger();
285
316
  }
286
317
  /**
287
318
  * Emits `ready` event. That signals to `Repo` that it can start using the adapter.
@@ -309,7 +340,7 @@ var MeshNetworkAdapter = class extends import_automerge_repo3.NetworkAdapter {
309
340
  });
310
341
  extension.sendSyncMessage({
311
342
  payload: import_automerge_repo3.cbor.encode(message)
312
- }).catch((err) => import_log3.log.catch(err, void 0, {
343
+ }).catch((err) => import_log2.log.catch(err, void 0, {
313
344
  F: __dxlog_file2,
314
345
  L: 39,
315
346
  S: this,
@@ -334,7 +365,7 @@ var MeshNetworkAdapter = class extends import_automerge_repo3.NetworkAdapter {
334
365
  }, {
335
366
  onStartReplication: async (info, remotePeerId) => {
336
367
  await this._connected.wait();
337
- (0, import_log3.log)("onStartReplication", {
368
+ (0, import_log2.log)("onStartReplication", {
338
369
  id: info.id,
339
370
  thisPeerId: this.peerId,
340
371
  remotePeerId: remotePeerId.toHex()
@@ -347,7 +378,7 @@ var MeshNetworkAdapter = class extends import_automerge_repo3.NetworkAdapter {
347
378
  if (!this._extensions.has(info.id)) {
348
379
  peerInfo = info;
349
380
  this._extensions.set(info.id, extension);
350
- (0, import_log3.log)("peer-candidate", {
381
+ (0, import_log2.log)("peer-candidate", {
351
382
  id: info.id,
352
383
  thisPeerId: this.peerId,
353
384
  remotePeerId: remotePeerId.toHex()
@@ -386,6 +417,108 @@ var MeshNetworkAdapter = class extends import_automerge_repo3.NetworkAdapter {
386
417
  return extension;
387
418
  }
388
419
  };
420
+ var AutomergeStorageAdapter = class {
421
+ constructor(_directory) {
422
+ this._directory = _directory;
423
+ this._state = "opened";
424
+ }
425
+ async load(key) {
426
+ if (this._state !== "opened") {
427
+ return void 0;
428
+ }
429
+ const filename = this._getFilename(key);
430
+ const file = this._directory.getOrCreateFile(filename);
431
+ const { size } = await file.stat();
432
+ if (!size || size === 0) {
433
+ return void 0;
434
+ }
435
+ const buffer = await file.read(0, size);
436
+ return (0, import_util2.bufferToArray)(buffer);
437
+ }
438
+ async save(key, data) {
439
+ if (this._state !== "opened") {
440
+ return void 0;
441
+ }
442
+ const filename = this._getFilename(key);
443
+ const file = this._directory.getOrCreateFile(filename);
444
+ await file.write(0, (0, import_util2.arrayToBuffer)(data));
445
+ await file.truncate?.(data.length);
446
+ await file.flush?.();
447
+ }
448
+ async remove(key) {
449
+ if (this._state !== "opened") {
450
+ return void 0;
451
+ }
452
+ const filename = this._getFilename(key);
453
+ const file = this._directory.getOrCreateFile(filename);
454
+ await file.destroy();
455
+ }
456
+ async loadRange(keyPrefix) {
457
+ if (this._state !== "opened") {
458
+ return [];
459
+ }
460
+ const filename = this._getFilename(keyPrefix);
461
+ const entries = await this._directory.list();
462
+ return Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
463
+ const file = this._directory.getOrCreateFile(entry);
464
+ const { size } = await file.stat();
465
+ const buffer = await file.read(0, size);
466
+ return {
467
+ key: this._getKeyFromFilename(entry),
468
+ data: (0, import_util2.bufferToArray)(buffer)
469
+ };
470
+ }));
471
+ }
472
+ async removeRange(keyPrefix) {
473
+ if (this._state !== "opened") {
474
+ return void 0;
475
+ }
476
+ const filename = this._getFilename(keyPrefix);
477
+ const entries = await this._directory.list();
478
+ await Promise.all(entries.filter((entry) => entry.startsWith(filename)).map(async (entry) => {
479
+ const file = this._directory.getOrCreateFile(entry);
480
+ await file.destroy();
481
+ }));
482
+ }
483
+ async close() {
484
+ this._state = "closed";
485
+ }
486
+ _getFilename(key) {
487
+ return key.map((k) => k.replaceAll("%", "%25").replaceAll("-", "%2D")).join("-");
488
+ }
489
+ _getKeyFromFilename(filename) {
490
+ return filename.split("-").map((k) => k.replaceAll("%2D", "-").replaceAll("%25", "%"));
491
+ }
492
+ };
493
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/migrations.ts";
494
+ var levelMigration = async ({ db, directory }) => {
495
+ const isNewLevel = !await db.iterator({
496
+ ...encodingOptions
497
+ }).next();
498
+ if (!isNewLevel) {
499
+ return;
500
+ }
501
+ const oldStorageAdapter = directory.type === import_random_access_storage.StorageType.IDB ? new import_automerge_repo_storage_indexeddb.IndexedDBStorageAdapter(directory.path, "data") : new AutomergeStorageAdapter(directory);
502
+ const chunks = await oldStorageAdapter.loadRange([]);
503
+ if (chunks.length === 0) {
504
+ return;
505
+ }
506
+ const batch = db.batch();
507
+ import_log3.log.info("found chunks on old storage adapter", {
508
+ chunks: chunks.length
509
+ }, {
510
+ F: __dxlog_file3,
511
+ L: 36,
512
+ S: void 0,
513
+ C: (f, a) => f(...a)
514
+ });
515
+ for (const { key, data } of await oldStorageAdapter.loadRange([])) {
516
+ data && batch.put(key, data, {
517
+ ...encodingOptions
518
+ });
519
+ }
520
+ await batch.write();
521
+ };
389
522
  function _ts_decorate(decorators, target, key, desc) {
390
523
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
391
524
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
@@ -396,26 +529,29 @@ function _ts_decorate(decorators, target, key, desc) {
396
529
  r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
397
530
  return c > 3 && r && Object.defineProperty(target, key, r), r;
398
531
  }
399
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
532
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-host.ts";
400
533
  var AutomergeHost = class {
401
- constructor({ directory, metadata }) {
534
+ constructor({ directory, db, storageCallbacks }) {
402
535
  this._ctx = new import_context.Context();
403
536
  this._authorizedDevices = new import_util.ComplexMap(import_keys.PublicKey.hash);
404
- this._updatingMetadata = /* @__PURE__ */ new Map();
405
537
  this._requestedDocs = /* @__PURE__ */ new Set();
406
- this._metadata = metadata;
407
- this._meshNetwork = new MeshNetworkAdapter();
408
- this._clientNetwork = new LocalHostNetworkAdapter();
409
- this._storage = new AutomergeStorageWrapper({
410
- storage: (
411
- // TODO(mykola): Delete specific handling of IDB storage.
412
- directory.type === import_random_access_storage.StorageType.IDB ? new import_automerge_repo_storage_indexeddb.IndexedDBStorageAdapter(directory.path, "data") : new AutomergeStorageAdapter(directory)
413
- ),
414
- callbacks: {
415
- beforeSave: (params) => this._beforeSave(params)
416
- }
538
+ this._directory = directory;
539
+ this._db = db;
540
+ this._storageCallbacks = storageCallbacks;
541
+ }
542
+ async open() {
543
+ this._directory && await levelMigration({
544
+ db: this._db,
545
+ directory: this._directory
417
546
  });
547
+ this._storage = new LevelDBStorageAdapter({
548
+ db: this._db,
549
+ callbacks: this._storageCallbacks
550
+ });
551
+ await this._storage.open?.();
418
552
  this._peerId = `host-${import_keys.PublicKey.random().toHex()}`;
553
+ this._meshNetwork = new MeshNetworkAdapter();
554
+ this._clientNetwork = new LocalHostNetworkAdapter();
419
555
  this._repo = new import_automerge_repo.Repo({
420
556
  peerId: this._peerId,
421
557
  network: [
@@ -440,8 +576,8 @@ var AutomergeHost = class {
440
576
  documentId,
441
577
  isRequested
442
578
  }, {
443
- F: __dxlog_file3,
444
- L: 96,
579
+ F: __dxlog_file4,
580
+ L: 100,
445
581
  S: this,
446
582
  C: (f, a) => f(...a)
447
583
  });
@@ -454,8 +590,8 @@ var AutomergeHost = class {
454
590
  peerId,
455
591
  documentId
456
592
  }, {
457
- F: __dxlog_file3,
458
- L: 103,
593
+ F: __dxlog_file4,
594
+ L: 107,
459
595
  S: this,
460
596
  C: (f, a) => f(...a)
461
597
  });
@@ -468,8 +604,8 @@ var AutomergeHost = class {
468
604
  peerId,
469
605
  documentId
470
606
  }, {
471
- F: __dxlog_file3,
472
- L: 112,
607
+ F: __dxlog_file4,
608
+ L: 116,
473
609
  S: this,
474
610
  C: (f, a) => f(...a)
475
611
  });
@@ -485,16 +621,16 @@ var AutomergeHost = class {
485
621
  spaceKey,
486
622
  isAuthorized
487
623
  }, {
488
- F: __dxlog_file3,
489
- L: 118,
624
+ F: __dxlog_file4,
625
+ L: 122,
490
626
  S: this,
491
627
  C: (f, a) => f(...a)
492
628
  });
493
629
  return isAuthorized;
494
630
  } catch (err) {
495
631
  import_log.log.catch(err, void 0, {
496
- F: __dxlog_file3,
497
- L: 128,
632
+ F: __dxlog_file4,
633
+ L: 132,
498
634
  S: this,
499
635
  C: (f, a) => f(...a)
500
636
  });
@@ -504,69 +640,22 @@ var AutomergeHost = class {
504
640
  });
505
641
  this._clientNetwork.ready();
506
642
  this._meshNetwork.ready();
507
- {
508
- const listener = ({ handle }) => this._onDocument(handle);
509
- this._repo.on("document", listener);
510
- this._ctx.onDispose(() => {
511
- this._repo.off("document", listener);
512
- });
513
- }
643
+ await this._clientNetwork.whenConnected();
644
+ }
645
+ async close() {
646
+ await this._storage.close?.();
647
+ await this._clientNetwork.close();
648
+ await this._ctx.dispose();
514
649
  }
515
650
  get repo() {
516
651
  return this._repo;
517
652
  }
518
- async _beforeSave(path) {
519
- const id = path[0];
520
- if (this._updatingMetadata.has(id)) {
521
- return this._updatingMetadata.get(id);
522
- }
523
- }
524
- _onDocument(handle) {
525
- const listener = (event) => this._onUpdate(event);
526
- handle.on("change", listener);
527
- this._ctx.onDispose(() => {
528
- handle.off("change", listener);
529
- });
530
- }
531
- _onUpdate(event) {
532
- if (this._metadata == null) {
533
- return;
534
- }
535
- const objectIds = getInlineChanges(event);
536
- if (objectIds.length === 0) {
537
- return;
538
- }
539
- const heads = (0, import_automerge.getHeads)(event.doc);
540
- const lastAvailableHash = heads.join("");
541
- if (!lastAvailableHash) {
542
- return;
543
- }
544
- const encodedIds = objectIds.map((objectId) => import_protocols.idCodec.encode({
545
- documentId: event.handle.documentId,
546
- objectId
547
- }));
548
- const idToLastHash = new Map(encodedIds.map((id) => [
549
- id,
550
- lastAvailableHash
551
- ]));
552
- const markingDirtyPromise = this._metadata.markDirty(idToLastHash).then(() => {
553
- this._updatingMetadata.delete(event.handle.documentId);
554
- }).catch((err) => {
555
- this._ctx.disposed && import_log.log.catch(err, void 0, {
556
- F: __dxlog_file3,
557
- L: 188,
558
- S: this,
559
- C: (f, a) => f(...a)
560
- });
561
- });
562
- this._updatingMetadata.set(event.handle.documentId, markingDirtyPromise);
563
- }
564
653
  _automergeDocs() {
565
654
  return (0, import_util.mapValues)(this._repo.handles, (handle) => ({
566
655
  state: handle.state,
567
656
  hasDoc: !!handle.docSync(),
568
657
  heads: handle.docSync() ? import_automerge.next.getHeads(handle.docSync()) : null,
569
- data: handle.docSync()?.doc && (0, import_util.mapValues)(handle.docSync()?.doc, (value, key) => {
658
+ data: handle.docSync() && (0, import_util.mapValues)(handle.docSync(), (value, key) => {
570
659
  try {
571
660
  switch (key) {
572
661
  case "access":
@@ -586,14 +675,25 @@ var AutomergeHost = class {
586
675
  _automergePeers() {
587
676
  return this._repo.peers;
588
677
  }
589
- async close() {
590
- await this._storage.close();
591
- await this._clientNetwork.close();
592
- await this._ctx.dispose();
593
- }
594
678
  //
595
679
  // Methods for client-services.
596
680
  //
681
+ async flush({ documentIds }) {
682
+ await Promise.all(documentIds?.map((id) => this._repo.find(id).whenReady()) ?? []);
683
+ try {
684
+ await (0, import_async.asyncTimeout)(this._repo.flush(documentIds), 500);
685
+ } catch (err) {
686
+ import_log.log.warn("flush error", {
687
+ documentIds,
688
+ err
689
+ }, {
690
+ F: __dxlog_file4,
691
+ L: 196,
692
+ S: this,
693
+ C: (f, a) => f(...a)
694
+ });
695
+ }
696
+ }
597
697
  syncRepo(request) {
598
698
  return this._clientNetwork.syncRepo(request);
599
699
  }
@@ -614,8 +714,8 @@ var AutomergeHost = class {
614
714
  spaceKey,
615
715
  deviceKey
616
716
  }, {
617
- F: __dxlog_file3,
618
- L: 255,
717
+ F: __dxlog_file4,
718
+ L: 221,
619
719
  S: this,
620
720
  C: (f, a) => f(...a)
621
721
  });
@@ -635,27 +735,14 @@ _ts_decorate([
635
735
  depth: null
636
736
  })
637
737
  ], AutomergeHost.prototype, "_automergePeers", null);
738
+ _ts_decorate([
739
+ import_tracing.trace.span({
740
+ showInBrowserTimeline: true
741
+ })
742
+ ], AutomergeHost.prototype, "flush", null);
638
743
  AutomergeHost = _ts_decorate([
639
744
  import_tracing.trace.resource()
640
745
  ], AutomergeHost);
641
- var getInlineChanges = (event) => {
642
- const inlineChangedObjectIds = /* @__PURE__ */ new Set();
643
- for (const { path } of event.patches) {
644
- if (path.length < 2) {
645
- continue;
646
- }
647
- switch (path[0]) {
648
- case "objects":
649
- if (path.length >= 2) {
650
- inlineChangedObjectIds.add(path[1]);
651
- }
652
- break;
653
- }
654
- }
655
- return [
656
- ...inlineChangedObjectIds
657
- ];
658
- };
659
746
  var getSpaceKeyFromDoc = (doc) => {
660
747
  const rawSpaceKey = doc.access?.spaceKey ?? doc.experimental_spaceKey;
661
748
  if (rawSpaceKey == null) {
@@ -663,19 +750,325 @@ var getSpaceKeyFromDoc = (doc) => {
663
750
  }
664
751
  return String(rawSpaceKey);
665
752
  };
753
+ function _ts_decorate2(decorators, target, key, desc) {
754
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
755
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
756
+ r = Reflect.decorate(decorators, target, key, desc);
757
+ else
758
+ for (var i = decorators.length - 1; i >= 0; i--)
759
+ if (d = decorators[i])
760
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
761
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
762
+ }
763
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/echo/echo-pipeline/src/automerge/automerge-doc-loader.ts";
764
+ var AutomergeDocumentLoaderImpl = class {
765
+ constructor(_spaceKey, _repo) {
766
+ this._spaceKey = _spaceKey;
767
+ this._repo = _repo;
768
+ this._spaceRootDocHandle = null;
769
+ this._objectDocumentHandles = /* @__PURE__ */ new Map();
770
+ this._objectsPendingDocumentLoad = /* @__PURE__ */ new Set();
771
+ this.onObjectDocumentLoaded = new import_async4.Event();
772
+ }
773
+ getAllHandles() {
774
+ return [
775
+ ...new Set(this._objectDocumentHandles.values())
776
+ ];
777
+ }
778
+ async loadSpaceRootDocHandle(ctx, spaceState) {
779
+ if (this._spaceRootDocHandle != null) {
780
+ return;
781
+ }
782
+ if (!spaceState.rootUrl) {
783
+ import_log4.log.error("Database opened with no rootUrl", {
784
+ spaceKey: this._spaceKey
785
+ }, {
786
+ F: __dxlog_file5,
787
+ L: 69,
788
+ S: this,
789
+ C: (f, a) => f(...a)
790
+ });
791
+ this._createContextBoundSpaceRootDocument(ctx);
792
+ } else {
793
+ const existingDocHandle = await this._initDocHandle(ctx, spaceState.rootUrl);
794
+ const doc = existingDocHandle.docSync();
795
+ (0, import_invariant3.invariant)(doc, void 0, {
796
+ F: __dxlog_file5,
797
+ L: 74,
798
+ S: this,
799
+ A: [
800
+ "doc",
801
+ ""
802
+ ]
803
+ });
804
+ if (doc.access == null) {
805
+ this._initDocAccess(existingDocHandle);
806
+ }
807
+ this._spaceRootDocHandle = existingDocHandle;
808
+ }
809
+ }
810
+ loadObjectDocument(objectId) {
811
+ (0, import_invariant3.invariant)(this._spaceRootDocHandle, void 0, {
812
+ F: __dxlog_file5,
813
+ L: 83,
814
+ S: this,
815
+ A: [
816
+ "this._spaceRootDocHandle",
817
+ ""
818
+ ]
819
+ });
820
+ if (this._objectDocumentHandles.has(objectId) || this._objectsPendingDocumentLoad.has(objectId)) {
821
+ return;
822
+ }
823
+ const spaceRootDoc = this._spaceRootDocHandle.docSync();
824
+ (0, import_invariant3.invariant)(spaceRootDoc, void 0, {
825
+ F: __dxlog_file5,
826
+ L: 88,
827
+ S: this,
828
+ A: [
829
+ "spaceRootDoc",
830
+ ""
831
+ ]
832
+ });
833
+ const documentUrl = (spaceRootDoc.links ?? {})[objectId];
834
+ if (documentUrl == null) {
835
+ this._objectsPendingDocumentLoad.add(objectId);
836
+ import_log4.log.info("loading delayed until object links are initialized", {
837
+ objectId
838
+ }, {
839
+ F: __dxlog_file5,
840
+ L: 92,
841
+ S: this,
842
+ C: (f, a) => f(...a)
843
+ });
844
+ return;
845
+ }
846
+ this._loadLinkedObjects({
847
+ [objectId]: documentUrl
848
+ });
849
+ }
850
+ onObjectLinksUpdated(links) {
851
+ if (!links) {
852
+ return;
853
+ }
854
+ const linksAwaitingLoad = Object.entries(links).filter(([objectId]) => this._objectsPendingDocumentLoad.has(objectId));
855
+ this._loadLinkedObjects(Object.fromEntries(linksAwaitingLoad));
856
+ linksAwaitingLoad.forEach(([objectId]) => this._objectsPendingDocumentLoad.delete(objectId));
857
+ }
858
+ getSpaceRootDocHandle() {
859
+ (0, import_invariant3.invariant)(this._spaceRootDocHandle, void 0, {
860
+ F: __dxlog_file5,
861
+ L: 110,
862
+ S: this,
863
+ A: [
864
+ "this._spaceRootDocHandle",
865
+ ""
866
+ ]
867
+ });
868
+ return this._spaceRootDocHandle;
869
+ }
870
+ createDocumentForObject(objectId) {
871
+ (0, import_invariant3.invariant)(this._spaceRootDocHandle, void 0, {
872
+ F: __dxlog_file5,
873
+ L: 115,
874
+ S: this,
875
+ A: [
876
+ "this._spaceRootDocHandle",
877
+ ""
878
+ ]
879
+ });
880
+ const spaceDocHandle = this._repo.create();
881
+ this._initDocAccess(spaceDocHandle);
882
+ this.onObjectBoundToDocument(spaceDocHandle, objectId);
883
+ this._spaceRootDocHandle.change((newDoc) => {
884
+ newDoc.links ??= {};
885
+ newDoc.links[objectId] = spaceDocHandle.url;
886
+ });
887
+ return spaceDocHandle;
888
+ }
889
+ onObjectBoundToDocument(handle, objectId) {
890
+ this._objectDocumentHandles.set(objectId, handle);
891
+ }
892
+ clearHandleReferences() {
893
+ const objectsWithHandles = [
894
+ ...this._objectDocumentHandles.keys()
895
+ ];
896
+ this._objectDocumentHandles.clear();
897
+ this._spaceRootDocHandle = null;
898
+ return objectsWithHandles;
899
+ }
900
+ _loadLinkedObjects(links) {
901
+ if (!links) {
902
+ return;
903
+ }
904
+ for (const [objectId, automergeUrl] of Object.entries(links)) {
905
+ const logMeta = {
906
+ objectId,
907
+ automergeUrl
908
+ };
909
+ const objectDocumentHandle = this._objectDocumentHandles.get(objectId);
910
+ if (objectDocumentHandle != null && objectDocumentHandle.url !== automergeUrl) {
911
+ import_log4.log.warn("object already inlined in a different document, ignoring the link", {
912
+ ...logMeta,
913
+ actualDocumentUrl: objectDocumentHandle.url
914
+ }, {
915
+ F: __dxlog_file5,
916
+ L: 145,
917
+ S: this,
918
+ C: (f, a) => f(...a)
919
+ });
920
+ continue;
921
+ }
922
+ if (objectDocumentHandle?.url === automergeUrl) {
923
+ import_log4.log.warn("object document was already loaded", logMeta, {
924
+ F: __dxlog_file5,
925
+ L: 152,
926
+ S: this,
927
+ C: (f, a) => f(...a)
928
+ });
929
+ continue;
930
+ }
931
+ const handle = this._repo.find(automergeUrl);
932
+ import_log4.log.debug("document loading triggered", logMeta, {
933
+ F: __dxlog_file5,
934
+ L: 156,
935
+ S: this,
936
+ C: (f, a) => f(...a)
937
+ });
938
+ this._objectDocumentHandles.set(objectId, handle);
939
+ void this._createObjectOnDocumentLoad(handle, objectId);
940
+ }
941
+ }
942
+ async _initDocHandle(ctx, url) {
943
+ const docHandle = this._repo.find(url);
944
+ while (true) {
945
+ try {
946
+ await (0, import_debug.warnAfterTimeout)(5e3, "Automerge root doc load timeout (AutomergeDb)", async () => {
947
+ await (0, import_context3.cancelWithContext)(ctx, docHandle.whenReady());
948
+ });
949
+ break;
950
+ } catch (err) {
951
+ if (`${err}`.includes("Timeout")) {
952
+ import_log4.log.info("wraparound", {
953
+ id: docHandle.documentId,
954
+ state: docHandle.state
955
+ }, {
956
+ F: __dxlog_file5,
957
+ L: 172,
958
+ S: this,
959
+ C: (f, a) => f(...a)
960
+ });
961
+ continue;
962
+ }
963
+ throw err;
964
+ }
965
+ }
966
+ if (docHandle.state === "unavailable") {
967
+ throw new Error("Automerge document is unavailable");
968
+ }
969
+ return docHandle;
970
+ }
971
+ _createContextBoundSpaceRootDocument(ctx) {
972
+ const docHandle = this._repo.create();
973
+ this._spaceRootDocHandle = docHandle;
974
+ ctx.onDispose(() => {
975
+ docHandle.delete();
976
+ this._spaceRootDocHandle = null;
977
+ });
978
+ }
979
+ _initDocAccess(handle) {
980
+ handle.change((newDoc) => {
981
+ newDoc.access ??= {
982
+ spaceKey: this._spaceKey.toHex()
983
+ };
984
+ newDoc.access.spaceKey = this._spaceKey.toHex();
985
+ });
986
+ }
987
+ async _createObjectOnDocumentLoad(handle, objectId) {
988
+ try {
989
+ await handle.doc([
990
+ "ready"
991
+ ]);
992
+ const logMeta = {
993
+ objectId,
994
+ docUrl: handle.url
995
+ };
996
+ if (this.onObjectDocumentLoaded.listenerCount() === 0) {
997
+ import_log4.log.info("document loaded after all listeners were removed", logMeta, {
998
+ F: __dxlog_file5,
999
+ L: 208,
1000
+ S: this,
1001
+ C: (f, a) => f(...a)
1002
+ });
1003
+ return;
1004
+ }
1005
+ const objectDocHandle = this._objectDocumentHandles.get(objectId);
1006
+ if (objectDocHandle?.url !== handle.url) {
1007
+ import_log4.log.warn("object was rebound while a document was loading, discarding handle", logMeta, {
1008
+ F: __dxlog_file5,
1009
+ L: 213,
1010
+ S: this,
1011
+ C: (f, a) => f(...a)
1012
+ });
1013
+ return;
1014
+ }
1015
+ this.onObjectDocumentLoaded.emit({
1016
+ handle,
1017
+ objectId
1018
+ });
1019
+ } catch (err) {
1020
+ const shouldRetryLoading = this.onObjectDocumentLoaded.listenerCount() > 0;
1021
+ import_log4.log.warn("failed to load a document", {
1022
+ objectId,
1023
+ automergeUrl: handle.url,
1024
+ retryLoading: shouldRetryLoading,
1025
+ err
1026
+ }, {
1027
+ F: __dxlog_file5,
1028
+ L: 219,
1029
+ S: this,
1030
+ C: (f, a) => f(...a)
1031
+ });
1032
+ if (shouldRetryLoading) {
1033
+ await this._createObjectOnDocumentLoad(handle, objectId);
1034
+ }
1035
+ }
1036
+ }
1037
+ };
1038
+ _ts_decorate2([
1039
+ import_tracing2.trace.span({
1040
+ showInBrowserTimeline: true
1041
+ })
1042
+ ], AutomergeDocumentLoaderImpl.prototype, "loadSpaceRootDocHandle", null);
1043
+ AutomergeDocumentLoaderImpl = _ts_decorate2([
1044
+ import_tracing2.trace.resource()
1045
+ ], AutomergeDocumentLoaderImpl);
1046
+ var REFERENCE_TYPE_TAG = "dxos.echo.model.document.Reference";
1047
+ var encodeReference = (reference) => ({
1048
+ "@type": REFERENCE_TYPE_TAG,
1049
+ // NOTE: Automerge do not support undefined values, so we need to use null instead.
1050
+ itemId: reference.itemId ?? null,
1051
+ protocol: reference.protocol ?? null,
1052
+ host: reference.host ?? null
1053
+ });
1054
+ var decodeReference = (value) => new import_echo_schema.Reference(value.itemId, value.protocol ?? void 0, value.host ?? void 0);
1055
+ var isEncodedReferenceObject = (value) => typeof value === "object" && value !== null && value["@type"] === REFERENCE_TYPE_TAG;
666
1056
  // Annotate the CommonJS export names for ESM import in node:
667
1057
  0 && (module.exports = {
668
1058
  AuthExtension,
669
1059
  AuthStatus,
1060
+ AutomergeDocumentLoaderImpl,
670
1061
  AutomergeHost,
671
1062
  AutomergeStorageAdapter,
672
1063
  DataServiceImpl,
1064
+ LevelDBStorageAdapter,
673
1065
  LocalHostNetworkAdapter,
674
1066
  MOCK_AUTH_PROVIDER,
675
1067
  MOCK_AUTH_VERIFIER,
676
1068
  MeshNetworkAdapter,
677
1069
  MetadataStore,
678
1070
  Pipeline,
1071
+ REFERENCE_TYPE_TAG,
679
1072
  SnapshotManager,
680
1073
  SnapshotStore,
681
1074
  Space,
@@ -685,7 +1078,12 @@ var getSpaceKeyFromDoc = (doc) => {
685
1078
  TimeframeClock,
686
1079
  codec,
687
1080
  createMappedFeedWriter,
1081
+ decodeReference,
1082
+ encodeReference,
1083
+ encodingOptions,
688
1084
  getSpaceKeyFromDoc,
1085
+ hasInvitationExpired,
1086
+ isEncodedReferenceObject,
689
1087
  mapFeedIndexesToTimeframe,
690
1088
  mapTimeframeToFeedIndexes,
691
1089
  startAfter,