@powerhousedao/reactor 6.2.3-dev.5 → 6.2.3-dev.50

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 (53) hide show
  1. package/dist/document-indexer-DwAMDVRI.js +1844 -0
  2. package/dist/document-indexer-DwAMDVRI.js.map +1 -0
  3. package/dist/drive-container-types-Ci1pdv4X.js +3766 -0
  4. package/dist/drive-container-types-Ci1pdv4X.js.map +1 -0
  5. package/dist/entry.d.ts +2 -1
  6. package/dist/entry.js +111 -7
  7. package/dist/entry.js.map +1 -1
  8. package/dist/{errors-D3S6Eysd.js → errors-BM_ULVWd.js} +9 -1
  9. package/dist/{errors-D3S6Eysd.js.map → errors-BM_ULVWd.js.map} +1 -1
  10. package/dist/forwarding-logger-ByfBFgMS.js +3635 -0
  11. package/dist/forwarding-logger-ByfBFgMS.js.map +1 -0
  12. package/dist/index-CNhT69De.d.ts +6383 -0
  13. package/dist/index-CNhT69De.d.ts.map +1 -0
  14. package/dist/index.d.ts +935 -5509
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +5189 -1022
  17. package/dist/index.js.map +1 -1
  18. package/dist/load-spec-ZLjuyhxz.js +246 -0
  19. package/dist/load-spec-ZLjuyhxz.js.map +1 -0
  20. package/dist/projection-entry.d.ts +2 -1
  21. package/dist/projection-entry.js +99 -21
  22. package/dist/projection-entry.js.map +1 -1
  23. package/dist/{projection-shard-manager-CPQc5XHL.js → projection-shard-manager-CQ5FwQmv.js} +24 -4
  24. package/dist/projection-shard-manager-CQ5FwQmv.js.map +1 -0
  25. package/dist/{projection-worker-wI4PwcV2.js → projection-worker-D8uNFdwX.js} +1 -1
  26. package/dist/{projection-worker-wI4PwcV2.js.map → projection-worker-D8uNFdwX.js.map} +1 -1
  27. package/dist/rpc.d.ts +332 -0
  28. package/dist/rpc.d.ts.map +1 -0
  29. package/dist/rpc.js +571 -0
  30. package/dist/rpc.js.map +1 -0
  31. package/dist/{transport-CuogVKN_.js → transport-B3G50KVd.js} +1 -1
  32. package/dist/{transport-CuogVKN_.js.map → transport-B3G50KVd.js.map} +1 -1
  33. package/dist/{transport-ByGviWdZ.js → transport-CZDHzfvy.js} +1 -1
  34. package/dist/{transport-ByGviWdZ.js.map → transport-CZDHzfvy.js.map} +1 -1
  35. package/dist/{worker-handle-CrERzl8s.js → worker-handle-CN2-oRv-.js} +30 -17
  36. package/dist/worker-handle-CN2-oRv-.js.map +1 -0
  37. package/package.json +34 -18
  38. package/dist/build-worker-executor-DnU3ZU4H.js +0 -83
  39. package/dist/build-worker-executor-DnU3ZU4H.js.map +0 -1
  40. package/dist/document-indexer-C5Gsa1B3.js +0 -958
  41. package/dist/document-indexer-C5Gsa1B3.js.map +0 -1
  42. package/dist/drive-container-types-yZrksiJR.js +0 -5310
  43. package/dist/drive-container-types-yZrksiJR.js.map +0 -1
  44. package/dist/error-info-Cpu4OY3o.js +0 -62
  45. package/dist/error-info-Cpu4OY3o.js.map +0 -1
  46. package/dist/forwarding-logger-BBkMSxuJ.js +0 -85
  47. package/dist/forwarding-logger-BBkMSxuJ.js.map +0 -1
  48. package/dist/projection-shard-manager-CPQc5XHL.js.map +0 -1
  49. package/dist/types-DMKLa0Ok.js +0 -33
  50. package/dist/types-DMKLa0Ok.js.map +0 -1
  51. package/dist/worker-HPysBfhx.js +0 -22
  52. package/dist/worker-HPysBfhx.js.map +0 -1
  53. package/dist/worker-handle-CrERzl8s.js.map +0 -1
