@korajs/store 0.6.0 → 1.0.0-beta.1
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/adapters/better-sqlite3.cjs +94 -40
- package/dist/adapters/better-sqlite3.cjs.map +1 -1
- package/dist/adapters/better-sqlite3.d.cts +9 -1
- package/dist/adapters/better-sqlite3.d.ts +9 -1
- package/dist/adapters/better-sqlite3.js +62 -41
- package/dist/adapters/better-sqlite3.js.map +1 -1
- package/dist/adapters/indexeddb.cjs +24 -13
- package/dist/adapters/indexeddb.cjs.map +1 -1
- package/dist/adapters/indexeddb.d.cts +2 -2
- package/dist/adapters/indexeddb.d.ts +2 -2
- package/dist/adapters/indexeddb.js +4 -3
- package/dist/adapters/indexeddb.js.map +1 -1
- package/dist/adapters/sqlite-wasm.cjs +24 -13
- package/dist/adapters/sqlite-wasm.cjs.map +1 -1
- package/dist/adapters/sqlite-wasm.d.cts +27 -4
- package/dist/adapters/sqlite-wasm.d.ts +27 -4
- package/dist/adapters/sqlite-wasm.js +6 -4
- package/dist/{backup-JN3LB4YT.js → backup-ZV4Y424B.js} +3 -3
- package/dist/blob-fs.cjs +166 -0
- package/dist/blob-fs.cjs.map +1 -0
- package/dist/blob-fs.d.cts +29 -0
- package/dist/blob-fs.d.ts +29 -0
- package/dist/blob-fs.js +128 -0
- package/dist/blob-fs.js.map +1 -0
- package/dist/{chunk-56LL4XP6.js → chunk-6NKLDBTY.js} +52 -1
- package/dist/chunk-6NKLDBTY.js.map +1 -0
- package/dist/{chunk-AGN3CIPB.js → chunk-FFYA7J5H.js} +2 -2
- package/dist/{chunk-XO4LMPAH.js → chunk-IOEFNHHP.js} +2 -35
- package/dist/chunk-IOEFNHHP.js.map +1 -0
- package/dist/{chunk-LAWV6CFH.js → chunk-QL2XVZRN.js} +12 -1
- package/dist/chunk-QL2XVZRN.js.map +1 -0
- package/dist/{chunk-6AHYGQQT.js → chunk-RBPVEAVM.js} +4 -4
- package/dist/chunk-TVJEC5S2.js +40 -0
- package/dist/chunk-TVJEC5S2.js.map +1 -0
- package/dist/chunk-W4MTTNEZ.js +55 -0
- package/dist/chunk-W4MTTNEZ.js.map +1 -0
- package/dist/{chunk-EZSTD2XC.js → chunk-X57MWW35.js} +2 -2
- package/dist/{chunk-7BPETY5Y.js → chunk-ZLWAYQEQ.js} +128 -15
- package/dist/chunk-ZLWAYQEQ.js.map +1 -0
- package/dist/content-addressed-blob-store-Dcj3SB9r.d.cts +60 -0
- package/dist/content-addressed-blob-store-Dcj3SB9r.d.ts +60 -0
- package/dist/{export-audit-5GV6VRDZ.js → export-audit-AJ7RORNK.js} +3 -3
- package/dist/index.cjs +1245 -113
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +468 -7
- package/dist/index.d.ts +468 -7
- package/dist/index.js +975 -61
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +123 -33
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +3 -3
- package/dist/internal.d.ts +3 -3
- package/dist/internal.js +3 -3
- package/dist/{sqlite-wasm-channel-I9y_jObg.d.cts → sqlite-wasm-channel-DUDPclTE.d.cts} +2 -15
- package/dist/{sqlite-wasm-channel-I9y_jObg.d.ts → sqlite-wasm-channel-DUDPclTE.d.ts} +2 -15
- package/dist/sqlite-wasm-channel-H43KEZLM.js +12 -0
- package/dist/{types-CTr00g_d.d.cts → types-5h4Hqcwc.d.ts} +10 -3
- package/dist/{types-BMyHmwvn.d.ts → types-DfPiPwKr.d.cts} +10 -3
- package/dist/{types-DepnRDk_.d.cts → types-k6AZgiH4.d.cts} +48 -2
- package/dist/{types-DepnRDk_.d.ts → types-k6AZgiH4.d.ts} +48 -2
- package/package.json +15 -2
- package/dist/chunk-56LL4XP6.js.map +0 -1
- package/dist/chunk-7BPETY5Y.js.map +0 -1
- package/dist/chunk-LAWV6CFH.js.map +0 -1
- package/dist/chunk-XO4LMPAH.js.map +0 -1
- package/dist/sqlite-wasm-channel-HDDW6UBH.js +0 -10
- /package/dist/{backup-JN3LB4YT.js.map → backup-ZV4Y424B.js.map} +0 -0
- /package/dist/{chunk-AGN3CIPB.js.map → chunk-FFYA7J5H.js.map} +0 -0
- /package/dist/{chunk-6AHYGQQT.js.map → chunk-RBPVEAVM.js.map} +0 -0
- /package/dist/{chunk-EZSTD2XC.js.map → chunk-X57MWW35.js.map} +0 -0
- /package/dist/{export-audit-5GV6VRDZ.js.map → export-audit-AJ7RORNK.js.map} +0 -0
- /package/dist/{sqlite-wasm-channel-HDDW6UBH.js.map → sqlite-wasm-channel-H43KEZLM.js.map} +0 -0
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/serialization/richtext-serializer.ts","../src/serialization/serializer.ts","../src/backup/backup.ts","../src/audit/audit-json.ts","../src/audit/audit-trace-store.ts","../src/audit/export-audit.ts","../src/index.ts","../src/errors.ts","../src/compaction/types.ts","../src/compaction/compact-operation-log.ts","../src/sync/sync-state.ts","../src/store/store.ts","../src/mutations/execute-delete.ts","../src/lww/row-version.ts","../src/query/sql-builder.ts","../src/store/sequence-allocator.ts","../src/mutations/resolve-causal-deps.ts","../src/mutations/execute-insert.ts","../src/mutations/execute-update.ts","../src/state-machine/state-validator.ts","../src/collection/collection.ts","../src/query/query-builder.ts","../src/query/pluralize.ts","../src/relations/relation-enforcer.ts","../src/relations/relation-lookup.ts","../src/replay/replay-to.ts","../src/sequences/sequence-manager.ts","../src/subscription/bloom-filter.ts","../src/subscription/subscription-manager.ts","../src/transaction/transaction-context.ts","../src/transaction/transaction-sequence.ts","../src/store/tab-node-id.ts","../src/reactivity/query-store.ts","../src/reactivity/assert-query-ready.ts","../src/reactivity/query-store-cache.ts","../src/richtext/create-richtext-controller.ts","../src/richtext/as-rich-text-sync-engine.ts","../src/backup/index.ts","../src/audit/index.ts"],"sourcesContent":["import * as Y from 'yjs'\n\nconst TEXT_KEY = 'content'\n\nexport type RichtextInput = string | Uint8Array | ArrayBuffer | null | undefined\n\n/**\n * Encodes richtext values into Yjs document updates.\n */\nexport function encodeRichtext(value: RichtextInput): Uint8Array | null {\n\tif (value === null || value === undefined) {\n\t\treturn null\n\t}\n\n\tif (typeof value === 'string') {\n\t\tconst doc = new Y.Doc()\n\t\tdoc.getText(TEXT_KEY).insert(0, value)\n\t\treturn Y.encodeStateAsUpdate(doc)\n\t}\n\n\tif (value instanceof Uint8Array) {\n\t\treturn value\n\t}\n\n\tif (value instanceof ArrayBuffer) {\n\t\treturn new Uint8Array(value)\n\t}\n\n\tthrow new Error('Richtext value must be a string, Uint8Array, ArrayBuffer, null, or undefined.')\n}\n\n/**\n * Decodes driver-provided richtext values into Uint8Array.\n */\nexport function decodeRichtext(value: unknown): Uint8Array | null {\n\tif (value === null || value === undefined) {\n\t\treturn null\n\t}\n\n\tif (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {\n\t\treturn new Uint8Array(value)\n\t}\n\n\tif (value instanceof Uint8Array) {\n\t\treturn value\n\t}\n\n\tif (value instanceof ArrayBuffer) {\n\t\treturn new Uint8Array(value)\n\t}\n\n\tthrow new Error(\n\t\t'Richtext storage value must be Uint8Array, ArrayBuffer, Buffer, null, or undefined.',\n\t)\n}\n\n/**\n * Reads plain text from a richtext Yjs state update.\n */\nexport function richtextToPlainText(value: RichtextInput): string {\n\tconst encoded = encodeRichtext(value)\n\tif (!encoded) return ''\n\n\tconst doc = new Y.Doc()\n\tY.applyUpdate(doc, encoded)\n\treturn doc.getText(TEXT_KEY).toString()\n}\n\n/**\n * Compares two richtext values by decoded plain text.\n * Yjs update bytes are not stable across separate encodes of the same string.\n */\nexport function richtextStatesEqual(a: unknown, b: unknown): boolean {\n\ttry {\n\t\treturn richtextToPlainText(a as RichtextInput) === richtextToPlainText(b as RichtextInput)\n\t} catch {\n\t\treturn false\n\t}\n}\n","import { HybridLogicalClock } from '@korajs/core'\nimport type { CollectionDefinition, FieldDescriptor, Operation } from '@korajs/core'\nimport type { CollectionRecord, OperationRow, RawCollectionRow } from '../types'\nimport { decodeRichtext, encodeRichtext } from './richtext-serializer'\n\n/**\n * Serialize a JS record to SQL-compatible values for INSERT/UPDATE.\n * Transforms: boolean → 0/1, array → JSON string, richtext → Yjs binary update.\n *\n * @param data - The record data with JS-native types\n * @param fields - The field descriptors from the schema\n * @returns An object with SQL-compatible values\n */\nexport function serializeRecord(\n\tdata: Record<string, unknown>,\n\tfields: Record<string, FieldDescriptor>,\n): Record<string, unknown> {\n\tconst result: Record<string, unknown> = {}\n\tfor (const [key, value] of Object.entries(data)) {\n\t\tconst descriptor = fields[key]\n\t\tif (!descriptor) {\n\t\t\tresult[key] = value\n\t\t\tcontinue\n\t\t}\n\t\tresult[key] = serializeValue(value, descriptor)\n\t}\n\treturn result\n}\n\n/**\n * Deserialize a SQL row to JS-native types for the application layer.\n * Transforms: 0/1 → boolean, JSON string → array, strips _deleted, maps _created_at/_updated_at.\n *\n * @param row - The raw SQL row\n * @param fields - The field descriptors from the schema\n * @returns A CollectionRecord with JS-native types\n */\nexport function deserializeRecord(\n\trow: RawCollectionRow,\n\tfields: Record<string, FieldDescriptor>,\n): CollectionRecord {\n\tconst result: CollectionRecord = {\n\t\tid: row.id,\n\t\tcreatedAt: row._created_at,\n\t\tupdatedAt: row._updated_at,\n\t}\n\n\tfor (const [key, descriptor] of Object.entries(fields)) {\n\t\tconst rawValue = row[key]\n\t\tif (rawValue === undefined || rawValue === null) {\n\t\t\tresult[key] = rawValue ?? null\n\t\t\tcontinue\n\t\t}\n\t\tresult[key] = deserializeValue(rawValue, descriptor)\n\t}\n\n\treturn result\n}\n\n/**\n * Internal key used to embed atomicOps metadata in the data JSON column.\n * This avoids adding a new column to the ops table (no migration needed).\n */\nconst ATOMIC_OPS_KEY = '__kora_atomic_ops__'\n\n/**\n * Internal key used to embed transactionId in the data JSON column.\n */\nconst TX_ID_KEY = '__kora_tx_id__'\n\n/**\n * Internal key used to embed mutationName in the data JSON column.\n */\nconst MUTATION_NAME_KEY = '__kora_mutation__'\n\n/**\n * Serialize an Operation to a row for the operations log table.\n *\n * @param op - The operation to serialize\n * @returns An OperationRow suitable for SQL INSERT\n */\nexport function serializeOperation(op: Operation): OperationRow {\n\tconst hasMetadata = op.transactionId !== undefined || op.mutationName !== undefined\n\tlet dataPayload: Record<string, unknown> | null = null\n\tif (op.data) {\n\t\t// Embed metadata in the data JSON when present\n\t\tdataPayload = { ...op.data }\n\t\tif (op.atomicOps !== undefined && Object.keys(op.atomicOps).length > 0) {\n\t\t\tdataPayload[ATOMIC_OPS_KEY] = op.atomicOps\n\t\t}\n\t\tif (op.transactionId !== undefined) {\n\t\t\tdataPayload[TX_ID_KEY] = op.transactionId\n\t\t}\n\t\tif (op.mutationName !== undefined) {\n\t\t\tdataPayload[MUTATION_NAME_KEY] = op.mutationName\n\t\t}\n\t} else if (hasMetadata) {\n\t\t// For delete operations (data is null), we still need to store metadata\n\t\tdataPayload = {}\n\t\tif (op.transactionId !== undefined) {\n\t\t\tdataPayload[TX_ID_KEY] = op.transactionId\n\t\t}\n\t\tif (op.mutationName !== undefined) {\n\t\t\tdataPayload[MUTATION_NAME_KEY] = op.mutationName\n\t\t}\n\t}\n\n\treturn {\n\t\tid: op.id,\n\t\tnode_id: op.nodeId,\n\t\ttype: op.type,\n\t\trecord_id: op.recordId,\n\t\tdata: dataPayload ? JSON.stringify(dataPayload) : null,\n\t\tprevious_data: op.previousData ? JSON.stringify(op.previousData) : null,\n\t\ttimestamp: HybridLogicalClock.serialize(op.timestamp),\n\t\tsequence_number: op.sequenceNumber,\n\t\tcausal_deps: JSON.stringify(op.causalDeps),\n\t\tschema_version: op.schemaVersion,\n\t}\n}\n\n/**\n * Deserialize a row from the operations log table back to an Operation.\n *\n * @param row - The raw operation row from SQL\n * @returns The deserialized Operation object\n */\nexport function deserializeOperation(row: OperationRow): Operation {\n\tlet data: Record<string, unknown> | null = null\n\tlet atomicOps: Record<string, unknown> | undefined\n\tlet transactionId: string | undefined\n\tlet mutationName: string | undefined\n\n\tif (row.data) {\n\t\tconst parsed = JSON.parse(row.data) as Record<string, unknown>\n\t\t// Extract embedded metadata keys\n\t\tif (ATOMIC_OPS_KEY in parsed) {\n\t\t\tatomicOps = parsed[ATOMIC_OPS_KEY] as Record<string, unknown>\n\t\t}\n\t\tif (TX_ID_KEY in parsed) {\n\t\t\ttransactionId = parsed[TX_ID_KEY] as string\n\t\t}\n\t\tif (MUTATION_NAME_KEY in parsed) {\n\t\t\tmutationName = parsed[MUTATION_NAME_KEY] as string\n\t\t}\n\t\t// Remove metadata keys from data\n\t\tconst { [ATOMIC_OPS_KEY]: _a, [TX_ID_KEY]: _t, [MUTATION_NAME_KEY]: _m, ...rest } = parsed\n\t\tdata = Object.keys(rest).length > 0 ? rest : null\n\t}\n\n\treturn {\n\t\tid: row.id,\n\t\tnodeId: row.node_id,\n\t\ttype: row.type as Operation['type'],\n\t\tcollection: '', // Collection name is derived from the table name by the caller\n\t\trecordId: row.record_id,\n\t\tdata,\n\t\tpreviousData: row.previous_data\n\t\t\t? (JSON.parse(row.previous_data) as Record<string, unknown>)\n\t\t\t: null,\n\t\ttimestamp: HybridLogicalClock.deserialize(row.timestamp),\n\t\tsequenceNumber: row.sequence_number,\n\t\tcausalDeps: JSON.parse(row.causal_deps) as string[],\n\t\tschemaVersion: row.schema_version,\n\t\t...(atomicOps !== undefined ? { atomicOps: atomicOps as Operation['atomicOps'] } : {}),\n\t\t...(transactionId !== undefined ? { transactionId } : {}),\n\t\t...(mutationName !== undefined ? { mutationName } : {}),\n\t}\n}\n\n/**\n * Deserialize an operation row with collection name already known.\n */\nexport function deserializeOperationWithCollection(\n\trow: OperationRow,\n\tcollection: string,\n): Operation {\n\tconst op = deserializeOperation(row)\n\treturn { ...op, collection }\n}\n\nfunction serializeValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tif (value === null || value === undefined) {\n\t\treturn null\n\t}\n\n\tswitch (descriptor.kind) {\n\t\tcase 'boolean':\n\t\t\treturn value ? 1 : 0\n\t\tcase 'array':\n\t\t\treturn JSON.stringify(value)\n\t\tcase 'richtext':\n\t\t\treturn encodeRichtext(value as string | Uint8Array | ArrayBuffer)\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n\nfunction deserializeValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tswitch (descriptor.kind) {\n\t\tcase 'boolean':\n\t\t\treturn value === 1 || value === true\n\t\tcase 'array':\n\t\t\tif (typeof value === 'string') {\n\t\t\t\treturn JSON.parse(value) as unknown[]\n\t\t\t}\n\t\t\treturn value\n\t\tcase 'richtext':\n\t\t\treturn decodeRichtext(value)\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n","import { generateUUIDv7 } from '@korajs/core'\nimport type { Operation, SchemaDefinition, VersionVector } from '@korajs/core'\nimport { deserializeOperationWithCollection } from '../serialization/serializer'\nimport type { OperationRow, StorageAdapter } from '../types'\nimport type {\n\tBackupManifest,\n\tBackupOptions,\n\tBackupProgress,\n\tRestoreOptions,\n\tRestoreResult,\n} from './types'\n\n// ── Section I/O helpers ──────────────────────────────────────────────────────\n\nfunction encodeSection(name: string, content: Uint8Array): Uint8Array {\n\tconst nameBytes = new TextEncoder().encode(name)\n\tconst header = new Uint8Array(8)\n\tconst dv = new DataView(header.buffer)\n\tdv.setUint32(0, nameBytes.length, true)\n\tdv.setUint32(4, content.length, true)\n\n\tconst result = new Uint8Array(header.length + nameBytes.length + content.length)\n\tresult.set(header, 0)\n\tresult.set(nameBytes, 8)\n\tresult.set(content, 8 + nameBytes.length)\n\treturn result\n}\n\nfunction encodeJsonSection(name: string, data: unknown): Uint8Array {\n\tconst json = JSON.stringify(data)\n\treturn encodeSection(name, new TextEncoder().encode(json))\n}\n\nfunction encodeNdjsonSection(name: string, records: unknown[]): Uint8Array {\n\tconst lines = `${records.map((r) => JSON.stringify(r)).join('\\n')}\\n`\n\treturn encodeSection(name, new TextEncoder().encode(lines))\n}\n\nfunction readUint32(view: DataView, offset: number): number {\n\treturn view.getUint32(offset, true)\n}\n\ninterface Section {\n\tname: string\n\tcontent: Uint8Array\n}\n\nfunction parseSections(data: Uint8Array): Section[] {\n\tconst sections: Section[] = []\n\tconst dv = new DataView(data.buffer, data.byteOffset, data.byteLength)\n\tlet offset = 0\n\n\twhile (offset + 8 <= data.byteLength) {\n\t\tconst nameLen = readUint32(dv, offset)\n\t\tconst contentLen = readUint32(dv, offset + 4)\n\t\toffset += 8\n\n\t\tif (offset + nameLen + contentLen > data.byteLength) break\n\n\t\tconst name = new TextDecoder().decode(data.slice(offset, offset + nameLen))\n\t\toffset += nameLen\n\n\t\tconst content = data.slice(offset, offset + contentLen)\n\t\toffset += contentLen\n\n\t\tsections.push({ name, content })\n\t}\n\n\treturn sections\n}\n\nfunction findSection(sections: Section[], name: string): Uint8Array | null {\n\tfor (const s of sections) {\n\t\tif (s.name === name) return s.content\n\t}\n\treturn null\n}\n\nfunction parseJsonSection<T>(sections: Section[], name: string): T | null {\n\tconst content = findSection(sections, name)\n\tif (!content) return null\n\treturn JSON.parse(new TextDecoder().decode(content)) as T\n}\n\n/**\n * Export format version. Bump on breaking changes.\n */\nconst BACKUP_VERSION = 1\n\n/**\n * Export a backup from a store.\n *\n * Reads all data via the adapter and produces a portable binary backup.\n *\n * @param adapter - The storage adapter\n * @param schema - The schema definition\n * @param nodeId - Current node ID\n * @param schemaVersion - Schema version\n * @param options - Backup options\n * @returns Backup as a Uint8Array\n */\nexport async function exportBackup(\n\tadapter: StorageAdapter,\n\tschema: SchemaDefinition,\n\tnodeId: string,\n\tschemaVersion: number,\n\toptions?: BackupOptions,\n): Promise<Uint8Array> {\n\tconst onProgress = options?.onProgress ?? (() => {})\n\tconst includeRecords = options?.includeRecords ?? true\n\tconst collectionFilter = options?.collections\n\tconst collections = collectionFilter\n\t\t? Object.keys(schema.collections).filter((c) => collectionFilter.includes(c))\n\t\t: Object.keys(schema.collections)\n\n\tonProgress({ phase: 'reading', progress: 0, message: 'Reading version vector' })\n\tconst versionVector = await readVersionVector(adapter)\n\tonProgress({ phase: 'reading', progress: 0.1, message: 'Reading metadata' })\n\tconst meta = await readMeta(adapter)\n\tonProgress({ phase: 'reading', progress: 0.2, message: 'Reading operations' })\n\tconst operations = await readAllOperations(adapter, schema)\n\tonProgress({ phase: 'reading', progress: 0.5, message: 'Reading records' })\n\n\tconst sections: Uint8Array[] = []\n\tlet allContentForChecksum = new Uint8Array(0)\n\n\t// Helper: add a section and update running checksum content\n\tconst addSection = (name: string, data: Uint8Array) => {\n\t\tsections.push(data)\n\t\tconst newLen = allContentForChecksum.length + data.length\n\t\tconst combined = new Uint8Array(newLen)\n\t\tcombined.set(allContentForChecksum, 0)\n\t\tcombined.set(data, allContentForChecksum.length)\n\t\tallContentForChecksum = combined\n\t}\n\n\t// Version vector section\n\tconst vvObj: Record<string, number> = {}\n\tfor (const [nid, seq] of versionVector) {\n\t\tvvObj[nid] = seq\n\t}\n\taddSection('version_vector', encodeJsonSection('version_vector', vvObj))\n\n\t// Meta section\n\tconst metaObj: Record<string, string> = {}\n\tfor (const row of meta) {\n\t\tmetaObj[row.key] = row.value\n\t}\n\taddSection('meta', encodeJsonSection('meta', metaObj))\n\n\t// Operations section\n\tconst opLines = `${operations.map((op) => JSON.stringify(op)).join('\\n')}\\n`\n\taddSection('operations', encodeSection('operations', new TextEncoder().encode(opLines)))\n\n\t// Records sections (optional)\n\tlet totalRecords = 0\n\tif (includeRecords) {\n\t\tfor (const col of collections) {\n\t\t\tconst records = await readCollectionRecords(adapter, col)\n\t\t\tif (records.length > 0) {\n\t\t\t\tconst lines = `${records.map((r) => JSON.stringify(r)).join('\\n')}\\n`\n\t\t\t\tconst sectionName = `records:${col}`\n\t\t\t\taddSection(sectionName, encodeSection(sectionName, new TextEncoder().encode(lines)))\n\t\t\t\ttotalRecords += records.length\n\t\t\t}\n\t\t}\n\t}\n\tonProgress({ phase: 'reading', progress: 0.9, message: 'Computing checksum' })\n\n\t// Compute SHA-256 checksum over all content sections\n\tconst checksumHex = await computeSha256(allContentForChecksum)\n\tonProgress({ phase: 'writing', progress: 1, message: 'Finalizing' })\n\n\t// Build manifest\n\tconst manifest: BackupManifest = {\n\t\tversion: BACKUP_VERSION,\n\t\tcreatedAt: Date.now(),\n\t\tnodeId,\n\t\tschemaVersion,\n\t\toperationCount: operations.length,\n\t\tcollections,\n\t\tincludesRecords: includeRecords,\n\t\tchecksum: checksumHex,\n\t}\n\n\t// Final output: header + manifest + all content sections + checksum section\n\tconst header = new Uint8Array(0)\n\n\t// Merge manifest + all sections + checksum section\n\tconst manifestSection = encodeJsonSection('manifest', manifest)\n\tconst checksumSection = encodeSection('checksum', new TextEncoder().encode(checksumHex))\n\n\tconst totalLen = manifestSection.length + allContentForChecksum.length + checksumSection.length\n\tconst result = new Uint8Array(totalLen)\n\tlet pos = 0\n\tresult.set(manifestSection, pos)\n\tpos += manifestSection.length\n\tresult.set(allContentForChecksum, pos)\n\tpos += allContentForChecksum.length\n\tresult.set(checksumSection, pos)\n\n\treturn result\n}\n\n/**\n * Read backup manifest without loading the entire backup.\n * Parses only the first section (which is always the manifest).\n *\n * @param data - The raw backup data\n * @returns The backup manifest\n */\nexport function readBackupManifest(data: Uint8Array): BackupManifest {\n\tconst sections = parseSections(data)\n\tconst manifest = parseJsonSection<BackupManifest>(sections, 'manifest')\n\tif (!manifest) {\n\t\tthrow new Error('Invalid backup: manifest section not found')\n\t}\n\treturn manifest\n}\n\n/**\n * Validate the backup checksum.\n *\n * @param data - The raw backup data\n * @returns True if the checksum is valid\n */\nexport async function verifyBackupChecksum(data: Uint8Array): Promise<boolean> {\n\tconst sections = parseSections(data)\n\tconst manifest = parseJsonSection<BackupManifest>(sections, 'manifest')\n\tif (!manifest) return false\n\n\tconst storedChecksum = manifest.checksum\n\tif (!storedChecksum) return false\n\n\t// Recompute checksum over content sections (everything after manifest, before checksum)\n\tconst manifestSection = findSection(sections, 'manifest')\n\tif (!manifestSection) return false\n\n\t// Find the checksum section\n\tconst checksumSection = findSection(sections, 'checksum')\n\n\t// The content spans from end of manifest section to start of checksum section\n\tconst checksumBytes = checksumSection\n\t\t? new TextEncoder().encode(manifest.checksum)\n\t\t: new Uint8Array(0)\n\n\t// Rebuild all content sections and hash them\n\tconst contentSections = sections.filter((s) => s.name !== 'manifest' && s.name !== 'checksum')\n\n\tlet contentForHash = new Uint8Array(0)\n\tfor (const section of contentSections) {\n\t\tconst sectionBytes = encodeSection(section.name, section.content)\n\t\tconst newLen = contentForHash.length + sectionBytes.length\n\t\tconst combined = new Uint8Array(newLen)\n\t\tcombined.set(contentForHash, 0)\n\t\tcombined.set(sectionBytes, contentForHash.length)\n\t\tcontentForHash = combined\n\t}\n\n\tconst computed = await computeSha256(contentForHash)\n\treturn computed === storedChecksum\n}\n\n/**\n * Restore a backup into a store.\n *\n * @param adapter - The storage adapter\n * @param schema - The schema definition\n * @param data - The backup data\n * @param options - Restore options\n * @returns Result of the restore operation\n */\nexport async function restoreBackup(\n\tadapter: StorageAdapter,\n\tschema: SchemaDefinition,\n\tdata: Uint8Array,\n\toptions?: RestoreOptions,\n): Promise<RestoreResult> {\n\tconst startTime = Date.now()\n\tconst onProgress = options?.onProgress ?? (() => {})\n\tconst collectionFilter = options?.collections\n\n\tonProgress({ phase: 'verifying', progress: 0, message: 'Parsing backup' })\n\n\tconst sections = parseSections(data)\n\tconst manifest = parseJsonSection<BackupManifest>(sections, 'manifest')\n\tif (!manifest) {\n\t\treturn {\n\t\t\toperationsRestored: 0,\n\t\t\trecordsRestored: 0,\n\t\t\tsuccess: false,\n\t\t\terror: 'Invalid backup: manifest section not found',\n\t\t\tduration: Date.now() - startTime,\n\t\t}\n\t}\n\n\t// Validate format version\n\tif (manifest.version !== BACKUP_VERSION) {\n\t\treturn {\n\t\t\toperationsRestored: 0,\n\t\t\trecordsRestored: 0,\n\t\t\tsuccess: false,\n\t\t\terror: `Unsupported backup version: ${manifest.version}`,\n\t\t\tduration: Date.now() - startTime,\n\t\t}\n\t}\n\n\tonProgress({ phase: 'verifying', progress: 0.2, message: 'Verifying checksum' })\n\n\t// Verify checksum\n\tconst valid = await verifyBackupChecksum(data)\n\tif (!valid) {\n\t\treturn {\n\t\t\toperationsRestored: 0,\n\t\t\trecordsRestored: 0,\n\t\t\tsuccess: false,\n\t\t\terror: 'Backup checksum mismatch: data may be corrupted',\n\t\t\tduration: Date.now() - startTime,\n\t\t}\n\t}\n\n\tonProgress({ phase: 'restoring', progress: 0.3, message: 'Loading operations' })\n\n\t// Parse operations\n\tconst opsContent = findSection(sections, 'operations')\n\tlet operations: Operation[] = []\n\tif (opsContent) {\n\t\tconst text = new TextDecoder().decode(opsContent)\n\t\tconst lines = text\n\t\t\t.trim()\n\t\t\t.split('\\n')\n\t\t\t.filter((l) => l.length > 0)\n\t\toperations = lines.map((line) => JSON.parse(line) as Operation)\n\t}\n\n\t// Filter collections if requested\n\tif (collectionFilter) {\n\t\toperations = operations.filter((op) => collectionFilter.includes(op.collection))\n\t}\n\n\t// Load version vector\n\tconst vvData = parseJsonSection<Record<string, number>>(sections, 'version_vector')\n\n\t// Load meta\n\tconst metaData = parseJsonSection<Record<string, string>>(sections, 'meta')\n\n\tonProgress({ phase: 'restoring', progress: 0.4, message: 'Applying operations' })\n\n\tif (options?.merge) {\n\t\t// Merge mode: replay operations through applyRemoteOperation.\n\t\t// This won't work directly since adapter doesn't have applyRemoteOperation.\n\t\t// Instead, we import the raw data into the adapter.\n\t\tawait adapter.transaction(async (tx) => {\n\t\t\t// Import version vector\n\t\t\tif (vvData) {\n\t\t\t\tfor (const [nid, seq] of Object.entries(vvData)) {\n\t\t\t\t\tawait tx.execute(\n\t\t\t\t\t\t'INSERT OR REPLACE INTO _kora_version_vector (node_id, sequence_number) VALUES (?, ?)',\n\t\t\t\t\t\t[nid, seq],\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Import meta\n\t\t\tif (metaData) {\n\t\t\t\tfor (const [key, value] of Object.entries(metaData)) {\n\t\t\t\t\tawait tx.execute('INSERT OR REPLACE INTO _kora_meta (key, value) VALUES (?, ?)', [\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t])\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Import operations into _kora_ops_ tables\n\t\t\tfor (const op of operations) {\n\t\t\t\tconst collection = op.collection\n\t\t\t\tconst opRow = {\n\t\t\t\t\tid: op.id,\n\t\t\t\t\tnode_id: op.nodeId,\n\t\t\t\t\ttype: op.type,\n\t\t\t\t\trecord_id: op.recordId,\n\t\t\t\t\tdata: op.data !== null ? JSON.stringify(op.data) : null,\n\t\t\t\t\tprevious_data: op.previousData !== null ? JSON.stringify(op.previousData) : null,\n\t\t\t\t\ttimestamp: JSON.stringify(op.timestamp),\n\t\t\t\t\tsequence_number: op.sequenceNumber,\n\t\t\t\t\tcausal_deps: JSON.stringify(op.causalDeps),\n\t\t\t\t\tschema_version: op.schemaVersion,\n\t\t\t\t}\n\n\t\t\t\tawait tx.execute(\n\t\t\t\t\t`INSERT OR IGNORE INTO _kora_ops_${collection} (id, node_id, type, record_id, data, previous_data, timestamp, sequence_number, causal_deps, schema_version) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n\t\t\t\t\t[\n\t\t\t\t\t\topRow.id,\n\t\t\t\t\t\topRow.node_id,\n\t\t\t\t\t\topRow.type,\n\t\t\t\t\t\topRow.record_id,\n\t\t\t\t\t\topRow.data,\n\t\t\t\t\t\topRow.previous_data,\n\t\t\t\t\t\topRow.timestamp,\n\t\t\t\t\t\topRow.sequence_number,\n\t\t\t\t\t\topRow.causal_deps,\n\t\t\t\t\t\topRow.schema_version,\n\t\t\t\t\t],\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\t} else {\n\t\t// Replace mode: clear existing data and bulk import\n\t\tawait adapter.transaction(async (tx) => {\n\t\t\t// Clear existing data\n\t\t\tfor (const collection of Object.keys(schema.collections)) {\n\t\t\t\tawait tx.execute(`DELETE FROM _kora_ops_${collection}`)\n\t\t\t\tawait tx.execute(`DELETE FROM ${collection}`)\n\t\t\t}\n\t\t\tawait tx.execute('DELETE FROM _kora_version_vector')\n\t\t\tawait tx.execute('DELETE FROM _kora_meta')\n\n\t\t\t// Import version vector\n\t\t\tif (vvData) {\n\t\t\t\tfor (const [nid, seq] of Object.entries(vvData)) {\n\t\t\t\t\tawait tx.execute(\n\t\t\t\t\t\t'INSERT INTO _kora_version_vector (node_id, sequence_number) VALUES (?, ?)',\n\t\t\t\t\t\t[nid, seq],\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Import meta\n\t\t\tif (metaData) {\n\t\t\t\tfor (const [key, value] of Object.entries(metaData)) {\n\t\t\t\t\tawait tx.execute('INSERT INTO _kora_meta (key, value) VALUES (?, ?)', [key, value])\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Import operations\n\t\t\tfor (const op of operations) {\n\t\t\t\tconst collection = op.collection\n\t\t\t\tawait tx.execute(\n\t\t\t\t\t`INSERT INTO _kora_ops_${collection} (id, node_id, type, record_id, data, previous_data, timestamp, sequence_number, causal_deps, schema_version) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n\t\t\t\t\t[\n\t\t\t\t\t\top.id,\n\t\t\t\t\t\top.nodeId,\n\t\t\t\t\t\top.type,\n\t\t\t\t\t\top.recordId,\n\t\t\t\t\t\top.data !== null ? JSON.stringify(op.data) : null,\n\t\t\t\t\t\top.previousData !== null ? JSON.stringify(op.previousData) : null,\n\t\t\t\t\t\tJSON.stringify(op.timestamp),\n\t\t\t\t\t\top.sequenceNumber,\n\t\t\t\t\t\tJSON.stringify(op.causalDeps),\n\t\t\t\t\t\top.schemaVersion,\n\t\t\t\t\t],\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\t}\n\n\tonProgress({ phase: 'restoring', progress: 0.8, message: 'Restoring records' })\n\n\t// Restore records sections (optional)\n\tlet recordsRestored = 0\n\tif (manifest.includesRecords) {\n\t\tfor (const col of manifest.collections) {\n\t\t\tif (collectionFilter && !collectionFilter.includes(col)) continue\n\n\t\t\tconst sectionContent = findSection(sections, `records:${col}`)\n\t\t\tif (!sectionContent) continue\n\n\t\t\tconst text = new TextDecoder().decode(sectionContent)\n\t\t\tconst lines = text\n\t\t\t\t.trim()\n\t\t\t\t.split('\\n')\n\t\t\t\t.filter((l) => l.length > 0)\n\t\t\tconst records = lines.map((line) => JSON.parse(line) as Record<string, unknown>)\n\n\t\t\tif (records.length === 0) continue\n\n\t\t\tawait adapter.transaction(async (tx) => {\n\t\t\t\tfor (const record of records) {\n\t\t\t\t\tconst keys = Object.keys(record)\n\t\t\t\t\tconst placeholders = keys.map(() => '?').join(', ')\n\t\t\t\t\tconst values = keys.map((k) => {\n\t\t\t\t\t\tconst v = record[k]\n\t\t\t\t\t\tif (typeof v === 'boolean') return v ? 1 : 0\n\t\t\t\t\t\tif (Array.isArray(v) || (typeof v === 'object' && v !== null)) return JSON.stringify(v)\n\t\t\t\t\t\treturn v\n\t\t\t\t\t})\n\n\t\t\t\t\tawait tx.execute(\n\t\t\t\t\t\t`INSERT OR REPLACE INTO ${col} (${keys.join(', ')}) VALUES (${placeholders})`,\n\t\t\t\t\t\tvalues,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t})\n\n\t\t\trecordsRestored += records.length\n\t\t}\n\t}\n\n\tonProgress({ phase: 'restoring', progress: 1, message: 'Done' })\n\n\treturn {\n\t\toperationsRestored: operations.length,\n\t\trecordsRestored,\n\t\tsuccess: true,\n\t\tduration: Date.now() - startTime,\n\t}\n}\n\n// ── Reading helpers ──────────────────────────────────────────────────────────\n\nasync function readVersionVector(adapter: StorageAdapter): Promise<Map<string, number>> {\n\tconst rows = await adapter.query<{ node_id: string; sequence_number: number }>(\n\t\t'SELECT node_id, sequence_number FROM _kora_version_vector',\n\t)\n\tconst vv = new Map<string, number>()\n\tfor (const row of rows) {\n\t\tvv.set(row.node_id, row.sequence_number)\n\t}\n\treturn vv\n}\n\ninterface MetaRow {\n\tkey: string\n\tvalue: string\n}\n\nasync function readMeta(adapter: StorageAdapter): Promise<MetaRow[]> {\n\treturn adapter.query<MetaRow>('SELECT key, value FROM _kora_meta')\n}\n\nasync function readAllOperations(\n\tadapter: StorageAdapter,\n\tschema: SchemaDefinition,\n): Promise<Operation[]> {\n\tconst allOps: Operation[] = []\n\n\tfor (const collectionName of Object.keys(schema.collections)) {\n\t\tconst rows = await adapter.query<OperationRow>(\n\t\t\t`SELECT * FROM _kora_ops_${collectionName} ORDER BY sequence_number ASC`,\n\t\t)\n\n\t\tfor (const row of rows) {\n\t\t\tallOps.push(deserializeOperationWithCollection(row, collectionName))\n\t\t}\n\t}\n\n\treturn allOps\n}\n\nasync function readCollectionRecords(\n\tadapter: StorageAdapter,\n\tcollection: string,\n): Promise<Record<string, unknown>[]> {\n\treturn adapter.query<Record<string, unknown>>(`SELECT * FROM ${collection} WHERE _deleted = 0`)\n}\n\n// ── Crypto helpers ───────────────────────────────────────────────────────────\n\nasync function computeSha256(data: Uint8Array<ArrayBuffer>): Promise<string> {\n\tconst hashBuffer = await crypto.subtle.digest('SHA-256', data)\n\tconst hashArray = Array.from(new Uint8Array(hashBuffer))\n\treturn hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')\n}\n","const WIRE_BYTES_KEY = '__kora_bytes__'\n\n/**\n * JSON.stringify replacer that preserves binary field values (e.g. richtext).\n */\nexport function auditJsonReplacer(_key: string, value: unknown): unknown {\n\tif (value instanceof Uint8Array) {\n\t\tlet binary = ''\n\t\tfor (let i = 0; i < value.length; i++) {\n\t\t\tbinary += String.fromCharCode(value[i] as number)\n\t\t}\n\t\treturn { [WIRE_BYTES_KEY]: btoa(binary) }\n\t}\n\treturn value\n}\n\n/**\n * JSON.parse reviver that restores binary field values.\n */\nexport function auditJsonReviver(_key: string, value: unknown): unknown {\n\tif (\n\t\tvalue !== null &&\n\t\ttypeof value === 'object' &&\n\t\tWIRE_BYTES_KEY in value &&\n\t\ttypeof (value as Record<string, unknown>)[WIRE_BYTES_KEY] === 'string'\n\t) {\n\t\tconst encoded = (value as Record<string, unknown>)[WIRE_BYTES_KEY]\n\t\tif (typeof encoded !== 'string') {\n\t\t\treturn value\n\t\t}\n\t\tconst binary = atob(encoded)\n\t\tconst bytes = new Uint8Array(binary.length)\n\t\tfor (let i = 0; i < binary.length; i++) {\n\t\t\tbytes[i] = binary.charCodeAt(i)\n\t\t}\n\t\treturn bytes\n\t}\n\treturn value\n}\n\n/**\n * Serialize a value for durable audit storage or export.\n */\nexport function serializeAuditJson(value: unknown): string {\n\treturn JSON.stringify(value, auditJsonReplacer)\n}\n\n/**\n * Deserialize audit JSON back to typed values.\n */\nexport function deserializeAuditJson<T>(json: string): T {\n\treturn JSON.parse(json, auditJsonReviver) as T\n}\n","import { generateUUIDv7 } from '@korajs/core'\nimport type { KoraEvent, MergeTrace } from '@korajs/core'\nimport type { StorageAdapter } from '../types'\nimport { deserializeAuditJson, serializeAuditJson } from './audit-json'\nimport type { AuditTraceQuery, PersistedAuditTrace } from './types'\n\ninterface AuditTraceRow {\n\tid: string\n\trecorded_at: number\n\tevent_type: string\n\tcollection: string\n\trecord_id: string\n\tfield: string\n\tstrategy: string\n\ttier: number\n\tconstraint_name: string | null\n\ttrace_json: string\n}\n\n/**\n * Build a {@link PersistedAuditTrace} from a merge-related Kora event.\n */\nexport function persistedAuditTraceFromEvent(\n\tevent: Extract<KoraEvent, { type: 'merge:completed' | 'merge:conflict' | 'constraint:violated' }>,\n): PersistedAuditTrace {\n\treturn {\n\t\tid: generateUUIDv7(),\n\t\trecordedAt: Date.now(),\n\t\teventType: event.type,\n\t\tconstraint: event.type === 'constraint:violated' ? event.constraint : undefined,\n\t\ttrace: event.trace,\n\t}\n}\n\n/**\n * Append a merge trace to the durable audit log.\n */\nexport async function appendAuditTrace(\n\tadapter: StorageAdapter,\n\ttrace: PersistedAuditTrace,\n): Promise<void> {\n\tconst collection = trace.trace.operationA.collection\n\tconst recordId = trace.trace.operationA.recordId\n\n\tawait adapter.execute(\n\t\t`INSERT INTO _kora_audit_traces (\n\t\t\tid, recorded_at, event_type, collection, record_id, field, strategy, tier, constraint_name, trace_json\n\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n\t\t[\n\t\t\ttrace.id,\n\t\t\ttrace.recordedAt,\n\t\t\ttrace.eventType,\n\t\t\tcollection,\n\t\t\trecordId,\n\t\t\ttrace.trace.field,\n\t\t\ttrace.trace.strategy,\n\t\t\ttrace.trace.tier,\n\t\t\ttrace.constraint ?? null,\n\t\t\tserializeAuditJson(trace),\n\t\t],\n\t)\n}\n\n/**\n * Load persisted audit traces with optional filters.\n */\nexport async function readAuditTraces(\n\tadapter: StorageAdapter,\n\tquery?: AuditTraceQuery,\n): Promise<PersistedAuditTrace[]> {\n\tconst conditions: string[] = []\n\tconst params: unknown[] = []\n\n\tif (query?.collections && query.collections.length > 0) {\n\t\tconst placeholders = query.collections.map(() => '?').join(', ')\n\t\tconditions.push(`collection IN (${placeholders})`)\n\t\tparams.push(...query.collections)\n\t}\n\tif (query?.since !== undefined) {\n\t\tconditions.push('recorded_at >= ?')\n\t\tparams.push(query.since)\n\t}\n\tif (query?.until !== undefined) {\n\t\tconditions.push('recorded_at <= ?')\n\t\tparams.push(query.until)\n\t}\n\n\tconst whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n\tconst rows = await adapter.query<AuditTraceRow>(\n\t\t`SELECT * FROM _kora_audit_traces ${whereClause} ORDER BY recorded_at ASC, id ASC`,\n\t\tparams,\n\t)\n\n\treturn rows.map(rowToPersistedTrace)\n}\n\nfunction rowToPersistedTrace(row: AuditTraceRow): PersistedAuditTrace {\n\treturn deserializeAuditJson<PersistedAuditTrace>(row.trace_json)\n}\n\n/**\n * Count persisted audit traces (for diagnostics).\n */\nexport async function countAuditTraces(adapter: StorageAdapter): Promise<number> {\n\tconst rows = await adapter.query<{ count: number }>(\n\t\t'SELECT COUNT(*) as count FROM _kora_audit_traces',\n\t)\n\treturn rows[0]?.count ?? 0\n}\n\n/**\n * Extract collection and record id from a merge trace for indexing.\n */\nexport function auditTraceIndexFields(trace: MergeTrace): {\n\tcollection: string\n\trecordId: string\n} {\n\treturn {\n\t\tcollection: trace.operationA.collection,\n\t\trecordId: trace.operationA.recordId,\n\t}\n}\n","import type { Operation, SchemaDefinition } from '@korajs/core'\nimport { deserializeOperationWithCollection } from '../serialization/serializer'\nimport type { StorageAdapter } from '../types'\nimport type { OperationRow } from '../types'\nimport { deserializeAuditJson, serializeAuditJson } from './audit-json'\nimport { readAuditTraces } from './audit-trace-store'\nimport type {\n\tAuditExportManifest,\n\tAuditExportOptions,\n\tAuditExportPayload,\n\tAuditTraceQuery,\n\tPersistedAuditTrace,\n} from './types'\n\nfunction encodeSection(name: string, content: Uint8Array): Uint8Array {\n\tconst nameBytes = new TextEncoder().encode(name)\n\tconst header = new Uint8Array(8)\n\tconst view = new DataView(header.buffer)\n\tview.setUint32(0, nameBytes.length, true)\n\tview.setUint32(4, content.length, true)\n\n\tconst result = new Uint8Array(header.length + nameBytes.length + content.length)\n\tresult.set(header, 0)\n\tresult.set(nameBytes, 8)\n\tresult.set(content, 8 + nameBytes.length)\n\treturn result\n}\n\nfunction encodeJsonSection(name: string, data: unknown): Uint8Array {\n\treturn encodeSection(name, new TextEncoder().encode(serializeAuditJson(data)))\n}\n\nfunction encodeNdjsonSection(name: string, records: unknown[]): Uint8Array {\n\tconst lines = `${records.map((record) => serializeAuditJson(record)).join('\\n')}\\n`\n\treturn encodeSection(name, new TextEncoder().encode(lines))\n}\n\nfunction readUint32(view: DataView, offset: number): number {\n\treturn view.getUint32(offset, true)\n}\n\ninterface Section {\n\tname: string\n\tcontent: Uint8Array\n}\n\nfunction parseSections(data: Uint8Array): Section[] {\n\tconst sections: Section[] = []\n\tconst view = new DataView(data.buffer, data.byteOffset, data.byteLength)\n\tlet offset = 0\n\n\twhile (offset + 8 <= data.byteLength) {\n\t\tconst nameLen = readUint32(view, offset)\n\t\tconst contentLen = readUint32(view, offset + 4)\n\t\toffset += 8\n\n\t\tif (offset + nameLen + contentLen > data.byteLength) {\n\t\t\tbreak\n\t\t}\n\n\t\tconst name = new TextDecoder().decode(data.slice(offset, offset + nameLen))\n\t\toffset += nameLen\n\n\t\tconst content = data.slice(offset, offset + contentLen)\n\t\toffset += contentLen\n\n\t\tsections.push({ name, content })\n\t}\n\n\treturn sections\n}\n\nfunction findSection(sections: Section[], name: string): Uint8Array | null {\n\tfor (const section of sections) {\n\t\tif (section.name === name) {\n\t\t\treturn section.content\n\t\t}\n\t}\n\treturn null\n}\n\nasync function computeSha256(data: Uint8Array<ArrayBuffer>): Promise<string> {\n\tconst hashBuffer = await crypto.subtle.digest('SHA-256', data)\n\treturn Array.from(new Uint8Array(hashBuffer))\n\t\t.map((byte) => byte.toString(16).padStart(2, '0'))\n\t\t.join('')\n}\n\nasync function readAllOperations(\n\tadapter: StorageAdapter,\n\tschema: SchemaDefinition,\n\tcollectionFilter?: string[],\n): Promise<Operation[]> {\n\tconst collections = collectionFilter\n\t\t? Object.keys(schema.collections).filter((name) => collectionFilter.includes(name))\n\t\t: Object.keys(schema.collections)\n\n\tconst allOps: Operation[] = []\n\tfor (const collectionName of collections) {\n\t\tconst rows = await adapter.query<OperationRow>(\n\t\t\t`SELECT * FROM _kora_ops_${collectionName} ORDER BY sequence_number ASC`,\n\t\t)\n\n\t\tfor (const row of rows) {\n\t\t\tallOps.push(deserializeOperationWithCollection(row, collectionName))\n\t\t}\n\t}\n\n\treturn allOps\n}\n\nfunction filterOperationsByCollections(\n\toperations: Operation[],\n\tcollectionFilter?: string[],\n): Operation[] {\n\tif (!collectionFilter || collectionFilter.length === 0) {\n\t\treturn operations\n\t}\n\tconst allowed = new Set(collectionFilter)\n\treturn operations.filter((op) => allowed.has(op.collection))\n}\n\n/**\n * Export operations and persisted merge traces as a portable binary audit bundle.\n */\nexport async function exportAudit(\n\tadapter: StorageAdapter,\n\tschema: SchemaDefinition,\n\tnodeId: string,\n\tschemaVersion: number,\n\toptions?: AuditExportOptions,\n): Promise<Uint8Array> {\n\tconst onProgress = options?.onProgress ?? (() => {})\n\tconst traceQuery: AuditTraceQuery = {\n\t\tcollections: options?.collections,\n\t\tsince: options?.since,\n\t\tuntil: options?.until,\n\t}\n\n\tonProgress({ phase: 'reading', progress: 0, message: 'Reading operations' })\n\tconst operations = filterOperationsByCollections(\n\t\tawait readAllOperations(adapter, schema, options?.collections),\n\t\toptions?.collections,\n\t)\n\n\tonProgress({ phase: 'reading', progress: 0.4, message: 'Reading merge traces' })\n\tconst mergeTraces = await readAuditTraces(adapter, traceQuery)\n\n\tonProgress({ phase: 'writing', progress: 0.7, message: 'Encoding audit export' })\n\tconst sections: Uint8Array[] = []\n\tlet contentForChecksum = new Uint8Array(0)\n\n\tconst addSection = (section: Uint8Array): void => {\n\t\tsections.push(section)\n\t\tconst combined = new Uint8Array(contentForChecksum.length + section.length)\n\t\tcombined.set(contentForChecksum, 0)\n\t\tcombined.set(section, contentForChecksum.length)\n\t\tcontentForChecksum = combined\n\t}\n\n\taddSection(encodeNdjsonSection('operations', operations))\n\taddSection(encodeNdjsonSection('merge_traces', mergeTraces))\n\n\tonProgress({ phase: 'verifying', progress: 0.9, message: 'Computing checksum' })\n\tconst checksum = await computeSha256(contentForChecksum as Uint8Array<ArrayBuffer>)\n\n\tconst manifest: AuditExportManifest = {\n\t\tversion: 1,\n\t\texportedAt: Date.now(),\n\t\tnodeId,\n\t\tschemaVersion,\n\t\toperationCount: operations.length,\n\t\tmergeTraceCount: mergeTraces.length,\n\t\tchecksum,\n\t}\n\n\tconst manifestSection = encodeJsonSection('manifest', manifest)\n\tconst checksumSection = encodeSection('checksum', new TextEncoder().encode(checksum))\n\n\tonProgress({ phase: 'writing', progress: 1, message: 'Finalizing' })\n\n\tconst parts = [manifestSection, ...sections, checksumSection]\n\tconst finalOutput = new Uint8Array(parts.reduce((sum, part) => sum + part.length, 0))\n\tlet offset = 0\n\tfor (const part of parts) {\n\t\tfinalOutput.set(part, offset)\n\t\toffset += part.length\n\t}\n\n\treturn finalOutput\n}\n\n/**\n * Decode an audit export binary into structured data.\n */\nexport function decodeAuditExport(data: Uint8Array): AuditExportPayload {\n\tconst sections = parseSections(data)\n\tconst manifest = JSON.parse(\n\t\tnew TextDecoder().decode(findSection(sections, 'manifest') ?? new Uint8Array()),\n\t) as AuditExportManifest\n\n\tconst operationsContent = findSection(sections, 'operations')\n\tconst mergeTracesContent = findSection(sections, 'merge_traces')\n\n\tconst operations = parseNdjsonSection<Operation>(operationsContent)\n\tconst mergeTraces = parseNdjsonSection<PersistedAuditTrace>(mergeTracesContent)\n\n\treturn { manifest, operations, mergeTraces }\n}\n\n/**\n * Read only the manifest from an audit export without decoding all sections.\n */\nexport function readAuditExportManifest(data: Uint8Array): AuditExportManifest {\n\tconst sections = parseSections(data)\n\tconst manifestContent = findSection(sections, 'manifest')\n\tif (!manifestContent) {\n\t\tthrow new Error('Invalid audit export: missing manifest section')\n\t}\n\treturn JSON.parse(new TextDecoder().decode(manifestContent)) as AuditExportManifest\n}\n\n/**\n * Verify the checksum of an audit export file.\n */\nexport async function verifyAuditExportChecksum(data: Uint8Array): Promise<boolean> {\n\tconst sections = parseSections(data)\n\tconst manifest = readAuditExportManifest(data)\n\tconst contentSections = sections.filter(\n\t\t(section) => section.name !== 'manifest' && section.name !== 'checksum',\n\t)\n\n\tlet content = new Uint8Array(0)\n\tfor (const section of contentSections) {\n\t\tconst encoded = encodeSection(section.name, section.content)\n\t\tconst combined = new Uint8Array(content.length + encoded.length)\n\t\tcombined.set(content, 0)\n\t\tcombined.set(encoded, content.length)\n\t\tcontent = combined\n\t}\n\n\tconst checksum = await computeSha256(content as Uint8Array<ArrayBuffer>)\n\treturn checksum === manifest.checksum\n}\n\nfunction parseNdjsonSection<T>(content: Uint8Array | null): T[] {\n\tif (!content || content.length === 0) {\n\t\treturn []\n\t}\n\tconst text = new TextDecoder().decode(content).trim()\n\tif (text.length === 0) {\n\t\treturn []\n\t}\n\treturn text.split('\\n').map((line) => deserializeAuditJson<T>(line))\n}\n","// @korajs/store — public API\n// Every export here is a public API commitment. Be explicit.\n\n// === Types ===\nexport type {\n\tApplyRemoteOptions,\n\tApplyResult,\n\tLocalMutationHandler,\n\tTransactionBufferedEntry,\n\tTransactionCommitBatch,\n\tTransactionCommitResult,\n\tMaterializedRowSnapshot,\n\tCollectionRecord,\n\tReplaySnapshot,\n\tMigrationPlan,\n\tOrderByClause,\n\tOrderByDirection,\n\tQueryDescriptor,\n\tStoreConfig,\n\tStoreIsolation,\n\tStorageAdapter,\n\tSubscriptionCallback,\n\tTransaction,\n\tWhereClause,\n\tWhereOperators,\n} from './types'\n\n// === Errors ===\nexport {\n\tAdapterError,\n\tPersistenceError,\n\tQueryError,\n\tRecordNotFoundError,\n\tStoreNotOpenError,\n\tWorkerInitError,\n\tWorkerTimeoutError,\n} from './errors'\n\n// === Operation log compaction ===\nexport type { CompactionResult, CompactionStrategy } from './compaction/types'\nexport { COMPACTION_BASELINE_META_KEY } from './compaction/types'\nexport {\n\tcompactOperationLog,\n\tcomputeAckCompactionWatermark,\n} from './compaction/compact-operation-log'\n\n// === Sync state helpers ===\nexport {\n\tcollectOperationsAheadOfServer,\n\tdeserializeVersionVectorFromMeta,\n\tLAST_ACKED_SERVER_VECTOR_META_KEY,\n\tmergeVersionVectors,\n\tserializeVersionVectorToMeta,\n} from './sync/sync-state'\n\n// === Store ===\nexport { Store } from './store/store'\nexport type { CollectionAccessor } from './store/store'\n\n// === Query ===\nexport { QueryBuilder } from './query/query-builder'\nexport { QueryStore } from './reactivity/query-store'\nexport { assertQueryReady } from './reactivity/assert-query-ready'\nexport {\n\tgetSharedQueryStoreCache,\n\tQueryStoreCache,\n} from './reactivity/query-store-cache'\n\n// === Subscription ===\nexport { SubscriptionManager } from './subscription/subscription-manager'\nexport type {\n\tSubscriptionManagerOptions,\n\tSubscriptionStats,\n} from './subscription/subscription-manager'\nexport { SubscriptionBloomFilter } from './subscription/bloom-filter'\n\n// === Collection ===\nexport { Collection } from './collection/collection'\n\n// === State Machine Validation ===\nexport {\n\tInvalidStateTransitionError,\n\tvalidateStateTransition,\n\tvalidateUpdateStateMachine,\n} from './state-machine/state-validator'\n\n// === Transaction ===\nexport { TransactionContext } from './transaction/transaction-context'\nexport type {\n\tTransactionCollectionAccessor,\n\tTransactionContextConfig,\n} from './transaction/transaction-context'\n\n// === Sequences ===\nexport { SequenceManager } from './sequences/sequence-manager'\n\n// === Richtext controller (framework bindings) ===\nexport { createRichTextController } from './richtext/create-richtext-controller'\nexport { asRichTextSyncEngine } from './richtext/as-rich-text-sync-engine'\nexport type {\n\tCreateRichTextControllerOptions,\n\tRichTextAwarenessUser,\n\tRichTextController,\n\tRichTextControllerSnapshot,\n\tRichTextCursorInfo,\n\tRichTextSyncEngine,\n} from './richtext/types'\n\n// === Richtext Serialization ===\nexport {\n\tdecodeRichtext,\n\tencodeRichtext,\n\trichtextToPlainText,\n\trichtextStatesEqual,\n} from './serialization/richtext-serializer'\n\n// === Query Utilities ===\nexport { pluralize, singularize } from './query/pluralize'\n\n// === Backup/Restore ===\nexport {\n\texportBackup,\n\treadBackupManifest,\n\trestoreBackup,\n\tverifyBackupChecksum,\n} from './backup'\nexport type {\n\tBackupManifest,\n\tBackupOptions,\n\tBackupProgress,\n\tRestoreOptions,\n\tRestoreResult,\n} from './backup'\n\n// === Audit export ===\nexport {\n\tdecodeAuditExport,\n\tpersistedAuditTraceFromEvent,\n\treadAuditExportManifest,\n\tverifyAuditExportChecksum,\n} from './audit'\nexport type {\n\tAuditExportManifest,\n\tAuditExportOptions,\n\tAuditExportPayload,\n\tAuditExportProgress,\n\tAuditTraceQuery,\n\tPersistedAuditTrace,\n} from './audit'\n","import { KoraError } from '@korajs/core'\n\n/**\n * Thrown when a query is invalid (bad field names, invalid operators, etc.).\n */\nexport class QueryError extends KoraError {\n\tconstructor(message: string, context?: Record<string, unknown>) {\n\t\tsuper(message, 'QUERY_ERROR', context)\n\t\tthis.name = 'QueryError'\n\t}\n}\n\n/**\n * Thrown when a record is not found by ID (findById, update, delete on missing record).\n */\nexport class RecordNotFoundError extends KoraError {\n\tconstructor(collection: string, recordId: string) {\n\t\tsuper(`Record \"${recordId}\" not found in collection \"${collection}\"`, 'RECORD_NOT_FOUND', {\n\t\t\tcollection,\n\t\t\trecordId,\n\t\t})\n\t\tthis.name = 'RecordNotFoundError'\n\t}\n}\n\n/**\n * Thrown when a storage adapter operation fails.\n */\nexport class AdapterError extends KoraError {\n\tconstructor(message: string, context?: Record<string, unknown>) {\n\t\tsuper(message, 'ADAPTER_ERROR', context)\n\t\tthis.name = 'AdapterError'\n\t}\n}\n\n/**\n * Thrown when an operation is attempted on a store that has not been opened.\n */\nexport class StoreNotOpenError extends KoraError {\n\tconstructor() {\n\t\tsuper('Store is not open. Call store.open() before performing operations.', 'STORE_NOT_OPEN')\n\t\tthis.name = 'StoreNotOpenError'\n\t}\n}\n\n/**\n * Thrown when the Web Worker fails to initialize (WASM load failure, OPFS unavailable, etc.).\n */\nexport class WorkerInitError extends KoraError {\n\tconstructor(message: string, context?: Record<string, unknown>) {\n\t\tsuper(`Worker initialization failed: ${message}`, 'WORKER_INIT_ERROR', context)\n\t\tthis.name = 'WorkerInitError'\n\t}\n}\n\n/**\n * Thrown when the Web Worker does not respond within the configured timeout.\n */\nexport class WorkerTimeoutError extends KoraError {\n\tconstructor(operation: string, timeoutMs: number) {\n\t\tsuper(\n\t\t\t`Worker did not respond within ${timeoutMs}ms for operation \"${operation}\"`,\n\t\t\t'WORKER_TIMEOUT',\n\t\t\t{ operation, timeoutMs },\n\t\t)\n\t\tthis.name = 'WorkerTimeoutError'\n\t}\n}\n\n/**\n * Thrown when IndexedDB persistence operations fail (serialize/deserialize).\n */\nexport class PersistenceError extends KoraError {\n\tconstructor(message: string, context?: Record<string, unknown>) {\n\t\tsuper(`Persistence error: ${message}`, 'PERSISTENCE_ERROR', context)\n\t\tthis.name = 'PersistenceError'\n\t}\n}\n","import type { VersionVector } from '@korajs/core'\n\n/**\n * How the local operation log may be compacted.\n * Materialized collection rows are always kept as the convergence baseline.\n */\nexport type CompactionStrategy =\n\t| { mode: 'never' }\n\t| {\n\t\t\tmode: 'after-ack'\n\t\t\t/** Server version vector; defaults to persisted last-acked vector on the store. */\n\t\t\tserverVector?: VersionVector\n\t }\n\t| {\n\t\t\tmode: 'after-days'\n\t\t\t/** Delete only ops older than this many days (still requires ack watermark). */\n\t\t\tdays: number\n\t\t\tserverVector?: VersionVector\n\t }\n\n/**\n * Result of a compaction run.\n */\nexport interface CompactionResult {\n\t/** Number of operation log rows removed. */\n\tdeletedCount: number\n\t/** Per-node sequence ceiling used for deletion (from server ack vector). */\n\twatermark: VersionVector\n}\n\nexport const COMPACTION_BASELINE_META_KEY = 'compaction_baseline_at'\n","import type { SchemaDefinition, VersionVector } from '@korajs/core'\nimport { HybridLogicalClock, createVersionVector } from '@korajs/core'\nimport type { StorageAdapter, Transaction } from '../types'\nimport type { CompactionResult, CompactionStrategy } from './types'\nimport { COMPACTION_BASELINE_META_KEY } from './types'\n\n/**\n * Compute per-node sequence watermarks safe to compact (server has acknowledged these ops).\n */\nexport function computeAckCompactionWatermark(serverVector: VersionVector): VersionVector {\n\tconst watermark = createVersionVector()\n\tfor (const [nodeId, seq] of serverVector) {\n\t\tif (seq > 0) {\n\t\t\twatermark.set(nodeId, seq)\n\t\t}\n\t}\n\treturn watermark\n}\n\n/**\n * Remove acknowledged, materialized operation log entries from `_kora_ops_*` tables.\n * Does not modify collection rows — they are the compaction baseline snapshot.\n */\nexport async function compactOperationLog(\n\tadapter: StorageAdapter,\n\tschema: SchemaDefinition,\n\tstrategy: CompactionStrategy,\n\tserverVector: VersionVector,\n): Promise<CompactionResult> {\n\tif (strategy.mode === 'never') {\n\t\treturn { deletedCount: 0, watermark: createVersionVector() }\n\t}\n\n\tconst watermark = computeAckCompactionWatermark(serverVector)\n\tif (watermark.size === 0) {\n\t\treturn { deletedCount: 0, watermark }\n\t}\n\n\tconst ageCutoffWall =\n\t\tstrategy.mode === 'after-days' ? Date.now() - strategy.days * 24 * 60 * 60 * 1000 : null\n\tconst ageCutoffSerialized =\n\t\tageCutoffWall !== null\n\t\t\t? HybridLogicalClock.serialize({\n\t\t\t\t\twallTime: ageCutoffWall,\n\t\t\t\t\tlogical: 0,\n\t\t\t\t\tnodeId: '',\n\t\t\t\t}).slice(0, 15)\n\t\t\t: null\n\n\tlet deletedCount = 0\n\tconst collectionNames = Object.keys(schema.collections)\n\n\tawait adapter.transaction(async (tx: Transaction) => {\n\t\tfor (const collectionName of collectionNames) {\n\t\t\tconst table = `_kora_ops_${collectionName}`\n\t\t\tfor (const [nodeId, maxSeq] of watermark) {\n\t\t\t\tif (maxSeq <= 0) continue\n\n\t\t\t\tconst countSql = buildCountSql(table, ageCutoffSerialized !== null)\n\t\t\t\tconst countParams =\n\t\t\t\t\tageCutoffSerialized !== null ? [nodeId, maxSeq, ageCutoffSerialized] : [nodeId, maxSeq]\n\t\t\t\tconst countRows = await tx.query<{ count: number }>(countSql, countParams)\n\t\t\t\tdeletedCount += countRows[0]?.count ?? 0\n\n\t\t\t\tconst deleteSql = buildDeleteSql(table, ageCutoffSerialized !== null)\n\t\t\t\tawait tx.execute(deleteSql, countParams)\n\t\t\t}\n\t\t}\n\n\t\tawait tx.execute('INSERT OR REPLACE INTO _kora_meta (key, value) VALUES (?, ?)', [\n\t\t\tCOMPACTION_BASELINE_META_KEY,\n\t\t\tString(Date.now()),\n\t\t])\n\t})\n\n\treturn { deletedCount, watermark }\n}\n\nfunction buildCountSql(table: string, withAge: boolean): string {\n\tif (withAge) {\n\t\treturn `SELECT COUNT(*) as count FROM ${table} WHERE node_id = ? AND sequence_number <= ? AND SUBSTR(timestamp, 1, 15) < ?`\n\t}\n\treturn `SELECT COUNT(*) as count FROM ${table} WHERE node_id = ? AND sequence_number <= ?`\n}\n\nfunction buildDeleteSql(table: string, withAge: boolean): string {\n\tif (withAge) {\n\t\treturn `DELETE FROM ${table} WHERE node_id = ? AND sequence_number <= ? AND SUBSTR(timestamp, 1, 15) < ?`\n\t}\n\treturn `DELETE FROM ${table} WHERE node_id = ? AND sequence_number <= ?`\n}\n","import type { Operation, VersionVector } from '@korajs/core'\nimport { createVersionVector } from '@korajs/core'\nimport type { MetaRow, StorageAdapter } from '../types'\n\nexport const LAST_ACKED_SERVER_VECTOR_META_KEY = 'last_acked_server_vector'\nexport const DELTA_CURSOR_META_KEY = 'delta_cursor'\n\n/**\n * Serialize a version vector for `_kora_meta` storage.\n */\nexport function serializeVersionVectorToMeta(vector: VersionVector): string {\n\tconst record: Record<string, number> = {}\n\tfor (const [nodeId, seq] of vector) {\n\t\trecord[nodeId] = seq\n\t}\n\treturn JSON.stringify(record)\n}\n\n/**\n * Deserialize a version vector from `_kora_meta`.\n */\nexport function deserializeVersionVectorFromMeta(value: string): VersionVector {\n\tconst parsed = JSON.parse(value) as Record<string, number>\n\tconst vector = createVersionVector()\n\tfor (const [nodeId, seq] of Object.entries(parsed)) {\n\t\tif (typeof seq === 'number' && seq >= 0) {\n\t\t\tvector.set(nodeId, seq)\n\t\t}\n\t}\n\treturn vector\n}\n\n/**\n * Merge two version vectors, keeping the maximum sequence per node.\n */\nexport function mergeVersionVectors(a: VersionVector, b: VersionVector): VersionVector {\n\tconst merged = new Map(a)\n\tfor (const [nodeId, seq] of b) {\n\t\tmerged.set(nodeId, Math.max(merged.get(nodeId) ?? 0, seq))\n\t}\n\treturn merged\n}\n\n/**\n * Operations present locally but not yet on the server (per server version vector).\n */\nexport async function collectOperationsAheadOfServer(\n\tlocalVector: VersionVector,\n\tserverVector: VersionVector,\n\tfetchRange: (nodeId: string, fromSeq: number, toSeq: number) => Promise<Operation[]>,\n): Promise<Operation[]> {\n\tconst missing: Operation[] = []\n\tfor (const [nodeId, localSeq] of localVector) {\n\t\tconst serverSeq = serverVector.get(nodeId) ?? 0\n\t\tif (localSeq > serverSeq) {\n\t\t\tconst ops = await fetchRange(nodeId, serverSeq + 1, localSeq)\n\t\t\tmissing.push(...ops)\n\t\t}\n\t}\n\tmissing.sort((a, b) => a.sequenceNumber - b.sequenceNumber)\n\treturn missing\n}\n\n/**\n * Load persisted last-acked server vector from `_kora_meta`.\n */\nexport async function loadLastAckedServerVector(adapter: StorageAdapter): Promise<VersionVector> {\n\tconst rows = await adapter.query<MetaRow>('SELECT value FROM _kora_meta WHERE key = ?', [\n\t\tLAST_ACKED_SERVER_VECTOR_META_KEY,\n\t])\n\tconst row = rows[0]\n\tif (!row?.value) {\n\t\treturn createVersionVector()\n\t}\n\ttry {\n\t\treturn deserializeVersionVectorFromMeta(row.value)\n\t} catch {\n\t\treturn createVersionVector()\n\t}\n}\n\n/**\n * Persist the last-acked server version vector to `_kora_meta`.\n */\nexport async function saveLastAckedServerVector(\n\tadapter: StorageAdapter,\n\tvector: VersionVector,\n): Promise<void> {\n\tawait adapter.execute('INSERT OR REPLACE INTO _kora_meta (key, value) VALUES (?, ?)', [\n\t\tLAST_ACKED_SERVER_VECTOR_META_KEY,\n\t\tserializeVersionVectorToMeta(vector),\n\t])\n}\n\n/**\n * Load a persisted delta cursor for resuming paginated initial sync.\n */\nexport async function loadDeltaCursor(adapter: StorageAdapter): Promise<string | null> {\n\tconst rows = await adapter.query<MetaRow>('SELECT value FROM _kora_meta WHERE key = ?', [\n\t\tDELTA_CURSOR_META_KEY,\n\t])\n\treturn rows[0]?.value ?? null\n}\n\n/**\n * Persist or clear the delta cursor in `_kora_meta`.\n */\nexport async function saveDeltaCursor(\n\tadapter: StorageAdapter,\n\tcursor: string | null,\n): Promise<void> {\n\tif (cursor === null) {\n\t\tawait adapter.execute('DELETE FROM _kora_meta WHERE key = ?', [DELTA_CURSOR_META_KEY])\n\t\treturn\n\t}\n\n\tawait adapter.execute('INSERT OR REPLACE INTO _kora_meta (key, value) VALUES (?, ?)', [\n\t\tDELTA_CURSOR_META_KEY,\n\t\tcursor,\n\t])\n}\n","import {\n\tCausalTracker,\n\tHybridLogicalClock,\n\tcreateVersionVector,\n\tgenerateUUIDv7,\n\tmigrationStepsToSQL,\n} from '@korajs/core'\nimport type {\n\tKoraEventEmitter,\n\tMigrationStep,\n\tOperation,\n\tOperationLog,\n\tSchemaDefinition,\n\tVersionVector,\n} from '@korajs/core'\nimport { readBackupManifest as readManifest } from '../backup/backup'\nimport type { BackupManifest, BackupOptions, RestoreOptions, RestoreResult } from '../backup/types'\nimport { Collection } from '../collection/collection'\nimport { compactOperationLog } from '../compaction/compact-operation-log'\nimport type { CompactionResult, CompactionStrategy } from '../compaction/types'\nimport { StoreNotOpenError } from '../errors'\nimport { isIncomingNewerThanRow, serializeRowVersion } from '../lww/row-version'\nimport type { LocalMutationContext } from '../mutations/types'\nimport { QueryBuilder } from '../query/query-builder'\nimport {\n\tbuildInsertQuery,\n\tbuildLwwSoftDeleteQuery,\n\tbuildLwwUpdateQuery,\n\tbuildSoftDeleteQuery,\n\tbuildUpdateQuery,\n} from '../query/sql-builder'\nimport { RelationEnforcer } from '../relations/relation-enforcer'\nimport { buildReplaySnapshot } from '../replay/replay-to'\nimport type { ReplaySnapshot } from '../replay/replay-to'\nimport { SequenceManager } from '../sequences/sequence-manager'\nimport {\n\tdeserializeOperationWithCollection,\n\tdeserializeRecord,\n\tserializeOperation,\n\tserializeRecord,\n} from '../serialization/serializer'\nimport { SubscriptionManager } from '../subscription/subscription-manager'\nimport {\n\tcollectOperationsAheadOfServer,\n\tloadDeltaCursor,\n\tloadLastAckedServerVector,\n\tmergeVersionVectors,\n\tsaveDeltaCursor,\n\tsaveLastAckedServerVector,\n} from '../sync/sync-state'\nimport { TransactionContext } from '../transaction/transaction-context'\nimport { TransactionSequenceAllocator } from '../transaction/transaction-sequence'\nimport type {\n\tApplyRemoteOptions,\n\tApplyResult,\n\tLocalMutationHandler,\n\tMaterializedRowSnapshot,\n\tMetaRow,\n\tOperationRow,\n\tRawCollectionRow,\n\tStorageAdapter,\n\tStoreConfig,\n\tStoreIsolation,\n\tVersionVectorRow,\n} from '../types'\nimport { allocateNextSequenceNumber } from './sequence-allocator'\nimport { resolvePerTabNodeId } from './tab-node-id'\n\n/**\n * Store is the main orchestrator. It owns a schema, a storage adapter,\n * a clock, and a subscription manager. It creates Collection instances\n * for each schema collection, and provides the sync contract via\n * applyRemoteOperation and getOperationRange.\n *\n * @example\n * ```typescript\n * const store = new Store({ schema, adapter })\n * await store.open()\n * const todo = await store.collection('todos').insert({ title: 'Hello' })\n * await store.close()\n * ```\n */\nexport class Store implements OperationLog {\n\tprivate opened = false\n\tprivate nodeId = ''\n\tprivate sequenceNumber = 0\n\tprivate versionVector: VersionVector = createVersionVector()\n\tprivate clock: HybridLogicalClock | null = null\n\tprivate collections = new Map<string, Collection>()\n\tprivate subscriptionManager: SubscriptionManager\n\tprivate sequenceManager: SequenceManager | null = null\n\n\tprivate readonly schema: SchemaDefinition\n\tprivate readonly adapter: StorageAdapter\n\tprivate readonly configNodeId: string | undefined\n\tprivate readonly dbName: string\n\tprivate readonly isolation: StoreIsolation\n\tprivate readonly emitter: KoraEventEmitter | null\n\tprivate localMutationHandler: LocalMutationHandler | null\n\tprivate relationEnforcer: RelationEnforcer | null = null\n\tprivate causalTracker: CausalTracker | null = null\n\n\tconstructor(config: StoreConfig) {\n\t\tthis.schema = config.schema\n\t\tthis.adapter = config.adapter\n\t\tthis.configNodeId = config.nodeId\n\t\tthis.dbName = config.dbName ?? 'kora-db'\n\t\tthis.isolation = config.isolation ?? 'shared'\n\t\tthis.emitter = config.emitter ?? null\n\t\tthis.localMutationHandler = config.localMutationHandler ?? null\n\t\tthis.subscriptionManager = new SubscriptionManager({\n\t\t\tonQuerySubscribed: config.onQuerySubscribed,\n\t\t})\n\t}\n\n\t/**\n\t * Open the store: initialize the database, load or generate a node ID,\n\t * restore the sequence number and version vector, and create Collection instances.\n\t */\n\tasync open(): Promise<void> {\n\t\tawait this.adapter.open(this.schema)\n\n\t\t// Run schema migrations if needed\n\t\tawait this.runMigrationsIfNeeded()\n\n\t\t// Load or generate node ID\n\t\tthis.nodeId = await this.loadOrGenerateNodeId()\n\t\tthis.clock = new HybridLogicalClock(this.nodeId)\n\t\tthis.causalTracker = new CausalTracker()\n\n\t\t// Initialize sequence manager\n\t\tthis.sequenceManager = new SequenceManager(this.adapter, this.nodeId)\n\n\t\t// Load sequence number and version vector\n\t\tthis.sequenceNumber = await this.loadSequenceNumber()\n\t\tthis.versionVector = await this.loadVersionVector()\n\n\t\t// Create RelationEnforcer if the schema has relations.\n\t\t// The enforcer is shared across all Collection instances so that\n\t\t// cascading deletes can cross collection boundaries.\n\t\tconst hasRelations = Object.keys(this.schema.relations).length > 0\n\t\tthis.relationEnforcer = hasRelations\n\t\t\t? new RelationEnforcer({\n\t\t\t\t\tschema: this.schema,\n\t\t\t\t\tadapter: this.adapter,\n\t\t\t\t\tclock: this.clock,\n\t\t\t\t\tnodeId: this.nodeId,\n\t\t\t\t})\n\t\t\t: null\n\n\t\t// Create collection instances\n\t\tfor (const [name, definition] of Object.entries(this.schema.collections)) {\n\t\t\tconst col = new Collection(\n\t\t\t\tname,\n\t\t\t\tdefinition,\n\t\t\t\tthis.schema,\n\t\t\t\tthis.adapter,\n\t\t\t\tthis.clock,\n\t\t\t\tthis.nodeId,\n\t\t\t\t() => this.allocateSequenceNumber(),\n\t\t\t\t(collectionName, operation) => {\n\t\t\t\t\tthis.recordOperationSequence(operation)\n\t\t\t\t\tthis.subscriptionManager.notify(collectionName, operation)\n\t\t\t\t\tif (this.emitter) {\n\t\t\t\t\t\tthis.emitter.emit({ type: 'operation:created', operation })\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tthis.relationEnforcer,\n\t\t\t\tthis.localMutationHandler,\n\t\t\t\tthis.causalTracker,\n\t\t\t)\n\t\t\tthis.collections.set(name, col)\n\t\t}\n\n\t\tthis.opened = true\n\t}\n\n\t/**\n\t * Close the store: clear subscriptions and close the adapter.\n\t */\n\tasync close(): Promise<void> {\n\t\tthis.subscriptionManager.clear()\n\t\tthis.collections.clear()\n\t\tthis.opened = false\n\t\tawait this.adapter.close()\n\t}\n\n\t/**\n\t * Get a Collection instance for CRUD operations.\n\t * @throws {StoreNotOpenError} If the store is not open\n\t * @throws {Error} If the collection name is not in the schema\n\t */\n\tcollection(name: string): CollectionAccessor {\n\t\tthis.ensureOpen()\n\t\tconst col = this.collections.get(name)\n\t\tif (!col) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${name}\". Available: ${[...this.collections.keys()].join(', ')}`,\n\t\t\t)\n\t\t}\n\n\t\tconst definition = this.schema.collections[name]\n\t\tif (!definition) {\n\t\t\tthrow new Error(`Collection definition not found for \"${name}\"`)\n\t\t}\n\n\t\treturn {\n\t\t\tinsert: (data: Record<string, unknown>) => col.insert(data),\n\t\t\tfindById: (id: string) => col.findById(id),\n\t\t\tupdate: (id: string, data: Record<string, unknown>) => col.update(id, data),\n\t\t\tdelete: (id: string) => col.delete(id),\n\t\t\twhere: (conditions) =>\n\t\t\t\tnew QueryBuilder(\n\t\t\t\t\tname,\n\t\t\t\t\tdefinition,\n\t\t\t\t\tthis.adapter,\n\t\t\t\t\tthis.subscriptionManager,\n\t\t\t\t\tconditions,\n\t\t\t\t\tthis.schema,\n\t\t\t\t),\n\t\t}\n\t}\n\n\t/**\n\t * Get the current version vector.\n\t */\n\tgetVersionVector(): VersionVector {\n\t\tthis.ensureOpen()\n\t\treturn new Map(this.versionVector)\n\t}\n\n\t/**\n\t * Get the node ID for this store instance.\n\t */\n\tgetNodeId(): string {\n\t\tthis.ensureOpen()\n\t\treturn this.nodeId\n\t}\n\n\t/**\n\t * Apply a remote operation received from sync.\n\t * Checks for duplicates, applies to the data table, persists the operation,\n\t * and updates the version vector.\n\t */\n\tasync applyRemoteOperation(op: Operation, options?: ApplyRemoteOptions): Promise<ApplyResult> {\n\t\tthis.ensureOpen()\n\n\t\tconst collection = op.collection\n\t\tconst definition = this.schema.collections[collection]\n\t\tif (!definition) {\n\t\t\treturn 'skipped'\n\t\t}\n\n\t\t// Check for duplicate (content-addressed dedup)\n\t\tconst existing = await this.adapter.query<{ id: string }>(\n\t\t\t`SELECT id FROM _kora_ops_${collection} WHERE id = ?`,\n\t\t\t[op.id],\n\t\t)\n\t\tif (existing.length > 0) {\n\t\t\treturn 'duplicate'\n\t\t}\n\n\t\t// Advance the local HLC; severe clock drift throws ClockDriftError (surfaced as sync:apply-failed).\n\t\tif (this.clock) {\n\t\t\tthis.clock.receive(op.timestamp)\n\t\t}\n\n\t\tconst remoteVersion = serializeRowVersion(op.timestamp)\n\t\tconst wallTime = op.timestamp.wallTime\n\n\t\t// Apply the operation to the data table (LWW-guarded; op log always appended below)\n\t\tawait this.adapter.transaction(async (tx) => {\n\t\t\tif (op.type === 'insert' && op.data) {\n\t\t\t\tconst existing = await tx.query<RawCollectionRow>(\n\t\t\t\t\t`SELECT _updated_at, _version FROM ${collection} WHERE id = ?`,\n\t\t\t\t\t[op.recordId],\n\t\t\t\t)\n\t\t\t\tconst row = existing[0]\n\t\t\t\tif (row && !isIncomingNewerThanRow(op.timestamp, row)) {\n\t\t\t\t\t// Stale remote insert — skip materialization, still record op below\n\t\t\t\t} else {\n\t\t\t\t\tconst serializedData = serializeRecord(op.data, definition.fields)\n\t\t\t\t\tconst record: Record<string, unknown> = {\n\t\t\t\t\t\tid: op.recordId,\n\t\t\t\t\t\t...serializedData,\n\t\t\t\t\t\t_created_at: wallTime,\n\t\t\t\t\t\t_updated_at: wallTime,\n\t\t\t\t\t\t_version: remoteVersion,\n\t\t\t\t\t}\n\t\t\t\t\tconst insertQuery = buildInsertQuery(collection, record)\n\t\t\t\t\tawait tx.execute(insertQuery.sql, insertQuery.params)\n\t\t\t\t}\n\t\t\t} else if (op.type === 'update' && op.data) {\n\t\t\t\tconst serializedChanges = serializeRecord(op.data, definition.fields)\n\t\t\t\tconst updatePayload: Record<string, unknown> = {\n\t\t\t\t\t...serializedChanges,\n\t\t\t\t\t_updated_at: wallTime,\n\t\t\t\t\t_version: remoteVersion,\n\t\t\t\t}\n\t\t\t\tif (options?.reactivateIfDeleted) {\n\t\t\t\t\tupdatePayload._deleted = 0\n\t\t\t\t}\n\t\t\t\tconst updateQuery = buildLwwUpdateQuery(\n\t\t\t\t\tcollection,\n\t\t\t\t\top.recordId,\n\t\t\t\t\tupdatePayload,\n\t\t\t\t\tremoteVersion,\n\t\t\t\t)\n\t\t\t\tawait tx.execute(updateQuery.sql, updateQuery.params)\n\t\t\t} else if (op.type === 'delete') {\n\t\t\t\tconst deleteQuery = buildLwwSoftDeleteQuery(\n\t\t\t\t\tcollection,\n\t\t\t\t\top.recordId,\n\t\t\t\t\twallTime,\n\t\t\t\t\tremoteVersion,\n\t\t\t\t)\n\t\t\t\tawait tx.execute(deleteQuery.sql, deleteQuery.params)\n\t\t\t}\n\n\t\t\t// Persist the operation\n\t\t\tconst opRow = serializeOperation(op)\n\t\t\tconst opInsert = buildInsertQuery(\n\t\t\t\t`_kora_ops_${collection}`,\n\t\t\t\topRow as unknown as Record<string, unknown>,\n\t\t\t)\n\t\t\tawait tx.execute(opInsert.sql, opInsert.params)\n\n\t\t\t// Update version vector\n\t\t\tconst currentSeq = this.versionVector.get(op.nodeId) ?? 0\n\t\t\tif (op.sequenceNumber > currentSeq) {\n\t\t\t\tthis.versionVector.set(op.nodeId, op.sequenceNumber)\n\t\t\t\tawait tx.execute(\n\t\t\t\t\t'INSERT OR REPLACE INTO _kora_version_vector (node_id, sequence_number) VALUES (?, ?)',\n\t\t\t\t\t[op.nodeId, op.sequenceNumber],\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\n\t\t// Notify subscriptions\n\t\tthis.subscriptionManager.notify(collection, op)\n\n\t\treturn 'applied'\n\t}\n\n\t/**\n\t * Get operations from a node within a sequence number range.\n\t * Implements the OperationLog interface for computeDelta.\n\t */\n\tasync getRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\treturn this.getOperationRange(nodeId, fromSeq, toSeq)\n\t}\n\n\t/**\n\t * Get operations from a node within a sequence number range.\n\t */\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\tthis.ensureOpen()\n\t\tconst allOps: Operation[] = []\n\n\t\tfor (const collectionName of Object.keys(this.schema.collections)) {\n\t\t\tconst rows = await this.adapter.query<OperationRow>(\n\t\t\t\t`SELECT * FROM _kora_ops_${collectionName} WHERE node_id = ? AND sequence_number >= ? AND sequence_number <= ? ORDER BY sequence_number ASC`,\n\t\t\t\t[nodeId, fromSeq, toSeq],\n\t\t\t)\n\t\t\tfor (const row of rows) {\n\t\t\t\tallOps.push(deserializeOperationWithCollection(row, collectionName))\n\t\t\t}\n\t\t}\n\n\t\t// Sort by sequence number across collections\n\t\tallOps.sort((a, b) => a.sequenceNumber - b.sequenceNumber)\n\t\treturn allOps\n\t}\n\n\t/**\n\t * Load every operation from the local append-only log across all collections.\n\t * Used by sync delta computation, backup export, and time-travel replay.\n\t */\n\tasync getAllOperations(): Promise<Operation[]> {\n\t\tthis.ensureOpen()\n\t\tconst allOps: Operation[] = []\n\n\t\tfor (const collectionName of Object.keys(this.schema.collections)) {\n\t\t\tconst rows = await this.adapter.query<OperationRow>(\n\t\t\t\t`SELECT * FROM _kora_ops_${collectionName} ORDER BY sequence_number ASC`,\n\t\t\t)\n\t\t\tfor (const row of rows) {\n\t\t\t\tallOps.push(deserializeOperationWithCollection(row, collectionName))\n\t\t\t}\n\t\t}\n\n\t\treturn allOps\n\t}\n\n\t/**\n\t * Rebuild an in-memory snapshot of materialized state at a causal cut in the op log.\n\t * Does not mutate the live store — intended for DevTools time-travel inspection.\n\t *\n\t * @param operationId - Content-addressed id of the operation to replay through (inclusive)\n\t * @throws {OperationError} When the operation id is not present in the local log\n\t */\n\tasync replayTo(operationId: string): Promise<ReplaySnapshot> {\n\t\tthis.ensureOpen()\n\t\tconst start = Date.now()\n\t\tconst allOps = await this.getAllOperations()\n\t\tconst snapshot = buildReplaySnapshot(this.schema, allOps, operationId)\n\n\t\tif (this.emitter) {\n\t\t\tthis.emitter.emit({\n\t\t\t\ttype: 'replay:completed',\n\t\t\t\ttargetOperationId: operationId,\n\t\t\t\toperationsApplied: snapshot.operationsApplied.length,\n\t\t\t\tduration: Date.now() - start,\n\t\t\t})\n\t\t}\n\n\t\treturn snapshot\n\t}\n\n\t/**\n\t * Persist a merge trace to the durable audit log.\n\t */\n\tasync appendAuditTrace(trace: import('../audit/types').PersistedAuditTrace): Promise<void> {\n\t\tthis.ensureOpen()\n\t\tconst { appendAuditTrace: append } = await import('../audit/audit-trace-store')\n\t\tawait append(this.adapter, trace)\n\t}\n\n\t/**\n\t * Read persisted audit traces with optional filters.\n\t */\n\tasync getAuditTraces(\n\t\tquery?: import('../audit/types').AuditTraceQuery,\n\t): Promise<import('../audit/types').PersistedAuditTrace[]> {\n\t\tthis.ensureOpen()\n\t\tconst { readAuditTraces } = await import('../audit/audit-trace-store')\n\t\treturn readAuditTraces(this.adapter, query)\n\t}\n\n\t/**\n\t * Export operations and merge traces as a portable audit bundle.\n\t */\n\tasync exportAudit(options?: import('../audit/types').AuditExportOptions): Promise<Uint8Array> {\n\t\tthis.ensureOpen()\n\t\tconst { exportAudit: doExport } = await import('../audit/export-audit')\n\t\treturn doExport(this.adapter, this.schema, this.nodeId, this.schema.version, options)\n\t}\n\n\t/**\n\t * Get the schema definition.\n\t */\n\tgetSchema(): SchemaDefinition {\n\t\treturn this.schema\n\t}\n\n\t/**\n\t * Route local CRUD through the unified apply pipeline (korajs ApplyPipeline).\n\t */\n\tsetLocalMutationHandler(handler: LocalMutationHandler | null): void {\n\t\tthis.localMutationHandler = handler\n\t\tfor (const col of this.collections.values()) {\n\t\t\tcol.setMutationHandler(handler)\n\t\t}\n\t}\n\n\t/**\n\t * Build mutation context for a collection (used by ApplyPipeline side effects).\n\t */\n\tcreateMutationContext(\n\t\tcollection: string,\n\t\toptions?: { inTransaction?: boolean; extraCausalDeps?: string[] },\n\t): LocalMutationContext {\n\t\tthis.ensureOpen()\n\t\tconst definition = this.schema.collections[collection]\n\t\tif (!definition || !this.clock) {\n\t\t\tthrow new StoreNotOpenError()\n\t\t}\n\t\treturn {\n\t\t\tcollection,\n\t\t\tdefinition,\n\t\t\tschema: this.schema,\n\t\t\tadapter: this.adapter,\n\t\t\tclock: this.clock,\n\t\t\tnodeId: this.nodeId,\n\t\t\tallocateSequenceNumber: () => this.allocateSequenceNumber(),\n\t\t\tonMutation: (collectionName, operation) => {\n\t\t\t\tthis.recordOperationSequence(operation)\n\t\t\t\tthis.subscriptionManager.notify(collectionName, operation)\n\t\t\t\tif (this.emitter) {\n\t\t\t\t\tthis.emitter.emit({ type: 'operation:created', operation })\n\t\t\t\t}\n\t\t\t},\n\t\t\trelationEnforcer: this.relationEnforcer,\n\t\t\tcausalTracker: this.causalTracker,\n\t\t\tinTransaction: options?.inTransaction ?? false,\n\t\t\textraCausalDeps: options?.extraCausalDeps,\n\t\t}\n\t}\n\n\t/**\n\t * Load a materialized row by ID, including soft-deleted tombstones.\n\t */\n\tasync findMaterializedRow(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<MaterializedRowSnapshot | null> {\n\t\tthis.ensureOpen()\n\t\tconst definition = this.schema.collections[collection]\n\t\tif (!definition) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst rows = await this.adapter.query<RawCollectionRow>(\n\t\t\t`SELECT * FROM ${collection} WHERE id = ?`,\n\t\t\t[recordId],\n\t\t)\n\t\tconst row = rows[0]\n\t\tif (!row) {\n\t\t\treturn null\n\t\t}\n\n\t\treturn {\n\t\t\trecord: deserializeRecord(row, definition.fields),\n\t\t\tdeleted: row._deleted === 1,\n\t\t}\n\t}\n\n\t/**\n\t * Latest operation from this device for a record (used for delete-vs-update merge on sync).\n\t */\n\t/**\n\t * Load the last server version vector acknowledged by this client (persisted in `_kora_meta`).\n\t */\n\tasync loadLastAckedServerVector(): Promise<VersionVector> {\n\t\tthis.ensureOpen()\n\t\treturn loadLastAckedServerVector(this.adapter)\n\t}\n\n\t/**\n\t * Persist the last server version vector this client believes the server has applied.\n\t */\n\tasync saveLastAckedServerVector(vector: VersionVector): Promise<void> {\n\t\tthis.ensureOpen()\n\t\tawait saveLastAckedServerVector(this.adapter, vector)\n\t}\n\n\t/**\n\t * Load persisted delta cursor for resuming paginated initial sync.\n\t */\n\tasync loadDeltaCursor(): Promise<string | null> {\n\t\tthis.ensureOpen()\n\t\treturn loadDeltaCursor(this.adapter)\n\t}\n\n\t/**\n\t * Persist or clear the delta cursor for paginated initial sync resume.\n\t */\n\tasync saveDeltaCursor(cursor: string | null): Promise<void> {\n\t\tthis.ensureOpen()\n\t\tawait saveDeltaCursor(this.adapter, cursor)\n\t}\n\n\t/**\n\t * Local operations not yet reflected on the server version vector.\n\t */\n\tasync getUnsyncedOperations(serverVector: VersionVector): Promise<Operation[]> {\n\t\tthis.ensureOpen()\n\t\treturn collectOperationsAheadOfServer(\n\t\t\tthis.getVersionVector(),\n\t\t\tserverVector,\n\t\t\t(nodeId, fromSeq, toSeq) => this.getOperationRange(nodeId, fromSeq, toSeq),\n\t\t)\n\t}\n\n\t/**\n\t * Count of local operations ahead of the server version vector.\n\t */\n\tasync countUnsyncedOperations(serverVector: VersionVector): Promise<number> {\n\t\tconst ops = await this.getUnsyncedOperations(serverVector)\n\t\treturn ops.length\n\t}\n\n\t/**\n\t * Compact the local operation log using materialized rows as the baseline.\n\t * Only removes ops the server has acknowledged (per {@link CompactionStrategy}).\n\t */\n\tasync compact(strategy: CompactionStrategy): Promise<CompactionResult> {\n\t\tthis.ensureOpen()\n\t\tif (strategy.mode === 'never') {\n\t\t\treturn compactOperationLog(this.adapter, this.schema, strategy, createVersionVector())\n\t\t}\n\n\t\tconst serverVector = strategy.serverVector ?? (await loadLastAckedServerVector(this.adapter))\n\t\treturn compactOperationLog(this.adapter, this.schema, strategy, serverVector)\n\t}\n\n\t/**\n\t * Merge session remote vector with persisted last-acked vector (max per node).\n\t */\n\tmergeServerVectors(sessionVector: VersionVector, persistedVector: VersionVector): VersionVector {\n\t\treturn mergeVersionVectors(persistedVector, sessionVector)\n\t}\n\n\tasync getLatestLocalOperationForRecord(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<Operation | null> {\n\t\tthis.ensureOpen()\n\t\tconst rows = await this.adapter.query<OperationRow>(\n\t\t\t`SELECT * FROM _kora_ops_${collection} WHERE node_id = ? AND record_id = ? ORDER BY sequence_number DESC LIMIT 1`,\n\t\t\t[this.nodeId, recordId],\n\t\t)\n\t\tconst row = rows[0]\n\t\tif (!row) {\n\t\t\treturn null\n\t\t}\n\t\treturn deserializeOperationWithCollection(row, collection)\n\t}\n\n\t/**\n\t * Latest operation for a record from any node (for 3-way merge when local op log is empty).\n\t */\n\tasync getLatestOperationForRecord(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<Operation | null> {\n\t\tthis.ensureOpen()\n\t\tconst rows = await this.adapter.query<OperationRow>(\n\t\t\t`SELECT * FROM _kora_ops_${collection} WHERE record_id = ?`,\n\t\t\t[recordId],\n\t\t)\n\n\t\tlet latest: Operation | null = null\n\t\tfor (const row of rows) {\n\t\t\tconst op = deserializeOperationWithCollection(row, collection)\n\t\t\tif (!latest || HybridLogicalClock.compare(op.timestamp, latest.timestamp) > 0) {\n\t\t\t\tlatest = op\n\t\t\t}\n\t\t}\n\t\treturn latest\n\t}\n\n\t/** Expose the subscription manager for direct access (e.g., by QueryBuilder) */\n\tgetSubscriptionManager(): SubscriptionManager {\n\t\treturn this.subscriptionManager\n\t}\n\n\t/**\n\t * Get the sequence manager for offline-safe sequence generation.\n\t * @throws {StoreNotOpenError} If the store is not open\n\t */\n\tgetSequenceManager(): SequenceManager {\n\t\tthis.ensureOpen()\n\t\tif (!this.sequenceManager) {\n\t\t\tthrow new StoreNotOpenError()\n\t\t}\n\t\treturn this.sequenceManager\n\t}\n\n\t/**\n\t * Create a TransactionContext for atomic multi-collection operations.\n\t * The returned context buffers all mutations and commits them atomically.\n\t *\n\t * After commit, the caller is responsible for notifying subscriptions\n\t * and emitting events for each operation.\n\t */\n\tcreateTransaction(): TransactionContext {\n\t\tthis.ensureOpen()\n\t\tif (!this.clock) {\n\t\t\tthrow new StoreNotOpenError()\n\t\t}\n\t\treturn new TransactionContext({\n\t\t\tschema: this.schema,\n\t\t\tadapter: this.adapter,\n\t\t\tclock: this.clock,\n\t\t\tnodeId: this.nodeId,\n\t\t\tsequenceAllocator: new TransactionSequenceAllocator(this.adapter, this.nodeId),\n\t\t\trelationEnforcer: this.relationEnforcer,\n\t\t\tcausalTracker: this.causalTracker,\n\t\t\tlocalMutationHandler: this.localMutationHandler,\n\t\t})\n\t}\n\n\t/**\n\t * Execute a function within a transaction. All mutations performed on the\n\t * TransactionContext are committed atomically. Subscription notifications\n\t * are batched and fired after the commit.\n\t *\n\t * If the function throws, the transaction is rolled back and the error is re-thrown.\n\t *\n\t * @param fn - Function receiving a TransactionContext for buffered operations\n\t * @returns The operations that were committed\n\t */\n\tasync transaction(fn: (tx: TransactionContext) => Promise<void>): Promise<Operation[]> {\n\t\tconst tx = this.createTransaction()\n\t\tthis.causalTracker?.beginTransaction()\n\t\ttry {\n\t\t\tawait fn(tx)\n\t\t\tconst { operations } = await tx.commit()\n\n\t\t\tthis.causalTracker?.clearTransaction()\n\n\t\t\t// Notify subscriptions and emit events after commit\n\t\t\tfor (const op of operations) {\n\t\t\t\tthis.recordOperationSequence(op)\n\t\t\t\tthis.subscriptionManager.notify(op.collection, op)\n\t\t\t\tif (this.emitter) {\n\t\t\t\t\tthis.emitter.emit({ type: 'operation:created', operation: op })\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn operations\n\t\t} catch (error) {\n\t\t\ttx.rollback()\n\t\t\tthis.causalTracker?.clearTransaction()\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Export all data as a portable backup binary.\n\t * Includes operations, version vector, metadata, and optionally materialized records.\n\t *\n\t * @param options - Backup options (includeRecords, collections, onProgress)\n\t * @returns Backup as a Uint8Array\n\t */\n\tasync exportBackup(options?: BackupOptions): Promise<Uint8Array> {\n\t\tthis.ensureOpen()\n\t\tconst { exportBackup: doExport } = await import('../backup/backup')\n\t\treturn doExport(this.adapter, this.schema, this.nodeId, this.schema.version, options)\n\t}\n\n\t/**\n\t * Restore data from a backup binary.\n\t *\n\t * @param data - The backup data\n\t * @param options - Restore options (merge, collections, onProgress)\n\t * @returns Result of the restore operation\n\t */\n\tasync importBackup(data: Uint8Array, options?: RestoreOptions): Promise<RestoreResult> {\n\t\tthis.ensureOpen()\n\t\tconst { restoreBackup: doRestore } = await import('../backup/backup')\n\t\treturn doRestore(this.adapter, this.schema, data, options)\n\t}\n\n\t/**\n\t * Read backup manifest without loading the entire backup.\n\t *\n\t * @param data - The raw backup data\n\t * @returns The backup manifest\n\t */\n\tstatic readBackupManifest(data: Uint8Array): BackupManifest {\n\t\treturn readManifest(data)\n\t}\n\n\tprivate recordOperationSequence(operation: Operation): void {\n\t\tconst prev = this.versionVector.get(operation.nodeId) ?? 0\n\t\tif (operation.sequenceNumber > prev) {\n\t\t\tthis.versionVector.set(operation.nodeId, operation.sequenceNumber)\n\t\t}\n\t\tif (operation.nodeId === this.nodeId) {\n\t\t\tthis.sequenceNumber = Math.max(this.sequenceNumber, operation.sequenceNumber)\n\t\t}\n\t}\n\n\tprivate async allocateSequenceNumber(): Promise<number> {\n\t\tconst seq = await allocateNextSequenceNumber(this.adapter, this.nodeId)\n\t\tthis.sequenceNumber = seq\n\t\tthis.versionVector.set(this.nodeId, seq)\n\t\treturn seq\n\t}\n\n\t/**\n\t * Check the stored schema version and run any pending migrations.\n\t * Migrations are applied in version order within a transaction.\n\t */\n\tprivate async runMigrationsIfNeeded(): Promise<void> {\n\t\tconst storedVersion = await this.getStoredSchemaVersion()\n\t\tconst targetVersion = this.schema.version\n\n\t\tif (storedVersion >= targetVersion) {\n\t\t\t// Already up to date (or first run with version 1)\n\t\t\tif (storedVersion === 0) {\n\t\t\t\t// First open — store the initial version\n\t\t\t\tawait this.adapter.execute(\n\t\t\t\t\t\"INSERT OR REPLACE INTO _kora_meta (key, value) VALUES ('schema_version', ?)\",\n\t\t\t\t\t[String(targetVersion)],\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\t// Run each migration in order from storedVersion+1 to targetVersion\n\t\tconst migrations = this.schema.migrations ?? {}\n\t\tfor (let v = storedVersion + 1; v <= targetVersion; v++) {\n\t\t\tconst migration = migrations[v]\n\t\t\tif (!migration) continue\n\n\t\t\t// Generate SQL from structural steps\n\t\t\tconst sqlStatements = migrationStepsToSQL(migration.steps)\n\n\t\t\t// Execute structural changes individually, tolerating \"duplicate column\" errors\n\t\t\t// because generateSQL already emits --kora:safe-alter ALTER TABLE statements\n\t\t\t// for the current schema's columns (run via generateFullDDL in adapter.open()).\n\t\t\tfor (const sql of sqlStatements) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.adapter.execute(sql)\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconst msg = (e as Error).message || ''\n\t\t\t\t\tif (!msg.includes('duplicate column name')) {\n\t\t\t\t\t\tthrow e\n\t\t\t\t\t}\n\t\t\t\t\t// Column already exists (added by safe-alter in generateSQL) — safe to skip\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Run backfills in a transaction\n\t\t\tconst backfillSteps = migration.steps.filter(\n\t\t\t\t(s): s is Extract<MigrationStep, { type: 'backfill' }> => s.type === 'backfill',\n\t\t\t)\n\t\t\tfor (const step of backfillSteps) {\n\t\t\t\tawait this.runBackfill(step.collection, step.transform)\n\t\t\t}\n\t\t}\n\n\t\t// Update stored schema version\n\t\tawait this.adapter.execute(\n\t\t\t\"INSERT OR REPLACE INTO _kora_meta (key, value) VALUES ('schema_version', ?)\",\n\t\t\t[String(targetVersion)],\n\t\t)\n\t}\n\n\t/**\n\t * Get the stored schema version from _kora_meta. Returns 0 if not set.\n\t */\n\tprivate async getStoredSchemaVersion(): Promise<number> {\n\t\tconst rows = await this.adapter.query<MetaRow>(\n\t\t\t\"SELECT value FROM _kora_meta WHERE key = 'schema_version'\",\n\t\t)\n\t\treturn rows[0] ? Number(rows[0].value) : 0\n\t}\n\n\t/**\n\t * Run a backfill transform on all records in a collection.\n\t * Reads all rows, applies the transform, and updates changed fields.\n\t */\n\tprivate async runBackfill(\n\t\tcollection: string,\n\t\ttransform: (record: Record<string, unknown>) => Record<string, unknown>,\n\t): Promise<void> {\n\t\tconst rows = await this.adapter.query<RawCollectionRow>(\n\t\t\t`SELECT * FROM ${collection} WHERE _deleted = 0`,\n\t\t)\n\n\t\tawait this.adapter.transaction(async (tx) => {\n\t\t\tfor (const row of rows) {\n\t\t\t\tconst updates = transform(row as Record<string, unknown>)\n\t\t\t\tconst fields = Object.keys(updates)\n\t\t\t\tif (fields.length === 0) continue\n\n\t\t\t\tconst setClauses = fields.map((f) => `${f} = ?`).join(', ')\n\t\t\t\tconst values = fields.map((f) => {\n\t\t\t\t\tconst val = updates[f]\n\t\t\t\t\t// Serialize booleans to 0/1 for SQLite\n\t\t\t\t\tif (typeof val === 'boolean') return val ? 1 : 0\n\t\t\t\t\t// Serialize arrays/objects to JSON\n\t\t\t\t\tif (Array.isArray(val) || (typeof val === 'object' && val !== null)) {\n\t\t\t\t\t\treturn JSON.stringify(val)\n\t\t\t\t\t}\n\t\t\t\t\treturn val\n\t\t\t\t})\n\t\t\t\tvalues.push(row.id)\n\n\t\t\t\tawait tx.execute(`UPDATE ${collection} SET ${setClauses} WHERE id = ?`, values)\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate async loadOrGenerateNodeId(): Promise<string> {\n\t\tif (this.configNodeId) {\n\t\t\tif (this.isolation !== 'per-tab') {\n\t\t\t\tawait this.adapter.execute(\n\t\t\t\t\t\"INSERT OR REPLACE INTO _kora_meta (key, value) VALUES ('node_id', ?)\",\n\t\t\t\t\t[this.configNodeId],\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn this.configNodeId\n\t\t}\n\n\t\tif (this.isolation === 'per-tab') {\n\t\t\treturn resolvePerTabNodeId(this.dbName)\n\t\t}\n\n\t\t// Try to load existing node ID\n\t\tconst rows = await this.adapter.query<MetaRow>(\n\t\t\t\"SELECT value FROM _kora_meta WHERE key = 'node_id'\",\n\t\t)\n\t\tif (rows[0]) {\n\t\t\treturn rows[0].value\n\t\t}\n\n\t\t// Generate new node ID\n\t\tconst newNodeId = generateUUIDv7()\n\t\tawait this.adapter.execute(\"INSERT INTO _kora_meta (key, value) VALUES ('node_id', ?)\", [\n\t\t\tnewNodeId,\n\t\t])\n\t\treturn newNodeId\n\t}\n\n\tprivate async loadSequenceNumber(): Promise<number> {\n\t\tconst rows = await this.adapter.query<VersionVectorRow>(\n\t\t\t'SELECT sequence_number FROM _kora_version_vector WHERE node_id = ?',\n\t\t\t[this.nodeId],\n\t\t)\n\t\treturn rows[0]?.sequence_number ?? 0\n\t}\n\n\tprivate async loadVersionVector(): Promise<VersionVector> {\n\t\tconst rows = await this.adapter.query<VersionVectorRow>(\n\t\t\t'SELECT node_id, sequence_number FROM _kora_version_vector',\n\t\t)\n\t\tconst vector = createVersionVector()\n\t\tfor (const row of rows) {\n\t\t\tvector.set(row.node_id, row.sequence_number)\n\t\t}\n\t\treturn vector\n\t}\n\n\tprivate ensureOpen(): void {\n\t\tif (!this.opened) {\n\t\t\tthrow new StoreNotOpenError()\n\t\t}\n\t}\n}\n\n/**\n * Public-facing collection accessor. Provides CRUD + where.\n */\nexport interface CollectionAccessor {\n\tinsert(data: Record<string, unknown>): Promise<import('../types').CollectionRecord>\n\tfindById(id: string): Promise<import('../types').CollectionRecord | null>\n\tupdate(id: string, data: Record<string, unknown>): Promise<import('../types').CollectionRecord>\n\tdelete(id: string): Promise<void>\n\twhere(conditions: Record<string, unknown>): QueryBuilder\n}\n","import { createOperation } from '@korajs/core'\nimport type { Operation } from '@korajs/core'\nimport { RecordNotFoundError } from '../errors'\nimport { serializeRowVersion } from '../lww/row-version'\nimport { buildInsertQuery, buildSoftDeleteQuery } from '../query/sql-builder'\nimport { serializeOperation } from '../serialization/serializer'\nimport { allocateNextSequenceInTransaction } from '../store/sequence-allocator'\nimport type { RawCollectionRow } from '../types'\nimport { resolveCausalDeps } from './resolve-causal-deps'\nimport type { LocalMutationContext } from './types'\n\nexport interface ExecuteDeleteOptions {\n\t/** When true, skip RelationEnforcer (caller already enforced referential integrity). */\n\tskipReferentialEnforcement?: boolean\n\t/** Pre-built delete operation (avoids duplicate sequence allocation). */\n\toperation?: Operation\n}\n\n/**\n * Soft-delete a record and persist the operation log entry atomically.\n * Returns the primary delete operation and any cascaded side-effect operations.\n */\nexport async function executeDelete(\n\tctx: LocalMutationContext,\n\tid: string,\n\toptions?: ExecuteDeleteOptions,\n): Promise<Operation[]> {\n\tconst currentRows = await ctx.adapter.query<RawCollectionRow>(\n\t\t`SELECT * FROM ${ctx.collection} WHERE id = ? AND _deleted = 0`,\n\t\t[id],\n\t)\n\tif (!currentRows[0]) {\n\t\tthrow new RecordNotFoundError(ctx.collection, id)\n\t}\n\n\tconst causalDeps = resolveCausalDeps(ctx)\n\tlet operation = options?.operation\n\tconst cascadedOps: Operation[] = []\n\n\tawait ctx.adapter.transaction(async (tx) => {\n\t\tif (!operation) {\n\t\t\tconst sequenceNumber = await allocateNextSequenceInTransaction(tx, ctx.nodeId)\n\t\t\toperation = await createOperation(\n\t\t\t\t{\n\t\t\t\t\tnodeId: ctx.nodeId,\n\t\t\t\t\ttype: 'delete',\n\t\t\t\t\tcollection: ctx.collection,\n\t\t\t\t\trecordId: id,\n\t\t\t\t\tdata: null,\n\t\t\t\t\tpreviousData: null,\n\t\t\t\t\tsequenceNumber,\n\t\t\t\t\tcausalDeps,\n\t\t\t\t\tschemaVersion: ctx.schema.version,\n\t\t\t\t},\n\t\t\t\tctx.clock,\n\t\t\t)\n\t\t\tctx.causalTracker?.afterOperation(ctx.collection, operation.id, ctx.inTransaction)\n\t\t}\n\n\t\tif (ctx.relationEnforcer && !options?.skipReferentialEnforcement) {\n\t\t\tconst enforcementResult = await ctx.relationEnforcer.enforceDelete(ctx.collection, id, tx, [\n\t\t\t\toperation.id,\n\t\t\t])\n\t\t\tcascadedOps.push(...enforcementResult.operations)\n\t\t}\n\n\t\tconst version = serializeRowVersion(operation.timestamp)\n\t\tconst deleteQuery = buildSoftDeleteQuery(\n\t\t\tctx.collection,\n\t\t\tid,\n\t\t\toperation.timestamp.wallTime,\n\t\t\tversion,\n\t\t)\n\t\tconst opInsert = buildInsertQuery(\n\t\t\t`_kora_ops_${ctx.collection}`,\n\t\t\tserializeOperation(operation) as unknown as Record<string, unknown>,\n\t\t)\n\n\t\tawait tx.execute(deleteQuery.sql, deleteQuery.params)\n\t\tawait tx.execute(opInsert.sql, opInsert.params)\n\t})\n\n\tif (!operation) {\n\t\tthrow new Error('Delete operation was not created')\n\t}\n\n\tctx.onMutation(ctx.collection, operation)\n\tfor (const cascadedOp of cascadedOps) {\n\t\tctx.onMutation(cascadedOp.collection, cascadedOp)\n\t}\n\n\treturn [operation, ...cascadedOps]\n}\n","import { type HLCTimestamp, HybridLogicalClock } from '@korajs/core'\nimport type { RawCollectionRow } from '../types'\n\n/** Empty _version means legacy rows (compare by wallTime only via fallback). */\nexport const EMPTY_ROW_VERSION = ''\n\n/**\n * Serialize an HLC timestamp for storage in the `_version` column.\n * Lexicographic order matches {@link HybridLogicalClock.compare}.\n */\nexport function serializeRowVersion(timestamp: HLCTimestamp): string {\n\treturn HybridLogicalClock.serialize(timestamp)\n}\n\n/**\n * Read the version stamp stored on a materialized row.\n * Legacy rows without `_version` fall back to wallTime with logical 0.\n */\nexport function rowVersionFromRecord(\n\trow: Pick<RawCollectionRow, '_updated_at' | '_version'>,\n): HLCTimestamp {\n\tconst version = row._version\n\tif (typeof version === 'string' && version.length > 0) {\n\t\treturn HybridLogicalClock.deserialize(version)\n\t}\n\treturn { wallTime: row._updated_at, logical: 0, nodeId: '' }\n}\n\n/**\n * Returns true when `incoming` is strictly newer than the version on `row`.\n */\nexport function isIncomingNewerThanRow(\n\tincoming: HLCTimestamp,\n\trow: Pick<RawCollectionRow, '_updated_at' | '_version'>,\n): boolean {\n\treturn HybridLogicalClock.compare(incoming, rowVersionFromRecord(row)) > 0\n}\n\n/**\n * SQL fragment and params for LWW guards: apply only when row is missing or older.\n * Uses serialized `_version` for total order (matches HLC compare).\n */\nexport function lwwVersionWhereClause(remoteVersion: string): { sql: string; params: string[] } {\n\treturn {\n\t\tsql: '(_version = ? OR _version < ?)',\n\t\tparams: [EMPTY_ROW_VERSION, remoteVersion],\n\t}\n}\n","import type { CollectionDefinition, FieldDescriptor } from '@korajs/core'\nimport { QueryError } from '../errors'\nimport { lwwVersionWhereClause } from '../lww/row-version'\nimport type { QueryDescriptor, WhereOperators } from '../types'\n\n/**\n * Result of building a SQL query: the parameterized SQL string and its bound values.\n */\nexport interface SqlQuery {\n\tsql: string\n\tparams: unknown[]\n}\n\n/**\n * Build a SELECT query from a QueryDescriptor.\n * Automatically adds `WHERE _deleted = 0` to exclude soft-deleted records.\n *\n * @param descriptor - The query descriptor\n * @param fields - The field descriptors from the collection schema\n * @returns A parameterized SQL query\n */\nexport function buildSelectQuery(\n\tdescriptor: QueryDescriptor,\n\tfields: Record<string, FieldDescriptor>,\n): SqlQuery {\n\tconst params: unknown[] = []\n\tconst parts = [`SELECT * FROM ${descriptor.collection}`]\n\n\tconst whereClause = buildWhereClauseParts(descriptor.where, fields, params)\n\t// Always filter out soft-deleted records\n\tconst deletedFilter = '_deleted = 0'\n\tif (whereClause) {\n\t\tparts.push(`WHERE ${deletedFilter} AND ${whereClause}`)\n\t} else {\n\t\tparts.push(`WHERE ${deletedFilter}`)\n\t}\n\n\tif (descriptor.orderBy.length > 0) {\n\t\tconst orderParts = descriptor.orderBy.map((o) => {\n\t\t\tvalidateFieldName(o.field, fields)\n\t\t\treturn `${o.field} ${o.direction.toUpperCase()}`\n\t\t})\n\t\tparts.push(`ORDER BY ${orderParts.join(', ')}`)\n\t}\n\n\tif (descriptor.limit !== undefined) {\n\t\tparts.push(`LIMIT ${descriptor.limit}`)\n\t}\n\n\tif (descriptor.offset !== undefined) {\n\t\tparts.push(`OFFSET ${descriptor.offset}`)\n\t}\n\n\treturn { sql: parts.join(' '), params }\n}\n\n/**\n * Build a COUNT query from a QueryDescriptor.\n * Automatically adds `WHERE _deleted = 0`.\n *\n * @param descriptor - The query descriptor\n * @param fields - The field descriptors from the collection schema\n * @returns A parameterized SQL query that returns { count: number }\n */\nexport function buildCountQuery(\n\tdescriptor: QueryDescriptor,\n\tfields: Record<string, FieldDescriptor>,\n): SqlQuery {\n\tconst params: unknown[] = []\n\tconst parts = [`SELECT COUNT(*) as count FROM ${descriptor.collection}`]\n\n\tconst whereClause = buildWhereClauseParts(descriptor.where, fields, params)\n\tconst deletedFilter = '_deleted = 0'\n\tif (whereClause) {\n\t\tparts.push(`WHERE ${deletedFilter} AND ${whereClause}`)\n\t} else {\n\t\tparts.push(`WHERE ${deletedFilter}`)\n\t}\n\n\treturn { sql: parts.join(' '), params }\n}\n\n/**\n * Build an INSERT query for a collection record.\n *\n * @param collection - The collection name\n * @param record - The record data (already serialized with id, _created_at, _updated_at)\n * @returns A parameterized SQL query\n */\nexport function buildInsertQuery(collection: string, record: Record<string, unknown>): SqlQuery {\n\tconst columns = Object.keys(record)\n\tconst placeholders = columns.map(() => '?')\n\tconst params = Object.values(record)\n\n\tconst sql = `INSERT INTO ${collection} (${columns.join(', ')}) VALUES (${placeholders.join(', ')})`\n\treturn { sql, params }\n}\n\n/**\n * Build an UPDATE query for a collection record.\n *\n * @param collection - The collection name\n * @param id - The record ID\n * @param changes - The fields to update (already serialized)\n * @returns A parameterized SQL query\n */\nexport function buildUpdateQuery(\n\tcollection: string,\n\tid: string,\n\tchanges: Record<string, unknown>,\n): SqlQuery {\n\tconst setClauses = Object.keys(changes).map((col) => `${col} = ?`)\n\tconst params = [...Object.values(changes), id]\n\n\tconst sql = `UPDATE ${collection} SET ${setClauses.join(', ')} WHERE id = ?`\n\treturn { sql, params }\n}\n\n/**\n * Build a soft-delete query (SET _deleted = 1).\n *\n * @param collection - The collection name\n * @param id - The record ID\n * @param updatedAt - The timestamp to set on _updated_at\n * @returns A parameterized SQL query\n */\nexport function buildSoftDeleteQuery(\n\tcollection: string,\n\tid: string,\n\tupdatedAt: number,\n\tversion?: string,\n): SqlQuery {\n\tif (version !== undefined) {\n\t\treturn {\n\t\t\tsql: `UPDATE ${collection} SET _deleted = 1, _updated_at = ?, _version = ? WHERE id = ?`,\n\t\t\tparams: [updatedAt, version, id],\n\t\t}\n\t}\n\treturn {\n\t\tsql: `UPDATE ${collection} SET _deleted = 1, _updated_at = ? WHERE id = ?`,\n\t\tparams: [updatedAt, id],\n\t}\n}\n\n/**\n * Build an UPDATE that applies only when the row is missing or older than `remoteVersion`\n * (serialized HLC). Prevents stale remote sync from overwriting newer local materialized state.\n */\nexport function buildLwwUpdateQuery(\n\tcollection: string,\n\tid: string,\n\tchanges: Record<string, unknown>,\n\tremoteVersion: string,\n): SqlQuery {\n\tconst setClauses = Object.keys(changes).map((col) => `${col} = ?`)\n\tconst lww = lwwVersionWhereClause(remoteVersion)\n\tconst sql = `UPDATE ${collection} SET ${setClauses.join(', ')} WHERE id = ? AND ${lww.sql}`\n\tconst params = [...Object.values(changes), id, ...lww.params]\n\treturn { sql, params }\n}\n\n/**\n * Build a soft-delete that applies only when the row is older than `remoteVersion`.\n */\nexport function buildLwwSoftDeleteQuery(\n\tcollection: string,\n\tid: string,\n\tupdatedAt: number,\n\tversion: string,\n): SqlQuery {\n\tconst lww = lwwVersionWhereClause(version)\n\treturn {\n\t\tsql: `UPDATE ${collection} SET _deleted = 1, _updated_at = ?, _version = ? WHERE id = ? AND ${lww.sql}`,\n\t\tparams: [updatedAt, version, id, ...lww.params],\n\t}\n}\n\n/**\n * Build a WHERE clause from conditions, validating field names against the schema.\n *\n * @param where - The where conditions\n * @param fields - The field descriptors from the collection schema\n * @returns The SQL WHERE clause string and params, or null if no conditions\n */\nexport function buildWhereClause(\n\twhere: Record<string, unknown>,\n\tfields: Record<string, FieldDescriptor>,\n): SqlQuery | null {\n\tconst params: unknown[] = []\n\tconst result = buildWhereClauseParts(where, fields, params)\n\tif (!result) return null\n\treturn { sql: result, params }\n}\n\n// --- Internal helpers ---\n\nconst VALID_OPERATORS = new Set(['$eq', '$ne', '$gt', '$gte', '$lt', '$lte', '$in'])\n\nfunction buildWhereClauseParts(\n\twhere: Record<string, unknown>,\n\tfields: Record<string, FieldDescriptor>,\n\tparams: unknown[],\n): string | null {\n\tconst conditions: string[] = []\n\n\tfor (const [fieldName, value] of Object.entries(where)) {\n\t\tvalidateFieldName(fieldName, fields)\n\t\tconst descriptor = fields[fieldName]\n\n\t\tif (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n\t\t\t// Operator object: { $gt: 5, $lt: 10 }\n\t\t\tconst ops = value as WhereOperators\n\t\t\tfor (const [op, opValue] of Object.entries(ops)) {\n\t\t\t\tif (!VALID_OPERATORS.has(op)) {\n\t\t\t\t\tthrow new QueryError(`Unknown operator \"${op}\" on field \"${fieldName}\"`, {\n\t\t\t\t\t\tfield: fieldName,\n\t\t\t\t\t\toperator: op,\n\t\t\t\t\t\tvalidOperators: [...VALID_OPERATORS],\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tconditions.push(buildOperatorCondition(fieldName, op, opValue, descriptor, params))\n\t\t\t}\n\t\t} else {\n\t\t\t// Shorthand: { completed: false } means { completed: { $eq: false } }\n\t\t\tconditions.push(buildOperatorCondition(fieldName, '$eq', value, descriptor, params))\n\t\t}\n\t}\n\n\tif (conditions.length === 0) return null\n\treturn conditions.join(' AND ')\n}\n\nfunction buildOperatorCondition(\n\tfieldName: string,\n\toperator: string,\n\tvalue: unknown,\n\tdescriptor: FieldDescriptor | undefined,\n\tparams: unknown[],\n): string {\n\t// Serialize boolean values to 0/1 for SQL comparison\n\tconst sqlValue =\n\t\tdescriptor?.kind === 'boolean' && typeof value === 'boolean' ? (value ? 1 : 0) : value\n\n\tswitch (operator) {\n\t\tcase '$eq':\n\t\t\tif (sqlValue === null) {\n\t\t\t\treturn `${fieldName} IS NULL`\n\t\t\t}\n\t\t\tparams.push(sqlValue)\n\t\t\treturn `${fieldName} = ?`\n\t\tcase '$ne':\n\t\t\tif (sqlValue === null) {\n\t\t\t\treturn `${fieldName} IS NOT NULL`\n\t\t\t}\n\t\t\tparams.push(sqlValue)\n\t\t\treturn `${fieldName} != ?`\n\t\tcase '$gt':\n\t\t\tparams.push(sqlValue)\n\t\t\treturn `${fieldName} > ?`\n\t\tcase '$gte':\n\t\t\tparams.push(sqlValue)\n\t\t\treturn `${fieldName} >= ?`\n\t\tcase '$lt':\n\t\t\tparams.push(sqlValue)\n\t\t\treturn `${fieldName} < ?`\n\t\tcase '$lte':\n\t\t\tparams.push(sqlValue)\n\t\t\treturn `${fieldName} <= ?`\n\t\tcase '$in': {\n\t\t\tif (!Array.isArray(sqlValue)) {\n\t\t\t\tthrow new QueryError(`$in operator requires an array value for field \"${fieldName}\"`, {\n\t\t\t\t\tfield: fieldName,\n\t\t\t\t\treceived: typeof sqlValue,\n\t\t\t\t})\n\t\t\t}\n\t\t\tconst placeholders = sqlValue.map(() => '?')\n\t\t\tfor (const item of sqlValue) {\n\t\t\t\tparams.push(\n\t\t\t\t\tdescriptor?.kind === 'boolean' && typeof item === 'boolean' ? (item ? 1 : 0) : item,\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn `${fieldName} IN (${placeholders.join(', ')})`\n\t\t}\n\t\tdefault:\n\t\t\tthrow new QueryError(`Unknown operator \"${operator}\"`, { operator })\n\t}\n}\n\nfunction validateFieldName(fieldName: string, fields: Record<string, FieldDescriptor>): void {\n\t// Allow schema fields plus metadata fields that map to query-able columns\n\tconst allowedFields = new Set([\n\t\t...Object.keys(fields),\n\t\t'id',\n\t\t'createdAt',\n\t\t'updatedAt',\n\t\t'_created_at',\n\t\t'_updated_at',\n\t])\n\tif (!allowedFields.has(fieldName)) {\n\t\tthrow new QueryError(\n\t\t\t`Unknown field \"${fieldName}\" in query. Available fields: ${[...allowedFields].join(', ')}`,\n\t\t\t{ field: fieldName },\n\t\t)\n\t}\n}\n","import type { StorageAdapter, Transaction } from '../types'\n\ninterface SequenceRow {\n\tsequence_number: number\n}\n\n/**\n * Atomically increment and return the next sequence number for a node.\n * Uses SQLite UPSERT + RETURNING so concurrent tabs do not reuse sequence slots.\n */\nexport async function allocateNextSequenceNumber(\n\tadapter: StorageAdapter,\n\tnodeId: string,\n): Promise<number> {\n\tconst rows = await adapter.query<SequenceRow>(\n\t\t`INSERT INTO _kora_version_vector (node_id, sequence_number) VALUES (?, 1)\n ON CONFLICT(node_id) DO UPDATE SET sequence_number = sequence_number + 1\n RETURNING sequence_number`,\n\t\t[nodeId],\n\t)\n\tconst seq = rows[0]?.sequence_number\n\tif (seq === undefined) {\n\t\tthrow new Error(`Failed to allocate sequence number for node \"${nodeId}\"`)\n\t}\n\treturn seq\n}\n\n/**\n * Allocate the next sequence inside an existing storage transaction.\n */\nexport async function allocateNextSequenceInTransaction(\n\ttx: Transaction,\n\tnodeId: string,\n): Promise<number> {\n\tconst rows = await tx.query<SequenceRow>(\n\t\t`INSERT INTO _kora_version_vector (node_id, sequence_number) VALUES (?, 1)\n ON CONFLICT(node_id) DO UPDATE SET sequence_number = sequence_number + 1\n RETURNING sequence_number`,\n\t\t[nodeId],\n\t)\n\tconst seq = rows[0]?.sequence_number\n\tif (seq === undefined) {\n\t\tthrow new Error(`Failed to allocate sequence number for node \"${nodeId}\" in transaction`)\n\t}\n\treturn seq\n}\n\n/**\n * Read the current sequence for a node without incrementing.\n */\nexport async function readSequenceNumber(adapter: StorageAdapter, nodeId: string): Promise<number> {\n\tconst rows = await adapter.query<SequenceRow>(\n\t\t'SELECT sequence_number FROM _kora_version_vector WHERE node_id = ?',\n\t\t[nodeId],\n\t)\n\treturn rows[0]?.sequence_number ?? 0\n}\n","import type { LocalMutationContext } from './types'\n\n/**\n * Merge explicit parent deps (e.g. referential cascade) with tracker-derived deps.\n */\nexport function resolveCausalDeps(ctx: LocalMutationContext): string[] {\n\tconst merged: string[] = []\n\tfor (const id of ctx.extraCausalDeps ?? []) {\n\t\tif (!merged.includes(id)) {\n\t\t\tmerged.push(id)\n\t\t}\n\t}\n\tfor (const id of ctx.causalTracker?.nextCausalDeps(ctx.collection, ctx.inTransaction) ?? []) {\n\t\tif (!merged.includes(id)) {\n\t\t\tmerged.push(id)\n\t\t}\n\t}\n\treturn merged\n}\n","import { createOperation, generateUUIDv7, validateRecord } from '@korajs/core'\nimport { serializeRowVersion } from '../lww/row-version'\nimport { buildInsertQuery } from '../query/sql-builder'\nimport { serializeOperation, serializeRecord } from '../serialization/serializer'\nimport { allocateNextSequenceInTransaction } from '../store/sequence-allocator'\nimport type { CollectionRecord } from '../types'\nimport { resolveCausalDeps } from './resolve-causal-deps'\nimport type { LocalMutationContext } from './types'\n\n/**\n * Insert a record and persist the operation log entry atomically.\n */\nexport async function executeInsert(\n\tctx: LocalMutationContext,\n\tdata: Record<string, unknown>,\n): Promise<CollectionRecord> {\n\tconst validated = validateRecord(ctx.collection, ctx.definition, data, 'insert')\n\tconst recordId = generateUUIDv7()\n\n\tfor (const [fieldName, descriptor] of Object.entries(ctx.definition.fields)) {\n\t\tif (descriptor.auto && descriptor.kind === 'timestamp') {\n\t\t\tvalidated[fieldName] = Date.now()\n\t\t}\n\t}\n\n\tconst causalDeps = resolveCausalDeps(ctx)\n\n\tlet operation!: Awaited<ReturnType<typeof createOperation>>\n\tlet record!: Record<string, unknown>\n\n\tawait ctx.adapter.transaction(async (tx) => {\n\t\tconst sequenceNumber = await allocateNextSequenceInTransaction(tx, ctx.nodeId)\n\t\toperation = await createOperation(\n\t\t\t{\n\t\t\t\tnodeId: ctx.nodeId,\n\t\t\t\ttype: 'insert',\n\t\t\t\tcollection: ctx.collection,\n\t\t\t\trecordId,\n\t\t\t\tdata: { ...validated },\n\t\t\t\tpreviousData: null,\n\t\t\t\tsequenceNumber,\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(ctx.collection, operation.id, ctx.inTransaction)\n\n\t\tconst serializedData = serializeRecord(validated, ctx.definition.fields)\n\t\tconst version = serializeRowVersion(operation.timestamp)\n\t\trecord = {\n\t\t\tid: recordId,\n\t\t\t...serializedData,\n\t\t\t_created_at: operation.timestamp.wallTime,\n\t\t\t_updated_at: operation.timestamp.wallTime,\n\t\t\t_version: version,\n\t\t}\n\n\t\tconst builtInsert = buildInsertQuery(ctx.collection, record)\n\t\tconst opInsert = buildInsertQuery(\n\t\t\t`_kora_ops_${ctx.collection}`,\n\t\t\tserializeOperation(operation) as unknown as Record<string, unknown>,\n\t\t)\n\n\t\tawait tx.execute(builtInsert.sql, builtInsert.params)\n\t\tawait tx.execute(opInsert.sql, opInsert.params)\n\t})\n\n\tctx.onMutation(ctx.collection, operation)\n\n\treturn {\n\t\tid: recordId,\n\t\t...validated,\n\t\tcreatedAt: operation.timestamp.wallTime,\n\t\tupdatedAt: operation.timestamp.wallTime,\n\t}\n}\n","import type { AtomicOp } from '@korajs/core'\nimport {\n\tcreateOperation,\n\tisAtomicOp,\n\tresolveAtomicOp,\n\ttoAtomicOp,\n\tvalidateRecord,\n} from '@korajs/core'\nimport { RecordNotFoundError } from '../errors'\nimport { serializeRowVersion } from '../lww/row-version'\nimport { buildInsertQuery, buildUpdateQuery } from '../query/sql-builder'\nimport { deserializeRecord, serializeOperation, serializeRecord } from '../serialization/serializer'\nimport { validateUpdateStateMachine } from '../state-machine/state-validator'\nimport { allocateNextSequenceInTransaction } from '../store/sequence-allocator'\nimport type { CollectionRecord, RawCollectionRow } from '../types'\nimport { resolveCausalDeps } from './resolve-causal-deps'\nimport type { LocalMutationContext } from './types'\n\n/**\n * Update a record and persist the operation log entry atomically.\n */\nexport async function executeUpdate(\n\tctx: LocalMutationContext,\n\tid: string,\n\tdata: Record<string, unknown>,\n): Promise<CollectionRecord> {\n\tconst currentRows = await ctx.adapter.query<RawCollectionRow>(\n\t\t`SELECT * FROM ${ctx.collection} WHERE id = ? AND _deleted = 0`,\n\t\t[id],\n\t)\n\tconst currentRow = currentRows[0]\n\tif (!currentRow) {\n\t\tthrow new RecordNotFoundError(ctx.collection, id)\n\t}\n\n\tlet validated = validateRecord(ctx.collection, ctx.definition, data, 'update')\n\tconst currentRecord = deserializeRecord(currentRow, ctx.definition.fields)\n\tvalidated = validateUpdateStateMachine(\n\t\tctx.collection,\n\t\tid,\n\t\tctx.definition,\n\t\tcurrentRecord,\n\t\tvalidated,\n\t)\n\n\tif (Object.keys(validated).length === 0) {\n\t\treturn { ...currentRecord }\n\t}\n\n\tconst previousData: Record<string, unknown> = {}\n\tconst resolvedData: Record<string, unknown> = {}\n\tconst atomicOps: Record<string, AtomicOp> = {}\n\n\tfor (const key of Object.keys(validated)) {\n\t\tconst value = validated[key]\n\t\tpreviousData[key] = currentRecord[key]\n\n\t\tif (isAtomicOp(value)) {\n\t\t\tresolvedData[key] = resolveAtomicOp(currentRecord[key], value)\n\t\t\tatomicOps[key] = toAtomicOp(value)\n\t\t} else {\n\t\t\tresolvedData[key] = value\n\t\t}\n\t}\n\n\tconst hasAtomicOps = Object.keys(atomicOps).length > 0\n\tconst causalDeps = resolveCausalDeps(ctx)\n\tlet operation!: Awaited<ReturnType<typeof createOperation>>\n\n\tawait ctx.adapter.transaction(async (tx) => {\n\t\tconst sequenceNumber = await allocateNextSequenceInTransaction(tx, ctx.nodeId)\n\t\toperation = await createOperation(\n\t\t\t{\n\t\t\t\tnodeId: ctx.nodeId,\n\t\t\t\ttype: 'update',\n\t\t\t\tcollection: ctx.collection,\n\t\t\t\trecordId: id,\n\t\t\t\tdata: { ...resolvedData },\n\t\t\t\tpreviousData,\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps,\n\t\t\t\tschemaVersion: ctx.schema.version,\n\t\t\t\t...(hasAtomicOps ? { atomicOps } : {}),\n\t\t\t},\n\t\t\tctx.clock,\n\t\t)\n\t\tctx.causalTracker?.afterOperation(ctx.collection, operation.id, ctx.inTransaction)\n\n\t\tconst serializedChanges = serializeRecord(resolvedData, ctx.definition.fields)\n\t\tconst version = serializeRowVersion(operation.timestamp)\n\t\tconst updateQuery = buildUpdateQuery(ctx.collection, id, {\n\t\t\t...serializedChanges,\n\t\t\t_updated_at: operation.timestamp.wallTime,\n\t\t\t_version: version,\n\t\t})\n\t\tconst opInsert = buildInsertQuery(\n\t\t\t`_kora_ops_${ctx.collection}`,\n\t\t\tserializeOperation(operation) as unknown as Record<string, unknown>,\n\t\t)\n\n\t\tawait tx.execute(updateQuery.sql, updateQuery.params)\n\t\tawait tx.execute(opInsert.sql, opInsert.params)\n\t})\n\n\tctx.onMutation(ctx.collection, operation)\n\n\tconst rows = await ctx.adapter.query<RawCollectionRow>(\n\t\t`SELECT * FROM ${ctx.collection} WHERE id = ? AND _deleted = 0`,\n\t\t[id],\n\t)\n\tconst row = rows[0]\n\tif (!row) {\n\t\tthrow new RecordNotFoundError(ctx.collection, id)\n\t}\n\treturn deserializeRecord(row, ctx.definition.fields)\n}\n","import { KoraError, validateTransition } from '@korajs/core'\nimport type {\n\tCollectionDefinition,\n\tStateMachineConstraint,\n\tStateMachineDefinition,\n} from '@korajs/core'\n\n/**\n * Error thrown when a local mutation attempts an invalid state transition.\n *\n * Contains enough context to debug without reproduction:\n * the collection, record, field, current state, attempted state, and allowed transitions.\n */\nexport class InvalidStateTransitionError extends KoraError {\n\tconstructor(\n\t\tpublic readonly collection: string,\n\t\tpublic readonly recordId: string,\n\t\tpublic readonly field: string,\n\t\tpublic readonly fromState: string,\n\t\tpublic readonly toState: string,\n\t\tpublic readonly allowedStates: string[],\n\t) {\n\t\tsuper(\n\t\t\t`Invalid state transition in collection \"${collection}\": ` +\n\t\t\t\t`cannot transition field \"${field}\" from \"${fromState}\" to \"${toState}\". ` +\n\t\t\t\t`Allowed transitions from \"${fromState}\": ${allowedStates.length > 0 ? allowedStates.join(', ') : '(none -- terminal state)'}`,\n\t\t\t'INVALID_STATE_TRANSITION',\n\t\t\t{ collection, recordId, field, fromState, toState, allowedStates },\n\t\t)\n\t\tthis.name = 'InvalidStateTransitionError'\n\t}\n}\n\n/**\n * Validates a state machine transition for a local mutation (insert or update).\n *\n * For inserts: validates that the initial state (from the data or the default value)\n * is a known state in the state machine.\n *\n * For updates: looks up the current state field value and checks whether\n * the transition to the new value is allowed.\n *\n * @param collectionName - Name of the collection\n * @param recordId - The record being mutated\n * @param stateMachine - The state machine definition\n * @param currentState - The current value of the state field (null for inserts)\n * @param newState - The new value being set for the state field\n * @returns An object indicating whether the transition is valid, and if not, the allowed states.\n * When `onInvalidTransition` is 'last-valid-state', callers should suppress the field update\n * rather than throwing.\n */\nexport function validateStateTransition(\n\tcollectionName: string,\n\trecordId: string,\n\tstateMachine: StateMachineDefinition,\n\tcurrentState: string | null,\n\tnewState: string,\n): { valid: boolean; allowedStates: string[] } {\n\t// For inserts, any valid enum value is acceptable as the initial state\n\t// (schema validation already ensures the value is a valid enum value)\n\tif (currentState === null) {\n\t\treturn { valid: true, allowedStates: [] }\n\t}\n\n\t// Same-state transitions are always valid (idempotent updates)\n\tif (currentState === newState) {\n\t\treturn { valid: true, allowedStates: stateMachine.transitions[currentState] ?? [] }\n\t}\n\n\tconst constraint: StateMachineConstraint = {\n\t\tfield: stateMachine.field,\n\t\tcollection: collectionName,\n\t\ttransitions: stateMachine.transitions,\n\t}\n\tconst transitionResult = validateTransition(constraint, currentState, newState)\n\tif (transitionResult.valid) {\n\t\treturn { valid: true, allowedStates: transitionResult.allowedTargets }\n\t}\n\n\tconst allowedStates = transitionResult.allowedTargets\n\n\tif (stateMachine.onInvalidTransition === 'reject') {\n\t\tthrow new InvalidStateTransitionError(\n\t\t\tcollectionName,\n\t\t\trecordId,\n\t\t\tstateMachine.field,\n\t\t\tcurrentState,\n\t\t\tnewState,\n\t\t\tallowedStates,\n\t\t)\n\t}\n\n\t// 'last-valid-state': return invalid so the caller can suppress the field update\n\treturn { valid: false, allowedStates }\n}\n\n/**\n * Checks whether a collection update data object contains a change to the state machine field,\n * and if so, validates the transition.\n *\n * If the state field is not in the update data, returns the data unchanged.\n * If the transition is invalid and mode is 'last-valid-state', removes the field from the data.\n * If the transition is invalid and mode is 'reject', throws InvalidStateTransitionError.\n *\n * @param collectionName - Name of the collection\n * @param recordId - The record being updated\n * @param collectionDef - The collection definition from the schema\n * @param currentRecord - The current record data (must include the state field)\n * @param updateData - The partial update data\n * @returns The update data, potentially with the state field removed if invalid and mode is 'last-valid-state'\n */\nexport function validateUpdateStateMachine(\n\tcollectionName: string,\n\trecordId: string,\n\tcollectionDef: CollectionDefinition,\n\tcurrentRecord: Record<string, unknown>,\n\tupdateData: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst stateMachine = collectionDef.stateMachine\n\tif (stateMachine === undefined) {\n\t\treturn updateData\n\t}\n\n\tconst stateField = stateMachine.field\n\tif (!(stateField in updateData)) {\n\t\t// State field not being changed -- no validation needed\n\t\treturn updateData\n\t}\n\n\tconst currentState = currentRecord[stateField]\n\tconst newState = updateData[stateField]\n\n\t// Both values must be strings for state machine validation\n\tif (typeof currentState !== 'string' || typeof newState !== 'string') {\n\t\treturn updateData\n\t}\n\n\tconst result = validateStateTransition(\n\t\tcollectionName,\n\t\trecordId,\n\t\tstateMachine,\n\t\tcurrentState,\n\t\tnewState,\n\t)\n\n\tif (result.valid) {\n\t\treturn updateData\n\t}\n\n\t// Mode is 'last-valid-state': silently remove the state field from the update\n\tconst filtered = { ...updateData }\n\tdelete filtered[stateField]\n\n\t// If no fields remain after removing the state field, the update becomes a no-op.\n\t// Return the empty object -- the caller can decide whether to proceed.\n\treturn filtered\n}\n","import type {\n\tCausalTracker,\n\tCollectionDefinition,\n\tHybridLogicalClock,\n\tOperation,\n\tSchemaDefinition,\n} from '@korajs/core'\nimport { executeDelete } from '../mutations/execute-delete'\nimport { executeInsert } from '../mutations/execute-insert'\nimport { executeUpdate } from '../mutations/execute-update'\nimport type { LocalMutationContext } from '../mutations/types'\nimport type { RelationEnforcer } from '../relations/relation-enforcer'\nimport { deserializeRecord } from '../serialization/serializer'\nimport type {\n\tCollectionRecord,\n\tLocalMutationHandler,\n\tRawCollectionRow,\n\tStorageAdapter,\n} from '../types'\n\n/**\n * Callback invoked after a mutation so the Store can notify subscriptions.\n */\nexport type MutationCallback = (collection: string, operation: Operation) => void\n\n/**\n * Collection provides CRUD operations on a single schema collection.\n * Delegates to {@link LocalMutationHandler} when configured (unified apply pipeline),\n * otherwise uses shared mutation executors directly.\n */\nexport class Collection {\n\tconstructor(\n\t\tprivate readonly name: string,\n\t\tprivate readonly definition: CollectionDefinition,\n\t\tprivate readonly schema: SchemaDefinition,\n\t\tprivate readonly adapter: StorageAdapter,\n\t\tprivate readonly clock: HybridLogicalClock,\n\t\tprivate readonly nodeId: string,\n\t\tprivate readonly allocateSequenceNumber: () => Promise<number>,\n\t\tprivate readonly onMutation: MutationCallback,\n\t\tprivate readonly relationEnforcer: RelationEnforcer | null,\n\t\tprivate mutationHandler: LocalMutationHandler | null,\n\t\tprivate readonly causalTracker: CausalTracker | null,\n\t) {}\n\n\tprivate mutationContext(): LocalMutationContext {\n\t\treturn {\n\t\t\tcollection: this.name,\n\t\t\tdefinition: this.definition,\n\t\t\tschema: this.schema,\n\t\t\tadapter: this.adapter,\n\t\t\tclock: this.clock,\n\t\t\tnodeId: this.nodeId,\n\t\t\tallocateSequenceNumber: this.allocateSequenceNumber,\n\t\t\tonMutation: this.onMutation,\n\t\t\trelationEnforcer: this.relationEnforcer,\n\t\t\tcausalTracker: this.causalTracker,\n\t\t\tinTransaction: false,\n\t\t}\n\t}\n\n\tasync insert(data: Record<string, unknown>): Promise<CollectionRecord> {\n\t\tif (this.mutationHandler) {\n\t\t\treturn this.mutationHandler.insert(this.name, data)\n\t\t}\n\t\treturn executeInsert(this.mutationContext(), data)\n\t}\n\n\tasync findById(id: string): Promise<CollectionRecord | null> {\n\t\tconst rows = await this.adapter.query<RawCollectionRow>(\n\t\t\t`SELECT * FROM ${this.name} WHERE id = ? AND _deleted = 0`,\n\t\t\t[id],\n\t\t)\n\t\tconst row = rows[0]\n\t\tif (!row) return null\n\t\treturn deserializeRecord(row, this.definition.fields)\n\t}\n\n\tasync update(id: string, data: Record<string, unknown>): Promise<CollectionRecord> {\n\t\tif (this.mutationHandler) {\n\t\t\treturn this.mutationHandler.update(this.name, id, data)\n\t\t}\n\t\treturn executeUpdate(this.mutationContext(), id, data)\n\t}\n\n\tasync delete(id: string): Promise<void> {\n\t\tif (this.mutationHandler) {\n\t\t\tawait this.mutationHandler.delete(this.name, id)\n\t\t\treturn\n\t\t}\n\t\tawait executeDelete(this.mutationContext(), id)\n\t}\n\n\tgetName(): string {\n\t\treturn this.name\n\t}\n\n\tgetDefinition(): CollectionDefinition {\n\t\treturn this.definition\n\t}\n\n\t/** Replace the mutation handler (e.g. after ApplyPipeline is wired in createApp). */\n\tsetMutationHandler(handler: LocalMutationHandler | null): void {\n\t\tthis.mutationHandler = handler\n\t}\n}\n","import type { CollectionDefinition, SchemaDefinition } from '@korajs/core'\nimport { deserializeRecord } from '../serialization/serializer'\nimport type { SubscriptionManager } from '../subscription/subscription-manager'\nimport type {\n\tCollectionRecord,\n\tOrderByDirection,\n\tQueryDescriptor,\n\tRawCollectionRow,\n\tStorageAdapter,\n\tSubscriptionCallback,\n\tWhereClause,\n} from '../types'\nimport { pluralize, singularize } from './pluralize'\nimport { buildCountQuery, buildSelectQuery } from './sql-builder'\n\n/**\n * Fluent query builder for constructing and executing collection queries.\n * Supports where, orderBy, limit, offset, include, exec, count, and subscribe.\n *\n * The generic parameter `T` defaults to `CollectionRecord` for backward compatibility\n * but can be narrowed to a specific record type for full type inference.\n *\n * @example\n * ```typescript\n * const todos = await app.todos\n * .where({ completed: false })\n * .orderBy('createdAt', 'desc')\n * .limit(10)\n * .exec()\n * ```\n */\nexport class QueryBuilder<T = CollectionRecord> {\n\tprivate descriptor: QueryDescriptor\n\n\tconstructor(\n\t\tprivate readonly collectionName: string,\n\t\tprivate readonly definition: CollectionDefinition,\n\t\tprivate readonly adapter: StorageAdapter,\n\t\tprivate readonly subscriptionManager: SubscriptionManager,\n\t\tinitialWhere: WhereClause = {},\n\t\tprivate readonly schema?: SchemaDefinition,\n\t) {\n\t\tthis.descriptor = {\n\t\t\tcollection: collectionName,\n\t\t\twhere: { ...initialWhere },\n\t\t\torderBy: [],\n\t\t}\n\t}\n\n\t/**\n\t * Add WHERE conditions (AND semantics, merged with existing conditions).\n\t */\n\twhere(conditions: WhereClause): QueryBuilder<T> {\n\t\tconst clone = this.clone()\n\t\tclone.descriptor = {\n\t\t\t...clone.descriptor,\n\t\t\twhere: { ...clone.descriptor.where, ...conditions },\n\t\t}\n\t\treturn clone\n\t}\n\n\t/**\n\t * Add ORDER BY clause.\n\t */\n\torderBy(field: string, direction: OrderByDirection = 'asc'): QueryBuilder<T> {\n\t\tconst clone = this.clone()\n\t\tclone.descriptor = {\n\t\t\t...clone.descriptor,\n\t\t\torderBy: [...clone.descriptor.orderBy, { field, direction }],\n\t\t}\n\t\treturn clone\n\t}\n\n\t/**\n\t * Set result limit.\n\t */\n\tlimit(n: number): QueryBuilder<T> {\n\t\tconst clone = this.clone()\n\t\tclone.descriptor = { ...clone.descriptor, limit: n }\n\t\treturn clone\n\t}\n\n\t/**\n\t * Set result offset.\n\t */\n\toffset(n: number): QueryBuilder<T> {\n\t\tconst clone = this.clone()\n\t\tclone.descriptor = { ...clone.descriptor, offset: n }\n\t\treturn clone\n\t}\n\n\t/**\n\t * Include related records in the query results.\n\t * Follows relations defined in the schema to batch-fetch related data.\n\t *\n\t * @param targets - Relation target names (collection names or relation names)\n\t * @returns A new QueryBuilder with include targets added\n\t *\n\t * @example\n\t * ```typescript\n\t * const todosWithProject = await app.todos\n\t * .where({ completed: false })\n\t * .include('project')\n\t * .exec()\n\t * ```\n\t */\n\tinclude(...targets: string[]): QueryBuilder<T> {\n\t\tconst clone = this.clone()\n\t\tconst existing = clone.descriptor.include ?? []\n\t\tclone.descriptor = {\n\t\t\t...clone.descriptor,\n\t\t\tinclude: [...existing, ...targets],\n\t\t}\n\t\treturn clone\n\t}\n\n\t/**\n\t * Execute the query and return results.\n\t */\n\tasync exec(): Promise<T[]> {\n\t\tconst { sql, params } = buildSelectQuery(this.descriptor, this.definition.fields)\n\t\tconst rows = await this.adapter.query<RawCollectionRow>(sql, params)\n\t\tconst records = rows.map((row) => deserializeRecord(row, this.definition.fields))\n\n\t\t// Resolve includes if any\n\t\tif (this.descriptor.include && this.descriptor.include.length > 0 && this.schema) {\n\t\t\tawait this.resolveIncludes(records)\n\t\t}\n\n\t\treturn records as T[]\n\t}\n\n\t/**\n\t * Execute a COUNT query and return the count.\n\t */\n\tasync count(): Promise<number> {\n\t\tconst { sql, params } = buildCountQuery(this.descriptor, this.definition.fields)\n\t\tconst rows = await this.adapter.query<{ count: number }>(sql, params)\n\t\treturn rows[0]?.count ?? 0\n\t}\n\n\t/**\n\t * Subscribe to query results. Callback is called immediately with current results,\n\t * then again whenever the results change due to mutations.\n\t *\n\t * @returns An unsubscribe function\n\t */\n\tsubscribe(callback: SubscriptionCallback<T>): () => void {\n\t\tconst executeFn = () => this.exec()\n\n\t\t// Resolve includeCollections for subscription tracking\n\t\tconst descriptorCopy = { ...this.descriptor }\n\t\tif (descriptorCopy.include && descriptorCopy.include.length > 0 && this.schema) {\n\t\t\tdescriptorCopy.includeCollections = this.resolveIncludeCollections(descriptorCopy.include)\n\t\t}\n\n\t\t// Use registerAndFetch to execute immediately, set lastResults,\n\t\t// and call callback — ensuring subsequent flushes diff correctly.\n\t\treturn this.subscriptionManager.registerAndFetch(\n\t\t\tdescriptorCopy,\n\t\t\tcallback as SubscriptionCallback<CollectionRecord>,\n\t\t\texecuteFn as () => Promise<CollectionRecord[]>,\n\t\t)\n\t}\n\n\t/** Get the internal descriptor (for testing/debugging) */\n\tgetDescriptor(): QueryDescriptor {\n\t\treturn { ...this.descriptor }\n\t}\n\n\tprivate clone(): QueryBuilder<T> {\n\t\tconst qb = new QueryBuilder<T>(\n\t\t\tthis.collectionName,\n\t\t\tthis.definition,\n\t\t\tthis.adapter,\n\t\t\tthis.subscriptionManager,\n\t\t\t{},\n\t\t\tthis.schema,\n\t\t)\n\t\tqb.descriptor = {\n\t\t\t...this.descriptor,\n\t\t\twhere: { ...this.descriptor.where },\n\t\t\torderBy: [...this.descriptor.orderBy],\n\t\t\tinclude: this.descriptor.include ? [...this.descriptor.include] : undefined,\n\t\t\tincludeCollections: this.descriptor.includeCollections\n\t\t\t\t? [...this.descriptor.includeCollections]\n\t\t\t\t: undefined,\n\t\t}\n\t\treturn qb\n\t}\n\n\t/**\n\t * Resolve include targets to their actual collection names for subscription tracking.\n\t */\n\tprivate resolveIncludeCollections(targets: string[]): string[] {\n\t\tif (!this.schema) return []\n\t\tconst collections: string[] = []\n\n\t\tfor (const target of targets) {\n\t\t\tconst relation = this.findRelation(target)\n\t\t\tif (relation) {\n\t\t\t\t// For many-to-one: the related collection is `relation.to`\n\t\t\t\t// For one-to-many: the related collection is `relation.from`\n\t\t\t\tif (relation.from === this.collectionName) {\n\t\t\t\t\tcollections.push(relation.to)\n\t\t\t\t} else {\n\t\t\t\t\tcollections.push(relation.from)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn collections\n\t}\n\n\t/**\n\t * Resolve includes after primary query, batch-fetching related records.\n\t */\n\tprivate async resolveIncludes(records: CollectionRecord[]): Promise<void> {\n\t\tif (!this.schema || !this.descriptor.include || records.length === 0) return\n\n\t\tfor (const target of this.descriptor.include) {\n\t\t\tconst relation = this.findRelation(target)\n\t\t\tif (!relation) {\n\t\t\t\tthrow new QueryError(\n\t\t\t\t\t`No relation found for include target \"${target}\" on collection \"${this.collectionName}\". ` +\n\t\t\t\t\t\t`Check that a relation is defined in your schema that connects \"${this.collectionName}\" to \"${target}\".`,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tif (relation.from === this.collectionName) {\n\t\t\t\t// Many-to-one or one-to-one: primary has FK → fetch parent records\n\t\t\t\tawait this.resolveManyToOneInclude(records, relation, target)\n\t\t\t} else {\n\t\t\t\t// One-to-many: related collection has FK → fetch children\n\t\t\t\tawait this.resolveOneToManyInclude(records, relation, target)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Many-to-one: collect FK values from primary results, batch-fetch related, attach as singular.\n\t */\n\tprivate async resolveManyToOneInclude(\n\t\trecords: CollectionRecord[],\n\t\trelation: { from: string; to: string; field: string },\n\t\ttarget: string,\n\t): Promise<void> {\n\t\tconst fkField = relation.field\n\t\tconst fkValues = records\n\t\t\t.map((r) => r[fkField])\n\t\t\t.filter((v): v is string => v !== null && v !== undefined && typeof v === 'string')\n\n\t\tif (fkValues.length === 0) {\n\t\t\t// All null FKs — set property to null on all records\n\t\t\tconst propName = singularize(target)\n\t\t\tfor (const record of records) {\n\t\t\t\t;(record as Record<string, unknown>)[propName] = null\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tconst uniqueFks = [...new Set(fkValues)]\n\t\tconst relatedCollection = relation.to\n\t\tconst relatedDef = this.schema?.collections[relatedCollection]\n\t\tif (!relatedDef) return\n\n\t\t// Batch fetch: SELECT * FROM <to> WHERE id IN (...) AND _deleted = 0\n\t\tconst placeholders = uniqueFks.map(() => '?').join(', ')\n\t\tconst sql = `SELECT * FROM ${relatedCollection} WHERE id IN (${placeholders}) AND _deleted = 0`\n\t\tconst rows = await this.adapter.query<RawCollectionRow>(sql, uniqueFks)\n\t\tconst relatedRecords = rows.map((row) => deserializeRecord(row, relatedDef.fields))\n\n\t\t// Build lookup\n\t\tconst lookup = new Map<string, CollectionRecord>()\n\t\tfor (const r of relatedRecords) {\n\t\t\tlookup.set(r.id, r)\n\t\t}\n\n\t\t// Attach as singular property\n\t\tconst propName = singularize(target)\n\t\tfor (const record of records) {\n\t\t\tconst fk = record[fkField] as string | null\n\t\t\t;(record as Record<string, unknown>)[propName] = fk ? (lookup.get(fk) ?? null) : null\n\t\t}\n\t}\n\n\t/**\n\t * One-to-many: collect primary IDs, batch-fetch children, attach as array.\n\t */\n\tprivate async resolveOneToManyInclude(\n\t\trecords: CollectionRecord[],\n\t\trelation: { from: string; to: string; field: string },\n\t\ttarget: string,\n\t): Promise<void> {\n\t\tconst primaryIds = records.map((r) => r.id)\n\t\tconst relatedCollection = relation.from\n\t\tconst relatedDef = this.schema?.collections[relatedCollection]\n\t\tif (!relatedDef) return\n\n\t\tconst fkField = relation.field\n\t\tconst placeholders = primaryIds.map(() => '?').join(', ')\n\t\tconst sql = `SELECT * FROM ${relatedCollection} WHERE ${fkField} IN (${placeholders}) AND _deleted = 0`\n\t\tconst rows = await this.adapter.query<RawCollectionRow>(sql, primaryIds)\n\t\tconst relatedRecords = rows.map((row) => deserializeRecord(row, relatedDef.fields))\n\n\t\t// Group by FK\n\t\tconst grouped = new Map<string, CollectionRecord[]>()\n\t\tfor (const r of relatedRecords) {\n\t\t\tconst fk = r[fkField] as string\n\t\t\tif (!grouped.has(fk)) {\n\t\t\t\tgrouped.set(fk, [])\n\t\t\t}\n\t\t\tgrouped.get(fk)?.push(r)\n\t\t}\n\n\t\t// Attach as array property\n\t\tconst propName = pluralize(target)\n\t\tfor (const record of records) {\n\t\t\t;(record as Record<string, unknown>)[propName] = grouped.get(record.id) ?? []\n\t\t}\n\t}\n\n\t/**\n\t * Find a relation definition matching the include target.\n\t * Searches by relation name, target collection name, and singularized/pluralized variants.\n\t */\n\tprivate findRelation(\n\t\ttarget: string,\n\t): { from: string; to: string; field: string; type: string } | null {\n\t\tif (!this.schema) return null\n\n\t\tfor (const [_name, rel] of Object.entries(this.schema.relations)) {\n\t\t\t// Direct match: target is the related collection name\n\t\t\tif (rel.from === this.collectionName && rel.to === target) return rel\n\t\t\tif (rel.to === this.collectionName && rel.from === target) return rel\n\n\t\t\t// Singularized match: \"project\" matches relation to \"projects\"\n\t\t\tif (rel.from === this.collectionName && rel.to === pluralize(target)) return rel\n\t\t\tif (rel.to === this.collectionName && rel.from === pluralize(target)) return rel\n\n\t\t\t// Pluralized match: \"todos\" matches relation from \"todos\"\n\t\t\tif (rel.from === this.collectionName && rel.to === singularize(target)) return rel\n\t\t\tif (rel.to === this.collectionName && rel.from === singularize(target)) return rel\n\t\t}\n\n\t\treturn null\n\t}\n}\n\n/**\n * Error thrown when a query encounters an invalid state.\n */\nclass QueryError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message)\n\t\tthis.name = 'QueryError'\n\t}\n}\n","/**\n * Minimal pluralization/singularization utilities for relation name resolution.\n * Handles common English patterns — not meant to be exhaustive.\n */\n\nfunction isVowel(char: string | undefined): boolean {\n\tif (!char) return false\n\treturn 'aeiouAEIOU'.includes(char)\n}\n\n/**\n * Pluralize a word using common English rules.\n *\n * @example\n * ```\n * pluralize('project') // 'projects'\n * pluralize('category') // 'categories'\n * pluralize('match') // 'matches'\n * ```\n */\nexport function pluralize(word: string): string {\n\tif (word.endsWith('s')) return word\n\tif (word.endsWith('y') && !isVowel(word[word.length - 2])) {\n\t\treturn `${word.slice(0, -1)}ies`\n\t}\n\tif (word.endsWith('sh') || word.endsWith('ch') || word.endsWith('x') || word.endsWith('z')) {\n\t\treturn `${word}es`\n\t}\n\treturn `${word}s`\n}\n\n/**\n * Singularize a word using common English rules.\n *\n * @example\n * ```\n * singularize('projects') // 'project'\n * singularize('categories') // 'category'\n * singularize('matches') // 'match'\n * ```\n */\nexport function singularize(word: string): string {\n\tif (word.endsWith('ies') && !isVowel(word[word.length - 4])) {\n\t\treturn `${word.slice(0, -3)}y`\n\t}\n\tif (\n\t\tword.endsWith('shes') ||\n\t\tword.endsWith('ches') ||\n\t\tword.endsWith('xes') ||\n\t\tword.endsWith('zes')\n\t) {\n\t\treturn word.slice(0, -2)\n\t}\n\tif (word.endsWith('ses')) {\n\t\treturn word.slice(0, -2)\n\t}\n\tif (word.endsWith('s') && !word.endsWith('ss')) {\n\t\treturn word.slice(0, -1)\n\t}\n\treturn word\n}\n","import type { HybridLogicalClock, Operation, SchemaDefinition } from '@korajs/core'\nimport { KoraError, createOperation } from '@korajs/core'\nimport { buildInsertQuery, buildSoftDeleteQuery, buildUpdateQuery } from '../query/sql-builder'\nimport { serializeOperation, serializeRecord } from '../serialization/serializer'\nimport { allocateNextSequenceInTransaction } from '../store/sequence-allocator'\nimport type { StorageAdapter, Transaction } from '../types'\nimport type { IncomingRelation } from './relation-lookup'\nimport { buildRelationLookup, getIncomingRelations } from './relation-lookup'\n\n/**\n * Error thrown when a delete is refused due to a 'restrict' referential integrity policy.\n * The error includes context about which relation caused the restriction and\n * how many referencing records exist.\n */\nexport class ReferentialIntegrityError extends KoraError {\n\tconstructor(\n\t\tcollection: string,\n\t\trecordId: string,\n\t\treferencingCollection: string,\n\t\trelationName: string,\n\t\treferencingCount: number,\n\t) {\n\t\tsuper(\n\t\t\t`Cannot delete record \"${recordId}\" from \"${collection}\": ${referencingCount} record(s) in \"${referencingCollection}\" reference it via relation \"${relationName}\" with onDelete: 'restrict'. Delete or reassign the referencing records first.`,\n\t\t\t'REFERENTIAL_INTEGRITY',\n\t\t\t{\n\t\t\t\tcollection,\n\t\t\t\trecordId,\n\t\t\t\treferencingCollection,\n\t\t\t\trelationName,\n\t\t\t\treferencingCount,\n\t\t\t},\n\t\t)\n\t\tthis.name = 'ReferentialIntegrityError'\n\t}\n}\n\n/**\n * Configuration for the RelationEnforcer.\n */\nexport interface RelationEnforcerConfig {\n\tschema: SchemaDefinition\n\tadapter: StorageAdapter\n\tclock: HybridLogicalClock\n\tnodeId: string\n}\n\n/**\n * Result of enforcing referential integrity on a delete operation.\n * Contains all additional operations that were created as side effects\n * (cascaded deletes and set-null updates).\n */\nexport interface EnforcementResult {\n\t/** Additional operations created by cascading deletes and set-null updates */\n\toperations: Operation[]\n}\n\n/**\n * Enforces referential integrity constraints during local delete operations.\n *\n * When a record is deleted, this enforcer checks all relations that reference\n * the deleted record's collection and applies the appropriate onDelete policy:\n *\n * - **cascade**: Recursively deletes all referencing records\n * - **set-null**: Sets the foreign key to null on all referencing records\n * - **restrict**: Throws a ReferentialIntegrityError if any references exist\n * - **no-action**: Does nothing (the foreign key is left dangling)\n *\n * The enforcer operates within a provided transaction to ensure atomicity.\n * All generated operations (cascaded deletes, set-null updates) share a\n * causal dependency chain through the original delete operation.\n *\n * @example\n * ```typescript\n * const enforcer = new RelationEnforcer({\n * schema, adapter, clock, nodeId,\n * allocateSequenceNumber: async () => ++seq,\n * })\n * const result = await enforcer.enforceDelete(\n * 'projects', 'proj-1', tx, ['delete-op-id']\n * )\n * // result.operations contains any cascaded delete/update ops\n * ```\n */\nexport class RelationEnforcer {\n\tprivate readonly lookup: Map<string, IncomingRelation[]>\n\tprivate readonly schema: SchemaDefinition\n\tprivate readonly adapter: StorageAdapter\n\tprivate readonly clock: HybridLogicalClock\n\tprivate readonly nodeId: string\n\n\tconstructor(config: RelationEnforcerConfig) {\n\t\tthis.schema = config.schema\n\t\tthis.adapter = config.adapter\n\t\tthis.clock = config.clock\n\t\tthis.nodeId = config.nodeId\n\t\tthis.lookup = buildRelationLookup(config.schema)\n\t}\n\n\t/**\n\t * Enforce referential integrity after deleting a record.\n\t *\n\t * Must be called within a transaction. The transaction handle is used\n\t * for all cascaded writes to ensure atomicity.\n\t *\n\t * @param collection - The collection the deleted record belongs to\n\t * @param recordId - The ID of the deleted record\n\t * @param tx - The active transaction handle\n\t * @param causalDeps - Causal dependencies for generated operations\n\t * @returns All additional operations created as side effects\n\t * @throws {ReferentialIntegrityError} If a 'restrict' policy is violated\n\t */\n\tasync enforceDelete(\n\t\tcollection: string,\n\t\trecordId: string,\n\t\ttx: Transaction,\n\t\tcausalDeps: string[],\n\t): Promise<EnforcementResult> {\n\t\tconst incomingRelations = getIncomingRelations(this.lookup, collection)\n\t\tif (incomingRelations.length === 0) {\n\t\t\treturn { operations: [] }\n\t\t}\n\n\t\tconst allOperations: Operation[] = []\n\n\t\t// Process relations in a deterministic order (sorted by relation name)\n\t\t// to ensure identical results regardless of Map iteration order.\n\t\tconst sortedRelations = [...incomingRelations].sort((a, b) =>\n\t\t\ta.relationName.localeCompare(b.relationName),\n\t\t)\n\n\t\tfor (const incoming of sortedRelations) {\n\t\t\tconst ops = await this.enforceRelation(incoming, recordId, tx, causalDeps)\n\t\t\tallOperations.push(...ops)\n\t\t}\n\n\t\treturn { operations: allOperations }\n\t}\n\n\t/**\n\t * Enforce a single relation's onDelete policy.\n\t */\n\tprivate async enforceRelation(\n\t\tincoming: IncomingRelation,\n\t\tdeletedRecordId: string,\n\t\ttx: Transaction,\n\t\tcausalDeps: string[],\n\t): Promise<Operation[]> {\n\t\tswitch (incoming.onDelete) {\n\t\t\tcase 'cascade':\n\t\t\t\treturn this.enforceCascade(incoming, deletedRecordId, tx, causalDeps)\n\t\t\tcase 'set-null':\n\t\t\t\treturn this.enforceSetNull(incoming, deletedRecordId, tx, causalDeps)\n\t\t\tcase 'restrict':\n\t\t\t\treturn this.enforceRestrict(incoming, deletedRecordId, tx)\n\t\t\tcase 'no-action':\n\t\t\t\treturn []\n\t\t}\n\t}\n\n\t/**\n\t * Cascade: delete all records in the source collection that reference\n\t * the deleted record, then recursively cascade those deletes.\n\t */\n\tprivate async enforceCascade(\n\t\tincoming: IncomingRelation,\n\t\tdeletedRecordId: string,\n\t\ttx: Transaction,\n\t\tcausalDeps: string[],\n\t): Promise<Operation[]> {\n\t\tconst { sourceCollection, foreignKeyField } = incoming\n\n\t\t// Find all non-deleted records that reference the deleted record\n\t\tconst referencingRows = await tx.query<{ id: string }>(\n\t\t\t`SELECT id FROM ${sourceCollection} WHERE ${foreignKeyField} = ? AND _deleted = 0`,\n\t\t\t[deletedRecordId],\n\t\t)\n\n\t\tif (referencingRows.length === 0) {\n\t\t\treturn []\n\t\t}\n\n\t\tconst operations: Operation[] = []\n\n\t\tfor (const row of referencingRows) {\n\t\t\tconst now = Date.now()\n\t\t\tconst sequenceNumber = await allocateNextSequenceInTransaction(tx, this.nodeId)\n\n\t\t\tconst operation = await createOperation(\n\t\t\t\t{\n\t\t\t\t\tnodeId: this.nodeId,\n\t\t\t\t\ttype: 'delete',\n\t\t\t\t\tcollection: sourceCollection,\n\t\t\t\t\trecordId: row.id,\n\t\t\t\t\tdata: null,\n\t\t\t\t\tpreviousData: null,\n\t\t\t\t\tsequenceNumber,\n\t\t\t\t\tcausalDeps: [...causalDeps],\n\t\t\t\t\tschemaVersion: this.schema.version,\n\t\t\t\t},\n\t\t\t\tthis.clock,\n\t\t\t)\n\n\t\t\tconst deleteQuery = buildSoftDeleteQuery(sourceCollection, row.id, now)\n\t\t\tawait tx.execute(deleteQuery.sql, deleteQuery.params)\n\n\t\t\tconst opInsert = buildInsertQuery(\n\t\t\t\t`_kora_ops_${sourceCollection}`,\n\t\t\t\tserializeOperation(operation) as unknown as Record<string, unknown>,\n\t\t\t)\n\t\t\tawait tx.execute(opInsert.sql, opInsert.params)\n\n\t\t\toperations.push(operation)\n\n\t\t\t// Recursively cascade: this deleted record might also be referenced\n\t\t\tconst cascadeResult = await this.enforceDelete(sourceCollection, row.id, tx, [operation.id])\n\t\t\toperations.push(...cascadeResult.operations)\n\t\t}\n\n\t\treturn operations\n\t}\n\n\t/**\n\t * Set-null: update all referencing records to set the foreign key to null.\n\t */\n\tprivate async enforceSetNull(\n\t\tincoming: IncomingRelation,\n\t\tdeletedRecordId: string,\n\t\ttx: Transaction,\n\t\tcausalDeps: string[],\n\t): Promise<Operation[]> {\n\t\tconst { sourceCollection, foreignKeyField } = incoming\n\t\tconst collectionDef = this.schema.collections[sourceCollection]\n\t\tif (!collectionDef) {\n\t\t\treturn []\n\t\t}\n\n\t\t// Find all non-deleted records that reference the deleted record\n\t\tconst referencingRows = await tx.query<{ id: string }>(\n\t\t\t`SELECT id FROM ${sourceCollection} WHERE ${foreignKeyField} = ? AND _deleted = 0`,\n\t\t\t[deletedRecordId],\n\t\t)\n\n\t\tif (referencingRows.length === 0) {\n\t\t\treturn []\n\t\t}\n\n\t\tconst operations: Operation[] = []\n\n\t\tfor (const row of referencingRows) {\n\t\t\tconst now = Date.now()\n\t\t\tconst sequenceNumber = await allocateNextSequenceInTransaction(tx, this.nodeId)\n\n\t\t\tconst updateData: Record<string, unknown> = { [foreignKeyField]: null }\n\t\t\tconst previousData: Record<string, unknown> = { [foreignKeyField]: deletedRecordId }\n\n\t\t\tconst operation = await createOperation(\n\t\t\t\t{\n\t\t\t\t\tnodeId: this.nodeId,\n\t\t\t\t\ttype: 'update',\n\t\t\t\t\tcollection: sourceCollection,\n\t\t\t\t\trecordId: row.id,\n\t\t\t\t\tdata: { ...updateData },\n\t\t\t\t\tpreviousData,\n\t\t\t\t\tsequenceNumber,\n\t\t\t\t\tcausalDeps: [...causalDeps],\n\t\t\t\t\tschemaVersion: this.schema.version,\n\t\t\t\t},\n\t\t\t\tthis.clock,\n\t\t\t)\n\n\t\t\t// Update the record's foreign key to null\n\t\t\tconst serializedChanges = serializeRecord(updateData, collectionDef.fields)\n\t\t\tconst updateQuery = buildUpdateQuery(sourceCollection, row.id, {\n\t\t\t\t...serializedChanges,\n\t\t\t\t_updated_at: now,\n\t\t\t})\n\t\t\tawait tx.execute(updateQuery.sql, updateQuery.params)\n\n\t\t\t// Persist the operation\n\t\t\tconst opRow = serializeOperation(operation)\n\t\t\tconst opInsert = buildInsertQuery(\n\t\t\t\t`_kora_ops_${sourceCollection}`,\n\t\t\t\topRow as unknown as Record<string, unknown>,\n\t\t\t)\n\t\t\tawait tx.execute(opInsert.sql, opInsert.params)\n\n\t\t\toperations.push(operation)\n\t\t}\n\n\t\treturn operations\n\t}\n\n\t/**\n\t * Restrict: refuse the delete if any referencing records exist.\n\t */\n\tprivate async enforceRestrict(\n\t\tincoming: IncomingRelation,\n\t\tdeletedRecordId: string,\n\t\ttx: Transaction,\n\t): Promise<Operation[]> {\n\t\tconst { sourceCollection, foreignKeyField, relationName } = incoming\n\n\t\tconst countRows = await tx.query<{ cnt: number }>(\n\t\t\t`SELECT COUNT(*) as cnt FROM ${sourceCollection} WHERE ${foreignKeyField} = ? AND _deleted = 0`,\n\t\t\t[deletedRecordId],\n\t\t)\n\t\tconst count = countRows[0]?.cnt ?? 0\n\n\t\tif (count > 0) {\n\t\t\t// Determine the target collection from the relation lookup\n\t\t\tconst targetCollection = incoming.relation.to\n\t\t\tthrow new ReferentialIntegrityError(\n\t\t\t\ttargetCollection,\n\t\t\t\tdeletedRecordId,\n\t\t\t\tsourceCollection,\n\t\t\t\trelationName,\n\t\t\t\tcount,\n\t\t\t)\n\t\t}\n\n\t\treturn []\n\t}\n\n\t/**\n\t * Get the relation lookup map for external use (e.g., by the merge engine).\n\t */\n\tgetRelationLookup(): Map<string, IncomingRelation[]> {\n\t\treturn this.lookup\n\t}\n}\n","import type { OnDeleteAction, RelationDefinition, SchemaDefinition } from '@korajs/core'\n\n/**\n * A resolved relation reference: describes a relation that points TO a given collection.\n * When a record in `targetCollection` is deleted, we must handle records in\n * `sourceCollection` that reference it via `foreignKeyField`.\n */\nexport interface IncomingRelation {\n\t/** Name of the relation in the schema */\n\trelationName: string\n\t/** Collection that holds the foreign key (the \"from\" side) */\n\tsourceCollection: string\n\t/** Field in the source collection that references the target */\n\tforeignKeyField: string\n\t/** What to do when the referenced record is deleted */\n\tonDelete: OnDeleteAction\n\t/** The full relation definition */\n\trelation: RelationDefinition\n}\n\n/**\n * Builds an efficient lookup from target collection to all relations that reference it.\n *\n * Given a schema with relations like:\n * ```\n * todoBelongsToProject: { from: 'todos', to: 'projects', field: 'projectId', onDelete: 'cascade' }\n * ```\n *\n * The lookup for 'projects' would return:\n * ```\n * [{ sourceCollection: 'todos', foreignKeyField: 'projectId', onDelete: 'cascade', ... }]\n * ```\n *\n * This enables O(1) lookup when deleting a record to find all dependent relations.\n *\n * @param schema - The full schema definition containing relations\n * @returns A map from target collection name to its incoming relations\n */\nexport function buildRelationLookup(schema: SchemaDefinition): Map<string, IncomingRelation[]> {\n\tconst lookup = new Map<string, IncomingRelation[]>()\n\n\tfor (const [relationName, relation] of Object.entries(schema.relations)) {\n\t\tconst targetCollection = relation.to\n\t\tconst existing = lookup.get(targetCollection) ?? []\n\t\texisting.push({\n\t\t\trelationName,\n\t\t\tsourceCollection: relation.from,\n\t\t\tforeignKeyField: relation.field,\n\t\t\tonDelete: relation.onDelete,\n\t\t\trelation,\n\t\t})\n\t\tlookup.set(targetCollection, existing)\n\t}\n\n\treturn lookup\n}\n\n/**\n * Get all incoming relations for a given collection.\n * Returns an empty array if no relations reference the collection.\n *\n * @param lookup - The pre-built relation lookup map\n * @param collection - The target collection name\n * @returns Array of incoming relations\n */\nexport function getIncomingRelations(\n\tlookup: Map<string, IncomingRelation[]>,\n\tcollection: string,\n): IncomingRelation[] {\n\treturn lookup.get(collection) ?? []\n}\n","import { OperationError } from '@korajs/core'\nimport type { CollectionDefinition, Operation, SchemaDefinition } from '@korajs/core'\nimport { topologicalSort } from '@korajs/core/internal'\nimport type { CollectionRecord } from '../types'\n\n/**\n * In-memory materialized state at a causal cut in the operation log.\n * Read-only — does not mutate the live store.\n */\nexport interface ReplaySnapshot {\n\t/** The operation whose causal past was replayed (inclusive). */\n\ttargetOperation: Operation\n\t/** Operations applied in causal order (ancestors + target). */\n\toperationsApplied: Operation[]\n\t/** Non-deleted records per collection after replay. */\n\tcollections: Record<string, CollectionRecord[]>\n\t/** Look up a single record at the replay cut. Returns null if deleted or missing. */\n\tfindRecord(collection: string, recordId: string): CollectionRecord | null\n}\n\ninterface MutableReplayRecord {\n\tid: string\n\tfields: Record<string, unknown>\n\tdeleted: boolean\n\tcreatedAt: number\n\tupdatedAt: number\n}\n\ntype ReplayMemoryState = Map<string, Map<string, MutableReplayRecord>>\n\n/**\n * Collect the target operation and all causal ancestors present in `allOps`.\n */\nexport function collectCausalClosure(allOps: Operation[], targetOperationId: string): Operation[] {\n\tconst opMap = new Map<string, Operation>()\n\tfor (const op of allOps) {\n\t\topMap.set(op.id, op)\n\t}\n\n\tconst target = opMap.get(targetOperationId)\n\tif (!target) {\n\t\tthrow new OperationError(\n\t\t\t`Operation \"${targetOperationId}\" not found in the local operation log`,\n\t\t\t{\n\t\t\t\toperationId: targetOperationId,\n\t\t\t},\n\t\t)\n\t}\n\n\tconst included = new Set<string>()\n\tconst stack: string[] = [targetOperationId]\n\n\twhile (stack.length > 0) {\n\t\tconst id = stack.pop()\n\t\tif (id === undefined || included.has(id)) {\n\t\t\tcontinue\n\t\t}\n\t\tincluded.add(id)\n\t\tconst op = opMap.get(id)\n\t\tif (!op) {\n\t\t\tcontinue\n\t\t}\n\t\tfor (const depId of op.causalDeps) {\n\t\t\tif (opMap.has(depId)) {\n\t\t\t\tstack.push(depId)\n\t\t\t}\n\t\t}\n\t}\n\n\tconst subset = allOps.filter((op) => included.has(op.id))\n\treturn topologicalSort(subset)\n}\n\n/**\n * Replay a causal subset of operations into an in-memory materialized snapshot.\n * Does not use the merge engine — concurrent ops outside the causal cut are excluded.\n */\nexport function buildReplaySnapshot(\n\tschema: SchemaDefinition,\n\tallOps: Operation[],\n\ttargetOperationId: string,\n): ReplaySnapshot {\n\tconst operationsApplied = collectCausalClosure(allOps, targetOperationId)\n\tconst targetOperation = operationsApplied.find((op) => op.id === targetOperationId)\n\tif (!targetOperation) {\n\t\tthrow new OperationError(`Operation \"${targetOperationId}\" not found after causal sort`, {\n\t\t\toperationId: targetOperationId,\n\t\t})\n\t}\n\n\tconst memory: ReplayMemoryState = new Map()\n\tfor (const op of operationsApplied) {\n\t\tapplyOperationToMemory(memory, op, schema)\n\t}\n\n\tconst collections = materializeCollections(schema, memory)\n\n\treturn {\n\t\ttargetOperation,\n\t\toperationsApplied,\n\t\tcollections,\n\t\tfindRecord(collection: string, recordId: string): CollectionRecord | null {\n\t\t\tconst colMap = memory.get(collection)\n\t\t\tconst record = colMap?.get(recordId)\n\t\t\tif (!record || record.deleted) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst definition = schema.collections[collection]\n\t\t\tif (!definition) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn toCollectionRecord(record, definition)\n\t\t},\n\t}\n}\n\nfunction applyOperationToMemory(\n\tstate: ReplayMemoryState,\n\top: Operation,\n\tschema: SchemaDefinition,\n): void {\n\tconst definition = schema.collections[op.collection]\n\tif (!definition) {\n\t\treturn\n\t}\n\n\tlet colMap = state.get(op.collection)\n\tif (!colMap) {\n\t\tcolMap = new Map()\n\t\tstate.set(op.collection, colMap)\n\t}\n\n\tconst wallTime = op.timestamp.wallTime\n\n\tswitch (op.type) {\n\t\tcase 'insert': {\n\t\t\tif (!op.data) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcolMap.set(op.recordId, {\n\t\t\t\tid: op.recordId,\n\t\t\t\tfields: { ...op.data },\n\t\t\t\tdeleted: false,\n\t\t\t\tcreatedAt: wallTime,\n\t\t\t\tupdatedAt: wallTime,\n\t\t\t})\n\t\t\tbreak\n\t\t}\n\t\tcase 'update': {\n\t\t\tif (!op.data) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst existing = colMap.get(op.recordId)\n\t\t\tif (existing && !existing.deleted) {\n\t\t\t\texisting.fields = { ...existing.fields, ...op.data }\n\t\t\t\texisting.updatedAt = wallTime\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (existing?.deleted) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcolMap.set(op.recordId, {\n\t\t\t\tid: op.recordId,\n\t\t\t\tfields: { ...op.data },\n\t\t\t\tdeleted: false,\n\t\t\t\tcreatedAt: wallTime,\n\t\t\t\tupdatedAt: wallTime,\n\t\t\t})\n\t\t\tbreak\n\t\t}\n\t\tcase 'delete': {\n\t\t\tconst existing = colMap.get(op.recordId)\n\t\t\tif (existing) {\n\t\t\t\texisting.deleted = true\n\t\t\t\texisting.updatedAt = wallTime\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcolMap.set(op.recordId, {\n\t\t\t\tid: op.recordId,\n\t\t\t\tfields: {},\n\t\t\t\tdeleted: true,\n\t\t\t\tcreatedAt: wallTime,\n\t\t\t\tupdatedAt: wallTime,\n\t\t\t})\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunction materializeCollections(\n\tschema: SchemaDefinition,\n\tmemory: ReplayMemoryState,\n): Record<string, CollectionRecord[]> {\n\tconst collections: Record<string, CollectionRecord[]> = {}\n\n\tfor (const [collectionName, definition] of Object.entries(schema.collections)) {\n\t\tconst colMap = memory.get(collectionName)\n\t\tconst records: CollectionRecord[] = []\n\t\tif (colMap) {\n\t\t\tfor (const record of colMap.values()) {\n\t\t\t\tif (!record.deleted) {\n\t\t\t\t\trecords.push(toCollectionRecord(record, definition))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcollections[collectionName] = records\n\t}\n\n\treturn collections\n}\n\nfunction toCollectionRecord(\n\trecord: MutableReplayRecord,\n\tdefinition: CollectionDefinition,\n): CollectionRecord {\n\tconst result: CollectionRecord = {\n\t\tid: record.id,\n\t\tcreatedAt: record.createdAt,\n\t\tupdatedAt: record.updatedAt,\n\t}\n\tfor (const [fieldName] of Object.entries(definition.fields)) {\n\t\tif (fieldName in record.fields) {\n\t\t\tresult[fieldName] = record.fields[fieldName]\n\t\t}\n\t}\n\treturn result\n}\n","import type { SequenceConfig } from '@korajs/core'\nimport { defaultSequenceFormat, formatSequenceValue } from '@korajs/core'\nimport type { StorageAdapter } from '../types'\n\ninterface SequenceRow {\n\tcounter: number\n}\n\n/**\n * Manages offline-safe sequences backed by a `_kora_sequences` table.\n *\n * Each sequence counter is scoped by (name, scope, nodeId), ensuring\n * that different devices never collide. The counter is atomically\n * incremented within a database transaction.\n *\n * @example\n * ```typescript\n * const mgr = new SequenceManager(adapter, 'node-abc')\n *\n * const receipt = await mgr.next('receipt', {\n * scope: 'store-1',\n * format: 'S-{date}-{node4}-{seq}',\n * })\n * // → \"S-20260508-node-0001\"\n * ```\n */\nexport class SequenceManager {\n\tprivate readonly adapter: StorageAdapter\n\tprivate readonly nodeId: string\n\n\tconstructor(adapter: StorageAdapter, nodeId: string) {\n\t\tthis.adapter = adapter\n\t\tthis.nodeId = nodeId\n\t}\n\n\t/**\n\t * Get the next value in a sequence, atomically incrementing the counter.\n\t *\n\t * @param name - The sequence name (e.g., 'receipt', 'invoice')\n\t * @param config - Optional configuration for scope, format, and starting value\n\t * @returns The formatted sequence value\n\t */\n\tasync next(name: string, config?: SequenceConfig): Promise<string> {\n\t\tconst scope = config?.scope ?? ''\n\t\tconst startAt = config?.startAt ?? 1\n\t\tconst format = config?.format ?? defaultSequenceFormat(name)\n\n\t\tlet counter = 0\n\n\t\tawait this.adapter.transaction(async (tx) => {\n\t\t\t// Try to read the current counter\n\t\t\tconst rows = await tx.query<SequenceRow>(\n\t\t\t\t'SELECT counter FROM _kora_sequences WHERE name = ? AND scope = ? AND node_id = ?',\n\t\t\t\t[name, scope, this.nodeId],\n\t\t\t)\n\n\t\t\tif (rows.length > 0) {\n\t\t\t\tconst row = rows[0] as SequenceRow\n\t\t\t\tcounter = row.counter + 1\n\t\t\t\tawait tx.execute(\n\t\t\t\t\t'UPDATE _kora_sequences SET counter = ? WHERE name = ? AND scope = ? AND node_id = ?',\n\t\t\t\t\t[counter, name, scope, this.nodeId],\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\t// First use — initialize with startAt\n\t\t\t\tcounter = startAt\n\t\t\t\tawait tx.execute(\n\t\t\t\t\t'INSERT INTO _kora_sequences (name, scope, node_id, counter) VALUES (?, ?, ?, ?)',\n\t\t\t\t\t[name, scope, this.nodeId, counter],\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\n\t\treturn formatSequenceValue(format, counter, this.nodeId)\n\t}\n\n\t/**\n\t * Get the current counter value without incrementing.\n\t *\n\t * @param name - The sequence name\n\t * @param config - Optional scope\n\t * @returns The current counter value, or 0 if the sequence has never been used\n\t */\n\tasync current(name: string, config?: { scope?: string }): Promise<number> {\n\t\tconst scope = config?.scope ?? ''\n\n\t\tconst rows = await this.adapter.query<SequenceRow>(\n\t\t\t'SELECT counter FROM _kora_sequences WHERE name = ? AND scope = ? AND node_id = ?',\n\t\t\t[name, scope, this.nodeId],\n\t\t)\n\n\t\tif (rows.length > 0) {\n\t\t\treturn (rows[0] as SequenceRow).counter\n\t\t}\n\t\treturn 0\n\t}\n\n\t/**\n\t * Reset a sequence counter.\n\t *\n\t * @param name - The sequence name\n\t * @param config - Optional scope and target value\n\t */\n\tasync reset(name: string, config?: { scope?: string; to?: number }): Promise<void> {\n\t\tconst scope = config?.scope ?? ''\n\t\tconst to = config?.to ?? 0\n\n\t\tawait this.adapter.execute(\n\t\t\t'DELETE FROM _kora_sequences WHERE name = ? AND scope = ? AND node_id = ?',\n\t\t\t[name, scope, this.nodeId],\n\t\t)\n\n\t\tif (to > 0) {\n\t\t\tawait this.adapter.execute(\n\t\t\t\t'INSERT INTO _kora_sequences (name, scope, node_id, counter) VALUES (?, ?, ?, ?)',\n\t\t\t\t[name, scope, this.nodeId, to],\n\t\t\t)\n\t\t}\n\t}\n}\n","/**\n * Bloom filter for fast subscription dependency pre-checking.\n *\n * When the SubscriptionManager has many active subscriptions, checking whether a\n * mutation might affect any subscription requires scanning all subscriptions.\n * This bloom filter provides a fast O(k) pre-check: if the filter says \"definitely\n * not present\", we can skip the subscription entirely. If it says \"maybe present\",\n * we fall through to the precise collection/field matching.\n *\n * Uses FNV-1a for hashing and Kirsch-Mitzenmacker double hashing to derive k\n * hash functions from two base hashes.\n */\n\n// FNV-1a constants for 32-bit hashes\nconst FNV_OFFSET_BASIS = 0x811c9dc5\nconst FNV_PRIME = 0x01000193\n\n/**\n * Compute FNV-1a 32-bit hash of a string.\n *\n * FNV-1a is a non-cryptographic hash function optimized for speed and distribution.\n * It processes one byte at a time: XOR then multiply, which gives better avalanche\n * behavior than the original FNV-1 (multiply then XOR).\n *\n * @param input - The string to hash\n * @returns A 32-bit unsigned integer hash\n */\nexport function fnv1a32(input: string): number {\n\tlet hash = FNV_OFFSET_BASIS\n\tfor (let i = 0; i < input.length; i++) {\n\t\thash ^= input.charCodeAt(i)\n\t\t// Math.imul gives true 32-bit integer multiplication without overflow issues\n\t\thash = Math.imul(hash, FNV_PRIME)\n\t}\n\t// Ensure unsigned 32-bit result\n\treturn hash >>> 0\n}\n\n/**\n * Calculate the optimal number of bits for a bloom filter.\n *\n * Formula: m = -(n * ln(p)) / (ln(2)^2)\n * Rounded up to the nearest multiple of 32 for Uint32Array alignment.\n *\n * @param expectedItems - Expected number of items to insert\n * @param falsePositiveRate - Desired false positive rate (0-1)\n * @returns Number of bits, rounded to nearest 32-bit multiple (minimum 32)\n */\nexport function optimalBitCount(expectedItems: number, falsePositiveRate: number): number {\n\tif (expectedItems <= 0) return 32\n\tif (falsePositiveRate <= 0 || falsePositiveRate >= 1) return 32\n\n\tconst ln2Squared = Math.LN2 * Math.LN2\n\tconst rawBits = -(expectedItems * Math.log(falsePositiveRate)) / ln2Squared\n\n\t// Round up to nearest 32-bit multiple for Uint32Array alignment\n\tconst aligned = Math.ceil(rawBits / 32) * 32\n\treturn Math.max(32, aligned)\n}\n\n/**\n * Calculate the optimal number of hash functions for a bloom filter.\n *\n * Formula: k = (m/n) * ln(2)\n * Clamped to [1, 30] to avoid degenerate cases.\n *\n * @param bitCount - Total number of bits in the filter\n * @param expectedItems - Expected number of items to insert\n * @returns Number of hash functions, clamped to [1, 30]\n */\nexport function optimalHashCount(bitCount: number, expectedItems: number): number {\n\tif (expectedItems <= 0) return 1\n\tconst raw = (bitCount / expectedItems) * Math.LN2\n\treturn Math.max(1, Math.min(30, Math.round(raw)))\n}\n\n/**\n * Bloom filter for subscription dependency tracking.\n *\n * Each subscription adds its watched collection (and optionally fields) to the\n * filter. When a mutation arrives, we check \"collection\" and \"collection:field\"\n * keys against the filter. A negative result means no subscription cares about\n * this mutation, so we can skip the expensive per-subscription scan.\n *\n * @example\n * ```typescript\n * const filter = new SubscriptionBloomFilter(100, 0.01)\n * filter.add('todos')\n * filter.add('todos', 'completed')\n *\n * filter.mightContain('todos') // true (definitely added)\n * filter.mightContain('projects') // false (definitely not added)\n * filter.mightContain('todos', 'completed') // true (definitely added)\n * ```\n */\nexport class SubscriptionBloomFilter {\n\tprivate bits: Uint32Array\n\tprivate readonly bitCount: number\n\tprivate readonly hashCount: number\n\tprivate itemCount = 0\n\n\tconstructor(expectedItems: number, falsePositiveRate = 0.01) {\n\t\tthis.bitCount = optimalBitCount(expectedItems, falsePositiveRate)\n\t\tthis.hashCount = optimalHashCount(this.bitCount, expectedItems)\n\t\tthis.bits = new Uint32Array(this.bitCount / 32)\n\t}\n\n\t/**\n\t * Add a collection (and optional field) to the bloom filter.\n\t *\n\t * @param collection - Collection name (e.g., \"todos\")\n\t * @param field - Optional field name (e.g., \"completed\")\n\t */\n\tadd(collection: string, field?: string): void {\n\t\tconst key = field !== undefined ? `${collection}:${field}` : collection\n\t\tconst positions = this.getPositions(key)\n\t\tfor (const pos of positions) {\n\t\t\tconst wordIndex = pos >>> 5 // equivalent to Math.floor(pos / 32)\n\t\t\tconst bitIndex = pos & 31 // equivalent to pos % 32\n\t\t\tconst current = this.bits[wordIndex] ?? 0\n\t\t\tthis.bits[wordIndex] = current | (1 << bitIndex)\n\t\t}\n\t\tthis.itemCount++\n\t}\n\n\t/**\n\t * Check if a collection (and optional field) might be in the filter.\n\t *\n\t * A return value of `false` means the item is DEFINITELY NOT in the filter.\n\t * A return value of `true` means the item MIGHT be in the filter (possible false positive).\n\t *\n\t * @param collection - Collection name to check\n\t * @param field - Optional field name to check\n\t * @returns false = definitely absent, true = possibly present\n\t */\n\tmightContain(collection: string, field?: string): boolean {\n\t\tconst key = field !== undefined ? `${collection}:${field}` : collection\n\t\tconst positions = this.getPositions(key)\n\t\tfor (const pos of positions) {\n\t\t\tconst wordIndex = pos >>> 5\n\t\t\tconst bitIndex = pos & 31\n\t\t\tif (((this.bits[wordIndex] ?? 0) & (1 << bitIndex)) === 0) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\n\t/**\n\t * Reset the bloom filter, clearing all bits and the item count.\n\t */\n\tclear(): void {\n\t\tthis.bits.fill(0)\n\t\tthis.itemCount = 0\n\t}\n\n\t/**\n\t * Estimate the current false positive rate based on the number of items inserted.\n\t *\n\t * Formula: (1 - e^(-kn/m))^k\n\t * where k = hash count, n = item count, m = bit count.\n\t *\n\t * @returns Estimated false positive rate as a number between 0 and 1\n\t */\n\testimatedFalsePositiveRate(): number {\n\t\tif (this.itemCount === 0) return 0\n\t\tconst exponent = -(this.hashCount * this.itemCount) / this.bitCount\n\t\treturn (1 - Math.exp(exponent)) ** this.hashCount\n\t}\n\n\t/**\n\t * @returns The number of items that have been added to the filter\n\t */\n\tgetItemCount(): number {\n\t\treturn this.itemCount\n\t}\n\n\t/**\n\t * @returns The total number of bits in the filter\n\t */\n\tgetBitCount(): number {\n\t\treturn this.bitCount\n\t}\n\n\t/**\n\t * @returns The number of hash functions used\n\t */\n\tgetHashCount(): number {\n\t\treturn this.hashCount\n\t}\n\n\t/**\n\t * Count the number of bits currently set to 1.\n\t * Uses Brian Kernighan's algorithm: each iteration clears the lowest set bit,\n\t * so the loop runs exactly as many times as there are set bits.\n\t *\n\t * @returns Number of bits set to 1\n\t */\n\tgetSetBitCount(): number {\n\t\tlet count = 0\n\t\tfor (let i = 0; i < this.bits.length; i++) {\n\t\t\tlet word = this.bits[i] ?? 0\n\t\t\twhile (word !== 0) {\n\t\t\t\t// Clear the lowest set bit: n & (n - 1) removes the rightmost 1-bit\n\t\t\t\tword &= word - 1\n\t\t\t\tcount++\n\t\t\t}\n\t\t}\n\t\treturn count\n\t}\n\n\t/**\n\t * Compute k bit positions for a given key using Kirsch-Mitzenmacker double hashing.\n\t *\n\t * Instead of computing k independent hash functions, we compute two base hashes\n\t * (h1 and h2) and derive the rest as: h_i = (h1 + i * h2) mod m.\n\t * This technique is proven to have the same asymptotic false positive rate as\n\t * k independent hash functions.\n\t *\n\t * We derive h1 and h2 from a single FNV-1a hash by splitting and mixing:\n\t * h1 = fnv1a(key), h2 = fnv1a(key + \"\\0salt\") to ensure independence.\n\t */\n\tprivate getPositions(key: string): number[] {\n\t\tconst h1 = fnv1a32(key)\n\t\t// Use a null-byte separator + salt suffix to derive a second independent hash\n\t\tconst h2 = fnv1a32(`${key}\\0bloom`)\n\n\t\tconst positions = new Array<number>(this.hashCount)\n\t\tfor (let i = 0; i < this.hashCount; i++) {\n\t\t\t// Combine h1 and h2 with Kirsch-Mitzenmacker technique\n\t\t\tpositions[i] = ((h1 + Math.imul(i, h2)) >>> 0) % this.bitCount\n\t\t}\n\t\treturn positions\n\t}\n}\n","import type { Operation } from '@korajs/core'\nimport type {\n\tCollectionRecord,\n\tQueryDescriptor,\n\tSubscription,\n\tSubscriptionCallback,\n} from '../types'\nimport { SubscriptionBloomFilter } from './bloom-filter'\n\nlet nextSubId = 0\n\n/**\n * Default threshold for activating bloom filter-based dependency tracking.\n * Below this count, linear scanning is faster due to bloom filter rebuild overhead.\n */\nconst DEFAULT_BLOOM_THRESHOLD = 100\n\n/**\n * Default expected items for bloom filter sizing.\n * Sized to handle typical subscription dependency counts with headroom.\n */\nconst DEFAULT_BLOOM_EXPECTED_ITEMS = 500\n\n/**\n * Default false positive rate for bloom filter.\n * 1% provides a good balance between filter size and accuracy.\n */\nconst DEFAULT_BLOOM_FALSE_POSITIVE_RATE = 0.01\n\n/**\n * Configuration options for the SubscriptionManager.\n */\nexport interface SubscriptionManagerOptions {\n\t/**\n\t * Minimum number of subscriptions before activating bloom filter.\n\t * Below this threshold, linear scanning is used (bloom filter overhead not worth it).\n\t * @default 100\n\t */\n\tbloomThreshold?: number\n\n\t/**\n\t * Expected number of unique collection+field dependencies for bloom filter sizing.\n\t * @default 500\n\t */\n\tbloomExpectedItems?: number\n\n\t/**\n\t * Target false positive rate for the bloom filter.\n\t * Lower values require more memory but reduce unnecessary precise checks.\n\t * @default 0.01\n\t */\n\tbloomFalsePositiveRate?: number\n\n\t/** Called when a query subscription is registered (e.g. to register sync query subsets). */\n\tonQuerySubscribed?: (descriptor: QueryDescriptor) => () => void\n}\n\n/**\n * Performance statistics for monitoring subscription checking efficiency.\n */\nexport interface SubscriptionStats {\n\t/** Total number of mutation notifications processed */\n\ttotalChecks: number\n\t/** Number of times bloom filter said \"maybe\" (proceeded to precise check) */\n\tbloomFilterHits: number\n\t/** Number of times bloom filter said \"definitely not\" (skipped all subscriptions) */\n\tbloomFilterMisses: number\n\t/** Number of times bloom filter said \"maybe\" but precise check found no match */\n\tfalsePositives: number\n\t/** Average time per check in milliseconds */\n\taverageCheckTimeMs: number\n\t/** Whether bloom filter is currently active */\n\tbloomFilterActive: boolean\n\t/** Current subscription count */\n\tsubscriptionCount: number\n}\n\n/**\n * Manages reactive subscriptions with two-level dependency checking.\n *\n * When a mutation occurs on a collection, affected subscriptions are re-evaluated\n * in a microtask batch and callbacks are invoked only if results actually changed.\n *\n * For large subscription counts (>= bloomThreshold), a bloom filter provides O(k)\n * pre-filtering to avoid scanning all subscriptions on every mutation:\n *\n * Level 1 (Bloom filter): Fast O(k) check -- does this mutation potentially affect\n * any subscription? If NO: skip all subscriptions (guaranteed correct).\n * If MAYBE: proceed to Level 2.\n *\n * Level 2 (Precise check): Only evaluate subscriptions that match the mutated\n * collection, including included (related) collection tracking.\n */\nexport class SubscriptionManager {\n\tprivate subscriptions = new Map<string, Subscription>()\n\tprivate pendingCollections = new Set<string>()\n\tprivate flushScheduled = false\n\tprivate readonly onQuerySubscribed?: (descriptor: QueryDescriptor) => () => void\n\n\t// Bloom filter state\n\tprivate bloomFilter: SubscriptionBloomFilter | null = null\n\tprivate bloomDirty = false\n\tprivate readonly bloomThreshold: number\n\tprivate readonly bloomExpectedItems: number\n\tprivate readonly bloomFalsePositiveRate: number\n\n\t// Performance stats\n\tprivate totalChecks = 0\n\tprivate bloomFilterHits = 0\n\tprivate bloomFilterMisses = 0\n\tprivate falsePositives = 0\n\tprivate totalCheckTimeMs = 0\n\n\tconstructor(options?: SubscriptionManagerOptions) {\n\t\tthis.bloomThreshold = options?.bloomThreshold ?? DEFAULT_BLOOM_THRESHOLD\n\t\tthis.bloomExpectedItems = options?.bloomExpectedItems ?? DEFAULT_BLOOM_EXPECTED_ITEMS\n\t\tthis.bloomFalsePositiveRate =\n\t\t\toptions?.bloomFalsePositiveRate ?? DEFAULT_BLOOM_FALSE_POSITIVE_RATE\n\t\tthis.onQuerySubscribed = options?.onQuerySubscribed\n\t}\n\n\t/**\n\t * Register a new subscription.\n\t *\n\t * @param descriptor - The query descriptor defining what this subscription watches\n\t * @param callback - Called with results whenever they change\n\t * @param executeFn - Function to re-execute the query and get current results\n\t * @returns An unsubscribe function\n\t */\n\tregister(\n\t\tdescriptor: QueryDescriptor,\n\t\tcallback: SubscriptionCallback<CollectionRecord>,\n\t\texecuteFn: () => Promise<CollectionRecord[]>,\n\t): () => void {\n\t\tconst id = `sub_${++nextSubId}`\n\t\tconst subscription: Subscription = {\n\t\t\tid,\n\t\t\tdescriptor,\n\t\t\tcallback,\n\t\t\texecuteFn,\n\t\t\tlastResults: [],\n\t\t}\n\t\tthis.subscriptions.set(id, subscription)\n\n\t\t// Mark bloom filter as needing rebuild since dependencies changed\n\t\tthis.bloomDirty = true\n\n\t\tconst externalCleanup = this.onQuerySubscribed?.(descriptor)\n\n\t\treturn () => {\n\t\t\tthis.subscriptions.delete(id)\n\t\t\tthis.bloomDirty = true\n\t\t\texternalCleanup?.()\n\t\t}\n\t}\n\n\t/**\n\t * Register a subscription and immediately execute the query.\n\t * The initial results are stored as lastResults so subsequent flushes\n\t * correctly diff against the initial state.\n\t *\n\t * @returns An unsubscribe function\n\t */\n\tregisterAndFetch(\n\t\tdescriptor: QueryDescriptor,\n\t\tcallback: SubscriptionCallback<CollectionRecord>,\n\t\texecuteFn: () => Promise<CollectionRecord[]>,\n\t): () => void {\n\t\tconst id = `sub_${++nextSubId}`\n\t\tconst subscription: Subscription = {\n\t\t\tid,\n\t\t\tdescriptor,\n\t\t\tcallback,\n\t\t\texecuteFn,\n\t\t\tlastResults: [],\n\t\t}\n\t\tthis.subscriptions.set(id, subscription)\n\n\t\t// Mark bloom filter as needing rebuild since dependencies changed\n\t\tthis.bloomDirty = true\n\n\t\tconst externalCleanup = this.onQuerySubscribed?.(descriptor)\n\n\t\t// Execute immediately, set lastResults, and call callback\n\t\texecuteFn().then((results) => {\n\t\t\t// Guard: subscription may have been removed before the async fetch completes\n\t\t\tif (this.subscriptions.has(id)) {\n\t\t\t\tsubscription.lastResults = results\n\t\t\t\tcallback(results)\n\t\t\t}\n\t\t})\n\n\t\treturn () => {\n\t\t\tthis.subscriptions.delete(id)\n\t\t\tthis.bloomDirty = true\n\t\t\texternalCleanup?.()\n\t\t}\n\t}\n\n\t/**\n\t * Notify the manager that a mutation occurred on a collection.\n\t * Schedules a microtask flush to batch multiple mutations in the same tick.\n\t */\n\tnotify(collection: string, _operation: Operation): void {\n\t\tthis.pendingCollections.add(collection)\n\t\tthis.scheduleFlush()\n\t}\n\n\t/**\n\t * Immediately flush all pending notifications.\n\t * Useful for testing. In production, flushing happens via microtask.\n\t */\n\tasync flush(): Promise<void> {\n\t\tif (this.pendingCollections.size === 0) return\n\n\t\tconst collections = new Set(this.pendingCollections)\n\t\tthis.pendingCollections.clear()\n\t\tthis.flushScheduled = false\n\n\t\tconst affected = this.findAffectedSubscriptions(collections)\n\n\t\t// Re-execute and diff\n\t\tfor (const sub of affected) {\n\t\t\ttry {\n\t\t\t\tconst newResults = await sub.executeFn()\n\t\t\t\tif (!this.resultsEqual(sub.lastResults, newResults)) {\n\t\t\t\t\tsub.lastResults = newResults\n\t\t\t\t\tsub.callback(newResults)\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Subscription re-execution failed -- skip silently for now.\n\t\t\t\t// In future, we could emit an error event for DevTools.\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Remove all subscriptions. Called on store close.\n\t */\n\tclear(): void {\n\t\tthis.subscriptions.clear()\n\t\tthis.pendingCollections.clear()\n\t\tthis.flushScheduled = false\n\t\tthis.bloomFilter = null\n\t\tthis.bloomDirty = false\n\t\tthis.totalChecks = 0\n\t\tthis.bloomFilterHits = 0\n\t\tthis.bloomFilterMisses = 0\n\t\tthis.falsePositives = 0\n\t\tthis.totalCheckTimeMs = 0\n\t}\n\n\t/** Number of active subscriptions (for testing/debugging) */\n\tget size(): number {\n\t\treturn this.subscriptions.size\n\t}\n\n\t/**\n\t * Get performance statistics for monitoring subscription checking efficiency.\n\t * Useful for DevTools integration and performance tuning.\n\t */\n\tgetStats(): SubscriptionStats {\n\t\treturn {\n\t\t\ttotalChecks: this.totalChecks,\n\t\t\tbloomFilterHits: this.bloomFilterHits,\n\t\t\tbloomFilterMisses: this.bloomFilterMisses,\n\t\t\tfalsePositives: this.falsePositives,\n\t\t\taverageCheckTimeMs: this.totalChecks > 0 ? this.totalCheckTimeMs / this.totalChecks : 0,\n\t\t\tbloomFilterActive: this.isBloomActive(),\n\t\t\tsubscriptionCount: this.subscriptions.size,\n\t\t}\n\t}\n\n\t/**\n\t * Check if bloom filter is currently active.\n\t * Active when subscription count meets or exceeds the threshold.\n\t */\n\tisBloomActive(): boolean {\n\t\treturn this.subscriptions.size >= this.bloomThreshold\n\t}\n\n\t/**\n\t * Find subscriptions affected by mutations to the given collections.\n\t * Uses two-level checking when bloom filter is active:\n\t *\n\t * Level 1: Bloom filter pre-check -- if no subscription depends on any\n\t * of the mutated collections, skip everything (O(k) per collection).\n\t *\n\t * Level 2: Precise check -- linear scan of subscriptions, matching\n\t * against the mutated collections.\n\t */\n\tprivate findAffectedSubscriptions(collections: Set<string>): Subscription[] {\n\t\tconst startTime = performance.now()\n\t\tthis.totalChecks++\n\n\t\tconst useBloom = this.isBloomActive()\n\n\t\tif (useBloom) {\n\t\t\t// Rebuild bloom filter if dependencies have changed\n\t\t\tif (this.bloomDirty || this.bloomFilter === null) {\n\t\t\t\tthis.rebuildBloomFilter()\n\t\t\t}\n\n\t\t\tconst filter = this.bloomFilter\n\t\t\tif (filter !== null) {\n\t\t\t\t// Level 1: Bloom filter pre-check\n\t\t\t\tlet anyPossibleMatch = false\n\t\t\t\tfor (const col of collections) {\n\t\t\t\t\tif (filter.mightContain(col)) {\n\t\t\t\t\t\tanyPossibleMatch = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!anyPossibleMatch) {\n\t\t\t\t\t// Bloom filter guarantees no subscription depends on these collections\n\t\t\t\t\tthis.bloomFilterMisses++\n\t\t\t\t\tthis.totalCheckTimeMs += performance.now() - startTime\n\t\t\t\t\treturn []\n\t\t\t\t}\n\n\t\t\t\tthis.bloomFilterHits++\n\t\t\t}\n\t\t}\n\n\t\t// Level 2: Precise check (or only check when bloom is not active)\n\t\tconst affected: Subscription[] = []\n\t\tlet anyPreciseMatch = false\n\n\t\tfor (const sub of this.subscriptions.values()) {\n\t\t\tif (collections.has(sub.descriptor.collection)) {\n\t\t\t\taffected.push(sub)\n\t\t\t\tanyPreciseMatch = true\n\t\t\t} else if (sub.descriptor.includeCollections) {\n\t\t\t\t// Re-evaluate if a mutation affects an included (related) collection\n\t\t\t\tfor (const incCol of sub.descriptor.includeCollections) {\n\t\t\t\t\tif (collections.has(incCol)) {\n\t\t\t\t\t\taffected.push(sub)\n\t\t\t\t\t\tanyPreciseMatch = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Track false positives: bloom said \"maybe\" but precise check found nothing\n\t\tif (useBloom && !anyPreciseMatch) {\n\t\t\tthis.falsePositives++\n\t\t}\n\n\t\tthis.totalCheckTimeMs += performance.now() - startTime\n\t\treturn affected\n\t}\n\n\t/**\n\t * Rebuild the bloom filter from all current subscriptions.\n\t * Adds collection-level dependencies for every subscription, plus\n\t * any included collection dependencies.\n\t */\n\tprivate rebuildBloomFilter(): void {\n\t\tconst filter = new SubscriptionBloomFilter(this.bloomExpectedItems, this.bloomFalsePositiveRate)\n\n\t\tfor (const sub of this.subscriptions.values()) {\n\t\t\t// Add the primary collection dependency\n\t\t\tfilter.add(sub.descriptor.collection)\n\n\t\t\t// Add included (related) collection dependencies\n\t\t\tif (sub.descriptor.includeCollections) {\n\t\t\t\tfor (const incCol of sub.descriptor.includeCollections) {\n\t\t\t\t\tfilter.add(incCol)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.bloomFilter = filter\n\t\tthis.bloomDirty = false\n\t}\n\n\tprivate scheduleFlush(): void {\n\t\tif (this.flushScheduled) return\n\t\tthis.flushScheduled = true\n\t\tqueueMicrotask(() => {\n\t\t\tthis.flush()\n\t\t})\n\t}\n\n\t/**\n\t * Compare two result sets. Uses ID-based comparison first (same length, same IDs),\n\t * then deep comparison of remaining fields when IDs match.\n\t * Avoids JSON.stringify which is O(n) and fragile to field ordering differences.\n\t */\n\tprivate resultsEqual(prev: CollectionRecord[], next: CollectionRecord[]): boolean {\n\t\tif (prev.length !== next.length) return false\n\t\tif (prev.length === 0) return true\n\n\t\t// Fast ID-based check: same records in same order means same result set\n\t\tfor (let i = 0; i < prev.length; i++) {\n\t\t\tif (prev[i]?.id !== next[i]?.id) return false\n\t\t}\n\n\t\t// IDs match — do a field-level comparison for safety\n\t\tfor (let i = 0; i < prev.length; i++) {\n\t\t\tconst a = prev[i] as Record<string, unknown>\n\t\t\tconst b = next[i] as Record<string, unknown>\n\t\t\tconst keysA = Object.keys(a)\n\t\t\tconst keysB = Object.keys(b)\n\t\t\tif (keysA.length !== keysB.length) return false\n\t\t\tfor (const key of keysA) {\n\t\t\t\tif (a[key] !== b[key]) return false\n\t\t\t}\n\t\t}\n\n\t\treturn true\n\t}\n}\n","import type {\n\tAtomicOp,\n\tCausalTracker,\n\tCollectionDefinition,\n\tHybridLogicalClock,\n\tOperation,\n\tSchemaDefinition,\n} from '@korajs/core'\nimport {\n\tcreateOperation,\n\tgenerateUUIDv7,\n\tisAtomicOp,\n\tresolveAtomicOp,\n\ttoAtomicOp,\n\tvalidateRecord,\n} from '@korajs/core'\nimport { RecordNotFoundError } from '../errors'\nimport { serializeRowVersion } from '../lww/row-version'\nimport { buildInsertQuery, buildSoftDeleteQuery, buildUpdateQuery } from '../query/sql-builder'\nimport type { RelationEnforcer } from '../relations/relation-enforcer'\nimport { deserializeRecord, serializeOperation, serializeRecord } from '../serialization/serializer'\nimport type {\n\tCollectionRecord,\n\tLocalMutationHandler,\n\tRawCollectionRow,\n\tStorageAdapter,\n\tTransaction,\n} from '../types'\n\n/**\n * A buffered SQL command to be executed during commit.\n */\ninterface BufferedCommand {\n\tsql: string\n\tparams: unknown[]\n}\n\n/**\n * A buffered operation with its associated SQL commands.\n */\ninterface BufferedEntry {\n\toperation: Operation\n\tcommands: BufferedCommand[]\n\tcollection: string\n}\n\n/**\n * Internal configuration for creating a TransactionContext.\n * Passed from Store to avoid exposing Store internals publicly.\n */\nexport interface TransactionContextConfig {\n\tschema: SchemaDefinition\n\tadapter: StorageAdapter\n\tclock: HybridLogicalClock\n\tnodeId: string\n\tsequenceAllocator: import('./transaction-sequence').TransactionSequenceAllocator\n\trelationEnforcer: RelationEnforcer | null\n\tcausalTracker: CausalTracker | null\n\tlocalMutationHandler: LocalMutationHandler | null\n}\n\n/**\n * A collection accessor within a transaction.\n * Operations are buffered and committed atomically when the transaction completes.\n */\nexport interface TransactionCollectionAccessor {\n\tinsert(data: Record<string, unknown>): Promise<CollectionRecord>\n\tupdate(id: string, data: Record<string, unknown>): Promise<CollectionRecord>\n\tdelete(id: string): Promise<void>\n\tfindById(id: string): Promise<CollectionRecord | null>\n}\n\n/**\n * TransactionContext provides atomic multi-collection operations.\n *\n * All mutations are buffered and committed in a single StorageAdapter.transaction()\n * call. All operations share the same transactionId (UUID v7).\n *\n * Subscription notifications are deferred until after commit.\n *\n * @example\n * ```typescript\n * const { operations, affectedCollections } = await txContext.commit()\n * // Notify subscriptions after commit\n * for (const op of operations) {\n * subscriptionManager.notify(op.collection, op)\n * }\n * ```\n */\nexport class TransactionContext {\n\tprivate readonly transactionId: string\n\tprivate mutationName: string | undefined\n\tprivate readonly buffer: BufferedEntry[] = []\n\tprivate committed = false\n\tprivate rolledBack = false\n\tprivate readonly config: TransactionContextConfig\n\n\tconstructor(config: TransactionContextConfig) {\n\t\tthis.config = config\n\t\tthis.transactionId = generateUUIDv7()\n\t}\n\n\t/**\n\t * Set a human-readable mutation name for this transaction.\n\t * Propagated to all operations for DevTools display.\n\t */\n\tsetMutationName(name: string): void {\n\t\tthis.mutationName = name\n\t}\n\n\t/**\n\t * Get the mutation name, if set.\n\t */\n\tgetMutationName(): string | undefined {\n\t\treturn this.mutationName\n\t}\n\n\t/**\n\t * Get a collection accessor for buffered operations within this transaction.\n\t */\n\tcollection(name: string): TransactionCollectionAccessor {\n\t\tconst definition = this.config.schema.collections[name]\n\t\tif (!definition) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${name}\". Available: ${Object.keys(this.config.schema.collections).join(', ')}`,\n\t\t\t)\n\t\t}\n\n\t\treturn {\n\t\t\tinsert: (data: Record<string, unknown>) => this.insert(name, definition, data),\n\t\t\tupdate: (id: string, data: Record<string, unknown>) =>\n\t\t\t\tthis.update(name, definition, id, data),\n\t\t\tdelete: (id: string) => this.deleteRecord(name, definition, id),\n\t\t\tfindById: (id: string) => this.findById(name, definition, id),\n\t\t}\n\t}\n\n\t/**\n\t * Commit all buffered operations atomically.\n\t * Returns the list of operations and affected collections for subscription notification.\n\t */\n\tasync commit(): Promise<{ operations: Operation[]; affectedCollections: Set<string> }> {\n\t\tif (this.committed) {\n\t\t\tthrow new Error('Transaction already committed.')\n\t\t}\n\t\tif (this.rolledBack) {\n\t\t\tthrow new Error('Transaction was rolled back and cannot be committed.')\n\t\t}\n\n\t\tthis.committed = true\n\n\t\tif (this.buffer.length === 0) {\n\t\t\treturn { operations: [], affectedCollections: new Set() }\n\t\t}\n\n\t\tconst handler = this.config.localMutationHandler\n\t\tif (handler?.commitTransaction) {\n\t\t\treturn handler.commitTransaction({\n\t\t\t\tentries: this.buffer.map((entry) => ({\n\t\t\t\t\toperation: entry.operation,\n\t\t\t\t\tcommands: entry.commands,\n\t\t\t\t\tcollection: entry.collection,\n\t\t\t\t})),\n\t\t\t\ttransactionId: this.transactionId,\n\t\t\t\t...(this.mutationName !== undefined ? { mutationName: this.mutationName } : {}),\n\t\t\t})\n\t\t}\n\n\t\tconst operations: Operation[] = []\n\t\tconst affectedCollections = new Set<string>()\n\n\t\t// Execute all buffered commands in a single adapter transaction\n\t\tawait this.config.adapter.transaction(async (tx: Transaction) => {\n\t\t\tfor (const entry of this.buffer) {\n\t\t\t\tif (entry.operation.type === 'delete' && this.config.relationEnforcer) {\n\t\t\t\t\tconst cascadeResult = await this.config.relationEnforcer.enforceDelete(\n\t\t\t\t\t\tentry.collection,\n\t\t\t\t\t\tentry.operation.recordId,\n\t\t\t\t\t\ttx,\n\t\t\t\t\t\t[entry.operation.id],\n\t\t\t\t\t)\n\t\t\t\t\tfor (const cascadedOp of cascadeResult.operations) {\n\t\t\t\t\t\toperations.push(cascadedOp)\n\t\t\t\t\t\taffectedCollections.add(cascadedOp.collection)\n\t\t\t\t\t\tthis.config.causalTracker?.afterOperation(cascadedOp.collection, cascadedOp.id, true)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (const cmd of entry.commands) {\n\t\t\t\t\tawait tx.execute(cmd.sql, cmd.params)\n\t\t\t\t}\n\t\t\t\toperations.push(entry.operation)\n\t\t\t\taffectedCollections.add(entry.collection)\n\t\t\t}\n\n\t\t\tconst finalSeq = this.config.sequenceAllocator.getHighWaterMark()\n\t\t\tif (finalSeq > 0) {\n\t\t\t\tawait tx.execute(\n\t\t\t\t\t'INSERT OR REPLACE INTO _kora_version_vector (node_id, sequence_number) VALUES (?, ?)',\n\t\t\t\t\t[this.config.nodeId, finalSeq],\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\n\t\treturn { operations, affectedCollections }\n\t}\n\n\t/**\n\t * Mark the transaction as rolled back. No operations will be committed.\n\t */\n\trollback(): void {\n\t\tthis.rolledBack = true\n\t\tthis.buffer.length = 0\n\t}\n\n\t/**\n\t * Get the transaction ID shared by all operations in this transaction.\n\t */\n\tgetTransactionId(): string {\n\t\treturn this.transactionId\n\t}\n\n\tprivate ensureActive(): void {\n\t\tif (this.committed) {\n\t\t\tthrow new Error('Cannot perform operations on a committed transaction.')\n\t\t}\n\t\tif (this.rolledBack) {\n\t\t\tthrow new Error('Cannot perform operations on a rolled-back transaction.')\n\t\t}\n\t}\n\n\tprivate async insert(\n\t\tcollectionName: string,\n\t\tdefinition: CollectionDefinition,\n\t\tdata: Record<string, unknown>,\n\t): Promise<CollectionRecord> {\n\t\tthis.ensureActive()\n\n\t\tconst validated = validateRecord(collectionName, definition, data, 'insert')\n\t\tconst recordId = generateUUIDv7()\n\t\tconst now = Date.now()\n\n\t\t// Set auto timestamp fields\n\t\tfor (const [fieldName, descriptor] of Object.entries(definition.fields)) {\n\t\t\tif (descriptor.auto && descriptor.kind === 'timestamp') {\n\t\t\t\tvalidated[fieldName] = now\n\t\t\t}\n\t\t}\n\n\t\tconst sequenceNumber = await this.config.sequenceAllocator.allocate()\n\t\tconst causalDeps = this.config.causalTracker?.nextCausalDeps(collectionName, true) ?? []\n\t\tconst operation = await createOperation(\n\t\t\t{\n\t\t\t\tnodeId: this.config.nodeId,\n\t\t\t\ttype: 'insert',\n\t\t\t\tcollection: collectionName,\n\t\t\t\trecordId,\n\t\t\t\tdata: { ...validated },\n\t\t\t\tpreviousData: null,\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps,\n\t\t\t\tschemaVersion: this.config.schema.version,\n\t\t\t\ttransactionId: this.transactionId,\n\t\t\t\t...(this.mutationName !== undefined ? { mutationName: this.mutationName } : {}),\n\t\t\t},\n\t\t\tthis.config.clock,\n\t\t)\n\t\tthis.config.causalTracker?.afterOperation(collectionName, operation.id, true)\n\n\t\tconst serializedData = serializeRecord(validated, definition.fields)\n\t\tconst version = serializeRowVersion(operation.timestamp)\n\t\tconst record: Record<string, unknown> = {\n\t\t\tid: recordId,\n\t\t\t...serializedData,\n\t\t\t_created_at: operation.timestamp.wallTime,\n\t\t\t_updated_at: operation.timestamp.wallTime,\n\t\t\t_version: version,\n\t\t}\n\n\t\tconst insertQuery = buildInsertQuery(collectionName, record)\n\t\tconst opRow = serializeOperation(operation)\n\t\tconst opInsert = buildInsertQuery(\n\t\t\t`_kora_ops_${collectionName}`,\n\t\t\topRow as unknown as Record<string, unknown>,\n\t\t)\n\n\t\tthis.buffer.push({\n\t\t\toperation,\n\t\t\tcollection: collectionName,\n\t\t\tcommands: [\n\t\t\t\t{ sql: insertQuery.sql, params: insertQuery.params },\n\t\t\t\t{ sql: opInsert.sql, params: opInsert.params },\n\t\t\t],\n\t\t})\n\n\t\treturn {\n\t\t\tid: recordId,\n\t\t\t...validated,\n\t\t\tcreatedAt: now,\n\t\t\tupdatedAt: now,\n\t\t}\n\t}\n\n\tprivate async update(\n\t\tcollectionName: string,\n\t\tdefinition: CollectionDefinition,\n\t\tid: string,\n\t\tdata: Record<string, unknown>,\n\t): Promise<CollectionRecord> {\n\t\tthis.ensureActive()\n\n\t\t// Check for buffered inserts/updates for this record to get current state\n\t\tconst currentRecord = await this.getEffectiveRecord(collectionName, definition, id)\n\t\tif (!currentRecord) {\n\t\t\tthrow new RecordNotFoundError(collectionName, id)\n\t\t}\n\n\t\tconst validated = validateRecord(collectionName, definition, data, 'update')\n\t\tconst now = Date.now()\n\n\t\tconst previousData: Record<string, unknown> = {}\n\t\tconst resolvedData: Record<string, unknown> = {}\n\t\tconst atomicOps: Record<string, AtomicOp> = {}\n\n\t\tfor (const key of Object.keys(validated)) {\n\t\t\tconst value = validated[key]\n\t\t\tpreviousData[key] = currentRecord[key]\n\n\t\t\tif (isAtomicOp(value)) {\n\t\t\t\tresolvedData[key] = resolveAtomicOp(currentRecord[key], value)\n\t\t\t\tatomicOps[key] = toAtomicOp(value)\n\t\t\t} else {\n\t\t\t\tresolvedData[key] = value\n\t\t\t}\n\t\t}\n\n\t\tconst hasAtomicOps = Object.keys(atomicOps).length > 0\n\n\t\tconst sequenceNumber = await this.config.sequenceAllocator.allocate()\n\t\tconst causalDeps = this.config.causalTracker?.nextCausalDeps(collectionName, true) ?? []\n\t\tconst operation = await createOperation(\n\t\t\t{\n\t\t\t\tnodeId: this.config.nodeId,\n\t\t\t\ttype: 'update',\n\t\t\t\tcollection: collectionName,\n\t\t\t\trecordId: id,\n\t\t\t\tdata: { ...resolvedData },\n\t\t\t\tpreviousData,\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps,\n\t\t\t\tschemaVersion: this.config.schema.version,\n\t\t\t\ttransactionId: this.transactionId,\n\t\t\t\t...(this.mutationName !== undefined ? { mutationName: this.mutationName } : {}),\n\t\t\t\t...(hasAtomicOps ? { atomicOps } : {}),\n\t\t\t},\n\t\t\tthis.config.clock,\n\t\t)\n\t\tthis.config.causalTracker?.afterOperation(collectionName, operation.id, true)\n\n\t\tconst serializedChanges = serializeRecord(resolvedData, definition.fields)\n\t\tconst version = serializeRowVersion(operation.timestamp)\n\t\tconst updateQuery = buildUpdateQuery(collectionName, id, {\n\t\t\t...serializedChanges,\n\t\t\t_updated_at: operation.timestamp.wallTime,\n\t\t\t_version: version,\n\t\t})\n\t\tconst opRow = serializeOperation(operation)\n\t\tconst opInsert = buildInsertQuery(\n\t\t\t`_kora_ops_${collectionName}`,\n\t\t\topRow as unknown as Record<string, unknown>,\n\t\t)\n\n\t\tthis.buffer.push({\n\t\t\toperation,\n\t\t\tcollection: collectionName,\n\t\t\tcommands: [\n\t\t\t\t{ sql: updateQuery.sql, params: updateQuery.params },\n\t\t\t\t{ sql: opInsert.sql, params: opInsert.params },\n\t\t\t],\n\t\t})\n\n\t\t// Merge current record with resolved changes for return value\n\t\treturn {\n\t\t\t...currentRecord,\n\t\t\t...resolvedData,\n\t\t\tupdatedAt: now,\n\t\t} as CollectionRecord\n\t}\n\n\tprivate async deleteRecord(\n\t\tcollectionName: string,\n\t\tdefinition: CollectionDefinition,\n\t\tid: string,\n\t): Promise<void> {\n\t\tthis.ensureActive()\n\n\t\tconst currentRecord = await this.getEffectiveRecord(collectionName, definition, id)\n\t\tif (!currentRecord) {\n\t\t\tthrow new RecordNotFoundError(collectionName, id)\n\t\t}\n\n\t\tconst now = Date.now()\n\t\tconst sequenceNumber = await this.config.sequenceAllocator.allocate()\n\t\tconst causalDeps = this.config.causalTracker?.nextCausalDeps(collectionName, true) ?? []\n\t\tconst operation = await createOperation(\n\t\t\t{\n\t\t\t\tnodeId: this.config.nodeId,\n\t\t\t\ttype: 'delete',\n\t\t\t\tcollection: collectionName,\n\t\t\t\trecordId: id,\n\t\t\t\tdata: null,\n\t\t\t\tpreviousData: null,\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps,\n\t\t\t\tschemaVersion: this.config.schema.version,\n\t\t\t\ttransactionId: this.transactionId,\n\t\t\t\t...(this.mutationName !== undefined ? { mutationName: this.mutationName } : {}),\n\t\t\t},\n\t\t\tthis.config.clock,\n\t\t)\n\t\tthis.config.causalTracker?.afterOperation(collectionName, operation.id, true)\n\n\t\tconst deleteQuery = buildSoftDeleteQuery(collectionName, id, now)\n\t\tconst opRow = serializeOperation(operation)\n\t\tconst opInsert = buildInsertQuery(\n\t\t\t`_kora_ops_${collectionName}`,\n\t\t\topRow as unknown as Record<string, unknown>,\n\t\t)\n\n\t\tthis.buffer.push({\n\t\t\toperation,\n\t\t\tcollection: collectionName,\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],\n\t\t})\n\t}\n\n\tprivate async findById(\n\t\tcollectionName: string,\n\t\tdefinition: CollectionDefinition,\n\t\tid: string,\n\t): Promise<CollectionRecord | null> {\n\t\treturn this.getEffectiveRecord(collectionName, definition, id)\n\t}\n\n\t/**\n\t * Get the effective state of a record, considering both the database and buffered operations.\n\t * Buffered inserts/updates take precedence over the database state.\n\t */\n\tprivate async getEffectiveRecord(\n\t\tcollectionName: string,\n\t\tdefinition: CollectionDefinition,\n\t\tid: string,\n\t): Promise<CollectionRecord | null> {\n\t\t// Check if there's a buffered delete for this record (scan from newest to oldest)\n\t\tfor (let i = this.buffer.length - 1; i >= 0; i--) {\n\t\t\tconst entry = this.buffer[i] as BufferedEntry\n\t\t\tif (entry.collection === collectionName && entry.operation.recordId === id) {\n\t\t\t\tif (entry.operation.type === 'delete') {\n\t\t\t\t\treturn null\n\t\t\t\t}\n\t\t\t\t// For buffered inserts/updates, reconstruct the record from the database + buffered changes\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// Read from database first\n\t\tconst rows = await this.config.adapter.query<RawCollectionRow>(\n\t\t\t`SELECT * FROM ${collectionName} WHERE id = ? AND _deleted = 0`,\n\t\t\t[id],\n\t\t)\n\n\t\tlet record: CollectionRecord | null = rows[0]\n\t\t\t? deserializeRecord(rows[0], definition.fields)\n\t\t\t: null\n\n\t\t// Apply buffered operations on top\n\t\tfor (const entry of this.buffer) {\n\t\t\tif (entry.collection !== collectionName || entry.operation.recordId !== id) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (entry.operation.type === 'insert' && entry.operation.data) {\n\t\t\t\trecord = {\n\t\t\t\t\tid,\n\t\t\t\t\t...entry.operation.data,\n\t\t\t\t\tcreatedAt: entry.operation.timestamp.wallTime,\n\t\t\t\t\tupdatedAt: entry.operation.timestamp.wallTime,\n\t\t\t\t}\n\t\t\t} else if (entry.operation.type === 'update' && entry.operation.data && record) {\n\t\t\t\trecord = {\n\t\t\t\t\t...record,\n\t\t\t\t\t...entry.operation.data,\n\t\t\t\t\tupdatedAt: entry.operation.timestamp.wallTime,\n\t\t\t\t}\n\t\t\t} else if (entry.operation.type === 'delete') {\n\t\t\t\trecord = null\n\t\t\t}\n\t\t}\n\n\t\treturn record\n\t}\n}\n","import { readSequenceNumber } from '../store/sequence-allocator'\nimport type { StorageAdapter } from '../types'\n\n/**\n * Allocates monotonic sequence numbers for a single open transaction.\n * Loads the current DB watermark once, then increments in memory until commit.\n */\nexport class TransactionSequenceAllocator {\n\tprivate loaded = false\n\tprivate watermark = 0\n\n\tconstructor(\n\t\tprivate readonly adapter: StorageAdapter,\n\t\tprivate readonly nodeId: string,\n\t) {}\n\n\tasync allocate(): Promise<number> {\n\t\tif (!this.loaded) {\n\t\t\tthis.watermark = await readSequenceNumber(this.adapter, this.nodeId)\n\t\t\tthis.loaded = true\n\t\t}\n\t\tthis.watermark++\n\t\treturn this.watermark\n\t}\n\n\tgetHighWaterMark(): number {\n\t\treturn this.watermark\n\t}\n}\n","import { generateUUIDv7 } from '@korajs/core'\n\nexport type StoreIsolation = 'shared' | 'per-tab'\n\nfunction perTabStorageKey(dbName: string): string {\n\treturn `kora-tab-node-${dbName}`\n}\n\n/**\n * Load a per-tab node id from sessionStorage (browser only).\n */\nexport function loadPerTabNodeId(dbName: string): string | null {\n\tif (typeof sessionStorage === 'undefined') {\n\t\treturn null\n\t}\n\treturn sessionStorage.getItem(perTabStorageKey(dbName))\n}\n\n/**\n * Persist a per-tab node id for this browser tab.\n */\nexport function savePerTabNodeId(dbName: string, nodeId: string): void {\n\tif (typeof sessionStorage === 'undefined') {\n\t\treturn\n\t}\n\tsessionStorage.setItem(perTabStorageKey(dbName), nodeId)\n}\n\n/**\n * Resolve or create a node id for `per-tab` isolation.\n */\nexport function resolvePerTabNodeId(dbName: string): string {\n\tconst existing = loadPerTabNodeId(dbName)\n\tif (existing) {\n\t\treturn existing\n\t}\n\tconst nodeId = generateUUIDv7()\n\tsavePerTabNodeId(dbName, nodeId)\n\treturn nodeId\n}\n","import type { CollectionRecord } from '../types'\nimport type { QueryBuilder } from '../query/query-builder'\n\n/**\n * Frozen empty array returned as the initial snapshot before any data loads.\n * Same reference every time prevents infinite update loops in UI bindings.\n */\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\n/**\n * Bridges the async QueryBuilder.subscribe() API with synchronous snapshot reads\n * required by React useSyncExternalStore, Vue composables, and Svelte stores.\n *\n * Uses lazy subscription: the underlying query subscription starts when the first\n * listener attaches and stops when the last listener detaches.\n */\nexport class QueryStore<T = CollectionRecord> {\n\tprivate snapshot: readonly T[] = EMPTY_ARRAY as readonly T[]\n\tprivate listeners = new Set<() => void>()\n\tprivate unsubscribeQuery: (() => void) | null = null\n\tprivate active = false\n\tprivate readonly queryBuilder: QueryBuilder<T>\n\n\tconstructor(queryBuilder: QueryBuilder<T>) {\n\t\tthis.queryBuilder = queryBuilder\n\t}\n\n\t/**\n\t * Subscribe to snapshot changes.\n\t *\n\t * @returns Unsubscribe function\n\t */\n\tsubscribe = (onStoreChange: () => void): (() => void) => {\n\t\tthis.listeners.add(onStoreChange)\n\n\t\tif (!this.active) {\n\t\t\tthis.startSubscription()\n\t\t}\n\n\t\treturn () => {\n\t\t\tthis.listeners.delete(onStoreChange)\n\t\t\tif (this.listeners.size === 0) {\n\t\t\t\tthis.stopSubscription()\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Synchronous read of the latest query results. */\n\tgetSnapshot = (): readonly T[] => {\n\t\treturn this.snapshot\n\t}\n\n\t/** Tear down listeners and the underlying query subscription. */\n\tdestroy(): void {\n\t\tthis.stopSubscription()\n\t\tthis.listeners.clear()\n\t\tthis.snapshot = EMPTY_ARRAY as readonly T[]\n\t}\n\n\tprivate startSubscription(): void {\n\t\tthis.active = true\n\t\tthis.unsubscribeQuery = this.queryBuilder.subscribe((results: readonly T[]) => {\n\t\t\tif (!this.active) return\n\t\t\tthis.snapshot = Object.freeze([...results])\n\t\t\tthis.notifyListeners()\n\t\t})\n\t}\n\n\tprivate stopSubscription(): void {\n\t\tthis.active = false\n\t\tif (this.unsubscribeQuery) {\n\t\t\tthis.unsubscribeQuery()\n\t\t\tthis.unsubscribeQuery = null\n\t\t}\n\t}\n\n\tprivate notifyListeners(): void {\n\t\tfor (const listener of this.listeners) {\n\t\t\tlistener()\n\t\t}\n\t}\n}\n","import { AppNotReadyError } from '@korajs/core'\nimport type { QueryBuilder } from '../query/query-builder'\n\nconst LEGACY_PENDING_COLLECTION = '__pending__'\n\n/**\n * Ensures a query builder is backed by an open store (not a legacy pending placeholder).\n */\nexport function assertQueryReady(query: QueryBuilder<unknown>): void {\n\tconst descriptor = query.getDescriptor()\n\tif (descriptor.collection === LEGACY_PENDING_COLLECTION) {\n\t\tthrow new AppNotReadyError(\n\t\t\t'Cannot use useQuery() before app.ready. Await app.ready or wrap your UI in <KoraProvider app={app}>.',\n\t\t)\n\t}\n}\n","import type { CollectionRecord } from '../types'\nimport type { QueryBuilder } from '../query/query-builder'\nimport { QueryStore } from './query-store'\n\ninterface CacheEntry {\n\tqueryStore: QueryStore<CollectionRecord>\n\trefCount: number\n}\n\n/**\n * Reference-counted cache of {@link QueryStore} instances keyed by query descriptor.\n * Identical queries from different components share one underlying subscription.\n */\nexport class QueryStoreCache {\n\tprivate entries = new Map<string, CacheEntry>()\n\n\tconstructor(private readonly scopeKey = 'default') {}\n\n\tgetOrCreate<T>(queryBuilder: QueryBuilder<T>): QueryStore<T> {\n\t\tconst key = this.getKey(queryBuilder)\n\t\tconst existing = this.entries.get(key)\n\n\t\tif (existing) {\n\t\t\texisting.refCount++\n\t\t\treturn existing.queryStore as QueryStore<T>\n\t\t}\n\n\t\tconst queryStore = new QueryStore<T>(queryBuilder)\n\t\tthis.entries.set(key, {\n\t\t\tqueryStore: queryStore as QueryStore<CollectionRecord>,\n\t\t\trefCount: 1,\n\t\t})\n\t\treturn queryStore\n\t}\n\n\trelease(queryBuilder: QueryBuilder<unknown>): void {\n\t\tconst key = this.getKey(queryBuilder)\n\t\tconst entry = this.entries.get(key)\n\t\tif (!entry) {\n\t\t\treturn\n\t\t}\n\n\t\tentry.refCount--\n\t\tif (entry.refCount <= 0) {\n\t\t\tentry.queryStore.destroy()\n\t\t\tthis.entries.delete(key)\n\t\t}\n\t}\n\n\tclear(): void {\n\t\tfor (const entry of this.entries.values()) {\n\t\t\tentry.queryStore.destroy()\n\t\t}\n\t\tthis.entries.clear()\n\t}\n\n\tget size(): number {\n\t\treturn this.entries.size\n\t}\n\n\tprivate getKey(queryBuilder: QueryBuilder<unknown>): string {\n\t\treturn `${this.scopeKey}:${JSON.stringify(queryBuilder.getDescriptor())}`\n\t}\n}\n\nlet sharedCache: QueryStoreCache | null = null\n\n/**\n * Process-wide shared query store cache for framework bindings.\n *\n * @deprecated Prefer {@link KoraApp.getQueryStoreCache} via `KoraProvider` context\n * so each app instance owns an isolated cache.\n */\nexport function getSharedQueryStoreCache(): QueryStoreCache {\n\tif (!sharedCache) {\n\t\tsharedCache = new QueryStoreCache()\n\t}\n\treturn sharedCache\n}\n","import * as Y from 'yjs'\nimport { encodeRichtext } from '../serialization/richtext-serializer'\nimport type {\n\tCreateRichTextControllerOptions,\n\tRichTextAwarenessState,\n\tRichTextAwarenessUser,\n\tRichTextController,\n\tRichTextControllerSnapshot,\n\tRichTextCursorInfo,\n} from './types'\n\nconst LOAD_ORIGIN = 'kora-load'\nconst REMOTE_ORIGIN = 'kora-remote'\nconst DOC_CHANNEL_ORIGIN = 'kora-doc-channel'\nconst TEXT_KEY = 'content'\nconst COMPACT_AFTER_DELTAS = 20\nconst PERSIST_DEBOUNCE_MS = 400\n\n/**\n * Framework-agnostic richtext binding: Yjs document lifecycle, persistence,\n * incremental doc channel, and awareness cursors.\n */\nexport function createRichTextController(\n\toptions: CreateRichTextControllerOptions,\n): RichTextController {\n\tconst {\n\t\tcollection,\n\t\tcollectionName,\n\t\trecordId,\n\t\tfieldName,\n\t\tstore,\n\t\tsyncEngine = null,\n\t\tuseDocChannel,\n\t} = options\n\n\tconst doc = new Y.Doc()\n\tconst text = doc.getText(TEXT_KEY)\n\tconst undoManager = new Y.UndoManager(text)\n\n\tlet user = options.user\n\tlet disposed = false\n\tlet ready = false\n\tlet error: Error | null = null\n\tlet canUndo = false\n\tlet canRedo = false\n\tlet cursors: RichTextCursorInfo[] = []\n\n\tconst listeners = new Set<() => void>()\n\tlet snapshot: RichTextControllerSnapshot = {\n\t\tready: false,\n\t\terror: null,\n\t\tcanUndo: false,\n\t\tcanRedo: false,\n\t\tcursors: [],\n\t}\n\tconst baseUpdateRef = { current: null as Uint8Array | null }\n\tconst pendingDeltasRef = { current: [] as Uint8Array[] }\n\tconst docChannelActiveRef = { current: false }\n\tlet persistTimer: ReturnType<typeof setTimeout> | null = null\n\n\tlet recordUnsubscribe: (() => void) | null = null\n\tlet docChannelUnsubscribe: (() => void) | null = null\n\tlet awarenessUnsubscribe: (() => void) | null = null\n\n\tconst refreshSnapshot = (): void => {\n\t\tsnapshot = {\n\t\t\tready,\n\t\t\terror,\n\t\t\tcanUndo,\n\t\t\tcanRedo,\n\t\t\tcursors: [...cursors],\n\t\t}\n\t}\n\n\tconst notify = (): void => {\n\t\trefreshSnapshot()\n\t\tfor (const listener of listeners) {\n\t\t\tlistener()\n\t\t}\n\t}\n\n\tconst syncHistoryState = (): void => {\n\t\tcanUndo = undoManager.undoStack.length > 0\n\t\tcanRedo = undoManager.redoStack.length > 0\n\t\tnotify()\n\t}\n\n\tconst getSnapshot = (): RichTextControllerSnapshot => snapshot\n\n\tconst resolveAwarenessUser = (): RichTextAwarenessUser => {\n\t\tif (user) {\n\t\t\treturn user\n\t\t}\n\t\tif (syncEngine) {\n\t\t\tconst existing = syncEngine.getAwarenessManager().getLocalState()?.user\n\t\t\tif (existing) {\n\t\t\t\treturn existing\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tname: 'Anonymous',\n\t\t\tcolor: '#6366f1',\n\t\t}\n\t}\n\n\tconst setCursor = (anchor: number, head: number): void => {\n\t\tif (!syncEngine) {\n\t\t\treturn\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tconst state: RichTextAwarenessState = {\n\t\t\tuser: resolveAwarenessUser(),\n\t\t\tcursor: {\n\t\t\t\tcollection: collectionName,\n\t\t\t\trecordId,\n\t\t\t\tfield: fieldName,\n\t\t\t\tanchor,\n\t\t\t\thead,\n\t\t\t},\n\t\t}\n\t\tawareness.setLocalState(state)\n\t}\n\n\tconst clearCursor = (): void => {\n\t\tif (!syncEngine) {\n\t\t\treturn\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tconst current = awareness.getLocalState()\n\t\tif (!current?.cursor) {\n\t\t\treturn\n\t\t}\n\t\tif (\n\t\t\tcurrent.cursor.collection !== collectionName ||\n\t\t\tcurrent.cursor.recordId !== recordId ||\n\t\t\tcurrent.cursor.field !== fieldName\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tawareness.setLocalState({ user: current.user })\n\t}\n\n\tconst applyRemoteSnapshot = (value: unknown): void => {\n\t\tconst encoded = encodeRichtextInput(value)\n\t\tif (!encoded) {\n\t\t\treturn\n\t\t}\n\n\t\tconst currentSnapshot = Y.encodeStateAsUpdate(doc)\n\t\tif (updatesEqual(currentSnapshot, encoded)) {\n\t\t\treturn\n\t\t}\n\n\t\tY.applyUpdate(doc, encoded, REMOTE_ORIGIN)\n\t\tbaseUpdateRef.current = encoded\n\t\tpendingDeltasRef.current = []\n\t\tsyncHistoryState()\n\t}\n\n\tconst flushPersist = async (): Promise<void> => {\n\t\tconst snapshot = composeRichtextSnapshot(baseUpdateRef.current, pendingDeltasRef.current)\n\t\tif (pendingDeltasRef.current.length >= COMPACT_AFTER_DELTAS) {\n\t\t\tbaseUpdateRef.current = snapshot\n\t\t\tpendingDeltasRef.current = []\n\t\t}\n\n\t\ttry {\n\t\t\tawait collection.update(recordId, {\n\t\t\t\t[fieldName]: snapshot,\n\t\t\t})\n\t\t} catch (cause) {\n\t\t\tif (!disposed) {\n\t\t\t\terror = cause instanceof Error ? cause : new Error(String(cause))\n\t\t\t\tnotify()\n\t\t\t}\n\t\t}\n\t}\n\n\tconst schedulePersist = (): void => {\n\t\tif (persistTimer) {\n\t\t\tclearTimeout(persistTimer)\n\t\t}\n\t\tpersistTimer = setTimeout(() => {\n\t\t\tpersistTimer = null\n\t\t\tvoid flushPersist()\n\t\t}, PERSIST_DEBOUNCE_MS)\n\t}\n\n\tconst onDocUpdate = (update: Uint8Array, origin: unknown): void => {\n\t\tsyncHistoryState()\n\t\tif (origin === LOAD_ORIGIN || origin === REMOTE_ORIGIN || origin === DOC_CHANNEL_ORIGIN) {\n\t\t\treturn\n\t\t}\n\n\t\tpendingDeltasRef.current.push(update)\n\n\t\tif (docChannelActiveRef.current && syncEngine) {\n\t\t\tsyncEngine.getRichtextDocChannel?.().send(collectionName, recordId, fieldName, update)\n\t\t\tschedulePersist()\n\t\t\treturn\n\t\t}\n\n\t\tvoid flushPersist()\n\t}\n\n\tconst subscribeRecordChanges = (): void => {\n\t\trecordUnsubscribe?.()\n\t\trecordUnsubscribe = store\n\t\t\t.collection(collectionName)\n\t\t\t.where({ id: recordId })\n\t\t\t.subscribe((results) => {\n\t\t\t\tconst record = results[0]\n\t\t\t\tif (!record) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tapplyRemoteSnapshot(record[fieldName])\n\t\t\t})\n\t}\n\n\tconst subscribeDocChannel = (): void => {\n\t\tdocChannelUnsubscribe?.()\n\t\tif (!ready || !syncEngine || !docChannelActiveRef.current) {\n\t\t\treturn\n\t\t}\n\n\t\tconst channel = syncEngine.getRichtextDocChannel?.()\n\t\tif (!channel) {\n\t\t\treturn\n\t\t}\n\n\t\tdocChannelUnsubscribe = channel.subscribe(collectionName, recordId, fieldName, (update) => {\n\t\t\tY.applyUpdate(doc, update, DOC_CHANNEL_ORIGIN)\n\t\t\tsyncHistoryState()\n\t\t})\n\t}\n\n\tconst updateCursors = (): void => {\n\t\tif (!syncEngine) {\n\t\t\tcursors = []\n\t\t\tnotify()\n\t\t\treturn\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tconst localClientId = awareness.clientId\n\t\tconst states = awareness.getStates()\n\t\tconst fieldCursors: RichTextCursorInfo[] = []\n\n\t\tfor (const [clientId, state] of states) {\n\t\t\tif (clientId === localClientId) continue\n\t\t\tif (!state.cursor) continue\n\t\t\tif (\n\t\t\t\tstate.cursor.collection !== collectionName ||\n\t\t\t\tstate.cursor.recordId !== recordId ||\n\t\t\t\tstate.cursor.field !== fieldName\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfieldCursors.push({\n\t\t\t\tclientId,\n\t\t\t\tuserName: state.user.name,\n\t\t\t\tcolor: state.user.color,\n\t\t\t\tanchor: state.cursor.anchor,\n\t\t\t\thead: state.cursor.head,\n\t\t\t})\n\t\t}\n\n\t\tcursors = fieldCursors\n\t\tnotify()\n\t}\n\n\tconst subscribeAwareness = (): void => {\n\t\tawarenessUnsubscribe?.()\n\t\tif (!syncEngine) {\n\t\t\tcursors = []\n\t\t\tnotify()\n\t\t\treturn\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tawarenessUnsubscribe = awareness.on('change', () => {\n\t\t\tupdateCursors()\n\t\t})\n\t\tupdateCursors()\n\t}\n\n\tconst initialize = async (): Promise<void> => {\n\t\tready = false\n\t\terror = null\n\t\tnotify()\n\n\t\ttry {\n\t\t\tconst record = await collection.findById(recordId)\n\t\t\tif (disposed) return\n\n\t\t\tdoc.transact(() => {\n\t\t\t\tconst target = doc.getText(TEXT_KEY)\n\t\t\t\ttarget.delete(0, target.length)\n\t\t\t}, LOAD_ORIGIN)\n\n\t\t\tconst encoded = encodeRichtextInput(record?.[fieldName])\n\t\t\tbaseUpdateRef.current = encoded\n\t\t\tpendingDeltasRef.current = []\n\t\t\tif (encoded) {\n\t\t\t\tY.applyUpdate(doc, encoded, LOAD_ORIGIN)\n\t\t\t}\n\n\t\t\tconst channel = syncEngine?.getRichtextDocChannel?.()\n\t\t\tdocChannelActiveRef.current =\n\t\t\t\tchannel?.shouldUseChannel(encoded?.length ?? 0, useDocChannel) ?? false\n\n\t\t\tready = true\n\t\t\tsyncHistoryState()\n\t\t\tsubscribeRecordChanges()\n\t\t\tsubscribeDocChannel()\n\t\t\tsubscribeAwareness()\n\t\t\tnotify()\n\t\t} catch (cause) {\n\t\t\tif (disposed) return\n\t\t\terror = cause instanceof Error ? cause : new Error(String(cause))\n\t\t\tnotify()\n\t\t}\n\t}\n\n\tdoc.on('update', onDocUpdate)\n\tvoid initialize()\n\n\treturn {\n\t\tdoc,\n\t\ttext,\n\t\tgetSnapshot,\n\t\tsubscribe(listener) {\n\t\t\tlisteners.add(listener)\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener)\n\t\t\t}\n\t\t},\n\t\tundo() {\n\t\t\tundoManager.undo()\n\t\t\tsyncHistoryState()\n\t\t},\n\t\tredo() {\n\t\t\tundoManager.redo()\n\t\t\tsyncHistoryState()\n\t\t},\n\t\tsetCursor,\n\t\tclearCursor,\n\t\tsetUser(nextUser: RichTextAwarenessUser | undefined) {\n\t\t\tuser = nextUser\n\t\t},\n\t\tdestroy() {\n\t\t\tif (disposed) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tdisposed = true\n\t\t\tif (persistTimer) {\n\t\t\t\tclearTimeout(persistTimer)\n\t\t\t\tpersistTimer = null\n\t\t\t}\n\t\t\tdoc.off('update', onDocUpdate)\n\t\t\trecordUnsubscribe?.()\n\t\t\tdocChannelUnsubscribe?.()\n\t\t\tawarenessUnsubscribe?.()\n\t\t\tclearCursor()\n\t\t\tundoManager.destroy()\n\t\t\tbaseUpdateRef.current = null\n\t\t\tpendingDeltasRef.current = []\n\t\t\tdocChannelActiveRef.current = false\n\t\t\tlisteners.clear()\n\t\t},\n\t}\n}\n\nfunction encodeRichtextInput(value: unknown): Uint8Array | null {\n\tif (value === null || value === undefined) {\n\t\treturn null\n\t}\n\n\ttry {\n\t\treturn encodeRichtext(value as Parameters<typeof encodeRichtext>[0])\n\t} catch {\n\t\tif (typeof value === 'string') {\n\t\t\tconst fallbackDoc = new Y.Doc()\n\t\t\tfallbackDoc.getText(TEXT_KEY).insert(0, value)\n\t\t\treturn Y.encodeStateAsUpdate(fallbackDoc)\n\t\t}\n\t\tthrow new Error('Richtext record value must be a string, Uint8Array, ArrayBuffer, or null.')\n\t}\n}\n\nfunction composeRichtextSnapshot(base: Uint8Array | null, deltas: Uint8Array[]): Uint8Array {\n\tconst mergedDoc = new Y.Doc()\n\tif (base) {\n\t\tY.applyUpdate(mergedDoc, base)\n\t}\n\n\tfor (const delta of deltas) {\n\t\tY.applyUpdate(mergedDoc, delta)\n\t}\n\n\treturn Y.encodeStateAsUpdate(mergedDoc)\n}\n\nfunction updatesEqual(left: Uint8Array, right: Uint8Array): boolean {\n\tif (left.length !== right.length) {\n\t\treturn false\n\t}\n\tfor (let index = 0; index < left.length; index++) {\n\t\tif (left[index] !== right[index]) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n","import type { RichTextSyncEngine } from './types'\n\n/**\n * Narrows a sync engine reference to the richtext controller surface.\n * SyncEngine satisfies this interface at runtime; types live in different packages.\n */\nexport function asRichTextSyncEngine(engine: unknown): RichTextSyncEngine | null {\n\tif (engine == null) {\n\t\treturn null\n\t}\n\treturn engine as RichTextSyncEngine\n}\n","export { exportBackup, readBackupManifest, restoreBackup, verifyBackupChecksum } from './backup'\nexport type {\n\tBackupManifest,\n\tBackupOptions,\n\tBackupProgress,\n\tRestoreOptions,\n\tRestoreResult,\n} from './types'\n","export {\n\tappendAuditTrace,\n\tauditTraceIndexFields,\n\tcountAuditTraces,\n\tpersistedAuditTraceFromEvent,\n\treadAuditTraces,\n} from './audit-trace-store'\nexport {\n\tauditJsonReplacer,\n\tauditJsonReviver,\n\tdeserializeAuditJson,\n\tserializeAuditJson,\n} from './audit-json'\nexport {\n\tdecodeAuditExport,\n\texportAudit,\n\treadAuditExportManifest,\n\tverifyAuditExportChecksum,\n} from './export-audit'\nexport type {\n\tAuditExportManifest,\n\tAuditExportOptions,\n\tAuditExportPayload,\n\tAuditExportProgress,\n\tAuditTraceQuery,\n\tPersistedAuditTrace,\n} from './types'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASO,SAAS,eAAe,OAAyC;AACvE,MAAI,UAAU,QAAQ,UAAU,QAAW;AAC1C,WAAO;AAAA,EACR;AAEA,MAAI,OAAO,UAAU,UAAU;AAC9B,UAAM,MAAM,IAAM,MAAI;AACtB,QAAI,QAAQ,QAAQ,EAAE,OAAO,GAAG,KAAK;AACrC,WAAS,sBAAoB,GAAG;AAAA,EACjC;AAEA,MAAI,iBAAiB,YAAY;AAChC,WAAO;AAAA,EACR;AAEA,MAAI,iBAAiB,aAAa;AACjC,WAAO,IAAI,WAAW,KAAK;AAAA,EAC5B;AAEA,QAAM,IAAI,MAAM,+EAA+E;AAChG;AAKO,SAAS,eAAe,OAAmC;AACjE,MAAI,UAAU,QAAQ,UAAU,QAAW;AAC1C,WAAO;AAAA,EACR;AAEA,MAAI,OAAO,WAAW,eAAe,OAAO,SAAS,KAAK,GAAG;AAC5D,WAAO,IAAI,WAAW,KAAK;AAAA,EAC5B;AAEA,MAAI,iBAAiB,YAAY;AAChC,WAAO;AAAA,EACR;AAEA,MAAI,iBAAiB,aAAa;AACjC,WAAO,IAAI,WAAW,KAAK;AAAA,EAC5B;AAEA,QAAM,IAAI;AAAA,IACT;AAAA,EACD;AACD;AAKO,SAAS,oBAAoB,OAA8B;AACjE,QAAM,UAAU,eAAe,KAAK;AACpC,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,MAAM,IAAM,MAAI;AACtB,EAAE,cAAY,KAAK,OAAO;AAC1B,SAAO,IAAI,QAAQ,QAAQ,EAAE,SAAS;AACvC;AAMO,SAAS,oBAAoB,GAAY,GAAqB;AACpE,MAAI;AACH,WAAO,oBAAoB,CAAkB,MAAM,oBAAoB,CAAkB;AAAA,EAC1F,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AA9EA,OAEM;AAFN;AAAA;AAAA;AAAA,QAAmB;AAEnB,IAAM,WAAW;AAAA;AAAA;;;ACWV,SAAS,gBACf,MACA,QAC0B;AAC1B,QAAM,SAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAChD,UAAM,aAAa,OAAO,GAAG;AAC7B,QAAI,CAAC,YAAY;AAChB,aAAO,GAAG,IAAI;AACd;AAAA,IACD;AACA,WAAO,GAAG,IAAI,eAAe,OAAO,UAAU;AAAA,EAC/C;AACA,SAAO;AACR;AAUO,SAAS,kBACf,KACA,QACmB;AACnB,QAAM,SAA2B;AAAA,IAChC,IAAI,IAAI;AAAA,IACR,WAAW,IAAI;AAAA,IACf,WAAW,IAAI;AAAA,EAChB;AAEA,aAAW,CAAC,KAAK,UAAU,KAAK,OAAO,QAAQ,MAAM,GAAG;AACvD,UAAM,WAAW,IAAI,GAAG;AACxB,QAAI,aAAa,UAAa,aAAa,MAAM;AAChD,aAAO,GAAG,IAAI,YAAY;AAC1B;AAAA,IACD;AACA,WAAO,GAAG,IAAI,iBAAiB,UAAU,UAAU;AAAA,EACpD;AAEA,SAAO;AACR;AAwBO,SAAS,mBAAmB,IAA6B;AAC/D,QAAM,cAAc,GAAG,kBAAkB,UAAa,GAAG,iBAAiB;AAC1E,MAAI,cAA8C;AAClD,MAAI,GAAG,MAAM;AAEZ,kBAAc,EAAE,GAAG,GAAG,KAAK;AAC3B,QAAI,GAAG,cAAc,UAAa,OAAO,KAAK,GAAG,SAAS,EAAE,SAAS,GAAG;AACvE,kBAAY,cAAc,IAAI,GAAG;AAAA,IAClC;AACA,QAAI,GAAG,kBAAkB,QAAW;AACnC,kBAAY,SAAS,IAAI,GAAG;AAAA,IAC7B;AACA,QAAI,GAAG,iBAAiB,QAAW;AAClC,kBAAY,iBAAiB,IAAI,GAAG;AAAA,IACrC;AAAA,EACD,WAAW,aAAa;AAEvB,kBAAc,CAAC;AACf,QAAI,GAAG,kBAAkB,QAAW;AACnC,kBAAY,SAAS,IAAI,GAAG;AAAA,IAC7B;AACA,QAAI,GAAG,iBAAiB,QAAW;AAClC,kBAAY,iBAAiB,IAAI,GAAG;AAAA,IACrC;AAAA,EACD;AAEA,SAAO;AAAA,IACN,IAAI,GAAG;AAAA,IACP,SAAS,GAAG;AAAA,IACZ,MAAM,GAAG;AAAA,IACT,WAAW,GAAG;AAAA,IACd,MAAM,cAAc,KAAK,UAAU,WAAW,IAAI;AAAA,IAClD,eAAe,GAAG,eAAe,KAAK,UAAU,GAAG,YAAY,IAAI;AAAA,IACnE,WAAW,gCAAmB,UAAU,GAAG,SAAS;AAAA,IACpD,iBAAiB,GAAG;AAAA,IACpB,aAAa,KAAK,UAAU,GAAG,UAAU;AAAA,IACzC,gBAAgB,GAAG;AAAA,EACpB;AACD;AAQO,SAAS,qBAAqB,KAA8B;AAClE,MAAI,OAAuC;AAC3C,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI,IAAI,MAAM;AACb,UAAM,SAAS,KAAK,MAAM,IAAI,IAAI;AAElC,QAAI,kBAAkB,QAAQ;AAC7B,kBAAY,OAAO,cAAc;AAAA,IAClC;AACA,QAAI,aAAa,QAAQ;AACxB,sBAAgB,OAAO,SAAS;AAAA,IACjC;AACA,QAAI,qBAAqB,QAAQ;AAChC,qBAAe,OAAO,iBAAiB;AAAA,IACxC;AAEA,UAAM,EAAE,CAAC,cAAc,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,iBAAiB,GAAG,IAAI,GAAG,KAAK,IAAI;AACpF,WAAO,OAAO,KAAK,IAAI,EAAE,SAAS,IAAI,OAAO;AAAA,EAC9C;AAEA,SAAO;AAAA,IACN,IAAI,IAAI;AAAA,IACR,QAAQ,IAAI;AAAA,IACZ,MAAM,IAAI;AAAA,IACV,YAAY;AAAA;AAAA,IACZ,UAAU,IAAI;AAAA,IACd;AAAA,IACA,cAAc,IAAI,gBACd,KAAK,MAAM,IAAI,aAAa,IAC7B;AAAA,IACH,WAAW,gCAAmB,YAAY,IAAI,SAAS;AAAA,IACvD,gBAAgB,IAAI;AAAA,IACpB,YAAY,KAAK,MAAM,IAAI,WAAW;AAAA,IACtC,eAAe,IAAI;AAAA,IACnB,GAAI,cAAc,SAAY,EAAE,UAA+C,IAAI,CAAC;AAAA,IACpF,GAAI,kBAAkB,SAAY,EAAE,cAAc,IAAI,CAAC;AAAA,IACvD,GAAI,iBAAiB,SAAY,EAAE,aAAa,IAAI,CAAC;AAAA,EACtD;AACD;AAKO,SAAS,mCACf,KACA,YACY;AACZ,QAAM,KAAK,qBAAqB,GAAG;AACnC,SAAO,EAAE,GAAG,IAAI,WAAW;AAC5B;AAEA,SAAS,eAAe,OAAgB,YAAsC;AAC7E,MAAI,UAAU,QAAQ,UAAU,QAAW;AAC1C,WAAO;AAAA,EACR;AAEA,UAAQ,WAAW,MAAM;AAAA,IACxB,KAAK;AACJ,aAAO,QAAQ,IAAI;AAAA,IACpB,KAAK;AACJ,aAAO,KAAK,UAAU,KAAK;AAAA,IAC5B,KAAK;AACJ,aAAO,eAAe,KAA0C;AAAA,IACjE;AACC,aAAO;AAAA,EACT;AACD;AAEA,SAAS,iBAAiB,OAAgB,YAAsC;AAC/E,UAAQ,WAAW,MAAM;AAAA,IACxB,KAAK;AACJ,aAAO,UAAU,KAAK,UAAU;AAAA,IACjC,KAAK;AACJ,UAAI,OAAO,UAAU,UAAU;AAC9B,eAAO,KAAK,MAAM,KAAK;AAAA,MACxB;AACA,aAAO;AAAA,IACR,KAAK;AACJ,aAAO,eAAe,KAAK;AAAA,IAC5B;AACC,aAAO;AAAA,EACT;AACD;AApNA,IAAAA,cA+DM,gBAKA,WAKA;AAzEN;AAAA;AAAA;AAAA,IAAAA,eAAmC;AAGnC;AA4DA,IAAM,iBAAiB;AAKvB,IAAM,YAAY;AAKlB,IAAM,oBAAoB;AAAA;AAAA;;;ACzE1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcA,SAAS,cAAc,MAAc,SAAiC;AACrE,QAAM,YAAY,IAAI,YAAY,EAAE,OAAO,IAAI;AAC/C,QAAM,SAAS,IAAI,WAAW,CAAC;AAC/B,QAAM,KAAK,IAAI,SAAS,OAAO,MAAM;AACrC,KAAG,UAAU,GAAG,UAAU,QAAQ,IAAI;AACtC,KAAG,UAAU,GAAG,QAAQ,QAAQ,IAAI;AAEpC,QAAM,SAAS,IAAI,WAAW,OAAO,SAAS,UAAU,SAAS,QAAQ,MAAM;AAC/E,SAAO,IAAI,QAAQ,CAAC;AACpB,SAAO,IAAI,WAAW,CAAC;AACvB,SAAO,IAAI,SAAS,IAAI,UAAU,MAAM;AACxC,SAAO;AACR;AAEA,SAAS,kBAAkB,MAAc,MAA2B;AACnE,QAAM,OAAO,KAAK,UAAU,IAAI;AAChC,SAAO,cAAc,MAAM,IAAI,YAAY,EAAE,OAAO,IAAI,CAAC;AAC1D;AAOA,SAAS,WAAW,MAAgB,QAAwB;AAC3D,SAAO,KAAK,UAAU,QAAQ,IAAI;AACnC;AAOA,SAAS,cAAc,MAA6B;AACnD,QAAM,WAAsB,CAAC;AAC7B,QAAM,KAAK,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACrE,MAAI,SAAS;AAEb,SAAO,SAAS,KAAK,KAAK,YAAY;AACrC,UAAM,UAAU,WAAW,IAAI,MAAM;AACrC,UAAM,aAAa,WAAW,IAAI,SAAS,CAAC;AAC5C,cAAU;AAEV,QAAI,SAAS,UAAU,aAAa,KAAK,WAAY;AAErD,UAAM,OAAO,IAAI,YAAY,EAAE,OAAO,KAAK,MAAM,QAAQ,SAAS,OAAO,CAAC;AAC1E,cAAU;AAEV,UAAM,UAAU,KAAK,MAAM,QAAQ,SAAS,UAAU;AACtD,cAAU;AAEV,aAAS,KAAK,EAAE,MAAM,QAAQ,CAAC;AAAA,EAChC;AAEA,SAAO;AACR;AAEA,SAAS,YAAY,UAAqB,MAAiC;AAC1E,aAAW,KAAK,UAAU;AACzB,QAAI,EAAE,SAAS,KAAM,QAAO,EAAE;AAAA,EAC/B;AACA,SAAO;AACR;AAEA,SAAS,iBAAoB,UAAqB,MAAwB;AACzE,QAAM,UAAU,YAAY,UAAU,IAAI;AAC1C,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,KAAK,MAAM,IAAI,YAAY,EAAE,OAAO,OAAO,CAAC;AACpD;AAmBA,eAAsB,aACrB,SACA,QACA,QACA,eACA,SACsB;AACtB,QAAM,aAAa,SAAS,eAAe,MAAM;AAAA,EAAC;AAClD,QAAM,iBAAiB,SAAS,kBAAkB;AAClD,QAAM,mBAAmB,SAAS;AAClC,QAAM,cAAc,mBACjB,OAAO,KAAK,OAAO,WAAW,EAAE,OAAO,CAAC,MAAM,iBAAiB,SAAS,CAAC,CAAC,IAC1E,OAAO,KAAK,OAAO,WAAW;AAEjC,aAAW,EAAE,OAAO,WAAW,UAAU,GAAG,SAAS,yBAAyB,CAAC;AAC/E,QAAM,gBAAgB,MAAM,kBAAkB,OAAO;AACrD,aAAW,EAAE,OAAO,WAAW,UAAU,KAAK,SAAS,mBAAmB,CAAC;AAC3E,QAAM,OAAO,MAAM,SAAS,OAAO;AACnC,aAAW,EAAE,OAAO,WAAW,UAAU,KAAK,SAAS,qBAAqB,CAAC;AAC7E,QAAM,aAAa,MAAM,kBAAkB,SAAS,MAAM;AAC1D,aAAW,EAAE,OAAO,WAAW,UAAU,KAAK,SAAS,kBAAkB,CAAC;AAE1E,QAAM,WAAyB,CAAC;AAChC,MAAI,wBAAwB,IAAI,WAAW,CAAC;AAG5C,QAAM,aAAa,CAAC,MAAc,SAAqB;AACtD,aAAS,KAAK,IAAI;AAClB,UAAM,SAAS,sBAAsB,SAAS,KAAK;AACnD,UAAM,WAAW,IAAI,WAAW,MAAM;AACtC,aAAS,IAAI,uBAAuB,CAAC;AACrC,aAAS,IAAI,MAAM,sBAAsB,MAAM;AAC/C,4BAAwB;AAAA,EACzB;AAGA,QAAM,QAAgC,CAAC;AACvC,aAAW,CAAC,KAAK,GAAG,KAAK,eAAe;AACvC,UAAM,GAAG,IAAI;AAAA,EACd;AACA,aAAW,kBAAkB,kBAAkB,kBAAkB,KAAK,CAAC;AAGvE,QAAM,UAAkC,CAAC;AACzC,aAAW,OAAO,MAAM;AACvB,YAAQ,IAAI,GAAG,IAAI,IAAI;AAAA,EACxB;AACA,aAAW,QAAQ,kBAAkB,QAAQ,OAAO,CAAC;AAGrD,QAAM,UAAU,GAAG,WAAW,IAAI,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA;AACxE,aAAW,cAAc,cAAc,cAAc,IAAI,YAAY,EAAE,OAAO,OAAO,CAAC,CAAC;AAGvF,MAAI,eAAe;AACnB,MAAI,gBAAgB;AACnB,eAAW,OAAO,aAAa;AAC9B,YAAM,UAAU,MAAM,sBAAsB,SAAS,GAAG;AACxD,UAAI,QAAQ,SAAS,GAAG;AACvB,cAAM,QAAQ,GAAG,QAAQ,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA;AACjE,cAAM,cAAc,WAAW,GAAG;AAClC,mBAAW,aAAa,cAAc,aAAa,IAAI,YAAY,EAAE,OAAO,KAAK,CAAC,CAAC;AACnF,wBAAgB,QAAQ;AAAA,MACzB;AAAA,IACD;AAAA,EACD;AACA,aAAW,EAAE,OAAO,WAAW,UAAU,KAAK,SAAS,qBAAqB,CAAC;AAG7E,QAAM,cAAc,MAAM,cAAc,qBAAqB;AAC7D,aAAW,EAAE,OAAO,WAAW,UAAU,GAAG,SAAS,aAAa,CAAC;AAGnE,QAAM,WAA2B;AAAA,IAChC,SAAS;AAAA,IACT,WAAW,KAAK,IAAI;AAAA,IACpB;AAAA,IACA;AAAA,IACA,gBAAgB,WAAW;AAAA,IAC3B;AAAA,IACA,iBAAiB;AAAA,IACjB,UAAU;AAAA,EACX;AAGA,QAAM,SAAS,IAAI,WAAW,CAAC;AAG/B,QAAM,kBAAkB,kBAAkB,YAAY,QAAQ;AAC9D,QAAM,kBAAkB,cAAc,YAAY,IAAI,YAAY,EAAE,OAAO,WAAW,CAAC;AAEvF,QAAM,WAAW,gBAAgB,SAAS,sBAAsB,SAAS,gBAAgB;AACzF,QAAM,SAAS,IAAI,WAAW,QAAQ;AACtC,MAAI,MAAM;AACV,SAAO,IAAI,iBAAiB,GAAG;AAC/B,SAAO,gBAAgB;AACvB,SAAO,IAAI,uBAAuB,GAAG;AACrC,SAAO,sBAAsB;AAC7B,SAAO,IAAI,iBAAiB,GAAG;AAE/B,SAAO;AACR;AASO,SAAS,mBAAmB,MAAkC;AACpE,QAAM,WAAW,cAAc,IAAI;AACnC,QAAM,WAAW,iBAAiC,UAAU,UAAU;AACtE,MAAI,CAAC,UAAU;AACd,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC7D;AACA,SAAO;AACR;AAQA,eAAsB,qBAAqB,MAAoC;AAC9E,QAAM,WAAW,cAAc,IAAI;AACnC,QAAM,WAAW,iBAAiC,UAAU,UAAU;AACtE,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,iBAAiB,SAAS;AAChC,MAAI,CAAC,eAAgB,QAAO;AAG5B,QAAM,kBAAkB,YAAY,UAAU,UAAU;AACxD,MAAI,CAAC,gBAAiB,QAAO;AAG7B,QAAM,kBAAkB,YAAY,UAAU,UAAU;AAGxD,QAAM,gBAAgB,kBACnB,IAAI,YAAY,EAAE,OAAO,SAAS,QAAQ,IAC1C,IAAI,WAAW,CAAC;AAGnB,QAAM,kBAAkB,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,SAAS,UAAU;AAE7F,MAAI,iBAAiB,IAAI,WAAW,CAAC;AACrC,aAAW,WAAW,iBAAiB;AACtC,UAAM,eAAe,cAAc,QAAQ,MAAM,QAAQ,OAAO;AAChE,UAAM,SAAS,eAAe,SAAS,aAAa;AACpD,UAAM,WAAW,IAAI,WAAW,MAAM;AACtC,aAAS,IAAI,gBAAgB,CAAC;AAC9B,aAAS,IAAI,cAAc,eAAe,MAAM;AAChD,qBAAiB;AAAA,EAClB;AAEA,QAAM,WAAW,MAAM,cAAc,cAAc;AACnD,SAAO,aAAa;AACrB;AAWA,eAAsB,cACrB,SACA,QACA,MACA,SACyB;AACzB,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,aAAa,SAAS,eAAe,MAAM;AAAA,EAAC;AAClD,QAAM,mBAAmB,SAAS;AAElC,aAAW,EAAE,OAAO,aAAa,UAAU,GAAG,SAAS,iBAAiB,CAAC;AAEzE,QAAM,WAAW,cAAc,IAAI;AACnC,QAAM,WAAW,iBAAiC,UAAU,UAAU;AACtE,MAAI,CAAC,UAAU;AACd,WAAO;AAAA,MACN,oBAAoB;AAAA,MACpB,iBAAiB;AAAA,MACjB,SAAS;AAAA,MACT,OAAO;AAAA,MACP,UAAU,KAAK,IAAI,IAAI;AAAA,IACxB;AAAA,EACD;AAGA,MAAI,SAAS,YAAY,gBAAgB;AACxC,WAAO;AAAA,MACN,oBAAoB;AAAA,MACpB,iBAAiB;AAAA,MACjB,SAAS;AAAA,MACT,OAAO,+BAA+B,SAAS,OAAO;AAAA,MACtD,UAAU,KAAK,IAAI,IAAI;AAAA,IACxB;AAAA,EACD;AAEA,aAAW,EAAE,OAAO,aAAa,UAAU,KAAK,SAAS,qBAAqB,CAAC;AAG/E,QAAM,QAAQ,MAAM,qBAAqB,IAAI;AAC7C,MAAI,CAAC,OAAO;AACX,WAAO;AAAA,MACN,oBAAoB;AAAA,MACpB,iBAAiB;AAAA,MACjB,SAAS;AAAA,MACT,OAAO;AAAA,MACP,UAAU,KAAK,IAAI,IAAI;AAAA,IACxB;AAAA,EACD;AAEA,aAAW,EAAE,OAAO,aAAa,UAAU,KAAK,SAAS,qBAAqB,CAAC;AAG/E,QAAM,aAAa,YAAY,UAAU,YAAY;AACrD,MAAI,aAA0B,CAAC;AAC/B,MAAI,YAAY;AACf,UAAM,OAAO,IAAI,YAAY,EAAE,OAAO,UAAU;AAChD,UAAM,QAAQ,KACZ,KAAK,EACL,MAAM,IAAI,EACV,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAC5B,iBAAa,MAAM,IAAI,CAAC,SAAS,KAAK,MAAM,IAAI,CAAc;AAAA,EAC/D;AAGA,MAAI,kBAAkB;AACrB,iBAAa,WAAW,OAAO,CAAC,OAAO,iBAAiB,SAAS,GAAG,UAAU,CAAC;AAAA,EAChF;AAGA,QAAM,SAAS,iBAAyC,UAAU,gBAAgB;AAGlF,QAAM,WAAW,iBAAyC,UAAU,MAAM;AAE1E,aAAW,EAAE,OAAO,aAAa,UAAU,KAAK,SAAS,sBAAsB,CAAC;AAEhF,MAAI,SAAS,OAAO;AAInB,UAAM,QAAQ,YAAY,OAAO,OAAO;AAEvC,UAAI,QAAQ;AACX,mBAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,MAAM,GAAG;AAChD,gBAAM,GAAG;AAAA,YACR;AAAA,YACA,CAAC,KAAK,GAAG;AAAA,UACV;AAAA,QACD;AAAA,MACD;AAGA,UAAI,UAAU;AACb,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACpD,gBAAM,GAAG,QAAQ,gEAAgE;AAAA,YAChF;AAAA,YACA;AAAA,UACD,CAAC;AAAA,QACF;AAAA,MACD;AAGA,iBAAW,MAAM,YAAY;AAC5B,cAAM,aAAa,GAAG;AACtB,cAAM,QAAQ;AAAA,UACb,IAAI,GAAG;AAAA,UACP,SAAS,GAAG;AAAA,UACZ,MAAM,GAAG;AAAA,UACT,WAAW,GAAG;AAAA,UACd,MAAM,GAAG,SAAS,OAAO,KAAK,UAAU,GAAG,IAAI,IAAI;AAAA,UACnD,eAAe,GAAG,iBAAiB,OAAO,KAAK,UAAU,GAAG,YAAY,IAAI;AAAA,UAC5E,WAAW,KAAK,UAAU,GAAG,SAAS;AAAA,UACtC,iBAAiB,GAAG;AAAA,UACpB,aAAa,KAAK,UAAU,GAAG,UAAU;AAAA,UACzC,gBAAgB,GAAG;AAAA,QACpB;AAEA,cAAM,GAAG;AAAA,UACR,mCAAmC,UAAU;AAAA,UAC7C;AAAA,YACC,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,UACP;AAAA,QACD;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF,OAAO;AAEN,UAAM,QAAQ,YAAY,OAAO,OAAO;AAEvC,iBAAW,cAAc,OAAO,KAAK,OAAO,WAAW,GAAG;AACzD,cAAM,GAAG,QAAQ,yBAAyB,UAAU,EAAE;AACtD,cAAM,GAAG,QAAQ,eAAe,UAAU,EAAE;AAAA,MAC7C;AACA,YAAM,GAAG,QAAQ,kCAAkC;AACnD,YAAM,GAAG,QAAQ,wBAAwB;AAGzC,UAAI,QAAQ;AACX,mBAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,MAAM,GAAG;AAChD,gBAAM,GAAG;AAAA,YACR;AAAA,YACA,CAAC,KAAK,GAAG;AAAA,UACV;AAAA,QACD;AAAA,MACD;AAGA,UAAI,UAAU;AACb,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACpD,gBAAM,GAAG,QAAQ,qDAAqD,CAAC,KAAK,KAAK,CAAC;AAAA,QACnF;AAAA,MACD;AAGA,iBAAW,MAAM,YAAY;AAC5B,cAAM,aAAa,GAAG;AACtB,cAAM,GAAG;AAAA,UACR,yBAAyB,UAAU;AAAA,UACnC;AAAA,YACC,GAAG;AAAA,YACH,GAAG;AAAA,YACH,GAAG;AAAA,YACH,GAAG;AAAA,YACH,GAAG,SAAS,OAAO,KAAK,UAAU,GAAG,IAAI,IAAI;AAAA,YAC7C,GAAG,iBAAiB,OAAO,KAAK,UAAU,GAAG,YAAY,IAAI;AAAA,YAC7D,KAAK,UAAU,GAAG,SAAS;AAAA,YAC3B,GAAG;AAAA,YACH,KAAK,UAAU,GAAG,UAAU;AAAA,YAC5B,GAAG;AAAA,UACJ;AAAA,QACD;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF;AAEA,aAAW,EAAE,OAAO,aAAa,UAAU,KAAK,SAAS,oBAAoB,CAAC;AAG9E,MAAI,kBAAkB;AACtB,MAAI,SAAS,iBAAiB;AAC7B,eAAW,OAAO,SAAS,aAAa;AACvC,UAAI,oBAAoB,CAAC,iBAAiB,SAAS,GAAG,EAAG;AAEzD,YAAM,iBAAiB,YAAY,UAAU,WAAW,GAAG,EAAE;AAC7D,UAAI,CAAC,eAAgB;AAErB,YAAM,OAAO,IAAI,YAAY,EAAE,OAAO,cAAc;AACpD,YAAM,QAAQ,KACZ,KAAK,EACL,MAAM,IAAI,EACV,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAC5B,YAAM,UAAU,MAAM,IAAI,CAAC,SAAS,KAAK,MAAM,IAAI,CAA4B;AAE/E,UAAI,QAAQ,WAAW,EAAG;AAE1B,YAAM,QAAQ,YAAY,OAAO,OAAO;AACvC,mBAAW,UAAU,SAAS;AAC7B,gBAAM,OAAO,OAAO,KAAK,MAAM;AAC/B,gBAAM,eAAe,KAAK,IAAI,MAAM,GAAG,EAAE,KAAK,IAAI;AAClD,gBAAM,SAAS,KAAK,IAAI,CAAC,MAAM;AAC9B,kBAAM,IAAI,OAAO,CAAC;AAClB,gBAAI,OAAO,MAAM,UAAW,QAAO,IAAI,IAAI;AAC3C,gBAAI,MAAM,QAAQ,CAAC,KAAM,OAAO,MAAM,YAAY,MAAM,KAAO,QAAO,KAAK,UAAU,CAAC;AACtF,mBAAO;AAAA,UACR,CAAC;AAED,gBAAM,GAAG;AAAA,YACR,0BAA0B,GAAG,KAAK,KAAK,KAAK,IAAI,CAAC,aAAa,YAAY;AAAA,YAC1E;AAAA,UACD;AAAA,QACD;AAAA,MACD,CAAC;AAED,yBAAmB,QAAQ;AAAA,IAC5B;AAAA,EACD;AAEA,aAAW,EAAE,OAAO,aAAa,UAAU,GAAG,SAAS,OAAO,CAAC;AAE/D,SAAO;AAAA,IACN,oBAAoB,WAAW;AAAA,IAC/B;AAAA,IACA,SAAS;AAAA,IACT,UAAU,KAAK,IAAI,IAAI;AAAA,EACxB;AACD;AAIA,eAAe,kBAAkB,SAAuD;AACvF,QAAM,OAAO,MAAM,QAAQ;AAAA,IAC1B;AAAA,EACD;AACA,QAAM,KAAK,oBAAI,IAAoB;AACnC,aAAW,OAAO,MAAM;AACvB,OAAG,IAAI,IAAI,SAAS,IAAI,eAAe;AAAA,EACxC;AACA,SAAO;AACR;AAOA,eAAe,SAAS,SAA6C;AACpE,SAAO,QAAQ,MAAe,mCAAmC;AAClE;AAEA,eAAe,kBACd,SACA,QACuB;AACvB,QAAM,SAAsB,CAAC;AAE7B,aAAW,kBAAkB,OAAO,KAAK,OAAO,WAAW,GAAG;AAC7D,UAAM,OAAO,MAAM,QAAQ;AAAA,MAC1B,2BAA2B,cAAc;AAAA,IAC1C;AAEA,eAAW,OAAO,MAAM;AACvB,aAAO,KAAK,mCAAmC,KAAK,cAAc,CAAC;AAAA,IACpE;AAAA,EACD;AAEA,SAAO;AACR;AAEA,eAAe,sBACd,SACA,YACqC;AACrC,SAAO,QAAQ,MAA+B,iBAAiB,UAAU,qBAAqB;AAC/F;AAIA,eAAe,cAAc,MAAgD;AAC5E,QAAM,aAAa,MAAM,OAAO,OAAO,OAAO,WAAW,IAAI;AAC7D,QAAM,YAAY,MAAM,KAAK,IAAI,WAAW,UAAU,CAAC;AACvD,SAAO,UAAU,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AACrE;AAljBA,IAAAC,cAuFM;AAvFN;AAAA;AAAA;AAAA,IAAAA,eAA+B;AAE/B;AAqFA,IAAM,iBAAiB;AAAA;AAAA;;;AClFhB,SAAS,kBAAkB,MAAc,OAAyB;AACxE,MAAI,iBAAiB,YAAY;AAChC,QAAI,SAAS;AACb,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACtC,gBAAU,OAAO,aAAa,MAAM,CAAC,CAAW;AAAA,IACjD;AACA,WAAO,EAAE,CAAC,cAAc,GAAG,KAAK,MAAM,EAAE;AAAA,EACzC;AACA,SAAO;AACR;AAKO,SAAS,iBAAiB,MAAc,OAAyB;AACvE,MACC,UAAU,QACV,OAAO,UAAU,YACjB,kBAAkB,SAClB,OAAQ,MAAkC,cAAc,MAAM,UAC7D;AACD,UAAM,UAAW,MAAkC,cAAc;AACjE,QAAI,OAAO,YAAY,UAAU;AAChC,aAAO;AAAA,IACR;AACA,UAAM,SAAS,KAAK,OAAO;AAC3B,UAAM,QAAQ,IAAI,WAAW,OAAO,MAAM;AAC1C,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACvC,YAAM,CAAC,IAAI,OAAO,WAAW,CAAC;AAAA,IAC/B;AACA,WAAO;AAAA,EACR;AACA,SAAO;AACR;AAKO,SAAS,mBAAmB,OAAwB;AAC1D,SAAO,KAAK,UAAU,OAAO,iBAAiB;AAC/C;AAKO,SAAS,qBAAwB,MAAiB;AACxD,SAAO,KAAK,MAAM,MAAM,gBAAgB;AACzC;AApDA,IAAM;AAAN;AAAA;AAAA;AAAA,IAAM,iBAAiB;AAAA;AAAA;;;ACAvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBO,SAAS,6BACf,OACsB;AACtB,SAAO;AAAA,IACN,QAAI,8BAAe;AAAA,IACnB,YAAY,KAAK,IAAI;AAAA,IACrB,WAAW,MAAM;AAAA,IACjB,YAAY,MAAM,SAAS,wBAAwB,MAAM,aAAa;AAAA,IACtE,OAAO,MAAM;AAAA,EACd;AACD;AAKA,eAAsB,iBACrB,SACA,OACgB;AAChB,QAAM,aAAa,MAAM,MAAM,WAAW;AAC1C,QAAM,WAAW,MAAM,MAAM,WAAW;AAExC,QAAM,QAAQ;AAAA,IACb;AAAA;AAAA;AAAA,IAGA;AAAA,MACC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,MAAM,MAAM;AAAA,MACZ,MAAM,MAAM;AAAA,MACZ,MAAM,MAAM;AAAA,MACZ,MAAM,cAAc;AAAA,MACpB,mBAAmB,KAAK;AAAA,IACzB;AAAA,EACD;AACD;AAKA,eAAsB,gBACrB,SACA,OACiC;AACjC,QAAM,aAAuB,CAAC;AAC9B,QAAM,SAAoB,CAAC;AAE3B,MAAI,OAAO,eAAe,MAAM,YAAY,SAAS,GAAG;AACvD,UAAM,eAAe,MAAM,YAAY,IAAI,MAAM,GAAG,EAAE,KAAK,IAAI;AAC/D,eAAW,KAAK,kBAAkB,YAAY,GAAG;AACjD,WAAO,KAAK,GAAG,MAAM,WAAW;AAAA,EACjC;AACA,MAAI,OAAO,UAAU,QAAW;AAC/B,eAAW,KAAK,kBAAkB;AAClC,WAAO,KAAK,MAAM,KAAK;AAAA,EACxB;AACA,MAAI,OAAO,UAAU,QAAW;AAC/B,eAAW,KAAK,kBAAkB;AAClC,WAAO,KAAK,MAAM,KAAK;AAAA,EACxB;AAEA,QAAM,cAAc,WAAW,SAAS,IAAI,SAAS,WAAW,KAAK,OAAO,CAAC,KAAK;AAClF,QAAM,OAAO,MAAM,QAAQ;AAAA,IAC1B,oCAAoC,WAAW;AAAA,IAC/C;AAAA,EACD;AAEA,SAAO,KAAK,IAAI,mBAAmB;AACpC;AAEA,SAAS,oBAAoB,KAAyC;AACrE,SAAO,qBAA0C,IAAI,UAAU;AAChE;AAKA,eAAsB,iBAAiB,SAA0C;AAChF,QAAM,OAAO,MAAM,QAAQ;AAAA,IAC1B;AAAA,EACD;AACA,SAAO,KAAK,CAAC,GAAG,SAAS;AAC1B;AAKO,SAAS,sBAAsB,OAGpC;AACD,SAAO;AAAA,IACN,YAAY,MAAM,WAAW;AAAA,IAC7B,UAAU,MAAM,WAAW;AAAA,EAC5B;AACD;AAzHA,IAAAC;AAAA;AAAA;AAAA;AAAA,IAAAA,gBAA+B;AAG/B;AAAA;AAAA;;;ACHA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcA,SAASC,eAAc,MAAc,SAAiC;AACrE,QAAM,YAAY,IAAI,YAAY,EAAE,OAAO,IAAI;AAC/C,QAAM,SAAS,IAAI,WAAW,CAAC;AAC/B,QAAM,OAAO,IAAI,SAAS,OAAO,MAAM;AACvC,OAAK,UAAU,GAAG,UAAU,QAAQ,IAAI;AACxC,OAAK,UAAU,GAAG,QAAQ,QAAQ,IAAI;AAEtC,QAAM,SAAS,IAAI,WAAW,OAAO,SAAS,UAAU,SAAS,QAAQ,MAAM;AAC/E,SAAO,IAAI,QAAQ,CAAC;AACpB,SAAO,IAAI,WAAW,CAAC;AACvB,SAAO,IAAI,SAAS,IAAI,UAAU,MAAM;AACxC,SAAO;AACR;AAEA,SAASC,mBAAkB,MAAc,MAA2B;AACnE,SAAOD,eAAc,MAAM,IAAI,YAAY,EAAE,OAAO,mBAAmB,IAAI,CAAC,CAAC;AAC9E;AAEA,SAAS,oBAAoB,MAAc,SAAgC;AAC1E,QAAM,QAAQ,GAAG,QAAQ,IAAI,CAAC,WAAW,mBAAmB,MAAM,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA;AAC/E,SAAOA,eAAc,MAAM,IAAI,YAAY,EAAE,OAAO,KAAK,CAAC;AAC3D;AAEA,SAASE,YAAW,MAAgB,QAAwB;AAC3D,SAAO,KAAK,UAAU,QAAQ,IAAI;AACnC;AAOA,SAASC,eAAc,MAA6B;AACnD,QAAM,WAAsB,CAAC;AAC7B,QAAM,OAAO,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACvE,MAAI,SAAS;AAEb,SAAO,SAAS,KAAK,KAAK,YAAY;AACrC,UAAM,UAAUD,YAAW,MAAM,MAAM;AACvC,UAAM,aAAaA,YAAW,MAAM,SAAS,CAAC;AAC9C,cAAU;AAEV,QAAI,SAAS,UAAU,aAAa,KAAK,YAAY;AACpD;AAAA,IACD;AAEA,UAAM,OAAO,IAAI,YAAY,EAAE,OAAO,KAAK,MAAM,QAAQ,SAAS,OAAO,CAAC;AAC1E,cAAU;AAEV,UAAM,UAAU,KAAK,MAAM,QAAQ,SAAS,UAAU;AACtD,cAAU;AAEV,aAAS,KAAK,EAAE,MAAM,QAAQ,CAAC;AAAA,EAChC;AAEA,SAAO;AACR;AAEA,SAASE,aAAY,UAAqB,MAAiC;AAC1E,aAAW,WAAW,UAAU;AAC/B,QAAI,QAAQ,SAAS,MAAM;AAC1B,aAAO,QAAQ;AAAA,IAChB;AAAA,EACD;AACA,SAAO;AACR;AAEA,eAAeC,eAAc,MAAgD;AAC5E,QAAM,aAAa,MAAM,OAAO,OAAO,OAAO,WAAW,IAAI;AAC7D,SAAO,MAAM,KAAK,IAAI,WAAW,UAAU,CAAC,EAC1C,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAChD,KAAK,EAAE;AACV;AAEA,eAAeC,mBACd,SACA,QACA,kBACuB;AACvB,QAAM,cAAc,mBACjB,OAAO,KAAK,OAAO,WAAW,EAAE,OAAO,CAAC,SAAS,iBAAiB,SAAS,IAAI,CAAC,IAChF,OAAO,KAAK,OAAO,WAAW;AAEjC,QAAM,SAAsB,CAAC;AAC7B,aAAW,kBAAkB,aAAa;AACzC,UAAM,OAAO,MAAM,QAAQ;AAAA,MAC1B,2BAA2B,cAAc;AAAA,IAC1C;AAEA,eAAW,OAAO,MAAM;AACvB,aAAO,KAAK,mCAAmC,KAAK,cAAc,CAAC;AAAA,IACpE;AAAA,EACD;AAEA,SAAO;AACR;AAEA,SAAS,8BACR,YACA,kBACc;AACd,MAAI,CAAC,oBAAoB,iBAAiB,WAAW,GAAG;AACvD,WAAO;AAAA,EACR;AACA,QAAM,UAAU,IAAI,IAAI,gBAAgB;AACxC,SAAO,WAAW,OAAO,CAAC,OAAO,QAAQ,IAAI,GAAG,UAAU,CAAC;AAC5D;AAKA,eAAsB,YACrB,SACA,QACA,QACA,eACA,SACsB;AACtB,QAAM,aAAa,SAAS,eAAe,MAAM;AAAA,EAAC;AAClD,QAAM,aAA8B;AAAA,IACnC,aAAa,SAAS;AAAA,IACtB,OAAO,SAAS;AAAA,IAChB,OAAO,SAAS;AAAA,EACjB;AAEA,aAAW,EAAE,OAAO,WAAW,UAAU,GAAG,SAAS,qBAAqB,CAAC;AAC3E,QAAM,aAAa;AAAA,IAClB,MAAMA,mBAAkB,SAAS,QAAQ,SAAS,WAAW;AAAA,IAC7D,SAAS;AAAA,EACV;AAEA,aAAW,EAAE,OAAO,WAAW,UAAU,KAAK,SAAS,uBAAuB,CAAC;AAC/E,QAAM,cAAc,MAAM,gBAAgB,SAAS,UAAU;AAE7D,aAAW,EAAE,OAAO,WAAW,UAAU,KAAK,SAAS,wBAAwB,CAAC;AAChF,QAAM,WAAyB,CAAC;AAChC,MAAI,qBAAqB,IAAI,WAAW,CAAC;AAEzC,QAAM,aAAa,CAAC,YAA8B;AACjD,aAAS,KAAK,OAAO;AACrB,UAAM,WAAW,IAAI,WAAW,mBAAmB,SAAS,QAAQ,MAAM;AAC1E,aAAS,IAAI,oBAAoB,CAAC;AAClC,aAAS,IAAI,SAAS,mBAAmB,MAAM;AAC/C,yBAAqB;AAAA,EACtB;AAEA,aAAW,oBAAoB,cAAc,UAAU,CAAC;AACxD,aAAW,oBAAoB,gBAAgB,WAAW,CAAC;AAE3D,aAAW,EAAE,OAAO,aAAa,UAAU,KAAK,SAAS,qBAAqB,CAAC;AAC/E,QAAM,WAAW,MAAMD,eAAc,kBAA6C;AAElF,QAAM,WAAgC;AAAA,IACrC,SAAS;AAAA,IACT,YAAY,KAAK,IAAI;AAAA,IACrB;AAAA,IACA;AAAA,IACA,gBAAgB,WAAW;AAAA,IAC3B,iBAAiB,YAAY;AAAA,IAC7B;AAAA,EACD;AAEA,QAAM,kBAAkBJ,mBAAkB,YAAY,QAAQ;AAC9D,QAAM,kBAAkBD,eAAc,YAAY,IAAI,YAAY,EAAE,OAAO,QAAQ,CAAC;AAEpF,aAAW,EAAE,OAAO,WAAW,UAAU,GAAG,SAAS,aAAa,CAAC;AAEnE,QAAM,QAAQ,CAAC,iBAAiB,GAAG,UAAU,eAAe;AAC5D,QAAM,cAAc,IAAI,WAAW,MAAM,OAAO,CAAC,KAAK,SAAS,MAAM,KAAK,QAAQ,CAAC,CAAC;AACpF,MAAI,SAAS;AACb,aAAW,QAAQ,OAAO;AACzB,gBAAY,IAAI,MAAM,MAAM;AAC5B,cAAU,KAAK;AAAA,EAChB;AAEA,SAAO;AACR;AAKO,SAAS,kBAAkB,MAAsC;AACvE,QAAM,WAAWG,eAAc,IAAI;AACnC,QAAM,WAAW,KAAK;AAAA,IACrB,IAAI,YAAY,EAAE,OAAOC,aAAY,UAAU,UAAU,KAAK,IAAI,WAAW,CAAC;AAAA,EAC/E;AAEA,QAAM,oBAAoBA,aAAY,UAAU,YAAY;AAC5D,QAAM,qBAAqBA,aAAY,UAAU,cAAc;AAE/D,QAAM,aAAa,mBAA8B,iBAAiB;AAClE,QAAM,cAAc,mBAAwC,kBAAkB;AAE9E,SAAO,EAAE,UAAU,YAAY,YAAY;AAC5C;AAKO,SAAS,wBAAwB,MAAuC;AAC9E,QAAM,WAAWD,eAAc,IAAI;AACnC,QAAM,kBAAkBC,aAAY,UAAU,UAAU;AACxD,MAAI,CAAC,iBAAiB;AACrB,UAAM,IAAI,MAAM,gDAAgD;AAAA,EACjE;AACA,SAAO,KAAK,MAAM,IAAI,YAAY,EAAE,OAAO,eAAe,CAAC;AAC5D;AAKA,eAAsB,0BAA0B,MAAoC;AACnF,QAAM,WAAWD,eAAc,IAAI;AACnC,QAAM,WAAW,wBAAwB,IAAI;AAC7C,QAAM,kBAAkB,SAAS;AAAA,IAChC,CAAC,YAAY,QAAQ,SAAS,cAAc,QAAQ,SAAS;AAAA,EAC9D;AAEA,MAAI,UAAU,IAAI,WAAW,CAAC;AAC9B,aAAW,WAAW,iBAAiB;AACtC,UAAM,UAAUH,eAAc,QAAQ,MAAM,QAAQ,OAAO;AAC3D,UAAM,WAAW,IAAI,WAAW,QAAQ,SAAS,QAAQ,MAAM;AAC/D,aAAS,IAAI,SAAS,CAAC;AACvB,aAAS,IAAI,SAAS,QAAQ,MAAM;AACpC,cAAU;AAAA,EACX;AAEA,QAAM,WAAW,MAAMK,eAAc,OAAkC;AACvE,SAAO,aAAa,SAAS;AAC9B;AAEA,SAAS,mBAAsB,SAAiC;AAC/D,MAAI,CAAC,WAAW,QAAQ,WAAW,GAAG;AACrC,WAAO,CAAC;AAAA,EACT;AACA,QAAM,OAAO,IAAI,YAAY,EAAE,OAAO,OAAO,EAAE,KAAK;AACpD,MAAI,KAAK,WAAW,GAAG;AACtB,WAAO,CAAC;AAAA,EACT;AACA,SAAO,KAAK,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,qBAAwB,IAAI,CAAC;AACpE;AA9PA;AAAA;AAAA;AACA;AAGA;AACA;AAAA;AAAA;;;ACLA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAA0B;AAKnB,IAAM,aAAN,cAAyB,sBAAU;AAAA,EACzC,YAAY,SAAiB,SAAmC;AAC/D,UAAM,SAAS,eAAe,OAAO;AACrC,SAAK,OAAO;AAAA,EACb;AACD;AAKO,IAAM,sBAAN,cAAkC,sBAAU;AAAA,EAClD,YAAY,YAAoB,UAAkB;AACjD,UAAM,WAAW,QAAQ,8BAA8B,UAAU,KAAK,oBAAoB;AAAA,MACzF;AAAA,MACA;AAAA,IACD,CAAC;AACD,SAAK,OAAO;AAAA,EACb;AACD;AAKO,IAAM,eAAN,cAA2B,sBAAU;AAAA,EAC3C,YAAY,SAAiB,SAAmC;AAC/D,UAAM,SAAS,iBAAiB,OAAO;AACvC,SAAK,OAAO;AAAA,EACb;AACD;AAKO,IAAM,oBAAN,cAAgC,sBAAU;AAAA,EAChD,cAAc;AACb,UAAM,sEAAsE,gBAAgB;AAC5F,SAAK,OAAO;AAAA,EACb;AACD;AAKO,IAAM,kBAAN,cAA8B,sBAAU;AAAA,EAC9C,YAAY,SAAiB,SAAmC;AAC/D,UAAM,iCAAiC,OAAO,IAAI,qBAAqB,OAAO;AAC9E,SAAK,OAAO;AAAA,EACb;AACD;AAKO,IAAM,qBAAN,cAAiC,sBAAU;AAAA,EACjD,YAAY,WAAmB,WAAmB;AACjD;AAAA,MACC,iCAAiC,SAAS,qBAAqB,SAAS;AAAA,MACxE;AAAA,MACA,EAAE,WAAW,UAAU;AAAA,IACxB;AACA,SAAK,OAAO;AAAA,EACb;AACD;AAKO,IAAM,mBAAN,cAA+B,sBAAU;AAAA,EAC/C,YAAY,SAAiB,SAAmC;AAC/D,UAAM,sBAAsB,OAAO,IAAI,qBAAqB,OAAO;AACnE,SAAK,OAAO;AAAA,EACb;AACD;;;AC/CO,IAAM,+BAA+B;;;AC7B5C,IAAAE,eAAwD;AAQjD,SAAS,8BAA8B,cAA4C;AACzF,QAAM,gBAAY,kCAAoB;AACtC,aAAW,CAAC,QAAQ,GAAG,KAAK,cAAc;AACzC,QAAI,MAAM,GAAG;AACZ,gBAAU,IAAI,QAAQ,GAAG;AAAA,IAC1B;AAAA,EACD;AACA,SAAO;AACR;AAMA,eAAsB,oBACrB,SACA,QACA,UACA,cAC4B;AAC5B,MAAI,SAAS,SAAS,SAAS;AAC9B,WAAO,EAAE,cAAc,GAAG,eAAW,kCAAoB,EAAE;AAAA,EAC5D;AAEA,QAAM,YAAY,8BAA8B,YAAY;AAC5D,MAAI,UAAU,SAAS,GAAG;AACzB,WAAO,EAAE,cAAc,GAAG,UAAU;AAAA,EACrC;AAEA,QAAM,gBACL,SAAS,SAAS,eAAe,KAAK,IAAI,IAAI,SAAS,OAAO,KAAK,KAAK,KAAK,MAAO;AACrF,QAAM,sBACL,kBAAkB,OACf,gCAAmB,UAAU;AAAA,IAC7B,UAAU;AAAA,IACV,SAAS;AAAA,IACT,QAAQ;AAAA,EACT,CAAC,EAAE,MAAM,GAAG,EAAE,IACb;AAEJ,MAAI,eAAe;AACnB,QAAM,kBAAkB,OAAO,KAAK,OAAO,WAAW;AAEtD,QAAM,QAAQ,YAAY,OAAO,OAAoB;AACpD,eAAW,kBAAkB,iBAAiB;AAC7C,YAAM,QAAQ,aAAa,cAAc;AACzC,iBAAW,CAAC,QAAQ,MAAM,KAAK,WAAW;AACzC,YAAI,UAAU,EAAG;AAEjB,cAAM,WAAW,cAAc,OAAO,wBAAwB,IAAI;AAClE,cAAM,cACL,wBAAwB,OAAO,CAAC,QAAQ,QAAQ,mBAAmB,IAAI,CAAC,QAAQ,MAAM;AACvF,cAAM,YAAY,MAAM,GAAG,MAAyB,UAAU,WAAW;AACzE,wBAAgB,UAAU,CAAC,GAAG,SAAS;AAEvC,cAAM,YAAY,eAAe,OAAO,wBAAwB,IAAI;AACpE,cAAM,GAAG,QAAQ,WAAW,WAAW;AAAA,MACxC;AAAA,IACD;AAEA,UAAM,GAAG,QAAQ,gEAAgE;AAAA,MAChF;AAAA,MACA,OAAO,KAAK,IAAI,CAAC;AAAA,IAClB,CAAC;AAAA,EACF,CAAC;AAED,SAAO,EAAE,cAAc,UAAU;AAClC;AAEA,SAAS,cAAc,OAAe,SAA0B;AAC/D,MAAI,SAAS;AACZ,WAAO,iCAAiC,KAAK;AAAA,EAC9C;AACA,SAAO,iCAAiC,KAAK;AAC9C;AAEA,SAAS,eAAe,OAAe,SAA0B;AAChE,MAAI,SAAS;AACZ,WAAO,eAAe,KAAK;AAAA,EAC5B;AACA,SAAO,eAAe,KAAK;AAC5B;;;ACzFA,IAAAC,eAAoC;AAG7B,IAAM,oCAAoC;AAC1C,IAAM,wBAAwB;AAK9B,SAAS,6BAA6B,QAA+B;AAC3E,QAAM,SAAiC,CAAC;AACxC,aAAW,CAAC,QAAQ,GAAG,KAAK,QAAQ;AACnC,WAAO,MAAM,IAAI;AAAA,EAClB;AACA,SAAO,KAAK,UAAU,MAAM;AAC7B;AAKO,SAAS,iCAAiC,OAA8B;AAC9E,QAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,QAAM,aAAS,kCAAoB;AACnC,aAAW,CAAC,QAAQ,GAAG,KAAK,OAAO,QAAQ,MAAM,GAAG;AACnD,QAAI,OAAO,QAAQ,YAAY,OAAO,GAAG;AACxC,aAAO,IAAI,QAAQ,GAAG;AAAA,IACvB;AAAA,EACD;AACA,SAAO;AACR;AAKO,SAAS,oBAAoB,GAAkB,GAAiC;AACtF,QAAM,SAAS,IAAI,IAAI,CAAC;AACxB,aAAW,CAAC,QAAQ,GAAG,KAAK,GAAG;AAC9B,WAAO,IAAI,QAAQ,KAAK,IAAI,OAAO,IAAI,MAAM,KAAK,GAAG,GAAG,CAAC;AAAA,EAC1D;AACA,SAAO;AACR;AAKA,eAAsB,+BACrB,aACA,cACA,YACuB;AACvB,QAAM,UAAuB,CAAC;AAC9B,aAAW,CAAC,QAAQ,QAAQ,KAAK,aAAa;AAC7C,UAAM,YAAY,aAAa,IAAI,MAAM,KAAK;AAC9C,QAAI,WAAW,WAAW;AACzB,YAAM,MAAM,MAAM,WAAW,QAAQ,YAAY,GAAG,QAAQ;AAC5D,cAAQ,KAAK,GAAG,GAAG;AAAA,IACpB;AAAA,EACD;AACA,UAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,iBAAiB,EAAE,cAAc;AAC1D,SAAO;AACR;AAKA,eAAsB,0BAA0B,SAAiD;AAChG,QAAM,OAAO,MAAM,QAAQ,MAAe,8CAA8C;AAAA,IACvF;AAAA,EACD,CAAC;AACD,QAAM,MAAM,KAAK,CAAC;AAClB,MAAI,CAAC,KAAK,OAAO;AAChB,eAAO,kCAAoB;AAAA,EAC5B;AACA,MAAI;AACH,WAAO,iCAAiC,IAAI,KAAK;AAAA,EAClD,QAAQ;AACP,eAAO,kCAAoB;AAAA,EAC5B;AACD;AAKA,eAAsB,0BACrB,SACA,QACgB;AAChB,QAAM,QAAQ,QAAQ,gEAAgE;AAAA,IACrF;AAAA,IACA,6BAA6B,MAAM;AAAA,EACpC,CAAC;AACF;AAKA,eAAsB,gBAAgB,SAAiD;AACtF,QAAM,OAAO,MAAM,QAAQ,MAAe,8CAA8C;AAAA,IACvF;AAAA,EACD,CAAC;AACD,SAAO,KAAK,CAAC,GAAG,SAAS;AAC1B;AAKA,eAAsB,gBACrB,SACA,QACgB;AAChB,MAAI,WAAW,MAAM;AACpB,UAAM,QAAQ,QAAQ,wCAAwC,CAAC,qBAAqB,CAAC;AACrF;AAAA,EACD;AAEA,QAAM,QAAQ,QAAQ,gEAAgE;AAAA,IACrF;AAAA,IACA;AAAA,EACD,CAAC;AACF;;;ACxHA,IAAAC,gBAMO;AASP;;;ACfA,IAAAC,eAAgC;;;ACAhC,IAAAC,eAAsD;AAI/C,IAAM,oBAAoB;AAM1B,SAAS,oBAAoB,WAAiC;AACpE,SAAO,gCAAmB,UAAU,SAAS;AAC9C;AAMO,SAAS,qBACf,KACe;AACf,QAAM,UAAU,IAAI;AACpB,MAAI,OAAO,YAAY,YAAY,QAAQ,SAAS,GAAG;AACtD,WAAO,gCAAmB,YAAY,OAAO;AAAA,EAC9C;AACA,SAAO,EAAE,UAAU,IAAI,aAAa,SAAS,GAAG,QAAQ,GAAG;AAC5D;AAKO,SAAS,uBACf,UACA,KACU;AACV,SAAO,gCAAmB,QAAQ,UAAU,qBAAqB,GAAG,CAAC,IAAI;AAC1E;AAMO,SAAS,sBAAsB,eAA0D;AAC/F,SAAO;AAAA,IACN,KAAK;AAAA,IACL,QAAQ,CAAC,mBAAmB,aAAa;AAAA,EAC1C;AACD;;;AC1BO,SAAS,iBACf,YACA,QACW;AACX,QAAM,SAAoB,CAAC;AAC3B,QAAM,QAAQ,CAAC,iBAAiB,WAAW,UAAU,EAAE;AAEvD,QAAM,cAAc,sBAAsB,WAAW,OAAO,QAAQ,MAAM;AAE1E,QAAM,gBAAgB;AACtB,MAAI,aAAa;AAChB,UAAM,KAAK,SAAS,aAAa,QAAQ,WAAW,EAAE;AAAA,EACvD,OAAO;AACN,UAAM,KAAK,SAAS,aAAa,EAAE;AAAA,EACpC;AAEA,MAAI,WAAW,QAAQ,SAAS,GAAG;AAClC,UAAM,aAAa,WAAW,QAAQ,IAAI,CAAC,MAAM;AAChD,wBAAkB,EAAE,OAAO,MAAM;AACjC,aAAO,GAAG,EAAE,KAAK,IAAI,EAAE,UAAU,YAAY,CAAC;AAAA,IAC/C,CAAC;AACD,UAAM,KAAK,YAAY,WAAW,KAAK,IAAI,CAAC,EAAE;AAAA,EAC/C;AAEA,MAAI,WAAW,UAAU,QAAW;AACnC,UAAM,KAAK,SAAS,WAAW,KAAK,EAAE;AAAA,EACvC;AAEA,MAAI,WAAW,WAAW,QAAW;AACpC,UAAM,KAAK,UAAU,WAAW,MAAM,EAAE;AAAA,EACzC;AAEA,SAAO,EAAE,KAAK,MAAM,KAAK,GAAG,GAAG,OAAO;AACvC;AAUO,SAAS,gBACf,YACA,QACW;AACX,QAAM,SAAoB,CAAC;AAC3B,QAAM,QAAQ,CAAC,iCAAiC,WAAW,UAAU,EAAE;AAEvE,QAAM,cAAc,sBAAsB,WAAW,OAAO,QAAQ,MAAM;AAC1E,QAAM,gBAAgB;AACtB,MAAI,aAAa;AAChB,UAAM,KAAK,SAAS,aAAa,QAAQ,WAAW,EAAE;AAAA,EACvD,OAAO;AACN,UAAM,KAAK,SAAS,aAAa,EAAE;AAAA,EACpC;AAEA,SAAO,EAAE,KAAK,MAAM,KAAK,GAAG,GAAG,OAAO;AACvC;AASO,SAAS,iBAAiB,YAAoB,QAA2C;AAC/F,QAAM,UAAU,OAAO,KAAK,MAAM;AAClC,QAAM,eAAe,QAAQ,IAAI,MAAM,GAAG;AAC1C,QAAM,SAAS,OAAO,OAAO,MAAM;AAEnC,QAAM,MAAM,eAAe,UAAU,KAAK,QAAQ,KAAK,IAAI,CAAC,aAAa,aAAa,KAAK,IAAI,CAAC;AAChG,SAAO,EAAE,KAAK,OAAO;AACtB;AAUO,SAAS,iBACf,YACA,IACA,SACW;AACX,QAAM,aAAa,OAAO,KAAK,OAAO,EAAE,IAAI,CAAC,QAAQ,GAAG,GAAG,MAAM;AACjE,QAAM,SAAS,CAAC,GAAG,OAAO,OAAO,OAAO,GAAG,EAAE;AAE7C,QAAM,MAAM,UAAU,UAAU,QAAQ,WAAW,KAAK,IAAI,CAAC;AAC7D,SAAO,EAAE,KAAK,OAAO;AACtB;AAUO,SAAS,qBACf,YACA,IACA,WACA,SACW;AACX,MAAI,YAAY,QAAW;AAC1B,WAAO;AAAA,MACN,KAAK,UAAU,UAAU;AAAA,MACzB,QAAQ,CAAC,WAAW,SAAS,EAAE;AAAA,IAChC;AAAA,EACD;AACA,SAAO;AAAA,IACN,KAAK,UAAU,UAAU;AAAA,IACzB,QAAQ,CAAC,WAAW,EAAE;AAAA,EACvB;AACD;AAMO,SAAS,oBACf,YACA,IACA,SACA,eACW;AACX,QAAM,aAAa,OAAO,KAAK,OAAO,EAAE,IAAI,CAAC,QAAQ,GAAG,GAAG,MAAM;AACjE,QAAM,MAAM,sBAAsB,aAAa;AAC/C,QAAM,MAAM,UAAU,UAAU,QAAQ,WAAW,KAAK,IAAI,CAAC,qBAAqB,IAAI,GAAG;AACzF,QAAM,SAAS,CAAC,GAAG,OAAO,OAAO,OAAO,GAAG,IAAI,GAAG,IAAI,MAAM;AAC5D,SAAO,EAAE,KAAK,OAAO;AACtB;AAKO,SAAS,wBACf,YACA,IACA,WACA,SACW;AACX,QAAM,MAAM,sBAAsB,OAAO;AACzC,SAAO;AAAA,IACN,KAAK,UAAU,UAAU,qEAAqE,IAAI,GAAG;AAAA,IACrG,QAAQ,CAAC,WAAW,SAAS,IAAI,GAAG,IAAI,MAAM;AAAA,EAC/C;AACD;AAqBA,IAAM,kBAAkB,oBAAI,IAAI,CAAC,OAAO,OAAO,OAAO,QAAQ,OAAO,QAAQ,KAAK,CAAC;AAEnF,SAAS,sBACR,OACA,QACA,QACgB;AAChB,QAAM,aAAuB,CAAC;AAE9B,aAAW,CAAC,WAAW,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AACvD,sBAAkB,WAAW,MAAM;AACnC,UAAM,aAAa,OAAO,SAAS;AAEnC,QAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAG;AAEzE,YAAM,MAAM;AACZ,iBAAW,CAAC,IAAI,OAAO,KAAK,OAAO,QAAQ,GAAG,GAAG;AAChD,YAAI,CAAC,gBAAgB,IAAI,EAAE,GAAG;AAC7B,gBAAM,IAAI,WAAW,qBAAqB,EAAE,eAAe,SAAS,KAAK;AAAA,YACxE,OAAO;AAAA,YACP,UAAU;AAAA,YACV,gBAAgB,CAAC,GAAG,eAAe;AAAA,UACpC,CAAC;AAAA,QACF;AACA,mBAAW,KAAK,uBAAuB,WAAW,IAAI,SAAS,YAAY,MAAM,CAAC;AAAA,MACnF;AAAA,IACD,OAAO;AAEN,iBAAW,KAAK,uBAAuB,WAAW,OAAO,OAAO,YAAY,MAAM,CAAC;AAAA,IACpF;AAAA,EACD;AAEA,MAAI,WAAW,WAAW,EAAG,QAAO;AACpC,SAAO,WAAW,KAAK,OAAO;AAC/B;AAEA,SAAS,uBACR,WACA,UACA,OACA,YACA,QACS;AAET,QAAM,WACL,YAAY,SAAS,aAAa,OAAO,UAAU,YAAa,QAAQ,IAAI,IAAK;AAElF,UAAQ,UAAU;AAAA,IACjB,KAAK;AACJ,UAAI,aAAa,MAAM;AACtB,eAAO,GAAG,SAAS;AAAA,MACpB;AACA,aAAO,KAAK,QAAQ;AACpB,aAAO,GAAG,SAAS;AAAA,IACpB,KAAK;AACJ,UAAI,aAAa,MAAM;AACtB,eAAO,GAAG,SAAS;AAAA,MACpB;AACA,aAAO,KAAK,QAAQ;AACpB,aAAO,GAAG,SAAS;AAAA,IACpB,KAAK;AACJ,aAAO,KAAK,QAAQ;AACpB,aAAO,GAAG,SAAS;AAAA,IACpB,KAAK;AACJ,aAAO,KAAK,QAAQ;AACpB,aAAO,GAAG,SAAS;AAAA,IACpB,KAAK;AACJ,aAAO,KAAK,QAAQ;AACpB,aAAO,GAAG,SAAS;AAAA,IACpB,KAAK;AACJ,aAAO,KAAK,QAAQ;AACpB,aAAO,GAAG,SAAS;AAAA,IACpB,KAAK,OAAO;AACX,UAAI,CAAC,MAAM,QAAQ,QAAQ,GAAG;AAC7B,cAAM,IAAI,WAAW,mDAAmD,SAAS,KAAK;AAAA,UACrF,OAAO;AAAA,UACP,UAAU,OAAO;AAAA,QAClB,CAAC;AAAA,MACF;AACA,YAAM,eAAe,SAAS,IAAI,MAAM,GAAG;AAC3C,iBAAW,QAAQ,UAAU;AAC5B,eAAO;AAAA,UACN,YAAY,SAAS,aAAa,OAAO,SAAS,YAAa,OAAO,IAAI,IAAK;AAAA,QAChF;AAAA,MACD;AACA,aAAO,GAAG,SAAS,QAAQ,aAAa,KAAK,IAAI,CAAC;AAAA,IACnD;AAAA,IACA;AACC,YAAM,IAAI,WAAW,qBAAqB,QAAQ,KAAK,EAAE,SAAS,CAAC;AAAA,EACrE;AACD;AAEA,SAAS,kBAAkB,WAAmB,QAA+C;AAE5F,QAAM,gBAAgB,oBAAI,IAAI;AAAA,IAC7B,GAAG,OAAO,KAAK,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC;AACD,MAAI,CAAC,cAAc,IAAI,SAAS,GAAG;AAClC,UAAM,IAAI;AAAA,MACT,kBAAkB,SAAS,iCAAiC,CAAC,GAAG,aAAa,EAAE,KAAK,IAAI,CAAC;AAAA,MACzF,EAAE,OAAO,UAAU;AAAA,IACpB;AAAA,EACD;AACD;;;AF3SA;;;AGKA,eAAsB,2BACrB,SACA,QACkB;AAClB,QAAM,OAAO,MAAM,QAAQ;AAAA,IAC1B;AAAA;AAAA;AAAA,IAGA,CAAC,MAAM;AAAA,EACR;AACA,QAAM,MAAM,KAAK,CAAC,GAAG;AACrB,MAAI,QAAQ,QAAW;AACtB,UAAM,IAAI,MAAM,gDAAgD,MAAM,GAAG;AAAA,EAC1E;AACA,SAAO;AACR;AAKA,eAAsB,kCACrB,IACA,QACkB;AAClB,QAAM,OAAO,MAAM,GAAG;AAAA,IACrB;AAAA;AAAA;AAAA,IAGA,CAAC,MAAM;AAAA,EACR;AACA,QAAM,MAAM,KAAK,CAAC,GAAG;AACrB,MAAI,QAAQ,QAAW;AACtB,UAAM,IAAI,MAAM,gDAAgD,MAAM,kBAAkB;AAAA,EACzF;AACA,SAAO;AACR;AAKA,eAAsB,mBAAmB,SAAyB,QAAiC;AAClG,QAAM,OAAO,MAAM,QAAQ;AAAA,IAC1B;AAAA,IACA,CAAC,MAAM;AAAA,EACR;AACA,SAAO,KAAK,CAAC,GAAG,mBAAmB;AACpC;;;ACnDO,SAAS,kBAAkB,KAAqC;AACtE,QAAM,SAAmB,CAAC;AAC1B,aAAW,MAAM,IAAI,mBAAmB,CAAC,GAAG;AAC3C,QAAI,CAAC,OAAO,SAAS,EAAE,GAAG;AACzB,aAAO,KAAK,EAAE;AAAA,IACf;AAAA,EACD;AACA,aAAW,MAAM,IAAI,eAAe,eAAe,IAAI,YAAY,IAAI,aAAa,KAAK,CAAC,GAAG;AAC5F,QAAI,CAAC,OAAO,SAAS,EAAE,GAAG;AACzB,aAAO,KAAK,EAAE;AAAA,IACf;AAAA,EACD;AACA,SAAO;AACR;;;AJIA,eAAsB,cACrB,KACA,IACA,SACuB;AACvB,QAAM,cAAc,MAAM,IAAI,QAAQ;AAAA,IACrC,iBAAiB,IAAI,UAAU;AAAA,IAC/B,CAAC,EAAE;AAAA,EACJ;AACA,MAAI,CAAC,YAAY,CAAC,GAAG;AACpB,UAAM,IAAI,oBAAoB,IAAI,YAAY,EAAE;AAAA,EACjD;AAEA,QAAM,aAAa,kBAAkB,GAAG;AACxC,MAAI,YAAY,SAAS;AACzB,QAAM,cAA2B,CAAC;AAElC,QAAM,IAAI,QAAQ,YAAY,OAAO,OAAO;AAC3C,QAAI,CAAC,WAAW;AACf,YAAM,iBAAiB,MAAM,kCAAkC,IAAI,IAAI,MAAM;AAC7E,kBAAY,UAAM;AAAA,QACjB;AAAA,UACC,QAAQ,IAAI;AAAA,UACZ,MAAM;AAAA,UACN,YAAY,IAAI;AAAA,UAChB,UAAU;AAAA,UACV,MAAM;AAAA,UACN,cAAc;AAAA,UACd;AAAA,UACA;AAAA,UACA,eAAe,IAAI,OAAO;AAAA,QAC3B;AAAA,QACA,IAAI;AAAA,MACL;AACA,UAAI,eAAe,eAAe,IAAI,YAAY,UAAU,IAAI,IAAI,aAAa;AAAA,IAClF;AAEA,QAAI,IAAI,oBAAoB,CAAC,SAAS,4BAA4B;AACjE,YAAM,oBAAoB,MAAM,IAAI,iBAAiB,cAAc,IAAI,YAAY,IAAI,IAAI;AAAA,QAC1F,UAAU;AAAA,MACX,CAAC;AACD,kBAAY,KAAK,GAAG,kBAAkB,UAAU;AAAA,IACjD;AAEA,UAAM,UAAU,oBAAoB,UAAU,SAAS;AACvD,UAAM,cAAc;AAAA,MACnB,IAAI;AAAA,MACJ;AAAA,MACA,UAAU,UAAU;AAAA,MACpB;AAAA,IACD;AACA,UAAM,WAAW;AAAA,MAChB,aAAa,IAAI,UAAU;AAAA,MAC3B,mBAAmB,SAAS;AAAA,IAC7B;AAEA,UAAM,GAAG,QAAQ,YAAY,KAAK,YAAY,MAAM;AACpD,UAAM,GAAG,QAAQ,SAAS,KAAK,SAAS,MAAM;AAAA,EAC/C,CAAC;AAED,MAAI,CAAC,WAAW;AACf,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACnD;AAEA,MAAI,WAAW,IAAI,YAAY,SAAS;AACxC,aAAW,cAAc,aAAa;AACrC,QAAI,WAAW,WAAW,YAAY,UAAU;AAAA,EACjD;AAEA,SAAO,CAAC,WAAW,GAAG,WAAW;AAClC;;;AK5FA,IAAAC,eAAgE;AAGhE;AASA,eAAsB,cACrB,KACA,MAC4B;AAC5B,QAAM,gBAAY,6BAAe,IAAI,YAAY,IAAI,YAAY,MAAM,QAAQ;AAC/E,QAAM,eAAW,6BAAe;AAEhC,aAAW,CAAC,WAAW,UAAU,KAAK,OAAO,QAAQ,IAAI,WAAW,MAAM,GAAG;AAC5E,QAAI,WAAW,QAAQ,WAAW,SAAS,aAAa;AACvD,gBAAU,SAAS,IAAI,KAAK,IAAI;AAAA,IACjC;AAAA,EACD;AAEA,QAAM,aAAa,kBAAkB,GAAG;AAExC,MAAI;AACJ,MAAI;AAEJ,QAAM,IAAI,QAAQ,YAAY,OAAO,OAAO;AAC3C,UAAM,iBAAiB,MAAM,kCAAkC,IAAI,IAAI,MAAM;AAC7E,gBAAY,UAAM;AAAA,MACjB;AAAA,QACC,QAAQ,IAAI;AAAA,QACZ,MAAM;AAAA,QACN,YAAY,IAAI;AAAA,QAChB;AAAA,QACA,MAAM,EAAE,GAAG,UAAU;AAAA,QACrB,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA,eAAe,IAAI,OAAO;AAAA,MAC3B;AAAA,MACA,IAAI;AAAA,IACL;AACA,QAAI,eAAe,eAAe,IAAI,YAAY,UAAU,IAAI,IAAI,aAAa;AAEjF,UAAM,iBAAiB,gBAAgB,WAAW,IAAI,WAAW,MAAM;AACvE,UAAM,UAAU,oBAAoB,UAAU,SAAS;AACvD,aAAS;AAAA,MACR,IAAI;AAAA,MACJ,GAAG;AAAA,MACH,aAAa,UAAU,UAAU;AAAA,MACjC,aAAa,UAAU,UAAU;AAAA,MACjC,UAAU;AAAA,IACX;AAEA,UAAM,cAAc,iBAAiB,IAAI,YAAY,MAAM;AAC3D,UAAM,WAAW;AAAA,MAChB,aAAa,IAAI,UAAU;AAAA,MAC3B,mBAAmB,SAAS;AAAA,IAC7B;AAEA,UAAM,GAAG,QAAQ,YAAY,KAAK,YAAY,MAAM;AACpD,UAAM,GAAG,QAAQ,SAAS,KAAK,SAAS,MAAM;AAAA,EAC/C,CAAC;AAED,MAAI,WAAW,IAAI,YAAY,SAAS;AAExC,SAAO;AAAA,IACN,IAAI;AAAA,IACJ,GAAG;AAAA,IACH,WAAW,UAAU,UAAU;AAAA,IAC/B,WAAW,UAAU,UAAU;AAAA,EAChC;AACD;;;AC3EA,IAAAC,gBAMO;AAIP;;;ACXA,IAAAC,eAA8C;AAavC,IAAM,8BAAN,cAA0C,uBAAU;AAAA,EAC1D,YACiB,YACA,UACA,OACA,WACA,SACA,eACf;AACD;AAAA,MACC,2CAA2C,UAAU,+BACxB,KAAK,WAAW,SAAS,SAAS,OAAO,gCACxC,SAAS,MAAM,cAAc,SAAS,IAAI,cAAc,KAAK,IAAI,IAAI,0BAA0B;AAAA,MAC7H;AAAA,MACA,EAAE,YAAY,UAAU,OAAO,WAAW,SAAS,cAAc;AAAA,IAClE;AAbgB;AACA;AACA;AACA;AACA;AACA;AAShB,SAAK,OAAO;AAAA,EACb;AAAA,EAfiB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAWlB;AAoBO,SAAS,wBACf,gBACA,UACA,cACA,cACA,UAC8C;AAG9C,MAAI,iBAAiB,MAAM;AAC1B,WAAO,EAAE,OAAO,MAAM,eAAe,CAAC,EAAE;AAAA,EACzC;AAGA,MAAI,iBAAiB,UAAU;AAC9B,WAAO,EAAE,OAAO,MAAM,eAAe,aAAa,YAAY,YAAY,KAAK,CAAC,EAAE;AAAA,EACnF;AAEA,QAAM,aAAqC;AAAA,IAC1C,OAAO,aAAa;AAAA,IACpB,YAAY;AAAA,IACZ,aAAa,aAAa;AAAA,EAC3B;AACA,QAAM,uBAAmB,iCAAmB,YAAY,cAAc,QAAQ;AAC9E,MAAI,iBAAiB,OAAO;AAC3B,WAAO,EAAE,OAAO,MAAM,eAAe,iBAAiB,eAAe;AAAA,EACtE;AAEA,QAAM,gBAAgB,iBAAiB;AAEvC,MAAI,aAAa,wBAAwB,UAAU;AAClD,UAAM,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA,aAAa;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAGA,SAAO,EAAE,OAAO,OAAO,cAAc;AACtC;AAiBO,SAAS,2BACf,gBACA,UACA,eACA,eACA,YAC0B;AAC1B,QAAM,eAAe,cAAc;AACnC,MAAI,iBAAiB,QAAW;AAC/B,WAAO;AAAA,EACR;AAEA,QAAM,aAAa,aAAa;AAChC,MAAI,EAAE,cAAc,aAAa;AAEhC,WAAO;AAAA,EACR;AAEA,QAAM,eAAe,cAAc,UAAU;AAC7C,QAAM,WAAW,WAAW,UAAU;AAGtC,MAAI,OAAO,iBAAiB,YAAY,OAAO,aAAa,UAAU;AACrE,WAAO;AAAA,EACR;AAEA,QAAM,SAAS;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAEA,MAAI,OAAO,OAAO;AACjB,WAAO;AAAA,EACR;AAGA,QAAM,WAAW,EAAE,GAAG,WAAW;AACjC,SAAO,SAAS,UAAU;AAI1B,SAAO;AACR;;;ADvIA,eAAsB,cACrB,KACA,IACA,MAC4B;AAC5B,QAAM,cAAc,MAAM,IAAI,QAAQ;AAAA,IACrC,iBAAiB,IAAI,UAAU;AAAA,IAC/B,CAAC,EAAE;AAAA,EACJ;AACA,QAAM,aAAa,YAAY,CAAC;AAChC,MAAI,CAAC,YAAY;AAChB,UAAM,IAAI,oBAAoB,IAAI,YAAY,EAAE;AAAA,EACjD;AAEA,MAAI,gBAAY,8BAAe,IAAI,YAAY,IAAI,YAAY,MAAM,QAAQ;AAC7E,QAAM,gBAAgB,kBAAkB,YAAY,IAAI,WAAW,MAAM;AACzE,cAAY;AAAA,IACX,IAAI;AAAA,IACJ;AAAA,IACA,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,EACD;AAEA,MAAI,OAAO,KAAK,SAAS,EAAE,WAAW,GAAG;AACxC,WAAO,EAAE,GAAG,cAAc;AAAA,EAC3B;AAEA,QAAM,eAAwC,CAAC;AAC/C,QAAM,eAAwC,CAAC;AAC/C,QAAM,YAAsC,CAAC;AAE7C,aAAW,OAAO,OAAO,KAAK,SAAS,GAAG;AACzC,UAAM,QAAQ,UAAU,GAAG;AAC3B,iBAAa,GAAG,IAAI,cAAc,GAAG;AAErC,YAAI,0BAAW,KAAK,GAAG;AACtB,mBAAa,GAAG,QAAI,+BAAgB,cAAc,GAAG,GAAG,KAAK;AAC7D,gBAAU,GAAG,QAAI,0BAAW,KAAK;AAAA,IAClC,OAAO;AACN,mBAAa,GAAG,IAAI;AAAA,IACrB;AAAA,EACD;AAEA,QAAM,eAAe,OAAO,KAAK,SAAS,EAAE,SAAS;AACrD,QAAM,aAAa,kBAAkB,GAAG;AACxC,MAAI;AAEJ,QAAM,IAAI,QAAQ,YAAY,OAAO,OAAO;AAC3C,UAAM,iBAAiB,MAAM,kCAAkC,IAAI,IAAI,MAAM;AAC7E,gBAAY,UAAM;AAAA,MACjB;AAAA,QACC,QAAQ,IAAI;AAAA,QACZ,MAAM;AAAA,QACN,YAAY,IAAI;AAAA,QAChB,UAAU;AAAA,QACV,MAAM,EAAE,GAAG,aAAa;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,IAAI,OAAO;AAAA,QAC1B,GAAI,eAAe,EAAE,UAAU,IAAI,CAAC;AAAA,MACrC;AAAA,MACA,IAAI;AAAA,IACL;AACA,QAAI,eAAe,eAAe,IAAI,YAAY,UAAU,IAAI,IAAI,aAAa;AAEjF,UAAM,oBAAoB,gBAAgB,cAAc,IAAI,WAAW,MAAM;AAC7E,UAAM,UAAU,oBAAoB,UAAU,SAAS;AACvD,UAAM,cAAc,iBAAiB,IAAI,YAAY,IAAI;AAAA,MACxD,GAAG;AAAA,MACH,aAAa,UAAU,UAAU;AAAA,MACjC,UAAU;AAAA,IACX,CAAC;AACD,UAAM,WAAW;AAAA,MAChB,aAAa,IAAI,UAAU;AAAA,MAC3B,mBAAmB,SAAS;AAAA,IAC7B;AAEA,UAAM,GAAG,QAAQ,YAAY,KAAK,YAAY,MAAM;AACpD,UAAM,GAAG,QAAQ,SAAS,KAAK,SAAS,MAAM;AAAA,EAC/C,CAAC;AAED,MAAI,WAAW,IAAI,YAAY,SAAS;AAExC,QAAM,OAAO,MAAM,IAAI,QAAQ;AAAA,IAC9B,iBAAiB,IAAI,UAAU;AAAA,IAC/B,CAAC,EAAE;AAAA,EACJ;AACA,QAAM,MAAM,KAAK,CAAC;AAClB,MAAI,CAAC,KAAK;AACT,UAAM,IAAI,oBAAoB,IAAI,YAAY,EAAE;AAAA,EACjD;AACA,SAAO,kBAAkB,KAAK,IAAI,WAAW,MAAM;AACpD;;;AEvGA;AAkBO,IAAM,aAAN,MAAiB;AAAA,EACvB,YACkB,MACA,YACA,QACA,SACA,OACA,QACA,wBACA,YACA,kBACT,iBACS,eAChB;AAXgB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACT;AACS;AAAA,EACf;AAAA,EAXe;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EACS;AAAA,EAGV,kBAAwC;AAC/C,WAAO;AAAA,MACN,YAAY,KAAK;AAAA,MACjB,YAAY,KAAK;AAAA,MACjB,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,wBAAwB,KAAK;AAAA,MAC7B,YAAY,KAAK;AAAA,MACjB,kBAAkB,KAAK;AAAA,MACvB,eAAe,KAAK;AAAA,MACpB,eAAe;AAAA,IAChB;AAAA,EACD;AAAA,EAEA,MAAM,OAAO,MAA0D;AACtE,QAAI,KAAK,iBAAiB;AACzB,aAAO,KAAK,gBAAgB,OAAO,KAAK,MAAM,IAAI;AAAA,IACnD;AACA,WAAO,cAAc,KAAK,gBAAgB,GAAG,IAAI;AAAA,EAClD;AAAA,EAEA,MAAM,SAAS,IAA8C;AAC5D,UAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,MAC/B,iBAAiB,KAAK,IAAI;AAAA,MAC1B,CAAC,EAAE;AAAA,IACJ;AACA,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,CAAC,IAAK,QAAO;AACjB,WAAO,kBAAkB,KAAK,KAAK,WAAW,MAAM;AAAA,EACrD;AAAA,EAEA,MAAM,OAAO,IAAY,MAA0D;AAClF,QAAI,KAAK,iBAAiB;AACzB,aAAO,KAAK,gBAAgB,OAAO,KAAK,MAAM,IAAI,IAAI;AAAA,IACvD;AACA,WAAO,cAAc,KAAK,gBAAgB,GAAG,IAAI,IAAI;AAAA,EACtD;AAAA,EAEA,MAAM,OAAO,IAA2B;AACvC,QAAI,KAAK,iBAAiB;AACzB,YAAM,KAAK,gBAAgB,OAAO,KAAK,MAAM,EAAE;AAC/C;AAAA,IACD;AACA,UAAM,cAAc,KAAK,gBAAgB,GAAG,EAAE;AAAA,EAC/C;AAAA,EAEA,UAAkB;AACjB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,gBAAsC;AACrC,WAAO,KAAK;AAAA,EACb;AAAA;AAAA,EAGA,mBAAmB,SAA4C;AAC9D,SAAK,kBAAkB;AAAA,EACxB;AACD;;;ACxGA;;;ACIA,SAAS,QAAQ,MAAmC;AACnD,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,aAAa,SAAS,IAAI;AAClC;AAYO,SAAS,UAAU,MAAsB;AAC/C,MAAI,KAAK,SAAS,GAAG,EAAG,QAAO;AAC/B,MAAI,KAAK,SAAS,GAAG,KAAK,CAAC,QAAQ,KAAK,KAAK,SAAS,CAAC,CAAC,GAAG;AAC1D,WAAO,GAAG,KAAK,MAAM,GAAG,EAAE,CAAC;AAAA,EAC5B;AACA,MAAI,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,GAAG,KAAK,KAAK,SAAS,GAAG,GAAG;AAC3F,WAAO,GAAG,IAAI;AAAA,EACf;AACA,SAAO,GAAG,IAAI;AACf;AAYO,SAAS,YAAY,MAAsB;AACjD,MAAI,KAAK,SAAS,KAAK,KAAK,CAAC,QAAQ,KAAK,KAAK,SAAS,CAAC,CAAC,GAAG;AAC5D,WAAO,GAAG,KAAK,MAAM,GAAG,EAAE,CAAC;AAAA,EAC5B;AACA,MACC,KAAK,SAAS,MAAM,KACpB,KAAK,SAAS,MAAM,KACpB,KAAK,SAAS,KAAK,KACnB,KAAK,SAAS,KAAK,GAClB;AACD,WAAO,KAAK,MAAM,GAAG,EAAE;AAAA,EACxB;AACA,MAAI,KAAK,SAAS,KAAK,GAAG;AACzB,WAAO,KAAK,MAAM,GAAG,EAAE;AAAA,EACxB;AACA,MAAI,KAAK,SAAS,GAAG,KAAK,CAAC,KAAK,SAAS,IAAI,GAAG;AAC/C,WAAO,KAAK,MAAM,GAAG,EAAE;AAAA,EACxB;AACA,SAAO;AACR;;;AD7BO,IAAM,eAAN,MAAM,cAAmC;AAAA,EAG/C,YACkB,gBACA,YACA,SACA,qBACjB,eAA4B,CAAC,GACZ,QAChB;AANgB;AACA;AACA;AACA;AAEA;AAEjB,SAAK,aAAa;AAAA,MACjB,YAAY;AAAA,MACZ,OAAO,EAAE,GAAG,aAAa;AAAA,MACzB,SAAS,CAAC;AAAA,IACX;AAAA,EACD;AAAA,EAZkB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EARV;AAAA;AAAA;AAAA;AAAA,EAoBR,MAAM,YAA0C;AAC/C,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,aAAa;AAAA,MAClB,GAAG,MAAM;AAAA,MACT,OAAO,EAAE,GAAG,MAAM,WAAW,OAAO,GAAG,WAAW;AAAA,IACnD;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,OAAe,YAA8B,OAAwB;AAC5E,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,aAAa;AAAA,MAClB,GAAG,MAAM;AAAA,MACT,SAAS,CAAC,GAAG,MAAM,WAAW,SAAS,EAAE,OAAO,UAAU,CAAC;AAAA,IAC5D;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,GAA4B;AACjC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,aAAa,EAAE,GAAG,MAAM,YAAY,OAAO,EAAE;AACnD,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,GAA4B;AAClC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,aAAa,EAAE,GAAG,MAAM,YAAY,QAAQ,EAAE;AACpD,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,WAAW,SAAoC;AAC9C,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,WAAW,MAAM,WAAW,WAAW,CAAC;AAC9C,UAAM,aAAa;AAAA,MAClB,GAAG,MAAM;AAAA,MACT,SAAS,CAAC,GAAG,UAAU,GAAG,OAAO;AAAA,IAClC;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAqB;AAC1B,UAAM,EAAE,KAAK,OAAO,IAAI,iBAAiB,KAAK,YAAY,KAAK,WAAW,MAAM;AAChF,UAAM,OAAO,MAAM,KAAK,QAAQ,MAAwB,KAAK,MAAM;AACnE,UAAM,UAAU,KAAK,IAAI,CAAC,QAAQ,kBAAkB,KAAK,KAAK,WAAW,MAAM,CAAC;AAGhF,QAAI,KAAK,WAAW,WAAW,KAAK,WAAW,QAAQ,SAAS,KAAK,KAAK,QAAQ;AACjF,YAAM,KAAK,gBAAgB,OAAO;AAAA,IACnC;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAyB;AAC9B,UAAM,EAAE,KAAK,OAAO,IAAI,gBAAgB,KAAK,YAAY,KAAK,WAAW,MAAM;AAC/E,UAAM,OAAO,MAAM,KAAK,QAAQ,MAAyB,KAAK,MAAM;AACpE,WAAO,KAAK,CAAC,GAAG,SAAS;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAU,UAA+C;AACxD,UAAM,YAAY,MAAM,KAAK,KAAK;AAGlC,UAAM,iBAAiB,EAAE,GAAG,KAAK,WAAW;AAC5C,QAAI,eAAe,WAAW,eAAe,QAAQ,SAAS,KAAK,KAAK,QAAQ;AAC/E,qBAAe,qBAAqB,KAAK,0BAA0B,eAAe,OAAO;AAAA,IAC1F;AAIA,WAAO,KAAK,oBAAoB;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAAA;AAAA,EAGA,gBAAiC;AAChC,WAAO,EAAE,GAAG,KAAK,WAAW;AAAA,EAC7B;AAAA,EAEQ,QAAyB;AAChC,UAAM,KAAK,IAAI;AAAA,MACd,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,CAAC;AAAA,MACD,KAAK;AAAA,IACN;AACA,OAAG,aAAa;AAAA,MACf,GAAG,KAAK;AAAA,MACR,OAAO,EAAE,GAAG,KAAK,WAAW,MAAM;AAAA,MAClC,SAAS,CAAC,GAAG,KAAK,WAAW,OAAO;AAAA,MACpC,SAAS,KAAK,WAAW,UAAU,CAAC,GAAG,KAAK,WAAW,OAAO,IAAI;AAAA,MAClE,oBAAoB,KAAK,WAAW,qBACjC,CAAC,GAAG,KAAK,WAAW,kBAAkB,IACtC;AAAA,IACJ;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKQ,0BAA0B,SAA6B;AAC9D,QAAI,CAAC,KAAK,OAAQ,QAAO,CAAC;AAC1B,UAAM,cAAwB,CAAC;AAE/B,eAAW,UAAU,SAAS;AAC7B,YAAM,WAAW,KAAK,aAAa,MAAM;AACzC,UAAI,UAAU;AAGb,YAAI,SAAS,SAAS,KAAK,gBAAgB;AAC1C,sBAAY,KAAK,SAAS,EAAE;AAAA,QAC7B,OAAO;AACN,sBAAY,KAAK,SAAS,IAAI;AAAA,QAC/B;AAAA,MACD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,gBAAgB,SAA4C;AACzE,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,WAAW,WAAW,QAAQ,WAAW,EAAG;AAEtE,eAAW,UAAU,KAAK,WAAW,SAAS;AAC7C,YAAM,WAAW,KAAK,aAAa,MAAM;AACzC,UAAI,CAAC,UAAU;AACd,cAAM,IAAIC;AAAA,UACT,yCAAyC,MAAM,oBAAoB,KAAK,cAAc,qEACnB,KAAK,cAAc,SAAS,MAAM;AAAA,QACtG;AAAA,MACD;AAEA,UAAI,SAAS,SAAS,KAAK,gBAAgB;AAE1C,cAAM,KAAK,wBAAwB,SAAS,UAAU,MAAM;AAAA,MAC7D,OAAO;AAEN,cAAM,KAAK,wBAAwB,SAAS,UAAU,MAAM;AAAA,MAC7D;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,wBACb,SACA,UACA,QACgB;AAChB,UAAM,UAAU,SAAS;AACzB,UAAM,WAAW,QACf,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EACrB,OAAO,CAAC,MAAmB,MAAM,QAAQ,MAAM,UAAa,OAAO,MAAM,QAAQ;AAEnF,QAAI,SAAS,WAAW,GAAG;AAE1B,YAAMC,YAAW,YAAY,MAAM;AACnC,iBAAW,UAAU,SAAS;AAC7B;AAAC,QAAC,OAAmCA,SAAQ,IAAI;AAAA,MAClD;AACA;AAAA,IACD;AAEA,UAAM,YAAY,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC;AACvC,UAAM,oBAAoB,SAAS;AACnC,UAAM,aAAa,KAAK,QAAQ,YAAY,iBAAiB;AAC7D,QAAI,CAAC,WAAY;AAGjB,UAAM,eAAe,UAAU,IAAI,MAAM,GAAG,EAAE,KAAK,IAAI;AACvD,UAAM,MAAM,iBAAiB,iBAAiB,iBAAiB,YAAY;AAC3E,UAAM,OAAO,MAAM,KAAK,QAAQ,MAAwB,KAAK,SAAS;AACtE,UAAM,iBAAiB,KAAK,IAAI,CAAC,QAAQ,kBAAkB,KAAK,WAAW,MAAM,CAAC;AAGlF,UAAM,SAAS,oBAAI,IAA8B;AACjD,eAAW,KAAK,gBAAgB;AAC/B,aAAO,IAAI,EAAE,IAAI,CAAC;AAAA,IACnB;AAGA,UAAM,WAAW,YAAY,MAAM;AACnC,eAAW,UAAU,SAAS;AAC7B,YAAM,KAAK,OAAO,OAAO;AACxB,MAAC,OAAmC,QAAQ,IAAI,KAAM,OAAO,IAAI,EAAE,KAAK,OAAQ;AAAA,IAClF;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,wBACb,SACA,UACA,QACgB;AAChB,UAAM,aAAa,QAAQ,IAAI,CAAC,MAAM,EAAE,EAAE;AAC1C,UAAM,oBAAoB,SAAS;AACnC,UAAM,aAAa,KAAK,QAAQ,YAAY,iBAAiB;AAC7D,QAAI,CAAC,WAAY;AAEjB,UAAM,UAAU,SAAS;AACzB,UAAM,eAAe,WAAW,IAAI,MAAM,GAAG,EAAE,KAAK,IAAI;AACxD,UAAM,MAAM,iBAAiB,iBAAiB,UAAU,OAAO,QAAQ,YAAY;AACnF,UAAM,OAAO,MAAM,KAAK,QAAQ,MAAwB,KAAK,UAAU;AACvE,UAAM,iBAAiB,KAAK,IAAI,CAAC,QAAQ,kBAAkB,KAAK,WAAW,MAAM,CAAC;AAGlF,UAAM,UAAU,oBAAI,IAAgC;AACpD,eAAW,KAAK,gBAAgB;AAC/B,YAAM,KAAK,EAAE,OAAO;AACpB,UAAI,CAAC,QAAQ,IAAI,EAAE,GAAG;AACrB,gBAAQ,IAAI,IAAI,CAAC,CAAC;AAAA,MACnB;AACA,cAAQ,IAAI,EAAE,GAAG,KAAK,CAAC;AAAA,IACxB;AAGA,UAAM,WAAW,UAAU,MAAM;AACjC,eAAW,UAAU,SAAS;AAC7B;AAAC,MAAC,OAAmC,QAAQ,IAAI,QAAQ,IAAI,OAAO,EAAE,KAAK,CAAC;AAAA,IAC7E;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,aACP,QACmE;AACnE,QAAI,CAAC,KAAK,OAAQ,QAAO;AAEzB,eAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,KAAK,OAAO,SAAS,GAAG;AAEjE,UAAI,IAAI,SAAS,KAAK,kBAAkB,IAAI,OAAO,OAAQ,QAAO;AAClE,UAAI,IAAI,OAAO,KAAK,kBAAkB,IAAI,SAAS,OAAQ,QAAO;AAGlE,UAAI,IAAI,SAAS,KAAK,kBAAkB,IAAI,OAAO,UAAU,MAAM,EAAG,QAAO;AAC7E,UAAI,IAAI,OAAO,KAAK,kBAAkB,IAAI,SAAS,UAAU,MAAM,EAAG,QAAO;AAG7E,UAAI,IAAI,SAAS,KAAK,kBAAkB,IAAI,OAAO,YAAY,MAAM,EAAG,QAAO;AAC/E,UAAI,IAAI,OAAO,KAAK,kBAAkB,IAAI,SAAS,YAAY,MAAM,EAAG,QAAO;AAAA,IAChF;AAEA,WAAO;AAAA,EACR;AACD;AAKA,IAAMD,cAAN,cAAyB,MAAM;AAAA,EAC9B,YAAY,SAAiB;AAC5B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACb;AACD;;;AEpWA,IAAAE,gBAA2C;AAE3C;;;ACmCO,SAAS,oBAAoB,QAA2D;AAC9F,QAAM,SAAS,oBAAI,IAAgC;AAEnD,aAAW,CAAC,cAAc,QAAQ,KAAK,OAAO,QAAQ,OAAO,SAAS,GAAG;AACxE,UAAM,mBAAmB,SAAS;AAClC,UAAM,WAAW,OAAO,IAAI,gBAAgB,KAAK,CAAC;AAClD,aAAS,KAAK;AAAA,MACb;AAAA,MACA,kBAAkB,SAAS;AAAA,MAC3B,iBAAiB,SAAS;AAAA,MAC1B,UAAU,SAAS;AAAA,MACnB;AAAA,IACD,CAAC;AACD,WAAO,IAAI,kBAAkB,QAAQ;AAAA,EACtC;AAEA,SAAO;AACR;AAUO,SAAS,qBACf,QACA,YACqB;AACrB,SAAO,OAAO,IAAI,UAAU,KAAK,CAAC;AACnC;;;ADxDO,IAAM,4BAAN,cAAwC,wBAAU;AAAA,EACxD,YACC,YACA,UACA,uBACA,cACA,kBACC;AACD;AAAA,MACC,yBAAyB,QAAQ,WAAW,UAAU,MAAM,gBAAgB,kBAAkB,qBAAqB,gCAAgC,YAAY;AAAA,MAC/J;AAAA,MACA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD;AACA,SAAK,OAAO;AAAA,EACb;AACD;AAiDO,IAAM,mBAAN,MAAuB;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,QAAgC;AAC3C,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO;AACtB,SAAK,QAAQ,OAAO;AACpB,SAAK,SAAS,OAAO;AACrB,SAAK,SAAS,oBAAoB,OAAO,MAAM;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,cACL,YACA,UACA,IACA,YAC6B;AAC7B,UAAM,oBAAoB,qBAAqB,KAAK,QAAQ,UAAU;AACtE,QAAI,kBAAkB,WAAW,GAAG;AACnC,aAAO,EAAE,YAAY,CAAC,EAAE;AAAA,IACzB;AAEA,UAAM,gBAA6B,CAAC;AAIpC,UAAM,kBAAkB,CAAC,GAAG,iBAAiB,EAAE;AAAA,MAAK,CAAC,GAAG,MACvD,EAAE,aAAa,cAAc,EAAE,YAAY;AAAA,IAC5C;AAEA,eAAW,YAAY,iBAAiB;AACvC,YAAM,MAAM,MAAM,KAAK,gBAAgB,UAAU,UAAU,IAAI,UAAU;AACzE,oBAAc,KAAK,GAAG,GAAG;AAAA,IAC1B;AAEA,WAAO,EAAE,YAAY,cAAc;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,gBACb,UACA,iBACA,IACA,YACuB;AACvB,YAAQ,SAAS,UAAU;AAAA,MAC1B,KAAK;AACJ,eAAO,KAAK,eAAe,UAAU,iBAAiB,IAAI,UAAU;AAAA,MACrE,KAAK;AACJ,eAAO,KAAK,eAAe,UAAU,iBAAiB,IAAI,UAAU;AAAA,MACrE,KAAK;AACJ,eAAO,KAAK,gBAAgB,UAAU,iBAAiB,EAAE;AAAA,MAC1D,KAAK;AACJ,eAAO,CAAC;AAAA,IACV;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,eACb,UACA,iBACA,IACA,YACuB;AACvB,UAAM,EAAE,kBAAkB,gBAAgB,IAAI;AAG9C,UAAM,kBAAkB,MAAM,GAAG;AAAA,MAChC,kBAAkB,gBAAgB,UAAU,eAAe;AAAA,MAC3D,CAAC,eAAe;AAAA,IACjB;AAEA,QAAI,gBAAgB,WAAW,GAAG;AACjC,aAAO,CAAC;AAAA,IACT;AAEA,UAAM,aAA0B,CAAC;AAEjC,eAAW,OAAO,iBAAiB;AAClC,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,iBAAiB,MAAM,kCAAkC,IAAI,KAAK,MAAM;AAE9E,YAAM,YAAY,UAAM;AAAA,QACvB;AAAA,UACC,QAAQ,KAAK;AAAA,UACb,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,UAAU,IAAI;AAAA,UACd,MAAM;AAAA,UACN,cAAc;AAAA,UACd;AAAA,UACA,YAAY,CAAC,GAAG,UAAU;AAAA,UAC1B,eAAe,KAAK,OAAO;AAAA,QAC5B;AAAA,QACA,KAAK;AAAA,MACN;AAEA,YAAM,cAAc,qBAAqB,kBAAkB,IAAI,IAAI,GAAG;AACtE,YAAM,GAAG,QAAQ,YAAY,KAAK,YAAY,MAAM;AAEpD,YAAM,WAAW;AAAA,QAChB,aAAa,gBAAgB;AAAA,QAC7B,mBAAmB,SAAS;AAAA,MAC7B;AACA,YAAM,GAAG,QAAQ,SAAS,KAAK,SAAS,MAAM;AAE9C,iBAAW,KAAK,SAAS;AAGzB,YAAM,gBAAgB,MAAM,KAAK,cAAc,kBAAkB,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;AAC3F,iBAAW,KAAK,GAAG,cAAc,UAAU;AAAA,IAC5C;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,eACb,UACA,iBACA,IACA,YACuB;AACvB,UAAM,EAAE,kBAAkB,gBAAgB,IAAI;AAC9C,UAAM,gBAAgB,KAAK,OAAO,YAAY,gBAAgB;AAC9D,QAAI,CAAC,eAAe;AACnB,aAAO,CAAC;AAAA,IACT;AAGA,UAAM,kBAAkB,MAAM,GAAG;AAAA,MAChC,kBAAkB,gBAAgB,UAAU,eAAe;AAAA,MAC3D,CAAC,eAAe;AAAA,IACjB;AAEA,QAAI,gBAAgB,WAAW,GAAG;AACjC,aAAO,CAAC;AAAA,IACT;AAEA,UAAM,aAA0B,CAAC;AAEjC,eAAW,OAAO,iBAAiB;AAClC,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,iBAAiB,MAAM,kCAAkC,IAAI,KAAK,MAAM;AAE9E,YAAM,aAAsC,EAAE,CAAC,eAAe,GAAG,KAAK;AACtE,YAAM,eAAwC,EAAE,CAAC,eAAe,GAAG,gBAAgB;AAEnF,YAAM,YAAY,UAAM;AAAA,QACvB;AAAA,UACC,QAAQ,KAAK;AAAA,UACb,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,UAAU,IAAI;AAAA,UACd,MAAM,EAAE,GAAG,WAAW;AAAA,UACtB;AAAA,UACA;AAAA,UACA,YAAY,CAAC,GAAG,UAAU;AAAA,UAC1B,eAAe,KAAK,OAAO;AAAA,QAC5B;AAAA,QACA,KAAK;AAAA,MACN;AAGA,YAAM,oBAAoB,gBAAgB,YAAY,cAAc,MAAM;AAC1E,YAAM,cAAc,iBAAiB,kBAAkB,IAAI,IAAI;AAAA,QAC9D,GAAG;AAAA,QACH,aAAa;AAAA,MACd,CAAC;AACD,YAAM,GAAG,QAAQ,YAAY,KAAK,YAAY,MAAM;AAGpD,YAAM,QAAQ,mBAAmB,SAAS;AAC1C,YAAM,WAAW;AAAA,QAChB,aAAa,gBAAgB;AAAA,QAC7B;AAAA,MACD;AACA,YAAM,GAAG,QAAQ,SAAS,KAAK,SAAS,MAAM;AAE9C,iBAAW,KAAK,SAAS;AAAA,IAC1B;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,gBACb,UACA,iBACA,IACuB;AACvB,UAAM,EAAE,kBAAkB,iBAAiB,aAAa,IAAI;AAE5D,UAAM,YAAY,MAAM,GAAG;AAAA,MAC1B,+BAA+B,gBAAgB,UAAU,eAAe;AAAA,MACxE,CAAC,eAAe;AAAA,IACjB;AACA,UAAM,QAAQ,UAAU,CAAC,GAAG,OAAO;AAEnC,QAAI,QAAQ,GAAG;AAEd,YAAM,mBAAmB,SAAS,SAAS;AAC3C,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,WAAO,CAAC;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAqD;AACpD,WAAO,KAAK;AAAA,EACb;AACD;;;AE1UA,IAAAC,gBAA+B;AAE/B,sBAAgC;AA+BzB,SAAS,qBAAqB,QAAqB,mBAAwC;AACjG,QAAM,QAAQ,oBAAI,IAAuB;AACzC,aAAW,MAAM,QAAQ;AACxB,UAAM,IAAI,GAAG,IAAI,EAAE;AAAA,EACpB;AAEA,QAAM,SAAS,MAAM,IAAI,iBAAiB;AAC1C,MAAI,CAAC,QAAQ;AACZ,UAAM,IAAI;AAAA,MACT,cAAc,iBAAiB;AAAA,MAC/B;AAAA,QACC,aAAa;AAAA,MACd;AAAA,IACD;AAAA,EACD;AAEA,QAAM,WAAW,oBAAI,IAAY;AACjC,QAAM,QAAkB,CAAC,iBAAiB;AAE1C,SAAO,MAAM,SAAS,GAAG;AACxB,UAAM,KAAK,MAAM,IAAI;AACrB,QAAI,OAAO,UAAa,SAAS,IAAI,EAAE,GAAG;AACzC;AAAA,IACD;AACA,aAAS,IAAI,EAAE;AACf,UAAM,KAAK,MAAM,IAAI,EAAE;AACvB,QAAI,CAAC,IAAI;AACR;AAAA,IACD;AACA,eAAW,SAAS,GAAG,YAAY;AAClC,UAAI,MAAM,IAAI,KAAK,GAAG;AACrB,cAAM,KAAK,KAAK;AAAA,MACjB;AAAA,IACD;AAAA,EACD;AAEA,QAAM,SAAS,OAAO,OAAO,CAAC,OAAO,SAAS,IAAI,GAAG,EAAE,CAAC;AACxD,aAAO,iCAAgB,MAAM;AAC9B;AAMO,SAAS,oBACf,QACA,QACA,mBACiB;AACjB,QAAM,oBAAoB,qBAAqB,QAAQ,iBAAiB;AACxE,QAAM,kBAAkB,kBAAkB,KAAK,CAAC,OAAO,GAAG,OAAO,iBAAiB;AAClF,MAAI,CAAC,iBAAiB;AACrB,UAAM,IAAI,6BAAe,cAAc,iBAAiB,iCAAiC;AAAA,MACxF,aAAa;AAAA,IACd,CAAC;AAAA,EACF;AAEA,QAAM,SAA4B,oBAAI,IAAI;AAC1C,aAAW,MAAM,mBAAmB;AACnC,2BAAuB,QAAQ,IAAI,MAAM;AAAA,EAC1C;AAEA,QAAM,cAAc,uBAAuB,QAAQ,MAAM;AAEzD,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,YAAoB,UAA2C;AACzE,YAAM,SAAS,OAAO,IAAI,UAAU;AACpC,YAAM,SAAS,QAAQ,IAAI,QAAQ;AACnC,UAAI,CAAC,UAAU,OAAO,SAAS;AAC9B,eAAO;AAAA,MACR;AACA,YAAM,aAAa,OAAO,YAAY,UAAU;AAChD,UAAI,CAAC,YAAY;AAChB,eAAO;AAAA,MACR;AACA,aAAO,mBAAmB,QAAQ,UAAU;AAAA,IAC7C;AAAA,EACD;AACD;AAEA,SAAS,uBACR,OACA,IACA,QACO;AACP,QAAM,aAAa,OAAO,YAAY,GAAG,UAAU;AACnD,MAAI,CAAC,YAAY;AAChB;AAAA,EACD;AAEA,MAAI,SAAS,MAAM,IAAI,GAAG,UAAU;AACpC,MAAI,CAAC,QAAQ;AACZ,aAAS,oBAAI,IAAI;AACjB,UAAM,IAAI,GAAG,YAAY,MAAM;AAAA,EAChC;AAEA,QAAM,WAAW,GAAG,UAAU;AAE9B,UAAQ,GAAG,MAAM;AAAA,IAChB,KAAK,UAAU;AACd,UAAI,CAAC,GAAG,MAAM;AACb;AAAA,MACD;AACA,aAAO,IAAI,GAAG,UAAU;AAAA,QACvB,IAAI,GAAG;AAAA,QACP,QAAQ,EAAE,GAAG,GAAG,KAAK;AAAA,QACrB,SAAS;AAAA,QACT,WAAW;AAAA,QACX,WAAW;AAAA,MACZ,CAAC;AACD;AAAA,IACD;AAAA,IACA,KAAK,UAAU;AACd,UAAI,CAAC,GAAG,MAAM;AACb;AAAA,MACD;AACA,YAAM,WAAW,OAAO,IAAI,GAAG,QAAQ;AACvC,UAAI,YAAY,CAAC,SAAS,SAAS;AAClC,iBAAS,SAAS,EAAE,GAAG,SAAS,QAAQ,GAAG,GAAG,KAAK;AACnD,iBAAS,YAAY;AACrB;AAAA,MACD;AACA,UAAI,UAAU,SAAS;AACtB;AAAA,MACD;AACA,aAAO,IAAI,GAAG,UAAU;AAAA,QACvB,IAAI,GAAG;AAAA,QACP,QAAQ,EAAE,GAAG,GAAG,KAAK;AAAA,QACrB,SAAS;AAAA,QACT,WAAW;AAAA,QACX,WAAW;AAAA,MACZ,CAAC;AACD;AAAA,IACD;AAAA,IACA,KAAK,UAAU;AACd,YAAM,WAAW,OAAO,IAAI,GAAG,QAAQ;AACvC,UAAI,UAAU;AACb,iBAAS,UAAU;AACnB,iBAAS,YAAY;AACrB;AAAA,MACD;AACA,aAAO,IAAI,GAAG,UAAU;AAAA,QACvB,IAAI,GAAG;AAAA,QACP,QAAQ,CAAC;AAAA,QACT,SAAS;AAAA,QACT,WAAW;AAAA,QACX,WAAW;AAAA,MACZ,CAAC;AACD;AAAA,IACD;AAAA,EACD;AACD;AAEA,SAAS,uBACR,QACA,QACqC;AACrC,QAAM,cAAkD,CAAC;AAEzD,aAAW,CAAC,gBAAgB,UAAU,KAAK,OAAO,QAAQ,OAAO,WAAW,GAAG;AAC9E,UAAM,SAAS,OAAO,IAAI,cAAc;AACxC,UAAM,UAA8B,CAAC;AACrC,QAAI,QAAQ;AACX,iBAAW,UAAU,OAAO,OAAO,GAAG;AACrC,YAAI,CAAC,OAAO,SAAS;AACpB,kBAAQ,KAAK,mBAAmB,QAAQ,UAAU,CAAC;AAAA,QACpD;AAAA,MACD;AAAA,IACD;AACA,gBAAY,cAAc,IAAI;AAAA,EAC/B;AAEA,SAAO;AACR;AAEA,SAAS,mBACR,QACA,YACmB;AACnB,QAAM,SAA2B;AAAA,IAChC,IAAI,OAAO;AAAA,IACX,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO;AAAA,EACnB;AACA,aAAW,CAAC,SAAS,KAAK,OAAO,QAAQ,WAAW,MAAM,GAAG;AAC5D,QAAI,aAAa,OAAO,QAAQ;AAC/B,aAAO,SAAS,IAAI,OAAO,OAAO,SAAS;AAAA,IAC5C;AAAA,EACD;AACA,SAAO;AACR;;;ACjOA,IAAAC,gBAA2D;AAyBpD,IAAM,kBAAN,MAAsB;AAAA,EACX;AAAA,EACA;AAAA,EAEjB,YAAY,SAAyB,QAAgB;AACpD,SAAK,UAAU;AACf,SAAK,SAAS;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,KAAK,MAAc,QAA0C;AAClE,UAAM,QAAQ,QAAQ,SAAS;AAC/B,UAAM,UAAU,QAAQ,WAAW;AACnC,UAAM,SAAS,QAAQ,cAAU,qCAAsB,IAAI;AAE3D,QAAI,UAAU;AAEd,UAAM,KAAK,QAAQ,YAAY,OAAO,OAAO;AAE5C,YAAM,OAAO,MAAM,GAAG;AAAA,QACrB;AAAA,QACA,CAAC,MAAM,OAAO,KAAK,MAAM;AAAA,MAC1B;AAEA,UAAI,KAAK,SAAS,GAAG;AACpB,cAAM,MAAM,KAAK,CAAC;AAClB,kBAAU,IAAI,UAAU;AACxB,cAAM,GAAG;AAAA,UACR;AAAA,UACA,CAAC,SAAS,MAAM,OAAO,KAAK,MAAM;AAAA,QACnC;AAAA,MACD,OAAO;AAEN,kBAAU;AACV,cAAM,GAAG;AAAA,UACR;AAAA,UACA,CAAC,MAAM,OAAO,KAAK,QAAQ,OAAO;AAAA,QACnC;AAAA,MACD;AAAA,IACD,CAAC;AAED,eAAO,mCAAoB,QAAQ,SAAS,KAAK,MAAM;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,MAAc,QAA8C;AACzE,UAAM,QAAQ,QAAQ,SAAS;AAE/B,UAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,MAC/B;AAAA,MACA,CAAC,MAAM,OAAO,KAAK,MAAM;AAAA,IAC1B;AAEA,QAAI,KAAK,SAAS,GAAG;AACpB,aAAQ,KAAK,CAAC,EAAkB;AAAA,IACjC;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MAAM,MAAc,QAAyD;AAClF,UAAM,QAAQ,QAAQ,SAAS;AAC/B,UAAM,KAAK,QAAQ,MAAM;AAEzB,UAAM,KAAK,QAAQ;AAAA,MAClB;AAAA,MACA,CAAC,MAAM,OAAO,KAAK,MAAM;AAAA,IAC1B;AAEA,QAAI,KAAK,GAAG;AACX,YAAM,KAAK,QAAQ;AAAA,QAClB;AAAA,QACA,CAAC,MAAM,OAAO,KAAK,QAAQ,EAAE;AAAA,MAC9B;AAAA,IACD;AAAA,EACD;AACD;;;AfpFA;;;AgBrBA,IAAM,mBAAmB;AACzB,IAAM,YAAY;AAYX,SAAS,QAAQ,OAAuB;AAC9C,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACtC,YAAQ,MAAM,WAAW,CAAC;AAE1B,WAAO,KAAK,KAAK,MAAM,SAAS;AAAA,EACjC;AAEA,SAAO,SAAS;AACjB;AAYO,SAAS,gBAAgB,eAAuB,mBAAmC;AACzF,MAAI,iBAAiB,EAAG,QAAO;AAC/B,MAAI,qBAAqB,KAAK,qBAAqB,EAAG,QAAO;AAE7D,QAAM,aAAa,KAAK,MAAM,KAAK;AACnC,QAAM,UAAU,EAAE,gBAAgB,KAAK,IAAI,iBAAiB,KAAK;AAGjE,QAAM,UAAU,KAAK,KAAK,UAAU,EAAE,IAAI;AAC1C,SAAO,KAAK,IAAI,IAAI,OAAO;AAC5B;AAYO,SAAS,iBAAiB,UAAkB,eAA+B;AACjF,MAAI,iBAAiB,EAAG,QAAO;AAC/B,QAAM,MAAO,WAAW,gBAAiB,KAAK;AAC9C,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,MAAM,GAAG,CAAC,CAAC;AACjD;AAqBO,IAAM,0BAAN,MAA8B;AAAA,EAC5B;AAAA,EACS;AAAA,EACA;AAAA,EACT,YAAY;AAAA,EAEpB,YAAY,eAAuB,oBAAoB,MAAM;AAC5D,SAAK,WAAW,gBAAgB,eAAe,iBAAiB;AAChE,SAAK,YAAY,iBAAiB,KAAK,UAAU,aAAa;AAC9D,SAAK,OAAO,IAAI,YAAY,KAAK,WAAW,EAAE;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,YAAoB,OAAsB;AAC7C,UAAM,MAAM,UAAU,SAAY,GAAG,UAAU,IAAI,KAAK,KAAK;AAC7D,UAAM,YAAY,KAAK,aAAa,GAAG;AACvC,eAAW,OAAO,WAAW;AAC5B,YAAM,YAAY,QAAQ;AAC1B,YAAM,WAAW,MAAM;AACvB,YAAM,UAAU,KAAK,KAAK,SAAS,KAAK;AACxC,WAAK,KAAK,SAAS,IAAI,UAAW,KAAK;AAAA,IACxC;AACA,SAAK;AAAA,EACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,aAAa,YAAoB,OAAyB;AACzD,UAAM,MAAM,UAAU,SAAY,GAAG,UAAU,IAAI,KAAK,KAAK;AAC7D,UAAM,YAAY,KAAK,aAAa,GAAG;AACvC,eAAW,OAAO,WAAW;AAC5B,YAAM,YAAY,QAAQ;AAC1B,YAAM,WAAW,MAAM;AACvB,YAAM,KAAK,KAAK,SAAS,KAAK,KAAM,KAAK,cAAe,GAAG;AAC1D,eAAO;AAAA,MACR;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACb,SAAK,KAAK,KAAK,CAAC;AAChB,SAAK,YAAY;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,6BAAqC;AACpC,QAAI,KAAK,cAAc,EAAG,QAAO;AACjC,UAAM,WAAW,EAAE,KAAK,YAAY,KAAK,aAAa,KAAK;AAC3D,YAAQ,IAAI,KAAK,IAAI,QAAQ,MAAM,KAAK;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,eAAuB;AACtB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,cAAsB;AACrB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,eAAuB;AACtB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,iBAAyB;AACxB,QAAI,QAAQ;AACZ,aAAS,IAAI,GAAG,IAAI,KAAK,KAAK,QAAQ,KAAK;AAC1C,UAAI,OAAO,KAAK,KAAK,CAAC,KAAK;AAC3B,aAAO,SAAS,GAAG;AAElB,gBAAQ,OAAO;AACf;AAAA,MACD;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaQ,aAAa,KAAuB;AAC3C,UAAM,KAAK,QAAQ,GAAG;AAEtB,UAAM,KAAK,QAAQ,GAAG,GAAG,SAAS;AAElC,UAAM,YAAY,IAAI,MAAc,KAAK,SAAS;AAClD,aAAS,IAAI,GAAG,IAAI,KAAK,WAAW,KAAK;AAExC,gBAAU,CAAC,KAAM,KAAK,KAAK,KAAK,GAAG,EAAE,MAAO,KAAK,KAAK;AAAA,IACvD;AACA,WAAO;AAAA,EACR;AACD;;;ACjOA,IAAI,YAAY;AAMhB,IAAM,0BAA0B;AAMhC,IAAM,+BAA+B;AAMrC,IAAM,oCAAoC;AAkEnC,IAAM,sBAAN,MAA0B;AAAA,EACxB,gBAAgB,oBAAI,IAA0B;AAAA,EAC9C,qBAAqB,oBAAI,IAAY;AAAA,EACrC,iBAAiB;AAAA,EACR;AAAA;AAAA,EAGT,cAA8C;AAAA,EAC9C,aAAa;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGT,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EAE3B,YAAY,SAAsC;AACjD,SAAK,iBAAiB,SAAS,kBAAkB;AACjD,SAAK,qBAAqB,SAAS,sBAAsB;AACzD,SAAK,yBACJ,SAAS,0BAA0B;AACpC,SAAK,oBAAoB,SAAS;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,SACC,YACA,UACA,WACa;AACb,UAAM,KAAK,OAAO,EAAE,SAAS;AAC7B,UAAM,eAA6B;AAAA,MAClC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,CAAC;AAAA,IACf;AACA,SAAK,cAAc,IAAI,IAAI,YAAY;AAGvC,SAAK,aAAa;AAElB,UAAM,kBAAkB,KAAK,oBAAoB,UAAU;AAE3D,WAAO,MAAM;AACZ,WAAK,cAAc,OAAO,EAAE;AAC5B,WAAK,aAAa;AAClB,wBAAkB;AAAA,IACnB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,iBACC,YACA,UACA,WACa;AACb,UAAM,KAAK,OAAO,EAAE,SAAS;AAC7B,UAAM,eAA6B;AAAA,MAClC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,CAAC;AAAA,IACf;AACA,SAAK,cAAc,IAAI,IAAI,YAAY;AAGvC,SAAK,aAAa;AAElB,UAAM,kBAAkB,KAAK,oBAAoB,UAAU;AAG3D,cAAU,EAAE,KAAK,CAAC,YAAY;AAE7B,UAAI,KAAK,cAAc,IAAI,EAAE,GAAG;AAC/B,qBAAa,cAAc;AAC3B,iBAAS,OAAO;AAAA,MACjB;AAAA,IACD,CAAC;AAED,WAAO,MAAM;AACZ,WAAK,cAAc,OAAO,EAAE;AAC5B,WAAK,aAAa;AAClB,wBAAkB;AAAA,IACnB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,YAAoB,YAA6B;AACvD,SAAK,mBAAmB,IAAI,UAAU;AACtC,SAAK,cAAc;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAuB;AAC5B,QAAI,KAAK,mBAAmB,SAAS,EAAG;AAExC,UAAM,cAAc,IAAI,IAAI,KAAK,kBAAkB;AACnD,SAAK,mBAAmB,MAAM;AAC9B,SAAK,iBAAiB;AAEtB,UAAM,WAAW,KAAK,0BAA0B,WAAW;AAG3D,eAAW,OAAO,UAAU;AAC3B,UAAI;AACH,cAAM,aAAa,MAAM,IAAI,UAAU;AACvC,YAAI,CAAC,KAAK,aAAa,IAAI,aAAa,UAAU,GAAG;AACpD,cAAI,cAAc;AAClB,cAAI,SAAS,UAAU;AAAA,QACxB;AAAA,MACD,QAAQ;AAAA,MAGR;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACb,SAAK,cAAc,MAAM;AACzB,SAAK,mBAAmB,MAAM;AAC9B,SAAK,iBAAiB;AACtB,SAAK,cAAc;AACnB,SAAK,aAAa;AAClB,SAAK,cAAc;AACnB,SAAK,kBAAkB;AACvB,SAAK,oBAAoB;AACzB,SAAK,iBAAiB;AACtB,SAAK,mBAAmB;AAAA,EACzB;AAAA;AAAA,EAGA,IAAI,OAAe;AAClB,WAAO,KAAK,cAAc;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAA8B;AAC7B,WAAO;AAAA,MACN,aAAa,KAAK;AAAA,MAClB,iBAAiB,KAAK;AAAA,MACtB,mBAAmB,KAAK;AAAA,MACxB,gBAAgB,KAAK;AAAA,MACrB,oBAAoB,KAAK,cAAc,IAAI,KAAK,mBAAmB,KAAK,cAAc;AAAA,MACtF,mBAAmB,KAAK,cAAc;AAAA,MACtC,mBAAmB,KAAK,cAAc;AAAA,IACvC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAyB;AACxB,WAAO,KAAK,cAAc,QAAQ,KAAK;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,0BAA0B,aAA0C;AAC3E,UAAM,YAAY,YAAY,IAAI;AAClC,SAAK;AAEL,UAAM,WAAW,KAAK,cAAc;AAEpC,QAAI,UAAU;AAEb,UAAI,KAAK,cAAc,KAAK,gBAAgB,MAAM;AACjD,aAAK,mBAAmB;AAAA,MACzB;AAEA,YAAM,SAAS,KAAK;AACpB,UAAI,WAAW,MAAM;AAEpB,YAAI,mBAAmB;AACvB,mBAAW,OAAO,aAAa;AAC9B,cAAI,OAAO,aAAa,GAAG,GAAG;AAC7B,+BAAmB;AACnB;AAAA,UACD;AAAA,QACD;AAEA,YAAI,CAAC,kBAAkB;AAEtB,eAAK;AACL,eAAK,oBAAoB,YAAY,IAAI,IAAI;AAC7C,iBAAO,CAAC;AAAA,QACT;AAEA,aAAK;AAAA,MACN;AAAA,IACD;AAGA,UAAM,WAA2B,CAAC;AAClC,QAAI,kBAAkB;AAEtB,eAAW,OAAO,KAAK,cAAc,OAAO,GAAG;AAC9C,UAAI,YAAY,IAAI,IAAI,WAAW,UAAU,GAAG;AAC/C,iBAAS,KAAK,GAAG;AACjB,0BAAkB;AAAA,MACnB,WAAW,IAAI,WAAW,oBAAoB;AAE7C,mBAAW,UAAU,IAAI,WAAW,oBAAoB;AACvD,cAAI,YAAY,IAAI,MAAM,GAAG;AAC5B,qBAAS,KAAK,GAAG;AACjB,8BAAkB;AAClB;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAGA,QAAI,YAAY,CAAC,iBAAiB;AACjC,WAAK;AAAA,IACN;AAEA,SAAK,oBAAoB,YAAY,IAAI,IAAI;AAC7C,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,qBAA2B;AAClC,UAAM,SAAS,IAAI,wBAAwB,KAAK,oBAAoB,KAAK,sBAAsB;AAE/F,eAAW,OAAO,KAAK,cAAc,OAAO,GAAG;AAE9C,aAAO,IAAI,IAAI,WAAW,UAAU;AAGpC,UAAI,IAAI,WAAW,oBAAoB;AACtC,mBAAW,UAAU,IAAI,WAAW,oBAAoB;AACvD,iBAAO,IAAI,MAAM;AAAA,QAClB;AAAA,MACD;AAAA,IACD;AAEA,SAAK,cAAc;AACnB,SAAK,aAAa;AAAA,EACnB;AAAA,EAEQ,gBAAsB;AAC7B,QAAI,KAAK,eAAgB;AACzB,SAAK,iBAAiB;AACtB,mBAAe,MAAM;AACpB,WAAK,MAAM;AAAA,IACZ,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,aAAa,MAA0B,MAAmC;AACjF,QAAI,KAAK,WAAW,KAAK,OAAQ,QAAO;AACxC,QAAI,KAAK,WAAW,EAAG,QAAO;AAG9B,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACrC,UAAI,KAAK,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,GAAI,QAAO;AAAA,IACzC;AAGA,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACrC,YAAM,IAAI,KAAK,CAAC;AAChB,YAAM,IAAI,KAAK,CAAC;AAChB,YAAM,QAAQ,OAAO,KAAK,CAAC;AAC3B,YAAM,QAAQ,OAAO,KAAK,CAAC;AAC3B,UAAI,MAAM,WAAW,MAAM,OAAQ,QAAO;AAC1C,iBAAW,OAAO,OAAO;AACxB,YAAI,EAAE,GAAG,MAAM,EAAE,GAAG,EAAG,QAAO;AAAA,MAC/B;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AACD;;;ACtZA,IAAAC,gBAOO;AAKP;AAqEO,IAAM,qBAAN,MAAyB;AAAA,EACd;AAAA,EACT;AAAA,EACS,SAA0B,CAAC;AAAA,EACpC,YAAY;AAAA,EACZ,aAAa;AAAA,EACJ;AAAA,EAEjB,YAAY,QAAkC;AAC7C,SAAK,SAAS;AACd,SAAK,oBAAgB,8BAAe;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,MAAoB;AACnC,SAAK,eAAe;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAsC;AACrC,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,MAA6C;AACvD,UAAM,aAAa,KAAK,OAAO,OAAO,YAAY,IAAI;AACtD,QAAI,CAAC,YAAY;AAChB,YAAM,IAAI;AAAA,QACT,uBAAuB,IAAI,iBAAiB,OAAO,KAAK,KAAK,OAAO,OAAO,WAAW,EAAE,KAAK,IAAI,CAAC;AAAA,MACnG;AAAA,IACD;AAEA,WAAO;AAAA,MACN,QAAQ,CAAC,SAAkC,KAAK,OAAO,MAAM,YAAY,IAAI;AAAA,MAC7E,QAAQ,CAAC,IAAY,SACpB,KAAK,OAAO,MAAM,YAAY,IAAI,IAAI;AAAA,MACvC,QAAQ,CAAC,OAAe,KAAK,aAAa,MAAM,YAAY,EAAE;AAAA,MAC9D,UAAU,CAAC,OAAe,KAAK,SAAS,MAAM,YAAY,EAAE;AAAA,IAC7D;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,SAAiF;AACtF,QAAI,KAAK,WAAW;AACnB,YAAM,IAAI,MAAM,gCAAgC;AAAA,IACjD;AACA,QAAI,KAAK,YAAY;AACpB,YAAM,IAAI,MAAM,sDAAsD;AAAA,IACvE;AAEA,SAAK,YAAY;AAEjB,QAAI,KAAK,OAAO,WAAW,GAAG;AAC7B,aAAO,EAAE,YAAY,CAAC,GAAG,qBAAqB,oBAAI,IAAI,EAAE;AAAA,IACzD;AAEA,UAAM,UAAU,KAAK,OAAO;AAC5B,QAAI,SAAS,mBAAmB;AAC/B,aAAO,QAAQ,kBAAkB;AAAA,QAChC,SAAS,KAAK,OAAO,IAAI,CAAC,WAAW;AAAA,UACpC,WAAW,MAAM;AAAA,UACjB,UAAU,MAAM;AAAA,UAChB,YAAY,MAAM;AAAA,QACnB,EAAE;AAAA,QACF,eAAe,KAAK;AAAA,QACpB,GAAI,KAAK,iBAAiB,SAAY,EAAE,cAAc,KAAK,aAAa,IAAI,CAAC;AAAA,MAC9E,CAAC;AAAA,IACF;AAEA,UAAM,aAA0B,CAAC;AACjC,UAAM,sBAAsB,oBAAI,IAAY;AAG5C,UAAM,KAAK,OAAO,QAAQ,YAAY,OAAO,OAAoB;AAChE,iBAAW,SAAS,KAAK,QAAQ;AAChC,YAAI,MAAM,UAAU,SAAS,YAAY,KAAK,OAAO,kBAAkB;AACtE,gBAAM,gBAAgB,MAAM,KAAK,OAAO,iBAAiB;AAAA,YACxD,MAAM;AAAA,YACN,MAAM,UAAU;AAAA,YAChB;AAAA,YACA,CAAC,MAAM,UAAU,EAAE;AAAA,UACpB;AACA,qBAAW,cAAc,cAAc,YAAY;AAClD,uBAAW,KAAK,UAAU;AAC1B,gCAAoB,IAAI,WAAW,UAAU;AAC7C,iBAAK,OAAO,eAAe,eAAe,WAAW,YAAY,WAAW,IAAI,IAAI;AAAA,UACrF;AAAA,QACD;AAEA,mBAAW,OAAO,MAAM,UAAU;AACjC,gBAAM,GAAG,QAAQ,IAAI,KAAK,IAAI,MAAM;AAAA,QACrC;AACA,mBAAW,KAAK,MAAM,SAAS;AAC/B,4BAAoB,IAAI,MAAM,UAAU;AAAA,MACzC;AAEA,YAAM,WAAW,KAAK,OAAO,kBAAkB,iBAAiB;AAChE,UAAI,WAAW,GAAG;AACjB,cAAM,GAAG;AAAA,UACR;AAAA,UACA,CAAC,KAAK,OAAO,QAAQ,QAAQ;AAAA,QAC9B;AAAA,MACD;AAAA,IACD,CAAC;AAED,WAAO,EAAE,YAAY,oBAAoB;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,WAAiB;AAChB,SAAK,aAAa;AAClB,SAAK,OAAO,SAAS;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,mBAA2B;AAC1B,WAAO,KAAK;AAAA,EACb;AAAA,EAEQ,eAAqB;AAC5B,QAAI,KAAK,WAAW;AACnB,YAAM,IAAI,MAAM,uDAAuD;AAAA,IACxE;AACA,QAAI,KAAK,YAAY;AACpB,YAAM,IAAI,MAAM,yDAAyD;AAAA,IAC1E;AAAA,EACD;AAAA,EAEA,MAAc,OACb,gBACA,YACA,MAC4B;AAC5B,SAAK,aAAa;AAElB,UAAM,gBAAY,8BAAe,gBAAgB,YAAY,MAAM,QAAQ;AAC3E,UAAM,eAAW,8BAAe;AAChC,UAAM,MAAM,KAAK,IAAI;AAGrB,eAAW,CAAC,WAAW,UAAU,KAAK,OAAO,QAAQ,WAAW,MAAM,GAAG;AACxE,UAAI,WAAW,QAAQ,WAAW,SAAS,aAAa;AACvD,kBAAU,SAAS,IAAI;AAAA,MACxB;AAAA,IACD;AAEA,UAAM,iBAAiB,MAAM,KAAK,OAAO,kBAAkB,SAAS;AACpE,UAAM,aAAa,KAAK,OAAO,eAAe,eAAe,gBAAgB,IAAI,KAAK,CAAC;AACvF,UAAM,YAAY,UAAM;AAAA,MACvB;AAAA,QACC,QAAQ,KAAK,OAAO;AAAA,QACpB,MAAM;AAAA,QACN,YAAY;AAAA,QACZ;AAAA,QACA,MAAM,EAAE,GAAG,UAAU;AAAA,QACrB,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA,eAAe,KAAK,OAAO,OAAO;AAAA,QAClC,eAAe,KAAK;AAAA,QACpB,GAAI,KAAK,iBAAiB,SAAY,EAAE,cAAc,KAAK,aAAa,IAAI,CAAC;AAAA,MAC9E;AAAA,MACA,KAAK,OAAO;AAAA,IACb;AACA,SAAK,OAAO,eAAe,eAAe,gBAAgB,UAAU,IAAI,IAAI;AAE5E,UAAM,iBAAiB,gBAAgB,WAAW,WAAW,MAAM;AACnE,UAAM,UAAU,oBAAoB,UAAU,SAAS;AACvD,UAAM,SAAkC;AAAA,MACvC,IAAI;AAAA,MACJ,GAAG;AAAA,MACH,aAAa,UAAU,UAAU;AAAA,MACjC,aAAa,UAAU,UAAU;AAAA,MACjC,UAAU;AAAA,IACX;AAEA,UAAM,cAAc,iBAAiB,gBAAgB,MAAM;AAC3D,UAAM,QAAQ,mBAAmB,SAAS;AAC1C,UAAM,WAAW;AAAA,MAChB,aAAa,cAAc;AAAA,MAC3B;AAAA,IACD;AAEA,SAAK,OAAO,KAAK;AAAA,MAChB;AAAA,MACA,YAAY;AAAA,MACZ,UAAU;AAAA,QACT,EAAE,KAAK,YAAY,KAAK,QAAQ,YAAY,OAAO;AAAA,QACnD,EAAE,KAAK,SAAS,KAAK,QAAQ,SAAS,OAAO;AAAA,MAC9C;AAAA,IACD,CAAC;AAED,WAAO;AAAA,MACN,IAAI;AAAA,MACJ,GAAG;AAAA,MACH,WAAW;AAAA,MACX,WAAW;AAAA,IACZ;AAAA,EACD;AAAA,EAEA,MAAc,OACb,gBACA,YACA,IACA,MAC4B;AAC5B,SAAK,aAAa;AAGlB,UAAM,gBAAgB,MAAM,KAAK,mBAAmB,gBAAgB,YAAY,EAAE;AAClF,QAAI,CAAC,eAAe;AACnB,YAAM,IAAI,oBAAoB,gBAAgB,EAAE;AAAA,IACjD;AAEA,UAAM,gBAAY,8BAAe,gBAAgB,YAAY,MAAM,QAAQ;AAC3E,UAAM,MAAM,KAAK,IAAI;AAErB,UAAM,eAAwC,CAAC;AAC/C,UAAM,eAAwC,CAAC;AAC/C,UAAM,YAAsC,CAAC;AAE7C,eAAW,OAAO,OAAO,KAAK,SAAS,GAAG;AACzC,YAAM,QAAQ,UAAU,GAAG;AAC3B,mBAAa,GAAG,IAAI,cAAc,GAAG;AAErC,cAAI,0BAAW,KAAK,GAAG;AACtB,qBAAa,GAAG,QAAI,+BAAgB,cAAc,GAAG,GAAG,KAAK;AAC7D,kBAAU,GAAG,QAAI,0BAAW,KAAK;AAAA,MAClC,OAAO;AACN,qBAAa,GAAG,IAAI;AAAA,MACrB;AAAA,IACD;AAEA,UAAM,eAAe,OAAO,KAAK,SAAS,EAAE,SAAS;AAErD,UAAM,iBAAiB,MAAM,KAAK,OAAO,kBAAkB,SAAS;AACpE,UAAM,aAAa,KAAK,OAAO,eAAe,eAAe,gBAAgB,IAAI,KAAK,CAAC;AACvF,UAAM,YAAY,UAAM;AAAA,MACvB;AAAA,QACC,QAAQ,KAAK,OAAO;AAAA,QACpB,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,MAAM,EAAE,GAAG,aAAa;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,KAAK,OAAO,OAAO;AAAA,QAClC,eAAe,KAAK;AAAA,QACpB,GAAI,KAAK,iBAAiB,SAAY,EAAE,cAAc,KAAK,aAAa,IAAI,CAAC;AAAA,QAC7E,GAAI,eAAe,EAAE,UAAU,IAAI,CAAC;AAAA,MACrC;AAAA,MACA,KAAK,OAAO;AAAA,IACb;AACA,SAAK,OAAO,eAAe,eAAe,gBAAgB,UAAU,IAAI,IAAI;AAE5E,UAAM,oBAAoB,gBAAgB,cAAc,WAAW,MAAM;AACzE,UAAM,UAAU,oBAAoB,UAAU,SAAS;AACvD,UAAM,cAAc,iBAAiB,gBAAgB,IAAI;AAAA,MACxD,GAAG;AAAA,MACH,aAAa,UAAU,UAAU;AAAA,MACjC,UAAU;AAAA,IACX,CAAC;AACD,UAAM,QAAQ,mBAAmB,SAAS;AAC1C,UAAM,WAAW;AAAA,MAChB,aAAa,cAAc;AAAA,MAC3B;AAAA,IACD;AAEA,SAAK,OAAO,KAAK;AAAA,MAChB;AAAA,MACA,YAAY;AAAA,MACZ,UAAU;AAAA,QACT,EAAE,KAAK,YAAY,KAAK,QAAQ,YAAY,OAAO;AAAA,QACnD,EAAE,KAAK,SAAS,KAAK,QAAQ,SAAS,OAAO;AAAA,MAC9C;AAAA,IACD,CAAC;AAGD,WAAO;AAAA,MACN,GAAG;AAAA,MACH,GAAG;AAAA,MACH,WAAW;AAAA,IACZ;AAAA,EACD;AAAA,EAEA,MAAc,aACb,gBACA,YACA,IACgB;AAChB,SAAK,aAAa;AAElB,UAAM,gBAAgB,MAAM,KAAK,mBAAmB,gBAAgB,YAAY,EAAE;AAClF,QAAI,CAAC,eAAe;AACnB,YAAM,IAAI,oBAAoB,gBAAgB,EAAE;AAAA,IACjD;AAEA,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,iBAAiB,MAAM,KAAK,OAAO,kBAAkB,SAAS;AACpE,UAAM,aAAa,KAAK,OAAO,eAAe,eAAe,gBAAgB,IAAI,KAAK,CAAC;AACvF,UAAM,YAAY,UAAM;AAAA,MACvB;AAAA,QACC,QAAQ,KAAK,OAAO;AAAA,QACpB,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,MAAM;AAAA,QACN,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA,eAAe,KAAK,OAAO,OAAO;AAAA,QAClC,eAAe,KAAK;AAAA,QACpB,GAAI,KAAK,iBAAiB,SAAY,EAAE,cAAc,KAAK,aAAa,IAAI,CAAC;AAAA,MAC9E;AAAA,MACA,KAAK,OAAO;AAAA,IACb;AACA,SAAK,OAAO,eAAe,eAAe,gBAAgB,UAAU,IAAI,IAAI;AAE5E,UAAM,cAAc,qBAAqB,gBAAgB,IAAI,GAAG;AAChE,UAAM,QAAQ,mBAAmB,SAAS;AAC1C,UAAM,WAAW;AAAA,MAChB,aAAa,cAAc;AAAA,MAC3B;AAAA,IACD;AAEA,SAAK,OAAO,KAAK;AAAA,MAChB;AAAA,MACA,YAAY;AAAA,MACZ,UAAU;AAAA,QACT,EAAE,KAAK,YAAY,KAAK,QAAQ,YAAY,OAAO;AAAA,QACnD,EAAE,KAAK,SAAS,KAAK,QAAQ,SAAS,OAAO;AAAA,MAC9C;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,MAAc,SACb,gBACA,YACA,IACmC;AACnC,WAAO,KAAK,mBAAmB,gBAAgB,YAAY,EAAE;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,mBACb,gBACA,YACA,IACmC;AAEnC,aAAS,IAAI,KAAK,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AACjD,YAAM,QAAQ,KAAK,OAAO,CAAC;AAC3B,UAAI,MAAM,eAAe,kBAAkB,MAAM,UAAU,aAAa,IAAI;AAC3E,YAAI,MAAM,UAAU,SAAS,UAAU;AACtC,iBAAO;AAAA,QACR;AAEA;AAAA,MACD;AAAA,IACD;AAGA,UAAM,OAAO,MAAM,KAAK,OAAO,QAAQ;AAAA,MACtC,iBAAiB,cAAc;AAAA,MAC/B,CAAC,EAAE;AAAA,IACJ;AAEA,QAAI,SAAkC,KAAK,CAAC,IACzC,kBAAkB,KAAK,CAAC,GAAG,WAAW,MAAM,IAC5C;AAGH,eAAW,SAAS,KAAK,QAAQ;AAChC,UAAI,MAAM,eAAe,kBAAkB,MAAM,UAAU,aAAa,IAAI;AAC3E;AAAA,MACD;AAEA,UAAI,MAAM,UAAU,SAAS,YAAY,MAAM,UAAU,MAAM;AAC9D,iBAAS;AAAA,UACR;AAAA,UACA,GAAG,MAAM,UAAU;AAAA,UACnB,WAAW,MAAM,UAAU,UAAU;AAAA,UACrC,WAAW,MAAM,UAAU,UAAU;AAAA,QACtC;AAAA,MACD,WAAW,MAAM,UAAU,SAAS,YAAY,MAAM,UAAU,QAAQ,QAAQ;AAC/E,iBAAS;AAAA,UACR,GAAG;AAAA,UACH,GAAG,MAAM,UAAU;AAAA,UACnB,WAAW,MAAM,UAAU,UAAU;AAAA,QACtC;AAAA,MACD,WAAW,MAAM,UAAU,SAAS,UAAU;AAC7C,iBAAS;AAAA,MACV;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AACD;;;ACjfO,IAAM,+BAAN,MAAmC;AAAA,EAIzC,YACkB,SACA,QAChB;AAFgB;AACA;AAAA,EACf;AAAA,EAFe;AAAA,EACA;AAAA,EALV,SAAS;AAAA,EACT,YAAY;AAAA,EAOpB,MAAM,WAA4B;AACjC,QAAI,CAAC,KAAK,QAAQ;AACjB,WAAK,YAAY,MAAM,mBAAmB,KAAK,SAAS,KAAK,MAAM;AACnE,WAAK,SAAS;AAAA,IACf;AACA,SAAK;AACL,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,mBAA2B;AAC1B,WAAO,KAAK;AAAA,EACb;AACD;;;AC5BA,IAAAC,gBAA+B;AAI/B,SAAS,iBAAiB,QAAwB;AACjD,SAAO,iBAAiB,MAAM;AAC/B;AAKO,SAAS,iBAAiB,QAA+B;AAC/D,MAAI,OAAO,mBAAmB,aAAa;AAC1C,WAAO;AAAA,EACR;AACA,SAAO,eAAe,QAAQ,iBAAiB,MAAM,CAAC;AACvD;AAKO,SAAS,iBAAiB,QAAgB,QAAsB;AACtE,MAAI,OAAO,mBAAmB,aAAa;AAC1C;AAAA,EACD;AACA,iBAAe,QAAQ,iBAAiB,MAAM,GAAG,MAAM;AACxD;AAKO,SAAS,oBAAoB,QAAwB;AAC3D,QAAM,WAAW,iBAAiB,MAAM;AACxC,MAAI,UAAU;AACb,WAAO;AAAA,EACR;AACA,QAAM,aAAS,8BAAe;AAC9B,mBAAiB,QAAQ,MAAM;AAC/B,SAAO;AACR;;;ApB2CO,IAAM,QAAN,MAAoC;AAAA,EAClC,SAAS;AAAA,EACT,SAAS;AAAA,EACT,iBAAiB;AAAA,EACjB,oBAA+B,mCAAoB;AAAA,EACnD,QAAmC;AAAA,EACnC,cAAc,oBAAI,IAAwB;AAAA,EAC1C;AAAA,EACA,kBAA0C;AAAA,EAEjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EACA,mBAA4C;AAAA,EAC5C,gBAAsC;AAAA,EAE9C,YAAY,QAAqB;AAChC,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO;AACtB,SAAK,eAAe,OAAO;AAC3B,SAAK,SAAS,OAAO,UAAU;AAC/B,SAAK,YAAY,OAAO,aAAa;AACrC,SAAK,UAAU,OAAO,WAAW;AACjC,SAAK,uBAAuB,OAAO,wBAAwB;AAC3D,SAAK,sBAAsB,IAAI,oBAAoB;AAAA,MAClD,mBAAmB,OAAO;AAAA,IAC3B,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAsB;AAC3B,UAAM,KAAK,QAAQ,KAAK,KAAK,MAAM;AAGnC,UAAM,KAAK,sBAAsB;AAGjC,SAAK,SAAS,MAAM,KAAK,qBAAqB;AAC9C,SAAK,QAAQ,IAAI,iCAAmB,KAAK,MAAM;AAC/C,SAAK,gBAAgB,IAAI,4BAAc;AAGvC,SAAK,kBAAkB,IAAI,gBAAgB,KAAK,SAAS,KAAK,MAAM;AAGpE,SAAK,iBAAiB,MAAM,KAAK,mBAAmB;AACpD,SAAK,gBAAgB,MAAM,KAAK,kBAAkB;AAKlD,UAAM,eAAe,OAAO,KAAK,KAAK,OAAO,SAAS,EAAE,SAAS;AACjE,SAAK,mBAAmB,eACrB,IAAI,iBAAiB;AAAA,MACrB,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,IACd,CAAC,IACA;AAGH,eAAW,CAAC,MAAM,UAAU,KAAK,OAAO,QAAQ,KAAK,OAAO,WAAW,GAAG;AACzE,YAAM,MAAM,IAAI;AAAA,QACf;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM,KAAK,uBAAuB;AAAA,QAClC,CAAC,gBAAgB,cAAc;AAC9B,eAAK,wBAAwB,SAAS;AACtC,eAAK,oBAAoB,OAAO,gBAAgB,SAAS;AACzD,cAAI,KAAK,SAAS;AACjB,iBAAK,QAAQ,KAAK,EAAE,MAAM,qBAAqB,UAAU,CAAC;AAAA,UAC3D;AAAA,QACD;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MACN;AACA,WAAK,YAAY,IAAI,MAAM,GAAG;AAAA,IAC/B;AAEA,SAAK,SAAS;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAuB;AAC5B,SAAK,oBAAoB,MAAM;AAC/B,SAAK,YAAY,MAAM;AACvB,SAAK,SAAS;AACd,UAAM,KAAK,QAAQ,MAAM;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,MAAkC;AAC5C,SAAK,WAAW;AAChB,UAAM,MAAM,KAAK,YAAY,IAAI,IAAI;AACrC,QAAI,CAAC,KAAK;AACT,YAAM,IAAI;AAAA,QACT,uBAAuB,IAAI,iBAAiB,CAAC,GAAG,KAAK,YAAY,KAAK,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,MACpF;AAAA,IACD;AAEA,UAAM,aAAa,KAAK,OAAO,YAAY,IAAI;AAC/C,QAAI,CAAC,YAAY;AAChB,YAAM,IAAI,MAAM,wCAAwC,IAAI,GAAG;AAAA,IAChE;AAEA,WAAO;AAAA,MACN,QAAQ,CAAC,SAAkC,IAAI,OAAO,IAAI;AAAA,MAC1D,UAAU,CAAC,OAAe,IAAI,SAAS,EAAE;AAAA,MACzC,QAAQ,CAAC,IAAY,SAAkC,IAAI,OAAO,IAAI,IAAI;AAAA,MAC1E,QAAQ,CAAC,OAAe,IAAI,OAAO,EAAE;AAAA,MACrC,OAAO,CAAC,eACP,IAAI;AAAA,QACH;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MACN;AAAA,IACF;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAkC;AACjC,SAAK,WAAW;AAChB,WAAO,IAAI,IAAI,KAAK,aAAa;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAoB;AACnB,SAAK,WAAW;AAChB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,qBAAqB,IAAe,SAAoD;AAC7F,SAAK,WAAW;AAEhB,UAAM,aAAa,GAAG;AACtB,UAAM,aAAa,KAAK,OAAO,YAAY,UAAU;AACrD,QAAI,CAAC,YAAY;AAChB,aAAO;AAAA,IACR;AAGA,UAAM,WAAW,MAAM,KAAK,QAAQ;AAAA,MACnC,4BAA4B,UAAU;AAAA,MACtC,CAAC,GAAG,EAAE;AAAA,IACP;AACA,QAAI,SAAS,SAAS,GAAG;AACxB,aAAO;AAAA,IACR;AAGA,QAAI,KAAK,OAAO;AACf,WAAK,MAAM,QAAQ,GAAG,SAAS;AAAA,IAChC;AAEA,UAAM,gBAAgB,oBAAoB,GAAG,SAAS;AACtD,UAAM,WAAW,GAAG,UAAU;AAG9B,UAAM,KAAK,QAAQ,YAAY,OAAO,OAAO;AAC5C,UAAI,GAAG,SAAS,YAAY,GAAG,MAAM;AACpC,cAAMC,YAAW,MAAM,GAAG;AAAA,UACzB,qCAAqC,UAAU;AAAA,UAC/C,CAAC,GAAG,QAAQ;AAAA,QACb;AACA,cAAM,MAAMA,UAAS,CAAC;AACtB,YAAI,OAAO,CAAC,uBAAuB,GAAG,WAAW,GAAG,GAAG;AAAA,QAEvD,OAAO;AACN,gBAAM,iBAAiB,gBAAgB,GAAG,MAAM,WAAW,MAAM;AACjE,gBAAM,SAAkC;AAAA,YACvC,IAAI,GAAG;AAAA,YACP,GAAG;AAAA,YACH,aAAa;AAAA,YACb,aAAa;AAAA,YACb,UAAU;AAAA,UACX;AACA,gBAAM,cAAc,iBAAiB,YAAY,MAAM;AACvD,gBAAM,GAAG,QAAQ,YAAY,KAAK,YAAY,MAAM;AAAA,QACrD;AAAA,MACD,WAAW,GAAG,SAAS,YAAY,GAAG,MAAM;AAC3C,cAAM,oBAAoB,gBAAgB,GAAG,MAAM,WAAW,MAAM;AACpE,cAAM,gBAAyC;AAAA,UAC9C,GAAG;AAAA,UACH,aAAa;AAAA,UACb,UAAU;AAAA,QACX;AACA,YAAI,SAAS,qBAAqB;AACjC,wBAAc,WAAW;AAAA,QAC1B;AACA,cAAM,cAAc;AAAA,UACnB;AAAA,UACA,GAAG;AAAA,UACH;AAAA,UACA;AAAA,QACD;AACA,cAAM,GAAG,QAAQ,YAAY,KAAK,YAAY,MAAM;AAAA,MACrD,WAAW,GAAG,SAAS,UAAU;AAChC,cAAM,cAAc;AAAA,UACnB;AAAA,UACA,GAAG;AAAA,UACH;AAAA,UACA;AAAA,QACD;AACA,cAAM,GAAG,QAAQ,YAAY,KAAK,YAAY,MAAM;AAAA,MACrD;AAGA,YAAM,QAAQ,mBAAmB,EAAE;AACnC,YAAM,WAAW;AAAA,QAChB,aAAa,UAAU;AAAA,QACvB;AAAA,MACD;AACA,YAAM,GAAG,QAAQ,SAAS,KAAK,SAAS,MAAM;AAG9C,YAAM,aAAa,KAAK,cAAc,IAAI,GAAG,MAAM,KAAK;AACxD,UAAI,GAAG,iBAAiB,YAAY;AACnC,aAAK,cAAc,IAAI,GAAG,QAAQ,GAAG,cAAc;AACnD,cAAM,GAAG;AAAA,UACR;AAAA,UACA,CAAC,GAAG,QAAQ,GAAG,cAAc;AAAA,QAC9B;AAAA,MACD;AAAA,IACD,CAAC;AAGD,SAAK,oBAAoB,OAAO,YAAY,EAAE;AAE9C,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,SAAS,QAAgB,SAAiB,OAAqC;AACpF,WAAO,KAAK,kBAAkB,QAAQ,SAAS,KAAK;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAkB,QAAgB,SAAiB,OAAqC;AAC7F,SAAK,WAAW;AAChB,UAAM,SAAsB,CAAC;AAE7B,eAAW,kBAAkB,OAAO,KAAK,KAAK,OAAO,WAAW,GAAG;AAClE,YAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,QAC/B,2BAA2B,cAAc;AAAA,QACzC,CAAC,QAAQ,SAAS,KAAK;AAAA,MACxB;AACA,iBAAW,OAAO,MAAM;AACvB,eAAO,KAAK,mCAAmC,KAAK,cAAc,CAAC;AAAA,MACpE;AAAA,IACD;AAGA,WAAO,KAAK,CAAC,GAAG,MAAM,EAAE,iBAAiB,EAAE,cAAc;AACzD,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,mBAAyC;AAC9C,SAAK,WAAW;AAChB,UAAM,SAAsB,CAAC;AAE7B,eAAW,kBAAkB,OAAO,KAAK,KAAK,OAAO,WAAW,GAAG;AAClE,YAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,QAC/B,2BAA2B,cAAc;AAAA,MAC1C;AACA,iBAAW,OAAO,MAAM;AACvB,eAAO,KAAK,mCAAmC,KAAK,cAAc,CAAC;AAAA,MACpE;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,SAAS,aAA8C;AAC5D,SAAK,WAAW;AAChB,UAAM,QAAQ,KAAK,IAAI;AACvB,UAAM,SAAS,MAAM,KAAK,iBAAiB;AAC3C,UAAM,WAAW,oBAAoB,KAAK,QAAQ,QAAQ,WAAW;AAErE,QAAI,KAAK,SAAS;AACjB,WAAK,QAAQ,KAAK;AAAA,QACjB,MAAM;AAAA,QACN,mBAAmB;AAAA,QACnB,mBAAmB,SAAS,kBAAkB;AAAA,QAC9C,UAAU,KAAK,IAAI,IAAI;AAAA,MACxB,CAAC;AAAA,IACF;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,OAAoE;AAC1F,SAAK,WAAW;AAChB,UAAM,EAAE,kBAAkB,OAAO,IAAI,MAAM;AAC3C,UAAM,OAAO,KAAK,SAAS,KAAK;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eACL,OAC0D;AAC1D,SAAK,WAAW;AAChB,UAAM,EAAE,iBAAAC,iBAAgB,IAAI,MAAM;AAClC,WAAOA,iBAAgB,KAAK,SAAS,KAAK;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,SAA4E;AAC7F,SAAK,WAAW;AAChB,UAAM,EAAE,aAAa,SAAS,IAAI,MAAM;AACxC,WAAO,SAAS,KAAK,SAAS,KAAK,QAAQ,KAAK,QAAQ,KAAK,OAAO,SAAS,OAAO;AAAA,EACrF;AAAA;AAAA;AAAA;AAAA,EAKA,YAA8B;AAC7B,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAwB,SAA4C;AACnE,SAAK,uBAAuB;AAC5B,eAAW,OAAO,KAAK,YAAY,OAAO,GAAG;AAC5C,UAAI,mBAAmB,OAAO;AAAA,IAC/B;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,sBACC,YACA,SACuB;AACvB,SAAK,WAAW;AAChB,UAAM,aAAa,KAAK,OAAO,YAAY,UAAU;AACrD,QAAI,CAAC,cAAc,CAAC,KAAK,OAAO;AAC/B,YAAM,IAAI,kBAAkB;AAAA,IAC7B;AACA,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,wBAAwB,MAAM,KAAK,uBAAuB;AAAA,MAC1D,YAAY,CAAC,gBAAgB,cAAc;AAC1C,aAAK,wBAAwB,SAAS;AACtC,aAAK,oBAAoB,OAAO,gBAAgB,SAAS;AACzD,YAAI,KAAK,SAAS;AACjB,eAAK,QAAQ,KAAK,EAAE,MAAM,qBAAqB,UAAU,CAAC;AAAA,QAC3D;AAAA,MACD;AAAA,MACA,kBAAkB,KAAK;AAAA,MACvB,eAAe,KAAK;AAAA,MACpB,eAAe,SAAS,iBAAiB;AAAA,MACzC,iBAAiB,SAAS;AAAA,IAC3B;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBACL,YACA,UAC0C;AAC1C,SAAK,WAAW;AAChB,UAAM,aAAa,KAAK,OAAO,YAAY,UAAU;AACrD,QAAI,CAAC,YAAY;AAChB,aAAO;AAAA,IACR;AAEA,UAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,MAC/B,iBAAiB,UAAU;AAAA,MAC3B,CAAC,QAAQ;AAAA,IACV;AACA,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,CAAC,KAAK;AACT,aAAO;AAAA,IACR;AAEA,WAAO;AAAA,MACN,QAAQ,kBAAkB,KAAK,WAAW,MAAM;AAAA,MAChD,SAAS,IAAI,aAAa;AAAA,IAC3B;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,4BAAoD;AACzD,SAAK,WAAW;AAChB,WAAO,0BAA0B,KAAK,OAAO;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,0BAA0B,QAAsC;AACrE,SAAK,WAAW;AAChB,UAAM,0BAA0B,KAAK,SAAS,MAAM;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAA0C;AAC/C,SAAK,WAAW;AAChB,WAAO,gBAAgB,KAAK,OAAO;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,QAAsC;AAC3D,SAAK,WAAW;AAChB,UAAM,gBAAgB,KAAK,SAAS,MAAM;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,sBAAsB,cAAmD;AAC9E,SAAK,WAAW;AAChB,WAAO;AAAA,MACN,KAAK,iBAAiB;AAAA,MACtB;AAAA,MACA,CAAC,QAAQ,SAAS,UAAU,KAAK,kBAAkB,QAAQ,SAAS,KAAK;AAAA,IAC1E;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,wBAAwB,cAA8C;AAC3E,UAAM,MAAM,MAAM,KAAK,sBAAsB,YAAY;AACzD,WAAO,IAAI;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAQ,UAAyD;AACtE,SAAK,WAAW;AAChB,QAAI,SAAS,SAAS,SAAS;AAC9B,aAAO,oBAAoB,KAAK,SAAS,KAAK,QAAQ,cAAU,mCAAoB,CAAC;AAAA,IACtF;AAEA,UAAM,eAAe,SAAS,gBAAiB,MAAM,0BAA0B,KAAK,OAAO;AAC3F,WAAO,oBAAoB,KAAK,SAAS,KAAK,QAAQ,UAAU,YAAY;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,eAA8B,iBAA+C;AAC/F,WAAO,oBAAoB,iBAAiB,aAAa;AAAA,EAC1D;AAAA,EAEA,MAAM,iCACL,YACA,UAC4B;AAC5B,SAAK,WAAW;AAChB,UAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,MAC/B,2BAA2B,UAAU;AAAA,MACrC,CAAC,KAAK,QAAQ,QAAQ;AAAA,IACvB;AACA,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,CAAC,KAAK;AACT,aAAO;AAAA,IACR;AACA,WAAO,mCAAmC,KAAK,UAAU;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,4BACL,YACA,UAC4B;AAC5B,SAAK,WAAW;AAChB,UAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,MAC/B,2BAA2B,UAAU;AAAA,MACrC,CAAC,QAAQ;AAAA,IACV;AAEA,QAAI,SAA2B;AAC/B,eAAW,OAAO,MAAM;AACvB,YAAM,KAAK,mCAAmC,KAAK,UAAU;AAC7D,UAAI,CAAC,UAAU,iCAAmB,QAAQ,GAAG,WAAW,OAAO,SAAS,IAAI,GAAG;AAC9E,iBAAS;AAAA,MACV;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA;AAAA,EAGA,yBAA8C;AAC7C,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAsC;AACrC,SAAK,WAAW;AAChB,QAAI,CAAC,KAAK,iBAAiB;AAC1B,YAAM,IAAI,kBAAkB;AAAA,IAC7B;AACA,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,oBAAwC;AACvC,SAAK,WAAW;AAChB,QAAI,CAAC,KAAK,OAAO;AAChB,YAAM,IAAI,kBAAkB;AAAA,IAC7B;AACA,WAAO,IAAI,mBAAmB;AAAA,MAC7B,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,mBAAmB,IAAI,6BAA6B,KAAK,SAAS,KAAK,MAAM;AAAA,MAC7E,kBAAkB,KAAK;AAAA,MACvB,eAAe,KAAK;AAAA,MACpB,sBAAsB,KAAK;AAAA,IAC5B,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,YAAY,IAAqE;AACtF,UAAM,KAAK,KAAK,kBAAkB;AAClC,SAAK,eAAe,iBAAiB;AACrC,QAAI;AACH,YAAM,GAAG,EAAE;AACX,YAAM,EAAE,WAAW,IAAI,MAAM,GAAG,OAAO;AAEvC,WAAK,eAAe,iBAAiB;AAGrC,iBAAW,MAAM,YAAY;AAC5B,aAAK,wBAAwB,EAAE;AAC/B,aAAK,oBAAoB,OAAO,GAAG,YAAY,EAAE;AACjD,YAAI,KAAK,SAAS;AACjB,eAAK,QAAQ,KAAK,EAAE,MAAM,qBAAqB,WAAW,GAAG,CAAC;AAAA,QAC/D;AAAA,MACD;AAEA,aAAO;AAAA,IACR,SAAS,OAAO;AACf,SAAG,SAAS;AACZ,WAAK,eAAe,iBAAiB;AACrC,YAAM;AAAA,IACP;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,aAAa,SAA8C;AAChE,SAAK,WAAW;AAChB,UAAM,EAAE,cAAc,SAAS,IAAI,MAAM;AACzC,WAAO,SAAS,KAAK,SAAS,KAAK,QAAQ,KAAK,QAAQ,KAAK,OAAO,SAAS,OAAO;AAAA,EACrF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,aAAa,MAAkB,SAAkD;AACtF,SAAK,WAAW;AAChB,UAAM,EAAE,eAAe,UAAU,IAAI,MAAM;AAC3C,WAAO,UAAU,KAAK,SAAS,KAAK,QAAQ,MAAM,OAAO;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,mBAAmB,MAAkC;AAC3D,WAAO,mBAAa,IAAI;AAAA,EACzB;AAAA,EAEQ,wBAAwB,WAA4B;AAC3D,UAAM,OAAO,KAAK,cAAc,IAAI,UAAU,MAAM,KAAK;AACzD,QAAI,UAAU,iBAAiB,MAAM;AACpC,WAAK,cAAc,IAAI,UAAU,QAAQ,UAAU,cAAc;AAAA,IAClE;AACA,QAAI,UAAU,WAAW,KAAK,QAAQ;AACrC,WAAK,iBAAiB,KAAK,IAAI,KAAK,gBAAgB,UAAU,cAAc;AAAA,IAC7E;AAAA,EACD;AAAA,EAEA,MAAc,yBAA0C;AACvD,UAAM,MAAM,MAAM,2BAA2B,KAAK,SAAS,KAAK,MAAM;AACtE,SAAK,iBAAiB;AACtB,SAAK,cAAc,IAAI,KAAK,QAAQ,GAAG;AACvC,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,wBAAuC;AACpD,UAAM,gBAAgB,MAAM,KAAK,uBAAuB;AACxD,UAAM,gBAAgB,KAAK,OAAO;AAElC,QAAI,iBAAiB,eAAe;AAEnC,UAAI,kBAAkB,GAAG;AAExB,cAAM,KAAK,QAAQ;AAAA,UAClB;AAAA,UACA,CAAC,OAAO,aAAa,CAAC;AAAA,QACvB;AAAA,MACD;AACA;AAAA,IACD;AAGA,UAAM,aAAa,KAAK,OAAO,cAAc,CAAC;AAC9C,aAAS,IAAI,gBAAgB,GAAG,KAAK,eAAe,KAAK;AACxD,YAAM,YAAY,WAAW,CAAC;AAC9B,UAAI,CAAC,UAAW;AAGhB,YAAM,oBAAgB,mCAAoB,UAAU,KAAK;AAKzD,iBAAW,OAAO,eAAe;AAChC,YAAI;AACH,gBAAM,KAAK,QAAQ,QAAQ,GAAG;AAAA,QAC/B,SAAS,GAAG;AACX,gBAAM,MAAO,EAAY,WAAW;AACpC,cAAI,CAAC,IAAI,SAAS,uBAAuB,GAAG;AAC3C,kBAAM;AAAA,UACP;AAAA,QAED;AAAA,MACD;AAGA,YAAM,gBAAgB,UAAU,MAAM;AAAA,QACrC,CAAC,MAAyD,EAAE,SAAS;AAAA,MACtE;AACA,iBAAW,QAAQ,eAAe;AACjC,cAAM,KAAK,YAAY,KAAK,YAAY,KAAK,SAAS;AAAA,MACvD;AAAA,IACD;AAGA,UAAM,KAAK,QAAQ;AAAA,MAClB;AAAA,MACA,CAAC,OAAO,aAAa,CAAC;AAAA,IACvB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,yBAA0C;AACvD,UAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,MAC/B;AAAA,IACD;AACA,WAAO,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,EAAE,KAAK,IAAI;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,YACb,YACA,WACgB;AAChB,UAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,MAC/B,iBAAiB,UAAU;AAAA,IAC5B;AAEA,UAAM,KAAK,QAAQ,YAAY,OAAO,OAAO;AAC5C,iBAAW,OAAO,MAAM;AACvB,cAAM,UAAU,UAAU,GAA8B;AACxD,cAAM,SAAS,OAAO,KAAK,OAAO;AAClC,YAAI,OAAO,WAAW,EAAG;AAEzB,cAAM,aAAa,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,MAAM,EAAE,KAAK,IAAI;AAC1D,cAAM,SAAS,OAAO,IAAI,CAAC,MAAM;AAChC,gBAAM,MAAM,QAAQ,CAAC;AAErB,cAAI,OAAO,QAAQ,UAAW,QAAO,MAAM,IAAI;AAE/C,cAAI,MAAM,QAAQ,GAAG,KAAM,OAAO,QAAQ,YAAY,QAAQ,MAAO;AACpE,mBAAO,KAAK,UAAU,GAAG;AAAA,UAC1B;AACA,iBAAO;AAAA,QACR,CAAC;AACD,eAAO,KAAK,IAAI,EAAE;AAElB,cAAM,GAAG,QAAQ,UAAU,UAAU,QAAQ,UAAU,iBAAiB,MAAM;AAAA,MAC/E;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,MAAc,uBAAwC;AACrD,QAAI,KAAK,cAAc;AACtB,UAAI,KAAK,cAAc,WAAW;AACjC,cAAM,KAAK,QAAQ;AAAA,UAClB;AAAA,UACA,CAAC,KAAK,YAAY;AAAA,QACnB;AAAA,MACD;AACA,aAAO,KAAK;AAAA,IACb;AAEA,QAAI,KAAK,cAAc,WAAW;AACjC,aAAO,oBAAoB,KAAK,MAAM;AAAA,IACvC;AAGA,UAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,MAC/B;AAAA,IACD;AACA,QAAI,KAAK,CAAC,GAAG;AACZ,aAAO,KAAK,CAAC,EAAE;AAAA,IAChB;AAGA,UAAM,gBAAY,8BAAe;AACjC,UAAM,KAAK,QAAQ,QAAQ,6DAA6D;AAAA,MACvF;AAAA,IACD,CAAC;AACD,WAAO;AAAA,EACR;AAAA,EAEA,MAAc,qBAAsC;AACnD,UAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,MAC/B;AAAA,MACA,CAAC,KAAK,MAAM;AAAA,IACb;AACA,WAAO,KAAK,CAAC,GAAG,mBAAmB;AAAA,EACpC;AAAA,EAEA,MAAc,oBAA4C;AACzD,UAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,MAC/B;AAAA,IACD;AACA,UAAM,aAAS,mCAAoB;AACnC,eAAW,OAAO,MAAM;AACvB,aAAO,IAAI,IAAI,SAAS,IAAI,eAAe;AAAA,IAC5C;AACA,WAAO;AAAA,EACR;AAAA,EAEQ,aAAmB;AAC1B,QAAI,CAAC,KAAK,QAAQ;AACjB,YAAM,IAAI,kBAAkB;AAAA,IAC7B;AAAA,EACD;AACD;;;AqB95BA,IAAM,cAAkC,OAAO,OAAO,CAAC,CAAC;AASjD,IAAM,aAAN,MAAuC;AAAA,EACrC,WAAyB;AAAA,EACzB,YAAY,oBAAI,IAAgB;AAAA,EAChC,mBAAwC;AAAA,EACxC,SAAS;AAAA,EACA;AAAA,EAEjB,YAAY,cAA+B;AAC1C,SAAK,eAAe;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,CAAC,kBAA4C;AACxD,SAAK,UAAU,IAAI,aAAa;AAEhC,QAAI,CAAC,KAAK,QAAQ;AACjB,WAAK,kBAAkB;AAAA,IACxB;AAEA,WAAO,MAAM;AACZ,WAAK,UAAU,OAAO,aAAa;AACnC,UAAI,KAAK,UAAU,SAAS,GAAG;AAC9B,aAAK,iBAAiB;AAAA,MACvB;AAAA,IACD;AAAA,EACD;AAAA;AAAA,EAGA,cAAc,MAAoB;AACjC,WAAO,KAAK;AAAA,EACb;AAAA;AAAA,EAGA,UAAgB;AACf,SAAK,iBAAiB;AACtB,SAAK,UAAU,MAAM;AACrB,SAAK,WAAW;AAAA,EACjB;AAAA,EAEQ,oBAA0B;AACjC,SAAK,SAAS;AACd,SAAK,mBAAmB,KAAK,aAAa,UAAU,CAAC,YAA0B;AAC9E,UAAI,CAAC,KAAK,OAAQ;AAClB,WAAK,WAAW,OAAO,OAAO,CAAC,GAAG,OAAO,CAAC;AAC1C,WAAK,gBAAgB;AAAA,IACtB,CAAC;AAAA,EACF;AAAA,EAEQ,mBAAyB;AAChC,SAAK,SAAS;AACd,QAAI,KAAK,kBAAkB;AAC1B,WAAK,iBAAiB;AACtB,WAAK,mBAAmB;AAAA,IACzB;AAAA,EACD;AAAA,EAEQ,kBAAwB;AAC/B,eAAW,YAAY,KAAK,WAAW;AACtC,eAAS;AAAA,IACV;AAAA,EACD;AACD;;;ACjFA,IAAAC,gBAAiC;AAGjC,IAAM,4BAA4B;AAK3B,SAAS,iBAAiB,OAAoC;AACpE,QAAM,aAAa,MAAM,cAAc;AACvC,MAAI,WAAW,eAAe,2BAA2B;AACxD,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AACD;;;ACFO,IAAM,kBAAN,MAAsB;AAAA,EAG5B,YAA6B,WAAW,WAAW;AAAtB;AAAA,EAAuB;AAAA,EAAvB;AAAA,EAFrB,UAAU,oBAAI,IAAwB;AAAA,EAI9C,YAAe,cAA8C;AAC5D,UAAM,MAAM,KAAK,OAAO,YAAY;AACpC,UAAM,WAAW,KAAK,QAAQ,IAAI,GAAG;AAErC,QAAI,UAAU;AACb,eAAS;AACT,aAAO,SAAS;AAAA,IACjB;AAEA,UAAM,aAAa,IAAI,WAAc,YAAY;AACjD,SAAK,QAAQ,IAAI,KAAK;AAAA,MACrB;AAAA,MACA,UAAU;AAAA,IACX,CAAC;AACD,WAAO;AAAA,EACR;AAAA,EAEA,QAAQ,cAA2C;AAClD,UAAM,MAAM,KAAK,OAAO,YAAY;AACpC,UAAM,QAAQ,KAAK,QAAQ,IAAI,GAAG;AAClC,QAAI,CAAC,OAAO;AACX;AAAA,IACD;AAEA,UAAM;AACN,QAAI,MAAM,YAAY,GAAG;AACxB,YAAM,WAAW,QAAQ;AACzB,WAAK,QAAQ,OAAO,GAAG;AAAA,IACxB;AAAA,EACD;AAAA,EAEA,QAAc;AACb,eAAW,SAAS,KAAK,QAAQ,OAAO,GAAG;AAC1C,YAAM,WAAW,QAAQ;AAAA,IAC1B;AACA,SAAK,QAAQ,MAAM;AAAA,EACpB;AAAA,EAEA,IAAI,OAAe;AAClB,WAAO,KAAK,QAAQ;AAAA,EACrB;AAAA,EAEQ,OAAO,cAA6C;AAC3D,WAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,UAAU,aAAa,cAAc,CAAC,CAAC;AAAA,EACxE;AACD;AAEA,IAAI,cAAsC;AAQnC,SAAS,2BAA4C;AAC3D,MAAI,CAAC,aAAa;AACjB,kBAAc,IAAI,gBAAgB;AAAA,EACnC;AACA,SAAO;AACR;;;AC9EA,IAAAC,KAAmB;AACnB;AAUA,IAAM,cAAc;AACpB,IAAM,gBAAgB;AACtB,IAAM,qBAAqB;AAC3B,IAAMC,YAAW;AACjB,IAAM,uBAAuB;AAC7B,IAAM,sBAAsB;AAMrB,SAAS,yBACf,SACqB;AACrB,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb;AAAA,EACD,IAAI;AAEJ,QAAM,MAAM,IAAM,OAAI;AACtB,QAAM,OAAO,IAAI,QAAQA,SAAQ;AACjC,QAAM,cAAc,IAAM,eAAY,IAAI;AAE1C,MAAI,OAAO,QAAQ;AACnB,MAAI,WAAW;AACf,MAAI,QAAQ;AACZ,MAAI,QAAsB;AAC1B,MAAI,UAAU;AACd,MAAI,UAAU;AACd,MAAI,UAAgC,CAAC;AAErC,QAAM,YAAY,oBAAI,IAAgB;AACtC,MAAI,WAAuC;AAAA,IAC1C,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS,CAAC;AAAA,EACX;AACA,QAAM,gBAAgB,EAAE,SAAS,KAA0B;AAC3D,QAAM,mBAAmB,EAAE,SAAS,CAAC,EAAkB;AACvD,QAAM,sBAAsB,EAAE,SAAS,MAAM;AAC7C,MAAI,eAAqD;AAEzD,MAAI,oBAAyC;AAC7C,MAAI,wBAA6C;AACjD,MAAI,uBAA4C;AAEhD,QAAM,kBAAkB,MAAY;AACnC,eAAW;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,CAAC,GAAG,OAAO;AAAA,IACrB;AAAA,EACD;AAEA,QAAM,SAAS,MAAY;AAC1B,oBAAgB;AAChB,eAAW,YAAY,WAAW;AACjC,eAAS;AAAA,IACV;AAAA,EACD;AAEA,QAAM,mBAAmB,MAAY;AACpC,cAAU,YAAY,UAAU,SAAS;AACzC,cAAU,YAAY,UAAU,SAAS;AACzC,WAAO;AAAA,EACR;AAEA,QAAM,cAAc,MAAkC;AAEtD,QAAM,uBAAuB,MAA6B;AACzD,QAAI,MAAM;AACT,aAAO;AAAA,IACR;AACA,QAAI,YAAY;AACf,YAAM,WAAW,WAAW,oBAAoB,EAAE,cAAc,GAAG;AACnE,UAAI,UAAU;AACb,eAAO;AAAA,MACR;AAAA,IACD;AACA,WAAO;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,IACR;AAAA,EACD;AAEA,QAAM,YAAY,CAAC,QAAgB,SAAuB;AACzD,QAAI,CAAC,YAAY;AAChB;AAAA,IACD;AAEA,UAAM,YAAY,WAAW,oBAAoB;AACjD,UAAM,QAAgC;AAAA,MACrC,MAAM,qBAAqB;AAAA,MAC3B,QAAQ;AAAA,QACP,YAAY;AAAA,QACZ;AAAA,QACA,OAAO;AAAA,QACP;AAAA,QACA;AAAA,MACD;AAAA,IACD;AACA,cAAU,cAAc,KAAK;AAAA,EAC9B;AAEA,QAAM,cAAc,MAAY;AAC/B,QAAI,CAAC,YAAY;AAChB;AAAA,IACD;AAEA,UAAM,YAAY,WAAW,oBAAoB;AACjD,UAAM,UAAU,UAAU,cAAc;AACxC,QAAI,CAAC,SAAS,QAAQ;AACrB;AAAA,IACD;AACA,QACC,QAAQ,OAAO,eAAe,kBAC9B,QAAQ,OAAO,aAAa,YAC5B,QAAQ,OAAO,UAAU,WACxB;AACD;AAAA,IACD;AAEA,cAAU,cAAc,EAAE,MAAM,QAAQ,KAAK,CAAC;AAAA,EAC/C;AAEA,QAAM,sBAAsB,CAAC,UAAyB;AACrD,UAAM,UAAU,oBAAoB,KAAK;AACzC,QAAI,CAAC,SAAS;AACb;AAAA,IACD;AAEA,UAAM,kBAAoB,uBAAoB,GAAG;AACjD,QAAI,aAAa,iBAAiB,OAAO,GAAG;AAC3C;AAAA,IACD;AAEA,IAAE,eAAY,KAAK,SAAS,aAAa;AACzC,kBAAc,UAAU;AACxB,qBAAiB,UAAU,CAAC;AAC5B,qBAAiB;AAAA,EAClB;AAEA,QAAM,eAAe,YAA2B;AAC/C,UAAMC,YAAW,wBAAwB,cAAc,SAAS,iBAAiB,OAAO;AACxF,QAAI,iBAAiB,QAAQ,UAAU,sBAAsB;AAC5D,oBAAc,UAAUA;AACxB,uBAAiB,UAAU,CAAC;AAAA,IAC7B;AAEA,QAAI;AACH,YAAM,WAAW,OAAO,UAAU;AAAA,QACjC,CAAC,SAAS,GAAGA;AAAA,MACd,CAAC;AAAA,IACF,SAAS,OAAO;AACf,UAAI,CAAC,UAAU;AACd,gBAAQ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAChE,eAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAEA,QAAM,kBAAkB,MAAY;AACnC,QAAI,cAAc;AACjB,mBAAa,YAAY;AAAA,IAC1B;AACA,mBAAe,WAAW,MAAM;AAC/B,qBAAe;AACf,WAAK,aAAa;AAAA,IACnB,GAAG,mBAAmB;AAAA,EACvB;AAEA,QAAM,cAAc,CAAC,QAAoB,WAA0B;AAClE,qBAAiB;AACjB,QAAI,WAAW,eAAe,WAAW,iBAAiB,WAAW,oBAAoB;AACxF;AAAA,IACD;AAEA,qBAAiB,QAAQ,KAAK,MAAM;AAEpC,QAAI,oBAAoB,WAAW,YAAY;AAC9C,iBAAW,wBAAwB,EAAE,KAAK,gBAAgB,UAAU,WAAW,MAAM;AACrF,sBAAgB;AAChB;AAAA,IACD;AAEA,SAAK,aAAa;AAAA,EACnB;AAEA,QAAM,yBAAyB,MAAY;AAC1C,wBAAoB;AACpB,wBAAoB,MAClB,WAAW,cAAc,EACzB,MAAM,EAAE,IAAI,SAAS,CAAC,EACtB,UAAU,CAAC,YAAY;AACvB,YAAM,SAAS,QAAQ,CAAC;AACxB,UAAI,CAAC,QAAQ;AACZ;AAAA,MACD;AACA,0BAAoB,OAAO,SAAS,CAAC;AAAA,IACtC,CAAC;AAAA,EACH;AAEA,QAAM,sBAAsB,MAAY;AACvC,4BAAwB;AACxB,QAAI,CAAC,SAAS,CAAC,cAAc,CAAC,oBAAoB,SAAS;AAC1D;AAAA,IACD;AAEA,UAAM,UAAU,WAAW,wBAAwB;AACnD,QAAI,CAAC,SAAS;AACb;AAAA,IACD;AAEA,4BAAwB,QAAQ,UAAU,gBAAgB,UAAU,WAAW,CAAC,WAAW;AAC1F,MAAE,eAAY,KAAK,QAAQ,kBAAkB;AAC7C,uBAAiB;AAAA,IAClB,CAAC;AAAA,EACF;AAEA,QAAM,gBAAgB,MAAY;AACjC,QAAI,CAAC,YAAY;AAChB,gBAAU,CAAC;AACX,aAAO;AACP;AAAA,IACD;AAEA,UAAM,YAAY,WAAW,oBAAoB;AACjD,UAAM,gBAAgB,UAAU;AAChC,UAAM,SAAS,UAAU,UAAU;AACnC,UAAM,eAAqC,CAAC;AAE5C,eAAW,CAAC,UAAU,KAAK,KAAK,QAAQ;AACvC,UAAI,aAAa,cAAe;AAChC,UAAI,CAAC,MAAM,OAAQ;AACnB,UACC,MAAM,OAAO,eAAe,kBAC5B,MAAM,OAAO,aAAa,YAC1B,MAAM,OAAO,UAAU,WACtB;AACD;AAAA,MACD;AACA,mBAAa,KAAK;AAAA,QACjB;AAAA,QACA,UAAU,MAAM,KAAK;AAAA,QACrB,OAAO,MAAM,KAAK;AAAA,QAClB,QAAQ,MAAM,OAAO;AAAA,QACrB,MAAM,MAAM,OAAO;AAAA,MACpB,CAAC;AAAA,IACF;AAEA,cAAU;AACV,WAAO;AAAA,EACR;AAEA,QAAM,qBAAqB,MAAY;AACtC,2BAAuB;AACvB,QAAI,CAAC,YAAY;AAChB,gBAAU,CAAC;AACX,aAAO;AACP;AAAA,IACD;AAEA,UAAM,YAAY,WAAW,oBAAoB;AACjD,2BAAuB,UAAU,GAAG,UAAU,MAAM;AACnD,oBAAc;AAAA,IACf,CAAC;AACD,kBAAc;AAAA,EACf;AAEA,QAAM,aAAa,YAA2B;AAC7C,YAAQ;AACR,YAAQ;AACR,WAAO;AAEP,QAAI;AACH,YAAM,SAAS,MAAM,WAAW,SAAS,QAAQ;AACjD,UAAI,SAAU;AAEd,UAAI,SAAS,MAAM;AAClB,cAAM,SAAS,IAAI,QAAQD,SAAQ;AACnC,eAAO,OAAO,GAAG,OAAO,MAAM;AAAA,MAC/B,GAAG,WAAW;AAEd,YAAM,UAAU,oBAAoB,SAAS,SAAS,CAAC;AACvD,oBAAc,UAAU;AACxB,uBAAiB,UAAU,CAAC;AAC5B,UAAI,SAAS;AACZ,QAAE,eAAY,KAAK,SAAS,WAAW;AAAA,MACxC;AAEA,YAAM,UAAU,YAAY,wBAAwB;AACpD,0BAAoB,UACnB,SAAS,iBAAiB,SAAS,UAAU,GAAG,aAAa,KAAK;AAEnE,cAAQ;AACR,uBAAiB;AACjB,6BAAuB;AACvB,0BAAoB;AACpB,yBAAmB;AACnB,aAAO;AAAA,IACR,SAAS,OAAO;AACf,UAAI,SAAU;AACd,cAAQ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAChE,aAAO;AAAA,IACR;AAAA,EACD;AAEA,MAAI,GAAG,UAAU,WAAW;AAC5B,OAAK,WAAW;AAEhB,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,UAAU;AACnB,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM;AACZ,kBAAU,OAAO,QAAQ;AAAA,MAC1B;AAAA,IACD;AAAA,IACA,OAAO;AACN,kBAAY,KAAK;AACjB,uBAAiB;AAAA,IAClB;AAAA,IACA,OAAO;AACN,kBAAY,KAAK;AACjB,uBAAiB;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,UAA6C;AACpD,aAAO;AAAA,IACR;AAAA,IACA,UAAU;AACT,UAAI,UAAU;AACb;AAAA,MACD;AACA,iBAAW;AACX,UAAI,cAAc;AACjB,qBAAa,YAAY;AACzB,uBAAe;AAAA,MAChB;AACA,UAAI,IAAI,UAAU,WAAW;AAC7B,0BAAoB;AACpB,8BAAwB;AACxB,6BAAuB;AACvB,kBAAY;AACZ,kBAAY,QAAQ;AACpB,oBAAc,UAAU;AACxB,uBAAiB,UAAU,CAAC;AAC5B,0BAAoB,UAAU;AAC9B,gBAAU,MAAM;AAAA,IACjB;AAAA,EACD;AACD;AAEA,SAAS,oBAAoB,OAAmC;AAC/D,MAAI,UAAU,QAAQ,UAAU,QAAW;AAC1C,WAAO;AAAA,EACR;AAEA,MAAI;AACH,WAAO,eAAe,KAA6C;AAAA,EACpE,QAAQ;AACP,QAAI,OAAO,UAAU,UAAU;AAC9B,YAAM,cAAc,IAAM,OAAI;AAC9B,kBAAY,QAAQA,SAAQ,EAAE,OAAO,GAAG,KAAK;AAC7C,aAAS,uBAAoB,WAAW;AAAA,IACzC;AACA,UAAM,IAAI,MAAM,2EAA2E;AAAA,EAC5F;AACD;AAEA,SAAS,wBAAwB,MAAyB,QAAkC;AAC3F,QAAM,YAAY,IAAM,OAAI;AAC5B,MAAI,MAAM;AACT,IAAE,eAAY,WAAW,IAAI;AAAA,EAC9B;AAEA,aAAW,SAAS,QAAQ;AAC3B,IAAE,eAAY,WAAW,KAAK;AAAA,EAC/B;AAEA,SAAS,uBAAoB,SAAS;AACvC;AAEA,SAAS,aAAa,MAAkB,OAA4B;AACnE,MAAI,KAAK,WAAW,MAAM,QAAQ;AACjC,WAAO;AAAA,EACR;AACA,WAAS,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS;AACjD,QAAI,KAAK,KAAK,MAAM,MAAM,KAAK,GAAG;AACjC,aAAO;AAAA,IACR;AAAA,EACD;AACA,SAAO;AACR;;;AC1ZO,SAAS,qBAAqB,QAA4C;AAChF,MAAI,UAAU,MAAM;AACnB,WAAO;AAAA,EACR;AACA,SAAO;AACR;;;A9BkGA;;;A+B7GA;;;ACAA;AAOA;AAMA;","names":["import_core","import_core","import_core","encodeSection","encodeJsonSection","readUint32","parseSections","findSection","computeSha256","readAllOperations","import_core","import_core","import_core","import_core","import_core","import_core","import_core","import_core","QueryError","propName","import_core","import_core","import_core","import_core","import_core","existing","readAuditTraces","import_core","Y","TEXT_KEY","snapshot"]}
|
|
1
|
+
{"version":3,"sources":["../src/serialization/op-data-encoding.ts","../src/serialization/richtext-serializer.ts","../src/serialization/serializer.ts","../src/backup/backup.ts","../src/audit/audit-json.ts","../src/audit/audit-trace-store.ts","../src/audit/export-audit.ts","../src/index.ts","../src/errors.ts","../src/compaction/types.ts","../src/compaction/compact-operation-log.ts","../src/sync/sync-state.ts","../src/store/store.ts","../src/mutations/execute-delete.ts","../src/lww/row-version.ts","../src/query/sql-builder.ts","../src/store/sequence-allocator.ts","../src/mutations/resolve-causal-deps.ts","../src/mutations/execute-insert.ts","../src/lww/field-versions.ts","../src/mutations/execute-update.ts","../src/state-machine/state-validator.ts","../src/collection/collection.ts","../src/query/query-builder.ts","../src/query/pluralize.ts","../src/relations/relation-enforcer.ts","../src/relations/relation-lookup.ts","../src/replay/replay-to.ts","../src/sequences/sequence-manager.ts","../src/subscription/bloom-filter.ts","../src/subscription/subscription-manager.ts","../src/sync/rebase-unsynced-operations.ts","../src/transaction/transaction-context.ts","../src/transaction/transaction-sequence.ts","../src/store/tab-node-id.ts","../src/reactivity/query-store.ts","../src/reactivity/assert-query-ready.ts","../src/reactivity/query-store-cache.ts","../src/richtext/create-richtext-controller.ts","../src/richtext/as-rich-text-sync-engine.ts","../src/backup/index.ts","../src/audit/index.ts","../src/blob/content-addressed-blob-store.ts","../src/blob/opfs-blob-store.ts","../src/blob/blob-chunking.ts","../src/blob/blob-transfer.ts","../src/blob/blob-manifest-transfer.ts","../src/blob/server-blob-callbacks.ts","../src/blob/blob-gc.ts","../src/blob/blob-chunk-transport.ts"],"sourcesContent":["import {\n\ttype KoraBytesValue,\n\tbase64ToBytes,\n\tbytesToBase64,\n\tdecodeBytesFromOpData,\n\tencodeBytesForOpData,\n\tisKoraBytesValue,\n\tisLegacyNumericByteObject,\n} from '@korajs/core'\nimport type { FieldDescriptor } from '@korajs/core'\n\n/**\n * The canonical binary op-data encoding lives in `@korajs/core` because\n * `op.data` is a core concept shared by store (creation, persistence) and merge\n * (CRDT merge). These re-exports keep existing store-internal import paths\n * working while the single source of truth is the core module.\n */\nexport type { KoraBytesValue }\nexport { base64ToBytes, bytesToBase64, isKoraBytesValue, isLegacyNumericByteObject }\n\n/** @deprecated Use {@link encodeRichtextForOpData}; kept for existing imports. */\nexport const encodeRichtextForOpData = encodeBytesForOpData\n/** @deprecated Use {@link decodeRichtextOpDataValue}; kept for existing imports. */\nexport const decodeRichtextOpDataValue = decodeBytesFromOpData\n\n/**\n * Apply {@link encodeBytesForOpData} to every richtext-typed field in an\n * operation's data payload. Called at operation creation, BEFORE the payload\n * is content-hashed, so the hash input, persisted JSON, wire payload, and the\n * value the merge engine sees are the identical canonical value. Non-richtext\n * fields are untouched.\n */\nexport function encodeRichtextFieldsForOpData(\n\tdata: Record<string, unknown>,\n\tfields: Record<string, FieldDescriptor>,\n): Record<string, unknown> {\n\tconst result: Record<string, unknown> = { ...data }\n\tfor (const [key, value] of Object.entries(data)) {\n\t\tif (fields[key]?.kind !== 'richtext') {\n\t\t\tcontinue\n\t\t}\n\t\tif (typeof value === 'string' || value instanceof Uint8Array || value instanceof ArrayBuffer) {\n\t\t\tresult[key] = encodeBytesForOpData(value)\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Reverse of {@link encodeRichtextFieldsForOpData}: decode tagged (or legacy\n * numeric-key) richtext values in an op-data payload back to record-shaped\n * values (string or Uint8Array). Null/undefined and plain strings pass\n * through, preserving pre-fix behavior exactly.\n */\nexport function decodeRichtextFieldsFromOpData(\n\tdata: Record<string, unknown>,\n\tfields: Record<string, FieldDescriptor>,\n): Record<string, unknown> {\n\tconst result: Record<string, unknown> = { ...data }\n\tfor (const [key, value] of Object.entries(data)) {\n\t\tif (fields[key]?.kind !== 'richtext' || value === null || value === undefined) {\n\t\t\tcontinue\n\t\t}\n\t\tresult[key] = decodeBytesFromOpData(value)\n\t}\n\treturn result\n}\n","import * as Y from 'yjs'\nimport {\n\ttype KoraBytesValue,\n\tdecodeRichtextOpDataValue,\n\tisKoraBytesValue,\n\tisLegacyNumericByteObject,\n} from './op-data-encoding'\n\nconst TEXT_KEY = 'content'\n\nexport type RichtextInput = string | Uint8Array | ArrayBuffer | null | undefined\n\n/**\n * Encodes richtext values into Yjs document updates.\n *\n * Also accepts the tagged `{ $koraBytes }` form that binary richtext values\n * take inside `op.data` (and, for old dev databases, the pre-fix numeric-key\n * object shape), so every consumer that writes op-data values to columns\n * inherits the decoding. Plain strings keep their exact historical behavior:\n * encoded as a fresh Yjs document containing the string.\n */\nexport function encodeRichtext(value: RichtextInput | KoraBytesValue): Uint8Array | null {\n\tif (value === null || value === undefined) {\n\t\treturn null\n\t}\n\n\tif (typeof value === 'string') {\n\t\tconst doc = new Y.Doc()\n\t\tdoc.getText(TEXT_KEY).insert(0, value)\n\t\treturn Y.encodeStateAsUpdate(doc)\n\t}\n\n\tif (value instanceof Uint8Array) {\n\t\treturn value\n\t}\n\n\tif (value instanceof ArrayBuffer) {\n\t\treturn new Uint8Array(value)\n\t}\n\n\tif (isKoraBytesValue(value) || isLegacyNumericByteObject(value)) {\n\t\tconst decoded = decodeRichtextOpDataValue(value)\n\t\t// Both accepted shapes decode to bytes; strings were handled above.\n\t\treturn decoded instanceof Uint8Array ? decoded : null\n\t}\n\n\tthrow new Error('Richtext value must be a string, Uint8Array, ArrayBuffer, null, or undefined.')\n}\n\n/**\n * Decodes driver-provided richtext values into Uint8Array.\n */\nexport function decodeRichtext(value: unknown): Uint8Array | null {\n\tif (value === null || value === undefined) {\n\t\treturn null\n\t}\n\n\tif (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {\n\t\treturn new Uint8Array(value)\n\t}\n\n\tif (value instanceof Uint8Array) {\n\t\treturn value\n\t}\n\n\tif (value instanceof ArrayBuffer) {\n\t\treturn new Uint8Array(value)\n\t}\n\n\tthrow new Error(\n\t\t'Richtext storage value must be Uint8Array, ArrayBuffer, Buffer, null, or undefined.',\n\t)\n}\n\n/**\n * Reads plain text from a richtext Yjs state update.\n */\nexport function richtextToPlainText(value: RichtextInput): string {\n\tconst encoded = encodeRichtext(value)\n\tif (!encoded) return ''\n\n\tconst doc = new Y.Doc()\n\tY.applyUpdate(doc, encoded)\n\treturn doc.getText(TEXT_KEY).toString()\n}\n\n/**\n * Compares two richtext values by decoded plain text.\n * Yjs update bytes are not stable across separate encodes of the same string.\n */\nexport function richtextStatesEqual(a: unknown, b: unknown): boolean {\n\ttry {\n\t\treturn richtextToPlainText(a as RichtextInput) === richtextToPlainText(b as RichtextInput)\n\t} catch {\n\t\treturn false\n\t}\n}\n","import { HybridLogicalClock } from '@korajs/core'\nimport type { CollectionDefinition, FieldDescriptor, Operation } from '@korajs/core'\nimport type { CollectionRecord, OperationRow, RawCollectionRow } from '../types'\nimport { decodeRichtext, encodeRichtext } from './richtext-serializer'\n\n/**\n * Serialize a JS record to SQL-compatible values for INSERT/UPDATE.\n * Transforms: boolean → 0/1, array → JSON string, richtext → Yjs binary update.\n *\n * @param data - The record data with JS-native types\n * @param fields - The field descriptors from the schema\n * @returns An object with SQL-compatible values\n */\nexport function serializeRecord(\n\tdata: Record<string, unknown>,\n\tfields: Record<string, FieldDescriptor>,\n): Record<string, unknown> {\n\tconst result: Record<string, unknown> = {}\n\tfor (const [key, value] of Object.entries(data)) {\n\t\tconst descriptor = fields[key]\n\t\tif (!descriptor) {\n\t\t\tresult[key] = value\n\t\t\tcontinue\n\t\t}\n\t\tresult[key] = serializeValue(value, descriptor)\n\t}\n\treturn result\n}\n\n/**\n * Deserialize a SQL row to JS-native types for the application layer.\n * Transforms: 0/1 → boolean, JSON string → array, strips _deleted, maps _created_at/_updated_at.\n *\n * @param row - The raw SQL row\n * @param fields - The field descriptors from the schema\n * @returns A CollectionRecord with JS-native types\n */\nexport function deserializeRecord(\n\trow: RawCollectionRow,\n\tfields: Record<string, FieldDescriptor>,\n): CollectionRecord {\n\tconst result: CollectionRecord = {\n\t\tid: row.id,\n\t\tcreatedAt: row._created_at,\n\t\tupdatedAt: row._updated_at,\n\t}\n\n\tfor (const [key, descriptor] of Object.entries(fields)) {\n\t\tconst rawValue = row[key]\n\t\tif (rawValue === undefined || rawValue === null) {\n\t\t\tresult[key] = rawValue ?? null\n\t\t\tcontinue\n\t\t}\n\t\tresult[key] = deserializeValue(rawValue, descriptor)\n\t}\n\n\treturn result\n}\n\n/**\n * Internal key used to embed atomicOps metadata in the data JSON column.\n * This avoids adding a new column to the ops table (no migration needed).\n */\nconst ATOMIC_OPS_KEY = '__kora_atomic_ops__'\n\n/**\n * Internal key used to embed transactionId in the data JSON column.\n */\nconst TX_ID_KEY = '__kora_tx_id__'\n\n/**\n * Internal key used to embed mutationName in the data JSON column.\n */\nconst MUTATION_NAME_KEY = '__kora_mutation__'\n\n/**\n * Serialize an Operation to a row for the operations log table.\n *\n * @param op - The operation to serialize\n * @returns An OperationRow suitable for SQL INSERT\n */\nexport function serializeOperation(op: Operation): OperationRow {\n\tconst hasMetadata = op.transactionId !== undefined || op.mutationName !== undefined\n\tlet dataPayload: Record<string, unknown> | null = null\n\tif (op.data) {\n\t\t// Embed metadata in the data JSON when present\n\t\tdataPayload = { ...op.data }\n\t\tif (op.atomicOps !== undefined && Object.keys(op.atomicOps).length > 0) {\n\t\t\tdataPayload[ATOMIC_OPS_KEY] = op.atomicOps\n\t\t}\n\t\tif (op.transactionId !== undefined) {\n\t\t\tdataPayload[TX_ID_KEY] = op.transactionId\n\t\t}\n\t\tif (op.mutationName !== undefined) {\n\t\t\tdataPayload[MUTATION_NAME_KEY] = op.mutationName\n\t\t}\n\t} else if (hasMetadata) {\n\t\t// For delete operations (data is null), we still need to store metadata\n\t\tdataPayload = {}\n\t\tif (op.transactionId !== undefined) {\n\t\t\tdataPayload[TX_ID_KEY] = op.transactionId\n\t\t}\n\t\tif (op.mutationName !== undefined) {\n\t\t\tdataPayload[MUTATION_NAME_KEY] = op.mutationName\n\t\t}\n\t}\n\n\treturn {\n\t\tid: op.id,\n\t\tnode_id: op.nodeId,\n\t\ttype: op.type,\n\t\trecord_id: op.recordId,\n\t\tdata: dataPayload ? JSON.stringify(dataPayload) : null,\n\t\tprevious_data: op.previousData ? JSON.stringify(op.previousData) : null,\n\t\ttimestamp: HybridLogicalClock.serialize(op.timestamp),\n\t\tsequence_number: op.sequenceNumber,\n\t\tcausal_deps: JSON.stringify(op.causalDeps),\n\t\tschema_version: op.schemaVersion,\n\t}\n}\n\n/**\n * Deserialize a row from the operations log table back to an Operation.\n *\n * @param row - The raw operation row from SQL\n * @returns The deserialized Operation object\n */\nexport function deserializeOperation(row: OperationRow): Operation {\n\tlet data: Record<string, unknown> | null = null\n\tlet atomicOps: Record<string, unknown> | undefined\n\tlet transactionId: string | undefined\n\tlet mutationName: string | undefined\n\n\tif (row.data) {\n\t\tconst parsed = JSON.parse(row.data) as Record<string, unknown>\n\t\t// Extract embedded metadata keys\n\t\tif (ATOMIC_OPS_KEY in parsed) {\n\t\t\tatomicOps = parsed[ATOMIC_OPS_KEY] as Record<string, unknown>\n\t\t}\n\t\tif (TX_ID_KEY in parsed) {\n\t\t\ttransactionId = parsed[TX_ID_KEY] as string\n\t\t}\n\t\tif (MUTATION_NAME_KEY in parsed) {\n\t\t\tmutationName = parsed[MUTATION_NAME_KEY] as string\n\t\t}\n\t\t// Remove metadata keys from data\n\t\tconst { [ATOMIC_OPS_KEY]: _a, [TX_ID_KEY]: _t, [MUTATION_NAME_KEY]: _m, ...rest } = parsed\n\t\tdata = Object.keys(rest).length > 0 ? rest : null\n\t}\n\n\treturn {\n\t\tid: row.id,\n\t\tnodeId: row.node_id,\n\t\ttype: row.type as Operation['type'],\n\t\tcollection: '', // Collection name is derived from the table name by the caller\n\t\trecordId: row.record_id,\n\t\tdata,\n\t\tpreviousData: row.previous_data\n\t\t\t? (JSON.parse(row.previous_data) as Record<string, unknown>)\n\t\t\t: null,\n\t\ttimestamp: HybridLogicalClock.deserialize(row.timestamp),\n\t\tsequenceNumber: row.sequence_number,\n\t\tcausalDeps: JSON.parse(row.causal_deps) as string[],\n\t\tschemaVersion: row.schema_version,\n\t\t...(atomicOps !== undefined ? { atomicOps: atomicOps as Operation['atomicOps'] } : {}),\n\t\t...(transactionId !== undefined ? { transactionId } : {}),\n\t\t...(mutationName !== undefined ? { mutationName } : {}),\n\t}\n}\n\n/**\n * Deserialize an operation row with collection name already known.\n */\nexport function deserializeOperationWithCollection(\n\trow: OperationRow,\n\tcollection: string,\n): Operation {\n\tconst op = deserializeOperation(row)\n\treturn { ...op, collection }\n}\n\nfunction serializeValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tif (value === null || value === undefined) {\n\t\treturn null\n\t}\n\n\tswitch (descriptor.kind) {\n\t\tcase 'boolean':\n\t\t\treturn value ? 1 : 0\n\t\tcase 'array':\n\t\tcase 'object':\n\t\tcase 'json':\n\t\tcase 'blob':\n\t\t\treturn JSON.stringify(value)\n\t\tcase 'richtext':\n\t\t\t// May be a record-shaped value (string/bytes) or an op-data value\n\t\t\t// (tagged { $koraBytes }) — encodeRichtext accepts every form.\n\t\t\treturn encodeRichtext(value as Parameters<typeof encodeRichtext>[0])\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n\nfunction deserializeValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tswitch (descriptor.kind) {\n\t\tcase 'boolean':\n\t\t\treturn value === 1 || value === true\n\t\tcase 'array':\n\t\t\tif (typeof value === 'string') {\n\t\t\t\treturn JSON.parse(value) as unknown[]\n\t\t\t}\n\t\t\treturn value\n\t\tcase 'object':\n\t\tcase 'json':\n\t\tcase 'blob':\n\t\t\tif (typeof value === 'string') {\n\t\t\t\treturn JSON.parse(value) as unknown\n\t\t\t}\n\t\t\treturn value\n\t\tcase 'richtext':\n\t\t\treturn decodeRichtext(value)\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n","import { generateUUIDv7 } from '@korajs/core'\nimport type { Operation, SchemaDefinition, VersionVector } from '@korajs/core'\nimport { deserializeOperationWithCollection } from '../serialization/serializer'\nimport type { OperationRow, StorageAdapter } from '../types'\nimport type {\n\tBackupManifest,\n\tBackupOptions,\n\tBackupProgress,\n\tRestoreOptions,\n\tRestoreResult,\n} from './types'\n\n// ── Section I/O helpers ──────────────────────────────────────────────────────\n\nfunction encodeSection(name: string, content: Uint8Array): Uint8Array {\n\tconst nameBytes = new TextEncoder().encode(name)\n\tconst header = new Uint8Array(8)\n\tconst dv = new DataView(header.buffer)\n\tdv.setUint32(0, nameBytes.length, true)\n\tdv.setUint32(4, content.length, true)\n\n\tconst result = new Uint8Array(header.length + nameBytes.length + content.length)\n\tresult.set(header, 0)\n\tresult.set(nameBytes, 8)\n\tresult.set(content, 8 + nameBytes.length)\n\treturn result\n}\n\nfunction encodeJsonSection(name: string, data: unknown): Uint8Array {\n\tconst json = JSON.stringify(data)\n\treturn encodeSection(name, new TextEncoder().encode(json))\n}\n\nfunction encodeNdjsonSection(name: string, records: unknown[]): Uint8Array {\n\tconst lines = `${records.map((r) => JSON.stringify(r)).join('\\n')}\\n`\n\treturn encodeSection(name, new TextEncoder().encode(lines))\n}\n\nfunction readUint32(view: DataView, offset: number): number {\n\treturn view.getUint32(offset, true)\n}\n\ninterface Section {\n\tname: string\n\tcontent: Uint8Array\n}\n\nfunction parseSections(data: Uint8Array): Section[] {\n\tconst sections: Section[] = []\n\tconst dv = new DataView(data.buffer, data.byteOffset, data.byteLength)\n\tlet offset = 0\n\n\twhile (offset + 8 <= data.byteLength) {\n\t\tconst nameLen = readUint32(dv, offset)\n\t\tconst contentLen = readUint32(dv, offset + 4)\n\t\toffset += 8\n\n\t\tif (offset + nameLen + contentLen > data.byteLength) break\n\n\t\tconst name = new TextDecoder().decode(data.slice(offset, offset + nameLen))\n\t\toffset += nameLen\n\n\t\tconst content = data.slice(offset, offset + contentLen)\n\t\toffset += contentLen\n\n\t\tsections.push({ name, content })\n\t}\n\n\treturn sections\n}\n\nfunction findSection(sections: Section[], name: string): Uint8Array | null {\n\tfor (const s of sections) {\n\t\tif (s.name === name) return s.content\n\t}\n\treturn null\n}\n\nfunction parseJsonSection<T>(sections: Section[], name: string): T | null {\n\tconst content = findSection(sections, name)\n\tif (!content) return null\n\treturn JSON.parse(new TextDecoder().decode(content)) as T\n}\n\n/**\n * Export format version. Bump on breaking changes.\n */\nconst BACKUP_VERSION = 1\n\n/**\n * Export a backup from a store.\n *\n * Reads all data via the adapter and produces a portable binary backup.\n *\n * @param adapter - The storage adapter\n * @param schema - The schema definition\n * @param nodeId - Current node ID\n * @param schemaVersion - Schema version\n * @param options - Backup options\n * @returns Backup as a Uint8Array\n */\nexport async function exportBackup(\n\tadapter: StorageAdapter,\n\tschema: SchemaDefinition,\n\tnodeId: string,\n\tschemaVersion: number,\n\toptions?: BackupOptions,\n): Promise<Uint8Array> {\n\tconst onProgress = options?.onProgress ?? (() => {})\n\tconst includeRecords = options?.includeRecords ?? true\n\tconst collectionFilter = options?.collections\n\tconst collections = collectionFilter\n\t\t? Object.keys(schema.collections).filter((c) => collectionFilter.includes(c))\n\t\t: Object.keys(schema.collections)\n\n\tonProgress({ phase: 'reading', progress: 0, message: 'Reading version vector' })\n\tconst versionVector = await readVersionVector(adapter)\n\tonProgress({ phase: 'reading', progress: 0.1, message: 'Reading metadata' })\n\tconst meta = await readMeta(adapter)\n\tonProgress({ phase: 'reading', progress: 0.2, message: 'Reading operations' })\n\tconst operations = await readAllOperations(adapter, schema)\n\tonProgress({ phase: 'reading', progress: 0.5, message: 'Reading records' })\n\n\tconst sections: Uint8Array[] = []\n\tlet allContentForChecksum = new Uint8Array(0)\n\n\t// Helper: add a section and update running checksum content\n\tconst addSection = (name: string, data: Uint8Array) => {\n\t\tsections.push(data)\n\t\tconst newLen = allContentForChecksum.length + data.length\n\t\tconst combined = new Uint8Array(newLen)\n\t\tcombined.set(allContentForChecksum, 0)\n\t\tcombined.set(data, allContentForChecksum.length)\n\t\tallContentForChecksum = combined\n\t}\n\n\t// Version vector section\n\tconst vvObj: Record<string, number> = {}\n\tfor (const [nid, seq] of versionVector) {\n\t\tvvObj[nid] = seq\n\t}\n\taddSection('version_vector', encodeJsonSection('version_vector', vvObj))\n\n\t// Meta section\n\tconst metaObj: Record<string, string> = {}\n\tfor (const row of meta) {\n\t\tmetaObj[row.key] = row.value\n\t}\n\taddSection('meta', encodeJsonSection('meta', metaObj))\n\n\t// Operations section\n\tconst opLines = `${operations.map((op) => JSON.stringify(op)).join('\\n')}\\n`\n\taddSection('operations', encodeSection('operations', new TextEncoder().encode(opLines)))\n\n\t// Records sections (optional)\n\tlet totalRecords = 0\n\tif (includeRecords) {\n\t\tfor (const col of collections) {\n\t\t\tconst records = await readCollectionRecords(adapter, col)\n\t\t\tif (records.length > 0) {\n\t\t\t\tconst lines = `${records.map((r) => JSON.stringify(r)).join('\\n')}\\n`\n\t\t\t\tconst sectionName = `records:${col}`\n\t\t\t\taddSection(sectionName, encodeSection(sectionName, new TextEncoder().encode(lines)))\n\t\t\t\ttotalRecords += records.length\n\t\t\t}\n\t\t}\n\t}\n\tonProgress({ phase: 'reading', progress: 0.9, message: 'Computing checksum' })\n\n\t// Compute SHA-256 checksum over all content sections\n\tconst checksumHex = await computeSha256(allContentForChecksum)\n\tonProgress({ phase: 'writing', progress: 1, message: 'Finalizing' })\n\n\t// Build manifest\n\tconst manifest: BackupManifest = {\n\t\tversion: BACKUP_VERSION,\n\t\tcreatedAt: Date.now(),\n\t\tnodeId,\n\t\tschemaVersion,\n\t\toperationCount: operations.length,\n\t\tcollections,\n\t\tincludesRecords: includeRecords,\n\t\tchecksum: checksumHex,\n\t}\n\n\t// Final output: header + manifest + all content sections + checksum section\n\tconst header = new Uint8Array(0)\n\n\t// Merge manifest + all sections + checksum section\n\tconst manifestSection = encodeJsonSection('manifest', manifest)\n\tconst checksumSection = encodeSection('checksum', new TextEncoder().encode(checksumHex))\n\n\tconst totalLen = manifestSection.length + allContentForChecksum.length + checksumSection.length\n\tconst result = new Uint8Array(totalLen)\n\tlet pos = 0\n\tresult.set(manifestSection, pos)\n\tpos += manifestSection.length\n\tresult.set(allContentForChecksum, pos)\n\tpos += allContentForChecksum.length\n\tresult.set(checksumSection, pos)\n\n\treturn result\n}\n\n/**\n * Read backup manifest without loading the entire backup.\n * Parses only the first section (which is always the manifest).\n *\n * @param data - The raw backup data\n * @returns The backup manifest\n */\nexport function readBackupManifest(data: Uint8Array): BackupManifest {\n\tconst sections = parseSections(data)\n\tconst manifest = parseJsonSection<BackupManifest>(sections, 'manifest')\n\tif (!manifest) {\n\t\tthrow new Error('Invalid backup: manifest section not found')\n\t}\n\treturn manifest\n}\n\n/**\n * Validate the backup checksum.\n *\n * @param data - The raw backup data\n * @returns True if the checksum is valid\n */\nexport async function verifyBackupChecksum(data: Uint8Array): Promise<boolean> {\n\tconst sections = parseSections(data)\n\tconst manifest = parseJsonSection<BackupManifest>(sections, 'manifest')\n\tif (!manifest) return false\n\n\tconst storedChecksum = manifest.checksum\n\tif (!storedChecksum) return false\n\n\t// Recompute checksum over content sections (everything after manifest, before checksum)\n\tconst manifestSection = findSection(sections, 'manifest')\n\tif (!manifestSection) return false\n\n\t// Find the checksum section\n\tconst checksumSection = findSection(sections, 'checksum')\n\n\t// The content spans from end of manifest section to start of checksum section\n\tconst checksumBytes = checksumSection\n\t\t? new TextEncoder().encode(manifest.checksum)\n\t\t: new Uint8Array(0)\n\n\t// Rebuild all content sections and hash them\n\tconst contentSections = sections.filter((s) => s.name !== 'manifest' && s.name !== 'checksum')\n\n\tlet contentForHash = new Uint8Array(0)\n\tfor (const section of contentSections) {\n\t\tconst sectionBytes = encodeSection(section.name, section.content)\n\t\tconst newLen = contentForHash.length + sectionBytes.length\n\t\tconst combined = new Uint8Array(newLen)\n\t\tcombined.set(contentForHash, 0)\n\t\tcombined.set(sectionBytes, contentForHash.length)\n\t\tcontentForHash = combined\n\t}\n\n\tconst computed = await computeSha256(contentForHash)\n\treturn computed === storedChecksum\n}\n\n/**\n * Restore a backup into a store.\n *\n * @param adapter - The storage adapter\n * @param schema - The schema definition\n * @param data - The backup data\n * @param options - Restore options\n * @returns Result of the restore operation\n */\nexport async function restoreBackup(\n\tadapter: StorageAdapter,\n\tschema: SchemaDefinition,\n\tdata: Uint8Array,\n\toptions?: RestoreOptions,\n): Promise<RestoreResult> {\n\tconst startTime = Date.now()\n\tconst onProgress = options?.onProgress ?? (() => {})\n\tconst collectionFilter = options?.collections\n\n\tonProgress({ phase: 'verifying', progress: 0, message: 'Parsing backup' })\n\n\tconst sections = parseSections(data)\n\tconst manifest = parseJsonSection<BackupManifest>(sections, 'manifest')\n\tif (!manifest) {\n\t\treturn {\n\t\t\toperationsRestored: 0,\n\t\t\trecordsRestored: 0,\n\t\t\tsuccess: false,\n\t\t\terror: 'Invalid backup: manifest section not found',\n\t\t\tduration: Date.now() - startTime,\n\t\t}\n\t}\n\n\t// Validate format version\n\tif (manifest.version !== BACKUP_VERSION) {\n\t\treturn {\n\t\t\toperationsRestored: 0,\n\t\t\trecordsRestored: 0,\n\t\t\tsuccess: false,\n\t\t\terror: `Unsupported backup version: ${manifest.version}`,\n\t\t\tduration: Date.now() - startTime,\n\t\t}\n\t}\n\n\tonProgress({ phase: 'verifying', progress: 0.2, message: 'Verifying checksum' })\n\n\t// Verify checksum\n\tconst valid = await verifyBackupChecksum(data)\n\tif (!valid) {\n\t\treturn {\n\t\t\toperationsRestored: 0,\n\t\t\trecordsRestored: 0,\n\t\t\tsuccess: false,\n\t\t\terror: 'Backup checksum mismatch: data may be corrupted',\n\t\t\tduration: Date.now() - startTime,\n\t\t}\n\t}\n\n\tonProgress({ phase: 'restoring', progress: 0.3, message: 'Loading operations' })\n\n\t// Parse operations\n\tconst opsContent = findSection(sections, 'operations')\n\tlet operations: Operation[] = []\n\tif (opsContent) {\n\t\tconst text = new TextDecoder().decode(opsContent)\n\t\tconst lines = text\n\t\t\t.trim()\n\t\t\t.split('\\n')\n\t\t\t.filter((l) => l.length > 0)\n\t\toperations = lines.map((line) => JSON.parse(line) as Operation)\n\t}\n\n\t// Filter collections if requested\n\tif (collectionFilter) {\n\t\toperations = operations.filter((op) => collectionFilter.includes(op.collection))\n\t}\n\n\t// Load version vector\n\tconst vvData = parseJsonSection<Record<string, number>>(sections, 'version_vector')\n\n\t// Load meta\n\tconst metaData = parseJsonSection<Record<string, string>>(sections, 'meta')\n\n\tonProgress({ phase: 'restoring', progress: 0.4, message: 'Applying operations' })\n\n\tif (options?.merge) {\n\t\t// Merge mode: replay operations through applyRemoteOperation.\n\t\t// This won't work directly since adapter doesn't have applyRemoteOperation.\n\t\t// Instead, we import the raw data into the adapter.\n\t\tawait adapter.transaction(async (tx) => {\n\t\t\t// Import version vector\n\t\t\tif (vvData) {\n\t\t\t\tfor (const [nid, seq] of Object.entries(vvData)) {\n\t\t\t\t\tawait tx.execute(\n\t\t\t\t\t\t'INSERT OR REPLACE INTO _kora_version_vector (node_id, sequence_number) VALUES (?, ?)',\n\t\t\t\t\t\t[nid, seq],\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Import meta\n\t\t\tif (metaData) {\n\t\t\t\tfor (const [key, value] of Object.entries(metaData)) {\n\t\t\t\t\tawait tx.execute('INSERT OR REPLACE INTO _kora_meta (key, value) VALUES (?, ?)', [\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t])\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Import operations into _kora_ops_ tables\n\t\t\tfor (const op of operations) {\n\t\t\t\tconst collection = op.collection\n\t\t\t\tconst opRow = {\n\t\t\t\t\tid: op.id,\n\t\t\t\t\tnode_id: op.nodeId,\n\t\t\t\t\ttype: op.type,\n\t\t\t\t\trecord_id: op.recordId,\n\t\t\t\t\tdata: op.data !== null ? JSON.stringify(op.data) : null,\n\t\t\t\t\tprevious_data: op.previousData !== null ? JSON.stringify(op.previousData) : null,\n\t\t\t\t\ttimestamp: JSON.stringify(op.timestamp),\n\t\t\t\t\tsequence_number: op.sequenceNumber,\n\t\t\t\t\tcausal_deps: JSON.stringify(op.causalDeps),\n\t\t\t\t\tschema_version: op.schemaVersion,\n\t\t\t\t}\n\n\t\t\t\tawait tx.execute(\n\t\t\t\t\t`INSERT OR IGNORE INTO _kora_ops_${collection} (id, node_id, type, record_id, data, previous_data, timestamp, sequence_number, causal_deps, schema_version) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n\t\t\t\t\t[\n\t\t\t\t\t\topRow.id,\n\t\t\t\t\t\topRow.node_id,\n\t\t\t\t\t\topRow.type,\n\t\t\t\t\t\topRow.record_id,\n\t\t\t\t\t\topRow.data,\n\t\t\t\t\t\topRow.previous_data,\n\t\t\t\t\t\topRow.timestamp,\n\t\t\t\t\t\topRow.sequence_number,\n\t\t\t\t\t\topRow.causal_deps,\n\t\t\t\t\t\topRow.schema_version,\n\t\t\t\t\t],\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\t} else {\n\t\t// Replace mode: clear existing data and bulk import\n\t\tawait adapter.transaction(async (tx) => {\n\t\t\t// Clear existing data\n\t\t\tfor (const collection of Object.keys(schema.collections)) {\n\t\t\t\tawait tx.execute(`DELETE FROM _kora_ops_${collection}`)\n\t\t\t\tawait tx.execute(`DELETE FROM ${collection}`)\n\t\t\t}\n\t\t\tawait tx.execute('DELETE FROM _kora_version_vector')\n\t\t\tawait tx.execute('DELETE FROM _kora_meta')\n\n\t\t\t// Import version vector\n\t\t\tif (vvData) {\n\t\t\t\tfor (const [nid, seq] of Object.entries(vvData)) {\n\t\t\t\t\tawait tx.execute(\n\t\t\t\t\t\t'INSERT INTO _kora_version_vector (node_id, sequence_number) VALUES (?, ?)',\n\t\t\t\t\t\t[nid, seq],\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Import meta\n\t\t\tif (metaData) {\n\t\t\t\tfor (const [key, value] of Object.entries(metaData)) {\n\t\t\t\t\tawait tx.execute('INSERT INTO _kora_meta (key, value) VALUES (?, ?)', [key, value])\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Import operations\n\t\t\tfor (const op of operations) {\n\t\t\t\tconst collection = op.collection\n\t\t\t\tawait tx.execute(\n\t\t\t\t\t`INSERT INTO _kora_ops_${collection} (id, node_id, type, record_id, data, previous_data, timestamp, sequence_number, causal_deps, schema_version) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n\t\t\t\t\t[\n\t\t\t\t\t\top.id,\n\t\t\t\t\t\top.nodeId,\n\t\t\t\t\t\top.type,\n\t\t\t\t\t\top.recordId,\n\t\t\t\t\t\top.data !== null ? JSON.stringify(op.data) : null,\n\t\t\t\t\t\top.previousData !== null ? JSON.stringify(op.previousData) : null,\n\t\t\t\t\t\tJSON.stringify(op.timestamp),\n\t\t\t\t\t\top.sequenceNumber,\n\t\t\t\t\t\tJSON.stringify(op.causalDeps),\n\t\t\t\t\t\top.schemaVersion,\n\t\t\t\t\t],\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\t}\n\n\tonProgress({ phase: 'restoring', progress: 0.8, message: 'Restoring records' })\n\n\t// Restore records sections (optional)\n\tlet recordsRestored = 0\n\tif (manifest.includesRecords) {\n\t\tfor (const col of manifest.collections) {\n\t\t\tif (collectionFilter && !collectionFilter.includes(col)) continue\n\n\t\t\tconst sectionContent = findSection(sections, `records:${col}`)\n\t\t\tif (!sectionContent) continue\n\n\t\t\tconst text = new TextDecoder().decode(sectionContent)\n\t\t\tconst lines = text\n\t\t\t\t.trim()\n\t\t\t\t.split('\\n')\n\t\t\t\t.filter((l) => l.length > 0)\n\t\t\tconst records = lines.map((line) => JSON.parse(line) as Record<string, unknown>)\n\n\t\t\tif (records.length === 0) continue\n\n\t\t\tawait adapter.transaction(async (tx) => {\n\t\t\t\tfor (const record of records) {\n\t\t\t\t\tconst keys = Object.keys(record)\n\t\t\t\t\tconst placeholders = keys.map(() => '?').join(', ')\n\t\t\t\t\tconst values = keys.map((k) => {\n\t\t\t\t\t\tconst v = record[k]\n\t\t\t\t\t\tif (typeof v === 'boolean') return v ? 1 : 0\n\t\t\t\t\t\tif (Array.isArray(v) || (typeof v === 'object' && v !== null)) return JSON.stringify(v)\n\t\t\t\t\t\treturn v\n\t\t\t\t\t})\n\n\t\t\t\t\tawait tx.execute(\n\t\t\t\t\t\t`INSERT OR REPLACE INTO ${col} (${keys.join(', ')}) VALUES (${placeholders})`,\n\t\t\t\t\t\tvalues,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t})\n\n\t\t\trecordsRestored += records.length\n\t\t}\n\t}\n\n\tonProgress({ phase: 'restoring', progress: 1, message: 'Done' })\n\n\treturn {\n\t\toperationsRestored: operations.length,\n\t\trecordsRestored,\n\t\tsuccess: true,\n\t\tduration: Date.now() - startTime,\n\t}\n}\n\n// ── Reading helpers ──────────────────────────────────────────────────────────\n\nasync function readVersionVector(adapter: StorageAdapter): Promise<Map<string, number>> {\n\tconst rows = await adapter.query<{ node_id: string; sequence_number: number }>(\n\t\t'SELECT node_id, sequence_number FROM _kora_version_vector',\n\t)\n\tconst vv = new Map<string, number>()\n\tfor (const row of rows) {\n\t\tvv.set(row.node_id, row.sequence_number)\n\t}\n\treturn vv\n}\n\ninterface MetaRow {\n\tkey: string\n\tvalue: string\n}\n\nasync function readMeta(adapter: StorageAdapter): Promise<MetaRow[]> {\n\treturn adapter.query<MetaRow>('SELECT key, value FROM _kora_meta')\n}\n\nasync function readAllOperations(\n\tadapter: StorageAdapter,\n\tschema: SchemaDefinition,\n): Promise<Operation[]> {\n\tconst allOps: Operation[] = []\n\n\tfor (const collectionName of Object.keys(schema.collections)) {\n\t\tconst rows = await adapter.query<OperationRow>(\n\t\t\t`SELECT * FROM _kora_ops_${collectionName} ORDER BY sequence_number ASC`,\n\t\t)\n\n\t\tfor (const row of rows) {\n\t\t\tallOps.push(deserializeOperationWithCollection(row, collectionName))\n\t\t}\n\t}\n\n\treturn allOps\n}\n\nasync function readCollectionRecords(\n\tadapter: StorageAdapter,\n\tcollection: string,\n): Promise<Record<string, unknown>[]> {\n\treturn adapter.query<Record<string, unknown>>(`SELECT * FROM ${collection} WHERE _deleted = 0`)\n}\n\n// ── Crypto helpers ───────────────────────────────────────────────────────────\n\nasync function computeSha256(data: Uint8Array<ArrayBuffer>): Promise<string> {\n\tconst hashBuffer = await crypto.subtle.digest('SHA-256', data)\n\tconst hashArray = Array.from(new Uint8Array(hashBuffer))\n\treturn hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')\n}\n","const WIRE_BYTES_KEY = '__kora_bytes__'\n\n/**\n * JSON.stringify replacer that preserves binary field values (e.g. richtext).\n */\nexport function auditJsonReplacer(_key: string, value: unknown): unknown {\n\tif (value instanceof Uint8Array) {\n\t\tlet binary = ''\n\t\tfor (let i = 0; i < value.length; i++) {\n\t\t\tbinary += String.fromCharCode(value[i] as number)\n\t\t}\n\t\treturn { [WIRE_BYTES_KEY]: btoa(binary) }\n\t}\n\treturn value\n}\n\n/**\n * JSON.parse reviver that restores binary field values.\n */\nexport function auditJsonReviver(_key: string, value: unknown): unknown {\n\tif (\n\t\tvalue !== null &&\n\t\ttypeof value === 'object' &&\n\t\tWIRE_BYTES_KEY in value &&\n\t\ttypeof (value as Record<string, unknown>)[WIRE_BYTES_KEY] === 'string'\n\t) {\n\t\tconst encoded = (value as Record<string, unknown>)[WIRE_BYTES_KEY]\n\t\tif (typeof encoded !== 'string') {\n\t\t\treturn value\n\t\t}\n\t\tconst binary = atob(encoded)\n\t\tconst bytes = new Uint8Array(binary.length)\n\t\tfor (let i = 0; i < binary.length; i++) {\n\t\t\tbytes[i] = binary.charCodeAt(i)\n\t\t}\n\t\treturn bytes\n\t}\n\treturn value\n}\n\n/**\n * Serialize a value for durable audit storage or export.\n */\nexport function serializeAuditJson(value: unknown): string {\n\treturn JSON.stringify(value, auditJsonReplacer)\n}\n\n/**\n * Deserialize audit JSON back to typed values.\n */\nexport function deserializeAuditJson<T>(json: string): T {\n\treturn JSON.parse(json, auditJsonReviver) as T\n}\n","import { generateUUIDv7 } from '@korajs/core'\nimport type { KoraEvent, MergeTrace } from '@korajs/core'\nimport type { StorageAdapter } from '../types'\nimport { deserializeAuditJson, serializeAuditJson } from './audit-json'\nimport type { AuditTraceQuery, PersistedAuditTrace } from './types'\n\ninterface AuditTraceRow {\n\tid: string\n\trecorded_at: number\n\tevent_type: string\n\tcollection: string\n\trecord_id: string\n\tfield: string\n\tstrategy: string\n\ttier: number\n\tconstraint_name: string | null\n\ttrace_json: string\n}\n\n/**\n * Build a {@link PersistedAuditTrace} from a merge-related Kora event.\n */\nexport function persistedAuditTraceFromEvent(\n\tevent: Extract<KoraEvent, { type: 'merge:completed' | 'merge:conflict' | 'constraint:violated' }>,\n): PersistedAuditTrace {\n\treturn {\n\t\tid: generateUUIDv7(),\n\t\trecordedAt: Date.now(),\n\t\teventType: event.type,\n\t\tconstraint: event.type === 'constraint:violated' ? event.constraint : undefined,\n\t\ttrace: event.trace,\n\t}\n}\n\n/**\n * Append a merge trace to the durable audit log.\n */\nexport async function appendAuditTrace(\n\tadapter: StorageAdapter,\n\ttrace: PersistedAuditTrace,\n): Promise<void> {\n\tconst collection = trace.trace.operationA.collection\n\tconst recordId = trace.trace.operationA.recordId\n\n\tawait adapter.execute(\n\t\t`INSERT INTO _kora_audit_traces (\n\t\t\tid, recorded_at, event_type, collection, record_id, field, strategy, tier, constraint_name, trace_json\n\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n\t\t[\n\t\t\ttrace.id,\n\t\t\ttrace.recordedAt,\n\t\t\ttrace.eventType,\n\t\t\tcollection,\n\t\t\trecordId,\n\t\t\ttrace.trace.field,\n\t\t\ttrace.trace.strategy,\n\t\t\ttrace.trace.tier,\n\t\t\ttrace.constraint ?? null,\n\t\t\tserializeAuditJson(trace),\n\t\t],\n\t)\n}\n\n/**\n * Load persisted audit traces with optional filters.\n */\nexport async function readAuditTraces(\n\tadapter: StorageAdapter,\n\tquery?: AuditTraceQuery,\n): Promise<PersistedAuditTrace[]> {\n\tconst conditions: string[] = []\n\tconst params: unknown[] = []\n\n\tif (query?.collections && query.collections.length > 0) {\n\t\tconst placeholders = query.collections.map(() => '?').join(', ')\n\t\tconditions.push(`collection IN (${placeholders})`)\n\t\tparams.push(...query.collections)\n\t}\n\tif (query?.since !== undefined) {\n\t\tconditions.push('recorded_at >= ?')\n\t\tparams.push(query.since)\n\t}\n\tif (query?.until !== undefined) {\n\t\tconditions.push('recorded_at <= ?')\n\t\tparams.push(query.until)\n\t}\n\n\tconst whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n\tconst rows = await adapter.query<AuditTraceRow>(\n\t\t`SELECT * FROM _kora_audit_traces ${whereClause} ORDER BY recorded_at ASC, id ASC`,\n\t\tparams,\n\t)\n\n\treturn rows.map(rowToPersistedTrace)\n}\n\nfunction rowToPersistedTrace(row: AuditTraceRow): PersistedAuditTrace {\n\treturn deserializeAuditJson<PersistedAuditTrace>(row.trace_json)\n}\n\n/**\n * Count persisted audit traces (for diagnostics).\n */\nexport async function countAuditTraces(adapter: StorageAdapter): Promise<number> {\n\tconst rows = await adapter.query<{ count: number }>(\n\t\t'SELECT COUNT(*) as count FROM _kora_audit_traces',\n\t)\n\treturn rows[0]?.count ?? 0\n}\n\n/**\n * Extract collection and record id from a merge trace for indexing.\n */\nexport function auditTraceIndexFields(trace: MergeTrace): {\n\tcollection: string\n\trecordId: string\n} {\n\treturn {\n\t\tcollection: trace.operationA.collection,\n\t\trecordId: trace.operationA.recordId,\n\t}\n}\n","import type { Operation, SchemaDefinition } from '@korajs/core'\nimport { deserializeOperationWithCollection } from '../serialization/serializer'\nimport type { StorageAdapter } from '../types'\nimport type { OperationRow } from '../types'\nimport { deserializeAuditJson, serializeAuditJson } from './audit-json'\nimport { readAuditTraces } from './audit-trace-store'\nimport type {\n\tAuditExportManifest,\n\tAuditExportOptions,\n\tAuditExportPayload,\n\tAuditTraceQuery,\n\tPersistedAuditTrace,\n} from './types'\n\nfunction encodeSection(name: string, content: Uint8Array): Uint8Array {\n\tconst nameBytes = new TextEncoder().encode(name)\n\tconst header = new Uint8Array(8)\n\tconst view = new DataView(header.buffer)\n\tview.setUint32(0, nameBytes.length, true)\n\tview.setUint32(4, content.length, true)\n\n\tconst result = new Uint8Array(header.length + nameBytes.length + content.length)\n\tresult.set(header, 0)\n\tresult.set(nameBytes, 8)\n\tresult.set(content, 8 + nameBytes.length)\n\treturn result\n}\n\nfunction encodeJsonSection(name: string, data: unknown): Uint8Array {\n\treturn encodeSection(name, new TextEncoder().encode(serializeAuditJson(data)))\n}\n\nfunction encodeNdjsonSection(name: string, records: unknown[]): Uint8Array {\n\tconst lines = `${records.map((record) => serializeAuditJson(record)).join('\\n')}\\n`\n\treturn encodeSection(name, new TextEncoder().encode(lines))\n}\n\nfunction readUint32(view: DataView, offset: number): number {\n\treturn view.getUint32(offset, true)\n}\n\ninterface Section {\n\tname: string\n\tcontent: Uint8Array\n}\n\nfunction parseSections(data: Uint8Array): Section[] {\n\tconst sections: Section[] = []\n\tconst view = new DataView(data.buffer, data.byteOffset, data.byteLength)\n\tlet offset = 0\n\n\twhile (offset + 8 <= data.byteLength) {\n\t\tconst nameLen = readUint32(view, offset)\n\t\tconst contentLen = readUint32(view, offset + 4)\n\t\toffset += 8\n\n\t\tif (offset + nameLen + contentLen > data.byteLength) {\n\t\t\tbreak\n\t\t}\n\n\t\tconst name = new TextDecoder().decode(data.slice(offset, offset + nameLen))\n\t\toffset += nameLen\n\n\t\tconst content = data.slice(offset, offset + contentLen)\n\t\toffset += contentLen\n\n\t\tsections.push({ name, content })\n\t}\n\n\treturn sections\n}\n\nfunction findSection(sections: Section[], name: string): Uint8Array | null {\n\tfor (const section of sections) {\n\t\tif (section.name === name) {\n\t\t\treturn section.content\n\t\t}\n\t}\n\treturn null\n}\n\nasync function computeSha256(data: Uint8Array<ArrayBuffer>): Promise<string> {\n\tconst hashBuffer = await crypto.subtle.digest('SHA-256', data)\n\treturn Array.from(new Uint8Array(hashBuffer))\n\t\t.map((byte) => byte.toString(16).padStart(2, '0'))\n\t\t.join('')\n}\n\nasync function readAllOperations(\n\tadapter: StorageAdapter,\n\tschema: SchemaDefinition,\n\tcollectionFilter?: string[],\n): Promise<Operation[]> {\n\tconst collections = collectionFilter\n\t\t? Object.keys(schema.collections).filter((name) => collectionFilter.includes(name))\n\t\t: Object.keys(schema.collections)\n\n\tconst allOps: Operation[] = []\n\tfor (const collectionName of collections) {\n\t\tconst rows = await adapter.query<OperationRow>(\n\t\t\t`SELECT * FROM _kora_ops_${collectionName} ORDER BY sequence_number ASC`,\n\t\t)\n\n\t\tfor (const row of rows) {\n\t\t\tallOps.push(deserializeOperationWithCollection(row, collectionName))\n\t\t}\n\t}\n\n\treturn allOps\n}\n\nfunction filterOperationsByCollections(\n\toperations: Operation[],\n\tcollectionFilter?: string[],\n): Operation[] {\n\tif (!collectionFilter || collectionFilter.length === 0) {\n\t\treturn operations\n\t}\n\tconst allowed = new Set(collectionFilter)\n\treturn operations.filter((op) => allowed.has(op.collection))\n}\n\n/**\n * Export operations and persisted merge traces as a portable binary audit bundle.\n */\nexport async function exportAudit(\n\tadapter: StorageAdapter,\n\tschema: SchemaDefinition,\n\tnodeId: string,\n\tschemaVersion: number,\n\toptions?: AuditExportOptions,\n): Promise<Uint8Array> {\n\tconst onProgress = options?.onProgress ?? (() => {})\n\tconst traceQuery: AuditTraceQuery = {\n\t\tcollections: options?.collections,\n\t\tsince: options?.since,\n\t\tuntil: options?.until,\n\t}\n\n\tonProgress({ phase: 'reading', progress: 0, message: 'Reading operations' })\n\tconst operations = filterOperationsByCollections(\n\t\tawait readAllOperations(adapter, schema, options?.collections),\n\t\toptions?.collections,\n\t)\n\n\tonProgress({ phase: 'reading', progress: 0.4, message: 'Reading merge traces' })\n\tconst mergeTraces = await readAuditTraces(adapter, traceQuery)\n\n\tonProgress({ phase: 'writing', progress: 0.7, message: 'Encoding audit export' })\n\tconst sections: Uint8Array[] = []\n\tlet contentForChecksum = new Uint8Array(0)\n\n\tconst addSection = (section: Uint8Array): void => {\n\t\tsections.push(section)\n\t\tconst combined = new Uint8Array(contentForChecksum.length + section.length)\n\t\tcombined.set(contentForChecksum, 0)\n\t\tcombined.set(section, contentForChecksum.length)\n\t\tcontentForChecksum = combined\n\t}\n\n\taddSection(encodeNdjsonSection('operations', operations))\n\taddSection(encodeNdjsonSection('merge_traces', mergeTraces))\n\n\tonProgress({ phase: 'verifying', progress: 0.9, message: 'Computing checksum' })\n\tconst checksum = await computeSha256(contentForChecksum as Uint8Array<ArrayBuffer>)\n\n\tconst manifest: AuditExportManifest = {\n\t\tversion: 1,\n\t\texportedAt: Date.now(),\n\t\tnodeId,\n\t\tschemaVersion,\n\t\toperationCount: operations.length,\n\t\tmergeTraceCount: mergeTraces.length,\n\t\tchecksum,\n\t}\n\n\tconst manifestSection = encodeJsonSection('manifest', manifest)\n\tconst checksumSection = encodeSection('checksum', new TextEncoder().encode(checksum))\n\n\tonProgress({ phase: 'writing', progress: 1, message: 'Finalizing' })\n\n\tconst parts = [manifestSection, ...sections, checksumSection]\n\tconst finalOutput = new Uint8Array(parts.reduce((sum, part) => sum + part.length, 0))\n\tlet offset = 0\n\tfor (const part of parts) {\n\t\tfinalOutput.set(part, offset)\n\t\toffset += part.length\n\t}\n\n\treturn finalOutput\n}\n\n/**\n * Decode an audit export binary into structured data.\n */\nexport function decodeAuditExport(data: Uint8Array): AuditExportPayload {\n\tconst sections = parseSections(data)\n\tconst manifest = JSON.parse(\n\t\tnew TextDecoder().decode(findSection(sections, 'manifest') ?? new Uint8Array()),\n\t) as AuditExportManifest\n\n\tconst operationsContent = findSection(sections, 'operations')\n\tconst mergeTracesContent = findSection(sections, 'merge_traces')\n\n\tconst operations = parseNdjsonSection<Operation>(operationsContent)\n\tconst mergeTraces = parseNdjsonSection<PersistedAuditTrace>(mergeTracesContent)\n\n\treturn { manifest, operations, mergeTraces }\n}\n\n/**\n * Read only the manifest from an audit export without decoding all sections.\n */\nexport function readAuditExportManifest(data: Uint8Array): AuditExportManifest {\n\tconst sections = parseSections(data)\n\tconst manifestContent = findSection(sections, 'manifest')\n\tif (!manifestContent) {\n\t\tthrow new Error('Invalid audit export: missing manifest section')\n\t}\n\treturn JSON.parse(new TextDecoder().decode(manifestContent)) as AuditExportManifest\n}\n\n/**\n * Verify the checksum of an audit export file.\n */\nexport async function verifyAuditExportChecksum(data: Uint8Array): Promise<boolean> {\n\tconst sections = parseSections(data)\n\tconst manifest = readAuditExportManifest(data)\n\tconst contentSections = sections.filter(\n\t\t(section) => section.name !== 'manifest' && section.name !== 'checksum',\n\t)\n\n\tlet content = new Uint8Array(0)\n\tfor (const section of contentSections) {\n\t\tconst encoded = encodeSection(section.name, section.content)\n\t\tconst combined = new Uint8Array(content.length + encoded.length)\n\t\tcombined.set(content, 0)\n\t\tcombined.set(encoded, content.length)\n\t\tcontent = combined\n\t}\n\n\tconst checksum = await computeSha256(content as Uint8Array<ArrayBuffer>)\n\treturn checksum === manifest.checksum\n}\n\nfunction parseNdjsonSection<T>(content: Uint8Array | null): T[] {\n\tif (!content || content.length === 0) {\n\t\treturn []\n\t}\n\tconst text = new TextDecoder().decode(content).trim()\n\tif (text.length === 0) {\n\t\treturn []\n\t}\n\treturn text.split('\\n').map((line) => deserializeAuditJson<T>(line))\n}\n","// @korajs/store — public API\n// Every export here is a public API commitment. Be explicit.\n\n// === Types ===\nexport type {\n\tApplyRemoteOptions,\n\tApplyResult,\n\tLocalMutationHandler,\n\tTransactionBufferedEntry,\n\tTransactionCommitBatch,\n\tTransactionCommitResult,\n\tMaterializedRowSnapshot,\n\tRowVersionState,\n\tCollectionRecord,\n\tReplaySnapshot,\n\tMigrationPlan,\n\tOrderByClause,\n\tOrderByDirection,\n\tQueryDescriptor,\n\tStoreConfig,\n\tStoreIsolation,\n\tStorageAdapter,\n\tSubscriptionCallback,\n\tTransaction,\n\tWhereClause,\n\tWhereOperators,\n} from './types'\n\n// === Errors ===\nexport {\n\tAdapterError,\n\tOptimisticLockError,\n\tPersistenceError,\n\tQueryError,\n\tRecordNotFoundError,\n\tStoreNotOpenError,\n\tWorkerInitError,\n\tWorkerTimeoutError,\n} from './errors'\n\n// === Operation log compaction ===\nexport type { CompactionResult, CompactionStrategy } from './compaction/types'\nexport { COMPACTION_BASELINE_META_KEY } from './compaction/types'\nexport {\n\tcompactOperationLog,\n\tcomputeAckCompactionWatermark,\n} from './compaction/compact-operation-log'\n\n// === Clock rebase (timestamp rebase of unsynced operations) ===\nexport type { ClockRebaseResult } from './sync/rebase-unsynced-operations'\n\n// === Sync state helpers ===\nexport {\n\tcollectOperationsAheadOfServer,\n\tdeserializeVersionVectorFromMeta,\n\tLAST_ACKED_SERVER_VECTOR_META_KEY,\n\tmergeVersionVectors,\n\tserializeVersionVectorToMeta,\n} from './sync/sync-state'\n\n// === Store ===\nexport { Store } from './store/store'\nexport type { CollectionAccessor } from './store/store'\n\n// === Query ===\nexport { QueryBuilder } from './query/query-builder'\nexport { QueryStore } from './reactivity/query-store'\nexport { assertQueryReady } from './reactivity/assert-query-ready'\nexport {\n\tgetSharedQueryStoreCache,\n\tQueryStoreCache,\n} from './reactivity/query-store-cache'\n\n// === Subscription ===\nexport { SubscriptionManager } from './subscription/subscription-manager'\nexport type {\n\tSubscriptionManagerOptions,\n\tSubscriptionStats,\n} from './subscription/subscription-manager'\nexport { SubscriptionBloomFilter } from './subscription/bloom-filter'\n\n// === Collection ===\nexport { Collection } from './collection/collection'\n\n// === State Machine Validation ===\nexport {\n\tInvalidStateTransitionError,\n\tvalidateStateTransition,\n\tvalidateUpdateStateMachine,\n} from './state-machine/state-validator'\n\n// === Transaction ===\nexport { TransactionContext } from './transaction/transaction-context'\nexport type {\n\tTransactionCollectionAccessor,\n\tTransactionContextConfig,\n} from './transaction/transaction-context'\n\n// === Sequences ===\nexport { SequenceManager } from './sequences/sequence-manager'\n\n// === Richtext controller (framework bindings) ===\nexport { createRichTextController } from './richtext/create-richtext-controller'\nexport { asRichTextSyncEngine } from './richtext/as-rich-text-sync-engine'\nexport type {\n\tCreateRichTextControllerOptions,\n\tRichTextAwarenessUser,\n\tRichTextController,\n\tRichTextControllerSnapshot,\n\tRichTextCursorInfo,\n\tRichTextSyncEngine,\n} from './richtext/types'\n\n// === Richtext Serialization ===\nexport {\n\tdecodeRichtext,\n\tencodeRichtext,\n\trichtextToPlainText,\n\trichtextStatesEqual,\n} from './serialization/richtext-serializer'\n\n// === Query Utilities ===\nexport { pluralize, singularize } from './query/pluralize'\n\n// === Backup/Restore ===\nexport {\n\texportBackup,\n\treadBackupManifest,\n\trestoreBackup,\n\tverifyBackupChecksum,\n} from './backup'\nexport type {\n\tBackupManifest,\n\tBackupOptions,\n\tBackupProgress,\n\tRestoreOptions,\n\tRestoreResult,\n} from './backup'\n\n// === Audit export ===\nexport {\n\tdecodeAuditExport,\n\tpersistedAuditTraceFromEvent,\n\treadAuditExportManifest,\n\tverifyAuditExportChecksum,\n} from './audit'\nexport type {\n\tAuditExportManifest,\n\tAuditExportOptions,\n\tAuditExportPayload,\n\tAuditExportProgress,\n\tAuditTraceQuery,\n\tPersistedAuditTrace,\n} from './audit'\n\n// === Content-addressed blob store ===\nexport {\n\tBlobIntegrityError,\n\tMemoryBlobStore,\n\ttype ContentAddressedBlobStore,\n} from './blob/content-addressed-blob-store'\nexport {\n\tOpfsBlobStore,\n\tcreateOpfsBlobDirectory,\n\tcreateOpfsBlobStore,\n\ttype OpfsBlobDirectory,\n} from './blob/opfs-blob-store'\nexport {\n\tDEFAULT_CHUNK_SIZE,\n\tchunkBlob,\n\treassembleBlob,\n\ttype BlobManifest,\n\ttype BlobManifestMetadata,\n} from './blob/blob-chunking'\nexport {\n\tprepareBlobForSend,\n\treceiveBlob,\n\ttype ChunkProvider,\n\ttype ReceiveBlobResult,\n\ttype ReceiveBlobStores,\n} from './blob/blob-transfer'\nexport {\n\tfetchBlobManifest,\n\tparseBlobManifest,\n\tputBlobForTransfer,\n\tresolveBlobManifest,\n\tserializeBlobManifest,\n} from './blob/blob-manifest-transfer'\nexport {\n\tcreateMemoryServerBlobStore,\n\ttoServerBlobCallbacks,\n\ttype ServerBlobCallbacks,\n} from './blob/server-blob-callbacks'\nexport {\n\tcollectBlobGarbage,\n\textractBlobRefs,\n\ttype BlobGcOptions,\n\ttype BlobGcResult,\n} from './blob/blob-gc'\nexport {\n\tcreateChunkPortPair,\n\tcreateRemoteChunkProvider,\n\tserveBlobChunks,\n\ttype ChunkMessage,\n\ttype ChunkMessagePort,\n\ttype ChunkRequestMessage,\n\ttype ChunkResponseMessage,\n\ttype RemoteChunkProvider,\n} from './blob/blob-chunk-transport'\n","import { KoraError } from '@korajs/core'\n\n/**\n * Thrown when a query is invalid (bad field names, invalid operators, etc.).\n */\nexport class QueryError extends KoraError {\n\tconstructor(message: string, context?: Record<string, unknown>) {\n\t\tsuper(message, 'QUERY_ERROR', context)\n\t\tthis.name = 'QueryError'\n\t}\n}\n\n/**\n * Thrown when a record is not found by ID (findById, update, delete on missing record).\n */\nexport class RecordNotFoundError extends KoraError {\n\tconstructor(collection: string, recordId: string) {\n\t\tsuper(`Record \"${recordId}\" not found in collection \"${collection}\"`, 'RECORD_NOT_FOUND', {\n\t\t\tcollection,\n\t\t\trecordId,\n\t\t})\n\t\tthis.name = 'RecordNotFoundError'\n\t}\n}\n\n/**\n * Thrown inside `applyRemoteOperation` when the row's version state changed\n * between the caller's snapshot read and the guarded write (a concurrent local\n * mutation landed in the window). The transaction is rolled back with nothing\n * written; the caller re-reads fresh state, recomputes its merge, and retries.\n * This is the optimistic-concurrency guard that keeps merge-engine results\n * (richtext, add-wins arrays, constraint resolutions) from clobbering newer\n * local edits they never saw.\n */\nexport class OptimisticLockError extends KoraError {\n\tconstructor(collection: string, recordId: string) {\n\t\tsuper(\n\t\t\t`Row version changed while merging record \"${recordId}\" in \"${collection}\"; retry with fresh state`,\n\t\t\t'OPTIMISTIC_LOCK',\n\t\t\t{ collection, recordId },\n\t\t)\n\t\tthis.name = 'OptimisticLockError'\n\t}\n}\n\n/**\n * Thrown when a storage adapter operation fails.\n */\nexport class AdapterError extends KoraError {\n\tconstructor(message: string, context?: Record<string, unknown>) {\n\t\tsuper(message, 'ADAPTER_ERROR', context)\n\t\tthis.name = 'AdapterError'\n\t}\n}\n\n/**\n * Thrown when an operation is attempted on a store that has not been opened.\n */\nexport class StoreNotOpenError extends KoraError {\n\tconstructor() {\n\t\tsuper('Store is not open. Call store.open() before performing operations.', 'STORE_NOT_OPEN')\n\t\tthis.name = 'StoreNotOpenError'\n\t}\n}\n\n/**\n * Thrown when the Web Worker fails to initialize (WASM load failure, OPFS unavailable, etc.).\n */\nexport class WorkerInitError extends KoraError {\n\tconstructor(message: string, context?: Record<string, unknown>) {\n\t\tsuper(`Worker initialization failed: ${message}`, 'WORKER_INIT_ERROR', context)\n\t\tthis.name = 'WorkerInitError'\n\t}\n}\n\n/**\n * Thrown when the Web Worker does not respond within the configured timeout.\n */\nexport class WorkerTimeoutError extends KoraError {\n\tconstructor(operation: string, timeoutMs: number) {\n\t\tsuper(\n\t\t\t`Worker did not respond within ${timeoutMs}ms for operation \"${operation}\"`,\n\t\t\t'WORKER_TIMEOUT',\n\t\t\t{ operation, timeoutMs },\n\t\t)\n\t\tthis.name = 'WorkerTimeoutError'\n\t}\n}\n\n/**\n * Thrown when IndexedDB persistence operations fail (serialize/deserialize).\n */\nexport class PersistenceError extends KoraError {\n\tconstructor(message: string, context?: Record<string, unknown>) {\n\t\tsuper(`Persistence error: ${message}`, 'PERSISTENCE_ERROR', context)\n\t\tthis.name = 'PersistenceError'\n\t}\n}\n","import type { VersionVector } from '@korajs/core'\n\n/**\n * How the local operation log may be compacted.\n * Materialized collection rows are always kept as the convergence baseline.\n */\nexport type CompactionStrategy =\n\t| { mode: 'never' }\n\t| {\n\t\t\tmode: 'after-ack'\n\t\t\t/** Server version vector; defaults to persisted last-acked vector on the store. */\n\t\t\tserverVector?: VersionVector\n\t }\n\t| {\n\t\t\tmode: 'after-days'\n\t\t\t/** Delete only ops older than this many days (still requires ack watermark). */\n\t\t\tdays: number\n\t\t\tserverVector?: VersionVector\n\t }\n\n/**\n * Result of a compaction run.\n */\nexport interface CompactionResult {\n\t/** Number of operation log rows removed. */\n\tdeletedCount: number\n\t/** Per-node sequence ceiling used for deletion (from server ack vector). */\n\twatermark: VersionVector\n}\n\nexport const COMPACTION_BASELINE_META_KEY = 'compaction_baseline_at'\n","import type { SchemaDefinition, VersionVector } from '@korajs/core'\nimport { HybridLogicalClock, createVersionVector } from '@korajs/core'\nimport type { StorageAdapter, Transaction } from '../types'\nimport type { CompactionResult, CompactionStrategy } from './types'\nimport { COMPACTION_BASELINE_META_KEY } from './types'\n\n/**\n * Compute per-node sequence watermarks safe to compact (server has acknowledged these ops).\n */\nexport function computeAckCompactionWatermark(serverVector: VersionVector): VersionVector {\n\tconst watermark = createVersionVector()\n\tfor (const [nodeId, seq] of serverVector) {\n\t\tif (seq > 0) {\n\t\t\twatermark.set(nodeId, seq)\n\t\t}\n\t}\n\treturn watermark\n}\n\n/**\n * Remove acknowledged, materialized operation log entries from `_kora_ops_*` tables.\n * Does not modify collection rows — they are the compaction baseline snapshot.\n */\nexport async function compactOperationLog(\n\tadapter: StorageAdapter,\n\tschema: SchemaDefinition,\n\tstrategy: CompactionStrategy,\n\tserverVector: VersionVector,\n): Promise<CompactionResult> {\n\tif (strategy.mode === 'never') {\n\t\treturn { deletedCount: 0, watermark: createVersionVector() }\n\t}\n\n\tconst watermark = computeAckCompactionWatermark(serverVector)\n\tif (watermark.size === 0) {\n\t\treturn { deletedCount: 0, watermark }\n\t}\n\n\tconst ageCutoffWall =\n\t\tstrategy.mode === 'after-days' ? Date.now() - strategy.days * 24 * 60 * 60 * 1000 : null\n\tconst ageCutoffSerialized =\n\t\tageCutoffWall !== null\n\t\t\t? HybridLogicalClock.serialize({\n\t\t\t\t\twallTime: ageCutoffWall,\n\t\t\t\t\tlogical: 0,\n\t\t\t\t\tnodeId: '',\n\t\t\t\t}).slice(0, 15)\n\t\t\t: null\n\n\tlet deletedCount = 0\n\tconst collectionNames = Object.keys(schema.collections)\n\n\tawait adapter.transaction(async (tx: Transaction) => {\n\t\tfor (const collectionName of collectionNames) {\n\t\t\tconst table = `_kora_ops_${collectionName}`\n\t\t\tfor (const [nodeId, maxSeq] of watermark) {\n\t\t\t\tif (maxSeq <= 0) continue\n\n\t\t\t\tconst countSql = buildCountSql(table, ageCutoffSerialized !== null)\n\t\t\t\tconst countParams =\n\t\t\t\t\tageCutoffSerialized !== null ? [nodeId, maxSeq, ageCutoffSerialized] : [nodeId, maxSeq]\n\t\t\t\tconst countRows = await tx.query<{ count: number }>(countSql, countParams)\n\t\t\t\tdeletedCount += countRows[0]?.count ?? 0\n\n\t\t\t\tconst deleteSql = buildDeleteSql(table, ageCutoffSerialized !== null)\n\t\t\t\tawait tx.execute(deleteSql, countParams)\n\t\t\t}\n\t\t}\n\n\t\tawait tx.execute('INSERT OR REPLACE INTO _kora_meta (key, value) VALUES (?, ?)', [\n\t\t\tCOMPACTION_BASELINE_META_KEY,\n\t\t\tString(Date.now()),\n\t\t])\n\t})\n\n\treturn { deletedCount, watermark }\n}\n\nfunction buildCountSql(table: string, withAge: boolean): string {\n\tif (withAge) {\n\t\treturn `SELECT COUNT(*) as count FROM ${table} WHERE node_id = ? AND sequence_number <= ? AND SUBSTR(timestamp, 1, 15) < ?`\n\t}\n\treturn `SELECT COUNT(*) as count FROM ${table} WHERE node_id = ? AND sequence_number <= ?`\n}\n\nfunction buildDeleteSql(table: string, withAge: boolean): string {\n\tif (withAge) {\n\t\treturn `DELETE FROM ${table} WHERE node_id = ? AND sequence_number <= ? AND SUBSTR(timestamp, 1, 15) < ?`\n\t}\n\treturn `DELETE FROM ${table} WHERE node_id = ? AND sequence_number <= ?`\n}\n","import type { Operation, VersionVector } from '@korajs/core'\nimport { createVersionVector } from '@korajs/core'\nimport type { MetaRow, StorageAdapter } from '../types'\n\nexport const LAST_ACKED_SERVER_VECTOR_META_KEY = 'last_acked_server_vector'\nexport const DELTA_CURSOR_META_KEY = 'delta_cursor'\n\n/**\n * Serialize a version vector for `_kora_meta` storage.\n */\nexport function serializeVersionVectorToMeta(vector: VersionVector): string {\n\tconst record: Record<string, number> = {}\n\tfor (const [nodeId, seq] of vector) {\n\t\trecord[nodeId] = seq\n\t}\n\treturn JSON.stringify(record)\n}\n\n/**\n * Deserialize a version vector from `_kora_meta`.\n */\nexport function deserializeVersionVectorFromMeta(value: string): VersionVector {\n\tconst parsed = JSON.parse(value) as Record<string, number>\n\tconst vector = createVersionVector()\n\tfor (const [nodeId, seq] of Object.entries(parsed)) {\n\t\tif (typeof seq === 'number' && seq >= 0) {\n\t\t\tvector.set(nodeId, seq)\n\t\t}\n\t}\n\treturn vector\n}\n\n/**\n * Merge two version vectors, keeping the maximum sequence per node.\n */\nexport function mergeVersionVectors(a: VersionVector, b: VersionVector): VersionVector {\n\tconst merged = new Map(a)\n\tfor (const [nodeId, seq] of b) {\n\t\tmerged.set(nodeId, Math.max(merged.get(nodeId) ?? 0, seq))\n\t}\n\treturn merged\n}\n\n/**\n * Operations present locally but not yet on the server (per server version vector).\n */\nexport async function collectOperationsAheadOfServer(\n\tlocalVector: VersionVector,\n\tserverVector: VersionVector,\n\tfetchRange: (nodeId: string, fromSeq: number, toSeq: number) => Promise<Operation[]>,\n): Promise<Operation[]> {\n\tconst missing: Operation[] = []\n\tfor (const [nodeId, localSeq] of localVector) {\n\t\tconst serverSeq = serverVector.get(nodeId) ?? 0\n\t\tif (localSeq > serverSeq) {\n\t\t\tconst ops = await fetchRange(nodeId, serverSeq + 1, localSeq)\n\t\t\tmissing.push(...ops)\n\t\t}\n\t}\n\tmissing.sort((a, b) => a.sequenceNumber - b.sequenceNumber)\n\treturn missing\n}\n\n/**\n * Load persisted last-acked server vector from `_kora_meta`.\n */\nexport async function loadLastAckedServerVector(adapter: StorageAdapter): Promise<VersionVector> {\n\tconst rows = await adapter.query<MetaRow>('SELECT value FROM _kora_meta WHERE key = ?', [\n\t\tLAST_ACKED_SERVER_VECTOR_META_KEY,\n\t])\n\tconst row = rows[0]\n\tif (!row?.value) {\n\t\treturn createVersionVector()\n\t}\n\ttry {\n\t\treturn deserializeVersionVectorFromMeta(row.value)\n\t} catch {\n\t\treturn createVersionVector()\n\t}\n}\n\n/**\n * Persist the last-acked server version vector to `_kora_meta`.\n */\nexport async function saveLastAckedServerVector(\n\tadapter: StorageAdapter,\n\tvector: VersionVector,\n): Promise<void> {\n\tawait adapter.execute('INSERT OR REPLACE INTO _kora_meta (key, value) VALUES (?, ?)', [\n\t\tLAST_ACKED_SERVER_VECTOR_META_KEY,\n\t\tserializeVersionVectorToMeta(vector),\n\t])\n}\n\n/**\n * Load a persisted delta cursor for resuming paginated initial sync.\n */\nexport async function loadDeltaCursor(adapter: StorageAdapter): Promise<string | null> {\n\tconst rows = await adapter.query<MetaRow>('SELECT value FROM _kora_meta WHERE key = ?', [\n\t\tDELTA_CURSOR_META_KEY,\n\t])\n\treturn rows[0]?.value ?? null\n}\n\n/**\n * Persist or clear the delta cursor in `_kora_meta`.\n */\nexport async function saveDeltaCursor(\n\tadapter: StorageAdapter,\n\tcursor: string | null,\n): Promise<void> {\n\tif (cursor === null) {\n\t\tawait adapter.execute('DELETE FROM _kora_meta WHERE key = ?', [DELTA_CURSOR_META_KEY])\n\t\treturn\n\t}\n\n\tawait adapter.execute('INSERT OR REPLACE INTO _kora_meta (key, value) VALUES (?, ?)', [\n\t\tDELTA_CURSOR_META_KEY,\n\t\tcursor,\n\t])\n}\n","import {\n\tCausalTracker,\n\tHybridLogicalClock,\n\tcreateVersionVector,\n\tgenerateUUIDv7,\n\tmigrationStepsToSQL,\n} from '@korajs/core'\nimport type {\n\tKoraEventEmitter,\n\tMigrationStep,\n\tOperation,\n\tOperationLog,\n\tSchemaDefinition,\n\tSecretKeyProvider,\n\tVersionVector,\n} from '@korajs/core'\nimport { readBackupManifest as readManifest } from '../backup/backup'\nimport type { BackupManifest, BackupOptions, RestoreOptions, RestoreResult } from '../backup/types'\nimport { Collection } from '../collection/collection'\nimport { compactOperationLog } from '../compaction/compact-operation-log'\nimport type { CompactionResult, CompactionStrategy } from '../compaction/types'\nimport { OptimisticLockError, StoreNotOpenError } from '../errors'\nimport {\n\tfieldVersionsForFields,\n\tparseFieldVersions,\n\tresolvePerFieldLww,\n\tserializeFieldVersions,\n} from '../lww/field-versions'\nimport { isIncomingNewerThanRow, serializeRowVersion } from '../lww/row-version'\nimport type { LocalMutationContext } from '../mutations/types'\nimport { QueryBuilder } from '../query/query-builder'\nimport {\n\tbuildFieldFastForwardUpdateQuery,\n\tbuildInsertQuery,\n\tbuildLwwSoftDeleteQuery,\n\tbuildSoftDeleteQuery,\n} from '../query/sql-builder'\nimport { RelationEnforcer } from '../relations/relation-enforcer'\nimport { buildReplaySnapshot } from '../replay/replay-to'\nimport type { ReplaySnapshot } from '../replay/replay-to'\nimport { SequenceManager } from '../sequences/sequence-manager'\nimport {\n\tdeserializeOperationWithCollection,\n\tdeserializeRecord,\n\tserializeOperation,\n\tserializeRecord,\n} from '../serialization/serializer'\nimport { SubscriptionManager } from '../subscription/subscription-manager'\nimport type { ClockRebaseResult } from '../sync/rebase-unsynced-operations'\nimport { rebaseUnsyncedOperationsInLog } from '../sync/rebase-unsynced-operations'\nimport {\n\tcollectOperationsAheadOfServer,\n\tloadDeltaCursor,\n\tloadLastAckedServerVector,\n\tmergeVersionVectors,\n\tsaveDeltaCursor,\n\tsaveLastAckedServerVector,\n} from '../sync/sync-state'\nimport { TransactionContext } from '../transaction/transaction-context'\nimport { TransactionSequenceAllocator } from '../transaction/transaction-sequence'\nimport type {\n\tApplyRemoteOptions,\n\tApplyResult,\n\tLocalMutationHandler,\n\tMaterializedRowSnapshot,\n\tMetaRow,\n\tOperationRow,\n\tRawCollectionRow,\n\tRowVersionState,\n\tStorageAdapter,\n\tStoreConfig,\n\tStoreIsolation,\n\tTransaction,\n\tVersionVectorRow,\n} from '../types'\nimport { allocateNextSequenceNumber } from './sequence-allocator'\nimport { resolvePerTabNodeId } from './tab-node-id'\n\n/**\n * Store is the main orchestrator. It owns a schema, a storage adapter,\n * a clock, and a subscription manager. It creates Collection instances\n * for each schema collection, and provides the sync contract via\n * applyRemoteOperation and getOperationRange.\n *\n * @example\n * ```typescript\n * const store = new Store({ schema, adapter })\n * await store.open()\n * const todo = await store.collection('todos').insert({ title: 'Hello' })\n * await store.close()\n * ```\n */\nexport class Store implements OperationLog {\n\tprivate opened = false\n\tprivate nodeId = ''\n\tprivate sequenceNumber = 0\n\tprivate versionVector: VersionVector = createVersionVector()\n\tprivate clock: HybridLogicalClock | null = null\n\tprivate collections = new Map<string, Collection>()\n\tprivate subscriptionManager: SubscriptionManager\n\tprivate sequenceManager: SequenceManager | null = null\n\n\tprivate readonly schema: SchemaDefinition\n\tprivate readonly adapter: StorageAdapter\n\tprivate readonly configNodeId: string | undefined\n\tprivate readonly dbName: string\n\tprivate readonly isolation: StoreIsolation\n\tprivate readonly emitter: KoraEventEmitter | null\n\tprivate localMutationHandler: LocalMutationHandler | null\n\tprivate relationEnforcer: RelationEnforcer | null = null\n\tprivate causalTracker: CausalTracker | null = null\n\tprivate readonly secretKeyProvider: SecretKeyProvider | undefined\n\n\tconstructor(config: StoreConfig) {\n\t\tthis.schema = config.schema\n\t\tthis.adapter = config.adapter\n\t\tthis.configNodeId = config.nodeId\n\t\tthis.dbName = config.dbName ?? 'kora-db'\n\t\tthis.isolation = config.isolation ?? 'shared'\n\t\tthis.emitter = config.emitter ?? null\n\t\tthis.localMutationHandler = config.localMutationHandler ?? null\n\t\tthis.secretKeyProvider = config.secretKeyProvider\n\t\tthis.subscriptionManager = new SubscriptionManager({\n\t\t\tonQuerySubscribed: config.onQuerySubscribed,\n\t\t})\n\t}\n\n\t/**\n\t * Open the store: initialize the database, load or generate a node ID,\n\t * restore the sequence number and version vector, and create Collection instances.\n\t */\n\tasync open(): Promise<void> {\n\t\tawait this.adapter.open(this.schema)\n\n\t\t// Run schema migrations if needed\n\t\tawait this.runMigrationsIfNeeded()\n\n\t\t// Load or generate node ID\n\t\tthis.nodeId = await this.loadOrGenerateNodeId()\n\t\tthis.clock = new HybridLogicalClock(this.nodeId)\n\t\tthis.causalTracker = new CausalTracker()\n\n\t\t// Initialize sequence manager\n\t\tthis.sequenceManager = new SequenceManager(this.adapter, this.nodeId)\n\n\t\t// Load sequence number and version vector\n\t\tthis.sequenceNumber = await this.loadSequenceNumber()\n\t\tthis.versionVector = await this.loadVersionVector()\n\n\t\t// Create RelationEnforcer if the schema has relations.\n\t\t// The enforcer is shared across all Collection instances so that\n\t\t// cascading deletes can cross collection boundaries.\n\t\tconst hasRelations = Object.keys(this.schema.relations).length > 0\n\t\tthis.relationEnforcer = hasRelations\n\t\t\t? new RelationEnforcer({\n\t\t\t\t\tschema: this.schema,\n\t\t\t\t\tadapter: this.adapter,\n\t\t\t\t\tclock: this.clock,\n\t\t\t\t\tnodeId: this.nodeId,\n\t\t\t\t})\n\t\t\t: null\n\n\t\t// Create collection instances\n\t\tfor (const [name, definition] of Object.entries(this.schema.collections)) {\n\t\t\tconst col = new Collection(\n\t\t\t\tname,\n\t\t\t\tdefinition,\n\t\t\t\tthis.schema,\n\t\t\t\tthis.adapter,\n\t\t\t\tthis.clock,\n\t\t\t\tthis.nodeId,\n\t\t\t\t() => this.allocateSequenceNumber(),\n\t\t\t\t(collectionName, operation) => {\n\t\t\t\t\tthis.recordOperationSequence(operation)\n\t\t\t\t\tthis.subscriptionManager.notify(collectionName, operation)\n\t\t\t\t\tif (this.emitter) {\n\t\t\t\t\t\tthis.emitter.emit({ type: 'operation:created', operation })\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tthis.relationEnforcer,\n\t\t\t\tthis.localMutationHandler,\n\t\t\t\tthis.causalTracker,\n\t\t\t\tthis.secretKeyProvider,\n\t\t\t)\n\t\t\tthis.collections.set(name, col)\n\t\t}\n\n\t\tthis.opened = true\n\t}\n\n\t/**\n\t * Close the store: clear subscriptions and close the adapter.\n\t */\n\tasync close(): Promise<void> {\n\t\tthis.subscriptionManager.clear()\n\t\tthis.collections.clear()\n\t\tthis.opened = false\n\t\tawait this.adapter.close()\n\t}\n\n\t/**\n\t * Get a Collection instance for CRUD operations.\n\t * @throws {StoreNotOpenError} If the store is not open\n\t * @throws {Error} If the collection name is not in the schema\n\t */\n\tcollection(name: string): CollectionAccessor {\n\t\tthis.ensureOpen()\n\t\tconst col = this.collections.get(name)\n\t\tif (!col) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${name}\". Available: ${[...this.collections.keys()].join(', ')}`,\n\t\t\t)\n\t\t}\n\n\t\tconst definition = this.schema.collections[name]\n\t\tif (!definition) {\n\t\t\tthrow new Error(`Collection definition not found for \"${name}\"`)\n\t\t}\n\n\t\treturn {\n\t\t\tinsert: (data: Record<string, unknown>) => col.insert(data),\n\t\t\tfindById: (id: string) => col.findById(id),\n\t\t\tupdate: (id: string, data: Record<string, unknown>) => col.update(id, data),\n\t\t\tdelete: (id: string) => col.delete(id),\n\t\t\twhere: (conditions) =>\n\t\t\t\tnew QueryBuilder(\n\t\t\t\t\tname,\n\t\t\t\t\tdefinition,\n\t\t\t\t\tthis.adapter,\n\t\t\t\t\tthis.subscriptionManager,\n\t\t\t\t\tconditions,\n\t\t\t\t\tthis.schema,\n\t\t\t\t),\n\t\t}\n\t}\n\n\t/**\n\t * Get the current version vector.\n\t */\n\tgetVersionVector(): VersionVector {\n\t\tthis.ensureOpen()\n\t\treturn new Map(this.versionVector)\n\t}\n\n\t/**\n\t * Get the node ID for this store instance.\n\t */\n\t/**\n\t * Records the offset between server time and this device's clock\n\t * (serverTime - localTime), learned at sync handshake. Lets the store's HLC\n\t * validate remote timestamps correctly even when the local clock is wrong.\n\t */\n\tsetClockReferenceOffset(offsetMs: number): void {\n\t\tthis.clock?.setReferenceOffset(offsetMs)\n\t}\n\n\tgetNodeId(): string {\n\t\tthis.ensureOpen()\n\t\treturn this.nodeId\n\t}\n\n\t/**\n\t * Apply a remote operation received from sync.\n\t * Checks for duplicates, applies to the data table, persists the operation,\n\t * and updates the version vector.\n\t */\n\tasync applyRemoteOperation(op: Operation, options?: ApplyRemoteOptions): Promise<ApplyResult> {\n\t\tthis.ensureOpen()\n\n\t\tconst collection = op.collection\n\t\tconst definition = this.schema.collections[collection]\n\t\tif (!definition) {\n\t\t\treturn 'skipped'\n\t\t}\n\n\t\t// Check for duplicate (content-addressed dedup)\n\t\tconst existing = await this.adapter.query<{ id: string }>(\n\t\t\t`SELECT id FROM _kora_ops_${collection} WHERE id = ?`,\n\t\t\t[op.id],\n\t\t)\n\t\tif (existing.length > 0) {\n\t\t\treturn 'duplicate'\n\t\t}\n\n\t\t// Advance the local HLC; severe clock drift throws ClockDriftError (surfaced as sync:apply-failed).\n\t\tif (this.clock) {\n\t\t\tthis.clock.receive(op.timestamp)\n\t\t}\n\n\t\t// Materialization may use overridden data/timestamp (authoritative merge\n\t\t// results), but the LOG below always stores the canonical operation:\n\t\t// operations are immutable and content-addressed, so merged values must\n\t\t// never be persisted under the original operation's id.\n\t\tconst materializeTimestamp = options?.materializeTimestamp ?? op.timestamp\n\t\tconst remoteVersion = serializeRowVersion(materializeTimestamp)\n\t\tconst wallTime = materializeTimestamp.wallTime\n\t\tconst materializeSource = options?.materializeData ?? op.data\n\n\t\t// Apply the operation to the data table (LWW-guarded; op log always appended below)\n\t\tawait this.adapter.transaction(async (tx) => {\n\t\t\t// Optimistic-concurrency guard: if the caller computed its data from a\n\t\t\t// snapshot, verify the row hasn't changed since. Throwing rolls the\n\t\t\t// whole transaction back (nothing written, op NOT logged) so the caller\n\t\t\t// can recompute against fresh state and retry.\n\t\t\tconst checkGuard = (row: RawCollectionRow | undefined): void => {\n\t\t\t\tconst guard = options?.guardRowState\n\t\t\t\tif (!guard) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst version = typeof row?._version === 'string' ? row._version : null\n\t\t\t\tconst fieldVersions = typeof row?._field_versions === 'string' ? row._field_versions : null\n\t\t\t\tif (version !== guard.version || fieldVersions !== guard.fieldVersions) {\n\t\t\t\t\tthrow new OptimisticLockError(collection, op.recordId)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (op.type === 'insert' && materializeSource) {\n\t\t\t\tconst serializedData = serializeRecord(materializeSource, definition.fields)\n\t\t\t\tconst existing = await tx.query<RawCollectionRow>(\n\t\t\t\t\t`SELECT _updated_at, _version, _field_versions, _deleted FROM ${collection} WHERE id = ?`,\n\t\t\t\t\t[op.recordId],\n\t\t\t\t)\n\t\t\t\tconst row = existing[0]\n\t\t\t\tcheckGuard(row)\n\n\t\t\t\tif (!row) {\n\t\t\t\t\tconst record: Record<string, unknown> = {\n\t\t\t\t\t\tid: op.recordId,\n\t\t\t\t\t\t...serializedData,\n\t\t\t\t\t\t_created_at: wallTime,\n\t\t\t\t\t\t_updated_at: wallTime,\n\t\t\t\t\t\t_version: remoteVersion,\n\t\t\t\t\t\t// Stamp every inserted field so per-field LWW has a real baseline.\n\t\t\t\t\t\t_field_versions: serializeFieldVersions(\n\t\t\t\t\t\t\tfieldVersionsForFields(Object.keys(serializedData), remoteVersion),\n\t\t\t\t\t\t),\n\t\t\t\t\t}\n\t\t\t\t\tconst insertQuery = buildInsertQuery(collection, record)\n\t\t\t\t\tawait tx.execute(insertQuery.sql, insertQuery.params)\n\n\t\t\t\t\t// Catch up on operations delivered BEFORE this insert (transports may\n\t\t\t\t\t// reorder): any update/delete already logged for this record was\n\t\t\t\t\t// applied while no row existed, so it never materialized. The row is\n\t\t\t\t\t// a fold of the log — fold the orphans now, in timestamp order,\n\t\t\t\t\t// inside this same transaction. Per-field LWW makes the result\n\t\t\t\t\t// identical to what an in-order device computed.\n\t\t\t\t\tawait this.foldOrphanedOperations(tx, collection, definition, op.recordId)\n\t\t\t\t} else if (row._deleted === 1) {\n\t\t\t\t\t// Insert vs tombstone: a strictly newer insert resurrects the record\n\t\t\t\t\t// with its full field set; an older one is stale (delete wins).\n\t\t\t\t\tif (isIncomingNewerThanRow(materializeTimestamp, row)) {\n\t\t\t\t\t\tconst fieldChanges: Record<string, unknown> = {\n\t\t\t\t\t\t\t...serializedData,\n\t\t\t\t\t\t\t_deleted: 0,\n\t\t\t\t\t\t\t_field_versions: serializeFieldVersions(\n\t\t\t\t\t\t\t\tfieldVersionsForFields(Object.keys(serializedData), remoteVersion),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst upsert = buildFieldFastForwardUpdateQuery(\n\t\t\t\t\t\t\tcollection,\n\t\t\t\t\t\t\top.recordId,\n\t\t\t\t\t\t\tfieldChanges,\n\t\t\t\t\t\t\tremoteVersion,\n\t\t\t\t\t\t\twallTime,\n\t\t\t\t\t\t\t{ maxCreatedAt: wallTime },\n\t\t\t\t\t\t)\n\t\t\t\t\t\tawait tx.execute(upsert.sql, upsert.params)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Insert collision on a LIVE row (relayed insert racing a local one,\n\t\t\t\t\t// or an insert-vs-insert merge). A plain INSERT would violate the\n\t\t\t\t\t// primary key; resolve per-field instead, exactly like an update, so\n\t\t\t\t\t// every node converges no matter which insert (or interleaved\n\t\t\t\t\t// update) it saw first. `_created_at` converges to the max insert\n\t\t\t\t\t// wall time seen, applied even when every field loses.\n\t\t\t\t\tconst currentVersions = parseFieldVersions(row._field_versions)\n\t\t\t\t\tconst rowVersion = typeof row._version === 'string' ? row._version : undefined\n\t\t\t\t\tconst fieldChanges: Record<string, unknown> = {}\n\t\t\t\t\tlet fieldVersionsJson: string\n\t\t\t\t\tif (options?.forceMaterialize) {\n\t\t\t\t\t\t// Authoritative merged insert: every field is written.\n\t\t\t\t\t\tconst merged = { ...currentVersions }\n\t\t\t\t\t\tfor (const field of Object.keys(serializedData)) {\n\t\t\t\t\t\t\tfieldChanges[field] = serializedData[field]\n\t\t\t\t\t\t\tmerged[field] = remoteVersion\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfieldVersionsJson = serializeFieldVersions(merged)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst { winners, merged } = resolvePerFieldLww(\n\t\t\t\t\t\t\tcurrentVersions,\n\t\t\t\t\t\t\tObject.keys(serializedData),\n\t\t\t\t\t\t\tremoteVersion,\n\t\t\t\t\t\t\trowVersion,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tfor (const field of winners) {\n\t\t\t\t\t\t\tfieldChanges[field] = serializedData[field]\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfieldVersionsJson = serializeFieldVersions(merged)\n\t\t\t\t\t}\n\t\t\t\t\tconst upsert = buildFieldFastForwardUpdateQuery(\n\t\t\t\t\t\tcollection,\n\t\t\t\t\t\top.recordId,\n\t\t\t\t\t\t{ ...fieldChanges, _field_versions: fieldVersionsJson },\n\t\t\t\t\t\tremoteVersion,\n\t\t\t\t\t\twallTime,\n\t\t\t\t\t\t{ maxCreatedAt: wallTime },\n\t\t\t\t\t)\n\t\t\t\t\tawait tx.execute(upsert.sql, upsert.params)\n\t\t\t\t}\n\t\t\t} else if (op.type === 'update' && materializeSource) {\n\t\t\t\tconst serializedChanges = serializeRecord(materializeSource, definition.fields)\n\t\t\t\tconst changedFields = Object.keys(serializedChanges)\n\n\t\t\t\t// Read the current per-field versions INSIDE the transaction so the\n\t\t\t\t// resolve-then-write is atomic with respect to any concurrent local\n\t\t\t\t// mutation — this is what prevents a relayed remote op from clobbering\n\t\t\t\t// a newer local edit that lands between the read and the write.\n\t\t\t\tconst currentRows = await tx.query<RawCollectionRow>(\n\t\t\t\t\t`SELECT _version, _field_versions FROM ${collection} WHERE id = ?`,\n\t\t\t\t\t[op.recordId],\n\t\t\t\t)\n\t\t\t\tconst currentRow = currentRows[0]\n\t\t\t\tcheckGuard(currentRow)\n\n\t\t\t\tif (currentRow) {\n\t\t\t\t\tconst currentVersions = parseFieldVersions(currentRow._field_versions)\n\t\t\t\t\tconst rowVersion =\n\t\t\t\t\t\ttypeof currentRow._version === 'string' ? currentRow._version : undefined\n\n\t\t\t\t\tif (options?.forceMaterialize) {\n\t\t\t\t\t\t// Authoritative merged result (richtext / add-wins-set / constraint\n\t\t\t\t\t\t// resolution computed by the merge engine): write every changed\n\t\t\t\t\t\t// field and stamp its per-field version to this op's version, while\n\t\t\t\t\t\t// advancing the row watermark monotonically.\n\t\t\t\t\t\tconst merged = { ...currentVersions }\n\t\t\t\t\t\tfor (const field of changedFields) {\n\t\t\t\t\t\t\tmerged[field] = remoteVersion\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst fieldChanges: Record<string, unknown> = {\n\t\t\t\t\t\t\t...serializedChanges,\n\t\t\t\t\t\t\t_field_versions: serializeFieldVersions(merged),\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (options?.reactivateIfDeleted) {\n\t\t\t\t\t\t\tfieldChanges._deleted = 0\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst forceQuery = buildFieldFastForwardUpdateQuery(\n\t\t\t\t\t\t\tcollection,\n\t\t\t\t\t\t\top.recordId,\n\t\t\t\t\t\t\tfieldChanges,\n\t\t\t\t\t\t\tremoteVersion,\n\t\t\t\t\t\t\twallTime,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tawait tx.execute(forceQuery.sql, forceQuery.params)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Deterministic field-level LWW: write only the fields this op\n\t\t\t\t\t\t// wins (strictly newer than the field's stored version). Same\n\t\t\t\t\t\t// result on every node regardless of arrival order.\n\t\t\t\t\t\tconst { winners, merged } = resolvePerFieldLww(\n\t\t\t\t\t\t\tcurrentVersions,\n\t\t\t\t\t\t\tchangedFields,\n\t\t\t\t\t\t\tremoteVersion,\n\t\t\t\t\t\t\trowVersion,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tif (winners.length > 0 || options?.reactivateIfDeleted) {\n\t\t\t\t\t\t\tconst winningChanges: Record<string, unknown> = {\n\t\t\t\t\t\t\t\t_field_versions: serializeFieldVersions(merged),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfor (const field of winners) {\n\t\t\t\t\t\t\t\twinningChanges[field] = serializedChanges[field]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (options?.reactivateIfDeleted) {\n\t\t\t\t\t\t\t\twinningChanges._deleted = 0\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst forceQuery = buildFieldFastForwardUpdateQuery(\n\t\t\t\t\t\t\t\tcollection,\n\t\t\t\t\t\t\t\top.recordId,\n\t\t\t\t\t\t\t\twinningChanges,\n\t\t\t\t\t\t\t\tremoteVersion,\n\t\t\t\t\t\t\t\twallTime,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tawait tx.execute(forceQuery.sql, forceQuery.params)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// currentRow absent: nothing materialized to update (insert not yet\n\t\t\t\t// applied, or hard-absent). The op is still appended to the log below;\n\t\t\t\t// the pipeline handles tombstone reactivation separately.\n\t\t\t} else if (op.type === 'delete') {\n\t\t\t\tconst deleteQuery = buildLwwSoftDeleteQuery(\n\t\t\t\t\tcollection,\n\t\t\t\t\top.recordId,\n\t\t\t\t\twallTime,\n\t\t\t\t\tremoteVersion,\n\t\t\t\t)\n\t\t\t\tawait tx.execute(deleteQuery.sql, deleteQuery.params)\n\t\t\t}\n\n\t\t\t// Persist the operation\n\t\t\tconst opRow = serializeOperation(op)\n\t\t\tconst opInsert = buildInsertQuery(\n\t\t\t\t`_kora_ops_${collection}`,\n\t\t\t\topRow as unknown as Record<string, unknown>,\n\t\t\t)\n\t\t\tawait tx.execute(opInsert.sql, opInsert.params)\n\n\t\t\t// Update version vector\n\t\t\tconst currentSeq = this.versionVector.get(op.nodeId) ?? 0\n\t\t\tif (op.sequenceNumber > currentSeq) {\n\t\t\t\tthis.versionVector.set(op.nodeId, op.sequenceNumber)\n\t\t\t\tawait tx.execute(\n\t\t\t\t\t'INSERT OR REPLACE INTO _kora_version_vector (node_id, sequence_number) VALUES (?, ?)',\n\t\t\t\t\t[op.nodeId, op.sequenceNumber],\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\n\t\t// Notify subscriptions\n\t\tthis.subscriptionManager.notify(collection, op)\n\n\t\treturn 'applied'\n\t}\n\n\t/**\n\t * Materialize update/delete operations that were logged for a record BEFORE\n\t * its insert arrived (reordered delivery). Runs inside the insert's write\n\t * transaction, folding each orphan in timestamp order through the exact\n\t * per-field LWW / LWW-delete rules the normal apply paths use, so the final\n\t * row state equals what a device that received the operations in causal\n\t * order computed. Called only when the insert created a previously-absent\n\t * row — in that case every logged update/delete for the record is\n\t * necessarily an orphan (rows are soft-deleted, never removed, so a row\n\t * that is absent now was never materialized).\n\t */\n\tprivate async foldOrphanedOperations(\n\t\ttx: Transaction,\n\t\tcollection: string,\n\t\tdefinition: NonNullable<SchemaDefinition['collections'][string]>,\n\t\trecordId: string,\n\t): Promise<void> {\n\t\tconst orphanRows = await tx.query<OperationRow>(\n\t\t\t`SELECT * FROM _kora_ops_${collection} WHERE record_id = ? AND type IN ('update', 'delete')`,\n\t\t\t[recordId],\n\t\t)\n\t\tif (orphanRows.length === 0) {\n\t\t\treturn\n\t\t}\n\n\t\tconst orphans = orphanRows\n\t\t\t.map((r) => deserializeOperationWithCollection(r, collection))\n\t\t\t.sort((a, b) => HybridLogicalClock.compare(a.timestamp, b.timestamp))\n\n\t\tfor (const orphan of orphans) {\n\t\t\tconst orphanVersion = serializeRowVersion(orphan.timestamp)\n\t\t\tconst orphanWall = orphan.timestamp.wallTime\n\n\t\t\tif (orphan.type === 'update' && orphan.data) {\n\t\t\t\tconst orphanChanges = serializeRecord(orphan.data, definition.fields)\n\t\t\t\tconst rows = await tx.query<RawCollectionRow>(\n\t\t\t\t\t`SELECT _version, _field_versions FROM ${collection} WHERE id = ?`,\n\t\t\t\t\t[recordId],\n\t\t\t\t)\n\t\t\t\tconst current = rows[0]\n\t\t\t\tif (!current) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst { winners, merged } = resolvePerFieldLww(\n\t\t\t\t\tparseFieldVersions(current._field_versions),\n\t\t\t\t\tObject.keys(orphanChanges),\n\t\t\t\t\torphanVersion,\n\t\t\t\t\ttypeof current._version === 'string' ? current._version : undefined,\n\t\t\t\t)\n\t\t\t\tif (winners.length > 0) {\n\t\t\t\t\tconst winningChanges: Record<string, unknown> = {\n\t\t\t\t\t\t_field_versions: serializeFieldVersions(merged),\n\t\t\t\t\t}\n\t\t\t\t\tfor (const field of winners) {\n\t\t\t\t\t\twinningChanges[field] = orphanChanges[field]\n\t\t\t\t\t}\n\t\t\t\t\tconst query = buildFieldFastForwardUpdateQuery(\n\t\t\t\t\t\tcollection,\n\t\t\t\t\t\trecordId,\n\t\t\t\t\t\twinningChanges,\n\t\t\t\t\t\torphanVersion,\n\t\t\t\t\t\torphanWall,\n\t\t\t\t\t)\n\t\t\t\t\tawait tx.execute(query.sql, query.params)\n\t\t\t\t}\n\t\t\t} else if (orphan.type === 'delete') {\n\t\t\t\tconst query = buildLwwSoftDeleteQuery(collection, recordId, orphanWall, orphanVersion)\n\t\t\t\tawait tx.execute(query.sql, query.params)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get operations from a node within a sequence number range.\n\t * Implements the OperationLog interface for computeDelta.\n\t */\n\tasync getRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\treturn this.getOperationRange(nodeId, fromSeq, toSeq)\n\t}\n\n\t/**\n\t * Get operations from a node within a sequence number range.\n\t */\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\tthis.ensureOpen()\n\t\tconst allOps: Operation[] = []\n\n\t\tfor (const collectionName of Object.keys(this.schema.collections)) {\n\t\t\tconst rows = await this.adapter.query<OperationRow>(\n\t\t\t\t`SELECT * FROM _kora_ops_${collectionName} WHERE node_id = ? AND sequence_number >= ? AND sequence_number <= ? ORDER BY sequence_number ASC`,\n\t\t\t\t[nodeId, fromSeq, toSeq],\n\t\t\t)\n\t\t\tfor (const row of rows) {\n\t\t\t\tallOps.push(deserializeOperationWithCollection(row, collectionName))\n\t\t\t}\n\t\t}\n\n\t\t// Sort by sequence number across collections\n\t\tallOps.sort((a, b) => a.sequenceNumber - b.sequenceNumber)\n\t\treturn allOps\n\t}\n\n\t/**\n\t * Load every operation from the local append-only log across all collections.\n\t * Used by sync delta computation, backup export, and time-travel replay.\n\t */\n\tasync getAllOperations(): Promise<Operation[]> {\n\t\tthis.ensureOpen()\n\t\tconst allOps: Operation[] = []\n\n\t\tfor (const collectionName of Object.keys(this.schema.collections)) {\n\t\t\tconst rows = await this.adapter.query<OperationRow>(\n\t\t\t\t`SELECT * FROM _kora_ops_${collectionName} ORDER BY sequence_number ASC`,\n\t\t\t)\n\t\t\tfor (const row of rows) {\n\t\t\t\tallOps.push(deserializeOperationWithCollection(row, collectionName))\n\t\t\t}\n\t\t}\n\n\t\treturn allOps\n\t}\n\n\t/**\n\t * Rebuild an in-memory snapshot of materialized state at a causal cut in the op log.\n\t * Does not mutate the live store — intended for DevTools time-travel inspection.\n\t *\n\t * @param operationId - Content-addressed id of the operation to replay through (inclusive)\n\t * @throws {OperationError} When the operation id is not present in the local log\n\t */\n\tasync replayTo(operationId: string): Promise<ReplaySnapshot> {\n\t\tthis.ensureOpen()\n\t\tconst start = Date.now()\n\t\tconst allOps = await this.getAllOperations()\n\t\tconst snapshot = buildReplaySnapshot(this.schema, allOps, operationId)\n\n\t\tif (this.emitter) {\n\t\t\tthis.emitter.emit({\n\t\t\t\ttype: 'replay:completed',\n\t\t\t\ttargetOperationId: operationId,\n\t\t\t\toperationsApplied: snapshot.operationsApplied.length,\n\t\t\t\tduration: Date.now() - start,\n\t\t\t})\n\t\t}\n\n\t\treturn snapshot\n\t}\n\n\t/**\n\t * Persist a merge trace to the durable audit log.\n\t */\n\tasync appendAuditTrace(trace: import('../audit/types').PersistedAuditTrace): Promise<void> {\n\t\tthis.ensureOpen()\n\t\tconst { appendAuditTrace: append } = await import('../audit/audit-trace-store')\n\t\tawait append(this.adapter, trace)\n\t}\n\n\t/**\n\t * Read persisted audit traces with optional filters.\n\t */\n\tasync getAuditTraces(\n\t\tquery?: import('../audit/types').AuditTraceQuery,\n\t): Promise<import('../audit/types').PersistedAuditTrace[]> {\n\t\tthis.ensureOpen()\n\t\tconst { readAuditTraces } = await import('../audit/audit-trace-store')\n\t\treturn readAuditTraces(this.adapter, query)\n\t}\n\n\t/**\n\t * Export operations and merge traces as a portable audit bundle.\n\t */\n\tasync exportAudit(options?: import('../audit/types').AuditExportOptions): Promise<Uint8Array> {\n\t\tthis.ensureOpen()\n\t\tconst { exportAudit: doExport } = await import('../audit/export-audit')\n\t\treturn doExport(this.adapter, this.schema, this.nodeId, this.schema.version, options)\n\t}\n\n\t/**\n\t * Get the schema definition.\n\t */\n\tgetSchema(): SchemaDefinition {\n\t\treturn this.schema\n\t}\n\n\t/**\n\t * Route local CRUD through the unified apply pipeline (korajs ApplyPipeline).\n\t */\n\tsetLocalMutationHandler(handler: LocalMutationHandler | null): void {\n\t\tthis.localMutationHandler = handler\n\t\tfor (const col of this.collections.values()) {\n\t\t\tcol.setMutationHandler(handler)\n\t\t}\n\t}\n\n\t/**\n\t * Build mutation context for a collection (used by ApplyPipeline side effects).\n\t */\n\tcreateMutationContext(\n\t\tcollection: string,\n\t\toptions?: { inTransaction?: boolean; extraCausalDeps?: string[] },\n\t): LocalMutationContext {\n\t\tthis.ensureOpen()\n\t\tconst definition = this.schema.collections[collection]\n\t\tif (!definition || !this.clock) {\n\t\t\tthrow new StoreNotOpenError()\n\t\t}\n\t\treturn {\n\t\t\tcollection,\n\t\t\tdefinition,\n\t\t\tschema: this.schema,\n\t\t\tadapter: this.adapter,\n\t\t\tclock: this.clock,\n\t\t\tnodeId: this.nodeId,\n\t\t\tallocateSequenceNumber: () => this.allocateSequenceNumber(),\n\t\t\tonMutation: (collectionName, operation) => {\n\t\t\t\tthis.recordOperationSequence(operation)\n\t\t\t\tthis.subscriptionManager.notify(collectionName, operation)\n\t\t\t\tif (this.emitter) {\n\t\t\t\t\tthis.emitter.emit({ type: 'operation:created', operation })\n\t\t\t\t}\n\t\t\t},\n\t\t\trelationEnforcer: this.relationEnforcer,\n\t\t\tcausalTracker: this.causalTracker,\n\t\t\tinTransaction: options?.inTransaction ?? false,\n\t\t\textraCausalDeps: options?.extraCausalDeps,\n\t\t\tsecretKeyProvider: this.secretKeyProvider,\n\t\t}\n\t}\n\n\t/**\n\t * Load a materialized row by ID, including soft-deleted tombstones.\n\t */\n\tasync findMaterializedRow(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<MaterializedRowSnapshot | null> {\n\t\tthis.ensureOpen()\n\t\tconst definition = this.schema.collections[collection]\n\t\tif (!definition) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst rows = await this.adapter.query<RawCollectionRow>(\n\t\t\t`SELECT * FROM ${collection} WHERE id = ?`,\n\t\t\t[recordId],\n\t\t)\n\t\tconst row = rows[0]\n\t\tif (!row) {\n\t\t\treturn null\n\t\t}\n\n\t\treturn {\n\t\t\trecord: deserializeRecord(row, definition.fields),\n\t\t\tdeleted: row._deleted === 1,\n\t\t}\n\t}\n\n\t/**\n\t * Raw version state of a materialized row, for optimistic-concurrency guarded\n\t * applies: capture this snapshot before computing a merge, pass it as\n\t * `guardRowState`, and the apply refuses to write if the row changed since.\n\t * Returns null when no row exists (which is itself a valid guard state — the\n\t * apply then requires the row to still be absent).\n\t */\n\tasync getRowVersionState(collection: string, recordId: string): Promise<RowVersionState | null> {\n\t\tthis.ensureOpen()\n\t\tif (!this.schema.collections[collection]) {\n\t\t\treturn null\n\t\t}\n\t\tconst rows = await this.adapter.query<RawCollectionRow>(\n\t\t\t`SELECT _version, _field_versions FROM ${collection} WHERE id = ?`,\n\t\t\t[recordId],\n\t\t)\n\t\tconst row = rows[0]\n\t\tif (!row) {\n\t\t\treturn null\n\t\t}\n\t\treturn {\n\t\t\tversion: typeof row._version === 'string' ? row._version : null,\n\t\t\tfieldVersions: typeof row._field_versions === 'string' ? row._field_versions : null,\n\t\t}\n\t}\n\n\t/**\n\t * Latest operation from this device for a record (used for delete-vs-update merge on sync).\n\t */\n\t/**\n\t * Load the last server version vector acknowledged by this client (persisted in `_kora_meta`).\n\t */\n\tasync loadLastAckedServerVector(): Promise<VersionVector> {\n\t\tthis.ensureOpen()\n\t\treturn loadLastAckedServerVector(this.adapter)\n\t}\n\n\t/**\n\t * Persist the last server version vector this client believes the server has applied.\n\t */\n\tasync saveLastAckedServerVector(vector: VersionVector): Promise<void> {\n\t\tthis.ensureOpen()\n\t\tawait saveLastAckedServerVector(this.adapter, vector)\n\t}\n\n\t/**\n\t * Load persisted delta cursor for resuming paginated initial sync.\n\t */\n\tasync loadDeltaCursor(): Promise<string | null> {\n\t\tthis.ensureOpen()\n\t\treturn loadDeltaCursor(this.adapter)\n\t}\n\n\t/**\n\t * Persist or clear the delta cursor for paginated initial sync resume.\n\t */\n\tasync saveDeltaCursor(cursor: string | null): Promise<void> {\n\t\tthis.ensureOpen()\n\t\tawait saveDeltaCursor(this.adapter, cursor)\n\t}\n\n\t/**\n\t * Local operations not yet reflected on the server version vector.\n\t */\n\tasync getUnsyncedOperations(serverVector: VersionVector): Promise<Operation[]> {\n\t\tthis.ensureOpen()\n\t\treturn collectOperationsAheadOfServer(\n\t\t\tthis.getVersionVector(),\n\t\t\tserverVector,\n\t\t\t(nodeId, fromSeq, toSeq) => this.getOperationRange(nodeId, fromSeq, toSeq),\n\t\t)\n\t}\n\n\t/**\n\t * Re-stamp never-acknowledged local operations after a fast device clock was\n\t * corrected, so sync can resume immediately. Safe because unacknowledged\n\t * operations are private to this device (like unpushed git commits);\n\t * acknowledged/shared operations are immutable and never touched.\n\t *\n\t * After the rewrite the store's HLC is advanced past the highest new\n\t * timestamp so subsequent local writes keep sorting after the rebased ops.\n\t * No data-change notifications are emitted: materialized values are\n\t * unchanged, only version stamps move.\n\t */\n\tasync rebaseUnsyncedOperations(\n\t\tunsyncedOpIds: string[],\n\t\tcorrectedNowMs: number,\n\t): Promise<ClockRebaseResult> {\n\t\tthis.ensureOpen()\n\t\tconst result = await rebaseUnsyncedOperationsInLog(\n\t\t\tthis.adapter,\n\t\t\tthis.schema,\n\t\t\tunsyncedOpIds,\n\t\t\tcorrectedNowMs,\n\t\t)\n\t\tif (result.newMaxTimestamp && this.clock) {\n\t\t\tthis.clock.advanceTo(result.newMaxTimestamp)\n\t\t}\n\t\treturn result\n\t}\n\n\t/**\n\t * Count of local operations ahead of the server version vector.\n\t */\n\tasync countUnsyncedOperations(serverVector: VersionVector): Promise<number> {\n\t\tconst ops = await this.getUnsyncedOperations(serverVector)\n\t\treturn ops.length\n\t}\n\n\t/**\n\t * Compact the local operation log using materialized rows as the baseline.\n\t * Only removes ops the server has acknowledged (per {@link CompactionStrategy}).\n\t */\n\tasync compact(strategy: CompactionStrategy): Promise<CompactionResult> {\n\t\tthis.ensureOpen()\n\t\tif (strategy.mode === 'never') {\n\t\t\treturn compactOperationLog(this.adapter, this.schema, strategy, createVersionVector())\n\t\t}\n\n\t\tconst serverVector = strategy.serverVector ?? (await loadLastAckedServerVector(this.adapter))\n\t\treturn compactOperationLog(this.adapter, this.schema, strategy, serverVector)\n\t}\n\n\t/**\n\t * Merge session remote vector with persisted last-acked vector (max per node).\n\t */\n\tmergeServerVectors(sessionVector: VersionVector, persistedVector: VersionVector): VersionVector {\n\t\treturn mergeVersionVectors(persistedVector, sessionVector)\n\t}\n\n\tasync getLatestLocalOperationForRecord(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<Operation | null> {\n\t\tthis.ensureOpen()\n\t\tconst rows = await this.adapter.query<OperationRow>(\n\t\t\t`SELECT * FROM _kora_ops_${collection} WHERE node_id = ? AND record_id = ? ORDER BY sequence_number DESC LIMIT 1`,\n\t\t\t[this.nodeId, recordId],\n\t\t)\n\t\tconst row = rows[0]\n\t\tif (!row) {\n\t\t\treturn null\n\t\t}\n\t\treturn deserializeOperationWithCollection(row, collection)\n\t}\n\n\t/**\n\t * Latest operation for a record from any node (for 3-way merge when local op log is empty).\n\t */\n\tasync getLatestOperationForRecord(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<Operation | null> {\n\t\tthis.ensureOpen()\n\t\tconst rows = await this.adapter.query<OperationRow>(\n\t\t\t`SELECT * FROM _kora_ops_${collection} WHERE record_id = ?`,\n\t\t\t[recordId],\n\t\t)\n\n\t\tlet latest: Operation | null = null\n\t\tfor (const row of rows) {\n\t\t\tconst op = deserializeOperationWithCollection(row, collection)\n\t\t\tif (!latest || HybridLogicalClock.compare(op.timestamp, latest.timestamp) > 0) {\n\t\t\t\tlatest = op\n\t\t\t}\n\t\t}\n\t\treturn latest\n\t}\n\n\t/** Expose the subscription manager for direct access (e.g., by QueryBuilder) */\n\tgetSubscriptionManager(): SubscriptionManager {\n\t\treturn this.subscriptionManager\n\t}\n\n\t/**\n\t * Get the sequence manager for offline-safe sequence generation.\n\t * @throws {StoreNotOpenError} If the store is not open\n\t */\n\tgetSequenceManager(): SequenceManager {\n\t\tthis.ensureOpen()\n\t\tif (!this.sequenceManager) {\n\t\t\tthrow new StoreNotOpenError()\n\t\t}\n\t\treturn this.sequenceManager\n\t}\n\n\t/**\n\t * Create a TransactionContext for atomic multi-collection operations.\n\t * The returned context buffers all mutations and commits them atomically.\n\t *\n\t * After commit, the caller is responsible for notifying subscriptions\n\t * and emitting events for each operation.\n\t */\n\tcreateTransaction(): TransactionContext {\n\t\tthis.ensureOpen()\n\t\tif (!this.clock) {\n\t\t\tthrow new StoreNotOpenError()\n\t\t}\n\t\treturn new TransactionContext({\n\t\t\tschema: this.schema,\n\t\t\tadapter: this.adapter,\n\t\t\tclock: this.clock,\n\t\t\tnodeId: this.nodeId,\n\t\t\tsequenceAllocator: new TransactionSequenceAllocator(this.adapter, this.nodeId),\n\t\t\trelationEnforcer: this.relationEnforcer,\n\t\t\tcausalTracker: this.causalTracker,\n\t\t\tlocalMutationHandler: this.localMutationHandler,\n\t\t})\n\t}\n\n\t/**\n\t * Execute a function within a transaction. All mutations performed on the\n\t * TransactionContext are committed atomically. Subscription notifications\n\t * are batched and fired after the commit.\n\t *\n\t * If the function throws, the transaction is rolled back and the error is re-thrown.\n\t *\n\t * @param fn - Function receiving a TransactionContext for buffered operations\n\t * @returns The operations that were committed\n\t */\n\tasync transaction(fn: (tx: TransactionContext) => Promise<void>): Promise<Operation[]> {\n\t\tconst tx = this.createTransaction()\n\t\tthis.causalTracker?.beginTransaction()\n\t\ttry {\n\t\t\tawait fn(tx)\n\t\t\tconst { operations } = await tx.commit()\n\n\t\t\tthis.causalTracker?.clearTransaction()\n\n\t\t\t// Notify subscriptions and emit events after commit\n\t\t\tfor (const op of operations) {\n\t\t\t\tthis.recordOperationSequence(op)\n\t\t\t\tthis.subscriptionManager.notify(op.collection, op)\n\t\t\t\tif (this.emitter) {\n\t\t\t\t\tthis.emitter.emit({ type: 'operation:created', operation: op })\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn operations\n\t\t} catch (error) {\n\t\t\ttx.rollback()\n\t\t\tthis.causalTracker?.clearTransaction()\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Export all data as a portable backup binary.\n\t * Includes operations, version vector, metadata, and optionally materialized records.\n\t *\n\t * @param options - Backup options (includeRecords, collections, onProgress)\n\t * @returns Backup as a Uint8Array\n\t */\n\tasync exportBackup(options?: BackupOptions): Promise<Uint8Array> {\n\t\tthis.ensureOpen()\n\t\tconst { exportBackup: doExport } = await import('../backup/backup')\n\t\treturn doExport(this.adapter, this.schema, this.nodeId, this.schema.version, options)\n\t}\n\n\t/**\n\t * Restore data from a backup binary.\n\t *\n\t * @param data - The backup data\n\t * @param options - Restore options (merge, collections, onProgress)\n\t * @returns Result of the restore operation\n\t */\n\tasync importBackup(data: Uint8Array, options?: RestoreOptions): Promise<RestoreResult> {\n\t\tthis.ensureOpen()\n\t\tconst { restoreBackup: doRestore } = await import('../backup/backup')\n\t\treturn doRestore(this.adapter, this.schema, data, options)\n\t}\n\n\t/**\n\t * Read backup manifest without loading the entire backup.\n\t *\n\t * @param data - The raw backup data\n\t * @returns The backup manifest\n\t */\n\tstatic readBackupManifest(data: Uint8Array): BackupManifest {\n\t\treturn readManifest(data)\n\t}\n\n\tprivate recordOperationSequence(operation: Operation): void {\n\t\tconst prev = this.versionVector.get(operation.nodeId) ?? 0\n\t\tif (operation.sequenceNumber > prev) {\n\t\t\tthis.versionVector.set(operation.nodeId, operation.sequenceNumber)\n\t\t}\n\t\tif (operation.nodeId === this.nodeId) {\n\t\t\tthis.sequenceNumber = Math.max(this.sequenceNumber, operation.sequenceNumber)\n\t\t}\n\t}\n\n\tprivate async allocateSequenceNumber(): Promise<number> {\n\t\tconst seq = await allocateNextSequenceNumber(this.adapter, this.nodeId)\n\t\tthis.sequenceNumber = seq\n\t\tthis.versionVector.set(this.nodeId, seq)\n\t\treturn seq\n\t}\n\n\t/**\n\t * Check the stored schema version and run any pending migrations.\n\t * Migrations are applied in version order within a transaction.\n\t */\n\tprivate async runMigrationsIfNeeded(): Promise<void> {\n\t\tconst storedVersion = await this.getStoredSchemaVersion()\n\t\tconst targetVersion = this.schema.version\n\n\t\tif (storedVersion >= targetVersion) {\n\t\t\t// Already up to date (or first run with version 1)\n\t\t\tif (storedVersion === 0) {\n\t\t\t\t// First open — store the initial version\n\t\t\t\tawait this.adapter.execute(\n\t\t\t\t\t\"INSERT OR REPLACE INTO _kora_meta (key, value) VALUES ('schema_version', ?)\",\n\t\t\t\t\t[String(targetVersion)],\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\t// Run each migration in order from storedVersion+1 to targetVersion\n\t\tconst migrations = this.schema.migrations ?? {}\n\t\tfor (let v = storedVersion + 1; v <= targetVersion; v++) {\n\t\t\tconst migration = migrations[v]\n\t\t\tif (!migration) continue\n\n\t\t\t// Generate SQL from structural steps\n\t\t\tconst sqlStatements = migrationStepsToSQL(migration.steps)\n\n\t\t\t// Execute structural changes individually, tolerating \"duplicate column\" errors\n\t\t\t// because generateSQL already emits --kora:safe-alter ALTER TABLE statements\n\t\t\t// for the current schema's columns (run via generateFullDDL in adapter.open()).\n\t\t\tfor (const sql of sqlStatements) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.adapter.execute(sql)\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconst msg = (e as Error).message || ''\n\t\t\t\t\tif (!msg.includes('duplicate column name')) {\n\t\t\t\t\t\tthrow e\n\t\t\t\t\t}\n\t\t\t\t\t// Column already exists (added by safe-alter in generateSQL) — safe to skip\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Run backfills in a transaction\n\t\t\tconst backfillSteps = migration.steps.filter(\n\t\t\t\t(s): s is Extract<MigrationStep, { type: 'backfill' }> => s.type === 'backfill',\n\t\t\t)\n\t\t\tfor (const step of backfillSteps) {\n\t\t\t\tawait this.runBackfill(step.collection, step.transform)\n\t\t\t}\n\t\t}\n\n\t\t// Update stored schema version\n\t\tawait this.adapter.execute(\n\t\t\t\"INSERT OR REPLACE INTO _kora_meta (key, value) VALUES ('schema_version', ?)\",\n\t\t\t[String(targetVersion)],\n\t\t)\n\t}\n\n\t/**\n\t * Get the stored schema version from _kora_meta. Returns 0 if not set.\n\t */\n\tprivate async getStoredSchemaVersion(): Promise<number> {\n\t\tconst rows = await this.adapter.query<MetaRow>(\n\t\t\t\"SELECT value FROM _kora_meta WHERE key = 'schema_version'\",\n\t\t)\n\t\treturn rows[0] ? Number(rows[0].value) : 0\n\t}\n\n\t/**\n\t * Run a backfill transform on all records in a collection.\n\t * Reads all rows, applies the transform, and updates changed fields.\n\t */\n\tprivate async runBackfill(\n\t\tcollection: string,\n\t\ttransform: (record: Record<string, unknown>) => Record<string, unknown>,\n\t): Promise<void> {\n\t\tconst rows = await this.adapter.query<RawCollectionRow>(\n\t\t\t`SELECT * FROM ${collection} WHERE _deleted = 0`,\n\t\t)\n\n\t\tawait this.adapter.transaction(async (tx) => {\n\t\t\tfor (const row of rows) {\n\t\t\t\tconst updates = transform(row as Record<string, unknown>)\n\t\t\t\tconst fields = Object.keys(updates)\n\t\t\t\tif (fields.length === 0) continue\n\n\t\t\t\tconst setClauses = fields.map((f) => `${f} = ?`).join(', ')\n\t\t\t\tconst values = fields.map((f) => {\n\t\t\t\t\tconst val = updates[f]\n\t\t\t\t\t// Serialize booleans to 0/1 for SQLite\n\t\t\t\t\tif (typeof val === 'boolean') return val ? 1 : 0\n\t\t\t\t\t// Serialize arrays/objects to JSON\n\t\t\t\t\tif (Array.isArray(val) || (typeof val === 'object' && val !== null)) {\n\t\t\t\t\t\treturn JSON.stringify(val)\n\t\t\t\t\t}\n\t\t\t\t\treturn val\n\t\t\t\t})\n\t\t\t\tvalues.push(row.id)\n\n\t\t\t\tawait tx.execute(`UPDATE ${collection} SET ${setClauses} WHERE id = ?`, values)\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate async loadOrGenerateNodeId(): Promise<string> {\n\t\tif (this.configNodeId) {\n\t\t\tif (this.isolation !== 'per-tab') {\n\t\t\t\tawait this.adapter.execute(\n\t\t\t\t\t\"INSERT OR REPLACE INTO _kora_meta (key, value) VALUES ('node_id', ?)\",\n\t\t\t\t\t[this.configNodeId],\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn this.configNodeId\n\t\t}\n\n\t\tif (this.isolation === 'per-tab') {\n\t\t\treturn resolvePerTabNodeId(this.dbName)\n\t\t}\n\n\t\t// Try to load existing node ID\n\t\tconst rows = await this.adapter.query<MetaRow>(\n\t\t\t\"SELECT value FROM _kora_meta WHERE key = 'node_id'\",\n\t\t)\n\t\tif (rows[0]) {\n\t\t\treturn rows[0].value\n\t\t}\n\n\t\t// Generate new node ID\n\t\tconst newNodeId = generateUUIDv7()\n\t\tawait this.adapter.execute(\"INSERT INTO _kora_meta (key, value) VALUES ('node_id', ?)\", [\n\t\t\tnewNodeId,\n\t\t])\n\t\treturn newNodeId\n\t}\n\n\tprivate async loadSequenceNumber(): Promise<number> {\n\t\tconst rows = await this.adapter.query<VersionVectorRow>(\n\t\t\t'SELECT sequence_number FROM _kora_version_vector WHERE node_id = ?',\n\t\t\t[this.nodeId],\n\t\t)\n\t\treturn rows[0]?.sequence_number ?? 0\n\t}\n\n\tprivate async loadVersionVector(): Promise<VersionVector> {\n\t\tconst rows = await this.adapter.query<VersionVectorRow>(\n\t\t\t'SELECT node_id, sequence_number FROM _kora_version_vector',\n\t\t)\n\t\tconst vector = createVersionVector()\n\t\tfor (const row of rows) {\n\t\t\tvector.set(row.node_id, row.sequence_number)\n\t\t}\n\t\treturn vector\n\t}\n\n\tprivate ensureOpen(): void {\n\t\tif (!this.opened) {\n\t\t\tthrow new StoreNotOpenError()\n\t\t}\n\t}\n}\n\n/**\n * Public-facing collection accessor. Provides CRUD + where.\n */\nexport interface CollectionAccessor {\n\tinsert(data: Record<string, unknown>): Promise<import('../types').CollectionRecord>\n\tfindById(id: string): Promise<import('../types').CollectionRecord | null>\n\tupdate(id: string, data: Record<string, unknown>): Promise<import('../types').CollectionRecord>\n\tdelete(id: string): Promise<void>\n\twhere(conditions: Record<string, unknown>): QueryBuilder\n}\n","import { createOperation } from '@korajs/core'\nimport type { Operation } from '@korajs/core'\nimport { RecordNotFoundError } from '../errors'\nimport { serializeRowVersion } from '../lww/row-version'\nimport { buildInsertQuery, buildSoftDeleteQuery } from '../query/sql-builder'\nimport { serializeOperation } from '../serialization/serializer'\nimport { allocateNextSequenceInTransaction } from '../store/sequence-allocator'\nimport type { RawCollectionRow } from '../types'\nimport { resolveCausalDeps } from './resolve-causal-deps'\nimport type { LocalMutationContext } from './types'\n\nexport interface ExecuteDeleteOptions {\n\t/** When true, skip RelationEnforcer (caller already enforced referential integrity). */\n\tskipReferentialEnforcement?: boolean\n\t/** Pre-built delete operation (avoids duplicate sequence allocation). */\n\toperation?: Operation\n}\n\n/**\n * Soft-delete a record and persist the operation log entry atomically.\n * Returns the primary delete operation and any cascaded side-effect operations.\n */\nexport async function executeDelete(\n\tctx: LocalMutationContext,\n\tid: string,\n\toptions?: ExecuteDeleteOptions,\n): Promise<Operation[]> {\n\tconst currentRows = await ctx.adapter.query<RawCollectionRow>(\n\t\t`SELECT * FROM ${ctx.collection} WHERE id = ? AND _deleted = 0`,\n\t\t[id],\n\t)\n\tif (!currentRows[0]) {\n\t\tthrow new RecordNotFoundError(ctx.collection, id)\n\t}\n\n\tconst causalDeps = resolveCausalDeps(ctx)\n\tlet operation = options?.operation\n\tconst cascadedOps: Operation[] = []\n\n\tawait ctx.adapter.transaction(async (tx) => {\n\t\tif (!operation) {\n\t\t\tconst sequenceNumber = await allocateNextSequenceInTransaction(tx, ctx.nodeId)\n\t\t\toperation = await createOperation(\n\t\t\t\t{\n\t\t\t\t\tnodeId: ctx.nodeId,\n\t\t\t\t\ttype: 'delete',\n\t\t\t\t\tcollection: ctx.collection,\n\t\t\t\t\trecordId: id,\n\t\t\t\t\tdata: null,\n\t\t\t\t\tpreviousData: null,\n\t\t\t\t\tsequenceNumber,\n\t\t\t\t\tcausalDeps,\n\t\t\t\t\tschemaVersion: ctx.schema.version,\n\t\t\t\t},\n\t\t\t\tctx.clock,\n\t\t\t)\n\t\t\tctx.causalTracker?.afterOperation(ctx.collection, operation.id, ctx.inTransaction)\n\t\t}\n\n\t\tif (ctx.relationEnforcer && !options?.skipReferentialEnforcement) {\n\t\t\tconst enforcementResult = await ctx.relationEnforcer.enforceDelete(ctx.collection, id, tx, [\n\t\t\t\toperation.id,\n\t\t\t])\n\t\t\tcascadedOps.push(...enforcementResult.operations)\n\t\t}\n\n\t\tconst version = serializeRowVersion(operation.timestamp)\n\t\tconst deleteQuery = buildSoftDeleteQuery(\n\t\t\tctx.collection,\n\t\t\tid,\n\t\t\toperation.timestamp.wallTime,\n\t\t\tversion,\n\t\t)\n\t\tconst opInsert = buildInsertQuery(\n\t\t\t`_kora_ops_${ctx.collection}`,\n\t\t\tserializeOperation(operation) as unknown as Record<string, unknown>,\n\t\t)\n\n\t\tawait tx.execute(deleteQuery.sql, deleteQuery.params)\n\t\tawait tx.execute(opInsert.sql, opInsert.params)\n\t})\n\n\tif (!operation) {\n\t\tthrow new Error('Delete operation was not created')\n\t}\n\n\tctx.onMutation(ctx.collection, operation)\n\tfor (const cascadedOp of cascadedOps) {\n\t\tctx.onMutation(cascadedOp.collection, cascadedOp)\n\t}\n\n\treturn [operation, ...cascadedOps]\n}\n","import { type HLCTimestamp, HybridLogicalClock } from '@korajs/core'\nimport type { RawCollectionRow } from '../types'\n\n/** Empty _version means legacy rows (compare by wallTime only via fallback). */\nexport const EMPTY_ROW_VERSION = ''\n\n/**\n * Serialize an HLC timestamp for storage in the `_version` column.\n * Lexicographic order matches {@link HybridLogicalClock.compare}.\n */\nexport function serializeRowVersion(timestamp: HLCTimestamp): string {\n\treturn HybridLogicalClock.serialize(timestamp)\n}\n\n/**\n * Read the version stamp stored on a materialized row.\n * Legacy rows without `_version` fall back to wallTime with logical 0.\n */\nexport function rowVersionFromRecord(\n\trow: Pick<RawCollectionRow, '_updated_at' | '_version'>,\n): HLCTimestamp {\n\tconst version = row._version\n\tif (typeof version === 'string' && version.length > 0) {\n\t\treturn HybridLogicalClock.deserialize(version)\n\t}\n\treturn { wallTime: row._updated_at, logical: 0, nodeId: '' }\n}\n\n/**\n * Returns true when `incoming` is strictly newer than the version on `row`.\n */\nexport function isIncomingNewerThanRow(\n\tincoming: HLCTimestamp,\n\trow: Pick<RawCollectionRow, '_updated_at' | '_version'>,\n): boolean {\n\treturn HybridLogicalClock.compare(incoming, rowVersionFromRecord(row)) > 0\n}\n\n/**\n * SQL fragment and params for LWW guards: apply only when row is missing or older.\n * Uses serialized `_version` for total order (matches HLC compare).\n */\nexport function lwwVersionWhereClause(remoteVersion: string): { sql: string; params: string[] } {\n\treturn {\n\t\tsql: '(_version = ? OR _version < ?)',\n\t\tparams: [EMPTY_ROW_VERSION, remoteVersion],\n\t}\n}\n","import type { CollectionDefinition, FieldDescriptor } from '@korajs/core'\nimport { QueryError } from '../errors'\nimport { lwwVersionWhereClause } from '../lww/row-version'\nimport type { QueryDescriptor, WhereOperators } from '../types'\n\n/**\n * Result of building a SQL query: the parameterized SQL string and its bound values.\n */\nexport interface SqlQuery {\n\tsql: string\n\tparams: unknown[]\n}\n\n/**\n * Build a SELECT query from a QueryDescriptor.\n * Automatically adds `WHERE _deleted = 0` to exclude soft-deleted records.\n *\n * @param descriptor - The query descriptor\n * @param fields - The field descriptors from the collection schema\n * @returns A parameterized SQL query\n */\nexport function buildSelectQuery(\n\tdescriptor: QueryDescriptor,\n\tfields: Record<string, FieldDescriptor>,\n): SqlQuery {\n\tconst params: unknown[] = []\n\tconst parts = [`SELECT * FROM ${descriptor.collection}`]\n\n\tconst whereClause = buildWhereClauseParts(descriptor.where, fields, params)\n\t// Always filter out soft-deleted records\n\tconst deletedFilter = '_deleted = 0'\n\tif (whereClause) {\n\t\tparts.push(`WHERE ${deletedFilter} AND ${whereClause}`)\n\t} else {\n\t\tparts.push(`WHERE ${deletedFilter}`)\n\t}\n\n\tif (descriptor.orderBy.length > 0) {\n\t\tconst orderParts = descriptor.orderBy.map((o) => {\n\t\t\tvalidateFieldName(o.field, fields)\n\t\t\treturn `${o.field} ${o.direction.toUpperCase()}`\n\t\t})\n\t\tparts.push(`ORDER BY ${orderParts.join(', ')}`)\n\t}\n\n\tif (descriptor.limit !== undefined) {\n\t\tparts.push(`LIMIT ${descriptor.limit}`)\n\t}\n\n\tif (descriptor.offset !== undefined) {\n\t\tparts.push(`OFFSET ${descriptor.offset}`)\n\t}\n\n\treturn { sql: parts.join(' '), params }\n}\n\n/**\n * Build a COUNT query from a QueryDescriptor.\n * Automatically adds `WHERE _deleted = 0`.\n *\n * @param descriptor - The query descriptor\n * @param fields - The field descriptors from the collection schema\n * @returns A parameterized SQL query that returns { count: number }\n */\nexport function buildCountQuery(\n\tdescriptor: QueryDescriptor,\n\tfields: Record<string, FieldDescriptor>,\n): SqlQuery {\n\tconst params: unknown[] = []\n\tconst parts = [`SELECT COUNT(*) as count FROM ${descriptor.collection}`]\n\n\tconst whereClause = buildWhereClauseParts(descriptor.where, fields, params)\n\tconst deletedFilter = '_deleted = 0'\n\tif (whereClause) {\n\t\tparts.push(`WHERE ${deletedFilter} AND ${whereClause}`)\n\t} else {\n\t\tparts.push(`WHERE ${deletedFilter}`)\n\t}\n\n\treturn { sql: parts.join(' '), params }\n}\n\n/**\n * Build an INSERT query for a collection record.\n *\n * @param collection - The collection name\n * @param record - The record data (already serialized with id, _created_at, _updated_at)\n * @returns A parameterized SQL query\n */\nexport function buildInsertQuery(collection: string, record: Record<string, unknown>): SqlQuery {\n\tconst columns = Object.keys(record)\n\tconst placeholders = columns.map(() => '?')\n\tconst params = Object.values(record)\n\n\tconst sql = `INSERT INTO ${collection} (${columns.join(', ')}) VALUES (${placeholders.join(', ')})`\n\treturn { sql, params }\n}\n\n/**\n * Build an UPDATE query for a collection record.\n *\n * @param collection - The collection name\n * @param id - The record ID\n * @param changes - The fields to update (already serialized)\n * @returns A parameterized SQL query\n */\nexport function buildUpdateQuery(\n\tcollection: string,\n\tid: string,\n\tchanges: Record<string, unknown>,\n): SqlQuery {\n\tconst setClauses = Object.keys(changes).map((col) => `${col} = ?`)\n\tconst params = [...Object.values(changes), id]\n\n\tconst sql = `UPDATE ${collection} SET ${setClauses.join(', ')} WHERE id = ?`\n\treturn { sql, params }\n}\n\n/**\n * Build a field-level fast-forward UPDATE: writes the changed field values\n * unconditionally (the caller has already proven per-field that the local value\n * still equals the base the remote wrote from, so the remote is the newest known\n * writer of those fields), while advancing the row's `_version` / `_updated_at`\n * watermark MONOTONICALLY — never regressing it below its current value.\n *\n * This is what makes per-field LWW correct on a per-row `_version` column: a\n * concurrent edit to a different field may have pushed `_version` past this\n * operation's timestamp, but that must not cause this operation's own field\n * change to be dropped, nor may materializing it move the watermark backward\n * (which would let a genuinely stale later operation win).\n *\n * @param collection - The collection name\n * @param id - The record ID\n * @param fieldChanges - Serialized field values to write unconditionally (must NOT include _version / _updated_at)\n * @param remoteVersion - The operation's serialized row version (lexicographically comparable)\n * @param wallTime - The operation's wall-clock time in ms\n * @param options - Optional extras. `maxCreatedAt` advances `_created_at` to the\n * greater of its current value and the given wall time — used for insert\n * collisions so every node converges on the max insert wall time regardless\n * of arrival order.\n */\nexport function buildFieldFastForwardUpdateQuery(\n\tcollection: string,\n\tid: string,\n\tfieldChanges: Record<string, unknown>,\n\tremoteVersion: string,\n\twallTime: number,\n\toptions?: { maxCreatedAt?: number },\n): SqlQuery {\n\tconst fieldClauses = Object.keys(fieldChanges).map((col) => `${col} = ?`)\n\t// _version is a lexicographically-sortable string; _updated_at is a number.\n\t// Keep the greater of the current and incoming value for each (monotonic).\n\tconst setClauses = [\n\t\t...fieldClauses,\n\t\t'_version = CASE WHEN _version >= ? THEN _version ELSE ? END',\n\t\t'_updated_at = CASE WHEN _updated_at >= ? THEN _updated_at ELSE ? END',\n\t]\n\tconst params: unknown[] = [\n\t\t...Object.values(fieldChanges),\n\t\tremoteVersion,\n\t\tremoteVersion,\n\t\twallTime,\n\t\twallTime,\n\t]\n\tif (options?.maxCreatedAt !== undefined) {\n\t\tsetClauses.push('_created_at = CASE WHEN _created_at >= ? THEN _created_at ELSE ? END')\n\t\tparams.push(options.maxCreatedAt, options.maxCreatedAt)\n\t}\n\tparams.push(id)\n\tconst sql = `UPDATE ${collection} SET ${setClauses.join(', ')} WHERE id = ?`\n\treturn { sql, params }\n}\n\n/**\n * Build a soft-delete query (SET _deleted = 1).\n *\n * @param collection - The collection name\n * @param id - The record ID\n * @param updatedAt - The timestamp to set on _updated_at\n * @returns A parameterized SQL query\n */\nexport function buildSoftDeleteQuery(\n\tcollection: string,\n\tid: string,\n\tupdatedAt: number,\n\tversion?: string,\n): SqlQuery {\n\tif (version !== undefined) {\n\t\treturn {\n\t\t\tsql: `UPDATE ${collection} SET _deleted = 1, _updated_at = ?, _version = ? WHERE id = ?`,\n\t\t\tparams: [updatedAt, version, id],\n\t\t}\n\t}\n\treturn {\n\t\tsql: `UPDATE ${collection} SET _deleted = 1, _updated_at = ? WHERE id = ?`,\n\t\tparams: [updatedAt, id],\n\t}\n}\n\n/**\n * Build an UPDATE that applies only when the row is missing or older than `remoteVersion`\n * (serialized HLC). Prevents stale remote sync from overwriting newer local materialized state.\n */\nexport function buildLwwUpdateQuery(\n\tcollection: string,\n\tid: string,\n\tchanges: Record<string, unknown>,\n\tremoteVersion: string,\n): SqlQuery {\n\tconst setClauses = Object.keys(changes).map((col) => `${col} = ?`)\n\tconst lww = lwwVersionWhereClause(remoteVersion)\n\tconst sql = `UPDATE ${collection} SET ${setClauses.join(', ')} WHERE id = ? AND ${lww.sql}`\n\tconst params = [...Object.values(changes), id, ...lww.params]\n\treturn { sql, params }\n}\n\n/**\n * Build a soft-delete that applies only when the row is older than `remoteVersion`.\n */\nexport function buildLwwSoftDeleteQuery(\n\tcollection: string,\n\tid: string,\n\tupdatedAt: number,\n\tversion: string,\n): SqlQuery {\n\tconst lww = lwwVersionWhereClause(version)\n\treturn {\n\t\tsql: `UPDATE ${collection} SET _deleted = 1, _updated_at = ?, _version = ? WHERE id = ? AND ${lww.sql}`,\n\t\tparams: [updatedAt, version, id, ...lww.params],\n\t}\n}\n\n/**\n * Build a WHERE clause from conditions, validating field names against the schema.\n *\n * @param where - The where conditions\n * @param fields - The field descriptors from the collection schema\n * @returns The SQL WHERE clause string and params, or null if no conditions\n */\nexport function buildWhereClause(\n\twhere: Record<string, unknown>,\n\tfields: Record<string, FieldDescriptor>,\n): SqlQuery | null {\n\tconst params: unknown[] = []\n\tconst result = buildWhereClauseParts(where, fields, params)\n\tif (!result) return null\n\treturn { sql: result, params }\n}\n\n// --- Internal helpers ---\n\nconst VALID_OPERATORS = new Set(['$eq', '$ne', '$gt', '$gte', '$lt', '$lte', '$in'])\n\nfunction buildWhereClauseParts(\n\twhere: Record<string, unknown>,\n\tfields: Record<string, FieldDescriptor>,\n\tparams: unknown[],\n): string | null {\n\tconst conditions: string[] = []\n\n\tfor (const [fieldName, value] of Object.entries(where)) {\n\t\tvalidateFieldName(fieldName, fields)\n\t\tconst descriptor = fields[fieldName]\n\n\t\tif (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n\t\t\t// Operator object: { $gt: 5, $lt: 10 }\n\t\t\tconst ops = value as WhereOperators\n\t\t\tfor (const [op, opValue] of Object.entries(ops)) {\n\t\t\t\tif (!VALID_OPERATORS.has(op)) {\n\t\t\t\t\tthrow new QueryError(`Unknown operator \"${op}\" on field \"${fieldName}\"`, {\n\t\t\t\t\t\tfield: fieldName,\n\t\t\t\t\t\toperator: op,\n\t\t\t\t\t\tvalidOperators: [...VALID_OPERATORS],\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tconditions.push(buildOperatorCondition(fieldName, op, opValue, descriptor, params))\n\t\t\t}\n\t\t} else {\n\t\t\t// Shorthand: { completed: false } means { completed: { $eq: false } }\n\t\t\tconditions.push(buildOperatorCondition(fieldName, '$eq', value, descriptor, params))\n\t\t}\n\t}\n\n\tif (conditions.length === 0) return null\n\treturn conditions.join(' AND ')\n}\n\nfunction buildOperatorCondition(\n\tfieldName: string,\n\toperator: string,\n\tvalue: unknown,\n\tdescriptor: FieldDescriptor | undefined,\n\tparams: unknown[],\n): string {\n\t// Serialize boolean values to 0/1 for SQL comparison\n\tconst sqlValue =\n\t\tdescriptor?.kind === 'boolean' && typeof value === 'boolean' ? (value ? 1 : 0) : value\n\n\tswitch (operator) {\n\t\tcase '$eq':\n\t\t\tif (sqlValue === null) {\n\t\t\t\treturn `${fieldName} IS NULL`\n\t\t\t}\n\t\t\tparams.push(sqlValue)\n\t\t\treturn `${fieldName} = ?`\n\t\tcase '$ne':\n\t\t\tif (sqlValue === null) {\n\t\t\t\treturn `${fieldName} IS NOT NULL`\n\t\t\t}\n\t\t\tparams.push(sqlValue)\n\t\t\treturn `${fieldName} != ?`\n\t\tcase '$gt':\n\t\t\tparams.push(sqlValue)\n\t\t\treturn `${fieldName} > ?`\n\t\tcase '$gte':\n\t\t\tparams.push(sqlValue)\n\t\t\treturn `${fieldName} >= ?`\n\t\tcase '$lt':\n\t\t\tparams.push(sqlValue)\n\t\t\treturn `${fieldName} < ?`\n\t\tcase '$lte':\n\t\t\tparams.push(sqlValue)\n\t\t\treturn `${fieldName} <= ?`\n\t\tcase '$in': {\n\t\t\tif (!Array.isArray(sqlValue)) {\n\t\t\t\tthrow new QueryError(`$in operator requires an array value for field \"${fieldName}\"`, {\n\t\t\t\t\tfield: fieldName,\n\t\t\t\t\treceived: typeof sqlValue,\n\t\t\t\t})\n\t\t\t}\n\t\t\tconst placeholders = sqlValue.map(() => '?')\n\t\t\tfor (const item of sqlValue) {\n\t\t\t\tparams.push(\n\t\t\t\t\tdescriptor?.kind === 'boolean' && typeof item === 'boolean' ? (item ? 1 : 0) : item,\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn `${fieldName} IN (${placeholders.join(', ')})`\n\t\t}\n\t\tdefault:\n\t\t\tthrow new QueryError(`Unknown operator \"${operator}\"`, { operator })\n\t}\n}\n\nfunction validateFieldName(fieldName: string, fields: Record<string, FieldDescriptor>): void {\n\t// Allow schema fields plus metadata fields that map to query-able columns\n\tconst allowedFields = new Set([\n\t\t...Object.keys(fields),\n\t\t'id',\n\t\t'createdAt',\n\t\t'updatedAt',\n\t\t'_created_at',\n\t\t'_updated_at',\n\t])\n\tif (!allowedFields.has(fieldName)) {\n\t\tthrow new QueryError(\n\t\t\t`Unknown field \"${fieldName}\" in query. Available fields: ${[...allowedFields].join(', ')}`,\n\t\t\t{ field: fieldName },\n\t\t)\n\t}\n}\n","import type { StorageAdapter, Transaction } from '../types'\n\ninterface SequenceRow {\n\tsequence_number: number\n}\n\n/**\n * Atomically increment and return the next sequence number for a node.\n * Uses SQLite UPSERT + RETURNING so concurrent tabs do not reuse sequence slots.\n */\nexport async function allocateNextSequenceNumber(\n\tadapter: StorageAdapter,\n\tnodeId: string,\n): Promise<number> {\n\tconst rows = await adapter.query<SequenceRow>(\n\t\t`INSERT INTO _kora_version_vector (node_id, sequence_number) VALUES (?, 1)\n ON CONFLICT(node_id) DO UPDATE SET sequence_number = sequence_number + 1\n RETURNING sequence_number`,\n\t\t[nodeId],\n\t)\n\tconst seq = rows[0]?.sequence_number\n\tif (seq === undefined) {\n\t\tthrow new Error(`Failed to allocate sequence number for node \"${nodeId}\"`)\n\t}\n\treturn seq\n}\n\n/**\n * Allocate the next sequence inside an existing storage transaction.\n */\nexport async function allocateNextSequenceInTransaction(\n\ttx: Transaction,\n\tnodeId: string,\n): Promise<number> {\n\tconst rows = await tx.query<SequenceRow>(\n\t\t`INSERT INTO _kora_version_vector (node_id, sequence_number) VALUES (?, 1)\n ON CONFLICT(node_id) DO UPDATE SET sequence_number = sequence_number + 1\n RETURNING sequence_number`,\n\t\t[nodeId],\n\t)\n\tconst seq = rows[0]?.sequence_number\n\tif (seq === undefined) {\n\t\tthrow new Error(`Failed to allocate sequence number for node \"${nodeId}\" in transaction`)\n\t}\n\treturn seq\n}\n\n/**\n * Read the current sequence for a node without incrementing.\n */\nexport async function readSequenceNumber(adapter: StorageAdapter, nodeId: string): Promise<number> {\n\tconst rows = await adapter.query<SequenceRow>(\n\t\t'SELECT sequence_number FROM _kora_version_vector WHERE node_id = ?',\n\t\t[nodeId],\n\t)\n\treturn rows[0]?.sequence_number ?? 0\n}\n","import type { LocalMutationContext } from './types'\n\n/**\n * Merge explicit parent deps (e.g. referential cascade) with tracker-derived deps.\n */\nexport function resolveCausalDeps(ctx: LocalMutationContext): string[] {\n\tconst merged: string[] = []\n\tfor (const id of ctx.extraCausalDeps ?? []) {\n\t\tif (!merged.includes(id)) {\n\t\t\tmerged.push(id)\n\t\t}\n\t}\n\tfor (const id of ctx.causalTracker?.nextCausalDeps(ctx.collection, ctx.inTransaction) ?? []) {\n\t\tif (!merged.includes(id)) {\n\t\t\tmerged.push(id)\n\t\t}\n\t}\n\treturn merged\n}\n","import {\n\tcreateOperation,\n\tgenerateUUIDv7,\n\ttransformSecretFieldsForWrite,\n\tvalidateRecord,\n} from '@korajs/core'\nimport { fieldVersionsForFields, serializeFieldVersions } from '../lww/field-versions'\nimport { serializeRowVersion } from '../lww/row-version'\nimport { buildInsertQuery } from '../query/sql-builder'\nimport { encodeRichtextFieldsForOpData } from '../serialization/op-data-encoding'\nimport { serializeOperation, serializeRecord } from '../serialization/serializer'\nimport { allocateNextSequenceInTransaction } from '../store/sequence-allocator'\nimport type { CollectionRecord } from '../types'\nimport { resolveCausalDeps } from './resolve-causal-deps'\nimport type { LocalMutationContext } from './types'\n\n/**\n * Insert a record and persist the operation log entry atomically.\n */\nexport async function executeInsert(\n\tctx: LocalMutationContext,\n\tdata: Record<string, unknown>,\n): Promise<CollectionRecord> {\n\tconst validated = validateRecord(ctx.collection, ctx.definition, data, 'insert')\n\tconst recordId = generateUUIDv7()\n\n\tfor (const [fieldName, descriptor] of Object.entries(ctx.definition.fields)) {\n\t\tif (descriptor.auto && descriptor.kind === 'timestamp') {\n\t\t\tvalidated[fieldName] = Date.now()\n\t\t}\n\t}\n\n\t// Transform secret fields to their at-rest form (hash/ciphertext) BEFORE the\n\t// operation is built, so plaintext never enters the op log, store, or sync.\n\tconst writeData = await transformSecretFieldsForWrite(\n\t\tvalidated,\n\t\tctx.definition,\n\t\tctx.secretKeyProvider,\n\t)\n\n\tconst causalDeps = resolveCausalDeps(ctx)\n\n\tlet operation!: Awaited<ReturnType<typeof createOperation>>\n\tlet record!: Record<string, unknown>\n\n\tawait ctx.adapter.transaction(async (tx) => {\n\t\tconst sequenceNumber = await allocateNextSequenceInTransaction(tx, ctx.nodeId)\n\t\toperation = await createOperation(\n\t\t\t{\n\t\t\t\tnodeId: ctx.nodeId,\n\t\t\t\ttype: 'insert',\n\t\t\t\tcollection: ctx.collection,\n\t\t\t\trecordId,\n\t\t\t\t// Binary richtext values are tagged as canonical JSON BEFORE the\n\t\t\t\t// operation is content-hashed, so the hash input, persisted JSON,\n\t\t\t\t// and wire payload are the identical value.\n\t\t\t\tdata: encodeRichtextFieldsForOpData(writeData, ctx.definition.fields),\n\t\t\t\tpreviousData: null,\n\t\t\t\tsequenceNumber,\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(ctx.collection, operation.id, ctx.inTransaction)\n\n\t\tconst serializedData = serializeRecord(writeData, ctx.definition.fields)\n\t\tconst version = serializeRowVersion(operation.timestamp)\n\t\trecord = {\n\t\t\tid: recordId,\n\t\t\t...serializedData,\n\t\t\t_created_at: operation.timestamp.wallTime,\n\t\t\t_updated_at: operation.timestamp.wallTime,\n\t\t\t_version: version,\n\t\t\t// Stamp every inserted field with this operation's version so later\n\t\t\t// per-field LWW compares against a real writer, not the fallback.\n\t\t\t_field_versions: serializeFieldVersions(\n\t\t\t\tfieldVersionsForFields(Object.keys(serializedData), version),\n\t\t\t),\n\t\t}\n\n\t\tconst builtInsert = buildInsertQuery(ctx.collection, record)\n\t\tconst opInsert = buildInsertQuery(\n\t\t\t`_kora_ops_${ctx.collection}`,\n\t\t\tserializeOperation(operation) as unknown as Record<string, unknown>,\n\t\t)\n\n\t\tawait tx.execute(builtInsert.sql, builtInsert.params)\n\t\tawait tx.execute(opInsert.sql, opInsert.params)\n\t})\n\n\tctx.onMutation(ctx.collection, operation)\n\n\treturn {\n\t\tid: recordId,\n\t\t...writeData,\n\t\tcreatedAt: operation.timestamp.wallTime,\n\t\tupdatedAt: operation.timestamp.wallTime,\n\t}\n}\n","import { EMPTY_ROW_VERSION } from './row-version'\n\n/**\n * Per-field last-writer versions for a materialized row.\n *\n * Each entry maps a field name to a serialized HLC timestamp (the same\n * lexicographically-sortable form used by the row `_version` column). Because\n * the serialized form sorts identically to {@link HybridLogicalClock.compare},\n * per-field last-write-wins is a plain string comparison: the greater string is\n * the newer writer. This makes field-level convergence deterministic and\n * independent of the order operations happen to arrive in.\n */\nexport type FieldVersions = Record<string, string>\n\n/**\n * Parse the `_field_versions` JSON column into a map. Tolerates null, empty,\n * and malformed values by returning an empty map — a row that predates\n * per-field tracking simply has no field versions and falls back to `_version`.\n */\nexport function parseFieldVersions(raw: unknown): FieldVersions {\n\tif (typeof raw !== 'string' || raw.length === 0) {\n\t\treturn {}\n\t}\n\ttry {\n\t\tconst parsed = JSON.parse(raw) as unknown\n\t\tif (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n\t\t\treturn {}\n\t\t}\n\t\tconst result: FieldVersions = {}\n\t\tfor (const [key, value] of Object.entries(parsed as Record<string, unknown>)) {\n\t\t\tif (typeof value === 'string') {\n\t\t\t\tresult[key] = value\n\t\t\t}\n\t\t}\n\t\treturn result\n\t} catch {\n\t\treturn {}\n\t}\n}\n\n/**\n * Serialize a field-version map for storage in the `_field_versions` column.\n */\nexport function serializeFieldVersions(versions: FieldVersions): string {\n\treturn JSON.stringify(versions)\n}\n\n/**\n * Build the initial field-version map for an insert: every supplied field is\n * stamped with the operation's version.\n */\nexport function fieldVersionsForFields(\n\tfieldNames: Iterable<string>,\n\tversion: string,\n): FieldVersions {\n\tconst versions: FieldVersions = {}\n\tfor (const field of fieldNames) {\n\t\tversions[field] = version\n\t}\n\treturn versions\n}\n\n/**\n * The effective stored version for a field: its own tracked version if present,\n * otherwise the row-level `_version` (so rows written before per-field tracking\n * still compare correctly), otherwise the empty sentinel (older than anything).\n */\nexport function effectiveFieldVersion(\n\tcurrent: FieldVersions,\n\tfield: string,\n\trowVersion: string | undefined,\n): string {\n\tconst own = current[field]\n\tif (own !== undefined) {\n\t\treturn own\n\t}\n\treturn rowVersion ?? EMPTY_ROW_VERSION\n}\n\n/**\n * Result of resolving an incoming operation against the current per-field\n * versions of a row.\n */\nexport interface PerFieldLwwResult {\n\t/** Fields the incoming operation wins (strictly newer than the stored version). */\n\twinners: string[]\n\t/** The merged field-version map to persist (winners advanced to `incomingVersion`). */\n\tmerged: FieldVersions\n}\n\n/**\n * Resolve per-field last-write-wins for an incoming operation.\n *\n * For each incoming field, the operation wins only when its version is strictly\n * greater than the field's effective stored version. Ties (identical version,\n * i.e. the same operation re-applied) are losses, keeping the resolution\n * idempotent. The comparison is a total order, so every node resolves the same\n * winner regardless of the order operations arrive.\n *\n * @param current - Parsed `_field_versions` of the target row\n * @param incomingFields - Field names carried by the incoming operation\n * @param incomingVersion - Serialized HLC version of the incoming operation\n * @param rowVersion - The row's `_version` (fallback for untracked fields)\n */\nexport function resolvePerFieldLww(\n\tcurrent: FieldVersions,\n\tincomingFields: Iterable<string>,\n\tincomingVersion: string,\n\trowVersion: string | undefined,\n): PerFieldLwwResult {\n\tconst winners: string[] = []\n\tconst merged: FieldVersions = { ...current }\n\tfor (const field of incomingFields) {\n\t\tconst stored = effectiveFieldVersion(current, field, rowVersion)\n\t\tif (incomingVersion > stored) {\n\t\t\twinners.push(field)\n\t\t\tmerged[field] = incomingVersion\n\t\t}\n\t\t// Losing fields are left untouched: their existing tracked version (or the\n\t\t// row-level `_version` fallback) already reflects the newer writer.\n\t}\n\treturn { winners, merged }\n}\n","import type { AtomicOp } from '@korajs/core'\nimport {\n\tcreateOperation,\n\tisAtomicOp,\n\tresolveAtomicOp,\n\ttoAtomicOp,\n\ttransformSecretFieldsForWrite,\n\tvalidateRecord,\n} from '@korajs/core'\nimport { RecordNotFoundError } from '../errors'\nimport { parseFieldVersions, serializeFieldVersions } from '../lww/field-versions'\nimport { serializeRowVersion } from '../lww/row-version'\nimport { buildInsertQuery, buildUpdateQuery } from '../query/sql-builder'\nimport { encodeRichtextFieldsForOpData } from '../serialization/op-data-encoding'\nimport { deserializeRecord, serializeOperation, serializeRecord } from '../serialization/serializer'\nimport { validateUpdateStateMachine } from '../state-machine/state-validator'\nimport { allocateNextSequenceInTransaction } from '../store/sequence-allocator'\nimport type { CollectionRecord, RawCollectionRow } from '../types'\nimport { resolveCausalDeps } from './resolve-causal-deps'\nimport type { LocalMutationContext } from './types'\n\n/**\n * Update a record and persist the operation log entry atomically.\n */\nexport async function executeUpdate(\n\tctx: LocalMutationContext,\n\tid: string,\n\tdata: Record<string, unknown>,\n): Promise<CollectionRecord> {\n\tconst currentRows = await ctx.adapter.query<RawCollectionRow>(\n\t\t`SELECT * FROM ${ctx.collection} WHERE id = ? AND _deleted = 0`,\n\t\t[id],\n\t)\n\tconst currentRow = currentRows[0]\n\tif (!currentRow) {\n\t\tthrow new RecordNotFoundError(ctx.collection, id)\n\t}\n\n\tlet validated = validateRecord(ctx.collection, ctx.definition, data, 'update')\n\tconst currentRecord = deserializeRecord(currentRow, ctx.definition.fields)\n\tvalidated = validateUpdateStateMachine(\n\t\tctx.collection,\n\t\tid,\n\t\tctx.definition,\n\t\tcurrentRecord,\n\t\tvalidated,\n\t)\n\n\tif (Object.keys(validated).length === 0) {\n\t\treturn { ...currentRecord }\n\t}\n\n\tconst previousData: Record<string, unknown> = {}\n\tconst resolvedData: Record<string, unknown> = {}\n\tconst atomicOps: Record<string, AtomicOp> = {}\n\n\tfor (const key of Object.keys(validated)) {\n\t\tconst value = validated[key]\n\t\tpreviousData[key] = currentRecord[key]\n\n\t\tif (isAtomicOp(value)) {\n\t\t\tresolvedData[key] = resolveAtomicOp(currentRecord[key], value)\n\t\t\tatomicOps[key] = toAtomicOp(value)\n\t\t} else {\n\t\t\tresolvedData[key] = value\n\t\t}\n\t}\n\n\t// Transform secret fields in the changed set to their at-rest form before the\n\t// operation is built. previousData already holds the stored (ciphertext) value\n\t// from the current record, so it needs no transform.\n\tconst writeData = await transformSecretFieldsForWrite(\n\t\tresolvedData,\n\t\tctx.definition,\n\t\tctx.secretKeyProvider,\n\t)\n\n\tconst hasAtomicOps = Object.keys(atomicOps).length > 0\n\tconst causalDeps = resolveCausalDeps(ctx)\n\tlet operation!: Awaited<ReturnType<typeof createOperation>>\n\n\tawait ctx.adapter.transaction(async (tx) => {\n\t\tconst sequenceNumber = await allocateNextSequenceInTransaction(tx, ctx.nodeId)\n\t\toperation = await createOperation(\n\t\t\t{\n\t\t\t\tnodeId: ctx.nodeId,\n\t\t\t\ttype: 'update',\n\t\t\t\tcollection: ctx.collection,\n\t\t\t\trecordId: id,\n\t\t\t\t// Binary richtext values (new and previous) are tagged as canonical\n\t\t\t\t// JSON BEFORE the operation is content-hashed, so the hash input,\n\t\t\t\t// persisted JSON, and wire payload are the identical value.\n\t\t\t\tdata: encodeRichtextFieldsForOpData(writeData, ctx.definition.fields),\n\t\t\t\tpreviousData: encodeRichtextFieldsForOpData(previousData, ctx.definition.fields),\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps,\n\t\t\t\tschemaVersion: ctx.schema.version,\n\t\t\t\t...(hasAtomicOps ? { atomicOps } : {}),\n\t\t\t},\n\t\t\tctx.clock,\n\t\t)\n\t\tctx.causalTracker?.afterOperation(ctx.collection, operation.id, ctx.inTransaction)\n\n\t\tconst serializedChanges = serializeRecord(writeData, ctx.definition.fields)\n\t\tconst version = serializeRowVersion(operation.timestamp)\n\t\t// A local edit is always the newest writer of the fields it touches (the\n\t\t// HLC advances past every timestamp this device has seen), so stamp each\n\t\t// changed field with this operation's version.\n\t\tconst mergedFieldVersions = parseFieldVersions(currentRow._field_versions)\n\t\tfor (const changedField of Object.keys(serializedChanges)) {\n\t\t\tmergedFieldVersions[changedField] = version\n\t\t}\n\t\tconst updateQuery = buildUpdateQuery(ctx.collection, id, {\n\t\t\t...serializedChanges,\n\t\t\t_updated_at: operation.timestamp.wallTime,\n\t\t\t_version: version,\n\t\t\t_field_versions: serializeFieldVersions(mergedFieldVersions),\n\t\t})\n\t\tconst opInsert = buildInsertQuery(\n\t\t\t`_kora_ops_${ctx.collection}`,\n\t\t\tserializeOperation(operation) as unknown as Record<string, unknown>,\n\t\t)\n\n\t\tawait tx.execute(updateQuery.sql, updateQuery.params)\n\t\tawait tx.execute(opInsert.sql, opInsert.params)\n\t})\n\n\tctx.onMutation(ctx.collection, operation)\n\n\tconst rows = await ctx.adapter.query<RawCollectionRow>(\n\t\t`SELECT * FROM ${ctx.collection} WHERE id = ? AND _deleted = 0`,\n\t\t[id],\n\t)\n\tconst row = rows[0]\n\tif (!row) {\n\t\tthrow new RecordNotFoundError(ctx.collection, id)\n\t}\n\treturn deserializeRecord(row, ctx.definition.fields)\n}\n","import { KoraError, validateTransition } from '@korajs/core'\nimport type {\n\tCollectionDefinition,\n\tStateMachineConstraint,\n\tStateMachineDefinition,\n} from '@korajs/core'\n\n/**\n * Error thrown when a local mutation attempts an invalid state transition.\n *\n * Contains enough context to debug without reproduction:\n * the collection, record, field, current state, attempted state, and allowed transitions.\n */\nexport class InvalidStateTransitionError extends KoraError {\n\tconstructor(\n\t\tpublic readonly collection: string,\n\t\tpublic readonly recordId: string,\n\t\tpublic readonly field: string,\n\t\tpublic readonly fromState: string,\n\t\tpublic readonly toState: string,\n\t\tpublic readonly allowedStates: string[],\n\t) {\n\t\tsuper(\n\t\t\t`Invalid state transition in collection \"${collection}\": ` +\n\t\t\t\t`cannot transition field \"${field}\" from \"${fromState}\" to \"${toState}\". ` +\n\t\t\t\t`Allowed transitions from \"${fromState}\": ${allowedStates.length > 0 ? allowedStates.join(', ') : '(none -- terminal state)'}`,\n\t\t\t'INVALID_STATE_TRANSITION',\n\t\t\t{ collection, recordId, field, fromState, toState, allowedStates },\n\t\t)\n\t\tthis.name = 'InvalidStateTransitionError'\n\t}\n}\n\n/**\n * Validates a state machine transition for a local mutation (insert or update).\n *\n * For inserts: validates that the initial state (from the data or the default value)\n * is a known state in the state machine.\n *\n * For updates: looks up the current state field value and checks whether\n * the transition to the new value is allowed.\n *\n * @param collectionName - Name of the collection\n * @param recordId - The record being mutated\n * @param stateMachine - The state machine definition\n * @param currentState - The current value of the state field (null for inserts)\n * @param newState - The new value being set for the state field\n * @returns An object indicating whether the transition is valid, and if not, the allowed states.\n * When `onInvalidTransition` is 'last-valid-state', callers should suppress the field update\n * rather than throwing.\n */\nexport function validateStateTransition(\n\tcollectionName: string,\n\trecordId: string,\n\tstateMachine: StateMachineDefinition,\n\tcurrentState: string | null,\n\tnewState: string,\n): { valid: boolean; allowedStates: string[] } {\n\t// For inserts, any valid enum value is acceptable as the initial state\n\t// (schema validation already ensures the value is a valid enum value)\n\tif (currentState === null) {\n\t\treturn { valid: true, allowedStates: [] }\n\t}\n\n\t// Same-state transitions are always valid (idempotent updates)\n\tif (currentState === newState) {\n\t\treturn { valid: true, allowedStates: stateMachine.transitions[currentState] ?? [] }\n\t}\n\n\tconst constraint: StateMachineConstraint = {\n\t\tfield: stateMachine.field,\n\t\tcollection: collectionName,\n\t\ttransitions: stateMachine.transitions,\n\t}\n\tconst transitionResult = validateTransition(constraint, currentState, newState)\n\tif (transitionResult.valid) {\n\t\treturn { valid: true, allowedStates: transitionResult.allowedTargets }\n\t}\n\n\tconst allowedStates = transitionResult.allowedTargets\n\n\tif (stateMachine.onInvalidTransition === 'reject') {\n\t\tthrow new InvalidStateTransitionError(\n\t\t\tcollectionName,\n\t\t\trecordId,\n\t\t\tstateMachine.field,\n\t\t\tcurrentState,\n\t\t\tnewState,\n\t\t\tallowedStates,\n\t\t)\n\t}\n\n\t// 'last-valid-state': return invalid so the caller can suppress the field update\n\treturn { valid: false, allowedStates }\n}\n\n/**\n * Checks whether a collection update data object contains a change to the state machine field,\n * and if so, validates the transition.\n *\n * If the state field is not in the update data, returns the data unchanged.\n * If the transition is invalid and mode is 'last-valid-state', removes the field from the data.\n * If the transition is invalid and mode is 'reject', throws InvalidStateTransitionError.\n *\n * @param collectionName - Name of the collection\n * @param recordId - The record being updated\n * @param collectionDef - The collection definition from the schema\n * @param currentRecord - The current record data (must include the state field)\n * @param updateData - The partial update data\n * @returns The update data, potentially with the state field removed if invalid and mode is 'last-valid-state'\n */\nexport function validateUpdateStateMachine(\n\tcollectionName: string,\n\trecordId: string,\n\tcollectionDef: CollectionDefinition,\n\tcurrentRecord: Record<string, unknown>,\n\tupdateData: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst stateMachine = collectionDef.stateMachine\n\tif (stateMachine === undefined) {\n\t\treturn updateData\n\t}\n\n\tconst stateField = stateMachine.field\n\tif (!(stateField in updateData)) {\n\t\t// State field not being changed -- no validation needed\n\t\treturn updateData\n\t}\n\n\tconst currentState = currentRecord[stateField]\n\tconst newState = updateData[stateField]\n\n\t// Both values must be strings for state machine validation\n\tif (typeof currentState !== 'string' || typeof newState !== 'string') {\n\t\treturn updateData\n\t}\n\n\tconst result = validateStateTransition(\n\t\tcollectionName,\n\t\trecordId,\n\t\tstateMachine,\n\t\tcurrentState,\n\t\tnewState,\n\t)\n\n\tif (result.valid) {\n\t\treturn updateData\n\t}\n\n\t// Mode is 'last-valid-state': silently remove the state field from the update\n\tconst filtered = { ...updateData }\n\tdelete filtered[stateField]\n\n\t// If no fields remain after removing the state field, the update becomes a no-op.\n\t// Return the empty object -- the caller can decide whether to proceed.\n\treturn filtered\n}\n","import type {\n\tCausalTracker,\n\tCollectionDefinition,\n\tHybridLogicalClock,\n\tOperation,\n\tSchemaDefinition,\n\tSecretKeyProvider,\n} from '@korajs/core'\nimport { executeDelete } from '../mutations/execute-delete'\nimport { executeInsert } from '../mutations/execute-insert'\nimport { executeUpdate } from '../mutations/execute-update'\nimport type { LocalMutationContext } from '../mutations/types'\nimport type { RelationEnforcer } from '../relations/relation-enforcer'\nimport { deserializeRecord } from '../serialization/serializer'\nimport type {\n\tCollectionRecord,\n\tLocalMutationHandler,\n\tRawCollectionRow,\n\tStorageAdapter,\n} from '../types'\n\n/**\n * Callback invoked after a mutation so the Store can notify subscriptions.\n */\nexport type MutationCallback = (collection: string, operation: Operation) => void\n\n/**\n * Collection provides CRUD operations on a single schema collection.\n * Delegates to {@link LocalMutationHandler} when configured (unified apply pipeline),\n * otherwise uses shared mutation executors directly.\n */\nexport class Collection {\n\tconstructor(\n\t\tprivate readonly name: string,\n\t\tprivate readonly definition: CollectionDefinition,\n\t\tprivate readonly schema: SchemaDefinition,\n\t\tprivate readonly adapter: StorageAdapter,\n\t\tprivate readonly clock: HybridLogicalClock,\n\t\tprivate readonly nodeId: string,\n\t\tprivate readonly allocateSequenceNumber: () => Promise<number>,\n\t\tprivate readonly onMutation: MutationCallback,\n\t\tprivate readonly relationEnforcer: RelationEnforcer | null,\n\t\tprivate mutationHandler: LocalMutationHandler | null,\n\t\tprivate readonly causalTracker: CausalTracker | null,\n\t\tprivate readonly secretKeyProvider?: SecretKeyProvider,\n\t) {}\n\n\tprivate mutationContext(): LocalMutationContext {\n\t\treturn {\n\t\t\tcollection: this.name,\n\t\t\tdefinition: this.definition,\n\t\t\tschema: this.schema,\n\t\t\tadapter: this.adapter,\n\t\t\tclock: this.clock,\n\t\t\tnodeId: this.nodeId,\n\t\t\tallocateSequenceNumber: this.allocateSequenceNumber,\n\t\t\tonMutation: this.onMutation,\n\t\t\trelationEnforcer: this.relationEnforcer,\n\t\t\tcausalTracker: this.causalTracker,\n\t\t\tinTransaction: false,\n\t\t\tsecretKeyProvider: this.secretKeyProvider,\n\t\t}\n\t}\n\n\tasync insert(data: Record<string, unknown>): Promise<CollectionRecord> {\n\t\tif (this.mutationHandler) {\n\t\t\treturn this.mutationHandler.insert(this.name, data)\n\t\t}\n\t\treturn executeInsert(this.mutationContext(), data)\n\t}\n\n\tasync findById(id: string): Promise<CollectionRecord | null> {\n\t\tconst rows = await this.adapter.query<RawCollectionRow>(\n\t\t\t`SELECT * FROM ${this.name} WHERE id = ? AND _deleted = 0`,\n\t\t\t[id],\n\t\t)\n\t\tconst row = rows[0]\n\t\tif (!row) return null\n\t\treturn deserializeRecord(row, this.definition.fields)\n\t}\n\n\tasync update(id: string, data: Record<string, unknown>): Promise<CollectionRecord> {\n\t\tif (this.mutationHandler) {\n\t\t\treturn this.mutationHandler.update(this.name, id, data)\n\t\t}\n\t\treturn executeUpdate(this.mutationContext(), id, data)\n\t}\n\n\tasync delete(id: string): Promise<void> {\n\t\tif (this.mutationHandler) {\n\t\t\tawait this.mutationHandler.delete(this.name, id)\n\t\t\treturn\n\t\t}\n\t\tawait executeDelete(this.mutationContext(), id)\n\t}\n\n\tgetName(): string {\n\t\treturn this.name\n\t}\n\n\tgetDefinition(): CollectionDefinition {\n\t\treturn this.definition\n\t}\n\n\t/** Replace the mutation handler (e.g. after ApplyPipeline is wired in createApp). */\n\tsetMutationHandler(handler: LocalMutationHandler | null): void {\n\t\tthis.mutationHandler = handler\n\t}\n}\n","import type { CollectionDefinition, SchemaDefinition } from '@korajs/core'\nimport { deserializeRecord } from '../serialization/serializer'\nimport type { SubscriptionManager } from '../subscription/subscription-manager'\nimport type {\n\tCollectionRecord,\n\tOrderByDirection,\n\tQueryDescriptor,\n\tRawCollectionRow,\n\tStorageAdapter,\n\tSubscriptionCallback,\n\tWhereClause,\n} from '../types'\nimport { pluralize, singularize } from './pluralize'\nimport { buildCountQuery, buildSelectQuery } from './sql-builder'\n\n/**\n * Fluent query builder for constructing and executing collection queries.\n * Supports where, orderBy, limit, offset, include, exec, count, and subscribe.\n *\n * The generic parameter `T` defaults to `CollectionRecord` for backward compatibility\n * but can be narrowed to a specific record type for full type inference.\n *\n * @example\n * ```typescript\n * const todos = await app.todos\n * .where({ completed: false })\n * .orderBy('createdAt', 'desc')\n * .limit(10)\n * .exec()\n * ```\n */\nexport class QueryBuilder<T = CollectionRecord> {\n\tprivate descriptor: QueryDescriptor\n\n\tconstructor(\n\t\tprivate readonly collectionName: string,\n\t\tprivate readonly definition: CollectionDefinition,\n\t\tprivate readonly adapter: StorageAdapter,\n\t\tprivate readonly subscriptionManager: SubscriptionManager,\n\t\tinitialWhere: WhereClause = {},\n\t\tprivate readonly schema?: SchemaDefinition,\n\t) {\n\t\tthis.descriptor = {\n\t\t\tcollection: collectionName,\n\t\t\twhere: { ...initialWhere },\n\t\t\torderBy: [],\n\t\t}\n\t}\n\n\t/**\n\t * Add WHERE conditions (AND semantics, merged with existing conditions).\n\t */\n\twhere(conditions: WhereClause): QueryBuilder<T> {\n\t\tconst clone = this.clone()\n\t\tclone.descriptor = {\n\t\t\t...clone.descriptor,\n\t\t\twhere: { ...clone.descriptor.where, ...conditions },\n\t\t}\n\t\treturn clone\n\t}\n\n\t/**\n\t * Add ORDER BY clause.\n\t */\n\torderBy(field: string, direction: OrderByDirection = 'asc'): QueryBuilder<T> {\n\t\tconst clone = this.clone()\n\t\tclone.descriptor = {\n\t\t\t...clone.descriptor,\n\t\t\torderBy: [...clone.descriptor.orderBy, { field, direction }],\n\t\t}\n\t\treturn clone\n\t}\n\n\t/**\n\t * Set result limit.\n\t */\n\tlimit(n: number): QueryBuilder<T> {\n\t\tconst clone = this.clone()\n\t\tclone.descriptor = { ...clone.descriptor, limit: n }\n\t\treturn clone\n\t}\n\n\t/**\n\t * Set result offset.\n\t */\n\toffset(n: number): QueryBuilder<T> {\n\t\tconst clone = this.clone()\n\t\tclone.descriptor = { ...clone.descriptor, offset: n }\n\t\treturn clone\n\t}\n\n\t/**\n\t * Include related records in the query results.\n\t * Follows relations defined in the schema to batch-fetch related data.\n\t *\n\t * @param targets - Relation target names (collection names or relation names)\n\t * @returns A new QueryBuilder with include targets added\n\t *\n\t * @example\n\t * ```typescript\n\t * const todosWithProject = await app.todos\n\t * .where({ completed: false })\n\t * .include('project')\n\t * .exec()\n\t * ```\n\t */\n\tinclude(...targets: string[]): QueryBuilder<T> {\n\t\tconst clone = this.clone()\n\t\tconst existing = clone.descriptor.include ?? []\n\t\tclone.descriptor = {\n\t\t\t...clone.descriptor,\n\t\t\tinclude: [...existing, ...targets],\n\t\t}\n\t\treturn clone\n\t}\n\n\t/**\n\t * Execute the query and return results.\n\t */\n\tasync exec(): Promise<T[]> {\n\t\tconst { sql, params } = buildSelectQuery(this.descriptor, this.definition.fields)\n\t\tconst rows = await this.adapter.query<RawCollectionRow>(sql, params)\n\t\tconst records = rows.map((row) => deserializeRecord(row, this.definition.fields))\n\n\t\t// Resolve includes if any\n\t\tif (this.descriptor.include && this.descriptor.include.length > 0 && this.schema) {\n\t\t\tawait this.resolveIncludes(records)\n\t\t}\n\n\t\treturn records as T[]\n\t}\n\n\t/**\n\t * Execute a COUNT query and return the count.\n\t */\n\tasync count(): Promise<number> {\n\t\tconst { sql, params } = buildCountQuery(this.descriptor, this.definition.fields)\n\t\tconst rows = await this.adapter.query<{ count: number }>(sql, params)\n\t\treturn rows[0]?.count ?? 0\n\t}\n\n\t/**\n\t * Subscribe to query results. Callback is called immediately with current results,\n\t * then again whenever the results change due to mutations.\n\t *\n\t * @returns An unsubscribe function\n\t */\n\tsubscribe(callback: SubscriptionCallback<T>): () => void {\n\t\tconst executeFn = () => this.exec()\n\n\t\t// Resolve includeCollections for subscription tracking\n\t\tconst descriptorCopy = { ...this.descriptor }\n\t\tif (descriptorCopy.include && descriptorCopy.include.length > 0 && this.schema) {\n\t\t\tdescriptorCopy.includeCollections = this.resolveIncludeCollections(descriptorCopy.include)\n\t\t}\n\n\t\t// Use registerAndFetch to execute immediately, set lastResults,\n\t\t// and call callback — ensuring subsequent flushes diff correctly.\n\t\treturn this.subscriptionManager.registerAndFetch(\n\t\t\tdescriptorCopy,\n\t\t\tcallback as SubscriptionCallback<CollectionRecord>,\n\t\t\texecuteFn as () => Promise<CollectionRecord[]>,\n\t\t)\n\t}\n\n\t/** Get the internal descriptor (for testing/debugging) */\n\tgetDescriptor(): QueryDescriptor {\n\t\treturn { ...this.descriptor }\n\t}\n\n\tprivate clone(): QueryBuilder<T> {\n\t\tconst qb = new QueryBuilder<T>(\n\t\t\tthis.collectionName,\n\t\t\tthis.definition,\n\t\t\tthis.adapter,\n\t\t\tthis.subscriptionManager,\n\t\t\t{},\n\t\t\tthis.schema,\n\t\t)\n\t\tqb.descriptor = {\n\t\t\t...this.descriptor,\n\t\t\twhere: { ...this.descriptor.where },\n\t\t\torderBy: [...this.descriptor.orderBy],\n\t\t\tinclude: this.descriptor.include ? [...this.descriptor.include] : undefined,\n\t\t\tincludeCollections: this.descriptor.includeCollections\n\t\t\t\t? [...this.descriptor.includeCollections]\n\t\t\t\t: undefined,\n\t\t}\n\t\treturn qb\n\t}\n\n\t/**\n\t * Resolve include targets to their actual collection names for subscription tracking.\n\t */\n\tprivate resolveIncludeCollections(targets: string[]): string[] {\n\t\tif (!this.schema) return []\n\t\tconst collections: string[] = []\n\n\t\tfor (const target of targets) {\n\t\t\tconst relation = this.findRelation(target)\n\t\t\tif (relation) {\n\t\t\t\t// For many-to-one: the related collection is `relation.to`\n\t\t\t\t// For one-to-many: the related collection is `relation.from`\n\t\t\t\tif (relation.from === this.collectionName) {\n\t\t\t\t\tcollections.push(relation.to)\n\t\t\t\t} else {\n\t\t\t\t\tcollections.push(relation.from)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn collections\n\t}\n\n\t/**\n\t * Resolve includes after primary query, batch-fetching related records.\n\t */\n\tprivate async resolveIncludes(records: CollectionRecord[]): Promise<void> {\n\t\tif (!this.schema || !this.descriptor.include || records.length === 0) return\n\n\t\tfor (const target of this.descriptor.include) {\n\t\t\tconst relation = this.findRelation(target)\n\t\t\tif (!relation) {\n\t\t\t\tthrow new QueryError(\n\t\t\t\t\t`No relation found for include target \"${target}\" on collection \"${this.collectionName}\". ` +\n\t\t\t\t\t\t`Check that a relation is defined in your schema that connects \"${this.collectionName}\" to \"${target}\".`,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tif (relation.from === this.collectionName) {\n\t\t\t\t// Many-to-one or one-to-one: primary has FK → fetch parent records\n\t\t\t\tawait this.resolveManyToOneInclude(records, relation, target)\n\t\t\t} else {\n\t\t\t\t// One-to-many: related collection has FK → fetch children\n\t\t\t\tawait this.resolveOneToManyInclude(records, relation, target)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Many-to-one: collect FK values from primary results, batch-fetch related, attach as singular.\n\t */\n\tprivate async resolveManyToOneInclude(\n\t\trecords: CollectionRecord[],\n\t\trelation: { from: string; to: string; field: string },\n\t\ttarget: string,\n\t): Promise<void> {\n\t\tconst fkField = relation.field\n\t\tconst fkValues = records\n\t\t\t.map((r) => r[fkField])\n\t\t\t.filter((v): v is string => v !== null && v !== undefined && typeof v === 'string')\n\n\t\tif (fkValues.length === 0) {\n\t\t\t// All null FKs — set property to null on all records\n\t\t\tconst propName = singularize(target)\n\t\t\tfor (const record of records) {\n\t\t\t\t;(record as Record<string, unknown>)[propName] = null\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tconst uniqueFks = [...new Set(fkValues)]\n\t\tconst relatedCollection = relation.to\n\t\tconst relatedDef = this.schema?.collections[relatedCollection]\n\t\tif (!relatedDef) return\n\n\t\t// Batch fetch: SELECT * FROM <to> WHERE id IN (...) AND _deleted = 0\n\t\tconst placeholders = uniqueFks.map(() => '?').join(', ')\n\t\tconst sql = `SELECT * FROM ${relatedCollection} WHERE id IN (${placeholders}) AND _deleted = 0`\n\t\tconst rows = await this.adapter.query<RawCollectionRow>(sql, uniqueFks)\n\t\tconst relatedRecords = rows.map((row) => deserializeRecord(row, relatedDef.fields))\n\n\t\t// Build lookup\n\t\tconst lookup = new Map<string, CollectionRecord>()\n\t\tfor (const r of relatedRecords) {\n\t\t\tlookup.set(r.id, r)\n\t\t}\n\n\t\t// Attach as singular property\n\t\tconst propName = singularize(target)\n\t\tfor (const record of records) {\n\t\t\tconst fk = record[fkField] as string | null\n\t\t\t;(record as Record<string, unknown>)[propName] = fk ? (lookup.get(fk) ?? null) : null\n\t\t}\n\t}\n\n\t/**\n\t * One-to-many: collect primary IDs, batch-fetch children, attach as array.\n\t */\n\tprivate async resolveOneToManyInclude(\n\t\trecords: CollectionRecord[],\n\t\trelation: { from: string; to: string; field: string },\n\t\ttarget: string,\n\t): Promise<void> {\n\t\tconst primaryIds = records.map((r) => r.id)\n\t\tconst relatedCollection = relation.from\n\t\tconst relatedDef = this.schema?.collections[relatedCollection]\n\t\tif (!relatedDef) return\n\n\t\tconst fkField = relation.field\n\t\tconst placeholders = primaryIds.map(() => '?').join(', ')\n\t\tconst sql = `SELECT * FROM ${relatedCollection} WHERE ${fkField} IN (${placeholders}) AND _deleted = 0`\n\t\tconst rows = await this.adapter.query<RawCollectionRow>(sql, primaryIds)\n\t\tconst relatedRecords = rows.map((row) => deserializeRecord(row, relatedDef.fields))\n\n\t\t// Group by FK\n\t\tconst grouped = new Map<string, CollectionRecord[]>()\n\t\tfor (const r of relatedRecords) {\n\t\t\tconst fk = r[fkField] as string\n\t\t\tif (!grouped.has(fk)) {\n\t\t\t\tgrouped.set(fk, [])\n\t\t\t}\n\t\t\tgrouped.get(fk)?.push(r)\n\t\t}\n\n\t\t// Attach as array property\n\t\tconst propName = pluralize(target)\n\t\tfor (const record of records) {\n\t\t\t;(record as Record<string, unknown>)[propName] = grouped.get(record.id) ?? []\n\t\t}\n\t}\n\n\t/**\n\t * Find a relation definition matching the include target.\n\t * Searches by relation name, target collection name, and singularized/pluralized variants.\n\t */\n\tprivate findRelation(\n\t\ttarget: string,\n\t): { from: string; to: string; field: string; type: string } | null {\n\t\tif (!this.schema) return null\n\n\t\tfor (const [_name, rel] of Object.entries(this.schema.relations)) {\n\t\t\t// Direct match: target is the related collection name\n\t\t\tif (rel.from === this.collectionName && rel.to === target) return rel\n\t\t\tif (rel.to === this.collectionName && rel.from === target) return rel\n\n\t\t\t// Singularized match: \"project\" matches relation to \"projects\"\n\t\t\tif (rel.from === this.collectionName && rel.to === pluralize(target)) return rel\n\t\t\tif (rel.to === this.collectionName && rel.from === pluralize(target)) return rel\n\n\t\t\t// Pluralized match: \"todos\" matches relation from \"todos\"\n\t\t\tif (rel.from === this.collectionName && rel.to === singularize(target)) return rel\n\t\t\tif (rel.to === this.collectionName && rel.from === singularize(target)) return rel\n\t\t}\n\n\t\treturn null\n\t}\n}\n\n/**\n * Error thrown when a query encounters an invalid state.\n */\nclass QueryError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message)\n\t\tthis.name = 'QueryError'\n\t}\n}\n","/**\n * Minimal pluralization/singularization utilities for relation name resolution.\n * Handles common English patterns — not meant to be exhaustive.\n */\n\nfunction isVowel(char: string | undefined): boolean {\n\tif (!char) return false\n\treturn 'aeiouAEIOU'.includes(char)\n}\n\n/**\n * Pluralize a word using common English rules.\n *\n * @example\n * ```\n * pluralize('project') // 'projects'\n * pluralize('category') // 'categories'\n * pluralize('match') // 'matches'\n * ```\n */\nexport function pluralize(word: string): string {\n\tif (word.endsWith('s')) return word\n\tif (word.endsWith('y') && !isVowel(word[word.length - 2])) {\n\t\treturn `${word.slice(0, -1)}ies`\n\t}\n\tif (word.endsWith('sh') || word.endsWith('ch') || word.endsWith('x') || word.endsWith('z')) {\n\t\treturn `${word}es`\n\t}\n\treturn `${word}s`\n}\n\n/**\n * Singularize a word using common English rules.\n *\n * @example\n * ```\n * singularize('projects') // 'project'\n * singularize('categories') // 'category'\n * singularize('matches') // 'match'\n * ```\n */\nexport function singularize(word: string): string {\n\tif (word.endsWith('ies') && !isVowel(word[word.length - 4])) {\n\t\treturn `${word.slice(0, -3)}y`\n\t}\n\tif (\n\t\tword.endsWith('shes') ||\n\t\tword.endsWith('ches') ||\n\t\tword.endsWith('xes') ||\n\t\tword.endsWith('zes')\n\t) {\n\t\treturn word.slice(0, -2)\n\t}\n\tif (word.endsWith('ses')) {\n\t\treturn word.slice(0, -2)\n\t}\n\tif (word.endsWith('s') && !word.endsWith('ss')) {\n\t\treturn word.slice(0, -1)\n\t}\n\treturn word\n}\n","import type { HybridLogicalClock, Operation, SchemaDefinition } from '@korajs/core'\nimport { KoraError, createOperation } from '@korajs/core'\nimport { buildInsertQuery, buildSoftDeleteQuery, buildUpdateQuery } from '../query/sql-builder'\nimport { serializeOperation, serializeRecord } from '../serialization/serializer'\nimport { allocateNextSequenceInTransaction } from '../store/sequence-allocator'\nimport type { StorageAdapter, Transaction } from '../types'\nimport type { IncomingRelation } from './relation-lookup'\nimport { buildRelationLookup, getIncomingRelations } from './relation-lookup'\n\n/**\n * Error thrown when a delete is refused due to a 'restrict' referential integrity policy.\n * The error includes context about which relation caused the restriction and\n * how many referencing records exist.\n */\nexport class ReferentialIntegrityError extends KoraError {\n\tconstructor(\n\t\tcollection: string,\n\t\trecordId: string,\n\t\treferencingCollection: string,\n\t\trelationName: string,\n\t\treferencingCount: number,\n\t) {\n\t\tsuper(\n\t\t\t`Cannot delete record \"${recordId}\" from \"${collection}\": ${referencingCount} record(s) in \"${referencingCollection}\" reference it via relation \"${relationName}\" with onDelete: 'restrict'. Delete or reassign the referencing records first.`,\n\t\t\t'REFERENTIAL_INTEGRITY',\n\t\t\t{\n\t\t\t\tcollection,\n\t\t\t\trecordId,\n\t\t\t\treferencingCollection,\n\t\t\t\trelationName,\n\t\t\t\treferencingCount,\n\t\t\t},\n\t\t)\n\t\tthis.name = 'ReferentialIntegrityError'\n\t}\n}\n\n/**\n * Configuration for the RelationEnforcer.\n */\nexport interface RelationEnforcerConfig {\n\tschema: SchemaDefinition\n\tadapter: StorageAdapter\n\tclock: HybridLogicalClock\n\tnodeId: string\n}\n\n/**\n * Result of enforcing referential integrity on a delete operation.\n * Contains all additional operations that were created as side effects\n * (cascaded deletes and set-null updates).\n */\nexport interface EnforcementResult {\n\t/** Additional operations created by cascading deletes and set-null updates */\n\toperations: Operation[]\n}\n\n/**\n * Enforces referential integrity constraints during local delete operations.\n *\n * When a record is deleted, this enforcer checks all relations that reference\n * the deleted record's collection and applies the appropriate onDelete policy:\n *\n * - **cascade**: Recursively deletes all referencing records\n * - **set-null**: Sets the foreign key to null on all referencing records\n * - **restrict**: Throws a ReferentialIntegrityError if any references exist\n * - **no-action**: Does nothing (the foreign key is left dangling)\n *\n * The enforcer operates within a provided transaction to ensure atomicity.\n * All generated operations (cascaded deletes, set-null updates) share a\n * causal dependency chain through the original delete operation.\n *\n * @example\n * ```typescript\n * const enforcer = new RelationEnforcer({\n * schema, adapter, clock, nodeId,\n * allocateSequenceNumber: async () => ++seq,\n * })\n * const result = await enforcer.enforceDelete(\n * 'projects', 'proj-1', tx, ['delete-op-id']\n * )\n * // result.operations contains any cascaded delete/update ops\n * ```\n */\nexport class RelationEnforcer {\n\tprivate readonly lookup: Map<string, IncomingRelation[]>\n\tprivate readonly schema: SchemaDefinition\n\tprivate readonly adapter: StorageAdapter\n\tprivate readonly clock: HybridLogicalClock\n\tprivate readonly nodeId: string\n\n\tconstructor(config: RelationEnforcerConfig) {\n\t\tthis.schema = config.schema\n\t\tthis.adapter = config.adapter\n\t\tthis.clock = config.clock\n\t\tthis.nodeId = config.nodeId\n\t\tthis.lookup = buildRelationLookup(config.schema)\n\t}\n\n\t/**\n\t * Enforce referential integrity after deleting a record.\n\t *\n\t * Must be called within a transaction. The transaction handle is used\n\t * for all cascaded writes to ensure atomicity.\n\t *\n\t * @param collection - The collection the deleted record belongs to\n\t * @param recordId - The ID of the deleted record\n\t * @param tx - The active transaction handle\n\t * @param causalDeps - Causal dependencies for generated operations\n\t * @returns All additional operations created as side effects\n\t * @throws {ReferentialIntegrityError} If a 'restrict' policy is violated\n\t */\n\tasync enforceDelete(\n\t\tcollection: string,\n\t\trecordId: string,\n\t\ttx: Transaction,\n\t\tcausalDeps: string[],\n\t): Promise<EnforcementResult> {\n\t\tconst incomingRelations = getIncomingRelations(this.lookup, collection)\n\t\tif (incomingRelations.length === 0) {\n\t\t\treturn { operations: [] }\n\t\t}\n\n\t\tconst allOperations: Operation[] = []\n\n\t\t// Process relations in a deterministic order (sorted by relation name)\n\t\t// to ensure identical results regardless of Map iteration order.\n\t\tconst sortedRelations = [...incomingRelations].sort((a, b) =>\n\t\t\ta.relationName.localeCompare(b.relationName),\n\t\t)\n\n\t\tfor (const incoming of sortedRelations) {\n\t\t\tconst ops = await this.enforceRelation(incoming, recordId, tx, causalDeps)\n\t\t\tallOperations.push(...ops)\n\t\t}\n\n\t\treturn { operations: allOperations }\n\t}\n\n\t/**\n\t * Enforce a single relation's onDelete policy.\n\t */\n\tprivate async enforceRelation(\n\t\tincoming: IncomingRelation,\n\t\tdeletedRecordId: string,\n\t\ttx: Transaction,\n\t\tcausalDeps: string[],\n\t): Promise<Operation[]> {\n\t\tswitch (incoming.onDelete) {\n\t\t\tcase 'cascade':\n\t\t\t\treturn this.enforceCascade(incoming, deletedRecordId, tx, causalDeps)\n\t\t\tcase 'set-null':\n\t\t\t\treturn this.enforceSetNull(incoming, deletedRecordId, tx, causalDeps)\n\t\t\tcase 'restrict':\n\t\t\t\treturn this.enforceRestrict(incoming, deletedRecordId, tx)\n\t\t\tcase 'no-action':\n\t\t\t\treturn []\n\t\t}\n\t}\n\n\t/**\n\t * Cascade: delete all records in the source collection that reference\n\t * the deleted record, then recursively cascade those deletes.\n\t */\n\tprivate async enforceCascade(\n\t\tincoming: IncomingRelation,\n\t\tdeletedRecordId: string,\n\t\ttx: Transaction,\n\t\tcausalDeps: string[],\n\t): Promise<Operation[]> {\n\t\tconst { sourceCollection, foreignKeyField } = incoming\n\n\t\t// Find all non-deleted records that reference the deleted record\n\t\tconst referencingRows = await tx.query<{ id: string }>(\n\t\t\t`SELECT id FROM ${sourceCollection} WHERE ${foreignKeyField} = ? AND _deleted = 0`,\n\t\t\t[deletedRecordId],\n\t\t)\n\n\t\tif (referencingRows.length === 0) {\n\t\t\treturn []\n\t\t}\n\n\t\tconst operations: Operation[] = []\n\n\t\tfor (const row of referencingRows) {\n\t\t\tconst now = Date.now()\n\t\t\tconst sequenceNumber = await allocateNextSequenceInTransaction(tx, this.nodeId)\n\n\t\t\tconst operation = await createOperation(\n\t\t\t\t{\n\t\t\t\t\tnodeId: this.nodeId,\n\t\t\t\t\ttype: 'delete',\n\t\t\t\t\tcollection: sourceCollection,\n\t\t\t\t\trecordId: row.id,\n\t\t\t\t\tdata: null,\n\t\t\t\t\tpreviousData: null,\n\t\t\t\t\tsequenceNumber,\n\t\t\t\t\tcausalDeps: [...causalDeps],\n\t\t\t\t\tschemaVersion: this.schema.version,\n\t\t\t\t},\n\t\t\t\tthis.clock,\n\t\t\t)\n\n\t\t\tconst deleteQuery = buildSoftDeleteQuery(sourceCollection, row.id, now)\n\t\t\tawait tx.execute(deleteQuery.sql, deleteQuery.params)\n\n\t\t\tconst opInsert = buildInsertQuery(\n\t\t\t\t`_kora_ops_${sourceCollection}`,\n\t\t\t\tserializeOperation(operation) as unknown as Record<string, unknown>,\n\t\t\t)\n\t\t\tawait tx.execute(opInsert.sql, opInsert.params)\n\n\t\t\toperations.push(operation)\n\n\t\t\t// Recursively cascade: this deleted record might also be referenced\n\t\t\tconst cascadeResult = await this.enforceDelete(sourceCollection, row.id, tx, [operation.id])\n\t\t\toperations.push(...cascadeResult.operations)\n\t\t}\n\n\t\treturn operations\n\t}\n\n\t/**\n\t * Set-null: update all referencing records to set the foreign key to null.\n\t */\n\tprivate async enforceSetNull(\n\t\tincoming: IncomingRelation,\n\t\tdeletedRecordId: string,\n\t\ttx: Transaction,\n\t\tcausalDeps: string[],\n\t): Promise<Operation[]> {\n\t\tconst { sourceCollection, foreignKeyField } = incoming\n\t\tconst collectionDef = this.schema.collections[sourceCollection]\n\t\tif (!collectionDef) {\n\t\t\treturn []\n\t\t}\n\n\t\t// Find all non-deleted records that reference the deleted record\n\t\tconst referencingRows = await tx.query<{ id: string }>(\n\t\t\t`SELECT id FROM ${sourceCollection} WHERE ${foreignKeyField} = ? AND _deleted = 0`,\n\t\t\t[deletedRecordId],\n\t\t)\n\n\t\tif (referencingRows.length === 0) {\n\t\t\treturn []\n\t\t}\n\n\t\tconst operations: Operation[] = []\n\n\t\tfor (const row of referencingRows) {\n\t\t\tconst now = Date.now()\n\t\t\tconst sequenceNumber = await allocateNextSequenceInTransaction(tx, this.nodeId)\n\n\t\t\tconst updateData: Record<string, unknown> = { [foreignKeyField]: null }\n\t\t\tconst previousData: Record<string, unknown> = { [foreignKeyField]: deletedRecordId }\n\n\t\t\tconst operation = await createOperation(\n\t\t\t\t{\n\t\t\t\t\tnodeId: this.nodeId,\n\t\t\t\t\ttype: 'update',\n\t\t\t\t\tcollection: sourceCollection,\n\t\t\t\t\trecordId: row.id,\n\t\t\t\t\tdata: { ...updateData },\n\t\t\t\t\tpreviousData,\n\t\t\t\t\tsequenceNumber,\n\t\t\t\t\tcausalDeps: [...causalDeps],\n\t\t\t\t\tschemaVersion: this.schema.version,\n\t\t\t\t},\n\t\t\t\tthis.clock,\n\t\t\t)\n\n\t\t\t// Update the record's foreign key to null\n\t\t\tconst serializedChanges = serializeRecord(updateData, collectionDef.fields)\n\t\t\tconst updateQuery = buildUpdateQuery(sourceCollection, row.id, {\n\t\t\t\t...serializedChanges,\n\t\t\t\t_updated_at: now,\n\t\t\t})\n\t\t\tawait tx.execute(updateQuery.sql, updateQuery.params)\n\n\t\t\t// Persist the operation\n\t\t\tconst opRow = serializeOperation(operation)\n\t\t\tconst opInsert = buildInsertQuery(\n\t\t\t\t`_kora_ops_${sourceCollection}`,\n\t\t\t\topRow as unknown as Record<string, unknown>,\n\t\t\t)\n\t\t\tawait tx.execute(opInsert.sql, opInsert.params)\n\n\t\t\toperations.push(operation)\n\t\t}\n\n\t\treturn operations\n\t}\n\n\t/**\n\t * Restrict: refuse the delete if any referencing records exist.\n\t */\n\tprivate async enforceRestrict(\n\t\tincoming: IncomingRelation,\n\t\tdeletedRecordId: string,\n\t\ttx: Transaction,\n\t): Promise<Operation[]> {\n\t\tconst { sourceCollection, foreignKeyField, relationName } = incoming\n\n\t\tconst countRows = await tx.query<{ cnt: number }>(\n\t\t\t`SELECT COUNT(*) as cnt FROM ${sourceCollection} WHERE ${foreignKeyField} = ? AND _deleted = 0`,\n\t\t\t[deletedRecordId],\n\t\t)\n\t\tconst count = countRows[0]?.cnt ?? 0\n\n\t\tif (count > 0) {\n\t\t\t// Determine the target collection from the relation lookup\n\t\t\tconst targetCollection = incoming.relation.to\n\t\t\tthrow new ReferentialIntegrityError(\n\t\t\t\ttargetCollection,\n\t\t\t\tdeletedRecordId,\n\t\t\t\tsourceCollection,\n\t\t\t\trelationName,\n\t\t\t\tcount,\n\t\t\t)\n\t\t}\n\n\t\treturn []\n\t}\n\n\t/**\n\t * Get the relation lookup map for external use (e.g., by the merge engine).\n\t */\n\tgetRelationLookup(): Map<string, IncomingRelation[]> {\n\t\treturn this.lookup\n\t}\n}\n","import type { OnDeleteAction, RelationDefinition, SchemaDefinition } from '@korajs/core'\n\n/**\n * A resolved relation reference: describes a relation that points TO a given collection.\n * When a record in `targetCollection` is deleted, we must handle records in\n * `sourceCollection` that reference it via `foreignKeyField`.\n */\nexport interface IncomingRelation {\n\t/** Name of the relation in the schema */\n\trelationName: string\n\t/** Collection that holds the foreign key (the \"from\" side) */\n\tsourceCollection: string\n\t/** Field in the source collection that references the target */\n\tforeignKeyField: string\n\t/** What to do when the referenced record is deleted */\n\tonDelete: OnDeleteAction\n\t/** The full relation definition */\n\trelation: RelationDefinition\n}\n\n/**\n * Builds an efficient lookup from target collection to all relations that reference it.\n *\n * Given a schema with relations like:\n * ```\n * todoBelongsToProject: { from: 'todos', to: 'projects', field: 'projectId', onDelete: 'cascade' }\n * ```\n *\n * The lookup for 'projects' would return:\n * ```\n * [{ sourceCollection: 'todos', foreignKeyField: 'projectId', onDelete: 'cascade', ... }]\n * ```\n *\n * This enables O(1) lookup when deleting a record to find all dependent relations.\n *\n * @param schema - The full schema definition containing relations\n * @returns A map from target collection name to its incoming relations\n */\nexport function buildRelationLookup(schema: SchemaDefinition): Map<string, IncomingRelation[]> {\n\tconst lookup = new Map<string, IncomingRelation[]>()\n\n\tfor (const [relationName, relation] of Object.entries(schema.relations)) {\n\t\tconst targetCollection = relation.to\n\t\tconst existing = lookup.get(targetCollection) ?? []\n\t\texisting.push({\n\t\t\trelationName,\n\t\t\tsourceCollection: relation.from,\n\t\t\tforeignKeyField: relation.field,\n\t\t\tonDelete: relation.onDelete,\n\t\t\trelation,\n\t\t})\n\t\tlookup.set(targetCollection, existing)\n\t}\n\n\treturn lookup\n}\n\n/**\n * Get all incoming relations for a given collection.\n * Returns an empty array if no relations reference the collection.\n *\n * @param lookup - The pre-built relation lookup map\n * @param collection - The target collection name\n * @returns Array of incoming relations\n */\nexport function getIncomingRelations(\n\tlookup: Map<string, IncomingRelation[]>,\n\tcollection: string,\n): IncomingRelation[] {\n\treturn lookup.get(collection) ?? []\n}\n","import { OperationError } from '@korajs/core'\nimport type { CollectionDefinition, Operation, SchemaDefinition } from '@korajs/core'\nimport { topologicalSort } from '@korajs/core/internal'\nimport { decodeRichtextFieldsFromOpData } from '../serialization/op-data-encoding'\nimport type { CollectionRecord } from '../types'\n\n/**\n * In-memory materialized state at a causal cut in the operation log.\n * Read-only — does not mutate the live store.\n */\nexport interface ReplaySnapshot {\n\t/** The operation whose causal past was replayed (inclusive). */\n\ttargetOperation: Operation\n\t/** Operations applied in causal order (ancestors + target). */\n\toperationsApplied: Operation[]\n\t/** Non-deleted records per collection after replay. */\n\tcollections: Record<string, CollectionRecord[]>\n\t/** Look up a single record at the replay cut. Returns null if deleted or missing. */\n\tfindRecord(collection: string, recordId: string): CollectionRecord | null\n}\n\ninterface MutableReplayRecord {\n\tid: string\n\tfields: Record<string, unknown>\n\tdeleted: boolean\n\tcreatedAt: number\n\tupdatedAt: number\n}\n\ntype ReplayMemoryState = Map<string, Map<string, MutableReplayRecord>>\n\n/**\n * Collect the target operation and all causal ancestors present in `allOps`.\n */\nexport function collectCausalClosure(allOps: Operation[], targetOperationId: string): Operation[] {\n\tconst opMap = new Map<string, Operation>()\n\tfor (const op of allOps) {\n\t\topMap.set(op.id, op)\n\t}\n\n\tconst target = opMap.get(targetOperationId)\n\tif (!target) {\n\t\tthrow new OperationError(\n\t\t\t`Operation \"${targetOperationId}\" not found in the local operation log`,\n\t\t\t{\n\t\t\t\toperationId: targetOperationId,\n\t\t\t},\n\t\t)\n\t}\n\n\tconst included = new Set<string>()\n\tconst stack: string[] = [targetOperationId]\n\n\twhile (stack.length > 0) {\n\t\tconst id = stack.pop()\n\t\tif (id === undefined || included.has(id)) {\n\t\t\tcontinue\n\t\t}\n\t\tincluded.add(id)\n\t\tconst op = opMap.get(id)\n\t\tif (!op) {\n\t\t\tcontinue\n\t\t}\n\t\tfor (const depId of op.causalDeps) {\n\t\t\tif (opMap.has(depId)) {\n\t\t\t\tstack.push(depId)\n\t\t\t}\n\t\t}\n\t}\n\n\tconst subset = allOps.filter((op) => included.has(op.id))\n\treturn topologicalSort(subset)\n}\n\n/**\n * Replay a causal subset of operations into an in-memory materialized snapshot.\n * Does not use the merge engine — concurrent ops outside the causal cut are excluded.\n */\nexport function buildReplaySnapshot(\n\tschema: SchemaDefinition,\n\tallOps: Operation[],\n\ttargetOperationId: string,\n): ReplaySnapshot {\n\tconst operationsApplied = collectCausalClosure(allOps, targetOperationId)\n\tconst targetOperation = operationsApplied.find((op) => op.id === targetOperationId)\n\tif (!targetOperation) {\n\t\tthrow new OperationError(`Operation \"${targetOperationId}\" not found after causal sort`, {\n\t\t\toperationId: targetOperationId,\n\t\t})\n\t}\n\n\tconst memory: ReplayMemoryState = new Map()\n\tfor (const op of operationsApplied) {\n\t\tapplyOperationToMemory(memory, op, schema)\n\t}\n\n\tconst collections = materializeCollections(schema, memory)\n\n\treturn {\n\t\ttargetOperation,\n\t\toperationsApplied,\n\t\tcollections,\n\t\tfindRecord(collection: string, recordId: string): CollectionRecord | null {\n\t\t\tconst colMap = memory.get(collection)\n\t\t\tconst record = colMap?.get(recordId)\n\t\t\tif (!record || record.deleted) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst definition = schema.collections[collection]\n\t\t\tif (!definition) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn toCollectionRecord(record, definition)\n\t\t},\n\t}\n}\n\nfunction applyOperationToMemory(\n\tstate: ReplayMemoryState,\n\top: Operation,\n\tschema: SchemaDefinition,\n): void {\n\tconst definition = schema.collections[op.collection]\n\tif (!definition) {\n\t\treturn\n\t}\n\n\tlet colMap = state.get(op.collection)\n\tif (!colMap) {\n\t\tcolMap = new Map()\n\t\tstate.set(op.collection, colMap)\n\t}\n\n\tconst wallTime = op.timestamp.wallTime\n\n\tswitch (op.type) {\n\t\tcase 'insert': {\n\t\t\tif (!op.data) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcolMap.set(op.recordId, {\n\t\t\t\tid: op.recordId,\n\t\t\t\t// op.data stores binary richtext as tagged JSON; snapshots must\n\t\t\t\t// expose record-shaped values (Uint8Array/string).\n\t\t\t\tfields: decodeRichtextFieldsFromOpData(op.data, definition.fields),\n\t\t\t\tdeleted: false,\n\t\t\t\tcreatedAt: wallTime,\n\t\t\t\tupdatedAt: wallTime,\n\t\t\t})\n\t\t\tbreak\n\t\t}\n\t\tcase 'update': {\n\t\t\tif (!op.data) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst decodedData = decodeRichtextFieldsFromOpData(op.data, definition.fields)\n\t\t\tconst existing = colMap.get(op.recordId)\n\t\t\tif (existing && !existing.deleted) {\n\t\t\t\texisting.fields = { ...existing.fields, ...decodedData }\n\t\t\t\texisting.updatedAt = wallTime\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (existing?.deleted) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcolMap.set(op.recordId, {\n\t\t\t\tid: op.recordId,\n\t\t\t\tfields: decodedData,\n\t\t\t\tdeleted: false,\n\t\t\t\tcreatedAt: wallTime,\n\t\t\t\tupdatedAt: wallTime,\n\t\t\t})\n\t\t\tbreak\n\t\t}\n\t\tcase 'delete': {\n\t\t\tconst existing = colMap.get(op.recordId)\n\t\t\tif (existing) {\n\t\t\t\texisting.deleted = true\n\t\t\t\texisting.updatedAt = wallTime\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcolMap.set(op.recordId, {\n\t\t\t\tid: op.recordId,\n\t\t\t\tfields: {},\n\t\t\t\tdeleted: true,\n\t\t\t\tcreatedAt: wallTime,\n\t\t\t\tupdatedAt: wallTime,\n\t\t\t})\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunction materializeCollections(\n\tschema: SchemaDefinition,\n\tmemory: ReplayMemoryState,\n): Record<string, CollectionRecord[]> {\n\tconst collections: Record<string, CollectionRecord[]> = {}\n\n\tfor (const [collectionName, definition] of Object.entries(schema.collections)) {\n\t\tconst colMap = memory.get(collectionName)\n\t\tconst records: CollectionRecord[] = []\n\t\tif (colMap) {\n\t\t\tfor (const record of colMap.values()) {\n\t\t\t\tif (!record.deleted) {\n\t\t\t\t\trecords.push(toCollectionRecord(record, definition))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcollections[collectionName] = records\n\t}\n\n\treturn collections\n}\n\nfunction toCollectionRecord(\n\trecord: MutableReplayRecord,\n\tdefinition: CollectionDefinition,\n): CollectionRecord {\n\tconst result: CollectionRecord = {\n\t\tid: record.id,\n\t\tcreatedAt: record.createdAt,\n\t\tupdatedAt: record.updatedAt,\n\t}\n\tfor (const [fieldName] of Object.entries(definition.fields)) {\n\t\tif (fieldName in record.fields) {\n\t\t\tresult[fieldName] = record.fields[fieldName]\n\t\t}\n\t}\n\treturn result\n}\n","import type { SequenceConfig } from '@korajs/core'\nimport { defaultSequenceFormat, formatSequenceValue } from '@korajs/core'\nimport type { StorageAdapter } from '../types'\n\ninterface SequenceRow {\n\tcounter: number\n}\n\n/**\n * Manages offline-safe sequences backed by a `_kora_sequences` table.\n *\n * Each sequence counter is scoped by (name, scope, nodeId), ensuring\n * that different devices never collide. The counter is atomically\n * incremented within a database transaction.\n *\n * @example\n * ```typescript\n * const mgr = new SequenceManager(adapter, 'node-abc')\n *\n * const receipt = await mgr.next('receipt', {\n * scope: 'store-1',\n * format: 'S-{date}-{node4}-{seq}',\n * })\n * // → \"S-20260508-node-0001\"\n * ```\n */\nexport class SequenceManager {\n\tprivate readonly adapter: StorageAdapter\n\tprivate readonly nodeId: string\n\n\tconstructor(adapter: StorageAdapter, nodeId: string) {\n\t\tthis.adapter = adapter\n\t\tthis.nodeId = nodeId\n\t}\n\n\t/**\n\t * Get the next value in a sequence, atomically incrementing the counter.\n\t *\n\t * @param name - The sequence name (e.g., 'receipt', 'invoice')\n\t * @param config - Optional configuration for scope, format, and starting value\n\t * @returns The formatted sequence value\n\t */\n\tasync next(name: string, config?: SequenceConfig): Promise<string> {\n\t\tconst scope = config?.scope ?? ''\n\t\tconst startAt = config?.startAt ?? 1\n\t\tconst format = config?.format ?? defaultSequenceFormat(name)\n\n\t\tlet counter = 0\n\n\t\tawait this.adapter.transaction(async (tx) => {\n\t\t\t// Try to read the current counter\n\t\t\tconst rows = await tx.query<SequenceRow>(\n\t\t\t\t'SELECT counter FROM _kora_sequences WHERE name = ? AND scope = ? AND node_id = ?',\n\t\t\t\t[name, scope, this.nodeId],\n\t\t\t)\n\n\t\t\tif (rows.length > 0) {\n\t\t\t\tconst row = rows[0] as SequenceRow\n\t\t\t\tcounter = row.counter + 1\n\t\t\t\tawait tx.execute(\n\t\t\t\t\t'UPDATE _kora_sequences SET counter = ? WHERE name = ? AND scope = ? AND node_id = ?',\n\t\t\t\t\t[counter, name, scope, this.nodeId],\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\t// First use — initialize with startAt\n\t\t\t\tcounter = startAt\n\t\t\t\tawait tx.execute(\n\t\t\t\t\t'INSERT INTO _kora_sequences (name, scope, node_id, counter) VALUES (?, ?, ?, ?)',\n\t\t\t\t\t[name, scope, this.nodeId, counter],\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\n\t\treturn formatSequenceValue(format, counter, this.nodeId)\n\t}\n\n\t/**\n\t * Get the current counter value without incrementing.\n\t *\n\t * @param name - The sequence name\n\t * @param config - Optional scope\n\t * @returns The current counter value, or 0 if the sequence has never been used\n\t */\n\tasync current(name: string, config?: { scope?: string }): Promise<number> {\n\t\tconst scope = config?.scope ?? ''\n\n\t\tconst rows = await this.adapter.query<SequenceRow>(\n\t\t\t'SELECT counter FROM _kora_sequences WHERE name = ? AND scope = ? AND node_id = ?',\n\t\t\t[name, scope, this.nodeId],\n\t\t)\n\n\t\tif (rows.length > 0) {\n\t\t\treturn (rows[0] as SequenceRow).counter\n\t\t}\n\t\treturn 0\n\t}\n\n\t/**\n\t * Reset a sequence counter.\n\t *\n\t * @param name - The sequence name\n\t * @param config - Optional scope and target value\n\t */\n\tasync reset(name: string, config?: { scope?: string; to?: number }): Promise<void> {\n\t\tconst scope = config?.scope ?? ''\n\t\tconst to = config?.to ?? 0\n\n\t\tawait this.adapter.execute(\n\t\t\t'DELETE FROM _kora_sequences WHERE name = ? AND scope = ? AND node_id = ?',\n\t\t\t[name, scope, this.nodeId],\n\t\t)\n\n\t\tif (to > 0) {\n\t\t\tawait this.adapter.execute(\n\t\t\t\t'INSERT INTO _kora_sequences (name, scope, node_id, counter) VALUES (?, ?, ?, ?)',\n\t\t\t\t[name, scope, this.nodeId, to],\n\t\t\t)\n\t\t}\n\t}\n}\n","/**\n * Bloom filter for fast subscription dependency pre-checking.\n *\n * When the SubscriptionManager has many active subscriptions, checking whether a\n * mutation might affect any subscription requires scanning all subscriptions.\n * This bloom filter provides a fast O(k) pre-check: if the filter says \"definitely\n * not present\", we can skip the subscription entirely. If it says \"maybe present\",\n * we fall through to the precise collection/field matching.\n *\n * Uses FNV-1a for hashing and Kirsch-Mitzenmacker double hashing to derive k\n * hash functions from two base hashes.\n */\n\n// FNV-1a constants for 32-bit hashes\nconst FNV_OFFSET_BASIS = 0x811c9dc5\nconst FNV_PRIME = 0x01000193\n\n/**\n * Compute FNV-1a 32-bit hash of a string.\n *\n * FNV-1a is a non-cryptographic hash function optimized for speed and distribution.\n * It processes one byte at a time: XOR then multiply, which gives better avalanche\n * behavior than the original FNV-1 (multiply then XOR).\n *\n * @param input - The string to hash\n * @returns A 32-bit unsigned integer hash\n */\nexport function fnv1a32(input: string): number {\n\tlet hash = FNV_OFFSET_BASIS\n\tfor (let i = 0; i < input.length; i++) {\n\t\thash ^= input.charCodeAt(i)\n\t\t// Math.imul gives true 32-bit integer multiplication without overflow issues\n\t\thash = Math.imul(hash, FNV_PRIME)\n\t}\n\t// Ensure unsigned 32-bit result\n\treturn hash >>> 0\n}\n\n/**\n * Calculate the optimal number of bits for a bloom filter.\n *\n * Formula: m = -(n * ln(p)) / (ln(2)^2)\n * Rounded up to the nearest multiple of 32 for Uint32Array alignment.\n *\n * @param expectedItems - Expected number of items to insert\n * @param falsePositiveRate - Desired false positive rate (0-1)\n * @returns Number of bits, rounded to nearest 32-bit multiple (minimum 32)\n */\nexport function optimalBitCount(expectedItems: number, falsePositiveRate: number): number {\n\tif (expectedItems <= 0) return 32\n\tif (falsePositiveRate <= 0 || falsePositiveRate >= 1) return 32\n\n\tconst ln2Squared = Math.LN2 * Math.LN2\n\tconst rawBits = -(expectedItems * Math.log(falsePositiveRate)) / ln2Squared\n\n\t// Round up to nearest 32-bit multiple for Uint32Array alignment\n\tconst aligned = Math.ceil(rawBits / 32) * 32\n\treturn Math.max(32, aligned)\n}\n\n/**\n * Calculate the optimal number of hash functions for a bloom filter.\n *\n * Formula: k = (m/n) * ln(2)\n * Clamped to [1, 30] to avoid degenerate cases.\n *\n * @param bitCount - Total number of bits in the filter\n * @param expectedItems - Expected number of items to insert\n * @returns Number of hash functions, clamped to [1, 30]\n */\nexport function optimalHashCount(bitCount: number, expectedItems: number): number {\n\tif (expectedItems <= 0) return 1\n\tconst raw = (bitCount / expectedItems) * Math.LN2\n\treturn Math.max(1, Math.min(30, Math.round(raw)))\n}\n\n/**\n * Bloom filter for subscription dependency tracking.\n *\n * Each subscription adds its watched collection (and optionally fields) to the\n * filter. When a mutation arrives, we check \"collection\" and \"collection:field\"\n * keys against the filter. A negative result means no subscription cares about\n * this mutation, so we can skip the expensive per-subscription scan.\n *\n * @example\n * ```typescript\n * const filter = new SubscriptionBloomFilter(100, 0.01)\n * filter.add('todos')\n * filter.add('todos', 'completed')\n *\n * filter.mightContain('todos') // true (definitely added)\n * filter.mightContain('projects') // false (definitely not added)\n * filter.mightContain('todos', 'completed') // true (definitely added)\n * ```\n */\nexport class SubscriptionBloomFilter {\n\tprivate bits: Uint32Array\n\tprivate readonly bitCount: number\n\tprivate readonly hashCount: number\n\tprivate itemCount = 0\n\n\tconstructor(expectedItems: number, falsePositiveRate = 0.01) {\n\t\tthis.bitCount = optimalBitCount(expectedItems, falsePositiveRate)\n\t\tthis.hashCount = optimalHashCount(this.bitCount, expectedItems)\n\t\tthis.bits = new Uint32Array(this.bitCount / 32)\n\t}\n\n\t/**\n\t * Add a collection (and optional field) to the bloom filter.\n\t *\n\t * @param collection - Collection name (e.g., \"todos\")\n\t * @param field - Optional field name (e.g., \"completed\")\n\t */\n\tadd(collection: string, field?: string): void {\n\t\tconst key = field !== undefined ? `${collection}:${field}` : collection\n\t\tconst positions = this.getPositions(key)\n\t\tfor (const pos of positions) {\n\t\t\tconst wordIndex = pos >>> 5 // equivalent to Math.floor(pos / 32)\n\t\t\tconst bitIndex = pos & 31 // equivalent to pos % 32\n\t\t\tconst current = this.bits[wordIndex] ?? 0\n\t\t\tthis.bits[wordIndex] = current | (1 << bitIndex)\n\t\t}\n\t\tthis.itemCount++\n\t}\n\n\t/**\n\t * Check if a collection (and optional field) might be in the filter.\n\t *\n\t * A return value of `false` means the item is DEFINITELY NOT in the filter.\n\t * A return value of `true` means the item MIGHT be in the filter (possible false positive).\n\t *\n\t * @param collection - Collection name to check\n\t * @param field - Optional field name to check\n\t * @returns false = definitely absent, true = possibly present\n\t */\n\tmightContain(collection: string, field?: string): boolean {\n\t\tconst key = field !== undefined ? `${collection}:${field}` : collection\n\t\tconst positions = this.getPositions(key)\n\t\tfor (const pos of positions) {\n\t\t\tconst wordIndex = pos >>> 5\n\t\t\tconst bitIndex = pos & 31\n\t\t\tif (((this.bits[wordIndex] ?? 0) & (1 << bitIndex)) === 0) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\t}\n\n\t/**\n\t * Reset the bloom filter, clearing all bits and the item count.\n\t */\n\tclear(): void {\n\t\tthis.bits.fill(0)\n\t\tthis.itemCount = 0\n\t}\n\n\t/**\n\t * Estimate the current false positive rate based on the number of items inserted.\n\t *\n\t * Formula: (1 - e^(-kn/m))^k\n\t * where k = hash count, n = item count, m = bit count.\n\t *\n\t * @returns Estimated false positive rate as a number between 0 and 1\n\t */\n\testimatedFalsePositiveRate(): number {\n\t\tif (this.itemCount === 0) return 0\n\t\tconst exponent = -(this.hashCount * this.itemCount) / this.bitCount\n\t\treturn (1 - Math.exp(exponent)) ** this.hashCount\n\t}\n\n\t/**\n\t * @returns The number of items that have been added to the filter\n\t */\n\tgetItemCount(): number {\n\t\treturn this.itemCount\n\t}\n\n\t/**\n\t * @returns The total number of bits in the filter\n\t */\n\tgetBitCount(): number {\n\t\treturn this.bitCount\n\t}\n\n\t/**\n\t * @returns The number of hash functions used\n\t */\n\tgetHashCount(): number {\n\t\treturn this.hashCount\n\t}\n\n\t/**\n\t * Count the number of bits currently set to 1.\n\t * Uses Brian Kernighan's algorithm: each iteration clears the lowest set bit,\n\t * so the loop runs exactly as many times as there are set bits.\n\t *\n\t * @returns Number of bits set to 1\n\t */\n\tgetSetBitCount(): number {\n\t\tlet count = 0\n\t\tfor (let i = 0; i < this.bits.length; i++) {\n\t\t\tlet word = this.bits[i] ?? 0\n\t\t\twhile (word !== 0) {\n\t\t\t\t// Clear the lowest set bit: n & (n - 1) removes the rightmost 1-bit\n\t\t\t\tword &= word - 1\n\t\t\t\tcount++\n\t\t\t}\n\t\t}\n\t\treturn count\n\t}\n\n\t/**\n\t * Compute k bit positions for a given key using Kirsch-Mitzenmacker double hashing.\n\t *\n\t * Instead of computing k independent hash functions, we compute two base hashes\n\t * (h1 and h2) and derive the rest as: h_i = (h1 + i * h2) mod m.\n\t * This technique is proven to have the same asymptotic false positive rate as\n\t * k independent hash functions.\n\t *\n\t * We derive h1 and h2 from a single FNV-1a hash by splitting and mixing:\n\t * h1 = fnv1a(key), h2 = fnv1a(key + \"\\0salt\") to ensure independence.\n\t */\n\tprivate getPositions(key: string): number[] {\n\t\tconst h1 = fnv1a32(key)\n\t\t// Use a null-byte separator + salt suffix to derive a second independent hash\n\t\tconst h2 = fnv1a32(`${key}\\0bloom`)\n\n\t\tconst positions = new Array<number>(this.hashCount)\n\t\tfor (let i = 0; i < this.hashCount; i++) {\n\t\t\t// Combine h1 and h2 with Kirsch-Mitzenmacker technique\n\t\t\tpositions[i] = ((h1 + Math.imul(i, h2)) >>> 0) % this.bitCount\n\t\t}\n\t\treturn positions\n\t}\n}\n","import type { Operation } from '@korajs/core'\nimport type {\n\tCollectionRecord,\n\tQueryDescriptor,\n\tSubscription,\n\tSubscriptionCallback,\n} from '../types'\nimport { SubscriptionBloomFilter } from './bloom-filter'\n\nlet nextSubId = 0\n\n/**\n * Default threshold for activating bloom filter-based dependency tracking.\n * Below this count, linear scanning is faster due to bloom filter rebuild overhead.\n */\nconst DEFAULT_BLOOM_THRESHOLD = 100\n\n/**\n * Default expected items for bloom filter sizing.\n * Sized to handle typical subscription dependency counts with headroom.\n */\nconst DEFAULT_BLOOM_EXPECTED_ITEMS = 500\n\n/**\n * Default false positive rate for bloom filter.\n * 1% provides a good balance between filter size and accuracy.\n */\nconst DEFAULT_BLOOM_FALSE_POSITIVE_RATE = 0.01\n\n/**\n * Configuration options for the SubscriptionManager.\n */\nexport interface SubscriptionManagerOptions {\n\t/**\n\t * Minimum number of subscriptions before activating bloom filter.\n\t * Below this threshold, linear scanning is used (bloom filter overhead not worth it).\n\t * @default 100\n\t */\n\tbloomThreshold?: number\n\n\t/**\n\t * Expected number of unique collection+field dependencies for bloom filter sizing.\n\t * @default 500\n\t */\n\tbloomExpectedItems?: number\n\n\t/**\n\t * Target false positive rate for the bloom filter.\n\t * Lower values require more memory but reduce unnecessary precise checks.\n\t * @default 0.01\n\t */\n\tbloomFalsePositiveRate?: number\n\n\t/** Called when a query subscription is registered (e.g. to register sync query subsets). */\n\tonQuerySubscribed?: (descriptor: QueryDescriptor) => () => void\n}\n\n/**\n * Performance statistics for monitoring subscription checking efficiency.\n */\nexport interface SubscriptionStats {\n\t/** Total number of mutation notifications processed */\n\ttotalChecks: number\n\t/** Number of times bloom filter said \"maybe\" (proceeded to precise check) */\n\tbloomFilterHits: number\n\t/** Number of times bloom filter said \"definitely not\" (skipped all subscriptions) */\n\tbloomFilterMisses: number\n\t/** Number of times bloom filter said \"maybe\" but precise check found no match */\n\tfalsePositives: number\n\t/** Average time per check in milliseconds */\n\taverageCheckTimeMs: number\n\t/** Whether bloom filter is currently active */\n\tbloomFilterActive: boolean\n\t/** Current subscription count */\n\tsubscriptionCount: number\n}\n\n/**\n * Manages reactive subscriptions with two-level dependency checking.\n *\n * When a mutation occurs on a collection, affected subscriptions are re-evaluated\n * in a microtask batch and callbacks are invoked only if results actually changed.\n *\n * For large subscription counts (>= bloomThreshold), a bloom filter provides O(k)\n * pre-filtering to avoid scanning all subscriptions on every mutation:\n *\n * Level 1 (Bloom filter): Fast O(k) check -- does this mutation potentially affect\n * any subscription? If NO: skip all subscriptions (guaranteed correct).\n * If MAYBE: proceed to Level 2.\n *\n * Level 2 (Precise check): Only evaluate subscriptions that match the mutated\n * collection, including included (related) collection tracking.\n */\nexport class SubscriptionManager {\n\tprivate subscriptions = new Map<string, Subscription>()\n\tprivate pendingCollections = new Set<string>()\n\tprivate flushScheduled = false\n\tprivate readonly onQuerySubscribed?: (descriptor: QueryDescriptor) => () => void\n\n\t// Bloom filter state\n\tprivate bloomFilter: SubscriptionBloomFilter | null = null\n\tprivate bloomDirty = false\n\tprivate readonly bloomThreshold: number\n\tprivate readonly bloomExpectedItems: number\n\tprivate readonly bloomFalsePositiveRate: number\n\n\t// Performance stats\n\tprivate totalChecks = 0\n\tprivate bloomFilterHits = 0\n\tprivate bloomFilterMisses = 0\n\tprivate falsePositives = 0\n\tprivate totalCheckTimeMs = 0\n\n\tconstructor(options?: SubscriptionManagerOptions) {\n\t\tthis.bloomThreshold = options?.bloomThreshold ?? DEFAULT_BLOOM_THRESHOLD\n\t\tthis.bloomExpectedItems = options?.bloomExpectedItems ?? DEFAULT_BLOOM_EXPECTED_ITEMS\n\t\tthis.bloomFalsePositiveRate =\n\t\t\toptions?.bloomFalsePositiveRate ?? DEFAULT_BLOOM_FALSE_POSITIVE_RATE\n\t\tthis.onQuerySubscribed = options?.onQuerySubscribed\n\t}\n\n\t/**\n\t * Register a new subscription.\n\t *\n\t * @param descriptor - The query descriptor defining what this subscription watches\n\t * @param callback - Called with results whenever they change\n\t * @param executeFn - Function to re-execute the query and get current results\n\t * @returns An unsubscribe function\n\t */\n\tregister(\n\t\tdescriptor: QueryDescriptor,\n\t\tcallback: SubscriptionCallback<CollectionRecord>,\n\t\texecuteFn: () => Promise<CollectionRecord[]>,\n\t): () => void {\n\t\tconst id = `sub_${++nextSubId}`\n\t\tconst subscription: Subscription = {\n\t\t\tid,\n\t\t\tdescriptor,\n\t\t\tcallback,\n\t\t\texecuteFn,\n\t\t\tlastResults: [],\n\t\t}\n\t\tthis.subscriptions.set(id, subscription)\n\n\t\t// Mark bloom filter as needing rebuild since dependencies changed\n\t\tthis.bloomDirty = true\n\n\t\tconst externalCleanup = this.onQuerySubscribed?.(descriptor)\n\n\t\treturn () => {\n\t\t\tthis.subscriptions.delete(id)\n\t\t\tthis.bloomDirty = true\n\t\t\texternalCleanup?.()\n\t\t}\n\t}\n\n\t/**\n\t * Register a subscription and immediately execute the query.\n\t * The initial results are stored as lastResults so subsequent flushes\n\t * correctly diff against the initial state.\n\t *\n\t * @returns An unsubscribe function\n\t */\n\tregisterAndFetch(\n\t\tdescriptor: QueryDescriptor,\n\t\tcallback: SubscriptionCallback<CollectionRecord>,\n\t\texecuteFn: () => Promise<CollectionRecord[]>,\n\t): () => void {\n\t\tconst id = `sub_${++nextSubId}`\n\t\tconst subscription: Subscription = {\n\t\t\tid,\n\t\t\tdescriptor,\n\t\t\tcallback,\n\t\t\texecuteFn,\n\t\t\tlastResults: [],\n\t\t}\n\t\tthis.subscriptions.set(id, subscription)\n\n\t\t// Mark bloom filter as needing rebuild since dependencies changed\n\t\tthis.bloomDirty = true\n\n\t\tconst externalCleanup = this.onQuerySubscribed?.(descriptor)\n\n\t\t// Execute immediately, set lastResults, and call callback\n\t\texecuteFn().then((results) => {\n\t\t\t// Guard: subscription may have been removed before the async fetch completes\n\t\t\tif (this.subscriptions.has(id)) {\n\t\t\t\tsubscription.lastResults = results\n\t\t\t\tcallback(results)\n\t\t\t}\n\t\t})\n\n\t\treturn () => {\n\t\t\tthis.subscriptions.delete(id)\n\t\t\tthis.bloomDirty = true\n\t\t\texternalCleanup?.()\n\t\t}\n\t}\n\n\t/**\n\t * Notify the manager that a mutation occurred on a collection.\n\t * Schedules a microtask flush to batch multiple mutations in the same tick.\n\t */\n\tnotify(collection: string, _operation: Operation): void {\n\t\tthis.pendingCollections.add(collection)\n\t\tthis.scheduleFlush()\n\t}\n\n\t/**\n\t * Immediately flush all pending notifications.\n\t * Useful for testing. In production, flushing happens via microtask.\n\t */\n\tasync flush(): Promise<void> {\n\t\tif (this.pendingCollections.size === 0) return\n\n\t\tconst collections = new Set(this.pendingCollections)\n\t\tthis.pendingCollections.clear()\n\t\tthis.flushScheduled = false\n\n\t\tconst affected = this.findAffectedSubscriptions(collections)\n\n\t\t// Re-execute and diff\n\t\tfor (const sub of affected) {\n\t\t\ttry {\n\t\t\t\tconst newResults = await sub.executeFn()\n\t\t\t\tif (!this.resultsEqual(sub.lastResults, newResults)) {\n\t\t\t\t\tsub.lastResults = newResults\n\t\t\t\t\tsub.callback(newResults)\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Subscription re-execution failed -- skip silently for now.\n\t\t\t\t// In future, we could emit an error event for DevTools.\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Remove all subscriptions. Called on store close.\n\t */\n\tclear(): void {\n\t\tthis.subscriptions.clear()\n\t\tthis.pendingCollections.clear()\n\t\tthis.flushScheduled = false\n\t\tthis.bloomFilter = null\n\t\tthis.bloomDirty = false\n\t\tthis.totalChecks = 0\n\t\tthis.bloomFilterHits = 0\n\t\tthis.bloomFilterMisses = 0\n\t\tthis.falsePositives = 0\n\t\tthis.totalCheckTimeMs = 0\n\t}\n\n\t/** Number of active subscriptions (for testing/debugging) */\n\tget size(): number {\n\t\treturn this.subscriptions.size\n\t}\n\n\t/**\n\t * Get performance statistics for monitoring subscription checking efficiency.\n\t * Useful for DevTools integration and performance tuning.\n\t */\n\tgetStats(): SubscriptionStats {\n\t\treturn {\n\t\t\ttotalChecks: this.totalChecks,\n\t\t\tbloomFilterHits: this.bloomFilterHits,\n\t\t\tbloomFilterMisses: this.bloomFilterMisses,\n\t\t\tfalsePositives: this.falsePositives,\n\t\t\taverageCheckTimeMs: this.totalChecks > 0 ? this.totalCheckTimeMs / this.totalChecks : 0,\n\t\t\tbloomFilterActive: this.isBloomActive(),\n\t\t\tsubscriptionCount: this.subscriptions.size,\n\t\t}\n\t}\n\n\t/**\n\t * Check if bloom filter is currently active.\n\t * Active when subscription count meets or exceeds the threshold.\n\t */\n\tisBloomActive(): boolean {\n\t\treturn this.subscriptions.size >= this.bloomThreshold\n\t}\n\n\t/**\n\t * Find subscriptions affected by mutations to the given collections.\n\t * Uses two-level checking when bloom filter is active:\n\t *\n\t * Level 1: Bloom filter pre-check -- if no subscription depends on any\n\t * of the mutated collections, skip everything (O(k) per collection).\n\t *\n\t * Level 2: Precise check -- linear scan of subscriptions, matching\n\t * against the mutated collections.\n\t */\n\tprivate findAffectedSubscriptions(collections: Set<string>): Subscription[] {\n\t\tconst startTime = performance.now()\n\t\tthis.totalChecks++\n\n\t\tconst useBloom = this.isBloomActive()\n\n\t\tif (useBloom) {\n\t\t\t// Rebuild bloom filter if dependencies have changed\n\t\t\tif (this.bloomDirty || this.bloomFilter === null) {\n\t\t\t\tthis.rebuildBloomFilter()\n\t\t\t}\n\n\t\t\tconst filter = this.bloomFilter\n\t\t\tif (filter !== null) {\n\t\t\t\t// Level 1: Bloom filter pre-check\n\t\t\t\tlet anyPossibleMatch = false\n\t\t\t\tfor (const col of collections) {\n\t\t\t\t\tif (filter.mightContain(col)) {\n\t\t\t\t\t\tanyPossibleMatch = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!anyPossibleMatch) {\n\t\t\t\t\t// Bloom filter guarantees no subscription depends on these collections\n\t\t\t\t\tthis.bloomFilterMisses++\n\t\t\t\t\tthis.totalCheckTimeMs += performance.now() - startTime\n\t\t\t\t\treturn []\n\t\t\t\t}\n\n\t\t\t\tthis.bloomFilterHits++\n\t\t\t}\n\t\t}\n\n\t\t// Level 2: Precise check (or only check when bloom is not active)\n\t\tconst affected: Subscription[] = []\n\t\tlet anyPreciseMatch = false\n\n\t\tfor (const sub of this.subscriptions.values()) {\n\t\t\tif (collections.has(sub.descriptor.collection)) {\n\t\t\t\taffected.push(sub)\n\t\t\t\tanyPreciseMatch = true\n\t\t\t} else if (sub.descriptor.includeCollections) {\n\t\t\t\t// Re-evaluate if a mutation affects an included (related) collection\n\t\t\t\tfor (const incCol of sub.descriptor.includeCollections) {\n\t\t\t\t\tif (collections.has(incCol)) {\n\t\t\t\t\t\taffected.push(sub)\n\t\t\t\t\t\tanyPreciseMatch = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Track false positives: bloom said \"maybe\" but precise check found nothing\n\t\tif (useBloom && !anyPreciseMatch) {\n\t\t\tthis.falsePositives++\n\t\t}\n\n\t\tthis.totalCheckTimeMs += performance.now() - startTime\n\t\treturn affected\n\t}\n\n\t/**\n\t * Rebuild the bloom filter from all current subscriptions.\n\t * Adds collection-level dependencies for every subscription, plus\n\t * any included collection dependencies.\n\t */\n\tprivate rebuildBloomFilter(): void {\n\t\tconst filter = new SubscriptionBloomFilter(this.bloomExpectedItems, this.bloomFalsePositiveRate)\n\n\t\tfor (const sub of this.subscriptions.values()) {\n\t\t\t// Add the primary collection dependency\n\t\t\tfilter.add(sub.descriptor.collection)\n\n\t\t\t// Add included (related) collection dependencies\n\t\t\tif (sub.descriptor.includeCollections) {\n\t\t\t\tfor (const incCol of sub.descriptor.includeCollections) {\n\t\t\t\t\tfilter.add(incCol)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.bloomFilter = filter\n\t\tthis.bloomDirty = false\n\t}\n\n\tprivate scheduleFlush(): void {\n\t\tif (this.flushScheduled) return\n\t\tthis.flushScheduled = true\n\t\tqueueMicrotask(() => {\n\t\t\tthis.flush()\n\t\t})\n\t}\n\n\t/**\n\t * Compare two result sets. Uses ID-based comparison first (same length, same IDs),\n\t * then deep comparison of remaining fields when IDs match.\n\t * Avoids JSON.stringify which is O(n) and fragile to field ordering differences.\n\t */\n\tprivate resultsEqual(prev: CollectionRecord[], next: CollectionRecord[]): boolean {\n\t\tif (prev.length !== next.length) return false\n\t\tif (prev.length === 0) return true\n\n\t\t// Fast ID-based check: same records in same order means same result set\n\t\tfor (let i = 0; i < prev.length; i++) {\n\t\t\tif (prev[i]?.id !== next[i]?.id) return false\n\t\t}\n\n\t\t// IDs match — do a field-level comparison for safety\n\t\tfor (let i = 0; i < prev.length; i++) {\n\t\t\tconst a = prev[i] as Record<string, unknown>\n\t\t\tconst b = next[i] as Record<string, unknown>\n\t\t\tconst keysA = Object.keys(a)\n\t\t\tconst keysB = Object.keys(b)\n\t\t\tif (keysA.length !== keysB.length) return false\n\t\t\tfor (const key of keysA) {\n\t\t\t\tif (a[key] !== b[key]) return false\n\t\t\t}\n\t\t}\n\n\t\treturn true\n\t}\n}\n","import { HybridLogicalClock, MAX_LOGICAL } from '@korajs/core'\nimport type { HLCTimestamp, Operation, OperationInput, SchemaDefinition } from '@korajs/core'\nimport { computeOperationId } from '@korajs/core/internal'\nimport { parseFieldVersions, serializeFieldVersions } from '../lww/field-versions'\nimport { serializeRowVersion } from '../lww/row-version'\nimport { buildInsertQuery } from '../query/sql-builder'\nimport { deserializeOperationWithCollection, serializeOperation } from '../serialization/serializer'\nimport type { OperationRow, RawCollectionRow, StorageAdapter } from '../types'\n\n/**\n * Result of re-stamping unsynced operations after a clock correction.\n */\nexport interface ClockRebaseResult {\n\t/** The rewritten operations, in causal order (original HLC total order preserved). */\n\toperations: Operation[]\n\t/** Maps each old (pre-rebase) operation id to its new content-addressed id. */\n\tidMapping: Record<string, string>\n\t/** Number of operations that were re-stamped. */\n\trebasedCount: number\n\t/** Highest timestamp assigned during the rebase, or null when nothing was rebased. */\n\tnewMaxTimestamp: HLCTimestamp | null\n}\n\n/**\n * The serialized logical counter is zero-padded to 5 digits; a logical value\n * needing more digits would break the lexicographic ordering of the stored\n * timestamp / `_version` columns. Overflow spills into wallTime instead.\n * Derived from the clock's own cap so the two can never drift apart.\n */\nconst LOGICAL_COUNTER_LIMIT = MAX_LOGICAL + 1\n\nfunction emptyResult(): ClockRebaseResult {\n\treturn { operations: [], idMapping: {}, rebasedCount: 0, newMaxTimestamp: null }\n}\n\n/**\n * Re-stamp unsynced (never server-acknowledged) operations after a fast device\n * clock was corrected, so sync can resume immediately instead of waiting for\n * real time to catch up with the future timestamps.\n *\n * This is safe for exactly the same reason rewriting unpushed git commits is\n * safe: unacknowledged operations have never been shared, so no other replica\n * can hold a reference to their old ids or timestamps. Acknowledged operations\n * are immutable forever and are never touched here.\n *\n * The relative order of the rebased operations is preserved: they are sorted by\n * their original HLC total order and assigned consecutive logical counters on a\n * single new wall time, chosen to sort after every non-rebased operation in the\n * log (and after corrected \"now\").\n */\nexport async function rebaseUnsyncedOperationsInLog(\n\tadapter: StorageAdapter,\n\tschema: SchemaDefinition,\n\tunsyncedOpIds: string[],\n\tcorrectedNowMs: number,\n): Promise<ClockRebaseResult> {\n\tif (unsyncedOpIds.length === 0) {\n\t\treturn emptyResult()\n\t}\n\tconst rebaseIds = new Set(unsyncedOpIds)\n\n\t// Read phase. A single full scan per collection serves two purposes at once:\n\t// locating the rebased rows and finding the max timestamp of everything else.\n\t// This avoids SQL IN-list size limits and keeps the logic trivially correct\n\t// (correctness over performance; the op log is compacted periodically anyway).\n\tconst rebased: Operation[] = []\n\t// Serialized HLC strings sort lexicographically in the same order as\n\t// HybridLogicalClock.compare, so a plain string max is a timestamp max.\n\tlet maxOtherSerializedTs: string | null = null\n\n\tfor (const collectionName of Object.keys(schema.collections)) {\n\t\tconst rows = await adapter.query<OperationRow>(`SELECT * FROM _kora_ops_${collectionName}`)\n\t\tfor (const row of rows) {\n\t\t\tif (rebaseIds.has(row.id)) {\n\t\t\t\trebased.push(deserializeOperationWithCollection(row, collectionName))\n\t\t\t} else if (maxOtherSerializedTs === null || row.timestamp > maxOtherSerializedTs) {\n\t\t\t\tmaxOtherSerializedTs = row.timestamp\n\t\t\t}\n\t\t}\n\t}\n\n\tif (rebased.length === 0) {\n\t\treturn emptyResult()\n\t}\n\n\t// The new wall time must sort after both corrected real time and every\n\t// operation that stays in the log, or the rebased ops could lose LWW\n\t// conflicts they previously won locally (silent data reordering).\n\tconst maxOtherWallTime =\n\t\tmaxOtherSerializedTs === null\n\t\t\t? Number.NEGATIVE_INFINITY\n\t\t\t: HybridLogicalClock.deserialize(maxOtherSerializedTs).wallTime\n\tconst baseWallTime = Math.max(correctedNowMs, maxOtherWallTime + 1)\n\n\t// Preserve the ORIGINAL total order so causal relationships (dep before\n\t// dependent) survive the re-stamp.\n\trebased.sort((a, b) => HybridLogicalClock.compare(a.timestamp, b.timestamp))\n\n\tconst newTimestamps: HLCTimestamp[] = rebased.map((op, i) => ({\n\t\t// Spill into wallTime past the 5-digit logical serialization limit so the\n\t\t// serialized order stays correct even for enormous offline queues.\n\t\twallTime: baseWallTime + Math.floor(i / LOGICAL_COUNTER_LIMIT),\n\t\tlogical: i % LOGICAL_COUNTER_LIMIT,\n\t\tnodeId: op.nodeId,\n\t}))\n\n\t// Recompute content-addressed ids first: the hash covers only\n\t// {type, collection, recordId, data, timestamp, nodeId} (+ atomicOps when\n\t// present), NOT causalDeps, so ids can be derived before dep remapping.\n\t// The deserialized `data` has the embedded metadata keys (transactionId,\n\t// mutationName, atomicOps) already stripped, matching exactly what the\n\t// original creation path hashed.\n\tconst idMapping: Record<string, string> = {}\n\tconst newIds: string[] = []\n\tfor (let i = 0; i < rebased.length; i++) {\n\t\tconst op = rebased[i]\n\t\tconst ts = newTimestamps[i]\n\t\tif (!op || !ts) {\n\t\t\tcontinue\n\t\t}\n\t\tconst input: OperationInput = {\n\t\t\tnodeId: op.nodeId,\n\t\t\ttype: op.type,\n\t\t\tcollection: op.collection,\n\t\t\trecordId: op.recordId,\n\t\t\tdata: op.data,\n\t\t\tpreviousData: op.previousData,\n\t\t\tsequenceNumber: op.sequenceNumber,\n\t\t\tcausalDeps: op.causalDeps,\n\t\t\tschemaVersion: op.schemaVersion,\n\t\t\t...(op.atomicOps !== undefined ? { atomicOps: op.atomicOps } : {}),\n\t\t}\n\t\tconst newId = await computeOperationId(input, HybridLogicalClock.serialize(ts))\n\t\tidMapping[op.id] = newId\n\t\tnewIds.push(newId)\n\t}\n\n\t// Remap causal deps among the rebased set; deps on non-rebased (already\n\t// acknowledged or foreign) operations keep their original ids.\n\tconst newOperations: Operation[] = []\n\tfor (let i = 0; i < rebased.length; i++) {\n\t\tconst op = rebased[i]\n\t\tconst ts = newTimestamps[i]\n\t\tconst newId = newIds[i]\n\t\tif (!op || !ts || newId === undefined) {\n\t\t\tcontinue\n\t\t}\n\t\tnewOperations.push({\n\t\t\t...op,\n\t\t\tid: newId,\n\t\t\ttimestamp: ts,\n\t\t\tcausalDeps: op.causalDeps.map((dep) => idMapping[dep] ?? dep),\n\t\t})\n\t}\n\n\t// Write phase: one transaction so a crash can never leave the log with a\n\t// mix of old and new stamps (which would corrupt causal deps).\n\tawait adapter.transaction(async (tx) => {\n\t\tfor (let i = 0; i < rebased.length; i++) {\n\t\t\tconst oldOp = rebased[i]\n\t\t\tconst newOp = newOperations[i]\n\t\t\tif (!oldOp || !newOp) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst opsTable = `_kora_ops_${oldOp.collection}`\n\t\t\tawait tx.execute(`DELETE FROM ${opsTable} WHERE id = ?`, [oldOp.id])\n\t\t\tconst opInsert = buildInsertQuery(\n\t\t\t\topsTable,\n\t\t\t\tserializeOperation(newOp) as unknown as Record<string, unknown>,\n\t\t\t)\n\t\t\tawait tx.execute(opInsert.sql, opInsert.params)\n\n\t\t\t// Only touch materialized rows whose current version stamp came from\n\t\t\t// this exact operation — a row last written by a different (newer,\n\t\t\t// non-rebased) op must keep its version, or LWW guards would lie.\n\t\t\tconst oldVersion = serializeRowVersion(oldOp.timestamp)\n\t\t\tconst newVersion = serializeRowVersion(newOp.timestamp)\n\t\t\tawait tx.execute(\n\t\t\t\t`UPDATE ${oldOp.collection} SET _version = ?, _updated_at = ? WHERE id = ? AND _version = ?`,\n\t\t\t\t[newVersion, newOp.timestamp.wallTime, oldOp.recordId, oldVersion],\n\t\t\t)\n\n\t\t\t// Per-field versions stamped by this operation carry the same old (pre-\n\t\t\t// rebase) version string, so re-stamp them too — otherwise field-level\n\t\t\t// LWW would keep comparing against the uncorrected timestamp forever.\n\t\t\tconst rows = await tx.query<RawCollectionRow>(\n\t\t\t\t`SELECT _field_versions FROM ${oldOp.collection} WHERE id = ?`,\n\t\t\t\t[oldOp.recordId],\n\t\t\t)\n\t\t\tconst fieldVersions = parseFieldVersions(rows[0]?._field_versions)\n\t\t\tlet changed = false\n\t\t\tfor (const [field, version] of Object.entries(fieldVersions)) {\n\t\t\t\tif (version === oldVersion) {\n\t\t\t\t\tfieldVersions[field] = newVersion\n\t\t\t\t\tchanged = true\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (changed) {\n\t\t\t\tawait tx.execute(`UPDATE ${oldOp.collection} SET _field_versions = ? WHERE id = ?`, [\n\t\t\t\t\tserializeFieldVersions(fieldVersions),\n\t\t\t\t\toldOp.recordId,\n\t\t\t\t])\n\t\t\t}\n\n\t\t\t// The insert op also stamped `_created_at` (the developer-visible\n\t\t\t// `createdAt`). Replicas materialize it from the rebased op's corrected\n\t\t\t// wallTime, so the originating device must re-stamp its own row too or\n\t\t\t// `createdAt` diverges forever after a clock rebase. Match on the old\n\t\t\t// (pre-rebase) created time so only rows this op created are touched.\n\t\t\tif (oldOp.type === 'insert') {\n\t\t\t\tawait tx.execute(\n\t\t\t\t\t`UPDATE ${oldOp.collection} SET _created_at = ? WHERE id = ? AND _created_at = ?`,\n\t\t\t\t\t[newOp.timestamp.wallTime, oldOp.recordId, oldOp.timestamp.wallTime],\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t\t// sequenceNumbers are intentionally unchanged, so `_kora_version_vector`\n\t\t// needs no update: the version vector tracks sequences, not timestamps.\n\t})\n\n\tconst newMaxTimestamp = newTimestamps[newTimestamps.length - 1] ?? null\n\n\treturn {\n\t\toperations: newOperations,\n\t\tidMapping,\n\t\trebasedCount: newOperations.length,\n\t\tnewMaxTimestamp,\n\t}\n}\n","import type {\n\tAtomicOp,\n\tCausalTracker,\n\tCollectionDefinition,\n\tHybridLogicalClock,\n\tOperation,\n\tSchemaDefinition,\n} from '@korajs/core'\nimport {\n\tcreateOperation,\n\tgenerateUUIDv7,\n\tisAtomicOp,\n\tresolveAtomicOp,\n\ttoAtomicOp,\n\tvalidateRecord,\n} from '@korajs/core'\nimport { RecordNotFoundError } from '../errors'\nimport { serializeRowVersion } from '../lww/row-version'\nimport { buildInsertQuery, buildSoftDeleteQuery, buildUpdateQuery } from '../query/sql-builder'\nimport type { RelationEnforcer } from '../relations/relation-enforcer'\nimport {\n\tdecodeRichtextFieldsFromOpData,\n\tencodeRichtextFieldsForOpData,\n} from '../serialization/op-data-encoding'\nimport { deserializeRecord, serializeOperation, serializeRecord } from '../serialization/serializer'\nimport type {\n\tCollectionRecord,\n\tLocalMutationHandler,\n\tRawCollectionRow,\n\tStorageAdapter,\n\tTransaction,\n} from '../types'\n\n/**\n * A buffered SQL command to be executed during commit.\n */\ninterface BufferedCommand {\n\tsql: string\n\tparams: unknown[]\n}\n\n/**\n * A buffered operation with its associated SQL commands.\n */\ninterface BufferedEntry {\n\toperation: Operation\n\tcommands: BufferedCommand[]\n\tcollection: string\n}\n\n/**\n * Internal configuration for creating a TransactionContext.\n * Passed from Store to avoid exposing Store internals publicly.\n */\nexport interface TransactionContextConfig {\n\tschema: SchemaDefinition\n\tadapter: StorageAdapter\n\tclock: HybridLogicalClock\n\tnodeId: string\n\tsequenceAllocator: import('./transaction-sequence').TransactionSequenceAllocator\n\trelationEnforcer: RelationEnforcer | null\n\tcausalTracker: CausalTracker | null\n\tlocalMutationHandler: LocalMutationHandler | null\n}\n\n/**\n * A collection accessor within a transaction.\n * Operations are buffered and committed atomically when the transaction completes.\n */\nexport interface TransactionCollectionAccessor {\n\tinsert(data: Record<string, unknown>): Promise<CollectionRecord>\n\tupdate(id: string, data: Record<string, unknown>): Promise<CollectionRecord>\n\tdelete(id: string): Promise<void>\n\tfindById(id: string): Promise<CollectionRecord | null>\n}\n\n/**\n * TransactionContext provides atomic multi-collection operations.\n *\n * All mutations are buffered and committed in a single StorageAdapter.transaction()\n * call. All operations share the same transactionId (UUID v7).\n *\n * Subscription notifications are deferred until after commit.\n *\n * @example\n * ```typescript\n * const { operations, affectedCollections } = await txContext.commit()\n * // Notify subscriptions after commit\n * for (const op of operations) {\n * subscriptionManager.notify(op.collection, op)\n * }\n * ```\n */\nexport class TransactionContext {\n\tprivate readonly transactionId: string\n\tprivate mutationName: string | undefined\n\tprivate readonly buffer: BufferedEntry[] = []\n\tprivate committed = false\n\tprivate rolledBack = false\n\tprivate readonly config: TransactionContextConfig\n\n\tconstructor(config: TransactionContextConfig) {\n\t\tthis.config = config\n\t\tthis.transactionId = generateUUIDv7()\n\t}\n\n\t/**\n\t * Set a human-readable mutation name for this transaction.\n\t * Propagated to all operations for DevTools display.\n\t */\n\tsetMutationName(name: string): void {\n\t\tthis.mutationName = name\n\t}\n\n\t/**\n\t * Get the mutation name, if set.\n\t */\n\tgetMutationName(): string | undefined {\n\t\treturn this.mutationName\n\t}\n\n\t/**\n\t * Get a collection accessor for buffered operations within this transaction.\n\t */\n\tcollection(name: string): TransactionCollectionAccessor {\n\t\tconst definition = this.config.schema.collections[name]\n\t\tif (!definition) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${name}\". Available: ${Object.keys(this.config.schema.collections).join(', ')}`,\n\t\t\t)\n\t\t}\n\n\t\treturn {\n\t\t\tinsert: (data: Record<string, unknown>) => this.insert(name, definition, data),\n\t\t\tupdate: (id: string, data: Record<string, unknown>) =>\n\t\t\t\tthis.update(name, definition, id, data),\n\t\t\tdelete: (id: string) => this.deleteRecord(name, definition, id),\n\t\t\tfindById: (id: string) => this.findById(name, definition, id),\n\t\t}\n\t}\n\n\t/**\n\t * Commit all buffered operations atomically.\n\t * Returns the list of operations and affected collections for subscription notification.\n\t */\n\tasync commit(): Promise<{ operations: Operation[]; affectedCollections: Set<string> }> {\n\t\tif (this.committed) {\n\t\t\tthrow new Error('Transaction already committed.')\n\t\t}\n\t\tif (this.rolledBack) {\n\t\t\tthrow new Error('Transaction was rolled back and cannot be committed.')\n\t\t}\n\n\t\tthis.committed = true\n\n\t\tif (this.buffer.length === 0) {\n\t\t\treturn { operations: [], affectedCollections: new Set() }\n\t\t}\n\n\t\tconst handler = this.config.localMutationHandler\n\t\tif (handler?.commitTransaction) {\n\t\t\treturn handler.commitTransaction({\n\t\t\t\tentries: this.buffer.map((entry) => ({\n\t\t\t\t\toperation: entry.operation,\n\t\t\t\t\tcommands: entry.commands,\n\t\t\t\t\tcollection: entry.collection,\n\t\t\t\t})),\n\t\t\t\ttransactionId: this.transactionId,\n\t\t\t\t...(this.mutationName !== undefined ? { mutationName: this.mutationName } : {}),\n\t\t\t})\n\t\t}\n\n\t\tconst operations: Operation[] = []\n\t\tconst affectedCollections = new Set<string>()\n\n\t\t// Execute all buffered commands in a single adapter transaction\n\t\tawait this.config.adapter.transaction(async (tx: Transaction) => {\n\t\t\tfor (const entry of this.buffer) {\n\t\t\t\tif (entry.operation.type === 'delete' && this.config.relationEnforcer) {\n\t\t\t\t\tconst cascadeResult = await this.config.relationEnforcer.enforceDelete(\n\t\t\t\t\t\tentry.collection,\n\t\t\t\t\t\tentry.operation.recordId,\n\t\t\t\t\t\ttx,\n\t\t\t\t\t\t[entry.operation.id],\n\t\t\t\t\t)\n\t\t\t\t\tfor (const cascadedOp of cascadeResult.operations) {\n\t\t\t\t\t\toperations.push(cascadedOp)\n\t\t\t\t\t\taffectedCollections.add(cascadedOp.collection)\n\t\t\t\t\t\tthis.config.causalTracker?.afterOperation(cascadedOp.collection, cascadedOp.id, true)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (const cmd of entry.commands) {\n\t\t\t\t\tawait tx.execute(cmd.sql, cmd.params)\n\t\t\t\t}\n\t\t\t\toperations.push(entry.operation)\n\t\t\t\taffectedCollections.add(entry.collection)\n\t\t\t}\n\n\t\t\tconst finalSeq = this.config.sequenceAllocator.getHighWaterMark()\n\t\t\tif (finalSeq > 0) {\n\t\t\t\tawait tx.execute(\n\t\t\t\t\t'INSERT OR REPLACE INTO _kora_version_vector (node_id, sequence_number) VALUES (?, ?)',\n\t\t\t\t\t[this.config.nodeId, finalSeq],\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\n\t\treturn { operations, affectedCollections }\n\t}\n\n\t/**\n\t * Mark the transaction as rolled back. No operations will be committed.\n\t */\n\trollback(): void {\n\t\tthis.rolledBack = true\n\t\tthis.buffer.length = 0\n\t}\n\n\t/**\n\t * Get the transaction ID shared by all operations in this transaction.\n\t */\n\tgetTransactionId(): string {\n\t\treturn this.transactionId\n\t}\n\n\tprivate ensureActive(): void {\n\t\tif (this.committed) {\n\t\t\tthrow new Error('Cannot perform operations on a committed transaction.')\n\t\t}\n\t\tif (this.rolledBack) {\n\t\t\tthrow new Error('Cannot perform operations on a rolled-back transaction.')\n\t\t}\n\t}\n\n\tprivate async insert(\n\t\tcollectionName: string,\n\t\tdefinition: CollectionDefinition,\n\t\tdata: Record<string, unknown>,\n\t): Promise<CollectionRecord> {\n\t\tthis.ensureActive()\n\n\t\tconst validated = validateRecord(collectionName, definition, data, 'insert')\n\t\tconst recordId = generateUUIDv7()\n\t\tconst now = Date.now()\n\n\t\t// Set auto timestamp fields\n\t\tfor (const [fieldName, descriptor] of Object.entries(definition.fields)) {\n\t\t\tif (descriptor.auto && descriptor.kind === 'timestamp') {\n\t\t\t\tvalidated[fieldName] = now\n\t\t\t}\n\t\t}\n\n\t\tconst sequenceNumber = await this.config.sequenceAllocator.allocate()\n\t\tconst causalDeps = this.config.causalTracker?.nextCausalDeps(collectionName, true) ?? []\n\t\tconst operation = await createOperation(\n\t\t\t{\n\t\t\t\tnodeId: this.config.nodeId,\n\t\t\t\ttype: 'insert',\n\t\t\t\tcollection: collectionName,\n\t\t\t\trecordId,\n\t\t\t\t// Binary richtext values are tagged as canonical JSON before the\n\t\t\t\t// operation is content-hashed (see encodeRichtextFieldsForOpData).\n\t\t\t\tdata: encodeRichtextFieldsForOpData(validated, definition.fields),\n\t\t\t\tpreviousData: null,\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps,\n\t\t\t\tschemaVersion: this.config.schema.version,\n\t\t\t\ttransactionId: this.transactionId,\n\t\t\t\t...(this.mutationName !== undefined ? { mutationName: this.mutationName } : {}),\n\t\t\t},\n\t\t\tthis.config.clock,\n\t\t)\n\t\tthis.config.causalTracker?.afterOperation(collectionName, operation.id, true)\n\n\t\tconst serializedData = serializeRecord(validated, definition.fields)\n\t\tconst version = serializeRowVersion(operation.timestamp)\n\t\tconst record: Record<string, unknown> = {\n\t\t\tid: recordId,\n\t\t\t...serializedData,\n\t\t\t_created_at: operation.timestamp.wallTime,\n\t\t\t_updated_at: operation.timestamp.wallTime,\n\t\t\t_version: version,\n\t\t}\n\n\t\tconst insertQuery = buildInsertQuery(collectionName, record)\n\t\tconst opRow = serializeOperation(operation)\n\t\tconst opInsert = buildInsertQuery(\n\t\t\t`_kora_ops_${collectionName}`,\n\t\t\topRow as unknown as Record<string, unknown>,\n\t\t)\n\n\t\tthis.buffer.push({\n\t\t\toperation,\n\t\t\tcollection: collectionName,\n\t\t\tcommands: [\n\t\t\t\t{ sql: insertQuery.sql, params: insertQuery.params },\n\t\t\t\t{ sql: opInsert.sql, params: opInsert.params },\n\t\t\t],\n\t\t})\n\n\t\treturn {\n\t\t\tid: recordId,\n\t\t\t...validated,\n\t\t\tcreatedAt: now,\n\t\t\tupdatedAt: now,\n\t\t}\n\t}\n\n\tprivate async update(\n\t\tcollectionName: string,\n\t\tdefinition: CollectionDefinition,\n\t\tid: string,\n\t\tdata: Record<string, unknown>,\n\t): Promise<CollectionRecord> {\n\t\tthis.ensureActive()\n\n\t\t// Check for buffered inserts/updates for this record to get current state\n\t\tconst currentRecord = await this.getEffectiveRecord(collectionName, definition, id)\n\t\tif (!currentRecord) {\n\t\t\tthrow new RecordNotFoundError(collectionName, id)\n\t\t}\n\n\t\tconst validated = validateRecord(collectionName, definition, data, 'update')\n\t\tconst now = Date.now()\n\n\t\tconst previousData: Record<string, unknown> = {}\n\t\tconst resolvedData: Record<string, unknown> = {}\n\t\tconst atomicOps: Record<string, AtomicOp> = {}\n\n\t\tfor (const key of Object.keys(validated)) {\n\t\t\tconst value = validated[key]\n\t\t\tpreviousData[key] = currentRecord[key]\n\n\t\t\tif (isAtomicOp(value)) {\n\t\t\t\tresolvedData[key] = resolveAtomicOp(currentRecord[key], value)\n\t\t\t\tatomicOps[key] = toAtomicOp(value)\n\t\t\t} else {\n\t\t\t\tresolvedData[key] = value\n\t\t\t}\n\t\t}\n\n\t\tconst hasAtomicOps = Object.keys(atomicOps).length > 0\n\n\t\tconst sequenceNumber = await this.config.sequenceAllocator.allocate()\n\t\tconst causalDeps = this.config.causalTracker?.nextCausalDeps(collectionName, true) ?? []\n\t\tconst operation = await createOperation(\n\t\t\t{\n\t\t\t\tnodeId: this.config.nodeId,\n\t\t\t\ttype: 'update',\n\t\t\t\tcollection: collectionName,\n\t\t\t\trecordId: id,\n\t\t\t\t// Binary richtext values (new and previous) are tagged as canonical\n\t\t\t\t// JSON before the operation is content-hashed.\n\t\t\t\tdata: encodeRichtextFieldsForOpData(resolvedData, definition.fields),\n\t\t\t\tpreviousData: encodeRichtextFieldsForOpData(previousData, definition.fields),\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps,\n\t\t\t\tschemaVersion: this.config.schema.version,\n\t\t\t\ttransactionId: this.transactionId,\n\t\t\t\t...(this.mutationName !== undefined ? { mutationName: this.mutationName } : {}),\n\t\t\t\t...(hasAtomicOps ? { atomicOps } : {}),\n\t\t\t},\n\t\t\tthis.config.clock,\n\t\t)\n\t\tthis.config.causalTracker?.afterOperation(collectionName, operation.id, true)\n\n\t\tconst serializedChanges = serializeRecord(resolvedData, definition.fields)\n\t\tconst version = serializeRowVersion(operation.timestamp)\n\t\tconst updateQuery = buildUpdateQuery(collectionName, id, {\n\t\t\t...serializedChanges,\n\t\t\t_updated_at: operation.timestamp.wallTime,\n\t\t\t_version: version,\n\t\t})\n\t\tconst opRow = serializeOperation(operation)\n\t\tconst opInsert = buildInsertQuery(\n\t\t\t`_kora_ops_${collectionName}`,\n\t\t\topRow as unknown as Record<string, unknown>,\n\t\t)\n\n\t\tthis.buffer.push({\n\t\t\toperation,\n\t\t\tcollection: collectionName,\n\t\t\tcommands: [\n\t\t\t\t{ sql: updateQuery.sql, params: updateQuery.params },\n\t\t\t\t{ sql: opInsert.sql, params: opInsert.params },\n\t\t\t],\n\t\t})\n\n\t\t// Merge current record with resolved changes for return value\n\t\treturn {\n\t\t\t...currentRecord,\n\t\t\t...resolvedData,\n\t\t\tupdatedAt: now,\n\t\t} as CollectionRecord\n\t}\n\n\tprivate async deleteRecord(\n\t\tcollectionName: string,\n\t\tdefinition: CollectionDefinition,\n\t\tid: string,\n\t): Promise<void> {\n\t\tthis.ensureActive()\n\n\t\tconst currentRecord = await this.getEffectiveRecord(collectionName, definition, id)\n\t\tif (!currentRecord) {\n\t\t\tthrow new RecordNotFoundError(collectionName, id)\n\t\t}\n\n\t\tconst now = Date.now()\n\t\tconst sequenceNumber = await this.config.sequenceAllocator.allocate()\n\t\tconst causalDeps = this.config.causalTracker?.nextCausalDeps(collectionName, true) ?? []\n\t\tconst operation = await createOperation(\n\t\t\t{\n\t\t\t\tnodeId: this.config.nodeId,\n\t\t\t\ttype: 'delete',\n\t\t\t\tcollection: collectionName,\n\t\t\t\trecordId: id,\n\t\t\t\tdata: null,\n\t\t\t\tpreviousData: null,\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps,\n\t\t\t\tschemaVersion: this.config.schema.version,\n\t\t\t\ttransactionId: this.transactionId,\n\t\t\t\t...(this.mutationName !== undefined ? { mutationName: this.mutationName } : {}),\n\t\t\t},\n\t\t\tthis.config.clock,\n\t\t)\n\t\tthis.config.causalTracker?.afterOperation(collectionName, operation.id, true)\n\n\t\tconst deleteQuery = buildSoftDeleteQuery(collectionName, id, now)\n\t\tconst opRow = serializeOperation(operation)\n\t\tconst opInsert = buildInsertQuery(\n\t\t\t`_kora_ops_${collectionName}`,\n\t\t\topRow as unknown as Record<string, unknown>,\n\t\t)\n\n\t\tthis.buffer.push({\n\t\t\toperation,\n\t\t\tcollection: collectionName,\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],\n\t\t})\n\t}\n\n\tprivate async findById(\n\t\tcollectionName: string,\n\t\tdefinition: CollectionDefinition,\n\t\tid: string,\n\t): Promise<CollectionRecord | null> {\n\t\treturn this.getEffectiveRecord(collectionName, definition, id)\n\t}\n\n\t/**\n\t * Get the effective state of a record, considering both the database and buffered operations.\n\t * Buffered inserts/updates take precedence over the database state.\n\t */\n\tprivate async getEffectiveRecord(\n\t\tcollectionName: string,\n\t\tdefinition: CollectionDefinition,\n\t\tid: string,\n\t): Promise<CollectionRecord | null> {\n\t\t// Check if there's a buffered delete for this record (scan from newest to oldest)\n\t\tfor (let i = this.buffer.length - 1; i >= 0; i--) {\n\t\t\tconst entry = this.buffer[i] as BufferedEntry\n\t\t\tif (entry.collection === collectionName && entry.operation.recordId === id) {\n\t\t\t\tif (entry.operation.type === 'delete') {\n\t\t\t\t\treturn null\n\t\t\t\t}\n\t\t\t\t// For buffered inserts/updates, reconstruct the record from the database + buffered changes\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// Read from database first\n\t\tconst rows = await this.config.adapter.query<RawCollectionRow>(\n\t\t\t`SELECT * FROM ${collectionName} WHERE id = ? AND _deleted = 0`,\n\t\t\t[id],\n\t\t)\n\n\t\tlet record: CollectionRecord | null = rows[0]\n\t\t\t? deserializeRecord(rows[0], definition.fields)\n\t\t\t: null\n\n\t\t// Apply buffered operations on top\n\t\tfor (const entry of this.buffer) {\n\t\t\tif (entry.collection !== collectionName || entry.operation.recordId !== id) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (entry.operation.type === 'insert' && entry.operation.data) {\n\t\t\t\trecord = {\n\t\t\t\t\tid,\n\t\t\t\t\t// op.data stores binary richtext as tagged JSON; the effective\n\t\t\t\t\t// record must expose record-shaped values (Uint8Array/string).\n\t\t\t\t\t...decodeRichtextFieldsFromOpData(entry.operation.data, definition.fields),\n\t\t\t\t\tcreatedAt: entry.operation.timestamp.wallTime,\n\t\t\t\t\tupdatedAt: entry.operation.timestamp.wallTime,\n\t\t\t\t}\n\t\t\t} else if (entry.operation.type === 'update' && entry.operation.data && record) {\n\t\t\t\trecord = {\n\t\t\t\t\t...record,\n\t\t\t\t\t...decodeRichtextFieldsFromOpData(entry.operation.data, definition.fields),\n\t\t\t\t\tupdatedAt: entry.operation.timestamp.wallTime,\n\t\t\t\t}\n\t\t\t} else if (entry.operation.type === 'delete') {\n\t\t\t\trecord = null\n\t\t\t}\n\t\t}\n\n\t\treturn record\n\t}\n}\n","import { readSequenceNumber } from '../store/sequence-allocator'\nimport type { StorageAdapter } from '../types'\n\n/**\n * Allocates monotonic sequence numbers for a single open transaction.\n * Loads the current DB watermark once, then increments in memory until commit.\n */\nexport class TransactionSequenceAllocator {\n\tprivate loaded = false\n\tprivate watermark = 0\n\n\tconstructor(\n\t\tprivate readonly adapter: StorageAdapter,\n\t\tprivate readonly nodeId: string,\n\t) {}\n\n\tasync allocate(): Promise<number> {\n\t\tif (!this.loaded) {\n\t\t\tthis.watermark = await readSequenceNumber(this.adapter, this.nodeId)\n\t\t\tthis.loaded = true\n\t\t}\n\t\tthis.watermark++\n\t\treturn this.watermark\n\t}\n\n\tgetHighWaterMark(): number {\n\t\treturn this.watermark\n\t}\n}\n","import { generateUUIDv7 } from '@korajs/core'\n\nexport type StoreIsolation = 'shared' | 'per-tab'\n\nfunction perTabStorageKey(dbName: string): string {\n\treturn `kora-tab-node-${dbName}`\n}\n\n/**\n * Load a per-tab node id from sessionStorage (browser only).\n */\nexport function loadPerTabNodeId(dbName: string): string | null {\n\tif (typeof sessionStorage === 'undefined') {\n\t\treturn null\n\t}\n\treturn sessionStorage.getItem(perTabStorageKey(dbName))\n}\n\n/**\n * Persist a per-tab node id for this browser tab.\n */\nexport function savePerTabNodeId(dbName: string, nodeId: string): void {\n\tif (typeof sessionStorage === 'undefined') {\n\t\treturn\n\t}\n\tsessionStorage.setItem(perTabStorageKey(dbName), nodeId)\n}\n\n/**\n * Resolve or create a node id for `per-tab` isolation.\n */\nexport function resolvePerTabNodeId(dbName: string): string {\n\tconst existing = loadPerTabNodeId(dbName)\n\tif (existing) {\n\t\treturn existing\n\t}\n\tconst nodeId = generateUUIDv7()\n\tsavePerTabNodeId(dbName, nodeId)\n\treturn nodeId\n}\n","import type { QueryBuilder } from '../query/query-builder'\nimport type { CollectionRecord } from '../types'\n\n/**\n * Frozen empty array returned as the initial snapshot before any data loads.\n * Same reference every time prevents infinite update loops in UI bindings.\n */\nconst EMPTY_ARRAY: readonly unknown[] = Object.freeze([])\n\n/**\n * Bridges the async QueryBuilder.subscribe() API with synchronous snapshot reads\n * required by React useSyncExternalStore, Vue composables, and Svelte stores.\n *\n * Uses lazy subscription: the underlying query subscription starts when the first\n * listener attaches and stops when the last listener detaches.\n */\nexport class QueryStore<T = CollectionRecord> {\n\tprivate snapshot: readonly T[] = EMPTY_ARRAY as readonly T[]\n\tprivate listeners = new Set<() => void>()\n\tprivate unsubscribeQuery: (() => void) | null = null\n\tprivate active = false\n\tprivate readonly queryBuilder: QueryBuilder<T>\n\n\tconstructor(queryBuilder: QueryBuilder<T>) {\n\t\tthis.queryBuilder = queryBuilder\n\t}\n\n\t/**\n\t * Subscribe to snapshot changes.\n\t *\n\t * @returns Unsubscribe function\n\t */\n\tsubscribe = (onStoreChange: () => void): (() => void) => {\n\t\tthis.listeners.add(onStoreChange)\n\n\t\tif (!this.active) {\n\t\t\tthis.startSubscription()\n\t\t}\n\n\t\treturn () => {\n\t\t\tthis.listeners.delete(onStoreChange)\n\t\t\tif (this.listeners.size === 0) {\n\t\t\t\tthis.stopSubscription()\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Synchronous read of the latest query results. */\n\tgetSnapshot = (): readonly T[] => {\n\t\treturn this.snapshot\n\t}\n\n\t/** Tear down listeners and the underlying query subscription. */\n\tdestroy(): void {\n\t\tthis.stopSubscription()\n\t\tthis.listeners.clear()\n\t\tthis.snapshot = EMPTY_ARRAY as readonly T[]\n\t}\n\n\tprivate startSubscription(): void {\n\t\tthis.active = true\n\t\tthis.unsubscribeQuery = this.queryBuilder.subscribe((results: readonly T[]) => {\n\t\t\tif (!this.active) return\n\t\t\tthis.snapshot = Object.freeze([...results])\n\t\t\tthis.notifyListeners()\n\t\t})\n\t}\n\n\tprivate stopSubscription(): void {\n\t\tthis.active = false\n\t\tif (this.unsubscribeQuery) {\n\t\t\tthis.unsubscribeQuery()\n\t\t\tthis.unsubscribeQuery = null\n\t\t}\n\t}\n\n\tprivate notifyListeners(): void {\n\t\tfor (const listener of this.listeners) {\n\t\t\tlistener()\n\t\t}\n\t}\n}\n","import { AppNotReadyError } from '@korajs/core'\nimport type { QueryBuilder } from '../query/query-builder'\n\nconst LEGACY_PENDING_COLLECTION = '__pending__'\n\n/**\n * Ensures a query builder is backed by an open store (not a legacy pending placeholder).\n */\nexport function assertQueryReady(query: QueryBuilder<unknown>): void {\n\tconst descriptor = query.getDescriptor()\n\tif (descriptor.collection === LEGACY_PENDING_COLLECTION) {\n\t\tthrow new AppNotReadyError(\n\t\t\t'Cannot use useQuery() before app.ready. Await app.ready or wrap your UI in <KoraProvider app={app}>.',\n\t\t)\n\t}\n}\n","import type { QueryBuilder } from '../query/query-builder'\nimport type { CollectionRecord } from '../types'\nimport { QueryStore } from './query-store'\n\ninterface CacheEntry {\n\tqueryStore: QueryStore<CollectionRecord>\n\trefCount: number\n}\n\n/**\n * Reference-counted cache of {@link QueryStore} instances keyed by query descriptor.\n * Identical queries from different components share one underlying subscription.\n */\nexport class QueryStoreCache {\n\tprivate entries = new Map<string, CacheEntry>()\n\n\tconstructor(private readonly scopeKey = 'default') {}\n\n\tgetOrCreate<T>(queryBuilder: QueryBuilder<T>): QueryStore<T> {\n\t\tconst key = this.getKey(queryBuilder)\n\t\tconst existing = this.entries.get(key)\n\n\t\tif (existing) {\n\t\t\texisting.refCount++\n\t\t\treturn existing.queryStore as QueryStore<T>\n\t\t}\n\n\t\tconst queryStore = new QueryStore<T>(queryBuilder)\n\t\tthis.entries.set(key, {\n\t\t\tqueryStore: queryStore as QueryStore<CollectionRecord>,\n\t\t\trefCount: 1,\n\t\t})\n\t\treturn queryStore\n\t}\n\n\trelease(queryBuilder: QueryBuilder<unknown>): void {\n\t\tconst key = this.getKey(queryBuilder)\n\t\tconst entry = this.entries.get(key)\n\t\tif (!entry) {\n\t\t\treturn\n\t\t}\n\n\t\tentry.refCount--\n\t\tif (entry.refCount <= 0) {\n\t\t\tentry.queryStore.destroy()\n\t\t\tthis.entries.delete(key)\n\t\t}\n\t}\n\n\tclear(): void {\n\t\tfor (const entry of this.entries.values()) {\n\t\t\tentry.queryStore.destroy()\n\t\t}\n\t\tthis.entries.clear()\n\t}\n\n\tget size(): number {\n\t\treturn this.entries.size\n\t}\n\n\tprivate getKey(queryBuilder: QueryBuilder<unknown>): string {\n\t\treturn `${this.scopeKey}:${JSON.stringify(queryBuilder.getDescriptor())}`\n\t}\n}\n\nlet sharedCache: QueryStoreCache | null = null\n\n/**\n * Process-wide shared query store cache for framework bindings.\n *\n * @deprecated Prefer {@link KoraApp.getQueryStoreCache} via `KoraProvider` context\n * so each app instance owns an isolated cache.\n */\nexport function getSharedQueryStoreCache(): QueryStoreCache {\n\tif (!sharedCache) {\n\t\tsharedCache = new QueryStoreCache()\n\t}\n\treturn sharedCache\n}\n","import * as Y from 'yjs'\nimport { encodeRichtext } from '../serialization/richtext-serializer'\nimport type {\n\tCreateRichTextControllerOptions,\n\tRichTextAwarenessState,\n\tRichTextAwarenessUser,\n\tRichTextController,\n\tRichTextControllerSnapshot,\n\tRichTextCursorInfo,\n} from './types'\n\nconst LOAD_ORIGIN = 'kora-load'\nconst REMOTE_ORIGIN = 'kora-remote'\nconst DOC_CHANNEL_ORIGIN = 'kora-doc-channel'\nconst TEXT_KEY = 'content'\nconst COMPACT_AFTER_DELTAS = 20\nconst PERSIST_DEBOUNCE_MS = 400\n\n/**\n * Framework-agnostic richtext binding: Yjs document lifecycle, persistence,\n * incremental doc channel, and awareness cursors.\n */\nexport function createRichTextController(\n\toptions: CreateRichTextControllerOptions,\n): RichTextController {\n\tconst {\n\t\tcollection,\n\t\tcollectionName,\n\t\trecordId,\n\t\tfieldName,\n\t\tstore,\n\t\tsyncEngine = null,\n\t\tuseDocChannel,\n\t} = options\n\n\tconst doc = new Y.Doc()\n\tconst text = doc.getText(TEXT_KEY)\n\tconst undoManager = new Y.UndoManager(text)\n\n\tlet user = options.user\n\tlet disposed = false\n\tlet ready = false\n\tlet error: Error | null = null\n\tlet canUndo = false\n\tlet canRedo = false\n\tlet cursors: RichTextCursorInfo[] = []\n\n\tconst listeners = new Set<() => void>()\n\tlet snapshot: RichTextControllerSnapshot = {\n\t\tready: false,\n\t\terror: null,\n\t\tcanUndo: false,\n\t\tcanRedo: false,\n\t\tcursors: [],\n\t}\n\tconst baseUpdateRef = { current: null as Uint8Array | null }\n\tconst pendingDeltasRef = { current: [] as Uint8Array[] }\n\tconst docChannelActiveRef = { current: false }\n\tlet persistTimer: ReturnType<typeof setTimeout> | null = null\n\n\tlet recordUnsubscribe: (() => void) | null = null\n\tlet docChannelUnsubscribe: (() => void) | null = null\n\tlet awarenessUnsubscribe: (() => void) | null = null\n\n\tconst refreshSnapshot = (): void => {\n\t\tsnapshot = {\n\t\t\tready,\n\t\t\terror,\n\t\t\tcanUndo,\n\t\t\tcanRedo,\n\t\t\tcursors: [...cursors],\n\t\t}\n\t}\n\n\tconst notify = (): void => {\n\t\trefreshSnapshot()\n\t\tfor (const listener of listeners) {\n\t\t\tlistener()\n\t\t}\n\t}\n\n\tconst syncHistoryState = (): void => {\n\t\tcanUndo = undoManager.undoStack.length > 0\n\t\tcanRedo = undoManager.redoStack.length > 0\n\t\tnotify()\n\t}\n\n\tconst getSnapshot = (): RichTextControllerSnapshot => snapshot\n\n\tconst resolveAwarenessUser = (): RichTextAwarenessUser => {\n\t\tif (user) {\n\t\t\treturn user\n\t\t}\n\t\tif (syncEngine) {\n\t\t\tconst existing = syncEngine.getAwarenessManager().getLocalState()?.user\n\t\t\tif (existing) {\n\t\t\t\treturn existing\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tname: 'Anonymous',\n\t\t\tcolor: '#6366f1',\n\t\t}\n\t}\n\n\tconst setCursor = (anchor: number, head: number): void => {\n\t\tif (!syncEngine) {\n\t\t\treturn\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tconst state: RichTextAwarenessState = {\n\t\t\tuser: resolveAwarenessUser(),\n\t\t\tcursor: {\n\t\t\t\tcollection: collectionName,\n\t\t\t\trecordId,\n\t\t\t\tfield: fieldName,\n\t\t\t\tanchor,\n\t\t\t\thead,\n\t\t\t},\n\t\t}\n\t\tawareness.setLocalState(state)\n\t}\n\n\tconst clearCursor = (): void => {\n\t\tif (!syncEngine) {\n\t\t\treturn\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tconst current = awareness.getLocalState()\n\t\tif (!current?.cursor) {\n\t\t\treturn\n\t\t}\n\t\tif (\n\t\t\tcurrent.cursor.collection !== collectionName ||\n\t\t\tcurrent.cursor.recordId !== recordId ||\n\t\t\tcurrent.cursor.field !== fieldName\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tawareness.setLocalState({ user: current.user })\n\t}\n\n\tconst applyRemoteSnapshot = (value: unknown): void => {\n\t\tconst encoded = encodeRichtextInput(value)\n\t\tif (!encoded) {\n\t\t\treturn\n\t\t}\n\n\t\tconst currentSnapshot = Y.encodeStateAsUpdate(doc)\n\t\tif (updatesEqual(currentSnapshot, encoded)) {\n\t\t\treturn\n\t\t}\n\n\t\tY.applyUpdate(doc, encoded, REMOTE_ORIGIN)\n\t\tbaseUpdateRef.current = encoded\n\t\tpendingDeltasRef.current = []\n\t\tsyncHistoryState()\n\t}\n\n\tconst flushPersist = async (): Promise<void> => {\n\t\tconst snapshot = composeRichtextSnapshot(baseUpdateRef.current, pendingDeltasRef.current)\n\t\tif (pendingDeltasRef.current.length >= COMPACT_AFTER_DELTAS) {\n\t\t\tbaseUpdateRef.current = snapshot\n\t\t\tpendingDeltasRef.current = []\n\t\t}\n\n\t\ttry {\n\t\t\tawait collection.update(recordId, {\n\t\t\t\t[fieldName]: snapshot,\n\t\t\t})\n\t\t} catch (cause) {\n\t\t\tif (!disposed) {\n\t\t\t\terror = cause instanceof Error ? cause : new Error(String(cause))\n\t\t\t\tnotify()\n\t\t\t}\n\t\t}\n\t}\n\n\tconst schedulePersist = (): void => {\n\t\tif (persistTimer) {\n\t\t\tclearTimeout(persistTimer)\n\t\t}\n\t\tpersistTimer = setTimeout(() => {\n\t\t\tpersistTimer = null\n\t\t\tvoid flushPersist()\n\t\t}, PERSIST_DEBOUNCE_MS)\n\t}\n\n\tconst onDocUpdate = (update: Uint8Array, origin: unknown): void => {\n\t\tsyncHistoryState()\n\t\tif (origin === LOAD_ORIGIN || origin === REMOTE_ORIGIN || origin === DOC_CHANNEL_ORIGIN) {\n\t\t\treturn\n\t\t}\n\n\t\tpendingDeltasRef.current.push(update)\n\n\t\tif (docChannelActiveRef.current && syncEngine) {\n\t\t\tsyncEngine.getRichtextDocChannel?.().send(collectionName, recordId, fieldName, update)\n\t\t\tschedulePersist()\n\t\t\treturn\n\t\t}\n\n\t\tvoid flushPersist()\n\t}\n\n\tconst subscribeRecordChanges = (): void => {\n\t\trecordUnsubscribe?.()\n\t\trecordUnsubscribe = store\n\t\t\t.collection(collectionName)\n\t\t\t.where({ id: recordId })\n\t\t\t.subscribe((results) => {\n\t\t\t\tconst record = results[0]\n\t\t\t\tif (!record) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tapplyRemoteSnapshot(record[fieldName])\n\t\t\t})\n\t}\n\n\tconst subscribeDocChannel = (): void => {\n\t\tdocChannelUnsubscribe?.()\n\t\tif (!ready || !syncEngine || !docChannelActiveRef.current) {\n\t\t\treturn\n\t\t}\n\n\t\tconst channel = syncEngine.getRichtextDocChannel?.()\n\t\tif (!channel) {\n\t\t\treturn\n\t\t}\n\n\t\tdocChannelUnsubscribe = channel.subscribe(collectionName, recordId, fieldName, (update) => {\n\t\t\tY.applyUpdate(doc, update, DOC_CHANNEL_ORIGIN)\n\t\t\tsyncHistoryState()\n\t\t})\n\t}\n\n\tconst updateCursors = (): void => {\n\t\tif (!syncEngine) {\n\t\t\tcursors = []\n\t\t\tnotify()\n\t\t\treturn\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tconst localClientId = awareness.clientId\n\t\tconst states = awareness.getStates()\n\t\tconst fieldCursors: RichTextCursorInfo[] = []\n\n\t\tfor (const [clientId, state] of states) {\n\t\t\tif (clientId === localClientId) continue\n\t\t\tif (!state.cursor) continue\n\t\t\tif (\n\t\t\t\tstate.cursor.collection !== collectionName ||\n\t\t\t\tstate.cursor.recordId !== recordId ||\n\t\t\t\tstate.cursor.field !== fieldName\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfieldCursors.push({\n\t\t\t\tclientId,\n\t\t\t\tuserName: state.user.name,\n\t\t\t\tcolor: state.user.color,\n\t\t\t\tanchor: state.cursor.anchor,\n\t\t\t\thead: state.cursor.head,\n\t\t\t})\n\t\t}\n\n\t\tcursors = fieldCursors\n\t\tnotify()\n\t}\n\n\tconst subscribeAwareness = (): void => {\n\t\tawarenessUnsubscribe?.()\n\t\tif (!syncEngine) {\n\t\t\tcursors = []\n\t\t\tnotify()\n\t\t\treturn\n\t\t}\n\n\t\tconst awareness = syncEngine.getAwarenessManager()\n\t\tawarenessUnsubscribe = awareness.on('change', () => {\n\t\t\tupdateCursors()\n\t\t})\n\t\tupdateCursors()\n\t}\n\n\tconst initialize = async (): Promise<void> => {\n\t\tready = false\n\t\terror = null\n\t\tnotify()\n\n\t\ttry {\n\t\t\tconst record = await collection.findById(recordId)\n\t\t\tif (disposed) return\n\n\t\t\tdoc.transact(() => {\n\t\t\t\tconst target = doc.getText(TEXT_KEY)\n\t\t\t\ttarget.delete(0, target.length)\n\t\t\t}, LOAD_ORIGIN)\n\n\t\t\tconst encoded = encodeRichtextInput(record?.[fieldName])\n\t\t\tbaseUpdateRef.current = encoded\n\t\t\tpendingDeltasRef.current = []\n\t\t\tif (encoded) {\n\t\t\t\tY.applyUpdate(doc, encoded, LOAD_ORIGIN)\n\t\t\t}\n\n\t\t\tconst channel = syncEngine?.getRichtextDocChannel?.()\n\t\t\tdocChannelActiveRef.current =\n\t\t\t\tchannel?.shouldUseChannel(encoded?.length ?? 0, useDocChannel) ?? false\n\n\t\t\tready = true\n\t\t\tsyncHistoryState()\n\t\t\tsubscribeRecordChanges()\n\t\t\tsubscribeDocChannel()\n\t\t\tsubscribeAwareness()\n\t\t\tnotify()\n\t\t} catch (cause) {\n\t\t\tif (disposed) return\n\t\t\terror = cause instanceof Error ? cause : new Error(String(cause))\n\t\t\tnotify()\n\t\t}\n\t}\n\n\tdoc.on('update', onDocUpdate)\n\tvoid initialize()\n\n\treturn {\n\t\tdoc,\n\t\ttext,\n\t\tgetSnapshot,\n\t\tsubscribe(listener) {\n\t\t\tlisteners.add(listener)\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener)\n\t\t\t}\n\t\t},\n\t\tundo() {\n\t\t\tundoManager.undo()\n\t\t\tsyncHistoryState()\n\t\t},\n\t\tredo() {\n\t\t\tundoManager.redo()\n\t\t\tsyncHistoryState()\n\t\t},\n\t\tsetCursor,\n\t\tclearCursor,\n\t\tsetUser(nextUser: RichTextAwarenessUser | undefined) {\n\t\t\tuser = nextUser\n\t\t},\n\t\tdestroy() {\n\t\t\tif (disposed) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tdisposed = true\n\t\t\tif (persistTimer) {\n\t\t\t\tclearTimeout(persistTimer)\n\t\t\t\tpersistTimer = null\n\t\t\t}\n\t\t\tdoc.off('update', onDocUpdate)\n\t\t\trecordUnsubscribe?.()\n\t\t\tdocChannelUnsubscribe?.()\n\t\t\tawarenessUnsubscribe?.()\n\t\t\tclearCursor()\n\t\t\tundoManager.destroy()\n\t\t\tbaseUpdateRef.current = null\n\t\t\tpendingDeltasRef.current = []\n\t\t\tdocChannelActiveRef.current = false\n\t\t\tlisteners.clear()\n\t\t},\n\t}\n}\n\nfunction encodeRichtextInput(value: unknown): Uint8Array | null {\n\tif (value === null || value === undefined) {\n\t\treturn null\n\t}\n\n\ttry {\n\t\treturn encodeRichtext(value as Parameters<typeof encodeRichtext>[0])\n\t} catch {\n\t\tif (typeof value === 'string') {\n\t\t\tconst fallbackDoc = new Y.Doc()\n\t\t\tfallbackDoc.getText(TEXT_KEY).insert(0, value)\n\t\t\treturn Y.encodeStateAsUpdate(fallbackDoc)\n\t\t}\n\t\tthrow new Error('Richtext record value must be a string, Uint8Array, ArrayBuffer, or null.')\n\t}\n}\n\nfunction composeRichtextSnapshot(base: Uint8Array | null, deltas: Uint8Array[]): Uint8Array {\n\tconst mergedDoc = new Y.Doc()\n\tif (base) {\n\t\tY.applyUpdate(mergedDoc, base)\n\t}\n\n\tfor (const delta of deltas) {\n\t\tY.applyUpdate(mergedDoc, delta)\n\t}\n\n\treturn Y.encodeStateAsUpdate(mergedDoc)\n}\n\nfunction updatesEqual(left: Uint8Array, right: Uint8Array): boolean {\n\tif (left.length !== right.length) {\n\t\treturn false\n\t}\n\tfor (let index = 0; index < left.length; index++) {\n\t\tif (left[index] !== right[index]) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n","import type { RichTextSyncEngine } from './types'\n\n/**\n * Narrows a sync engine reference to the richtext controller surface.\n * SyncEngine satisfies this interface at runtime; types live in different packages.\n */\nexport function asRichTextSyncEngine(engine: unknown): RichTextSyncEngine | null {\n\tif (engine == null) {\n\t\treturn null\n\t}\n\treturn engine as RichTextSyncEngine\n}\n","export { exportBackup, readBackupManifest, restoreBackup, verifyBackupChecksum } from './backup'\nexport type {\n\tBackupManifest,\n\tBackupOptions,\n\tBackupProgress,\n\tRestoreOptions,\n\tRestoreResult,\n} from './types'\n","export {\n\tappendAuditTrace,\n\tauditTraceIndexFields,\n\tcountAuditTraces,\n\tpersistedAuditTraceFromEvent,\n\treadAuditTraces,\n} from './audit-trace-store'\nexport {\n\tauditJsonReplacer,\n\tauditJsonReviver,\n\tdeserializeAuditJson,\n\tserializeAuditJson,\n} from './audit-json'\nexport {\n\tdecodeAuditExport,\n\texportAudit,\n\treadAuditExportManifest,\n\tverifyAuditExportChecksum,\n} from './export-audit'\nexport type {\n\tAuditExportManifest,\n\tAuditExportOptions,\n\tAuditExportPayload,\n\tAuditExportProgress,\n\tAuditTraceQuery,\n\tPersistedAuditTrace,\n} from './types'\n","import { type BlobRef, type BlobRefMetadata, createBlobRef, hashBlob } from '@korajs/core'\n\n/**\n * Thrown when a blob read fails its integrity check: the bytes stored under a\n * hash do not actually hash to that value (corruption or tampering).\n */\nexport class BlobIntegrityError extends Error {\n\tconstructor(\n\t\treadonly expectedHash: string,\n\t\treadonly actualHash: string,\n\t) {\n\t\tsuper(`Blob integrity check failed: content under hash ${expectedHash} hashes to ${actualHash}`)\n\t\tthis.name = 'BlobIntegrityError'\n\t}\n}\n\n/**\n * A content-addressed store for the bytes behind `blob` fields.\n *\n * Blobs are keyed by the SHA-256 hash of their content, so identical content is\n * stored exactly once (deduplication) and a peer never needs to transfer bytes\n * it already holds. Reads are integrity-checked: the returned bytes are verified\n * to hash to the requested key.\n */\nexport interface ContentAddressedBlobStore {\n\t/**\n\t * Store bytes and return their content-addressed reference. Storing content\n\t * that already exists is a no-op that returns the same reference (dedup).\n\t */\n\tput(bytes: Uint8Array, metadata?: BlobRefMetadata): Promise<BlobRef>\n\t/**\n\t * Retrieve the bytes for a hash, or null if absent. The returned bytes are\n\t * verified to hash to the requested value; a mismatch throws\n\t * {@link BlobIntegrityError} rather than returning corrupt data.\n\t */\n\tget(hash: string): Promise<Uint8Array | null>\n\t/** Whether the store holds content for the given hash. */\n\thas(hash: string): Promise<boolean>\n\t/** Remove the content for a hash. Returns whether anything was removed. */\n\tdelete(hash: string): Promise<boolean>\n\t/** Number of distinct blobs held. */\n\tsize(): Promise<number>\n\t/**\n\t * List the hashes of every blob currently held. Used by garbage collection to\n\t * find content no live reference points to. Order is unspecified.\n\t */\n\tlist(): Promise<string[]>\n}\n\n/**\n * In-memory {@link ContentAddressedBlobStore}. The reference backend used for\n * tests and for environments without a persistent blob backend yet. Persistent\n * backends (OPFS client-side, filesystem/S3 server-side) implement the same\n * interface.\n */\nexport class MemoryBlobStore implements ContentAddressedBlobStore {\n\tprivate readonly blobs = new Map<string, Uint8Array>()\n\n\tasync put(bytes: Uint8Array, metadata: BlobRefMetadata = {}): Promise<BlobRef> {\n\t\tconst ref = await createBlobRef(bytes, metadata)\n\t\tif (!this.blobs.has(ref.hash)) {\n\t\t\t// Copy so later mutation of the caller's buffer cannot corrupt the store.\n\t\t\tconst stored = new Uint8Array(bytes.byteLength)\n\t\t\tstored.set(bytes)\n\t\t\tthis.blobs.set(ref.hash, stored)\n\t\t}\n\t\treturn ref\n\t}\n\n\tasync get(hash: string): Promise<Uint8Array | null> {\n\t\tconst stored = this.blobs.get(hash)\n\t\tif (stored === undefined) {\n\t\t\treturn null\n\t\t}\n\t\tconst actualHash = await hashBlob(stored)\n\t\tif (actualHash !== hash) {\n\t\t\tthrow new BlobIntegrityError(hash, actualHash)\n\t\t}\n\t\t// Return a copy so callers cannot mutate the stored bytes.\n\t\tconst out = new Uint8Array(stored.byteLength)\n\t\tout.set(stored)\n\t\treturn out\n\t}\n\n\tasync has(hash: string): Promise<boolean> {\n\t\treturn this.blobs.has(hash)\n\t}\n\n\tasync delete(hash: string): Promise<boolean> {\n\t\treturn this.blobs.delete(hash)\n\t}\n\n\tasync size(): Promise<number> {\n\t\treturn this.blobs.size\n\t}\n\n\tasync list(): Promise<string[]> {\n\t\treturn [...this.blobs.keys()]\n\t}\n}\n","import { type BlobRef, type BlobRefMetadata, createBlobRef, hashBlob } from '@korajs/core'\nimport { BlobIntegrityError, type ContentAddressedBlobStore } from './content-addressed-blob-store'\n\n/**\n * The minimal directory abstraction an {@link OpfsBlobStore} needs. Blobs are\n * laid out as `<shard>/<name>` (shard = first two hex chars of the hash) so a\n * single directory never holds millions of entries.\n *\n * The real backend ({@link createOpfsBlobDirectory}) is the browser Origin\n * Private File System; tests supply an in-memory implementation. Keeping this\n * port small means the content-addressed logic (hashing, integrity, dedup,\n * sharding) is fully testable without a browser.\n */\nexport interface OpfsBlobDirectory {\n\t/** Read the bytes at `<shard>/<name>`, or null if absent. */\n\tread(shard: string, name: string): Promise<Uint8Array | null>\n\t/**\n\t * Write bytes at `<shard>/<name>`, creating the shard directory as needed.\n\t * Must be atomic: a crash mid-write may not leave a partially-written file\n\t * that a later read would trust.\n\t */\n\twrite(shard: string, name: string, bytes: Uint8Array): Promise<void>\n\t/** Remove `<shard>/<name>`. Returns whether anything was removed. */\n\tremove(shard: string, name: string): Promise<boolean>\n\t/** Whether `<shard>/<name>` exists. */\n\thas(shard: string, name: string): Promise<boolean>\n\t/** Count of stored blobs across all shards (temp files excluded). */\n\tcount(): Promise<number>\n\t/** Every stored blob name (hash) across all shards (temp files excluded). */\n\tkeys(): Promise<string[]>\n}\n\n/**\n * A persistent {@link ContentAddressedBlobStore} for the browser, backed by the\n * Origin Private File System (OPFS) — the same durable storage the SQLite WASM\n * adapter uses. Blobs survive reloads, are sharded by hash prefix, deduplicated,\n * and integrity-verified on read (the returned bytes are checked to hash to the\n * requested key). Writes commit atomically so a torn write cannot surface as\n * trusted data.\n *\n * The store itself is environment-neutral: it talks to an {@link OpfsBlobDirectory}.\n * Use {@link createOpfsBlobStore} in a browser to get one backed by real OPFS.\n */\nexport class OpfsBlobStore implements ContentAddressedBlobStore {\n\tconstructor(private readonly dir: OpfsBlobDirectory) {}\n\n\tprivate shardFor(hash: string): string {\n\t\t// Two hex chars → 256 shards. Hashes are hex, so this is always well-formed.\n\t\treturn hash.slice(0, 2)\n\t}\n\n\tasync put(bytes: Uint8Array, metadata: BlobRefMetadata = {}): Promise<BlobRef> {\n\t\tconst ref = await createBlobRef(bytes, metadata)\n\t\tconst shard = this.shardFor(ref.hash)\n\n\t\t// Dedup: identical content already stored is a no-op.\n\t\tif (await this.dir.has(shard, ref.hash)) {\n\t\t\treturn ref\n\t\t}\n\n\t\t// Copy into an exactly-sized buffer so a subarray view writes its own bytes.\n\t\tconst out = new Uint8Array(bytes.byteLength)\n\t\tout.set(bytes)\n\t\tawait this.dir.write(shard, ref.hash, out)\n\t\treturn ref\n\t}\n\n\tasync get(hash: string): Promise<Uint8Array | null> {\n\t\tconst bytes = await this.dir.read(this.shardFor(hash), hash)\n\t\tif (bytes === null) {\n\t\t\treturn null\n\t\t}\n\t\tconst actual = await hashBlob(bytes)\n\t\tif (actual !== hash) {\n\t\t\tthrow new BlobIntegrityError(hash, actual)\n\t\t}\n\t\treturn bytes\n\t}\n\n\tasync has(hash: string): Promise<boolean> {\n\t\treturn this.dir.has(this.shardFor(hash), hash)\n\t}\n\n\tasync delete(hash: string): Promise<boolean> {\n\t\treturn this.dir.remove(this.shardFor(hash), hash)\n\t}\n\n\tasync size(): Promise<number> {\n\t\treturn this.dir.count()\n\t}\n\n\tasync list(): Promise<string[]> {\n\t\treturn this.dir.keys()\n\t}\n}\n\n// --- Real OPFS binding (browser only) ---\n\n/** Minimal structural views of the File System Access handles we use. */\ninterface OpfsWritableStream {\n\twrite(data: Uint8Array): Promise<void>\n\tclose(): Promise<void>\n}\ninterface OpfsFileHandle {\n\tcreateWritable(options?: { keepExistingData?: boolean }): Promise<OpfsWritableStream>\n\tgetFile(): Promise<{ arrayBuffer(): Promise<ArrayBuffer> }>\n}\ninterface OpfsDirectoryHandle {\n\tgetDirectoryHandle(name: string, options?: { create?: boolean }): Promise<OpfsDirectoryHandle>\n\tgetFileHandle(name: string, options?: { create?: boolean }): Promise<OpfsFileHandle>\n\tremoveEntry(name: string, options?: { recursive?: boolean }): Promise<void>\n\tkeys(): AsyncIterableIterator<string>\n}\n\ninterface StorageManagerLike {\n\tgetDirectory(): Promise<OpfsDirectoryHandle>\n\tpersist?(): Promise<boolean>\n}\n\nfunction getStorageManager(): StorageManagerLike {\n\tconst nav = (globalThis as { navigator?: { storage?: StorageManagerLike } }).navigator\n\tif (!nav?.storage || typeof nav.storage.getDirectory !== 'function') {\n\t\tthrow new Error(\n\t\t\t'OPFS is unavailable in this environment. The OPFS blob store requires a browser with Origin Private File System support; use MemoryBlobStore or a server-side store elsewhere.',\n\t\t)\n\t}\n\treturn nav.storage\n}\n\nfunction isNotFoundError(error: unknown): boolean {\n\treturn (\n\t\ttypeof error === 'object' &&\n\t\terror !== null &&\n\t\t(error as { name?: string }).name === 'NotFoundError'\n\t)\n}\n\n/**\n * Create an {@link OpfsBlobDirectory} backed by the browser's Origin Private\n * File System, rooted at a named subdirectory. Best-effort requests persistent\n * storage so the browser is less likely to evict blobs under storage pressure.\n *\n * @param rootDirName - The OPFS subdirectory to store blobs under (default `kora-blobs`)\n * @throws {Error} If OPFS is unavailable (e.g. called outside a browser)\n */\nexport async function createOpfsBlobDirectory(\n\trootDirName = 'kora-blobs',\n): Promise<OpfsBlobDirectory> {\n\tconst storage = getStorageManager()\n\t// Best-effort durability: ask the browser not to evict this origin's storage.\n\tif (typeof storage.persist === 'function') {\n\t\ttry {\n\t\t\tawait storage.persist()\n\t\t} catch {\n\t\t\t// Persistence is an optimization, not a requirement; ignore failures.\n\t\t}\n\t}\n\tconst opfsRoot = await storage.getDirectory()\n\tconst root = await opfsRoot.getDirectoryHandle(rootDirName, { create: true })\n\n\tasync function shardHandle(shard: string, create: boolean): Promise<OpfsDirectoryHandle | null> {\n\t\ttry {\n\t\t\treturn await root.getDirectoryHandle(shard, { create })\n\t\t} catch (error) {\n\t\t\tif (isNotFoundError(error)) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\treturn {\n\t\tasync read(shard, name) {\n\t\t\tconst dir = await shardHandle(shard, false)\n\t\t\tif (!dir) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tlet handle: OpfsFileHandle\n\t\t\ttry {\n\t\t\t\thandle = await dir.getFileHandle(name, { create: false })\n\t\t\t} catch (error) {\n\t\t\t\tif (isNotFoundError(error)) {\n\t\t\t\t\treturn null\n\t\t\t\t}\n\t\t\t\tthrow error\n\t\t\t}\n\t\t\tconst file = await handle.getFile()\n\t\t\treturn new Uint8Array(await file.arrayBuffer())\n\t\t},\n\t\tasync write(shard, name, bytes) {\n\t\t\tconst dir = await root.getDirectoryHandle(shard, { create: true })\n\t\t\tconst handle = await dir.getFileHandle(name, { create: true })\n\t\t\t// createWritable buffers to a swap file and only commits on close(), so\n\t\t\t// the target file is updated atomically. Combined with integrity-on-read,\n\t\t\t// a torn write is never trusted.\n\t\t\tconst writable = await handle.createWritable({ keepExistingData: false })\n\t\t\ttry {\n\t\t\t\tawait writable.write(bytes)\n\t\t\t} finally {\n\t\t\t\tawait writable.close()\n\t\t\t}\n\t\t},\n\t\tasync remove(shard, name) {\n\t\t\tconst dir = await shardHandle(shard, false)\n\t\t\tif (!dir) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait dir.removeEntry(name)\n\t\t\t\treturn true\n\t\t\t} catch (error) {\n\t\t\t\tif (isNotFoundError(error)) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\tasync has(shard, name) {\n\t\t\tconst dir = await shardHandle(shard, false)\n\t\t\tif (!dir) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait dir.getFileHandle(name, { create: false })\n\t\t\t\treturn true\n\t\t\t} catch (error) {\n\t\t\t\tif (isNotFoundError(error)) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\tasync count() {\n\t\t\tlet total = 0\n\t\t\tfor await (const shard of root.keys()) {\n\t\t\t\tconst dir = await shardHandle(shard, false)\n\t\t\t\tif (!dir) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tfor await (const name of dir.keys()) {\n\t\t\t\t\tif (!name.endsWith('.tmp')) {\n\t\t\t\t\t\ttotal++\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn total\n\t\t},\n\t\tasync keys() {\n\t\t\tconst names: string[] = []\n\t\t\tfor await (const shard of root.keys()) {\n\t\t\t\tconst dir = await shardHandle(shard, false)\n\t\t\t\tif (!dir) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tfor await (const name of dir.keys()) {\n\t\t\t\t\tif (!name.endsWith('.tmp')) {\n\t\t\t\t\t\tnames.push(name)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn names\n\t\t},\n\t}\n}\n\n/**\n * Create a persistent {@link OpfsBlobStore} backed by real browser OPFS.\n *\n * @param rootDirName - The OPFS subdirectory to store blobs under (default `kora-blobs`)\n * @throws {Error} If OPFS is unavailable (e.g. called outside a browser)\n */\nexport async function createOpfsBlobStore(rootDirName = 'kora-blobs'): Promise<OpfsBlobStore> {\n\treturn new OpfsBlobStore(await createOpfsBlobDirectory(rootDirName))\n}\n","import { hashBlob } from '@korajs/core'\nimport { BlobIntegrityError, type ContentAddressedBlobStore } from './content-addressed-blob-store'\n\n/** Default chunk size for out-of-band blob transfer (256 KiB). */\nexport const DEFAULT_CHUNK_SIZE = 256 * 1024\n\n/**\n * A manifest describing how a blob is split into content-addressed chunks.\n *\n * The manifest is small and travels with the operation stream (or alongside it);\n * the chunk bytes travel out of band. Because every chunk is content-addressed,\n * identical chunks across blobs are stored and transferred once, and a peer only\n * ever requests chunk hashes it does not already hold.\n */\nexport interface BlobManifest {\n\t/** Hex SHA-256 hash of the full reassembled blob (its content address). */\n\tblobHash: string\n\t/** Total size of the full blob in bytes. */\n\tsize: number\n\t/** The chunk size used to split the blob. */\n\tchunkSize: number\n\t/** Ordered hashes of each chunk. Repeats when identical chunks recur. */\n\tchunkHashes: string[]\n\tmimeType?: string\n\tfilename?: string\n}\n\n/** Optional metadata carried on a manifest. */\nexport interface BlobManifestMetadata {\n\tmimeType?: string\n\tfilename?: string\n}\n\n/**\n * Split a blob into content-addressed chunks and produce its manifest.\n *\n * @param bytes - The full blob content\n * @param chunkSize - Bytes per chunk (defaults to {@link DEFAULT_CHUNK_SIZE})\n * @param metadata - Optional mime type / filename to record on the manifest\n * @returns The manifest and a map of chunk hash to chunk bytes (deduplicated)\n */\nexport async function chunkBlob(\n\tbytes: Uint8Array,\n\tchunkSize: number = DEFAULT_CHUNK_SIZE,\n\tmetadata: BlobManifestMetadata = {},\n): Promise<{ manifest: BlobManifest; chunks: Map<string, Uint8Array> }> {\n\tif (chunkSize <= 0) {\n\t\tthrow new Error(`chunkBlob requires a positive chunkSize, got ${chunkSize}`)\n\t}\n\n\tconst chunkHashes: string[] = []\n\tconst chunks = new Map<string, Uint8Array>()\n\n\tfor (let offset = 0; offset < bytes.byteLength; offset += chunkSize) {\n\t\tconst end = Math.min(offset + chunkSize, bytes.byteLength)\n\t\tconst chunk = new Uint8Array(end - offset)\n\t\tchunk.set(bytes.subarray(offset, end))\n\t\tconst hash = await hashBlob(chunk)\n\t\tchunkHashes.push(hash)\n\t\t// Identical chunks collapse to one stored entry; the ordered hash list\n\t\t// still records every position so reassembly reproduces the exact bytes.\n\t\tif (!chunks.has(hash)) {\n\t\t\tchunks.set(hash, chunk)\n\t\t}\n\t}\n\n\tconst blobHash = await hashBlob(bytes)\n\tconst manifest: BlobManifest = {\n\t\tblobHash,\n\t\tsize: bytes.byteLength,\n\t\tchunkSize,\n\t\tchunkHashes,\n\t}\n\tif (metadata.mimeType !== undefined) {\n\t\tmanifest.mimeType = metadata.mimeType\n\t}\n\tif (metadata.filename !== undefined) {\n\t\tmanifest.filename = metadata.filename\n\t}\n\n\treturn { manifest, chunks }\n}\n\n/**\n * Reassemble a blob from chunks held in a content-addressed store, verifying\n * integrity at both levels: each chunk is verified by the store on read, and the\n * reassembled whole is verified against the manifest's blob hash.\n *\n * @param manifest - The blob manifest\n * @param chunkStore - A store holding the chunk bytes keyed by chunk hash\n * @returns The full reassembled blob bytes\n * @throws {BlobIntegrityError} If the reassembled bytes do not match blobHash\n * @throws {Error} If a chunk named in the manifest is missing from the store\n */\nexport async function reassembleBlob(\n\tmanifest: BlobManifest,\n\tchunkStore: ContentAddressedBlobStore,\n): Promise<Uint8Array> {\n\tconst parts: Uint8Array[] = []\n\tlet total = 0\n\n\tfor (const hash of manifest.chunkHashes) {\n\t\tconst chunk = await chunkStore.get(hash)\n\t\tif (chunk === null) {\n\t\t\tthrow new Error(`Cannot reassemble blob ${manifest.blobHash}: missing chunk ${hash}`)\n\t\t}\n\t\tparts.push(chunk)\n\t\ttotal += chunk.byteLength\n\t}\n\n\tconst out = new Uint8Array(total)\n\tlet offset = 0\n\tfor (const part of parts) {\n\t\tout.set(part, offset)\n\t\toffset += part.byteLength\n\t}\n\n\tconst actual = await hashBlob(out)\n\tif (actual !== manifest.blobHash) {\n\t\tthrow new BlobIntegrityError(manifest.blobHash, actual)\n\t}\n\treturn out\n}\n","import { type BlobRef, hashBlob } from '@korajs/core'\nimport { type BlobManifest, chunkBlob, reassembleBlob } from './blob-chunking'\nimport { BlobIntegrityError, type ContentAddressedBlobStore } from './content-addressed-blob-store'\n\n/**\n * A source of chunk bytes on the sending side of a transfer. In production this\n * is backed by the sync connection (the receiver requests a chunk hash, the peer\n * that holds the blob answers with the bytes); in tests it is backed by a map.\n */\nexport interface ChunkProvider {\n\t/** Fetch the bytes for a chunk hash, or null if the provider does not have it. */\n\tgetChunk(hash: string): Promise<Uint8Array | null>\n}\n\n/** Result of receiving a blob out of band. */\nexport interface ReceiveBlobResult {\n\t/** The content-addressed reference to the reassembled blob. */\n\tref: BlobRef\n\t/** Number of chunks actually fetched from the provider. */\n\tchunksFetched: number\n\t/** Number of chunks skipped because they were already held locally. */\n\tchunksSkipped: number\n}\n\n/** Stores used while receiving a blob. */\nexport interface ReceiveBlobStores {\n\t/**\n\t * Where fetched chunks are staged, keyed by chunk hash. A persistent chunk\n\t * store makes a transfer resumable: an interrupted transfer leaves its chunks\n\t * here, and a resumed transfer skips them.\n\t */\n\tchunkStore: ContentAddressedBlobStore\n\t/** Where the fully reassembled, verified blob is written. */\n\tblobStore: ContentAddressedBlobStore\n}\n\n/**\n * Receive a blob out of band, chunk by chunk, resumably and with integrity\n * verification at every step.\n *\n * For each chunk named in the manifest: if the chunk store already holds it (a\n * prior, possibly interrupted transfer), it is skipped; otherwise it is fetched\n * from the provider and verified to hash to the expected chunk hash before being\n * staged. Once every chunk is present, the blob is reassembled, verified against\n * the manifest's blob hash, and written to the blob store (which deduplicates).\n *\n * The transfer is idempotent: running it again after completion fetches nothing\n * and returns the same reference.\n *\n * @param manifest - The manifest of the blob to receive\n * @param provider - The source of chunk bytes\n * @param stores - The chunk staging store and the destination blob store\n * @returns The reference plus how many chunks were fetched versus skipped\n * @throws {BlobIntegrityError} If a fetched chunk or the whole blob fails verification\n * @throws {Error} If the provider cannot supply a required chunk\n */\nexport async function receiveBlob(\n\tmanifest: BlobManifest,\n\tprovider: ChunkProvider,\n\tstores: ReceiveBlobStores,\n): Promise<ReceiveBlobResult> {\n\tlet chunksFetched = 0\n\tlet chunksSkipped = 0\n\n\t// Distinct chunk hashes only: a manifest may repeat a hash, but we need each\n\t// unique chunk exactly once. Skipping duplicates also means a blob made of\n\t// identical chunks transfers that chunk a single time.\n\tconst seen = new Set<string>()\n\tfor (const hash of manifest.chunkHashes) {\n\t\tif (seen.has(hash)) {\n\t\t\tcontinue\n\t\t}\n\t\tseen.add(hash)\n\n\t\tif (await stores.chunkStore.has(hash)) {\n\t\t\tchunksSkipped++\n\t\t\tcontinue\n\t\t}\n\n\t\tconst bytes = await provider.getChunk(hash)\n\t\tif (bytes === null) {\n\t\t\tthrow new Error(`Blob transfer failed: provider could not supply chunk ${hash}`)\n\t\t}\n\t\tconst actual = await hashBlob(bytes)\n\t\tif (actual !== hash) {\n\t\t\tthrow new BlobIntegrityError(hash, actual)\n\t\t}\n\t\tawait stores.chunkStore.put(bytes)\n\t\tchunksFetched++\n\t}\n\n\tconst full = await reassembleBlob(manifest, stores.chunkStore)\n\tconst ref = await stores.blobStore.put(full, {\n\t\tmimeType: manifest.mimeType,\n\t\tfilename: manifest.filename,\n\t})\n\n\treturn { ref, chunksFetched, chunksSkipped }\n}\n\n/**\n * Prepare a blob for out-of-band sending: split it into chunks, stage those\n * chunks in a content-addressed store, and return the manifest plus a\n * {@link ChunkProvider} that serves the chunks from that store.\n *\n * @param bytes - The full blob content\n * @param chunkStore - Where to stage the chunks (served to receivers)\n * @param options - Optional chunk size and metadata\n * @returns The manifest and a provider that serves the staged chunks\n */\nexport async function prepareBlobForSend(\n\tbytes: Uint8Array,\n\tchunkStore: ContentAddressedBlobStore,\n\toptions: { chunkSize?: number; mimeType?: string; filename?: string } = {},\n): Promise<{ manifest: BlobManifest; provider: ChunkProvider }> {\n\tconst { manifest, chunks } = await chunkBlob(bytes, options.chunkSize, {\n\t\tmimeType: options.mimeType,\n\t\tfilename: options.filename,\n\t})\n\tfor (const chunk of chunks.values()) {\n\t\tawait chunkStore.put(chunk)\n\t}\n\tconst provider: ChunkProvider = {\n\t\tgetChunk: (hash) => chunkStore.get(hash),\n\t}\n\treturn { manifest, provider }\n}\n","import { type BlobRef, type BlobRefMetadata, hashBlob } from '@korajs/core'\nimport { type BlobManifest, chunkBlob } from './blob-chunking'\nimport type { ChunkProvider } from './blob-transfer'\nimport { BlobIntegrityError, type ContentAddressedBlobStore } from './content-addressed-blob-store'\n\n/**\n * Serialize a {@link BlobManifest} to canonical bytes for content addressing.\n *\n * Fields are emitted in a fixed order so the same manifest always produces the\n * same bytes, which is what lets the manifest be stored and fetched under its own\n * SHA-256 hash. Optional fields are omitted when absent.\n */\nexport function serializeBlobManifest(manifest: BlobManifest): Uint8Array {\n\tconst canonical: Record<string, unknown> = {\n\t\tblobHash: manifest.blobHash,\n\t\tsize: manifest.size,\n\t\tchunkSize: manifest.chunkSize,\n\t\tchunkHashes: manifest.chunkHashes,\n\t}\n\tif (manifest.mimeType !== undefined) {\n\t\tcanonical.mimeType = manifest.mimeType\n\t}\n\tif (manifest.filename !== undefined) {\n\t\tcanonical.filename = manifest.filename\n\t}\n\treturn new TextEncoder().encode(JSON.stringify(canonical))\n}\n\n/**\n * Parse canonical manifest bytes back into a {@link BlobManifest}, validating the\n * shape. Throws on malformed input rather than returning a partial manifest.\n */\nexport function parseBlobManifest(bytes: Uint8Array): BlobManifest {\n\tconst parsed: unknown = JSON.parse(new TextDecoder().decode(bytes))\n\tif (typeof parsed !== 'object' || parsed === null) {\n\t\tthrow new Error('Invalid blob manifest: not an object')\n\t}\n\tconst obj = parsed as Record<string, unknown>\n\tif (typeof obj.blobHash !== 'string') {\n\t\tthrow new Error('Invalid blob manifest: missing blobHash')\n\t}\n\tif (typeof obj.size !== 'number' || typeof obj.chunkSize !== 'number') {\n\t\tthrow new Error('Invalid blob manifest: missing size or chunkSize')\n\t}\n\tif (!Array.isArray(obj.chunkHashes) || obj.chunkHashes.some((h) => typeof h !== 'string')) {\n\t\tthrow new Error('Invalid blob manifest: chunkHashes must be an array of strings')\n\t}\n\tconst manifest: BlobManifest = {\n\t\tblobHash: obj.blobHash,\n\t\tsize: obj.size,\n\t\tchunkSize: obj.chunkSize,\n\t\tchunkHashes: obj.chunkHashes as string[],\n\t}\n\tif (typeof obj.mimeType === 'string') {\n\t\tmanifest.mimeType = obj.mimeType\n\t}\n\tif (typeof obj.filename === 'string') {\n\t\tmanifest.filename = obj.filename\n\t}\n\treturn manifest\n}\n\n/**\n * Store a blob for out-of-band transfer, addressed entirely by content.\n *\n * Stages the blob's chunks (so this device can serve them), stores the full blob\n * (so local reads by hash are O(1)), and stores the blob's manifest as its own\n * content-addressed object. The returned {@link BlobRef} carries `manifestHash`,\n * so a peer that receives the reference in a synced record can pull the bytes\n * knowing only the reference — no separate manifest hand-off.\n *\n * @param store - The content-addressed store to stage chunks, blob, and manifest in\n * @param bytes - The full blob content\n * @param options - Optional chunk size and metadata\n * @returns The reference (including `manifestHash`) and the manifest\n */\nexport async function putBlobForTransfer(\n\tstore: ContentAddressedBlobStore,\n\tbytes: Uint8Array,\n\toptions: { chunkSize?: number } & BlobRefMetadata = {},\n): Promise<{ ref: BlobRef; manifest: BlobManifest }> {\n\tconst { manifest, chunks } = await chunkBlob(bytes, options.chunkSize, {\n\t\t...(options.mimeType !== undefined ? { mimeType: options.mimeType } : {}),\n\t\t...(options.filename !== undefined ? { filename: options.filename } : {}),\n\t})\n\tfor (const chunk of chunks.values()) {\n\t\tawait store.put(chunk)\n\t}\n\t// Full blob for local O(1) reads by content hash.\n\tconst baseRef = await store.put(bytes, {\n\t\t...(options.mimeType !== undefined ? { mimeType: options.mimeType } : {}),\n\t\t...(options.filename !== undefined ? { filename: options.filename } : {}),\n\t})\n\t// Manifest as its own content-addressed object, served over the same channel.\n\tconst manifestRef = await store.put(serializeBlobManifest(manifest))\n\treturn { ref: { ...baseRef, manifestHash: manifestRef.hash }, manifest }\n}\n\n/**\n * Fetch and integrity-verify a blob's manifest from a {@link ChunkProvider}.\n *\n * The manifest is a content-addressed object like a chunk, so it is requested by\n * its hash, verified to hash to that value, and parsed. Used to resolve a\n * {@link BlobRef}'s manifest before pulling the blob's chunks.\n *\n * @param provider - The source to fetch the manifest bytes from\n * @param manifestHash - The manifest's content hash (from `BlobRef.manifestHash`)\n * @throws {BlobIntegrityError} If the fetched bytes do not hash to `manifestHash`\n * @throws {Error} If the provider cannot supply the manifest\n */\nexport async function fetchBlobManifest(\n\tprovider: ChunkProvider,\n\tmanifestHash: string,\n): Promise<BlobManifest> {\n\tconst bytes = await provider.getChunk(manifestHash)\n\tif (bytes === null) {\n\t\tthrow new Error(`Blob manifest ${manifestHash} could not be fetched from the provider`)\n\t}\n\tconst actual = await hashBlob(bytes)\n\tif (actual !== manifestHash) {\n\t\tthrow new BlobIntegrityError(manifestHash, actual)\n\t}\n\treturn parseBlobManifest(bytes)\n}\n\n/**\n * Resolve the manifest for a {@link BlobRef} that was stored via\n * {@link putBlobForTransfer}. Fetches and verifies the manifest by the ref's\n * `manifestHash`.\n *\n * @throws {Error} If the ref has no `manifestHash` (it was not stored for transfer)\n */\nexport async function resolveBlobManifest(\n\tprovider: ChunkProvider,\n\tref: BlobRef,\n): Promise<BlobManifest> {\n\tif (ref.manifestHash === undefined) {\n\t\tthrow new Error(\n\t\t\t`Blob ${ref.hash} has no manifest to resolve. Store it with putBlobForTransfer (or app.blobs.put) so its reference carries a manifestHash, or pull with an explicit manifest.`,\n\t\t)\n\t}\n\treturn fetchBlobManifest(provider, ref.manifestHash)\n}\n","import { hashBlob } from '@korajs/core'\nimport { type ContentAddressedBlobStore, MemoryBlobStore } from './content-addressed-blob-store'\n\n/**\n * The server-side blob callbacks a `KoraSyncServer` accepts: read a chunk by\n * hash (to serve it) and persist an uploaded chunk by hash (to store it).\n */\nexport interface ServerBlobCallbacks {\n\tresolveBlobChunk: (hash: string) => Promise<Uint8Array | null>\n\tpersistBlobChunk: (hash: string, bytes: Uint8Array) => Promise<void>\n}\n\n/**\n * Adapt a {@link ContentAddressedBlobStore} into the read/persist callbacks a\n * `KoraSyncServer` needs for central blob storage. The server package depends\n * only on these plain function signatures, so a self-hosted server can back its\n * blob storage with any store (for example a `FilesystemBlobStore`) without the\n * server package taking a dependency on `@korajs/store`.\n *\n * @example\n * ```typescript\n * const server = new KoraSyncServer({\n * store,\n * ...toServerBlobCallbacks(new FilesystemBlobStore('/var/kora/blobs')),\n * })\n * ```\n */\nexport function toServerBlobCallbacks(store: ContentAddressedBlobStore): ServerBlobCallbacks {\n\treturn {\n\t\tresolveBlobChunk: (hash) => store.get(hash),\n\t\tasync persistBlobChunk(hash, bytes) {\n\t\t\t// The store keys by the hash it computes from the bytes; verify it matches\n\t\t\t// the declared hash so a mismatched upload is rejected, not silently stored\n\t\t\t// under the wrong key.\n\t\t\tconst actual = await hashBlob(bytes)\n\t\t\tif (actual !== hash) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tawait store.put(bytes)\n\t\t},\n\t}\n}\n\n/**\n * Convenience: an in-memory central blob store plus its server callbacks. For\n * tests and single-process deployments. Persistent deployments should back\n * {@link toServerBlobCallbacks} with a durable store instead.\n */\nexport function createMemoryServerBlobStore(): {\n\tstore: MemoryBlobStore\n\tcallbacks: ServerBlobCallbacks\n} {\n\tconst store = new MemoryBlobStore()\n\treturn { store, callbacks: toServerBlobCallbacks(store) }\n}\n","import { type BlobRef, isBlobRef } from '@korajs/core'\nimport { parseBlobManifest } from './blob-manifest-transfer'\nimport type { ContentAddressedBlobStore } from './content-addressed-blob-store'\n\n/** Outcome of a blob garbage-collection sweep. */\nexport interface BlobGcResult {\n\t/** Total distinct blobs held before the sweep. */\n\tscanned: number\n\t/** Distinct hashes kept because a live reference points to them (blob, manifest, or chunk). */\n\tlive: number\n\t/** Number of blobs deleted (or, with `dryRun`, that would be deleted). */\n\tcollected: number\n\t/** The hashes deleted (or, with `dryRun`, that would be deleted). */\n\tcollectedHashes: string[]\n}\n\n/** Options for {@link collectBlobGarbage}. */\nexport interface BlobGcOptions {\n\t/** Compute what would be collected without deleting anything. */\n\tdryRun?: boolean\n}\n\n/**\n * Extract the {@link BlobRef}s referenced by a materialized record. Scans the\n * record's top-level field values, so it works without the schema; a `blob`\n * field simply holds a `BlobRef`.\n */\nexport function extractBlobRefs(record: Record<string, unknown>): BlobRef[] {\n\tconst refs: BlobRef[] = []\n\tfor (const value of Object.values(record)) {\n\t\tif (isBlobRef(value)) {\n\t\t\trefs.push(value)\n\t\t}\n\t}\n\treturn refs\n}\n\n/**\n * Garbage-collect a content-addressed blob store by mark-and-sweep: keep every\n * blob reachable from a live reference, delete the rest.\n *\n * The live set is closed over the reference graph — for each live {@link BlobRef}\n * it retains the blob hash, the manifest hash, and every chunk hash named in that\n * manifest. Because chunks (and blobs) are shared by content address, a chunk\n * referenced by any surviving blob is retained even if another blob that used it\n * was collected. This makes GC safe under deduplication.\n *\n * Mark-and-sweep (rather than reference counting) is deliberate: counts are\n * fragile under concurrent edits and CRDT merges, whereas a sweep against the\n * current live set is always correct for the state it observes. Run it\n * periodically or on demand.\n *\n * A manifest that cannot be read or parsed (corruption) contributes no chunk\n * hashes; its own hash still counts as live. The blob it describes is already\n * unusable, so its chunks becoming collectable is acceptable, and GC never\n * throws on a single bad manifest.\n *\n * @param store - The blob store to sweep\n * @param liveRefs - Every reference still reachable from live records\n * @param options - `dryRun` to report without deleting\n */\nexport async function collectBlobGarbage(\n\tstore: ContentAddressedBlobStore,\n\tliveRefs: Iterable<BlobRef>,\n\toptions: BlobGcOptions = {},\n): Promise<BlobGcResult> {\n\tconst live = new Set<string>()\n\tfor (const ref of liveRefs) {\n\t\tlive.add(ref.hash)\n\t\tif (ref.manifestHash === undefined) {\n\t\t\tcontinue\n\t\t}\n\t\tlive.add(ref.manifestHash)\n\t\ttry {\n\t\t\tconst manifestBytes = await store.get(ref.manifestHash)\n\t\t\tif (manifestBytes !== null) {\n\t\t\t\tconst manifest = parseBlobManifest(manifestBytes)\n\t\t\t\tfor (const chunkHash of manifest.chunkHashes) {\n\t\t\t\t\tlive.add(chunkHash)\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// A corrupt/unreadable manifest contributes no chunk hashes; the blob is\n\t\t\t// already broken. Never abort the whole sweep for one bad manifest.\n\t\t}\n\t}\n\n\tconst all = await store.list()\n\tconst collectedHashes: string[] = []\n\tfor (const hash of all) {\n\t\tif (live.has(hash)) {\n\t\t\tcontinue\n\t\t}\n\t\tcollectedHashes.push(hash)\n\t\tif (!options.dryRun) {\n\t\t\tawait store.delete(hash)\n\t\t}\n\t}\n\n\treturn {\n\t\tscanned: all.length,\n\t\tlive: live.size,\n\t\tcollected: collectedHashes.length,\n\t\tcollectedHashes,\n\t}\n}\n","import { generateUUIDv7 } from '@korajs/core'\nimport type { ChunkProvider } from './blob-transfer'\nimport type { ContentAddressedBlobStore } from './content-addressed-blob-store'\n\n/**\n * Blob chunk exchange messages. These ride any message transport (the sync\n * WebSocket in production, an in-memory pair in tests). A receiver requests a\n * chunk by hash and correlates the answer by `requestId`.\n */\nexport interface ChunkRequestMessage {\n\ttype: 'blob-chunk-request'\n\trequestId: string\n\thash: string\n}\nexport interface ChunkResponseMessage {\n\ttype: 'blob-chunk-response'\n\trequestId: string\n\t/** The chunk bytes, or null when the responder does not hold that hash. */\n\tbytes: Uint8Array | null\n}\nexport type ChunkMessage = ChunkRequestMessage | ChunkResponseMessage\n\n/**\n * A bidirectional message port carrying {@link ChunkMessage}s. Implemented over\n * the sync connection in production; `createChunkPortPair` provides an in-memory\n * duplex pair for tests.\n */\nexport interface ChunkMessagePort {\n\tsend(message: ChunkMessage): void\n\t/** Register a handler for incoming messages. Multiple handlers are allowed. */\n\tonMessage(handler: (message: ChunkMessage) => void): void\n}\n\n/** A {@link ChunkProvider} that fetches chunks over a message port. */\nexport interface RemoteChunkProvider extends ChunkProvider {\n\t/** Number of requests still awaiting a response (for diagnostics/tests). */\n\tpendingCount(): number\n}\n\n/**\n * Create a {@link ChunkProvider} that requests chunks over a message port,\n * correlating each answer to its request and timing out a stalled request so a\n * dropped response cannot hang a transfer forever (the transfer is resumable, so\n * a timed-out request can simply be retried).\n *\n * @param port - The message port to the peer that holds the blob\n * @param options.timeoutMs - Per-request timeout (default 30s)\n */\nexport function createRemoteChunkProvider(\n\tport: ChunkMessagePort,\n\toptions: { timeoutMs?: number } = {},\n): RemoteChunkProvider {\n\tconst timeoutMs = options.timeoutMs ?? 30_000\n\tconst pending = new Map<\n\t\tstring,\n\t\t{\n\t\t\tresolve: (bytes: Uint8Array | null) => void\n\t\t\treject: (error: Error) => void\n\t\t\ttimer: ReturnType<typeof setTimeout>\n\t\t}\n\t>()\n\n\tport.onMessage((message) => {\n\t\tif (message.type !== 'blob-chunk-response') {\n\t\t\treturn\n\t\t}\n\t\tconst entry = pending.get(message.requestId)\n\t\tif (!entry) {\n\t\t\treturn\n\t\t}\n\t\tpending.delete(message.requestId)\n\t\tclearTimeout(entry.timer)\n\t\tentry.resolve(message.bytes)\n\t})\n\n\treturn {\n\t\tpendingCount: () => pending.size,\n\t\tgetChunk(hash: string): Promise<Uint8Array | null> {\n\t\t\tconst requestId = generateUUIDv7()\n\t\t\treturn new Promise<Uint8Array | null>((resolve, reject) => {\n\t\t\t\tconst timer = setTimeout(() => {\n\t\t\t\t\tpending.delete(requestId)\n\t\t\t\t\treject(new Error(`Blob chunk request for ${hash} timed out after ${timeoutMs}ms`))\n\t\t\t\t}, timeoutMs)\n\t\t\t\tpending.set(requestId, { resolve, reject, timer })\n\t\t\t\tport.send({ type: 'blob-chunk-request', requestId, hash })\n\t\t\t})\n\t\t},\n\t}\n}\n\n/**\n * Serve blob chunk requests arriving on a message port from a blob store. Answers\n * each `blob-chunk-request` with the bytes for that hash, or null when the store\n * does not hold it. Returns nothing; attach it once per connection.\n *\n * @param port - The message port from the peer requesting chunks\n * @param blobStore - The store to serve chunks from (keyed by chunk hash)\n */\nexport function serveBlobChunks(\n\tport: ChunkMessagePort,\n\tblobStore: ContentAddressedBlobStore,\n): void {\n\tport.onMessage((message) => {\n\t\tif (message.type !== 'blob-chunk-request') {\n\t\t\treturn\n\t\t}\n\t\tvoid blobStore.get(message.hash).then(\n\t\t\t(bytes) => {\n\t\t\t\tport.send({ type: 'blob-chunk-response', requestId: message.requestId, bytes })\n\t\t\t},\n\t\t\t() => {\n\t\t\t\t// Integrity failure or read error: report as not-held rather than\n\t\t\t\t// crashing the connection. The requester treats null as unavailable.\n\t\t\t\tport.send({ type: 'blob-chunk-response', requestId: message.requestId, bytes: null })\n\t\t\t},\n\t\t)\n\t})\n}\n\n/**\n * Create a connected in-memory pair of {@link ChunkMessagePort}s. Messages sent\n * on one arrive on the other, asynchronously (next microtask) so the pair models\n * a real transport rather than re-entrant synchronous delivery. For tests.\n */\nexport function createChunkPortPair(): { a: ChunkMessagePort; b: ChunkMessagePort } {\n\tconst handlersA: Array<(m: ChunkMessage) => void> = []\n\tconst handlersB: Array<(m: ChunkMessage) => void> = []\n\n\tconst a: ChunkMessagePort = {\n\t\tsend(message) {\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tfor (const handler of handlersB) {\n\t\t\t\t\thandler(message)\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\tonMessage(handler) {\n\t\t\thandlersA.push(handler)\n\t\t},\n\t}\n\tconst b: ChunkMessagePort = {\n\t\tsend(message) {\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tfor (const handler of handlersA) {\n\t\t\t\t\thandler(message)\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\tonMessage(handler) {\n\t\t\thandlersB.push(handler)\n\t\t},\n\t}\n\treturn { a, b }\n}\n"],"mappings":"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","names":["import_core","import_core","import_core","import_core","encodeSection","encodeJsonSection","readUint32","parseSections","findSection","computeSha256","readAllOperations","import_core","import_core","import_core","import_core","import_core","import_core","import_core","import_core","QueryError","propName","import_core","import_core","import_core","import_core","import_internal","import_core","import_core","existing","readAuditTraces","import_core","Y","TEXT_KEY","snapshot","import_core","import_core","import_core","import_core","import_core","import_core","import_core","import_core"]}
|