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