@powerhousedao/reactor 6.0.0-dev.252 → 6.0.0-dev.254

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.
package/dist/index.js CHANGED
@@ -55,13 +55,18 @@ function deleteDocumentAction(documentId) {
55
55
  };
56
56
  }
57
57
  /**
58
- * Creates an ADD_RELATIONSHIP action to establish a parent-child relationship.
58
+ * Creates an ADD_RELATIONSHIP action that records a directed edge from
59
+ * `sourceId` to `targetId` with an arbitrary `relationshipType` and optional
60
+ * `metadata`. The edge is opaque to the reactor — consumers (e.g. reactor-drive)
61
+ * define their own type strings such as `"drive/child"` and attach
62
+ * domain-specific metadata.
59
63
  */
60
- function addRelationshipAction(sourceId, targetId, relationshipType = "child") {
64
+ function addRelationshipAction(sourceId, targetId, relationshipType, metadata) {
61
65
  const input = {
62
66
  sourceId,
63
67
  targetId,
64
- relationshipType
68
+ relationshipType,
69
+ ...metadata !== void 0 ? { metadata } : {}
65
70
  };
66
71
  return {
67
72
  id: generateId(),
@@ -72,6 +77,25 @@ function addRelationshipAction(sourceId, targetId, relationshipType = "child") {
72
77
  };
73
78
  }
74
79
  /**
80
+ * Creates an UPDATE_RELATIONSHIP action to replace a relationship's metadata
81
+ * without losing its createdAt ordering.
82
+ */
83
+ function updateRelationshipAction(sourceId, targetId, relationshipType, metadata) {
84
+ const input = {
85
+ sourceId,
86
+ targetId,
87
+ relationshipType,
88
+ metadata
89
+ };
90
+ return {
91
+ id: generateId(),
92
+ type: "UPDATE_RELATIONSHIP",
93
+ scope: "document",
94
+ timestampUtcMs: (/* @__PURE__ */ new Date()).toISOString(),
95
+ input
96
+ };
97
+ }
98
+ /**
75
99
  * Creates a REMOVE_RELATIONSHIP action to remove a parent-child relationship.
76
100
  */
77
101
  function removeRelationshipAction(sourceId, targetId, relationshipType = "child") {
@@ -291,6 +315,44 @@ let JobStatus = /* @__PURE__ */ function(JobStatus) {
291
315
  return JobStatus;
292
316
  }({});
293
317
  //#endregion
318
+ //#region src/shared/utils.ts
319
+ function matchesScope(view = {}, scope) {
320
+ if (view.scopes) return view.scopes.includes(scope);
321
+ return true;
322
+ }
323
+ function yieldToMain() {
324
+ const s = globalThis.scheduler;
325
+ if (s?.yield) return s.yield();
326
+ return new Promise((resolve) => setTimeout(resolve, 0));
327
+ }
328
+ const defaultAbortError = () => /* @__PURE__ */ new Error("Operation aborted");
329
+ function throwIfAborted(signal, makeError = defaultAbortError) {
330
+ if (signal?.aborted) throw makeError();
331
+ }
332
+ /**
333
+ * Validates PagingOptions and returns a normalized offset and limit.
334
+ * Throws if the cursor is not empty and not a non-negative integer, or if
335
+ * limit is less than 1. When `paging` is undefined, returns offset 0 and
336
+ * the caller-supplied `defaultLimit`.
337
+ */
338
+ function parsePagingOptions(paging, defaultLimit) {
339
+ if (paging === void 0) return {
340
+ offset: 0,
341
+ limit: defaultLimit
342
+ };
343
+ if (!Number.isInteger(paging.limit) || paging.limit < 1) throw new Error(`Invalid paging limit: ${String(paging.limit)} (must be an integer >= 1)`);
344
+ if (paging.cursor === "") return {
345
+ offset: 0,
346
+ limit: paging.limit
347
+ };
348
+ const parsed = Number(paging.cursor);
349
+ if (!Number.isInteger(parsed) || parsed < 0) throw new Error(`Invalid paging cursor: ${JSON.stringify(paging.cursor)} (must be empty or a non-negative integer)`);
350
+ return {
351
+ offset: parsed,
352
+ limit: paging.limit
353
+ };
354
+ }
355
+ //#endregion
294
356
  //#region src/client/drive-client.ts
295
357
  /**
296
358
  * Implementation of {@link IDriveClient}.
@@ -460,11 +522,22 @@ var DriveClient = class {
460
522
  if (!node) throw new Error(`Node ${nodeId} not found in drive ${driveIdentifier}`);
461
523
  return node;
462
524
  }
463
- async listNodes(driveIdentifier, parentFolder, signal) {
464
- this.logger.verbose("drives.listNodes(@driveIdentifier, @parentFolder)", driveIdentifier, parentFolder);
465
- const nodes = (await this.client.get(driveIdentifier, void 0, signal)).state.global.nodes;
466
- if (parentFolder === void 0) return [...nodes];
467
- return nodes.filter((n) => (n.parentFolder ?? null) === parentFolder);
525
+ async listNodes(driveIdentifier, parentFolder, paging, signal) {
526
+ this.logger.verbose("drives.listNodes(@driveIdentifier, @parentFolder, @paging)", driveIdentifier, parentFolder, paging);
527
+ const allNodes = (await this.client.get(driveIdentifier, void 0, signal)).state.global.nodes;
528
+ const filtered = parentFolder === void 0 ? [...allNodes] : allNodes.filter((n) => (n.parentFolder ?? null) === parentFolder);
529
+ const { offset: startIndex, limit } = parsePagingOptions(paging, filtered.length);
530
+ const effective = paging ?? {
531
+ cursor: "",
532
+ limit
533
+ };
534
+ const endIndex = startIndex + limit;
535
+ return {
536
+ results: filtered.slice(startIndex, endIndex),
537
+ options: effective,
538
+ ...endIndex < filtered.length ? { nextCursor: String(endIndex) } : {},
539
+ totalCount: filtered.length
540
+ };
468
541
  }
469
542
  async removeFileNode(driveId, fileId, signal) {
470
543
  const relationshipActions = await signActions([removeRelationshipAction(driveId, fileId, "child")], this.signer, signal);
@@ -924,6 +997,17 @@ var ReactorClient = class {
924
997
  const signedActions = await signActions(actions, this.signer, signal);
925
998
  return this.reactor.execute(documentIdentifier, branch, signedActions, signal);
926
999
  }
1000
+ async executeBatch(request, signal) {
1001
+ this.logger.verbose("executeBatch(@count jobs)", request.jobs.length);
1002
+ const signedJobs = await Promise.all(request.jobs.map(async (job) => ({
1003
+ ...job,
1004
+ actions: await signActions(job.actions, this.signer, signal)
1005
+ })));
1006
+ const batchResult = await this.reactor.executeBatch({ jobs: signedJobs }, signal);
1007
+ const completedJobs = await Promise.all(Object.values(batchResult.jobs).map((job) => this.waitForJob(job, signal)));
1008
+ for (const job of completedJobs) if (job.status === JobStatus.FAILED) throw new Error(job.error?.message);
1009
+ return batchResult;
1010
+ }
927
1011
  /**
928
1012
  * Renames a document and waits for completion
929
1013
  */
@@ -2162,7 +2246,6 @@ var KyselyWriteCache = class KyselyWriteCache {
2162
2246
  startRevision = keyframe.revision;
2163
2247
  documentType = keyframe.document.header.documentType;
2164
2248
  } else {
2165
- document = void 0;
2166
2249
  startRevision = -1;
2167
2250
  const createOpResult = await this.operationStore.getSince(documentId, "document", branch, -1, void 0, {
2168
2251
  cursor: "0",
@@ -2722,28 +2805,17 @@ var SimpleJobExecutorManager = class {
2722
2805
  }
2723
2806
  };
2724
2807
  //#endregion
2725
- //#region src/shared/utils.ts
2726
- function matchesScope(view = {}, scope) {
2727
- if (view.scopes) return view.scopes.includes(scope);
2728
- return true;
2729
- }
2730
- function yieldToMain() {
2731
- const s = globalThis.scheduler;
2732
- if (s?.yield) return s.yield();
2733
- return new Promise((resolve) => setTimeout(resolve, 0));
2734
- }
2735
- const defaultAbortError = () => /* @__PURE__ */ new Error("Operation aborted");
2736
- function throwIfAborted(signal, makeError = defaultAbortError) {
2737
- if (signal?.aborted) throw makeError();
2738
- }
2739
- //#endregion
2740
2808
  //#region src/utils/reshuffle.ts
2741
2809
  const STRICT_ORDER_ACTION_TYPES = new Set([
2742
2810
  "CREATE_DOCUMENT",
2743
2811
  "DELETE_DOCUMENT",
2744
2812
  "UPGRADE_DOCUMENT",
2745
2813
  "ADD_RELATIONSHIP",
2746
- "REMOVE_RELATIONSHIP"
2814
+ "REMOVE_RELATIONSHIP",
2815
+ "UPDATE_RELATIONSHIP",
2816
+ "ADD_FOLDER",
2817
+ "UPDATE_FOLDER",
2818
+ "REMOVE_FOLDER"
2747
2819
  ]);
2748
2820
  /**
2749
2821
  * Reshuffles operations by timestamp, then applies deterministic tie-breaking.
@@ -2790,9 +2862,10 @@ function driveCollectionId(branch, driveId) {
2790
2862
  //#endregion
2791
2863
  //#region src/executor/document-action-handler.ts
2792
2864
  var DocumentActionHandler = class {
2793
- constructor(registry, logger) {
2865
+ constructor(registry, logger, driveContainerTypes) {
2794
2866
  this.registry = registry;
2795
2867
  this.logger = logger;
2868
+ this.driveContainerTypes = driveContainerTypes;
2796
2869
  }
2797
2870
  async execute(job, action, startTime, indexTxn, stores, skip = 0, sourceRemote = "", signal) {
2798
2871
  switch (action.type) {
@@ -2801,6 +2874,7 @@ var DocumentActionHandler = class {
2801
2874
  case "UPGRADE_DOCUMENT": return this.executeUpgrade(job, action, startTime, indexTxn, stores, skip, sourceRemote, signal);
2802
2875
  case "ADD_RELATIONSHIP": return this.executeAddRelationship(job, action, startTime, indexTxn, stores, sourceRemote, signal);
2803
2876
  case "REMOVE_RELATIONSHIP": return this.executeRemoveRelationship(job, action, startTime, indexTxn, stores, sourceRemote, signal);
2877
+ case "UPDATE_RELATIONSHIP": return this.executeUpdateRelationship(job, action, startTime, indexTxn, stores, sourceRemote, signal);
2804
2878
  default: return buildErrorResult(job, /* @__PURE__ */ new Error(`Unknown document action type: ${action.type}`), startTime);
2805
2879
  }
2806
2880
  }
@@ -2825,6 +2899,10 @@ var DocumentActionHandler = class {
2825
2899
  const writeError = await this.writeOperationToStore(document.header.id, document.header.documentType, job.scope, job.branch, operation, job, startTime, stores, signal);
2826
2900
  if (writeError !== null) return writeError;
2827
2901
  updateDocumentRevision(document, job.scope, operation.index);
2902
+ document.operations = {
2903
+ ...document.operations,
2904
+ [job.scope]: [...document.operations[job.scope] ?? [], operation]
2905
+ };
2828
2906
  stores.writeCache.putState(document.header.id, job.scope, job.branch, operation.index, document);
2829
2907
  indexTxn.write([{
2830
2908
  ...operation,
@@ -2834,7 +2912,7 @@ var DocumentActionHandler = class {
2834
2912
  scope: job.scope,
2835
2913
  sourceRemote
2836
2914
  }]);
2837
- if (document.header.documentType === "powerhouse/document-drive") {
2915
+ if (this.driveContainerTypes.has(document.header.documentType)) {
2838
2916
  const collectionId = driveCollectionId(job.branch, document.header.id);
2839
2917
  indexTxn.createCollection(collectionId);
2840
2918
  indexTxn.addToCollection(collectionId, document.header.id);
@@ -2872,6 +2950,10 @@ var DocumentActionHandler = class {
2872
2950
  const writeError = await this.writeOperationToStore(documentId, document.header.documentType, job.scope, job.branch, operation, job, startTime, stores, signal);
2873
2951
  if (writeError !== null) return writeError;
2874
2952
  updateDocumentRevision(document, job.scope, operation.index);
2953
+ document.operations = {
2954
+ ...document.operations,
2955
+ [job.scope]: [...document.operations[job.scope] ?? [], operation]
2956
+ };
2875
2957
  stores.writeCache.putState(documentId, job.scope, job.branch, operation.index, document);
2876
2958
  indexTxn.write([{
2877
2959
  ...operation,
@@ -2934,6 +3016,10 @@ var DocumentActionHandler = class {
2934
3016
  const writeError = await this.writeOperationToStore(documentId, document.header.documentType, job.scope, job.branch, operation, job, startTime, stores, signal);
2935
3017
  if (writeError !== null) return writeError;
2936
3018
  updateDocumentRevision(document, job.scope, operation.index);
3019
+ document.operations = {
3020
+ ...document.operations,
3021
+ [job.scope]: [...document.operations[job.scope] ?? [], operation]
3022
+ };
2937
3023
  stores.writeCache.putState(documentId, job.scope, job.branch, operation.index, document);
2938
3024
  indexTxn.write([{
2939
3025
  ...operation,
@@ -2950,66 +3036,40 @@ var DocumentActionHandler = class {
2950
3036
  });
2951
3037
  return buildSuccessResult(job, operation, documentId, document.header.documentType, resultingState, startTime);
2952
3038
  }
2953
- async executeAddRelationship(job, action, startTime, indexTxn, stores, sourceRemote = "", signal) {
2954
- if (job.scope !== "document") return buildErrorResult(job, /* @__PURE__ */ new Error(`ADD_RELATIONSHIP must be in "document" scope, got "${job.scope}"`), startTime);
2955
- const input = action.input;
2956
- if (!input.sourceId || !input.targetId || !input.relationshipType) return buildErrorResult(job, /* @__PURE__ */ new Error("ADD_RELATIONSHIP action requires sourceId, targetId, and relationshipType in input"), startTime);
2957
- if (input.sourceId === input.targetId) return buildErrorResult(job, /* @__PURE__ */ new Error("ADD_RELATIONSHIP: sourceId and targetId cannot be the same (self-relationships not allowed)"), startTime);
2958
- let sourceDoc;
2959
- try {
2960
- sourceDoc = await stores.writeCache.getState(input.sourceId, "document", job.branch, void 0, signal);
2961
- } catch (error) {
2962
- return buildErrorResult(job, /* @__PURE__ */ new Error(`ADD_RELATIONSHIP: source document ${input.sourceId} not found: ${error instanceof Error ? error.message : String(error)}`), startTime);
2963
- }
2964
- const operation = createOperation(action, getNextIndexForScope(sourceDoc, job.scope), 0, {
2965
- documentId: input.sourceId,
2966
- scope: job.scope,
2967
- branch: job.branch
3039
+ executeAddRelationship(job, action, startTime, indexTxn, stores, sourceRemote = "", signal) {
3040
+ return this.withRelationshipAction("ADD_RELATIONSHIP", job, action, startTime, indexTxn, stores, sourceRemote, signal, (input) => input.sourceId === input.targetId ? /* @__PURE__ */ new Error("ADD_RELATIONSHIP: sourceId and targetId cannot be the same (self-relationships not allowed)") : null, ({ indexTxn: txn, stores: s, sourceDoc, input, job: j }) => {
3041
+ if (this.driveContainerTypes.has(sourceDoc.header.documentType)) {
3042
+ const collectionId = driveCollectionId(j.branch, input.sourceId);
3043
+ txn.addToCollection(collectionId, input.targetId);
3044
+ s.collectionMembershipCache.invalidate(input.targetId);
3045
+ }
2968
3046
  });
2969
- const writeError = await this.writeOperationToStore(input.sourceId, sourceDoc.header.documentType, job.scope, job.branch, operation, job, startTime, stores, signal);
2970
- if (writeError !== null) return writeError;
2971
- sourceDoc.header.lastModifiedAtUtcIso = operation.timestampUtcMs || (/* @__PURE__ */ new Date()).toISOString();
2972
- updateDocumentRevision(sourceDoc, job.scope, operation.index);
2973
- sourceDoc.operations = {
2974
- ...sourceDoc.operations,
2975
- [job.scope]: [...sourceDoc.operations[job.scope] ?? [], operation]
2976
- };
2977
- const scopeState = sourceDoc.state[job.scope];
2978
- const resultingStateObj = {
2979
- header: structuredClone(sourceDoc.header),
2980
- [job.scope]: scopeState === void 0 ? {} : structuredClone(scopeState)
2981
- };
2982
- const resultingState = JSON.stringify(resultingStateObj);
2983
- stores.writeCache.putState(input.sourceId, job.scope, job.branch, operation.index, sourceDoc);
2984
- indexTxn.write([{
2985
- ...operation,
2986
- documentId: input.sourceId,
2987
- documentType: sourceDoc.header.documentType,
2988
- branch: job.branch,
2989
- scope: job.scope,
2990
- sourceRemote
2991
- }]);
2992
- if (sourceDoc.header.documentType === "powerhouse/document-drive") {
2993
- const collectionId = driveCollectionId(job.branch, input.sourceId);
2994
- indexTxn.addToCollection(collectionId, input.targetId);
2995
- stores.collectionMembershipCache.invalidate(input.targetId);
2996
- }
2997
- stores.documentMetaCache.putDocumentMeta(input.sourceId, job.branch, {
2998
- state: sourceDoc.state.document,
2999
- documentType: sourceDoc.header.documentType,
3000
- documentScopeRevision: operation.index + 1
3047
+ }
3048
+ executeRemoveRelationship(job, action, startTime, indexTxn, stores, sourceRemote = "", signal) {
3049
+ return this.withRelationshipAction("REMOVE_RELATIONSHIP", job, action, startTime, indexTxn, stores, sourceRemote, signal, null, ({ indexTxn: txn, stores: s, sourceDoc, input, job: j }) => {
3050
+ if (this.driveContainerTypes.has(sourceDoc.header.documentType)) {
3051
+ const collectionId = driveCollectionId(j.branch, input.sourceId);
3052
+ txn.removeFromCollection(collectionId, input.targetId);
3053
+ s.collectionMembershipCache.invalidate(input.targetId);
3054
+ }
3001
3055
  });
3002
- return buildSuccessResult(job, operation, input.sourceId, sourceDoc.header.documentType, resultingState, startTime);
3003
3056
  }
3004
- async executeRemoveRelationship(job, action, startTime, indexTxn, stores, sourceRemote = "", signal) {
3005
- if (job.scope !== "document") return buildErrorResult(job, /* @__PURE__ */ new Error(`REMOVE_RELATIONSHIP must be in "document" scope, got "${job.scope}"`), startTime);
3057
+ executeUpdateRelationship(job, action, startTime, indexTxn, stores, sourceRemote = "", signal) {
3058
+ return this.withRelationshipAction("UPDATE_RELATIONSHIP", job, action, startTime, indexTxn, stores, sourceRemote, signal, null, null);
3059
+ }
3060
+ async withRelationshipAction(actionTypeName, job, action, startTime, indexTxn, stores, sourceRemote, signal, preValidate, postWrite) {
3061
+ if (job.scope !== "document") return buildErrorResult(job, /* @__PURE__ */ new Error(`${actionTypeName} must be in "document" scope, got "${job.scope}"`), startTime);
3006
3062
  const input = action.input;
3007
- if (!input.sourceId || !input.targetId || !input.relationshipType) return buildErrorResult(job, /* @__PURE__ */ new Error("REMOVE_RELATIONSHIP action requires sourceId, targetId, and relationshipType in input"), startTime);
3063
+ if (!input.sourceId || !input.targetId || !input.relationshipType) return buildErrorResult(job, /* @__PURE__ */ new Error(`${actionTypeName} action requires sourceId, targetId, and relationshipType in input`), startTime);
3064
+ if (preValidate !== null) {
3065
+ const validationError = preValidate(input);
3066
+ if (validationError !== null) return buildErrorResult(job, validationError, startTime);
3067
+ }
3008
3068
  let sourceDoc;
3009
3069
  try {
3010
3070
  sourceDoc = await stores.writeCache.getState(input.sourceId, "document", job.branch, void 0, signal);
3011
3071
  } catch (error) {
3012
- return buildErrorResult(job, /* @__PURE__ */ new Error(`REMOVE_RELATIONSHIP: source document ${input.sourceId} not found: ${error instanceof Error ? error.message : String(error)}`), startTime);
3072
+ return buildErrorResult(job, /* @__PURE__ */ new Error(`${actionTypeName}: source document ${input.sourceId} not found: ${error instanceof Error ? error.message : String(error)}`), startTime);
3013
3073
  }
3014
3074
  const operation = createOperation(action, getNextIndexForScope(sourceDoc, job.scope), 0, {
3015
3075
  documentId: input.sourceId,
@@ -3039,11 +3099,13 @@ var DocumentActionHandler = class {
3039
3099
  scope: job.scope,
3040
3100
  sourceRemote
3041
3101
  }]);
3042
- if (sourceDoc.header.documentType === "powerhouse/document-drive") {
3043
- const collectionId = driveCollectionId(job.branch, input.sourceId);
3044
- indexTxn.removeFromCollection(collectionId, input.targetId);
3045
- stores.collectionMembershipCache.invalidate(input.targetId);
3046
- }
3102
+ if (postWrite !== null) postWrite({
3103
+ indexTxn,
3104
+ stores,
3105
+ sourceDoc,
3106
+ input,
3107
+ job
3108
+ });
3047
3109
  stores.documentMetaCache.putDocumentMeta(input.sourceId, job.branch, {
3048
3110
  state: sourceDoc.state.document,
3049
3111
  documentType: sourceDoc.header.documentType,
@@ -3082,7 +3144,7 @@ var SignatureVerifier = class {
3082
3144
  if (!signer) continue;
3083
3145
  if (signer.signatures.length === 0) throw new InvalidSignatureError(documentId, `Action ${action.id} has signer but no signatures`);
3084
3146
  const publicKey = signer.app.key;
3085
- let isValid = false;
3147
+ let isValid;
3086
3148
  try {
3087
3149
  const tempOperation = {
3088
3150
  id: deriveOperationId(documentId, action.scope, branch, action.id),
@@ -3108,7 +3170,7 @@ var SignatureVerifier = class {
3108
3170
  if (!signer) continue;
3109
3171
  if (signer.signatures.length === 0) throw new InvalidSignatureError(documentId, `Operation ${operation.id} at index ${operation.index} has signer but no signatures`);
3110
3172
  const publicKey = signer.app.key;
3111
- let isValid = false;
3173
+ let isValid;
3112
3174
  try {
3113
3175
  isValid = await this.verifier(operation, publicKey);
3114
3176
  } catch (error) {
@@ -3132,7 +3194,8 @@ const documentScopeActions = [
3132
3194
  "DELETE_DOCUMENT",
3133
3195
  "UPGRADE_DOCUMENT",
3134
3196
  "ADD_RELATIONSHIP",
3135
- "REMOVE_RELATIONSHIP"
3197
+ "REMOVE_RELATIONSHIP",
3198
+ "UPDATE_RELATIONSHIP"
3136
3199
  ];
3137
3200
  /**
3138
3201
  * Simple job executor that processes a job by applying actions through document model reducers.
@@ -3142,7 +3205,7 @@ var SimpleJobExecutor = class {
3142
3205
  signatureVerifierModule;
3143
3206
  documentActionHandler;
3144
3207
  executionScope;
3145
- constructor(logger, registry, operationStore, eventBus, writeCache, operationIndex, documentMetaCache, collectionMembershipCache, config, signatureVerifier, executionScope) {
3208
+ constructor(logger, registry, operationStore, eventBus, writeCache, operationIndex, documentMetaCache, collectionMembershipCache, driveContainerTypes, config, signatureVerifier, executionScope) {
3146
3209
  this.logger = logger;
3147
3210
  this.registry = registry;
3148
3211
  this.operationStore = operationStore;
@@ -3151,6 +3214,7 @@ var SimpleJobExecutor = class {
3151
3214
  this.operationIndex = operationIndex;
3152
3215
  this.documentMetaCache = documentMetaCache;
3153
3216
  this.collectionMembershipCache = collectionMembershipCache;
3217
+ this.driveContainerTypes = driveContainerTypes;
3154
3218
  this.config = {
3155
3219
  maxSkipThreshold: config.maxSkipThreshold ?? MAX_SKIP_THRESHOLD,
3156
3220
  maxConcurrency: config.maxConcurrency ?? 1,
@@ -3160,7 +3224,7 @@ var SimpleJobExecutor = class {
3160
3224
  yieldDeadlineMs: config.yieldDeadlineMs ?? 50
3161
3225
  };
3162
3226
  this.signatureVerifierModule = new SignatureVerifier(signatureVerifier);
3163
- this.documentActionHandler = new DocumentActionHandler(registry, logger);
3227
+ this.documentActionHandler = new DocumentActionHandler(registry, logger, driveContainerTypes);
3164
3228
  this.executionScope = executionScope ?? new DefaultExecutionScope(operationStore, operationIndex, writeCache, documentMetaCache, collectionMembershipCache);
3165
3229
  }
3166
3230
  /**
@@ -3395,7 +3459,7 @@ var SimpleJobExecutor = class {
3395
3459
  } catch {}
3396
3460
  if (docMeta?.state.isDeleted) return buildErrorResult(job, new DocumentDeletedError(job.documentId, docMeta.state.deletedAtUtcIso), startTime);
3397
3461
  const scope = job.scope;
3398
- let latestRevision = 0;
3462
+ let latestRevision;
3399
3463
  try {
3400
3464
  latestRevision = (await stores.operationStore.getRevisions(job.documentId, job.branch, signal)).revision[scope] ?? 0;
3401
3465
  } catch {
@@ -3414,7 +3478,7 @@ var SimpleJobExecutor = class {
3414
3478
  const ts = operation.timestampUtcMs || "";
3415
3479
  if (ts < minIncomingTimestamp) minIncomingTimestamp = ts;
3416
3480
  }
3417
- let conflictingOps = [];
3481
+ let conflictingOps;
3418
3482
  try {
3419
3483
  conflictingOps = (await stores.operationStore.getConflicting(job.documentId, scope, job.branch, minIncomingTimestamp, void 0, signal)).results;
3420
3484
  } catch {
@@ -3429,7 +3493,9 @@ var SimpleJobExecutor = class {
3429
3493
  allOpsFromMinConflictingIndex = conflictingOps;
3430
3494
  }
3431
3495
  }
3496
+ const incomingActionIds = new Set(job.operations.map((op) => op.action.id));
3432
3497
  const nonSupersededOps = conflictingOps.filter((op) => {
3498
+ if (op.index < minIncomingIndex && !incomingActionIds.has(op.action.id)) return false;
3433
3499
  for (const laterOp of allOpsFromMinConflictingIndex) if (laterOp.index > op.index && laterOp.skip > 0) {
3434
3500
  if (laterOp.index - laterOp.skip <= op.index) return false;
3435
3501
  }
@@ -3467,7 +3533,10 @@ var SimpleJobExecutor = class {
3467
3533
  operationsWithContext: [],
3468
3534
  duration: Date.now() - startTime
3469
3535
  };
3470
- const reshuffledOperations = reshuffleByTimestamp({
3536
+ const reshuffledOperations = existingOpsToReshuffle.length === 0 && skipCount === 0 ? incomingOpsToApply.slice().sort((a, b) => a.index - b.index).map((operation, i) => ({
3537
+ ...operation,
3538
+ index: latestRevision + i
3539
+ })) : reshuffleByTimestamp({
3471
3540
  index: latestRevision,
3472
3541
  skip: skipCount
3473
3542
  }, existingOpsToReshuffle, incomingOpsToApply.map((operation) => ({
@@ -3736,10 +3805,6 @@ var BaseReadModel = class {
3736
3805
  };
3737
3806
  //#endregion
3738
3807
  //#region src/processors/utils.ts
3739
- const DRIVE_DOCUMENT_TYPE = "powerhouse/document-drive";
3740
- function isDriveCreation(op) {
3741
- return op.operation.action.type === "CREATE_DOCUMENT" && op.context.documentType === "powerhouse/document-drive";
3742
- }
3743
3808
  function isDriveDeletion(op) {
3744
3809
  return op.operation.action.type === "DELETE_DOCUMENT";
3745
3810
  }
@@ -3750,10 +3815,10 @@ function extractDriveHeader(op) {
3750
3815
  function extractDeletedDocumentId(op) {
3751
3816
  return op.operation.action.input.documentId ?? op.context.documentId;
3752
3817
  }
3753
- function createMinimalDriveHeader(driveId) {
3818
+ function createMinimalDriveHeader(driveId, documentType) {
3754
3819
  return {
3755
3820
  id: driveId,
3756
- documentType: DRIVE_DOCUMENT_TYPE,
3821
+ documentType,
3757
3822
  sig: {
3758
3823
  publicKey: {},
3759
3824
  nonce: ""
@@ -3798,15 +3863,17 @@ var ProcessorManager = class extends BaseReadModel {
3798
3863
  factoryRegistry = /* @__PURE__ */ new Map();
3799
3864
  processorsByDrive = /* @__PURE__ */ new Map();
3800
3865
  factoryToProcessors = /* @__PURE__ */ new Map();
3801
- knownDriveIds = /* @__PURE__ */ new Set();
3866
+ knownDrives = /* @__PURE__ */ new Map();
3802
3867
  cursorCache = /* @__PURE__ */ new Map();
3803
3868
  logger;
3804
- constructor(db, operationIndex, writeCache, consistencyTracker, logger) {
3869
+ driveContainerTypes;
3870
+ constructor(db, operationIndex, writeCache, consistencyTracker, logger, driveContainerTypes) {
3805
3871
  super(db, operationIndex, writeCache, consistencyTracker, {
3806
3872
  readModelId: "processor-manager",
3807
3873
  rebuildStateOnInit: true
3808
3874
  });
3809
3875
  this.logger = logger;
3876
+ this.driveContainerTypes = driveContainerTypes;
3810
3877
  }
3811
3878
  async init() {
3812
3879
  await super.init();
@@ -3822,8 +3889,8 @@ var ProcessorManager = class extends BaseReadModel {
3822
3889
  if (this.factoryRegistry.has(identifier)) await this.unregisterFactory(identifier);
3823
3890
  this.factoryRegistry.set(identifier, factory);
3824
3891
  this.factoryToProcessors.set(identifier, /* @__PURE__ */ new Map());
3825
- for (const driveId of this.knownDriveIds) {
3826
- const driveHeader = createMinimalDriveHeader(driveId);
3892
+ for (const [driveId, documentType] of this.knownDrives) {
3893
+ const driveHeader = createMinimalDriveHeader(driveId, documentType);
3827
3894
  await this.createProcessorsForDrive(driveId, identifier, factory, driveHeader);
3828
3895
  }
3829
3896
  }
@@ -3854,34 +3921,37 @@ var ProcessorManager = class extends BaseReadModel {
3854
3921
  }
3855
3922
  async detectAndRegisterNewDrives(operations) {
3856
3923
  for (const op of operations) {
3857
- if (!isDriveCreation(op)) continue;
3924
+ if (!this.isDriveCreation(op)) continue;
3858
3925
  const driveId = op.context.documentId;
3859
- if (this.knownDriveIds.has(driveId)) continue;
3860
- this.knownDriveIds.add(driveId);
3926
+ if (this.knownDrives.has(driveId)) continue;
3927
+ this.knownDrives.set(driveId, op.context.documentType);
3861
3928
  const driveHeader = extractDriveHeader(op);
3862
3929
  if (!driveHeader) continue;
3863
3930
  for (const [identifier, factory] of this.factoryRegistry) await this.createProcessorsForDrive(driveId, identifier, factory, driveHeader);
3864
3931
  }
3865
3932
  }
3933
+ isDriveCreation(op) {
3934
+ return op.operation.action.type === "CREATE_DOCUMENT" && this.driveContainerTypes.has(op.context.documentType);
3935
+ }
3866
3936
  async detectAndCleanupDeletedDrives(operations) {
3867
3937
  for (const op of operations) {
3868
3938
  if (!isDriveDeletion(op)) continue;
3869
3939
  const driveId = extractDeletedDocumentId(op);
3870
- if (!driveId || !this.knownDriveIds.has(driveId)) continue;
3940
+ if (!driveId || !this.knownDrives.has(driveId)) continue;
3871
3941
  if (!this.isDeletedDocumentADrive(driveId)) continue;
3872
3942
  await this.cleanupDriveProcessors(driveId);
3873
- this.knownDriveIds.delete(driveId);
3943
+ this.knownDrives.delete(driveId);
3874
3944
  }
3875
3945
  }
3876
3946
  async discoverExistingDrives() {
3877
- const drives = await this.db.selectFrom("DocumentSnapshot").select("documentId").where("documentType", "=", DRIVE_DOCUMENT_TYPE).where("isDeleted", "=", false).execute();
3878
- for (const drive of drives) this.knownDriveIds.add(drive.documentId);
3947
+ const drives = await this.db.selectFrom("DocumentSnapshot").select(["documentId", "documentType"]).where("documentType", "in", [...this.driveContainerTypes]).where("isDeleted", "=", false).execute();
3948
+ for (const drive of drives) this.knownDrives.set(drive.documentId, drive.documentType);
3879
3949
  }
3880
3950
  isDeletedDocumentADrive(documentId) {
3881
- return this.knownDriveIds.has(documentId);
3951
+ return this.knownDrives.has(documentId);
3882
3952
  }
3883
3953
  async createProcessorsForDrive(driveId, identifier, factory, driveHeader) {
3884
- let records = [];
3954
+ let records;
3885
3955
  try {
3886
3956
  records = await factory(driveHeader);
3887
3957
  } catch (error) {
@@ -4550,7 +4620,7 @@ var KyselyDocumentView = class extends BaseReadModel {
4550
4620
  const { documentId, scope, branch, documentType, resultingState } = context;
4551
4621
  const { index, hash } = operation;
4552
4622
  if (!resultingState) throw new Error(`Missing resultingState in context for operation ${operation.id || "unknown"}. IDocumentView requires resultingState from upstream - it does not rebuild documents.`);
4553
- let fullState = {};
4623
+ let fullState;
4554
4624
  try {
4555
4625
  fullState = JSON.parse(resultingState);
4556
4626
  } catch (error) {
@@ -5144,6 +5214,7 @@ var KyselyDocumentIndexer = class extends BaseReadModel {
5144
5214
  const actionType = operation.action.type;
5145
5215
  if (actionType === "ADD_RELATIONSHIP") await this.handleAddRelationship(trx, operation);
5146
5216
  else if (actionType === "REMOVE_RELATIONSHIP") await this.handleRemoveRelationship(trx, operation);
5217
+ else if (actionType === "UPDATE_RELATIONSHIP") await this.handleUpdateRelationship(trx, operation);
5147
5218
  }
5148
5219
  });
5149
5220
  }
@@ -5358,6 +5429,13 @@ var KyselyDocumentIndexer = class extends BaseReadModel {
5358
5429
  const input = operation.action.input;
5359
5430
  await trx.deleteFrom("DocumentRelationship").where("sourceId", "=", input.sourceId).where("targetId", "=", input.targetId).where("relationshipType", "=", input.relationshipType).execute();
5360
5431
  }
5432
+ async handleUpdateRelationship(trx, operation) {
5433
+ const input = operation.action.input;
5434
+ await trx.updateTable("DocumentRelationship").set({
5435
+ metadata: input.metadata,
5436
+ updatedAt: /* @__PURE__ */ new Date()
5437
+ }).where("sourceId", "=", input.sourceId).where("targetId", "=", input.targetId).where("relationshipType", "=", input.relationshipType).execute();
5438
+ }
5361
5439
  };
5362
5440
  //#endregion
5363
5441
  //#region src/storage/kysely/keyframe-store.ts
@@ -6695,25 +6773,6 @@ function consolidateSyncOperations(syncOps) {
6695
6773
  }
6696
6774
  return result;
6697
6775
  }
6698
- function mergeCollectionMemberships(events) {
6699
- const mergedMemberships = {};
6700
- for (const event of events) {
6701
- if (event.collectionMemberships) for (const [docId, collections] of Object.entries(event.collectionMemberships)) {
6702
- if (!(docId in mergedMemberships)) mergedMemberships[docId] = [];
6703
- for (const c of collections) if (!mergedMemberships[docId].includes(c)) mergedMemberships[docId].push(c);
6704
- }
6705
- for (const op of event.operations) {
6706
- const action = op.operation.action;
6707
- if (action.type !== "ADD_RELATIONSHIP") continue;
6708
- const input = action.input;
6709
- if (!input?.sourceId || !input.targetId) continue;
6710
- const collectionId = driveCollectionId(op.context.branch, input.sourceId);
6711
- if (!(input.targetId in mergedMemberships)) mergedMemberships[input.targetId] = [];
6712
- if (!mergedMemberships[input.targetId].includes(collectionId)) mergedMemberships[input.targetId].push(collectionId);
6713
- }
6714
- }
6715
- return mergedMemberships;
6716
- }
6717
6776
  /**
6718
6777
  * Chunks sync operations into batches that respect dependency-connected
6719
6778
  * components. SyncOps linked by jobDependencies are kept in the same chunk.
@@ -8042,12 +8101,14 @@ var KyselySyncRemoteStorage = class {
8042
8101
  //#region src/sync/batch-aggregator.ts
8043
8102
  var BatchAggregator = class {
8044
8103
  logger;
8104
+ driveContainerTypes;
8045
8105
  onBatchReady;
8046
8106
  queue = [];
8047
8107
  processing = false;
8048
8108
  pendingBatches = /* @__PURE__ */ new Map();
8049
- constructor(logger, onBatchReady) {
8109
+ constructor(logger, driveContainerTypes, onBatchReady) {
8050
8110
  this.logger = logger;
8111
+ this.driveContainerTypes = driveContainerTypes;
8051
8112
  this.onBatchReady = onBatchReady;
8052
8113
  }
8053
8114
  async enqueueWriteReady(event) {
@@ -8106,7 +8167,7 @@ var BatchAggregator = class {
8106
8167
  }
8107
8168
  }
8108
8169
  prepareBatch(events) {
8109
- const collectionMemberships = mergeCollectionMemberships(events);
8170
+ const collectionMemberships = this.mergeCollectionMemberships(events);
8110
8171
  const isBatch = events.length > 1;
8111
8172
  const priorJobIds = [];
8112
8173
  const entries = [];
@@ -8122,6 +8183,26 @@ var BatchAggregator = class {
8122
8183
  entries
8123
8184
  };
8124
8185
  }
8186
+ mergeCollectionMemberships(events) {
8187
+ const mergedMemberships = {};
8188
+ for (const event of events) {
8189
+ if (event.collectionMemberships) for (const [docId, collections] of Object.entries(event.collectionMemberships)) {
8190
+ if (!(docId in mergedMemberships)) mergedMemberships[docId] = [];
8191
+ for (const c of collections) if (!mergedMemberships[docId].includes(c)) mergedMemberships[docId].push(c);
8192
+ }
8193
+ for (const op of event.operations) {
8194
+ const action = op.operation.action;
8195
+ if (action.type !== "ADD_RELATIONSHIP") continue;
8196
+ if (!this.driveContainerTypes.has(op.context.documentType)) continue;
8197
+ const input = action.input;
8198
+ if (!input?.sourceId || !input.targetId) continue;
8199
+ const collectionId = driveCollectionId(op.context.branch, input.sourceId);
8200
+ if (!(input.targetId in mergedMemberships)) mergedMemberships[input.targetId] = [];
8201
+ if (!mergedMemberships[input.targetId].includes(collectionId)) mergedMemberships[input.targetId].push(collectionId);
8202
+ }
8203
+ }
8204
+ return mergedMemberships;
8205
+ }
8125
8206
  };
8126
8207
  //#endregion
8127
8208
  //#region src/sync/sync-awaiter.ts
@@ -8373,7 +8454,7 @@ var SyncManager = class {
8373
8454
  planKeyToJobUuid = /* @__PURE__ */ new Map();
8374
8455
  lastEnqueuedJobIdByKey = /* @__PURE__ */ new Map();
8375
8456
  inboxChunkChain = Promise.resolve();
8376
- constructor(logger, remoteStorage, cursorStorage, deadLetterStorage, channelFactory, operationIndex, reactor, eventBus, config = {}) {
8457
+ constructor(logger, remoteStorage, cursorStorage, deadLetterStorage, channelFactory, operationIndex, reactor, eventBus, driveContainerTypes, config = {}) {
8377
8458
  this.logger = logger;
8378
8459
  this.remoteStorage = remoteStorage;
8379
8460
  this.cursorStorage = cursorStorage;
@@ -8390,7 +8471,7 @@ var SyncManager = class {
8390
8471
  this.awaiter = new JobAwaiter(eventBus, (jobId, signal) => reactor.getJobStatus(jobId, signal));
8391
8472
  this.syncAwaiter = new SyncAwaiter(eventBus);
8392
8473
  this.isShutdown = false;
8393
- this.batchAggregator = new BatchAggregator(logger, (batch) => this.processCompleteBatch(batch));
8474
+ this.batchAggregator = new BatchAggregator(logger, driveContainerTypes, (batch) => this.processCompleteBatch(batch));
8394
8475
  this.syncStatusTracker = new SyncStatusTracker();
8395
8476
  }
8396
8477
  async startup() {
@@ -8888,15 +8969,15 @@ var SyncBuilder = class {
8888
8969
  this.config.maxInboxBatchSize = limit;
8889
8970
  return this;
8890
8971
  }
8891
- build(reactor, logger, operationIndex, eventBus, db) {
8892
- return this.buildModule(reactor, logger, operationIndex, eventBus, db).syncManager;
8972
+ build(reactor, logger, operationIndex, eventBus, db, driveContainerTypes) {
8973
+ return this.buildModule(reactor, logger, operationIndex, eventBus, db, driveContainerTypes).syncManager;
8893
8974
  }
8894
- buildModule(reactor, logger, operationIndex, eventBus, db) {
8975
+ buildModule(reactor, logger, operationIndex, eventBus, db, driveContainerTypes) {
8895
8976
  if (!this.channelFactory) throw new Error("Channel factory is required");
8896
8977
  const remoteStorage = this.remoteStorage ?? new KyselySyncRemoteStorage(db);
8897
8978
  const cursorStorage = this.cursorStorage ?? new KyselySyncCursorStorage(db);
8898
8979
  const deadLetterStorage = this.deadLetterStorage ?? new KyselySyncDeadLetterStorage(db);
8899
- const syncManager = new SyncManager(logger, remoteStorage, cursorStorage, deadLetterStorage, this.channelFactory, operationIndex, reactor, eventBus, this.config);
8980
+ const syncManager = new SyncManager(logger, remoteStorage, cursorStorage, deadLetterStorage, this.channelFactory, operationIndex, reactor, eventBus, driveContainerTypes, this.config);
8900
8981
  return {
8901
8982
  remoteStorage,
8902
8983
  cursorStorage,
@@ -8915,6 +8996,9 @@ async function createDefaultDatabase() {
8915
8996
  return new Kysely({ dialect: new PGliteDialect(new PGlite()) });
8916
8997
  }
8917
8998
  //#endregion
8999
+ //#region src/core/drive-container-types.ts
9000
+ const DEFAULT_DRIVE_CONTAINER_TYPES = new Set(["powerhouse/document-drive", "powerhouse/reactor-drive"]);
9001
+ //#endregion
8918
9002
  //#region src/shared/factories.ts
8919
9003
  /**
8920
9004
  * Factory method to create a ShutdownStatus that can be updated
@@ -9494,6 +9578,7 @@ var ReactorBuilder = class {
9494
9578
  upgradeManifests = [];
9495
9579
  features = { legacyStorageEnabled: false };
9496
9580
  readModels = [];
9581
+ readModelFactories = [];
9497
9582
  executorManager;
9498
9583
  executorConfig = {};
9499
9584
  writeCacheConfig;
@@ -9509,6 +9594,7 @@ var ReactorBuilder = class {
9509
9594
  jwtHandler;
9510
9595
  documentModelLoader;
9511
9596
  shutdownHooks = [];
9597
+ driveContainerTypes = DEFAULT_DRIVE_CONTAINER_TYPES;
9512
9598
  withLogger(logger) {
9513
9599
  this.logger = logger;
9514
9600
  return this;
@@ -9532,6 +9618,17 @@ var ReactorBuilder = class {
9532
9618
  this.readModels.push(readModel);
9533
9619
  return this;
9534
9620
  }
9621
+ /**
9622
+ * Register a factory that builds a pre-ready read model after the reactor's
9623
+ * internal `operationIndex`, `writeCache`, and processor-manager consistency
9624
+ * tracker are constructed. Use this for read models (e.g. `BaseReadModel`
9625
+ * subclasses) that need those dependencies and therefore cannot be built
9626
+ * before calling `buildModule()`.
9627
+ */
9628
+ withReadModelFactory(factory) {
9629
+ this.readModelFactories.push(factory);
9630
+ return this;
9631
+ }
9535
9632
  withReadModelCoordinator(readModelCoordinator) {
9536
9633
  this.readModelCoordinator = readModelCoordinator;
9537
9634
  return this;
@@ -9551,6 +9648,10 @@ var ReactorBuilder = class {
9551
9648
  this.writeCacheConfig = config;
9552
9649
  return this;
9553
9650
  }
9651
+ withDriveContainerTypes(types) {
9652
+ this.driveContainerTypes = new Set(types);
9653
+ return this;
9654
+ }
9554
9655
  withMigrationStrategy(strategy) {
9555
9656
  this.migrationStrategy = strategy;
9556
9657
  return this;
@@ -9641,7 +9742,7 @@ var ReactorBuilder = class {
9641
9742
  const collectionMembershipCache = new CollectionMembershipCache(operationIndex);
9642
9743
  const executionScope = new KyselyExecutionScope(database, operationStore, operationIndex, keyframeStore, writeCache, documentMetaCache, collectionMembershipCache);
9643
9744
  let executorManager = this.executorManager;
9644
- if (!executorManager) executorManager = new SimpleJobExecutorManager(() => new SimpleJobExecutor(this.logger, documentModelRegistry, operationStore, eventBus, writeCache, operationIndex, documentMetaCache, collectionMembershipCache, this.executorConfig, this.signatureVerifier, executionScope), eventBus, queue, jobTracker, this.logger, resolver, this.executorConfig.jobTimeoutMs);
9745
+ if (!executorManager) executorManager = new SimpleJobExecutorManager(() => new SimpleJobExecutor(this.logger, documentModelRegistry, operationStore, eventBus, writeCache, operationIndex, documentMetaCache, collectionMembershipCache, this.driveContainerTypes, this.executorConfig, this.signatureVerifier, executionScope), eventBus, queue, jobTracker, this.logger, resolver, this.executorConfig.jobTimeoutMs);
9645
9746
  await executorManager.start(this.executorConfig.maxConcurrency ?? 1);
9646
9747
  const readModelInstances = Array.from(new Set([...this.readModels]));
9647
9748
  const documentViewConsistencyTracker = new ConsistencyTracker();
@@ -9663,21 +9764,29 @@ var ReactorBuilder = class {
9663
9764
  const subscriptionManager = new ReactorSubscriptionManager(new DefaultSubscriptionErrorHandler());
9664
9765
  const subscriptionNotificationReadModel = new SubscriptionNotificationReadModel(subscriptionManager, documentView);
9665
9766
  const processorManagerConsistencyTracker = new ConsistencyTracker();
9666
- const processorManager = new ProcessorManager(database, operationIndex, writeCache, processorManagerConsistencyTracker, this.logger);
9767
+ const processorManager = new ProcessorManager(database, operationIndex, writeCache, processorManagerConsistencyTracker, this.logger, this.driveContainerTypes);
9667
9768
  try {
9668
9769
  await processorManager.init();
9669
9770
  } catch (error) {
9670
9771
  console.error("Error initializing processor manager", error);
9671
9772
  }
9773
+ for (const factory of this.readModelFactories) {
9774
+ const readModel = await factory({
9775
+ operationIndex,
9776
+ writeCache,
9777
+ processorManagerConsistencyTracker
9778
+ });
9779
+ readModelInstances.push(readModel);
9780
+ }
9672
9781
  const readModelCoordinator = this.readModelCoordinator ? this.readModelCoordinator : new ReadModelCoordinator(eventBus, readModelInstances, [subscriptionNotificationReadModel, processorManager]);
9673
9782
  const reactor = new Reactor(this.logger, documentModelRegistry, queue, jobTracker, readModelCoordinator, this.features, documentView, documentIndexer, operationStore, eventBus, executorManager);
9674
9783
  let syncModule = void 0;
9675
9784
  if (this.channelScheme) {
9676
9785
  const factory = this.channelScheme === ChannelScheme.CONNECT ? new GqlRequestChannelFactory(this.logger, this.jwtHandler, queue) : new GqlResponseChannelFactory(this.logger);
9677
- syncModule = new SyncBuilder().withChannelFactory(factory).buildModule(reactor, this.logger, operationIndex, eventBus, database);
9786
+ syncModule = new SyncBuilder().withChannelFactory(factory).buildModule(reactor, this.logger, operationIndex, eventBus, database, this.driveContainerTypes);
9678
9787
  await syncModule.syncManager.startup();
9679
9788
  } else if (this.syncBuilder) {
9680
- syncModule = this.syncBuilder.buildModule(reactor, this.logger, operationIndex, eventBus, database);
9789
+ syncModule = this.syncBuilder.buildModule(reactor, this.logger, operationIndex, eventBus, database, this.driveContainerTypes);
9681
9790
  await syncModule.syncManager.startup();
9682
9791
  }
9683
9792
  const module = {
@@ -10032,6 +10141,6 @@ var DocumentIntegrityService = class {
10032
10141
  }
10033
10142
  };
10034
10143
  //#endregion
10035
- export { BaseReadModel, ChannelError, ChannelErrorSource, ChannelScheme, ConsistencyTracker, DefaultSubscriptionErrorHandler, DocumentChangeType, DocumentIntegrityService, DocumentModelRegistry, DocumentModelResolver, DriveClient, DuplicateManifestError, DuplicateModuleError, DuplicateOperationError, EventBus, EventBusAggregateError, GqlRequestChannel, GqlRequestChannelFactory, GqlResponseChannel, GqlResponseChannelFactory, SimpleJobExecutor as InMemoryJobExecutor, SimpleJobExecutor, InMemoryJobTracker, InMemoryQueue, IntervalPollTimer, InvalidModuleError, JobAwaiter, JobExecutorEventTypes, JobStatus, KyselyDocumentIndexer, KyselyDocumentView, KyselyKeyframeStore, KyselyOperationStore, KyselySyncCursorStorage, KyselySyncRemoteStorage, KyselyWriteCache, Mailbox, ModuleNotFoundError, NullDocumentModelResolver, OptimisticLockError, PollBehavior, PollingChannelError, ProcessorManager, PropagationMode, QueueEventTypes, REACTOR_SCHEMA, Reactor, ReactorBuilder, ReactorClient, ReactorClientBuilder, ReactorEventTypes, ReactorSubscriptionManager, ReadModelCoordinator, RelationalDbProcessor, RelationshipChangeType, RevisionMismatchError, SimpleJobExecutorManager, SyncBuilder, SyncEventTypes, SyncOperation, SyncOperationAggregateError, SyncOperationStatus, SyncStatus, SyncStatusTracker, addRelationshipAction, batchOperationsByDocument, consolidateSyncOperations, createDocumentAction, createMutableShutdownStatus, createRelationalDb, deleteDocumentAction, documentActions, driveCollectionId, driveIdFromUrl, envelopesToSyncOperations, getMigrationStatus, makeConsistencyKey, parseDriveUrl, removeRelationshipAction, runMigrations, trimMailboxFromAckOrdinal, upgradeDocumentAction };
10144
+ export { BaseReadModel, ChannelError, ChannelErrorSource, ChannelScheme, ConsistencyTracker, DEFAULT_DRIVE_CONTAINER_TYPES, DefaultSubscriptionErrorHandler, DocumentChangeType, DocumentIntegrityService, DocumentModelRegistry, DocumentModelResolver, DriveClient, DuplicateManifestError, DuplicateModuleError, DuplicateOperationError, EventBus, EventBusAggregateError, GqlRequestChannel, GqlRequestChannelFactory, GqlResponseChannel, GqlResponseChannelFactory, SimpleJobExecutor as InMemoryJobExecutor, SimpleJobExecutor, InMemoryJobTracker, InMemoryQueue, IntervalPollTimer, InvalidModuleError, JobAwaiter, JobExecutorEventTypes, JobStatus, KyselyDocumentIndexer, KyselyDocumentView, KyselyKeyframeStore, KyselyOperationStore, KyselySyncCursorStorage, KyselySyncRemoteStorage, KyselyWriteCache, Mailbox, ModuleNotFoundError, NullDocumentModelResolver, OptimisticLockError, PollBehavior, PollingChannelError, ProcessorManager, PropagationMode, QueueEventTypes, REACTOR_SCHEMA, Reactor, ReactorBuilder, ReactorClient, ReactorClientBuilder, ReactorEventTypes, ReactorSubscriptionManager, ReadModelCoordinator, RelationalDbProcessor, RelationshipChangeType, RevisionMismatchError, SimpleJobExecutorManager, SyncBuilder, SyncEventTypes, SyncOperation, SyncOperationAggregateError, SyncOperationStatus, SyncStatus, SyncStatusTracker, addRelationshipAction, batchOperationsByDocument, consolidateSyncOperations, createDocumentAction, createMutableShutdownStatus, createRelationalDb, deleteDocumentAction, documentActions, driveCollectionId, driveIdFromUrl, envelopesToSyncOperations, getMigrationStatus, makeConsistencyKey, parseDriveUrl, parsePagingOptions, removeRelationshipAction, runMigrations, trimMailboxFromAckOrdinal, updateRelationshipAction, upgradeDocumentAction };
10036
10145
 
10037
10146
  //# sourceMappingURL=index.js.map