korajs 0.6.0 → 1.0.0-beta.0
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/LICENSE +21 -0
- package/dist/{chunk-WALHLVVF.js → chunk-HPBI67CZ.js} +167 -35
- package/dist/chunk-HPBI67CZ.js.map +1 -0
- package/dist/index.cjs +149 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +12 -31
- package/dist/index.js.map +1 -1
- package/dist/testing.cjs +168 -35
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +30 -1
- package/dist/testing.d.ts +30 -1
- package/dist/testing.js +5 -3
- package/package.json +13 -13
- package/dist/chunk-WALHLVVF.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dr. Obed Ehoneah
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { HybridLogicalClock, KoraError, createOperation as createOperation2 } from "@korajs/core";
|
|
3
3
|
import { topologicalSort } from "@korajs/core/internal";
|
|
4
4
|
import { buildMergeRelationLookup, checkReferentialIntegrityOnDelete } from "@korajs/merge";
|
|
5
|
-
import { richtextStatesEqual } from "@korajs/store";
|
|
5
|
+
import { OptimisticLockError, richtextStatesEqual } from "@korajs/store";
|
|
6
6
|
import {
|
|
7
7
|
executeDelete,
|
|
8
8
|
executeInsert,
|
|
@@ -104,6 +104,7 @@ async function buildSideEffectEntry(ctx, effect, parentOpId, transactionId, muta
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
// src/apply-pipeline.ts
|
|
107
|
+
var MERGE_APPLY_RETRY_LIMIT = 8;
|
|
107
108
|
var ApplyPipeline = class {
|
|
108
109
|
constructor(deps) {
|
|
109
110
|
this.deps = deps;
|
|
@@ -305,15 +306,37 @@ var ApplyPipeline = class {
|
|
|
305
306
|
if (!collectionDef) {
|
|
306
307
|
return this.deps.store.applyRemoteOperation(op);
|
|
307
308
|
}
|
|
309
|
+
let lockError = null;
|
|
310
|
+
for (let attempt = 0; attempt < MERGE_APPLY_RETRY_LIMIT; attempt++) {
|
|
311
|
+
try {
|
|
312
|
+
return await this.applyRemoteUpdateAttempt(op, collectionDef);
|
|
313
|
+
} catch (error) {
|
|
314
|
+
if (!(error instanceof OptimisticLockError)) {
|
|
315
|
+
throw error;
|
|
316
|
+
}
|
|
317
|
+
lockError = error;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
throw lockError ?? new OptimisticLockError(op.collection, op.recordId);
|
|
321
|
+
}
|
|
322
|
+
async applyRemoteUpdateAttempt(op, collectionDef) {
|
|
323
|
+
const guard = await this.deps.store.getRowVersionState(
|
|
324
|
+
op.collection,
|
|
325
|
+
op.recordId
|
|
326
|
+
) ?? { version: null, fieldVersions: null };
|
|
308
327
|
const accessor = this.deps.store.collection(op.collection);
|
|
309
328
|
const currentRecord = await accessor.findById(op.recordId);
|
|
310
329
|
if (!currentRecord) {
|
|
311
|
-
const tombstoneResult = await this.applyRemoteUpdateOnDeletedRow(op, collectionDef);
|
|
330
|
+
const tombstoneResult = await this.applyRemoteUpdateOnDeletedRow(op, collectionDef, guard);
|
|
312
331
|
if (tombstoneResult !== null) {
|
|
313
332
|
return tombstoneResult;
|
|
314
333
|
}
|
|
315
334
|
return this.deps.store.applyRemoteOperation(op);
|
|
316
335
|
}
|
|
336
|
+
if (!updateNeedsMergeEngine(op, collectionDef)) {
|
|
337
|
+
await this.observeScalarMerge(op, collectionDef);
|
|
338
|
+
return this.deps.store.applyRemoteOperation(op);
|
|
339
|
+
}
|
|
317
340
|
let hasConflict = false;
|
|
318
341
|
for (const field of Object.keys(op.data ?? {})) {
|
|
319
342
|
const fieldDef = collectionDef.fields[field];
|
|
@@ -331,14 +354,50 @@ var ApplyPipeline = class {
|
|
|
331
354
|
}
|
|
332
355
|
}
|
|
333
356
|
if (!hasConflict) {
|
|
334
|
-
return this.deps.store.applyRemoteOperation(op
|
|
357
|
+
return this.deps.store.applyRemoteOperation(op, {
|
|
358
|
+
forceMaterialize: true,
|
|
359
|
+
guardRowState: guard
|
|
360
|
+
});
|
|
335
361
|
}
|
|
336
|
-
return this.applyMergedUpdate(op, collectionDef, currentRecord, op.previousData ?? {});
|
|
362
|
+
return this.applyMergedUpdate(op, collectionDef, currentRecord, op.previousData ?? {}, guard);
|
|
337
363
|
}
|
|
338
364
|
/**
|
|
339
365
|
* Remote update vs local soft-delete: merge before materializing to avoid zombie rows.
|
|
340
366
|
*/
|
|
341
|
-
|
|
367
|
+
/**
|
|
368
|
+
* Emit merge observability (trace + conflict counter) for a scalar update that
|
|
369
|
+
* concurrently touches a field a local operation also changed.
|
|
370
|
+
*
|
|
371
|
+
* The store resolves the actual value by deterministic per-field LWW; this
|
|
372
|
+
* method exists only so the decision is loggable (CLAUDE.md: every merge
|
|
373
|
+
* decision must be traceable). It reads the local operation from the append-
|
|
374
|
+
* only log — which is immutable — rather than the materialized row, so it is
|
|
375
|
+
* not subject to the read-then-write race the store write path was hardened
|
|
376
|
+
* against. The merge engine is invoked purely to build an accurate trace; its
|
|
377
|
+
* timestamps match the store's LWW comparison, so the trace never lies.
|
|
378
|
+
*/
|
|
379
|
+
async observeScalarMerge(op, collectionDef) {
|
|
380
|
+
const localOp = await this.deps.store.getLatestLocalOperationForRecord(
|
|
381
|
+
op.collection,
|
|
382
|
+
op.recordId
|
|
383
|
+
);
|
|
384
|
+
if (!localOp || !localOp.data) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
const remoteFields = Object.keys(op.data ?? {});
|
|
388
|
+
const sharesField = remoteFields.some((field) => localOp.data?.[field] !== void 0);
|
|
389
|
+
if (!sharesField) {
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
const mergeResult = await this.deps.mergeEngine.merge({
|
|
393
|
+
local: localOp,
|
|
394
|
+
remote: op,
|
|
395
|
+
baseState: op.previousData ?? {},
|
|
396
|
+
collectionDef
|
|
397
|
+
});
|
|
398
|
+
this.emitMergeLifecycle(op, localOp, mergeResult);
|
|
399
|
+
}
|
|
400
|
+
async applyRemoteUpdateOnDeletedRow(op, collectionDef, guard) {
|
|
342
401
|
const snapshot = await this.deps.store.findMaterializedRow(op.collection, op.recordId);
|
|
343
402
|
if (!snapshot?.deleted) {
|
|
344
403
|
return null;
|
|
@@ -356,37 +415,41 @@ var ApplyPipeline = class {
|
|
|
356
415
|
baseState: op.previousData ?? {},
|
|
357
416
|
collectionDef
|
|
358
417
|
});
|
|
359
|
-
this.emitMergeLifecycle(op, localOp, mergeResult);
|
|
360
418
|
if (mergeResult.appliedOperation === "local") {
|
|
419
|
+
this.emitMergeLifecycle(op, localOp, mergeResult);
|
|
361
420
|
return "skipped";
|
|
362
421
|
}
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
reactivateIfDeleted: true
|
|
422
|
+
const applyResult = await this.deps.store.applyRemoteOperation(op, {
|
|
423
|
+
reactivateIfDeleted: true,
|
|
424
|
+
forceMaterialize: true,
|
|
425
|
+
materializeData: { ...mergeResult.mergedData },
|
|
426
|
+
materializeTimestamp: maxTimestamp(op.timestamp, localOp.timestamp),
|
|
427
|
+
guardRowState: guard
|
|
370
428
|
});
|
|
429
|
+
this.emitMergeLifecycle(op, localOp, mergeResult);
|
|
371
430
|
if (applyResult === "applied" && mergeResult.sideEffects.length > 0) {
|
|
372
431
|
await applySideEffectOps(this.deps.store, mergeResult.sideEffects, op.id);
|
|
373
432
|
}
|
|
374
433
|
return applyResult;
|
|
375
434
|
}
|
|
376
|
-
async applyMergedUpdate(op, collectionDef, currentRecord, baseState, applyOptions) {
|
|
377
|
-
const
|
|
378
|
-
this.deps.store,
|
|
435
|
+
async applyMergedUpdate(op, collectionDef, currentRecord, baseState, guard, applyOptions) {
|
|
436
|
+
const latestLocal = await this.deps.store.getLatestLocalOperationForRecord(
|
|
379
437
|
op.collection,
|
|
380
|
-
op.recordId
|
|
438
|
+
op.recordId
|
|
439
|
+
);
|
|
440
|
+
const localTimestamp = resolveLocalTimestamp(
|
|
441
|
+
latestLocal,
|
|
381
442
|
currentRecord,
|
|
382
443
|
this.deps.store.getNodeId()
|
|
383
444
|
);
|
|
445
|
+
const { atomicOps: _remoteAtomicOps, ...opWithoutAtomic } = op;
|
|
384
446
|
const localOp = {
|
|
385
|
-
...
|
|
447
|
+
...opWithoutAtomic,
|
|
386
448
|
data: buildLocalDiff(baseState, currentRecord, Object.keys(op.data ?? {})),
|
|
387
449
|
previousData: op.previousData,
|
|
388
450
|
nodeId: this.deps.store.getNodeId(),
|
|
389
|
-
timestamp: localTimestamp
|
|
451
|
+
timestamp: localTimestamp,
|
|
452
|
+
...latestLocal?.atomicOps !== void 0 ? { atomicOps: latestLocal.atomicOps } : {}
|
|
390
453
|
};
|
|
391
454
|
const constraintContext = createConstraintContext(this.deps.store);
|
|
392
455
|
const mergeResult = await this.deps.mergeEngine.merge(
|
|
@@ -398,13 +461,14 @@ var ApplyPipeline = class {
|
|
|
398
461
|
},
|
|
399
462
|
constraintContext
|
|
400
463
|
);
|
|
464
|
+
const applyResult = await this.deps.store.applyRemoteOperation(op, {
|
|
465
|
+
...applyOptions,
|
|
466
|
+
forceMaterialize: true,
|
|
467
|
+
materializeData: mergeResult.mergedData,
|
|
468
|
+
materializeTimestamp: maxTimestamp(op.timestamp, localTimestamp),
|
|
469
|
+
guardRowState: guard
|
|
470
|
+
});
|
|
401
471
|
this.emitMergeLifecycle(op, localOp, mergeResult);
|
|
402
|
-
const mergedOp = {
|
|
403
|
-
...op,
|
|
404
|
-
data: mergeResult.mergedData,
|
|
405
|
-
timestamp: maxTimestamp(op.timestamp, localTimestamp)
|
|
406
|
-
};
|
|
407
|
-
const applyResult = await this.deps.store.applyRemoteOperation(mergedOp, applyOptions);
|
|
408
472
|
if (applyResult === "applied" && mergeResult.sideEffects.length > 0) {
|
|
409
473
|
await applySideEffectOps(this.deps.store, mergeResult.sideEffects, op.id);
|
|
410
474
|
}
|
|
@@ -415,9 +479,27 @@ var ApplyPipeline = class {
|
|
|
415
479
|
if (!collectionDef || !op.data) {
|
|
416
480
|
return this.deps.store.applyRemoteOperation(op);
|
|
417
481
|
}
|
|
482
|
+
let lockError = null;
|
|
483
|
+
for (let attempt = 0; attempt < MERGE_APPLY_RETRY_LIMIT; attempt++) {
|
|
484
|
+
try {
|
|
485
|
+
return await this.applyRemoteInsertAttempt(op, collectionDef);
|
|
486
|
+
} catch (error) {
|
|
487
|
+
if (!(error instanceof OptimisticLockError)) {
|
|
488
|
+
throw error;
|
|
489
|
+
}
|
|
490
|
+
lockError = error;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
throw lockError ?? new OptimisticLockError(op.collection, op.recordId);
|
|
494
|
+
}
|
|
495
|
+
async applyRemoteInsertAttempt(op, collectionDef) {
|
|
496
|
+
const guard = await this.deps.store.getRowVersionState(
|
|
497
|
+
op.collection,
|
|
498
|
+
op.recordId
|
|
499
|
+
) ?? { version: null, fieldVersions: null };
|
|
418
500
|
const snapshot = await this.deps.store.findMaterializedRow(op.collection, op.recordId);
|
|
419
501
|
if (!snapshot || snapshot.deleted) {
|
|
420
|
-
return this.deps.store.applyRemoteOperation(op);
|
|
502
|
+
return this.deps.store.applyRemoteOperation(op, { guardRowState: guard });
|
|
421
503
|
}
|
|
422
504
|
const localOp = await resolveLocalOpForRecord(
|
|
423
505
|
this.deps.store,
|
|
@@ -431,13 +513,14 @@ var ApplyPipeline = class {
|
|
|
431
513
|
baseState: {},
|
|
432
514
|
collectionDef
|
|
433
515
|
});
|
|
516
|
+
const applyResult = await this.deps.store.applyRemoteOperation(op, {
|
|
517
|
+
forceMaterialize: true,
|
|
518
|
+
materializeData: mergeResult.mergedData,
|
|
519
|
+
materializeTimestamp: maxTimestamp(op.timestamp, localOp.timestamp),
|
|
520
|
+
guardRowState: guard
|
|
521
|
+
});
|
|
434
522
|
this.emitMergeLifecycle(op, localOp, mergeResult);
|
|
435
|
-
|
|
436
|
-
...op,
|
|
437
|
-
data: mergeResult.mergedData,
|
|
438
|
-
timestamp: maxTimestamp(op.timestamp, localOp.timestamp)
|
|
439
|
-
};
|
|
440
|
-
return this.deps.store.applyRemoteOperation(mergedOp);
|
|
523
|
+
return applyResult;
|
|
441
524
|
}
|
|
442
525
|
emitMergeLifecycle(remote, local, mergeResult) {
|
|
443
526
|
this.deps.emitter?.emit({
|
|
@@ -529,6 +612,24 @@ async function applySideEffectOps(store, sideEffects, parentOpId) {
|
|
|
529
612
|
}
|
|
530
613
|
}
|
|
531
614
|
}
|
|
615
|
+
function updateNeedsMergeEngine(op, collectionDef) {
|
|
616
|
+
if (collectionDef.constraints.length > 0) {
|
|
617
|
+
return true;
|
|
618
|
+
}
|
|
619
|
+
if (op.atomicOps && Object.keys(op.atomicOps).length > 0) {
|
|
620
|
+
return true;
|
|
621
|
+
}
|
|
622
|
+
for (const field of Object.keys(op.data ?? {})) {
|
|
623
|
+
const kind = collectionDef.fields[field]?.kind;
|
|
624
|
+
if (kind === "richtext" || kind === "array") {
|
|
625
|
+
return true;
|
|
626
|
+
}
|
|
627
|
+
if (collectionDef.resolvers[field]) {
|
|
628
|
+
return true;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
532
633
|
function buildLocalDiff(baseState, currentRecord, fields) {
|
|
533
634
|
const diff = {};
|
|
534
635
|
for (const field of fields) {
|
|
@@ -536,8 +637,7 @@ function buildLocalDiff(baseState, currentRecord, fields) {
|
|
|
536
637
|
}
|
|
537
638
|
return diff;
|
|
538
639
|
}
|
|
539
|
-
|
|
540
|
-
const latestLocal = await store.getLatestLocalOperationForRecord(collection, recordId);
|
|
640
|
+
function resolveLocalTimestamp(latestLocal, currentRecord, nodeId) {
|
|
541
641
|
if (latestLocal) {
|
|
542
642
|
return latestLocal.timestamp;
|
|
543
643
|
}
|
|
@@ -570,6 +670,30 @@ function deepEqual(a, b) {
|
|
|
570
670
|
return false;
|
|
571
671
|
}
|
|
572
672
|
|
|
673
|
+
// src/audit-bridge.ts
|
|
674
|
+
import { persistedAuditTraceFromEvent } from "@korajs/store";
|
|
675
|
+
var AUDIT_EVENT_TYPES = ["merge:completed", "merge:conflict", "constraint:violated"];
|
|
676
|
+
function isAuditEvent(event) {
|
|
677
|
+
return AUDIT_EVENT_TYPES.includes(event.type);
|
|
678
|
+
}
|
|
679
|
+
function wireAuditPersistence(store, emitter) {
|
|
680
|
+
const unsubscribers = AUDIT_EVENT_TYPES.map(
|
|
681
|
+
(eventType) => emitter.on(eventType, (event) => {
|
|
682
|
+
if (!isAuditEvent(event)) {
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
const trace = persistedAuditTraceFromEvent(event);
|
|
686
|
+
void store.appendAuditTrace(trace).catch(() => {
|
|
687
|
+
});
|
|
688
|
+
})
|
|
689
|
+
);
|
|
690
|
+
return () => {
|
|
691
|
+
for (const unsub of unsubscribers) {
|
|
692
|
+
unsub();
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
|
|
573
697
|
// src/merge-aware-sync-store.ts
|
|
574
698
|
var MergeAwareSyncStore = class {
|
|
575
699
|
constructor(store, mergeEngine, emitter, options) {
|
|
@@ -595,6 +719,13 @@ var MergeAwareSyncStore = class {
|
|
|
595
719
|
async applyRemoteOperation(op) {
|
|
596
720
|
return this.pipeline.applyRemote(op);
|
|
597
721
|
}
|
|
722
|
+
/**
|
|
723
|
+
* Delegates timestamp rebase to the store so the sync engine can re-stamp
|
|
724
|
+
* never-acknowledged operations after a fast device clock is corrected.
|
|
725
|
+
*/
|
|
726
|
+
async rebaseUnsyncedOperations(ids, correctedNowMs) {
|
|
727
|
+
return this.store.rebaseUnsyncedOperations(ids, correctedNowMs);
|
|
728
|
+
}
|
|
598
729
|
};
|
|
599
730
|
|
|
600
731
|
// src/store-queue-storage.ts
|
|
@@ -676,8 +807,9 @@ var StoreSyncStatePersistence = class {
|
|
|
676
807
|
|
|
677
808
|
export {
|
|
678
809
|
ApplyPipeline,
|
|
810
|
+
wireAuditPersistence,
|
|
679
811
|
MergeAwareSyncStore,
|
|
680
812
|
StoreQueueStorage,
|
|
681
813
|
StoreSyncStatePersistence
|
|
682
814
|
};
|
|
683
|
-
//# sourceMappingURL=chunk-
|
|
815
|
+
//# sourceMappingURL=chunk-HPBI67CZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/apply-pipeline.ts","../src/build-side-effect-entry.ts","../src/audit-bridge.ts","../src/merge-aware-sync-store.ts","../src/store-queue-storage.ts","../src/store-sync-state.ts"],"sourcesContent":["import type {\n\tCollectionDefinition,\n\tHLCTimestamp,\n\tKoraEventEmitter,\n\tOperation,\n\tSchemaDefinition,\n} from '@korajs/core'\nimport { HybridLogicalClock, KoraError, createOperation } from '@korajs/core'\nimport { topologicalSort } from '@korajs/core/internal'\nimport type { MergeEngine, MergeResult, ReferentialMergeContext, SideEffectOp } from '@korajs/merge'\nimport { buildMergeRelationLookup, checkReferentialIntegrityOnDelete } from '@korajs/merge'\nimport type { ConstraintContext } from '@korajs/merge'\nimport type {\n\tApplyRemoteOptions,\n\tCollectionRecord,\n\tLocalMutationHandler,\n\tRowVersionState,\n\tStore,\n\tTransactionCommitBatch,\n\tTransactionCommitResult,\n} from '@korajs/store'\nimport { OptimisticLockError, richtextStatesEqual } from '@korajs/store'\nimport {\n\texecuteDelete,\n\texecuteInsert,\n\texecuteUpdate,\n\tresolveCausalDeps,\n} from '@korajs/store/internal'\nimport type { ApplyResult } from '@korajs/sync'\nimport { buildSideEffectEntry } from './build-side-effect-entry'\n\n/**\n * Whether the operation originated locally or arrived from sync.\n */\nexport type ApplyMode = 'local' | 'remote'\n\n/**\n * How many times a merge-engine apply retries when the row changed underneath\n * it (OptimisticLockError). Each retry recomputes the merge from fresh state;\n * since JavaScript is single-threaded, invalidation requires an actual new\n * local write landing at an `await` point, so contention is self-limiting.\n * Exhaustion rethrows: the operation stays unacknowledged and sync retries it\n * later — data is never dropped.\n */\nconst MERGE_APPLY_RETRY_LIMIT = 8\n\n/**\n * Dependencies for the unified apply pipeline.\n */\nexport interface ApplyPipelineDeps {\n\treadonly store: Store\n\treadonly mergeEngine: MergeEngine\n\treadonly emitter: KoraEventEmitter | null\n\t/** Called when a field-level merge runs (updates sync conflict counter). */\n\treadonly onMergeConflict?: () => void\n}\n\n/**\n * Context passed into each apply invocation.\n */\nexport interface ApplyContext {\n\treadonly mode: ApplyMode\n\treadonly schema: SchemaDefinition\n}\n\n/**\n * Single entry point for applying remote sync operations with merge + referential integrity.\n */\nexport class ApplyPipeline implements LocalMutationHandler {\n\tprivate readonly relationLookupMap: ReturnType<typeof buildMergeRelationLookup>\n\n\tconstructor(private readonly deps: ApplyPipelineDeps) {\n\t\tthis.relationLookupMap = buildMergeRelationLookup(deps.store.getSchema())\n\t}\n\n\t/** Local insert — same persistence path as remote apply side effects. */\n\tasync insert(collection: string, data: Record<string, unknown>): Promise<CollectionRecord> {\n\t\treturn executeInsert(this.deps.store.createMutationContext(collection), data)\n\t}\n\n\t/** Local update. */\n\tasync update(\n\t\tcollection: string,\n\t\tid: string,\n\t\tdata: Record<string, unknown>,\n\t): Promise<CollectionRecord> {\n\t\treturn executeUpdate(this.deps.store.createMutationContext(collection), id, data)\n\t}\n\n\t/**\n\t * Local delete with merge-package referential integrity (same rules as remote delete).\n\t */\n\tasync delete(collection: string, id: string): Promise<void> {\n\t\tconst ctx = this.deps.store.createMutationContext(collection)\n\t\tconst causalDeps = resolveCausalDeps(ctx)\n\t\tconst operation = await createOperation(\n\t\t\t{\n\t\t\t\tnodeId: ctx.nodeId,\n\t\t\t\ttype: 'delete',\n\t\t\t\tcollection,\n\t\t\t\trecordId: id,\n\t\t\t\tdata: null,\n\t\t\t\tpreviousData: null,\n\t\t\t\tsequenceNumber: await ctx.allocateSequenceNumber(),\n\t\t\t\tcausalDeps,\n\t\t\t\tschemaVersion: ctx.schema.version,\n\t\t\t},\n\t\t\tctx.clock,\n\t\t)\n\t\tctx.causalTracker?.afterOperation(collection, operation.id, ctx.inTransaction)\n\n\t\tconst refCtx = createReferentialMergeContext(this.deps.store)\n\t\tconst check = await checkReferentialIntegrityOnDelete(\n\t\t\toperation,\n\t\t\tthis.deps.store.getSchema(),\n\t\t\trefCtx,\n\t\t\tthis.relationLookupMap,\n\t\t)\n\n\t\tfor (const trace of check.traces) {\n\t\t\tthis.deps.emitter?.emit({ type: 'merge:conflict', trace })\n\t\t}\n\n\t\tif (!check.allowed) {\n\t\t\tthrow new KoraError(\n\t\t\t\t`Cannot delete record \"${id}\" from \"${collection}\": referential restrict policy violated`,\n\t\t\t\t'REFERENTIAL_INTEGRITY',\n\t\t\t\t{ collection, recordId: id },\n\t\t\t)\n\t\t}\n\n\t\tawait executeDelete(ctx, id, {\n\t\t\tskipReferentialEnforcement: true,\n\t\t\toperation,\n\t\t})\n\n\t\tif (check.sideEffectOps.length > 0) {\n\t\t\tawait applySideEffectOps(this.deps.store, check.sideEffectOps, operation.id)\n\t\t}\n\t}\n\n\t/**\n\t * Commit a buffered transaction: merge-package delete enforcement, causal ordering, single DB txn.\n\t */\n\tasync commitTransaction(batch: TransactionCommitBatch): Promise<TransactionCommitResult> {\n\t\tconst store = this.deps.store\n\t\tconst supplemental: TransactionCommitBatch['entries'] = []\n\n\t\tfor (const entry of batch.entries) {\n\t\t\tif (entry.operation.type !== 'delete') {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst refCtx = createReferentialMergeContext(store)\n\t\t\tconst check = await checkReferentialIntegrityOnDelete(\n\t\t\t\tentry.operation,\n\t\t\t\tstore.getSchema(),\n\t\t\t\trefCtx,\n\t\t\t\tthis.relationLookupMap,\n\t\t\t)\n\n\t\t\tfor (const trace of check.traces) {\n\t\t\t\tthis.deps.emitter?.emit({ type: 'merge:conflict', trace })\n\t\t\t}\n\n\t\t\tif (!check.allowed) {\n\t\t\t\tthrow new KoraError(\n\t\t\t\t\t`Cannot delete record \"${entry.operation.recordId}\" from \"${entry.collection}\": referential restrict policy violated`,\n\t\t\t\t\t'REFERENTIAL_INTEGRITY',\n\t\t\t\t\t{ collection: entry.collection, recordId: entry.operation.recordId },\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tfor (const effect of check.sideEffectOps) {\n\t\t\t\tconst ctx = store.createMutationContext(effect.collection, { inTransaction: true })\n\t\t\t\tsupplemental.push(\n\t\t\t\t\tawait buildSideEffectEntry(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\teffect,\n\t\t\t\t\t\tentry.operation.id,\n\t\t\t\t\t\tbatch.transactionId,\n\t\t\t\t\t\tbatch.mutationName,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\tconst allEntries = [...batch.entries, ...supplemental]\n\t\tconst sortedOps = topologicalSort(allEntries.map((e) => e.operation))\n\t\tconst commandsByOpId = new Map(allEntries.map((e) => [e.operation.id, e.commands] as const))\n\n\t\tconst ctx = store.createMutationContext(\n\t\t\tbatch.entries[0]?.collection ?? Object.keys(store.getSchema().collections)[0] ?? 'todos',\n\t\t\t{ inTransaction: true },\n\t\t)\n\n\t\tawait ctx.adapter.transaction(async (tx) => {\n\t\t\tfor (const op of sortedOps) {\n\t\t\t\tconst commands = commandsByOpId.get(op.id)\n\t\t\t\tif (!commands) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tfor (const cmd of commands) {\n\t\t\t\t\tawait tx.execute(cmd.sql, cmd.params)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tconst affectedCollections = new Set<string>()\n\t\tfor (const entry of allEntries) {\n\t\t\taffectedCollections.add(entry.collection)\n\t\t}\n\n\t\treturn { operations: sortedOps, affectedCollections }\n\t}\n\n\tasync applyRemote(op: Operation): Promise<ApplyResult> {\n\t\treturn this.apply(op, { mode: 'remote', schema: this.deps.store.getSchema() })\n\t}\n\n\tasync apply(op: Operation, context: ApplyContext): Promise<ApplyResult> {\n\t\tif (context.mode === 'local') {\n\t\t\treturn this.deps.store.applyRemoteOperation(op)\n\t\t}\n\n\t\tif (op.type === 'delete') {\n\t\t\treturn this.applyRemoteDelete(op)\n\t\t}\n\n\t\tif (op.type === 'insert' && op.data) {\n\t\t\treturn this.applyRemoteInsert(op)\n\t\t}\n\n\t\tif (op.type === 'update' && op.data && op.previousData) {\n\t\t\treturn this.applyRemoteUpdate(op)\n\t\t}\n\n\t\treturn this.deps.store.applyRemoteOperation(op)\n\t}\n\n\tprivate async applyRemoteDelete(op: Operation): Promise<ApplyResult> {\n\t\tconst blocked = await this.resolveRemoteDeleteVsLocalUpdate(op)\n\t\tif (blocked) {\n\t\t\treturn 'skipped'\n\t\t}\n\n\t\tconst refCtx = createReferentialMergeContext(this.deps.store)\n\t\tconst check = await checkReferentialIntegrityOnDelete(\n\t\t\top,\n\t\t\tthis.deps.store.getSchema(),\n\t\t\trefCtx,\n\t\t\tthis.relationLookupMap,\n\t\t)\n\n\t\tfor (const trace of check.traces) {\n\t\t\tthis.deps.emitter?.emit({ type: 'merge:conflict', trace })\n\t\t}\n\n\t\tif (!check.allowed) {\n\t\t\treturn 'rejected'\n\t\t}\n\n\t\tconst result = await this.deps.store.applyRemoteOperation(op)\n\t\tif (result !== 'applied') {\n\t\t\treturn result\n\t\t}\n\n\t\tif (check.sideEffectOps.length > 0) {\n\t\t\tawait applySideEffectOps(this.deps.store, check.sideEffectOps, op.id)\n\t\t}\n\n\t\treturn 'applied'\n\t}\n\n\t/**\n\t * When a local update is newer than a remote delete, keep the record alive.\n\t */\n\tprivate async resolveRemoteDeleteVsLocalUpdate(op: Operation): Promise<boolean> {\n\t\tconst collectionDef = this.deps.store.getSchema().collections[op.collection]\n\t\tif (!collectionDef) {\n\t\t\treturn false\n\t\t}\n\n\t\tconst localOp = await this.deps.store.getLatestLocalOperationForRecord(\n\t\t\top.collection,\n\t\t\top.recordId,\n\t\t)\n\t\tif (!localOp || localOp.type !== 'update') {\n\t\t\treturn false\n\t\t}\n\n\t\tconst baseState = localOp.previousData ?? {}\n\t\tconst mergeResult = await this.deps.mergeEngine.merge({\n\t\t\tlocal: localOp,\n\t\t\tremote: op,\n\t\t\tbaseState,\n\t\t\tcollectionDef,\n\t\t})\n\n\t\tthis.emitMergeLifecycle(op, localOp, mergeResult)\n\n\t\treturn mergeResult.appliedOperation === 'local'\n\t}\n\n\tprivate async applyRemoteUpdate(op: Operation): Promise<ApplyResult> {\n\t\tconst schema = this.deps.store.getSchema()\n\t\tconst collectionDef = schema.collections[op.collection]\n\t\tif (!collectionDef) {\n\t\t\treturn this.deps.store.applyRemoteOperation(op)\n\t\t}\n\n\t\t// Merge-engine paths read state, compute a merge, then write. A concurrent\n\t\t// local mutation landing between read and write invalidates the merge; the\n\t\t// guarded apply detects this (OptimisticLockError) and we recompute from\n\t\t// fresh state. Bounded so a pathological writer can't spin forever —\n\t\t// exhaustion rethrows, leaving the op unacknowledged for a later sync\n\t\t// retry (never silently dropped).\n\t\tlet lockError: OptimisticLockError | null = null\n\t\tfor (let attempt = 0; attempt < MERGE_APPLY_RETRY_LIMIT; attempt++) {\n\t\t\ttry {\n\t\t\t\treturn await this.applyRemoteUpdateAttempt(op, collectionDef)\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof OptimisticLockError)) {\n\t\t\t\t\tthrow error\n\t\t\t\t}\n\t\t\t\tlockError = error\n\t\t\t}\n\t\t}\n\t\tthrow lockError ?? new OptimisticLockError(op.collection, op.recordId)\n\t}\n\n\tprivate async applyRemoteUpdateAttempt(\n\t\top: Operation,\n\t\tcollectionDef: CollectionDefinition,\n\t): Promise<ApplyResult> {\n\t\t// Snapshot the row's version state BEFORE reading the record: if a local\n\t\t// write lands between these two reads, the guard is older than the record\n\t\t// and the guarded apply fails safe (retry). The reverse order would let a\n\t\t// merge computed from a stale record pass a fresh guard and clobber the\n\t\t// local write.\n\t\tconst guard: RowVersionState = (await this.deps.store.getRowVersionState(\n\t\t\top.collection,\n\t\t\top.recordId,\n\t\t)) ?? { version: null, fieldVersions: null }\n\n\t\tconst accessor = this.deps.store.collection(op.collection)\n\t\tconst currentRecord = await accessor.findById(op.recordId)\n\n\t\tif (!currentRecord) {\n\t\t\tconst tombstoneResult = await this.applyRemoteUpdateOnDeletedRow(op, collectionDef, guard)\n\t\t\tif (tombstoneResult !== null) {\n\t\t\t\treturn tombstoneResult\n\t\t\t}\n\t\t\t// No materialized row at all: the store's atomic path appends the op\n\t\t\t// (nothing to guard — materialization is a no-op until the insert lands).\n\t\t\treturn this.deps.store.applyRemoteOperation(op)\n\t\t}\n\n\t\t// Pure scalar last-write-wins is resolved deterministically and atomically\n\t\t// inside the store using per-field HLC versions. Routing it there (instead\n\t\t// of pre-reading the row here to guess a conflict) both removes the\n\t\t// read-decide-write race — a concurrent local edit can no longer slip\n\t\t// between the check and the write — and guarantees every node converges to\n\t\t// the max-timestamp writer regardless of the order operations arrive. Only\n\t\t// CRDT fields (richtext, add-wins-set arrays), declared constraints, or\n\t\t// custom resolvers still need the three-tier merge engine.\n\t\tif (!updateNeedsMergeEngine(op, collectionDef)) {\n\t\t\t// The store resolves the write deterministically, but a same-field\n\t\t\t// concurrent edit is still a merge decision the developer/DevTools must\n\t\t\t// see. Emit the trace from the immutable local op in the log (race-free),\n\t\t\t// then let the store perform the authoritative atomic write.\n\t\t\tawait this.observeScalarMerge(op, collectionDef)\n\t\t\treturn this.deps.store.applyRemoteOperation(op)\n\t\t}\n\n\t\tlet hasConflict = false\n\t\tfor (const field of Object.keys(op.data ?? {})) {\n\t\t\tconst fieldDef = collectionDef.fields[field]\n\t\t\tconst expectedBase = op.previousData?.[field]\n\t\t\tconst currentLocal = currentRecord[field]\n\n\t\t\tif (fieldDef?.kind === 'richtext') {\n\t\t\t\tif (!richtextStatesEqual(currentLocal, expectedBase)) {\n\t\t\t\t\thasConflict = true\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (!deepEqual(expectedBase, currentLocal)) {\n\t\t\t\thasConflict = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (!hasConflict) {\n\t\t\t// No CRDT/constraint field the remote op touches has diverged locally\n\t\t\t// from the base it wrote from: a clean fast-forward. Guarded, because\n\t\t\t// the divergence check above read the row outside the write transaction.\n\t\t\treturn this.deps.store.applyRemoteOperation(op, {\n\t\t\t\tforceMaterialize: true,\n\t\t\t\tguardRowState: guard,\n\t\t\t})\n\t\t}\n\n\t\treturn this.applyMergedUpdate(op, collectionDef, currentRecord, op.previousData ?? {}, guard)\n\t}\n\n\t/**\n\t * Remote update vs local soft-delete: merge before materializing to avoid zombie rows.\n\t */\n\t/**\n\t * Emit merge observability (trace + conflict counter) for a scalar update that\n\t * concurrently touches a field a local operation also changed.\n\t *\n\t * The store resolves the actual value by deterministic per-field LWW; this\n\t * method exists only so the decision is loggable (CLAUDE.md: every merge\n\t * decision must be traceable). It reads the local operation from the append-\n\t * only log — which is immutable — rather than the materialized row, so it is\n\t * not subject to the read-then-write race the store write path was hardened\n\t * against. The merge engine is invoked purely to build an accurate trace; its\n\t * timestamps match the store's LWW comparison, so the trace never lies.\n\t */\n\tprivate async observeScalarMerge(\n\t\top: Operation,\n\t\tcollectionDef: CollectionDefinition,\n\t): Promise<void> {\n\t\tconst localOp = await this.deps.store.getLatestLocalOperationForRecord(\n\t\t\top.collection,\n\t\t\top.recordId,\n\t\t)\n\t\tif (!localOp || !localOp.data) {\n\t\t\treturn\n\t\t}\n\t\tconst remoteFields = Object.keys(op.data ?? {})\n\t\tconst sharesField = remoteFields.some((field) => localOp.data?.[field] !== undefined)\n\t\tif (!sharesField) {\n\t\t\treturn\n\t\t}\n\n\t\tconst mergeResult = await this.deps.mergeEngine.merge({\n\t\t\tlocal: localOp,\n\t\t\tremote: op,\n\t\t\tbaseState: op.previousData ?? {},\n\t\t\tcollectionDef,\n\t\t})\n\t\tthis.emitMergeLifecycle(op, localOp, mergeResult)\n\t}\n\n\tprivate async applyRemoteUpdateOnDeletedRow(\n\t\top: Operation,\n\t\tcollectionDef: CollectionDefinition,\n\t\tguard: RowVersionState,\n\t): Promise<ApplyResult | null> {\n\t\tconst snapshot = await this.deps.store.findMaterializedRow(op.collection, op.recordId)\n\t\tif (!snapshot?.deleted) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst localOp = await this.deps.store.getLatestLocalOperationForRecord(\n\t\t\top.collection,\n\t\t\top.recordId,\n\t\t)\n\t\tif (!localOp || localOp.type !== 'delete') {\n\t\t\treturn null\n\t\t}\n\n\t\tconst mergeResult = await this.deps.mergeEngine.merge({\n\t\t\tlocal: localOp,\n\t\t\tremote: op,\n\t\t\tbaseState: op.previousData ?? {},\n\t\t\tcollectionDef,\n\t\t})\n\n\t\tif (mergeResult.appliedOperation === 'local') {\n\t\t\tthis.emitMergeLifecycle(op, localOp, mergeResult)\n\t\t\treturn 'skipped'\n\t\t}\n\n\t\t// The log keeps the canonical op; only the ROW materializes the merged\n\t\t// data at max(local, remote). Guarded: a local write between our snapshot\n\t\t// read and this apply invalidates the merge and triggers a retry.\n\t\tconst applyResult = await this.deps.store.applyRemoteOperation(op, {\n\t\t\treactivateIfDeleted: true,\n\t\t\tforceMaterialize: true,\n\t\t\tmaterializeData: { ...mergeResult.mergedData },\n\t\t\tmaterializeTimestamp: maxTimestamp(op.timestamp, localOp.timestamp),\n\t\t\tguardRowState: guard,\n\t\t})\n\n\t\tthis.emitMergeLifecycle(op, localOp, mergeResult)\n\n\t\tif (applyResult === 'applied' && mergeResult.sideEffects.length > 0) {\n\t\t\tawait applySideEffectOps(this.deps.store, mergeResult.sideEffects, op.id)\n\t\t}\n\n\t\treturn applyResult\n\t}\n\n\tprivate async applyMergedUpdate(\n\t\top: Operation,\n\t\tcollectionDef: CollectionDefinition,\n\t\tcurrentRecord: CollectionRecord,\n\t\tbaseState: Record<string, unknown>,\n\t\tguard: RowVersionState,\n\t\tapplyOptions?: ApplyRemoteOptions,\n\t): Promise<ApplyResult> {\n\t\tconst latestLocal = await this.deps.store.getLatestLocalOperationForRecord(\n\t\t\top.collection,\n\t\t\top.recordId,\n\t\t)\n\t\tconst localTimestamp = resolveLocalTimestamp(\n\t\t\tlatestLocal,\n\t\t\tcurrentRecord,\n\t\t\tthis.deps.store.getNodeId(),\n\t\t)\n\t\t// The spread of `op` would copy the REMOTE op's atomicOps onto the local\n\t\t// side, making atomic composition double the remote delta instead of\n\t\t// summing both intents. The local side's intent metadata must come from\n\t\t// the actual local operation — or be absent entirely.\n\t\tconst { atomicOps: _remoteAtomicOps, ...opWithoutAtomic } = op\n\t\tconst localOp: Operation = {\n\t\t\t...opWithoutAtomic,\n\t\t\tdata: buildLocalDiff(baseState, currentRecord, Object.keys(op.data ?? {})),\n\t\t\tpreviousData: op.previousData,\n\t\t\tnodeId: this.deps.store.getNodeId(),\n\t\t\ttimestamp: localTimestamp,\n\t\t\t...(latestLocal?.atomicOps !== undefined ? { atomicOps: latestLocal.atomicOps } : {}),\n\t\t}\n\n\t\tconst constraintContext = createConstraintContext(this.deps.store)\n\t\tconst mergeResult = await this.deps.mergeEngine.merge(\n\t\t\t{\n\t\t\t\tlocal: localOp,\n\t\t\t\tremote: op,\n\t\t\t\tbaseState,\n\t\t\t\tcollectionDef,\n\t\t\t},\n\t\t\tconstraintContext,\n\t\t)\n\n\t\t// The merged data is authoritative (it already folds in the current local\n\t\t// row), so it must materialize even when its timestamp ties the current\n\t\t// row version — otherwise the device that authored the newer of two\n\t\t// concurrent edits silently drops the merge result and never converges.\n\t\t// The LOG stores the canonical op (ops are immutable, content-addressed);\n\t\t// only the row write uses the merged data and max(local, remote) stamp.\n\t\t// Guarded: a local write since our snapshot invalidates the merge.\n\t\tconst applyResult = await this.deps.store.applyRemoteOperation(op, {\n\t\t\t...applyOptions,\n\t\t\tforceMaterialize: true,\n\t\t\tmaterializeData: mergeResult.mergedData,\n\t\t\tmaterializeTimestamp: maxTimestamp(op.timestamp, localTimestamp),\n\t\t\tguardRowState: guard,\n\t\t})\n\n\t\t// Emit AFTER the guarded apply so a retried attempt doesn't double-report\n\t\t// a merge decision that never materialized.\n\t\tthis.emitMergeLifecycle(op, localOp, mergeResult)\n\n\t\tif (applyResult === 'applied' && mergeResult.sideEffects.length > 0) {\n\t\t\tawait applySideEffectOps(this.deps.store, mergeResult.sideEffects, op.id)\n\t\t}\n\n\t\treturn applyResult\n\t}\n\n\tprivate async applyRemoteInsert(op: Operation): Promise<ApplyResult> {\n\t\tconst collectionDef = this.deps.store.getSchema().collections[op.collection]\n\t\tif (!collectionDef || !op.data) {\n\t\t\treturn this.deps.store.applyRemoteOperation(op)\n\t\t}\n\n\t\tlet lockError: OptimisticLockError | null = null\n\t\tfor (let attempt = 0; attempt < MERGE_APPLY_RETRY_LIMIT; attempt++) {\n\t\t\ttry {\n\t\t\t\treturn await this.applyRemoteInsertAttempt(op, collectionDef)\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof OptimisticLockError)) {\n\t\t\t\t\tthrow error\n\t\t\t\t}\n\t\t\t\tlockError = error\n\t\t\t}\n\t\t}\n\t\tthrow lockError ?? new OptimisticLockError(op.collection, op.recordId)\n\t}\n\n\tprivate async applyRemoteInsertAttempt(\n\t\top: Operation,\n\t\tcollectionDef: CollectionDefinition,\n\t): Promise<ApplyResult> {\n\t\t// Guard snapshot BEFORE the record read (see applyRemoteUpdateAttempt).\n\t\tconst guard: RowVersionState = (await this.deps.store.getRowVersionState(\n\t\t\top.collection,\n\t\t\top.recordId,\n\t\t)) ?? { version: null, fieldVersions: null }\n\n\t\tconst snapshot = await this.deps.store.findMaterializedRow(op.collection, op.recordId)\n\t\tif (!snapshot || snapshot.deleted) {\n\t\t\t// Absent row and insert-vs-tombstone are resolved atomically inside the\n\t\t\t// store; guard against a local write racing this decision.\n\t\t\treturn this.deps.store.applyRemoteOperation(op, { guardRowState: guard })\n\t\t}\n\n\t\tconst localOp = await resolveLocalOpForRecord(\n\t\t\tthis.deps.store,\n\t\t\top.collection,\n\t\t\top.recordId,\n\t\t\tsnapshot.record,\n\t\t)\n\n\t\tconst mergeResult = await this.deps.mergeEngine.merge({\n\t\t\tlocal: localOp,\n\t\t\tremote: op,\n\t\t\tbaseState: {},\n\t\t\tcollectionDef,\n\t\t})\n\n\t\t// Canonical op in the log; merged data + max(local, remote) stamp on the\n\t\t// row. Force, because the merged result folds in the current local row and\n\t\t// must win even on a version tie with it.\n\t\tconst applyResult = await this.deps.store.applyRemoteOperation(op, {\n\t\t\tforceMaterialize: true,\n\t\t\tmaterializeData: mergeResult.mergedData,\n\t\t\tmaterializeTimestamp: maxTimestamp(op.timestamp, localOp.timestamp),\n\t\t\tguardRowState: guard,\n\t\t})\n\n\t\tthis.emitMergeLifecycle(op, localOp, mergeResult)\n\n\t\treturn applyResult\n\t}\n\n\tprivate emitMergeLifecycle(remote: Operation, local: Operation, mergeResult: MergeResult): void {\n\t\tthis.deps.emitter?.emit({\n\t\t\ttype: 'merge:started',\n\t\t\toperationA: remote,\n\t\t\toperationB: local,\n\t\t})\n\n\t\tconst hadMergeConflict = mergeResult.traces.some(\n\t\t\t(t) =>\n\t\t\t\tt.strategy !== 'no-conflict-local' &&\n\t\t\t\tt.strategy !== 'no-conflict-remote' &&\n\t\t\t\tt.strategy !== 'no-conflict-unchanged',\n\t\t)\n\t\tif (hadMergeConflict) {\n\t\t\tthis.deps.onMergeConflict?.()\n\t\t}\n\n\t\tfor (const trace of mergeResult.traces) {\n\t\t\tif (\n\t\t\t\ttrace.strategy !== 'no-conflict-local' &&\n\t\t\t\ttrace.strategy !== 'no-conflict-remote' &&\n\t\t\t\ttrace.strategy !== 'no-conflict-unchanged'\n\t\t\t) {\n\t\t\t\tthis.deps.emitter?.emit({ type: 'merge:conflict', trace })\n\t\t\t}\n\t\t}\n\t\tconst firstTrace = mergeResult.traces[0]\n\t\tif (firstTrace) {\n\t\t\tthis.deps.emitter?.emit({ type: 'merge:completed', trace: firstTrace })\n\t\t}\n\t}\n}\n\n/**\n * Prefer the latest local op, then any op in the log for this record, then a snapshot-derived insert.\n */\nasync function resolveLocalOpForRecord(\n\tstore: Store,\n\tcollection: string,\n\trecordId: string,\n\trecord: CollectionRecord,\n): Promise<Operation> {\n\tconst localLatest = await store.getLatestLocalOperationForRecord(collection, recordId)\n\tif (localLatest) {\n\t\treturn localLatest\n\t}\n\n\tconst anyLatest = await store.getLatestOperationForRecord(collection, recordId)\n\tif (anyLatest) {\n\t\treturn anyLatest\n\t}\n\n\treturn syntheticInsertFromSnapshot(\n\t\trecord,\n\t\tcollection,\n\t\tstore.getNodeId(),\n\t\tstore.getSchema().version,\n\t)\n}\n\nfunction syntheticInsertFromSnapshot(\n\trecord: CollectionRecord,\n\tcollection: string,\n\tnodeId: string,\n\tschemaVersion: number,\n): Operation {\n\tconst { id, createdAt, updatedAt, ...fields } = record\n\treturn {\n\t\tid: `synthetic-local-${id}`,\n\t\tnodeId,\n\t\ttype: 'insert',\n\t\tcollection,\n\t\trecordId: id,\n\t\tdata: fields,\n\t\tpreviousData: null,\n\t\ttimestamp: { wallTime: updatedAt, logical: 0, nodeId },\n\t\tsequenceNumber: 0,\n\t\tcausalDeps: [],\n\t\tschemaVersion,\n\t}\n}\n\nfunction createConstraintContext(store: Store): ConstraintContext {\n\treturn {\n\t\tasync queryRecords(collection: string, where: Record<string, unknown>) {\n\t\t\tconst rows = await store.collection(collection).where(where).exec()\n\t\t\treturn rows as Record<string, unknown>[]\n\t\t},\n\t\tasync countRecords(collection: string, where: Record<string, unknown>) {\n\t\t\treturn store.collection(collection).where(where).count()\n\t\t},\n\t}\n}\n\nfunction createReferentialMergeContext(store: Store): ReferentialMergeContext {\n\treturn {\n\t\tasync queryRecords(collection: string, where: Record<string, unknown>) {\n\t\t\tconst rows = await store.collection(collection).where(where).exec()\n\t\t\treturn rows as Record<string, unknown>[]\n\t\t},\n\t\tasync recordExists(collection: string, recordId: string) {\n\t\t\tconst row = await store.collection(collection).findById(recordId)\n\t\t\treturn row !== null\n\t\t},\n\t}\n}\n\nasync function applySideEffectOps(\n\tstore: Store,\n\tsideEffects: SideEffectOp[],\n\tparentOpId: string,\n): Promise<void> {\n\tfor (const effect of sideEffects) {\n\t\tconst ctx = store.createMutationContext(effect.collection, {\n\t\t\textraCausalDeps: [parentOpId],\n\t\t})\n\t\tif (effect.type === 'delete') {\n\t\t\tawait executeDelete(ctx, effect.recordId, { skipReferentialEnforcement: true })\n\t\t} else if (effect.type === 'update' && effect.data) {\n\t\t\tawait executeUpdate(ctx, effect.recordId, effect.data)\n\t\t}\n\t}\n}\n\n/**\n * Whether applying this remote update requires the three-tier merge engine.\n *\n * Scalar fields converge under deterministic per-field LWW handled entirely in\n * the store. The merge engine is only needed when a changed field is a CRDT\n * (richtext or add-wins-set array), when the collection declares constraints, or\n * when a changed field has a custom resolver.\n */\nfunction updateNeedsMergeEngine(op: Operation, collectionDef: CollectionDefinition): boolean {\n\tif (collectionDef.constraints.length > 0) {\n\t\treturn true\n\t}\n\t// Intent-preserving atomic ops (increment/max/min) COMPOSE with a concurrent\n\t// local atomic op instead of last-write-wins — plain per-field LWW would\n\t// silently drop one side's delta (a lost update).\n\tif (op.atomicOps && Object.keys(op.atomicOps).length > 0) {\n\t\treturn true\n\t}\n\tfor (const field of Object.keys(op.data ?? {})) {\n\t\tconst kind = collectionDef.fields[field]?.kind\n\t\tif (kind === 'richtext' || kind === 'array') {\n\t\t\treturn true\n\t\t}\n\t\tif (collectionDef.resolvers[field]) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunction buildLocalDiff(\n\tbaseState: Record<string, unknown>,\n\tcurrentRecord: Record<string, unknown>,\n\tfields: string[],\n): Record<string, unknown> {\n\tconst diff: Record<string, unknown> = {}\n\tfor (const field of fields) {\n\t\tdiff[field] = currentRecord[field]\n\t}\n\treturn diff\n}\n\nfunction resolveLocalTimestamp(\n\tlatestLocal: Operation | null,\n\tcurrentRecord: CollectionRecord,\n\tnodeId: string,\n): HLCTimestamp {\n\tif (latestLocal) {\n\t\treturn latestLocal.timestamp\n\t}\n\tconst updatedAt = currentRecord.updatedAt\n\tif (typeof updatedAt === 'number') {\n\t\treturn { wallTime: updatedAt, logical: 0, nodeId }\n\t}\n\treturn { wallTime: Date.now(), logical: 0, nodeId }\n}\n\nfunction maxTimestamp(a: HLCTimestamp, b: HLCTimestamp): HLCTimestamp {\n\treturn HybridLogicalClock.compare(a, b) >= 0 ? a : b\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n\tif (a === b) return true\n\tif (a === null || b === null) return false\n\tif (a === undefined || b === undefined) return false\n\tif (typeof a !== typeof b) return false\n\n\tif (Array.isArray(a) && Array.isArray(b)) {\n\t\tif (a.length !== b.length) return false\n\t\treturn a.every((val, i) => deepEqual(val, b[i]))\n\t}\n\n\tif (typeof a === 'object' && typeof b === 'object') {\n\t\tconst keysA = Object.keys(a as Record<string, unknown>)\n\t\tconst keysB = Object.keys(b as Record<string, unknown>)\n\t\tif (keysA.length !== keysB.length) return false\n\t\treturn keysA.every((key) =>\n\t\t\tdeepEqual((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key]),\n\t\t)\n\t}\n\n\treturn false\n}\n","import { createOperation } from '@korajs/core'\nimport type { SideEffectOp } from '@korajs/merge'\nimport type { TransactionBufferedEntry } from '@korajs/store'\nimport type { LocalMutationContext } from '@korajs/store/internal'\nimport {\n\tbuildInsertQuery,\n\tbuildSoftDeleteQuery,\n\tbuildUpdateQuery,\n\tserializeOperation,\n\tserializeRecord,\n\tserializeRowVersion,\n} from '@korajs/store/internal'\n\n/**\n * Materialize a merge-package referential side effect as an operation log entry + SQL commands.\n */\nexport async function buildSideEffectEntry(\n\tctx: LocalMutationContext,\n\teffect: SideEffectOp,\n\tparentOpId: string,\n\ttransactionId?: string,\n\tmutationName?: string,\n): Promise<TransactionBufferedEntry> {\n\tconst causalDeps = [parentOpId]\n\tconst baseInput = {\n\t\tnodeId: ctx.nodeId,\n\t\tcollection: effect.collection,\n\t\trecordId: effect.recordId,\n\t\tsequenceNumber: await ctx.allocateSequenceNumber(),\n\t\tcausalDeps,\n\t\tschemaVersion: ctx.schema.version,\n\t\t...(transactionId !== undefined ? { transactionId } : {}),\n\t\t...(mutationName !== undefined ? { mutationName } : {}),\n\t}\n\n\tif (effect.type === 'delete') {\n\t\tconst operation = await createOperation(\n\t\t\t{\n\t\t\t\t...baseInput,\n\t\t\t\ttype: 'delete',\n\t\t\t\tdata: null,\n\t\t\t\tpreviousData: effect.previousData,\n\t\t\t},\n\t\t\tctx.clock,\n\t\t)\n\t\tctx.causalTracker?.afterOperation(effect.collection, operation.id, ctx.inTransaction)\n\n\t\tconst version = serializeRowVersion(operation.timestamp)\n\t\tconst deleteQuery = buildSoftDeleteQuery(\n\t\t\teffect.collection,\n\t\t\teffect.recordId,\n\t\t\toperation.timestamp.wallTime,\n\t\t\tversion,\n\t\t)\n\t\tconst opInsert = buildInsertQuery(\n\t\t\t`_kora_ops_${effect.collection}`,\n\t\t\tserializeOperation(operation) as unknown as Record<string, unknown>,\n\t\t)\n\n\t\treturn {\n\t\t\toperation,\n\t\t\tcollection: effect.collection,\n\t\t\tcommands: [\n\t\t\t\t{ sql: deleteQuery.sql, params: deleteQuery.params },\n\t\t\t\t{ sql: opInsert.sql, params: opInsert.params },\n\t\t\t\t{\n\t\t\t\t\tsql: 'INSERT OR REPLACE INTO _kora_version_vector (node_id, sequence_number) VALUES (?, ?)',\n\t\t\t\t\tparams: [ctx.nodeId, operation.sequenceNumber],\n\t\t\t\t},\n\t\t\t],\n\t\t}\n\t}\n\n\tconst operation = await createOperation(\n\t\t{\n\t\t\t...baseInput,\n\t\t\ttype: 'update',\n\t\t\tdata: effect.data,\n\t\t\tpreviousData: effect.previousData,\n\t\t},\n\t\tctx.clock,\n\t)\n\tctx.causalTracker?.afterOperation(effect.collection, operation.id, ctx.inTransaction)\n\n\tconst definition = ctx.schema.collections[effect.collection]\n\tconst serializedChanges =\n\t\teffect.data && definition\n\t\t\t? serializeRecord(effect.data, definition.fields)\n\t\t\t: (effect.data ?? {})\n\tconst version = serializeRowVersion(operation.timestamp)\n\tconst updateQuery = buildUpdateQuery(effect.collection, effect.recordId, {\n\t\t...serializedChanges,\n\t\t_updated_at: operation.timestamp.wallTime,\n\t\t_version: version,\n\t})\n\tconst opInsert = buildInsertQuery(\n\t\t`_kora_ops_${effect.collection}`,\n\t\tserializeOperation(operation) as unknown as Record<string, unknown>,\n\t)\n\n\treturn {\n\t\toperation,\n\t\tcollection: effect.collection,\n\t\tcommands: [\n\t\t\t{ sql: updateQuery.sql, params: updateQuery.params },\n\t\t\t{ sql: opInsert.sql, params: opInsert.params },\n\t\t\t{\n\t\t\t\tsql: 'INSERT OR REPLACE INTO _kora_version_vector (node_id, sequence_number) VALUES (?, ?)',\n\t\t\t\tparams: [ctx.nodeId, operation.sequenceNumber],\n\t\t\t},\n\t\t],\n\t}\n}\n","import type { KoraEvent, KoraEventEmitter } from '@korajs/core'\nimport type { Store } from '@korajs/store'\nimport { persistedAuditTraceFromEvent } from '@korajs/store'\n\nconst AUDIT_EVENT_TYPES = ['merge:completed', 'merge:conflict', 'constraint:violated'] as const\n\ntype AuditEventType = (typeof AUDIT_EVENT_TYPES)[number]\n\nfunction isAuditEvent(event: KoraEvent): event is Extract<KoraEvent, { type: AuditEventType }> {\n\treturn (AUDIT_EVENT_TYPES as readonly string[]).includes(event.type)\n}\n\n/**\n * Persist merge and constraint traces from the event bus to `_kora_audit_traces`.\n */\nexport function wireAuditPersistence(store: Store, emitter: KoraEventEmitter): () => void {\n\tconst unsubscribers = AUDIT_EVENT_TYPES.map((eventType) =>\n\t\temitter.on(eventType, (event) => {\n\t\t\tif (!isAuditEvent(event)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst trace = persistedAuditTraceFromEvent(event)\n\t\t\tvoid store.appendAuditTrace(trace).catch(() => {\n\t\t\t\t// Audit persistence must not break mutations or sync.\n\t\t\t})\n\t\t}),\n\t)\n\n\treturn () => {\n\t\tfor (const unsub of unsubscribers) {\n\t\t\tunsub()\n\t\t}\n\t}\n}\n","import type { KoraEventEmitter, Operation, VersionVector } from '@korajs/core'\nimport type { MergeEngine } from '@korajs/merge'\nimport type { Store } from '@korajs/store'\nimport type { ApplyResult, SyncStore } from '@korajs/sync'\nimport { ApplyPipeline } from './apply-pipeline'\n\nexport interface MergeAwareSyncStoreOptions {\n\t/** Increments SyncEngine conflict counter when merge runs on a conflicting update. */\n\tonMergeConflict?: () => void\n}\n\n/**\n * Wraps a Store to route remote sync operations through {@link ApplyPipeline}.\n *\n * Ensures remote deletes honor referential integrity (cascade, set-null, restrict)\n * and remote updates use the full three-tier merge engine with constraint context.\n */\nexport class MergeAwareSyncStore implements SyncStore {\n\tprivate readonly pipeline: ApplyPipeline\n\n\tconstructor(\n\t\tprivate readonly store: Store,\n\t\tmergeEngine: MergeEngine,\n\t\temitter: KoraEventEmitter | null,\n\t\toptions?: MergeAwareSyncStoreOptions,\n\t) {\n\t\tthis.pipeline = new ApplyPipeline({\n\t\t\tstore,\n\t\t\tmergeEngine,\n\t\t\temitter,\n\t\t\tonMergeConflict: options?.onMergeConflict,\n\t\t})\n\t}\n\n\tgetVersionVector(): VersionVector {\n\t\treturn this.store.getVersionVector()\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.store.getNodeId()\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\treturn this.store.getOperationRange(nodeId, fromSeq, toSeq)\n\t}\n\n\tasync applyRemoteOperation(op: Operation): Promise<ApplyResult> {\n\t\treturn this.pipeline.applyRemote(op)\n\t}\n\n\t/**\n\t * Delegates timestamp rebase to the store so the sync engine can re-stamp\n\t * never-acknowledged operations after a fast device clock is corrected.\n\t */\n\tasync rebaseUnsyncedOperations(\n\t\tids: string[],\n\t\tcorrectedNowMs: number,\n\t): Promise<{ operations: Operation[]; idMapping: Record<string, string>; rebasedCount: number }> {\n\t\treturn this.store.rebaseUnsyncedOperations(ids, correctedNowMs)\n\t}\n}\n","import type { Operation } from '@korajs/core'\nimport type { StorageAdapter } from '@korajs/store'\nimport { deserializeOperation, serializeOperation } from '@korajs/store/internal'\nimport type { OperationRow } from '@korajs/store/internal'\nimport type { QueueStorage } from '@korajs/sync'\n\ninterface SyncQueueRow {\n\tid: string\n\tpayload: string\n}\n\ntype QueuePayload = OperationRow & { _collection: string }\n\n/**\n * Persists the outbound sync queue in `_kora_sync_queue` via the local StorageAdapter.\n */\nexport class StoreQueueStorage implements QueueStorage {\n\tconstructor(private readonly adapter: StorageAdapter) {}\n\n\tasync load(): Promise<Operation[]> {\n\t\tconst rows = await this.adapter.query<SyncQueueRow>(\n\t\t\t'SELECT id, payload FROM _kora_sync_queue ORDER BY rowid ASC',\n\t\t)\n\t\treturn rows.map((row) => operationFromQueuePayload(row.payload))\n\t}\n\n\tasync enqueue(op: Operation): Promise<void> {\n\t\tconst row = serializeOperation(op)\n\t\tconst payload: QueuePayload = { ...row, _collection: op.collection }\n\t\tawait this.adapter.execute(\n\t\t\t'INSERT OR REPLACE INTO _kora_sync_queue (id, payload) VALUES (?, ?)',\n\t\t\t[op.id, JSON.stringify(payload)],\n\t\t)\n\t}\n\n\tasync dequeue(ids: string[]): Promise<void> {\n\t\tif (ids.length === 0) return\n\t\tconst placeholders = ids.map(() => '?').join(', ')\n\t\tawait this.adapter.execute(`DELETE FROM _kora_sync_queue WHERE id IN (${placeholders})`, ids)\n\t}\n\n\tasync count(): Promise<number> {\n\t\tconst rows = await this.adapter.query<{ cnt: number }>(\n\t\t\t'SELECT COUNT(*) as cnt FROM _kora_sync_queue',\n\t\t)\n\t\treturn rows[0]?.cnt ?? 0\n\t}\n}\n\nfunction operationFromQueuePayload(payload: string): Operation {\n\tconst parsed = JSON.parse(payload) as QueuePayload\n\tconst op = deserializeOperation(parsed)\n\treturn {\n\t\t...op,\n\t\tcollection: parsed._collection,\n\t}\n}\n","import type { Operation, VersionVector } from '@korajs/core'\nimport { mergeVersionVectors } from '@korajs/store'\nimport type { Store } from '@korajs/store'\nimport { decodeDeltaCursor, encodeDeltaCursor, operationMatchesScope } from '@korajs/sync'\nimport type { DeltaCursor, SyncScopeMap, SyncStatePersistence } from '@korajs/sync'\n\n/**\n * Persists and queries sync acknowledgment state via the local Store.\n */\nexport class StoreSyncStatePersistence implements SyncStatePersistence {\n\tconstructor(\n\t\tprivate readonly store: Store,\n\t\tprivate readonly scope?: SyncScopeMap,\n\t) {}\n\n\tloadLastAckedServerVector(): Promise<VersionVector> {\n\t\treturn this.store.loadLastAckedServerVector()\n\t}\n\n\tsaveLastAckedServerVector(vector: VersionVector): Promise<void> {\n\t\treturn this.store.saveLastAckedServerVector(vector)\n\t}\n\n\tmergeServerVectors(a: VersionVector, b: VersionVector): VersionVector {\n\t\treturn this.store.mergeServerVectors(a, b)\n\t}\n\n\tasync countUnsyncedOperations(serverVector: VersionVector): Promise<number> {\n\t\tconst ops = await this.getUnsyncedOperations(serverVector)\n\t\treturn ops.length\n\t}\n\n\tasync getUnsyncedOperations(serverVector: VersionVector): Promise<Operation[]> {\n\t\tconst ops = await this.store.getUnsyncedOperations(serverVector)\n\t\treturn ops.filter((op) => operationMatchesScope(op, this.scope))\n\t}\n\n\tloadDeltaCursor(): Promise<DeltaCursor | null> {\n\t\treturn this.store.loadDeltaCursor().then((encoded) => decodeDeltaCursor(encoded))\n\t}\n\n\tasync saveDeltaCursor(cursor: DeltaCursor | null): Promise<void> {\n\t\tawait this.store.saveDeltaCursor(cursor ? encodeDeltaCursor(cursor) : null)\n\t}\n}\n"],"mappings":"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","names":["createOperation","operation","version","opInsert","createOperation","ctx","serializeOperation"]}
|