@dxos/echo-pipeline 0.1.24-next.6b1f434

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 (134) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +22 -0
  3. package/dist/lib/browser/chunk-3GAE5CKD.mjs +1621 -0
  4. package/dist/lib/browser/chunk-3GAE5CKD.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +114 -0
  6. package/dist/lib/browser/index.mjs.map +7 -0
  7. package/dist/lib/browser/meta.json +1 -0
  8. package/dist/lib/browser/testing/index.mjs +238 -0
  9. package/dist/lib/browser/testing/index.mjs.map +7 -0
  10. package/dist/lib/node/index.cjs +1747 -0
  11. package/dist/lib/node/index.cjs.map +7 -0
  12. package/dist/lib/node/meta.json +1 -0
  13. package/dist/lib/node/testing/index.cjs +1835 -0
  14. package/dist/lib/node/testing/index.cjs.map +7 -0
  15. package/dist/types/src/common/codec.d.ts +12 -0
  16. package/dist/types/src/common/codec.d.ts.map +1 -0
  17. package/dist/types/src/common/feeds.d.ts +7 -0
  18. package/dist/types/src/common/feeds.d.ts.map +1 -0
  19. package/dist/types/src/common/index.d.ts +3 -0
  20. package/dist/types/src/common/index.d.ts.map +1 -0
  21. package/dist/types/src/dbhost/data-service-host.d.ts +22 -0
  22. package/dist/types/src/dbhost/data-service-host.d.ts.map +1 -0
  23. package/dist/types/src/dbhost/data-service.d.ts +21 -0
  24. package/dist/types/src/dbhost/data-service.d.ts.map +1 -0
  25. package/dist/types/src/dbhost/database-backend.d.ts +28 -0
  26. package/dist/types/src/dbhost/database-backend.d.ts.map +1 -0
  27. package/dist/types/src/dbhost/index.d.ts +6 -0
  28. package/dist/types/src/dbhost/index.d.ts.map +1 -0
  29. package/dist/types/src/dbhost/snapshot-manager.d.ts +17 -0
  30. package/dist/types/src/dbhost/snapshot-manager.d.ts.map +1 -0
  31. package/dist/types/src/dbhost/snapshot-store.d.ts +9 -0
  32. package/dist/types/src/dbhost/snapshot-store.d.ts.map +1 -0
  33. package/dist/types/src/dbhost/snapshot-store.test.d.ts +2 -0
  34. package/dist/types/src/dbhost/snapshot-store.test.d.ts.map +1 -0
  35. package/dist/types/src/errors/errors.d.ts +26 -0
  36. package/dist/types/src/errors/errors.d.ts.map +1 -0
  37. package/dist/types/src/errors/index.d.ts +2 -0
  38. package/dist/types/src/errors/index.d.ts.map +1 -0
  39. package/dist/types/src/index.d.ts +7 -0
  40. package/dist/types/src/index.d.ts.map +1 -0
  41. package/dist/types/src/metadata/index.d.ts +2 -0
  42. package/dist/types/src/metadata/index.d.ts.map +1 -0
  43. package/dist/types/src/metadata/metadata-store.d.ts +42 -0
  44. package/dist/types/src/metadata/metadata-store.d.ts.map +1 -0
  45. package/dist/types/src/pipeline/index.d.ts +3 -0
  46. package/dist/types/src/pipeline/index.d.ts.map +1 -0
  47. package/dist/types/src/pipeline/message-selector.d.ts +11 -0
  48. package/dist/types/src/pipeline/message-selector.d.ts.map +1 -0
  49. package/dist/types/src/pipeline/pipeline.d.ts +98 -0
  50. package/dist/types/src/pipeline/pipeline.d.ts.map +1 -0
  51. package/dist/types/src/pipeline/pipeline.test.d.ts +2 -0
  52. package/dist/types/src/pipeline/pipeline.test.d.ts.map +1 -0
  53. package/dist/types/src/pipeline/timeframe-clock.d.ts +19 -0
  54. package/dist/types/src/pipeline/timeframe-clock.d.ts.map +1 -0
  55. package/dist/types/src/space/auth.d.ts +23 -0
  56. package/dist/types/src/space/auth.d.ts.map +1 -0
  57. package/dist/types/src/space/control-pipeline.d.ts +31 -0
  58. package/dist/types/src/space/control-pipeline.d.ts.map +1 -0
  59. package/dist/types/src/space/control-pipeline.test.d.ts +2 -0
  60. package/dist/types/src/space/control-pipeline.test.d.ts.map +1 -0
  61. package/dist/types/src/space/data-pipeline-controller.d.ts +63 -0
  62. package/dist/types/src/space/data-pipeline-controller.d.ts.map +1 -0
  63. package/dist/types/src/space/genesis.d.ts +5 -0
  64. package/dist/types/src/space/genesis.d.ts.map +1 -0
  65. package/dist/types/src/space/index.d.ts +7 -0
  66. package/dist/types/src/space/index.d.ts.map +1 -0
  67. package/dist/types/src/space/replication.browser.test.d.ts +2 -0
  68. package/dist/types/src/space/replication.browser.test.d.ts.map +1 -0
  69. package/dist/types/src/space/space-manager.browser.test.d.ts +2 -0
  70. package/dist/types/src/space/space-manager.browser.test.d.ts.map +1 -0
  71. package/dist/types/src/space/space-manager.d.ts +41 -0
  72. package/dist/types/src/space/space-manager.d.ts.map +1 -0
  73. package/dist/types/src/space/space-protocol.browser.test.d.ts +2 -0
  74. package/dist/types/src/space/space-protocol.browser.test.d.ts.map +1 -0
  75. package/dist/types/src/space/space-protocol.d.ts +76 -0
  76. package/dist/types/src/space/space-protocol.d.ts.map +1 -0
  77. package/dist/types/src/space/space-protocol.test.d.ts +2 -0
  78. package/dist/types/src/space/space-protocol.test.d.ts.map +1 -0
  79. package/dist/types/src/space/space.d.ts +59 -0
  80. package/dist/types/src/space/space.d.ts.map +1 -0
  81. package/dist/types/src/space/space.test.d.ts +2 -0
  82. package/dist/types/src/space/space.test.d.ts.map +1 -0
  83. package/dist/types/src/testing/index.d.ts +4 -0
  84. package/dist/types/src/testing/index.d.ts.map +1 -0
  85. package/dist/types/src/testing/test-agent-builder.d.ts +52 -0
  86. package/dist/types/src/testing/test-agent-builder.d.ts.map +1 -0
  87. package/dist/types/src/testing/test-feed-builder.d.ts +9 -0
  88. package/dist/types/src/testing/test-feed-builder.d.ts.map +1 -0
  89. package/dist/types/src/testing/util.d.ts +14 -0
  90. package/dist/types/src/testing/util.d.ts.map +1 -0
  91. package/dist/types/src/tests/database.test.d.ts +2 -0
  92. package/dist/types/src/tests/database.test.d.ts.map +1 -0
  93. package/package.json +60 -0
  94. package/src/common/codec.ts +18 -0
  95. package/src/common/feeds.ts +23 -0
  96. package/src/common/index.ts +6 -0
  97. package/src/dbhost/data-service-host.ts +103 -0
  98. package/src/dbhost/data-service.ts +66 -0
  99. package/src/dbhost/database-backend.ts +64 -0
  100. package/src/dbhost/index.ts +9 -0
  101. package/src/dbhost/snapshot-manager.ts +68 -0
  102. package/src/dbhost/snapshot-store.test.ts +30 -0
  103. package/src/dbhost/snapshot-store.ts +45 -0
  104. package/src/errors/errors.ts +52 -0
  105. package/src/errors/index.ts +5 -0
  106. package/src/index.ts +10 -0
  107. package/src/metadata/index.ts +5 -0
  108. package/src/metadata/metadata-store.ts +173 -0
  109. package/src/pipeline/index.ts +6 -0
  110. package/src/pipeline/message-selector.ts +38 -0
  111. package/src/pipeline/pipeline.test.ts +71 -0
  112. package/src/pipeline/pipeline.ts +249 -0
  113. package/src/pipeline/timeframe-clock.ts +56 -0
  114. package/src/space/auth.ts +88 -0
  115. package/src/space/control-pipeline.test.ts +162 -0
  116. package/src/space/control-pipeline.ts +103 -0
  117. package/src/space/data-pipeline-controller.ts +234 -0
  118. package/src/space/genesis.ts +29 -0
  119. package/src/space/index.ts +10 -0
  120. package/src/space/replication.browser.test.ts +64 -0
  121. package/src/space/space-manager.browser.test.ts +44 -0
  122. package/src/space/space-manager.ts +92 -0
  123. package/src/space/space-protocol.browser.test.ts +135 -0
  124. package/src/space/space-protocol.test.ts +136 -0
  125. package/src/space/space-protocol.ts +222 -0
  126. package/src/space/space.test.ts +144 -0
  127. package/src/space/space.ts +199 -0
  128. package/src/testing/index.ts +7 -0
  129. package/src/testing/test-agent-builder.ts +193 -0
  130. package/src/testing/test-feed-builder.ts +19 -0
  131. package/src/testing/util.ts +77 -0
  132. package/src/tests/database.test.ts +53 -0
  133. package/testing.d.ts +11 -0
  134. package/testing.js +5 -0
