korajs 0.4.0 → 0.6.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/apply-pipeline.ts","../src/build-side-effect-entry.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\tStore,\n\tTransactionCommitBatch,\n\tTransactionCommitResult,\n} from '@korajs/store'\nimport { 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 * 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\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)\n\t\t\tif (tombstoneResult !== null) {\n\t\t\t\treturn tombstoneResult\n\t\t\t}\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\treturn this.deps.store.applyRemoteOperation(op)\n\t\t}\n\n\t\treturn this.applyMergedUpdate(op, collectionDef, currentRecord, op.previousData ?? {})\n\t}\n\n\t/**\n\t * Remote update vs local soft-delete: merge before materializing to avoid zombie rows.\n\t */\n\tprivate async applyRemoteUpdateOnDeletedRow(\n\t\top: Operation,\n\t\tcollectionDef: CollectionDefinition,\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\tthis.emitMergeLifecycle(op, localOp, mergeResult)\n\n\t\tif (mergeResult.appliedOperation === 'local') {\n\t\t\treturn 'skipped'\n\t\t}\n\n\t\tconst mergedOp: Operation = {\n\t\t\t...op,\n\t\t\tdata: { ...mergeResult.mergedData },\n\t\t\ttimestamp: maxTimestamp(op.timestamp, localOp.timestamp),\n\t\t}\n\n\t\tconst applyResult = await this.deps.store.applyRemoteOperation(mergedOp, {\n\t\t\treactivateIfDeleted: true,\n\t\t})\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\tapplyOptions?: ApplyRemoteOptions,\n\t): Promise<ApplyResult> {\n\t\tconst localTimestamp = await resolveLocalTimestamp(\n\t\t\tthis.deps.store,\n\t\t\top.collection,\n\t\t\top.recordId,\n\t\t\tcurrentRecord,\n\t\t\tthis.deps.store.getNodeId(),\n\t\t)\n\t\tconst localOp: Operation = {\n\t\t\t...op,\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}\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\tthis.emitMergeLifecycle(op, localOp, mergeResult)\n\n\t\tconst mergedOp: Operation = {\n\t\t\t...op,\n\t\t\tdata: mergeResult.mergedData,\n\t\t\ttimestamp: maxTimestamp(op.timestamp, localTimestamp),\n\t\t}\n\n\t\tconst applyResult = await this.deps.store.applyRemoteOperation(mergedOp, applyOptions)\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\tconst snapshot = await this.deps.store.findMaterializedRow(op.collection, op.recordId)\n\t\tif (!snapshot || snapshot.deleted) {\n\t\t\treturn this.deps.store.applyRemoteOperation(op)\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\tthis.emitMergeLifecycle(op, localOp, mergeResult)\n\n\t\tconst mergedOp: Operation = {\n\t\t\t...op,\n\t\t\tdata: mergeResult.mergedData,\n\t\t\ttimestamp: maxTimestamp(op.timestamp, localOp.timestamp),\n\t\t}\n\n\t\treturn this.deps.store.applyRemoteOperation(mergedOp)\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\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\nasync function resolveLocalTimestamp(\n\tstore: Store,\n\tcollection: string,\n\trecordId: string,\n\tcurrentRecord: CollectionRecord,\n\tnodeId: string,\n): Promise<HLCTimestamp> {\n\tconst latestLocal = await store.getLatestLocalOperationForRecord(collection, recordId)\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 { 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","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"]}