@@ -1,958 +0,0 @@
1
- import { L as DocumentExistence } from "./drive-container-types-yZrksiJR.js";
2
- import { n as ReactorEventTypes } from "./types-DMKLa0Ok.js";
3
- import { createAuthState, isDenied } from "@powerhousedao/shared/document-model";
4
- import { v4 } from "uuid";
5
- import { childLogger } from "document-model";
6
- //#region src/read-models/base-read-model.ts
7
- /**
8
- * Base class for read models that provides catch-up/rewind functionality.
9
- * Handles initialization, state tracking via ViewState table, and consistency tracking.
10
- * Subclasses override commitOperations() with their specific domain logic.
11
- */
12
- var BaseReadModel = class {
13
- lastOrdinal = 0;
14
- name;
15
- constructor(db, operationIndex, writeCache, consistencyTracker, config) {
16
- this.db = db;
17
- this.operationIndex = operationIndex;
18
- this.writeCache = writeCache;
19
- this.consistencyTracker = consistencyTracker;
20
- this.config = config;
21
- this.name = config.readModelId;
22
- }
23
- /**
24
- * Initializes the read model by loading state and catching up on missed operations.
25
- */
26
- async init() {
27
- const viewState = await this.loadState();
28
- if (viewState !== void 0) this.lastOrdinal = viewState;
29
- else await this.initializeState();
30
- let page = await this.operationIndex.getSinceOrdinal(this.lastOrdinal);
31
- while (page.results.length > 0) {
32
- const ops = this.config.rebuildStateOnInit ? await this.rebuildStateForOperations(page.results) : page.results;
33
- await this.indexOperations(ops);
34
- if (!page.next) break;
35
- page = await page.next();
36
- }
37
- }
38
- /**
39
- * Template method: runs domain-specific commitOperations, then persists
40
- * state and updates consistency tracking.
41
- */
42
- async indexOperations(items) {
43
- if (items.length === 0) return;
44
- await this.commitOperations(items);
45
- await this.db.transaction().execute(async (trx) => {
46
- await this.saveState(trx, items);
47
- });
48
- this.updateConsistencyTracker(items);
49
- }
50
- /**
51
- * Waits for the read model to reach the specified consistency level.
52
- */
53
- async waitForConsistency(token, timeoutMs, signal) {
54
- if (token.coordinates.length === 0) return;
55
- await this.consistencyTracker.waitFor(token.coordinates, timeoutMs, signal);
56
- }
57
- async commitOperations(items) {}
58
- /**
59
- * Rebuilds document state for each operation using the write cache.
60
- */
61
- async rebuildStateForOperations(operations) {
62
- const result = [];
63
- for (const op of operations) {
64
- const { documentId, scope, branch } = op.context;
65
- const targetRevision = op.operation.index;
66
- const document = await this.writeCache.getState(documentId, scope, branch, targetRevision);
67
- result.push({
68
- operation: op.operation,
69
- context: {
70
- ...op.context,
71
- resultingState: JSON.stringify(document)
72
- }
73
- });
74
- }
75
- return result;
76
- }
77
- /**
78
- * Loads the last processed ordinal from the ViewState table.
79
- * Returns undefined if no state exists for this read model.
80
- */
81
- async loadState() {
82
- return (await this.db.selectFrom("ViewState").select("lastOrdinal").where("readModelId", "=", this.config.readModelId).executeTakeFirst())?.lastOrdinal;
83
- }
84
- /**
85
- * Initializes the ViewState row for this read model.
86
- */
87
- async initializeState() {
88
- await this.db.insertInto("ViewState").values({
89
- readModelId: this.config.readModelId,
90
- lastOrdinal: 0
91
- }).execute();
92
- }
93
- /**
94
- * Saves the last processed ordinal to the ViewState table.
95
- */
96
- async saveState(trx, items) {
97
- let maxOrdinal = 0;
98
- for (const item of items) maxOrdinal = Math.max(maxOrdinal, item.context.ordinal);
99
- this.lastOrdinal = maxOrdinal;
100
- await trx.updateTable("ViewState").set({
101
- lastOrdinal: maxOrdinal,
102
- lastOperationTimestamp: /* @__PURE__ */ new Date()
103
- }).where("readModelId", "=", this.config.readModelId).execute();
104
- }
105
- /**
106
- * Updates the consistency tracker with the processed operations.
107
- */
108
- updateConsistencyTracker(items) {
109
- const coordinates = [];
110
- for (let i = 0; i < items.length; i++) {
111
- const item = items[i];
112
- coordinates.push({
113
- documentId: item.context.documentId,
114
- scope: item.context.scope,
115
- branch: item.context.branch,
116
- operationIndex: item.operation.index
117
- });
118
- }
119
- this.consistencyTracker.update(coordinates);
120
- }
121
- };
122
- //#endregion
123
- //#region src/read-models/coordinator.ts
124
- /**
125
- * Coordinates read model synchronization by listening to operation write events
126
- * and updating all registered read models on per-`documentId:scope:branch`
127
- * serial chains. Cross-key projection runs in parallel; same-key projection is
128
- * serialized so the executor can return to dispatch without holding ordering
129
- * implicitly.
130
- */
131
- var ReadModelCoordinator = class {
132
- unsubscribe;
133
- isRunning = false;
134
- chains = /* @__PURE__ */ new Map();
135
- logger;
136
- readModels;
137
- constructor(eventBus, preReady, postReady) {
138
- this.eventBus = eventBus;
139
- this.preReady = preReady;
140
- this.postReady = postReady;
141
- this.readModels = [...preReady, ...postReady];
142
- this.logger = childLogger(["reactor", "read-model-coordinator"]);
143
- }
144
- start() {
145
- if (this.isRunning) return;
146
- this.unsubscribe = this.eventBus.subscribe(ReactorEventTypes.JOB_WRITE_READY, (type, event) => {
147
- return this.handleWriteReady(event);
148
- });
149
- this.isRunning = true;
150
- }
151
- stop() {
152
- if (!this.isRunning) return;
153
- if (this.unsubscribe) {
154
- this.unsubscribe();
155
- this.unsubscribe = void 0;
156
- }
157
- this.isRunning = false;
158
- }
159
- /**
160
- * Resolves when every per-queueKey projection chain has flushed. Intended
161
- * for test fixtures and explicit shutdown; production callers use
162
- * consistency tokens instead.
163
- */
164
- async drain() {
165
- while (this.chains.size > 0) {
166
- const pending = Array.from(this.chains.values());
167
- await Promise.allSettled(pending);
168
- }
169
- }
170
- getChainDepth() {
171
- return this.chains.size;
172
- }
173
- addReadModel(readModel, stage) {
174
- if (this.readModels.some(({ name }) => name === readModel.name)) throw new Error(`Read model "${readModel.name}" is already registered`);
175
- if (stage === "pre_ready") this.preReady.push(readModel);
176
- else this.postReady.push(readModel);
177
- this.readModels.push(readModel);
178
- }
179
- handleWriteReady(event) {
180
- if (event.operations.length === 0) {
181
- this.emitEmptyReadReady(event);
182
- return;
183
- }
184
- const enqueuedAt = performance.now();
185
- const key = this.queueKeyFor(event);
186
- const current = (this.chains.get(key) ?? Promise.resolve()).then(() => this.runChain(event, enqueuedAt));
187
- this.chains.set(key, current);
188
- current.finally(() => {
189
- if (this.chains.get(key) === current) this.chains.delete(key);
190
- });
191
- }
192
- async emitEmptyReadReady(event) {
193
- const readyEvent = {
194
- jobId: event.jobId,
195
- operations: event.operations
196
- };
197
- try {
198
- await this.eventBus.emit(ReactorEventTypes.JOB_READ_READY, readyEvent);
199
- } catch (error) {
200
- this.logger.error("JOB_READ_READY emit failed for job @jobId: @Error", { jobId: event.jobId }, error);
201
- }
202
- this.emitBatchCompleted({
203
- jobId: event.jobId,
204
- batchSize: 0,
205
- chainWaitDurationMs: 0,
206
- preReadyDurationMs: 0,
207
- emitDurationMs: 0,
208
- postReadyDurationMs: 0
209
- });
210
- }
211
- async runChain(event, enqueuedAt) {
212
- const chainWaitDurationMs = performance.now() - enqueuedAt;
213
- const preReadyStart = performance.now();
214
- try {
215
- await Promise.all(this.preReady.map((readModel) => this.indexWithTiming(readModel, "pre_ready", event)));
216
- } catch (error) {
217
- this.logger.error("Pre-ready read model indexing failed for job @jobId: @Error", { jobId: event.jobId }, error);
218
- }
219
- const preReadyDurationMs = performance.now() - preReadyStart;
220
- const readyEvent = {
221
- jobId: event.jobId,
222
- operations: event.operations
223
- };
224
- const emitStart = performance.now();
225
- try {
226
- await this.eventBus.emit(ReactorEventTypes.JOB_READ_READY, readyEvent);
227
- } catch (error) {
228
- this.logger.error("JOB_READ_READY emit failed for job @jobId: @Error", { jobId: event.jobId }, error);
229
- }
230
- const emitDurationMs = performance.now() - emitStart;
231
- const postReadyStart = performance.now();
232
- try {
233
- await Promise.all(this.postReady.map((readModel) => this.indexWithTiming(readModel, "post_ready", event)));
234
- } catch (error) {
235
- this.logger.error("Post-ready read model indexing failed for job @jobId: @Error", { jobId: event.jobId }, error);
236
- }
237
- const postReadyDurationMs = performance.now() - postReadyStart;
238
- this.emitBatchCompleted({
239
- jobId: event.jobId,
240
- batchSize: event.operations.length,
241
- chainWaitDurationMs,
242
- preReadyDurationMs,
243
- emitDurationMs,
244
- postReadyDurationMs
245
- });
246
- }
247
- async indexWithTiming(readModel, stage, event) {
248
- const start = performance.now();
249
- let success = false;
250
- try {
251
- await readModel.indexOperations(event.operations);
252
- success = true;
253
- } finally {
254
- this.emitReadModelIndexed({
255
- jobId: event.jobId,
256
- readModelName: readModel.name,
257
- stage,
258
- durationMs: performance.now() - start,
259
- operationCount: event.operations.length,
260
- success
261
- });
262
- }
263
- }
264
- emitReadModelIndexed(payload) {
265
- this.eventBus.emit(ReactorEventTypes.READMODEL_INDEXED, payload).catch((err) => this.logger.error("READMODEL_INDEXED emit failed for job @jobId: @Error", { jobId: payload.jobId }, err));
266
- }
267
- emitBatchCompleted(payload) {
268
- this.eventBus.emit(ReactorEventTypes.READMODEL_BATCH_COMPLETED, payload).catch((err) => this.logger.error("READMODEL_BATCH_COMPLETED emit failed for job @jobId: @Error", { jobId: payload.jobId }, err));
269
- }
270
- queueKeyFor(event) {
271
- const ctx = event.operations[0].context;
272
- return `${ctx.documentId}:${ctx.scope}:${ctx.branch}`;
273
- }
274
- };
275
- //#endregion
276
- //#region src/read-models/names.ts
277
- /** `getReadModel` name of the document view; see {@link ReactorReadModels}. */
278
- const DOCUMENT_VIEW_READ_MODEL = "document-view";
279
- /** `getReadModel` name of the document indexer; see {@link ReactorReadModels}. */
280
- const DOCUMENT_INDEXER_READ_MODEL = "document-indexer";
281
- //#endregion
282
- //#region src/read-models/document-view.ts
283
- var KyselyDocumentView = class extends BaseReadModel {
284
- _db;
285
- constructor(db, operationStore, operationIndex, writeCache, consistencyTracker, servesDeletionBoundary) {
286
- super(db, operationIndex, writeCache, consistencyTracker, {
287
- readModelId: DOCUMENT_VIEW_READ_MODEL,
288
- rebuildStateOnInit: true
289
- });
290
- this.operationStore = operationStore;
291
- this.servesDeletionBoundary = servesDeletionBoundary;
292
- this._db = db;
293
- }
294
- /**
295
- * Indexes committed operations into DocumentSnapshot rows. CREATE_DOCUMENT
296
- * only seeds header/document/auth. UPGRADE_DOCUMENT reindexes every scope
297
- * present in resultingState when the operation vouches for them — a seed
298
- * carrying initialState or a migration stamped with the __migrated marker
299
- * — since the upgrade reducer may have reshaped any of them; upgrades
300
- * without either fall back to header/document/auth, because their sibling
301
- * echoes may be stale. All other action types index only header and their
302
- * own scope.
303
- */
304
- async commitOperations(items) {
305
- await this._db.transaction().execute(async (trx) => {
306
- for (const item of items) {
307
- const { operation, context } = item;
308
- const { documentId, scope, branch, documentType, resultingState } = context;
309
- const { index, hash } = operation;
310
- if (!resultingState) throw new Error(`Missing resultingState in context for operation ${operation.id || "unknown"}. IDocumentView requires resultingState from upstream - it does not rebuild documents.`);
311
- let fullState;
312
- try {
313
- fullState = JSON.parse(resultingState);
314
- } catch (error) {
315
- throw new Error(`Failed to parse resultingState for operation ${operation.id || "unknown"}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
316
- }
317
- const operationType = operation.action.type;
318
- const denied = isDenied(operation);
319
- const preserveHeaderMeta = denied || operationType !== "CREATE_DOCUMENT" && operationType !== "UPGRADE_DOCUMENT" && operationType !== "DELETE_DOCUMENT" && scope !== "header";
320
- if (operationType === "DELETE_DOCUMENT" && !denied) {
321
- const now = /* @__PURE__ */ new Date();
322
- await trx.updateTable("DocumentSnapshot").set({
323
- isDeleted: true,
324
- deletedAt: now,
325
- lastOperationIndex: index,
326
- lastOperationHash: hash,
327
- lastUpdatedAt: now
328
- }).where("documentId", "=", documentId).where("branch", "=", branch).execute();
329
- const deletedDocumentScope = fullState?.document;
330
- if (deletedDocumentScope !== void 0) await trx.updateTable("DocumentSnapshot").set({ content: deletedDocumentScope }).where("documentId", "=", documentId).where("branch", "=", branch).where("scope", "=", "document").execute();
331
- await trx.deleteFrom("SlugMapping").where("documentId", "=", documentId).where("branch", "=", branch).execute();
332
- continue;
333
- }
334
- let scopesToIndex;
335
- if (operationType === "CREATE_DOCUMENT") scopesToIndex = Object.entries(fullState).filter(([key]) => key === "header" || key === "document" || key === "auth");
336
- else if (operationType === "UPGRADE_DOCUMENT") {
337
- const upgradeInput = operation.action.input;
338
- const scopesVouchedFor = fullState.__migrated === true || upgradeInput.initialState !== void 0;
339
- delete fullState.__migrated;
340
- scopesToIndex = scopesVouchedFor ? Object.entries(fullState) : Object.entries(fullState).filter(([key]) => key === "header" || key === "document" || key === "auth");
341
- } else {
342
- scopesToIndex = [];
343
- if (fullState.header !== void 0) scopesToIndex.push(["header", fullState.header]);
344
- if (fullState[scope] !== void 0) scopesToIndex.push([scope, fullState[scope]]);
345
- else scopesToIndex.push([scope, {}]);
346
- }
347
- for (const [scopeName, scopeState] of scopesToIndex) {
348
- const existingSnapshot = await trx.selectFrom("DocumentSnapshot").selectAll().where("documentId", "=", documentId).where("scope", "=", scopeName).where("branch", "=", branch).executeTakeFirst();
349
- const newState = typeof scopeState === "object" && scopeState !== null ? scopeState : {};
350
- let slug = existingSnapshot?.slug ?? null;
351
- let name = existingSnapshot?.name ?? null;
352
- if (scopeName === "header") {
353
- const headerSlug = newState.slug;
354
- const headerName = newState.name;
355
- if (typeof headerSlug === "string") slug = headerSlug;
356
- if (typeof headerName === "string") name = headerName;
357
- if (preserveHeaderMeta && existingSnapshot) {
358
- const existingHeader = existingSnapshot.content;
359
- if (existingHeader && "meta" in existingHeader) newState.meta = existingHeader.meta;
360
- }
361
- if (slug && slug !== documentId && !existingSnapshot?.isDeleted) await trx.insertInto("SlugMapping").values({
362
- slug,
363
- documentId,
364
- scope: scopeName,
365
- branch
366
- }).onConflict((oc) => oc.column("slug").doUpdateSet({
367
- documentId,
368
- scope: scopeName,
369
- branch
370
- })).execute();
371
- }
372
- if (existingSnapshot) await trx.updateTable("DocumentSnapshot").set({
373
- lastOperationIndex: index,
374
- lastOperationHash: hash,
375
- lastUpdatedAt: /* @__PURE__ */ new Date(),
376
- snapshotVersion: existingSnapshot.snapshotVersion + 1,
377
- content: newState,
378
- slug,
379
- name
380
- }).where("documentId", "=", documentId).where("scope", "=", scopeName).where("branch", "=", branch).execute();
381
- else {
382
- const snapshot = {
383
- id: v4(),
384
- documentId,
385
- slug,
386
- name,
387
- scope: scopeName,
388
- branch,
389
- content: newState,
390
- documentType,
391
- lastOperationIndex: index,
392
- lastOperationHash: hash,
393
- identifiers: null,
394
- metadata: null,
395
- deletedAt: null
396
- };
397
- await trx.insertInto("DocumentSnapshot").values(snapshot).execute();
398
- }
399
- }
400
- }
401
- });
402
- }
403
- async exists(documentIds, existence, consistencyToken, signal) {
404
- if (consistencyToken) await this.waitForConsistency(consistencyToken, void 0, signal);
405
- if (signal?.aborted) throw new Error("Operation aborted");
406
- if (documentIds.length === 0) return [];
407
- const existingIds = existence === DocumentExistence.IncludingDeleted ? await this.idsWithStreams(documentIds, signal) : await this.liveIds(documentIds);
408
- return documentIds.map((id) => existingIds.has(id));
409
- }
410
- async get(documentId, view, consistencyToken, signal) {
411
- if (consistencyToken) await this.waitForConsistency(consistencyToken, void 0, signal);
412
- if (signal?.aborted) throw new Error("Operation aborted");
413
- const branch = view?.branch || "main";
414
- let scopesToQuery;
415
- if (view?.scopes && view.scopes.length > 0) scopesToQuery = [...new Set([
416
- "header",
417
- "document",
418
- ...view.scopes
419
- ])];
420
- else scopesToQuery = [];
421
- let query = this._db.selectFrom("DocumentSnapshot").selectAll().where("documentId", "=", documentId).where("branch", "=", branch);
422
- if (!this.servesDeletionBoundary) query = query.where("isDeleted", "=", false);
423
- if (scopesToQuery.length > 0) query = query.where("scope", "in", scopesToQuery);
424
- const snapshots = await query.execute();
425
- if (snapshots.length === 0) throw new Error(`Document not found: ${documentId}`);
426
- if (signal?.aborted) throw new Error("Operation aborted");
427
- const headerSnapshot = snapshots.find((s) => s.scope === "header");
428
- if (!headerSnapshot) throw new Error(`Document header not found: ${documentId}`);
429
- const header = headerSnapshot.content;
430
- const revisions = await this.operationStore.getRevisions(documentId, branch, signal);
431
- header.revision = revisions.revision;
432
- header.lastModifiedAtUtcIso = revisions.latestTimestamp;
433
- const state = {};
434
- for (const snapshot of snapshots) {
435
- if (snapshot.scope === "header") continue;
436
- state[snapshot.scope] = snapshot.scope === "auth" ? createAuthState(snapshot.content) : snapshot.content;
437
- }
438
- return {
439
- header,
440
- state,
441
- operations: {},
442
- initialState: state,
443
- clipboard: []
444
- };
445
- }
446
- async getMany(documentIds, view, consistencyToken, signal) {
447
- if (documentIds.length === 0) return [];
448
- if (consistencyToken) await this.waitForConsistency(consistencyToken, void 0, signal);
449
- if (signal?.aborted) throw new Error("Operation aborted");
450
- const branch = view?.branch || "main";
451
- let scopesToQuery;
452
- if (view?.scopes && view.scopes.length > 0) scopesToQuery = [...new Set([
453
- "header",
454
- "document",
455
- ...view.scopes
456
- ])];
457
- else scopesToQuery = [];
458
- let query = this._db.selectFrom("DocumentSnapshot").selectAll().where("documentId", "in", documentIds).where("branch", "=", branch).where("isDeleted", "=", false);
459
- if (scopesToQuery.length > 0) query = query.where("scope", "in", scopesToQuery);
460
- const allSnapshots = await query.execute();
461
- if (signal?.aborted) throw new Error("Operation aborted");
462
- const snapshotsByDocId = /* @__PURE__ */ new Map();
463
- for (const snapshot of allSnapshots) {
464
- const existing = snapshotsByDocId.get(snapshot.documentId) || [];
465
- existing.push(snapshot);
466
- snapshotsByDocId.set(snapshot.documentId, existing);
467
- }
468
- const foundDocumentIds = [...snapshotsByDocId.keys()];
469
- const revisionResults = await Promise.all(foundDocumentIds.map((docId) => this.operationStore.getRevisions(docId, branch, signal)));
470
- const revisionsByDocId = /* @__PURE__ */ new Map();
471
- for (let i = 0; i < foundDocumentIds.length; i++) revisionsByDocId.set(foundDocumentIds[i], revisionResults[i]);
472
- if (signal?.aborted) throw new Error("Operation aborted");
473
- const documents = [];
474
- for (const documentId of documentIds) {
475
- const snapshots = snapshotsByDocId.get(documentId);
476
- if (!snapshots || snapshots.length === 0) continue;
477
- const headerSnapshot = snapshots.find((s) => s.scope === "header");
478
- if (!headerSnapshot) continue;
479
- const header = headerSnapshot.content;
480
- const revisions = revisionsByDocId.get(documentId);
481
- if (revisions) {
482
- header.revision = revisions.revision;
483
- header.lastModifiedAtUtcIso = revisions.latestTimestamp;
484
- }
485
- const state = {};
486
- for (const snapshot of snapshots) {
487
- if (snapshot.scope === "header") continue;
488
- state[snapshot.scope] = snapshot.scope === "auth" ? createAuthState(snapshot.content) : snapshot.content;
489
- }
490
- const document = {
491
- header,
492
- state,
493
- operations: {},
494
- initialState: state,
495
- clipboard: []
496
- };
497
- documents.push(document);
498
- }
499
- return documents;
500
- }
501
- async getByIdOrSlug(identifier, view, consistencyToken, signal) {
502
- const documentId = await this.resolveIdOrSlug(identifier, view, consistencyToken, signal);
503
- return this.get(documentId, view, void 0, signal);
504
- }
505
- async findByType(type, view, paging, consistencyToken, signal) {
506
- if (consistencyToken) await this.waitForConsistency(consistencyToken, void 0, signal);
507
- if (signal?.aborted) throw new Error("Operation aborted");
508
- const branch = view?.branch || "main";
509
- const startIndex = paging?.cursor ? parseInt(paging.cursor) : 0;
510
- const limit = paging?.limit || 100;
511
- const documents = [];
512
- const processedDocumentIds = /* @__PURE__ */ new Set();
513
- const allDocumentIds = [];
514
- const snapshots = await this._db.selectFrom("DocumentSnapshot").selectAll().where("documentType", "=", type).where("branch", "=", branch).where("isDeleted", "=", false).orderBy("lastUpdatedAt", "desc").execute();
515
- if (signal?.aborted) throw new Error("Operation aborted");
516
- for (const snapshot of snapshots) {
517
- if (processedDocumentIds.has(snapshot.documentId)) continue;
518
- processedDocumentIds.add(snapshot.documentId);
519
- allDocumentIds.push(snapshot.documentId);
520
- }
521
- const docsToFetch = allDocumentIds.slice(startIndex, startIndex + limit);
522
- for (const documentId of docsToFetch) {
523
- if (signal?.aborted) throw new Error("Operation aborted");
524
- try {
525
- const document = await this.get(documentId, view, void 0, signal);
526
- documents.push(document);
527
- } catch {
528
- continue;
529
- }
530
- }
531
- const hasMore = allDocumentIds.length > startIndex + limit;
532
- const nextCursor = hasMore ? String(startIndex + limit) : void 0;
533
- return {
534
- results: documents,
535
- options: paging || {
536
- cursor: "0",
537
- limit: 100
538
- },
539
- nextCursor,
540
- totalCount: allDocumentIds.length,
541
- next: hasMore ? () => this.findByType(type, view, {
542
- cursor: nextCursor,
543
- limit
544
- }, consistencyToken, signal) : void 0
545
- };
546
- }
547
- async resolveSlug(slug, view, consistencyToken, signal) {
548
- if (consistencyToken) await this.waitForConsistency(consistencyToken, void 0, signal);
549
- if (signal?.aborted) throw new Error("Operation aborted");
550
- const branch = view?.branch || "main";
551
- const mapping = await this._db.selectFrom("SlugMapping").select("documentId").where("slug", "=", slug).where("branch", "=", branch).executeTakeFirst();
552
- if (!mapping) return;
553
- if (signal?.aborted) throw new Error("Operation aborted");
554
- if (view?.scopes && view.scopes.length > 0) {
555
- if (!await this._db.selectFrom("DocumentSnapshot").select("scope").where("documentId", "=", mapping.documentId).where("branch", "=", branch).where("scope", "in", view.scopes).where("isDeleted", "=", false).executeTakeFirst()) return;
556
- }
557
- return mapping.documentId;
558
- }
559
- async resolveSlugs(slugs, view, consistencyToken, signal) {
560
- return (await Promise.all(slugs.map((slug) => this.resolveSlug(slug, view, consistencyToken, signal)))).filter((id) => id !== void 0);
561
- }
562
- async resolveIdOrSlug(identifier, view, consistencyToken, signal) {
563
- if (consistencyToken) await this.waitForConsistency(consistencyToken, void 0, signal);
564
- if (signal?.aborted) throw new Error("Operation aborted");
565
- const branch = view?.branch || "main";
566
- let idCheckQuery = this._db.selectFrom("DocumentSnapshot").select("documentId").where("documentId", "=", identifier).where("branch", "=", branch);
567
- if (!this.servesDeletionBoundary) idCheckQuery = idCheckQuery.where("isDeleted", "=", false);
568
- const idCheckPromise = idCheckQuery.executeTakeFirst();
569
- const slugCheckPromise = this._db.selectFrom("SlugMapping").select("documentId").where("slug", "=", identifier).where("branch", "=", branch).executeTakeFirst();
570
- const [idMatch, slugMatch] = await Promise.all([idCheckPromise, slugCheckPromise]);
571
- if (signal?.aborted) throw new Error("Operation aborted");
572
- const idMatchDocId = idMatch?.documentId;
573
- const slugMatchDocId = slugMatch?.documentId;
574
- if (idMatchDocId && slugMatchDocId && idMatchDocId !== slugMatchDocId) throw new Error(`Ambiguous identifier "${identifier}": matches both document ID "${idMatchDocId}" and slug for document ID "${slugMatchDocId}". Please use get() for ID or resolveSlug() + get() for slug to be explicit.`);
575
- const resolvedDocumentId = idMatchDocId || slugMatchDocId;
576
- if (!resolvedDocumentId) throw new Error(`Document not found: ${identifier}`);
577
- return resolvedDocumentId;
578
- }
579
- /**
580
- * Ids that have at least one stream, asked of the operation store rather than
581
- * of a table, so the answer holds for any store implementation. A deleted
582
- * document keeps its stream, so this is the id-is-taken answer, and it does
583
- * not drift when a snapshot row is missing.
584
- *
585
- * Asked on main because that is the branch a create writes: the store this
586
- * question exists to agree with validates the create against main's head.
587
- */
588
- async idsWithStreams(documentIds, signal) {
589
- const unique = [...new Set(documentIds)];
590
- const revisions = await Promise.all(unique.map((documentId) => this.operationStore.getRevisions(documentId, "main", signal)));
591
- const taken = /* @__PURE__ */ new Set();
592
- for (let i = 0; i < unique.length; i++) if (Object.keys(revisions[i].revision).length > 0) taken.add(unique[i]);
593
- return taken;
594
- }
595
- async liveIds(documentIds) {
596
- const rows = await this._db.selectFrom("DocumentSnapshot").select(["documentId"]).where("documentId", "in", documentIds).where("isDeleted", "=", false).distinct().execute();
597
- return new Set(rows.map((row) => row.documentId));
598
- }
599
- };
600
- //#endregion
601
- //#region src/shared/consistency-tracker.ts
602
- /**
603
- * Creates a consistency key from documentId, scope, and branch.
604
- */
605
- function makeConsistencyKey(documentId, scope, branch) {
606
- return `${documentId}:${scope}:${branch}`;
607
- }
608
- /**
609
- * Tracks operation indexes for documents and provides read-after-write consistency guarantees.
610
- * Maintains an in-memory map of the latest operation index for each (documentId, scope, branch) tuple.
611
- */
612
- var ConsistencyTracker = class {
613
- state = /* @__PURE__ */ new Map();
614
- waiters = [];
615
- update(coordinates) {
616
- const deduplicated = this.deduplicateCoordinates(coordinates);
617
- for (let i = 0; i < deduplicated.length; i++) {
618
- const coord = deduplicated[i];
619
- const key = makeConsistencyKey(coord.documentId, coord.scope, coord.branch);
620
- const current = this.state.get(key);
621
- if (current === void 0 || coord.operationIndex > current) this.state.set(key, coord.operationIndex);
622
- }
623
- this.checkWaiters();
624
- }
625
- getLatest(key) {
626
- return this.state.get(key);
627
- }
628
- waitFor(coordinates, timeoutMs, signal) {
629
- if (signal?.aborted) return Promise.reject(/* @__PURE__ */ new Error("Operation aborted"));
630
- if (this.areCoordinatesSatisfied(coordinates)) return Promise.resolve();
631
- return new Promise((resolve, reject) => {
632
- const waiter = {
633
- coordinates,
634
- resolve,
635
- reject,
636
- signal
637
- };
638
- if (timeoutMs !== void 0) waiter.timeoutId = setTimeout(() => {
639
- this.removeWaiter(waiter);
640
- reject(/* @__PURE__ */ new Error(`Consistency wait timed out after ${timeoutMs}ms`));
641
- }, timeoutMs);
642
- if (signal) {
643
- const abortHandler = () => {
644
- this.removeWaiter(waiter);
645
- reject(/* @__PURE__ */ new Error("Operation aborted"));
646
- };
647
- signal.addEventListener("abort", abortHandler, { once: true });
648
- }
649
- this.waiters.push(waiter);
650
- });
651
- }
652
- serialize() {
653
- return Array.from(this.state.entries());
654
- }
655
- hydrate(entries) {
656
- this.state.clear();
657
- for (const [key, index] of entries) this.state.set(key, index);
658
- }
659
- deduplicateCoordinates(coordinates) {
660
- const map = /* @__PURE__ */ new Map();
661
- for (let i = 0; i < coordinates.length; i++) {
662
- const coord = coordinates[i];
663
- const key = makeConsistencyKey(coord.documentId, coord.scope, coord.branch);
664
- const existing = map.get(key);
665
- if (!existing || coord.operationIndex > existing.operationIndex) map.set(key, coord);
666
- }
667
- return Array.from(map.values());
668
- }
669
- areCoordinatesSatisfied(coordinates) {
670
- for (let i = 0; i < coordinates.length; i++) {
671
- const coord = coordinates[i];
672
- const key = makeConsistencyKey(coord.documentId, coord.scope, coord.branch);
673
- const latest = this.state.get(key);
674
- if (latest === void 0 || latest < coord.operationIndex) return false;
675
- }
676
- return true;
677
- }
678
- checkWaiters() {
679
- const satisfiedWaiters = [];
680
- const unsatisfiedWaiters = [];
681
- for (const waiter of this.waiters) {
682
- if (waiter.signal?.aborted) continue;
683
- if (this.areCoordinatesSatisfied(waiter.coordinates)) satisfiedWaiters.push(waiter);
684
- else unsatisfiedWaiters.push(waiter);
685
- }
686
- this.waiters = unsatisfiedWaiters;
687
- for (const waiter of satisfiedWaiters) {
688
- if (waiter.timeoutId !== void 0) clearTimeout(waiter.timeoutId);
689
- waiter.resolve();
690
- }
691
- }
692
- removeWaiter(waiter) {
693
- const index = this.waiters.indexOf(waiter);
694
- if (index !== -1) this.waiters.splice(index, 1);
695
- if (waiter.timeoutId !== void 0) clearTimeout(waiter.timeoutId);
696
- }
697
- };
698
- //#endregion
699
- //#region src/shared/collect-all-pages.ts
700
- /**
701
- * Collects all results from a paged result set by following the next() function
702
- * until all pages have been fetched.
703
- */
704
- async function collectAllPages(firstPage, signal) {
705
- const allResults = [...firstPage.results];
706
- let currentPage = firstPage;
707
- while (currentPage.next) {
708
- if (signal?.aborted) throw new Error("Operation aborted");
709
- currentPage = await currentPage.next();
710
- allResults.push(...currentPage.results);
711
- }
712
- return allResults;
713
- }
714
- //#endregion
715
- //#region src/storage/kysely/document-indexer.ts
716
- var KyselyDocumentIndexer = class extends BaseReadModel {
717
- _db;
718
- constructor(db, operationIndex, writeCache, consistencyTracker) {
719
- super(db, operationIndex, writeCache, consistencyTracker, {
720
- readModelId: DOCUMENT_INDEXER_READ_MODEL,
721
- rebuildStateOnInit: false
722
- });
723
- this._db = db;
724
- }
725
- async commitOperations(items) {
726
- await this._db.transaction().execute(async (trx) => {
727
- for (const item of items) {
728
- const { operation } = item;
729
- const actionType = operation.action.type;
730
- if (actionType === "ADD_RELATIONSHIP") await this.handleAddRelationship(trx, operation);
731
- else if (actionType === "REMOVE_RELATIONSHIP") await this.handleRemoveRelationship(trx, operation);
732
- else if (actionType === "UPDATE_RELATIONSHIP") await this.handleUpdateRelationship(trx, operation);
733
- }
734
- });
735
- }
736
- async getOutgoing(documentId, types, paging, consistencyToken, signal) {
737
- if (consistencyToken) await this.waitForConsistency(consistencyToken, void 0, signal);
738
- if (signal?.aborted) throw new Error("Operation aborted");
739
- const startIndex = paging?.cursor ? parseInt(paging.cursor) : 0;
740
- const limit = paging?.limit || 100;
741
- let query = this._db.selectFrom("DocumentRelationship").selectAll().where("sourceId", "=", documentId);
742
- if (types && types.length > 0) query = query.where("relationshipType", "in", types);
743
- const rows = await query.orderBy("createdAt", "asc").orderBy("id", "asc").offset(startIndex).limit(limit + 1).execute();
744
- const hasMore = rows.length > limit;
745
- const results = hasMore ? rows.slice(0, limit) : rows;
746
- const nextCursor = hasMore ? String(startIndex + limit) : void 0;
747
- return {
748
- results: results.map((row) => ({
749
- sourceId: row.sourceId,
750
- targetId: row.targetId,
751
- relationshipType: row.relationshipType,
752
- metadata: row.metadata ? row.metadata : void 0,
753
- createdAt: row.createdAt,
754
- updatedAt: row.updatedAt
755
- })),
756
- options: paging || {
757
- cursor: "0",
758
- limit: 100
759
- },
760
- nextCursor,
761
- next: hasMore ? () => this.getOutgoing(documentId, types, {
762
- cursor: nextCursor,
763
- limit
764
- }, consistencyToken, signal) : void 0
765
- };
766
- }
767
- async getIncoming(documentId, types, paging, consistencyToken, signal) {
768
- if (consistencyToken) await this.waitForConsistency(consistencyToken, void 0, signal);
769
- if (signal?.aborted) throw new Error("Operation aborted");
770
- const startIndex = paging?.cursor ? parseInt(paging.cursor) : 0;
771
- const limit = paging?.limit || 100;
772
- let query = this._db.selectFrom("DocumentRelationship").selectAll().where("targetId", "=", documentId);
773
- if (types && types.length > 0) query = query.where("relationshipType", "in", types);
774
- const rows = await query.orderBy("createdAt", "asc").orderBy("id", "asc").offset(startIndex).limit(limit + 1).execute();
775
- const hasMore = rows.length > limit;
776
- const results = hasMore ? rows.slice(0, limit) : rows;
777
- const nextCursor = hasMore ? String(startIndex + limit) : void 0;
778
- return {
779
- results: results.map((row) => ({
780
- sourceId: row.sourceId,
781
- targetId: row.targetId,
782
- relationshipType: row.relationshipType,
783
- metadata: row.metadata ? row.metadata : void 0,
784
- createdAt: row.createdAt,
785
- updatedAt: row.updatedAt
786
- })),
787
- options: paging || {
788
- cursor: "0",
789
- limit: 100
790
- },
791
- nextCursor,
792
- next: hasMore ? () => this.getIncoming(documentId, types, {
793
- cursor: nextCursor,
794
- limit
795
- }, consistencyToken, signal) : void 0
796
- };
797
- }
798
- async getOrphanedChildren(parentIds, types, signal) {
799
- if (parentIds.length === 0) return [];
800
- if (signal?.aborted) throw new Error("Operation aborted");
801
- let query = this._db.selectFrom("DocumentRelationship as r").select("r.targetId").distinct().where("r.sourceId", "in", parentIds).where((eb) => eb.not(eb.exists(eb.selectFrom("DocumentRelationship as other").select("other.id").whereRef("other.targetId", "=", "r.targetId").where("other.sourceId", "not in", parentIds))));
802
- if (types && types.length > 0) query = query.where("r.relationshipType", "in", types);
803
- return (await query.execute()).map((row) => row.targetId);
804
- }
805
- async hasRelationship(sourceId, targetId, types, consistencyToken, signal) {
806
- if (consistencyToken) await this.waitForConsistency(consistencyToken, void 0, signal);
807
- if (signal?.aborted) throw new Error("Operation aborted");
808
- let query = this._db.selectFrom("DocumentRelationship").select("id").where("sourceId", "=", sourceId).where("targetId", "=", targetId);
809
- if (types && types.length > 0) query = query.where("relationshipType", "in", types);
810
- return await query.executeTakeFirst() !== void 0;
811
- }
812
- async getUndirectedRelationships(a, b, types, paging, consistencyToken, signal) {
813
- if (consistencyToken) await this.waitForConsistency(consistencyToken, void 0, signal);
814
- if (signal?.aborted) throw new Error("Operation aborted");
815
- const startIndex = paging?.cursor ? parseInt(paging.cursor) : 0;
816
- const limit = paging?.limit || 100;
817
- let query = this._db.selectFrom("DocumentRelationship").selectAll().where((eb) => eb.or([eb.and([eb("sourceId", "=", a), eb("targetId", "=", b)]), eb.and([eb("sourceId", "=", b), eb("targetId", "=", a)])]));
818
- if (types && types.length > 0) query = query.where("relationshipType", "in", types);
819
- const rows = await query.orderBy("createdAt", "asc").orderBy("id", "asc").offset(startIndex).limit(limit + 1).execute();
820
- const hasMore = rows.length > limit;
821
- const results = hasMore ? rows.slice(0, limit) : rows;
822
- const nextCursor = hasMore ? String(startIndex + limit) : void 0;
823
- return {
824
- results: results.map((row) => ({
825
- sourceId: row.sourceId,
826
- targetId: row.targetId,
827
- relationshipType: row.relationshipType,
828
- metadata: row.metadata ? row.metadata : void 0,
829
- createdAt: row.createdAt,
830
- updatedAt: row.updatedAt
831
- })),
832
- options: paging || {
833
- cursor: "0",
834
- limit: 100
835
- },
836
- nextCursor,
837
- next: hasMore ? () => this.getUndirectedRelationships(a, b, types, {
838
- cursor: nextCursor,
839
- limit
840
- }, consistencyToken, signal) : void 0
841
- };
842
- }
843
- async getDirectedRelationships(sourceId, targetId, types, paging, consistencyToken, signal) {
844
- if (consistencyToken) await this.waitForConsistency(consistencyToken, void 0, signal);
845
- if (signal?.aborted) throw new Error("Operation aborted");
846
- const startIndex = paging?.cursor ? parseInt(paging.cursor) : 0;
847
- const limit = paging?.limit || 100;
848
- let query = this._db.selectFrom("DocumentRelationship").selectAll().where("sourceId", "=", sourceId).where("targetId", "=", targetId);
849
- if (types && types.length > 0) query = query.where("relationshipType", "in", types);
850
- const rows = await query.orderBy("createdAt", "asc").orderBy("id", "asc").offset(startIndex).limit(limit + 1).execute();
851
- const hasMore = rows.length > limit;
852
- const results = hasMore ? rows.slice(0, limit) : rows;
853
- const nextCursor = hasMore ? String(startIndex + limit) : void 0;
854
- return {
855
- results: results.map((row) => ({
856
- sourceId: row.sourceId,
857
- targetId: row.targetId,
858
- relationshipType: row.relationshipType,
859
- metadata: row.metadata ? row.metadata : void 0,
860
- createdAt: row.createdAt,
861
- updatedAt: row.updatedAt
862
- })),
863
- options: paging || {
864
- cursor: "0",
865
- limit: 100
866
- },
867
- nextCursor,
868
- next: hasMore ? () => this.getDirectedRelationships(sourceId, targetId, types, {
869
- cursor: nextCursor,
870
- limit
871
- }, consistencyToken, signal) : void 0
872
- };
873
- }
874
- async findPath(sourceId, targetId, types, consistencyToken, signal) {
875
- if (consistencyToken) await this.waitForConsistency(consistencyToken, void 0, signal);
876
- if (signal?.aborted) throw new Error("Operation aborted");
877
- if (sourceId === targetId) return [sourceId];
878
- const visited = /* @__PURE__ */ new Set();
879
- const queue = [{
880
- id: sourceId,
881
- path: [sourceId]
882
- }];
883
- while (queue.length > 0) {
884
- const current = queue.shift();
885
- if (current.id === targetId) return current.path;
886
- if (visited.has(current.id)) continue;
887
- visited.add(current.id);
888
- const outgoingRelationships = await collectAllPages(await this.getOutgoing(current.id, types, void 0, consistencyToken, signal), signal);
889
- for (const rel of outgoingRelationships) if (!visited.has(rel.targetId)) queue.push({
890
- id: rel.targetId,
891
- path: [...current.path, rel.targetId]
892
- });
893
- }
894
- return null;
895
- }
896
- async findAncestors(documentId, types, consistencyToken, signal) {
897
- if (consistencyToken) await this.waitForConsistency(consistencyToken, void 0, signal);
898
- if (signal?.aborted) throw new Error("Operation aborted");
899
- const nodes = new Set([documentId]);
900
- const edges = [];
901
- const queue = [documentId];
902
- const visited = /* @__PURE__ */ new Set();
903
- while (queue.length > 0) {
904
- const currentId = queue.shift();
905
- if (visited.has(currentId)) continue;
906
- visited.add(currentId);
907
- const incomingRelationships = await collectAllPages(await this.getIncoming(currentId, types, void 0, consistencyToken, signal), signal);
908
- for (const rel of incomingRelationships) {
909
- nodes.add(rel.sourceId);
910
- edges.push({
911
- from: rel.sourceId,
912
- to: rel.targetId,
913
- type: rel.relationshipType
914
- });
915
- if (!visited.has(rel.sourceId)) queue.push(rel.sourceId);
916
- }
917
- }
918
- return {
919
- nodes: Array.from(nodes),
920
- edges
921
- };
922
- }
923
- async getRelationshipTypes(consistencyToken, signal) {
924
- if (consistencyToken) await this.waitForConsistency(consistencyToken, void 0, signal);
925
- if (signal?.aborted) throw new Error("Operation aborted");
926
- return (await this._db.selectFrom("DocumentRelationship").select("relationshipType").distinct().execute()).map((row) => row.relationshipType);
927
- }
928
- async handleAddRelationship(trx, operation) {
929
- const input = operation.action.input;
930
- if (!await trx.selectFrom("Document").select("id").where("id", "=", input.sourceId).executeTakeFirst()) await trx.insertInto("Document").values({ id: input.sourceId }).execute();
931
- if (!await trx.selectFrom("Document").select("id").where("id", "=", input.targetId).executeTakeFirst()) await trx.insertInto("Document").values({ id: input.targetId }).execute();
932
- if (!await trx.selectFrom("DocumentRelationship").select("id").where("sourceId", "=", input.sourceId).where("targetId", "=", input.targetId).where("relationshipType", "=", input.relationshipType).executeTakeFirst()) {
933
- const relationship = {
934
- id: v4(),
935
- sourceId: input.sourceId,
936
- targetId: input.targetId,
937
- relationshipType: input.relationshipType,
938
- metadata: input.metadata || null
939
- };
940
- await trx.insertInto("DocumentRelationship").values(relationship).execute();
941
- }
942
- }
943
- async handleRemoveRelationship(trx, operation) {
944
- const input = operation.action.input;
945
- await trx.deleteFrom("DocumentRelationship").where("sourceId", "=", input.sourceId).where("targetId", "=", input.targetId).where("relationshipType", "=", input.relationshipType).execute();
946
- }
947
- async handleUpdateRelationship(trx, operation) {
948
- const input = operation.action.input;
949
- await trx.updateTable("DocumentRelationship").set({
950
- metadata: input.metadata,
951
- updatedAt: /* @__PURE__ */ new Date()
952
- }).where("sourceId", "=", input.sourceId).where("targetId", "=", input.targetId).where("relationshipType", "=", input.relationshipType).execute();
953
- }
954
- };
955
- //#endregion
956
- export { DOCUMENT_INDEXER_READ_MODEL as a, BaseReadModel as c, KyselyDocumentView as i, ConsistencyTracker as n, DOCUMENT_VIEW_READ_MODEL as o, makeConsistencyKey as r, ReadModelCoordinator as s, KyselyDocumentIndexer as t };
957
-
958
- //# sourceMappingURL=document-indexer-C5Gsa1B3.js.map