@@ -0,0 +1,1621 @@
1
+ import "@dxos/node-std/globals"
2
+
3
+ // packages/core/echo/echo-pipeline/src/metadata/metadata-store.ts
4
+ import assert from "@dxos/node-std/assert";
5
+ import { synchronized } from "@dxos/async";
6
+ import { log } from "@dxos/log";
7
+ import { schema } from "@dxos/protocols";
8
+ var __decorate = function(decorators, target, key, desc) {
9
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
10
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
11
+ r = Reflect.decorate(decorators, target, key, desc);
12
+ else
13
+ for (var i = decorators.length - 1; i >= 0; i--)
14
+ if (d = decorators[i])
15
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
16
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
17
+ };
18
+ var STORAGE_VERSION = 1;
19
+ var emptyEchoMetadata = () => ({
20
+ version: STORAGE_VERSION,
21
+ spaces: [],
22
+ created: new Date(),
23
+ updated: new Date()
24
+ });
25
+ var MetadataStore = class {
26
+ // prettier-ignore
27
+ constructor(_directory) {
28
+ this._directory = _directory;
29
+ this._metadata = emptyEchoMetadata();
30
+ }
31
+ get version() {
32
+ var _a;
33
+ return (_a = this._metadata.version) != null ? _a : 0;
34
+ }
35
+ /**
36
+ * Returns a list of currently saved spaces. The list and objects in it can be modified addSpace and
37
+ * addSpaceFeed functions.
38
+ */
39
+ get spaces() {
40
+ var _a;
41
+ return (_a = this._metadata.spaces) != null ? _a : [];
42
+ }
43
+ /**
44
+ * Loads metadata from persistent storage.
45
+ */
46
+ async load() {
47
+ const file = this._directory.getOrCreateFile("EchoMetadata");
48
+ try {
49
+ const { size: fileLength } = await file.stat();
50
+ if (fileLength < 4) {
51
+ return;
52
+ }
53
+ const dataSize = fromBytesInt32(await file.read(0, 4));
54
+ log("loaded", {
55
+ size: dataSize
56
+ }, {
57
+ file: "metadata-store.ts",
58
+ line: 68,
59
+ scope: this,
60
+ callSite: (f, a) => f(...a)
61
+ });
62
+ {
63
+ if (fileLength < dataSize + 4) {
64
+ throw new Error("Metadata storage is corrupted");
65
+ }
66
+ }
67
+ const data = await file.read(4, dataSize);
68
+ this._metadata = schema.getCodecForType("dxos.echo.metadata.EchoMetadata").decode(data);
69
+ } catch (err) {
70
+ log.error("failed to load metadata", {
71
+ err
72
+ }, {
73
+ file: "metadata-store.ts",
74
+ line: 80,
75
+ scope: this,
76
+ callSite: (f, a) => f(...a)
77
+ });
78
+ this._metadata = emptyEchoMetadata();
79
+ } finally {
80
+ await file.close();
81
+ }
82
+ }
83
+ async _save() {
84
+ var _a;
85
+ const data = {
86
+ ...this._metadata,
87
+ version: STORAGE_VERSION,
88
+ created: (_a = this._metadata.created) != null ? _a : new Date(),
89
+ updated: new Date()
90
+ };
91
+ const file = this._directory.getOrCreateFile("EchoMetadata");
92
+ try {
93
+ const encoded = Buffer.from(schema.getCodecForType("dxos.echo.metadata.EchoMetadata").encode(data));
94
+ await file.write(0, toBytesInt32(encoded.length));
95
+ log("saved", {
96
+ size: encoded.length
97
+ }, {
98
+ file: "metadata-store.ts",
99
+ line: 103,
100
+ scope: this,
101
+ callSite: (f, a) => f(...a)
102
+ });
103
+ await file.write(4, encoded);
104
+ } finally {
105
+ await file.close();
106
+ }
107
+ }
108
+ /**
109
+ * Clears storage - doesn't work for now.
110
+ */
111
+ async clear() {
112
+ log("clearing all metadata", {}, {
113
+ file: "metadata-store.ts",
114
+ line: 116,
115
+ scope: this,
116
+ callSite: (f, a) => f(...a)
117
+ });
118
+ await this._directory.delete();
119
+ }
120
+ getIdentityRecord() {
121
+ return this._metadata.identity;
122
+ }
123
+ async setIdentityRecord(record) {
124
+ assert(!this._metadata.identity, "Cannot overwrite existing identity in metadata");
125
+ this._metadata.identity = record;
126
+ await this._save();
127
+ }
128
+ async addSpace(record) {
129
+ var _a, _b, _c;
130
+ assert(!((_a = this._metadata.spaces) != null ? _a : []).find((space) => space.key === record.key), "Cannot overwrite existing space in metadata");
131
+ ((_c = (_b = this._metadata).spaces) != null ? _c : _b.spaces = []).push(record);
132
+ await this._save();
133
+ }
134
+ async setSpaceLatestTimeframe(spaceKey, timeframe) {
135
+ const space = this.spaces.find((space2) => space2.key === spaceKey);
136
+ assert(space, "Space not found");
137
+ space.dataTimeframe = timeframe;
138
+ await this._save();
139
+ }
140
+ async setSpaceSnapshot(spaceKey, snapshot) {
141
+ const space = this.spaces.find((space2) => space2.key === spaceKey);
142
+ assert(space, "Space not found");
143
+ space.snapshot = snapshot;
144
+ await this._save();
145
+ }
146
+ async setWritableFeedKeys(spaceKey, controlFeedKey, dataFeedKey) {
147
+ const space = this.spaces.find((space2) => space2.key === spaceKey);
148
+ assert(space, "Space not found");
149
+ space.controlFeedKey = controlFeedKey;
150
+ space.dataFeedKey = dataFeedKey;
151
+ await this._save();
152
+ }
153
+ };
154
+ __decorate([
155
+ synchronized
156
+ ], MetadataStore.prototype, "load", null);
157
+ __decorate([
158
+ synchronized
159
+ ], MetadataStore.prototype, "_save", null);
160
+ var toBytesInt32 = (num) => {
161
+ const buf = Buffer.alloc(4);
162
+ buf.writeInt32LE(num, 0);
163
+ return buf;
164
+ };
165
+ var fromBytesInt32 = (buf) => buf.readInt32LE(0);
166
+
167
+ // packages/core/echo/echo-pipeline/src/common/codec.ts
168
+ import { createCodecEncoding } from "@dxos/hypercore";
169
+ import { schema as schema2 } from "@dxos/protocols";
170
+ var codec = schema2.getCodecForType("dxos.echo.feed.FeedMessage");
171
+ var valueEncoding = createCodecEncoding(codec);
172
+
173
+ // packages/core/echo/echo-pipeline/src/common/feeds.ts
174
+ import assert2 from "@dxos/node-std/assert";
175
+ var createMappedFeedWriter = (mapper, writer) => {
176
+ assert2(mapper);
177
+ assert2(writer);
178
+ return {
179
+ write: async (data) => await writer.write(await mapper(data))
180
+ };
181
+ };
182
+
183
+ // packages/core/echo/echo-pipeline/src/pipeline/timeframe-clock.ts
184
+ import { Event } from "@dxos/async";
185
+ import { timed } from "@dxos/debug";
186
+ import { log as log2 } from "@dxos/log";
187
+ import { Timeframe } from "@dxos/timeframe";
188
+ var __decorate2 = function(decorators, target, key, desc) {
189
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
190
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
191
+ r = Reflect.decorate(decorators, target, key, desc);
192
+ else
193
+ for (var i = decorators.length - 1; i >= 0; i--)
194
+ if (d = decorators[i])
195
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
196
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
197
+ };
198
+ var mapTimeframeToFeedIndexes = (timeframe) => timeframe.frames().map(([feedKey, index]) => ({
199
+ feedKey,
200
+ index
201
+ }));
202
+ var mapFeedIndexesToTimeframe = (indexes) => new Timeframe(indexes.map(({ feedKey, index }) => [
203
+ feedKey,
204
+ index
205
+ ]));
206
+ var TimeframeClock = class {
207
+ // prettier-ignore
208
+ constructor(_timeframe = new Timeframe()) {
209
+ this._timeframe = _timeframe;
210
+ this.update = new Event();
211
+ }
212
+ get timeframe() {
213
+ return this._timeframe;
214
+ }
215
+ updateTimeframe(key, seq) {
216
+ this._timeframe = Timeframe.merge(this._timeframe, new Timeframe([
217
+ [
218
+ key,
219
+ seq
220
+ ]
221
+ ]));
222
+ this.update.emit(this._timeframe);
223
+ }
224
+ hasGaps(timeframe) {
225
+ const gaps = Timeframe.dependencies(timeframe, this._timeframe);
226
+ return !gaps.isEmpty();
227
+ }
228
+ async waitUntilReached(target) {
229
+ log2.debug("waitUntilReached", {
230
+ target,
231
+ current: this._timeframe
232
+ }, {
233
+ file: "timeframe-clock.ts",
234
+ line: 45,
235
+ scope: this,
236
+ callSite: (f, a) => f(...a)
237
+ });
238
+ await this.update.waitForCondition(() => {
239
+ log2("check if reached", {
240
+ target,
241
+ current: this._timeframe,
242
+ deps: Timeframe.dependencies(target, this._timeframe)
243
+ }, {
244
+ file: "timeframe-clock.ts",
245
+ line: 47,
246
+ scope: this,
247
+ callSite: (f, a) => f(...a)
248
+ });
249
+ return Timeframe.dependencies(target, this._timeframe).isEmpty();
250
+ });
251
+ }
252
+ };
253
+ __decorate2([
254
+ timed(5e3)
255
+ ], TimeframeClock.prototype, "waitUntilReached", null);
256
+
257
+ // packages/core/echo/echo-pipeline/src/pipeline/pipeline.ts
258
+ import assert4 from "@dxos/node-std/assert";
259
+ import { sleep, Trigger } from "@dxos/async";
260
+ import { FeedSetIterator } from "@dxos/feed-store";
261
+ import { PublicKey } from "@dxos/keys";
262
+ import { log as log4 } from "@dxos/log";
263
+ import { Timeframe as Timeframe2 } from "@dxos/timeframe";
264
+
265
+ // packages/core/echo/echo-pipeline/src/pipeline/message-selector.ts
266
+ import debug from "debug";
267
+ import assert3 from "@dxos/node-std/assert";
268
+ var log3 = debug("dxos:echo-db:message-selector");
269
+ var createMessageSelector = (timeframeClock) => {
270
+ return (messages) => {
271
+ for (let i = 0; i < messages.length; i++) {
272
+ const { data: { timeframe } } = messages[i];
273
+ assert3(timeframe);
274
+ if (!timeframeClock.hasGaps(timeframe)) {
275
+ return i;
276
+ }
277
+ }
278
+ log3("Skipping...");
279
+ };
280
+ };
281
+
282
+ // packages/core/echo/echo-pipeline/src/pipeline/pipeline.ts
283
+ var PipelineState = class {
284
+ // prettier-ignore
285
+ constructor(_iterator, _timeframeClock) {
286
+ this._iterator = _iterator;
287
+ this._timeframeClock = _timeframeClock;
288
+ this.timeframeUpdate = this._timeframeClock.update;
289
+ }
290
+ /**
291
+ * Latest theoretical timeframe based on the last mutation in each feed.
292
+ * NOTE: This might never be reached if the mutation dependencies
293
+ */
294
+ get endTimeframe() {
295
+ return mapFeedIndexesToTimeframe(this._iterator.feeds.filter((feed) => feed.properties.length > 0).map((feed) => ({
296
+ feedKey: feed.key,
297
+ index: feed.properties.length - 1
298
+ })));
299
+ }
300
+ get timeframe() {
301
+ return this._timeframeClock.timeframe;
302
+ }
303
+ get targetTimeframe() {
304
+ return this._targetTimeframe ? Timeframe2.merge(this.endTimeframe, this._targetTimeframe) : this.endTimeframe;
305
+ }
306
+ async waitUntilTimeframe(target) {
307
+ await this._timeframeClock.waitUntilReached(target);
308
+ }
309
+ setTargetTimeframe(target) {
310
+ this._targetTimeframe = target;
311
+ }
312
+ /**
313
+ * Wait until the pipeline processes all messages in the feed and reaches the target timeframe if that is set.
314
+ *
315
+ * This function will resolve immediately if the pipeline is stalled.
316
+ *
317
+ * @param timeout Timeout in milliseconds to specify the maximum wait time.
318
+ */
319
+ async waitUntilReachedTargetTimeframe({ timeout } = {}) {
320
+ var _a;
321
+ log4("waitUntilReachedTargetTimeframe", {
322
+ timeout,
323
+ current: this.timeframe,
324
+ target: this.targetTimeframe
325
+ }, {
326
+ file: "pipeline.ts",
327
+ line: 82,
328
+ scope: this,
329
+ callSite: (f, a) => f(...a)
330
+ });
331
+ (_a = this._reachedTargetPromise) != null ? _a : this._reachedTargetPromise = Promise.race([
332
+ this._timeframeClock.update.waitForCondition(() => {
333
+ return Timeframe2.dependencies(this.targetTimeframe, this.timeframe).isEmpty();
334
+ }),
335
+ this._iterator.stalled.discardParameter().waitForCount(1)
336
+ ]);
337
+ let done = false;
338
+ if (timeout) {
339
+ return Promise.race([
340
+ this._reachedTargetPromise.then(() => {
341
+ done = true;
342
+ }),
343
+ sleep(timeout).then(() => {
344
+ if (done) {
345
+ return;
346
+ }
347
+ log4.warn("waitUntilReachedTargetTimeframe timed out", {
348
+ timeout,
349
+ current: this.timeframe,
350
+ target: this.targetTimeframe,
351
+ dependencies: Timeframe2.dependencies(this.targetTimeframe, this.timeframe)
352
+ }, {
353
+ file: "pipeline.ts",
354
+ line: 107,
355
+ scope: this,
356
+ callSite: (f, a) => f(...a)
357
+ });
358
+ })
359
+ ]);
360
+ } else {
361
+ return this._reachedTargetPromise;
362
+ }
363
+ }
364
+ };
365
+ var Pipeline = class {
366
+ // prettier-ignore
367
+ constructor(_initialTimeframe = new Timeframe2()) {
368
+ this._initialTimeframe = _initialTimeframe;
369
+ this._timeframeClock = new TimeframeClock(this._initialTimeframe);
370
+ this._feedSetIterator = new FeedSetIterator(createMessageSelector(this._timeframeClock), {
371
+ start: mapTimeframeToFeedIndexes(this._initialTimeframe),
372
+ stallTimeout: 1e3
373
+ });
374
+ this._state = new PipelineState(this._feedSetIterator, this._timeframeClock);
375
+ this._processingTrigger = new Trigger().wake();
376
+ this._isOpen = false;
377
+ this._feedSetIterator.stalled.on((iterator) => {
378
+ log4.warn(`Stalled after ${iterator.options.stallTimeout}ms with ${iterator.size} feeds.`, {}, {
379
+ file: "pipeline.ts",
380
+ line: 183,
381
+ scope: this,
382
+ callSite: (f, a) => f(...a)
383
+ });
384
+ });
385
+ }
386
+ get state() {
387
+ return this._state;
388
+ }
389
+ get writer() {
390
+ assert4(this._writer, "Writer not set.");
391
+ return this._writer;
392
+ }
393
+ getFeeds() {
394
+ return this._feedSetIterator.feeds;
395
+ }
396
+ async addFeed(feed) {
397
+ await this._feedSetIterator.addFeed(feed);
398
+ }
399
+ setWriteFeed(feed) {
400
+ assert4(!this._writer, "Writer already set.");
401
+ assert4(feed.properties.writable, "Feed must be writable.");
402
+ this._writer = createMappedFeedWriter((payload) => ({
403
+ timeframe: this._timeframeClock.timeframe,
404
+ payload
405
+ }), feed.createFeedWriter());
406
+ }
407
+ async start() {
408
+ log4("starting...", {}, {
409
+ file: "pipeline.ts",
410
+ line: 218,
411
+ scope: this,
412
+ callSite: (f, a) => f(...a)
413
+ });
414
+ await this._feedSetIterator.open();
415
+ log4("started", {}, {
416
+ file: "pipeline.ts",
417
+ line: 220,
418
+ scope: this,
419
+ callSite: (f, a) => f(...a)
420
+ });
421
+ }
422
+ async stop() {
423
+ log4("stopping...", {}, {
424
+ file: "pipeline.ts",
425
+ line: 224,
426
+ scope: this,
427
+ callSite: (f, a) => f(...a)
428
+ });
429
+ await this._feedSetIterator.close();
430
+ await this._processingTrigger.wait();
431
+ log4("stopped", {}, {
432
+ file: "pipeline.ts",
433
+ line: 227,
434
+ scope: this,
435
+ callSite: (f, a) => f(...a)
436
+ });
437
+ }
438
+ /**
439
+ * Starts to iterate over the ordered messages from the added feeds.
440
+ * Updates the timeframe clock after the message has bee processed.
441
+ */
442
+ async *consume() {
443
+ assert4(!this._isOpen, "Pipeline is already being consumed.");
444
+ this._isOpen = true;
445
+ for await (const block of this._feedSetIterator) {
446
+ this._processingTrigger.reset();
447
+ yield block;
448
+ this._processingTrigger.wake();
449
+ this._timeframeClock.updateTimeframe(PublicKey.from(block.feedKey), block.seq);
450
+ }
451
+ this._isOpen = false;
452
+ }
453
+ };
454
+
455
+ // packages/core/echo/echo-pipeline/src/space/auth.ts
456
+ import assert5 from "@dxos/node-std/assert";
457
+ import { runInContext, scheduleTask } from "@dxos/async";
458
+ import { Context } from "@dxos/context";
459
+ import { randomBytes } from "@dxos/crypto";
460
+ import { log as log5 } from "@dxos/log";
461
+ import { schema as schema3 } from "@dxos/protocols";
462
+ import { RpcExtension } from "@dxos/teleport";
463
+ var AuthExtension = class extends RpcExtension {
464
+ constructor(_authParams) {
465
+ super({
466
+ requested: {
467
+ AuthService: schema3.getService("dxos.mesh.teleport.auth.AuthService")
468
+ },
469
+ exposed: {
470
+ AuthService: schema3.getService("dxos.mesh.teleport.auth.AuthService")
471
+ },
472
+ timeout: 60 * 1e3
473
+ // Long timeout because auth can wait for sync in certain cases.
474
+ });
475
+ this._authParams = _authParams;
476
+ this._ctx = new Context({
477
+ onError: (err) => {
478
+ log5.catch(err, {}, {
479
+ file: "auth.ts",
480
+ line: 29,
481
+ scope: this,
482
+ callSite: (f, a) => f(...a)
483
+ });
484
+ }
485
+ });
486
+ }
487
+ async getHandlers() {
488
+ return {
489
+ AuthService: {
490
+ authenticate: async ({ challenge }) => {
491
+ try {
492
+ const credential = await this._authParams.provider(challenge);
493
+ if (!credential) {
494
+ throw new Error("auth rejected");
495
+ }
496
+ return {
497
+ credential
498
+ };
499
+ } catch (err) {
500
+ log5.error("failed to generate auth credentials", err, {
501
+ file: "auth.ts",
502
+ line: 56,
503
+ scope: this,
504
+ callSite: (f, a) => f(...a)
505
+ });
506
+ throw new Error("auth rejected");
507
+ }
508
+ }
509
+ }
510
+ };
511
+ }
512
+ async onOpen(context) {
513
+ await super.onOpen(context);
514
+ scheduleTask(this._ctx, async () => {
515
+ try {
516
+ const challenge = randomBytes(32);
517
+ const { credential } = await this.rpc.AuthService.authenticate({
518
+ challenge
519
+ });
520
+ assert5((credential == null ? void 0 : credential.length) > 0, "invalid credential");
521
+ const success = await this._authParams.verifier(challenge, credential);
522
+ assert5(success, "credential not verified");
523
+ runInContext(this._ctx, () => this._authParams.onAuthSuccess());
524
+ } catch (err) {
525
+ log5.warn("auth failed", err, {
526
+ file: "auth.ts",
527
+ line: 75,
528
+ scope: this,
529
+ callSite: (f, a) => f(...a)
530
+ });
531
+ this.close();
532
+ this._authParams.onAuthFailure();
533
+ }
534
+ });
535
+ }
536
+ async onClose() {
537
+ await this._ctx.dispose();
538
+ await super.onClose();
539
+ }
540
+ };
541
+
542
+ // packages/core/echo/echo-pipeline/src/space/space.ts
543
+ import assert6 from "@dxos/node-std/assert";
544
+ import { Event as Event2, synchronized as synchronized2, trackLeaks } from "@dxos/async";
545
+ import { log as log7, logInfo } from "@dxos/log";
546
+ import { AdmittedFeed as AdmittedFeed2 } from "@dxos/protocols/proto/dxos/halo/credentials";
547
+ import { Callback as Callback2 } from "@dxos/util";
548
+
549
+ // packages/core/echo/echo-pipeline/src/space/control-pipeline.ts
550
+ import { SpaceStateMachine } from "@dxos/credentials";
551
+ import { PublicKey as PublicKey2 } from "@dxos/keys";
552
+ import { log as log6 } from "@dxos/log";
553
+ import { AdmittedFeed } from "@dxos/protocols/proto/dxos/halo/credentials";
554
+ import { Callback } from "@dxos/util";
555
+ var ControlPipeline = class {
556
+ constructor({ spaceKey, genesisFeed, feedProvider, initialTimeframe }) {
557
+ this.onFeedAdmitted = new Callback();
558
+ this._pipeline = new Pipeline(initialTimeframe);
559
+ void this._pipeline.addFeed(genesisFeed);
560
+ this._spaceStateMachine = new SpaceStateMachine(spaceKey);
561
+ this._spaceStateMachine.onFeedAdmitted.set(async (info) => {
562
+ log6("feed admitted", {
563
+ key: info.key
564
+ }, {
565
+ file: "control-pipeline.ts",
566
+ line: 41,
567
+ scope: this,
568
+ callSite: (f, a) => f(...a)
569
+ });
570
+ if (info.assertion.designation === AdmittedFeed.Designation.CONTROL && !info.key.equals(genesisFeed.key)) {
571
+ try {
572
+ const feed = await feedProvider(info.key);
573
+ await this._pipeline.addFeed(feed);
574
+ } catch (err) {
575
+ log6.catch(err, {}, {
576
+ file: "control-pipeline.ts",
577
+ line: 49,
578
+ scope: this,
579
+ callSite: (f, a) => f(...a)
580
+ });
581
+ }
582
+ }
583
+ await this.onFeedAdmitted.callIfSet(info);
584
+ });
585
+ this.onMemberAdmitted = this._spaceStateMachine.onMemberAdmitted;
586
+ this.onCredentialProcessed = this._spaceStateMachine.onCredentialProcessed;
587
+ }
588
+ get spaceState() {
589
+ return this._spaceStateMachine;
590
+ }
591
+ get pipeline() {
592
+ return this._pipeline;
593
+ }
594
+ setWriteFeed(feed) {
595
+ this._pipeline.setWriteFeed(feed);
596
+ }
597
+ async start() {
598
+ log6("starting...", {}, {
599
+ file: "control-pipeline.ts",
600
+ line: 73,
601
+ scope: this,
602
+ callSite: (f, a) => f(...a)
603
+ });
604
+ setTimeout(async () => {
605
+ for await (const msg of this._pipeline.consume()) {
606
+ try {
607
+ log6("processing", {
608
+ key: msg.feedKey,
609
+ seq: msg.seq
610
+ }, {
611
+ file: "control-pipeline.ts",
612
+ line: 78,
613
+ scope: this,
614
+ callSite: (f, a) => f(...a)
615
+ });
616
+ if (msg.data.payload.credential) {
617
+ const result = await this._spaceStateMachine.process(msg.data.payload.credential.credential, PublicKey2.from(msg.feedKey));
618
+ if (!result) {
619
+ log6.warn("processing failed", {
620
+ msg
621
+ }, {
622
+ file: "control-pipeline.ts",
623
+ line: 85,
624
+ scope: this,
625
+ callSite: (f, a) => f(...a)
626
+ });
627
+ }
628
+ }
629
+ } catch (err) {
630
+ log6.catch(err, {}, {
631
+ file: "control-pipeline.ts",
632
+ line: 89,
633
+ scope: this,
634
+ callSite: (f, a) => f(...a)
635
+ });
636
+ }
637
+ }
638
+ });
639
+ await this._pipeline.start();
640
+ log6("started", {}, {
641
+ file: "control-pipeline.ts",
642
+ line: 95,
643
+ scope: this,
644
+ callSite: (f, a) => f(...a)
645
+ });
646
+ }
647
+ async stop() {
648
+ log6("stopping...", {}, {
649
+ file: "control-pipeline.ts",
650
+ line: 99,
651
+ scope: this,
652
+ callSite: (f, a) => f(...a)
653
+ });
654
+ await this._pipeline.stop();
655
+ log6("stopped", {}, {
656
+ file: "control-pipeline.ts",
657
+ line: 101,
658
+ scope: this,
659
+ callSite: (f, a) => f(...a)
660
+ });
661
+ }
662
+ };
663
+
664
+ // packages/core/echo/echo-pipeline/src/space/space.ts
665
+ var __decorate3 = function(decorators, target, key, desc) {
666
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
667
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
668
+ r = Reflect.decorate(decorators, target, key, desc);
669
+ else
670
+ for (var i = decorators.length - 1; i >= 0; i--)
671
+ if (d = decorators[i])
672
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
673
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
674
+ };
675
+ var Space = class Space2 {
676
+ constructor({ spaceKey, protocol, genesisFeed, feedProvider }) {
677
+ this.onCredentialProcessed = new Callback2();
678
+ this.stateUpdate = new Event2();
679
+ this._isOpen = false;
680
+ assert6(spaceKey && feedProvider);
681
+ this._key = spaceKey;
682
+ this._genesisFeedKey = genesisFeed.key;
683
+ this._feedProvider = feedProvider;
684
+ this._controlPipeline = new ControlPipeline({
685
+ spaceKey,
686
+ genesisFeed,
687
+ feedProvider
688
+ });
689
+ this._controlPipeline.onFeedAdmitted.set(async (info) => {
690
+ if (info.assertion.designation === AdmittedFeed2.Designation.DATA) {
691
+ if (this._dataPipeline) {
692
+ await this._dataPipeline.addFeed(await feedProvider(info.key));
693
+ }
694
+ }
695
+ if (!info.key.equals(genesisFeed.key)) {
696
+ this.protocol.addFeed(await feedProvider(info.key));
697
+ }
698
+ });
699
+ this._controlPipeline.onCredentialProcessed.set(async (credential) => {
700
+ await this.onCredentialProcessed.callIfSet(credential);
701
+ log7("onCredentialProcessed", {
702
+ credential
703
+ }, {
704
+ file: "space.ts",
705
+ line: 74,
706
+ scope: this,
707
+ callSite: (f, a) => f(...a)
708
+ });
709
+ this.stateUpdate.emit();
710
+ });
711
+ this.protocol = protocol;
712
+ this.protocol.addFeed(genesisFeed);
713
+ }
714
+ get key() {
715
+ return this._key;
716
+ }
717
+ get isOpen() {
718
+ return this._isOpen;
719
+ }
720
+ get genesisFeedKey() {
721
+ return this._genesisFeedKey;
722
+ }
723
+ get controlFeedKey() {
724
+ var _a;
725
+ return (_a = this._controlFeed) == null ? void 0 : _a.key;
726
+ }
727
+ get dataFeedKey() {
728
+ var _a;
729
+ return (_a = this._dataFeed) == null ? void 0 : _a.key;
730
+ }
731
+ get spaceState() {
732
+ return this._controlPipeline.spaceState;
733
+ }
734
+ /**
735
+ * @test-only
736
+ */
737
+ get controlPipeline() {
738
+ return this._controlPipeline.pipeline;
739
+ }
740
+ setControlFeed(feed) {
741
+ assert6(!this._controlFeed, "Control feed already set.");
742
+ this._controlFeed = feed;
743
+ this._controlPipeline.setWriteFeed(feed);
744
+ return this;
745
+ }
746
+ setDataFeed(feed) {
747
+ var _a;
748
+ assert6(!this._dataFeed, "Data feed already set.");
749
+ this._dataFeed = feed;
750
+ (_a = this._dataPipeline) == null ? void 0 : _a.setWriteFeed(feed);
751
+ return this;
752
+ }
753
+ /**
754
+ * Use for diagnostics.
755
+ */
756
+ getControlFeeds() {
757
+ return Array.from(this._controlPipeline.spaceState.feeds.values());
758
+ }
759
+ /**
760
+ * Use for diagnostics.
761
+ */
762
+ // getDataFeeds(): FeedInfo[] {
763
+ // return this._dataPipeline?.getFeeds();
764
+ // }
765
+ async open() {
766
+ log7("opening...", {}, {
767
+ file: "space.ts",
768
+ line: 145,
769
+ scope: this,
770
+ callSite: (f, a) => f(...a)
771
+ });
772
+ if (this._isOpen) {
773
+ return;
774
+ }
775
+ await this._controlPipeline.start();
776
+ await this.protocol.start();
777
+ this._isOpen = true;
778
+ log7("opened", {}, {
779
+ file: "space.ts",
780
+ line: 155,
781
+ scope: this,
782
+ callSite: (f, a) => f(...a)
783
+ });
784
+ }
785
+ async close() {
786
+ var _a;
787
+ log7("closing...", {
788
+ key: this._key
789
+ }, {
790
+ file: "space.ts",
791
+ line: 160,
792
+ scope: this,
793
+ callSite: (f, a) => f(...a)
794
+ });
795
+ if (!this._isOpen) {
796
+ return;
797
+ }
798
+ await this.protocol.stop();
799
+ await ((_a = this._dataPipelineController) == null ? void 0 : _a.close());
800
+ await this._controlPipeline.stop();
801
+ this._isOpen = false;
802
+ log7("closed", {}, {
803
+ file: "space.ts",
804
+ line: 171,
805
+ scope: this,
806
+ callSite: (f, a) => f(...a)
807
+ });
808
+ }
809
+ async initDataPipeline(controller) {
810
+ assert6(this._isOpen, "Space must be open to initialize data pipeline.");
811
+ assert6(!this._dataPipelineController, "Data pipeline already initialized.");
812
+ assert6(!this._dataPipeline, "Data pipeline already initialized.");
813
+ this._dataPipelineController = controller;
814
+ await this._dataPipelineController.open({
815
+ openPipeline: async (start) => {
816
+ assert6(!this._dataPipeline, "Data pipeline already initialized.");
817
+ this._dataPipeline = new Pipeline(start);
818
+ if (this._dataFeed) {
819
+ this._dataPipeline.setWriteFeed(this._dataFeed);
820
+ }
821
+ for (const feed of this._controlPipeline.spaceState.feeds.values()) {
822
+ if (feed.assertion.designation === AdmittedFeed2.Designation.DATA) {
823
+ await this._dataPipeline.addFeed(await this._feedProvider(feed.key));
824
+ }
825
+ }
826
+ await this._dataPipeline.start();
827
+ return this._dataPipeline;
828
+ }
829
+ });
830
+ }
831
+ };
832
+ __decorate3([
833
+ logInfo
834
+ ], Space.prototype, "key", null);
835
+ __decorate3([
836
+ synchronized2
837
+ ], Space.prototype, "open", null);
838
+ __decorate3([
839
+ synchronized2
840
+ ], Space.prototype, "close", null);
841
+ Space = __decorate3([
842
+ trackLeaks("open", "close")
843
+ ], Space);
844
+
845
+ // packages/core/echo/echo-pipeline/src/space/space-protocol.ts
846
+ import { discoveryKey, sha256 } from "@dxos/crypto";
847
+ import { PublicKey as PublicKey3 } from "@dxos/keys";
848
+ import { log as log8, logInfo as logInfo2 } from "@dxos/log";
849
+ import { MMSTTopology } from "@dxos/network-manager";
850
+ import { Teleport } from "@dxos/teleport";
851
+ import { ReplicatorExtension } from "@dxos/teleport-extension-replicator";
852
+ import { ComplexMap } from "@dxos/util";
853
+ var __decorate4 = function(decorators, target, key, desc) {
854
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
855
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
856
+ r = Reflect.decorate(decorators, target, key, desc);
857
+ else
858
+ for (var i = decorators.length - 1; i >= 0; i--)
859
+ if (d = decorators[i])
860
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
861
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
862
+ };
863
+ var MOCK_AUTH_PROVIDER = async (nonce) => Buffer.from("mock");
864
+ var MOCK_AUTH_VERIFIER = async (nonce, credential) => true;
865
+ var SpaceProtocol = class {
866
+ constructor({ topic, swarmIdentity, networkManager, onSessionAuth }) {
867
+ this._feeds = /* @__PURE__ */ new Set();
868
+ this._sessions = new ComplexMap(PublicKey3.hash);
869
+ this._networkManager = networkManager;
870
+ this._swarmIdentity = swarmIdentity;
871
+ this._onSessionAuth = onSessionAuth;
872
+ this._topic = PublicKey3.from(discoveryKey(sha256(topic.toHex())));
873
+ }
874
+ get sessions() {
875
+ return this._sessions;
876
+ }
877
+ get feeds() {
878
+ return this._feeds;
879
+ }
880
+ get _ownPeerKey() {
881
+ return this._swarmIdentity.peerKey;
882
+ }
883
+ // TODO(burdon): Create abstraction for Space (e.g., add keys and have provider).
884
+ addFeed(feed) {
885
+ log8("addFeed", {
886
+ key: feed.key
887
+ }, {
888
+ file: "space-protocol.ts",
889
+ line: 84,
890
+ scope: this,
891
+ callSite: (f, a) => f(...a)
892
+ });
893
+ this._feeds.add(feed);
894
+ for (const session of this._sessions.values()) {
895
+ session.replicator.addFeed(feed);
896
+ }
897
+ }
898
+ async start() {
899
+ if (this._connection) {
900
+ return;
901
+ }
902
+ const credentials = await this._swarmIdentity.credentialProvider(Buffer.from(""));
903
+ const topologyConfig = {
904
+ originateConnections: 4,
905
+ maxPeers: 10,
906
+ sampleSize: 20
907
+ };
908
+ log8("starting...", {}, {
909
+ file: "space-protocol.ts",
910
+ line: 107,
911
+ scope: this,
912
+ callSite: (f, a) => f(...a)
913
+ });
914
+ this._connection = await this._networkManager.joinSwarm({
915
+ protocolProvider: this._createProtocolProvider(credentials),
916
+ peerId: this._swarmIdentity.peerKey,
917
+ topic: this._topic,
918
+ topology: new MMSTTopology(topologyConfig),
919
+ label: `Protocol swarm: ${this._topic}`
920
+ });
921
+ log8("started", {}, {
922
+ file: "space-protocol.ts",
923
+ line: 116,
924
+ scope: this,
925
+ callSite: (f, a) => f(...a)
926
+ });
927
+ }
928
+ async stop() {
929
+ if (this._connection) {
930
+ log8("stopping...", {}, {
931
+ file: "space-protocol.ts",
932
+ line: 121,
933
+ scope: this,
934
+ callSite: (f, a) => f(...a)
935
+ });
936
+ await this._connection.close();
937
+ log8("stopped", {}, {
938
+ file: "space-protocol.ts",
939
+ line: 123,
940
+ scope: this,
941
+ callSite: (f, a) => f(...a)
942
+ });
943
+ }
944
+ }
945
+ _createProtocolProvider(credentials) {
946
+ return (wireParams) => {
947
+ const session = new SpaceProtocolSession({
948
+ wireParams,
949
+ swarmIdentity: this._swarmIdentity,
950
+ onSessionAuth: this._onSessionAuth
951
+ });
952
+ this._sessions.set(wireParams.remotePeerId, session);
953
+ for (const feed of this._feeds) {
954
+ session.replicator.addFeed(feed);
955
+ }
956
+ return session;
957
+ };
958
+ }
959
+ };
960
+ __decorate4([
961
+ logInfo2
962
+ ], SpaceProtocol.prototype, "_topic", void 0);
963
+ __decorate4([
964
+ logInfo2
965
+ ], SpaceProtocol.prototype, "_ownPeerKey", null);
966
+ var AuthStatus;
967
+ (function(AuthStatus2) {
968
+ AuthStatus2["INITIAL"] = "INITIAL";
969
+ AuthStatus2["SUCCESS"] = "SUCCESS";
970
+ AuthStatus2["FAILURE"] = "FAILURE";
971
+ })(AuthStatus || (AuthStatus = {}));
972
+ var SpaceProtocolSession = class {
973
+ // TODO(dmaretskyi): Allow to pass in extra extensions.
974
+ constructor({ wireParams, swarmIdentity, onSessionAuth }) {
975
+ // TODO(dmaretskyi): Start with upload=false when switching it on the fly works.
976
+ this.replicator = new ReplicatorExtension().setOptions({
977
+ upload: true
978
+ });
979
+ this._authStatus = AuthStatus.INITIAL;
980
+ this._wireParams = wireParams;
981
+ this._swarmIdentity = swarmIdentity;
982
+ this._onSessionAuth = onSessionAuth;
983
+ this._teleport = new Teleport(wireParams);
984
+ }
985
+ get authStatus() {
986
+ return this._authStatus;
987
+ }
988
+ get stream() {
989
+ return this._teleport.stream;
990
+ }
991
+ async initialize() {
992
+ await this._teleport.open();
993
+ this._teleport.addExtension("dxos.mesh.teleport.auth", new AuthExtension({
994
+ provider: this._swarmIdentity.credentialProvider,
995
+ verifier: this._swarmIdentity.credentialAuthenticator,
996
+ onAuthSuccess: () => {
997
+ var _a;
998
+ this._authStatus = AuthStatus.SUCCESS;
999
+ log8("Peer authenticated", {}, {
1000
+ file: "space-protocol.ts",
1001
+ line: 206,
1002
+ scope: this,
1003
+ callSite: (f, a) => f(...a)
1004
+ });
1005
+ (_a = this._onSessionAuth) == null ? void 0 : _a.call(this, this._teleport);
1006
+ },
1007
+ onAuthFailure: () => {
1008
+ log8.warn("Auth failed", {}, {
1009
+ file: "space-protocol.ts",
1010
+ line: 211,
1011
+ scope: this,
1012
+ callSite: (f, a) => f(...a)
1013
+ });
1014
+ this._authStatus = AuthStatus.FAILURE;
1015
+ }
1016
+ }));
1017
+ this._teleport.addExtension("dxos.mesh.teleport.replicator", this.replicator);
1018
+ }
1019
+ async destroy() {
1020
+ await this._teleport.close();
1021
+ }
1022
+ };
1023
+ __decorate4([
1024
+ logInfo2
1025
+ ], SpaceProtocolSession.prototype, "_wireParams", void 0);
1026
+ __decorate4([
1027
+ logInfo2
1028
+ ], SpaceProtocolSession.prototype, "authStatus", null);
1029
+
1030
+ // packages/core/echo/echo-pipeline/src/space/space-manager.ts
1031
+ import { synchronized as synchronized3, trackLeaks as trackLeaks2 } from "@dxos/async";
1032
+ import { failUndefined } from "@dxos/debug";
1033
+ import { PublicKey as PublicKey4 } from "@dxos/keys";
1034
+ import { log as log9 } from "@dxos/log";
1035
+ import { ComplexMap as ComplexMap2 } from "@dxos/util";
1036
+ var __decorate5 = function(decorators, target, key, desc) {
1037
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1038
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
1039
+ r = Reflect.decorate(decorators, target, key, desc);
1040
+ else
1041
+ for (var i = decorators.length - 1; i >= 0; i--)
1042
+ if (d = decorators[i])
1043
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1044
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1045
+ };
1046
+ var SpaceManager = class SpaceManager2 {
1047
+ constructor({ feedStore, networkManager }) {
1048
+ this._spaces = new ComplexMap2(PublicKey4.hash);
1049
+ this._feedStore = feedStore;
1050
+ this._networkManager = networkManager;
1051
+ }
1052
+ // TODO(burdon): Remove.
1053
+ get spaces() {
1054
+ return this._spaces;
1055
+ }
1056
+ async open() {
1057
+ }
1058
+ async close() {
1059
+ await Promise.all([
1060
+ ...this._spaces.values()
1061
+ ].map((space) => space.close()));
1062
+ }
1063
+ async constructSpace({ metadata, swarmIdentity, onNetworkConnection }) {
1064
+ var _a;
1065
+ log9("constructing space...", {
1066
+ spaceKey: metadata.genesisFeedKey
1067
+ }, {
1068
+ file: "space-manager.ts",
1069
+ line: 70,
1070
+ scope: this,
1071
+ callSite: (f, a) => f(...a)
1072
+ });
1073
+ const genesisFeed = await this._feedStore.openFeed((_a = metadata.genesisFeedKey) != null ? _a : failUndefined());
1074
+ const spaceKey = metadata.key;
1075
+ const protocol = new SpaceProtocol({
1076
+ topic: spaceKey,
1077
+ swarmIdentity,
1078
+ networkManager: this._networkManager,
1079
+ onSessionAuth: onNetworkConnection
1080
+ });
1081
+ const space = new Space({
1082
+ spaceKey,
1083
+ protocol,
1084
+ genesisFeed,
1085
+ feedProvider: (feedKey) => this._feedStore.openFeed(feedKey)
1086
+ });
1087
+ this._spaces.set(space.key, space);
1088
+ return space;
1089
+ }
1090
+ };
1091
+ __decorate5([
1092
+ synchronized3
1093
+ ], SpaceManager.prototype, "open", null);
1094
+ __decorate5([
1095
+ synchronized3
1096
+ ], SpaceManager.prototype, "close", null);
1097
+ SpaceManager = __decorate5([
1098
+ trackLeaks2("open", "close")
1099
+ ], SpaceManager);
1100
+
1101
+ // packages/core/echo/echo-pipeline/src/space/genesis.ts
1102
+ import { CredentialGenerator } from "@dxos/credentials";
1103
+ import { failUndefined as failUndefined2 } from "@dxos/debug";
1104
+ import { AdmittedFeed as AdmittedFeed3 } from "@dxos/protocols/proto/dxos/halo/credentials";
1105
+ var spaceGenesis = async (keyring, signingContext, space) => {
1106
+ var _a, _b;
1107
+ const generator = new CredentialGenerator(keyring, signingContext.identityKey, signingContext.deviceKey);
1108
+ const credentials = [
1109
+ ...await generator.createSpaceGenesis(space.key, (_a = space.controlFeedKey) != null ? _a : failUndefined2(), signingContext.profile),
1110
+ await generator.createFeedAdmission(space.key, (_b = space.dataFeedKey) != null ? _b : failUndefined2(), AdmittedFeed3.Designation.DATA)
1111
+ ];
1112
+ for (const credential of credentials) {
1113
+ await space.controlPipeline.writer.write({
1114
+ credential: {
1115
+ credential
1116
+ }
1117
+ });
1118
+ }
1119
+ return credentials;
1120
+ };
1121
+
1122
+ // packages/core/echo/echo-pipeline/src/dbhost/data-service-host.ts
1123
+ import assert7 from "@dxos/node-std/assert";
1124
+ import { Stream } from "@dxos/codec-protobuf";
1125
+ import { tagMutationsInBatch } from "@dxos/echo-db";
1126
+ import { log as log10 } from "@dxos/log";
1127
+ import { ComplexMap as ComplexMap3 } from "@dxos/util";
1128
+ var DataServiceHost = class {
1129
+ constructor(_itemManager, _itemDemuxer, _writeStream) {
1130
+ this._itemManager = _itemManager;
1131
+ this._itemDemuxer = _itemDemuxer;
1132
+ this._writeStream = _writeStream;
1133
+ this._clientTagMap = new ComplexMap3(([feedKey, seq]) => `${feedKey.toHex()}:${seq}`);
1134
+ }
1135
+ /**
1136
+ * Real-time subscription to data objects in a space.
1137
+ */
1138
+ subscribe() {
1139
+ return new Stream(({ next, ctx }) => {
1140
+ const objects = Array.from(this._itemManager.entities.values()).map((entity) => entity.createSnapshot());
1141
+ next({
1142
+ batch: {
1143
+ objects
1144
+ }
1145
+ });
1146
+ this._itemDemuxer.mutation.on(ctx, (mutation) => {
1147
+ var _a;
1148
+ log10("Object update", {
1149
+ mutation
1150
+ }, {
1151
+ file: "data-service-host.ts",
1152
+ line: 49,
1153
+ scope: this,
1154
+ callSite: (f, a) => f(...a)
1155
+ });
1156
+ const clientTag = this._clientTagMap.get([
1157
+ mutation.meta.feedKey,
1158
+ mutation.meta.seq
1159
+ ]);
1160
+ const batch = {
1161
+ objects: [
1162
+ {
1163
+ ...mutation.data,
1164
+ mutations: (_a = mutation.data.mutations) == null ? void 0 : _a.map((m, mutationIdx) => ({
1165
+ ...m,
1166
+ meta: mutation.meta
1167
+ })),
1168
+ meta: mutation.meta
1169
+ }
1170
+ ]
1171
+ };
1172
+ if (clientTag) {
1173
+ tagMutationsInBatch(batch, clientTag);
1174
+ }
1175
+ next({
1176
+ clientTag,
1177
+ feedKey: mutation.meta.feedKey,
1178
+ seq: mutation.meta.seq,
1179
+ batch
1180
+ });
1181
+ });
1182
+ });
1183
+ }
1184
+ async write(request) {
1185
+ var _a, _b;
1186
+ assert7(this._writeStream, "Cannot write mutations in readonly mode");
1187
+ assert7(((_a = request.batch.objects) == null ? void 0 : _a.length) === 1, "Only single object mutations are supported");
1188
+ const receipt = await this._writeStream.write({
1189
+ object: {
1190
+ ...request.batch.objects[0],
1191
+ mutations: (_b = request.batch.objects[0].mutations) == null ? void 0 : _b.map((m) => ({
1192
+ ...m,
1193
+ meta: void 0
1194
+ })),
1195
+ meta: void 0
1196
+ }
1197
+ });
1198
+ if (request.clientTag) {
1199
+ this._clientTagMap.set([
1200
+ receipt.feedKey,
1201
+ receipt.seq
1202
+ ], request.clientTag);
1203
+ }
1204
+ return receipt;
1205
+ }
1206
+ };
1207
+
1208
+ // packages/core/echo/echo-pipeline/src/dbhost/database-backend.ts
1209
+ import { ItemDemuxer } from "@dxos/echo-db";
1210
+ var DatabaseBackendHost = class {
1211
+ constructor(_outboundStream, _snapshot, _options = {}) {
1212
+ this._outboundStream = _outboundStream;
1213
+ this._snapshot = _snapshot;
1214
+ this._options = _options;
1215
+ }
1216
+ get isReadOnly() {
1217
+ return !!this._outboundStream;
1218
+ }
1219
+ get echoProcessor() {
1220
+ return this._echoProcessor;
1221
+ }
1222
+ async open(itemManager, modelFactory) {
1223
+ this._itemManager = itemManager;
1224
+ this._itemManager._debugLabel = "host";
1225
+ this._itemDemuxer = new ItemDemuxer(itemManager, modelFactory, this._options);
1226
+ this._echoProcessor = this._itemDemuxer.open();
1227
+ if (this._snapshot) {
1228
+ await this._itemDemuxer.restoreFromSnapshot(this._snapshot);
1229
+ }
1230
+ }
1231
+ async close() {
1232
+ }
1233
+ getWriteStream() {
1234
+ return this._outboundStream;
1235
+ }
1236
+ createSnapshot() {
1237
+ return this._itemDemuxer.createSnapshot();
1238
+ }
1239
+ createDataServiceHost() {
1240
+ var _a;
1241
+ return new DataServiceHost(this._itemManager, this._itemDemuxer, (_a = this._outboundStream) != null ? _a : void 0);
1242
+ }
1243
+ };
1244
+
1245
+ // packages/core/echo/echo-pipeline/src/dbhost/snapshot-manager.ts
1246
+ import { trackLeaks as trackLeaks3 } from "@dxos/async";
1247
+ import { schema as schema4 } from "@dxos/protocols";
1248
+ import { ObjectSync } from "@dxos/teleport-extension-object-sync";
1249
+ var __decorate6 = function(decorators, target, key, desc) {
1250
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1251
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
1252
+ r = Reflect.decorate(decorators, target, key, desc);
1253
+ else
1254
+ for (var i = decorators.length - 1; i >= 0; i--)
1255
+ if (d = decorators[i])
1256
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1257
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1258
+ };
1259
+ var SnapshotManager = class SnapshotManager2 {
1260
+ // prettier-ignore
1261
+ constructor(_snapshotStore) {
1262
+ this._snapshotStore = _snapshotStore;
1263
+ this._objectSync = new ObjectSync({
1264
+ getObject: async (id) => {
1265
+ const snapshot = await this._snapshotStore.loadSnapshot(id);
1266
+ if (!snapshot) {
1267
+ return void 0;
1268
+ }
1269
+ return {
1270
+ id,
1271
+ payload: schema4.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").encodeAsAny(snapshot)
1272
+ };
1273
+ },
1274
+ setObject: async (data) => {
1275
+ const snapshot = schema4.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").decode(data.payload);
1276
+ await this._snapshotStore.saveSnapshot(snapshot);
1277
+ }
1278
+ });
1279
+ }
1280
+ get objectSync() {
1281
+ return this._objectSync;
1282
+ }
1283
+ async open() {
1284
+ await this._objectSync.open();
1285
+ }
1286
+ async close() {
1287
+ await this._objectSync.close();
1288
+ }
1289
+ async load(id) {
1290
+ const local = await this._snapshotStore.loadSnapshot(id);
1291
+ if (local) {
1292
+ return local;
1293
+ }
1294
+ const remote = await this._objectSync.download(id);
1295
+ return schema4.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").decode(remote.payload);
1296
+ }
1297
+ async store(snapshot) {
1298
+ const id = await this._snapshotStore.saveSnapshot(snapshot);
1299
+ return id;
1300
+ }
1301
+ };
1302
+ SnapshotManager = __decorate6([
1303
+ trackLeaks3("open", "close")
1304
+ ], SnapshotManager);
1305
+
1306
+ // packages/core/echo/echo-pipeline/src/dbhost/snapshot-store.ts
1307
+ import { subtleCrypto } from "@dxos/crypto";
1308
+ import { schema as schema5 } from "@dxos/protocols";
1309
+ var SnapshotStore = class {
1310
+ // prettier-ignore
1311
+ constructor(_directory) {
1312
+ this._directory = _directory;
1313
+ }
1314
+ async saveSnapshot(snapshot) {
1315
+ const encoded = schema5.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").encode(snapshot);
1316
+ const key = await subtleCrypto.digest("SHA-256", encoded);
1317
+ const keyString = Buffer.from(key).toString("hex");
1318
+ const file = await this._directory.getOrCreateFile(keyString);
1319
+ try {
1320
+ await file.write(0, Buffer.from(encoded));
1321
+ } finally {
1322
+ await file.close();
1323
+ }
1324
+ return keyString;
1325
+ }
1326
+ async loadSnapshot(key) {
1327
+ const file = await this._directory.getOrCreateFile(key);
1328
+ try {
1329
+ const { size } = await file.stat();
1330
+ if (size === 0) {
1331
+ return void 0;
1332
+ }
1333
+ const buffer = await file.read(0, size);
1334
+ return schema5.getCodecForType("dxos.echo.snapshot.SpaceSnapshot").decode(buffer);
1335
+ } finally {
1336
+ await file.close();
1337
+ }
1338
+ }
1339
+ };
1340
+
1341
+ // packages/core/echo/echo-pipeline/src/dbhost/data-service.ts
1342
+ import assert8 from "@dxos/node-std/assert";
1343
+ import { raise } from "@dxos/debug";
1344
+ import { PublicKey as PublicKey5 } from "@dxos/keys";
1345
+ import { log as log11 } from "@dxos/log";
1346
+ import { ComplexMap as ComplexMap4 } from "@dxos/util";
1347
+ var DataServiceSubscriptions = class {
1348
+ constructor() {
1349
+ this._spaces = new ComplexMap4(PublicKey5.hash);
1350
+ }
1351
+ clear() {
1352
+ this._spaces.clear();
1353
+ }
1354
+ registerSpace(spaceKey, host) {
1355
+ log11("Registering space", {
1356
+ spaceKey
1357
+ }, {
1358
+ file: "data-service.ts",
1359
+ line: 31,
1360
+ scope: this,
1361
+ callSite: (f, a) => f(...a)
1362
+ });
1363
+ this._spaces.set(spaceKey, host);
1364
+ }
1365
+ unregisterSpace(spaceKey) {
1366
+ log11("Unregistering space", {
1367
+ spaceKey
1368
+ }, {
1369
+ file: "data-service.ts",
1370
+ line: 36,
1371
+ scope: this,
1372
+ callSite: (f, a) => f(...a)
1373
+ });
1374
+ this._spaces.delete(spaceKey);
1375
+ }
1376
+ getDataService(spaceKey) {
1377
+ return this._spaces.get(spaceKey);
1378
+ }
1379
+ };
1380
+ var DataServiceImpl = class {
1381
+ constructor(_subscriptions) {
1382
+ this._subscriptions = _subscriptions;
1383
+ }
1384
+ subscribe(request) {
1385
+ var _a;
1386
+ assert8(request.spaceKey);
1387
+ const host = (_a = this._subscriptions.getDataService(request.spaceKey)) != null ? _a : raise(new Error(`space not found: ${request.spaceKey}`));
1388
+ return host.subscribe();
1389
+ }
1390
+ write(request) {
1391
+ var _a;
1392
+ assert8(request.spaceKey);
1393
+ assert8(request.batch);
1394
+ const host = (_a = this._subscriptions.getDataService(request.spaceKey)) != null ? _a : raise(new Error(`space not found: ${request.spaceKey}`));
1395
+ return host.write(request);
1396
+ }
1397
+ };
1398
+
1399
+ // packages/core/echo/echo-pipeline/src/space/data-pipeline-controller.ts
1400
+ import assert9 from "@dxos/node-std/assert";
1401
+ import { Event as Event3, scheduleTask as scheduleTask2, trackLeaks as trackLeaks4 } from "@dxos/async";
1402
+ import { Context as Context2 } from "@dxos/context";
1403
+ import { failUndefined as failUndefined3 } from "@dxos/debug";
1404
+ import { ItemManager } from "@dxos/echo-db";
1405
+ import { log as log12 } from "@dxos/log";
1406
+ import { Timeframe as Timeframe3 } from "@dxos/timeframe";
1407
+ var __decorate7 = function(decorators, target, key, desc) {
1408
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1409
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
1410
+ r = Reflect.decorate(decorators, target, key, desc);
1411
+ else
1412
+ for (var i = decorators.length - 1; i >= 0; i--)
1413
+ if (d = decorators[i])
1414
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1415
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1416
+ };
1417
+ var NoopDataPipelineController = class {
1418
+ async open(context) {
1419
+ }
1420
+ async close() {
1421
+ }
1422
+ };
1423
+ var MESSAGES_PER_SNAPSHOT = 10;
1424
+ var AUTOMATIC_SNAPSHOT_DEBOUNCE_INTERVAL = 5e3;
1425
+ var TIMEFRAME_SAVE_DEBOUNCE_INTERVAL = 500;
1426
+ var DataPipelineControllerImpl = class DataPipelineControllerImpl2 {
1427
+ constructor(_params) {
1428
+ this._params = _params;
1429
+ this._ctx = new Context2();
1430
+ this._lastAutomaticSnapshotTimeframe = new Timeframe3();
1431
+ this.onTimeframeReached = new Event3();
1432
+ }
1433
+ get pipelineState() {
1434
+ var _a;
1435
+ return (_a = this._pipeline) == null ? void 0 : _a.state;
1436
+ }
1437
+ get snapshotTimeframe() {
1438
+ var _a;
1439
+ return (_a = this._snapshot) == null ? void 0 : _a.timeframe;
1440
+ }
1441
+ getStartTimeframe() {
1442
+ var _a;
1443
+ return snapshotTimeframeToStartingTimeframe((_a = this.snapshotTimeframe) != null ? _a : new Timeframe3());
1444
+ }
1445
+ async open(spaceContext) {
1446
+ var _a, _b, _c, _d;
1447
+ this._spaceContext = spaceContext;
1448
+ if (this._params.snapshotId) {
1449
+ this._snapshot = await this._params.snapshotManager.load(this._params.snapshotId);
1450
+ this._lastAutomaticSnapshotTimeframe = (_b = (_a = this._snapshot) == null ? void 0 : _a.timeframe) != null ? _b : new Timeframe3();
1451
+ }
1452
+ this._pipeline = await this._spaceContext.openPipeline(this.getStartTimeframe());
1453
+ const feedWriter = createMappedFeedWriter((data) => ({
1454
+ data
1455
+ }), (_c = this._pipeline.writer) != null ? _c : failUndefined3());
1456
+ this.databaseBackend = new DatabaseBackendHost(feedWriter, (_d = this._snapshot) == null ? void 0 : _d.database, {
1457
+ snapshots: true
1458
+ // TODO(burdon): Config.
1459
+ });
1460
+ this._itemManager = new ItemManager(this._params.modelFactory);
1461
+ await this.databaseBackend.open(this._itemManager, this._params.modelFactory);
1462
+ scheduleTask2(this._ctx, async () => {
1463
+ await this._consumePipeline();
1464
+ });
1465
+ this._createPeriodicSnapshots();
1466
+ }
1467
+ _createPeriodicSnapshots() {
1468
+ this.onTimeframeReached.debounce(TIMEFRAME_SAVE_DEBOUNCE_INTERVAL).on(this._ctx, async () => {
1469
+ await this._saveLatestTimeframe();
1470
+ });
1471
+ this.onTimeframeReached.debounce(AUTOMATIC_SNAPSHOT_DEBOUNCE_INTERVAL).on(this._ctx, async () => {
1472
+ var _a, _b;
1473
+ const latestTimeframe = (_a = this._pipeline) == null ? void 0 : _a.state.timeframe;
1474
+ if (!latestTimeframe) {
1475
+ return;
1476
+ }
1477
+ if (latestTimeframe.totalMessages() - this._lastAutomaticSnapshotTimeframe.totalMessages() > MESSAGES_PER_SNAPSHOT) {
1478
+ const snapshot = await this._saveSnapshot();
1479
+ this._lastAutomaticSnapshotTimeframe = (_b = snapshot.timeframe) != null ? _b : failUndefined3();
1480
+ log12("save", {
1481
+ snapshot
1482
+ }, {
1483
+ file: "data-pipeline-controller.ts",
1484
+ line: 151,
1485
+ scope: this,
1486
+ callSite: (f, a) => f(...a)
1487
+ });
1488
+ }
1489
+ });
1490
+ }
1491
+ async _saveSnapshot() {
1492
+ const snapshot = await this.createSnapshot();
1493
+ const snapshotKey = await this._params.snapshotManager.store(snapshot);
1494
+ await this._params.metadataStore.setSpaceSnapshot(this._params.spaceKey, snapshotKey);
1495
+ return snapshot;
1496
+ }
1497
+ async _saveLatestTimeframe() {
1498
+ var _a;
1499
+ const latestTimeframe = (_a = this._pipeline) == null ? void 0 : _a.state.timeframe;
1500
+ if (latestTimeframe) {
1501
+ await this._params.metadataStore.setSpaceLatestTimeframe(this._params.spaceKey, latestTimeframe);
1502
+ }
1503
+ }
1504
+ async close() {
1505
+ var _a, _b, _c;
1506
+ try {
1507
+ await this._saveLatestTimeframe();
1508
+ await this._saveSnapshot();
1509
+ } catch (err) {
1510
+ log12.catch(err, {}, {
1511
+ file: "data-pipeline-controller.ts",
1512
+ line: 175,
1513
+ scope: this,
1514
+ callSite: (f, a) => f(...a)
1515
+ });
1516
+ }
1517
+ await this._ctx.dispose();
1518
+ await ((_a = this._pipeline) == null ? void 0 : _a.stop());
1519
+ await ((_b = this.databaseBackend) == null ? void 0 : _b.close());
1520
+ await ((_c = this._itemManager) == null ? void 0 : _c.destroy());
1521
+ await this._params.snapshotManager.close();
1522
+ }
1523
+ createSnapshot() {
1524
+ var _a, _b;
1525
+ return {
1526
+ spaceKey: this._params.spaceKey.asUint8Array(),
1527
+ timeframe: (_b = (_a = this._pipeline) == null ? void 0 : _a.state.timeframe) != null ? _b : new Timeframe3(),
1528
+ database: this.databaseBackend.createSnapshot()
1529
+ };
1530
+ }
1531
+ async _consumePipeline() {
1532
+ assert9(this._pipeline, "Pipeline is not initialized.");
1533
+ for await (const msg of this._pipeline.consume()) {
1534
+ const { feedKey, seq, data } = msg;
1535
+ log12("processing message", {
1536
+ msg
1537
+ }, {
1538
+ file: "data-pipeline-controller.ts",
1539
+ line: 196,
1540
+ scope: this,
1541
+ callSite: (f, a) => f(...a)
1542
+ });
1543
+ try {
1544
+ if (data.payload.data) {
1545
+ const feedInfo = this._params.feedInfoProvider(feedKey);
1546
+ if (!feedInfo) {
1547
+ log12.error("Could not find feed.", {
1548
+ feedKey
1549
+ }, {
1550
+ file: "data-pipeline-controller.ts",
1551
+ line: 202,
1552
+ scope: this,
1553
+ callSite: (f, a) => f(...a)
1554
+ });
1555
+ continue;
1556
+ }
1557
+ await this.databaseBackend.echoProcessor({
1558
+ data: data.payload.data.object,
1559
+ meta: {
1560
+ feedKey,
1561
+ seq,
1562
+ timeframe: data.timeframe,
1563
+ memberKey: feedInfo.assertion.identityKey
1564
+ }
1565
+ });
1566
+ this.onTimeframeReached.emit(data.timeframe);
1567
+ }
1568
+ } catch (err) {
1569
+ log12.catch(err, {}, {
1570
+ file: "data-pipeline-controller.ts",
1571
+ line: 218,
1572
+ scope: this,
1573
+ callSite: (f, a) => f(...a)
1574
+ });
1575
+ }
1576
+ }
1577
+ }
1578
+ async waitUntilTimeframe(timeframe) {
1579
+ assert9(this._pipeline, "Pipeline is not initialized.");
1580
+ await this._pipeline.state.waitUntilTimeframe(timeframe);
1581
+ }
1582
+ };
1583
+ DataPipelineControllerImpl = __decorate7([
1584
+ trackLeaks4("open", "close")
1585
+ ], DataPipelineControllerImpl);
1586
+ var snapshotTimeframeToStartingTimeframe = (snapshotTimeframe) => {
1587
+ return snapshotTimeframe.map(([key, seq]) => [
1588
+ key,
1589
+ seq + 1
1590
+ ]);
1591
+ };
1592
+
1593
+ export {
1594
+ STORAGE_VERSION,
1595
+ MetadataStore,
1596
+ codec,
1597
+ valueEncoding,
1598
+ createMappedFeedWriter,
1599
+ mapTimeframeToFeedIndexes,
1600
+ mapFeedIndexesToTimeframe,
1601
+ TimeframeClock,
1602
+ Pipeline,
1603
+ AuthExtension,
1604
+ Space,
1605
+ MOCK_AUTH_PROVIDER,
1606
+ MOCK_AUTH_VERIFIER,
1607
+ SpaceProtocol,
1608
+ AuthStatus,
1609
+ SpaceProtocolSession,
1610
+ SpaceManager,
1611
+ spaceGenesis,
1612
+ DataServiceHost,
1613
+ DatabaseBackendHost,
1614
+ SnapshotManager,
1615
+ SnapshotStore,
1616
+ DataServiceSubscriptions,
1617
+ DataServiceImpl,
1618
+ NoopDataPipelineController,
1619
+ DataPipelineControllerImpl
1620
+ };
1621
+ //# sourceMappingURL=chunk-3GAE5CKD.mjs.map