@korajs/server 1.0.0-beta.11 → 1.0.0-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/logging/structured-logger.ts","../src/apply/rejection-taxonomy.ts","../src/store/memory-server-store.ts","../src/store/materialization.ts","../src/store/postgres-server-store.ts","../src/store/drizzle-pg-schema.ts","../src/store/sqlite-server-store.ts","../src/store/drizzle-schema.ts","../src/transport/http-server-transport.ts","../src/transport/ws-server-transport.ts","../src/session/client-session.ts","../src/apply/apply-server-operation.ts","../src/constraints/operation-constraint-validator.ts","../src/constraints/server-constraint-context.ts","../src/constraints/server-referential-context.ts","../src/apply/server-side-effect-operation.ts","../src/auth/no-auth.ts","../src/scopes/resolve-session-scopes.ts","../src/scopes/server-scope-filter.ts","../src/session/operation-validation.ts","../src/session/session-operation-limits.ts","../src/server/kora-sync-server.ts","../src/awareness/awareness-relay.ts","../src/diagnostics/server-metrics-collector.ts","../src/richtext/blob-chunk-relay.ts","../src/richtext/yjs-doc-relay.ts","../src/server/route-context.ts","../src/apply/route-predicate.ts","../src/auth/token-auth.ts","../src/auth/kora-auth-provider.ts","../src/auth/mixed-auth-provider.ts","../src/server/create-server.ts","../src/server/production-server.ts"],"sourcesContent":["/**\n * Log severity levels.\n */\nexport type LogLevel = 'info' | 'warn' | 'error'\n\n/**\n * A structured log entry with timestamp and metadata.\n */\nexport interface LogEntry {\n\ttimestamp: number\n\tlevel: LogLevel\n\tevent: string\n\tsessionId?: string\n\tnodeId?: string\n\tduration?: number\n\tcount?: number\n\tbytes?: number\n\terror?: string\n\tdetails?: Record<string, unknown>\n}\n\n/**\n * Logger interface for structured logging.\n * Implementations control output format and destination.\n */\nexport interface Logger {\n\tlog(entry: LogEntry): void\n\tchild?(context: Partial<LogEntry>): Logger\n}\n\n/**\n * Serializes LogEntry to a single log line.\n */\nexport type LogSerializer = (entry: LogEntry) => string\n\nfunction defaultJsonSerializer(entry: LogEntry): string {\n\treturn JSON.stringify(entry)\n}\n\nfunction defaultPrettySerializer(entry: LogEntry): string {\n\tconst time = new Date(entry.timestamp).toISOString().slice(11, 23)\n\tconst levelTag = { info: ' INFO', warn: ' WARN', error: 'ERROR' }[entry.level]\n\tconst node = entry.nodeId ? ` [${entry.nodeId.slice(0, 8)}]` : ''\n\tconst session = entry.sessionId ? ` [session:${entry.sessionId.slice(0, 8)}]` : ''\n\tconst dur = entry.duration !== undefined ? ` +${entry.duration}ms` : ''\n\tconst count = entry.count !== undefined ? ` (${entry.count})` : ''\n\tconst err = entry.error ? ` — ${entry.error}` : ''\n\treturn `${time} ${levelTag}${node}${session} ${entry.event}${count}${dur}${err}`\n}\n\n/**\n * Creates a JSON-lines logger that writes to stdout/stderr.\n * Suitable for production use where log aggregators (Datadog, Loki, etc.) consume JSON.\n */\nexport function createJsonLogger(writer?: {\n\tinfo: (s: string) => void\n\terror: (s: string) => void\n}): Logger {\n\tconst out = writer ?? {\n\t\tinfo: (s: string) => process.stdout.write(`${s}\\n`),\n\t\terror: (s: string) => process.stderr.write(`${s}\\n`),\n\t}\n\n\treturn {\n\t\tlog(entry: LogEntry): void {\n\t\t\tconst line = defaultJsonSerializer(entry)\n\t\t\tif (entry.level === 'error') {\n\t\t\t\tout.error(line)\n\t\t\t} else {\n\t\t\t\tout.info(line)\n\t\t\t}\n\t\t},\n\t}\n}\n\n/**\n * Creates a pretty-printed logger for development use.\n * Writes human-readable colored output to the terminal.\n */\nexport function createPrettyLogger(writer?: { write: (s: string) => void }): Logger {\n\tconst out = writer ?? { write: (s: string) => process.stdout.write(`${s}\\n`) }\n\n\treturn {\n\t\tlog(entry: LogEntry): void {\n\t\t\tout.write(defaultPrettySerializer(entry))\n\t\t},\n\t}\n}\n\n/**\n * A logger that discards all entries (for testing or when logging is disabled).\n */\nexport function createSilentLogger(): Logger {\n\treturn { log() {} }\n}\n\n/**\n * Creates a logger based on the NODE_ENV environment variable.\n * - production: JSON lines to stdout/stderr\n * - test: silent\n * - otherwise: pretty-printed to stdout\n */\nexport function createDefaultLogger(): Logger {\n\tswitch (process.env.NODE_ENV) {\n\t\tcase 'production':\n\t\t\treturn createJsonLogger()\n\t\tcase 'test':\n\t\t\treturn createSilentLogger()\n\t\tdefault:\n\t\t\treturn createPrettyLogger()\n\t}\n}\n","/**\n * Shared vocabulary for why the server refused an operation.\n *\n * The `retriable` flag answers one question for the caller: is it worth\n * submitting this SAME operation again later?\n *\n * - `true` — the rejection is transient (for example a rate limit). The\n * identical operation may succeed once the condition clears, so a\n * client is right to back off and retry the same bytes.\n * - `false` — the rejection is permanent for the operation as written (a\n * constraint violation, a referential conflict, a malformed\n * mutation, a scope violation). Resubmitting the same bytes will\n * always fail; the caller must change the operation or give up.\n *\n * This is deliberately defined once, in one place, so the trusted server\n * data-plane (route context / `server.kora`) and the untrusted client-ingestion\n * path speak the same language. `retriable` (this spelling) matches the wire\n * `ErrorMessage.retriable` field the sync protocol already ships, so a single\n * flag flows from the pipeline out to connected clients unchanged.\n */\nexport interface OperationRejection {\n\t/** Stable, machine-readable reason code (for example `CONSTRAINT_VIOLATION`). */\n\tcode: string\n\t/** Human-readable explanation with enough context to debug without reproduction. */\n\tmessage: string\n\t/** Whether resubmitting the identical operation may later succeed. */\n\tretriable: boolean\n}\n\n/**\n * Reason codes whose underlying condition is transient, so the identical\n * operation may succeed on a later attempt.\n *\n * Everything NOT listed here is treated as permanent. Permanent is the safe\n * default: a client should never be told to keep hammering a genuinely invalid\n * operation, so a new code is non-retriable until it is deliberately added here.\n *\n * `RATE_LIMIT` is the code the session emits when a client exceeds its\n * per-minute operation budget (see `client-session.ts`).\n */\nexport const RETRIABLE_REJECTION_CODES: ReadonlySet<string> = new Set(['RATE_LIMIT'])\n\n/**\n * Classify a reason code as retriable (transient) or not (permanent).\n *\n * @param code - A rejection reason code.\n * @returns `true` when resubmitting the identical operation may later succeed.\n */\nexport function isRetriableRejection(code: string): boolean {\n\treturn RETRIABLE_REJECTION_CODES.has(code)\n}\n","import type { Operation, SchemaDefinition, VersionVector } from '@korajs/core'\nimport { generateUUIDv7 } from '@korajs/core'\nimport type { ApplyResult } from '@korajs/sync'\nimport {\n\tdeserializeFieldValue,\n\treplayOperationsForRecord,\n\tserializeFieldValue,\n\tvalidateFieldName,\n} from './materialization'\nimport type {\n\tCollectionQueryOptions,\n\tDeliveredOperation,\n\tMaterializedRecord,\n\tServerStore,\n} from './server-store'\n\n/**\n * In-memory server store for testing and quick prototyping.\n * Not suitable for production — data does not survive process restart.\n *\n * When a schema is set via setSchema(), maintains materialized records\n * in-memory for efficient queries.\n */\nexport class MemoryServerStore implements ServerStore {\n\tprivate readonly nodeId: string\n\tprivate readonly operations: Operation[] = []\n\tprivate readonly operationIndex = new Map<string, Operation>()\n\tprivate readonly versionVector: Map<string, number> = new Map()\n\t/**\n\t * Server-assigned delivery sequence per operation id. Single-process, so a plain\n\t * counter incremented at insert time gives commit-order delivery sequence with no\n\t * gaps. `operations` is kept in insertion (== delivery) order, so a delivery scan\n\t * is a forward walk.\n\t */\n\tprivate readonly deliverySeqByOpId = new Map<string, number>()\n\tprivate deliverySeqCounter = 0\n\tprivate schema: SchemaDefinition | null = null\n\n\t/** Materialized records: collection -> recordId -> record data */\n\tprivate readonly materializedRecords = new Map<string, Map<string, MaterializedRecord>>()\n\n\tprivate closed = false\n\n\tconstructor(nodeId?: string) {\n\t\tthis.nodeId = nodeId ?? generateUUIDv7()\n\t}\n\n\tgetVersionVector(): VersionVector {\n\t\treturn new Map(this.versionVector)\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.nodeId\n\t}\n\n\tgetSchema(): SchemaDefinition | null {\n\t\treturn this.schema\n\t}\n\n\tasync setSchema(schema: SchemaDefinition): Promise<void> {\n\t\tthis.assertOpen()\n\t\tthis.schema = schema\n\n\t\t// Initialize collection maps\n\t\tfor (const collectionName of Object.keys(schema.collections)) {\n\t\t\tif (!this.materializedRecords.has(collectionName)) {\n\t\t\t\tthis.materializedRecords.set(collectionName, new Map())\n\t\t\t}\n\t\t}\n\n\t\t// Backfill from existing operations\n\t\tthis.backfillAllCollections()\n\t}\n\n\tasync applyRemoteOperation(op: Operation): Promise<ApplyResult> {\n\t\tthis.assertOpen()\n\n\t\t// Content-addressed dedup: same id = same content\n\t\tif (this.operationIndex.has(op.id)) {\n\t\t\treturn 'duplicate'\n\t\t}\n\n\t\tthis.operations.push(op)\n\t\tthis.operationIndex.set(op.id, op)\n\n\t\t// Assign the next delivery sequence in commit order (single-process: no race).\n\t\tthis.deliverySeqCounter += 1\n\t\tthis.deliverySeqByOpId.set(op.id, this.deliverySeqCounter)\n\n\t\t// Advance version vector\n\t\tconst currentSeq = this.versionVector.get(op.nodeId) ?? 0\n\t\tif (op.sequenceNumber > currentSeq) {\n\t\t\tthis.versionVector.set(op.nodeId, op.sequenceNumber)\n\t\t}\n\n\t\t// Dual-write: update materialized records if schema is set\n\t\tif (this.schema?.collections[op.collection]) {\n\t\t\tthis.rebuildMaterializedRecord(op.collection, op.recordId)\n\t\t}\n\n\t\treturn 'applied'\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\n\t\treturn this.operations\n\t\t\t.filter(\n\t\t\t\t(op) => op.nodeId === nodeId && op.sequenceNumber >= fromSeq && op.sequenceNumber <= toSeq,\n\t\t\t)\n\t\t\t.sort((a, b) => a.sequenceNumber - b.sequenceNumber)\n\t}\n\n\tasync getOperationCount(): Promise<number> {\n\t\tthis.assertOpen()\n\t\treturn this.operations.length\n\t}\n\n\tasync getMaxDeliverySequence(): Promise<number> {\n\t\tthis.assertOpen()\n\t\treturn this.deliverySeqCounter\n\t}\n\n\tasync getOperationsAfterDelivery(\n\t\tafterDeliverySequence: number,\n\t\tlimit: number,\n\t): Promise<DeliveredOperation[]> {\n\t\tthis.assertOpen()\n\t\tconst result: DeliveredOperation[] = []\n\t\tif (limit <= 0) return result\n\t\t// operations is in delivery order, so once entries exceed the cursor they all do;\n\t\t// the guard on each entry keeps this correct even if that invariant ever weakens.\n\t\tfor (const op of this.operations) {\n\t\t\tconst deliverySequence = this.deliverySeqByOpId.get(op.id) ?? 0\n\t\t\tif (deliverySequence > afterDeliverySequence) {\n\t\t\t\tresult.push({ operation: op, deliverySequence })\n\t\t\t\tif (result.length >= limit) break\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\tasync materializeCollection(collection: string): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\n\t\t// Fast path: if schema is set, read from materialized records\n\t\tif (this.schema?.collections[collection]) {\n\t\t\treturn this.queryCollection(collection)\n\t\t}\n\n\t\t// Fallback: replay operations\n\t\treturn this.materializeFromOps(collection)\n\t}\n\n\tasync queryCollection(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions,\n\t): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\t// Validate field names\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (options?.where) {\n\t\t\tfor (const key of Object.keys(options.where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\t\tif (options?.orderBy) {\n\t\t\tvalidateFieldName(collection, options.orderBy, schema)\n\t\t}\n\n\t\tconst collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) return []\n\n\t\t// Get all non-deleted records\n\t\tlet records = Array.from(collectionMap.values()).filter((r) => {\n\t\t\tif (!options?.includeDeleted && r._deleted === 1) return false\n\t\t\treturn true\n\t\t})\n\n\t\t// Apply WHERE filters\n\t\tif (options?.where) {\n\t\t\tfor (const [key, value] of Object.entries(options.where)) {\n\t\t\t\trecords = records.filter((r) => r[key] === value)\n\t\t\t}\n\t\t}\n\n\t\t// Apply ORDER BY\n\t\tif (options?.orderBy) {\n\t\t\tconst field = options.orderBy\n\t\t\tconst dir = options.orderDirection === 'desc' ? -1 : 1\n\t\t\trecords.sort((a, b) => {\n\t\t\t\tconst aVal = a[field]\n\t\t\t\tconst bVal = b[field]\n\t\t\t\tif (aVal === bVal) return 0\n\t\t\t\tif (aVal === null || aVal === undefined) return 1\n\t\t\t\tif (bVal === null || bVal === undefined) return -1\n\t\t\t\treturn aVal < bVal ? -1 * dir : 1 * dir\n\t\t\t})\n\t\t}\n\n\t\t// Apply OFFSET\n\t\tif (options?.offset !== undefined) {\n\t\t\trecords = records.slice(options.offset)\n\t\t}\n\n\t\t// Apply LIMIT\n\t\tif (options?.limit !== undefined) {\n\t\t\trecords = records.slice(0, options.limit)\n\t\t}\n\n\t\t// Return clean copies without internal fields\n\t\treturn records.map((r) => {\n\t\t\tconst clean: MaterializedRecord = { id: r.id }\n\t\t\tconst collectionDef = (this.schema as SchemaDefinition).collections[\n\t\t\t\tcollection\n\t\t\t] as NonNullable<SchemaDefinition['collections'][string]>\n\t\t\tfor (const fieldName of Object.keys(collectionDef.fields)) {\n\t\t\t\tif (fieldName in r) {\n\t\t\t\t\tclean[fieldName] = r[fieldName]\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ('_created_at' in r) clean._created_at = r._created_at\n\t\t\tif ('_updated_at' in r) clean._updated_at = r._updated_at\n\t\t\treturn clean\n\t\t})\n\t}\n\n\tasync findRecord(collection: string, id: string): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) return null\n\n\t\tconst record = collectionMap.get(id)\n\t\tif (!record || record._deleted === 1) return null\n\n\t\t// Return clean copy\n\t\tconst clean: MaterializedRecord = { id: record.id }\n\t\tconst collectionDef = (this.schema as SchemaDefinition).collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tfor (const fieldName of Object.keys(collectionDef.fields)) {\n\t\t\tif (fieldName in record) {\n\t\t\t\tclean[fieldName] = record[fieldName]\n\t\t\t}\n\t\t}\n\t\tif ('_created_at' in record) clean._created_at = record._created_at\n\t\tif ('_updated_at' in record) clean._updated_at = record._updated_at\n\t\treturn clean\n\t}\n\n\tasync countCollection(collection: string, where?: Record<string, unknown>): Promise<number> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (where) {\n\t\t\tfor (const key of Object.keys(where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\n\t\tconst collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) return 0\n\n\t\tlet count = 0\n\t\tfor (const record of collectionMap.values()) {\n\t\t\tif (record._deleted === 1) continue\n\t\t\tif (where) {\n\t\t\t\tlet matches = true\n\t\t\t\tfor (const [key, value] of Object.entries(where)) {\n\t\t\t\t\tif (record[key] !== value) {\n\t\t\t\t\t\tmatches = false\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!matches) continue\n\t\t\t}\n\t\t\tcount++\n\t\t}\n\t\treturn count\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true\n\t}\n\n\t/**\n\t * Wipes all in-memory state. For tests and E2E isolation only.\n\t */\n\tresetForTests(): void {\n\t\tthis.assertOpen()\n\t\tthis.operations.length = 0\n\t\tthis.operationIndex.clear()\n\t\tthis.versionVector.clear()\n\t\tthis.materializedRecords.clear()\n\t\tthis.schema = null\n\t}\n\n\tasync exportBackup(): Promise<Uint8Array> {\n\t\tthis.assertOpen()\n\t\tconst { buildServerBackup } = await import('./server-backup')\n\t\treturn buildServerBackup(this.nodeId, this.operations, this.versionVector)\n\t}\n\n\tasync importBackup(\n\t\tdata: Uint8Array,\n\t\tmerge?: boolean,\n\t): Promise<{ operationsRestored: number; success: boolean }> {\n\t\tthis.assertOpen()\n\t\tconst { parseServerBackup } = await import('./server-backup')\n\t\tconst { operations, versionVector } = parseServerBackup(data)\n\n\t\tif (merge) {\n\t\t\tlet restored = 0\n\t\t\tfor (const op of operations) {\n\t\t\t\tconst result = await this.applyRemoteOperation(op)\n\t\t\t\tif (result === 'applied') restored++\n\t\t\t}\n\t\t\treturn { operationsRestored: restored, success: true }\n\t\t}\n\n\t\t// Replace mode: clear and reload\n\t\tthis.operations.length = 0\n\t\tthis.operationIndex.clear()\n\t\tthis.versionVector.clear()\n\t\tthis.deliverySeqByOpId.clear()\n\t\tthis.deliverySeqCounter = 0\n\n\t\tfor (const [nid, seq] of versionVector) {\n\t\t\tthis.versionVector.set(nid, seq)\n\t\t}\n\n\t\tfor (const op of operations) {\n\t\t\tthis.operations.push(op)\n\t\t\tthis.operationIndex.set(op.id, op)\n\t\t\t// Re-assign delivery sequence in backup order (the order ops were shipped).\n\t\t\tthis.deliverySeqCounter += 1\n\t\t\tthis.deliverySeqByOpId.set(op.id, this.deliverySeqCounter)\n\n\t\t\t// Update materialized records if schema is set\n\t\t\tif (this.schema?.collections[op.collection]) {\n\t\t\t\tthis.rebuildMaterializedRecord(op.collection, op.recordId)\n\t\t\t}\n\t\t}\n\n\t\treturn { operationsRestored: operations.length, success: true }\n\t}\n\n\t// --- Testing helpers (not on interface) ---\n\n\t/**\n\t * Get all stored operations (for test assertions).\n\t */\n\tgetAllOperations(): Operation[] {\n\t\treturn [...this.operations]\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Materialization internals\n\t// ---------------------------------------------------------------------------\n\n\tprivate rebuildMaterializedRecord(collection: string, recordId: string): void {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (!collectionDef) return\n\n\t\t// Get or create collection map\n\t\tlet collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) {\n\t\t\tcollectionMap = new Map()\n\t\t\tthis.materializedRecords.set(collection, collectionMap)\n\t\t}\n\n\t\t// Get all ops for this record in HLC total order (wallTime, logical, nodeId)\n\t\t// so atomic composition and LWW converge like the merge engine.\n\t\tconst recordOps = this.operations\n\t\t\t.filter((op) => op.collection === collection && op.recordId === recordId)\n\t\t\t.sort((a, b) => {\n\t\t\t\tif (a.timestamp.wallTime !== b.timestamp.wallTime)\n\t\t\t\t\treturn a.timestamp.wallTime - b.timestamp.wallTime\n\t\t\t\tif (a.timestamp.logical !== b.timestamp.logical)\n\t\t\t\t\treturn a.timestamp.logical - b.timestamp.logical\n\t\t\t\treturn a.timestamp.nodeId < b.timestamp.nodeId\n\t\t\t\t\t? -1\n\t\t\t\t\t: a.timestamp.nodeId > b.timestamp.nodeId\n\t\t\t\t\t\t? 1\n\t\t\t\t\t\t: 0\n\t\t\t})\n\n\t\tconst parsedOps = recordOps.map((op) => ({\n\t\t\ttype: op.type,\n\t\t\tdata: op.data,\n\t\t\tatomicOps: op.atomicOps ?? null,\n\t\t}))\n\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\tif (recordData) {\n\t\t\tconst createdAt =\n\t\t\t\trecordOps.length > 0 ? (recordOps[0] as Operation).timestamp.wallTime : Date.now()\n\t\t\tconst updatedAt =\n\t\t\t\trecordOps.length > 0\n\t\t\t\t\t? (recordOps[recordOps.length - 1] as Operation).timestamp.wallTime\n\t\t\t\t\t: Date.now()\n\n\t\t\tconst materialized: MaterializedRecord = {\n\t\t\t\tid: recordId,\n\t\t\t\t...recordData,\n\t\t\t\t_created_at: createdAt,\n\t\t\t\t_updated_at: updatedAt,\n\t\t\t\t_deleted: 0,\n\t\t\t}\n\t\t\tcollectionMap.set(recordId, materialized)\n\t\t} else {\n\t\t\t// Record was deleted\n\t\t\tconst existing = collectionMap.get(recordId)\n\t\t\tif (existing) {\n\t\t\t\texisting._deleted = 1\n\t\t\t\texisting._updated_at = Date.now()\n\t\t\t} else {\n\t\t\t\tcollectionMap.set(recordId, {\n\t\t\t\t\tid: recordId,\n\t\t\t\t\t_deleted: 1,\n\t\t\t\t\t_created_at: Date.now(),\n\t\t\t\t\t_updated_at: Date.now(),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate backfillAllCollections(): void {\n\t\tif (!this.schema) return\n\n\t\t// Get all unique (collection, recordId) pairs\n\t\tconst recordKeys = new Set<string>()\n\t\tfor (const op of this.operations) {\n\t\t\tif (this.schema.collections[op.collection]) {\n\t\t\t\trecordKeys.add(`${op.collection}:::${op.recordId}`)\n\t\t\t}\n\t\t}\n\n\t\tfor (const key of recordKeys) {\n\t\t\tconst [collection, recordId] = key.split(':::') as [string, string]\n\t\t\tthis.rebuildMaterializedRecord(collection, recordId)\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Fallback materialization (no schema)\n\t// ---------------------------------------------------------------------------\n\n\tprivate materializeFromOps(collection: string): MaterializedRecord[] {\n\t\tconst collectionOps = this.operations\n\t\t\t.filter((op) => op.collection === collection)\n\t\t\t.sort((a, b) => {\n\t\t\t\tif (a.timestamp.wallTime !== b.timestamp.wallTime)\n\t\t\t\t\treturn a.timestamp.wallTime - b.timestamp.wallTime\n\t\t\t\tif (a.timestamp.logical !== b.timestamp.logical)\n\t\t\t\t\treturn a.timestamp.logical - b.timestamp.logical\n\t\t\t\treturn a.sequenceNumber - b.sequenceNumber\n\t\t\t})\n\n\t\tconst records = new Map<string, Record<string, unknown>>()\n\t\tconst deleted = new Set<string>()\n\n\t\tfor (const op of collectionOps) {\n\t\t\tswitch (op.type) {\n\t\t\t\tcase 'insert':\n\t\t\t\t\tif (op.data) {\n\t\t\t\t\t\trecords.set(op.recordId, { id: op.recordId, ...op.data })\n\t\t\t\t\t\tdeleted.delete(op.recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'update':\n\t\t\t\t\tif (op.data) {\n\t\t\t\t\t\tconst existing = records.get(op.recordId) ?? { id: op.recordId }\n\t\t\t\t\t\trecords.set(op.recordId, { ...existing, ...op.data })\n\t\t\t\t\t\tdeleted.delete(op.recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'delete':\n\t\t\t\t\tdeleted.add(op.recordId)\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tfor (const id of deleted) {\n\t\t\trecords.delete(id)\n\t\t}\n\n\t\treturn Array.from(records.values()) as MaterializedRecord[]\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Assertions\n\t// ---------------------------------------------------------------------------\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) {\n\t\t\tthrow new Error('MemoryServerStore is closed')\n\t\t}\n\t}\n\n\tprivate assertSchema(): void {\n\t\tif (!this.schema) {\n\t\t\tthrow new Error(\n\t\t\t\t'Schema not set. Call setSchema() before using queryCollection/findRecord/countCollection.',\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate assertCollection(collection: string): void {\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (!schema.collections[collection]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${collection}\". Available: ${Object.keys(schema.collections).join(', ')}`,\n\t\t\t)\n\t\t}\n\t}\n}\n","import { StorageError, quoteIdent, replayOperationsForRecord } from '@korajs/core'\nimport type {\n\tCollectionDefinition,\n\tFieldDescriptor,\n\tReplayOperation,\n\tSchemaDefinition,\n} from '@korajs/core'\n\n// Re-exported so existing server-internal imports keep working; the implementation\n// now lives in @korajs/core so the client apply pipeline and the server materialize\n// records through the exact same atomic-aware fold.\nexport { replayOperationsForRecord }\nexport type { ReplayOperation }\n\n/**\n * SQL dialect for DDL generation.\n * SQLite and PostgreSQL differ in some column types.\n */\nexport type SqlDialect = 'sqlite' | 'postgres'\n\n/**\n * Map a Kora field kind to its SQL column type for the given dialect.\n */\nfunction fieldTypeToSql(descriptor: FieldDescriptor, dialect: SqlDialect): string {\n\tswitch (descriptor.kind) {\n\t\tcase 'string':\n\t\t\treturn 'TEXT'\n\t\tcase 'number':\n\t\t\treturn dialect === 'postgres' ? 'DOUBLE PRECISION' : 'REAL'\n\t\tcase 'boolean':\n\t\t\treturn 'INTEGER'\n\t\tcase 'enum':\n\t\t\treturn 'TEXT'\n\t\tcase 'timestamp':\n\t\t\treturn dialect === 'postgres' ? 'BIGINT' : 'INTEGER'\n\t\tcase 'array':\n\t\t\treturn dialect === 'postgres' ? 'JSONB' : 'TEXT'\n\t\tcase 'object':\n\t\t\treturn dialect === 'postgres' ? 'JSONB' : 'TEXT'\n\t\tcase 'json':\n\t\t\treturn dialect === 'postgres' ? 'JSONB' : 'TEXT'\n\t\tcase 'blob':\n\t\t\t// Content-addressed BlobRef metadata is stored as JSON; the bytes live\n\t\t\t// out of band, so the column is textual, not binary.\n\t\t\treturn 'TEXT'\n\t\tcase 'secret':\n\t\t\treturn 'TEXT'\n\t\tcase 'richtext':\n\t\t\treturn dialect === 'postgres' ? 'BYTEA' : 'BLOB'\n\t}\n}\n\nfunction sqlDefaultLiteral(value: unknown): string {\n\tif (value === null) return 'NULL'\n\tif (typeof value === 'string') return `'${value}'`\n\tif (typeof value === 'number') return String(value)\n\tif (typeof value === 'boolean') return value ? '1' : '0'\n\treturn `'${JSON.stringify(value)}'`\n}\n\n/**\n * Generate DDL statements for creating a materialized collection table.\n * Includes CREATE TABLE, safe ALTER TABLE for schema evolution, and indexes.\n *\n * @param name - Collection/table name\n * @param collection - Collection definition from the schema\n * @param dialect - SQL dialect ('sqlite' or 'postgres')\n * @returns Array of DDL SQL strings\n */\nexport function generateCollectionDDL(\n\tname: string,\n\tcollection: CollectionDefinition,\n\tdialect: SqlDialect,\n): string[] {\n\tconst statements: string[] = []\n\tconst columns: string[] = ['id TEXT PRIMARY KEY NOT NULL']\n\n\tfor (const [fieldName, descriptor] of Object.entries(collection.fields)) {\n\t\tconst sqlType = fieldTypeToSql(descriptor, dialect)\n\t\tlet colDef = `${quoteIdent(fieldName)} ${sqlType}`\n\t\tif (descriptor.defaultValue !== undefined) {\n\t\t\tcolDef += ` DEFAULT ${sqlDefaultLiteral(descriptor.defaultValue)}`\n\t\t}\n\t\tif (descriptor.kind === 'enum' && descriptor.enumValues) {\n\t\t\tconst values = descriptor.enumValues.map((v) => `'${v}'`).join(', ')\n\t\t\tcolDef += ` CHECK (${quoteIdent(fieldName)} IN (${values}))`\n\t\t}\n\t\tcolumns.push(colDef)\n\t}\n\n\tconst tsType = dialect === 'postgres' ? 'BIGINT' : 'INTEGER'\n\tcolumns.push(`_created_at ${tsType} NOT NULL DEFAULT 0`)\n\tcolumns.push(`_updated_at ${tsType} NOT NULL DEFAULT 0`)\n\tcolumns.push('_deleted INTEGER NOT NULL DEFAULT 0')\n\n\tstatements.push(`CREATE TABLE IF NOT EXISTS ${quoteIdent(name)} (\\n ${columns.join(',\\n ')}\\n)`)\n\n\t// Safe ALTER TABLE for adding new columns to existing tables\n\tfor (const [fieldName, descriptor] of Object.entries(collection.fields)) {\n\t\tconst sqlType = fieldTypeToSql(descriptor, dialect)\n\t\tlet colDef = `${quoteIdent(fieldName)} ${sqlType}`\n\t\tif (descriptor.defaultValue !== undefined) {\n\t\t\tcolDef += ` DEFAULT ${sqlDefaultLiteral(descriptor.defaultValue)}`\n\t\t}\n\t\tstatements.push(`--kora:safe-alter\\nALTER TABLE ${quoteIdent(name)} ADD COLUMN ${colDef}`)\n\t}\n\n\t// User-defined indexes from schema. The index NAME stays unquoted (only ever\n\t// created/dropped by this construction); the table and column are quoted.\n\tfor (const indexField of collection.indexes) {\n\t\tstatements.push(\n\t\t\t`CREATE INDEX IF NOT EXISTS idx_${name}_${indexField} ON ${quoteIdent(name)} (${quoteIdent(indexField)})`,\n\t\t)\n\t}\n\n\t// Always index _deleted for efficient soft-delete filtering\n\tstatements.push(\n\t\t`CREATE INDEX IF NOT EXISTS idx_${name}__deleted ON ${quoteIdent(name)} (_deleted)`,\n\t)\n\n\treturn statements\n}\n\n/**\n * Generate all collection table DDL from a full schema.\n */\nexport function generateAllCollectionDDL(schema: SchemaDefinition, dialect: SqlDialect): string[] {\n\tconst statements: string[] = []\n\tfor (const [name, collection] of Object.entries(schema.collections)) {\n\t\tstatements.push(...generateCollectionDDL(name, collection, dialect))\n\t}\n\treturn statements\n}\n\nconst BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nconst BASE64_REVERSE: ReadonlyMap<string, number> = new Map(\n\tArray.from(BASE64_ALPHABET, (char, index) => [char, index]),\n)\n\nfunction base64ToBytes(base64: string): Uint8Array {\n\tconst cleaned = base64.replace(/=+$/, '')\n\tconst out = new Uint8Array(Math.floor((cleaned.length * 6) / 8))\n\tlet buffer = 0\n\tlet bits = 0\n\tlet index = 0\n\tfor (const char of cleaned) {\n\t\tconst value = BASE64_REVERSE.get(char)\n\t\tif (value === undefined) {\n\t\t\tthrow new StorageError(`Invalid base64 character \"${char}\" in tagged richtext value`, {\n\t\t\t\tchar,\n\t\t\t})\n\t\t}\n\t\tbuffer = (buffer << 6) | value\n\t\tbits += 6\n\t\tif (bits >= 8) {\n\t\t\tbits -= 8\n\t\t\tout[index] = (buffer >> bits) & 0xff\n\t\t\tindex += 1\n\t\t}\n\t}\n\treturn out\n}\n\n/**\n * Decode a richtext op-data value to something a BLOB/BYTEA column accepts.\n * Client operations carry binary richtext as the canonical tagged\n * `{ $koraBytes: base64 }` form (raw bytes cannot survive the JSON `dataJson`\n * wire field). The server cannot import the store package (dependency rules),\n * so the tiny base64 decode is duplicated here rather than shared.\n * Strings and byte views pass through unchanged.\n */\nfunction decodeRichtextColumnValue(value: unknown): unknown {\n\tif (typeof value !== 'object' || value === null || ArrayBuffer.isView(value)) {\n\t\treturn value\n\t}\n\tconst record = value as Record<string, unknown>\n\tif (Object.keys(record).length === 1 && typeof record.$koraBytes === 'string') {\n\t\treturn base64ToBytes(record.$koraBytes)\n\t}\n\t// Pre-fix operations serialized raw Uint8Arrays as numeric-key objects;\n\t// reconstruct the bytes so old dev databases keep materializing.\n\tconst keys = Object.keys(record)\n\tif (keys.length > 0 && keys.every((k, i) => k === String(i) && typeof record[k] === 'number')) {\n\t\tconst bytes = new Uint8Array(keys.length)\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tconst byte = record[String(i)]\n\t\t\tbytes[i] = typeof byte === 'number' ? byte & 0xff : 0\n\t\t}\n\t\treturn bytes\n\t}\n\treturn value\n}\n\n/**\n * Serialize a field value for SQL storage.\n * Arrays become JSON strings, booleans become 0/1, etc.\n */\nexport function serializeFieldValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tif (value === null || value === undefined) return null\n\tswitch (descriptor.kind) {\n\t\tcase 'array':\n\t\tcase 'object':\n\t\tcase 'json':\n\t\tcase 'blob':\n\t\t\treturn typeof value === 'string' ? value : JSON.stringify(value)\n\t\tcase 'boolean':\n\t\t\treturn value ? 1 : 0\n\t\tcase 'richtext':\n\t\t\treturn decodeRichtextColumnValue(value)\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n\n/**\n * Deserialize a field value from SQL storage back to JavaScript types.\n */\nexport function deserializeFieldValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tif (value === null || value === undefined) return null\n\tswitch (descriptor.kind) {\n\t\tcase 'array':\n\t\tcase 'object':\n\t\tcase 'json':\n\t\tcase 'blob':\n\t\t\treturn typeof value === 'string' ? JSON.parse(value) : value\n\t\tcase 'boolean':\n\t\t\treturn value === 1 || value === true\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n\n/**\n * Validate that a field name is a valid column in the given collection schema.\n * Includes system fields (id, _created_at, _updated_at, _deleted).\n */\nexport function validateFieldName(\n\tcollectionName: string,\n\tfieldName: string,\n\tschema: SchemaDefinition,\n): void {\n\tconst collection = schema.collections[collectionName]\n\tif (!collection) {\n\t\tthrow new Error(`Unknown collection: ${collectionName}`)\n\t}\n\tconst validFields = new Set([\n\t\t'id',\n\t\t'_created_at',\n\t\t'_updated_at',\n\t\t'_deleted',\n\t\t...Object.keys(collection.fields),\n\t])\n\tif (!validFields.has(fieldName)) {\n\t\tthrow new Error(\n\t\t\t`Invalid field name \"${fieldName}\" for collection \"${collectionName}\". ` +\n\t\t\t\t`Valid fields: ${Array.from(validFields).join(', ')}`,\n\t\t)\n\t}\n}\n","import type {\n\tAtomicOp,\n\tHLCTimestamp,\n\tOperation,\n\tSchemaDefinition,\n\tTimeSource,\n\tVersionVector,\n} from '@korajs/core'\nimport { HybridLogicalClock, generateUUIDv7, quoteIdent } from '@korajs/core'\nimport type { ApplyResult } from '@korajs/sync'\nimport type { SQL } from 'drizzle-orm'\nimport { and, asc, between, count, desc, eq, gt, sql } from 'drizzle-orm'\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'\nimport { pgOperations, pgSyncState } from './drizzle-pg-schema'\nimport {\n\tdeserializeFieldValue,\n\tgenerateAllCollectionDDL,\n\treplayOperationsForRecord,\n\tserializeFieldValue,\n\tvalidateFieldName,\n} from './materialization'\nimport type {\n\tCollectionQueryOptions,\n\tConditionalApplyInput,\n\tConditionalApplyResult,\n\tDeliveredOperation,\n\tMaterializedRecord,\n\tServerStore,\n} from './server-store'\n\n/**\n * PostgreSQL-backed server store using Drizzle ORM.\n * All reads and writes go through Drizzle's typed query builder.\n *\n * When a schema is set via setSchema(), also maintains materialized\n * collection tables for efficient indexed queries (dual-write).\n */\nexport class PostgresServerStore implements ServerStore {\n\tprivate readonly nodeId: string\n\tprivate readonly db: PostgresJsDatabase\n\tprivate readonly versionVector: VersionVector = new Map()\n\tprivate readonly ready: Promise<void>\n\tprivate schema: SchemaDefinition | null = null\n\tprivate closed = false\n\t/**\n\t * Monotonic counter for this node's server-originated sequence numbers. Lazily\n\t * seeded from the persisted version vector on first use, then advanced in memory\n\t * (a synchronous `++`, atomic on the single JS thread) so concurrent conditional\n\t * applies never receive the same number. Null means \"not yet seeded\"; reset to\n\t * null after a backup import so it re-seeds from the restored version vector.\n\t */\n\tprivate sequenceCounter: number | null = null\n\t/**\n\t * Time source for HLC timestamps on server-originated operations. Injectable so a\n\t * test can freeze wall-clock time and prove the conditional-apply ordering holds\n\t * under same-millisecond commits (the case the advisory lock and clock advance\n\t * exist to make correct). Defaults to the system clock in production.\n\t */\n\tprivate readonly timeSource: TimeSource\n\n\tconstructor(db: PostgresJsDatabase, nodeId?: string, timeSource?: TimeSource) {\n\t\tthis.db = db\n\t\tthis.nodeId = nodeId ?? generateUUIDv7()\n\t\tthis.timeSource = timeSource ?? { now: () => Date.now() }\n\t\tthis.ready = this.initialize()\n\t}\n\n\tgetVersionVector(): VersionVector {\n\t\tthis.assertOpen()\n\t\treturn new Map(this.versionVector)\n\t}\n\n\t/**\n\t * Atomically reserve this node's next server-operation sequence number. The\n\t * synchronous increment cannot interleave on the single JS thread, so two\n\t * concurrent conditional applies are always handed distinct numbers.\n\t */\n\treserveSequenceNumber(): number {\n\t\tif (this.sequenceCounter === null) {\n\t\t\tthis.sequenceCounter = this.versionVector.get(this.nodeId) ?? 0\n\t\t}\n\t\tthis.sequenceCounter += 1\n\t\treturn this.sequenceCounter\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.nodeId\n\t}\n\n\tgetSchema(): SchemaDefinition | null {\n\t\treturn this.schema\n\t}\n\n\tasync setSchema(schema: SchemaDefinition): Promise<void> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.schema = schema\n\n\t\t// Generate and execute DDL for all collection tables\n\t\tconst ddlStatements = generateAllCollectionDDL(schema, 'postgres')\n\t\tfor (const stmt of ddlStatements) {\n\t\t\tif (stmt.startsWith('--kora:safe-alter')) {\n\t\t\t\tconst alterSql = stmt.replace('--kora:safe-alter\\n', '')\n\t\t\t\ttry {\n\t\t\t\t\tawait this.db.execute(sql.raw(alterSql))\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// Ignore \"already exists\" errors from safe ALTER TABLE.\n\t\t\t\t\t// Drizzle wraps the actual DB error in e.cause, so check both.\n\t\t\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\t\t\tif (\n\t\t\t\t\t\t!msg.includes('already exists') &&\n\t\t\t\t\t\t!msg.includes('duplicate column') &&\n\t\t\t\t\t\t!causeMsg.includes('already exists') &&\n\t\t\t\t\t\t!causeMsg.includes('duplicate column')\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow e\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait this.db.execute(sql.raw(stmt))\n\t\t\t}\n\t\t}\n\n\t\t// Backfill materialized tables from existing operations\n\t\tawait this.backfillAllCollections()\n\t}\n\n\tasync applyRemoteOperation(op: Operation): Promise<ApplyResult> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\t// Content-addressed dedup check\n\t\tconst existing = await this.db\n\t\t\t.select({ id: pgOperations.id })\n\t\t\t.from(pgOperations)\n\t\t\t.where(eq(pgOperations.id, op.id))\n\t\t\t.limit(1)\n\n\t\tif (existing.length > 0) {\n\t\t\treturn 'duplicate'\n\t\t}\n\n\t\tconst now = Date.now()\n\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\t// Assign the delivery sequence in commit order (see nextDeliverySeq). A rare\n\t\t\t// concurrent duplicate insert below no-ops and simply leaves a harmless gap.\n\t\t\tconst deliverySeq = await this.nextDeliverySeq(tx)\n\t\t\tconst row = this.serializeOperation(op, now, deliverySeq)\n\n\t\t\t// Insert operation with dedup\n\t\t\tawait tx.insert(pgOperations).values(row).onConflictDoNothing({ target: pgOperations.id })\n\n\t\t\t// Upsert version vector: advance max sequence number with GREATEST\n\t\t\tawait tx\n\t\t\t\t.insert(pgSyncState)\n\t\t\t\t.values({\n\t\t\t\t\tnodeId: op.nodeId,\n\t\t\t\t\tmaxSequenceNumber: op.sequenceNumber,\n\t\t\t\t\tlastSeenAt: now,\n\t\t\t\t})\n\t\t\t\t.onConflictDoUpdate({\n\t\t\t\t\ttarget: pgSyncState.nodeId,\n\t\t\t\t\tset: {\n\t\t\t\t\t\tmaxSequenceNumber: sql`GREATEST(${pgSyncState.maxSequenceNumber}, ${op.sequenceNumber})`,\n\t\t\t\t\t\tlastSeenAt: sql`${now}`,\n\t\t\t\t\t},\n\t\t\t\t})\n\n\t\t\t// Dual-write: update materialized collection table if schema is set\n\t\t\tif (this.schema?.collections[op.collection]) {\n\t\t\t\tawait this.rebuildMaterializedRecord(tx, op.collection, op.recordId)\n\t\t\t}\n\t\t})\n\n\t\t// Update in-memory version vector cache\n\t\tconst currentMax = this.versionVector.get(op.nodeId) ?? 0\n\t\tif (op.sequenceNumber > currentMax) {\n\t\t\tthis.versionVector.set(op.nodeId, op.sequenceNumber)\n\t\t}\n\n\t\treturn 'applied'\n\t}\n\n\t/**\n\t * Conditionally apply operations atomically, serialized across server instances\n\t * on the target record via a transaction-scoped advisory lock. The lock makes\n\t * the read-decide-write cycle atomic against concurrent instances, so a cap\n\t * check like `responseCount < max` cannot be passed by two admissions at once.\n\t */\n\tasync applyConditional(input: ConditionalApplyInput): Promise<ConditionalApplyResult> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(input.target.collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[input.target.collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tconst lockKey = `kora:${input.target.collection}:${input.target.id}`\n\n\t\tconst result = await this.db.transaction(async (tx) => {\n\t\t\t// Serialize this target across every server instance sharing the database.\n\t\t\t// hashtextextended maps the key to the bigint pg_advisory_xact_lock expects;\n\t\t\t// the lock releases automatically when the transaction ends.\n\t\t\tawait tx.execute(sql`SELECT pg_advisory_xact_lock(hashtextextended(${lockKey}, 0))`)\n\n\t\t\t// Idempotency: if the key record already exists (from an earlier attempt),\n\t\t\t// this set is already committed. Checked under the lock so a retry racing a\n\t\t\t// first attempt on another instance still resolves to at-most-once.\n\t\t\tif (input.idempotencyKey) {\n\t\t\t\tconst existing = (await tx.execute(\n\t\t\t\t\tsql`SELECT 1 FROM ${sql.raw(quoteIdent(input.idempotencyKey.collection))} WHERE id = ${input.idempotencyKey.id} AND _deleted = 0 LIMIT 1`,\n\t\t\t\t)) as unknown as unknown[]\n\t\t\t\tif (existing.length > 0) {\n\t\t\t\t\treturn { admitted: true, idempotent: true, applied: [] as Operation[] }\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst rows = (await tx.execute(\n\t\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(input.target.collection))} WHERE id = ${input.target.id} AND _deleted = 0`,\n\t\t\t)) as unknown as Record<string, unknown>[]\n\t\t\tconst current =\n\t\t\t\trows.length > 0\n\t\t\t\t\t? this.deserializeRow(rows[0] as Record<string, unknown>, collectionDef)\n\t\t\t\t\t: null\n\n\t\t\tif (!input.admit(current)) {\n\t\t\t\treturn { admitted: false, idempotent: false, applied: [] as Operation[] }\n\t\t\t}\n\n\t\t\t// Seed a clock past the target record's latest committed operation so the\n\t\t\t// operations built next sort strictly after every prior write to it. Under\n\t\t\t// the advisory lock this makes last-write-wins materialization agree with the\n\t\t\t// serialized commit order, so a same-millisecond commit on another instance\n\t\t\t// cannot cause the counter to be undercounted (which would admit past a cap).\n\t\t\tconst clock = new HybridLogicalClock(this.nodeId, this.timeSource)\n\t\t\tconst latest = await this.latestOperationTimestamp(\n\t\t\t\ttx,\n\t\t\t\tinput.target.collection,\n\t\t\t\tinput.target.id,\n\t\t\t)\n\t\t\tif (latest) {\n\t\t\t\tclock.advanceTo(latest)\n\t\t\t}\n\n\t\t\tconst ops = await input.buildOperations(current, { clock })\n\t\t\tconst now = Date.now()\n\t\t\tfor (const op of ops) {\n\t\t\t\tconst deliverySeq = await this.nextDeliverySeq(tx)\n\t\t\t\tconst row = this.serializeOperation(op, now, deliverySeq)\n\t\t\t\tawait tx.insert(pgOperations).values(row).onConflictDoNothing({ target: pgOperations.id })\n\t\t\t\tawait tx\n\t\t\t\t\t.insert(pgSyncState)\n\t\t\t\t\t.values({ nodeId: op.nodeId, maxSequenceNumber: op.sequenceNumber, lastSeenAt: now })\n\t\t\t\t\t.onConflictDoUpdate({\n\t\t\t\t\t\ttarget: pgSyncState.nodeId,\n\t\t\t\t\t\tset: {\n\t\t\t\t\t\t\tmaxSequenceNumber: sql`GREATEST(${pgSyncState.maxSequenceNumber}, ${op.sequenceNumber})`,\n\t\t\t\t\t\t\tlastSeenAt: sql`${now}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\tif (this.schema?.collections[op.collection]) {\n\t\t\t\t\tawait this.rebuildMaterializedRecord(tx, op.collection, op.recordId)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { admitted: true, idempotent: false, applied: ops }\n\t\t})\n\n\t\t// Advance the in-memory version vector cache after commit.\n\t\tfor (const op of result.applied) {\n\t\t\tconst currentMax = this.versionVector.get(op.nodeId) ?? 0\n\t\t\tif (op.sequenceNumber > currentMax) {\n\t\t\t\tthis.versionVector.set(op.nodeId, op.sequenceNumber)\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst rows = await this.db\n\t\t\t.select()\n\t\t\t.from(pgOperations)\n\t\t\t.where(\n\t\t\t\tand(eq(pgOperations.nodeId, nodeId), between(pgOperations.sequenceNumber, fromSeq, toSeq)),\n\t\t\t)\n\t\t\t.orderBy(asc(pgOperations.sequenceNumber))\n\n\t\treturn rows.map((row) => this.deserializeOperation(row))\n\t}\n\n\tasync getOperationCount(): Promise<number> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst result = await this.db.select({ value: count() }).from(pgOperations)\n\t\treturn result[0]?.value ?? 0\n\t}\n\n\tasync getMaxDeliverySequence(): Promise<number> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = (await this.db.execute(\n\t\t\tsql`SELECT COALESCE(MAX(delivery_seq), 0) AS m FROM operations`,\n\t\t)) as unknown as { m: number | string | bigint }[]\n\t\treturn Number(rows[0]?.m ?? 0)\n\t}\n\n\tasync getOperationsAfterDelivery(\n\t\tafterDeliverySequence: number,\n\t\tlimit: number,\n\t): Promise<DeliveredOperation[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = await this.db\n\t\t\t.select()\n\t\t\t.from(pgOperations)\n\t\t\t.where(gt(pgOperations.deliverySeq, afterDeliverySequence))\n\t\t\t.orderBy(asc(pgOperations.deliverySeq))\n\t\t\t.limit(limit)\n\t\treturn rows.map((row) => ({\n\t\t\toperation: this.deserializeOperation(row),\n\t\t\tdeliverySequence: row.deliverySeq ?? 0,\n\t\t}))\n\t}\n\n\tasync materializeCollection(collection: string): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\t// Fast path: if schema is set, read directly from the materialized table\n\t\tif (this.schema?.collections[collection]) {\n\t\t\treturn this.queryCollection(collection)\n\t\t}\n\n\t\t// Fallback: replay operations (legacy path when schema is not set)\n\t\treturn this.materializeFromOpsLog(collection)\n\t}\n\n\tasync queryCollection(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions,\n\t): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\n\t\t// Validate field names in options\n\t\tif (options?.where) {\n\t\t\tfor (const key of Object.keys(options.where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\t\tif (options?.orderBy) {\n\t\t\tvalidateFieldName(collection, options.orderBy, schema)\n\t\t}\n\n\t\tconst query = this.buildSelectQuery(collection, options)\n\t\tconst rows = (await this.db.execute(query)) as unknown as Record<string, unknown>[]\n\n\t\treturn rows.map((row) => this.deserializeRow(row, collectionDef))\n\t}\n\n\tasync findRecord(collection: string, id: string): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tconst query = sql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id = ${id} AND _deleted = 0`\n\t\tconst rows = (await this.db.execute(query)) as unknown as Record<string, unknown>[]\n\n\t\tif (rows.length === 0) return null\n\t\treturn this.deserializeRow(rows[0] as Record<string, unknown>, collectionDef)\n\t}\n\n\tasync countCollection(collection: string, where?: Record<string, unknown>): Promise<number> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (where) {\n\t\t\tfor (const key of Object.keys(where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\n\t\tconst whereClause = this.buildWhereClause(where ?? {}, false)\n\t\tconst query = sql`SELECT COUNT(*) as cnt FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`\n\t\tconst rows = (await this.db.execute(query)) as unknown as Array<{ cnt: number | string }>\n\t\tconst cnt = rows[0]?.cnt\n\t\treturn typeof cnt === 'string' ? Number.parseInt(cnt, 10) : (cnt ?? 0)\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true\n\t}\n\n\tasync exportBackup(): Promise<Uint8Array> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst { buildServerBackup } = await import('./server-backup')\n\n\t\t// Export in delivery-sequence order (commit order), NOT sequenceNumber order.\n\t\t// sequenceNumber is per-node and interleaves nodes arbitrarily, which can place a\n\t\t// dependent operation before its dependency; restoring in that order would then\n\t\t// reassign delivery sequences non-causally, so a resumed client would receive the\n\t\t// dependent first, defer it, advance its watermark past it, and lose it. Delivery\n\t\t// order is commit order and therefore respects causality.\n\t\tconst rows = await this.db.select().from(pgOperations).orderBy(asc(pgOperations.deliverySeq))\n\t\tconst operations = rows.map((row) => this.deserializeOperation(row))\n\n\t\treturn buildServerBackup(this.nodeId, operations, this.versionVector)\n\t}\n\n\tasync importBackup(\n\t\tdata: Uint8Array,\n\t\tmerge?: boolean,\n\t): Promise<{ operationsRestored: number; success: boolean }> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst { parseServerBackup } = await import('./server-backup')\n\t\tconst { operations, versionVector } = parseServerBackup(data)\n\n\t\tif (merge) {\n\t\t\tlet restored = 0\n\t\t\tfor (const op of operations) {\n\t\t\t\tconst result = await this.applyRemoteOperation(op)\n\t\t\t\tif (result === 'applied') restored++\n\t\t\t}\n\t\t\t// Re-seed the sequence counter from the (possibly advanced) version vector,\n\t\t\t// in case the merge restored operations on this node with higher numbers.\n\t\t\tthis.sequenceCounter = null\n\t\t\treturn { operationsRestored: restored, success: true }\n\t\t}\n\n\t\tconst now = Date.now()\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\tawait tx.delete(pgOperations)\n\t\t\tawait tx.delete(pgSyncState)\n\n\t\t\tfor (const [nid, seq] of versionVector) {\n\t\t\t\tawait tx\n\t\t\t\t\t.insert(pgSyncState)\n\t\t\t\t\t.values({ nodeId: nid, maxSequenceNumber: seq, lastSeenAt: now })\n\t\t\t\t\t.onConflictDoNothing({ target: pgSyncState.nodeId })\n\t\t\t}\n\n\t\t\t// Re-assign delivery sequence from scratch in backup order, then realign the\n\t\t\t// counter so future appends continue above the restored maximum.\n\t\t\tlet deliverySeq = 0\n\t\t\tfor (const op of operations) {\n\t\t\t\tdeliverySeq += 1\n\t\t\t\tconst row = this.serializeOperation(op, now, deliverySeq)\n\t\t\t\tawait tx.insert(pgOperations).values(row).onConflictDoNothing({ target: pgOperations.id })\n\t\t\t}\n\t\t\tawait tx.execute(\n\t\t\t\tsql`INSERT INTO delivery_counter (id, value) VALUES (1, ${deliverySeq})\n\t\t\t\t\tON CONFLICT (id) DO UPDATE SET value = ${deliverySeq}`,\n\t\t\t)\n\t\t})\n\n\t\t// Rebuild in-memory version vector\n\t\tthis.versionVector.clear()\n\t\tfor (const [nid, seq] of versionVector) {\n\t\t\tthis.versionVector.set(nid, seq)\n\t\t}\n\t\t// Re-seed the sequence counter from the restored version vector.\n\t\tthis.sequenceCounter = null\n\n\t\treturn { operationsRestored: operations.length, success: true }\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Materialization internals\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * The HLC timestamp of the most recent operation on a record, by total order\n\t * (wallTime, logical, nodeId), or null when the record has no operations. Used\n\t * by {@link applyConditional} to advance its clock past the record's latest\n\t * write so newly built operations sort strictly after it.\n\t */\n\tprivate async latestOperationTimestamp(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<HLCTimestamp | null> {\n\t\tconst rows = await txOrDb\n\t\t\t.select({\n\t\t\t\twallTime: pgOperations.wallTime,\n\t\t\t\tlogical: pgOperations.logical,\n\t\t\t\ttimestampNodeId: pgOperations.timestampNodeId,\n\t\t\t})\n\t\t\t.from(pgOperations)\n\t\t\t.where(and(eq(pgOperations.collection, collection), eq(pgOperations.recordId, recordId)))\n\t\t\t.orderBy(\n\t\t\t\tdesc(pgOperations.wallTime),\n\t\t\t\tdesc(pgOperations.logical),\n\t\t\t\tdesc(pgOperations.timestampNodeId),\n\t\t\t)\n\t\t\t.limit(1)\n\n\t\tconst row = rows[0]\n\t\tif (!row) {\n\t\t\treturn null\n\t\t}\n\t\treturn { wallTime: row.wallTime, logical: row.logical, nodeId: row.timestampNodeId }\n\t}\n\n\t/**\n\t * Rebuild a single record in the materialized collection table by replaying\n\t * all operations for that record.\n\t */\n\tprivate async rebuildMaterializedRecord(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<void> {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (!collectionDef) return\n\n\t\t// Fetch all ops for this specific record, ordered by HLC\n\t\tconst ops = await txOrDb\n\t\t\t.select({\n\t\t\t\ttype: pgOperations.type,\n\t\t\t\tdata: pgOperations.data,\n\t\t\t\tatomicOps: pgOperations.atomicOps,\n\t\t\t\twallTime: pgOperations.wallTime,\n\t\t\t})\n\t\t\t.from(pgOperations)\n\t\t\t.where(and(eq(pgOperations.collection, collection), eq(pgOperations.recordId, recordId)))\n\t\t\t// HLC total order (wallTime, logical, nodeId) so atomic composition and LWW\n\t\t\t// see operations in exactly the order the merge engine converges them.\n\t\t\t.orderBy(\n\t\t\t\tasc(pgOperations.wallTime),\n\t\t\t\tasc(pgOperations.logical),\n\t\t\t\tasc(pgOperations.timestampNodeId),\n\t\t\t)\n\n\t\t// Replay to get current state\n\t\tconst parsedOps = ops.map((op) => ({\n\t\t\ttype: op.type,\n\t\t\tdata: op.data !== null ? JSON.parse(op.data) : null,\n\t\t\tatomicOps:\n\t\t\t\top.atomicOps != null ? (JSON.parse(op.atomicOps) as Record<string, AtomicOp>) : null,\n\t\t}))\n\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\tconst fieldNames = Object.keys(collectionDef.fields)\n\n\t\tif (recordData) {\n\t\t\tconst createdAt = ops.length > 0 ? (ops[0] as (typeof ops)[0]).wallTime : Date.now()\n\t\t\tconst updatedAt =\n\t\t\t\tops.length > 0 ? (ops[ops.length - 1] as (typeof ops)[0]).wallTime : Date.now()\n\n\t\t\tawait this.upsertMaterializedRecord(\n\t\t\t\ttxOrDb,\n\t\t\t\tcollection,\n\t\t\t\trecordId,\n\t\t\t\trecordData,\n\t\t\t\tfieldNames,\n\t\t\t\tcollectionDef,\n\t\t\t\tcreatedAt,\n\t\t\t\tupdatedAt,\n\t\t\t)\n\t\t} else {\n\t\t\tawait txOrDb.execute(\n\t\t\t\tsql`UPDATE ${sql.raw(quoteIdent(collection))} SET _deleted = 1, _updated_at = ${Date.now()} WHERE id = ${recordId}`,\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * UPSERT a record into the materialized collection table.\n\t */\n\tprivate async upsertMaterializedRecord(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\ttableName: string,\n\t\trecordId: string,\n\t\trecordData: Record<string, unknown>,\n\t\tfieldNames: string[],\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t\tcreatedAt: number,\n\t\tupdatedAt: number,\n\t): Promise<void> {\n\t\tconst allColumns = ['id', ...fieldNames, '_created_at', '_updated_at', '_deleted']\n\t\tconst values: unknown[] = [\n\t\t\trecordId,\n\t\t\t...fieldNames.map((f) => {\n\t\t\t\tconst descriptor = collectionDef.fields[f]\n\t\t\t\treturn descriptor ? serializeFieldValue(recordData[f] ?? null, descriptor) : null\n\t\t\t}),\n\t\t\tcreatedAt,\n\t\t\tupdatedAt,\n\t\t\t0,\n\t\t]\n\n\t\tconst columnsSql = sql.raw(allColumns.map((c) => quoteIdent(c)).join(', '))\n\t\tconst valuesSql = sql.join(\n\t\t\tvalues.map((v) => sql`${v}`),\n\t\t\tsql.raw(', '),\n\t\t)\n\t\tconst updateSet = sql.raw(\n\t\t\tallColumns\n\t\t\t\t.slice(1)\n\t\t\t\t.map((c) => `${quoteIdent(c)} = excluded.${quoteIdent(c)}`)\n\t\t\t\t.join(', '),\n\t\t)\n\n\t\tawait txOrDb.execute(\n\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(tableName))} (${columnsSql}) VALUES (${valuesSql}) ON CONFLICT (id) DO UPDATE SET ${updateSet}`,\n\t\t)\n\t}\n\n\t/**\n\t * Backfill all materialized collection tables from the existing operation log.\n\t */\n\tprivate async backfillAllCollections(): Promise<void> {\n\t\tif (!this.schema) return\n\n\t\tfor (const collectionName of Object.keys(this.schema.collections)) {\n\t\t\tawait this.backfillCollection(collectionName)\n\t\t}\n\t}\n\n\t/**\n\t * Backfill a single collection's materialized table from operations.\n\t */\n\tprivate async backfillCollection(collectionName: string): Promise<void> {\n\t\tconst collectionDef = this.schema?.collections[collectionName]\n\t\tif (!collectionDef) return\n\n\t\tconst allOps = await this.db\n\t\t\t.select({\n\t\t\t\trecordId: pgOperations.recordId,\n\t\t\t\ttype: pgOperations.type,\n\t\t\t\tdata: pgOperations.data,\n\t\t\t\tatomicOps: pgOperations.atomicOps,\n\t\t\t\twallTime: pgOperations.wallTime,\n\t\t\t})\n\t\t\t.from(pgOperations)\n\t\t\t.where(eq(pgOperations.collection, collectionName))\n\t\t\t// HLC total order (wallTime, logical, nodeId) for correct atomic composition.\n\t\t\t.orderBy(\n\t\t\t\tasc(pgOperations.wallTime),\n\t\t\t\tasc(pgOperations.logical),\n\t\t\t\tasc(pgOperations.timestampNodeId),\n\t\t\t)\n\n\t\tif (allOps.length === 0) return\n\n\t\t// Group by recordId\n\t\tconst grouped = new Map<string, typeof allOps>()\n\t\tfor (const op of allOps) {\n\t\t\tlet group = grouped.get(op.recordId)\n\t\t\tif (!group) {\n\t\t\t\tgroup = []\n\t\t\t\tgrouped.set(op.recordId, group)\n\t\t\t}\n\t\t\tgroup.push(op)\n\t\t}\n\n\t\tconst fieldNames = Object.keys(collectionDef.fields)\n\n\t\t// Rebuild each record\n\t\tfor (const [recordId, recordOps] of grouped) {\n\t\t\tconst parsedOps = recordOps.map((op) => ({\n\t\t\t\ttype: op.type,\n\t\t\t\tdata: op.data !== null ? JSON.parse(op.data) : null,\n\t\t\t\tatomicOps:\n\t\t\t\t\top.atomicOps != null ? (JSON.parse(op.atomicOps) as Record<string, AtomicOp>) : null,\n\t\t\t}))\n\t\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\t\tif (recordData) {\n\t\t\t\tconst createdAt = (recordOps[0] as (typeof recordOps)[0]).wallTime\n\t\t\t\tconst updatedAt = (recordOps[recordOps.length - 1] as (typeof recordOps)[0]).wallTime\n\t\t\t\tawait this.upsertMaterializedRecord(\n\t\t\t\t\tthis.db,\n\t\t\t\t\tcollectionName,\n\t\t\t\t\trecordId,\n\t\t\t\t\trecordData,\n\t\t\t\t\tfieldNames,\n\t\t\t\t\tcollectionDef,\n\t\t\t\t\tcreatedAt,\n\t\t\t\t\tupdatedAt,\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tawait this.db.execute(\n\t\t\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(collectionName))} (id, _deleted, _created_at, _updated_at) VALUES (${recordId}, 1, ${Date.now()}, ${Date.now()}) ON CONFLICT (id) DO UPDATE SET _deleted = 1, _updated_at = ${Date.now()}`,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Query building\n\t// ---------------------------------------------------------------------------\n\n\tprivate buildSelectQuery(collection: string, options?: CollectionQueryOptions): SQL {\n\t\tconst whereClause = this.buildWhereClause(\n\t\t\toptions?.where ?? {},\n\t\t\toptions?.includeDeleted ?? false,\n\t\t)\n\n\t\tconst parts: SQL[] = [\n\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`,\n\t\t]\n\n\t\tif (options?.orderBy) {\n\t\t\tconst dir = options.orderDirection === 'desc' ? 'DESC' : 'ASC'\n\t\t\tparts.push(sql.raw(` ORDER BY ${quoteIdent(options.orderBy)} ${dir}`))\n\t\t}\n\n\t\tif (options?.limit !== undefined) {\n\t\t\tparts.push(sql` LIMIT ${options.limit}`)\n\t\t}\n\n\t\tif (options?.offset !== undefined) {\n\t\t\tparts.push(sql` OFFSET ${options.offset}`)\n\t\t}\n\n\t\treturn sql.join(parts, sql.raw(''))\n\t}\n\n\tprivate buildWhereClause(where: Record<string, unknown>, includeDeleted: boolean): SQL {\n\t\tconst conditions: SQL[] = []\n\n\t\tif (!includeDeleted) {\n\t\t\tconditions.push(sql.raw('_deleted = 0'))\n\t\t}\n\n\t\tfor (const [key, value] of Object.entries(where)) {\n\t\t\tconditions.push(sql`${sql.raw(quoteIdent(key))} = ${value}`)\n\t\t}\n\n\t\tif (conditions.length === 0) {\n\t\t\treturn sql.raw('1 = 1')\n\t\t}\n\n\t\treturn sql.join(conditions, sql.raw(' AND '))\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Row deserialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate deserializeRow(\n\t\trow: Record<string, unknown>,\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t): MaterializedRecord {\n\t\tconst record: MaterializedRecord = { id: row.id as string }\n\n\t\tfor (const [fieldName, descriptor] of Object.entries(collectionDef.fields)) {\n\t\t\tif (fieldName in row) {\n\t\t\t\trecord[fieldName] = deserializeFieldValue(row[fieldName], descriptor)\n\t\t\t}\n\t\t}\n\n\t\tif ('_created_at' in row) record._created_at = row._created_at\n\t\tif ('_updated_at' in row) record._updated_at = row._updated_at\n\n\t\treturn record\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Fallback materialization (operation replay, no schema)\n\t// ---------------------------------------------------------------------------\n\n\tprivate async materializeFromOpsLog(collection: string): Promise<MaterializedRecord[]> {\n\t\tconst rows = await this.db\n\t\t\t.select()\n\t\t\t.from(pgOperations)\n\t\t\t.where(eq(pgOperations.collection, collection))\n\t\t\t.orderBy(\n\t\t\t\tasc(pgOperations.wallTime),\n\t\t\t\tasc(pgOperations.logical),\n\t\t\t\tasc(pgOperations.sequenceNumber),\n\t\t\t)\n\n\t\tconst records = new Map<string, Record<string, unknown>>()\n\t\tconst deleted = new Set<string>()\n\n\t\tfor (const row of rows) {\n\t\t\tconst recordId = row.recordId\n\t\t\tconst data = row.data !== null ? JSON.parse(row.data) : null\n\n\t\t\tswitch (row.type) {\n\t\t\t\tcase 'insert':\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\trecords.set(recordId, { id: recordId, ...data })\n\t\t\t\t\t\tdeleted.delete(recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'update':\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\tconst existing = records.get(recordId) ?? { id: recordId }\n\t\t\t\t\t\trecords.set(recordId, { ...existing, ...data })\n\t\t\t\t\t\tdeleted.delete(recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'delete':\n\t\t\t\t\tdeleted.add(recordId)\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tfor (const id of deleted) {\n\t\t\trecords.delete(id)\n\t\t}\n\n\t\treturn Array.from(records.values()) as MaterializedRecord[]\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Initialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate async initialize(): Promise<void> {\n\t\tawait this.ensureTables()\n\n\t\t// Hydrate in-memory version vector cache\n\t\tconst rows = await this.db\n\t\t\t.select({\n\t\t\t\tnodeId: pgSyncState.nodeId,\n\t\t\t\tmaxSequenceNumber: pgSyncState.maxSequenceNumber,\n\t\t\t})\n\t\t\t.from(pgSyncState)\n\n\t\tfor (const row of rows) {\n\t\t\tthis.versionVector.set(row.nodeId, row.maxSequenceNumber)\n\t\t}\n\t}\n\n\tprivate async ensureTables(): Promise<void> {\n\t\t// Serialize all schema setup across instances with an advisory transaction lock.\n\t\t// `CREATE TABLE IF NOT EXISTS` is not atomic in Postgres: two servers cold-starting\n\t\t// against the same empty database race and one fails with a duplicate-type error.\n\t\t// Running every setup statement in one advisory-locked transaction makes concurrent\n\t\t// startup safe and also serializes the delivery-sequence backfill.\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\tawait tx.execute(sql`SELECT pg_advisory_xact_lock(hashtextextended('kora:ensure-tables', 0))`)\n\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS operations (\n\t\t\t\t\tid TEXT PRIMARY KEY,\n\t\t\t\t\tnode_id TEXT NOT NULL,\n\t\t\t\t\ttype TEXT NOT NULL,\n\t\t\t\t\tcollection TEXT NOT NULL,\n\t\t\t\t\trecord_id TEXT NOT NULL,\n\t\t\t\t\tdata TEXT,\n\t\t\t\t\tprevious_data TEXT,\n\t\t\t\t\tatomic_ops TEXT,\n\t\t\t\t\twall_time BIGINT NOT NULL,\n\t\t\t\t\tlogical INTEGER NOT NULL,\n\t\t\t\t\ttimestamp_node_id TEXT NOT NULL,\n\t\t\t\t\tsequence_number INTEGER NOT NULL,\n\t\t\t\t\tcausal_deps TEXT NOT NULL DEFAULT '[]',\n\t\t\t\t\tschema_version INTEGER NOT NULL,\n\t\t\t\t\treceived_at BIGINT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\t// Backward-compatible migration: add atomic_ops to operation logs created\n\t\t\t// before atomic-op persistence. Nullable, so existing rows read as \"no atomic\n\t\t\t// ops\" and keep materializing by last-write-wins exactly as before.\n\t\t\tawait tx.execute(sql`ALTER TABLE operations ADD COLUMN IF NOT EXISTS atomic_ops TEXT`)\n\n\t\t\t// Backward-compatible migration: add the delivery_seq column for the gap-free\n\t\t\t// delivery watermark.\n\t\t\tawait tx.execute(sql`ALTER TABLE operations ADD COLUMN IF NOT EXISTS delivery_seq BIGINT`)\n\n\t\t\tawait tx.execute(\n\t\t\t\tsql`CREATE INDEX IF NOT EXISTS idx_node_seq ON operations (node_id, sequence_number)`,\n\t\t\t)\n\t\t\tawait tx.execute(sql`CREATE INDEX IF NOT EXISTS idx_collection ON operations (collection)`)\n\t\t\tawait tx.execute(sql`CREATE INDEX IF NOT EXISTS idx_received ON operations (received_at)`)\n\t\t\tawait tx.execute(\n\t\t\t\tsql`CREATE INDEX IF NOT EXISTS idx_delivery_seq ON operations (delivery_seq)`,\n\t\t\t)\n\t\t\t// Index for efficient per-record operation lookups during materialization\n\t\t\tawait tx.execute(\n\t\t\t\tsql`CREATE INDEX IF NOT EXISTS idx_collection_record ON operations (collection, record_id)`,\n\t\t\t)\n\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS sync_state (\n\t\t\t\t\tnode_id TEXT PRIMARY KEY,\n\t\t\t\t\tmax_sequence_number INTEGER NOT NULL,\n\t\t\t\t\tlast_seen_at BIGINT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\t// Counter row that assigns delivery sequences in commit order. Every append\n\t\t\t// does `UPDATE ... value = value + 1 RETURNING value` inside its transaction,\n\t\t\t// which holds an exclusive row lock until commit. So a later assigner cannot\n\t\t\t// obtain its number until the earlier one has committed: delivery-sequence\n\t\t\t// order equals commit (visibility) order, which is what makes a `> watermark`\n\t\t\t// stream provably gap-free across instances. This serializes appends through\n\t\t\t// one row (correctness over throughput, per the framework's priorities).\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS delivery_counter (\n\t\t\t\t\tid INTEGER PRIMARY KEY,\n\t\t\t\t\tvalue BIGINT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\t// Backfill any pre-column rows deterministically, then seed the counter to the\n\t\t\t// resulting maximum. Under the advisory lock two starting servers cannot\n\t\t\t// double-assign. The window scan touches only rows lacking a sequence, so a\n\t\t\t// fresh or already-migrated table does almost no work here.\n\t\t\tawait tx.execute(sql`\n\t\t\t\tWITH ordered AS (\n\t\t\t\t\tSELECT id, ROW_NUMBER() OVER (\n\t\t\t\t\t\tORDER BY received_at ASC, sequence_number ASC, id ASC\n\t\t\t\t\t) + COALESCE((SELECT MAX(delivery_seq) FROM operations), 0) AS rn\n\t\t\t\t\tFROM operations WHERE delivery_seq IS NULL\n\t\t\t\t)\n\t\t\t\tUPDATE operations o SET delivery_seq = ordered.rn\n\t\t\t\tFROM ordered WHERE o.id = ordered.id\n\t\t\t`)\n\t\t\tawait tx.execute(sql`\n\t\t\t\tINSERT INTO delivery_counter (id, value)\n\t\t\t\tVALUES (1, COALESCE((SELECT MAX(delivery_seq) FROM operations), 0))\n\t\t\t\tON CONFLICT (id) DO UPDATE\n\t\t\t\t\tSET value = GREATEST(delivery_counter.value, EXCLUDED.value)\n\t\t\t`)\n\t\t})\n\t}\n\n\t/**\n\t * Reserve the next delivery sequence inside an open append transaction. The\n\t * `UPDATE ... RETURNING` locks the counter row until this transaction commits,\n\t * serializing assignment into commit order (see the counter table comment).\n\t */\n\tprivate async nextDeliverySeq(tx: {\n\t\texecute: (query: SQL) => Promise<unknown>\n\t}): Promise<number> {\n\t\tconst rows = (await tx.execute(\n\t\t\tsql`UPDATE delivery_counter SET value = value + 1 WHERE id = 1 RETURNING value`,\n\t\t)) as unknown as { value: number | string | bigint }[]\n\t\tconst value = rows[0]?.value\n\t\tif (value === undefined || value === null) {\n\t\t\t// The counter row must always exist (ensureTables seeds it). A missing row would\n\t\t\t// silently return 0 and stamp every op with delivery_seq 0, making them invisible\n\t\t\t// to clients (a `> watermark` scan never returns 0). Fail loudly instead of\n\t\t\t// corrupting the delivery stream.\n\t\t\tthrow new Error(\n\t\t\t\t'delivery_counter row (id=1) is missing; the operations log cannot assign delivery sequences',\n\t\t\t)\n\t\t}\n\t\treturn Number(value)\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Operation serialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate serializeOperation(\n\t\top: Operation,\n\t\treceivedAt: number,\n\t\tdeliverySeq: number,\n\t): typeof pgOperations.$inferInsert {\n\t\treturn {\n\t\t\tid: op.id,\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 !== null ? JSON.stringify(op.data) : null,\n\t\t\tpreviousData: op.previousData !== null ? JSON.stringify(op.previousData) : null,\n\t\t\tatomicOps:\n\t\t\t\top.atomicOps && Object.keys(op.atomicOps).length > 0 ? JSON.stringify(op.atomicOps) : null,\n\t\t\twallTime: op.timestamp.wallTime,\n\t\t\tlogical: op.timestamp.logical,\n\t\t\ttimestampNodeId: op.timestamp.nodeId,\n\t\t\tsequenceNumber: op.sequenceNumber,\n\t\t\tcausalDeps: JSON.stringify(op.causalDeps),\n\t\t\tschemaVersion: op.schemaVersion,\n\t\t\treceivedAt,\n\t\t\tdeliverySeq,\n\t\t}\n\t}\n\n\tprivate deserializeOperation(row: typeof pgOperations.$inferSelect): Operation {\n\t\tconst atomicOps =\n\t\t\trow.atomicOps != null ? (JSON.parse(row.atomicOps) as Record<string, AtomicOp>) : undefined\n\t\treturn {\n\t\t\tid: row.id,\n\t\t\tnodeId: row.nodeId,\n\t\t\ttype: row.type as Operation['type'],\n\t\t\tcollection: row.collection,\n\t\t\trecordId: row.recordId,\n\t\t\tdata: row.data !== null ? JSON.parse(row.data) : null,\n\t\t\tpreviousData: row.previousData !== null ? JSON.parse(row.previousData) : null,\n\t\t\ttimestamp: {\n\t\t\t\twallTime: row.wallTime,\n\t\t\t\tlogical: row.logical,\n\t\t\t\tnodeId: row.timestampNodeId,\n\t\t\t},\n\t\t\tsequenceNumber: row.sequenceNumber,\n\t\t\tcausalDeps: JSON.parse(row.causalDeps),\n\t\t\tschemaVersion: row.schemaVersion,\n\t\t\t...(atomicOps ? { atomicOps } : {}),\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Assertions\n\t// ---------------------------------------------------------------------------\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) {\n\t\t\tthrow new Error('PostgresServerStore is closed')\n\t\t}\n\t}\n\n\tprivate assertSchema(): void {\n\t\tif (!this.schema) {\n\t\t\tthrow new Error(\n\t\t\t\t'Schema not set. Call setSchema() before using queryCollection/findRecord/countCollection.',\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate assertCollection(collection: string): void {\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (!schema.collections[collection]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${collection}\". Available: ${Object.keys(schema.collections).join(', ')}`,\n\t\t\t)\n\t\t}\n\t}\n}\n\n/**\n * Creates a PostgresServerStore from a PostgreSQL connection string.\n */\nexport async function createPostgresServerStore(options: {\n\tconnectionString: string\n\tnodeId?: string\n}): Promise<PostgresServerStore> {\n\tconst { postgresClient, drizzleFn } = await loadPostgresDeps()\n\tconst client = postgresClient(options.connectionString)\n\tconst db = drizzleFn(client)\n\n\treturn new PostgresServerStore(db, options.nodeId)\n}\n\nasync function loadPostgresDeps(): Promise<{\n\tpostgresClient: (connectionString: string) => unknown\n\tdrizzleFn: (client: unknown) => PostgresJsDatabase\n}> {\n\ttry {\n\t\tconst dynamicImport = new Function('specifier', 'return import(specifier)') as (\n\t\t\tspecifier: string,\n\t\t) => Promise<unknown>\n\n\t\tconst postgresMod = (await dynamicImport('postgres')) as { default: (cs: string) => unknown }\n\t\tconst drizzleMod = (await dynamicImport('drizzle-orm/postgres-js')) as {\n\t\t\tdrizzle: (client: unknown) => PostgresJsDatabase\n\t\t}\n\n\t\treturn {\n\t\t\tpostgresClient: postgresMod.default,\n\t\t\tdrizzleFn: drizzleMod.drizzle,\n\t\t}\n\t} catch {\n\t\tthrow new Error(\n\t\t\t'PostgreSQL backend requires the \"postgres\" package. Install it in your project dependencies.',\n\t\t)\n\t}\n}\n","import { bigint, index, integer, pgTable, text } from 'drizzle-orm/pg-core'\n\n/**\n * Drizzle schema for the Kora sync server's PostgreSQL database.\n *\n * Two tables:\n * - `pgOperations` — the append-only operation log (content-addressed by id)\n * - `pgSyncState` — tracks the max sequence number seen per node (version vector)\n *\n * Column structure mirrors the SQLite drizzle-schema.ts but uses pgTable.\n */\n\nexport const pgOperations = pgTable(\n\t'operations',\n\t{\n\t\tid: text('id').primaryKey(),\n\t\tnodeId: text('node_id').notNull(),\n\t\ttype: text('type').notNull(),\n\t\tcollection: text('collection').notNull(),\n\t\trecordId: text('record_id').notNull(),\n\t\tdata: text('data'), // JSON-serialized, null for deletes\n\t\tpreviousData: text('previous_data'), // JSON-serialized, null for insert/delete\n\t\tatomicOps: text('atomic_ops'), // JSON-serialized Record<field, AtomicOp>, null when none\n\t\twallTime: bigint('wall_time', { mode: 'number' }).notNull(),\n\t\tlogical: integer('logical').notNull(),\n\t\ttimestampNodeId: text('timestamp_node_id').notNull(),\n\t\tsequenceNumber: integer('sequence_number').notNull(),\n\t\tcausalDeps: text('causal_deps').notNull().default('[]'), // JSON array of op IDs\n\t\tschemaVersion: integer('schema_version').notNull(),\n\t\treceivedAt: bigint('received_at', { mode: 'number' }).notNull(),\n\t\t// Server-assigned monotonic delivery sequence, ordered by commit (assigned from\n\t\t// a counter row locked inside the append transaction, so delivery order equals\n\t\t// visibility order even across instances). Drives the gap-free server->client\n\t\t// delivery watermark. Nullable only for pre-column rows, backfilled on startup.\n\t\tdeliverySeq: bigint('delivery_seq', { mode: 'number' }),\n\t},\n\t(table) => ({\n\t\tnodeSeqIdx: index('idx_pg_node_seq').on(table.nodeId, table.sequenceNumber),\n\t\tcollectionIdx: index('idx_pg_collection').on(table.collection),\n\t\treceivedIdx: index('idx_pg_received').on(table.receivedAt),\n\t\tdeliveryIdx: index('idx_pg_delivery_seq').on(table.deliverySeq),\n\t}),\n)\n\nexport const pgSyncState = pgTable('sync_state', {\n\tnodeId: text('node_id').primaryKey(),\n\tmaxSequenceNumber: integer('max_sequence_number').notNull(),\n\tlastSeenAt: bigint('last_seen_at', { mode: 'number' }).notNull(),\n})\n","import { createRequire } from 'node:module'\nimport type { AtomicOp, Operation, SchemaDefinition, VersionVector } from '@korajs/core'\nimport { generateUUIDv7, quoteIdent } from '@korajs/core'\nimport type { ApplyResult } from '@korajs/sync'\nimport type { SQL } from 'drizzle-orm'\nimport { and, asc, between, count, eq, gt, sql } from 'drizzle-orm'\nimport type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3'\nimport { deliveryCounter, operations, syncState } from './drizzle-schema'\nimport {\n\tdeserializeFieldValue,\n\tgenerateAllCollectionDDL,\n\treplayOperationsForRecord,\n\tserializeFieldValue,\n\tvalidateFieldName,\n} from './materialization'\nimport type {\n\tCollectionQueryOptions,\n\tDeliveredOperation,\n\tMaterializedRecord,\n\tServerStore,\n} from './server-store'\n\n// better-sqlite3 is a native CJS addon that cannot be loaded via ESM import().\n// createRequire provides a CJS require() that works in both ESM and CJS contexts.\n// tsup's shims option ensures import.meta.url is available in CJS builds.\nconst esmRequire = createRequire(import.meta.url)\n\n/**\n * SQLite-backed server store using Drizzle ORM.\n * Persists operations and version vectors to a real database file,\n * surviving process restarts.\n *\n * When a schema is set via setSchema(), also maintains materialized\n * collection tables for efficient indexed queries (dual-write).\n */\nexport class SqliteServerStore implements ServerStore {\n\tprivate readonly nodeId: string\n\tprivate readonly db: BetterSQLite3Database\n\tprivate schema: SchemaDefinition | null = null\n\tprivate closed = false\n\n\tconstructor(db: BetterSQLite3Database, nodeId?: string) {\n\t\tthis.db = db\n\t\tthis.nodeId = nodeId ?? generateUUIDv7()\n\t\tthis.ensureTables()\n\t}\n\n\tgetVersionVector(): VersionVector {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db.select().from(syncState).all()\n\t\tconst vv: VersionVector = new Map()\n\t\tfor (const row of rows) {\n\t\t\tvv.set(row.nodeId, row.maxSequenceNumber)\n\t\t}\n\t\treturn vv\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.nodeId\n\t}\n\n\tgetSchema(): SchemaDefinition | null {\n\t\treturn this.schema\n\t}\n\n\tasync setSchema(schema: SchemaDefinition): Promise<void> {\n\t\tthis.assertOpen()\n\t\tthis.schema = schema\n\n\t\t// Generate and execute DDL for all collection tables\n\t\tconst ddlStatements = generateAllCollectionDDL(schema, 'sqlite')\n\t\tfor (const stmt of ddlStatements) {\n\t\t\tif (stmt.startsWith('--kora:safe-alter')) {\n\t\t\t\tconst alterSql = stmt.replace('--kora:safe-alter\\n', '')\n\t\t\t\ttry {\n\t\t\t\t\tthis.db.run(sql.raw(alterSql))\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// Ignore \"duplicate column\" errors from safe ALTER TABLE.\n\t\t\t\t\t// Drizzle wraps SQLite errors, so check both outer message and cause.\n\t\t\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\t\t\tthrow e\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.db.run(sql.raw(stmt))\n\t\t\t}\n\t\t}\n\n\t\t// Backfill materialized tables from existing operations\n\t\tawait this.backfillAllCollections()\n\t}\n\n\tasync applyRemoteOperation(op: Operation): Promise<ApplyResult> {\n\t\tthis.assertOpen()\n\n\t\tconst now = Date.now()\n\n\t\t// Use a transaction for atomicity: insert op + update version vector + materialize\n\t\tconst result = this.db.transaction((tx) => {\n\t\t\t// Content-addressed dedup: check before assigning a delivery sequence so a\n\t\t\t// duplicate never burns one (keeps the sequence gap-free on this store).\n\t\t\tconst existing = tx.all<{ id: string }>(\n\t\t\t\tsql`SELECT id FROM operations WHERE id = ${op.id} LIMIT 1`,\n\t\t\t)\n\t\t\tif (existing.length > 0) {\n\t\t\t\treturn 'duplicate' as const\n\t\t\t}\n\n\t\t\tconst row = this.serializeOperation(op, now, this.nextDeliverySeq(tx))\n\t\t\ttx.insert(operations).values(row).run()\n\n\t\t\t// Advance version vector: upsert with MAX to ensure monotonic progress\n\t\t\ttx.insert(syncState)\n\t\t\t\t.values({\n\t\t\t\t\tnodeId: op.nodeId,\n\t\t\t\t\tmaxSequenceNumber: op.sequenceNumber,\n\t\t\t\t\tlastSeenAt: now,\n\t\t\t\t})\n\t\t\t\t.onConflictDoUpdate({\n\t\t\t\t\ttarget: syncState.nodeId,\n\t\t\t\t\tset: {\n\t\t\t\t\t\tmaxSequenceNumber: sql`MAX(${syncState.maxSequenceNumber}, ${op.sequenceNumber})`,\n\t\t\t\t\t\tlastSeenAt: sql`${now}`,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\t.run()\n\n\t\t\t// Dual-write: update materialized collection table if schema is set\n\t\t\tif (this.schema?.collections[op.collection]) {\n\t\t\t\tthis.rebuildMaterializedRecord(tx, op.collection, op.recordId)\n\t\t\t}\n\n\t\t\treturn 'applied' as const\n\t\t})\n\n\t\treturn result\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\n\t\tconst rows = this.db\n\t\t\t.select()\n\t\t\t.from(operations)\n\t\t\t.where(and(eq(operations.nodeId, nodeId), between(operations.sequenceNumber, fromSeq, toSeq)))\n\t\t\t.orderBy(asc(operations.sequenceNumber))\n\t\t\t.all()\n\n\t\treturn rows.map((row) => this.deserializeOperation(row))\n\t}\n\n\tasync getOperationCount(): Promise<number> {\n\t\tthis.assertOpen()\n\n\t\tconst result = this.db.select({ value: count() }).from(operations).all()\n\t\treturn result[0]?.value ?? 0\n\t}\n\n\tasync getMaxDeliverySequence(): Promise<number> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db.all<{ m: number | null }>(\n\t\t\tsql`SELECT MAX(delivery_seq) AS m FROM operations`,\n\t\t)\n\t\treturn rows[0]?.m ?? 0\n\t}\n\n\tasync getOperationsAfterDelivery(\n\t\tafterDeliverySequence: number,\n\t\tlimit: number,\n\t): Promise<DeliveredOperation[]> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db\n\t\t\t.select()\n\t\t\t.from(operations)\n\t\t\t.where(gt(operations.deliverySeq, afterDeliverySequence))\n\t\t\t.orderBy(asc(operations.deliverySeq))\n\t\t\t.limit(limit)\n\t\t\t.all()\n\t\treturn rows.map((row) => ({\n\t\t\toperation: this.deserializeOperation(row),\n\t\t\tdeliverySequence: row.deliverySeq ?? 0,\n\t\t}))\n\t}\n\n\tasync materializeCollection(collection: string): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\n\t\t// Fast path: if schema is set, read directly from the materialized table\n\t\tif (this.schema?.collections[collection]) {\n\t\t\treturn this.queryCollection(collection)\n\t\t}\n\n\t\t// Fallback: replay operations (legacy path when schema is not set)\n\t\treturn this.materializeFromOpsLog(collection)\n\t}\n\n\tasync queryCollection(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions,\n\t): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\n\t\t// Validate field names in options\n\t\tif (options?.where) {\n\t\t\tfor (const key of Object.keys(options.where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\t\tif (options?.orderBy) {\n\t\t\tvalidateFieldName(collection, options.orderBy, schema)\n\t\t}\n\n\t\tconst query = this.buildSelectQuery(collection, options)\n\t\tconst rows = this.db.all<Record<string, unknown>>(query)\n\n\t\treturn rows.map((row) => this.deserializeRow(row, collectionDef))\n\t}\n\n\tasync findRecord(collection: string, id: string): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tconst query = sql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id = ${id} AND _deleted = 0`\n\t\tconst rows = this.db.all<Record<string, unknown>>(query)\n\n\t\tif (rows.length === 0) return null\n\t\treturn this.deserializeRow(rows[0] as Record<string, unknown>, collectionDef)\n\t}\n\n\tasync countCollection(collection: string, where?: Record<string, unknown>): Promise<number> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (where) {\n\t\t\tfor (const key of Object.keys(where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\n\t\tconst whereClause = this.buildWhereClause(where ?? {}, false)\n\t\tconst query = sql`SELECT COUNT(*) as cnt FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`\n\t\tconst rows = this.db.all<{ cnt: number }>(query)\n\t\treturn rows[0]?.cnt ?? 0\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true\n\t}\n\n\tasync exportBackup(): Promise<Uint8Array> {\n\t\tthis.assertOpen()\n\n\t\tconst { buildServerBackup } = await import('./server-backup')\n\t\t// Export in delivery-sequence (commit) order so a restore reassigns delivery\n\t\t// sequences causally; an implicit scan order must not be relied on.\n\t\tconst rows = this.db.select().from(operations).orderBy(asc(operations.deliverySeq)).all()\n\t\tconst deserialized = rows.map((row) => this.deserializeOperation(row))\n\t\tconst vv = this.getVersionVector()\n\n\t\treturn buildServerBackup(this.nodeId, deserialized, vv)\n\t}\n\n\tasync importBackup(\n\t\tdata: Uint8Array,\n\t\tmerge?: boolean,\n\t): Promise<{ operationsRestored: number; success: boolean }> {\n\t\tthis.assertOpen()\n\n\t\tconst { parseServerBackup } = await import('./server-backup')\n\t\tconst { operations: ops, versionVector } = parseServerBackup(data)\n\n\t\tif (merge) {\n\t\t\tlet restored = 0\n\t\t\tfor (const op of ops) {\n\t\t\t\tconst result = await this.applyRemoteOperation(op)\n\t\t\t\tif (result === 'applied') restored++\n\t\t\t}\n\t\t\treturn { operationsRestored: restored, success: true }\n\t\t}\n\n\t\t// Replace mode: DROP and recreate\n\t\tthis.db.transaction((tx) => {\n\t\t\ttx.run(sql.raw('DELETE FROM operations'))\n\t\t\ttx.run(sql.raw('DELETE FROM sync_state'))\n\t\t\ttx.update(deliveryCounter).set({ value: 0 }).where(eq(deliveryCounter.id, 1)).run()\n\n\t\t\tfor (const [nid, seq] of versionVector) {\n\t\t\t\ttx.insert(syncState)\n\t\t\t\t\t.values({ nodeId: nid, maxSequenceNumber: seq, lastSeenAt: Date.now() })\n\t\t\t\t\t.run()\n\t\t\t}\n\n\t\t\t// Re-assign delivery sequence from scratch in backup order.\n\t\t\tlet deliverySeq = 0\n\t\t\tfor (const op of ops) {\n\t\t\t\tdeliverySeq += 1\n\t\t\t\tconst row = this.serializeOperation(op, Date.now(), deliverySeq)\n\t\t\t\ttx.insert(operations).values(row).run()\n\t\t\t}\n\t\t\ttx.update(deliveryCounter).set({ value: deliverySeq }).where(eq(deliveryCounter.id, 1)).run()\n\t\t})\n\n\t\treturn { operationsRestored: ops.length, success: true }\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Materialization internals\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * Rebuild a single record in the materialized collection table by replaying\n\t * all operations for that record. Called within the applyRemoteOperation\n\t * transaction for atomic dual-write.\n\t */\n\tprivate rebuildMaterializedRecord(\n\t\ttxOrDb: BetterSQLite3Database,\n\t\tcollection: string,\n\t\trecordId: string,\n\t): void {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (!collectionDef) return\n\n\t\t// Fetch all ops for this specific record, in HLC total order (wallTime,\n\t\t// logical, nodeId) so atomic composition and LWW converge like the merge engine.\n\t\tconst ops = txOrDb\n\t\t\t.select({\n\t\t\t\ttype: operations.type,\n\t\t\t\tdata: operations.data,\n\t\t\t\tatomicOps: operations.atomicOps,\n\t\t\t\twallTime: operations.wallTime,\n\t\t\t})\n\t\t\t.from(operations)\n\t\t\t.where(and(eq(operations.collection, collection), eq(operations.recordId, recordId)))\n\t\t\t.orderBy(asc(operations.wallTime), asc(operations.logical), asc(operations.timestampNodeId))\n\t\t\t.all()\n\n\t\t// Replay to get current state\n\t\tconst parsedOps = ops.map((op) => ({\n\t\t\ttype: op.type,\n\t\t\tdata: op.data !== null ? JSON.parse(op.data) : null,\n\t\t\tatomicOps:\n\t\t\t\top.atomicOps != null ? (JSON.parse(op.atomicOps) as Record<string, AtomicOp>) : null,\n\t\t}))\n\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\tconst fieldNames = Object.keys(collectionDef.fields)\n\n\t\tif (recordData) {\n\t\t\t// Compute timestamps from operations\n\t\t\tconst createdAt = ops.length > 0 ? (ops[0] as (typeof ops)[0]).wallTime : Date.now()\n\t\t\tconst updatedAt =\n\t\t\t\tops.length > 0 ? (ops[ops.length - 1] as (typeof ops)[0]).wallTime : Date.now()\n\n\t\t\tthis.upsertMaterializedRecord(\n\t\t\t\ttxOrDb,\n\t\t\t\tcollection,\n\t\t\t\trecordId,\n\t\t\t\trecordData,\n\t\t\t\tfieldNames,\n\t\t\t\tcollectionDef,\n\t\t\t\tcreatedAt,\n\t\t\t\tupdatedAt,\n\t\t\t)\n\t\t} else {\n\t\t\t// Record was deleted — soft-delete in materialized table\n\t\t\ttxOrDb.run(\n\t\t\t\tsql`UPDATE ${sql.raw(quoteIdent(collection))} SET _deleted = 1, _updated_at = ${Date.now()} WHERE id = ${recordId}`,\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * UPSERT a record into the materialized collection table.\n\t * Uses INSERT ... ON CONFLICT (id) DO UPDATE SET for atomic upsert.\n\t */\n\tprivate upsertMaterializedRecord(\n\t\ttxOrDb: BetterSQLite3Database,\n\t\ttableName: string,\n\t\trecordId: string,\n\t\trecordData: Record<string, unknown>,\n\t\tfieldNames: string[],\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t\tcreatedAt: number,\n\t\tupdatedAt: number,\n\t): void {\n\t\tconst allColumns = ['id', ...fieldNames, '_created_at', '_updated_at', '_deleted']\n\t\tconst values: unknown[] = [\n\t\t\trecordId,\n\t\t\t...fieldNames.map((f) => {\n\t\t\t\tconst descriptor = collectionDef.fields[f]\n\t\t\t\treturn descriptor ? serializeFieldValue(recordData[f] ?? null, descriptor) : null\n\t\t\t}),\n\t\t\tcreatedAt,\n\t\t\tupdatedAt,\n\t\t\t0, // _deleted = false\n\t\t]\n\n\t\tconst columnsSql = sql.raw(allColumns.map((c) => quoteIdent(c)).join(', '))\n\t\tconst valuesSql = sql.join(\n\t\t\tvalues.map((v) => sql`${v}`),\n\t\t\tsql.raw(', '),\n\t\t)\n\t\tconst updateSet = sql.raw(\n\t\t\tallColumns\n\t\t\t\t.slice(1)\n\t\t\t\t.map((c) => `${quoteIdent(c)} = excluded.${quoteIdent(c)}`)\n\t\t\t\t.join(', '),\n\t\t)\n\n\t\ttxOrDb.run(\n\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(tableName))} (${columnsSql}) VALUES (${valuesSql}) ON CONFLICT (id) DO UPDATE SET ${updateSet}`,\n\t\t)\n\t}\n\n\t/**\n\t * Backfill all materialized collection tables from the existing operation log.\n\t * Called when setSchema() is invoked and operations already exist.\n\t */\n\tprivate async backfillAllCollections(): Promise<void> {\n\t\tif (!this.schema) return\n\n\t\tfor (const collectionName of Object.keys(this.schema.collections)) {\n\t\t\tthis.backfillCollection(collectionName)\n\t\t}\n\t}\n\n\t/**\n\t * Backfill a single collection's materialized table from operations.\n\t */\n\tprivate backfillCollection(collectionName: string): void {\n\t\tconst collectionDef = this.schema?.collections[collectionName]\n\t\tif (!collectionDef) return\n\n\t\t// Fetch all ops for this collection, in HLC total order (wallTime, logical, nodeId).\n\t\tconst allOps = this.db\n\t\t\t.select({\n\t\t\t\trecordId: operations.recordId,\n\t\t\t\ttype: operations.type,\n\t\t\t\tdata: operations.data,\n\t\t\t\tatomicOps: operations.atomicOps,\n\t\t\t\twallTime: operations.wallTime,\n\t\t\t})\n\t\t\t.from(operations)\n\t\t\t.where(eq(operations.collection, collectionName))\n\t\t\t.orderBy(asc(operations.wallTime), asc(operations.logical), asc(operations.timestampNodeId))\n\t\t\t.all()\n\n\t\tif (allOps.length === 0) return\n\n\t\t// Group by recordId\n\t\tconst grouped = new Map<string, typeof allOps>()\n\t\tfor (const op of allOps) {\n\t\t\tlet group = grouped.get(op.recordId)\n\t\t\tif (!group) {\n\t\t\t\tgroup = []\n\t\t\t\tgrouped.set(op.recordId, group)\n\t\t\t}\n\t\t\tgroup.push(op)\n\t\t}\n\n\t\t// Rebuild each record inside a single transaction for efficiency\n\t\tconst fieldNames = Object.keys(collectionDef.fields)\n\t\tthis.db.transaction((tx) => {\n\t\t\tfor (const [recordId, recordOps] of grouped) {\n\t\t\t\tconst parsedOps = recordOps.map((op) => ({\n\t\t\t\t\ttype: op.type,\n\t\t\t\t\tdata: op.data !== null ? JSON.parse(op.data) : null,\n\t\t\t\t\tatomicOps:\n\t\t\t\t\t\top.atomicOps != null ? (JSON.parse(op.atomicOps) as Record<string, AtomicOp>) : null,\n\t\t\t\t}))\n\t\t\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\t\t\tif (recordData) {\n\t\t\t\t\tconst createdAt = (recordOps[0] as (typeof recordOps)[0]).wallTime\n\t\t\t\t\tconst updatedAt = (recordOps[recordOps.length - 1] as (typeof recordOps)[0]).wallTime\n\t\t\t\t\tthis.upsertMaterializedRecord(\n\t\t\t\t\t\ttx,\n\t\t\t\t\t\tcollectionName,\n\t\t\t\t\t\trecordId,\n\t\t\t\t\t\trecordData,\n\t\t\t\t\t\tfieldNames,\n\t\t\t\t\t\tcollectionDef,\n\t\t\t\t\t\tcreatedAt,\n\t\t\t\t\t\tupdatedAt,\n\t\t\t\t\t)\n\t\t\t\t} else {\n\t\t\t\t\ttx.run(\n\t\t\t\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(collectionName))} (id, _deleted, _created_at, _updated_at) VALUES (${recordId}, 1, ${Date.now()}, ${Date.now()}) ON CONFLICT (id) DO UPDATE SET _deleted = 1, _updated_at = ${Date.now()}`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Query building\n\t// ---------------------------------------------------------------------------\n\n\tprivate buildSelectQuery(collection: string, options?: CollectionQueryOptions): SQL {\n\t\tconst whereClause = this.buildWhereClause(\n\t\t\toptions?.where ?? {},\n\t\t\toptions?.includeDeleted ?? false,\n\t\t)\n\n\t\tconst parts: SQL[] = [\n\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`,\n\t\t]\n\n\t\tif (options?.orderBy) {\n\t\t\tconst dir = options.orderDirection === 'desc' ? 'DESC' : 'ASC'\n\t\t\tparts.push(sql.raw(` ORDER BY ${quoteIdent(options.orderBy)} ${dir}`))\n\t\t}\n\n\t\tif (options?.limit !== undefined) {\n\t\t\tparts.push(sql` LIMIT ${options.limit}`)\n\t\t}\n\n\t\tif (options?.offset !== undefined) {\n\t\t\tparts.push(sql` OFFSET ${options.offset}`)\n\t\t}\n\n\t\treturn sql.join(parts, sql.raw(''))\n\t}\n\n\tprivate buildWhereClause(where: Record<string, unknown>, includeDeleted: boolean): SQL {\n\t\tconst conditions: SQL[] = []\n\n\t\tif (!includeDeleted) {\n\t\t\tconditions.push(sql.raw('_deleted = 0'))\n\t\t}\n\n\t\tfor (const [key, value] of Object.entries(where)) {\n\t\t\tconditions.push(sql`${sql.raw(quoteIdent(key))} = ${value}`)\n\t\t}\n\n\t\tif (conditions.length === 0) {\n\t\t\treturn sql.raw('1 = 1')\n\t\t}\n\n\t\treturn sql.join(conditions, sql.raw(' AND '))\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Row deserialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate deserializeRow(\n\t\trow: Record<string, unknown>,\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t): MaterializedRecord {\n\t\tconst record: MaterializedRecord = { id: row.id as string }\n\n\t\tfor (const [fieldName, descriptor] of Object.entries(collectionDef.fields)) {\n\t\t\tif (fieldName in row) {\n\t\t\t\trecord[fieldName] = deserializeFieldValue(row[fieldName], descriptor)\n\t\t\t}\n\t\t}\n\n\t\t// Include metadata fields\n\t\tif ('_created_at' in row) record._created_at = row._created_at\n\t\tif ('_updated_at' in row) record._updated_at = row._updated_at\n\n\t\treturn record\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Fallback materialization (operation replay, no schema)\n\t// ---------------------------------------------------------------------------\n\n\tprivate materializeFromOpsLog(collection: string): MaterializedRecord[] {\n\t\tconst rows = this.db\n\t\t\t.select()\n\t\t\t.from(operations)\n\t\t\t.where(eq(operations.collection, collection))\n\t\t\t.orderBy(asc(operations.wallTime), asc(operations.logical), asc(operations.sequenceNumber))\n\t\t\t.all()\n\n\t\tconst records = new Map<string, Record<string, unknown>>()\n\t\tconst deleted = new Set<string>()\n\n\t\tfor (const row of rows) {\n\t\t\tconst recordId = row.recordId\n\t\t\tconst data = row.data !== null ? JSON.parse(row.data) : null\n\n\t\t\tswitch (row.type) {\n\t\t\t\tcase 'insert':\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\trecords.set(recordId, { id: recordId, ...data })\n\t\t\t\t\t\tdeleted.delete(recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'update':\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\tconst existing = records.get(recordId) ?? { id: recordId }\n\t\t\t\t\t\trecords.set(recordId, { ...existing, ...data })\n\t\t\t\t\t\tdeleted.delete(recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'delete':\n\t\t\t\t\tdeleted.add(recordId)\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tfor (const id of deleted) {\n\t\t\trecords.delete(id)\n\t\t}\n\n\t\treturn Array.from(records.values()) as MaterializedRecord[]\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Table setup\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * Create the operations and sync_state tables if they don't exist.\n\t */\n\tprivate ensureTables(): void {\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS operations (\n\t\t\t\tid TEXT PRIMARY KEY,\n\t\t\t\tnode_id TEXT NOT NULL,\n\t\t\t\ttype TEXT NOT NULL,\n\t\t\t\tcollection TEXT NOT NULL,\n\t\t\t\trecord_id TEXT NOT NULL,\n\t\t\t\tdata TEXT,\n\t\t\t\tprevious_data TEXT,\n\t\t\t\tatomic_ops TEXT,\n\t\t\t\twall_time INTEGER NOT NULL,\n\t\t\t\tlogical INTEGER NOT NULL,\n\t\t\t\ttimestamp_node_id TEXT NOT NULL,\n\t\t\t\tsequence_number INTEGER NOT NULL,\n\t\t\t\tcausal_deps TEXT NOT NULL DEFAULT '[]',\n\t\t\t\tschema_version INTEGER NOT NULL,\n\t\t\t\treceived_at INTEGER NOT NULL\n\t\t\t)\n\t\t`)\n\n\t\t// Backward-compatible migration: add atomic_ops to operation logs created\n\t\t// before atomic-op persistence. Nullable, so existing rows read as \"no atomic\n\t\t// ops\" and keep materializing by last-write-wins exactly as before. SQLite has\n\t\t// no ADD COLUMN IF NOT EXISTS, so tolerate the duplicate-column error on re-run.\n\t\ttry {\n\t\t\tthis.db.run(sql`ALTER TABLE operations ADD COLUMN atomic_ops TEXT`)\n\t\t} catch (e) {\n\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\t\t// Backward-compatible migration: add the delivery_seq column for the gap-free\n\t\t// delivery watermark. SQLite has no ADD COLUMN IF NOT EXISTS, so tolerate the\n\t\t// duplicate-column error on re-run.\n\t\ttry {\n\t\t\tthis.db.run(sql`ALTER TABLE operations ADD COLUMN delivery_seq INTEGER`)\n\t\t} catch (e) {\n\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_node_seq ON operations (node_id, sequence_number)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_delivery_seq ON operations (delivery_seq)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE UNIQUE INDEX IF NOT EXISTS idx_delivery_seq_unique\n\t\t\tON operations (delivery_seq)\n\t\t\tWHERE delivery_seq IS NOT NULL\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_collection ON operations (collection)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_received ON operations (received_at)\n\t\t`)\n\n\t\t// Index for efficient per-record operation lookups during materialization\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_collection_record ON operations (collection, record_id)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS sync_state (\n\t\t\t\tnode_id TEXT PRIMARY KEY,\n\t\t\t\tmax_sequence_number INTEGER NOT NULL,\n\t\t\t\tlast_seen_at INTEGER NOT NULL\n\t\t\t)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS delivery_counter (\n\t\t\t\tid INTEGER PRIMARY KEY,\n\t\t\t\tvalue INTEGER NOT NULL\n\t\t\t)\n\t\t`)\n\n\t\tthis.backfillDeliverySequence()\n\t}\n\n\t/**\n\t * Assign delivery sequences to any operations written before the column existed,\n\t * then seed the durable counter from the current max. Ordered by\n\t * (received_at, sequence_number, id) so the backfill is deterministic and stable\n\t * across restarts. A one-time migration: after it runs, all rows have a value.\n\t */\n\tprivate backfillDeliverySequence(): void {\n\t\tthis.db.transaction((tx) => {\n\t\t\tconst maxRow = tx.all<{ m: number | null }>(\n\t\t\t\tsql`SELECT MAX(delivery_seq) AS m FROM operations`,\n\t\t\t)\n\t\t\tlet next = maxRow[0]?.m ?? 0\n\t\t\tconst nullRows = tx.all<{ id: string }>(\n\t\t\t\tsql`SELECT id FROM operations WHERE delivery_seq IS NULL ORDER BY received_at ASC, sequence_number ASC, id ASC`,\n\t\t\t)\n\t\t\tfor (const row of nullRows) {\n\t\t\t\tnext += 1\n\t\t\t\ttx.run(sql`UPDATE operations SET delivery_seq = ${next} WHERE id = ${row.id}`)\n\t\t\t}\n\t\t\ttx.insert(deliveryCounter)\n\t\t\t\t.values({ id: 1, value: next })\n\t\t\t\t.onConflictDoUpdate({\n\t\t\t\t\ttarget: deliveryCounter.id,\n\t\t\t\t\tset: {\n\t\t\t\t\t\tvalue: sql`MAX(${deliveryCounter.value}, ${next})`,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\t.run()\n\t\t})\n\t}\n\n\t/**\n\t * Reserve the next delivery sequence inside the append transaction. SQLite locks\n\t * the database for the write transaction, and this counter row keeps sequence\n\t * allocation shared by every SqliteServerStore instance using the same file.\n\t */\n\tprivate nextDeliverySeq(tx: BetterSQLite3Database): number {\n\t\tconst rows = tx\n\t\t\t.update(deliveryCounter)\n\t\t\t.set({ value: sql`${deliveryCounter.value} + 1` })\n\t\t\t.where(eq(deliveryCounter.id, 1))\n\t\t\t.returning({ value: deliveryCounter.value })\n\t\t\t.all()\n\t\tconst value = rows[0]?.value\n\t\tif (value === undefined || value === null) {\n\t\t\tthrow new Error(\n\t\t\t\t'delivery_counter row (id=1) is missing; the operations log cannot assign delivery sequences',\n\t\t\t)\n\t\t}\n\t\treturn value\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Operation serialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate serializeOperation(\n\t\top: Operation,\n\t\treceivedAt: number,\n\t\tdeliverySeq: number,\n\t): typeof operations.$inferInsert {\n\t\treturn {\n\t\t\tid: op.id,\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 !== null ? JSON.stringify(op.data) : null,\n\t\t\tpreviousData: op.previousData !== null ? JSON.stringify(op.previousData) : null,\n\t\t\tatomicOps:\n\t\t\t\top.atomicOps && Object.keys(op.atomicOps).length > 0 ? JSON.stringify(op.atomicOps) : null,\n\t\t\twallTime: op.timestamp.wallTime,\n\t\t\tlogical: op.timestamp.logical,\n\t\t\ttimestampNodeId: op.timestamp.nodeId,\n\t\t\tsequenceNumber: op.sequenceNumber,\n\t\t\tcausalDeps: JSON.stringify(op.causalDeps),\n\t\t\tschemaVersion: op.schemaVersion,\n\t\t\treceivedAt,\n\t\t\tdeliverySeq,\n\t\t}\n\t}\n\n\tprivate deserializeOperation(row: typeof operations.$inferSelect): Operation {\n\t\tconst atomicOps =\n\t\t\trow.atomicOps != null ? (JSON.parse(row.atomicOps) as Record<string, AtomicOp>) : undefined\n\t\treturn {\n\t\t\tid: row.id,\n\t\t\tnodeId: row.nodeId,\n\t\t\ttype: row.type as Operation['type'],\n\t\t\tcollection: row.collection,\n\t\t\trecordId: row.recordId,\n\t\t\tdata: row.data !== null ? JSON.parse(row.data) : null,\n\t\t\tpreviousData: row.previousData !== null ? JSON.parse(row.previousData) : null,\n\t\t\ttimestamp: {\n\t\t\t\twallTime: row.wallTime,\n\t\t\t\tlogical: row.logical,\n\t\t\t\tnodeId: row.timestampNodeId,\n\t\t\t},\n\t\t\tsequenceNumber: row.sequenceNumber,\n\t\t\tcausalDeps: JSON.parse(row.causalDeps),\n\t\t\tschemaVersion: row.schemaVersion,\n\t\t\t...(atomicOps ? { atomicOps } : {}),\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Assertions\n\t// ---------------------------------------------------------------------------\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) {\n\t\t\tthrow new Error('SqliteServerStore is closed')\n\t\t}\n\t}\n\n\tprivate assertSchema(): void {\n\t\tif (!this.schema) {\n\t\t\tthrow new Error(\n\t\t\t\t'Schema not set. Call setSchema() before using queryCollection/findRecord/countCollection.',\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate assertCollection(collection: string): void {\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (!schema.collections[collection]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${collection}\". Available: ${Object.keys(schema.collections).join(', ')}`,\n\t\t\t)\n\t\t}\n\t}\n}\n\n/**\n * Creates a SqliteServerStore with a file-backed or in-memory database.\n * Handles database creation, Drizzle wrapping, and table setup.\n *\n * @param options - Configuration options\n * @param options.filename - Path to SQLite database file. Defaults to ':memory:' for testing.\n * @param options.nodeId - Server node ID. Auto-generated if not provided.\n * @returns A ready-to-use SqliteServerStore\n *\n * @example\n * ```typescript\n * import { createSqliteServerStore } from '@korajs/server'\n *\n * const store = createSqliteServerStore({ filename: './kora-server.db' })\n *\n * // Optional: enable materialized collection tables for fast queries\n * await store.setSchema(mySchema)\n *\n * const server = createKoraServer({ store, port: 3001 })\n * ```\n */\nexport function createSqliteServerStore(options: {\n\tfilename?: string\n\tnodeId?: string\n}): SqliteServerStore {\n\t// better-sqlite3 is a native CJS addon — use esmRequire (from createRequire)\n\t// so this works in both ESM and CJS contexts.\n\tconst Database = esmRequire('better-sqlite3')\n\tconst { drizzle } = esmRequire('drizzle-orm/better-sqlite3')\n\n\tconst filename = options.filename ?? ':memory:'\n\tconst sqlite = new Database(filename)\n\n\t// Enable WAL mode for better concurrent read/write performance\n\tsqlite.pragma('journal_mode = WAL')\n\n\tconst db = drizzle(sqlite)\n\treturn new SqliteServerStore(db, options.nodeId)\n}\n","import { index, integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'\n\n/**\n * Drizzle schema for the Kora sync server's SQLite database.\n *\n * Two tables:\n * - `operations` — the append-only operation log (content-addressed by id)\n * - `syncState` — tracks the max sequence number seen per node (version vector)\n */\n\nexport const operations = sqliteTable(\n\t'operations',\n\t{\n\t\tid: text('id').primaryKey(),\n\t\tnodeId: text('node_id').notNull(),\n\t\ttype: text('type').notNull(),\n\t\tcollection: text('collection').notNull(),\n\t\trecordId: text('record_id').notNull(),\n\t\tdata: text('data'), // JSON-serialized, null for deletes\n\t\tpreviousData: text('previous_data'), // JSON-serialized, null for insert/delete\n\t\tatomicOps: text('atomic_ops'), // JSON-serialized Record<field, AtomicOp>, null when none\n\t\twallTime: integer('wall_time').notNull(),\n\t\tlogical: integer('logical').notNull(),\n\t\ttimestampNodeId: text('timestamp_node_id').notNull(),\n\t\tsequenceNumber: integer('sequence_number').notNull(),\n\t\tcausalDeps: text('causal_deps').notNull().default('[]'), // JSON array of op IDs\n\t\tschemaVersion: integer('schema_version').notNull(),\n\t\treceivedAt: integer('received_at').notNull(),\n\t\t// Server-assigned monotonic delivery sequence, ordered by commit. Drives the\n\t\t// gap-free server->client delivery watermark. Nullable only for rows written\n\t\t// before the column existed; those are backfilled on startup.\n\t\tdeliverySeq: integer('delivery_seq'),\n\t},\n\t(table) => ({\n\t\tnodeSeqIdx: index('idx_node_seq').on(table.nodeId, table.sequenceNumber),\n\t\tcollectionIdx: index('idx_collection').on(table.collection),\n\t\treceivedIdx: index('idx_received').on(table.receivedAt),\n\t\tdeliveryIdx: index('idx_delivery_seq').on(table.deliverySeq),\n\t}),\n)\n\nexport const syncState = sqliteTable('sync_state', {\n\tnodeId: text('node_id').primaryKey(),\n\tmaxSequenceNumber: integer('max_sequence_number').notNull(),\n\tlastSeenAt: integer('last_seen_at').notNull(),\n})\n\nexport const deliveryCounter = sqliteTable('delivery_counter', {\n\tid: integer('id').primaryKey(),\n\tvalue: integer('value').notNull(),\n})\n","import { SyncError } from '@korajs/core'\nimport type { MessageSerializer } from '@korajs/sync'\nimport type {\n\tServerCloseHandler,\n\tServerErrorHandler,\n\tServerMessageHandler,\n\tServerTransport,\n} from './server-transport'\n\nexport interface HttpPollResponse {\n\tstatus: 200 | 204 | 304 | 410\n\tbody?: string | Uint8Array\n\theaders?: Record<string, string>\n}\n\ninterface QueuedMessage {\n\tetag: string\n\tcontentType: string\n\tpayload: string | Uint8Array\n}\n\n/**\n * Server-side transport for HTTP long-polling clients.\n *\n * Incoming client messages are pushed via POST, while outbound server\n * messages are pulled via GET long-poll requests.\n */\nexport class HttpServerTransport implements ServerTransport {\n\tprivate readonly serializer: MessageSerializer\n\n\tprivate messageHandler: ServerMessageHandler | null = null\n\tprivate closeHandler: ServerCloseHandler | null = null\n\tprivate errorHandler: ServerErrorHandler | null = null\n\n\tprivate connected = true\n\tprivate nextSequence = 1\n\tprivate readonly queue: QueuedMessage[] = []\n\n\tconstructor(serializer: MessageSerializer) {\n\t\tthis.serializer = serializer\n\t}\n\n\tsend(message: import('@korajs/sync').SyncMessage): void {\n\t\tif (!this.connected) return\n\n\t\tconst encoded = this.serializer.encode(message)\n\t\tconst isBinary = encoded instanceof Uint8Array\n\t\tthis.queue.push({\n\t\t\tetag: this.makeEtag(this.nextSequence++),\n\t\t\tcontentType: isBinary ? 'application/x-protobuf' : 'application/json',\n\t\t\tpayload: encoded,\n\t\t})\n\t}\n\n\tonMessage(handler: ServerMessageHandler): void {\n\t\tthis.messageHandler = handler\n\t}\n\n\tonClose(handler: ServerCloseHandler): void {\n\t\tthis.closeHandler = handler\n\t}\n\n\tonError(handler: ServerErrorHandler): void {\n\t\tthis.errorHandler = handler\n\t}\n\n\tisConnected(): boolean {\n\t\treturn this.connected\n\t}\n\n\tclose(code = 1000, reason = 'transport closed'): void {\n\t\tif (!this.connected) return\n\t\tthis.connected = false\n\t\tthis.queue.length = 0\n\t\tthis.closeHandler?.(code, reason)\n\t}\n\n\treceive(payload: string | Uint8Array): void {\n\t\tif (!this.connected) {\n\t\t\tthrow new SyncError('HTTP server transport is closed')\n\t\t}\n\n\t\ttry {\n\t\t\tconst message = this.serializer.decode(payload)\n\t\t\tthis.messageHandler?.(message)\n\t\t} catch (error) {\n\t\t\tthis.errorHandler?.(error instanceof Error ? error : new Error(String(error)))\n\t\t}\n\t}\n\n\tpoll(ifNoneMatch?: string): HttpPollResponse {\n\t\tif (!this.connected) {\n\t\t\treturn { status: 410 }\n\t\t}\n\n\t\tconst next = this.queue[0]\n\t\tif (!next) {\n\t\t\treturn { status: 204 }\n\t\t}\n\n\t\tif (ifNoneMatch && ifNoneMatch === next.etag) {\n\t\t\treturn {\n\t\t\t\tstatus: 304,\n\t\t\t\theaders: { etag: next.etag },\n\t\t\t}\n\t\t}\n\n\t\tthis.queue.shift()\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\tbody: next.payload,\n\t\t\theaders: {\n\t\t\t\t'content-type': next.contentType,\n\t\t\t\tetag: next.etag,\n\t\t\t},\n\t\t}\n\t}\n\n\tprivate makeEtag(sequence: number): string {\n\t\treturn `W/\"${sequence}\"`\n\t}\n}\n","import { SyncError } from '@korajs/core'\nimport type { SyncMessage } from '@korajs/sync'\nimport { JsonMessageSerializer } from '@korajs/sync'\nimport type { MessageSerializer } from '@korajs/sync'\nimport type {\n\tServerCloseHandler,\n\tServerErrorHandler,\n\tServerMessageHandler,\n\tServerTransport,\n} from './server-transport'\n\n/** WebSocket ready states (mirrors ws constants) */\nconst WS_OPEN = 1\n\n/**\n * Minimal interface for a ws.WebSocket instance.\n * Allows dependency injection for testing without importing ws directly.\n */\nexport interface WsWebSocket {\n\treadyState: number\n\tsend(data: string | Uint8Array, callback?: (err?: Error) => void): void\n\tclose(code?: number, reason?: string): void\n\ton(event: string, listener: (...args: unknown[]) => void): void\n\tremoveAllListeners(): void\n}\n\n/**\n * Options for WsServerTransport.\n */\nexport interface WsServerTransportOptions {\n\t/** Message serializer. Defaults to JsonMessageSerializer. */\n\tserializer?: MessageSerializer\n}\n\n/**\n * Server-side transport wrapping a ws.WebSocket connection.\n * Created for each incoming client connection.\n */\nexport class WsServerTransport implements ServerTransport {\n\tprivate readonly ws: WsWebSocket\n\tprivate readonly serializer: MessageSerializer\n\tprivate messageHandler: ServerMessageHandler | null = null\n\tprivate closeHandler: ServerCloseHandler | null = null\n\tprivate errorHandler: ServerErrorHandler | null = null\n\n\tconstructor(ws: WsWebSocket, options?: WsServerTransportOptions) {\n\t\tthis.ws = ws\n\t\tthis.serializer = options?.serializer ?? new JsonMessageSerializer()\n\t\tthis.setupListeners()\n\t}\n\n\tsend(message: SyncMessage): void {\n\t\tif (this.ws.readyState !== WS_OPEN) {\n\t\t\tthrow new SyncError('Cannot send message: WebSocket is not open', {\n\t\t\t\treadyState: this.ws.readyState,\n\t\t\t\tmessageType: message.type,\n\t\t\t})\n\t\t}\n\n\t\tconst encoded = this.serializer.encode(message)\n\t\tthis.ws.send(encoded)\n\t}\n\n\tonMessage(handler: ServerMessageHandler): void {\n\t\tthis.messageHandler = handler\n\t}\n\n\tonClose(handler: ServerCloseHandler): void {\n\t\tthis.closeHandler = handler\n\t}\n\n\tonError(handler: ServerErrorHandler): void {\n\t\tthis.errorHandler = handler\n\t}\n\n\tisConnected(): boolean {\n\t\treturn this.ws.readyState === WS_OPEN\n\t}\n\n\tclose(code?: number, reason?: string): void {\n\t\tthis.ws.close(code ?? 1000, reason ?? 'server closing')\n\t}\n\n\tprivate setupListeners(): void {\n\t\tthis.ws.on('message', (data: unknown) => {\n\t\t\ttry {\n\t\t\t\tif (\n\t\t\t\t\ttypeof data !== 'string' &&\n\t\t\t\t\t!(data instanceof Uint8Array) &&\n\t\t\t\t\t!(data instanceof ArrayBuffer)\n\t\t\t\t) {\n\t\t\t\t\tthrow new SyncError('Unsupported WebSocket payload type', {\n\t\t\t\t\t\tpayloadType: typeof data,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tconst decoded = this.serializer.decode(data)\n\t\t\t\tthis.messageHandler?.(decoded)\n\t\t\t} catch (err) {\n\t\t\t\tthis.errorHandler?.(err instanceof Error ? err : new Error(String(err)))\n\t\t\t}\n\t\t})\n\n\t\tthis.ws.on('close', (code: unknown, reason: unknown) => {\n\t\t\tthis.closeHandler?.(Number(code) || 1006, String(reason || 'connection closed'))\n\t\t})\n\n\t\tthis.ws.on('error', (err: unknown) => {\n\t\t\tthis.errorHandler?.(err instanceof Error ? err : new Error(String(err)))\n\t\t})\n\t}\n}\n","import type {\n\tKoraEventEmitter,\n\tOperation,\n\tOperationTransform,\n\tSchemaDefinition,\n} from '@korajs/core'\nimport { applyOperationTransforms } from '@korajs/core'\nimport { SyncError, generateUUIDv7, hashBlob } from '@korajs/core'\nimport { topologicalSort } from '@korajs/core/internal'\nimport type {\n\tAwarenessUpdateMessage,\n\tBlobChunkPushMessage,\n\tBlobChunkRequestMessage,\n\tBlobChunkResponseMessage,\n\tHandshakeMessage,\n\tMessageSerializer,\n\tOperationBatchMessage,\n\tSyncMessage,\n\tWireFormat,\n\tYjsDocUpdateMessage,\n} from '@korajs/sync'\nimport { decodeBlobChunkBytes } from '@korajs/sync'\nimport {\n\ttype DeltaCursor,\n\tNegotiatedMessageSerializer,\n\tSCHEMA_MISMATCH_PREFIX,\n\ttype SyncQuerySubset,\n\tcreateDeltaCursorFromBatch,\n\tdecodeDeltaCursor,\n\tdedupeQuerySubsets,\n\tencodeDeltaCursor,\n\tisClientSchemaVersionSupported,\n\toperationMatchesQuerySubsets,\n\tsliceOperationsAfterCursor,\n\tversionVectorToWire,\n\twireToVersionVector,\n} from '@korajs/sync'\nimport { applyServerOperation } from '../apply/apply-server-operation'\nimport type { OperationValidator } from '../apply/operation-validator'\nimport { isRetriableRejection } from '../apply/rejection-taxonomy'\nimport { NoAuthProvider } from '../auth/no-auth'\nimport type { Logger } from '../logging/structured-logger'\nimport { resolveSessionScopes } from '../scopes/resolve-session-scopes'\nimport {\n\tmissingScopeFields,\n\tnormalizeScopeMap,\n\toperationMatchesScopes,\n} from '../scopes/server-scope-filter'\nimport type { ProductionHttpRouteContext } from '../server/route-context'\nimport type { DeliveredOperation, ServerStore } from '../store/server-store'\nimport type { ServerTransport } from '../transport/server-transport'\nimport type { AuthContext, AuthProvider } from '../types'\nimport { isOperationTimestampValid } from './operation-validation'\nimport {\n\tDEFAULT_MAX_OPERATION_BYTES,\n\tDEFAULT_MAX_OPS_PER_MINUTE,\n\tSessionRateLimiter,\n\tvalidateOperationSize,\n} from './session-operation-limits'\n\nconst DEFAULT_BATCH_SIZE = 100\nconst DEFAULT_SCHEMA_VERSION = 1\n\n/**\n * Tracks auth providers we have already warned about, so the multi-tenant\n * no-scopes guardrail fires once per server (keyed by provider instance)\n * rather than once per client connection.\n */\nconst warnedUnscopedProviders = new WeakSet<AuthProvider>()\n\n/**\n * Warn once when a real (multi-user) auth provider is configured but an\n * authenticated session resolves to no sync scopes at all.\n *\n * With no scopes, `operationMatchesScopes` treats every operation as visible,\n * which is the correct zero-config behavior for a single-user local-first app.\n * But once a real auth provider is in play, \"no scopes\" means every user syncs\n * every other user's data — a silent cross-tenant data exposure. We cannot flip\n * the default to deny-all without breaking the zero-config promise, so instead\n * we surface the dangerous configuration loudly and exactly once.\n *\n * `null` auth (local-first, no auth) and `NoAuthProvider` (dev/testing) are\n * intentionally excluded: for those, unscoped sync is the intended behavior.\n */\nfunction warnIfMultiTenantWithoutScopes(\n\tauth: AuthProvider | null,\n\tresolvedScopes: unknown,\n\tschema: SchemaDefinition | null,\n): void {\n\tif (!auth || auth instanceof NoAuthProvider) {\n\t\treturn\n\t}\n\tif (resolvedScopes) {\n\t\treturn\n\t}\n\tif (!schema || Object.keys(schema.collections).length === 0) {\n\t\treturn\n\t}\n\tif (warnedUnscopedProviders.has(auth)) {\n\t\treturn\n\t}\n\twarnedUnscopedProviders.add(auth)\n\tconsole.warn(\n\t\t'[kora] An authenticated session resolved to no sync scopes, so every ' +\n\t\t\t\"user will sync every other user's data. Return per-user sync scopes \" +\n\t\t\t\"from your auth provider (for example KoraAuthProvider's resolveScopes) \" +\n\t\t\t'to isolate tenants. Note: declaring sync rules in your schema is not ' +\n\t\t\t'enough on its own — the per-user values come from the auth provider. ' +\n\t\t\t'(This warning is expected for single-tenant apps where all authenticated ' +\n\t\t\t'users are meant to share the same data.)',\n\t)\n}\n\nfunction stableStringify(value: unknown): string {\n\tif (Array.isArray(value)) {\n\t\treturn `[${value.map((item) => stableStringify(item)).join(',')}]`\n\t}\n\tif (value && typeof value === 'object') {\n\t\tconst record = value as Record<string, unknown>\n\t\tconst entries = Object.keys(record)\n\t\t\t.sort()\n\t\t\t.map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`)\n\t\treturn `{${entries.join(',')}}`\n\t}\n\treturn JSON.stringify(value)\n}\n\nfunction sameScopeMap(a: unknown, b: unknown): boolean {\n\tconst normalize = (value: unknown): unknown =>\n\t\tvalue && typeof value === 'object'\n\t\t\t? normalizeScopeMap(value as Record<string, Record<string, unknown>>)\n\t\t\t: value\n\treturn stableStringify(normalize(a) ?? null) === stableStringify(normalize(b) ?? null)\n}\n\n/**\n * Possible states for a client session.\n */\nexport type SessionState = 'connected' | 'authenticated' | 'syncing' | 'streaming' | 'closed'\n\n/**\n * Callback invoked when a session has new operations to relay to other sessions.\n */\nexport type RelayCallback = (sourceSessionId: string, operations: Operation[]) => void\n\n/**\n * Callback invoked when a session receives an awareness update to relay to other sessions.\n */\nexport type AwarenessRelayCallback = (\n\tsourceSessionId: string,\n\tmessage: AwarenessUpdateMessage,\n) => void\n\n/**\n * Callback invoked when a session receives a Yjs doc channel update to relay.\n */\nexport type YjsDocRelayCallback = (sourceSessionId: string, message: YjsDocUpdateMessage) => void\n\n/**\n * Callback invoked when a session receives a blob chunk request to route.\n */\nexport type BlobChunkRequestCallback = (\n\tsourceSessionId: string,\n\tmessage: BlobChunkRequestMessage,\n) => void\n\n/**\n * Callback invoked when a session receives a blob chunk response to route back.\n */\nexport type BlobChunkResponseCallback = (\n\tsourceSessionId: string,\n\tmessage: BlobChunkResponseMessage,\n) => void\n\n/**\n * Persist a blob chunk (or manifest) uploaded by a client, keyed by its content\n * hash. Provided by the server operator; enables central blob storage so bytes\n * survive the authoring device going offline.\n */\nexport type PersistBlobChunk = (hash: string, bytes: Uint8Array) => Promise<void> | void\n\n/**\n * Options for creating a ClientSession.\n */\nexport interface ClientSessionOptions {\n\t/** Unique session identifier */\n\tsessionId: string\n\t/** Transport for this client connection */\n\ttransport: ServerTransport\n\t/** Server-side operation store */\n\tstore: ServerStore\n\t/** Authentication provider (optional) */\n\tauth?: AuthProvider\n\t/** Message serializer */\n\tserializer?: MessageSerializer\n\t/** Event emitter for DevTools integration */\n\temitter?: KoraEventEmitter\n\t/** Structured logger used for protocol and persistence failures */\n\tlogger?: Logger\n\t/** Max operations per sync batch */\n\tbatchSize?: number\n\t/** Schema version the server expects */\n\tschemaVersion?: number\n\t/** Inclusive client schema versions accepted at handshake */\n\tsupportedSchemaVersions?: { min: number; max: number }\n\t/** Transform accepted legacy operations into the server schema before validation. */\n\toperationTransforms?: OperationTransform[]\n\t/** Called when this session has operations to relay to other sessions */\n\tonRelay?: RelayCallback\n\t/** Called when this session receives an awareness update to broadcast */\n\tonAwarenessUpdate?: AwarenessRelayCallback\n\t/** Called when this session receives a Yjs doc channel update to broadcast */\n\tonYjsDocUpdate?: YjsDocRelayCallback\n\t/** Called when this session receives a blob chunk request to route */\n\tonBlobChunkRequest?: BlobChunkRequestCallback\n\t/** Called when this session receives a blob chunk response to route back */\n\tonBlobChunkResponse?: BlobChunkResponseCallback\n\t/** Persist a client-uploaded blob chunk centrally (keyed by content hash) */\n\tpersistBlobChunk?: PersistBlobChunk\n\t/** Called when this session closes */\n\tonClose?: (sessionId: string) => void\n\t/**\n\t * Called on close with relay operations this client never acknowledged, so the\n\t * server can buffer them per node id and redeliver on the client's next\n\t * connection. Closes the window where a relay dropped just before a reconnect\n\t * would otherwise be lost (the per-session retransmit tick never fires in time).\n\t */\n\tonOrphanedRelays?: (nodeId: string, ops: Operation[]) => void\n\t/**\n\t * Called once this session reaches streaming to pull any relay operations buffered\n\t * for its node id while it was disconnected. They are re-sent through the normal\n\t * relay path (re-filtered by this session's current scope).\n\t */\n\ttakeOrphanedRelays?: (nodeId: string) => Operation[]\n\t/** Maximum serialized operation size in bytes. Defaults to 256 KiB. */\n\tmaxOperationBytes?: number\n\t/** Maximum operations accepted per minute for this session. Defaults to 600. */\n\tmaxOpsPerMinute?: number\n\t/**\n\t * Adjudicate untrusted client operations before materialization. When present,\n\t * each incoming operation is passed to this validator; a `reject` decision\n\t * sends an operation-rejected message and skips materialization.\n\t */\n\tvalidateOperation?: OperationValidator\n\t/** Trusted data-plane context handed to the validator (read state, author derived ops). */\n\tkoraContext?: ProductionHttpRouteContext\n}\n\n/**\n * Handles the sync protocol for a single connected client.\n *\n * Lifecycle: connected → (authenticated) → syncing → streaming → closed\n *\n * The session:\n * 1. Receives a handshake from the client\n * 2. Authenticates if an AuthProvider is configured\n * 3. Sends back a HandshakeResponse with the server's version vector\n * 4. Computes and sends the server's delta to the client (paginated)\n * 5. Processes incoming operation batches from the client\n * 6. Transitions to streaming for real-time bidirectional sync\n * 7. Relays new operations to other sessions via the RelayCallback\n */\nexport class ClientSession {\n\tprivate state: SessionState = 'connected'\n\tprivate clientNodeId: string | null = null\n\tprivate authContext: AuthContext | null = null\n\tprivate syncQuerySubsets: SyncQuerySubset[] = []\n\tprivate resumeDeltaCursor: DeltaCursor | null = null\n\n\t/**\n\t * The delivery watermark the client reported at handshake, or null when the client\n\t * does not use the delivery watermark (old client, or no watermark yet). When set,\n\t * the server drives the gap-free server->client stream from delivery sequences\n\t * instead of the version-vector delta.\n\t */\n\tprivate clientDeliveryWatermark: number | null = null\n\t/**\n\t * The highest delivery sequence this client has ACKNOWLEDGED (its confirmed\n\t * watermark, as reported in acks). Incremental streaming pushes resume from here, not\n\t * from the highest sequence sent, so a dropped or unapplied batch is always\n\t * re-included by the next push (which re-scans from the acknowledged position). This\n\t * is what makes streaming recovery independent of any bounded retransmit buffer: there\n\t * is no sent-but-unacked window that a buffer eviction could strand. Seeded from the\n\t * client's reported watermark at handshake.\n\t */\n\tprivate lastAckedDeliverySeq = 0\n\t/**\n\t * Timestamp of the last delivery-stream send attempt. Periodic retransmission uses\n\t * this as its stale window so a slow client does not receive duplicate full-stream\n\t * batches every server tick while the first batch is still being applied.\n\t */\n\tprivate lastDeliveryPushAttemptAtMs = 0\n\tprivate deliveryStallRepeatCount = 0\n\t/** Serializes incremental delivery pushes so their batches never interleave. */\n\tprivate deliveryPushChain: Promise<void> = Promise.resolve()\n\n\t/**\n\t * Relay batches sent to this client but not yet acknowledged, keyed by messageId.\n\t * The client acks every operation-batch it applies; on ack the entry is cleared.\n\t * {@link retransmitPendingRelays} re-sends anything still unacked, so a relay\n\t * dropped by a lossy transport is redelivered instead of leaving the client with a\n\t * permanent version-vector gap (a lost operation) that delta sync cannot recover.\n\t * Bounded so a silent client cannot grow it without limit.\n\t */\n\tprivate readonly pendingRelays = new Map<\n\t\tstring,\n\t\t{ message: SyncMessage; ops: Operation[]; sentAtMs: number }\n\t>()\n\tprivate static readonly MAX_PENDING_RELAYS = 1000\n\n\tprivate readonly sessionId: string\n\tprivate readonly transport: ServerTransport\n\tprivate readonly store: ServerStore\n\tprivate readonly auth: AuthProvider | null\n\tprivate readonly serializer: MessageSerializer\n\tprivate readonly emitter: KoraEventEmitter | null\n\tprivate readonly logger: Logger | null\n\tprivate readonly batchSize: number\n\tprivate readonly schemaVersion: number\n\tprivate readonly supportedSchemaVersions: { min: number; max: number }\n\tprivate readonly operationTransforms: OperationTransform[]\n\tprivate readonly onRelay: RelayCallback | null\n\tprivate readonly onAwarenessUpdate: AwarenessRelayCallback | null\n\tprivate readonly onYjsDocUpdate: YjsDocRelayCallback | null\n\tprivate readonly onBlobChunkRequest: BlobChunkRequestCallback | null\n\tprivate readonly onBlobChunkResponse: BlobChunkResponseCallback | null\n\tprivate readonly persistBlobChunk: PersistBlobChunk | null\n\tprivate readonly onClose: ((sessionId: string) => void) | null\n\tprivate readonly onOrphanedRelays: ((nodeId: string, ops: Operation[]) => void) | null\n\tprivate readonly takeOrphanedRelays: ((nodeId: string) => Operation[]) | null\n\tprivate readonly maxOperationBytes: number\n\tprivate readonly maxOpsPerMinute: number\n\tprivate readonly rateLimiter: SessionRateLimiter\n\tprivate readonly validateOperation: OperationValidator | null\n\tprivate readonly koraContext: ProductionHttpRouteContext | null\n\n\tconstructor(options: ClientSessionOptions) {\n\t\tthis.sessionId = options.sessionId\n\t\tthis.transport = options.transport\n\t\tthis.store = options.store\n\t\tthis.auth = options.auth ?? null\n\t\tthis.serializer = options.serializer ?? new NegotiatedMessageSerializer('json')\n\t\tthis.emitter = options.emitter ?? null\n\t\tthis.logger = options.logger ?? null\n\t\tthis.batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE\n\t\tthis.schemaVersion = options.schemaVersion ?? DEFAULT_SCHEMA_VERSION\n\t\tconst supported = options.supportedSchemaVersions\n\t\tthis.supportedSchemaVersions = supported ?? {\n\t\t\tmin: this.schemaVersion,\n\t\t\tmax: this.schemaVersion,\n\t\t}\n\t\tthis.operationTransforms = options.operationTransforms ?? []\n\t\tthis.onRelay = options.onRelay ?? null\n\t\tthis.onAwarenessUpdate = options.onAwarenessUpdate ?? null\n\t\tthis.onYjsDocUpdate = options.onYjsDocUpdate ?? null\n\t\tthis.onBlobChunkRequest = options.onBlobChunkRequest ?? null\n\t\tthis.onBlobChunkResponse = options.onBlobChunkResponse ?? null\n\t\tthis.persistBlobChunk = options.persistBlobChunk ?? null\n\t\tthis.onClose = options.onClose ?? null\n\t\tthis.onOrphanedRelays = options.onOrphanedRelays ?? null\n\t\tthis.takeOrphanedRelays = options.takeOrphanedRelays ?? null\n\t\tthis.maxOperationBytes = options.maxOperationBytes ?? DEFAULT_MAX_OPERATION_BYTES\n\t\tthis.maxOpsPerMinute = options.maxOpsPerMinute ?? DEFAULT_MAX_OPS_PER_MINUTE\n\t\tthis.rateLimiter = new SessionRateLimiter(this.maxOpsPerMinute)\n\t\tthis.validateOperation = options.validateOperation ?? null\n\t\tthis.koraContext = options.koraContext ?? null\n\t}\n\n\t/**\n\t * Start handling messages from the client transport.\n\t */\n\tstart(): void {\n\t\tthis.transport.onMessage((msg) => this.enqueueMessage(msg))\n\t\tthis.transport.onClose((_code, _reason) => this.handleTransportClose())\n\t\tthis.transport.onError((_err) => {\n\t\t\t// Transport errors during active session cause close\n\t\t\tif (this.state !== 'closed') {\n\t\t\t\tthis.handleTransportClose()\n\t\t\t}\n\t\t})\n\t}\n\n\t/**\n\t * Relay operations from another session to this client.\n\t * Only relays if the session is in streaming state and transport is connected.\n\t */\n\trelayOperations(operations: Operation[]): void {\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\t// A delivery-watermark client is fed by the gap-free delivery stream, resumed from\n\t\t// the last sequence sent to it, so its watermark keeps advancing live and a\n\t\t// reconnect resends only what was genuinely missed. The specific operations from\n\t\t// the fan-out are only a wake-up: the push pulls everything in scope after the send\n\t\t// cursor from the delivery log, which is the authoritative, contiguous order.\n\t\tif (this.clientDeliveryWatermark !== null) {\n\t\t\tthis.pushDeliveryStream()\n\t\t\treturn\n\t\t}\n\t\tif (operations.length === 0) return\n\t\t// Visibility now requires an async record lookup (scope/subset backfill); relay\n\t\t// is fire-and-forget, so run it without blocking the caller's fan-out loop.\n\t\tvoid this.relayVisibleOperations(operations)\n\t}\n\n\t/**\n\t * Push newly-available in-scope operations to a delivery-watermark client, resuming\n\t * from the highest delivery sequence already sent. Pushes are serialized so their\n\t * batches never interleave (which would break the base/max chain).\n\t */\n\tprivate pushDeliveryStream(): void {\n\t\tthis.deliveryPushChain = this.deliveryPushChain.then(async () => {\n\t\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\t\ttry {\n\t\t\t\tthis.lastDeliveryPushAttemptAtMs = Date.now()\n\t\t\t\t// Resume from the client's last acknowledged sequence, not the last sent, so a\n\t\t\t\t// dropped or unapplied batch is re-included here. Exclude the client's own\n\t\t\t\t// operations during streaming; it already has them.\n\t\t\t\tawait this.sendDeliveryStream(\n\t\t\t\t\tthis.lastAckedDeliverySeq,\n\t\t\t\t\tfalse,\n\t\t\t\t\tthis.clientNodeId ?? undefined,\n\t\t\t\t)\n\t\t\t} catch {\n\t\t\t\t// A failed push (e.g. a transient store read error) must not reject the chain\n\t\t\t\t// and stall all future pushes. The next push, or a reconnect resend from the\n\t\t\t\t// client's watermark, recovers anything this push did not deliver.\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate async relayVisibleOperations(operations: Operation[]): Promise<void> {\n\t\tconst visibleOperations: Operation[] = []\n\t\tfor (const op of operations) {\n\t\t\tif (await this.operationVisibleToClient(op)) {\n\t\t\t\tvisibleOperations.push(op)\n\t\t\t}\n\t\t}\n\t\tif (visibleOperations.length === 0) return\n\t\t// Re-check liveness: an await may have elapsed since the caller's guard.\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\n\t\tconst serializedOps = visibleOperations.map((op) => this.serializer.encodeOperation(op))\n\t\tconst msg: SyncMessage = {\n\t\t\ttype: 'operation-batch',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\toperations: serializedOps,\n\t\t\tisFinal: true,\n\t\t\tbatchIndex: 0,\n\t\t}\n\t\t// Track this relay until the client acks it, so a drop can be retransmitted.\n\t\tthis.trackPendingRelay(msg, visibleOperations)\n\t\tthis.sendToClient(msg)\n\t}\n\n\t/** Record a relay batch as awaiting acknowledgment, evicting the oldest if full. */\n\tprivate trackPendingRelay(msg: SyncMessage, ops: Operation[]): void {\n\t\tif (this.pendingRelays.size >= ClientSession.MAX_PENDING_RELAYS) {\n\t\t\tconst oldest = this.pendingRelays.keys().next().value\n\t\t\tif (oldest !== undefined) {\n\t\t\t\tthis.pendingRelays.delete(oldest)\n\t\t\t}\n\t\t}\n\t\tthis.pendingRelays.set(msg.messageId, { message: msg, ops, sentAtMs: Date.now() })\n\t}\n\n\t/**\n\t * Retransmit relay batches this client has not acknowledged within `staleMs`.\n\t * Called on a periodic tick by the server (and directly by tests). Redelivering an\n\t * already-applied op is harmless: the client dedups by content-addressed id.\n\t */\n\tretransmitPendingRelays(staleMs = 0): void {\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\tif (this.clientDeliveryWatermark !== null) {\n\t\t\treturn\n\t\t}\n\t\tif (this.pendingRelays.size === 0) return\n\t\tconst cutoff = Date.now() - staleMs\n\t\tfor (const { message, sentAtMs } of this.pendingRelays.values()) {\n\t\t\tif (sentAtMs <= cutoff) {\n\t\t\t\tthis.sendToClient(message)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Wake the durable delivery stream for clients that negotiated delivery\n\t * watermarks. This is used both for dropped watermark batches and for operations\n\t * appended by another server/store instance: the session always scans from its\n\t * own acknowledged cursor and applies its visibility filter before sending.\n\t */\n\tpushDeliveryStreamIfSupported(staleMs = 0, options: { trackStall?: boolean } = {}): void {\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\tif (this.clientDeliveryWatermark === null) return\n\t\tif (staleMs > 0 && Date.now() - this.lastDeliveryPushAttemptAtMs < staleMs) {\n\t\t\treturn\n\t\t}\n\t\tif (options.trackStall) {\n\t\t\tthis.deliveryStallRepeatCount += 1\n\t\t\tif (this.deliveryStallRepeatCount >= 3) {\n\t\t\t\tthis.emitter?.emit({\n\t\t\t\t\ttype: 'sync:delivery-stalled',\n\t\t\t\t\tsessionId: this.sessionId,\n\t\t\t\t\twatermark: this.lastAckedDeliverySeq,\n\t\t\t\t\trepeatCount: this.deliveryStallRepeatCount,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tthis.pushDeliveryStream()\n\t}\n\n\t/**\n\t * Close this session.\n\t */\n\t/**\n\t * Hand any unacknowledged relays to the server so they survive this session and are\n\t * redelivered when this client reconnects (per-node buffer), then clear them. Called\n\t * from every session-teardown path (explicit close and transport close).\n\t */\n\tprivate flushOrphanedRelays(): void {\n\t\tif (this.onOrphanedRelays && this.clientNodeId && this.pendingRelays.size > 0) {\n\t\t\tconst ops: Operation[] = []\n\t\t\tfor (const entry of this.pendingRelays.values()) {\n\t\t\t\tops.push(...entry.ops)\n\t\t\t}\n\t\t\tif (ops.length > 0) {\n\t\t\t\tthis.onOrphanedRelays(this.clientNodeId, ops)\n\t\t\t}\n\t\t}\n\t\tthis.pendingRelays.clear()\n\t}\n\n\tclose(reason?: string): void {\n\t\tif (this.state === 'closed') return\n\t\tthis.state = 'closed'\n\t\tthis.flushOrphanedRelays()\n\n\t\tif (this.transport.isConnected()) {\n\t\t\tthis.transport.close(1000, reason ?? 'session closed')\n\t\t}\n\n\t\tthis.onClose?.(this.sessionId)\n\t}\n\n\t// --- Getters ---\n\n\tgetState(): SessionState {\n\t\treturn this.state\n\t}\n\n\tgetSessionId(): string {\n\t\treturn this.sessionId\n\t}\n\n\tgetClientNodeId(): string | null {\n\t\treturn this.clientNodeId\n\t}\n\n\tgetAuthContext(): AuthContext | null {\n\t\treturn this.authContext\n\t}\n\n\tisStreaming(): boolean {\n\t\treturn this.state === 'streaming'\n\t}\n\n\t/**\n\t * Get the transport for this session.\n\t * Used by the awareness relay to send messages to this client.\n\t */\n\tgetTransport(): ServerTransport {\n\t\treturn this.transport\n\t}\n\n\t// --- Private protocol handlers ---\n\n\tprivate messageChain: Promise<void> = Promise.resolve()\n\n\t/** Send to the client when the transport is still connected; no-op otherwise. */\n\tprivate sendToClient(message: SyncMessage): boolean {\n\t\tif (!this.transport.isConnected()) {\n\t\t\treturn false\n\t\t}\n\t\ttry {\n\t\t\tthis.transport.send(message)\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tprivate enqueueMessage(message: SyncMessage): void {\n\t\tthis.messageChain = this.messageChain\n\t\t\t.then(() => this.handleMessageAsync(message))\n\t\t\t.catch((error) => this.handleMessageFailure(error))\n\t}\n\n\tprivate async handleMessageAsync(message: SyncMessage): Promise<void> {\n\t\tswitch (message.type) {\n\t\t\tcase 'handshake':\n\t\t\t\tawait this.handleHandshake(message)\n\t\t\t\tbreak\n\t\t\tcase 'operation-batch':\n\t\t\t\tawait this.handleOperationBatch(message)\n\t\t\t\tbreak\n\t\t\tcase 'acknowledgment':\n\t\t\t\tthis.pendingRelays.delete(message.acknowledgedMessageId)\n\t\t\t\tif (message.deliverySequence !== undefined) {\n\t\t\t\t\t// Advance the confirmed watermark; the next streaming push resumes here.\n\t\t\t\t\tthis.lastAckedDeliverySeq = Math.max(this.lastAckedDeliverySeq, message.deliverySequence)\n\t\t\t\t\tthis.deliveryStallRepeatCount = 0\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\tcase 'error':\n\t\t\t\tbreak\n\t\t\tcase 'awareness-update':\n\t\t\t\tthis.handleAwarenessUpdate(message)\n\t\t\t\tbreak\n\t\t\tcase 'yjs-doc-update':\n\t\t\t\tthis.handleYjsDocUpdate(message)\n\t\t\t\tbreak\n\t\t\tcase 'blob-chunk-request':\n\t\t\t\tthis.onBlobChunkRequest?.(this.sessionId, message)\n\t\t\t\tbreak\n\t\t\tcase 'blob-chunk-response':\n\t\t\t\tthis.onBlobChunkResponse?.(this.sessionId, message)\n\t\t\t\tbreak\n\t\t\tcase 'blob-chunk-push':\n\t\t\t\tawait this.handleBlobChunkPush(message)\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\t/**\n\t * Persist a client-uploaded blob chunk (or manifest) centrally. The bytes are\n\t * verified to hash to the declared hash before storing, so a corrupt or\n\t * mislabeled upload is rejected rather than served later as trusted content.\n\t */\n\tprivate async handleBlobChunkPush(message: BlobChunkPushMessage): Promise<void> {\n\t\tif (!this.persistBlobChunk) {\n\t\t\treturn\n\t\t}\n\t\tconst bytes = decodeBlobChunkBytes(message.bytes)\n\t\tconst actual = await hashBlob(bytes)\n\t\tif (actual !== message.hash) {\n\t\t\t// Reject a mismatched upload rather than persisting untrusted bytes.\n\t\t\treturn\n\t\t}\n\t\tawait this.persistBlobChunk(message.hash, bytes)\n\t}\n\n\tprivate handleMessageFailure(error: unknown): void {\n\t\tconst reason = error instanceof Error ? error.message : 'Message handling failed'\n\t\tthis.logger?.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'error',\n\t\t\tevent: 'session.message_failed',\n\t\t\tsessionId: this.sessionId,\n\t\t\tnodeId: this.clientNodeId ?? undefined,\n\t\t\terror: reason,\n\t\t\tdetails: {\n\t\t\t\tstate: this.state,\n\t\t\t\terrorName: error instanceof Error ? error.name : typeof error,\n\t\t\t},\n\t\t})\n\t\tthis.sendError('SYNC_ERROR', reason, true)\n\t\tthis.close(reason)\n\t}\n\n\tprivate async handleHandshake(msg: HandshakeMessage): Promise<void> {\n\t\t// Only accept handshake in 'connected' state (prevent duplicate handshakes)\n\t\tif (this.state !== 'connected') {\n\t\t\tthis.sendError('DUPLICATE_HANDSHAKE', 'Handshake already completed', false)\n\t\t\treturn\n\t\t}\n\n\t\tthis.clientNodeId = msg.nodeId\n\n\t\t// Authenticate if provider is configured\n\t\tif (this.auth) {\n\t\t\tconst token = msg.authToken ?? ''\n\t\t\tconst context = await this.auth.authenticate(token)\n\t\t\tif (!context) {\n\t\t\t\tthis.sendError('AUTH_FAILED', 'Authentication failed', false)\n\t\t\t\tthis.close('authentication failed')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.authContext = context\n\t\t\tthis.state = 'authenticated'\n\t\t}\n\n\t\t// Merge handshake sync scopes with auth scopes using schema sync rules.\n\t\tconst rawResolvedScopes = resolveSessionScopes(this.store.getSchema(), {\n\t\t\thandshakeScope: msg.syncScope,\n\t\t\tauthScopes: this.authContext?.scopes,\n\t\t})\n\t\tlet resolvedScopes: typeof rawResolvedScopes\n\t\ttry {\n\t\t\tresolvedScopes = rawResolvedScopes ? normalizeScopeMap(rawResolvedScopes) : undefined\n\t\t} catch (error) {\n\t\t\tthis.sendToClient({\n\t\t\t\ttype: 'error',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tcode: 'SCOPE_PREDICATE_LIMIT',\n\t\t\t\tmessage: error instanceof Error ? error.message : 'Invalid scope predicate',\n\t\t\t\tretriable: false,\n\t\t\t})\n\t\t\tthis.close('invalid scope predicate')\n\t\t\treturn\n\t\t}\n\n\t\tif (resolvedScopes) {\n\t\t\tif (this.authContext) {\n\t\t\t\tthis.authContext = { ...this.authContext, scopes: resolvedScopes }\n\t\t\t} else {\n\t\t\t\tthis.authContext = { userId: msg.nodeId, scopes: resolvedScopes }\n\t\t\t}\n\t\t}\n\n\t\twarnIfMultiTenantWithoutScopes(this.auth, resolvedScopes, this.store.getSchema())\n\n\t\tif (msg.syncQueries && msg.syncQueries.length > 0) {\n\t\t\tthis.syncQuerySubsets = dedupeQuerySubsets(msg.syncQueries)\n\t\t} else {\n\t\t\tthis.syncQuerySubsets = []\n\t\t}\n\n\t\tthis.resumeDeltaCursor = msg.deltaCursor ? decodeDeltaCursor(msg.deltaCursor) : null\n\t\tthis.clientDeliveryWatermark = msg.lastDeliverySequence ?? null\n\t\t// A delivery watermark is valid only for the exact server-visible view that\n\t\t// earned it. When the server resolves a different scope than the client sent\n\t\t// (common with server-auth scopes, promotions, or invite acceptance), the client\n\t\t// cannot have keyed its local watermark by that authoritative view before this\n\t\t// handshake. Reset to a full scoped backfill instead of trusting a cursor that may\n\t\t// have advanced over previously hidden operations.\n\t\tif (\n\t\t\tthis.clientDeliveryWatermark !== null &&\n\t\t\t!sameScopeMap(msg.syncScope, this.authContext?.scopes)\n\t\t) {\n\t\t\tthis.clientDeliveryWatermark = 0\n\t\t}\n\n\t\t// Only read the server's delivery frontier when the client actually uses the\n\t\t// watermark. If the client's reported watermark exceeds that frontier, the server's\n\t\t// log was rolled back (for example a backup restore reset the sequence), so resync\n\t\t// that client from the beginning rather than let it sit above a frontier that no\n\t\t// longer exists; the server advertises its max so the client resets to match.\n\t\tconst clientUsesWatermark = this.clientDeliveryWatermark !== null\n\t\tlet serverMaxDelivery = 0\n\t\tif (clientUsesWatermark) {\n\t\t\tserverMaxDelivery = await this.store.getMaxDeliverySequence()\n\t\t\tif (\n\t\t\t\tthis.clientDeliveryWatermark !== null &&\n\t\t\t\tthis.clientDeliveryWatermark > serverMaxDelivery\n\t\t\t) {\n\t\t\t\tthis.clientDeliveryWatermark = 0\n\t\t\t}\n\t\t}\n\n\t\tconst serverVector = this.store.getVersionVector()\n\t\tconst selectedWireFormat = selectWireFormat(msg.supportedWireFormats)\n\t\tthis.setSerializerWireFormat(selectedWireFormat)\n\n\t\tif (!isClientSchemaVersionSupported(msg.schemaVersion, this.supportedSchemaVersions)) {\n\t\t\tconst { min, max } = this.supportedSchemaVersions\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:schema-mismatch',\n\t\t\t\tclientSchemaVersion: msg.schemaVersion,\n\t\t\t\tserverSchemaVersion: this.schemaVersion,\n\t\t\t\tsupportedMin: min,\n\t\t\t\tsupportedMax: max,\n\t\t\t\treason: `${SCHEMA_MISMATCH_PREFIX}: client schema version ${msg.schemaVersion} not in supported range [${min}, ${max}]`,\n\t\t\t})\n\t\t\tconst response: SyncMessage = {\n\t\t\t\ttype: 'handshake-response',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tnodeId: this.store.getNodeId(),\n\t\t\t\tversionVector: versionVectorToWire(serverVector),\n\t\t\t\tschemaVersion: this.schemaVersion,\n\t\t\t\taccepted: false,\n\t\t\t\trejectReason: `${SCHEMA_MISMATCH_PREFIX}: client schema version ${msg.schemaVersion} not in supported range [${min}, ${max}]`,\n\t\t\t\tsupportedSchemaMin: min,\n\t\t\t\tsupportedSchemaMax: max,\n\t\t\t\tserverTime: Date.now(),\n\t\t\t}\n\t\t\tthis.sendToClient(response)\n\t\t\tthis.close('schema version mismatch')\n\t\t\treturn\n\t\t}\n\n\t\t// Send handshake response with server's version vector and accepted scope\n\t\tconst response: SyncMessage = {\n\t\t\ttype: 'handshake-response',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tnodeId: this.store.getNodeId(),\n\t\t\tversionVector: versionVectorToWire(serverVector),\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t\taccepted: true,\n\t\t\tselectedWireFormat,\n\t\t\tserverTime: Date.now(),\n\t\t\t// The server's highest delivery sequence, so a client whose persisted watermark\n\t\t\t// is ahead of it (server rolled back) can reset to a full resync. Sent only to\n\t\t\t// watermark-using clients.\n\t\t\t...(clientUsesWatermark ? { serverMaxDeliverySequence: serverMaxDelivery } : {}),\n\t\t\t// Advertise central blob storage so the client uploads the bytes behind\n\t\t\t// its blob fields, keeping them available after the author goes offline.\n\t\t\t...(this.persistBlobChunk ? { blobStorageEnabled: true } : {}),\n\t\t\t// Confirm the accepted scope so the client knows what data will be synced.\n\t\t\t// This may differ from what the client requested if auth scopes are narrower.\n\t\t\t...(this.authContext?.scopes ? { acceptedScope: this.authContext.scopes } : {}),\n\t\t}\n\t\tthis.sendToClient(response)\n\n\t\tthis.emitter?.emit({ type: 'sync:connected', nodeId: msg.nodeId })\n\n\t\t// Transition to syncing and send the server->client stream. A client that\n\t\t// reports a delivery watermark gets the gap-free delivery stream (resumed from\n\t\t// that watermark); an older client gets the version-vector delta. Both send only\n\t\t// operations visible in this session's scope.\n\t\tthis.state = 'syncing'\n\t\tif (this.clientDeliveryWatermark !== null) {\n\t\t\tthis.lastAckedDeliverySeq = this.clientDeliveryWatermark\n\t\t\t// Resuming from a non-zero watermark: the client already holds its own history,\n\t\t\t// so exclude its own operations. A full resync (watermark 0, e.g. a fresh or\n\t\t\t// recovered client) passes no exclusion so it recovers everything, its own\n\t\t\t// operations included.\n\t\t\tconst excludeOwn =\n\t\t\t\tthis.clientDeliveryWatermark > 0 ? (this.clientNodeId ?? undefined) : undefined\n\t\t\tthis.lastDeliveryPushAttemptAtMs = Date.now()\n\t\t\tawait this.sendDeliveryStream(this.clientDeliveryWatermark, true, excludeOwn)\n\t\t} else {\n\t\t\tconst clientVector = wireToVersionVector(msg.versionVector)\n\t\t\tawait this.sendDelta(clientVector)\n\t\t}\n\n\t\t// Transition to streaming after delta is sent\n\t\tthis.state = 'streaming'\n\n\t\t// Redeliver any relays buffered while this client's node id was disconnected\n\t\t// (dropped just before a prior reconnect). relayOperations re-filters them by\n\t\t// this session's current scope and re-tracks them for acknowledgment.\n\t\tif (this.takeOrphanedRelays && this.clientNodeId) {\n\t\t\tconst buffered = this.takeOrphanedRelays(this.clientNodeId)\n\t\t\tif (buffered.length > 0) {\n\t\t\t\tthis.relayOperations(buffered)\n\t\t\t}\n\t\t}\n\t\t// A delivery-watermark client needs no explicit drain here: an operation committed\n\t\t// during the handshake-scan-to-streaming window is picked up by the next streaming\n\t\t// push (or the retransmit tick), which resumes from the client's acknowledged\n\t\t// position. Draining here would re-scan from the not-yet-advanced acknowledged\n\t\t// position and re-send the whole handshake stream.\n\t}\n\n\tprivate async handleOperationBatch(msg: OperationBatchMessage): Promise<void> {\n\t\tconst operations = msg.operations.map((s) => this.serializer.decodeOperation(s))\n\t\tconst applied: Operation[] = []\n\t\tlet acknowledgedThrough = 0\n\t\tlet canAdvanceAck = true\n\n\t\tfor (const op of operations) {\n\t\t\tif (!canAdvanceAck) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (!(await this.operationVisibleToClient(op))) {\n\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\top,\n\t\t\t\t\t'SCOPE_VIOLATION',\n\t\t\t\t\t`Operation \"${op.id}\" in collection \"${op.collection}\" is outside the client's sync scope. Refresh sync scopes and retry.`,\n\t\t\t\t\ttrue,\n\t\t\t\t)\n\t\t\t\tcanAdvanceAck = false\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (!isOperationTimestampValid(op)) {\n\t\t\t\tthis.sendError(\n\t\t\t\t\t'INVALID_TIMESTAMP',\n\t\t\t\t\t`Operation \"${op.id}\" timestamp is too far in the future`,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\tcanAdvanceAck = false\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (!this.rateLimiter.allow(1)) {\n\t\t\t\tthis.sendError(\n\t\t\t\t\t'RATE_LIMIT',\n\t\t\t\t\t`Session exceeded operation rate limit (${String(this.maxOpsPerMinute)} ops/min)`,\n\t\t\t\t\ttrue,\n\t\t\t\t)\n\t\t\t\tcanAdvanceAck = false\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst sizeCheck = validateOperationSize(op, this.maxOperationBytes)\n\t\t\tif (!sizeCheck.valid) {\n\t\t\t\tthis.sendError(\n\t\t\t\t\t'OPERATION_TOO_LARGE',\n\t\t\t\t\tsizeCheck.message ?? `Operation \"${op.id}\" is too large`,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\tcanAdvanceAck = false\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst serverOp = this.transformForServerSchema(op)\n\t\t\tif (serverOp === null) {\n\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\top,\n\t\t\t\t\t'SCHEMA_TRANSFORM_UNAVAILABLE',\n\t\t\t\t\t`Operation \"${op.id}\" cannot be transformed from schema v${op.schemaVersion} to server schema v${this.schemaVersion}.`,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Server-side adjudication of untrusted client operations. Runs after\n\t\t\t// the built-in guards and before materialization, so a rejected op never\n\t\t\t// enters the authoritative log and never relays to other clients.\n\t\t\tif (this.validateOperation && this.koraContext) {\n\t\t\t\tlet decision: Awaited<ReturnType<OperationValidator>>\n\t\t\t\ttry {\n\t\t\t\t\tdecision = await this.validateOperation(serverOp, {\n\t\t\t\t\t\tauth: this.authContext,\n\t\t\t\t\t\tkora: this.koraContext,\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// A throwing validator must not crash ingestion or silently accept.\n\t\t\t\t\t// Treat it as a retriable rejection so the submitter can try again.\n\t\t\t\t\tconst message = error instanceof Error ? error.message : 'validator error'\n\t\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\t\tserverOp,\n\t\t\t\t\t\t'VALIDATION_ERROR',\n\t\t\t\t\t\t`Validator threw: ${message}`,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t)\n\t\t\t\t\tcanAdvanceAck = false\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (decision.action === 'reject') {\n\t\t\t\t\tconst retriable = decision.retriable ?? isRetriableRejection(decision.code)\n\t\t\t\t\tthis.sendOperationRejected(serverOp, decision.code, decision.message, retriable)\n\t\t\t\t\tif (retriable) {\n\t\t\t\t\t\tcanAdvanceAck = false\n\t\t\t\t\t} else {\n\t\t\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (decision.action === 'ignore') {\n\t\t\t\t\t// The server took responsibility out of band; do not materialize the\n\t\t\t\t\t// raw op and do not reject. The batch ack lets the client drop it.\n\t\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// action === 'accept' falls through to normal materialization.\n\t\t\t}\n\n\t\t\tconst applyResult = await applyServerOperation(this.store, serverOp)\n\t\t\tif (applyResult.rejection) {\n\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\tserverOp,\n\t\t\t\t\tapplyResult.rejection.code,\n\t\t\t\t\tapplyResult.rejection.message,\n\t\t\t\t\tapplyResult.rejection.retriable,\n\t\t\t\t)\n\t\t\t\tif (applyResult.rejection.retriable) {\n\t\t\t\t\tcanAdvanceAck = false\n\t\t\t\t} else {\n\t\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (applyResult.result === 'applied') {\n\t\t\t\tapplied.push(...applyResult.appliedOperations)\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t} else {\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t}\n\t\t}\n\n\t\tif (operations.length > 0) {\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:received',\n\t\t\t\toperations,\n\t\t\t\tbatchSize: operations.length,\n\t\t\t})\n\t\t}\n\n\t\t// Send acknowledgment\n\t\tconst lastOp = operations[operations.length - 1]\n\t\tconst ack: SyncMessage = {\n\t\t\ttype: 'acknowledgment',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tacknowledgedMessageId: msg.messageId,\n\t\t\tlastSequenceNumber: lastOp ? Math.min(acknowledgedThrough, lastOp.sequenceNumber) : 0,\n\t\t}\n\t\tthis.sendToClient(ack)\n\n\t\t// Relay only newly applied operations to other sessions\n\t\tif (applied.length > 0) {\n\t\t\tthis.onRelay?.(this.sessionId, applied)\n\t\t}\n\t}\n\n\tprivate transformForServerSchema(op: Operation): Operation | null {\n\t\tif (op.schemaVersion === this.schemaVersion) {\n\t\t\treturn op\n\t\t}\n\t\treturn applyOperationTransforms(op, this.schemaVersion, this.operationTransforms)\n\t}\n\n\tprivate async sendDelta(clientVector: Map<string, number>): Promise<void> {\n\t\tconst serverVector = this.store.getVersionVector()\n\t\tconst missing: Operation[] = []\n\n\t\tfor (const [nodeId, serverSeq] of serverVector) {\n\t\t\tconst clientSeq = clientVector.get(nodeId) ?? 0\n\t\t\tif (serverSeq > clientSeq) {\n\t\t\t\tconst ops = await this.store.getOperationRange(nodeId, clientSeq + 1, serverSeq)\n\t\t\t\tfor (const op of ops) {\n\t\t\t\t\tif (await this.operationVisibleToClient(op)) {\n\t\t\t\t\t\tmissing.push(op)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (missing.length === 0) {\n\t\t\tconst emptyBatch: SyncMessage = {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\toperations: [],\n\t\t\t\tisFinal: true,\n\t\t\t\tbatchIndex: 0,\n\t\t\t\ttotalBatches: 1,\n\t\t\t}\n\t\t\tthis.sendToClient(emptyBatch)\n\t\t\treturn\n\t\t}\n\n\t\tconst sorted = topologicalSort(missing)\n\t\tconst afterCursor = sliceOperationsAfterCursor(sorted, this.resumeDeltaCursor)\n\t\tconst totalBatches = Math.ceil(afterCursor.length / this.batchSize)\n\n\t\tif (afterCursor.length === 0) {\n\t\t\tconst emptyBatch: SyncMessage = {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\toperations: [],\n\t\t\t\tisFinal: true,\n\t\t\t\tbatchIndex: this.resumeDeltaCursor?.batchIndex ?? 0,\n\t\t\t\ttotalBatches: 1,\n\t\t\t}\n\t\t\tthis.sendToClient(emptyBatch)\n\t\t\treturn\n\t\t}\n\n\t\tfor (let i = 0; i < totalBatches; i++) {\n\t\t\tconst start = i * this.batchSize\n\t\t\tconst batchOps = afterCursor.slice(start, start + this.batchSize)\n\t\t\tconst serializedOps = batchOps.map((op) => this.serializer.encodeOperation(op))\n\t\t\tconst batchCursor = createDeltaCursorFromBatch(batchOps, i)\n\n\t\t\tconst batchMsg: SyncMessage = {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\toperations: serializedOps,\n\t\t\t\tisFinal: i === totalBatches - 1,\n\t\t\t\tbatchIndex: i,\n\t\t\t\ttotalBatches,\n\t\t\t\t...(batchCursor ? { cursor: encodeDeltaCursor(batchCursor) } : {}),\n\t\t\t}\n\t\t\tthis.sendToClient(batchMsg)\n\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:sent',\n\t\t\t\toperations: batchOps,\n\t\t\t\tbatchSize: batchOps.length,\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Send the gap-free server->client delivery stream, resuming just after\n\t * `fromDeliverySeq`. Operations are scanned in server delivery-sequence order\n\t * (commit order), scope-filtered for this session, and sent in batches that chain:\n\t * each batch's `baseDeliverySequence` equals the previous batch's\n\t * `maxDeliverySequence` (the first batch bases on `fromDeliverySeq`). The client\n\t * applies a batch only when its watermark equals the base and advances the\n\t * watermark to the max, so a dropped batch stalls the watermark and is recovered by\n\t * the next handshake resend. Because delivery-sequence order respects causal order\n\t * (a dependency is always committed, and thus sequenced, before its dependent), no\n\t * topological sort is needed and the client never defers on a missing dependency\n\t * that is itself in this stream.\n\t *\n\t * The final batch advances the watermark to the highest delivery sequence scanned,\n\t * not merely the last in-scope one, so an out-of-scope tail is not re-scanned on the\n\t * next reconnect. Returns the number of operations actually sent.\n\t */\n\tprivate async sendDeliveryStream(\n\t\tfromDeliverySeq: number,\n\t\tfinalizeWhenEmpty: boolean,\n\t\texcludeNodeId?: string,\n\t): Promise<number> {\n\t\tconst scanChunk = Math.max(this.batchSize, 1) * 5\n\t\tlet scanCursor = fromDeliverySeq\n\t\tlet maxScanned = fromDeliverySeq\n\t\tconst visible: DeliveredOperation[] = []\n\n\t\twhile (true) {\n\t\t\tconst chunk = await this.store.getOperationsAfterDelivery(scanCursor, scanChunk)\n\t\t\tconst last = chunk[chunk.length - 1]\n\t\t\tif (last === undefined) break\n\t\t\tscanCursor = last.deliverySequence\n\t\t\t// maxScanned counts every operation scanned, including any excluded (own or\n\t\t\t// out-of-scope) ones, so the batch max advances the client's watermark past\n\t\t\t// them even though they are not sent.\n\t\t\tmaxScanned = scanCursor\n\t\t\tfor (const delivered of chunk) {\n\t\t\t\t// Skip the client's own operations during streaming: it already holds them,\n\t\t\t\t// so echoing them back is pure waste. They are still counted in maxScanned,\n\t\t\t\t// and a full resync (fromDeliverySeq 0) passes no excludeNodeId, so a client\n\t\t\t\t// that lost its local store still recovers its own history.\n\t\t\t\tif (excludeNodeId !== undefined && delivered.operation.nodeId === excludeNodeId) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (await this.operationVisibleToClient(delivered.operation)) {\n\t\t\t\t\tvisible.push(delivered)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (chunk.length < scanChunk) break\n\t\t}\n\n\t\tif (visible.length === 0) {\n\t\t\t// Nothing in scope after the cursor. On a handshake resume, send a single empty\n\t\t\t// final batch so the client advances past an out-of-scope tail and completes\n\t\t\t// initial sync. During streaming, send nothing (an empty batch every relay tick\n\t\t\t// would be pure noise); a reconnect re-scans the small tail if needed.\n\t\t\tif (finalizeWhenEmpty) {\n\t\t\t\tthis.sendDeliveryBatch([], fromDeliverySeq, maxScanned, 0, true)\n\t\t\t}\n\t\t\treturn 0\n\t\t}\n\n\t\tconst totalBatches = Math.ceil(visible.length / this.batchSize)\n\t\tlet base = fromDeliverySeq\n\t\tfor (let i = 0; i < totalBatches; i++) {\n\t\t\tconst slice = visible.slice(i * this.batchSize, (i + 1) * this.batchSize)\n\t\t\tconst lastInSlice = slice[slice.length - 1]\n\t\t\tif (lastInSlice === undefined) continue\n\t\t\tconst isFinal = i === totalBatches - 1\n\t\t\tconst lastSeq = lastInSlice.deliverySequence\n\t\t\t// The final batch carries the max scanned sequence (>= lastSeq) so the client\n\t\t\t// skips past any out-of-scope operations above the last in-scope one.\n\t\t\tconst max = isFinal ? Math.max(maxScanned, lastSeq) : lastSeq\n\t\t\tthis.sendDeliveryBatch(slice, base, max, i, isFinal)\n\t\t\tbase = max\n\t\t}\n\t\treturn visible.length\n\t}\n\n\t/** Build, track, and send one chained delivery-stream batch. */\n\tprivate sendDeliveryBatch(\n\t\tslice: DeliveredOperation[],\n\t\tbase: number,\n\t\tmax: number,\n\t\tbatchIndex: number,\n\t\tisFinal: boolean,\n\t): void {\n\t\tconst batchMsg: SyncMessage = {\n\t\t\ttype: 'operation-batch',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\toperations: slice.map((delivered) => this.serializer.encodeOperation(delivered.operation)),\n\t\t\tisFinal,\n\t\t\tbatchIndex,\n\t\t\tbaseDeliverySequence: base,\n\t\t\tmaxDeliverySequence: max,\n\t\t}\n\t\t// Delivery batches are NOT tracked in the bounded pending-relay buffer: recovery of\n\t\t// a dropped or unapplied batch is by re-scan from the client's acknowledged\n\t\t// position (the next push or the retransmit tick), which cannot be defeated by a\n\t\t// buffer eviction. The client re-acks a duplicate and stalls on a gap, so re-sends\n\t\t// are always safe.\n\t\tthis.sendToClient(batchMsg)\n\t\tif (slice.length > 0) {\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:sent',\n\t\t\t\toperations: slice.map((delivered) => delivered.operation),\n\t\t\t\tbatchSize: slice.length,\n\t\t\t})\n\t\t}\n\t}\n\n\tprivate async operationVisibleToClient(op: Operation): Promise<boolean> {\n\t\tconst scopes = this.authContext?.scopes\n\t\tconst subsets = this.syncQuerySubsets\n\t\t// A partial update (or a delete) may not carry the scope / query-subset fields\n\t\t// in its own data. Judging visibility from the bare op would wrongly hide such\n\t\t// an operation, so backfill those fields from the materialized record (including\n\t\t// a soft-deleted one) whenever they are missing. Only look up when needed so the\n\t\t// common case (inserts, or ops that already carry the fields) stays lookup-free.\n\t\tconst needsBackfill =\n\t\t\tmissingScopeFields(op, scopes).length > 0 || (subsets !== undefined && subsets.length > 0)\n\t\tconst fullRecord = needsBackfill\n\t\t\t? await this.lookupRecordFields(op.collection, op.recordId)\n\t\t\t: undefined\n\n\t\tif (!operationMatchesScopes(op, scopes, fullRecord)) {\n\t\t\treturn false\n\t\t}\n\t\treturn operationMatchesQuerySubsets(op, subsets, fullRecord)\n\t}\n\n\t/**\n\t * Read a record's current field values from the materialized store for scope /\n\t * query-subset backfill. Includes soft-deleted rows so a relayed delete (whose op\n\t * carries no fields) is still judged against the record's actual scope. Returns\n\t * undefined when the record cannot be read (never materialized, or no schema).\n\t */\n\tprivate async lookupRecordFields(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<Record<string, unknown> | undefined> {\n\t\ttry {\n\t\t\tconst rows = await this.store.queryCollection(collection, {\n\t\t\t\twhere: { id: recordId },\n\t\t\t\tincludeDeleted: true,\n\t\t\t\tlimit: 1,\n\t\t\t})\n\t\t\treturn rows[0]\n\t\t} catch {\n\t\t\treturn undefined\n\t\t}\n\t}\n\n\tprivate handleAwarenessUpdate(msg: AwarenessUpdateMessage): void {\n\t\t// Relay awareness updates to the server for broadcasting to other clients.\n\t\t// Awareness is purely ephemeral -- no persistence.\n\t\tthis.onAwarenessUpdate?.(this.sessionId, msg)\n\t}\n\n\tprivate handleYjsDocUpdate(msg: YjsDocUpdateMessage): void {\n\t\tthis.onYjsDocUpdate?.(this.sessionId, msg)\n\t}\n\n\tprivate sendError(code: string, message: string, retriable: boolean): void {\n\t\tconst errorMsg: SyncMessage = {\n\t\t\ttype: 'error',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tcode,\n\t\t\tmessage,\n\t\t\tretriable,\n\t\t}\n\t\tthis.sendToClient(errorMsg)\n\t}\n\n\t/**\n\t * Reject one specific client operation, tied to its id, so the submitter can\n\t * divert it out of its pending queue into a durable rejected store rather than\n\t * losing it or retrying forever. The op is NOT materialized, so no other\n\t * replica ever sees it.\n\t */\n\tprivate sendOperationRejected(\n\t\top: Operation,\n\t\tcode: string,\n\t\tmessage: string,\n\t\tretriable: boolean,\n\t): void {\n\t\tconst rejectedMsg: SyncMessage = {\n\t\t\ttype: 'operation-rejected',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\toperationId: op.id,\n\t\t\tcollection: op.collection,\n\t\t\trecordId: op.recordId,\n\t\t\tcode,\n\t\t\tmessage,\n\t\t\tretriable,\n\t\t}\n\t\tthis.sendToClient(rejectedMsg)\n\t}\n\n\tprivate setSerializerWireFormat(format: WireFormat): void {\n\t\tif (typeof this.serializer.setWireFormat === 'function') {\n\t\t\tthis.serializer.setWireFormat(format)\n\t\t}\n\t}\n\n\tprivate handleTransportClose(): void {\n\t\tif (this.state === 'closed') return\n\t\tthis.state = 'closed'\n\t\tthis.flushOrphanedRelays()\n\t\tthis.emitter?.emit({ type: 'sync:disconnected', reason: 'transport closed' })\n\t\tthis.onClose?.(this.sessionId)\n\t}\n}\n\nfunction selectWireFormat(supportedWireFormats?: WireFormat[]): WireFormat {\n\tif (supportedWireFormats?.includes('protobuf')) {\n\t\treturn 'protobuf'\n\t}\n\n\treturn 'json'\n}\n","import type { Operation } from '@korajs/core'\nimport { buildMergeRelationLookup, checkReferentialIntegrityOnDelete } from '@korajs/merge'\nimport type { ApplyResult } from '@korajs/sync'\nimport { validateIncomingOperationConstraints } from '../constraints/operation-constraint-validator'\nimport { createServerReferentialContext } from '../constraints/server-referential-context'\nimport type { ServerStore } from '../store/server-store'\nimport { type OperationRejection, isRetriableRejection } from './rejection-taxonomy'\nimport {\n\tcreateServerSideEffectOperation,\n\tnextServerSequenceNumber,\n} from './server-side-effect-operation'\n\nexport interface ApplyServerOperationResult {\n\t/** Result of applying the primary operation */\n\tresult: ApplyResult\n\t/** Primary op when applied, plus any server-generated side-effect operations */\n\tappliedOperations: Operation[]\n\t/** Rejection reason when the operation was not applied */\n\trejection?: OperationRejection\n}\n\n/**\n * Applies an incoming client operation with Tier 2 constraints and referential integrity.\n * Cascade/set-null side effects are persisted as server-originated operations in the op log.\n */\nexport async function applyServerOperation(\n\tstore: ServerStore,\n\top: Operation,\n\trelationLookup?: ReturnType<typeof buildMergeRelationLookup>,\n): Promise<ApplyServerOperationResult> {\n\tconst schema = store.getSchema()\n\tconst lookup = relationLookup ?? (schema ? buildMergeRelationLookup(schema) : new Map())\n\n\tconst shapeCheck = validateOperationShape(op, schema)\n\tif (!shapeCheck.valid) {\n\t\treturn {\n\t\t\tresult: 'skipped',\n\t\t\tappliedOperations: [],\n\t\t\trejection: {\n\t\t\t\tcode: shapeCheck.code ?? 'SCHEMA_VALIDATION_ERROR',\n\t\t\t\tmessage: shapeCheck.message ?? `Operation \"${op.id}\" does not match the server schema`,\n\t\t\t\tretriable: false,\n\t\t\t},\n\t\t}\n\t}\n\n\tconst constraintCheck = await validateIncomingOperationConstraints(store, op, schema)\n\tif (!constraintCheck.valid) {\n\t\tconst code = constraintCheck.code ?? 'CONSTRAINT_VIOLATION'\n\t\treturn {\n\t\t\tresult: 'skipped',\n\t\t\tappliedOperations: [],\n\t\t\trejection: {\n\t\t\t\tcode,\n\t\t\t\tmessage: constraintCheck.message ?? `Operation \"${op.id}\" violates a schema constraint`,\n\t\t\t\tretriable: isRetriableRejection(code),\n\t\t\t},\n\t\t}\n\t}\n\n\tif (op.type === 'delete' && schema) {\n\t\tconst refCtx = createServerReferentialContext(store)\n\t\tconst referential = await checkReferentialIntegrityOnDelete(op, schema, refCtx, lookup)\n\n\t\tif (!referential.allowed) {\n\t\t\treturn {\n\t\t\t\tresult: 'skipped',\n\t\t\t\tappliedOperations: [],\n\t\t\t\trejection: {\n\t\t\t\t\tcode: 'REFERENTIAL_INTEGRITY',\n\t\t\t\t\tmessage: `Operation \"${op.id}\" violates referential integrity on \"${op.collection}\"`,\n\t\t\t\t\tretriable: isRetriableRejection('REFERENTIAL_INTEGRITY'),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\tconst primaryResult = await store.applyRemoteOperation(op)\n\t\tif (primaryResult !== 'applied') {\n\t\t\treturn { result: primaryResult, appliedOperations: [] }\n\t\t}\n\n\t\tconst appliedOperations: Operation[] = [op]\n\n\t\tfor (const effect of referential.sideEffectOps) {\n\t\t\t// Allocate each side-effect's sequence number individually. On a store\n\t\t\t// that reserves atomically (Postgres), this keeps a concurrent conditional\n\t\t\t// apply from being handed the same server sequence number; on a serialized\n\t\t\t// store, each allocation reads the version vector the prior apply advanced.\n\t\t\tconst sideOp = await createServerSideEffectOperation(\n\t\t\t\tstore,\n\t\t\t\top,\n\t\t\t\teffect,\n\t\t\t\top.schemaVersion,\n\t\t\t\tnextServerSequenceNumber(store),\n\t\t\t)\n\t\t\tconst sideResult = await store.applyRemoteOperation(sideOp)\n\t\t\tif (sideResult === 'applied') {\n\t\t\t\tappliedOperations.push(sideOp)\n\t\t\t}\n\t\t}\n\n\t\treturn { result: 'applied', appliedOperations }\n\t}\n\n\tconst result = await store.applyRemoteOperation(op)\n\treturn {\n\t\tresult,\n\t\tappliedOperations: result === 'applied' ? [op] : [],\n\t}\n}\n\nfunction validateOperationShape(\n\top: Operation,\n\tschema: ReturnType<ServerStore['getSchema']>,\n): { valid: true } | { valid: false; code: string; message: string } {\n\tif (!schema) {\n\t\treturn { valid: true }\n\t}\n\n\tconst collection = schema.collections[op.collection]\n\tif (!collection) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: 'UNKNOWN_COLLECTION',\n\t\t\tmessage: `Operation \"${op.id}\" targets unknown collection \"${op.collection}\".`,\n\t\t}\n\t}\n\n\tconst declaredFields = new Set(Object.keys(collection.fields))\n\tconst systemPreviousFields = new Set(['id', '_created_at', '_updated_at', '_deleted'])\n\tconst invalidDataField = firstInvalidField(op.data, declaredFields)\n\tif (invalidDataField) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: 'SCHEMA_VALIDATION_ERROR',\n\t\t\tmessage: `Operation \"${op.id}\" contains undeclared field \"${invalidDataField}\" in data for collection \"${op.collection}\".`,\n\t\t}\n\t}\n\n\tconst invalidPreviousField = firstInvalidField(\n\t\top.previousData,\n\t\tdeclaredFields,\n\t\tsystemPreviousFields,\n\t)\n\tif (invalidPreviousField) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: 'SCHEMA_VALIDATION_ERROR',\n\t\t\tmessage: `Operation \"${op.id}\" contains undeclared field \"${invalidPreviousField}\" in previousData for collection \"${op.collection}\".`,\n\t\t}\n\t}\n\n\tif (op.atomicOps) {\n\t\tfor (const field of Object.keys(op.atomicOps)) {\n\t\t\tif (!declaredFields.has(field)) {\n\t\t\t\treturn {\n\t\t\t\t\tvalid: false,\n\t\t\t\t\tcode: 'SCHEMA_VALIDATION_ERROR',\n\t\t\t\t\tmessage: `Operation \"${op.id}\" contains undeclared atomic field \"${field}\" for collection \"${op.collection}\".`,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { valid: true }\n}\n\nfunction firstInvalidField(\n\tvalue: unknown,\n\tdeclaredFields: Set<string>,\n\textraAllowedFields?: Set<string>,\n): string | null {\n\tif (value === null || value === undefined) {\n\t\treturn null\n\t}\n\tif (typeof value !== 'object' || Array.isArray(value)) {\n\t\treturn null\n\t}\n\tfor (const field of Object.keys(value)) {\n\t\tif (!declaredFields.has(field) && !extraAllowedFields?.has(field)) {\n\t\t\treturn field\n\t\t}\n\t}\n\treturn null\n}\n","import type { Operation, SchemaDefinition } from '@korajs/core'\nimport { checkConstraints } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\nimport { createServerConstraintContext } from './server-constraint-context'\n\nexport interface OperationConstraintValidation {\n\tvalid: boolean\n\tcode?: string\n\tmessage?: string\n}\n\n/**\n * Validates an incoming operation against Tier 2 schema constraints on the server.\n * Deletes are skipped (removal cannot violate capacity/unique on the deleted row).\n */\nexport async function validateIncomingOperationConstraints(\n\tstore: ServerStore,\n\top: Operation,\n\tschema: SchemaDefinition | null,\n): Promise<OperationConstraintValidation> {\n\tif (!schema) {\n\t\treturn { valid: true }\n\t}\n\n\tif (op.type === 'delete') {\n\t\treturn { valid: true }\n\t}\n\n\tconst collectionDef = schema.collections[op.collection]\n\tif (!collectionDef || collectionDef.constraints.length === 0) {\n\t\treturn { valid: true }\n\t}\n\n\tconst candidate = await projectCandidateRecord(store, op)\n\tif (candidate === null) {\n\t\treturn { valid: true }\n\t}\n\n\tconst ctx = createServerConstraintContext(store)\n\tconst violations = await checkConstraints(\n\t\tcandidate,\n\t\top.recordId,\n\t\top.collection,\n\t\tcollectionDef,\n\t\tctx,\n\t)\n\n\tif (violations.length === 0) {\n\t\treturn { valid: true }\n\t}\n\n\tconst first = violations[0]\n\tif (first === undefined) {\n\t\treturn { valid: true }\n\t}\n\treturn {\n\t\tvalid: false,\n\t\tcode: 'CONSTRAINT_VIOLATION',\n\t\tmessage: first.message,\n\t}\n}\n\nasync function projectCandidateRecord(\n\tstore: ServerStore,\n\top: Operation,\n): Promise<Record<string, unknown> | null> {\n\tif (op.data === null) {\n\t\treturn null\n\t}\n\n\tconst existing = await store.findRecord(op.collection, op.recordId)\n\tconst base = existing ? { ...existing } : {}\n\n\tif (op.type === 'insert') {\n\t\treturn { ...op.data, id: op.recordId }\n\t}\n\n\treturn { ...base, ...op.data, id: op.recordId }\n}\n","import type { ConstraintContext } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\n\n/**\n * Adapts {@link ServerStore} materialized tables for Tier 2 constraint checks.\n */\nexport function createServerConstraintContext(store: ServerStore): ConstraintContext {\n\treturn {\n\t\tasync queryRecords(\n\t\t\tcollection: string,\n\t\t\twhere: Record<string, unknown>,\n\t\t): Promise<Record<string, unknown>[]> {\n\t\t\tconst rows = await store.queryCollection(collection, { where })\n\t\t\treturn rows.map((row) => ({ ...row }))\n\t\t},\n\t\tasync countRecords(collection: string, where: Record<string, unknown>): Promise<number> {\n\t\t\treturn store.countCollection(collection, where)\n\t\t},\n\t}\n}\n","import type { ReferentialMergeContext } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\n\n/**\n * Adapts {@link ServerStore} materialized tables for referential integrity checks.\n */\nexport function createServerReferentialContext(store: ServerStore): ReferentialMergeContext {\n\treturn {\n\t\tasync queryRecords(\n\t\t\tcollection: string,\n\t\t\twhere: Record<string, unknown>,\n\t\t): Promise<Record<string, unknown>[]> {\n\t\t\tconst rows = await store.queryCollection(collection, { where })\n\t\t\treturn rows.map((row) => ({ ...row }))\n\t\t},\n\t\tasync recordExists(collection: string, recordId: string): Promise<boolean> {\n\t\t\tconst row = await store.findRecord(collection, recordId)\n\t\t\treturn row !== null && row._deleted !== 1\n\t\t},\n\t}\n}\n","import { HybridLogicalClock, createOperation } from '@korajs/core'\nimport type { Operation } from '@korajs/core'\nimport type { SideEffectOp } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\n\n/**\n * Converts a merge-package referential side effect into a server-originated operation.\n */\nexport async function createServerSideEffectOperation(\n\tstore: ServerStore,\n\tparentOp: Operation,\n\teffect: SideEffectOp,\n\tschemaVersion: number,\n\tsequenceNumber: number,\n): Promise<Operation> {\n\tconst nodeId = store.getNodeId()\n\tconst clock = new HybridLogicalClock(nodeId)\n\tclock.receive(parentOp.timestamp)\n\n\treturn createOperation(\n\t\t{\n\t\t\tnodeId,\n\t\t\ttype: effect.type === 'delete' ? 'delete' : 'update',\n\t\t\tcollection: effect.collection,\n\t\t\trecordId: effect.recordId,\n\t\t\tdata: effect.data,\n\t\t\tpreviousData: effect.previousData,\n\t\t\tsequenceNumber,\n\t\t\tcausalDeps: [parentOp.id],\n\t\t\tschemaVersion,\n\t\t},\n\t\tclock,\n\t)\n}\n\n/**\n * Allocate the next sequence number for server-originated operations.\n */\nexport function nextServerSequenceNumber(store: ServerStore): number {\n\t// Prefer the store's atomic reservation when it serves writes concurrently (the\n\t// Postgres conditional path), so two in-flight server operations never collide on\n\t// a sequence number. Serialized stores fall back to the version vector, which is\n\t// safe because only one server operation is ever in flight at a time.\n\tif (store.reserveSequenceNumber) {\n\t\treturn store.reserveSequenceNumber()\n\t}\n\tconst nodeId = store.getNodeId()\n\tconst current = store.getVersionVector().get(nodeId) ?? 0\n\treturn current + 1\n}\n","import type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Auth provider that accepts all connections.\n * Returns a default anonymous context for any token.\n * Useful for development and testing.\n */\nexport class NoAuthProvider implements AuthProvider {\n\tasync authenticate(_token: string): Promise<AuthContext> {\n\t\treturn { userId: 'anonymous' }\n\t}\n}\n","import type { ScopeMap } from '@korajs/core'\nimport { type SchemaDefinition, buildScopeMap } from '@korajs/core'\n\nexport interface ResolveSessionScopesOptions {\n\t/** Scope map sent by the client during handshake */\n\thandshakeScope?: ScopeMap\n\t/** Scope map from the auth provider (server-controlled) */\n\tauthScopes?: ScopeMap\n\t/** Flat scope values used to derive schema sync rules */\n\tscopeValues?: Record<string, unknown>\n}\n\n/**\n * Resolve the effective per-session sync scope map.\n *\n * Combines schema sync rules, auth scopes, and client handshake scopes into\n * a single unified model. Auth scopes take precedence over handshake scopes\n * per collection; schema sync rules define which collections participate in\n * partial sync.\n */\nexport function resolveSessionScopes(\n\tschema: SchemaDefinition | null,\n\toptions: ResolveSessionScopesOptions,\n): ScopeMap | undefined {\n\tconst { handshakeScope, authScopes, scopeValues } = options\n\n\tlet resolved: ScopeMap | undefined\n\n\tif (schema && scopeValues && Object.keys(scopeValues).length > 0) {\n\t\tresolved = buildScopeMap(schema, scopeValues)\n\t} else if (handshakeScope) {\n\t\tresolved = { ...handshakeScope }\n\t} else if (authScopes) {\n\t\tresolved = { ...authScopes }\n\t}\n\n\tif (schema && !resolved && scopeValues) {\n\t\tresolved = buildScopeMap(schema, scopeValues)\n\t}\n\n\tif (authScopes) {\n\t\tresolved = mergeScopeMaps(resolved, authScopes, 'auth')\n\t}\n\n\tif (handshakeScope) {\n\t\tresolved = mergeScopeMaps(resolved, handshakeScope, 'handshake')\n\t}\n\n\treturn resolved && Object.keys(resolved).length > 0 ? resolved : undefined\n}\n\nfunction mergeScopeMaps(\n\tbase: ScopeMap | undefined,\n\toverlay: ScopeMap,\n\tsource: 'auth' | 'handshake',\n): ScopeMap {\n\tconst merged: ScopeMap = { ...(base ?? {}) }\n\n\tfor (const [collection, overlayScope] of Object.entries(overlay)) {\n\t\tif (source === 'auth') {\n\t\t\tmerged[collection] = { ...(merged[collection] ?? {}), ...overlayScope }\n\t\t} else {\n\t\t\tmerged[collection] = { ...(overlayScope ?? {}), ...(merged[collection] ?? {}) }\n\t\t}\n\t}\n\n\treturn merged\n}\n","import type { Operation } from '@korajs/core'\n\n/**\n * Per-collection scope map from auth context.\n */\nexport type ScopeMap = Record<string, Record<string, unknown>>\n\nexport const DEFAULT_MAX_SCOPE_PREDICATE_VALUES = 100\n\n/** Canonicalize bounded `$in` predicates so equivalent authorization has one signature. */\nexport function normalizeScopeMap(\n\tscopes: ScopeMap,\n\tmaxValues = DEFAULT_MAX_SCOPE_PREDICATE_VALUES,\n): ScopeMap {\n\tconst normalized: ScopeMap = {}\n\tfor (const collection of Object.keys(scopes).sort()) {\n\t\tconst predicate: Record<string, unknown> = {}\n\t\tfor (const field of Object.keys(scopes[collection] ?? {}).sort()) {\n\t\t\tconst expected = scopes[collection]?.[field]\n\t\t\tif (\n\t\t\t\texpected &&\n\t\t\t\ttypeof expected === 'object' &&\n\t\t\t\t!Array.isArray(expected) &&\n\t\t\t\t'$in' in expected\n\t\t\t) {\n\t\t\t\tconst values = (expected as { $in?: unknown }).$in\n\t\t\t\tif (!Array.isArray(values))\n\t\t\t\t\tthrow new Error(`Invalid $in predicate for ${collection}.${field}`)\n\t\t\t\tconst unique = [...new Map(values.map((value) => [stableValueKey(value), value])).values()]\n\t\t\t\tif (unique.length > maxValues)\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Scope predicate for ${collection}.${field} exceeds the ${maxValues}-value limit`,\n\t\t\t\t\t)\n\t\t\t\tpredicate[field] = {\n\t\t\t\t\t$in: unique.sort((a, b) => stableValueKey(a).localeCompare(stableValueKey(b))),\n\t\t\t\t}\n\t\t\t} else predicate[field] = expected\n\t\t}\n\t\tnormalized[collection] = predicate\n\t}\n\treturn normalized\n}\n\nfunction stableValueKey(value: unknown): string {\n\tif (Array.isArray(value)) return `[${value.map(stableValueKey).join(',')}]`\n\tif (value && typeof value === 'object')\n\t\treturn `{${Object.keys(value as Record<string, unknown>)\n\t\t\t.sort()\n\t\t\t.map(\n\t\t\t\t(key) =>\n\t\t\t\t\t`${JSON.stringify(key)}:${stableValueKey((value as Record<string, unknown>)[key])}`,\n\t\t\t)\n\t\t\t.join(',')}}`\n\treturn JSON.stringify(value)\n}\n\n/**\n * Returns true if an operation is visible to a session based on its scopes.\n *\n * Rules:\n * - No scopes configured => visible\n * - Collection missing from scope map => hidden\n * - All scoped field/value pairs must match the operation snapshot\n */\nexport function operationMatchesScopes(\n\top: Operation,\n\tscopes: ScopeMap | undefined,\n\tfullRecord?: Record<string, unknown> | null,\n): boolean {\n\tif (!scopes) return true\n\n\tconst collectionScope = scopes[op.collection]\n\tif (!collectionScope) return false\n\tif (Object.keys(collectionScope).length === 0) return true\n\n\tconst snapshot = buildSnapshot(op, fullRecord)\n\tif (!snapshot) return false\n\n\tfor (const [field, expected] of Object.entries(collectionScope)) {\n\t\tif (!matchesPredicate(snapshot[field], expected)) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\nfunction matchesPredicate(actual: unknown, expected: unknown): boolean {\n\tif (expected && typeof expected === 'object' && !Array.isArray(expected) && '$in' in expected) {\n\t\tconst values = (expected as { $in?: unknown }).$in\n\t\treturn Array.isArray(values) && values.some((value) => Object.is(actual, value))\n\t}\n\treturn Object.is(actual, expected)\n}\n\n/**\n * Returns the scope fields (for `op.collection`) that a bare operation does NOT\n * carry in its own `data`/`previousData`. When any are missing, the caller must\n * backfill them from the materialized record before scope-checking, otherwise a\n * partial update (or a delete) that does not restate the scope field is wrongly\n * judged out of scope and dropped from relay/delta — silently diverging tenants.\n */\nexport function missingScopeFields(op: Operation, scopes: ScopeMap | undefined): string[] {\n\tif (!scopes) return []\n\tconst collectionScope = scopes[op.collection]\n\tif (!collectionScope) return []\n\tif (Object.keys(collectionScope).length === 0) return []\n\tconst snapshot = buildSnapshot(op)\n\treturn Object.keys(collectionScope).filter((field) => !snapshot || !(field in snapshot))\n}\n\nfunction buildSnapshot(\n\top: Operation,\n\tfullRecord?: Record<string, unknown> | null,\n): Record<string, unknown> | null {\n\tconst previous = asRecord(op.previousData)\n\tconst next = asRecord(op.data)\n\n\tif (!previous && !next && !fullRecord) return null\n\n\treturn {\n\t\t...(fullRecord ?? {}),\n\t\t...(previous ?? {}),\n\t\t...(next ?? {}),\n\t}\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n\tif (typeof value !== 'object' || value === null || Array.isArray(value)) {\n\t\treturn null\n\t}\n\n\treturn value as Record<string, unknown>\n}\n","import { MAX_LOGICAL } from '@korajs/core'\nimport type { Operation } from '@korajs/core'\n\n/** Max allowed future skew for operation timestamps at server ingest (1 minute). */\nexport const SERVER_MAX_TIMESTAMP_FUTURE_MS = 60_000\n\n/**\n * Returns false when an operation's HLC timestamp is structurally invalid or\n * unreasonably far in the future.\n *\n * Structural checks matter because operations are content-addressed and\n * immutable: a timestamp with a non-integer/negative field or a logical\n * counter past the 5-digit serialization cap would poison the shared log\n * forever (its serialized form no longer sorts like HybridLogicalClock.compare),\n * so it must never be accepted at ingest.\n */\nexport function isOperationTimestampValid(op: Operation, now: number = Date.now()): boolean {\n\tconst { wallTime, logical } = op.timestamp\n\tif (!Number.isInteger(wallTime) || wallTime < 0) {\n\t\treturn false\n\t}\n\tif (!Number.isInteger(logical) || logical < 0 || logical > MAX_LOGICAL) {\n\t\treturn false\n\t}\n\treturn wallTime <= now + SERVER_MAX_TIMESTAMP_FUTURE_MS\n}\n","import type { Operation } from '@korajs/core'\n\n/** Default maximum serialized size of a single operation at server ingest (256 KiB). */\nexport const DEFAULT_MAX_OPERATION_BYTES = 256 * 1024\n\n/** Default maximum operations accepted per client session per minute. */\nexport const DEFAULT_MAX_OPS_PER_MINUTE = 600\n\n/**\n * Approximate UTF-8 byte length of an operation payload for rate/size guards.\n */\nexport function measureOperationBytes(op: Operation): number {\n\treturn Buffer.byteLength(JSON.stringify(op), 'utf8')\n}\n\nexport interface OperationSizeValidation {\n\tvalid: boolean\n\tbytes: number\n\tmessage?: string\n}\n\n/**\n * Returns false when an operation exceeds the configured byte limit.\n */\nexport function validateOperationSize(\n\top: Operation,\n\tmaxBytes: number = DEFAULT_MAX_OPERATION_BYTES,\n): OperationSizeValidation {\n\tconst bytes = measureOperationBytes(op)\n\tif (bytes <= maxBytes) {\n\t\treturn { valid: true, bytes }\n\t}\n\treturn {\n\t\tvalid: false,\n\t\tbytes,\n\t\tmessage: `Operation \"${op.id}\" exceeds max size (${String(bytes)} > ${String(maxBytes)} bytes)`,\n\t}\n}\n\n/**\n * Simple sliding-window rate limiter for per-session operation ingest.\n */\nexport class SessionRateLimiter {\n\tprivate windowStartMs = Date.now()\n\tprivate count = 0\n\n\tconstructor(private readonly maxOpsPerMinute: number = DEFAULT_MAX_OPS_PER_MINUTE) {}\n\n\tget limit(): number {\n\t\treturn this.maxOpsPerMinute\n\t}\n\n\t/** Record N operations and return false when the limit is exceeded. */\n\tallow(count = 1): boolean {\n\t\tconst now = Date.now()\n\t\tif (now - this.windowStartMs >= 60_000) {\n\t\t\tthis.windowStartMs = now\n\t\t\tthis.count = 0\n\t\t}\n\t\tthis.count += count\n\t\treturn this.count <= this.maxOpsPerMinute\n\t}\n\n\treset(): void {\n\t\tthis.windowStartMs = Date.now()\n\t\tthis.count = 0\n\t}\n}\n","import type { BlobRef, KoraEventEmitter, Operation, OperationTransform } from '@korajs/core'\nimport { SyncError, generateUUIDv7, isBlobRef } from '@korajs/core'\nimport { SimpleEventEmitter } from '@korajs/core/internal'\nimport type { AwarenessUpdateMessage, MessageSerializer, YjsDocUpdateMessage } from '@korajs/sync'\nimport { JsonMessageSerializer } from '@korajs/sync'\nimport {\n\ttype ApplyServerOperationResult,\n\tapplyServerOperation,\n} from '../apply/apply-server-operation'\nimport type { OperationValidator } from '../apply/operation-validator'\nimport { AwarenessRelay } from '../awareness/awareness-relay'\nimport { ServerMetricsCollector, estimateByteSize } from '../diagnostics/server-metrics-collector'\nimport type { Logger } from '../logging/structured-logger'\nimport { createDefaultLogger } from '../logging/structured-logger'\nimport { BlobChunkRelay } from '../richtext/blob-chunk-relay'\nimport { YjsDocRelay } from '../richtext/yjs-doc-relay'\nimport { ClientSession } from '../session/client-session'\nimport type { ServerStore } from '../store/server-store'\nimport { HttpServerTransport } from '../transport/http-server-transport'\nimport type { ServerTransport } from '../transport/server-transport'\nimport { WsServerTransport } from '../transport/ws-server-transport'\nimport type {\n\tAuthProvider,\n\tHttpSyncRequest,\n\tHttpSyncResponse,\n\tKoraSyncServerConfig,\n\tServerStatus,\n} from '../types'\nimport { type ProductionHttpRouteContext, createRouteContext } from './route-context'\n\nconst DEFAULT_MAX_CONNECTIONS = 0 // unlimited\nconst DEFAULT_BATCH_SIZE = 100\nconst DEFAULT_SCHEMA_VERSION = 1\nconst DEFAULT_HOST = '0.0.0.0'\nconst DEFAULT_PATH = '/'\nconst DEFAULT_RELAY_RETRANSMIT_INTERVAL_MS = 2000\nconst DEFAULT_DELIVERY_POLL_INTERVAL_MS = 2000\n\n/**\n * Minimal interface for a ws.WebSocketServer instance.\n * Allows dependency injection for testing without importing ws directly.\n */\nexport interface WsServerLike {\n\ton(event: string, listener: (...args: unknown[]) => void): void\n\tclose(callback?: (err?: Error) => void): void\n\taddress(): { port: number } | string | null\n}\n\n/**\n * Constructor type for creating a WebSocket server.\n */\nexport type WsServerConstructor = new (options: {\n\tport?: number\n\thost?: string\n\tpath?: string\n}) => WsServerLike\n\nfunction validateIntervalOption(name: string, value: number): number {\n\tif (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) {\n\t\tthrow new SyncError(`${name} must be a non-negative integer number of milliseconds`, {\n\t\t\t[name]: value,\n\t\t})\n\t}\n\treturn value\n}\n\n/**\n * Self-hosted sync server. Accepts WebSocket connections from clients,\n * handles the sync protocol, stores operations, and relays changes\n * between connected clients.\n *\n * Two modes of operation:\n * 1. **Standalone**: Call `start()` with a port — creates its own WebSocket server.\n * 2. **Attach**: Call `handleConnection(transport)` — attach to an existing HTTP server.\n */\nexport class KoraSyncServer {\n\tprivate readonly store: ServerStore\n\tprivate readonly auth: AuthProvider | null\n\tprivate readonly serializer: MessageSerializer\n\tprivate readonly emitter: KoraEventEmitter | null\n\tprivate readonly maxConnections: number\n\tprivate readonly batchSize: number\n\tprivate readonly relayRetransmitIntervalMs: number\n\tprivate readonly deliveryPollIntervalMs: number\n\tprivate readonly schemaVersion: number\n\tprivate readonly supportedSchemaVersions: { min: number; max: number }\n\tprivate readonly operationTransforms: OperationTransform[]\n\tprivate readonly port: number | undefined\n\tprivate readonly host: string\n\tprivate readonly path: string\n\tprivate readonly logger: Logger\n\tprivate readonly metrics: ServerMetricsCollector\n\n\tprivate readonly awarenessRelay = new AwarenessRelay()\n\tprivate readonly yjsDocRelay = new YjsDocRelay()\n\tprivate readonly blobChunkRelay: BlobChunkRelay\n\tprivate readonly persistBlobChunk:\n\t\t| ((hash: string, bytes: Uint8Array) => Promise<void> | void)\n\t\t| null\n\tprivate readonly maxOperationBytes: number | undefined\n\tprivate readonly maxOpsPerMinute: number | undefined\n\tprivate readonly validateOperation: OperationValidator | undefined\n\tprivate readonly koraContext: ProductionHttpRouteContext\n\tprivate readonly sessions = new Map<string, ClientSession>()\n\tprivate readonly httpClients = new Map<\n\t\tstring,\n\t\t{ sessionId: string; transport: HttpServerTransport }\n\t>()\n\tprivate readonly httpSessionToClient = new Map<string, string>()\n\t// Informational value reported by getStatus(). Keep in sync with the\n\t// @korajs/server package version on release; it is not used for protocol negotiation.\n\tprivate readonly serverVersion = '1.0.0-beta.0'\n\tprivate wsServer: WsServerLike | null = null\n\tprivate running = false\n\t/**\n\t * Periodic tick that retransmits relay batches connected clients have not\n\t * acknowledged, so a relay dropped by a lossy transport is redelivered instead of\n\t * leaving that client with a permanent version-vector gap (a lost operation).\n\t */\n\tprivate relayRetransmitTimer: ReturnType<typeof setInterval> | null = null\n\tprivate deliveryPollTimer: ReturnType<typeof setInterval> | null = null\n\tprivate lastObservedDeliverySequence = 0\n\tprivate deliveryPollInFlight = false\n\t/**\n\t * Relay operations a client never acknowledged before it disconnected, buffered by\n\t * client node id so they can be redelivered on its next connection. Bounded per\n\t * node and expired by age so a client that never returns cannot grow this forever.\n\t */\n\tprivate readonly orphanedRelaysByNode = new Map<\n\t\tstring,\n\t\t{ ops: Operation[]; bufferedAtMs: number }\n\t>()\n\tprivate static readonly MAX_ORPHANED_RELAY_OPS_PER_NODE = 5000\n\tprivate static readonly ORPHANED_RELAY_TTL_MS = 5 * 60_000\n\n\tconstructor(config: KoraSyncServerConfig) {\n\t\tthis.store = config.store\n\t\tconst storeSchemaVersion = this.store.getSchema()?.version\n\t\tif (\n\t\t\tconfig.schemaVersion !== undefined &&\n\t\t\tstoreSchemaVersion !== undefined &&\n\t\t\tconfig.schemaVersion !== storeSchemaVersion\n\t\t) {\n\t\t\tthrow new SyncError('Sync schema version does not match the configured store schema.', {\n\t\t\t\tsyncSchemaVersion: config.schemaVersion,\n\t\t\t\tstoreSchemaVersion,\n\t\t\t})\n\t\t}\n\t\tthis.auth = config.auth ?? null\n\t\tthis.serializer = config.serializer ?? new JsonMessageSerializer()\n\t\tthis.emitter = config.emitter ?? null\n\t\tthis.maxConnections = config.maxConnections ?? DEFAULT_MAX_CONNECTIONS\n\t\tthis.batchSize = config.batchSize ?? DEFAULT_BATCH_SIZE\n\t\tthis.relayRetransmitIntervalMs = validateIntervalOption(\n\t\t\t'relayRetransmitIntervalMs',\n\t\t\tconfig.relayRetransmitIntervalMs ?? DEFAULT_RELAY_RETRANSMIT_INTERVAL_MS,\n\t\t)\n\t\tthis.deliveryPollIntervalMs = validateIntervalOption(\n\t\t\t'deliveryPollIntervalMs',\n\t\t\tconfig.deliveryPollIntervalMs ?? DEFAULT_DELIVERY_POLL_INTERVAL_MS,\n\t\t)\n\t\tthis.schemaVersion = config.schemaVersion ?? storeSchemaVersion ?? DEFAULT_SCHEMA_VERSION\n\t\tthis.supportedSchemaVersions = config.supportedSchemaVersions ?? {\n\t\t\tmin: this.schemaVersion,\n\t\t\tmax: this.schemaVersion,\n\t\t}\n\t\tthis.operationTransforms = config.operationTransforms ?? []\n\t\tthis.port = config.port\n\t\tthis.host = config.host ?? DEFAULT_HOST\n\t\tthis.path = config.path ?? DEFAULT_PATH\n\t\tthis.logger = config.logger ?? createDefaultLogger()\n\t\tthis.metrics = config.metricsCollector ?? new ServerMetricsCollector()\n\t\tthis.metrics.setSchemaVersion(this.schemaVersion)\n\t\tthis.blobChunkRelay = new BlobChunkRelay(config.resolveBlobChunk)\n\t\tthis.persistBlobChunk = config.persistBlobChunk ?? null\n\t\tthis.maxOperationBytes = config.maxOperationBytes\n\t\tthis.maxOpsPerMinute = config.maxOpsPerMinute\n\t\tthis.validateOperation = config.validateOperation\n\t\t// One trusted data-plane context, shared by custom HTTP routes (via\n\t\t// production-server) and by the operation validator. It holds no per-request\n\t\t// state; the closures only reach back into `this` when actually invoked.\n\t\tthis.koraContext = createRouteContext(this, this.store)\n\n\t\t// If no external emitter was provided, create an internal one for\n\t\t// subscribing to session events for metrics and logging.\n\t\tif (!this.emitter) {\n\t\t\tthis.emitter = new SimpleEventEmitter()\n\t\t}\n\t}\n\n\tprivate ensureBackgroundTimersStarted(): void {\n\t\tif (this.relayRetransmitIntervalMs > 0 && !this.relayRetransmitTimer) {\n\t\t\tthis.relayRetransmitTimer = setInterval(() => {\n\t\t\t\tthis.retransmitPendingRelays(this.relayRetransmitIntervalMs)\n\t\t\t}, this.relayRetransmitIntervalMs)\n\t\t\tthis.relayRetransmitTimer.unref?.()\n\t\t}\n\n\t\tif (this.deliveryPollIntervalMs > 0 && !this.deliveryPollTimer) {\n\t\t\tthis.deliveryPollTimer = setInterval(() => {\n\t\t\t\tvoid this.pollDeliveryLog()\n\t\t\t}, this.deliveryPollIntervalMs)\n\t\t\tthis.deliveryPollTimer.unref?.()\n\t\t}\n\t}\n\n\t/**\n\t * Retransmit relay batches that connected clients have not acknowledged within\n\t * `staleMs`. Called on a periodic tick and directly by tests. Redelivering an\n\t * already-applied operation is harmless (clients dedup by content-addressed id).\n\t */\n\tretransmitPendingRelays(staleMs = 0): void {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tsession.retransmitPendingRelays(staleMs)\n\t\t}\n\t\tthis.expireOrphanedRelays()\n\t}\n\n\t/**\n\t * Check whether the authoritative delivery log advanced without passing through\n\t * this server instance, then wake delivery-watermark sessions to scan from their\n\t * own acknowledged cursors. Session-level filtering remains the only fan-out path.\n\t */\n\tasync pollDeliveryLog(): Promise<void> {\n\t\tif (this.deliveryPollInFlight) return\n\t\tthis.deliveryPollInFlight = true\n\t\ttry {\n\t\t\tconst maxDeliverySequence = await this.store.getMaxDeliverySequence()\n\t\t\tif (maxDeliverySequence <= this.lastObservedDeliverySequence) {\n\t\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\t\tsession.pushDeliveryStreamIfSupported(this.deliveryPollIntervalMs, {\n\t\t\t\t\t\ttrackStall: true,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.lastObservedDeliverySequence = maxDeliverySequence\n\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\tsession.pushDeliveryStreamIfSupported(0)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'delivery_poll.failed',\n\t\t\t\tdetails: { error: error instanceof Error ? error.message : String(error) },\n\t\t\t})\n\t\t} finally {\n\t\t\tthis.deliveryPollInFlight = false\n\t\t}\n\t}\n\n\t/**\n\t * Buffer relay operations a disconnected client never acknowledged, keyed by its\n\t * node id, deduped by operation id and bounded by count. Redelivered when the\n\t * client reconnects (see {@link takeOrphanedRelays}).\n\t */\n\tprivate bufferOrphanedRelays(nodeId: string, ops: Operation[]): void {\n\t\tif (ops.length === 0) return\n\t\tconst existing = this.orphanedRelaysByNode.get(nodeId)\n\t\tconst merged = existing ? existing.ops : []\n\t\tconst seen = new Set(merged.map((op) => op.id))\n\t\tfor (const op of ops) {\n\t\t\tif (!seen.has(op.id)) {\n\t\t\t\tmerged.push(op)\n\t\t\t\tseen.add(op.id)\n\t\t\t}\n\t\t}\n\t\t// Keep only the most recent ops if the buffer is oversized.\n\t\tconst bounded =\n\t\t\tmerged.length > KoraSyncServer.MAX_ORPHANED_RELAY_OPS_PER_NODE\n\t\t\t\t? merged.slice(merged.length - KoraSyncServer.MAX_ORPHANED_RELAY_OPS_PER_NODE)\n\t\t\t\t: merged\n\t\tthis.orphanedRelaysByNode.set(nodeId, { ops: bounded, bufferedAtMs: Date.now() })\n\t}\n\n\t/** Remove and return a node's buffered orphaned relay operations, if any. */\n\tprivate takeOrphanedRelays(nodeId: string): Operation[] {\n\t\tconst entry = this.orphanedRelaysByNode.get(nodeId)\n\t\tif (!entry) return []\n\t\tthis.orphanedRelaysByNode.delete(nodeId)\n\t\treturn entry.ops\n\t}\n\n\t/** Drop buffered orphaned relays older than the TTL (client never returned). */\n\tprivate expireOrphanedRelays(): void {\n\t\tif (this.orphanedRelaysByNode.size === 0) return\n\t\tconst cutoff = Date.now() - KoraSyncServer.ORPHANED_RELAY_TTL_MS\n\t\tfor (const [nodeId, entry] of this.orphanedRelaysByNode) {\n\t\t\tif (entry.bufferedAtMs <= cutoff) {\n\t\t\t\tthis.orphanedRelaysByNode.delete(nodeId)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * The trusted, scoped data-plane context (`apply` / `query` / `findById`).\n\t * Shared with the production server so HTTP routes, the operation validator,\n\t * and `server.kora` are all the same object over the same pipeline.\n\t */\n\tgetKoraContext(): ProductionHttpRouteContext {\n\t\treturn this.koraContext\n\t}\n\n\t/**\n\t * Subscribe to session-level events for metrics collection and logging.\n\t * Called when a new session is created.\n\t */\n\tprivate attachSessionEvents(sessionId: string, sessionEmitter: KoraEventEmitter): void {\n\t\tsessionEmitter.on('sync:connected', (event) => {\n\t\t\tthis.metrics.recordHandshake(sessionId, event.nodeId)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.handshake',\n\t\t\t\tsessionId,\n\t\t\t\tnodeId: event.nodeId,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:received', (event) => {\n\t\t\tconst byteSize = estimateByteSize(event.operations)\n\t\t\tthis.metrics.recordReceived(sessionId, event.batchSize, byteSize)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.received',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:sent', (event) => {\n\t\t\tconst byteSize = estimateByteSize(event.operations)\n\t\t\tthis.metrics.recordSent(sessionId, event.batchSize, byteSize)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.sent',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:disconnected', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.disconnected',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: { reason: event.reason },\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:schema-mismatch', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'session.schema_mismatch',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: {\n\t\t\t\t\tclientSchemaVersion: event.clientSchemaVersion,\n\t\t\t\t\tserverSchemaVersion: event.serverSchemaVersion,\n\t\t\t\t\tsupportedMin: event.supportedMin,\n\t\t\t\t\tsupportedMax: event.supportedMax,\n\t\t\t\t\treason: event.reason,\n\t\t\t\t},\n\t\t\t})\n\t\t})\n\t}\n\n\t/**\n\t * Get the metrics collector for external access (e.g., HTTP endpoints).\n\t */\n\tgetMetricsCollector(): ServerMetricsCollector {\n\t\treturn this.metrics\n\t}\n\n\t/**\n\t * Get the logger for external access (e.g., event streaming).\n\t */\n\tgetLogger(): Logger {\n\t\treturn this.logger\n\t}\n\n\t/**\n\t * Start the WebSocket server in standalone mode.\n\t *\n\t * @param wsServerImpl - Optional WebSocket server constructor for testing\n\t */\n\tasync start(wsServerImpl?: WsServerConstructor): Promise<void> {\n\t\tif (this.running) {\n\t\t\tthrow new SyncError('Server is already running', { port: this.port })\n\t\t}\n\n\t\tif (!wsServerImpl && this.port === undefined) {\n\t\t\tthrow new SyncError(\n\t\t\t\t'Port is required for standalone mode. Provide port in config or use handleConnection() for attach mode.',\n\t\t\t\t{},\n\t\t\t)\n\t\t}\n\n\t\tif (wsServerImpl) {\n\t\t\tthis.wsServer = new wsServerImpl({\n\t\t\t\tport: this.port,\n\t\t\t\thost: this.host,\n\t\t\t\tpath: this.path,\n\t\t\t})\n\t\t} else {\n\t\t\t// Dynamic import of ws — only needed in standalone mode\n\t\t\tconst { WebSocketServer } = await import('ws')\n\t\t\tthis.wsServer = new WebSocketServer({\n\t\t\t\tport: this.port,\n\t\t\t\thost: this.host,\n\t\t\t\tpath: this.path,\n\t\t\t})\n\t\t}\n\n\t\tthis.wsServer.on('connection', (ws: unknown) => {\n\t\t\tconst transport = new WsServerTransport(\n\t\t\t\tws as import('../transport/ws-server-transport').WsWebSocket,\n\t\t\t\t{\n\t\t\t\t\tserializer: this.serializer,\n\t\t\t\t},\n\t\t\t)\n\t\t\tthis.handleConnection(transport)\n\t\t})\n\n\t\tthis.running = true\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'server.started',\n\t\t\tdetails: { port: this.port, host: this.host, path: this.path },\n\t\t})\n\t}\n\n\t/**\n\t * Stop the server. Closes all sessions and the WebSocket server.\n\t */\n\tasync stop(): Promise<void> {\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'server.stopping',\n\t\t\tdetails: { connectedClients: this.sessions.size },\n\t\t})\n\n\t\t// Stop the relay retransmit tick and drop buffered orphaned relays.\n\t\tif (this.relayRetransmitTimer) {\n\t\t\tclearInterval(this.relayRetransmitTimer)\n\t\t\tthis.relayRetransmitTimer = null\n\t\t}\n\t\tif (this.deliveryPollTimer) {\n\t\t\tclearInterval(this.deliveryPollTimer)\n\t\t\tthis.deliveryPollTimer = null\n\t\t}\n\t\tthis.orphanedRelaysByNode.clear()\n\n\t\t// Clean up awareness relay\n\t\tthis.awarenessRelay.clear()\n\t\tthis.yjsDocRelay.clear()\n\t\tthis.blobChunkRelay.clear()\n\n\t\t// Close all active sessions (works in both standalone and attach mode)\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tsession.close('server shutting down')\n\t\t}\n\t\tthis.sessions.clear()\n\t\tthis.httpClients.clear()\n\t\tthis.httpSessionToClient.clear()\n\n\t\t// Close WebSocket server (standalone mode only)\n\t\tif (this.wsServer) {\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tthis.wsServer?.close(() => resolve())\n\t\t\t})\n\t\t\tthis.wsServer = null\n\t\t}\n\n\t\tthis.running = false\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'server.stopped',\n\t\t})\n\t}\n\n\t/**\n\t * Handle one HTTP sync request for a long-polling client.\n\t *\n\t * A stable `clientId` identifies the logical connection across requests.\n\t */\n\tasync handleHttpRequest(request: HttpSyncRequest): Promise<HttpSyncResponse> {\n\t\tif (!request.clientId || request.clientId.trim().length === 0) {\n\t\t\treturn { status: 400 }\n\t\t}\n\n\t\tconst client = this.getOrCreateHttpClient(request.clientId)\n\n\t\tif (request.method === 'POST') {\n\t\t\tif (request.body === undefined) {\n\t\t\t\treturn { status: 400 }\n\t\t\t}\n\n\t\t\tconst payload = normalizeHttpBody(request.body, request.contentType)\n\t\t\tclient.transport.receive(payload)\n\t\t\treturn { status: 202 }\n\t\t}\n\n\t\tif (request.method === 'GET') {\n\t\t\tconst polled = client.transport.poll(request.ifNoneMatch)\n\t\t\treturn {\n\t\t\t\tstatus: polled.status,\n\t\t\t\tbody: polled.body,\n\t\t\t\theaders: polled.headers,\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tstatus: 405,\n\t\t\theaders: { allow: 'GET, POST' },\n\t\t}\n\t}\n\n\t/**\n\t * Handle an incoming client connection (attach mode).\n\t * Creates a new ClientSession for the transport.\n\t *\n\t * @param transport - The server transport for the new connection\n\t * @returns The session ID\n\t */\n\thandleConnection(transport: ServerTransport): string {\n\t\t// Check max connections\n\t\tif (this.maxConnections > 0 && this.sessions.size >= this.maxConnections) {\n\t\t\ttransport.send({\n\t\t\t\ttype: 'error',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tcode: 'MAX_CONNECTIONS',\n\t\t\t\tmessage: `Server has reached maximum connections (${this.maxConnections})`,\n\t\t\t\tretriable: true,\n\t\t\t})\n\t\t\ttransport.close(4029, 'max connections reached')\n\t\t\tthis.metrics.recordError()\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'connection.rejected',\n\t\t\t\tdetails: { reason: 'max_connections', max: this.maxConnections },\n\t\t\t})\n\t\t\tthrow new SyncError('Maximum connections reached', {\n\t\t\t\tcurrent: this.sessions.size,\n\t\t\t\tmax: this.maxConnections,\n\t\t\t})\n\t\t}\n\n\t\tthis.ensureBackgroundTimersStarted()\n\n\t\tconst sessionId = generateUUIDv7()\n\t\tthis.metrics.recordConnection(sessionId)\n\n\t\t// Create a per-session emitter so we can track events with session context.\n\t\t// The session emits events on this emitter, and we listen here for metrics + logging.\n\t\tconst sessionEmitter = new SimpleEventEmitter()\n\n\t\tsessionEmitter.on('sync:connected', (event) => {\n\t\t\tthis.metrics.recordHandshake(sessionId, event.nodeId)\n\t\t\tthis.metrics.updateSessionState(sessionId, 'authenticated')\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.handshake',\n\t\t\t\tsessionId,\n\t\t\t\tnodeId: event.nodeId,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:received', (event) => {\n\t\t\tconst byteSize = estimateOperationByteSize(event.operations)\n\t\t\tthis.metrics.recordReceived(sessionId, event.batchSize, byteSize)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.received',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:sent', (event) => {\n\t\t\tconst byteSize = estimateOperationByteSize(event.operations)\n\t\t\tthis.metrics.recordSent(sessionId, event.batchSize, byteSize)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.sent',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:disconnected', () => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.disconnected',\n\t\t\t\tsessionId,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:schema-mismatch', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'session.schema_mismatch',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: {\n\t\t\t\t\tclientSchemaVersion: event.clientSchemaVersion,\n\t\t\t\t\tserverSchemaVersion: event.serverSchemaVersion,\n\t\t\t\t\tsupportedMin: event.supportedMin,\n\t\t\t\t\tsupportedMax: event.supportedMax,\n\t\t\t\t\treason: event.reason,\n\t\t\t\t},\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:delivery-stalled', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'session.delivery_stalled',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: {\n\t\t\t\t\twatermark: event.watermark,\n\t\t\t\t\trepeatCount: event.repeatCount,\n\t\t\t\t},\n\t\t\t})\n\t\t})\n\n\t\tconst session = new ClientSession({\n\t\t\tsessionId,\n\t\t\ttransport,\n\t\t\tstore: this.store,\n\t\t\tauth: this.auth ?? undefined,\n\t\t\tserializer: this.serializer,\n\t\t\temitter: sessionEmitter,\n\t\t\tlogger: this.logger,\n\t\t\tbatchSize: this.batchSize,\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t\tsupportedSchemaVersions: this.supportedSchemaVersions,\n\t\t\toperationTransforms: this.operationTransforms,\n\t\t\tonRelay: (sourceSessionId, operations) => {\n\t\t\t\tthis.handleRelay(sourceSessionId, operations)\n\t\t\t},\n\t\t\tonAwarenessUpdate: (sourceSessionId, message) => {\n\t\t\t\tthis.handleAwarenessRelay(sourceSessionId, message)\n\t\t\t},\n\t\t\tonYjsDocUpdate: (sourceSessionId, message) => {\n\t\t\t\tthis.handleYjsDocRelay(sourceSessionId, message)\n\t\t\t},\n\t\t\tonBlobChunkRequest: (sourceSessionId, message) => {\n\t\t\t\tthis.blobChunkRelay.handleRequest(sourceSessionId, message)\n\t\t\t},\n\t\t\tonBlobChunkResponse: (sourceSessionId, message) => {\n\t\t\t\tthis.blobChunkRelay.handleResponse(sourceSessionId, message)\n\t\t\t},\n\t\t\t...(this.persistBlobChunk ? { persistBlobChunk: this.persistBlobChunk } : {}),\n\t\t\t// Only forward when configured, so an unset server value leaves the\n\t\t\t// session on its own documented default rather than `undefined`.\n\t\t\t...(this.maxOperationBytes !== undefined\n\t\t\t\t? { maxOperationBytes: this.maxOperationBytes }\n\t\t\t\t: {}),\n\t\t\t...(this.maxOpsPerMinute !== undefined ? { maxOpsPerMinute: this.maxOpsPerMinute } : {}),\n\t\t\t...(this.validateOperation\n\t\t\t\t? { validateOperation: this.validateOperation, koraContext: this.koraContext }\n\t\t\t\t: {}),\n\t\t\tonClose: (sid) => {\n\t\t\t\tthis.handleSessionClose(sid)\n\t\t\t},\n\t\t\tonOrphanedRelays: (nodeId, ops) => {\n\t\t\t\tthis.bufferOrphanedRelays(nodeId, ops)\n\t\t\t},\n\t\t\ttakeOrphanedRelays: (nodeId) => this.takeOrphanedRelays(nodeId),\n\t\t})\n\n\t\tthis.sessions.set(sessionId, session)\n\t\tthis.yjsDocRelay.addClient(sessionId, transport)\n\t\tthis.blobChunkRelay.addClient(sessionId, transport)\n\t\tsession.start()\n\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'session.connected',\n\t\t\tsessionId,\n\t\t\tdetails: { totalSessions: this.sessions.size },\n\t\t})\n\n\t\treturn sessionId\n\t}\n\n\t/**\n\t * Get the current server status.\n\t */\n\tasync getStatus(): Promise<ServerStatus> {\n\t\tconst totalOps = await this.store.getOperationCount()\n\t\tconst snapshot = this.metrics.getSnapshot(totalOps)\n\t\treturn {\n\t\t\trunning: this.running,\n\t\t\tconnectedClients: snapshot.connectedClients,\n\t\t\tport: this.port ?? null,\n\t\t\ttotalOperations: snapshot.totalOperations,\n\t\t\tuptime: snapshot.uptime,\n\t\t\tversion: this.serverVersion,\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t\tconnectedNodeIds: snapshot.connectedNodeIds,\n\t\t\tpeakConnections: snapshot.peakConnections,\n\t\t\tconnectionsTotal: snapshot.connectionsTotal,\n\t\t\toperationsReceived: snapshot.operationsReceived,\n\t\t\toperationsSent: snapshot.operationsSent,\n\t\t\terrorCount: snapshot.errorCount,\n\t\t}\n\t}\n\n\t/**\n\t * Apply a server-originated operation (for example one created by a custom\n\t * HTTP route) through the same validated pipeline that incoming client\n\t * operations use — Tier 2 constraints, referential integrity, and cascade\n\t * side effects — then relay every applied operation to connected clients.\n\t *\n\t * Because the operation did not come from a client session, it is relayed to\n\t * ALL sessions (there is no source session to exclude). Each session still\n\t * applies its own per-scope visibility filter in `relayOperations`, so a\n\t * client only receives the operation if it falls within that client's scope.\n\t *\n\t * @param op - A fully-formed, server-originated operation to apply\n\t * @returns The apply result, including any server-generated side-effect ops\n\t */\n\tasync applyLocalOperation(op: Operation): Promise<ApplyServerOperationResult> {\n\t\tconst result = await applyServerOperation(this.store, op)\n\n\t\tif (result.result === 'applied' && result.appliedOperations.length > 0) {\n\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\tsession.relayOperations(result.appliedOperations)\n\t\t\t}\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Relay already-applied, server-originated operations to every connected client.\n\t * Used by the conditional route apply, which commits its operations atomically\n\t * through the store (bypassing {@link applyLocalOperation}) and then fans them\n\t * out. Each session still enforces its own per-scope visibility filter.\n\t *\n\t * @param operations - Operations that have already been committed to the store\n\t */\n\trelayServerOperations(operations: Operation[]): void {\n\t\tif (operations.length === 0) {\n\t\t\treturn\n\t\t}\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tsession.relayOperations(operations)\n\t\t}\n\t}\n\n\t/**\n\t * Collect every blob reference still reachable from live records on the server.\n\t *\n\t * This is the live set for garbage-collecting the server's central blob store:\n\t * pass the result to `collectBlobGarbage(blobStore, liveRefs)` from\n\t * `@korajs/store` to reclaim bytes no record references any more. Only\n\t * collections that declare a `blob` field are scanned.\n\t *\n\t * @returns Every live blob reference across all collections\n\t */\n\tasync getLiveBlobRefs(): Promise<BlobRef[]> {\n\t\tconst schema = this.store.getSchema()\n\t\tif (!schema) {\n\t\t\treturn []\n\t\t}\n\t\tconst refs: BlobRef[] = []\n\t\tfor (const [name, collection] of Object.entries(schema.collections)) {\n\t\t\tconst hasBlobField = Object.values(collection.fields).some((field) => field.kind === 'blob')\n\t\t\tif (!hasBlobField) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst records = await this.store.materializeCollection(name)\n\t\t\tfor (const record of records) {\n\t\t\t\tfor (const value of Object.values(record)) {\n\t\t\t\t\tif (isBlobRef(value)) {\n\t\t\t\t\t\trefs.push(value)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn refs\n\t}\n\n\t/**\n\t * Get the number of currently connected clients.\n\t */\n\tgetConnectionCount(): number {\n\t\treturn this.sessions.size\n\t}\n\n\t// --- Private ---\n\n\tprivate handleRelay(sourceSessionId: string, operations: Operation[]): void {\n\t\tconst targetCount = this.sessions.size - 1\n\t\tconst byteSize = estimateOperationByteSize(operations)\n\t\tthis.metrics.recordSent(\n\t\t\tsourceSessionId,\n\t\t\toperations.length * targetCount,\n\t\t\tbyteSize * targetCount,\n\t\t)\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'operations.relayed',\n\t\t\tsessionId: sourceSessionId,\n\t\t\tcount: operations.length,\n\t\t\tbytes: byteSize * targetCount,\n\t\t\tdetails: { targetSessions: targetCount },\n\t\t})\n\n\t\tfor (const [sessionId, session] of this.sessions) {\n\t\t\tif (sessionId === sourceSessionId) continue\n\t\t\tsession.relayOperations(operations)\n\t\t}\n\t}\n\n\tprivate handleSessionClose(sessionId: string): void {\n\t\tthis.metrics.recordDisconnection(sessionId)\n\t\tthis.awarenessRelay.removeClient(sessionId)\n\t\tthis.yjsDocRelay.removeClient(sessionId)\n\t\tthis.blobChunkRelay.removeClient(sessionId)\n\n\t\tthis.sessions.delete(sessionId)\n\n\t\tconst clientId = this.httpSessionToClient.get(sessionId)\n\t\tif (clientId) {\n\t\t\tthis.httpSessionToClient.delete(sessionId)\n\t\t\tthis.httpClients.delete(clientId)\n\t\t}\n\t}\n\n\tprivate handleAwarenessRelay(sourceSessionId: string, message: AwarenessUpdateMessage): void {\n\t\t// Register client with awareness relay if not already done\n\t\tconst session = this.sessions.get(sourceSessionId)\n\t\tif (!session) return\n\n\t\tconst transport = session.getTransport()\n\t\tif (!this.awarenessRelay.getClientCount() || !transport) {\n\t\t\t// First awareness update from this client -- register\n\t\t}\n\t\tthis.awarenessRelay.addClient(sourceSessionId, message.clientId, transport)\n\t\tthis.awarenessRelay.handleUpdate(sourceSessionId, message)\n\t}\n\n\tprivate handleYjsDocRelay(sourceSessionId: string, message: YjsDocUpdateMessage): void {\n\t\tif (!this.sessions.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\t\tthis.yjsDocRelay.handleUpdate(sourceSessionId, message)\n\t}\n\n\tprivate getOrCreateHttpClient(clientId: string): {\n\t\tsessionId: string\n\t\ttransport: HttpServerTransport\n\t} {\n\t\tconst existing = this.httpClients.get(clientId)\n\t\tif (existing) {\n\t\t\treturn existing\n\t\t}\n\n\t\tconst transport = new HttpServerTransport(this.serializer)\n\t\tconst sessionId = this.handleConnection(transport)\n\t\tconst client = { sessionId, transport }\n\n\t\tthis.httpClients.set(clientId, client)\n\t\tthis.httpSessionToClient.set(sessionId, clientId)\n\n\t\treturn client\n\t}\n}\n\n/**\n * Estimate the total byte size of serialized operations.\n * Used for bandwidth tracking.\n */\nfunction estimateOperationByteSize(operations: Operation[]): number {\n\tlet total = 0\n\tfor (const op of operations) {\n\t\ttotal += JSON.stringify(op).length\n\t}\n\treturn total\n}\n\nfunction normalizeHttpBody(body: string | Uint8Array, contentType?: string): string | Uint8Array {\n\tif (body instanceof Uint8Array) {\n\t\treturn body\n\t}\n\n\tif (contentType?.includes('application/x-protobuf')) {\n\t\treturn new TextEncoder().encode(body)\n\t}\n\n\treturn body\n}\n","import { generateUUIDv7 } from '@korajs/core'\nimport type { AwarenessStateWire, AwarenessUpdateMessage, SyncMessage } from '@korajs/sync'\nimport type { ServerTransport } from '../transport/server-transport'\n\n/**\n * Tracks a single client's awareness registration.\n */\ninterface AwarenessClient {\n\t/** Session ID for this client */\n\tsessionId: string\n\t/** Client-assigned awareness ID (numeric, unique per client) */\n\tclientId: number\n\t/** Transport for sending messages to this client */\n\ttransport: ServerTransport\n\t/** Current awareness state, if any */\n\tstate: AwarenessStateWire | null\n}\n\n/**\n * Server-side awareness relay. Broadcasts ephemeral awareness states\n * (cursor positions, user presence) between connected clients.\n *\n * Awareness data is never persisted. The relay simply forwards awareness\n * updates from one client to all other connected clients, and broadcasts\n * removal notifications when a client disconnects.\n */\nexport class AwarenessRelay {\n\tprivate readonly clients = new Map<string, AwarenessClient>()\n\n\t/**\n\t * Register a client for awareness broadcasting.\n\t *\n\t * @param sessionId - Unique session identifier\n\t * @param clientId - Client-assigned awareness ID\n\t * @param transport - Transport for sending messages to this client\n\t */\n\taddClient(sessionId: string, clientId: number, transport: ServerTransport): void {\n\t\tthis.clients.set(sessionId, {\n\t\t\tsessionId,\n\t\t\tclientId,\n\t\t\ttransport,\n\t\t\tstate: null,\n\t\t})\n\n\t\t// Send this client all existing awareness states so it catches up\n\t\tconst existingStates: Record<string, AwarenessStateWire | null> = {}\n\t\tlet hasStates = false\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === sessionId) continue\n\t\t\tif (client.state) {\n\t\t\t\texistingStates[String(client.clientId)] = client.state\n\t\t\t\thasStates = true\n\t\t\t}\n\t\t}\n\n\t\tif (hasStates) {\n\t\t\tconst catchUpMsg: SyncMessage = {\n\t\t\t\ttype: 'awareness-update',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tclientId: 0, // Server-sourced\n\t\t\t\tstates: existingStates,\n\t\t\t}\n\t\t\ttransport.send(catchUpMsg)\n\t\t}\n\t}\n\n\t/**\n\t * Remove a client and broadcast its removal to all remaining clients.\n\t *\n\t * @param sessionId - Session ID of the disconnecting client\n\t */\n\tremoveClient(sessionId: string): void {\n\t\tconst client = this.clients.get(sessionId)\n\t\tif (!client) return\n\n\t\tthis.clients.delete(sessionId)\n\n\t\t// Only broadcast removal if the client had an awareness state\n\t\tif (client.state === null) return\n\n\t\tconst removalStates: Record<string, AwarenessStateWire | null> = {\n\t\t\t[String(client.clientId)]: null,\n\t\t}\n\n\t\tconst msg: SyncMessage = {\n\t\t\ttype: 'awareness-update',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tclientId: client.clientId,\n\t\t\tstates: removalStates,\n\t\t}\n\n\t\tthis.broadcastExcept(sessionId, msg)\n\t}\n\n\t/**\n\t * Handle an incoming awareness update from a client.\n\t * Stores the state and relays to all other connected clients.\n\t *\n\t * @param sessionId - Session ID of the sending client\n\t * @param message - The awareness update message\n\t */\n\thandleUpdate(sessionId: string, message: AwarenessUpdateMessage): void {\n\t\tconst sender = this.clients.get(sessionId)\n\t\tif (!sender) return\n\n\t\t// Update stored state for this client\n\t\tconst senderState = message.states[String(message.clientId)]\n\t\tif (senderState !== undefined) {\n\t\t\tsender.state = senderState\n\t\t}\n\n\t\t// Relay to all other clients\n\t\tthis.broadcastExcept(sessionId, message)\n\t}\n\n\t/**\n\t * Get the number of registered awareness clients.\n\t */\n\tgetClientCount(): number {\n\t\treturn this.clients.size\n\t}\n\n\t/**\n\t * Remove all clients and clear all state.\n\t */\n\tclear(): void {\n\t\tthis.clients.clear()\n\t}\n\n\t// --- Private ---\n\n\tprivate broadcastExcept(excludeSessionId: string, message: SyncMessage): void {\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === excludeSessionId) continue\n\t\t\tif (!client.transport.isConnected()) continue\n\n\t\t\tclient.transport.send(message)\n\t\t}\n\t}\n}\n","import type { AuthContext, SessionState } from '../types'\n\n/**\n * Snapshot of server-side sync metrics at a point in time.\n */\nexport interface ServerMetricsSnapshot {\n\tconnectedClients: number\n\tconnectedNodeIds: string[]\n\tpeakConnections: number\n\tconnectionsTotal: number\n\toperationsReceived: number\n\toperationsSent: number\n\tbytesReceived: number\n\tbytesSent: number\n\tclients: ClientMetrics[]\n\tuptime: number\n\ttotalOperations: number\n\terrorCount: number\n\tschemaVersion: number\n}\n\n/**\n * Per-client metrics tracked by the server.\n */\nexport interface ClientMetrics {\n\tsessionId: string\n\tnodeId: string | null\n\tstate: SessionState\n\tconnectedAt: number\n\toperationsReceived: number\n\toperationsSent: number\n\tauthContext: AuthContext | null\n}\n\n/**\n * Collects and aggregates server-side sync metrics.\n *\n * Tracks connected clients, throughput, error counts, and per-session\n * metadata. Designed to be hooked into KoraSyncServer lifecycle events.\n */\n/**\n * Estimate the byte size of a batch of operations.\n * Used for bandwidth tracking in sync events.\n * Each operation is approximated by JSON-serializing and measuring length.\n */\nexport function estimateByteSize(operations: Array<unknown>): number {\n\tlet total = 0\n\tfor (const op of operations) {\n\t\ttotal += JSON.stringify(op).length\n\t}\n\treturn total\n}\n\nexport class ServerMetricsCollector {\n\tprivate startedAt = Date.now()\n\n\tprivate peakConnections = 0\n\tprivate connectionsTotal = 0\n\tprivate operationsReceived = 0\n\tprivate operationsSent = 0\n\tprivate bytesReceived = 0\n\tprivate bytesSent = 0\n\tprivate errorCount = 0\n\tprivate schemaVersion = 1\n\n\tprivate readonly clientMetrics = new Map<string, ClientMetrics>()\n\n\t/** Record a new client connection. */\n\trecordConnection(sessionId: string): void {\n\t\tthis.connectionsTotal++\n\t\tthis.clientMetrics.set(sessionId, {\n\t\t\tsessionId,\n\t\t\tnodeId: null,\n\t\t\tstate: 'connected',\n\t\t\tconnectedAt: Date.now(),\n\t\t\toperationsReceived: 0,\n\t\t\toperationsSent: 0,\n\t\t\tauthContext: null,\n\t\t})\n\t\tthis.peakConnections = Math.max(this.peakConnections, this.clientMetrics.size)\n\t}\n\n\t/** Record a client disconnection. */\n\trecordDisconnection(sessionId: string): void {\n\t\tthis.clientMetrics.delete(sessionId)\n\t}\n\n\t/** Update the node ID after a handshake completes. */\n\trecordHandshake(sessionId: string, nodeId: string): void {\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.nodeId = nodeId\n\t\t}\n\t}\n\n\t/** Update session state. */\n\tupdateSessionState(sessionId: string, state: SessionState): void {\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.state = state\n\t\t}\n\t}\n\n\t/** Record authentication context for a session. */\n\trecordAuth(sessionId: string, authContext: AuthContext | null): void {\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.authContext = authContext\n\t\t}\n\t}\n\n\t/** Record operations received from a client. */\n\trecordReceived(sessionId: string, count: number, byteSize: number): void {\n\t\tthis.operationsReceived += count\n\t\tthis.bytesReceived += byteSize\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.operationsReceived += count\n\t\t}\n\t}\n\n\t/** Record operations sent to a client. */\n\trecordSent(sessionId: string, count: number, byteSize: number): void {\n\t\tthis.operationsSent += count\n\t\tthis.bytesSent += byteSize\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.operationsSent += count\n\t\t}\n\t}\n\n\t/** Record an error. */\n\trecordError(): void {\n\t\tthis.errorCount++\n\t}\n\n\t/** Set the schema version. */\n\tsetSchemaVersion(version: number): void {\n\t\tthis.schemaVersion = version\n\t}\n\n\t/** Return a full snapshot of current metrics. */\n\tgetSnapshot(totalOperations: number): ServerMetricsSnapshot {\n\t\treturn {\n\t\t\tconnectedClients: this.clientMetrics.size,\n\t\t\tconnectedNodeIds: Array.from(this.clientMetrics.values())\n\t\t\t\t.filter((c) => c.nodeId !== null)\n\t\t\t\t.map((c) => c.nodeId as string),\n\t\t\tpeakConnections: this.peakConnections,\n\t\t\tconnectionsTotal: this.connectionsTotal,\n\t\t\toperationsReceived: this.operationsReceived,\n\t\t\toperationsSent: this.operationsSent,\n\t\t\tbytesReceived: this.bytesReceived,\n\t\t\tbytesSent: this.bytesSent,\n\t\t\tclients: Array.from(this.clientMetrics.values()),\n\t\t\tuptime: Date.now() - this.startedAt,\n\t\t\ttotalOperations,\n\t\t\terrorCount: this.errorCount,\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t}\n\t}\n\n\t/** Reset all metrics. */\n\treset(): void {\n\t\tthis.startedAt = Date.now()\n\t\tthis.peakConnections = 0\n\t\tthis.connectionsTotal = 0\n\t\tthis.operationsReceived = 0\n\t\tthis.operationsSent = 0\n\t\tthis.bytesReceived = 0\n\t\tthis.bytesSent = 0\n\t\tthis.errorCount = 0\n\t\tthis.clientMetrics.clear()\n\t}\n}\n","import {\n\ttype BlobChunkRequestMessage,\n\ttype BlobChunkResponseMessage,\n\tencodeBlobChunkBytes,\n} from '@korajs/sync'\nimport type { ServerTransport } from '../transport/server-transport'\n\n/**\n * Resolves a blob chunk by content hash from server-side storage. Optional: when\n * provided, the server can answer chunk requests directly from its own store\n * (central-store deployment). When absent, the server acts as a pure relay,\n * forwarding chunk requests to peer sessions and their responses back.\n */\nexport type ResolveBlobChunk = (hash: string) => Promise<Uint8Array | null>\n\ninterface RelayClient {\n\tsessionId: string\n\ttransport: ServerTransport\n}\n\n/**\n * Routes out-of-band blob chunk transfer between connected clients (and,\n * optionally, a server-side blob store).\n *\n * The server never stores or inspects blob bytes on the relay path: a\n * `blob-chunk-request` is forwarded to peer sessions, and the first peer to\n * answer with the bytes has its `blob-chunk-response` routed back to the\n * original requester by `requestId`. Blob bytes never enter the operation log;\n * only the `BlobRef` reference inside a record does.\n *\n * Not persisted — this is an ephemeral side channel, like the Yjs doc relay.\n */\nexport class BlobChunkRelay {\n\tprivate readonly clients = new Map<string, RelayClient>()\n\t/** requestId -> the session that originated the request (to route the answer back). */\n\tprivate readonly pending = new Map<string, string>()\n\tprivate readonly resolveBlobChunk: ResolveBlobChunk | null\n\n\tconstructor(resolveBlobChunk?: ResolveBlobChunk) {\n\t\tthis.resolveBlobChunk = resolveBlobChunk ?? null\n\t}\n\n\taddClient(sessionId: string, transport: ServerTransport): void {\n\t\tthis.clients.set(sessionId, { sessionId, transport })\n\t}\n\n\tremoveClient(sessionId: string): void {\n\t\tthis.clients.delete(sessionId)\n\t\t// Drop any requests this session was waiting on; their answers can no\n\t\t// longer be delivered.\n\t\tfor (const [requestId, originSessionId] of this.pending) {\n\t\t\tif (originSessionId === sessionId) {\n\t\t\t\tthis.pending.delete(requestId)\n\t\t\t}\n\t\t}\n\t}\n\n\tgetClientCount(): number {\n\t\treturn this.clients.size\n\t}\n\n\tgetPendingCount(): number {\n\t\treturn this.pending.size\n\t}\n\n\tclear(): void {\n\t\tthis.clients.clear()\n\t\tthis.pending.clear()\n\t}\n\n\t/**\n\t * Handle an inbound chunk request from a session. Tries the server's own\n\t * store first (if configured), otherwise forwards the request to peer\n\t * sessions and remembers who to route the answer back to.\n\t */\n\thandleRequest(sourceSessionId: string, message: BlobChunkRequestMessage): void {\n\t\tif (!this.clients.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\n\t\tif (this.resolveBlobChunk) {\n\t\t\tvoid this.resolveBlobChunk(message.hash).then(\n\t\t\t\t(bytes) => {\n\t\t\t\t\tif (bytes !== null) {\n\t\t\t\t\t\tthis.sendResponseTo(sourceSessionId, message.requestId, encodeBlobChunkBytes(bytes))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tthis.forwardRequestToPeers(sourceSessionId, message)\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\t// A store read error is treated as \"not held here\": fall back to peers\n\t\t\t\t\t// rather than crashing the connection.\n\t\t\t\t\tthis.forwardRequestToPeers(sourceSessionId, message)\n\t\t\t\t},\n\t\t\t)\n\t\t\treturn\n\t\t}\n\n\t\tthis.forwardRequestToPeers(sourceSessionId, message)\n\t}\n\n\t/**\n\t * Handle an inbound chunk response from a peer. Routes it back to the session\n\t * that originally requested it. A \"not held\" answer (bytes === null) is\n\t * ignored so a peer without the chunk does not preempt one that has it; the\n\t * requester's own per-request timeout bounds the wait.\n\t */\n\thandleResponse(sourceSessionId: string, message: BlobChunkResponseMessage): void {\n\t\tif (!this.clients.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\t\tif (message.bytes === null) {\n\t\t\treturn\n\t\t}\n\t\tconst originSessionId = this.pending.get(message.requestId)\n\t\tif (!originSessionId) {\n\t\t\treturn\n\t\t}\n\t\tthis.pending.delete(message.requestId)\n\t\tthis.sendResponseTo(originSessionId, message.requestId, message.bytes)\n\t}\n\n\tprivate forwardRequestToPeers(sourceSessionId: string, message: BlobChunkRequestMessage): void {\n\t\tthis.pending.set(message.requestId, sourceSessionId)\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === sourceSessionId) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (!client.transport.isConnected()) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tclient.transport.send(message)\n\t\t}\n\t}\n\n\tprivate sendResponseTo(sessionId: string, requestId: string, bytes: string): void {\n\t\tconst client = this.clients.get(sessionId)\n\t\tif (!client || !client.transport.isConnected()) {\n\t\t\treturn\n\t\t}\n\t\tconst response: BlobChunkResponseMessage = {\n\t\t\ttype: 'blob-chunk-response',\n\t\t\tmessageId: generateResponseId(requestId),\n\t\t\trequestId,\n\t\t\tbytes,\n\t\t}\n\t\tclient.transport.send(response)\n\t}\n}\n\n/**\n * Derive a deterministic wire messageId for a routed response. The correlation\n * that matters is `requestId`; `messageId` only needs to be a non-empty string,\n * so deriving it avoids a clock/random dependency in the relay.\n */\nfunction generateResponseId(requestId: string): string {\n\treturn `blob-resp-${requestId}`\n}\n","import type { SyncMessage, YjsDocUpdateMessage } from '@korajs/sync'\nimport type { ServerTransport } from '../transport/server-transport'\n\ninterface RelayClient {\n\tsessionId: string\n\ttransport: ServerTransport\n}\n\n/**\n * Relays ephemeral Yjs doc channel updates between connected clients.\n * Not persisted — durable richtext state still flows through the operation log.\n */\nexport class YjsDocRelay {\n\tprivate readonly clients = new Map<string, RelayClient>()\n\n\taddClient(sessionId: string, transport: ServerTransport): void {\n\t\tthis.clients.set(sessionId, { sessionId, transport })\n\t}\n\n\tremoveClient(sessionId: string): void {\n\t\tthis.clients.delete(sessionId)\n\t}\n\n\thandleUpdate(sourceSessionId: string, message: YjsDocUpdateMessage): void {\n\t\tif (!this.clients.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\t\tthis.broadcastExcept(sourceSessionId, message)\n\t}\n\n\tgetClientCount(): number {\n\t\treturn this.clients.size\n\t}\n\n\tclear(): void {\n\t\tthis.clients.clear()\n\t}\n\n\tprivate broadcastExcept(excludeSessionId: string, message: SyncMessage): void {\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === excludeSessionId) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (!client.transport.isConnected()) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tclient.transport.send(message)\n\t\t}\n\t}\n}\n","import {\n\ttype AtomicOp,\n\tHybridLogicalClock,\n\ttype Operation,\n\tcreateOperation,\n\tgenerateUUIDv7,\n\tisAtomicOp,\n\tresolveAtomicOp,\n\ttoAtomicOp,\n} from '@korajs/core'\nimport { isRetriableRejection } from '../apply/rejection-taxonomy'\nimport { type RoutePredicate, evaluateRoutePredicate } from '../apply/route-predicate'\nimport { nextServerSequenceNumber } from '../apply/server-side-effect-operation'\nimport type { ScopeMap } from '../scopes/server-scope-filter'\nimport { operationMatchesScopes } from '../scopes/server-scope-filter'\nimport type {\n\tCollectionQueryOptions,\n\tConditionalApplyInput,\n\tConditionalApplyResult,\n\tMaterializedRecord,\n\tServerStore,\n} from '../store/server-store'\nimport type { KoraSyncServer } from './kora-sync-server'\n\n/**\n * A mutation a custom HTTP route asks the server to apply on the data plane.\n *\n * `recordId` is optional for inserts (a UUID v7 is generated when omitted) and\n * required for updates and deletes. For updates, `data` holds only the changed\n * fields; the server reads the current record to capture the previous values so\n * the change three-way merges correctly with concurrent client edits.\n */\nexport interface RouteMutation {\n\tcollection: string\n\ttype: 'insert' | 'update' | 'delete'\n\trecordId?: string\n\tdata?: Record<string, unknown> | null\n}\n\n/**\n * Scope the route derived from the request's authenticated actor. When present,\n * it is enforced exactly like a sync session's scope: `apply()` rejects a\n * mutation whose resulting record falls outside the scope, and `query()` /\n * `findById()` only return records inside it. Omit it for genuinely public\n * routes (for example a signup endpoint) where no per-actor isolation applies.\n */\nexport interface RouteScopeOptions {\n\tscope?: ScopeMap\n}\n\n/** Result of {@link ProductionHttpRouteContext.apply}. */\nexport type RouteApplyResult =\n\t| { ok: true; operation: Operation; record: MaterializedRecord | null }\n\t| { ok: false; code: string; message: string; retriable: boolean }\n\n/**\n * A conditional, multi-collection admission gate applied atomically per instance.\n *\n * The gate reads the current state of the target record (`collection` + `id`),\n * checks the `if` predicate against it, and only then applies the `update` to the\n * target plus every mutation in `also` as one set. If the predicate fails it\n * applies nothing and returns the structured `reject`. `idempotencyKey` names a\n * record whose prior existence proves the set already committed, so a retry\n * returns the earlier outcome instead of applying the set (and its non-idempotent\n * counter increments) again.\n *\n * Atomicity note: within one server instance the check and the writes do not\n * interleave with other route mutations. Cross-instance, race-free admission and\n * all-or-nothing across a mid-set crash require the store-level conditional\n * transaction (a Postgres `WHERE ... < cap` commit), which is the next increment.\n */\nexport interface RouteConditionalApply {\n\t/** Collection of the record the predicate reads and the `update` targets. */\n\tcollection: string\n\t/** Id of the target record. */\n\tid: string\n\t/** Admission predicate evaluated against the target's current state. */\n\tif?: RoutePredicate\n\t/** Partial update applied to the target record when the predicate holds. */\n\tupdate?: Record<string, unknown> | null\n\t/** Additional mutations committed atomically with the target update. */\n\talso?: RouteMutation[]\n\t/** Structured rejection returned when the predicate does not hold. */\n\treject?: { code: string; message: string }\n\t/**\n\t * Names a record whose existence means this set already committed. When it is\n\t * present the set is skipped and the prior outcome returned. Use a stable,\n\t * client-generated id (for example the accepted record's own id).\n\t */\n\tidempotencyKey?: { collection: string; id: string }\n}\n\n/** Result of {@link ProductionHttpRouteContext.applyConditional}. */\nexport type RouteConditionalResult =\n\t| {\n\t\t\tok: true\n\t\t\t/** True when the set was already committed and this call was a no-op. */\n\t\t\tidempotent: boolean\n\t\t\toperations: Operation[]\n\t\t\trecords: (MaterializedRecord | null)[]\n\t }\n\t| { ok: false; code: string; message: string; retriable: boolean }\n\n/**\n * Scoped, validated data-plane access handed to custom HTTP route handlers.\n *\n * Every mutation goes through the same pipeline as sync (Tier 2 constraints,\n * referential integrity, materialization, and fan-out to connected clients), so\n * REST endpoints cannot accidentally bypass validation, constraints, or tenant\n * isolation the way hand-rolled store writes can.\n */\nexport interface ProductionHttpRouteContext {\n\t/**\n\t * Apply a mutation through the validated server pipeline and relay the\n\t * resulting operation(s) to connected clients.\n\t */\n\tapply(mutation: RouteMutation, options?: RouteScopeOptions): Promise<RouteApplyResult>\n\t/**\n\t * Conditionally apply a multi-collection mutation set as one admission gate:\n\t * read the target, check the predicate, and commit the update plus every `also`\n\t * mutation only if it holds, with at-most-once semantics via `idempotencyKey`.\n\t */\n\tapplyConditional(\n\t\tspec: RouteConditionalApply,\n\t\toptions?: RouteScopeOptions,\n\t): Promise<RouteConditionalResult>\n\t/** Read materialized records from a collection, optionally scoped. */\n\tquery(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions & RouteScopeOptions,\n\t): Promise<MaterializedRecord[]>\n\t/** Read a single materialized record by id, optionally scoped. */\n\tfindById(\n\t\tcollection: string,\n\t\tid: string,\n\t\toptions?: RouteScopeOptions,\n\t): Promise<MaterializedRecord | null>\n}\n\n/**\n * Returns true when a materialized record satisfies the scope declared for its\n * collection. A collection absent from the scope map is treated as out of scope\n * (hidden), mirroring `operationMatchesScopes` on the write path.\n */\nfunction recordMatchesScope(\n\tcollection: string,\n\trecord: MaterializedRecord,\n\tscope: ScopeMap,\n): boolean {\n\tconst collectionScope = scope[collection]\n\tif (!collectionScope) {\n\t\treturn false\n\t}\n\tfor (const [field, expected] of Object.entries(collectionScope)) {\n\t\tif (record[field] !== expected) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n/** Picks only the given keys from a record (used to capture previousData). */\nfunction pickFields(record: Record<string, unknown>, keys: string[]): Record<string, unknown> {\n\tconst picked: Record<string, unknown> = {}\n\tfor (const key of keys) {\n\t\tif (key in record) {\n\t\t\tpicked[key] = record[key]\n\t\t}\n\t}\n\treturn picked\n}\n\n/**\n * Build a server-originated operation for a route mutation, reading current\n * materialized state so updates and deletes carry accurate previous values.\n *\n * `currentOverride`, when provided, supplies that current state instead of reading\n * it from the store. The conditional apply passes the record it read under the\n * cross-instance lock, so an atomic-op update (for example `op.increment`) resolves\n * against the authoritative locked value rather than a stale read.\n *\n * `clockOverride`, when provided, stamps the operation instead of a fresh clock. The\n * cross-instance conditional apply passes a clock the store advanced past the target\n * record's latest write, so the operation sorts strictly after it and last-write-wins\n * materialization matches the serialized commit order.\n */\nasync function buildRouteOperation(\n\tstore: ServerStore,\n\tmutation: RouteMutation,\n\tcurrentOverride?: { record: MaterializedRecord | null },\n\tclockOverride?: HybridLogicalClock,\n): Promise<Operation> {\n\tconst nodeId = store.getNodeId()\n\tconst clock = clockOverride ?? new HybridLogicalClock(nodeId)\n\tconst schemaVersion = store.getSchema()?.version ?? 1\n\tconst sequenceNumber = nextServerSequenceNumber(store)\n\n\tif (mutation.type === 'insert') {\n\t\treturn createOperation(\n\t\t\t{\n\t\t\t\tnodeId,\n\t\t\t\ttype: 'insert',\n\t\t\t\tcollection: mutation.collection,\n\t\t\t\trecordId: mutation.recordId ?? generateUUIDv7(),\n\t\t\t\tdata: mutation.data ?? {},\n\t\t\t\tpreviousData: null,\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps: [],\n\t\t\t\tschemaVersion,\n\t\t\t},\n\t\t\tclock,\n\t\t)\n\t}\n\n\tif (!mutation.recordId) {\n\t\tthrow new RouteMutationError(\n\t\t\t'MISSING_RECORD_ID',\n\t\t\t`A ${mutation.type} mutation on \"${mutation.collection}\" requires a recordId.`,\n\t\t)\n\t}\n\n\tconst current = currentOverride\n\t\t? currentOverride.record\n\t\t: await store.findRecord(mutation.collection, mutation.recordId)\n\n\tif (mutation.type === 'update') {\n\t\tconst rawData = mutation.data ?? {}\n\t\t// Resolve atomic-op sentinels (op.increment, op.max, ...) exactly as the\n\t\t// client's update path does: `data` carries the concrete resolved value for\n\t\t// materialization, and `atomicOps` carries the intent so concurrent atomic\n\t\t// writes compose in the merge engine instead of last-write-wins.\n\t\tconst data: Record<string, unknown> = {}\n\t\tconst atomicOps: Record<string, AtomicOp> = {}\n\t\tfor (const key of Object.keys(rawData)) {\n\t\t\tconst value = rawData[key]\n\t\t\tif (isAtomicOp(value)) {\n\t\t\t\tdata[key] = resolveAtomicOp(current ? current[key] : undefined, value)\n\t\t\t\tatomicOps[key] = toAtomicOp(value)\n\t\t\t} else {\n\t\t\t\tdata[key] = value\n\t\t\t}\n\t\t}\n\t\treturn createOperation(\n\t\t\t{\n\t\t\t\tnodeId,\n\t\t\t\ttype: 'update',\n\t\t\t\tcollection: mutation.collection,\n\t\t\t\trecordId: mutation.recordId,\n\t\t\t\tdata,\n\t\t\t\tpreviousData: current ? pickFields(current, Object.keys(rawData)) : {},\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps: [],\n\t\t\t\tschemaVersion,\n\t\t\t\t...(Object.keys(atomicOps).length > 0 ? { atomicOps } : {}),\n\t\t\t},\n\t\t\tclock,\n\t\t)\n\t}\n\n\t// delete\n\treturn createOperation(\n\t\t{\n\t\t\tnodeId,\n\t\t\ttype: 'delete',\n\t\t\tcollection: mutation.collection,\n\t\t\trecordId: mutation.recordId,\n\t\t\tdata: null,\n\t\t\tpreviousData: current ? { ...current } : null,\n\t\t\tsequenceNumber,\n\t\t\tcausalDeps: [],\n\t\t\tschemaVersion,\n\t\t},\n\t\tclock,\n\t)\n}\n\n/** Internal error carrying a stable code for route-context failures. */\nclass RouteMutationError extends Error {\n\tconstructor(\n\t\treadonly code: string,\n\t\tmessage: string,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'RouteMutationError'\n\t}\n}\n\n/**\n * Create the scoped, validated data-plane context handed to custom HTTP route\n * handlers as `request.kora`.\n *\n * Mutations are serialized so concurrent requests cannot race on server\n * sequence-number allocation: each `apply()` builds and applies its operation\n * before the next begins.\n */\nexport function createRouteContext(\n\tserver: KoraSyncServer,\n\tstore: ServerStore,\n): ProductionHttpRouteContext {\n\t// Promise chain that serializes apply() so sequence allocation + apply is\n\t// atomic per mutation, even under concurrent in-flight requests.\n\tlet mutationTail: Promise<unknown> = Promise.resolve()\n\n\tfunction serialize<T>(work: () => Promise<T>): Promise<T> {\n\t\tconst run = mutationTail.then(work, work)\n\t\t// Keep the tail from rejecting so one failed mutation does not poison the\n\t\t// chain for subsequent ones.\n\t\tmutationTail = run.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t)\n\t\treturn run\n\t}\n\n\t// Build a route operation and check scope, WITHOUT applying it. Splitting\n\t// preparation from commit lets applyConditional validate an entire mutation set\n\t// before committing any of it, so a scope violation or malformed mutation in\n\t// `also` cannot leave the target update (for example a counter increment)\n\t// committed while the rest is rejected.\n\ttype RouteRejection = { ok: false; code: string; message: string; retriable: boolean }\n\ttype PreparedMutation = { ok: true; op: Operation } | { ok: false; rejection: RouteRejection }\n\tasync function prepareMutation(\n\t\tmutation: RouteMutation,\n\t\tscope: ScopeMap | undefined,\n\t): Promise<PreparedMutation> {\n\t\tlet op: Operation\n\t\ttry {\n\t\t\top = await buildRouteOperation(store, mutation)\n\t\t} catch (error) {\n\t\t\tif (error instanceof RouteMutationError) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\trejection: {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tcode: error.code,\n\t\t\t\t\t\tmessage: error.message,\n\t\t\t\t\t\tretriable: isRetriableRejection(error.code),\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\tif (scope && !operationMatchesScopes(op, scope)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\trejection: {\n\t\t\t\t\tok: false,\n\t\t\t\t\tcode: 'SCOPE_VIOLATION',\n\t\t\t\t\tmessage: `Mutation on \"${mutation.collection}\" is outside the provided scope.`,\n\t\t\t\t\tretriable: isRetriableRejection('SCOPE_VIOLATION'),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\treturn { ok: true, op }\n\t}\n\n\t// Apply a prepared operation and read back the resulting record.\n\tasync function commitOperation(op: Operation, collection: string): Promise<RouteApplyResult> {\n\t\tconst result = await server.applyLocalOperation(op)\n\t\tif (result.result !== 'applied') {\n\t\t\tconst code = result.rejection?.code ?? 'NOT_APPLIED'\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tcode,\n\t\t\t\tmessage:\n\t\t\t\t\tresult.rejection?.message ??\n\t\t\t\t\t`Operation on \"${collection}\" was not applied (${result.result}).`,\n\t\t\t\t// Prefer the pipeline's own classification when present; fall back\n\t\t\t\t// to classifying the code so this stays correct if new codes appear.\n\t\t\t\tretriable: result.rejection?.retriable ?? isRetriableRejection(code),\n\t\t\t}\n\t\t}\n\n\t\tconst record = await store.findRecord(collection, op.recordId)\n\t\treturn { ok: true, operation: op, record }\n\t}\n\n\t// The un-serialized core of a single mutation. Both apply() and\n\t// applyConditional() call this inside a serialized block, so it must NOT\n\t// serialize itself (that would deadlock the promise-chain tail).\n\tasync function rawApply(\n\t\tmutation: RouteMutation,\n\t\tscope: ScopeMap | undefined,\n\t): Promise<RouteApplyResult> {\n\t\tconst prepared = await prepareMutation(mutation, scope)\n\t\tif (!prepared.ok) {\n\t\t\treturn prepared.rejection\n\t\t}\n\t\treturn commitOperation(prepared.op, mutation.collection)\n\t}\n\n\t// Cross-instance conditional apply, delegating admission and atomicity to the\n\t// store (the Postgres advisory-lock transaction). The store owns the\n\t// read-decide-write cycle so a cap check is race-free across instances; this\n\t// bridge translates the route spec into the store's callback shape, validates\n\t// scope on each built operation while still inside the locked transaction (so a\n\t// violation rolls everything back), then relays the committed set to clients.\n\tasync function runConditionalViaStore(\n\t\tstoreApplyConditional: (input: ConditionalApplyInput) => Promise<ConditionalApplyResult>,\n\t\tspec: RouteConditionalApply,\n\t\toptions: RouteScopeOptions | undefined,\n\t): Promise<RouteConditionalResult> {\n\t\tconst scope = options?.scope\n\n\t\t// Assemble the set: the target update (when given) first, then every `also`.\n\t\tconst mutations: RouteMutation[] = []\n\t\tconst hasTargetUpdate = spec.update !== undefined && spec.update !== null\n\t\tif (hasTargetUpdate) {\n\t\t\tmutations.push({\n\t\t\t\tcollection: spec.collection,\n\t\t\t\ttype: 'update',\n\t\t\t\trecordId: spec.id,\n\t\t\t\tdata: spec.update,\n\t\t\t})\n\t\t}\n\t\tif (spec.also) {\n\t\t\tmutations.push(...spec.also)\n\t\t}\n\n\t\tlet result: ConditionalApplyResult\n\t\ttry {\n\t\t\tresult = await storeApplyConditional({\n\t\t\t\ttarget: { collection: spec.collection, id: spec.id },\n\t\t\t\t...(spec.idempotencyKey ? { idempotencyKey: spec.idempotencyKey } : {}),\n\t\t\t\tadmit: (current) =>\n\t\t\t\t\tspec.if && Object.keys(spec.if).length > 0\n\t\t\t\t\t\t? evaluateRoutePredicate(current, spec.if)\n\t\t\t\t\t\t: true,\n\t\t\t\tbuildOperations: async (current, context) => {\n\t\t\t\t\tconst ops: Operation[] = []\n\t\t\t\t\tfor (let i = 0; i < mutations.length; i++) {\n\t\t\t\t\t\tconst mutation = mutations[i] as RouteMutation\n\t\t\t\t\t\t// The target update (index 0 when present) resolves its atomic ops\n\t\t\t\t\t\t// against the locked `current`; `also` mutations address distinct\n\t\t\t\t\t\t// records and read their own current state from the store. Every op\n\t\t\t\t\t\t// is stamped with the store-provided clock so the set sorts strictly\n\t\t\t\t\t\t// after the target's latest committed write.\n\t\t\t\t\t\tconst useLockedCurrent = i === 0 && hasTargetUpdate\n\t\t\t\t\t\tconst op = await buildRouteOperation(\n\t\t\t\t\t\t\tstore,\n\t\t\t\t\t\t\tmutation,\n\t\t\t\t\t\t\tuseLockedCurrent ? { record: current } : undefined,\n\t\t\t\t\t\t\tcontext.clock,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t// Validate scope inside the locked transaction. Throwing here rolls\n\t\t\t\t\t\t// the transaction back, so a violation in any mutation applies nothing.\n\t\t\t\t\t\tif (scope && !operationMatchesScopes(op, scope)) {\n\t\t\t\t\t\t\tthrow new RouteMutationError(\n\t\t\t\t\t\t\t\t'SCOPE_VIOLATION',\n\t\t\t\t\t\t\t\t`Mutation on \"${mutation.collection}\" is outside the provided scope.`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tops.push(op)\n\t\t\t\t\t}\n\t\t\t\t\treturn ops\n\t\t\t\t},\n\t\t\t})\n\t\t} catch (error) {\n\t\t\t// A malformed mutation or scope violation surfaced from inside the locked\n\t\t\t// transaction (which rolled back) becomes a structured rejection, not a 500.\n\t\t\tif (error instanceof RouteMutationError) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tcode: error.code,\n\t\t\t\t\tmessage: error.message,\n\t\t\t\t\tretriable: isRetriableRejection(error.code),\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\t// Predicate failed under the lock: nothing was applied.\n\t\tif (!result.admitted) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tcode: spec.reject?.code ?? 'CONDITION_NOT_MET',\n\t\t\t\tmessage:\n\t\t\t\t\tspec.reject?.message ??\n\t\t\t\t\t`Admission condition not met on \"${spec.collection}\" record \"${spec.id}\".`,\n\t\t\t\tretriable: false,\n\t\t\t}\n\t\t}\n\n\t\t// Idempotent hit: the set committed on an earlier attempt. Return the anchor's\n\t\t// committed state without re-applying (so counter increments run at most once).\n\t\tif (result.idempotent) {\n\t\t\tconst records: (MaterializedRecord | null)[] = spec.idempotencyKey\n\t\t\t\t? [await store.findRecord(spec.idempotencyKey.collection, spec.idempotencyKey.id)]\n\t\t\t\t: []\n\t\t\treturn { ok: true, idempotent: true, operations: [], records }\n\t\t}\n\n\t\t// Admitted and committed. Fan the operations out to connected clients (each\n\t\t// session re-applies its own scope filter), then read back each record.\n\t\tserver.relayServerOperations(result.applied)\n\t\tconst records: (MaterializedRecord | null)[] = []\n\t\tfor (const op of result.applied) {\n\t\t\trecords.push(await store.findRecord(op.collection, op.recordId))\n\t\t}\n\t\treturn { ok: true, idempotent: false, operations: result.applied, records }\n\t}\n\n\treturn {\n\t\tapply(mutation, options): Promise<RouteApplyResult> {\n\t\t\treturn serialize(() => rawApply(mutation, options?.scope))\n\t\t},\n\n\t\tapplyConditional(spec, options): Promise<RouteConditionalResult> {\n\t\t\t// Prefer the store's cross-instance conditional apply when available (the\n\t\t\t// Postgres store): it serializes the admission on the target across every\n\t\t\t// server instance via an advisory lock, so a cap check is race-free even\n\t\t\t// under concurrent admissions on different instances. Stores without it\n\t\t\t// (single-process SQLite / in-memory) use the per-instance serialized path\n\t\t\t// below, which is correct because there is only one instance.\n\t\t\tconst storeApplyConditional = store.applyConditional\n\t\t\tif (storeApplyConditional) {\n\t\t\t\treturn runConditionalViaStore(storeApplyConditional.bind(store), spec, options)\n\t\t\t}\n\t\t\treturn serialize(async () => {\n\t\t\t\t// Idempotency: if the anchor record already exists, this set was\n\t\t\t\t// committed by an earlier attempt. Return the prior outcome without\n\t\t\t\t// re-applying (so counter increments run at most once).\n\t\t\t\tif (spec.idempotencyKey) {\n\t\t\t\t\tconst existing = await store.findRecord(\n\t\t\t\t\t\tspec.idempotencyKey.collection,\n\t\t\t\t\t\tspec.idempotencyKey.id,\n\t\t\t\t\t)\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\treturn { ok: true, idempotent: true, operations: [], records: [existing] }\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Admission predicate against the target's current materialized state.\n\t\t\t\tif (spec.if && Object.keys(spec.if).length > 0) {\n\t\t\t\t\tconst target = await store.findRecord(spec.collection, spec.id)\n\t\t\t\t\tif (!evaluateRoutePredicate(target, spec.if)) {\n\t\t\t\t\t\tconst code = spec.reject?.code ?? 'CONDITION_NOT_MET'\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tcode,\n\t\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\tspec.reject?.message ??\n\t\t\t\t\t\t\t\t`Admission condition not met on \"${spec.collection}\" record \"${spec.id}\".`,\n\t\t\t\t\t\t\tretriable: false,\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Build the atomic set: the target update (when given) then every\n\t\t\t\t// `also` mutation. Mutations in one set should address distinct records;\n\t\t\t\t// a mutation's previous-value capture reads the pre-set state.\n\t\t\t\tconst mutations: RouteMutation[] = []\n\t\t\t\tif (spec.update !== undefined && spec.update !== null) {\n\t\t\t\t\tmutations.push({\n\t\t\t\t\t\tcollection: spec.collection,\n\t\t\t\t\t\ttype: 'update',\n\t\t\t\t\t\trecordId: spec.id,\n\t\t\t\t\t\tdata: spec.update,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tif (spec.also) {\n\t\t\t\t\tmutations.push(...spec.also)\n\t\t\t\t}\n\n\t\t\t\t// Pre-build and scope-validate the WHOLE set before committing any of\n\t\t\t\t// it, so a validation failure applies nothing.\n\t\t\t\tconst prepared: { op: Operation; collection: string }[] = []\n\t\t\t\tfor (const mutation of mutations) {\n\t\t\t\t\tconst p = await prepareMutation(mutation, options?.scope)\n\t\t\t\t\tif (!p.ok) {\n\t\t\t\t\t\treturn p.rejection\n\t\t\t\t\t}\n\t\t\t\t\tprepared.push({ op: p.op, collection: mutation.collection })\n\t\t\t\t}\n\n\t\t\t\tconst operations: Operation[] = []\n\t\t\t\tconst records: (MaterializedRecord | null)[] = []\n\t\t\t\tfor (const { op, collection } of prepared) {\n\t\t\t\t\tconst result = await commitOperation(op, collection)\n\t\t\t\t\tif (!result.ok) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tcode: result.code,\n\t\t\t\t\t\t\tmessage: result.message,\n\t\t\t\t\t\t\tretriable: result.retriable,\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\toperations.push(result.operation)\n\t\t\t\t\trecords.push(result.record)\n\t\t\t\t}\n\n\t\t\t\treturn { ok: true, idempotent: false, operations, records }\n\t\t\t})\n\t\t},\n\n\t\tasync query(collection, options): Promise<MaterializedRecord[]> {\n\t\t\tconst { scope, ...queryOptions } = options ?? {}\n\t\t\tconst records = await store.queryCollection(collection, queryOptions)\n\t\t\tif (!scope) {\n\t\t\t\treturn records\n\t\t\t}\n\t\t\treturn records.filter((record) => recordMatchesScope(collection, record, scope))\n\t\t},\n\n\t\tasync findById(collection, id, options): Promise<MaterializedRecord | null> {\n\t\t\tconst record = await store.findRecord(collection, id)\n\t\t\tif (!record) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (options?.scope && !recordMatchesScope(collection, record, options.scope)) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn record\n\t\t},\n\t}\n}\n","/**\n * Predicate evaluation for conditional route mutations.\n *\n * A predicate is a small, total comparison language evaluated against the current\n * materialized state of a single record at admission time. It is deliberately not\n * a general query language: it exists so a server route can express an atomic\n * admission guard (for example \"accept this response only while the form is still\n * below its cap\") without pulling a query DSL into the write path.\n */\n\n/**\n * Comparison operators applied to one field. All operators present on a field\n * must hold for the field to match. Numeric operators (`$lt`, `$lte`, `$gt`,\n * `$gte`) require the record value to be a number; a non-numeric value fails.\n */\nexport interface RoutePredicateOperators {\n\t$eq?: unknown\n\t$ne?: unknown\n\t$lt?: number\n\t$lte?: number\n\t$gt?: number\n\t$gte?: number\n\t$in?: readonly unknown[]\n}\n\n/** A predicate: every listed field must satisfy all of its operators. */\nexport type RoutePredicate = Record<string, RoutePredicateOperators>\n\nfunction evaluateField(actual: unknown, operators: RoutePredicateOperators): boolean {\n\tif ('$eq' in operators && !Object.is(actual, operators.$eq)) {\n\t\treturn false\n\t}\n\tif ('$ne' in operators && Object.is(actual, operators.$ne)) {\n\t\treturn false\n\t}\n\tif (\n\t\toperators.$in !== undefined &&\n\t\t!operators.$in.some((candidate) => Object.is(actual, candidate))\n\t) {\n\t\treturn false\n\t}\n\n\tconst numericChecks: [keyof RoutePredicateOperators, (a: number, b: number) => boolean][] = [\n\t\t['$lt', (a, b) => a < b],\n\t\t['$lte', (a, b) => a <= b],\n\t\t['$gt', (a, b) => a > b],\n\t\t['$gte', (a, b) => a >= b],\n\t]\n\tfor (const [operator, compare] of numericChecks) {\n\t\tconst bound = operators[operator]\n\t\tif (bound === undefined) {\n\t\t\tcontinue\n\t\t}\n\t\tif (typeof actual !== 'number' || typeof bound !== 'number') {\n\t\t\treturn false\n\t\t}\n\t\tif (!compare(actual, bound)) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n/**\n * Evaluates a predicate against a record. A `null` record (the target does not\n * exist) satisfies only an empty predicate; any field condition fails, since a\n * missing record cannot meet a comparison.\n *\n * @param record - The current materialized record, or `null` if absent\n * @param predicate - The field conditions that must all hold\n * @returns `true` when every field condition is satisfied\n */\nexport function evaluateRoutePredicate(\n\trecord: Record<string, unknown> | null,\n\tpredicate: RoutePredicate,\n): boolean {\n\tconst fields = Object.keys(predicate)\n\tif (fields.length === 0) {\n\t\treturn true\n\t}\n\tif (record === null) {\n\t\treturn false\n\t}\n\tfor (const field of fields) {\n\t\tconst operators = predicate[field]\n\t\tif (operators && !evaluateField(record[field], operators)) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n","import type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Options for creating a TokenAuthProvider.\n */\nexport interface TokenAuthProviderOptions {\n\t/**\n\t * Validate a token and return an AuthContext if valid, or null if rejected.\n\t * This is where you implement your auth logic (JWT verification, database lookup, etc.).\n\t */\n\tvalidate: (token: string) => Promise<AuthContext | null>\n}\n\n/**\n * Token-based auth provider that delegates validation to a user-provided function.\n *\n * @example\n * ```typescript\n * const auth = new TokenAuthProvider({\n * validate: async (token) => {\n * const user = await verifyJWT(token)\n * return user ? { userId: user.id } : null\n * }\n * })\n * ```\n */\nexport class TokenAuthProvider implements AuthProvider {\n\tprivate readonly validate: (token: string) => Promise<AuthContext | null>\n\n\tconstructor(options: TokenAuthProviderOptions) {\n\t\tthis.validate = options.validate\n\t}\n\n\tasync authenticate(token: string): Promise<AuthContext | null> {\n\t\treturn this.validate(token)\n\t}\n}\n","import type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Validates a Kora auth JWT and returns identity claims.\n * This interface matches the signature of TokenManager.validateToken()\n * from @korajs/auth without requiring a direct import.\n */\ninterface TokenValidator {\n\tvalidateToken(token: string): {\n\t\tsub: string\n\t\tdev: string\n\t\ttype: string\n\t} | null\n\tvalidateTokenWithRevocation?(token: string): Promise<{\n\t\tsub: string\n\t\tdev: string\n\t\ttype: string\n\t} | null>\n}\n\n/**\n * Looks up a user by ID. Returns null if the user doesn't exist.\n * This interface matches InMemoryUserStore.findById() from @korajs/auth\n * without requiring a direct import.\n */\ninterface UserLookup {\n\tfindById(userId: string): Promise<{\n\t\tid: string\n\t\temail: string\n\t\tname: string\n\t} | null>\n}\n\n/**\n * Optional device touch callback for updating last-seen timestamps.\n */\ninterface DeviceToucher {\n\ttouchDevice(deviceId: string): Promise<void>\n}\n\n/**\n * Configuration for creating a KoraAuthProvider.\n */\nexport interface KoraAuthProviderOptions {\n\t/**\n\t * Token validator that verifies JWT signatures and returns claims.\n\t * Typically a `TokenManager` instance from `@korajs/auth/server`.\n\t * If the validator also implements `validateTokenWithRevocation`, the sync\n\t * server uses it so signed-out sessions and revoked devices are rejected.\n\t */\n\ttokenValidator: TokenValidator\n\n\t/**\n\t * User lookup for verifying the user still exists.\n\t * Typically an `InMemoryUserStore` instance from `@korajs/auth/server`.\n\t */\n\tuserLookup: UserLookup\n\n\t/**\n\t * Optional device tracker for updating last-seen timestamps.\n\t * Typically the same `InMemoryUserStore` if it implements `touchDevice`.\n\t */\n\tdeviceTracker?: DeviceToucher\n\n\t/**\n\t * Optional scope resolver. Called with the user ID to determine\n\t * which collections/records the user can sync.\n\t */\n\tresolveScopes?: (userId: string) => Promise<Record<string, Record<string, unknown>>>\n}\n\n/**\n * Auth provider that bridges `@korajs/auth` token management with the\n * sync server's authentication layer.\n *\n * Validates access tokens issued by `@korajs/auth`'s `TokenManager`,\n * verifies the user still exists, and optionally computes per-user\n * sync scopes. This is the recommended way to connect @korajs/auth\n * to @korajs/server.\n *\n * @example\n * ```typescript\n * import { TokenManager, InMemoryUserStore } from '@korajs/auth/server'\n * import { KoraAuthProvider, KoraSyncServer } from '@korajs/server'\n *\n * const tokenManager = new TokenManager({ secret: 'my-secret' })\n * const userStore = new InMemoryUserStore()\n *\n * const auth = new KoraAuthProvider({\n * tokenValidator: tokenManager,\n * userLookup: userStore,\n * deviceTracker: userStore,\n * resolveScopes: async (userId) => ({\n * forms: { userId },\n * responses: { formOwnerId: userId },\n * }),\n * })\n *\n * const server = new KoraSyncServer({ store, auth })\n * ```\n */\nexport class KoraAuthProvider implements AuthProvider {\n\tprivate readonly tokenValidator: TokenValidator\n\tprivate readonly userLookup: UserLookup\n\tprivate readonly deviceTracker: DeviceToucher | undefined\n\tprivate readonly resolveScopes:\n\t\t| ((userId: string) => Promise<Record<string, Record<string, unknown>>>)\n\t\t| undefined\n\n\tconstructor(options: KoraAuthProviderOptions) {\n\t\tthis.tokenValidator = options.tokenValidator\n\t\tthis.userLookup = options.userLookup\n\t\tthis.deviceTracker = options.deviceTracker\n\t\tthis.resolveScopes = options.resolveScopes\n\t}\n\n\tasync authenticate(token: string): Promise<AuthContext | null> {\n\t\t// Validate the JWT signature and expiration\n\t\tconst payload = this.tokenValidator.validateTokenWithRevocation\n\t\t\t? await this.tokenValidator.validateTokenWithRevocation(token)\n\t\t\t: this.tokenValidator.validateToken(token)\n\t\tif (payload === null) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Only accept access tokens for sync authentication\n\t\tif (payload.type !== 'access') {\n\t\t\treturn null\n\t\t}\n\n\t\t// Verify the user still exists (may have been deleted since token was issued)\n\t\tconst user = await this.userLookup.findById(payload.sub)\n\t\tif (user === null) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Update device last-seen timestamp\n\t\tif (this.deviceTracker) {\n\t\t\tawait this.deviceTracker.touchDevice(payload.dev)\n\t\t}\n\n\t\t// Compute sync scopes if a resolver is configured\n\t\tconst scopes = this.resolveScopes ? await this.resolveScopes(payload.sub) : undefined\n\n\t\treturn {\n\t\t\tuserId: payload.sub,\n\t\t\tscopes,\n\t\t\tmetadata: {\n\t\t\t\tdeviceId: payload.dev,\n\t\t\t\temail: user.email,\n\t\t\t\tname: user.name,\n\t\t\t},\n\t\t}\n\t}\n}\n","import type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Configuration for creating a MixedAuthProvider.\n */\nexport interface MixedAuthProviderOptions {\n\t/**\n\t * Primary auth provider that validates tokens from authenticated users.\n\t * Typically a `KoraAuthProvider`, `TokenAuthProvider`, or the result of\n\t * `authRoutes.toSyncAuthProvider()`.\n\t */\n\tprimary: AuthProvider\n\n\t/**\n\t * Scopes to apply to anonymous connections.\n\t * Each key is a collection name; the value is a filter object\n\t * (use `{}` for unrestricted access to that collection).\n\t *\n\t * @example\n\t * ```typescript\n\t * // Anonymous users can only sync the 'responses' collection\n\t * anonymousScopes: { responses: {} }\n\t *\n\t * // Anonymous users can read published forms\n\t * anonymousScopes: { forms: { status: 'published' } }\n\t * ```\n\t */\n\tanonymousScopes: Record<string, Record<string, unknown>>\n\n\t/**\n\t * Prefix for generated anonymous user IDs.\n\t * A unique suffix is appended to each connection.\n\t * @default 'anon'\n\t */\n\tanonymousPrefix?: string\n}\n\n/**\n * Auth provider that supports both authenticated and anonymous connections.\n *\n * When a client connects with a valid token, the primary auth provider\n * handles authentication normally. When a client connects without a token\n * (or with an invalid one), the connection is accepted as anonymous with\n * restricted sync scopes.\n *\n * This is the recommended pattern for apps that need public data access\n * alongside authenticated users — for example, a form builder where\n * authenticated users create forms but anyone can submit responses.\n *\n * @example\n * ```typescript\n * import { MixedAuthProvider, KoraAuthProvider } from '@korajs/server'\n *\n * const auth = new MixedAuthProvider({\n * primary: authRoutes.toSyncAuthProvider(),\n * anonymousScopes: {\n * // Anonymous users can only sync the 'responses' collection\n * responses: {},\n * },\n * })\n *\n * const server = new KoraSyncServer({ store, auth })\n * ```\n *\n * @example\n * ```typescript\n * // On the client, return an empty token for unauthenticated users:\n * const app = createApp({\n * schema,\n * sync: {\n * url: 'wss://my-server.com/kora',\n * auth: async () => ({\n * token: (await authClient.getAccessToken()) ?? '',\n * }),\n * },\n * })\n * ```\n */\nexport class MixedAuthProvider implements AuthProvider {\n\tprivate readonly primary: AuthProvider\n\tprivate readonly anonymousScopes: Record<string, Record<string, unknown>>\n\tprivate readonly anonymousPrefix: string\n\tprivate anonymousCounter = 0\n\n\tconstructor(options: MixedAuthProviderOptions) {\n\t\tthis.primary = options.primary\n\t\tthis.anonymousScopes = options.anonymousScopes\n\t\tthis.anonymousPrefix = options.anonymousPrefix ?? 'anon'\n\t}\n\n\tasync authenticate(token: string): Promise<AuthContext> {\n\t\t// Try authenticated path first when a token is provided\n\t\tif (token) {\n\t\t\tconst ctx = await this.primary.authenticate(token)\n\t\t\tif (ctx) return ctx\n\t\t}\n\n\t\t// Fall back to scoped anonymous access\n\t\tthis.anonymousCounter++\n\t\treturn {\n\t\t\tuserId: `${this.anonymousPrefix}-${Date.now()}-${this.anonymousCounter}`,\n\t\t\tscopes: this.anonymousScopes,\n\t\t}\n\t}\n}\n","import type { KoraSyncServerConfig } from '../types'\nimport { KoraSyncServer } from './kora-sync-server'\n\n/**\n * Factory function to create a KoraSyncServer.\n *\n * @param config - Server configuration\n * @returns A new KoraSyncServer instance\n *\n * @example\n * ```typescript\n * const server = createKoraServer({\n * store: new MemoryServerStore(),\n * port: 3000,\n * })\n * await server.start()\n * ```\n */\nexport function createKoraServer(config: KoraSyncServerConfig): KoraSyncServer {\n\treturn new KoraSyncServer(config)\n}\n","import type { BlobRef } from '@korajs/core'\nimport type { ServerStore } from '../store/server-store'\nimport { WsServerTransport } from '../transport/ws-server-transport'\nimport type { KoraSyncServerConfig } from '../types'\nimport { KoraSyncServer } from './kora-sync-server'\nimport type { ProductionHttpRouteContext } from './route-context'\n\n/**\n * Configuration for the production server that serves both\n * static files and WebSocket sync on a single port.\n */\nexport interface ProductionServerConfig {\n\t/** Server-side operation store */\n\tstore: ServerStore\n\t/** Port to listen on. Defaults to 3001 or process.env.PORT. */\n\tport?: number\n\t/** Directory containing built static files. Defaults to './dist'. */\n\tstaticDir?: string\n\t/** WebSocket sync path. Defaults to '/kora-sync'. */\n\tsyncPath?: string\n\t/** Additional KoraSyncServer options */\n\tsyncOptions?: Omit<KoraSyncServerConfig, 'store' | 'port' | 'host' | 'path'>\n\t/**\n\t * Cross-Origin-Embedder-Policy for static and route responses. Defaults to\n\t * `credentialless`, which keeps third-party embeds usable while allowing\n\t * capable browsers to enable cross-origin isolation. Use `require-corp` only\n\t * when every embedded resource explicitly opts in with CORP/CORS headers.\n\t */\n\tcrossOriginEmbedderPolicy?: 'credentialless' | 'require-corp' | 'unsafe-none'\n\t/**\n\t * Optional HTTP route handlers mounted before static file serving.\n\t *\n\t * This is intentionally framework-agnostic so packages such as\n\t * `@korajs/auth` can plug into the production server without requiring\n\t * Express, Hono, or another HTTP framework.\n\t */\n\thttpRoutes?: ProductionHttpRoute[]\n\t/**\n\t * Optional token protection for operational endpoints.\n\t *\n\t * When a token is omitted, the matching endpoint group remains public for\n\t * backward compatibility. Production apps should set at least adminToken and\n\t * backupToken.\n\t */\n\toperationalAuth?: ProductionOperationalAuth\n}\n\nexport interface ProductionOperationalAuth {\n\t/** Protects /__kora, /__kora/status, and /__kora/events. */\n\tadminToken?: string\n\t/** Protects /__kora/metrics. Falls back to adminToken when omitted. */\n\tmetricsToken?: string\n\t/** Protects /__kora/backup/*. Falls back to adminToken when omitted. */\n\tbackupToken?: string\n}\n\nexport interface ProductionHttpRouteRequest {\n\tmethod: string\n\tpath: string\n\tbody?: unknown\n\theaders?: Record<string, string | string[] | undefined>\n\tquery?: Record<string, string | string[] | undefined>\n\tip?: string\n\t/**\n\t * Scoped, validated data-plane access. Use `kora.apply()` to mutate through\n\t * the same pipeline as sync (constraints, referential integrity, fan-out) and\n\t * `kora.query()` / `kora.findById()` to read materialized state, instead of\n\t * writing to the store directly and bypassing those guarantees.\n\t */\n\tkora: ProductionHttpRouteContext\n}\n\nexport interface ProductionHttpRouteResponse {\n\tstatus: number\n\tbody?: unknown\n\theaders?: Record<string, string>\n}\n\nexport interface ProductionHttpRoute {\n\t/** URL path prefix, for example `/auth`. */\n\tpath: string\n\thandle(request: ProductionHttpRouteRequest): Promise<ProductionHttpRouteResponse>\n}\n\n/**\n * A production server handle returned by createProductionServer.\n */\nexport interface ProductionServer {\n\t/** Start listening. Returns the URL the server is available at. */\n\tstart(): Promise<string>\n\t/** Stop the server gracefully. */\n\tstop(): Promise<void>\n\t/**\n\t * Trusted, scoped data-plane access for server-side callers that have no HTTP\n\t * request — background jobs, scheduled tasks, seeding scripts.\n\t *\n\t * `kora.apply()` runs the mutation through the exact same validated pipeline as\n\t * sync (Tier 2 constraints, referential integrity, materialization, and fan-out\n\t * to connected clients), and `kora.query()` / `kora.findById()` read\n\t * materialized state. This is the same context handed to custom HTTP routes as\n\t * `request.kora`, so a job and a request share one code path and one set of\n\t * guarantees instead of the job writing to the store directly and silently\n\t * bypassing validation.\n\t */\n\tkora: ProductionHttpRouteContext\n\t/**\n\t * Every blob reference still reachable from a live record across all\n\t * collections that declare a `blob` field. This is the live set for\n\t * garbage-collecting the server's central blob store: pass it to\n\t * `collectBlobGarbage(blobStore, refs)` from `@korajs/store` on a schedule to\n\t * reclaim bytes no record points at any more.\n\t *\n\t * @returns Every live blob reference the server can currently see.\n\t */\n\tgetLiveBlobRefs(): Promise<BlobRef[]>\n}\n\n// MIME types for static file serving\nconst MIME_TYPES: Record<string, string> = {\n\t'.html': 'text/html',\n\t'.js': 'text/javascript',\n\t'.css': 'text/css',\n\t'.json': 'application/json',\n\t'.png': 'image/png',\n\t'.jpg': 'image/jpeg',\n\t'.svg': 'image/svg+xml',\n\t'.ico': 'image/x-icon',\n\t'.wasm': 'application/wasm',\n\t'.woff': 'font/woff',\n\t'.woff2': 'font/woff2',\n\t'.map': 'application/json',\n}\n\n/**\n * Creates a production server that serves both static files and WebSocket sync\n * on a single port, plus built-in dashboard and observability endpoints.\n *\n * @param config - Production server configuration\n * @returns A ProductionServer instance\n *\n * @example\n * ```typescript\n * const server = createProductionServer({\n * store: createSqliteServerStore({ filename: './kora-server.db' }),\n * })\n * const url = await server.start()\n * ```\n */\nexport function createProductionServer(config: ProductionServerConfig): ProductionServer {\n\tconst port = config.port ?? (Number(process.env.PORT) || 3001)\n\tconst staticDir = config.staticDir ?? './dist'\n\tconst syncPath = config.syncPath ?? '/kora-sync'\n\tconst crossOriginEmbedderPolicy = config.crossOriginEmbedderPolicy ?? 'credentialless'\n\n\tconst syncServer = new KoraSyncServer({\n\t\tstore: config.store,\n\t\tenableDashboard: true,\n\t\t...config.syncOptions,\n\t})\n\n\t// Scoped, validated data-plane access handed to every custom HTTP route as\n\t// `request.kora`, exposed on the handle as `server.kora`, and used by the\n\t// operation validator. One shared context (it holds no per-request state).\n\tconst routeContext = syncServer.getKoraContext()\n\n\tlet httpServer: import('node:http').Server | null = null\n\n\tfunction getOperationalToken(kind: 'admin' | 'metrics' | 'backup'): string | undefined {\n\t\tconst auth = config.operationalAuth\n\t\tif (!auth) return undefined\n\t\tif (kind === 'metrics') return auth.metricsToken || auth.adminToken\n\t\tif (kind === 'backup') return auth.backupToken || auth.adminToken\n\t\treturn auth.adminToken\n\t}\n\n\tfunction extractRequestToken(req: import('node:http').IncomingMessage): string | null {\n\t\tconst authorization = req.headers.authorization\n\t\tif (authorization?.startsWith('Bearer ')) {\n\t\t\treturn authorization.slice('Bearer '.length).trim()\n\t\t}\n\n\t\tconst headerNames = ['x-kora-admin-token', 'x-kora-metrics-token', 'x-kora-backup-token']\n\t\tfor (const name of headerNames) {\n\t\t\tconst value = req.headers[name]\n\t\t\tif (typeof value === 'string' && value.length > 0) return value\n\t\t\tif (Array.isArray(value) && typeof value[0] === 'string' && value[0].length > 0) {\n\t\t\t\treturn value[0]\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t}\n\n\tfunction isOperationalRequestAllowed(\n\t\treq: import('node:http').IncomingMessage,\n\t\tkind: 'admin' | 'metrics' | 'backup',\n\t): boolean {\n\t\tconst expected = getOperationalToken(kind)\n\t\tif (!expected) return true\n\t\treturn extractRequestToken(req) === expected\n\t}\n\n\tfunction rejectUnauthorized(res: import('node:http').ServerResponse): void {\n\t\tres.writeHead(401, {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t'WWW-Authenticate': 'Bearer realm=\"kora\"',\n\t\t})\n\t\tres.end(JSON.stringify({ error: 'Unauthorized' }))\n\t}\n\n\t/**\n\t * Format the metrics snapshot as Prometheus exposition format.\n\t * Zero-dependency — no prom-client needed.\n\t */\n\tfunction formatPrometheusMetrics(): string {\n\t\tconst status = syncServer.getMetricsCollector().getSnapshot(0)\n\t\tconst lines: string[] = [\n\t\t\t'# HELP kora_connected_clients Current number of connected clients',\n\t\t\t'# TYPE kora_connected_clients gauge',\n\t\t\t`kora_connected_clients ${status.connectedClients}`,\n\t\t\t'',\n\t\t\t'# HELP kora_peak_connections Peak number of simultaneous connections since server start',\n\t\t\t'# TYPE kora_peak_connections gauge',\n\t\t\t`kora_peak_connections ${status.peakConnections}`,\n\t\t\t'',\n\t\t\t'# HELP kora_connections_total Total number of connections handled since server start',\n\t\t\t'# TYPE kora_connections_total counter',\n\t\t\t`kora_connections_total ${status.connectionsTotal}`,\n\t\t\t'',\n\t\t\t'# HELP kora_operations_received_total Total operations received from clients',\n\t\t\t'# TYPE kora_operations_received_total counter',\n\t\t\t`kora_operations_received_total ${status.operationsReceived}`,\n\t\t\t'',\n\t\t\t'# HELP kora_operations_sent_total Total operations sent to clients',\n\t\t\t'# TYPE kora_operations_sent_total counter',\n\t\t\t`kora_operations_sent_total ${status.operationsSent}`,\n\t\t\t'',\n\t\t\t'# HELP kora_bytes_received_total Total bytes received from clients',\n\t\t\t'# TYPE kora_bytes_received_total counter',\n\t\t\t`kora_bytes_received_total ${status.bytesReceived}`,\n\t\t\t'',\n\t\t\t'# HELP kora_bytes_sent_total Total bytes sent to clients',\n\t\t\t'# TYPE kora_bytes_sent_total counter',\n\t\t\t`kora_bytes_sent_total ${status.bytesSent}`,\n\t\t\t'',\n\t\t\t'# HELP kora_errors_total Total errors since server start',\n\t\t\t'# TYPE kora_errors_total counter',\n\t\t\t`kora_errors_total ${status.errorCount}`,\n\t\t\t'',\n\t\t\t'# HELP kora_uptime_seconds Server uptime in seconds',\n\t\t\t'# TYPE kora_uptime_seconds gauge',\n\t\t\t`kora_uptime_seconds ${Math.floor(status.uptime / 1000)}`,\n\t\t\t'',\n\t\t\t'# HELP kora_schema_version Schema version the server expects',\n\t\t\t'# TYPE kora_schema_version gauge',\n\t\t\t`kora_schema_version ${status.schemaVersion}`,\n\t\t\t'',\n\t\t]\n\t\treturn lines.join('\\n')\n\t}\n\n\tfunction readBodyBuffer(req: import('node:http').IncomingMessage): Promise<Buffer> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst chunks: Buffer[] = []\n\t\t\treq.on('data', (chunk: Buffer) => chunks.push(chunk))\n\t\t\treq.on('end', () => resolve(Buffer.concat(chunks)))\n\t\t\t// A raw http.IncomingMessage starts paused: attaching 'data'/'end'\n\t\t\t// listeners alone does not put it in flowing mode. Without an\n\t\t\t// explicit resume(), 'data' never fires, 'end' fires immediately with\n\t\t\t// zero chunks, and every POST body silently reads back as empty —\n\t\t\t// which is exactly what broke httpRoutes handlers (including\n\t\t\t// @korajs/auth's signup/signin) reading `req.body`. Guard with\n\t\t\t// `readableFlowing` so this stays a no-op if the stream is already\n\t\t\t// flowing (e.g. a future caller that reads it differently).\n\t\t\tif (!req.readableFlowing) {\n\t\t\t\treq.resume()\n\t\t\t}\n\t\t\t// If the client disconnects mid-upload, `end` never fires; resolve\n\t\t\t// with whatever arrived instead of leaving the request hung forever.\n\t\t\treq.on('error', () => resolve(Buffer.concat(chunks)))\n\t\t})\n\t}\n\n\tasync function readJsonBody(req: import('node:http').IncomingMessage): Promise<unknown> {\n\t\tconst buffer = await readBodyBuffer(req)\n\t\tif (buffer.byteLength === 0) return undefined\n\t\ttry {\n\t\t\treturn JSON.parse(buffer.toString('utf8')) as unknown\n\t\t} catch {\n\t\t\treturn undefined\n\t\t}\n\t}\n\n\tfunction matchesRoutePrefix(pathname: string, prefix: string): boolean {\n\t\tconst normalizedPrefix = normalizeRoutePath(prefix)\n\t\treturn pathname === normalizedPrefix || pathname.startsWith(`${normalizedPrefix}/`)\n\t}\n\n\tfunction normalizeRoutePath(path: string): string {\n\t\tconst prefixed = path.startsWith('/') ? path : `/${path}`\n\t\treturn prefixed.length > 1 ? prefixed.replace(/\\/+$/, '') : prefixed\n\t}\n\n\tfunction getClientIp(req: import('node:http').IncomingMessage): string | undefined {\n\t\tconst forwarded = req.headers['x-forwarded-for']\n\t\tif (typeof forwarded === 'string' && forwarded.length > 0) {\n\t\t\treturn forwarded.split(',')[0]?.trim()\n\t\t}\n\t\treturn req.socket.remoteAddress\n\t}\n\n\tfunction getQuery(url: URL): Record<string, string | string[] | undefined> {\n\t\tconst query: Record<string, string | string[] | undefined> = {}\n\t\tfor (const [key, value] of url.searchParams) {\n\t\t\tconst existing = query[key]\n\t\t\tif (existing === undefined) {\n\t\t\t\tquery[key] = value\n\t\t\t} else if (Array.isArray(existing)) {\n\t\t\t\texisting.push(value)\n\t\t\t} else {\n\t\t\t\tquery[key] = [existing, value]\n\t\t\t}\n\t\t}\n\t\treturn query\n\t}\n\n\tfunction writeJsonResponse(\n\t\tres: import('node:http').ServerResponse,\n\t\tresult: ProductionHttpRouteResponse,\n\t): void {\n\t\tconst headers = {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t...(result.headers ?? {}),\n\t\t}\n\t\tres.writeHead(result.status, headers)\n\t\tres.end(JSON.stringify(result.body ?? null))\n\t}\n\n\treturn {\n\t\tkora: routeContext,\n\n\t\tgetLiveBlobRefs(): Promise<BlobRef[]> {\n\t\t\treturn syncServer.getLiveBlobRefs()\n\t\t},\n\n\t\tasync start(): Promise<string> {\n\t\t\tconst { createServer } = await import('node:http')\n\t\t\tconst { createReadStream, existsSync, statSync } = await import('node:fs')\n\t\t\tconst { extname, join, resolve } = await import('node:path')\n\t\t\tconst { WebSocketServer } = await import('ws')\n\n\t\t\tconst distDir = resolve(staticDir)\n\n\t\t\thttpServer = createServer(async (req, res) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait handleRequest(req, res)\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// http.createServer never awaits its request listener, so a\n\t\t\t\t\t// callback that rejects becomes an unhandled promise rejection\n\t\t\t\t\t// process-wide, and Node's default `--unhandled-rejections=throw`\n\t\t\t\t\t// crashes the entire server. One bad request (malformed body,\n\t\t\t\t\t// a buggy custom httpRoute handler, anything unexpected) must\n\t\t\t\t\t// only fail that one response, never take the whole process\n\t\t\t\t\t// down with it.\n\t\t\t\t\tconsole.error('[kora] Unhandled error in HTTP request handler:', error)\n\t\t\t\t\tif (!res.headersSent) {\n\t\t\t\t\t\tres.writeHead(500, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify({ error: 'Internal server error' }))\n\t\t\t\t\t} else if (!res.writableEnded) {\n\t\t\t\t\t\tres.end()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tasync function handleRequest(\n\t\t\t\treq: import('node:http').IncomingMessage,\n\t\t\t\tres: import('node:http').ServerResponse,\n\t\t\t): Promise<void> {\n\t\t\t\t// COOP/COEP headers required for SharedArrayBuffer (OPFS persistence)\n\t\t\t\tres.setHeader('Cross-Origin-Opener-Policy', 'same-origin')\n\t\t\t\tres.setHeader('Cross-Origin-Embedder-Policy', crossOriginEmbedderPolicy)\n\n\t\t\t\tconst url = new URL(req.url || '/', `http://${req.headers.host}`)\n\n\t\t\t\t// ── Health check ──────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/health') {\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'application/json' })\n\t\t\t\t\tres.end(\n\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\tstatus: 'ok',\n\t\t\t\t\t\t\tversion: status.version,\n\t\t\t\t\t\t\tuptime: status.uptime,\n\t\t\t\t\t\t\tconnectedClients: status.connectedClients,\n\t\t\t\t\t\t\ttotalOperations: status.totalOperations,\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Status endpoint ───────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/status') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'admin')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'application/json' })\n\t\t\t\t\tres.end(JSON.stringify(status, null, 2))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Prometheus metrics endpoint ───────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/metrics') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'metrics')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'text/plain; version=0.0.4' })\n\t\t\t\t\tres.end(formatPrometheusMetrics())\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Server-Sent Events endpoint ───────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/events') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'admin')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tres.writeHead(200, {\n\t\t\t\t\t\t'Content-Type': 'text/event-stream',\n\t\t\t\t\t\t'Cache-Control': 'no-cache',\n\t\t\t\t\t\tConnection: 'keep-alive',\n\t\t\t\t\t\t'X-Accel-Buffering': 'no',\n\t\t\t\t\t})\n\n\t\t\t\t\t// Send initial status event\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.write(`event: status\\ndata: ${JSON.stringify(status)}\\n\\n`)\n\n\t\t\t\t\t// Poll metrics periodically and push as SSE events\n\t\t\t\t\tconst interval = setInterval(async () => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst s = await syncServer.getStatus()\n\t\t\t\t\t\t\tres.write(`event: status\\ndata: ${JSON.stringify(s)}\\n\\n`)\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Connection may have closed\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 2000)\n\n\t\t\t\t\t// Clean up on connection close\n\t\t\t\t\treq.on('close', () => {\n\t\t\t\t\t\tclearInterval(interval)\n\t\t\t\t\t})\n\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Dashboard HTML ────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora' || url.pathname === '/__kora/') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'admin')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })\n\t\t\t\t\tres.end(renderDashboardHtml(status))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Backup export ─────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/backup/export' && req.method === 'POST') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'backup')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst backup = await config.store.exportBackup()\n\t\t\t\t\t\tres.writeHead(200, {\n\t\t\t\t\t\t\t'Content-Type': 'application/octet-stream',\n\t\t\t\t\t\t\t'Content-Disposition': `attachment; filename=\"kora-backup-${Date.now()}.kora\"`,\n\t\t\t\t\t\t\t'Content-Length': String(backup.byteLength),\n\t\t\t\t\t\t})\n\t\t\t\t\t\tres.end(Buffer.from(backup))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tres.writeHead(500, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify({ error: 'Backup failed', message: (error as Error).message }))\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Backup import ─────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/backup/import' && req.method === 'POST') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'backup')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst body = await readBodyBuffer(req)\n\t\t\t\t\t\tconst merge = url.searchParams.get('merge') === 'true'\n\t\t\t\t\t\tconst result = await config.store.importBackup(\n\t\t\t\t\t\t\tnew Uint8Array(body.buffer, body.byteOffset, body.byteLength),\n\t\t\t\t\t\t\tmerge,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tres.writeHead(result.success ? 200 : 400, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify(result))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tres.writeHead(500, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify({ error: 'Restore failed', message: (error as Error).message }))\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Custom HTTP routes (auth, webhooks, app APIs) ─────────────\n\t\t\t\tconst customRoute = config.httpRoutes?.find((route) =>\n\t\t\t\t\tmatchesRoutePrefix(url.pathname, route.path),\n\t\t\t\t)\n\t\t\t\tif (customRoute) {\n\t\t\t\t\tconst result = await customRoute.handle({\n\t\t\t\t\t\tmethod: req.method ?? 'GET',\n\t\t\t\t\t\tpath: url.pathname,\n\t\t\t\t\t\tbody: await readJsonBody(req),\n\t\t\t\t\t\theaders: req.headers,\n\t\t\t\t\t\tquery: getQuery(url),\n\t\t\t\t\t\tip: getClientIp(req),\n\t\t\t\t\t\tkora: routeContext,\n\t\t\t\t\t})\n\t\t\t\t\twriteJsonResponse(res, result)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Static file serving ───────────────────────────────────────\n\t\t\t\tlet filePath = join(distDir, url.pathname)\n\n\t\t\t\t// SPA fallback: serve index.html for non-file routes\n\t\t\t\tif (!extname(filePath)) {\n\t\t\t\t\tconst indexPath = join(filePath, 'index.html')\n\t\t\t\t\tif (existsSync(indexPath)) {\n\t\t\t\t\t\tfilePath = indexPath\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfilePath = join(distDir, 'index.html')\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!existsSync(filePath)) {\n\t\t\t\t\tfilePath = join(distDir, 'index.html')\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst stat = statSync(filePath)\n\t\t\t\t\tif (stat.isDirectory()) {\n\t\t\t\t\t\tfilePath = join(filePath, 'index.html')\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\tfilePath = join(distDir, 'index.html')\n\t\t\t\t}\n\n\t\t\t\tif (!existsSync(filePath)) {\n\t\t\t\t\tres.writeHead(404)\n\t\t\t\t\tres.end('Not Found')\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst ext = extname(filePath)\n\t\t\t\tconst contentType = MIME_TYPES[ext] || 'application/octet-stream'\n\t\t\t\tres.writeHead(200, { 'Content-Type': contentType })\n\t\t\t\tcreateReadStream(filePath).pipe(res)\n\t\t\t}\n\n\t\t\tconst wss = new WebSocketServer({ noServer: true })\n\n\t\t\thttpServer.on('upgrade', (req, socket, head) => {\n\t\t\t\tconst url = new URL(req.url || '/', `http://${req.headers.host}`)\n\t\t\t\tif (url.pathname === syncPath) {\n\t\t\t\t\twss.handleUpgrade(req, socket, head, (ws) => {\n\t\t\t\t\t\tconst transport = new WsServerTransport(ws)\n\t\t\t\t\t\tsyncServer.handleConnection(transport)\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tsocket.destroy()\n\t\t\t\t}\n\t\t\t})\n\n\t\t\treturn new Promise<string>((resolve, reject) => {\n\t\t\t\tconst onError = (error: Error) => {\n\t\t\t\t\treject(error)\n\t\t\t\t}\n\t\t\t\thttpServer?.once('error', onError)\n\t\t\t\thttpServer?.listen(port, '0.0.0.0', () => {\n\t\t\t\t\thttpServer?.off('error', onError)\n\t\t\t\t\tresolve(`http://localhost:${port}`)\n\t\t\t\t})\n\t\t\t})\n\t\t},\n\n\t\tasync stop(): Promise<void> {\n\t\t\tawait syncServer.stop()\n\t\t\tif (httpServer) {\n\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\thttpServer?.close(() => resolve())\n\t\t\t\t})\n\t\t\t\thttpServer = null\n\t\t\t}\n\t\t},\n\t}\n}\n\n/**\n * Render a minimal self-contained dashboard HTML page.\n * Shows server status with live-updating metrics via SSE.\n */\nfunction renderDashboardHtml(status: {\n\tversion: string\n\tuptime: number\n\tconnectedClients: number\n\ttotalOperations: number\n\tschemaVersion: number\n\tpeakConnections: number\n\tconnectionsTotal: number\n\toperationsReceived: number\n\toperationsSent: number\n\terrorCount: number\n}): string {\n\tconst version = status.version\n\tconst uptime = formatUptime(status.uptime)\n\treturn `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Kora Dashboard</title>\n<style>\n * { box-sizing: border-box; margin: 0; padding: 0 }\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0f172a; color: #e2e8f0; padding: 2rem }\n h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.25rem }\n .subtitle { color: #64748b; margin-bottom: 2rem; font-size: 0.875rem }\n .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 2rem }\n .card { background: #1e293b; border: 1px solid #334155; border-radius: 0.75rem; padding: 1.25rem }\n .card .label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: #64748b; margin-bottom: 0.5rem }\n .card .value { font-size: 1.75rem; font-weight: 700; color: #38bdf8 }\n .card .value.green { color: #4ade80 }\n .card .value.red { color: #f87171 }\n .card .value.yellow { color: #fbbf24 }\n .section-title { font-size: 1rem; font-weight: 600; margin-bottom: 0.75rem; margin-top: 1.5rem }\n table { width: 100%; border-collapse: collapse; font-size: 0.875rem }\n th { text-align: left; padding: 0.5rem 0.75rem; color: #64748b; font-weight: 500; border-bottom: 1px solid #334155 }\n td { padding: 0.5rem 0.75rem; border-bottom: 1px solid #1e293b }\n .status-dot { display: inline-block; width: 0.5rem; height: 0.5rem; border-radius: 50%; margin-right: 0.375rem }\n .status-dot.running { background: #4ade80 }\n .status-dot.stopped { background: #f87171 }\n</style>\n</head>\n<body>\n<h1>Kora Sync Server</h1>\n<p class=\"subtitle\">v${version} &middot; <span class=\"status-dot running\"></span>Running</p>\n<div class=\"grid\">\n <div class=\"card\"><div class=\"label\">Uptime</div><div class=\"value\">${uptime}</div></div>\n <div class=\"card\"><div class=\"label\">Connected Clients</div><div class=\"value\" id=\"connectedClients\">${status.connectedClients}</div></div>\n <div class=\"card\"><div class=\"label\">Total Operations</div><div class=\"value\" id=\"totalOperations\">${status.totalOperations}</div></div>\n <div class=\"card\"><div class=\"label\">Peak Connections</div><div class=\"value green\" id=\"peakConnections\">${status.peakConnections}</div></div>\n <div class=\"card\"><div class=\"label\">Ops Received</div><div class=\"value\" id=\"opsReceived\">${status.operationsReceived}</div></div>\n <div class=\"card\"><div class=\"label\">Ops Sent</div><div class=\"value\" id=\"opsSent\">${status.operationsSent}</div></div>\n <div class=\"card\"><div class=\"label\">Errors</div><div class=\"value ${status.errorCount > 0 ? 'red' : 'green'}\" id=\"errors\">${status.errorCount}</div></div>\n <div class=\"card\"><div class=\"label\">Schema Version</div><div class=\"value\">${status.schemaVersion}</div></div>\n</div>\n<script>\n(function() {\n const es = new EventSource('/__kora/events');\n es.addEventListener('status', (e) => {\n const s = JSON.parse(e.data);\n for (const [id, val] of Object.entries({\n connectedClients: s.connectedClients,\n totalOperations: s.totalOperations,\n peakConnections: s.peakConnections,\n opsReceived: s.operationsReceived,\n opsSent: s.operationsSent,\n errors: s.errorCount,\n })) {\n const el = document.getElementById(id);\n if (el) { el.textContent = String(val); el.className = 'value' + (id === 'errors' && val > 0 ? ' red' : id === 'errors' ? ' green' : ''); }\n }\n });\n es.onerror = () => { setTimeout(() => document.location.reload(), 5000); };\n})();\n</script>\n</body>\n</html>`\n}\n\nfunction formatUptime(ms: number): string {\n\tconst seconds = Math.floor(ms / 1000)\n\tconst minutes = Math.floor(seconds / 60)\n\tconst hours = Math.floor(minutes / 60)\n\tconst parts: string[] = []\n\tif (hours > 0) parts.push(`${hours}h`)\n\tif (minutes % 60 > 0) parts.push(`${minutes % 60}m`)\n\tparts.push(`${seconds % 60}s`)\n\treturn parts.join(' ')\n}\n"],"mappings":";AAmCA,SAAS,sBAAsB,OAAyB;AACvD,SAAO,KAAK,UAAU,KAAK;AAC5B;AAEA,SAAS,wBAAwB,OAAyB;AACzD,QAAM,OAAO,IAAI,KAAK,MAAM,SAAS,EAAE,YAAY,EAAE,MAAM,IAAI,EAAE;AACjE,QAAM,WAAW,EAAE,MAAM,SAAS,MAAM,SAAS,OAAO,QAAQ,EAAE,MAAM,KAAK;AAC7E,QAAM,OAAO,MAAM,SAAS,KAAK,MAAM,OAAO,MAAM,GAAG,CAAC,CAAC,MAAM;AAC/D,QAAM,UAAU,MAAM,YAAY,aAAa,MAAM,UAAU,MAAM,GAAG,CAAC,CAAC,MAAM;AAChF,QAAM,MAAM,MAAM,aAAa,SAAY,KAAK,MAAM,QAAQ,OAAO;AACrE,QAAMA,SAAQ,MAAM,UAAU,SAAY,KAAK,MAAM,KAAK,MAAM;AAChE,QAAM,MAAM,MAAM,QAAQ,WAAM,MAAM,KAAK,KAAK;AAChD,SAAO,GAAG,IAAI,IAAI,QAAQ,GAAG,IAAI,GAAG,OAAO,IAAI,MAAM,KAAK,GAAGA,MAAK,GAAG,GAAG,GAAG,GAAG;AAC/E;AAMO,SAAS,iBAAiB,QAGtB;AACV,QAAM,MAAM,UAAU;AAAA,IACrB,MAAM,CAAC,MAAc,QAAQ,OAAO,MAAM,GAAG,CAAC;AAAA,CAAI;AAAA,IAClD,OAAO,CAAC,MAAc,QAAQ,OAAO,MAAM,GAAG,CAAC;AAAA,CAAI;AAAA,EACpD;AAEA,SAAO;AAAA,IACN,IAAI,OAAuB;AAC1B,YAAM,OAAO,sBAAsB,KAAK;AACxC,UAAI,MAAM,UAAU,SAAS;AAC5B,YAAI,MAAM,IAAI;AAAA,MACf,OAAO;AACN,YAAI,KAAK,IAAI;AAAA,MACd;AAAA,IACD;AAAA,EACD;AACD;AAMO,SAAS,mBAAmB,QAAiD;AACnF,QAAM,MAAM,UAAU,EAAE,OAAO,CAAC,MAAc,QAAQ,OAAO,MAAM,GAAG,CAAC;AAAA,CAAI,EAAE;AAE7E,SAAO;AAAA,IACN,IAAI,OAAuB;AAC1B,UAAI,MAAM,wBAAwB,KAAK,CAAC;AAAA,IACzC;AAAA,EACD;AACD;AAKO,SAAS,qBAA6B;AAC5C,SAAO,EAAE,MAAM;AAAA,EAAC,EAAE;AACnB;AAQO,SAAS,sBAA8B;AAC7C,UAAQ,QAAQ,IAAI,UAAU;AAAA,IAC7B,KAAK;AACJ,aAAO,iBAAiB;AAAA,IACzB,KAAK;AACJ,aAAO,mBAAmB;AAAA,IAC3B;AACC,aAAO,mBAAmB;AAAA,EAC5B;AACD;;;ACvEO,IAAM,4BAAiD,oBAAI,IAAI,CAAC,YAAY,CAAC;AAQ7E,SAAS,qBAAqB,MAAuB;AAC3D,SAAO,0BAA0B,IAAI,IAAI;AAC1C;;;ACjDA,SAAS,sBAAsB;;;ACD/B,SAAS,cAAc,YAAY,iCAAiC;AAuBpE,SAAS,eAAe,YAA6B,SAA6B;AACjF,UAAQ,WAAW,MAAM;AAAA,IACxB,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO,YAAY,aAAa,qBAAqB;AAAA,IACtD,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO,YAAY,aAAa,WAAW;AAAA,IAC5C,KAAK;AACJ,aAAO,YAAY,aAAa,UAAU;AAAA,IAC3C,KAAK;AACJ,aAAO,YAAY,aAAa,UAAU;AAAA,IAC3C,KAAK;AACJ,aAAO,YAAY,aAAa,UAAU;AAAA,IAC3C,KAAK;AAGJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO,YAAY,aAAa,UAAU;AAAA,EAC5C;AACD;AAEA,SAAS,kBAAkB,OAAwB;AAClD,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,OAAO,UAAU,SAAU,QAAO,IAAI,KAAK;AAC/C,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK;AAClD,MAAI,OAAO,UAAU,UAAW,QAAO,QAAQ,MAAM;AACrD,SAAO,IAAI,KAAK,UAAU,KAAK,CAAC;AACjC;AAWO,SAAS,sBACf,MACA,YACA,SACW;AACX,QAAM,aAAuB,CAAC;AAC9B,QAAM,UAAoB,CAAC,8BAA8B;AAEzD,aAAW,CAAC,WAAW,UAAU,KAAK,OAAO,QAAQ,WAAW,MAAM,GAAG;AACxE,UAAM,UAAU,eAAe,YAAY,OAAO;AAClD,QAAI,SAAS,GAAG,WAAW,SAAS,CAAC,IAAI,OAAO;AAChD,QAAI,WAAW,iBAAiB,QAAW;AAC1C,gBAAU,YAAY,kBAAkB,WAAW,YAAY,CAAC;AAAA,IACjE;AACA,QAAI,WAAW,SAAS,UAAU,WAAW,YAAY;AACxD,YAAM,SAAS,WAAW,WAAW,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI;AACnE,gBAAU,WAAW,WAAW,SAAS,CAAC,QAAQ,MAAM;AAAA,IACzD;AACA,YAAQ,KAAK,MAAM;AAAA,EACpB;AAEA,QAAM,SAAS,YAAY,aAAa,WAAW;AACnD,UAAQ,KAAK,eAAe,MAAM,qBAAqB;AACvD,UAAQ,KAAK,eAAe,MAAM,qBAAqB;AACvD,UAAQ,KAAK,qCAAqC;AAElD,aAAW,KAAK,8BAA8B,WAAW,IAAI,CAAC;AAAA,IAAS,QAAQ,KAAK,OAAO,CAAC;AAAA,EAAK;AAGjG,aAAW,CAAC,WAAW,UAAU,KAAK,OAAO,QAAQ,WAAW,MAAM,GAAG;AACxE,UAAM,UAAU,eAAe,YAAY,OAAO;AAClD,QAAI,SAAS,GAAG,WAAW,SAAS,CAAC,IAAI,OAAO;AAChD,QAAI,WAAW,iBAAiB,QAAW;AAC1C,gBAAU,YAAY,kBAAkB,WAAW,YAAY,CAAC;AAAA,IACjE;AACA,eAAW,KAAK;AAAA,cAAkC,WAAW,IAAI,CAAC,eAAe,MAAM,EAAE;AAAA,EAC1F;AAIA,aAAW,cAAc,WAAW,SAAS;AAC5C,eAAW;AAAA,MACV,kCAAkC,IAAI,IAAI,UAAU,OAAO,WAAW,IAAI,CAAC,KAAK,WAAW,UAAU,CAAC;AAAA,IACvG;AAAA,EACD;AAGA,aAAW;AAAA,IACV,kCAAkC,IAAI,gBAAgB,WAAW,IAAI,CAAC;AAAA,EACvE;AAEA,SAAO;AACR;AAKO,SAAS,yBAAyB,QAA0B,SAA+B;AACjG,QAAM,aAAuB,CAAC;AAC9B,aAAW,CAAC,MAAM,UAAU,KAAK,OAAO,QAAQ,OAAO,WAAW,GAAG;AACpE,eAAW,KAAK,GAAG,sBAAsB,MAAM,YAAY,OAAO,CAAC;AAAA,EACpE;AACA,SAAO;AACR;AAEA,IAAM,kBAAkB;AACxB,IAAM,iBAA8C,IAAI;AAAA,EACvD,MAAM,KAAK,iBAAiB,CAAC,MAAMC,WAAU,CAAC,MAAMA,MAAK,CAAC;AAC3D;AAEA,SAAS,cAAc,QAA4B;AAClD,QAAM,UAAU,OAAO,QAAQ,OAAO,EAAE;AACxC,QAAM,MAAM,IAAI,WAAW,KAAK,MAAO,QAAQ,SAAS,IAAK,CAAC,CAAC;AAC/D,MAAI,SAAS;AACb,MAAI,OAAO;AACX,MAAIA,SAAQ;AACZ,aAAW,QAAQ,SAAS;AAC3B,UAAM,QAAQ,eAAe,IAAI,IAAI;AACrC,QAAI,UAAU,QAAW;AACxB,YAAM,IAAI,aAAa,6BAA6B,IAAI,8BAA8B;AAAA,QACrF;AAAA,MACD,CAAC;AAAA,IACF;AACA,aAAU,UAAU,IAAK;AACzB,YAAQ;AACR,QAAI,QAAQ,GAAG;AACd,cAAQ;AACR,UAAIA,MAAK,IAAK,UAAU,OAAQ;AAChC,MAAAA,UAAS;AAAA,IACV;AAAA,EACD;AACA,SAAO;AACR;AAUA,SAAS,0BAA0B,OAAyB;AAC3D,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,YAAY,OAAO,KAAK,GAAG;AAC7E,WAAO;AAAA,EACR;AACA,QAAM,SAAS;AACf,MAAI,OAAO,KAAK,MAAM,EAAE,WAAW,KAAK,OAAO,OAAO,eAAe,UAAU;AAC9E,WAAO,cAAc,OAAO,UAAU;AAAA,EACvC;AAGA,QAAM,OAAO,OAAO,KAAK,MAAM;AAC/B,MAAI,KAAK,SAAS,KAAK,KAAK,MAAM,CAAC,GAAG,MAAM,MAAM,OAAO,CAAC,KAAK,OAAO,OAAO,CAAC,MAAM,QAAQ,GAAG;AAC9F,UAAM,QAAQ,IAAI,WAAW,KAAK,MAAM;AACxC,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACrC,YAAM,OAAO,OAAO,OAAO,CAAC,CAAC;AAC7B,YAAM,CAAC,IAAI,OAAO,SAAS,WAAW,OAAO,MAAO;AAAA,IACrD;AACA,WAAO;AAAA,EACR;AACA,SAAO;AACR;AAMO,SAAS,oBAAoB,OAAgB,YAAsC;AACzF,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,UAAQ,WAAW,MAAM;AAAA,IACxB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACJ,aAAO,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK;AAAA,IAChE,KAAK;AACJ,aAAO,QAAQ,IAAI;AAAA,IACpB,KAAK;AACJ,aAAO,0BAA0B,KAAK;AAAA,IACvC;AACC,aAAO;AAAA,EACT;AACD;AAKO,SAAS,sBAAsB,OAAgB,YAAsC;AAC3F,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,UAAQ,WAAW,MAAM;AAAA,IACxB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACJ,aAAO,OAAO,UAAU,WAAW,KAAK,MAAM,KAAK,IAAI;AAAA,IACxD,KAAK;AACJ,aAAO,UAAU,KAAK,UAAU;AAAA,IACjC;AACC,aAAO;AAAA,EACT;AACD;AAMO,SAAS,kBACf,gBACA,WACA,QACO;AACP,QAAM,aAAa,OAAO,YAAY,cAAc;AACpD,MAAI,CAAC,YAAY;AAChB,UAAM,IAAI,MAAM,uBAAuB,cAAc,EAAE;AAAA,EACxD;AACA,QAAM,cAAc,oBAAI,IAAI;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,OAAO,KAAK,WAAW,MAAM;AAAA,EACjC,CAAC;AACD,MAAI,CAAC,YAAY,IAAI,SAAS,GAAG;AAChC,UAAM,IAAI;AAAA,MACT,uBAAuB,SAAS,qBAAqB,cAAc,oBACjD,MAAM,KAAK,WAAW,EAAE,KAAK,IAAI,CAAC;AAAA,IACrD;AAAA,EACD;AACD;;;AD3OO,IAAM,oBAAN,MAA+C;AAAA,EACpC;AAAA,EACA,aAA0B,CAAC;AAAA,EAC3B,iBAAiB,oBAAI,IAAuB;AAAA,EAC5C,gBAAqC,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7C,oBAAoB,oBAAI,IAAoB;AAAA,EACrD,qBAAqB;AAAA,EACrB,SAAkC;AAAA;AAAA,EAGzB,sBAAsB,oBAAI,IAA6C;AAAA,EAEhF,SAAS;AAAA,EAEjB,YAAY,QAAiB;AAC5B,SAAK,SAAS,UAAU,eAAe;AAAA,EACxC;AAAA,EAEA,mBAAkC;AACjC,WAAO,IAAI,IAAI,KAAK,aAAa;AAAA,EAClC;AAAA,EAEA,YAAoB;AACnB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,YAAqC;AACpC,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,MAAM,UAAU,QAAyC;AACxD,SAAK,WAAW;AAChB,SAAK,SAAS;AAGd,eAAW,kBAAkB,OAAO,KAAK,OAAO,WAAW,GAAG;AAC7D,UAAI,CAAC,KAAK,oBAAoB,IAAI,cAAc,GAAG;AAClD,aAAK,oBAAoB,IAAI,gBAAgB,oBAAI,IAAI,CAAC;AAAA,MACvD;AAAA,IACD;AAGA,SAAK,uBAAuB;AAAA,EAC7B;AAAA,EAEA,MAAM,qBAAqB,IAAqC;AAC/D,SAAK,WAAW;AAGhB,QAAI,KAAK,eAAe,IAAI,GAAG,EAAE,GAAG;AACnC,aAAO;AAAA,IACR;AAEA,SAAK,WAAW,KAAK,EAAE;AACvB,SAAK,eAAe,IAAI,GAAG,IAAI,EAAE;AAGjC,SAAK,sBAAsB;AAC3B,SAAK,kBAAkB,IAAI,GAAG,IAAI,KAAK,kBAAkB;AAGzD,UAAM,aAAa,KAAK,cAAc,IAAI,GAAG,MAAM,KAAK;AACxD,QAAI,GAAG,iBAAiB,YAAY;AACnC,WAAK,cAAc,IAAI,GAAG,QAAQ,GAAG,cAAc;AAAA,IACpD;AAGA,QAAI,KAAK,QAAQ,YAAY,GAAG,UAAU,GAAG;AAC5C,WAAK,0BAA0B,GAAG,YAAY,GAAG,QAAQ;AAAA,IAC1D;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,kBAAkB,QAAgB,SAAiB,OAAqC;AAC7F,SAAK,WAAW;AAEhB,WAAO,KAAK,WACV;AAAA,MACA,CAAC,OAAO,GAAG,WAAW,UAAU,GAAG,kBAAkB,WAAW,GAAG,kBAAkB;AAAA,IACtF,EACC,KAAK,CAAC,GAAG,MAAM,EAAE,iBAAiB,EAAE,cAAc;AAAA,EACrD;AAAA,EAEA,MAAM,oBAAqC;AAC1C,SAAK,WAAW;AAChB,WAAO,KAAK,WAAW;AAAA,EACxB;AAAA,EAEA,MAAM,yBAA0C;AAC/C,SAAK,WAAW;AAChB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,MAAM,2BACL,uBACA,OACgC;AAChC,SAAK,WAAW;AAChB,UAAM,SAA+B,CAAC;AACtC,QAAI,SAAS,EAAG,QAAO;AAGvB,eAAW,MAAM,KAAK,YAAY;AACjC,YAAM,mBAAmB,KAAK,kBAAkB,IAAI,GAAG,EAAE,KAAK;AAC9D,UAAI,mBAAmB,uBAAuB;AAC7C,eAAO,KAAK,EAAE,WAAW,IAAI,iBAAiB,CAAC;AAC/C,YAAI,OAAO,UAAU,MAAO;AAAA,MAC7B;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,sBAAsB,YAAmD;AAC9E,SAAK,WAAW;AAGhB,QAAI,KAAK,QAAQ,YAAY,UAAU,GAAG;AACzC,aAAO,KAAK,gBAAgB,UAAU;AAAA,IACvC;AAGA,WAAO,KAAK,mBAAmB,UAAU;AAAA,EAC1C;AAAA,EAEA,MAAM,gBACL,YACA,SACgC;AAChC,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,SAAK,iBAAiB,UAAU;AAGhC,UAAM,SAAS,KAAK;AACpB,QAAI,SAAS,OAAO;AACnB,iBAAW,OAAO,OAAO,KAAK,QAAQ,KAAK,GAAG;AAC7C,0BAAkB,YAAY,KAAK,MAAM;AAAA,MAC1C;AAAA,IACD;AACA,QAAI,SAAS,SAAS;AACrB,wBAAkB,YAAY,QAAQ,SAAS,MAAM;AAAA,IACtD;AAEA,UAAM,gBAAgB,KAAK,oBAAoB,IAAI,UAAU;AAC7D,QAAI,CAAC,cAAe,QAAO,CAAC;AAG5B,QAAI,UAAU,MAAM,KAAK,cAAc,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM;AAC9D,UAAI,CAAC,SAAS,kBAAkB,EAAE,aAAa,EAAG,QAAO;AACzD,aAAO;AAAA,IACR,CAAC;AAGD,QAAI,SAAS,OAAO;AACnB,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,KAAK,GAAG;AACzD,kBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,GAAG,MAAM,KAAK;AAAA,MACjD;AAAA,IACD;AAGA,QAAI,SAAS,SAAS;AACrB,YAAM,QAAQ,QAAQ;AACtB,YAAM,MAAM,QAAQ,mBAAmB,SAAS,KAAK;AACrD,cAAQ,KAAK,CAAC,GAAG,MAAM;AACtB,cAAM,OAAO,EAAE,KAAK;AACpB,cAAM,OAAO,EAAE,KAAK;AACpB,YAAI,SAAS,KAAM,QAAO;AAC1B,YAAI,SAAS,QAAQ,SAAS,OAAW,QAAO;AAChD,YAAI,SAAS,QAAQ,SAAS,OAAW,QAAO;AAChD,eAAO,OAAO,OAAO,KAAK,MAAM,IAAI;AAAA,MACrC,CAAC;AAAA,IACF;AAGA,QAAI,SAAS,WAAW,QAAW;AAClC,gBAAU,QAAQ,MAAM,QAAQ,MAAM;AAAA,IACvC;AAGA,QAAI,SAAS,UAAU,QAAW;AACjC,gBAAU,QAAQ,MAAM,GAAG,QAAQ,KAAK;AAAA,IACzC;AAGA,WAAO,QAAQ,IAAI,CAAC,MAAM;AACzB,YAAM,QAA4B,EAAE,IAAI,EAAE,GAAG;AAC7C,YAAM,gBAAiB,KAAK,OAA4B,YACvD,UACD;AACA,iBAAW,aAAa,OAAO,KAAK,cAAc,MAAM,GAAG;AAC1D,YAAI,aAAa,GAAG;AACnB,gBAAM,SAAS,IAAI,EAAE,SAAS;AAAA,QAC/B;AAAA,MACD;AACA,UAAI,iBAAiB,EAAG,OAAM,cAAc,EAAE;AAC9C,UAAI,iBAAiB,EAAG,OAAM,cAAc,EAAE;AAC9C,aAAO;AAAA,IACR,CAAC;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,YAAoB,IAAgD;AACpF,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,SAAK,iBAAiB,UAAU;AAEhC,UAAM,gBAAgB,KAAK,oBAAoB,IAAI,UAAU;AAC7D,QAAI,CAAC,cAAe,QAAO;AAE3B,UAAM,SAAS,cAAc,IAAI,EAAE;AACnC,QAAI,CAAC,UAAU,OAAO,aAAa,EAAG,QAAO;AAG7C,UAAM,QAA4B,EAAE,IAAI,OAAO,GAAG;AAClD,UAAM,gBAAiB,KAAK,OAA4B,YAAY,UAAU;AAG9E,eAAW,aAAa,OAAO,KAAK,cAAc,MAAM,GAAG;AAC1D,UAAI,aAAa,QAAQ;AACxB,cAAM,SAAS,IAAI,OAAO,SAAS;AAAA,MACpC;AAAA,IACD;AACA,QAAI,iBAAiB,OAAQ,OAAM,cAAc,OAAO;AACxD,QAAI,iBAAiB,OAAQ,OAAM,cAAc,OAAO;AACxD,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,gBAAgB,YAAoB,OAAkD;AAC3F,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,SAAK,iBAAiB,UAAU;AAEhC,UAAM,SAAS,KAAK;AACpB,QAAI,OAAO;AACV,iBAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACrC,0BAAkB,YAAY,KAAK,MAAM;AAAA,MAC1C;AAAA,IACD;AAEA,UAAM,gBAAgB,KAAK,oBAAoB,IAAI,UAAU;AAC7D,QAAI,CAAC,cAAe,QAAO;AAE3B,QAAIC,SAAQ;AACZ,eAAW,UAAU,cAAc,OAAO,GAAG;AAC5C,UAAI,OAAO,aAAa,EAAG;AAC3B,UAAI,OAAO;AACV,YAAI,UAAU;AACd,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AACjD,cAAI,OAAO,GAAG,MAAM,OAAO;AAC1B,sBAAU;AACV;AAAA,UACD;AAAA,QACD;AACA,YAAI,CAAC,QAAS;AAAA,MACf;AACA,MAAAA;AAAA,IACD;AACA,WAAOA;AAAA,EACR;AAAA,EAEA,MAAM,QAAuB;AAC5B,SAAK,SAAS;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAsB;AACrB,SAAK,WAAW;AAChB,SAAK,WAAW,SAAS;AACzB,SAAK,eAAe,MAAM;AAC1B,SAAK,cAAc,MAAM;AACzB,SAAK,oBAAoB,MAAM;AAC/B,SAAK,SAAS;AAAA,EACf;AAAA,EAEA,MAAM,eAAoC;AACzC,SAAK,WAAW;AAChB,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,6BAAiB;AAC5D,WAAO,kBAAkB,KAAK,QAAQ,KAAK,YAAY,KAAK,aAAa;AAAA,EAC1E;AAAA,EAEA,MAAM,aACL,MACA,OAC4D;AAC5D,SAAK,WAAW;AAChB,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,6BAAiB;AAC5D,UAAM,EAAE,YAAAC,aAAY,cAAc,IAAI,kBAAkB,IAAI;AAE5D,QAAI,OAAO;AACV,UAAI,WAAW;AACf,iBAAW,MAAMA,aAAY;AAC5B,cAAM,SAAS,MAAM,KAAK,qBAAqB,EAAE;AACjD,YAAI,WAAW,UAAW;AAAA,MAC3B;AACA,aAAO,EAAE,oBAAoB,UAAU,SAAS,KAAK;AAAA,IACtD;AAGA,SAAK,WAAW,SAAS;AACzB,SAAK,eAAe,MAAM;AAC1B,SAAK,cAAc,MAAM;AACzB,SAAK,kBAAkB,MAAM;AAC7B,SAAK,qBAAqB;AAE1B,eAAW,CAAC,KAAK,GAAG,KAAK,eAAe;AACvC,WAAK,cAAc,IAAI,KAAK,GAAG;AAAA,IAChC;AAEA,eAAW,MAAMA,aAAY;AAC5B,WAAK,WAAW,KAAK,EAAE;AACvB,WAAK,eAAe,IAAI,GAAG,IAAI,EAAE;AAEjC,WAAK,sBAAsB;AAC3B,WAAK,kBAAkB,IAAI,GAAG,IAAI,KAAK,kBAAkB;AAGzD,UAAI,KAAK,QAAQ,YAAY,GAAG,UAAU,GAAG;AAC5C,aAAK,0BAA0B,GAAG,YAAY,GAAG,QAAQ;AAAA,MAC1D;AAAA,IACD;AAEA,WAAO,EAAE,oBAAoBA,YAAW,QAAQ,SAAS,KAAK;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBAAgC;AAC/B,WAAO,CAAC,GAAG,KAAK,UAAU;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAMQ,0BAA0B,YAAoB,UAAwB;AAC7E,UAAM,gBAAgB,KAAK,QAAQ,YAAY,UAAU;AACzD,QAAI,CAAC,cAAe;AAGpB,QAAI,gBAAgB,KAAK,oBAAoB,IAAI,UAAU;AAC3D,QAAI,CAAC,eAAe;AACnB,sBAAgB,oBAAI,IAAI;AACxB,WAAK,oBAAoB,IAAI,YAAY,aAAa;AAAA,IACvD;AAIA,UAAM,YAAY,KAAK,WACrB,OAAO,CAAC,OAAO,GAAG,eAAe,cAAc,GAAG,aAAa,QAAQ,EACvE,KAAK,CAAC,GAAG,MAAM;AACf,UAAI,EAAE,UAAU,aAAa,EAAE,UAAU;AACxC,eAAO,EAAE,UAAU,WAAW,EAAE,UAAU;AAC3C,UAAI,EAAE,UAAU,YAAY,EAAE,UAAU;AACvC,eAAO,EAAE,UAAU,UAAU,EAAE,UAAU;AAC1C,aAAO,EAAE,UAAU,SAAS,EAAE,UAAU,SACrC,KACA,EAAE,UAAU,SAAS,EAAE,UAAU,SAChC,IACA;AAAA,IACL,CAAC;AAEF,UAAM,YAAY,UAAU,IAAI,CAAC,QAAQ;AAAA,MACxC,MAAM,GAAG;AAAA,MACT,MAAM,GAAG;AAAA,MACT,WAAW,GAAG,aAAa;AAAA,IAC5B,EAAE;AACF,UAAM,aAAa,0BAA0B,SAAS;AAEtD,QAAI,YAAY;AACf,YAAM,YACL,UAAU,SAAS,IAAK,UAAU,CAAC,EAAgB,UAAU,WAAW,KAAK,IAAI;AAClF,YAAM,YACL,UAAU,SAAS,IACf,UAAU,UAAU,SAAS,CAAC,EAAgB,UAAU,WACzD,KAAK,IAAI;AAEb,YAAM,eAAmC;AAAA,QACxC,IAAI;AAAA,QACJ,GAAG;AAAA,QACH,aAAa;AAAA,QACb,aAAa;AAAA,QACb,UAAU;AAAA,MACX;AACA,oBAAc,IAAI,UAAU,YAAY;AAAA,IACzC,OAAO;AAEN,YAAM,WAAW,cAAc,IAAI,QAAQ;AAC3C,UAAI,UAAU;AACb,iBAAS,WAAW;AACpB,iBAAS,cAAc,KAAK,IAAI;AAAA,MACjC,OAAO;AACN,sBAAc,IAAI,UAAU;AAAA,UAC3B,IAAI;AAAA,UACJ,UAAU;AAAA,UACV,aAAa,KAAK,IAAI;AAAA,UACtB,aAAa,KAAK,IAAI;AAAA,QACvB,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,yBAA+B;AACtC,QAAI,CAAC,KAAK,OAAQ;AAGlB,UAAM,aAAa,oBAAI,IAAY;AACnC,eAAW,MAAM,KAAK,YAAY;AACjC,UAAI,KAAK,OAAO,YAAY,GAAG,UAAU,GAAG;AAC3C,mBAAW,IAAI,GAAG,GAAG,UAAU,MAAM,GAAG,QAAQ,EAAE;AAAA,MACnD;AAAA,IACD;AAEA,eAAW,OAAO,YAAY;AAC7B,YAAM,CAAC,YAAY,QAAQ,IAAI,IAAI,MAAM,KAAK;AAC9C,WAAK,0BAA0B,YAAY,QAAQ;AAAA,IACpD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmB,YAA0C;AACpE,UAAM,gBAAgB,KAAK,WACzB,OAAO,CAAC,OAAO,GAAG,eAAe,UAAU,EAC3C,KAAK,CAAC,GAAG,MAAM;AACf,UAAI,EAAE,UAAU,aAAa,EAAE,UAAU;AACxC,eAAO,EAAE,UAAU,WAAW,EAAE,UAAU;AAC3C,UAAI,EAAE,UAAU,YAAY,EAAE,UAAU;AACvC,eAAO,EAAE,UAAU,UAAU,EAAE,UAAU;AAC1C,aAAO,EAAE,iBAAiB,EAAE;AAAA,IAC7B,CAAC;AAEF,UAAM,UAAU,oBAAI,IAAqC;AACzD,UAAM,UAAU,oBAAI,IAAY;AAEhC,eAAW,MAAM,eAAe;AAC/B,cAAQ,GAAG,MAAM;AAAA,QAChB,KAAK;AACJ,cAAI,GAAG,MAAM;AACZ,oBAAQ,IAAI,GAAG,UAAU,EAAE,IAAI,GAAG,UAAU,GAAG,GAAG,KAAK,CAAC;AACxD,oBAAQ,OAAO,GAAG,QAAQ;AAAA,UAC3B;AACA;AAAA,QACD,KAAK;AACJ,cAAI,GAAG,MAAM;AACZ,kBAAM,WAAW,QAAQ,IAAI,GAAG,QAAQ,KAAK,EAAE,IAAI,GAAG,SAAS;AAC/D,oBAAQ,IAAI,GAAG,UAAU,EAAE,GAAG,UAAU,GAAG,GAAG,KAAK,CAAC;AACpD,oBAAQ,OAAO,GAAG,QAAQ;AAAA,UAC3B;AACA;AAAA,QACD,KAAK;AACJ,kBAAQ,IAAI,GAAG,QAAQ;AACvB;AAAA,MACF;AAAA,IACD;AAEA,eAAW,MAAM,SAAS;AACzB,cAAQ,OAAO,EAAE;AAAA,IAClB;AAEA,WAAO,MAAM,KAAK,QAAQ,OAAO,CAAC;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAMQ,aAAmB;AAC1B,QAAI,KAAK,QAAQ;AAChB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC9C;AAAA,EACD;AAAA,EAEQ,eAAqB;AAC5B,QAAI,CAAC,KAAK,QAAQ;AACjB,YAAM,IAAI;AAAA,QACT;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,iBAAiB,YAA0B;AAClD,UAAM,SAAS,KAAK;AACpB,QAAI,CAAC,OAAO,YAAY,UAAU,GAAG;AACpC,YAAM,IAAI;AAAA,QACT,uBAAuB,UAAU,iBAAiB,OAAO,KAAK,OAAO,WAAW,EAAE,KAAK,IAAI,CAAC;AAAA,MAC7F;AAAA,IACD;AAAA,EACD;AACD;;;AEpgBA,SAAS,oBAAoB,kBAAAC,iBAAgB,cAAAC,mBAAkB;AAG/D,SAAS,KAAK,KAAK,SAAS,OAAO,MAAM,IAAI,IAAI,WAAW;;;ACX5D,SAAS,QAAQ,OAAO,SAAS,SAAS,YAAY;AAY/C,IAAM,eAAe;AAAA,EAC3B;AAAA,EACA;AAAA,IACC,IAAI,KAAK,IAAI,EAAE,WAAW;AAAA,IAC1B,QAAQ,KAAK,SAAS,EAAE,QAAQ;AAAA,IAChC,MAAM,KAAK,MAAM,EAAE,QAAQ;AAAA,IAC3B,YAAY,KAAK,YAAY,EAAE,QAAQ;AAAA,IACvC,UAAU,KAAK,WAAW,EAAE,QAAQ;AAAA,IACpC,MAAM,KAAK,MAAM;AAAA;AAAA,IACjB,cAAc,KAAK,eAAe;AAAA;AAAA,IAClC,WAAW,KAAK,YAAY;AAAA;AAAA,IAC5B,UAAU,OAAO,aAAa,EAAE,MAAM,SAAS,CAAC,EAAE,QAAQ;AAAA,IAC1D,SAAS,QAAQ,SAAS,EAAE,QAAQ;AAAA,IACpC,iBAAiB,KAAK,mBAAmB,EAAE,QAAQ;AAAA,IACnD,gBAAgB,QAAQ,iBAAiB,EAAE,QAAQ;AAAA,IACnD,YAAY,KAAK,aAAa,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA;AAAA,IACtD,eAAe,QAAQ,gBAAgB,EAAE,QAAQ;AAAA,IACjD,YAAY,OAAO,eAAe,EAAE,MAAM,SAAS,CAAC,EAAE,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,IAK9D,aAAa,OAAO,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAAA,EACvD;AAAA,EACA,CAAC,WAAW;AAAA,IACX,YAAY,MAAM,iBAAiB,EAAE,GAAG,MAAM,QAAQ,MAAM,cAAc;AAAA,IAC1E,eAAe,MAAM,mBAAmB,EAAE,GAAG,MAAM,UAAU;AAAA,IAC7D,aAAa,MAAM,iBAAiB,EAAE,GAAG,MAAM,UAAU;AAAA,IACzD,aAAa,MAAM,qBAAqB,EAAE,GAAG,MAAM,WAAW;AAAA,EAC/D;AACD;AAEO,IAAM,cAAc,QAAQ,cAAc;AAAA,EAChD,QAAQ,KAAK,SAAS,EAAE,WAAW;AAAA,EACnC,mBAAmB,QAAQ,qBAAqB,EAAE,QAAQ;AAAA,EAC1D,YAAY,OAAO,gBAAgB,EAAE,MAAM,SAAS,CAAC,EAAE,QAAQ;AAChE,CAAC;;;ADXM,IAAM,sBAAN,MAAiD;AAAA,EACtC;AAAA,EACA;AAAA,EACA,gBAA+B,oBAAI,IAAI;AAAA,EACvC;AAAA,EACT,SAAkC;AAAA,EAClC,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,kBAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxB;AAAA,EAEjB,YAAY,IAAwB,QAAiB,YAAyB;AAC7E,SAAK,KAAK;AACV,SAAK,SAAS,UAAUC,gBAAe;AACvC,SAAK,aAAa,cAAc,EAAE,KAAK,MAAM,KAAK,IAAI,EAAE;AACxD,SAAK,QAAQ,KAAK,WAAW;AAAA,EAC9B;AAAA,EAEA,mBAAkC;AACjC,SAAK,WAAW;AAChB,WAAO,IAAI,IAAI,KAAK,aAAa;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,wBAAgC;AAC/B,QAAI,KAAK,oBAAoB,MAAM;AAClC,WAAK,kBAAkB,KAAK,cAAc,IAAI,KAAK,MAAM,KAAK;AAAA,IAC/D;AACA,SAAK,mBAAmB;AACxB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,YAAoB;AACnB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,YAAqC;AACpC,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,MAAM,UAAU,QAAyC;AACxD,SAAK,WAAW;AAChB,UAAM,KAAK;AACX,SAAK,SAAS;AAGd,UAAM,gBAAgB,yBAAyB,QAAQ,UAAU;AACjE,eAAW,QAAQ,eAAe;AACjC,UAAI,KAAK,WAAW,mBAAmB,GAAG;AACzC,cAAM,WAAW,KAAK,QAAQ,uBAAuB,EAAE;AACvD,YAAI;AACH,gBAAM,KAAK,GAAG,QAAQ,IAAI,IAAI,QAAQ,CAAC;AAAA,QACxC,SAAS,GAAG;AAGX,gBAAM,MAAM,aAAa,QAAQ,EAAE,UAAU;AAC7C,gBAAM,WAAW,aAAa,SAAS,EAAE,iBAAiB,QAAQ,EAAE,MAAM,UAAU;AACpF,cACC,CAAC,IAAI,SAAS,gBAAgB,KAC9B,CAAC,IAAI,SAAS,kBAAkB,KAChC,CAAC,SAAS,SAAS,gBAAgB,KACnC,CAAC,SAAS,SAAS,kBAAkB,GACpC;AACD,kBAAM;AAAA,UACP;AAAA,QACD;AAAA,MACD,OAAO;AACN,cAAM,KAAK,GAAG,QAAQ,IAAI,IAAI,IAAI,CAAC;AAAA,MACpC;AAAA,IACD;AAGA,UAAM,KAAK,uBAAuB;AAAA,EACnC;AAAA,EAEA,MAAM,qBAAqB,IAAqC;AAC/D,SAAK,WAAW;AAChB,UAAM,KAAK;AAGX,UAAM,WAAW,MAAM,KAAK,GAC1B,OAAO,EAAE,IAAI,aAAa,GAAG,CAAC,EAC9B,KAAK,YAAY,EACjB,MAAM,GAAG,aAAa,IAAI,GAAG,EAAE,CAAC,EAChC,MAAM,CAAC;AAET,QAAI,SAAS,SAAS,GAAG;AACxB,aAAO;AAAA,IACR;AAEA,UAAM,MAAM,KAAK,IAAI;AAErB,UAAM,KAAK,GAAG,YAAY,OAAO,OAAO;AAGvC,YAAM,cAAc,MAAM,KAAK,gBAAgB,EAAE;AACjD,YAAM,MAAM,KAAK,mBAAmB,IAAI,KAAK,WAAW;AAGxD,YAAM,GAAG,OAAO,YAAY,EAAE,OAAO,GAAG,EAAE,oBAAoB,EAAE,QAAQ,aAAa,GAAG,CAAC;AAGzF,YAAM,GACJ,OAAO,WAAW,EAClB,OAAO;AAAA,QACP,QAAQ,GAAG;AAAA,QACX,mBAAmB,GAAG;AAAA,QACtB,YAAY;AAAA,MACb,CAAC,EACA,mBAAmB;AAAA,QACnB,QAAQ,YAAY;AAAA,QACpB,KAAK;AAAA,UACJ,mBAAmB,eAAe,YAAY,iBAAiB,KAAK,GAAG,cAAc;AAAA,UACrF,YAAY,MAAM,GAAG;AAAA,QACtB;AAAA,MACD,CAAC;AAGF,UAAI,KAAK,QAAQ,YAAY,GAAG,UAAU,GAAG;AAC5C,cAAM,KAAK,0BAA0B,IAAI,GAAG,YAAY,GAAG,QAAQ;AAAA,MACpE;AAAA,IACD,CAAC;AAGD,UAAM,aAAa,KAAK,cAAc,IAAI,GAAG,MAAM,KAAK;AACxD,QAAI,GAAG,iBAAiB,YAAY;AACnC,WAAK,cAAc,IAAI,GAAG,QAAQ,GAAG,cAAc;AAAA,IACpD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,iBAAiB,OAA+D;AACrF,SAAK,WAAW;AAChB,UAAM,KAAK;AACX,SAAK,aAAa;AAClB,SAAK,iBAAiB,MAAM,OAAO,UAAU;AAE7C,UAAM,SAAS,KAAK;AACpB,UAAM,gBAAgB,OAAO,YAAY,MAAM,OAAO,UAAU;AAGhE,UAAM,UAAU,QAAQ,MAAM,OAAO,UAAU,IAAI,MAAM,OAAO,EAAE;AAElE,UAAM,SAAS,MAAM,KAAK,GAAG,YAAY,OAAO,OAAO;AAItD,YAAM,GAAG,QAAQ,oDAAoD,OAAO,OAAO;AAKnF,UAAI,MAAM,gBAAgB;AACzB,cAAM,WAAY,MAAM,GAAG;AAAA,UAC1B,oBAAoB,IAAI,IAAIC,YAAW,MAAM,eAAe,UAAU,CAAC,CAAC,eAAe,MAAM,eAAe,EAAE;AAAA,QAC/G;AACA,YAAI,SAAS,SAAS,GAAG;AACxB,iBAAO,EAAE,UAAU,MAAM,YAAY,MAAM,SAAS,CAAC,EAAiB;AAAA,QACvE;AAAA,MACD;AAEA,YAAM,OAAQ,MAAM,GAAG;AAAA,QACtB,oBAAoB,IAAI,IAAIA,YAAW,MAAM,OAAO,UAAU,CAAC,CAAC,eAAe,MAAM,OAAO,EAAE;AAAA,MAC/F;AACA,YAAM,UACL,KAAK,SAAS,IACX,KAAK,eAAe,KAAK,CAAC,GAA8B,aAAa,IACrE;AAEJ,UAAI,CAAC,MAAM,MAAM,OAAO,GAAG;AAC1B,eAAO,EAAE,UAAU,OAAO,YAAY,OAAO,SAAS,CAAC,EAAiB;AAAA,MACzE;AAOA,YAAM,QAAQ,IAAI,mBAAmB,KAAK,QAAQ,KAAK,UAAU;AACjE,YAAM,SAAS,MAAM,KAAK;AAAA,QACzB;AAAA,QACA,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,MACd;AACA,UAAI,QAAQ;AACX,cAAM,UAAU,MAAM;AAAA,MACvB;AAEA,YAAM,MAAM,MAAM,MAAM,gBAAgB,SAAS,EAAE,MAAM,CAAC;AAC1D,YAAM,MAAM,KAAK,IAAI;AACrB,iBAAW,MAAM,KAAK;AACrB,cAAM,cAAc,MAAM,KAAK,gBAAgB,EAAE;AACjD,cAAM,MAAM,KAAK,mBAAmB,IAAI,KAAK,WAAW;AACxD,cAAM,GAAG,OAAO,YAAY,EAAE,OAAO,GAAG,EAAE,oBAAoB,EAAE,QAAQ,aAAa,GAAG,CAAC;AACzF,cAAM,GACJ,OAAO,WAAW,EAClB,OAAO,EAAE,QAAQ,GAAG,QAAQ,mBAAmB,GAAG,gBAAgB,YAAY,IAAI,CAAC,EACnF,mBAAmB;AAAA,UACnB,QAAQ,YAAY;AAAA,UACpB,KAAK;AAAA,YACJ,mBAAmB,eAAe,YAAY,iBAAiB,KAAK,GAAG,cAAc;AAAA,YACrF,YAAY,MAAM,GAAG;AAAA,UACtB;AAAA,QACD,CAAC;AACF,YAAI,KAAK,QAAQ,YAAY,GAAG,UAAU,GAAG;AAC5C,gBAAM,KAAK,0BAA0B,IAAI,GAAG,YAAY,GAAG,QAAQ;AAAA,QACpE;AAAA,MACD;AACA,aAAO,EAAE,UAAU,MAAM,YAAY,OAAO,SAAS,IAAI;AAAA,IAC1D,CAAC;AAGD,eAAW,MAAM,OAAO,SAAS;AAChC,YAAM,aAAa,KAAK,cAAc,IAAI,GAAG,MAAM,KAAK;AACxD,UAAI,GAAG,iBAAiB,YAAY;AACnC,aAAK,cAAc,IAAI,GAAG,QAAQ,GAAG,cAAc;AAAA,MACpD;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,kBAAkB,QAAgB,SAAiB,OAAqC;AAC7F,SAAK,WAAW;AAChB,UAAM,KAAK;AAEX,UAAM,OAAO,MAAM,KAAK,GACtB,OAAO,EACP,KAAK,YAAY,EACjB;AAAA,MACA,IAAI,GAAG,aAAa,QAAQ,MAAM,GAAG,QAAQ,aAAa,gBAAgB,SAAS,KAAK,CAAC;AAAA,IAC1F,EACC,QAAQ,IAAI,aAAa,cAAc,CAAC;AAE1C,WAAO,KAAK,IAAI,CAAC,QAAQ,KAAK,qBAAqB,GAAG,CAAC;AAAA,EACxD;AAAA,EAEA,MAAM,oBAAqC;AAC1C,SAAK,WAAW;AAChB,UAAM,KAAK;AAEX,UAAM,SAAS,MAAM,KAAK,GAAG,OAAO,EAAE,OAAO,MAAM,EAAE,CAAC,EAAE,KAAK,YAAY;AACzE,WAAO,OAAO,CAAC,GAAG,SAAS;AAAA,EAC5B;AAAA,EAEA,MAAM,yBAA0C;AAC/C,SAAK,WAAW;AAChB,UAAM,KAAK;AACX,UAAM,OAAQ,MAAM,KAAK,GAAG;AAAA,MAC3B;AAAA,IACD;AACA,WAAO,OAAO,KAAK,CAAC,GAAG,KAAK,CAAC;AAAA,EAC9B;AAAA,EAEA,MAAM,2BACL,uBACA,OACgC;AAChC,SAAK,WAAW;AAChB,UAAM,KAAK;AACX,UAAM,OAAO,MAAM,KAAK,GACtB,OAAO,EACP,KAAK,YAAY,EACjB,MAAM,GAAG,aAAa,aAAa,qBAAqB,CAAC,EACzD,QAAQ,IAAI,aAAa,WAAW,CAAC,EACrC,MAAM,KAAK;AACb,WAAO,KAAK,IAAI,CAAC,SAAS;AAAA,MACzB,WAAW,KAAK,qBAAqB,GAAG;AAAA,MACxC,kBAAkB,IAAI,eAAe;AAAA,IACtC,EAAE;AAAA,EACH;AAAA,EAEA,MAAM,sBAAsB,YAAmD;AAC9E,SAAK,WAAW;AAChB,UAAM,KAAK;AAGX,QAAI,KAAK,QAAQ,YAAY,UAAU,GAAG;AACzC,aAAO,KAAK,gBAAgB,UAAU;AAAA,IACvC;AAGA,WAAO,KAAK,sBAAsB,UAAU;AAAA,EAC7C;AAAA,EAEA,MAAM,gBACL,YACA,SACgC;AAChC,SAAK,WAAW;AAChB,UAAM,KAAK;AACX,SAAK,aAAa;AAClB,SAAK,iBAAiB,UAAU;AAEhC,UAAM,SAAS,KAAK;AACpB,UAAM,gBAAgB,OAAO,YAAY,UAAU;AAKnD,QAAI,SAAS,OAAO;AACnB,iBAAW,OAAO,OAAO,KAAK,QAAQ,KAAK,GAAG;AAC7C,0BAAkB,YAAY,KAAK,MAAM;AAAA,MAC1C;AAAA,IACD;AACA,QAAI,SAAS,SAAS;AACrB,wBAAkB,YAAY,QAAQ,SAAS,MAAM;AAAA,IACtD;AAEA,UAAM,QAAQ,KAAK,iBAAiB,YAAY,OAAO;AACvD,UAAM,OAAQ,MAAM,KAAK,GAAG,QAAQ,KAAK;AAEzC,WAAO,KAAK,IAAI,CAAC,QAAQ,KAAK,eAAe,KAAK,aAAa,CAAC;AAAA,EACjE;AAAA,EAEA,MAAM,WAAW,YAAoB,IAAgD;AACpF,SAAK,WAAW;AAChB,UAAM,KAAK;AACX,SAAK,aAAa;AAClB,SAAK,iBAAiB,UAAU;AAEhC,UAAM,SAAS,KAAK;AACpB,UAAM,gBAAgB,OAAO,YAAY,UAAU;AAGnD,UAAM,QAAQ,oBAAoB,IAAI,IAAIA,YAAW,UAAU,CAAC,CAAC,eAAe,EAAE;AAClF,UAAM,OAAQ,MAAM,KAAK,GAAG,QAAQ,KAAK;AAEzC,QAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,WAAO,KAAK,eAAe,KAAK,CAAC,GAA8B,aAAa;AAAA,EAC7E;AAAA,EAEA,MAAM,gBAAgB,YAAoB,OAAkD;AAC3F,SAAK,WAAW;AAChB,UAAM,KAAK;AACX,SAAK,aAAa;AAClB,SAAK,iBAAiB,UAAU;AAEhC,UAAM,SAAS,KAAK;AACpB,QAAI,OAAO;AACV,iBAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACrC,0BAAkB,YAAY,KAAK,MAAM;AAAA,MAC1C;AAAA,IACD;AAEA,UAAM,cAAc,KAAK,iBAAiB,SAAS,CAAC,GAAG,KAAK;AAC5D,UAAM,QAAQ,kCAAkC,IAAI,IAAIA,YAAW,UAAU,CAAC,CAAC,UAAU,WAAW;AACpG,UAAM,OAAQ,MAAM,KAAK,GAAG,QAAQ,KAAK;AACzC,UAAM,MAAM,KAAK,CAAC,GAAG;AACrB,WAAO,OAAO,QAAQ,WAAW,OAAO,SAAS,KAAK,EAAE,IAAK,OAAO;AAAA,EACrE;AAAA,EAEA,MAAM,QAAuB;AAC5B,SAAK,SAAS;AAAA,EACf;AAAA,EAEA,MAAM,eAAoC;AACzC,SAAK,WAAW;AAChB,UAAM,KAAK;AAEX,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,6BAAiB;AAQ5D,UAAM,OAAO,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,YAAY,EAAE,QAAQ,IAAI,aAAa,WAAW,CAAC;AAC5F,UAAMC,cAAa,KAAK,IAAI,CAAC,QAAQ,KAAK,qBAAqB,GAAG,CAAC;AAEnE,WAAO,kBAAkB,KAAK,QAAQA,aAAY,KAAK,aAAa;AAAA,EACrE;AAAA,EAEA,MAAM,aACL,MACA,OAC4D;AAC5D,SAAK,WAAW;AAChB,UAAM,KAAK;AAEX,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,6BAAiB;AAC5D,UAAM,EAAE,YAAAA,aAAY,cAAc,IAAI,kBAAkB,IAAI;AAE5D,QAAI,OAAO;AACV,UAAI,WAAW;AACf,iBAAW,MAAMA,aAAY;AAC5B,cAAM,SAAS,MAAM,KAAK,qBAAqB,EAAE;AACjD,YAAI,WAAW,UAAW;AAAA,MAC3B;AAGA,WAAK,kBAAkB;AACvB,aAAO,EAAE,oBAAoB,UAAU,SAAS,KAAK;AAAA,IACtD;AAEA,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,KAAK,GAAG,YAAY,OAAO,OAAO;AACvC,YAAM,GAAG,OAAO,YAAY;AAC5B,YAAM,GAAG,OAAO,WAAW;AAE3B,iBAAW,CAAC,KAAK,GAAG,KAAK,eAAe;AACvC,cAAM,GACJ,OAAO,WAAW,EAClB,OAAO,EAAE,QAAQ,KAAK,mBAAmB,KAAK,YAAY,IAAI,CAAC,EAC/D,oBAAoB,EAAE,QAAQ,YAAY,OAAO,CAAC;AAAA,MACrD;AAIA,UAAI,cAAc;AAClB,iBAAW,MAAMA,aAAY;AAC5B,uBAAe;AACf,cAAM,MAAM,KAAK,mBAAmB,IAAI,KAAK,WAAW;AACxD,cAAM,GAAG,OAAO,YAAY,EAAE,OAAO,GAAG,EAAE,oBAAoB,EAAE,QAAQ,aAAa,GAAG,CAAC;AAAA,MAC1F;AACA,YAAM,GAAG;AAAA,QACR,0DAA0D,WAAW;AAAA,8CAC3B,WAAW;AAAA,MACtD;AAAA,IACD,CAAC;AAGD,SAAK,cAAc,MAAM;AACzB,eAAW,CAAC,KAAK,GAAG,KAAK,eAAe;AACvC,WAAK,cAAc,IAAI,KAAK,GAAG;AAAA,IAChC;AAEA,SAAK,kBAAkB;AAEvB,WAAO,EAAE,oBAAoBA,YAAW,QAAQ,SAAS,KAAK;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAc,yBACb,QACA,YACA,UAC+B;AAC/B,UAAM,OAAO,MAAM,OACjB,OAAO;AAAA,MACP,UAAU,aAAa;AAAA,MACvB,SAAS,aAAa;AAAA,MACtB,iBAAiB,aAAa;AAAA,IAC/B,CAAC,EACA,KAAK,YAAY,EACjB,MAAM,IAAI,GAAG,aAAa,YAAY,UAAU,GAAG,GAAG,aAAa,UAAU,QAAQ,CAAC,CAAC,EACvF;AAAA,MACA,KAAK,aAAa,QAAQ;AAAA,MAC1B,KAAK,aAAa,OAAO;AAAA,MACzB,KAAK,aAAa,eAAe;AAAA,IAClC,EACC,MAAM,CAAC;AAET,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,CAAC,KAAK;AACT,aAAO;AAAA,IACR;AACA,WAAO,EAAE,UAAU,IAAI,UAAU,SAAS,IAAI,SAAS,QAAQ,IAAI,gBAAgB;AAAA,EACpF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,0BACb,QACA,YACA,UACgB;AAChB,UAAM,gBAAgB,KAAK,QAAQ,YAAY,UAAU;AACzD,QAAI,CAAC,cAAe;AAGpB,UAAM,MAAM,MAAM,OAChB,OAAO;AAAA,MACP,MAAM,aAAa;AAAA,MACnB,MAAM,aAAa;AAAA,MACnB,WAAW,aAAa;AAAA,MACxB,UAAU,aAAa;AAAA,IACxB,CAAC,EACA,KAAK,YAAY,EACjB,MAAM,IAAI,GAAG,aAAa,YAAY,UAAU,GAAG,GAAG,aAAa,UAAU,QAAQ,CAAC,CAAC,EAGvF;AAAA,MACA,IAAI,aAAa,QAAQ;AAAA,MACzB,IAAI,aAAa,OAAO;AAAA,MACxB,IAAI,aAAa,eAAe;AAAA,IACjC;AAGD,UAAM,YAAY,IAAI,IAAI,CAAC,QAAQ;AAAA,MAClC,MAAM,GAAG;AAAA,MACT,MAAM,GAAG,SAAS,OAAO,KAAK,MAAM,GAAG,IAAI,IAAI;AAAA,MAC/C,WACC,GAAG,aAAa,OAAQ,KAAK,MAAM,GAAG,SAAS,IAAiC;AAAA,IAClF,EAAE;AACF,UAAM,aAAa,0BAA0B,SAAS;AAEtD,UAAM,aAAa,OAAO,KAAK,cAAc,MAAM;AAEnD,QAAI,YAAY;AACf,YAAM,YAAY,IAAI,SAAS,IAAK,IAAI,CAAC,EAAsB,WAAW,KAAK,IAAI;AACnF,YAAM,YACL,IAAI,SAAS,IAAK,IAAI,IAAI,SAAS,CAAC,EAAsB,WAAW,KAAK,IAAI;AAE/E,YAAM,KAAK;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD,OAAO;AACN,YAAM,OAAO;AAAA,QACZ,aAAa,IAAI,IAAID,YAAW,UAAU,CAAC,CAAC,oCAAoC,KAAK,IAAI,CAAC,eAAe,QAAQ;AAAA,MAClH;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,yBACb,QACA,WACA,UACA,YACA,YACA,eACA,WACA,WACgB;AAChB,UAAM,aAAa,CAAC,MAAM,GAAG,YAAY,eAAe,eAAe,UAAU;AACjF,UAAM,SAAoB;AAAA,MACzB;AAAA,MACA,GAAG,WAAW,IAAI,CAAC,MAAM;AACxB,cAAM,aAAa,cAAc,OAAO,CAAC;AACzC,eAAO,aAAa,oBAAoB,WAAW,CAAC,KAAK,MAAM,UAAU,IAAI;AAAA,MAC9E,CAAC;AAAA,MACD;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAEA,UAAM,aAAa,IAAI,IAAI,WAAW,IAAI,CAAC,MAAMA,YAAW,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;AAC1E,UAAM,YAAY,IAAI;AAAA,MACrB,OAAO,IAAI,CAAC,MAAM,MAAM,CAAC,EAAE;AAAA,MAC3B,IAAI,IAAI,IAAI;AAAA,IACb;AACA,UAAM,YAAY,IAAI;AAAA,MACrB,WACE,MAAM,CAAC,EACP,IAAI,CAAC,MAAM,GAAGA,YAAW,CAAC,CAAC,eAAeA,YAAW,CAAC,CAAC,EAAE,EACzD,KAAK,IAAI;AAAA,IACZ;AAEA,UAAM,OAAO;AAAA,MACZ,kBAAkB,IAAI,IAAIA,YAAW,SAAS,CAAC,CAAC,KAAK,UAAU,aAAa,SAAS,oCAAoC,SAAS;AAAA,IACnI;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,yBAAwC;AACrD,QAAI,CAAC,KAAK,OAAQ;AAElB,eAAW,kBAAkB,OAAO,KAAK,KAAK,OAAO,WAAW,GAAG;AAClE,YAAM,KAAK,mBAAmB,cAAc;AAAA,IAC7C;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,mBAAmB,gBAAuC;AACvE,UAAM,gBAAgB,KAAK,QAAQ,YAAY,cAAc;AAC7D,QAAI,CAAC,cAAe;AAEpB,UAAM,SAAS,MAAM,KAAK,GACxB,OAAO;AAAA,MACP,UAAU,aAAa;AAAA,MACvB,MAAM,aAAa;AAAA,MACnB,MAAM,aAAa;AAAA,MACnB,WAAW,aAAa;AAAA,MACxB,UAAU,aAAa;AAAA,IACxB,CAAC,EACA,KAAK,YAAY,EACjB,MAAM,GAAG,aAAa,YAAY,cAAc,CAAC,EAEjD;AAAA,MACA,IAAI,aAAa,QAAQ;AAAA,MACzB,IAAI,aAAa,OAAO;AAAA,MACxB,IAAI,aAAa,eAAe;AAAA,IACjC;AAED,QAAI,OAAO,WAAW,EAAG;AAGzB,UAAM,UAAU,oBAAI,IAA2B;AAC/C,eAAW,MAAM,QAAQ;AACxB,UAAI,QAAQ,QAAQ,IAAI,GAAG,QAAQ;AACnC,UAAI,CAAC,OAAO;AACX,gBAAQ,CAAC;AACT,gBAAQ,IAAI,GAAG,UAAU,KAAK;AAAA,MAC/B;AACA,YAAM,KAAK,EAAE;AAAA,IACd;AAEA,UAAM,aAAa,OAAO,KAAK,cAAc,MAAM;AAGnD,eAAW,CAAC,UAAU,SAAS,KAAK,SAAS;AAC5C,YAAM,YAAY,UAAU,IAAI,CAAC,QAAQ;AAAA,QACxC,MAAM,GAAG;AAAA,QACT,MAAM,GAAG,SAAS,OAAO,KAAK,MAAM,GAAG,IAAI,IAAI;AAAA,QAC/C,WACC,GAAG,aAAa,OAAQ,KAAK,MAAM,GAAG,SAAS,IAAiC;AAAA,MAClF,EAAE;AACF,YAAM,aAAa,0BAA0B,SAAS;AAEtD,UAAI,YAAY;AACf,cAAM,YAAa,UAAU,CAAC,EAA4B;AAC1D,cAAM,YAAa,UAAU,UAAU,SAAS,CAAC,EAA4B;AAC7E,cAAM,KAAK;AAAA,UACV,KAAK;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAAA,MACD,OAAO;AACN,cAAM,KAAK,GAAG;AAAA,UACb,kBAAkB,IAAI,IAAIA,YAAW,cAAc,CAAC,CAAC,qDAAqD,QAAQ,QAAQ,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,gEAAgE,KAAK,IAAI,CAAC;AAAA,QAC9N;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAiB,YAAoB,SAAuC;AACnF,UAAM,cAAc,KAAK;AAAA,MACxB,SAAS,SAAS,CAAC;AAAA,MACnB,SAAS,kBAAkB;AAAA,IAC5B;AAEA,UAAM,QAAe;AAAA,MACpB,oBAAoB,IAAI,IAAIA,YAAW,UAAU,CAAC,CAAC,UAAU,WAAW;AAAA,IACzE;AAEA,QAAI,SAAS,SAAS;AACrB,YAAM,MAAM,QAAQ,mBAAmB,SAAS,SAAS;AACzD,YAAM,KAAK,IAAI,IAAI,aAAaA,YAAW,QAAQ,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC;AAAA,IACtE;AAEA,QAAI,SAAS,UAAU,QAAW;AACjC,YAAM,KAAK,aAAa,QAAQ,KAAK,EAAE;AAAA,IACxC;AAEA,QAAI,SAAS,WAAW,QAAW;AAClC,YAAM,KAAK,cAAc,QAAQ,MAAM,EAAE;AAAA,IAC1C;AAEA,WAAO,IAAI,KAAK,OAAO,IAAI,IAAI,EAAE,CAAC;AAAA,EACnC;AAAA,EAEQ,iBAAiB,OAAgC,gBAA8B;AACtF,UAAM,aAAoB,CAAC;AAE3B,QAAI,CAAC,gBAAgB;AACpB,iBAAW,KAAK,IAAI,IAAI,cAAc,CAAC;AAAA,IACxC;AAEA,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AACjD,iBAAW,KAAK,MAAM,IAAI,IAAIA,YAAW,GAAG,CAAC,CAAC,MAAM,KAAK,EAAE;AAAA,IAC5D;AAEA,QAAI,WAAW,WAAW,GAAG;AAC5B,aAAO,IAAI,IAAI,OAAO;AAAA,IACvB;AAEA,WAAO,IAAI,KAAK,YAAY,IAAI,IAAI,OAAO,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAMQ,eACP,KACA,eACqB;AACrB,UAAM,SAA6B,EAAE,IAAI,IAAI,GAAa;AAE1D,eAAW,CAAC,WAAW,UAAU,KAAK,OAAO,QAAQ,cAAc,MAAM,GAAG;AAC3E,UAAI,aAAa,KAAK;AACrB,eAAO,SAAS,IAAI,sBAAsB,IAAI,SAAS,GAAG,UAAU;AAAA,MACrE;AAAA,IACD;AAEA,QAAI,iBAAiB,IAAK,QAAO,cAAc,IAAI;AACnD,QAAI,iBAAiB,IAAK,QAAO,cAAc,IAAI;AAEnD,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,sBAAsB,YAAmD;AACtF,UAAM,OAAO,MAAM,KAAK,GACtB,OAAO,EACP,KAAK,YAAY,EACjB,MAAM,GAAG,aAAa,YAAY,UAAU,CAAC,EAC7C;AAAA,MACA,IAAI,aAAa,QAAQ;AAAA,MACzB,IAAI,aAAa,OAAO;AAAA,MACxB,IAAI,aAAa,cAAc;AAAA,IAChC;AAED,UAAM,UAAU,oBAAI,IAAqC;AACzD,UAAM,UAAU,oBAAI,IAAY;AAEhC,eAAW,OAAO,MAAM;AACvB,YAAM,WAAW,IAAI;AACrB,YAAM,OAAO,IAAI,SAAS,OAAO,KAAK,MAAM,IAAI,IAAI,IAAI;AAExD,cAAQ,IAAI,MAAM;AAAA,QACjB,KAAK;AACJ,cAAI,MAAM;AACT,oBAAQ,IAAI,UAAU,EAAE,IAAI,UAAU,GAAG,KAAK,CAAC;AAC/C,oBAAQ,OAAO,QAAQ;AAAA,UACxB;AACA;AAAA,QACD,KAAK;AACJ,cAAI,MAAM;AACT,kBAAM,WAAW,QAAQ,IAAI,QAAQ,KAAK,EAAE,IAAI,SAAS;AACzD,oBAAQ,IAAI,UAAU,EAAE,GAAG,UAAU,GAAG,KAAK,CAAC;AAC9C,oBAAQ,OAAO,QAAQ;AAAA,UACxB;AACA;AAAA,QACD,KAAK;AACJ,kBAAQ,IAAI,QAAQ;AACpB;AAAA,MACF;AAAA,IACD;AAEA,eAAW,MAAM,SAAS;AACzB,cAAQ,OAAO,EAAE;AAAA,IAClB;AAEA,WAAO,MAAM,KAAK,QAAQ,OAAO,CAAC;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,aAA4B;AACzC,UAAM,KAAK,aAAa;AAGxB,UAAM,OAAO,MAAM,KAAK,GACtB,OAAO;AAAA,MACP,QAAQ,YAAY;AAAA,MACpB,mBAAmB,YAAY;AAAA,IAChC,CAAC,EACA,KAAK,WAAW;AAElB,eAAW,OAAO,MAAM;AACvB,WAAK,cAAc,IAAI,IAAI,QAAQ,IAAI,iBAAiB;AAAA,IACzD;AAAA,EACD;AAAA,EAEA,MAAc,eAA8B;AAM3C,UAAM,KAAK,GAAG,YAAY,OAAO,OAAO;AACvC,YAAM,GAAG,QAAQ,4EAA4E;AAE7F,YAAM,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAkBhB;AAKD,YAAM,GAAG,QAAQ,oEAAoE;AAIrF,YAAM,GAAG,QAAQ,wEAAwE;AAEzF,YAAM,GAAG;AAAA,QACR;AAAA,MACD;AACA,YAAM,GAAG,QAAQ,yEAAyE;AAC1F,YAAM,GAAG,QAAQ,wEAAwE;AACzF,YAAM,GAAG;AAAA,QACR;AAAA,MACD;AAEA,YAAM,GAAG;AAAA,QACR;AAAA,MACD;AAEA,YAAM,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMhB;AASD,YAAM,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,IAKhB;AAMD,YAAM,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAShB;AACD,YAAM,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,IAKhB;AAAA,IACF,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,gBAAgB,IAEV;AACnB,UAAM,OAAQ,MAAM,GAAG;AAAA,MACtB;AAAA,IACD;AACA,UAAM,QAAQ,KAAK,CAAC,GAAG;AACvB,QAAI,UAAU,UAAa,UAAU,MAAM;AAK1C,YAAM,IAAI;AAAA,QACT;AAAA,MACD;AAAA,IACD;AACA,WAAO,OAAO,KAAK;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAMQ,mBACP,IACA,YACA,aACmC;AACnC,WAAO;AAAA,MACN,IAAI,GAAG;AAAA,MACP,QAAQ,GAAG;AAAA,MACX,MAAM,GAAG;AAAA,MACT,YAAY,GAAG;AAAA,MACf,UAAU,GAAG;AAAA,MACb,MAAM,GAAG,SAAS,OAAO,KAAK,UAAU,GAAG,IAAI,IAAI;AAAA,MACnD,cAAc,GAAG,iBAAiB,OAAO,KAAK,UAAU,GAAG,YAAY,IAAI;AAAA,MAC3E,WACC,GAAG,aAAa,OAAO,KAAK,GAAG,SAAS,EAAE,SAAS,IAAI,KAAK,UAAU,GAAG,SAAS,IAAI;AAAA,MACvF,UAAU,GAAG,UAAU;AAAA,MACvB,SAAS,GAAG,UAAU;AAAA,MACtB,iBAAiB,GAAG,UAAU;AAAA,MAC9B,gBAAgB,GAAG;AAAA,MACnB,YAAY,KAAK,UAAU,GAAG,UAAU;AAAA,MACxC,eAAe,GAAG;AAAA,MAClB;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,qBAAqB,KAAkD;AAC9E,UAAM,YACL,IAAI,aAAa,OAAQ,KAAK,MAAM,IAAI,SAAS,IAAiC;AACnF,WAAO;AAAA,MACN,IAAI,IAAI;AAAA,MACR,QAAQ,IAAI;AAAA,MACZ,MAAM,IAAI;AAAA,MACV,YAAY,IAAI;AAAA,MAChB,UAAU,IAAI;AAAA,MACd,MAAM,IAAI,SAAS,OAAO,KAAK,MAAM,IAAI,IAAI,IAAI;AAAA,MACjD,cAAc,IAAI,iBAAiB,OAAO,KAAK,MAAM,IAAI,YAAY,IAAI;AAAA,MACzE,WAAW;AAAA,QACV,UAAU,IAAI;AAAA,QACd,SAAS,IAAI;AAAA,QACb,QAAQ,IAAI;AAAA,MACb;AAAA,MACA,gBAAgB,IAAI;AAAA,MACpB,YAAY,KAAK,MAAM,IAAI,UAAU;AAAA,MACrC,eAAe,IAAI;AAAA,MACnB,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IAClC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAMQ,aAAmB;AAC1B,QAAI,KAAK,QAAQ;AAChB,YAAM,IAAI,MAAM,+BAA+B;AAAA,IAChD;AAAA,EACD;AAAA,EAEQ,eAAqB;AAC5B,QAAI,CAAC,KAAK,QAAQ;AACjB,YAAM,IAAI;AAAA,QACT;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,iBAAiB,YAA0B;AAClD,UAAM,SAAS,KAAK;AACpB,QAAI,CAAC,OAAO,YAAY,UAAU,GAAG;AACpC,YAAM,IAAI;AAAA,QACT,uBAAuB,UAAU,iBAAiB,OAAO,KAAK,OAAO,WAAW,EAAE,KAAK,IAAI,CAAC;AAAA,MAC7F;AAAA,IACD;AAAA,EACD;AACD;AAKA,eAAsB,0BAA0B,SAGf;AAChC,QAAM,EAAE,gBAAgB,UAAU,IAAI,MAAM,iBAAiB;AAC7D,QAAM,SAAS,eAAe,QAAQ,gBAAgB;AACtD,QAAM,KAAK,UAAU,MAAM;AAE3B,SAAO,IAAI,oBAAoB,IAAI,QAAQ,MAAM;AAClD;AAEA,eAAe,mBAGZ;AACF,MAAI;AACH,UAAM,gBAAgB,IAAI,SAAS,aAAa,0BAA0B;AAI1E,UAAM,cAAe,MAAM,cAAc,UAAU;AACnD,UAAM,aAAc,MAAM,cAAc,yBAAyB;AAIjE,WAAO;AAAA,MACN,gBAAgB,YAAY;AAAA,MAC5B,WAAW,WAAW;AAAA,IACvB;AAAA,EACD,QAAQ;AACP,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AACD;;;AEpkCA,SAAS,qBAAqB;AAE9B,SAAS,kBAAAE,iBAAgB,cAAAC,mBAAkB;AAG3C,SAAS,OAAAC,MAAK,OAAAC,MAAK,WAAAC,UAAS,SAAAC,QAAO,MAAAC,KAAI,MAAAC,KAAI,OAAAC,YAAW;;;ACLtD,SAAS,SAAAC,QAAO,WAAAC,UAAS,aAAa,QAAAC,aAAY;AAU3C,IAAM,aAAa;AAAA,EACzB;AAAA,EACA;AAAA,IACC,IAAIA,MAAK,IAAI,EAAE,WAAW;AAAA,IAC1B,QAAQA,MAAK,SAAS,EAAE,QAAQ;AAAA,IAChC,MAAMA,MAAK,MAAM,EAAE,QAAQ;AAAA,IAC3B,YAAYA,MAAK,YAAY,EAAE,QAAQ;AAAA,IACvC,UAAUA,MAAK,WAAW,EAAE,QAAQ;AAAA,IACpC,MAAMA,MAAK,MAAM;AAAA;AAAA,IACjB,cAAcA,MAAK,eAAe;AAAA;AAAA,IAClC,WAAWA,MAAK,YAAY;AAAA;AAAA,IAC5B,UAAUD,SAAQ,WAAW,EAAE,QAAQ;AAAA,IACvC,SAASA,SAAQ,SAAS,EAAE,QAAQ;AAAA,IACpC,iBAAiBC,MAAK,mBAAmB,EAAE,QAAQ;AAAA,IACnD,gBAAgBD,SAAQ,iBAAiB,EAAE,QAAQ;AAAA,IACnD,YAAYC,MAAK,aAAa,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA;AAAA,IACtD,eAAeD,SAAQ,gBAAgB,EAAE,QAAQ;AAAA,IACjD,YAAYA,SAAQ,aAAa,EAAE,QAAQ;AAAA;AAAA;AAAA;AAAA,IAI3C,aAAaA,SAAQ,cAAc;AAAA,EACpC;AAAA,EACA,CAAC,WAAW;AAAA,IACX,YAAYD,OAAM,cAAc,EAAE,GAAG,MAAM,QAAQ,MAAM,cAAc;AAAA,IACvE,eAAeA,OAAM,gBAAgB,EAAE,GAAG,MAAM,UAAU;AAAA,IAC1D,aAAaA,OAAM,cAAc,EAAE,GAAG,MAAM,UAAU;AAAA,IACtD,aAAaA,OAAM,kBAAkB,EAAE,GAAG,MAAM,WAAW;AAAA,EAC5D;AACD;AAEO,IAAM,YAAY,YAAY,cAAc;AAAA,EAClD,QAAQE,MAAK,SAAS,EAAE,WAAW;AAAA,EACnC,mBAAmBD,SAAQ,qBAAqB,EAAE,QAAQ;AAAA,EAC1D,YAAYA,SAAQ,cAAc,EAAE,QAAQ;AAC7C,CAAC;AAEM,IAAM,kBAAkB,YAAY,oBAAoB;AAAA,EAC9D,IAAIA,SAAQ,IAAI,EAAE,WAAW;AAAA,EAC7B,OAAOA,SAAQ,OAAO,EAAE,QAAQ;AACjC,CAAC;;;ADzBD,IAAM,aAAa,cAAc,YAAY,GAAG;AAUzC,IAAM,oBAAN,MAA+C;AAAA,EACpC;AAAA,EACA;AAAA,EACT,SAAkC;AAAA,EAClC,SAAS;AAAA,EAEjB,YAAY,IAA2B,QAAiB;AACvD,SAAK,KAAK;AACV,SAAK,SAAS,UAAUE,gBAAe;AACvC,SAAK,aAAa;AAAA,EACnB;AAAA,EAEA,mBAAkC;AACjC,SAAK,WAAW;AAChB,UAAM,OAAO,KAAK,GAAG,OAAO,EAAE,KAAK,SAAS,EAAE,IAAI;AAClD,UAAM,KAAoB,oBAAI,IAAI;AAClC,eAAW,OAAO,MAAM;AACvB,SAAG,IAAI,IAAI,QAAQ,IAAI,iBAAiB;AAAA,IACzC;AACA,WAAO;AAAA,EACR;AAAA,EAEA,YAAoB;AACnB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,YAAqC;AACpC,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,MAAM,UAAU,QAAyC;AACxD,SAAK,WAAW;AAChB,SAAK,SAAS;AAGd,UAAM,gBAAgB,yBAAyB,QAAQ,QAAQ;AAC/D,eAAW,QAAQ,eAAe;AACjC,UAAI,KAAK,WAAW,mBAAmB,GAAG;AACzC,cAAM,WAAW,KAAK,QAAQ,uBAAuB,EAAE;AACvD,YAAI;AACH,eAAK,GAAG,IAAIC,KAAI,IAAI,QAAQ,CAAC;AAAA,QAC9B,SAAS,GAAG;AAGX,gBAAM,MAAM,aAAa,QAAQ,EAAE,UAAU;AAC7C,gBAAM,WAAW,aAAa,SAAS,EAAE,iBAAiB,QAAQ,EAAE,MAAM,UAAU;AACpF,cAAI,CAAC,IAAI,SAAS,kBAAkB,KAAK,CAAC,SAAS,SAAS,kBAAkB,GAAG;AAChF,kBAAM;AAAA,UACP;AAAA,QACD;AAAA,MACD,OAAO;AACN,aAAK,GAAG,IAAIA,KAAI,IAAI,IAAI,CAAC;AAAA,MAC1B;AAAA,IACD;AAGA,UAAM,KAAK,uBAAuB;AAAA,EACnC;AAAA,EAEA,MAAM,qBAAqB,IAAqC;AAC/D,SAAK,WAAW;AAEhB,UAAM,MAAM,KAAK,IAAI;AAGrB,UAAM,SAAS,KAAK,GAAG,YAAY,CAAC,OAAO;AAG1C,YAAM,WAAW,GAAG;AAAA,QACnBA,4CAA2C,GAAG,EAAE;AAAA,MACjD;AACA,UAAI,SAAS,SAAS,GAAG;AACxB,eAAO;AAAA,MACR;AAEA,YAAM,MAAM,KAAK,mBAAmB,IAAI,KAAK,KAAK,gBAAgB,EAAE,CAAC;AACrE,SAAG,OAAO,UAAU,EAAE,OAAO,GAAG,EAAE,IAAI;AAGtC,SAAG,OAAO,SAAS,EACjB,OAAO;AAAA,QACP,QAAQ,GAAG;AAAA,QACX,mBAAmB,GAAG;AAAA,QACtB,YAAY;AAAA,MACb,CAAC,EACA,mBAAmB;AAAA,QACnB,QAAQ,UAAU;AAAA,QAClB,KAAK;AAAA,UACJ,mBAAmBA,WAAU,UAAU,iBAAiB,KAAK,GAAG,cAAc;AAAA,UAC9E,YAAYA,OAAM,GAAG;AAAA,QACtB;AAAA,MACD,CAAC,EACA,IAAI;AAGN,UAAI,KAAK,QAAQ,YAAY,GAAG,UAAU,GAAG;AAC5C,aAAK,0BAA0B,IAAI,GAAG,YAAY,GAAG,QAAQ;AAAA,MAC9D;AAEA,aAAO;AAAA,IACR,CAAC;AAED,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,kBAAkB,QAAgB,SAAiB,OAAqC;AAC7F,SAAK,WAAW;AAEhB,UAAM,OAAO,KAAK,GAChB,OAAO,EACP,KAAK,UAAU,EACf,MAAMC,KAAIC,IAAG,WAAW,QAAQ,MAAM,GAAGC,SAAQ,WAAW,gBAAgB,SAAS,KAAK,CAAC,CAAC,EAC5F,QAAQC,KAAI,WAAW,cAAc,CAAC,EACtC,IAAI;AAEN,WAAO,KAAK,IAAI,CAAC,QAAQ,KAAK,qBAAqB,GAAG,CAAC;AAAA,EACxD;AAAA,EAEA,MAAM,oBAAqC;AAC1C,SAAK,WAAW;AAEhB,UAAM,SAAS,KAAK,GAAG,OAAO,EAAE,OAAOC,OAAM,EAAE,CAAC,EAAE,KAAK,UAAU,EAAE,IAAI;AACvE,WAAO,OAAO,CAAC,GAAG,SAAS;AAAA,EAC5B;AAAA,EAEA,MAAM,yBAA0C;AAC/C,SAAK,WAAW;AAChB,UAAM,OAAO,KAAK,GAAG;AAAA,MACpBL;AAAA,IACD;AACA,WAAO,KAAK,CAAC,GAAG,KAAK;AAAA,EACtB;AAAA,EAEA,MAAM,2BACL,uBACA,OACgC;AAChC,SAAK,WAAW;AAChB,UAAM,OAAO,KAAK,GAChB,OAAO,EACP,KAAK,UAAU,EACf,MAAMM,IAAG,WAAW,aAAa,qBAAqB,CAAC,EACvD,QAAQF,KAAI,WAAW,WAAW,CAAC,EACnC,MAAM,KAAK,EACX,IAAI;AACN,WAAO,KAAK,IAAI,CAAC,SAAS;AAAA,MACzB,WAAW,KAAK,qBAAqB,GAAG;AAAA,MACxC,kBAAkB,IAAI,eAAe;AAAA,IACtC,EAAE;AAAA,EACH;AAAA,EAEA,MAAM,sBAAsB,YAAmD;AAC9E,SAAK,WAAW;AAGhB,QAAI,KAAK,QAAQ,YAAY,UAAU,GAAG;AACzC,aAAO,KAAK,gBAAgB,UAAU;AAAA,IACvC;AAGA,WAAO,KAAK,sBAAsB,UAAU;AAAA,EAC7C;AAAA,EAEA,MAAM,gBACL,YACA,SACgC;AAChC,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,SAAK,iBAAiB,UAAU;AAEhC,UAAM,SAAS,KAAK;AACpB,UAAM,gBAAgB,OAAO,YAAY,UAAU;AAKnD,QAAI,SAAS,OAAO;AACnB,iBAAW,OAAO,OAAO,KAAK,QAAQ,KAAK,GAAG;AAC7C,0BAAkB,YAAY,KAAK,MAAM;AAAA,MAC1C;AAAA,IACD;AACA,QAAI,SAAS,SAAS;AACrB,wBAAkB,YAAY,QAAQ,SAAS,MAAM;AAAA,IACtD;AAEA,UAAM,QAAQ,KAAK,iBAAiB,YAAY,OAAO;AACvD,UAAM,OAAO,KAAK,GAAG,IAA6B,KAAK;AAEvD,WAAO,KAAK,IAAI,CAAC,QAAQ,KAAK,eAAe,KAAK,aAAa,CAAC;AAAA,EACjE;AAAA,EAEA,MAAM,WAAW,YAAoB,IAAgD;AACpF,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,SAAK,iBAAiB,UAAU;AAEhC,UAAM,SAAS,KAAK;AACpB,UAAM,gBAAgB,OAAO,YAAY,UAAU;AAGnD,UAAM,QAAQJ,qBAAoBA,KAAI,IAAIO,YAAW,UAAU,CAAC,CAAC,eAAe,EAAE;AAClF,UAAM,OAAO,KAAK,GAAG,IAA6B,KAAK;AAEvD,QAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,WAAO,KAAK,eAAe,KAAK,CAAC,GAA8B,aAAa;AAAA,EAC7E;AAAA,EAEA,MAAM,gBAAgB,YAAoB,OAAkD;AAC3F,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,SAAK,iBAAiB,UAAU;AAEhC,UAAM,SAAS,KAAK;AACpB,QAAI,OAAO;AACV,iBAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACrC,0BAAkB,YAAY,KAAK,MAAM;AAAA,MAC1C;AAAA,IACD;AAEA,UAAM,cAAc,KAAK,iBAAiB,SAAS,CAAC,GAAG,KAAK;AAC5D,UAAM,QAAQP,mCAAkCA,KAAI,IAAIO,YAAW,UAAU,CAAC,CAAC,UAAU,WAAW;AACpG,UAAM,OAAO,KAAK,GAAG,IAAqB,KAAK;AAC/C,WAAO,KAAK,CAAC,GAAG,OAAO;AAAA,EACxB;AAAA,EAEA,MAAM,QAAuB;AAC5B,SAAK,SAAS;AAAA,EACf;AAAA,EAEA,MAAM,eAAoC;AACzC,SAAK,WAAW;AAEhB,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,6BAAiB;AAG5D,UAAM,OAAO,KAAK,GAAG,OAAO,EAAE,KAAK,UAAU,EAAE,QAAQH,KAAI,WAAW,WAAW,CAAC,EAAE,IAAI;AACxF,UAAM,eAAe,KAAK,IAAI,CAAC,QAAQ,KAAK,qBAAqB,GAAG,CAAC;AACrE,UAAM,KAAK,KAAK,iBAAiB;AAEjC,WAAO,kBAAkB,KAAK,QAAQ,cAAc,EAAE;AAAA,EACvD;AAAA,EAEA,MAAM,aACL,MACA,OAC4D;AAC5D,SAAK,WAAW;AAEhB,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,6BAAiB;AAC5D,UAAM,EAAE,YAAY,KAAK,cAAc,IAAI,kBAAkB,IAAI;AAEjE,QAAI,OAAO;AACV,UAAI,WAAW;AACf,iBAAW,MAAM,KAAK;AACrB,cAAM,SAAS,MAAM,KAAK,qBAAqB,EAAE;AACjD,YAAI,WAAW,UAAW;AAAA,MAC3B;AACA,aAAO,EAAE,oBAAoB,UAAU,SAAS,KAAK;AAAA,IACtD;AAGA,SAAK,GAAG,YAAY,CAAC,OAAO;AAC3B,SAAG,IAAIJ,KAAI,IAAI,wBAAwB,CAAC;AACxC,SAAG,IAAIA,KAAI,IAAI,wBAAwB,CAAC;AACxC,SAAG,OAAO,eAAe,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,MAAME,IAAG,gBAAgB,IAAI,CAAC,CAAC,EAAE,IAAI;AAElF,iBAAW,CAAC,KAAK,GAAG,KAAK,eAAe;AACvC,WAAG,OAAO,SAAS,EACjB,OAAO,EAAE,QAAQ,KAAK,mBAAmB,KAAK,YAAY,KAAK,IAAI,EAAE,CAAC,EACtE,IAAI;AAAA,MACP;AAGA,UAAI,cAAc;AAClB,iBAAW,MAAM,KAAK;AACrB,uBAAe;AACf,cAAM,MAAM,KAAK,mBAAmB,IAAI,KAAK,IAAI,GAAG,WAAW;AAC/D,WAAG,OAAO,UAAU,EAAE,OAAO,GAAG,EAAE,IAAI;AAAA,MACvC;AACA,SAAG,OAAO,eAAe,EAAE,IAAI,EAAE,OAAO,YAAY,CAAC,EAAE,MAAMA,IAAG,gBAAgB,IAAI,CAAC,CAAC,EAAE,IAAI;AAAA,IAC7F,CAAC;AAED,WAAO,EAAE,oBAAoB,IAAI,QAAQ,SAAS,KAAK;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,0BACP,QACA,YACA,UACO;AACP,UAAM,gBAAgB,KAAK,QAAQ,YAAY,UAAU;AACzD,QAAI,CAAC,cAAe;AAIpB,UAAM,MAAM,OACV,OAAO;AAAA,MACP,MAAM,WAAW;AAAA,MACjB,MAAM,WAAW;AAAA,MACjB,WAAW,WAAW;AAAA,MACtB,UAAU,WAAW;AAAA,IACtB,CAAC,EACA,KAAK,UAAU,EACf,MAAMD,KAAIC,IAAG,WAAW,YAAY,UAAU,GAAGA,IAAG,WAAW,UAAU,QAAQ,CAAC,CAAC,EACnF,QAAQE,KAAI,WAAW,QAAQ,GAAGA,KAAI,WAAW,OAAO,GAAGA,KAAI,WAAW,eAAe,CAAC,EAC1F,IAAI;AAGN,UAAM,YAAY,IAAI,IAAI,CAAC,QAAQ;AAAA,MAClC,MAAM,GAAG;AAAA,MACT,MAAM,GAAG,SAAS,OAAO,KAAK,MAAM,GAAG,IAAI,IAAI;AAAA,MAC/C,WACC,GAAG,aAAa,OAAQ,KAAK,MAAM,GAAG,SAAS,IAAiC;AAAA,IAClF,EAAE;AACF,UAAM,aAAa,0BAA0B,SAAS;AAEtD,UAAM,aAAa,OAAO,KAAK,cAAc,MAAM;AAEnD,QAAI,YAAY;AAEf,YAAM,YAAY,IAAI,SAAS,IAAK,IAAI,CAAC,EAAsB,WAAW,KAAK,IAAI;AACnF,YAAM,YACL,IAAI,SAAS,IAAK,IAAI,IAAI,SAAS,CAAC,EAAsB,WAAW,KAAK,IAAI;AAE/E,WAAK;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD,OAAO;AAEN,aAAO;AAAA,QACNJ,cAAaA,KAAI,IAAIO,YAAW,UAAU,CAAC,CAAC,oCAAoC,KAAK,IAAI,CAAC,eAAe,QAAQ;AAAA,MAClH;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,yBACP,QACA,WACA,UACA,YACA,YACA,eACA,WACA,WACO;AACP,UAAM,aAAa,CAAC,MAAM,GAAG,YAAY,eAAe,eAAe,UAAU;AACjF,UAAM,SAAoB;AAAA,MACzB;AAAA,MACA,GAAG,WAAW,IAAI,CAAC,MAAM;AACxB,cAAM,aAAa,cAAc,OAAO,CAAC;AACzC,eAAO,aAAa,oBAAoB,WAAW,CAAC,KAAK,MAAM,UAAU,IAAI;AAAA,MAC9E,CAAC;AAAA,MACD;AAAA,MACA;AAAA,MACA;AAAA;AAAA,IACD;AAEA,UAAM,aAAaP,KAAI,IAAI,WAAW,IAAI,CAAC,MAAMO,YAAW,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;AAC1E,UAAM,YAAYP,KAAI;AAAA,MACrB,OAAO,IAAI,CAAC,MAAMA,OAAM,CAAC,EAAE;AAAA,MAC3BA,KAAI,IAAI,IAAI;AAAA,IACb;AACA,UAAM,YAAYA,KAAI;AAAA,MACrB,WACE,MAAM,CAAC,EACP,IAAI,CAAC,MAAM,GAAGO,YAAW,CAAC,CAAC,eAAeA,YAAW,CAAC,CAAC,EAAE,EACzD,KAAK,IAAI;AAAA,IACZ;AAEA,WAAO;AAAA,MACNP,mBAAkBA,KAAI,IAAIO,YAAW,SAAS,CAAC,CAAC,KAAK,UAAU,aAAa,SAAS,oCAAoC,SAAS;AAAA,IACnI;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,yBAAwC;AACrD,QAAI,CAAC,KAAK,OAAQ;AAElB,eAAW,kBAAkB,OAAO,KAAK,KAAK,OAAO,WAAW,GAAG;AAClE,WAAK,mBAAmB,cAAc;AAAA,IACvC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,gBAA8B;AACxD,UAAM,gBAAgB,KAAK,QAAQ,YAAY,cAAc;AAC7D,QAAI,CAAC,cAAe;AAGpB,UAAM,SAAS,KAAK,GAClB,OAAO;AAAA,MACP,UAAU,WAAW;AAAA,MACrB,MAAM,WAAW;AAAA,MACjB,MAAM,WAAW;AAAA,MACjB,WAAW,WAAW;AAAA,MACtB,UAAU,WAAW;AAAA,IACtB,CAAC,EACA,KAAK,UAAU,EACf,MAAML,IAAG,WAAW,YAAY,cAAc,CAAC,EAC/C,QAAQE,KAAI,WAAW,QAAQ,GAAGA,KAAI,WAAW,OAAO,GAAGA,KAAI,WAAW,eAAe,CAAC,EAC1F,IAAI;AAEN,QAAI,OAAO,WAAW,EAAG;AAGzB,UAAM,UAAU,oBAAI,IAA2B;AAC/C,eAAW,MAAM,QAAQ;AACxB,UAAI,QAAQ,QAAQ,IAAI,GAAG,QAAQ;AACnC,UAAI,CAAC,OAAO;AACX,gBAAQ,CAAC;AACT,gBAAQ,IAAI,GAAG,UAAU,KAAK;AAAA,MAC/B;AACA,YAAM,KAAK,EAAE;AAAA,IACd;AAGA,UAAM,aAAa,OAAO,KAAK,cAAc,MAAM;AACnD,SAAK,GAAG,YAAY,CAAC,OAAO;AAC3B,iBAAW,CAAC,UAAU,SAAS,KAAK,SAAS;AAC5C,cAAM,YAAY,UAAU,IAAI,CAAC,QAAQ;AAAA,UACxC,MAAM,GAAG;AAAA,UACT,MAAM,GAAG,SAAS,OAAO,KAAK,MAAM,GAAG,IAAI,IAAI;AAAA,UAC/C,WACC,GAAG,aAAa,OAAQ,KAAK,MAAM,GAAG,SAAS,IAAiC;AAAA,QAClF,EAAE;AACF,cAAM,aAAa,0BAA0B,SAAS;AAEtD,YAAI,YAAY;AACf,gBAAM,YAAa,UAAU,CAAC,EAA4B;AAC1D,gBAAM,YAAa,UAAU,UAAU,SAAS,CAAC,EAA4B;AAC7E,eAAK;AAAA,YACJ;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACD;AAAA,QACD,OAAO;AACN,aAAG;AAAA,YACFJ,mBAAkBA,KAAI,IAAIO,YAAW,cAAc,CAAC,CAAC,qDAAqD,QAAQ,QAAQ,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,gEAAgE,KAAK,IAAI,CAAC;AAAA,UAC9N;AAAA,QACD;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAiB,YAAoB,SAAuC;AACnF,UAAM,cAAc,KAAK;AAAA,MACxB,SAAS,SAAS,CAAC;AAAA,MACnB,SAAS,kBAAkB;AAAA,IAC5B;AAEA,UAAM,QAAe;AAAA,MACpBP,qBAAoBA,KAAI,IAAIO,YAAW,UAAU,CAAC,CAAC,UAAU,WAAW;AAAA,IACzE;AAEA,QAAI,SAAS,SAAS;AACrB,YAAM,MAAM,QAAQ,mBAAmB,SAAS,SAAS;AACzD,YAAM,KAAKP,KAAI,IAAI,aAAaO,YAAW,QAAQ,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC;AAAA,IACtE;AAEA,QAAI,SAAS,UAAU,QAAW;AACjC,YAAM,KAAKP,cAAa,QAAQ,KAAK,EAAE;AAAA,IACxC;AAEA,QAAI,SAAS,WAAW,QAAW;AAClC,YAAM,KAAKA,eAAc,QAAQ,MAAM,EAAE;AAAA,IAC1C;AAEA,WAAOA,KAAI,KAAK,OAAOA,KAAI,IAAI,EAAE,CAAC;AAAA,EACnC;AAAA,EAEQ,iBAAiB,OAAgC,gBAA8B;AACtF,UAAM,aAAoB,CAAC;AAE3B,QAAI,CAAC,gBAAgB;AACpB,iBAAW,KAAKA,KAAI,IAAI,cAAc,CAAC;AAAA,IACxC;AAEA,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AACjD,iBAAW,KAAKA,OAAMA,KAAI,IAAIO,YAAW,GAAG,CAAC,CAAC,MAAM,KAAK,EAAE;AAAA,IAC5D;AAEA,QAAI,WAAW,WAAW,GAAG;AAC5B,aAAOP,KAAI,IAAI,OAAO;AAAA,IACvB;AAEA,WAAOA,KAAI,KAAK,YAAYA,KAAI,IAAI,OAAO,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAMQ,eACP,KACA,eACqB;AACrB,UAAM,SAA6B,EAAE,IAAI,IAAI,GAAa;AAE1D,eAAW,CAAC,WAAW,UAAU,KAAK,OAAO,QAAQ,cAAc,MAAM,GAAG;AAC3E,UAAI,aAAa,KAAK;AACrB,eAAO,SAAS,IAAI,sBAAsB,IAAI,SAAS,GAAG,UAAU;AAAA,MACrE;AAAA,IACD;AAGA,QAAI,iBAAiB,IAAK,QAAO,cAAc,IAAI;AACnD,QAAI,iBAAiB,IAAK,QAAO,cAAc,IAAI;AAEnD,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAMQ,sBAAsB,YAA0C;AACvE,UAAM,OAAO,KAAK,GAChB,OAAO,EACP,KAAK,UAAU,EACf,MAAME,IAAG,WAAW,YAAY,UAAU,CAAC,EAC3C,QAAQE,KAAI,WAAW,QAAQ,GAAGA,KAAI,WAAW,OAAO,GAAGA,KAAI,WAAW,cAAc,CAAC,EACzF,IAAI;AAEN,UAAM,UAAU,oBAAI,IAAqC;AACzD,UAAM,UAAU,oBAAI,IAAY;AAEhC,eAAW,OAAO,MAAM;AACvB,YAAM,WAAW,IAAI;AACrB,YAAM,OAAO,IAAI,SAAS,OAAO,KAAK,MAAM,IAAI,IAAI,IAAI;AAExD,cAAQ,IAAI,MAAM;AAAA,QACjB,KAAK;AACJ,cAAI,MAAM;AACT,oBAAQ,IAAI,UAAU,EAAE,IAAI,UAAU,GAAG,KAAK,CAAC;AAC/C,oBAAQ,OAAO,QAAQ;AAAA,UACxB;AACA;AAAA,QACD,KAAK;AACJ,cAAI,MAAM;AACT,kBAAM,WAAW,QAAQ,IAAI,QAAQ,KAAK,EAAE,IAAI,SAAS;AACzD,oBAAQ,IAAI,UAAU,EAAE,GAAG,UAAU,GAAG,KAAK,CAAC;AAC9C,oBAAQ,OAAO,QAAQ;AAAA,UACxB;AACA;AAAA,QACD,KAAK;AACJ,kBAAQ,IAAI,QAAQ;AACpB;AAAA,MACF;AAAA,IACD;AAEA,eAAW,MAAM,SAAS;AACzB,cAAQ,OAAO,EAAE;AAAA,IAClB;AAEA,WAAO,MAAM,KAAK,QAAQ,OAAO,CAAC;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,eAAqB;AAC5B,SAAK,GAAG,IAAIJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAkBX;AAMD,QAAI;AACH,WAAK,GAAG,IAAIA,uDAAsD;AAAA,IACnE,SAAS,GAAG;AACX,YAAM,MAAM,aAAa,QAAQ,EAAE,UAAU;AAC7C,YAAM,WAAW,aAAa,SAAS,EAAE,iBAAiB,QAAQ,EAAE,MAAM,UAAU;AACpF,UAAI,CAAC,IAAI,SAAS,kBAAkB,KAAK,CAAC,SAAS,SAAS,kBAAkB,GAAG;AAChF,cAAM;AAAA,MACP;AAAA,IACD;AAKA,QAAI;AACH,WAAK,GAAG,IAAIA,4DAA2D;AAAA,IACxE,SAAS,GAAG;AACX,YAAM,MAAM,aAAa,QAAQ,EAAE,UAAU;AAC7C,YAAM,WAAW,aAAa,SAAS,EAAE,iBAAiB,QAAQ,EAAE,MAAM,UAAU;AACpF,UAAI,CAAC,IAAI,SAAS,kBAAkB,KAAK,CAAC,SAAS,SAAS,kBAAkB,GAAG;AAChF,cAAM;AAAA,MACP;AAAA,IACD;AAEA,SAAK,GAAG,IAAIA;AAAA;AAAA,GAEX;AAED,SAAK,GAAG,IAAIA;AAAA;AAAA,GAEX;AAED,SAAK,GAAG,IAAIA;AAAA;AAAA;AAAA;AAAA,GAIX;AAED,SAAK,GAAG,IAAIA;AAAA;AAAA,GAEX;AAED,SAAK,GAAG,IAAIA;AAAA;AAAA,GAEX;AAGD,SAAK,GAAG,IAAIA;AAAA;AAAA,GAEX;AAED,SAAK,GAAG,IAAIA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAMX;AAED,SAAK,GAAG,IAAIA;AAAA;AAAA;AAAA;AAAA;AAAA,GAKX;AAED,SAAK,yBAAyB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,2BAAiC;AACxC,SAAK,GAAG,YAAY,CAAC,OAAO;AAC3B,YAAM,SAAS,GAAG;AAAA,QACjBA;AAAA,MACD;AACA,UAAI,OAAO,OAAO,CAAC,GAAG,KAAK;AAC3B,YAAM,WAAW,GAAG;AAAA,QACnBA;AAAA,MACD;AACA,iBAAW,OAAO,UAAU;AAC3B,gBAAQ;AACR,WAAG,IAAIA,4CAA2C,IAAI,eAAe,IAAI,EAAE,EAAE;AAAA,MAC9E;AACA,SAAG,OAAO,eAAe,EACvB,OAAO,EAAE,IAAI,GAAG,OAAO,KAAK,CAAC,EAC7B,mBAAmB;AAAA,QACnB,QAAQ,gBAAgB;AAAA,QACxB,KAAK;AAAA,UACJ,OAAOA,WAAU,gBAAgB,KAAK,KAAK,IAAI;AAAA,QAChD;AAAA,MACD,CAAC,EACA,IAAI;AAAA,IACP,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,gBAAgB,IAAmC;AAC1D,UAAM,OAAO,GACX,OAAO,eAAe,EACtB,IAAI,EAAE,OAAOA,OAAM,gBAAgB,KAAK,OAAO,CAAC,EAChD,MAAME,IAAG,gBAAgB,IAAI,CAAC,CAAC,EAC/B,UAAU,EAAE,OAAO,gBAAgB,MAAM,CAAC,EAC1C,IAAI;AACN,UAAM,QAAQ,KAAK,CAAC,GAAG;AACvB,QAAI,UAAU,UAAa,UAAU,MAAM;AAC1C,YAAM,IAAI;AAAA,QACT;AAAA,MACD;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAMQ,mBACP,IACA,YACA,aACiC;AACjC,WAAO;AAAA,MACN,IAAI,GAAG;AAAA,MACP,QAAQ,GAAG;AAAA,MACX,MAAM,GAAG;AAAA,MACT,YAAY,GAAG;AAAA,MACf,UAAU,GAAG;AAAA,MACb,MAAM,GAAG,SAAS,OAAO,KAAK,UAAU,GAAG,IAAI,IAAI;AAAA,MACnD,cAAc,GAAG,iBAAiB,OAAO,KAAK,UAAU,GAAG,YAAY,IAAI;AAAA,MAC3E,WACC,GAAG,aAAa,OAAO,KAAK,GAAG,SAAS,EAAE,SAAS,IAAI,KAAK,UAAU,GAAG,SAAS,IAAI;AAAA,MACvF,UAAU,GAAG,UAAU;AAAA,MACvB,SAAS,GAAG,UAAU;AAAA,MACtB,iBAAiB,GAAG,UAAU;AAAA,MAC9B,gBAAgB,GAAG;AAAA,MACnB,YAAY,KAAK,UAAU,GAAG,UAAU;AAAA,MACxC,eAAe,GAAG;AAAA,MAClB;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,qBAAqB,KAAgD;AAC5E,UAAM,YACL,IAAI,aAAa,OAAQ,KAAK,MAAM,IAAI,SAAS,IAAiC;AACnF,WAAO;AAAA,MACN,IAAI,IAAI;AAAA,MACR,QAAQ,IAAI;AAAA,MACZ,MAAM,IAAI;AAAA,MACV,YAAY,IAAI;AAAA,MAChB,UAAU,IAAI;AAAA,MACd,MAAM,IAAI,SAAS,OAAO,KAAK,MAAM,IAAI,IAAI,IAAI;AAAA,MACjD,cAAc,IAAI,iBAAiB,OAAO,KAAK,MAAM,IAAI,YAAY,IAAI;AAAA,MACzE,WAAW;AAAA,QACV,UAAU,IAAI;AAAA,QACd,SAAS,IAAI;AAAA,QACb,QAAQ,IAAI;AAAA,MACb;AAAA,MACA,gBAAgB,IAAI;AAAA,MACpB,YAAY,KAAK,MAAM,IAAI,UAAU;AAAA,MACrC,eAAe,IAAI;AAAA,MACnB,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IAClC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAMQ,aAAmB;AAC1B,QAAI,KAAK,QAAQ;AAChB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC9C;AAAA,EACD;AAAA,EAEQ,eAAqB;AAC5B,QAAI,CAAC,KAAK,QAAQ;AACjB,YAAM,IAAI;AAAA,QACT;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,iBAAiB,YAA0B;AAClD,UAAM,SAAS,KAAK;AACpB,QAAI,CAAC,OAAO,YAAY,UAAU,GAAG;AACpC,YAAM,IAAI;AAAA,QACT,uBAAuB,UAAU,iBAAiB,OAAO,KAAK,OAAO,WAAW,EAAE,KAAK,IAAI,CAAC;AAAA,MAC7F;AAAA,IACD;AAAA,EACD;AACD;AAuBO,SAAS,wBAAwB,SAGlB;AAGrB,QAAM,WAAW,WAAW,gBAAgB;AAC5C,QAAM,EAAE,QAAQ,IAAI,WAAW,4BAA4B;AAE3D,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAM,SAAS,IAAI,SAAS,QAAQ;AAGpC,SAAO,OAAO,oBAAoB;AAElC,QAAM,KAAK,QAAQ,MAAM;AACzB,SAAO,IAAI,kBAAkB,IAAI,QAAQ,MAAM;AAChD;;;AEl4BA,SAAS,iBAAiB;AA2BnB,IAAM,sBAAN,MAAqD;AAAA,EAC1C;AAAA,EAET,iBAA8C;AAAA,EAC9C,eAA0C;AAAA,EAC1C,eAA0C;AAAA,EAE1C,YAAY;AAAA,EACZ,eAAe;AAAA,EACN,QAAyB,CAAC;AAAA,EAE3C,YAAY,YAA+B;AAC1C,SAAK,aAAa;AAAA,EACnB;AAAA,EAEA,KAAK,SAAmD;AACvD,QAAI,CAAC,KAAK,UAAW;AAErB,UAAM,UAAU,KAAK,WAAW,OAAO,OAAO;AAC9C,UAAM,WAAW,mBAAmB;AACpC,SAAK,MAAM,KAAK;AAAA,MACf,MAAM,KAAK,SAAS,KAAK,cAAc;AAAA,MACvC,aAAa,WAAW,2BAA2B;AAAA,MACnD,SAAS;AAAA,IACV,CAAC;AAAA,EACF;AAAA,EAEA,UAAU,SAAqC;AAC9C,SAAK,iBAAiB;AAAA,EACvB;AAAA,EAEA,QAAQ,SAAmC;AAC1C,SAAK,eAAe;AAAA,EACrB;AAAA,EAEA,QAAQ,SAAmC;AAC1C,SAAK,eAAe;AAAA,EACrB;AAAA,EAEA,cAAuB;AACtB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,KAAM,SAAS,oBAA0B;AACrD,QAAI,CAAC,KAAK,UAAW;AACrB,SAAK,YAAY;AACjB,SAAK,MAAM,SAAS;AACpB,SAAK,eAAe,MAAM,MAAM;AAAA,EACjC;AAAA,EAEA,QAAQ,SAAoC;AAC3C,QAAI,CAAC,KAAK,WAAW;AACpB,YAAM,IAAI,UAAU,iCAAiC;AAAA,IACtD;AAEA,QAAI;AACH,YAAM,UAAU,KAAK,WAAW,OAAO,OAAO;AAC9C,WAAK,iBAAiB,OAAO;AAAA,IAC9B,SAAS,OAAO;AACf,WAAK,eAAe,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,IAC9E;AAAA,EACD;AAAA,EAEA,KAAK,aAAwC;AAC5C,QAAI,CAAC,KAAK,WAAW;AACpB,aAAO,EAAE,QAAQ,IAAI;AAAA,IACtB;AAEA,UAAM,OAAO,KAAK,MAAM,CAAC;AACzB,QAAI,CAAC,MAAM;AACV,aAAO,EAAE,QAAQ,IAAI;AAAA,IACtB;AAEA,QAAI,eAAe,gBAAgB,KAAK,MAAM;AAC7C,aAAO;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,EAAE,MAAM,KAAK,KAAK;AAAA,MAC5B;AAAA,IACD;AAEA,SAAK,MAAM,MAAM;AACjB,WAAO;AAAA,MACN,QAAQ;AAAA,MACR,MAAM,KAAK;AAAA,MACX,SAAS;AAAA,QACR,gBAAgB,KAAK;AAAA,QACrB,MAAM,KAAK;AAAA,MACZ;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,SAAS,UAA0B;AAC1C,WAAO,MAAM,QAAQ;AAAA,EACtB;AACD;;;ACzHA,SAAS,aAAAM,kBAAiB;AAE1B,SAAS,6BAA6B;AAUtC,IAAM,UAAU;AA0BT,IAAM,oBAAN,MAAmD;AAAA,EACxC;AAAA,EACA;AAAA,EACT,iBAA8C;AAAA,EAC9C,eAA0C;AAAA,EAC1C,eAA0C;AAAA,EAElD,YAAY,IAAiB,SAAoC;AAChE,SAAK,KAAK;AACV,SAAK,aAAa,SAAS,cAAc,IAAI,sBAAsB;AACnE,SAAK,eAAe;AAAA,EACrB;AAAA,EAEA,KAAK,SAA4B;AAChC,QAAI,KAAK,GAAG,eAAe,SAAS;AACnC,YAAM,IAAIA,WAAU,8CAA8C;AAAA,QACjE,YAAY,KAAK,GAAG;AAAA,QACpB,aAAa,QAAQ;AAAA,MACtB,CAAC;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,WAAW,OAAO,OAAO;AAC9C,SAAK,GAAG,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,UAAU,SAAqC;AAC9C,SAAK,iBAAiB;AAAA,EACvB;AAAA,EAEA,QAAQ,SAAmC;AAC1C,SAAK,eAAe;AAAA,EACrB;AAAA,EAEA,QAAQ,SAAmC;AAC1C,SAAK,eAAe;AAAA,EACrB;AAAA,EAEA,cAAuB;AACtB,WAAO,KAAK,GAAG,eAAe;AAAA,EAC/B;AAAA,EAEA,MAAM,MAAe,QAAuB;AAC3C,SAAK,GAAG,MAAM,QAAQ,KAAM,UAAU,gBAAgB;AAAA,EACvD;AAAA,EAEQ,iBAAuB;AAC9B,SAAK,GAAG,GAAG,WAAW,CAAC,SAAkB;AACxC,UAAI;AACH,YACC,OAAO,SAAS,YAChB,EAAE,gBAAgB,eAClB,EAAE,gBAAgB,cACjB;AACD,gBAAM,IAAIA,WAAU,sCAAsC;AAAA,YACzD,aAAa,OAAO;AAAA,UACrB,CAAC;AAAA,QACF;AAEA,cAAM,UAAU,KAAK,WAAW,OAAO,IAAI;AAC3C,aAAK,iBAAiB,OAAO;AAAA,MAC9B,SAAS,KAAK;AACb,aAAK,eAAe,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;AAAA,MACxE;AAAA,IACD,CAAC;AAED,SAAK,GAAG,GAAG,SAAS,CAAC,MAAe,WAAoB;AACvD,WAAK,eAAe,OAAO,IAAI,KAAK,MAAM,OAAO,UAAU,mBAAmB,CAAC;AAAA,IAChF,CAAC;AAED,SAAK,GAAG,GAAG,SAAS,CAAC,QAAiB;AACrC,WAAK,eAAe,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;AAAA,IACxE,CAAC;AAAA,EACF;AACD;;;ACzGA,SAAS,gCAAgC;AACzC,SAAoB,kBAAAC,iBAAgB,gBAAgB;AACpD,SAAS,uBAAuB;AAahC,SAAS,4BAA4B;AACrC;AAAA,EAEC;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;;;ACnCP,SAAS,0BAA0B,yCAAyC;;;ACA5E,SAAS,wBAAwB;;;ACK1B,SAAS,8BAA8B,OAAuC;AACpF,SAAO;AAAA,IACN,MAAM,aACL,YACA,OACqC;AACrC,YAAM,OAAO,MAAM,MAAM,gBAAgB,YAAY,EAAE,MAAM,CAAC;AAC9D,aAAO,KAAK,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,EAAE;AAAA,IACtC;AAAA,IACA,MAAM,aAAa,YAAoB,OAAiD;AACvF,aAAO,MAAM,gBAAgB,YAAY,KAAK;AAAA,IAC/C;AAAA,EACD;AACD;;;ADJA,eAAsB,qCACrB,OACA,IACA,QACyC;AACzC,MAAI,CAAC,QAAQ;AACZ,WAAO,EAAE,OAAO,KAAK;AAAA,EACtB;AAEA,MAAI,GAAG,SAAS,UAAU;AACzB,WAAO,EAAE,OAAO,KAAK;AAAA,EACtB;AAEA,QAAM,gBAAgB,OAAO,YAAY,GAAG,UAAU;AACtD,MAAI,CAAC,iBAAiB,cAAc,YAAY,WAAW,GAAG;AAC7D,WAAO,EAAE,OAAO,KAAK;AAAA,EACtB;AAEA,QAAM,YAAY,MAAM,uBAAuB,OAAO,EAAE;AACxD,MAAI,cAAc,MAAM;AACvB,WAAO,EAAE,OAAO,KAAK;AAAA,EACtB;AAEA,QAAM,MAAM,8BAA8B,KAAK;AAC/C,QAAM,aAAa,MAAM;AAAA,IACxB;AAAA,IACA,GAAG;AAAA,IACH,GAAG;AAAA,IACH;AAAA,IACA;AAAA,EACD;AAEA,MAAI,WAAW,WAAW,GAAG;AAC5B,WAAO,EAAE,OAAO,KAAK;AAAA,EACtB;AAEA,QAAM,QAAQ,WAAW,CAAC;AAC1B,MAAI,UAAU,QAAW;AACxB,WAAO,EAAE,OAAO,KAAK;AAAA,EACtB;AACA,SAAO;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,SAAS,MAAM;AAAA,EAChB;AACD;AAEA,eAAe,uBACd,OACA,IAC0C;AAC1C,MAAI,GAAG,SAAS,MAAM;AACrB,WAAO;AAAA,EACR;AAEA,QAAM,WAAW,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,QAAQ;AAClE,QAAM,OAAO,WAAW,EAAE,GAAG,SAAS,IAAI,CAAC;AAE3C,MAAI,GAAG,SAAS,UAAU;AACzB,WAAO,EAAE,GAAG,GAAG,MAAM,IAAI,GAAG,SAAS;AAAA,EACtC;AAEA,SAAO,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,IAAI,GAAG,SAAS;AAC/C;;;AExEO,SAAS,+BAA+B,OAA6C;AAC3F,SAAO;AAAA,IACN,MAAM,aACL,YACA,OACqC;AACrC,YAAM,OAAO,MAAM,MAAM,gBAAgB,YAAY,EAAE,MAAM,CAAC;AAC9D,aAAO,KAAK,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,EAAE;AAAA,IACtC;AAAA,IACA,MAAM,aAAa,YAAoB,UAAoC;AAC1E,YAAM,MAAM,MAAM,MAAM,WAAW,YAAY,QAAQ;AACvD,aAAO,QAAQ,QAAQ,IAAI,aAAa;AAAA,IACzC;AAAA,EACD;AACD;;;ACpBA,SAAS,sBAAAC,qBAAoB,uBAAuB;AAQpD,eAAsB,gCACrB,OACA,UACA,QACA,eACA,gBACqB;AACrB,QAAM,SAAS,MAAM,UAAU;AAC/B,QAAM,QAAQ,IAAIA,oBAAmB,MAAM;AAC3C,QAAM,QAAQ,SAAS,SAAS;AAEhC,SAAO;AAAA,IACN;AAAA,MACC;AAAA,MACA,MAAM,OAAO,SAAS,WAAW,WAAW;AAAA,MAC5C,YAAY,OAAO;AAAA,MACnB,UAAU,OAAO;AAAA,MACjB,MAAM,OAAO;AAAA,MACb,cAAc,OAAO;AAAA,MACrB;AAAA,MACA,YAAY,CAAC,SAAS,EAAE;AAAA,MACxB;AAAA,IACD;AAAA,IACA;AAAA,EACD;AACD;AAKO,SAAS,yBAAyB,OAA4B;AAKpE,MAAI,MAAM,uBAAuB;AAChC,WAAO,MAAM,sBAAsB;AAAA,EACpC;AACA,QAAM,SAAS,MAAM,UAAU;AAC/B,QAAM,UAAU,MAAM,iBAAiB,EAAE,IAAI,MAAM,KAAK;AACxD,SAAO,UAAU;AAClB;;;AJxBA,eAAsB,qBACrB,OACA,IACA,gBACsC;AACtC,QAAM,SAAS,MAAM,UAAU;AAC/B,QAAM,SAAS,mBAAmB,SAAS,yBAAyB,MAAM,IAAI,oBAAI,IAAI;AAEtF,QAAM,aAAa,uBAAuB,IAAI,MAAM;AACpD,MAAI,CAAC,WAAW,OAAO;AACtB,WAAO;AAAA,MACN,QAAQ;AAAA,MACR,mBAAmB,CAAC;AAAA,MACpB,WAAW;AAAA,QACV,MAAM,WAAW,QAAQ;AAAA,QACzB,SAAS,WAAW,WAAW,cAAc,GAAG,EAAE;AAAA,QAClD,WAAW;AAAA,MACZ;AAAA,IACD;AAAA,EACD;AAEA,QAAM,kBAAkB,MAAM,qCAAqC,OAAO,IAAI,MAAM;AACpF,MAAI,CAAC,gBAAgB,OAAO;AAC3B,UAAM,OAAO,gBAAgB,QAAQ;AACrC,WAAO;AAAA,MACN,QAAQ;AAAA,MACR,mBAAmB,CAAC;AAAA,MACpB,WAAW;AAAA,QACV;AAAA,QACA,SAAS,gBAAgB,WAAW,cAAc,GAAG,EAAE;AAAA,QACvD,WAAW,qBAAqB,IAAI;AAAA,MACrC;AAAA,IACD;AAAA,EACD;AAEA,MAAI,GAAG,SAAS,YAAY,QAAQ;AACnC,UAAM,SAAS,+BAA+B,KAAK;AACnD,UAAM,cAAc,MAAM,kCAAkC,IAAI,QAAQ,QAAQ,MAAM;AAEtF,QAAI,CAAC,YAAY,SAAS;AACzB,aAAO;AAAA,QACN,QAAQ;AAAA,QACR,mBAAmB,CAAC;AAAA,QACpB,WAAW;AAAA,UACV,MAAM;AAAA,UACN,SAAS,cAAc,GAAG,EAAE,wCAAwC,GAAG,UAAU;AAAA,UACjF,WAAW,qBAAqB,uBAAuB;AAAA,QACxD;AAAA,MACD;AAAA,IACD;AAEA,UAAM,gBAAgB,MAAM,MAAM,qBAAqB,EAAE;AACzD,QAAI,kBAAkB,WAAW;AAChC,aAAO,EAAE,QAAQ,eAAe,mBAAmB,CAAC,EAAE;AAAA,IACvD;AAEA,UAAM,oBAAiC,CAAC,EAAE;AAE1C,eAAW,UAAU,YAAY,eAAe;AAK/C,YAAM,SAAS,MAAM;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,QACA,GAAG;AAAA,QACH,yBAAyB,KAAK;AAAA,MAC/B;AACA,YAAM,aAAa,MAAM,MAAM,qBAAqB,MAAM;AAC1D,UAAI,eAAe,WAAW;AAC7B,0BAAkB,KAAK,MAAM;AAAA,MAC9B;AAAA,IACD;AAEA,WAAO,EAAE,QAAQ,WAAW,kBAAkB;AAAA,EAC/C;AAEA,QAAM,SAAS,MAAM,MAAM,qBAAqB,EAAE;AAClD,SAAO;AAAA,IACN;AAAA,IACA,mBAAmB,WAAW,YAAY,CAAC,EAAE,IAAI,CAAC;AAAA,EACnD;AACD;AAEA,SAAS,uBACR,IACA,QACoE;AACpE,MAAI,CAAC,QAAQ;AACZ,WAAO,EAAE,OAAO,KAAK;AAAA,EACtB;AAEA,QAAM,aAAa,OAAO,YAAY,GAAG,UAAU;AACnD,MAAI,CAAC,YAAY;AAChB,WAAO;AAAA,MACN,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS,cAAc,GAAG,EAAE,iCAAiC,GAAG,UAAU;AAAA,IAC3E;AAAA,EACD;AAEA,QAAM,iBAAiB,IAAI,IAAI,OAAO,KAAK,WAAW,MAAM,CAAC;AAC7D,QAAM,uBAAuB,oBAAI,IAAI,CAAC,MAAM,eAAe,eAAe,UAAU,CAAC;AACrF,QAAM,mBAAmB,kBAAkB,GAAG,MAAM,cAAc;AAClE,MAAI,kBAAkB;AACrB,WAAO;AAAA,MACN,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS,cAAc,GAAG,EAAE,gCAAgC,gBAAgB,6BAA6B,GAAG,UAAU;AAAA,IACvH;AAAA,EACD;AAEA,QAAM,uBAAuB;AAAA,IAC5B,GAAG;AAAA,IACH;AAAA,IACA;AAAA,EACD;AACA,MAAI,sBAAsB;AACzB,WAAO;AAAA,MACN,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS,cAAc,GAAG,EAAE,gCAAgC,oBAAoB,qCAAqC,GAAG,UAAU;AAAA,IACnI;AAAA,EACD;AAEA,MAAI,GAAG,WAAW;AACjB,eAAW,SAAS,OAAO,KAAK,GAAG,SAAS,GAAG;AAC9C,UAAI,CAAC,eAAe,IAAI,KAAK,GAAG;AAC/B,eAAO;AAAA,UACN,OAAO;AAAA,UACP,MAAM;AAAA,UACN,SAAS,cAAc,GAAG,EAAE,uCAAuC,KAAK,qBAAqB,GAAG,UAAU;AAAA,QAC3G;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAEA,SAAO,EAAE,OAAO,KAAK;AACtB;AAEA,SAAS,kBACR,OACA,gBACA,oBACgB;AAChB,MAAI,UAAU,QAAQ,UAAU,QAAW;AAC1C,WAAO;AAAA,EACR;AACA,MAAI,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AACtD,WAAO;AAAA,EACR;AACA,aAAW,SAAS,OAAO,KAAK,KAAK,GAAG;AACvC,QAAI,CAAC,eAAe,IAAI,KAAK,KAAK,CAAC,oBAAoB,IAAI,KAAK,GAAG;AAClE,aAAO;AAAA,IACR;AAAA,EACD;AACA,SAAO;AACR;;;AKjLO,IAAM,iBAAN,MAA6C;AAAA,EACnD,MAAM,aAAa,QAAsC;AACxD,WAAO,EAAE,QAAQ,YAAY;AAAA,EAC9B;AACD;;;ACVA,SAAgC,qBAAqB;AAmB9C,SAAS,qBACf,QACA,SACuB;AACvB,QAAM,EAAE,gBAAgB,YAAY,YAAY,IAAI;AAEpD,MAAI;AAEJ,MAAI,UAAU,eAAe,OAAO,KAAK,WAAW,EAAE,SAAS,GAAG;AACjE,eAAW,cAAc,QAAQ,WAAW;AAAA,EAC7C,WAAW,gBAAgB;AAC1B,eAAW,EAAE,GAAG,eAAe;AAAA,EAChC,WAAW,YAAY;AACtB,eAAW,EAAE,GAAG,WAAW;AAAA,EAC5B;AAEA,MAAI,UAAU,CAAC,YAAY,aAAa;AACvC,eAAW,cAAc,QAAQ,WAAW;AAAA,EAC7C;AAEA,MAAI,YAAY;AACf,eAAW,eAAe,UAAU,YAAY,MAAM;AAAA,EACvD;AAEA,MAAI,gBAAgB;AACnB,eAAW,eAAe,UAAU,gBAAgB,WAAW;AAAA,EAChE;AAEA,SAAO,YAAY,OAAO,KAAK,QAAQ,EAAE,SAAS,IAAI,WAAW;AAClE;AAEA,SAAS,eACR,MACA,SACA,QACW;AACX,QAAM,SAAmB,EAAE,GAAI,QAAQ,CAAC,EAAG;AAE3C,aAAW,CAAC,YAAY,YAAY,KAAK,OAAO,QAAQ,OAAO,GAAG;AACjE,QAAI,WAAW,QAAQ;AACtB,aAAO,UAAU,IAAI,EAAE,GAAI,OAAO,UAAU,KAAK,CAAC,GAAI,GAAG,aAAa;AAAA,IACvE,OAAO;AACN,aAAO,UAAU,IAAI,EAAE,GAAI,gBAAgB,CAAC,GAAI,GAAI,OAAO,UAAU,KAAK,CAAC,EAAG;AAAA,IAC/E;AAAA,EACD;AAEA,SAAO;AACR;;;AC5DO,IAAM,qCAAqC;AAG3C,SAAS,kBACf,QACA,YAAY,oCACD;AACX,QAAM,aAAuB,CAAC;AAC9B,aAAW,cAAc,OAAO,KAAK,MAAM,EAAE,KAAK,GAAG;AACpD,UAAM,YAAqC,CAAC;AAC5C,eAAW,SAAS,OAAO,KAAK,OAAO,UAAU,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG;AACjE,YAAM,WAAW,OAAO,UAAU,IAAI,KAAK;AAC3C,UACC,YACA,OAAO,aAAa,YACpB,CAAC,MAAM,QAAQ,QAAQ,KACvB,SAAS,UACR;AACD,cAAM,SAAU,SAA+B;AAC/C,YAAI,CAAC,MAAM,QAAQ,MAAM;AACxB,gBAAM,IAAI,MAAM,6BAA6B,UAAU,IAAI,KAAK,EAAE;AACnE,cAAM,SAAS,CAAC,GAAG,IAAI,IAAI,OAAO,IAAI,CAAC,UAAU,CAAC,eAAe,KAAK,GAAG,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC;AAC1F,YAAI,OAAO,SAAS;AACnB,gBAAM,IAAI;AAAA,YACT,uBAAuB,UAAU,IAAI,KAAK,gBAAgB,SAAS;AAAA,UACpE;AACD,kBAAU,KAAK,IAAI;AAAA,UAClB,KAAK,OAAO,KAAK,CAAC,GAAG,MAAM,eAAe,CAAC,EAAE,cAAc,eAAe,CAAC,CAAC,CAAC;AAAA,QAC9E;AAAA,MACD,MAAO,WAAU,KAAK,IAAI;AAAA,IAC3B;AACA,eAAW,UAAU,IAAI;AAAA,EAC1B;AACA,SAAO;AACR;AAEA,SAAS,eAAe,OAAwB;AAC/C,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,IAAI,MAAM,IAAI,cAAc,EAAE,KAAK,GAAG,CAAC;AACxE,MAAI,SAAS,OAAO,UAAU;AAC7B,WAAO,IAAI,OAAO,KAAK,KAAgC,EACrD,KAAK,EACL;AAAA,MACA,CAAC,QACA,GAAG,KAAK,UAAU,GAAG,CAAC,IAAI,eAAgB,MAAkC,GAAG,CAAC,CAAC;AAAA,IACnF,EACC,KAAK,GAAG,CAAC;AACZ,SAAO,KAAK,UAAU,KAAK;AAC5B;AAUO,SAAS,uBACf,IACA,QACA,YACU;AACV,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,kBAAkB,OAAO,GAAG,UAAU;AAC5C,MAAI,CAAC,gBAAiB,QAAO;AAC7B,MAAI,OAAO,KAAK,eAAe,EAAE,WAAW,EAAG,QAAO;AAEtD,QAAM,WAAW,cAAc,IAAI,UAAU;AAC7C,MAAI,CAAC,SAAU,QAAO;AAEtB,aAAW,CAAC,OAAO,QAAQ,KAAK,OAAO,QAAQ,eAAe,GAAG;AAChE,QAAI,CAAC,iBAAiB,SAAS,KAAK,GAAG,QAAQ,GAAG;AACjD,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;AAEA,SAAS,iBAAiB,QAAiB,UAA4B;AACtE,MAAI,YAAY,OAAO,aAAa,YAAY,CAAC,MAAM,QAAQ,QAAQ,KAAK,SAAS,UAAU;AAC9F,UAAM,SAAU,SAA+B;AAC/C,WAAO,MAAM,QAAQ,MAAM,KAAK,OAAO,KAAK,CAAC,UAAU,OAAO,GAAG,QAAQ,KAAK,CAAC;AAAA,EAChF;AACA,SAAO,OAAO,GAAG,QAAQ,QAAQ;AAClC;AASO,SAAS,mBAAmB,IAAe,QAAwC;AACzF,MAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,QAAM,kBAAkB,OAAO,GAAG,UAAU;AAC5C,MAAI,CAAC,gBAAiB,QAAO,CAAC;AAC9B,MAAI,OAAO,KAAK,eAAe,EAAE,WAAW,EAAG,QAAO,CAAC;AACvD,QAAM,WAAW,cAAc,EAAE;AACjC,SAAO,OAAO,KAAK,eAAe,EAAE,OAAO,CAAC,UAAU,CAAC,YAAY,EAAE,SAAS,SAAS;AACxF;AAEA,SAAS,cACR,IACA,YACiC;AACjC,QAAM,WAAW,SAAS,GAAG,YAAY;AACzC,QAAM,OAAO,SAAS,GAAG,IAAI;AAE7B,MAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,WAAY,QAAO;AAE9C,SAAO;AAAA,IACN,GAAI,cAAc,CAAC;AAAA,IACnB,GAAI,YAAY,CAAC;AAAA,IACjB,GAAI,QAAQ,CAAC;AAAA,EACd;AACD;AAEA,SAAS,SAAS,OAAgD;AACjE,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG;AACxE,WAAO;AAAA,EACR;AAEA,SAAO;AACR;;;ACrIA,SAAS,mBAAmB;AAIrB,IAAM,iCAAiC;AAYvC,SAAS,0BAA0B,IAAe,MAAc,KAAK,IAAI,GAAY;AAC3F,QAAM,EAAE,UAAU,QAAQ,IAAI,GAAG;AACjC,MAAI,CAAC,OAAO,UAAU,QAAQ,KAAK,WAAW,GAAG;AAChD,WAAO;AAAA,EACR;AACA,MAAI,CAAC,OAAO,UAAU,OAAO,KAAK,UAAU,KAAK,UAAU,aAAa;AACvE,WAAO;AAAA,EACR;AACA,SAAO,YAAY,MAAM;AAC1B;;;ACtBO,IAAM,8BAA8B,MAAM;AAG1C,IAAM,6BAA6B;AAKnC,SAAS,sBAAsB,IAAuB;AAC5D,SAAO,OAAO,WAAW,KAAK,UAAU,EAAE,GAAG,MAAM;AACpD;AAWO,SAAS,sBACf,IACA,WAAmB,6BACO;AAC1B,QAAM,QAAQ,sBAAsB,EAAE;AACtC,MAAI,SAAS,UAAU;AACtB,WAAO,EAAE,OAAO,MAAM,MAAM;AAAA,EAC7B;AACA,SAAO;AAAA,IACN,OAAO;AAAA,IACP;AAAA,IACA,SAAS,cAAc,GAAG,EAAE,uBAAuB,OAAO,KAAK,CAAC,MAAM,OAAO,QAAQ,CAAC;AAAA,EACvF;AACD;AAKO,IAAM,qBAAN,MAAyB;AAAA,EAI/B,YAA6B,kBAA0B,4BAA4B;AAAtD;AAAA,EAAuD;AAAA,EAAvD;AAAA,EAHrB,gBAAgB,KAAK,IAAI;AAAA,EACzB,QAAQ;AAAA,EAIhB,IAAI,QAAgB;AACnB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA,EAGA,MAAMC,SAAQ,GAAY;AACzB,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,MAAM,KAAK,iBAAiB,KAAQ;AACvC,WAAK,gBAAgB;AACrB,WAAK,QAAQ;AAAA,IACd;AACA,SAAK,SAASA;AACd,WAAO,KAAK,SAAS,KAAK;AAAA,EAC3B;AAAA,EAEA,QAAc;AACb,SAAK,gBAAgB,KAAK,IAAI;AAC9B,SAAK,QAAQ;AAAA,EACd;AACD;;;AVPA,IAAM,qBAAqB;AAC3B,IAAM,yBAAyB;AAO/B,IAAM,0BAA0B,oBAAI,QAAsB;AAgB1D,SAAS,+BACR,MACA,gBACA,QACO;AACP,MAAI,CAAC,QAAQ,gBAAgB,gBAAgB;AAC5C;AAAA,EACD;AACA,MAAI,gBAAgB;AACnB;AAAA,EACD;AACA,MAAI,CAAC,UAAU,OAAO,KAAK,OAAO,WAAW,EAAE,WAAW,GAAG;AAC5D;AAAA,EACD;AACA,MAAI,wBAAwB,IAAI,IAAI,GAAG;AACtC;AAAA,EACD;AACA,0BAAwB,IAAI,IAAI;AAChC,UAAQ;AAAA,IACP;AAAA,EAOD;AACD;AAEA,SAAS,gBAAgB,OAAwB;AAChD,MAAI,MAAM,QAAQ,KAAK,GAAG;AACzB,WAAO,IAAI,MAAM,IAAI,CAAC,SAAS,gBAAgB,IAAI,CAAC,EAAE,KAAK,GAAG,CAAC;AAAA,EAChE;AACA,MAAI,SAAS,OAAO,UAAU,UAAU;AACvC,UAAM,SAAS;AACf,UAAM,UAAU,OAAO,KAAK,MAAM,EAChC,KAAK,EACL,IAAI,CAAC,QAAQ,GAAG,KAAK,UAAU,GAAG,CAAC,IAAI,gBAAgB,OAAO,GAAG,CAAC,CAAC,EAAE;AACvE,WAAO,IAAI,QAAQ,KAAK,GAAG,CAAC;AAAA,EAC7B;AACA,SAAO,KAAK,UAAU,KAAK;AAC5B;AAEA,SAAS,aAAa,GAAY,GAAqB;AACtD,QAAM,YAAY,CAAC,UAClB,SAAS,OAAO,UAAU,WACvB,kBAAkB,KAAgD,IAClE;AACJ,SAAO,gBAAgB,UAAU,CAAC,KAAK,IAAI,MAAM,gBAAgB,UAAU,CAAC,KAAK,IAAI;AACtF;AAiIO,IAAM,gBAAN,MAAM,eAAc;AAAA,EAClB,QAAsB;AAAA,EACtB,eAA8B;AAAA,EAC9B,cAAkC;AAAA,EAClC,mBAAsC,CAAC;AAAA,EACvC,oBAAwC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQxC,0BAAyC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUzC,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMvB,8BAA8B;AAAA,EAC9B,2BAA2B;AAAA;AAAA,EAE3B,oBAAmC,QAAQ,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU1C,gBAAgB,oBAAI,IAGnC;AAAA,EACF,OAAwB,qBAAqB;AAAA,EAE5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAA+B;AAC1C,SAAK,YAAY,QAAQ;AACzB,SAAK,YAAY,QAAQ;AACzB,SAAK,QAAQ,QAAQ;AACrB,SAAK,OAAO,QAAQ,QAAQ;AAC5B,SAAK,aAAa,QAAQ,cAAc,IAAI,4BAA4B,MAAM;AAC9E,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,SAAS,QAAQ,UAAU;AAChC,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,UAAM,YAAY,QAAQ;AAC1B,SAAK,0BAA0B,aAAa;AAAA,MAC3C,KAAK,KAAK;AAAA,MACV,KAAK,KAAK;AAAA,IACX;AACA,SAAK,sBAAsB,QAAQ,uBAAuB,CAAC;AAC3D,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,oBAAoB,QAAQ,qBAAqB;AACtD,SAAK,iBAAiB,QAAQ,kBAAkB;AAChD,SAAK,qBAAqB,QAAQ,sBAAsB;AACxD,SAAK,sBAAsB,QAAQ,uBAAuB;AAC1D,SAAK,mBAAmB,QAAQ,oBAAoB;AACpD,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,mBAAmB,QAAQ,oBAAoB;AACpD,SAAK,qBAAqB,QAAQ,sBAAsB;AACxD,SAAK,oBAAoB,QAAQ,qBAAqB;AACtD,SAAK,kBAAkB,QAAQ,mBAAmB;AAClD,SAAK,cAAc,IAAI,mBAAmB,KAAK,eAAe;AAC9D,SAAK,oBAAoB,QAAQ,qBAAqB;AACtD,SAAK,cAAc,QAAQ,eAAe;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACb,SAAK,UAAU,UAAU,CAAC,QAAQ,KAAK,eAAe,GAAG,CAAC;AAC1D,SAAK,UAAU,QAAQ,CAAC,OAAO,YAAY,KAAK,qBAAqB,CAAC;AACtE,SAAK,UAAU,QAAQ,CAAC,SAAS;AAEhC,UAAI,KAAK,UAAU,UAAU;AAC5B,aAAK,qBAAqB;AAAA,MAC3B;AAAA,IACD,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgBC,aAA+B;AAC9C,QAAI,KAAK,UAAU,eAAe,CAAC,KAAK,UAAU,YAAY,EAAG;AAMjE,QAAI,KAAK,4BAA4B,MAAM;AAC1C,WAAK,mBAAmB;AACxB;AAAA,IACD;AACA,QAAIA,YAAW,WAAW,EAAG;AAG7B,SAAK,KAAK,uBAAuBA,WAAU;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,qBAA2B;AAClC,SAAK,oBAAoB,KAAK,kBAAkB,KAAK,YAAY;AAChE,UAAI,KAAK,UAAU,eAAe,CAAC,KAAK,UAAU,YAAY,EAAG;AACjE,UAAI;AACH,aAAK,8BAA8B,KAAK,IAAI;AAI5C,cAAM,KAAK;AAAA,UACV,KAAK;AAAA,UACL;AAAA,UACA,KAAK,gBAAgB;AAAA,QACtB;AAAA,MACD,QAAQ;AAAA,MAIR;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,MAAc,uBAAuBA,aAAwC;AAC5E,UAAM,oBAAiC,CAAC;AACxC,eAAW,MAAMA,aAAY;AAC5B,UAAI,MAAM,KAAK,yBAAyB,EAAE,GAAG;AAC5C,0BAAkB,KAAK,EAAE;AAAA,MAC1B;AAAA,IACD;AACA,QAAI,kBAAkB,WAAW,EAAG;AAEpC,QAAI,KAAK,UAAU,eAAe,CAAC,KAAK,UAAU,YAAY,EAAG;AAEjE,UAAM,gBAAgB,kBAAkB,IAAI,CAAC,OAAO,KAAK,WAAW,gBAAgB,EAAE,CAAC;AACvF,UAAM,MAAmB;AAAA,MACxB,MAAM;AAAA,MACN,WAAWC,gBAAe;AAAA,MAC1B,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,YAAY;AAAA,IACb;AAEA,SAAK,kBAAkB,KAAK,iBAAiB;AAC7C,SAAK,aAAa,GAAG;AAAA,EACtB;AAAA;AAAA,EAGQ,kBAAkB,KAAkB,KAAwB;AACnE,QAAI,KAAK,cAAc,QAAQ,eAAc,oBAAoB;AAChE,YAAM,SAAS,KAAK,cAAc,KAAK,EAAE,KAAK,EAAE;AAChD,UAAI,WAAW,QAAW;AACzB,aAAK,cAAc,OAAO,MAAM;AAAA,MACjC;AAAA,IACD;AACA,SAAK,cAAc,IAAI,IAAI,WAAW,EAAE,SAAS,KAAK,KAAK,UAAU,KAAK,IAAI,EAAE,CAAC;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,wBAAwB,UAAU,GAAS;AAC1C,QAAI,KAAK,UAAU,eAAe,CAAC,KAAK,UAAU,YAAY,EAAG;AACjE,QAAI,KAAK,4BAA4B,MAAM;AAC1C;AAAA,IACD;AACA,QAAI,KAAK,cAAc,SAAS,EAAG;AACnC,UAAM,SAAS,KAAK,IAAI,IAAI;AAC5B,eAAW,EAAE,SAAS,SAAS,KAAK,KAAK,cAAc,OAAO,GAAG;AAChE,UAAI,YAAY,QAAQ;AACvB,aAAK,aAAa,OAAO;AAAA,MAC1B;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,8BAA8B,UAAU,GAAG,UAAoC,CAAC,GAAS;AACxF,QAAI,KAAK,UAAU,eAAe,CAAC,KAAK,UAAU,YAAY,EAAG;AACjE,QAAI,KAAK,4BAA4B,KAAM;AAC3C,QAAI,UAAU,KAAK,KAAK,IAAI,IAAI,KAAK,8BAA8B,SAAS;AAC3E;AAAA,IACD;AACA,QAAI,QAAQ,YAAY;AACvB,WAAK,4BAA4B;AACjC,UAAI,KAAK,4BAA4B,GAAG;AACvC,aAAK,SAAS,KAAK;AAAA,UAClB,MAAM;AAAA,UACN,WAAW,KAAK;AAAA,UAChB,WAAW,KAAK;AAAA,UAChB,aAAa,KAAK;AAAA,QACnB,CAAC;AAAA,MACF;AAAA,IACD;AACA,SAAK,mBAAmB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,sBAA4B;AACnC,QAAI,KAAK,oBAAoB,KAAK,gBAAgB,KAAK,cAAc,OAAO,GAAG;AAC9E,YAAM,MAAmB,CAAC;AAC1B,iBAAW,SAAS,KAAK,cAAc,OAAO,GAAG;AAChD,YAAI,KAAK,GAAG,MAAM,GAAG;AAAA,MACtB;AACA,UAAI,IAAI,SAAS,GAAG;AACnB,aAAK,iBAAiB,KAAK,cAAc,GAAG;AAAA,MAC7C;AAAA,IACD;AACA,SAAK,cAAc,MAAM;AAAA,EAC1B;AAAA,EAEA,MAAM,QAAuB;AAC5B,QAAI,KAAK,UAAU,SAAU;AAC7B,SAAK,QAAQ;AACb,SAAK,oBAAoB;AAEzB,QAAI,KAAK,UAAU,YAAY,GAAG;AACjC,WAAK,UAAU,MAAM,KAAM,UAAU,gBAAgB;AAAA,IACtD;AAEA,SAAK,UAAU,KAAK,SAAS;AAAA,EAC9B;AAAA;AAAA,EAIA,WAAyB;AACxB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,eAAuB;AACtB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,kBAAiC;AAChC,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,iBAAqC;AACpC,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,cAAuB;AACtB,WAAO,KAAK,UAAU;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAgC;AAC/B,WAAO,KAAK;AAAA,EACb;AAAA;AAAA,EAIQ,eAA8B,QAAQ,QAAQ;AAAA;AAAA,EAG9C,aAAa,SAA+B;AACnD,QAAI,CAAC,KAAK,UAAU,YAAY,GAAG;AAClC,aAAO;AAAA,IACR;AACA,QAAI;AACH,WAAK,UAAU,KAAK,OAAO;AAC3B,aAAO;AAAA,IACR,QAAQ;AACP,aAAO;AAAA,IACR;AAAA,EACD;AAAA,EAEQ,eAAe,SAA4B;AAClD,SAAK,eAAe,KAAK,aACvB,KAAK,MAAM,KAAK,mBAAmB,OAAO,CAAC,EAC3C,MAAM,CAAC,UAAU,KAAK,qBAAqB,KAAK,CAAC;AAAA,EACpD;AAAA,EAEA,MAAc,mBAAmB,SAAqC;AACrE,YAAQ,QAAQ,MAAM;AAAA,MACrB,KAAK;AACJ,cAAM,KAAK,gBAAgB,OAAO;AAClC;AAAA,MACD,KAAK;AACJ,cAAM,KAAK,qBAAqB,OAAO;AACvC;AAAA,MACD,KAAK;AACJ,aAAK,cAAc,OAAO,QAAQ,qBAAqB;AACvD,YAAI,QAAQ,qBAAqB,QAAW;AAE3C,eAAK,uBAAuB,KAAK,IAAI,KAAK,sBAAsB,QAAQ,gBAAgB;AACxF,eAAK,2BAA2B;AAAA,QACjC;AACA;AAAA,MACD,KAAK;AACJ;AAAA,MACD,KAAK;AACJ,aAAK,sBAAsB,OAAO;AAClC;AAAA,MACD,KAAK;AACJ,aAAK,mBAAmB,OAAO;AAC/B;AAAA,MACD,KAAK;AACJ,aAAK,qBAAqB,KAAK,WAAW,OAAO;AACjD;AAAA,MACD,KAAK;AACJ,aAAK,sBAAsB,KAAK,WAAW,OAAO;AAClD;AAAA,MACD,KAAK;AACJ,cAAM,KAAK,oBAAoB,OAAO;AACtC;AAAA,IACF;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,oBAAoB,SAA8C;AAC/E,QAAI,CAAC,KAAK,kBAAkB;AAC3B;AAAA,IACD;AACA,UAAM,QAAQ,qBAAqB,QAAQ,KAAK;AAChD,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,QAAI,WAAW,QAAQ,MAAM;AAE5B;AAAA,IACD;AACA,UAAM,KAAK,iBAAiB,QAAQ,MAAM,KAAK;AAAA,EAChD;AAAA,EAEQ,qBAAqB,OAAsB;AAClD,UAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AACxD,SAAK,QAAQ,IAAI;AAAA,MAChB,WAAW,KAAK,IAAI;AAAA,MACpB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK,gBAAgB;AAAA,MAC7B,OAAO;AAAA,MACP,SAAS;AAAA,QACR,OAAO,KAAK;AAAA,QACZ,WAAW,iBAAiB,QAAQ,MAAM,OAAO,OAAO;AAAA,MACzD;AAAA,IACD,CAAC;AACD,SAAK,UAAU,cAAc,QAAQ,IAAI;AACzC,SAAK,MAAM,MAAM;AAAA,EAClB;AAAA,EAEA,MAAc,gBAAgB,KAAsC;AAEnE,QAAI,KAAK,UAAU,aAAa;AAC/B,WAAK,UAAU,uBAAuB,+BAA+B,KAAK;AAC1E;AAAA,IACD;AAEA,SAAK,eAAe,IAAI;AAGxB,QAAI,KAAK,MAAM;AACd,YAAM,QAAQ,IAAI,aAAa;AAC/B,YAAM,UAAU,MAAM,KAAK,KAAK,aAAa,KAAK;AAClD,UAAI,CAAC,SAAS;AACb,aAAK,UAAU,eAAe,yBAAyB,KAAK;AAC5D,aAAK,MAAM,uBAAuB;AAClC;AAAA,MACD;AACA,WAAK,cAAc;AACnB,WAAK,QAAQ;AAAA,IACd;AAGA,UAAM,oBAAoB,qBAAqB,KAAK,MAAM,UAAU,GAAG;AAAA,MACtE,gBAAgB,IAAI;AAAA,MACpB,YAAY,KAAK,aAAa;AAAA,IAC/B,CAAC;AACD,QAAI;AACJ,QAAI;AACH,uBAAiB,oBAAoB,kBAAkB,iBAAiB,IAAI;AAAA,IAC7E,SAAS,OAAO;AACf,WAAK,aAAa;AAAA,QACjB,MAAM;AAAA,QACN,WAAWA,gBAAe;AAAA,QAC1B,MAAM;AAAA,QACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAClD,WAAW;AAAA,MACZ,CAAC;AACD,WAAK,MAAM,yBAAyB;AACpC;AAAA,IACD;AAEA,QAAI,gBAAgB;AACnB,UAAI,KAAK,aAAa;AACrB,aAAK,cAAc,EAAE,GAAG,KAAK,aAAa,QAAQ,eAAe;AAAA,MAClE,OAAO;AACN,aAAK,cAAc,EAAE,QAAQ,IAAI,QAAQ,QAAQ,eAAe;AAAA,MACjE;AAAA,IACD;AAEA,mCAA+B,KAAK,MAAM,gBAAgB,KAAK,MAAM,UAAU,CAAC;AAEhF,QAAI,IAAI,eAAe,IAAI,YAAY,SAAS,GAAG;AAClD,WAAK,mBAAmB,mBAAmB,IAAI,WAAW;AAAA,IAC3D,OAAO;AACN,WAAK,mBAAmB,CAAC;AAAA,IAC1B;AAEA,SAAK,oBAAoB,IAAI,cAAc,kBAAkB,IAAI,WAAW,IAAI;AAChF,SAAK,0BAA0B,IAAI,wBAAwB;AAO3D,QACC,KAAK,4BAA4B,QACjC,CAAC,aAAa,IAAI,WAAW,KAAK,aAAa,MAAM,GACpD;AACD,WAAK,0BAA0B;AAAA,IAChC;AAOA,UAAM,sBAAsB,KAAK,4BAA4B;AAC7D,QAAI,oBAAoB;AACxB,QAAI,qBAAqB;AACxB,0BAAoB,MAAM,KAAK,MAAM,uBAAuB;AAC5D,UACC,KAAK,4BAA4B,QACjC,KAAK,0BAA0B,mBAC9B;AACD,aAAK,0BAA0B;AAAA,MAChC;AAAA,IACD;AAEA,UAAM,eAAe,KAAK,MAAM,iBAAiB;AACjD,UAAM,qBAAqB,iBAAiB,IAAI,oBAAoB;AACpE,SAAK,wBAAwB,kBAAkB;AAE/C,QAAI,CAAC,+BAA+B,IAAI,eAAe,KAAK,uBAAuB,GAAG;AACrF,YAAM,EAAE,KAAK,IAAI,IAAI,KAAK;AAC1B,WAAK,SAAS,KAAK;AAAA,QAClB,MAAM;AAAA,QACN,qBAAqB,IAAI;AAAA,QACzB,qBAAqB,KAAK;AAAA,QAC1B,cAAc;AAAA,QACd,cAAc;AAAA,QACd,QAAQ,GAAG,sBAAsB,2BAA2B,IAAI,aAAa,4BAA4B,GAAG,KAAK,GAAG;AAAA,MACrH,CAAC;AACD,YAAMC,YAAwB;AAAA,QAC7B,MAAM;AAAA,QACN,WAAWD,gBAAe;AAAA,QAC1B,QAAQ,KAAK,MAAM,UAAU;AAAA,QAC7B,eAAe,oBAAoB,YAAY;AAAA,QAC/C,eAAe,KAAK;AAAA,QACpB,UAAU;AAAA,QACV,cAAc,GAAG,sBAAsB,2BAA2B,IAAI,aAAa,4BAA4B,GAAG,KAAK,GAAG;AAAA,QAC1H,oBAAoB;AAAA,QACpB,oBAAoB;AAAA,QACpB,YAAY,KAAK,IAAI;AAAA,MACtB;AACA,WAAK,aAAaC,SAAQ;AAC1B,WAAK,MAAM,yBAAyB;AACpC;AAAA,IACD;AAGA,UAAM,WAAwB;AAAA,MAC7B,MAAM;AAAA,MACN,WAAWD,gBAAe;AAAA,MAC1B,QAAQ,KAAK,MAAM,UAAU;AAAA,MAC7B,eAAe,oBAAoB,YAAY;AAAA,MAC/C,eAAe,KAAK;AAAA,MACpB,UAAU;AAAA,MACV;AAAA,MACA,YAAY,KAAK,IAAI;AAAA;AAAA;AAAA;AAAA,MAIrB,GAAI,sBAAsB,EAAE,2BAA2B,kBAAkB,IAAI,CAAC;AAAA;AAAA;AAAA,MAG9E,GAAI,KAAK,mBAAmB,EAAE,oBAAoB,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA,MAG5D,GAAI,KAAK,aAAa,SAAS,EAAE,eAAe,KAAK,YAAY,OAAO,IAAI,CAAC;AAAA,IAC9E;AACA,SAAK,aAAa,QAAQ;AAE1B,SAAK,SAAS,KAAK,EAAE,MAAM,kBAAkB,QAAQ,IAAI,OAAO,CAAC;AAMjE,SAAK,QAAQ;AACb,QAAI,KAAK,4BAA4B,MAAM;AAC1C,WAAK,uBAAuB,KAAK;AAKjC,YAAM,aACL,KAAK,0BAA0B,IAAK,KAAK,gBAAgB,SAAa;AACvE,WAAK,8BAA8B,KAAK,IAAI;AAC5C,YAAM,KAAK,mBAAmB,KAAK,yBAAyB,MAAM,UAAU;AAAA,IAC7E,OAAO;AACN,YAAM,eAAe,oBAAoB,IAAI,aAAa;AAC1D,YAAM,KAAK,UAAU,YAAY;AAAA,IAClC;AAGA,SAAK,QAAQ;AAKb,QAAI,KAAK,sBAAsB,KAAK,cAAc;AACjD,YAAM,WAAW,KAAK,mBAAmB,KAAK,YAAY;AAC1D,UAAI,SAAS,SAAS,GAAG;AACxB,aAAK,gBAAgB,QAAQ;AAAA,MAC9B;AAAA,IACD;AAAA,EAMD;AAAA,EAEA,MAAc,qBAAqB,KAA2C;AAC7E,UAAMD,cAAa,IAAI,WAAW,IAAI,CAAC,MAAM,KAAK,WAAW,gBAAgB,CAAC,CAAC;AAC/E,UAAM,UAAuB,CAAC;AAC9B,QAAI,sBAAsB;AAC1B,QAAI,gBAAgB;AAEpB,eAAW,MAAMA,aAAY;AAC5B,UAAI,CAAC,eAAe;AACnB;AAAA,MACD;AAEA,UAAI,CAAE,MAAM,KAAK,yBAAyB,EAAE,GAAI;AAC/C,aAAK;AAAA,UACJ;AAAA,UACA;AAAA,UACA,cAAc,GAAG,EAAE,oBAAoB,GAAG,UAAU;AAAA,UACpD;AAAA,QACD;AACA,wBAAgB;AAChB;AAAA,MACD;AAEA,UAAI,CAAC,0BAA0B,EAAE,GAAG;AACnC,aAAK;AAAA,UACJ;AAAA,UACA,cAAc,GAAG,EAAE;AAAA,UACnB;AAAA,QACD;AACA,wBAAgB;AAChB;AAAA,MACD;AAEA,UAAI,CAAC,KAAK,YAAY,MAAM,CAAC,GAAG;AAC/B,aAAK;AAAA,UACJ;AAAA,UACA,0CAA0C,OAAO,KAAK,eAAe,CAAC;AAAA,UACtE;AAAA,QACD;AACA,wBAAgB;AAChB;AAAA,MACD;AAEA,YAAM,YAAY,sBAAsB,IAAI,KAAK,iBAAiB;AAClE,UAAI,CAAC,UAAU,OAAO;AACrB,aAAK;AAAA,UACJ;AAAA,UACA,UAAU,WAAW,cAAc,GAAG,EAAE;AAAA,UACxC;AAAA,QACD;AACA,wBAAgB;AAChB;AAAA,MACD;AAEA,YAAM,WAAW,KAAK,yBAAyB,EAAE;AACjD,UAAI,aAAa,MAAM;AACtB,aAAK;AAAA,UACJ;AAAA,UACA;AAAA,UACA,cAAc,GAAG,EAAE,wCAAwC,GAAG,aAAa,sBAAsB,KAAK,aAAa;AAAA,UACnH;AAAA,QACD;AACA,8BAAsB,GAAG;AACzB;AAAA,MACD;AAKA,UAAI,KAAK,qBAAqB,KAAK,aAAa;AAC/C,YAAI;AACJ,YAAI;AACH,qBAAW,MAAM,KAAK,kBAAkB,UAAU;AAAA,YACjD,MAAM,KAAK;AAAA,YACX,MAAM,KAAK;AAAA,UACZ,CAAC;AAAA,QACF,SAAS,OAAO;AAGf,gBAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,eAAK;AAAA,YACJ;AAAA,YACA;AAAA,YACA,oBAAoB,OAAO;AAAA,YAC3B;AAAA,UACD;AACA,0BAAgB;AAChB;AAAA,QACD;AACA,YAAI,SAAS,WAAW,UAAU;AACjC,gBAAM,YAAY,SAAS,aAAa,qBAAqB,SAAS,IAAI;AAC1E,eAAK,sBAAsB,UAAU,SAAS,MAAM,SAAS,SAAS,SAAS;AAC/E,cAAI,WAAW;AACd,4BAAgB;AAAA,UACjB,OAAO;AACN,kCAAsB,GAAG;AAAA,UAC1B;AACA;AAAA,QACD;AACA,YAAI,SAAS,WAAW,UAAU;AAGjC,gCAAsB,GAAG;AACzB;AAAA,QACD;AAAA,MAED;AAEA,YAAM,cAAc,MAAM,qBAAqB,KAAK,OAAO,QAAQ;AACnE,UAAI,YAAY,WAAW;AAC1B,aAAK;AAAA,UACJ;AAAA,UACA,YAAY,UAAU;AAAA,UACtB,YAAY,UAAU;AAAA,UACtB,YAAY,UAAU;AAAA,QACvB;AACA,YAAI,YAAY,UAAU,WAAW;AACpC,0BAAgB;AAAA,QACjB,OAAO;AACN,gCAAsB,GAAG;AAAA,QAC1B;AACA;AAAA,MACD;AACA,UAAI,YAAY,WAAW,WAAW;AACrC,gBAAQ,KAAK,GAAG,YAAY,iBAAiB;AAC7C,8BAAsB,GAAG;AAAA,MAC1B,OAAO;AACN,8BAAsB,GAAG;AAAA,MAC1B;AAAA,IACD;AAEA,QAAIA,YAAW,SAAS,GAAG;AAC1B,WAAK,SAAS,KAAK;AAAA,QAClB,MAAM;AAAA,QACN,YAAAA;AAAA,QACA,WAAWA,YAAW;AAAA,MACvB,CAAC;AAAA,IACF;AAGA,UAAM,SAASA,YAAWA,YAAW,SAAS,CAAC;AAC/C,UAAM,MAAmB;AAAA,MACxB,MAAM;AAAA,MACN,WAAWC,gBAAe;AAAA,MAC1B,uBAAuB,IAAI;AAAA,MAC3B,oBAAoB,SAAS,KAAK,IAAI,qBAAqB,OAAO,cAAc,IAAI;AAAA,IACrF;AACA,SAAK,aAAa,GAAG;AAGrB,QAAI,QAAQ,SAAS,GAAG;AACvB,WAAK,UAAU,KAAK,WAAW,OAAO;AAAA,IACvC;AAAA,EACD;AAAA,EAEQ,yBAAyB,IAAiC;AACjE,QAAI,GAAG,kBAAkB,KAAK,eAAe;AAC5C,aAAO;AAAA,IACR;AACA,WAAO,yBAAyB,IAAI,KAAK,eAAe,KAAK,mBAAmB;AAAA,EACjF;AAAA,EAEA,MAAc,UAAU,cAAkD;AACzE,UAAM,eAAe,KAAK,MAAM,iBAAiB;AACjD,UAAM,UAAuB,CAAC;AAE9B,eAAW,CAAC,QAAQ,SAAS,KAAK,cAAc;AAC/C,YAAM,YAAY,aAAa,IAAI,MAAM,KAAK;AAC9C,UAAI,YAAY,WAAW;AAC1B,cAAM,MAAM,MAAM,KAAK,MAAM,kBAAkB,QAAQ,YAAY,GAAG,SAAS;AAC/E,mBAAW,MAAM,KAAK;AACrB,cAAI,MAAM,KAAK,yBAAyB,EAAE,GAAG;AAC5C,oBAAQ,KAAK,EAAE;AAAA,UAChB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,QAAI,QAAQ,WAAW,GAAG;AACzB,YAAM,aAA0B;AAAA,QAC/B,MAAM;AAAA,QACN,WAAWA,gBAAe;AAAA,QAC1B,YAAY,CAAC;AAAA,QACb,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,cAAc;AAAA,MACf;AACA,WAAK,aAAa,UAAU;AAC5B;AAAA,IACD;AAEA,UAAM,SAAS,gBAAgB,OAAO;AACtC,UAAM,cAAc,2BAA2B,QAAQ,KAAK,iBAAiB;AAC7E,UAAM,eAAe,KAAK,KAAK,YAAY,SAAS,KAAK,SAAS;AAElE,QAAI,YAAY,WAAW,GAAG;AAC7B,YAAM,aAA0B;AAAA,QAC/B,MAAM;AAAA,QACN,WAAWA,gBAAe;AAAA,QAC1B,YAAY,CAAC;AAAA,QACb,SAAS;AAAA,QACT,YAAY,KAAK,mBAAmB,cAAc;AAAA,QAClD,cAAc;AAAA,MACf;AACA,WAAK,aAAa,UAAU;AAC5B;AAAA,IACD;AAEA,aAAS,IAAI,GAAG,IAAI,cAAc,KAAK;AACtC,YAAM,QAAQ,IAAI,KAAK;AACvB,YAAM,WAAW,YAAY,MAAM,OAAO,QAAQ,KAAK,SAAS;AAChE,YAAM,gBAAgB,SAAS,IAAI,CAAC,OAAO,KAAK,WAAW,gBAAgB,EAAE,CAAC;AAC9E,YAAM,cAAc,2BAA2B,UAAU,CAAC;AAE1D,YAAM,WAAwB;AAAA,QAC7B,MAAM;AAAA,QACN,WAAWA,gBAAe;AAAA,QAC1B,YAAY;AAAA,QACZ,SAAS,MAAM,eAAe;AAAA,QAC9B,YAAY;AAAA,QACZ;AAAA,QACA,GAAI,cAAc,EAAE,QAAQ,kBAAkB,WAAW,EAAE,IAAI,CAAC;AAAA,MACjE;AACA,WAAK,aAAa,QAAQ;AAE1B,WAAK,SAAS,KAAK;AAAA,QAClB,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,WAAW,SAAS;AAAA,MACrB,CAAC;AAAA,IACF;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAc,mBACb,iBACA,mBACA,eACkB;AAClB,UAAM,YAAY,KAAK,IAAI,KAAK,WAAW,CAAC,IAAI;AAChD,QAAI,aAAa;AACjB,QAAI,aAAa;AACjB,UAAM,UAAgC,CAAC;AAEvC,WAAO,MAAM;AACZ,YAAM,QAAQ,MAAM,KAAK,MAAM,2BAA2B,YAAY,SAAS;AAC/E,YAAM,OAAO,MAAM,MAAM,SAAS,CAAC;AACnC,UAAI,SAAS,OAAW;AACxB,mBAAa,KAAK;AAIlB,mBAAa;AACb,iBAAW,aAAa,OAAO;AAK9B,YAAI,kBAAkB,UAAa,UAAU,UAAU,WAAW,eAAe;AAChF;AAAA,QACD;AACA,YAAI,MAAM,KAAK,yBAAyB,UAAU,SAAS,GAAG;AAC7D,kBAAQ,KAAK,SAAS;AAAA,QACvB;AAAA,MACD;AACA,UAAI,MAAM,SAAS,UAAW;AAAA,IAC/B;AAEA,QAAI,QAAQ,WAAW,GAAG;AAKzB,UAAI,mBAAmB;AACtB,aAAK,kBAAkB,CAAC,GAAG,iBAAiB,YAAY,GAAG,IAAI;AAAA,MAChE;AACA,aAAO;AAAA,IACR;AAEA,UAAM,eAAe,KAAK,KAAK,QAAQ,SAAS,KAAK,SAAS;AAC9D,QAAI,OAAO;AACX,aAAS,IAAI,GAAG,IAAI,cAAc,KAAK;AACtC,YAAM,QAAQ,QAAQ,MAAM,IAAI,KAAK,YAAY,IAAI,KAAK,KAAK,SAAS;AACxE,YAAM,cAAc,MAAM,MAAM,SAAS,CAAC;AAC1C,UAAI,gBAAgB,OAAW;AAC/B,YAAM,UAAU,MAAM,eAAe;AACrC,YAAM,UAAU,YAAY;AAG5B,YAAM,MAAM,UAAU,KAAK,IAAI,YAAY,OAAO,IAAI;AACtD,WAAK,kBAAkB,OAAO,MAAM,KAAK,GAAG,OAAO;AACnD,aAAO;AAAA,IACR;AACA,WAAO,QAAQ;AAAA,EAChB;AAAA;AAAA,EAGQ,kBACP,OACA,MACA,KACA,YACA,SACO;AACP,UAAM,WAAwB;AAAA,MAC7B,MAAM;AAAA,MACN,WAAWA,gBAAe;AAAA,MAC1B,YAAY,MAAM,IAAI,CAAC,cAAc,KAAK,WAAW,gBAAgB,UAAU,SAAS,CAAC;AAAA,MACzF;AAAA,MACA;AAAA,MACA,sBAAsB;AAAA,MACtB,qBAAqB;AAAA,IACtB;AAMA,SAAK,aAAa,QAAQ;AAC1B,QAAI,MAAM,SAAS,GAAG;AACrB,WAAK,SAAS,KAAK;AAAA,QAClB,MAAM;AAAA,QACN,YAAY,MAAM,IAAI,CAAC,cAAc,UAAU,SAAS;AAAA,QACxD,WAAW,MAAM;AAAA,MAClB,CAAC;AAAA,IACF;AAAA,EACD;AAAA,EAEA,MAAc,yBAAyB,IAAiC;AACvE,UAAM,SAAS,KAAK,aAAa;AACjC,UAAM,UAAU,KAAK;AAMrB,UAAM,gBACL,mBAAmB,IAAI,MAAM,EAAE,SAAS,KAAM,YAAY,UAAa,QAAQ,SAAS;AACzF,UAAM,aAAa,gBAChB,MAAM,KAAK,mBAAmB,GAAG,YAAY,GAAG,QAAQ,IACxD;AAEH,QAAI,CAAC,uBAAuB,IAAI,QAAQ,UAAU,GAAG;AACpD,aAAO;AAAA,IACR;AACA,WAAO,6BAA6B,IAAI,SAAS,UAAU;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,mBACb,YACA,UAC+C;AAC/C,QAAI;AACH,YAAM,OAAO,MAAM,KAAK,MAAM,gBAAgB,YAAY;AAAA,QACzD,OAAO,EAAE,IAAI,SAAS;AAAA,QACtB,gBAAgB;AAAA,QAChB,OAAO;AAAA,MACR,CAAC;AACD,aAAO,KAAK,CAAC;AAAA,IACd,QAAQ;AACP,aAAO;AAAA,IACR;AAAA,EACD;AAAA,EAEQ,sBAAsB,KAAmC;AAGhE,SAAK,oBAAoB,KAAK,WAAW,GAAG;AAAA,EAC7C;AAAA,EAEQ,mBAAmB,KAAgC;AAC1D,SAAK,iBAAiB,KAAK,WAAW,GAAG;AAAA,EAC1C;AAAA,EAEQ,UAAU,MAAc,SAAiB,WAA0B;AAC1E,UAAM,WAAwB;AAAA,MAC7B,MAAM;AAAA,MACN,WAAWA,gBAAe;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,IACD;AACA,SAAK,aAAa,QAAQ;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,sBACP,IACA,MACA,SACA,WACO;AACP,UAAM,cAA2B;AAAA,MAChC,MAAM;AAAA,MACN,WAAWA,gBAAe;AAAA,MAC1B,aAAa,GAAG;AAAA,MAChB,YAAY,GAAG;AAAA,MACf,UAAU,GAAG;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,IACD;AACA,SAAK,aAAa,WAAW;AAAA,EAC9B;AAAA,EAEQ,wBAAwB,QAA0B;AACzD,QAAI,OAAO,KAAK,WAAW,kBAAkB,YAAY;AACxD,WAAK,WAAW,cAAc,MAAM;AAAA,IACrC;AAAA,EACD;AAAA,EAEQ,uBAA6B;AACpC,QAAI,KAAK,UAAU,SAAU;AAC7B,SAAK,QAAQ;AACb,SAAK,oBAAoB;AACzB,SAAK,SAAS,KAAK,EAAE,MAAM,qBAAqB,QAAQ,mBAAmB,CAAC;AAC5E,SAAK,UAAU,KAAK,SAAS;AAAA,EAC9B;AACD;AAEA,SAAS,iBAAiB,sBAAiD;AAC1E,MAAI,sBAAsB,SAAS,UAAU,GAAG;AAC/C,WAAO;AAAA,EACR;AAEA,SAAO;AACR;;;AWvxCA,SAAS,aAAAE,YAAW,kBAAAC,iBAAgB,iBAAiB;AACrD,SAAS,0BAA0B;AAEnC,SAAS,yBAAAC,8BAA6B;;;ACJtC,SAAS,kBAAAC,uBAAsB;AA0BxB,IAAM,iBAAN,MAAqB;AAAA,EACV,UAAU,oBAAI,IAA6B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS5D,UAAU,WAAmB,UAAkB,WAAkC;AAChF,SAAK,QAAQ,IAAI,WAAW;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACR,CAAC;AAGD,UAAM,iBAA4D,CAAC;AACnE,QAAI,YAAY;AAChB,eAAW,CAAC,EAAE,MAAM,KAAK,KAAK,SAAS;AACtC,UAAI,OAAO,cAAc,UAAW;AACpC,UAAI,OAAO,OAAO;AACjB,uBAAe,OAAO,OAAO,QAAQ,CAAC,IAAI,OAAO;AACjD,oBAAY;AAAA,MACb;AAAA,IACD;AAEA,QAAI,WAAW;AACd,YAAM,aAA0B;AAAA,QAC/B,MAAM;AAAA,QACN,WAAWA,gBAAe;AAAA,QAC1B,UAAU;AAAA;AAAA,QACV,QAAQ;AAAA,MACT;AACA,gBAAU,KAAK,UAAU;AAAA,IAC1B;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,WAAyB;AACrC,UAAM,SAAS,KAAK,QAAQ,IAAI,SAAS;AACzC,QAAI,CAAC,OAAQ;AAEb,SAAK,QAAQ,OAAO,SAAS;AAG7B,QAAI,OAAO,UAAU,KAAM;AAE3B,UAAM,gBAA2D;AAAA,MAChE,CAAC,OAAO,OAAO,QAAQ,CAAC,GAAG;AAAA,IAC5B;AAEA,UAAM,MAAmB;AAAA,MACxB,MAAM;AAAA,MACN,WAAWA,gBAAe;AAAA,MAC1B,UAAU,OAAO;AAAA,MACjB,QAAQ;AAAA,IACT;AAEA,SAAK,gBAAgB,WAAW,GAAG;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAAa,WAAmB,SAAuC;AACtE,UAAM,SAAS,KAAK,QAAQ,IAAI,SAAS;AACzC,QAAI,CAAC,OAAQ;AAGb,UAAM,cAAc,QAAQ,OAAO,OAAO,QAAQ,QAAQ,CAAC;AAC3D,QAAI,gBAAgB,QAAW;AAC9B,aAAO,QAAQ;AAAA,IAChB;AAGA,SAAK,gBAAgB,WAAW,OAAO;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAyB;AACxB,WAAO,KAAK,QAAQ;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACb,SAAK,QAAQ,MAAM;AAAA,EACpB;AAAA;AAAA,EAIQ,gBAAgB,kBAA0B,SAA4B;AAC7E,eAAW,CAAC,EAAE,MAAM,KAAK,KAAK,SAAS;AACtC,UAAI,OAAO,cAAc,iBAAkB;AAC3C,UAAI,CAAC,OAAO,UAAU,YAAY,EAAG;AAErC,aAAO,UAAU,KAAK,OAAO;AAAA,IAC9B;AAAA,EACD;AACD;;;AC9FO,SAAS,iBAAiBC,aAAoC;AACpE,MAAI,QAAQ;AACZ,aAAW,MAAMA,aAAY;AAC5B,aAAS,KAAK,UAAU,EAAE,EAAE;AAAA,EAC7B;AACA,SAAO;AACR;AAEO,IAAM,yBAAN,MAA6B;AAAA,EAC3B,YAAY,KAAK,IAAI;AAAA,EAErB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,gBAAgB;AAAA,EAEP,gBAAgB,oBAAI,IAA2B;AAAA;AAAA,EAGhE,iBAAiB,WAAyB;AACzC,SAAK;AACL,SAAK,cAAc,IAAI,WAAW;AAAA,MACjC;AAAA,MACA,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,aAAa,KAAK,IAAI;AAAA,MACtB,oBAAoB;AAAA,MACpB,gBAAgB;AAAA,MAChB,aAAa;AAAA,IACd,CAAC;AACD,SAAK,kBAAkB,KAAK,IAAI,KAAK,iBAAiB,KAAK,cAAc,IAAI;AAAA,EAC9E;AAAA;AAAA,EAGA,oBAAoB,WAAyB;AAC5C,SAAK,cAAc,OAAO,SAAS;AAAA,EACpC;AAAA;AAAA,EAGA,gBAAgB,WAAmB,QAAsB;AACxD,UAAM,SAAS,KAAK,cAAc,IAAI,SAAS;AAC/C,QAAI,QAAQ;AACX,aAAO,SAAS;AAAA,IACjB;AAAA,EACD;AAAA;AAAA,EAGA,mBAAmB,WAAmB,OAA2B;AAChE,UAAM,SAAS,KAAK,cAAc,IAAI,SAAS;AAC/C,QAAI,QAAQ;AACX,aAAO,QAAQ;AAAA,IAChB;AAAA,EACD;AAAA;AAAA,EAGA,WAAW,WAAmB,aAAuC;AACpE,UAAM,SAAS,KAAK,cAAc,IAAI,SAAS;AAC/C,QAAI,QAAQ;AACX,aAAO,cAAc;AAAA,IACtB;AAAA,EACD;AAAA;AAAA,EAGA,eAAe,WAAmBC,QAAe,UAAwB;AACxE,SAAK,sBAAsBA;AAC3B,SAAK,iBAAiB;AACtB,UAAM,SAAS,KAAK,cAAc,IAAI,SAAS;AAC/C,QAAI,QAAQ;AACX,aAAO,sBAAsBA;AAAA,IAC9B;AAAA,EACD;AAAA;AAAA,EAGA,WAAW,WAAmBA,QAAe,UAAwB;AACpE,SAAK,kBAAkBA;AACvB,SAAK,aAAa;AAClB,UAAM,SAAS,KAAK,cAAc,IAAI,SAAS;AAC/C,QAAI,QAAQ;AACX,aAAO,kBAAkBA;AAAA,IAC1B;AAAA,EACD;AAAA;AAAA,EAGA,cAAoB;AACnB,SAAK;AAAA,EACN;AAAA;AAAA,EAGA,iBAAiB,SAAuB;AACvC,SAAK,gBAAgB;AAAA,EACtB;AAAA;AAAA,EAGA,YAAY,iBAAgD;AAC3D,WAAO;AAAA,MACN,kBAAkB,KAAK,cAAc;AAAA,MACrC,kBAAkB,MAAM,KAAK,KAAK,cAAc,OAAO,CAAC,EACtD,OAAO,CAAC,MAAM,EAAE,WAAW,IAAI,EAC/B,IAAI,CAAC,MAAM,EAAE,MAAgB;AAAA,MAC/B,iBAAiB,KAAK;AAAA,MACtB,kBAAkB,KAAK;AAAA,MACvB,oBAAoB,KAAK;AAAA,MACzB,gBAAgB,KAAK;AAAA,MACrB,eAAe,KAAK;AAAA,MACpB,WAAW,KAAK;AAAA,MAChB,SAAS,MAAM,KAAK,KAAK,cAAc,OAAO,CAAC;AAAA,MAC/C,QAAQ,KAAK,IAAI,IAAI,KAAK;AAAA,MAC1B;AAAA,MACA,YAAY,KAAK;AAAA,MACjB,eAAe,KAAK;AAAA,IACrB;AAAA,EACD;AAAA;AAAA,EAGA,QAAc;AACb,SAAK,YAAY,KAAK,IAAI;AAC1B,SAAK,kBAAkB;AACvB,SAAK,mBAAmB;AACxB,SAAK,qBAAqB;AAC1B,SAAK,iBAAiB;AACtB,SAAK,gBAAgB;AACrB,SAAK,YAAY;AACjB,SAAK,aAAa;AAClB,SAAK,cAAc,MAAM;AAAA,EAC1B;AACD;;;AC9KA;AAAA,EAGC;AAAA,OACM;AA4BA,IAAM,iBAAN,MAAqB;AAAA,EACV,UAAU,oBAAI,IAAyB;AAAA;AAAA,EAEvC,UAAU,oBAAI,IAAoB;AAAA,EAClC;AAAA,EAEjB,YAAY,kBAAqC;AAChD,SAAK,mBAAmB,oBAAoB;AAAA,EAC7C;AAAA,EAEA,UAAU,WAAmB,WAAkC;AAC9D,SAAK,QAAQ,IAAI,WAAW,EAAE,WAAW,UAAU,CAAC;AAAA,EACrD;AAAA,EAEA,aAAa,WAAyB;AACrC,SAAK,QAAQ,OAAO,SAAS;AAG7B,eAAW,CAAC,WAAW,eAAe,KAAK,KAAK,SAAS;AACxD,UAAI,oBAAoB,WAAW;AAClC,aAAK,QAAQ,OAAO,SAAS;AAAA,MAC9B;AAAA,IACD;AAAA,EACD;AAAA,EAEA,iBAAyB;AACxB,WAAO,KAAK,QAAQ;AAAA,EACrB;AAAA,EAEA,kBAA0B;AACzB,WAAO,KAAK,QAAQ;AAAA,EACrB;AAAA,EAEA,QAAc;AACb,SAAK,QAAQ,MAAM;AACnB,SAAK,QAAQ,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAc,iBAAyB,SAAwC;AAC9E,QAAI,CAAC,KAAK,QAAQ,IAAI,eAAe,GAAG;AACvC;AAAA,IACD;AAEA,QAAI,KAAK,kBAAkB;AAC1B,WAAK,KAAK,iBAAiB,QAAQ,IAAI,EAAE;AAAA,QACxC,CAAC,UAAU;AACV,cAAI,UAAU,MAAM;AACnB,iBAAK,eAAe,iBAAiB,QAAQ,WAAW,qBAAqB,KAAK,CAAC;AACnF;AAAA,UACD;AACA,eAAK,sBAAsB,iBAAiB,OAAO;AAAA,QACpD;AAAA,QACA,MAAM;AAGL,eAAK,sBAAsB,iBAAiB,OAAO;AAAA,QACpD;AAAA,MACD;AACA;AAAA,IACD;AAEA,SAAK,sBAAsB,iBAAiB,OAAO;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,eAAe,iBAAyB,SAAyC;AAChF,QAAI,CAAC,KAAK,QAAQ,IAAI,eAAe,GAAG;AACvC;AAAA,IACD;AACA,QAAI,QAAQ,UAAU,MAAM;AAC3B;AAAA,IACD;AACA,UAAM,kBAAkB,KAAK,QAAQ,IAAI,QAAQ,SAAS;AAC1D,QAAI,CAAC,iBAAiB;AACrB;AAAA,IACD;AACA,SAAK,QAAQ,OAAO,QAAQ,SAAS;AACrC,SAAK,eAAe,iBAAiB,QAAQ,WAAW,QAAQ,KAAK;AAAA,EACtE;AAAA,EAEQ,sBAAsB,iBAAyB,SAAwC;AAC9F,SAAK,QAAQ,IAAI,QAAQ,WAAW,eAAe;AACnD,eAAW,CAAC,EAAE,MAAM,KAAK,KAAK,SAAS;AACtC,UAAI,OAAO,cAAc,iBAAiB;AACzC;AAAA,MACD;AACA,UAAI,CAAC,OAAO,UAAU,YAAY,GAAG;AACpC;AAAA,MACD;AACA,aAAO,UAAU,KAAK,OAAO;AAAA,IAC9B;AAAA,EACD;AAAA,EAEQ,eAAe,WAAmB,WAAmB,OAAqB;AACjF,UAAM,SAAS,KAAK,QAAQ,IAAI,SAAS;AACzC,QAAI,CAAC,UAAU,CAAC,OAAO,UAAU,YAAY,GAAG;AAC/C;AAAA,IACD;AACA,UAAM,WAAqC;AAAA,MAC1C,MAAM;AAAA,MACN,WAAW,mBAAmB,SAAS;AAAA,MACvC;AAAA,MACA;AAAA,IACD;AACA,WAAO,UAAU,KAAK,QAAQ;AAAA,EAC/B;AACD;AAOA,SAAS,mBAAmB,WAA2B;AACtD,SAAO,aAAa,SAAS;AAC9B;;;ACjJO,IAAM,cAAN,MAAkB;AAAA,EACP,UAAU,oBAAI,IAAyB;AAAA,EAExD,UAAU,WAAmB,WAAkC;AAC9D,SAAK,QAAQ,IAAI,WAAW,EAAE,WAAW,UAAU,CAAC;AAAA,EACrD;AAAA,EAEA,aAAa,WAAyB;AACrC,SAAK,QAAQ,OAAO,SAAS;AAAA,EAC9B;AAAA,EAEA,aAAa,iBAAyB,SAAoC;AACzE,QAAI,CAAC,KAAK,QAAQ,IAAI,eAAe,GAAG;AACvC;AAAA,IACD;AACA,SAAK,gBAAgB,iBAAiB,OAAO;AAAA,EAC9C;AAAA,EAEA,iBAAyB;AACxB,WAAO,KAAK,QAAQ;AAAA,EACrB;AAAA,EAEA,QAAc;AACb,SAAK,QAAQ,MAAM;AAAA,EACpB;AAAA,EAEQ,gBAAgB,kBAA0B,SAA4B;AAC7E,eAAW,CAAC,EAAE,MAAM,KAAK,KAAK,SAAS;AACtC,UAAI,OAAO,cAAc,kBAAkB;AAC1C;AAAA,MACD;AACA,UAAI,CAAC,OAAO,UAAU,YAAY,GAAG;AACpC;AAAA,MACD;AACA,aAAO,UAAU,KAAK,OAAO;AAAA,IAC9B;AAAA,EACD;AACD;;;ACjDA;AAAA,EAEC,sBAAAC;AAAA,EAEA,mBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;;;ACmBP,SAAS,cAAc,QAAiB,WAA6C;AACpF,MAAI,SAAS,aAAa,CAAC,OAAO,GAAG,QAAQ,UAAU,GAAG,GAAG;AAC5D,WAAO;AAAA,EACR;AACA,MAAI,SAAS,aAAa,OAAO,GAAG,QAAQ,UAAU,GAAG,GAAG;AAC3D,WAAO;AAAA,EACR;AACA,MACC,UAAU,QAAQ,UAClB,CAAC,UAAU,IAAI,KAAK,CAAC,cAAc,OAAO,GAAG,QAAQ,SAAS,CAAC,GAC9D;AACD,WAAO;AAAA,EACR;AAEA,QAAM,gBAAsF;AAAA,IAC3F,CAAC,OAAO,CAAC,GAAG,MAAM,IAAI,CAAC;AAAA,IACvB,CAAC,QAAQ,CAAC,GAAG,MAAM,KAAK,CAAC;AAAA,IACzB,CAAC,OAAO,CAAC,GAAG,MAAM,IAAI,CAAC;AAAA,IACvB,CAAC,QAAQ,CAAC,GAAG,MAAM,KAAK,CAAC;AAAA,EAC1B;AACA,aAAW,CAAC,UAAU,OAAO,KAAK,eAAe;AAChD,UAAM,QAAQ,UAAU,QAAQ;AAChC,QAAI,UAAU,QAAW;AACxB;AAAA,IACD;AACA,QAAI,OAAO,WAAW,YAAY,OAAO,UAAU,UAAU;AAC5D,aAAO;AAAA,IACR;AACA,QAAI,CAAC,QAAQ,QAAQ,KAAK,GAAG;AAC5B,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;AAWO,SAAS,uBACf,QACA,WACU;AACV,QAAM,SAAS,OAAO,KAAK,SAAS;AACpC,MAAI,OAAO,WAAW,GAAG;AACxB,WAAO;AAAA,EACR;AACA,MAAI,WAAW,MAAM;AACpB,WAAO;AAAA,EACR;AACA,aAAW,SAAS,QAAQ;AAC3B,UAAM,YAAY,UAAU,KAAK;AACjC,QAAI,aAAa,CAAC,cAAc,OAAO,KAAK,GAAG,SAAS,GAAG;AAC1D,aAAO;AAAA,IACR;AAAA,EACD;AACA,SAAO;AACR;;;ADqDA,SAAS,mBACR,YACA,QACA,OACU;AACV,QAAM,kBAAkB,MAAM,UAAU;AACxC,MAAI,CAAC,iBAAiB;AACrB,WAAO;AAAA,EACR;AACA,aAAW,CAAC,OAAO,QAAQ,KAAK,OAAO,QAAQ,eAAe,GAAG;AAChE,QAAI,OAAO,KAAK,MAAM,UAAU;AAC/B,aAAO;AAAA,IACR;AAAA,EACD;AACA,SAAO;AACR;AAGA,SAAS,WAAW,QAAiC,MAAyC;AAC7F,QAAM,SAAkC,CAAC;AACzC,aAAW,OAAO,MAAM;AACvB,QAAI,OAAO,QAAQ;AAClB,aAAO,GAAG,IAAI,OAAO,GAAG;AAAA,IACzB;AAAA,EACD;AACA,SAAO;AACR;AAgBA,eAAe,oBACd,OACA,UACA,iBACA,eACqB;AACrB,QAAM,SAAS,MAAM,UAAU;AAC/B,QAAM,QAAQ,iBAAiB,IAAIC,oBAAmB,MAAM;AAC5D,QAAM,gBAAgB,MAAM,UAAU,GAAG,WAAW;AACpD,QAAM,iBAAiB,yBAAyB,KAAK;AAErD,MAAI,SAAS,SAAS,UAAU;AAC/B,WAAOC;AAAA,MACN;AAAA,QACC;AAAA,QACA,MAAM;AAAA,QACN,YAAY,SAAS;AAAA,QACrB,UAAU,SAAS,YAAYC,gBAAe;AAAA,QAC9C,MAAM,SAAS,QAAQ,CAAC;AAAA,QACxB,cAAc;AAAA,QACd;AAAA,QACA,YAAY,CAAC;AAAA,QACb;AAAA,MACD;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAEA,MAAI,CAAC,SAAS,UAAU;AACvB,UAAM,IAAI;AAAA,MACT;AAAA,MACA,KAAK,SAAS,IAAI,iBAAiB,SAAS,UAAU;AAAA,IACvD;AAAA,EACD;AAEA,QAAM,UAAU,kBACb,gBAAgB,SAChB,MAAM,MAAM,WAAW,SAAS,YAAY,SAAS,QAAQ;AAEhE,MAAI,SAAS,SAAS,UAAU;AAC/B,UAAM,UAAU,SAAS,QAAQ,CAAC;AAKlC,UAAM,OAAgC,CAAC;AACvC,UAAM,YAAsC,CAAC;AAC7C,eAAW,OAAO,OAAO,KAAK,OAAO,GAAG;AACvC,YAAM,QAAQ,QAAQ,GAAG;AACzB,UAAI,WAAW,KAAK,GAAG;AACtB,aAAK,GAAG,IAAI,gBAAgB,UAAU,QAAQ,GAAG,IAAI,QAAW,KAAK;AACrE,kBAAU,GAAG,IAAI,WAAW,KAAK;AAAA,MAClC,OAAO;AACN,aAAK,GAAG,IAAI;AAAA,MACb;AAAA,IACD;AACA,WAAOD;AAAA,MACN;AAAA,QACC;AAAA,QACA,MAAM;AAAA,QACN,YAAY,SAAS;AAAA,QACrB,UAAU,SAAS;AAAA,QACnB;AAAA,QACA,cAAc,UAAU,WAAW,SAAS,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC;AAAA,QACrE;AAAA,QACA,YAAY,CAAC;AAAA,QACb;AAAA,QACA,GAAI,OAAO,KAAK,SAAS,EAAE,SAAS,IAAI,EAAE,UAAU,IAAI,CAAC;AAAA,MAC1D;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAGA,SAAOA;AAAA,IACN;AAAA,MACC;AAAA,MACA,MAAM;AAAA,MACN,YAAY,SAAS;AAAA,MACrB,UAAU,SAAS;AAAA,MACnB,MAAM;AAAA,MACN,cAAc,UAAU,EAAE,GAAG,QAAQ,IAAI;AAAA,MACzC;AAAA,MACA,YAAY,CAAC;AAAA,MACb;AAAA,IACD;AAAA,IACA;AAAA,EACD;AACD;AAGA,IAAM,qBAAN,cAAiC,MAAM;AAAA,EACtC,YACU,MACT,SACC;AACD,UAAM,OAAO;AAHJ;AAIT,SAAK,OAAO;AAAA,EACb;AAAA,EALU;AAMX;AAUO,SAAS,mBACf,QACA,OAC6B;AAG7B,MAAI,eAAiC,QAAQ,QAAQ;AAErD,WAAS,UAAa,MAAoC;AACzD,UAAM,MAAM,aAAa,KAAK,MAAM,IAAI;AAGxC,mBAAe,IAAI;AAAA,MAClB,MAAM;AAAA,MACN,MAAM;AAAA,IACP;AACA,WAAO;AAAA,EACR;AASA,iBAAe,gBACd,UACA,OAC4B;AAC5B,QAAI;AACJ,QAAI;AACH,WAAK,MAAM,oBAAoB,OAAO,QAAQ;AAAA,IAC/C,SAAS,OAAO;AACf,UAAI,iBAAiB,oBAAoB;AACxC,eAAO;AAAA,UACN,IAAI;AAAA,UACJ,WAAW;AAAA,YACV,IAAI;AAAA,YACJ,MAAM,MAAM;AAAA,YACZ,SAAS,MAAM;AAAA,YACf,WAAW,qBAAqB,MAAM,IAAI;AAAA,UAC3C;AAAA,QACD;AAAA,MACD;AACA,YAAM;AAAA,IACP;AAEA,QAAI,SAAS,CAAC,uBAAuB,IAAI,KAAK,GAAG;AAChD,aAAO;AAAA,QACN,IAAI;AAAA,QACJ,WAAW;AAAA,UACV,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,SAAS,gBAAgB,SAAS,UAAU;AAAA,UAC5C,WAAW,qBAAqB,iBAAiB;AAAA,QAClD;AAAA,MACD;AAAA,IACD;AAEA,WAAO,EAAE,IAAI,MAAM,GAAG;AAAA,EACvB;AAGA,iBAAe,gBAAgB,IAAe,YAA+C;AAC5F,UAAM,SAAS,MAAM,OAAO,oBAAoB,EAAE;AAClD,QAAI,OAAO,WAAW,WAAW;AAChC,YAAM,OAAO,OAAO,WAAW,QAAQ;AACvC,aAAO;AAAA,QACN,IAAI;AAAA,QACJ;AAAA,QACA,SACC,OAAO,WAAW,WAClB,iBAAiB,UAAU,sBAAsB,OAAO,MAAM;AAAA;AAAA;AAAA,QAG/D,WAAW,OAAO,WAAW,aAAa,qBAAqB,IAAI;AAAA,MACpE;AAAA,IACD;AAEA,UAAM,SAAS,MAAM,MAAM,WAAW,YAAY,GAAG,QAAQ;AAC7D,WAAO,EAAE,IAAI,MAAM,WAAW,IAAI,OAAO;AAAA,EAC1C;AAKA,iBAAe,SACd,UACA,OAC4B;AAC5B,UAAM,WAAW,MAAM,gBAAgB,UAAU,KAAK;AACtD,QAAI,CAAC,SAAS,IAAI;AACjB,aAAO,SAAS;AAAA,IACjB;AACA,WAAO,gBAAgB,SAAS,IAAI,SAAS,UAAU;AAAA,EACxD;AAQA,iBAAe,uBACd,uBACA,MACA,SACkC;AAClC,UAAM,QAAQ,SAAS;AAGvB,UAAM,YAA6B,CAAC;AACpC,UAAM,kBAAkB,KAAK,WAAW,UAAa,KAAK,WAAW;AACrE,QAAI,iBAAiB;AACpB,gBAAU,KAAK;AAAA,QACd,YAAY,KAAK;AAAA,QACjB,MAAM;AAAA,QACN,UAAU,KAAK;AAAA,QACf,MAAM,KAAK;AAAA,MACZ,CAAC;AAAA,IACF;AACA,QAAI,KAAK,MAAM;AACd,gBAAU,KAAK,GAAG,KAAK,IAAI;AAAA,IAC5B;AAEA,QAAI;AACJ,QAAI;AACH,eAAS,MAAM,sBAAsB;AAAA,QACpC,QAAQ,EAAE,YAAY,KAAK,YAAY,IAAI,KAAK,GAAG;AAAA,QACnD,GAAI,KAAK,iBAAiB,EAAE,gBAAgB,KAAK,eAAe,IAAI,CAAC;AAAA,QACrE,OAAO,CAAC,YACP,KAAK,MAAM,OAAO,KAAK,KAAK,EAAE,EAAE,SAAS,IACtC,uBAAuB,SAAS,KAAK,EAAE,IACvC;AAAA,QACJ,iBAAiB,OAAO,SAAS,YAAY;AAC5C,gBAAM,MAAmB,CAAC;AAC1B,mBAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AAC1C,kBAAM,WAAW,UAAU,CAAC;AAM5B,kBAAM,mBAAmB,MAAM,KAAK;AACpC,kBAAM,KAAK,MAAM;AAAA,cAChB;AAAA,cACA;AAAA,cACA,mBAAmB,EAAE,QAAQ,QAAQ,IAAI;AAAA,cACzC,QAAQ;AAAA,YACT;AAGA,gBAAI,SAAS,CAAC,uBAAuB,IAAI,KAAK,GAAG;AAChD,oBAAM,IAAI;AAAA,gBACT;AAAA,gBACA,gBAAgB,SAAS,UAAU;AAAA,cACpC;AAAA,YACD;AACA,gBAAI,KAAK,EAAE;AAAA,UACZ;AACA,iBAAO;AAAA,QACR;AAAA,MACD,CAAC;AAAA,IACF,SAAS,OAAO;AAGf,UAAI,iBAAiB,oBAAoB;AACxC,eAAO;AAAA,UACN,IAAI;AAAA,UACJ,MAAM,MAAM;AAAA,UACZ,SAAS,MAAM;AAAA,UACf,WAAW,qBAAqB,MAAM,IAAI;AAAA,QAC3C;AAAA,MACD;AACA,YAAM;AAAA,IACP;AAGA,QAAI,CAAC,OAAO,UAAU;AACrB,aAAO;AAAA,QACN,IAAI;AAAA,QACJ,MAAM,KAAK,QAAQ,QAAQ;AAAA,QAC3B,SACC,KAAK,QAAQ,WACb,mCAAmC,KAAK,UAAU,aAAa,KAAK,EAAE;AAAA,QACvE,WAAW;AAAA,MACZ;AAAA,IACD;AAIA,QAAI,OAAO,YAAY;AACtB,YAAME,WAAyC,KAAK,iBACjD,CAAC,MAAM,MAAM,WAAW,KAAK,eAAe,YAAY,KAAK,eAAe,EAAE,CAAC,IAC/E,CAAC;AACJ,aAAO,EAAE,IAAI,MAAM,YAAY,MAAM,YAAY,CAAC,GAAG,SAAAA,SAAQ;AAAA,IAC9D;AAIA,WAAO,sBAAsB,OAAO,OAAO;AAC3C,UAAM,UAAyC,CAAC;AAChD,eAAW,MAAM,OAAO,SAAS;AAChC,cAAQ,KAAK,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,QAAQ,CAAC;AAAA,IAChE;AACA,WAAO,EAAE,IAAI,MAAM,YAAY,OAAO,YAAY,OAAO,SAAS,QAAQ;AAAA,EAC3E;AAEA,SAAO;AAAA,IACN,MAAM,UAAU,SAAoC;AACnD,aAAO,UAAU,MAAM,SAAS,UAAU,SAAS,KAAK,CAAC;AAAA,IAC1D;AAAA,IAEA,iBAAiB,MAAM,SAA0C;AAOhE,YAAM,wBAAwB,MAAM;AACpC,UAAI,uBAAuB;AAC1B,eAAO,uBAAuB,sBAAsB,KAAK,KAAK,GAAG,MAAM,OAAO;AAAA,MAC/E;AACA,aAAO,UAAU,YAAY;AAI5B,YAAI,KAAK,gBAAgB;AACxB,gBAAM,WAAW,MAAM,MAAM;AAAA,YAC5B,KAAK,eAAe;AAAA,YACpB,KAAK,eAAe;AAAA,UACrB;AACA,cAAI,UAAU;AACb,mBAAO,EAAE,IAAI,MAAM,YAAY,MAAM,YAAY,CAAC,GAAG,SAAS,CAAC,QAAQ,EAAE;AAAA,UAC1E;AAAA,QACD;AAGA,YAAI,KAAK,MAAM,OAAO,KAAK,KAAK,EAAE,EAAE,SAAS,GAAG;AAC/C,gBAAM,SAAS,MAAM,MAAM,WAAW,KAAK,YAAY,KAAK,EAAE;AAC9D,cAAI,CAAC,uBAAuB,QAAQ,KAAK,EAAE,GAAG;AAC7C,kBAAM,OAAO,KAAK,QAAQ,QAAQ;AAClC,mBAAO;AAAA,cACN,IAAI;AAAA,cACJ;AAAA,cACA,SACC,KAAK,QAAQ,WACb,mCAAmC,KAAK,UAAU,aAAa,KAAK,EAAE;AAAA,cACvE,WAAW;AAAA,YACZ;AAAA,UACD;AAAA,QACD;AAKA,cAAM,YAA6B,CAAC;AACpC,YAAI,KAAK,WAAW,UAAa,KAAK,WAAW,MAAM;AACtD,oBAAU,KAAK;AAAA,YACd,YAAY,KAAK;AAAA,YACjB,MAAM;AAAA,YACN,UAAU,KAAK;AAAA,YACf,MAAM,KAAK;AAAA,UACZ,CAAC;AAAA,QACF;AACA,YAAI,KAAK,MAAM;AACd,oBAAU,KAAK,GAAG,KAAK,IAAI;AAAA,QAC5B;AAIA,cAAM,WAAoD,CAAC;AAC3D,mBAAW,YAAY,WAAW;AACjC,gBAAM,IAAI,MAAM,gBAAgB,UAAU,SAAS,KAAK;AACxD,cAAI,CAAC,EAAE,IAAI;AACV,mBAAO,EAAE;AAAA,UACV;AACA,mBAAS,KAAK,EAAE,IAAI,EAAE,IAAI,YAAY,SAAS,WAAW,CAAC;AAAA,QAC5D;AAEA,cAAMC,cAA0B,CAAC;AACjC,cAAM,UAAyC,CAAC;AAChD,mBAAW,EAAE,IAAI,WAAW,KAAK,UAAU;AAC1C,gBAAM,SAAS,MAAM,gBAAgB,IAAI,UAAU;AACnD,cAAI,CAAC,OAAO,IAAI;AACf,mBAAO;AAAA,cACN,IAAI;AAAA,cACJ,MAAM,OAAO;AAAA,cACb,SAAS,OAAO;AAAA,cAChB,WAAW,OAAO;AAAA,YACnB;AAAA,UACD;AACA,UAAAA,YAAW,KAAK,OAAO,SAAS;AAChC,kBAAQ,KAAK,OAAO,MAAM;AAAA,QAC3B;AAEA,eAAO,EAAE,IAAI,MAAM,YAAY,OAAO,YAAAA,aAAY,QAAQ;AAAA,MAC3D,CAAC;AAAA,IACF;AAAA,IAEA,MAAM,MAAM,YAAY,SAAwC;AAC/D,YAAM,EAAE,OAAO,GAAG,aAAa,IAAI,WAAW,CAAC;AAC/C,YAAM,UAAU,MAAM,MAAM,gBAAgB,YAAY,YAAY;AACpE,UAAI,CAAC,OAAO;AACX,eAAO;AAAA,MACR;AACA,aAAO,QAAQ,OAAO,CAAC,WAAW,mBAAmB,YAAY,QAAQ,KAAK,CAAC;AAAA,IAChF;AAAA,IAEA,MAAM,SAAS,YAAY,IAAI,SAA6C;AAC3E,YAAM,SAAS,MAAM,MAAM,WAAW,YAAY,EAAE;AACpD,UAAI,CAAC,QAAQ;AACZ,eAAO;AAAA,MACR;AACA,UAAI,SAAS,SAAS,CAAC,mBAAmB,YAAY,QAAQ,QAAQ,KAAK,GAAG;AAC7E,eAAO;AAAA,MACR;AACA,aAAO;AAAA,IACR;AAAA,EACD;AACD;;;AL3kBA,IAAM,0BAA0B;AAChC,IAAMC,sBAAqB;AAC3B,IAAMC,0BAAyB;AAC/B,IAAM,eAAe;AACrB,IAAM,eAAe;AACrB,IAAM,uCAAuC;AAC7C,IAAM,oCAAoC;AAqB1C,SAAS,uBAAuB,MAAc,OAAuB;AACpE,MAAI,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,GAAG;AACrE,UAAM,IAAIC,WAAU,GAAG,IAAI,0DAA0D;AAAA,MACpF,CAAC,IAAI,GAAG;AAAA,IACT,CAAC;AAAA,EACF;AACA,SAAO;AACR;AAWO,IAAM,iBAAN,MAAM,gBAAe;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,iBAAiB,IAAI,eAAe;AAAA,EACpC,cAAc,IAAI,YAAY;AAAA,EAC9B;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW,oBAAI,IAA2B;AAAA,EAC1C,cAAc,oBAAI,IAGjC;AAAA,EACe,sBAAsB,oBAAI,IAAoB;AAAA;AAAA;AAAA,EAG9C,gBAAgB;AAAA,EACzB,WAAgC;AAAA,EAChC,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMV,uBAA8D;AAAA,EAC9D,oBAA2D;AAAA,EAC3D,+BAA+B;AAAA,EAC/B,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMd,uBAAuB,oBAAI,IAG1C;AAAA,EACF,OAAwB,kCAAkC;AAAA,EAC1D,OAAwB,wBAAwB,IAAI;AAAA,EAEpD,YAAY,QAA8B;AACzC,SAAK,QAAQ,OAAO;AACpB,UAAM,qBAAqB,KAAK,MAAM,UAAU,GAAG;AACnD,QACC,OAAO,kBAAkB,UACzB,uBAAuB,UACvB,OAAO,kBAAkB,oBACxB;AACD,YAAM,IAAIA,WAAU,mEAAmE;AAAA,QACtF,mBAAmB,OAAO;AAAA,QAC1B;AAAA,MACD,CAAC;AAAA,IACF;AACA,SAAK,OAAO,OAAO,QAAQ;AAC3B,SAAK,aAAa,OAAO,cAAc,IAAIC,uBAAsB;AACjE,SAAK,UAAU,OAAO,WAAW;AACjC,SAAK,iBAAiB,OAAO,kBAAkB;AAC/C,SAAK,YAAY,OAAO,aAAaH;AACrC,SAAK,4BAA4B;AAAA,MAChC;AAAA,MACA,OAAO,6BAA6B;AAAA,IACrC;AACA,SAAK,yBAAyB;AAAA,MAC7B;AAAA,MACA,OAAO,0BAA0B;AAAA,IAClC;AACA,SAAK,gBAAgB,OAAO,iBAAiB,sBAAsBC;AACnE,SAAK,0BAA0B,OAAO,2BAA2B;AAAA,MAChE,KAAK,KAAK;AAAA,MACV,KAAK,KAAK;AAAA,IACX;AACA,SAAK,sBAAsB,OAAO,uBAAuB,CAAC;AAC1D,SAAK,OAAO,OAAO;AACnB,SAAK,OAAO,OAAO,QAAQ;AAC3B,SAAK,OAAO,OAAO,QAAQ;AAC3B,SAAK,SAAS,OAAO,UAAU,oBAAoB;AACnD,SAAK,UAAU,OAAO,oBAAoB,IAAI,uBAAuB;AACrE,SAAK,QAAQ,iBAAiB,KAAK,aAAa;AAChD,SAAK,iBAAiB,IAAI,eAAe,OAAO,gBAAgB;AAChE,SAAK,mBAAmB,OAAO,oBAAoB;AACnD,SAAK,oBAAoB,OAAO;AAChC,SAAK,kBAAkB,OAAO;AAC9B,SAAK,oBAAoB,OAAO;AAIhC,SAAK,cAAc,mBAAmB,MAAM,KAAK,KAAK;AAItD,QAAI,CAAC,KAAK,SAAS;AAClB,WAAK,UAAU,IAAI,mBAAmB;AAAA,IACvC;AAAA,EACD;AAAA,EAEQ,gCAAsC;AAC7C,QAAI,KAAK,4BAA4B,KAAK,CAAC,KAAK,sBAAsB;AACrE,WAAK,uBAAuB,YAAY,MAAM;AAC7C,aAAK,wBAAwB,KAAK,yBAAyB;AAAA,MAC5D,GAAG,KAAK,yBAAyB;AACjC,WAAK,qBAAqB,QAAQ;AAAA,IACnC;AAEA,QAAI,KAAK,yBAAyB,KAAK,CAAC,KAAK,mBAAmB;AAC/D,WAAK,oBAAoB,YAAY,MAAM;AAC1C,aAAK,KAAK,gBAAgB;AAAA,MAC3B,GAAG,KAAK,sBAAsB;AAC9B,WAAK,kBAAkB,QAAQ;AAAA,IAChC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,wBAAwB,UAAU,GAAS;AAC1C,eAAW,WAAW,KAAK,SAAS,OAAO,GAAG;AAC7C,cAAQ,wBAAwB,OAAO;AAAA,IACxC;AACA,SAAK,qBAAqB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,kBAAiC;AACtC,QAAI,KAAK,qBAAsB;AAC/B,SAAK,uBAAuB;AAC5B,QAAI;AACH,YAAM,sBAAsB,MAAM,KAAK,MAAM,uBAAuB;AACpE,UAAI,uBAAuB,KAAK,8BAA8B;AAC7D,mBAAW,WAAW,KAAK,SAAS,OAAO,GAAG;AAC7C,kBAAQ,8BAA8B,KAAK,wBAAwB;AAAA,YAClE,YAAY;AAAA,UACb,CAAC;AAAA,QACF;AACA;AAAA,MACD;AACA,WAAK,+BAA+B;AACpC,iBAAW,WAAW,KAAK,SAAS,OAAO,GAAG;AAC7C,gBAAQ,8BAA8B,CAAC;AAAA,MACxC;AAAA,IACD,SAAS,OAAO;AACf,WAAK,OAAO,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP,SAAS,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,MAC1E,CAAC;AAAA,IACF,UAAE;AACD,WAAK,uBAAuB;AAAA,IAC7B;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,qBAAqB,QAAgB,KAAwB;AACpE,QAAI,IAAI,WAAW,EAAG;AACtB,UAAM,WAAW,KAAK,qBAAqB,IAAI,MAAM;AACrD,UAAM,SAAS,WAAW,SAAS,MAAM,CAAC;AAC1C,UAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;AAC9C,eAAW,MAAM,KAAK;AACrB,UAAI,CAAC,KAAK,IAAI,GAAG,EAAE,GAAG;AACrB,eAAO,KAAK,EAAE;AACd,aAAK,IAAI,GAAG,EAAE;AAAA,MACf;AAAA,IACD;AAEA,UAAM,UACL,OAAO,SAAS,gBAAe,kCAC5B,OAAO,MAAM,OAAO,SAAS,gBAAe,+BAA+B,IAC3E;AACJ,SAAK,qBAAqB,IAAI,QAAQ,EAAE,KAAK,SAAS,cAAc,KAAK,IAAI,EAAE,CAAC;AAAA,EACjF;AAAA;AAAA,EAGQ,mBAAmB,QAA6B;AACvD,UAAM,QAAQ,KAAK,qBAAqB,IAAI,MAAM;AAClD,QAAI,CAAC,MAAO,QAAO,CAAC;AACpB,SAAK,qBAAqB,OAAO,MAAM;AACvC,WAAO,MAAM;AAAA,EACd;AAAA;AAAA,EAGQ,uBAA6B;AACpC,QAAI,KAAK,qBAAqB,SAAS,EAAG;AAC1C,UAAM,SAAS,KAAK,IAAI,IAAI,gBAAe;AAC3C,eAAW,CAAC,QAAQ,KAAK,KAAK,KAAK,sBAAsB;AACxD,UAAI,MAAM,gBAAgB,QAAQ;AACjC,aAAK,qBAAqB,OAAO,MAAM;AAAA,MACxC;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAA6C;AAC5C,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,oBAAoB,WAAmB,gBAAwC;AACtF,mBAAe,GAAG,kBAAkB,CAAC,UAAU;AAC9C,WAAK,QAAQ,gBAAgB,WAAW,MAAM,MAAM;AACpD,WAAK,OAAO,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA,QAAQ,MAAM;AAAA,MACf,CAAC;AAAA,IACF,CAAC;AAED,mBAAe,GAAG,iBAAiB,CAAC,UAAU;AAC7C,YAAM,WAAW,iBAAiB,MAAM,UAAU;AAClD,WAAK,QAAQ,eAAe,WAAW,MAAM,WAAW,QAAQ;AAChE,WAAK,OAAO,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA,OAAO,MAAM;AAAA,QACb,OAAO;AAAA,MACR,CAAC;AAAA,IACF,CAAC;AAED,mBAAe,GAAG,aAAa,CAAC,UAAU;AACzC,YAAM,WAAW,iBAAiB,MAAM,UAAU;AAClD,WAAK,QAAQ,WAAW,WAAW,MAAM,WAAW,QAAQ;AAC5D,WAAK,OAAO,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA,OAAO,MAAM;AAAA,QACb,OAAO;AAAA,MACR,CAAC;AAAA,IACF,CAAC;AAED,mBAAe,GAAG,qBAAqB,CAAC,UAAU;AACjD,WAAK,OAAO,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA,SAAS,EAAE,QAAQ,MAAM,OAAO;AAAA,MACjC,CAAC;AAAA,IACF,CAAC;AAED,mBAAe,GAAG,wBAAwB,CAAC,UAAU;AACpD,WAAK,OAAO,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA,SAAS;AAAA,UACR,qBAAqB,MAAM;AAAA,UAC3B,qBAAqB,MAAM;AAAA,UAC3B,cAAc,MAAM;AAAA,UACpB,cAAc,MAAM;AAAA,UACpB,QAAQ,MAAM;AAAA,QACf;AAAA,MACD,CAAC;AAAA,IACF,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,sBAA8C;AAC7C,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,YAAoB;AACnB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,MAAM,cAAmD;AAC9D,QAAI,KAAK,SAAS;AACjB,YAAM,IAAIC,WAAU,6BAA6B,EAAE,MAAM,KAAK,KAAK,CAAC;AAAA,IACrE;AAEA,QAAI,CAAC,gBAAgB,KAAK,SAAS,QAAW;AAC7C,YAAM,IAAIA;AAAA,QACT;AAAA,QACA,CAAC;AAAA,MACF;AAAA,IACD;AAEA,QAAI,cAAc;AACjB,WAAK,WAAW,IAAI,aAAa;AAAA,QAChC,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,MACZ,CAAC;AAAA,IACF,OAAO;AAEN,YAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,IAAI;AAC7C,WAAK,WAAW,IAAI,gBAAgB;AAAA,QACnC,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,MACZ,CAAC;AAAA,IACF;AAEA,SAAK,SAAS,GAAG,cAAc,CAAC,OAAgB;AAC/C,YAAM,YAAY,IAAI;AAAA,QACrB;AAAA,QACA;AAAA,UACC,YAAY,KAAK;AAAA,QAClB;AAAA,MACD;AACA,WAAK,iBAAiB,SAAS;AAAA,IAChC,CAAC;AAED,SAAK,UAAU;AACf,SAAK,OAAO,IAAI;AAAA,MACf,WAAW,KAAK,IAAI;AAAA,MACpB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS,EAAE,MAAM,KAAK,MAAM,MAAM,KAAK,MAAM,MAAM,KAAK,KAAK;AAAA,IAC9D,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAsB;AAC3B,SAAK,OAAO,IAAI;AAAA,MACf,WAAW,KAAK,IAAI;AAAA,MACpB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS,EAAE,kBAAkB,KAAK,SAAS,KAAK;AAAA,IACjD,CAAC;AAGD,QAAI,KAAK,sBAAsB;AAC9B,oBAAc,KAAK,oBAAoB;AACvC,WAAK,uBAAuB;AAAA,IAC7B;AACA,QAAI,KAAK,mBAAmB;AAC3B,oBAAc,KAAK,iBAAiB;AACpC,WAAK,oBAAoB;AAAA,IAC1B;AACA,SAAK,qBAAqB,MAAM;AAGhC,SAAK,eAAe,MAAM;AAC1B,SAAK,YAAY,MAAM;AACvB,SAAK,eAAe,MAAM;AAG1B,eAAW,WAAW,KAAK,SAAS,OAAO,GAAG;AAC7C,cAAQ,MAAM,sBAAsB;AAAA,IACrC;AACA,SAAK,SAAS,MAAM;AACpB,SAAK,YAAY,MAAM;AACvB,SAAK,oBAAoB,MAAM;AAG/B,QAAI,KAAK,UAAU;AAClB,YAAM,IAAI,QAAc,CAAC,YAAY;AACpC,aAAK,UAAU,MAAM,MAAM,QAAQ,CAAC;AAAA,MACrC,CAAC;AACD,WAAK,WAAW;AAAA,IACjB;AAEA,SAAK,UAAU;AACf,SAAK,OAAO,IAAI;AAAA,MACf,WAAW,KAAK,IAAI;AAAA,MACpB,OAAO;AAAA,MACP,OAAO;AAAA,IACR,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,kBAAkB,SAAqD;AAC5E,QAAI,CAAC,QAAQ,YAAY,QAAQ,SAAS,KAAK,EAAE,WAAW,GAAG;AAC9D,aAAO,EAAE,QAAQ,IAAI;AAAA,IACtB;AAEA,UAAM,SAAS,KAAK,sBAAsB,QAAQ,QAAQ;AAE1D,QAAI,QAAQ,WAAW,QAAQ;AAC9B,UAAI,QAAQ,SAAS,QAAW;AAC/B,eAAO,EAAE,QAAQ,IAAI;AAAA,MACtB;AAEA,YAAM,UAAU,kBAAkB,QAAQ,MAAM,QAAQ,WAAW;AACnE,aAAO,UAAU,QAAQ,OAAO;AAChC,aAAO,EAAE,QAAQ,IAAI;AAAA,IACtB;AAEA,QAAI,QAAQ,WAAW,OAAO;AAC7B,YAAM,SAAS,OAAO,UAAU,KAAK,QAAQ,WAAW;AACxD,aAAO;AAAA,QACN,QAAQ,OAAO;AAAA,QACf,MAAM,OAAO;AAAA,QACb,SAAS,OAAO;AAAA,MACjB;AAAA,IACD;AAEA,WAAO;AAAA,MACN,QAAQ;AAAA,MACR,SAAS,EAAE,OAAO,YAAY;AAAA,IAC/B;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,iBAAiB,WAAoC;AAEpD,QAAI,KAAK,iBAAiB,KAAK,KAAK,SAAS,QAAQ,KAAK,gBAAgB;AACzE,gBAAU,KAAK;AAAA,QACd,MAAM;AAAA,QACN,WAAWE,gBAAe;AAAA,QAC1B,MAAM;AAAA,QACN,SAAS,2CAA2C,KAAK,cAAc;AAAA,QACvE,WAAW;AAAA,MACZ,CAAC;AACD,gBAAU,MAAM,MAAM,yBAAyB;AAC/C,WAAK,QAAQ,YAAY;AACzB,WAAK,OAAO,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP,SAAS,EAAE,QAAQ,mBAAmB,KAAK,KAAK,eAAe;AAAA,MAChE,CAAC;AACD,YAAM,IAAIF,WAAU,+BAA+B;AAAA,QAClD,SAAS,KAAK,SAAS;AAAA,QACvB,KAAK,KAAK;AAAA,MACX,CAAC;AAAA,IACF;AAEA,SAAK,8BAA8B;AAEnC,UAAM,YAAYE,gBAAe;AACjC,SAAK,QAAQ,iBAAiB,SAAS;AAIvC,UAAM,iBAAiB,IAAI,mBAAmB;AAE9C,mBAAe,GAAG,kBAAkB,CAAC,UAAU;AAC9C,WAAK,QAAQ,gBAAgB,WAAW,MAAM,MAAM;AACpD,WAAK,QAAQ,mBAAmB,WAAW,eAAe;AAC1D,WAAK,OAAO,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA,QAAQ,MAAM;AAAA,MACf,CAAC;AAAA,IACF,CAAC;AAED,mBAAe,GAAG,iBAAiB,CAAC,UAAU;AAC7C,YAAM,WAAW,0BAA0B,MAAM,UAAU;AAC3D,WAAK,QAAQ,eAAe,WAAW,MAAM,WAAW,QAAQ;AAChE,WAAK,OAAO,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA,OAAO,MAAM;AAAA,QACb,OAAO;AAAA,MACR,CAAC;AAAA,IACF,CAAC;AAED,mBAAe,GAAG,aAAa,CAAC,UAAU;AACzC,YAAM,WAAW,0BAA0B,MAAM,UAAU;AAC3D,WAAK,QAAQ,WAAW,WAAW,MAAM,WAAW,QAAQ;AAC5D,WAAK,OAAO,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA,OAAO,MAAM;AAAA,QACb,OAAO;AAAA,MACR,CAAC;AAAA,IACF,CAAC;AAED,mBAAe,GAAG,qBAAqB,MAAM;AAC5C,WAAK,OAAO,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,MACD,CAAC;AAAA,IACF,CAAC;AAED,mBAAe,GAAG,wBAAwB,CAAC,UAAU;AACpD,WAAK,OAAO,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA,SAAS;AAAA,UACR,qBAAqB,MAAM;AAAA,UAC3B,qBAAqB,MAAM;AAAA,UAC3B,cAAc,MAAM;AAAA,UACpB,cAAc,MAAM;AAAA,UACpB,QAAQ,MAAM;AAAA,QACf;AAAA,MACD,CAAC;AAAA,IACF,CAAC;AAED,mBAAe,GAAG,yBAAyB,CAAC,UAAU;AACrD,WAAK,OAAO,IAAI;AAAA,QACf,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA,SAAS;AAAA,UACR,WAAW,MAAM;AAAA,UACjB,aAAa,MAAM;AAAA,QACpB;AAAA,MACD,CAAC;AAAA,IACF,CAAC;AAED,UAAM,UAAU,IAAI,cAAc;AAAA,MACjC;AAAA,MACA;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,MAAM,KAAK,QAAQ;AAAA,MACnB,YAAY,KAAK;AAAA,MACjB,SAAS;AAAA,MACT,QAAQ,KAAK;AAAA,MACb,WAAW,KAAK;AAAA,MAChB,eAAe,KAAK;AAAA,MACpB,yBAAyB,KAAK;AAAA,MAC9B,qBAAqB,KAAK;AAAA,MAC1B,SAAS,CAAC,iBAAiBC,gBAAe;AACzC,aAAK,YAAY,iBAAiBA,WAAU;AAAA,MAC7C;AAAA,MACA,mBAAmB,CAAC,iBAAiB,YAAY;AAChD,aAAK,qBAAqB,iBAAiB,OAAO;AAAA,MACnD;AAAA,MACA,gBAAgB,CAAC,iBAAiB,YAAY;AAC7C,aAAK,kBAAkB,iBAAiB,OAAO;AAAA,MAChD;AAAA,MACA,oBAAoB,CAAC,iBAAiB,YAAY;AACjD,aAAK,eAAe,cAAc,iBAAiB,OAAO;AAAA,MAC3D;AAAA,MACA,qBAAqB,CAAC,iBAAiB,YAAY;AAClD,aAAK,eAAe,eAAe,iBAAiB,OAAO;AAAA,MAC5D;AAAA,MACA,GAAI,KAAK,mBAAmB,EAAE,kBAAkB,KAAK,iBAAiB,IAAI,CAAC;AAAA;AAAA;AAAA,MAG3E,GAAI,KAAK,sBAAsB,SAC5B,EAAE,mBAAmB,KAAK,kBAAkB,IAC5C,CAAC;AAAA,MACJ,GAAI,KAAK,oBAAoB,SAAY,EAAE,iBAAiB,KAAK,gBAAgB,IAAI,CAAC;AAAA,MACtF,GAAI,KAAK,oBACN,EAAE,mBAAmB,KAAK,mBAAmB,aAAa,KAAK,YAAY,IAC3E,CAAC;AAAA,MACJ,SAAS,CAAC,QAAQ;AACjB,aAAK,mBAAmB,GAAG;AAAA,MAC5B;AAAA,MACA,kBAAkB,CAAC,QAAQ,QAAQ;AAClC,aAAK,qBAAqB,QAAQ,GAAG;AAAA,MACtC;AAAA,MACA,oBAAoB,CAAC,WAAW,KAAK,mBAAmB,MAAM;AAAA,IAC/D,CAAC;AAED,SAAK,SAAS,IAAI,WAAW,OAAO;AACpC,SAAK,YAAY,UAAU,WAAW,SAAS;AAC/C,SAAK,eAAe,UAAU,WAAW,SAAS;AAClD,YAAQ,MAAM;AAEd,SAAK,OAAO,IAAI;AAAA,MACf,WAAW,KAAK,IAAI;AAAA,MACpB,OAAO;AAAA,MACP,OAAO;AAAA,MACP;AAAA,MACA,SAAS,EAAE,eAAe,KAAK,SAAS,KAAK;AAAA,IAC9C,CAAC;AAED,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAmC;AACxC,UAAM,WAAW,MAAM,KAAK,MAAM,kBAAkB;AACpD,UAAM,WAAW,KAAK,QAAQ,YAAY,QAAQ;AAClD,WAAO;AAAA,MACN,SAAS,KAAK;AAAA,MACd,kBAAkB,SAAS;AAAA,MAC3B,MAAM,KAAK,QAAQ;AAAA,MACnB,iBAAiB,SAAS;AAAA,MAC1B,QAAQ,SAAS;AAAA,MACjB,SAAS,KAAK;AAAA,MACd,eAAe,KAAK;AAAA,MACpB,kBAAkB,SAAS;AAAA,MAC3B,iBAAiB,SAAS;AAAA,MAC1B,kBAAkB,SAAS;AAAA,MAC3B,oBAAoB,SAAS;AAAA,MAC7B,gBAAgB,SAAS;AAAA,MACzB,YAAY,SAAS;AAAA,IACtB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,oBAAoB,IAAoD;AAC7E,UAAM,SAAS,MAAM,qBAAqB,KAAK,OAAO,EAAE;AAExD,QAAI,OAAO,WAAW,aAAa,OAAO,kBAAkB,SAAS,GAAG;AACvE,iBAAW,WAAW,KAAK,SAAS,OAAO,GAAG;AAC7C,gBAAQ,gBAAgB,OAAO,iBAAiB;AAAA,MACjD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,sBAAsBA,aAA+B;AACpD,QAAIA,YAAW,WAAW,GAAG;AAC5B;AAAA,IACD;AACA,eAAW,WAAW,KAAK,SAAS,OAAO,GAAG;AAC7C,cAAQ,gBAAgBA,WAAU;AAAA,IACnC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,kBAAsC;AAC3C,UAAM,SAAS,KAAK,MAAM,UAAU;AACpC,QAAI,CAAC,QAAQ;AACZ,aAAO,CAAC;AAAA,IACT;AACA,UAAM,OAAkB,CAAC;AACzB,eAAW,CAAC,MAAM,UAAU,KAAK,OAAO,QAAQ,OAAO,WAAW,GAAG;AACpE,YAAM,eAAe,OAAO,OAAO,WAAW,MAAM,EAAE,KAAK,CAAC,UAAU,MAAM,SAAS,MAAM;AAC3F,UAAI,CAAC,cAAc;AAClB;AAAA,MACD;AACA,YAAM,UAAU,MAAM,KAAK,MAAM,sBAAsB,IAAI;AAC3D,iBAAW,UAAU,SAAS;AAC7B,mBAAW,SAAS,OAAO,OAAO,MAAM,GAAG;AAC1C,cAAI,UAAU,KAAK,GAAG;AACrB,iBAAK,KAAK,KAAK;AAAA,UAChB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,qBAA6B;AAC5B,WAAO,KAAK,SAAS;AAAA,EACtB;AAAA;AAAA,EAIQ,YAAY,iBAAyBA,aAA+B;AAC3E,UAAM,cAAc,KAAK,SAAS,OAAO;AACzC,UAAM,WAAW,0BAA0BA,WAAU;AACrD,SAAK,QAAQ;AAAA,MACZ;AAAA,MACAA,YAAW,SAAS;AAAA,MACpB,WAAW;AAAA,IACZ;AACA,SAAK,OAAO,IAAI;AAAA,MACf,WAAW,KAAK,IAAI;AAAA,MACpB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,WAAW;AAAA,MACX,OAAOA,YAAW;AAAA,MAClB,OAAO,WAAW;AAAA,MAClB,SAAS,EAAE,gBAAgB,YAAY;AAAA,IACxC,CAAC;AAED,eAAW,CAAC,WAAW,OAAO,KAAK,KAAK,UAAU;AACjD,UAAI,cAAc,gBAAiB;AACnC,cAAQ,gBAAgBA,WAAU;AAAA,IACnC;AAAA,EACD;AAAA,EAEQ,mBAAmB,WAAyB;AACnD,SAAK,QAAQ,oBAAoB,SAAS;AAC1C,SAAK,eAAe,aAAa,SAAS;AAC1C,SAAK,YAAY,aAAa,SAAS;AACvC,SAAK,eAAe,aAAa,SAAS;AAE1C,SAAK,SAAS,OAAO,SAAS;AAE9B,UAAM,WAAW,KAAK,oBAAoB,IAAI,SAAS;AACvD,QAAI,UAAU;AACb,WAAK,oBAAoB,OAAO,SAAS;AACzC,WAAK,YAAY,OAAO,QAAQ;AAAA,IACjC;AAAA,EACD;AAAA,EAEQ,qBAAqB,iBAAyB,SAAuC;AAE5F,UAAM,UAAU,KAAK,SAAS,IAAI,eAAe;AACjD,QAAI,CAAC,QAAS;AAEd,UAAM,YAAY,QAAQ,aAAa;AACvC,QAAI,CAAC,KAAK,eAAe,eAAe,KAAK,CAAC,WAAW;AAAA,IAEzD;AACA,SAAK,eAAe,UAAU,iBAAiB,QAAQ,UAAU,SAAS;AAC1E,SAAK,eAAe,aAAa,iBAAiB,OAAO;AAAA,EAC1D;AAAA,EAEQ,kBAAkB,iBAAyB,SAAoC;AACtF,QAAI,CAAC,KAAK,SAAS,IAAI,eAAe,GAAG;AACxC;AAAA,IACD;AACA,SAAK,YAAY,aAAa,iBAAiB,OAAO;AAAA,EACvD;AAAA,EAEQ,sBAAsB,UAG5B;AACD,UAAM,WAAW,KAAK,YAAY,IAAI,QAAQ;AAC9C,QAAI,UAAU;AACb,aAAO;AAAA,IACR;AAEA,UAAM,YAAY,IAAI,oBAAoB,KAAK,UAAU;AACzD,UAAM,YAAY,KAAK,iBAAiB,SAAS;AACjD,UAAM,SAAS,EAAE,WAAW,UAAU;AAEtC,SAAK,YAAY,IAAI,UAAU,MAAM;AACrC,SAAK,oBAAoB,IAAI,WAAW,QAAQ;AAEhD,WAAO;AAAA,EACR;AACD;AAMA,SAAS,0BAA0BA,aAAiC;AACnE,MAAI,QAAQ;AACZ,aAAW,MAAMA,aAAY;AAC5B,aAAS,KAAK,UAAU,EAAE,EAAE;AAAA,EAC7B;AACA,SAAO;AACR;AAEA,SAAS,kBAAkB,MAA2B,aAA2C;AAChG,MAAI,gBAAgB,YAAY;AAC/B,WAAO;AAAA,EACR;AAEA,MAAI,aAAa,SAAS,wBAAwB,GAAG;AACpD,WAAO,IAAI,YAAY,EAAE,OAAO,IAAI;AAAA,EACrC;AAEA,SAAO;AACR;;;AOx3BO,IAAM,oBAAN,MAAgD;AAAA,EACrC;AAAA,EAEjB,YAAY,SAAmC;AAC9C,SAAK,WAAW,QAAQ;AAAA,EACzB;AAAA,EAEA,MAAM,aAAa,OAA4C;AAC9D,WAAO,KAAK,SAAS,KAAK;AAAA,EAC3B;AACD;;;ACiEO,IAAM,mBAAN,MAA+C;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAIjB,YAAY,SAAkC;AAC7C,SAAK,iBAAiB,QAAQ;AAC9B,SAAK,aAAa,QAAQ;AAC1B,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,gBAAgB,QAAQ;AAAA,EAC9B;AAAA,EAEA,MAAM,aAAa,OAA4C;AAE9D,UAAM,UAAU,KAAK,eAAe,8BACjC,MAAM,KAAK,eAAe,4BAA4B,KAAK,IAC3D,KAAK,eAAe,cAAc,KAAK;AAC1C,QAAI,YAAY,MAAM;AACrB,aAAO;AAAA,IACR;AAGA,QAAI,QAAQ,SAAS,UAAU;AAC9B,aAAO;AAAA,IACR;AAGA,UAAM,OAAO,MAAM,KAAK,WAAW,SAAS,QAAQ,GAAG;AACvD,QAAI,SAAS,MAAM;AAClB,aAAO;AAAA,IACR;AAGA,QAAI,KAAK,eAAe;AACvB,YAAM,KAAK,cAAc,YAAY,QAAQ,GAAG;AAAA,IACjD;AAGA,UAAM,SAAS,KAAK,gBAAgB,MAAM,KAAK,cAAc,QAAQ,GAAG,IAAI;AAE5E,WAAO;AAAA,MACN,QAAQ,QAAQ;AAAA,MAChB;AAAA,MACA,UAAU;AAAA,QACT,UAAU,QAAQ;AAAA,QAClB,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,MACZ;AAAA,IACD;AAAA,EACD;AACD;;;AC5EO,IAAM,oBAAN,MAAgD;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACT,mBAAmB;AAAA,EAE3B,YAAY,SAAmC;AAC9C,SAAK,UAAU,QAAQ;AACvB,SAAK,kBAAkB,QAAQ;AAC/B,SAAK,kBAAkB,QAAQ,mBAAmB;AAAA,EACnD;AAAA,EAEA,MAAM,aAAa,OAAqC;AAEvD,QAAI,OAAO;AACV,YAAM,MAAM,MAAM,KAAK,QAAQ,aAAa,KAAK;AACjD,UAAI,IAAK,QAAO;AAAA,IACjB;AAGA,SAAK;AACL,WAAO;AAAA,MACN,QAAQ,GAAG,KAAK,eAAe,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,gBAAgB;AAAA,MACtE,QAAQ,KAAK;AAAA,IACd;AAAA,EACD;AACD;;;ACtFO,SAAS,iBAAiB,QAA8C;AAC9E,SAAO,IAAI,eAAe,MAAM;AACjC;;;ACkGA,IAAM,aAAqC;AAAA,EAC1C,SAAS;AAAA,EACT,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AACT;AAiBO,SAAS,uBAAuB,QAAkD;AACxF,QAAM,OAAO,OAAO,SAAS,OAAO,QAAQ,IAAI,IAAI,KAAK;AACzD,QAAM,YAAY,OAAO,aAAa;AACtC,QAAM,WAAW,OAAO,YAAY;AACpC,QAAM,4BAA4B,OAAO,6BAA6B;AAEtE,QAAM,aAAa,IAAI,eAAe;AAAA,IACrC,OAAO,OAAO;AAAA,IACd,iBAAiB;AAAA,IACjB,GAAG,OAAO;AAAA,EACX,CAAC;AAKD,QAAM,eAAe,WAAW,eAAe;AAE/C,MAAI,aAAgD;AAEpD,WAAS,oBAAoB,MAA0D;AACtF,UAAM,OAAO,OAAO;AACpB,QAAI,CAAC,KAAM,QAAO;AAClB,QAAI,SAAS,UAAW,QAAO,KAAK,gBAAgB,KAAK;AACzD,QAAI,SAAS,SAAU,QAAO,KAAK,eAAe,KAAK;AACvD,WAAO,KAAK;AAAA,EACb;AAEA,WAAS,oBAAoB,KAAyD;AACrF,UAAM,gBAAgB,IAAI,QAAQ;AAClC,QAAI,eAAe,WAAW,SAAS,GAAG;AACzC,aAAO,cAAc,MAAM,UAAU,MAAM,EAAE,KAAK;AAAA,IACnD;AAEA,UAAM,cAAc,CAAC,sBAAsB,wBAAwB,qBAAqB;AACxF,eAAW,QAAQ,aAAa;AAC/B,YAAM,QAAQ,IAAI,QAAQ,IAAI;AAC9B,UAAI,OAAO,UAAU,YAAY,MAAM,SAAS,EAAG,QAAO;AAC1D,UAAI,MAAM,QAAQ,KAAK,KAAK,OAAO,MAAM,CAAC,MAAM,YAAY,MAAM,CAAC,EAAE,SAAS,GAAG;AAChF,eAAO,MAAM,CAAC;AAAA,MACf;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAEA,WAAS,4BACR,KACA,MACU;AACV,UAAM,WAAW,oBAAoB,IAAI;AACzC,QAAI,CAAC,SAAU,QAAO;AACtB,WAAO,oBAAoB,GAAG,MAAM;AAAA,EACrC;AAEA,WAAS,mBAAmB,KAA+C;AAC1E,QAAI,UAAU,KAAK;AAAA,MAClB,gBAAgB;AAAA,MAChB,oBAAoB;AAAA,IACrB,CAAC;AACD,QAAI,IAAI,KAAK,UAAU,EAAE,OAAO,eAAe,CAAC,CAAC;AAAA,EAClD;AAMA,WAAS,0BAAkC;AAC1C,UAAM,SAAS,WAAW,oBAAoB,EAAE,YAAY,CAAC;AAC7D,UAAM,QAAkB;AAAA,MACvB;AAAA,MACA;AAAA,MACA,0BAA0B,OAAO,gBAAgB;AAAA,MACjD;AAAA,MACA;AAAA,MACA;AAAA,MACA,yBAAyB,OAAO,eAAe;AAAA,MAC/C;AAAA,MACA;AAAA,MACA;AAAA,MACA,0BAA0B,OAAO,gBAAgB;AAAA,MACjD;AAAA,MACA;AAAA,MACA;AAAA,MACA,kCAAkC,OAAO,kBAAkB;AAAA,MAC3D;AAAA,MACA;AAAA,MACA;AAAA,MACA,8BAA8B,OAAO,cAAc;AAAA,MACnD;AAAA,MACA;AAAA,MACA;AAAA,MACA,6BAA6B,OAAO,aAAa;AAAA,MACjD;AAAA,MACA;AAAA,MACA;AAAA,MACA,yBAAyB,OAAO,SAAS;AAAA,MACzC;AAAA,MACA;AAAA,MACA;AAAA,MACA,qBAAqB,OAAO,UAAU;AAAA,MACtC;AAAA,MACA;AAAA,MACA;AAAA,MACA,uBAAuB,KAAK,MAAM,OAAO,SAAS,GAAI,CAAC;AAAA,MACvD;AAAA,MACA;AAAA,MACA;AAAA,MACA,uBAAuB,OAAO,aAAa;AAAA,MAC3C;AAAA,IACD;AACA,WAAO,MAAM,KAAK,IAAI;AAAA,EACvB;AAEA,WAAS,eAAe,KAA2D;AAClF,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC/B,YAAM,SAAmB,CAAC;AAC1B,UAAI,GAAG,QAAQ,CAAC,UAAkB,OAAO,KAAK,KAAK,CAAC;AACpD,UAAI,GAAG,OAAO,MAAM,QAAQ,OAAO,OAAO,MAAM,CAAC,CAAC;AASlD,UAAI,CAAC,IAAI,iBAAiB;AACzB,YAAI,OAAO;AAAA,MACZ;AAGA,UAAI,GAAG,SAAS,MAAM,QAAQ,OAAO,OAAO,MAAM,CAAC,CAAC;AAAA,IACrD,CAAC;AAAA,EACF;AAEA,iBAAe,aAAa,KAA4D;AACvF,UAAM,SAAS,MAAM,eAAe,GAAG;AACvC,QAAI,OAAO,eAAe,EAAG,QAAO;AACpC,QAAI;AACH,aAAO,KAAK,MAAM,OAAO,SAAS,MAAM,CAAC;AAAA,IAC1C,QAAQ;AACP,aAAO;AAAA,IACR;AAAA,EACD;AAEA,WAAS,mBAAmB,UAAkB,QAAyB;AACtE,UAAM,mBAAmB,mBAAmB,MAAM;AAClD,WAAO,aAAa,oBAAoB,SAAS,WAAW,GAAG,gBAAgB,GAAG;AAAA,EACnF;AAEA,WAAS,mBAAmB,MAAsB;AACjD,UAAM,WAAW,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AACvD,WAAO,SAAS,SAAS,IAAI,SAAS,QAAQ,QAAQ,EAAE,IAAI;AAAA,EAC7D;AAEA,WAAS,YAAY,KAA8D;AAClF,UAAM,YAAY,IAAI,QAAQ,iBAAiB;AAC/C,QAAI,OAAO,cAAc,YAAY,UAAU,SAAS,GAAG;AAC1D,aAAO,UAAU,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK;AAAA,IACtC;AACA,WAAO,IAAI,OAAO;AAAA,EACnB;AAEA,WAAS,SAAS,KAAyD;AAC1E,UAAM,QAAuD,CAAC;AAC9D,eAAW,CAAC,KAAK,KAAK,KAAK,IAAI,cAAc;AAC5C,YAAM,WAAW,MAAM,GAAG;AAC1B,UAAI,aAAa,QAAW;AAC3B,cAAM,GAAG,IAAI;AAAA,MACd,WAAW,MAAM,QAAQ,QAAQ,GAAG;AACnC,iBAAS,KAAK,KAAK;AAAA,MACpB,OAAO;AACN,cAAM,GAAG,IAAI,CAAC,UAAU,KAAK;AAAA,MAC9B;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAEA,WAAS,kBACR,KACA,QACO;AACP,UAAM,UAAU;AAAA,MACf,gBAAgB;AAAA,MAChB,GAAI,OAAO,WAAW,CAAC;AAAA,IACxB;AACA,QAAI,UAAU,OAAO,QAAQ,OAAO;AACpC,QAAI,IAAI,KAAK,UAAU,OAAO,QAAQ,IAAI,CAAC;AAAA,EAC5C;AAEA,SAAO;AAAA,IACN,MAAM;AAAA,IAEN,kBAAsC;AACrC,aAAO,WAAW,gBAAgB;AAAA,IACnC;AAAA,IAEA,MAAM,QAAyB;AAC9B,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,MAAW;AACjD,YAAM,EAAE,kBAAkB,YAAY,SAAS,IAAI,MAAM,OAAO,IAAS;AACzE,YAAM,EAAE,SAAS,MAAM,QAAQ,IAAI,MAAM,OAAO,MAAW;AAC3D,YAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,IAAI;AAE7C,YAAM,UAAU,QAAQ,SAAS;AAEjC,mBAAa,aAAa,OAAO,KAAK,QAAQ;AAC7C,YAAI;AACH,gBAAM,cAAc,KAAK,GAAG;AAAA,QAC7B,SAAS,OAAO;AAQf,kBAAQ,MAAM,mDAAmD,KAAK;AACtE,cAAI,CAAC,IAAI,aAAa;AACrB,gBAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,gBAAI,IAAI,KAAK,UAAU,EAAE,OAAO,wBAAwB,CAAC,CAAC;AAAA,UAC3D,WAAW,CAAC,IAAI,eAAe;AAC9B,gBAAI,IAAI;AAAA,UACT;AAAA,QACD;AAAA,MACD,CAAC;AAED,qBAAe,cACd,KACA,KACgB;AAEhB,YAAI,UAAU,8BAA8B,aAAa;AACzD,YAAI,UAAU,gCAAgC,yBAAyB;AAEvE,cAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,UAAU,IAAI,QAAQ,IAAI,EAAE;AAGhE,YAAI,IAAI,aAAa,WAAW;AAC/B,gBAAM,SAAS,MAAM,WAAW,UAAU;AAC1C,cAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,cAAI;AAAA,YACH,KAAK,UAAU;AAAA,cACd,QAAQ;AAAA,cACR,SAAS,OAAO;AAAA,cAChB,QAAQ,OAAO;AAAA,cACf,kBAAkB,OAAO;AAAA,cACzB,iBAAiB,OAAO;AAAA,cACxB,WAAW,KAAK,IAAI;AAAA,YACrB,CAAC;AAAA,UACF;AACA;AAAA,QACD;AAGA,YAAI,IAAI,aAAa,kBAAkB;AACtC,cAAI,CAAC,4BAA4B,KAAK,OAAO,GAAG;AAC/C,+BAAmB,GAAG;AACtB;AAAA,UACD;AACA,gBAAM,SAAS,MAAM,WAAW,UAAU;AAC1C,cAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,cAAI,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AACvC;AAAA,QACD;AAGA,YAAI,IAAI,aAAa,mBAAmB;AACvC,cAAI,CAAC,4BAA4B,KAAK,SAAS,GAAG;AACjD,+BAAmB,GAAG;AACtB;AAAA,UACD;AACA,cAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,cAAI,IAAI,wBAAwB,CAAC;AACjC;AAAA,QACD;AAGA,YAAI,IAAI,aAAa,kBAAkB;AACtC,cAAI,CAAC,4BAA4B,KAAK,OAAO,GAAG;AAC/C,+BAAmB,GAAG;AACtB;AAAA,UACD;AACA,cAAI,UAAU,KAAK;AAAA,YAClB,gBAAgB;AAAA,YAChB,iBAAiB;AAAA,YACjB,YAAY;AAAA,YACZ,qBAAqB;AAAA,UACtB,CAAC;AAGD,gBAAM,SAAS,MAAM,WAAW,UAAU;AAC1C,cAAI,MAAM;AAAA,QAAwB,KAAK,UAAU,MAAM,CAAC;AAAA;AAAA,CAAM;AAG9D,gBAAM,WAAW,YAAY,YAAY;AACxC,gBAAI;AACH,oBAAM,IAAI,MAAM,WAAW,UAAU;AACrC,kBAAI,MAAM;AAAA,QAAwB,KAAK,UAAU,CAAC,CAAC;AAAA;AAAA,CAAM;AAAA,YAC1D,QAAQ;AAAA,YAER;AAAA,UACD,GAAG,GAAI;AAGP,cAAI,GAAG,SAAS,MAAM;AACrB,0BAAc,QAAQ;AAAA,UACvB,CAAC;AAED;AAAA,QACD;AAGA,YAAI,IAAI,aAAa,aAAa,IAAI,aAAa,YAAY;AAC9D,cAAI,CAAC,4BAA4B,KAAK,OAAO,GAAG;AAC/C,+BAAmB,GAAG;AACtB;AAAA,UACD;AACA,gBAAM,SAAS,MAAM,WAAW,UAAU;AAC1C,cAAI,UAAU,KAAK,EAAE,gBAAgB,2BAA2B,CAAC;AACjE,cAAI,IAAI,oBAAoB,MAAM,CAAC;AACnC;AAAA,QACD;AAGA,YAAI,IAAI,aAAa,2BAA2B,IAAI,WAAW,QAAQ;AACtE,cAAI,CAAC,4BAA4B,KAAK,QAAQ,GAAG;AAChD,+BAAmB,GAAG;AACtB;AAAA,UACD;AACA,cAAI;AACH,kBAAM,SAAS,MAAM,OAAO,MAAM,aAAa;AAC/C,gBAAI,UAAU,KAAK;AAAA,cAClB,gBAAgB;AAAA,cAChB,uBAAuB,qCAAqC,KAAK,IAAI,CAAC;AAAA,cACtE,kBAAkB,OAAO,OAAO,UAAU;AAAA,YAC3C,CAAC;AACD,gBAAI,IAAI,OAAO,KAAK,MAAM,CAAC;AAAA,UAC5B,SAAS,OAAO;AACf,gBAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,gBAAI,IAAI,KAAK,UAAU,EAAE,OAAO,iBAAiB,SAAU,MAAgB,QAAQ,CAAC,CAAC;AAAA,UACtF;AACA;AAAA,QACD;AAGA,YAAI,IAAI,aAAa,2BAA2B,IAAI,WAAW,QAAQ;AACtE,cAAI,CAAC,4BAA4B,KAAK,QAAQ,GAAG;AAChD,+BAAmB,GAAG;AACtB;AAAA,UACD;AACA,cAAI;AACH,kBAAM,OAAO,MAAM,eAAe,GAAG;AACrC,kBAAM,QAAQ,IAAI,aAAa,IAAI,OAAO,MAAM;AAChD,kBAAM,SAAS,MAAM,OAAO,MAAM;AAAA,cACjC,IAAI,WAAW,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AAAA,cAC5D;AAAA,YACD;AACA,gBAAI,UAAU,OAAO,UAAU,MAAM,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AAChF,gBAAI,IAAI,KAAK,UAAU,MAAM,CAAC;AAAA,UAC/B,SAAS,OAAO;AACf,gBAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,gBAAI,IAAI,KAAK,UAAU,EAAE,OAAO,kBAAkB,SAAU,MAAgB,QAAQ,CAAC,CAAC;AAAA,UACvF;AACA;AAAA,QACD;AAGA,cAAM,cAAc,OAAO,YAAY;AAAA,UAAK,CAAC,UAC5C,mBAAmB,IAAI,UAAU,MAAM,IAAI;AAAA,QAC5C;AACA,YAAI,aAAa;AAChB,gBAAM,SAAS,MAAM,YAAY,OAAO;AAAA,YACvC,QAAQ,IAAI,UAAU;AAAA,YACtB,MAAM,IAAI;AAAA,YACV,MAAM,MAAM,aAAa,GAAG;AAAA,YAC5B,SAAS,IAAI;AAAA,YACb,OAAO,SAAS,GAAG;AAAA,YACnB,IAAI,YAAY,GAAG;AAAA,YACnB,MAAM;AAAA,UACP,CAAC;AACD,4BAAkB,KAAK,MAAM;AAC7B;AAAA,QACD;AAGA,YAAI,WAAW,KAAK,SAAS,IAAI,QAAQ;AAGzC,YAAI,CAAC,QAAQ,QAAQ,GAAG;AACvB,gBAAM,YAAY,KAAK,UAAU,YAAY;AAC7C,cAAI,WAAW,SAAS,GAAG;AAC1B,uBAAW;AAAA,UACZ,OAAO;AACN,uBAAW,KAAK,SAAS,YAAY;AAAA,UACtC;AAAA,QACD;AAEA,YAAI,CAAC,WAAW,QAAQ,GAAG;AAC1B,qBAAW,KAAK,SAAS,YAAY;AAAA,QACtC;AAEA,YAAI;AACH,gBAAM,OAAO,SAAS,QAAQ;AAC9B,cAAI,KAAK,YAAY,GAAG;AACvB,uBAAW,KAAK,UAAU,YAAY;AAAA,UACvC;AAAA,QACD,QAAQ;AACP,qBAAW,KAAK,SAAS,YAAY;AAAA,QACtC;AAEA,YAAI,CAAC,WAAW,QAAQ,GAAG;AAC1B,cAAI,UAAU,GAAG;AACjB,cAAI,IAAI,WAAW;AACnB;AAAA,QACD;AAEA,cAAM,MAAM,QAAQ,QAAQ;AAC5B,cAAM,cAAc,WAAW,GAAG,KAAK;AACvC,YAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAClD,yBAAiB,QAAQ,EAAE,KAAK,GAAG;AAAA,MACpC;AAEA,YAAM,MAAM,IAAI,gBAAgB,EAAE,UAAU,KAAK,CAAC;AAElD,iBAAW,GAAG,WAAW,CAAC,KAAK,QAAQ,SAAS;AAC/C,cAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,UAAU,IAAI,QAAQ,IAAI,EAAE;AAChE,YAAI,IAAI,aAAa,UAAU;AAC9B,cAAI,cAAc,KAAK,QAAQ,MAAM,CAAC,OAAO;AAC5C,kBAAM,YAAY,IAAI,kBAAkB,EAAE;AAC1C,uBAAW,iBAAiB,SAAS;AAAA,UACtC,CAAC;AAAA,QACF,OAAO;AACN,iBAAO,QAAQ;AAAA,QAChB;AAAA,MACD,CAAC;AAED,aAAO,IAAI,QAAgB,CAACC,UAAS,WAAW;AAC/C,cAAM,UAAU,CAAC,UAAiB;AACjC,iBAAO,KAAK;AAAA,QACb;AACA,oBAAY,KAAK,SAAS,OAAO;AACjC,oBAAY,OAAO,MAAM,WAAW,MAAM;AACzC,sBAAY,IAAI,SAAS,OAAO;AAChC,UAAAA,SAAQ,oBAAoB,IAAI,EAAE;AAAA,QACnC,CAAC;AAAA,MACF,CAAC;AAAA,IACF;AAAA,IAEA,MAAM,OAAsB;AAC3B,YAAM,WAAW,KAAK;AACtB,UAAI,YAAY;AACf,cAAM,IAAI,QAAc,CAAC,YAAY;AACpC,sBAAY,MAAM,MAAM,QAAQ,CAAC;AAAA,QAClC,CAAC;AACD,qBAAa;AAAA,MACd;AAAA,IACD;AAAA,EACD;AACD;AAMA,SAAS,oBAAoB,QAWlB;AACV,QAAM,UAAU,OAAO;AACvB,QAAM,SAAS,aAAa,OAAO,MAAM;AACzC,SAAO;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,uBA6Be,OAAO;AAAA;AAAA,wEAE0C,MAAM;AAAA,yGAC2B,OAAO,gBAAgB;AAAA,uGACzB,OAAO,eAAe;AAAA,6GAChB,OAAO,eAAe;AAAA,+FACpC,OAAO,kBAAkB;AAAA,uFACjC,OAAO,cAAc;AAAA,uEACrC,OAAO,aAAa,IAAI,QAAQ,OAAO,iBAAiB,OAAO,UAAU;AAAA,gFAChE,OAAO,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBpG;AAEA,SAAS,aAAa,IAAoB;AACzC,QAAM,UAAU,KAAK,MAAM,KAAK,GAAI;AACpC,QAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,QAAM,QAAkB,CAAC;AACzB,MAAI,QAAQ,EAAG,OAAM,KAAK,GAAG,KAAK,GAAG;AACrC,MAAI,UAAU,KAAK,EAAG,OAAM,KAAK,GAAG,UAAU,EAAE,GAAG;AACnD,QAAM,KAAK,GAAG,UAAU,EAAE,GAAG;AAC7B,SAAO,MAAM,KAAK,GAAG;AACtB;","names":["count","index","count","operations","generateUUIDv7","quoteIdent","generateUUIDv7","quoteIdent","operations","generateUUIDv7","quoteIdent","and","asc","between","count","eq","gt","sql","index","integer","text","generateUUIDv7","sql","and","eq","between","asc","count","gt","quoteIdent","SyncError","generateUUIDv7","HybridLogicalClock","count","operations","generateUUIDv7","response","SyncError","generateUUIDv7","JsonMessageSerializer","generateUUIDv7","operations","count","HybridLogicalClock","createOperation","generateUUIDv7","HybridLogicalClock","createOperation","generateUUIDv7","records","operations","DEFAULT_BATCH_SIZE","DEFAULT_SCHEMA_VERSION","SyncError","JsonMessageSerializer","generateUUIDv7","operations","resolve"]}
1
+ {"version":3,"sources":["../src/logging/structured-logger.ts","../src/apply/rejection-taxonomy.ts","../src/store/memory-server-store.ts","../src/store/materialization.ts","../src/store/postgres-server-store.ts","../src/store/drizzle-pg-schema.ts","../src/store/sqlite-server-store.ts","../src/store/drizzle-schema.ts","../src/transport/http-server-transport.ts","../src/transport/ws-server-transport.ts","../src/session/client-session.ts","../src/apply/apply-server-operation.ts","../src/constraints/operation-constraint-validator.ts","../src/constraints/server-constraint-context.ts","../src/constraints/server-referential-context.ts","../src/apply/server-side-effect-operation.ts","../src/auth/no-auth.ts","../src/scopes/resolve-session-scopes.ts","../src/scopes/server-scope-filter.ts","../src/session/operation-validation.ts","../src/session/session-operation-limits.ts","../src/server/kora-sync-server.ts","../src/awareness/awareness-relay.ts","../src/diagnostics/server-metrics-collector.ts","../src/richtext/blob-chunk-relay.ts","../src/richtext/yjs-doc-relay.ts","../src/server/route-context.ts","../src/apply/route-predicate.ts","../src/auth/token-auth.ts","../src/auth/kora-auth-provider.ts","../src/auth/mixed-auth-provider.ts","../src/server/create-server.ts","../src/server/production-server.ts"],"sourcesContent":["/**\n * Log severity levels.\n */\nexport type LogLevel = 'info' | 'warn' | 'error'\n\n/**\n * A structured log entry with timestamp and metadata.\n */\nexport interface LogEntry {\n\ttimestamp: number\n\tlevel: LogLevel\n\tevent: string\n\tsessionId?: string\n\tnodeId?: string\n\tduration?: number\n\tcount?: number\n\tbytes?: number\n\terror?: string\n\tdetails?: Record<string, unknown>\n}\n\n/**\n * Logger interface for structured logging.\n * Implementations control output format and destination.\n */\nexport interface Logger {\n\tlog(entry: LogEntry): void\n\tchild?(context: Partial<LogEntry>): Logger\n}\n\n/**\n * Serializes LogEntry to a single log line.\n */\nexport type LogSerializer = (entry: LogEntry) => string\n\nfunction defaultJsonSerializer(entry: LogEntry): string {\n\treturn JSON.stringify(entry)\n}\n\nfunction defaultPrettySerializer(entry: LogEntry): string {\n\tconst time = new Date(entry.timestamp).toISOString().slice(11, 23)\n\tconst levelTag = { info: ' INFO', warn: ' WARN', error: 'ERROR' }[entry.level]\n\tconst node = entry.nodeId ? ` [${entry.nodeId.slice(0, 8)}]` : ''\n\tconst session = entry.sessionId ? ` [session:${entry.sessionId.slice(0, 8)}]` : ''\n\tconst dur = entry.duration !== undefined ? ` +${entry.duration}ms` : ''\n\tconst count = entry.count !== undefined ? ` (${entry.count})` : ''\n\tconst err = entry.error ? ` — ${entry.error}` : ''\n\treturn `${time} ${levelTag}${node}${session} ${entry.event}${count}${dur}${err}`\n}\n\n/**\n * Creates a JSON-lines logger that writes to stdout/stderr.\n * Suitable for production use where log aggregators (Datadog, Loki, etc.) consume JSON.\n */\nexport function createJsonLogger(writer?: {\n\tinfo: (s: string) => void\n\terror: (s: string) => void\n}): Logger {\n\tconst out = writer ?? {\n\t\tinfo: (s: string) => process.stdout.write(`${s}\\n`),\n\t\terror: (s: string) => process.stderr.write(`${s}\\n`),\n\t}\n\n\treturn {\n\t\tlog(entry: LogEntry): void {\n\t\t\tconst line = defaultJsonSerializer(entry)\n\t\t\tif (entry.level === 'error') {\n\t\t\t\tout.error(line)\n\t\t\t} else {\n\t\t\t\tout.info(line)\n\t\t\t}\n\t\t},\n\t}\n}\n\n/**\n * Creates a pretty-printed logger for development use.\n * Writes human-readable colored output to the terminal.\n */\nexport function createPrettyLogger(writer?: { write: (s: string) => void }): Logger {\n\tconst out = writer ?? { write: (s: string) => process.stdout.write(`${s}\\n`) }\n\n\treturn {\n\t\tlog(entry: LogEntry): void {\n\t\t\tout.write(defaultPrettySerializer(entry))\n\t\t},\n\t}\n}\n\n/**\n * A logger that discards all entries (for testing or when logging is disabled).\n */\nexport function createSilentLogger(): Logger {\n\treturn { log() {} }\n}\n\n/**\n * Creates a logger based on the NODE_ENV environment variable.\n * - production: JSON lines to stdout/stderr\n * - test: silent\n * - otherwise: pretty-printed to stdout\n */\nexport function createDefaultLogger(): Logger {\n\tswitch (process.env.NODE_ENV) {\n\t\tcase 'production':\n\t\t\treturn createJsonLogger()\n\t\tcase 'test':\n\t\t\treturn createSilentLogger()\n\t\tdefault:\n\t\t\treturn createPrettyLogger()\n\t}\n}\n","/**\n * Shared vocabulary for why the server refused an operation.\n *\n * The `retriable` flag answers one question for the caller: is it worth\n * submitting this SAME operation again later?\n *\n * - `true` — the rejection is transient (for example a rate limit). The\n * identical operation may succeed once the condition clears, so a\n * client is right to back off and retry the same bytes.\n * - `false` — the rejection is permanent for the operation as written (a\n * constraint violation, a referential conflict, a malformed\n * mutation, a scope violation). Resubmitting the same bytes will\n * always fail; the caller must change the operation or give up.\n *\n * This is deliberately defined once, in one place, so the trusted server\n * data-plane (route context / `server.kora`) and the untrusted client-ingestion\n * path speak the same language. `retriable` (this spelling) matches the wire\n * `ErrorMessage.retriable` field the sync protocol already ships, so a single\n * flag flows from the pipeline out to connected clients unchanged.\n */\nexport interface OperationRejection {\n\t/** Stable, machine-readable reason code (for example `CONSTRAINT_VIOLATION`). */\n\tcode: string\n\t/** Human-readable explanation with enough context to debug without reproduction. */\n\tmessage: string\n\t/** Whether resubmitting the identical operation may later succeed. */\n\tretriable: boolean\n}\n\n/**\n * Reason codes whose underlying condition is transient, so the identical\n * operation may succeed on a later attempt.\n *\n * Everything NOT listed here is treated as permanent. Permanent is the safe\n * default: a client should never be told to keep hammering a genuinely invalid\n * operation, so a new code is non-retriable until it is deliberately added here.\n *\n * `RATE_LIMIT` is the code the session emits when a client exceeds its\n * per-minute operation budget (see `client-session.ts`).\n */\nexport const RETRIABLE_REJECTION_CODES: ReadonlySet<string> = new Set(['RATE_LIMIT'])\n\n/**\n * Classify a reason code as retriable (transient) or not (permanent).\n *\n * @param code - A rejection reason code.\n * @returns `true` when resubmitting the identical operation may later succeed.\n */\nexport function isRetriableRejection(code: string): boolean {\n\treturn RETRIABLE_REJECTION_CODES.has(code)\n}\n","import type { Operation, SchemaDefinition, VersionVector } from '@korajs/core'\nimport { generateUUIDv7 } from '@korajs/core'\nimport type { ApplyResult } from '@korajs/sync'\nimport {\n\tdeserializeFieldValue,\n\treplayOperationsForRecord,\n\tserializeFieldValue,\n\tvalidateFieldName,\n} from './materialization'\nimport type {\n\tCollectionQueryOptions,\n\tDeliveredOperation,\n\tMaterializedRecord,\n\tServerStore,\n} from './server-store'\n\n/**\n * In-memory server store for testing and quick prototyping.\n * Not suitable for production — data does not survive process restart.\n *\n * When a schema is set via setSchema(), maintains materialized records\n * in-memory for efficient queries.\n */\nexport class MemoryServerStore implements ServerStore {\n\tprivate readonly nodeId: string\n\tprivate readonly operations: Operation[] = []\n\tprivate readonly operationIndex = new Map<string, Operation>()\n\tprivate readonly versionVector: Map<string, number> = new Map()\n\t/**\n\t * Server-assigned delivery sequence per operation id. Single-process, so a plain\n\t * counter incremented at insert time gives commit-order delivery sequence with no\n\t * gaps. `operations` is kept in insertion (== delivery) order, so a delivery scan\n\t * is a forward walk.\n\t */\n\tprivate readonly deliverySeqByOpId = new Map<string, number>()\n\tprivate deliverySeqCounter = 0\n\tprivate schema: SchemaDefinition | null = null\n\n\t/** Materialized records: collection -> recordId -> record data */\n\tprivate readonly materializedRecords = new Map<string, Map<string, MaterializedRecord>>()\n\n\tprivate closed = false\n\n\tconstructor(nodeId?: string) {\n\t\tthis.nodeId = nodeId ?? generateUUIDv7()\n\t}\n\n\tgetVersionVector(): VersionVector {\n\t\treturn new Map(this.versionVector)\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.nodeId\n\t}\n\n\tgetSchema(): SchemaDefinition | null {\n\t\treturn this.schema\n\t}\n\n\tasync setSchema(schema: SchemaDefinition): Promise<void> {\n\t\tthis.assertOpen()\n\t\tthis.schema = schema\n\n\t\t// Initialize collection maps\n\t\tfor (const collectionName of Object.keys(schema.collections)) {\n\t\t\tif (!this.materializedRecords.has(collectionName)) {\n\t\t\t\tthis.materializedRecords.set(collectionName, new Map())\n\t\t\t}\n\t\t}\n\n\t\t// Backfill from existing operations\n\t\tthis.backfillAllCollections()\n\t}\n\n\tasync applyRemoteOperation(op: Operation): Promise<ApplyResult> {\n\t\tthis.assertOpen()\n\n\t\t// Content-addressed dedup: same id = same content\n\t\tif (this.operationIndex.has(op.id)) {\n\t\t\treturn 'duplicate'\n\t\t}\n\n\t\tthis.operations.push(op)\n\t\tthis.operationIndex.set(op.id, op)\n\n\t\t// Assign the next delivery sequence in commit order (single-process: no race).\n\t\tthis.deliverySeqCounter += 1\n\t\tthis.deliverySeqByOpId.set(op.id, this.deliverySeqCounter)\n\n\t\t// Advance version vector\n\t\tconst currentSeq = this.versionVector.get(op.nodeId) ?? 0\n\t\tif (op.sequenceNumber > currentSeq) {\n\t\t\tthis.versionVector.set(op.nodeId, op.sequenceNumber)\n\t\t}\n\n\t\t// Dual-write: update materialized records if schema is set\n\t\tif (this.schema?.collections[op.collection]) {\n\t\t\tthis.rebuildMaterializedRecord(op.collection, op.recordId)\n\t\t}\n\n\t\treturn 'applied'\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\n\t\treturn this.operations\n\t\t\t.filter(\n\t\t\t\t(op) => op.nodeId === nodeId && op.sequenceNumber >= fromSeq && op.sequenceNumber <= toSeq,\n\t\t\t)\n\t\t\t.sort((a, b) => a.sequenceNumber - b.sequenceNumber)\n\t}\n\n\tasync getOperationCount(): Promise<number> {\n\t\tthis.assertOpen()\n\t\treturn this.operations.length\n\t}\n\n\tasync getMaxDeliverySequence(): Promise<number> {\n\t\tthis.assertOpen()\n\t\treturn this.deliverySeqCounter\n\t}\n\n\tasync getOperationsAfterDelivery(\n\t\tafterDeliverySequence: number,\n\t\tlimit: number,\n\t): Promise<DeliveredOperation[]> {\n\t\tthis.assertOpen()\n\t\tconst result: DeliveredOperation[] = []\n\t\tif (limit <= 0) return result\n\t\t// operations is in delivery order, so once entries exceed the cursor they all do;\n\t\t// the guard on each entry keeps this correct even if that invariant ever weakens.\n\t\tfor (const op of this.operations) {\n\t\t\tconst deliverySequence = this.deliverySeqByOpId.get(op.id) ?? 0\n\t\t\tif (deliverySequence > afterDeliverySequence) {\n\t\t\t\tresult.push({ operation: op, deliverySequence })\n\t\t\t\tif (result.length >= limit) break\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\tasync materializeCollection(collection: string): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\n\t\t// Fast path: if schema is set, read from materialized records\n\t\tif (this.schema?.collections[collection]) {\n\t\t\treturn this.queryCollection(collection)\n\t\t}\n\n\t\t// Fallback: replay operations\n\t\treturn this.materializeFromOps(collection)\n\t}\n\n\tasync queryCollection(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions,\n\t): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\t// Validate field names\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (options?.where) {\n\t\t\tfor (const key of Object.keys(options.where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\t\tif (options?.orderBy) {\n\t\t\tvalidateFieldName(collection, options.orderBy, schema)\n\t\t}\n\n\t\tconst collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) return []\n\n\t\t// Get all non-deleted records\n\t\tlet records = Array.from(collectionMap.values()).filter((r) => {\n\t\t\tif (!options?.includeDeleted && r._deleted === 1) return false\n\t\t\treturn true\n\t\t})\n\n\t\t// Apply WHERE filters\n\t\tif (options?.where) {\n\t\t\tfor (const [key, value] of Object.entries(options.where)) {\n\t\t\t\trecords = records.filter((r) => r[key] === value)\n\t\t\t}\n\t\t}\n\n\t\t// Apply ORDER BY\n\t\tif (options?.orderBy) {\n\t\t\tconst field = options.orderBy\n\t\t\tconst dir = options.orderDirection === 'desc' ? -1 : 1\n\t\t\trecords.sort((a, b) => {\n\t\t\t\tconst aVal = a[field]\n\t\t\t\tconst bVal = b[field]\n\t\t\t\tif (aVal === bVal) return 0\n\t\t\t\tif (aVal === null || aVal === undefined) return 1\n\t\t\t\tif (bVal === null || bVal === undefined) return -1\n\t\t\t\treturn aVal < bVal ? -1 * dir : 1 * dir\n\t\t\t})\n\t\t}\n\n\t\t// Apply OFFSET\n\t\tif (options?.offset !== undefined) {\n\t\t\trecords = records.slice(options.offset)\n\t\t}\n\n\t\t// Apply LIMIT\n\t\tif (options?.limit !== undefined) {\n\t\t\trecords = records.slice(0, options.limit)\n\t\t}\n\n\t\t// Return clean copies without internal fields\n\t\treturn records.map((r) => {\n\t\t\tconst clean: MaterializedRecord = { id: r.id }\n\t\t\tconst collectionDef = (this.schema as SchemaDefinition).collections[\n\t\t\t\tcollection\n\t\t\t] as NonNullable<SchemaDefinition['collections'][string]>\n\t\t\tfor (const fieldName of Object.keys(collectionDef.fields)) {\n\t\t\t\tif (fieldName in r) {\n\t\t\t\t\tclean[fieldName] = r[fieldName]\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ('_created_at' in r) clean._created_at = r._created_at\n\t\t\tif ('_updated_at' in r) clean._updated_at = r._updated_at\n\t\t\treturn clean\n\t\t})\n\t}\n\n\tasync findRecord(collection: string, id: string): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) return null\n\n\t\tconst record = collectionMap.get(id)\n\t\tif (!record || record._deleted === 1) return null\n\n\t\t// Return clean copy\n\t\tconst clean: MaterializedRecord = { id: record.id }\n\t\tconst collectionDef = (this.schema as SchemaDefinition).collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tfor (const fieldName of Object.keys(collectionDef.fields)) {\n\t\t\tif (fieldName in record) {\n\t\t\t\tclean[fieldName] = record[fieldName]\n\t\t\t}\n\t\t}\n\t\tif ('_created_at' in record) clean._created_at = record._created_at\n\t\tif ('_updated_at' in record) clean._updated_at = record._updated_at\n\t\treturn clean\n\t}\n\n\tasync countCollection(collection: string, where?: Record<string, unknown>): Promise<number> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (where) {\n\t\t\tfor (const key of Object.keys(where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\n\t\tconst collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) return 0\n\n\t\tlet count = 0\n\t\tfor (const record of collectionMap.values()) {\n\t\t\tif (record._deleted === 1) continue\n\t\t\tif (where) {\n\t\t\t\tlet matches = true\n\t\t\t\tfor (const [key, value] of Object.entries(where)) {\n\t\t\t\t\tif (record[key] !== value) {\n\t\t\t\t\t\tmatches = false\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!matches) continue\n\t\t\t}\n\t\t\tcount++\n\t\t}\n\t\treturn count\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true\n\t}\n\n\t/**\n\t * Wipes all in-memory state. For tests and E2E isolation only.\n\t */\n\tresetForTests(): void {\n\t\tthis.assertOpen()\n\t\tthis.operations.length = 0\n\t\tthis.operationIndex.clear()\n\t\tthis.versionVector.clear()\n\t\tthis.materializedRecords.clear()\n\t\tthis.schema = null\n\t}\n\n\tasync exportBackup(): Promise<Uint8Array> {\n\t\tthis.assertOpen()\n\t\tconst { buildServerBackup } = await import('./server-backup')\n\t\treturn buildServerBackup(this.nodeId, this.operations, this.versionVector)\n\t}\n\n\tasync importBackup(\n\t\tdata: Uint8Array,\n\t\tmerge?: boolean,\n\t): Promise<{ operationsRestored: number; success: boolean }> {\n\t\tthis.assertOpen()\n\t\tconst { parseServerBackup } = await import('./server-backup')\n\t\tconst { operations, versionVector } = parseServerBackup(data)\n\n\t\tif (merge) {\n\t\t\tlet restored = 0\n\t\t\tfor (const op of operations) {\n\t\t\t\tconst result = await this.applyRemoteOperation(op)\n\t\t\t\tif (result === 'applied') restored++\n\t\t\t}\n\t\t\treturn { operationsRestored: restored, success: true }\n\t\t}\n\n\t\t// Replace mode: clear and reload\n\t\tthis.operations.length = 0\n\t\tthis.operationIndex.clear()\n\t\tthis.versionVector.clear()\n\t\tthis.deliverySeqByOpId.clear()\n\t\tthis.deliverySeqCounter = 0\n\n\t\tfor (const [nid, seq] of versionVector) {\n\t\t\tthis.versionVector.set(nid, seq)\n\t\t}\n\n\t\tfor (const op of operations) {\n\t\t\tthis.operations.push(op)\n\t\t\tthis.operationIndex.set(op.id, op)\n\t\t\t// Re-assign delivery sequence in backup order (the order ops were shipped).\n\t\t\tthis.deliverySeqCounter += 1\n\t\t\tthis.deliverySeqByOpId.set(op.id, this.deliverySeqCounter)\n\n\t\t\t// Update materialized records if schema is set\n\t\t\tif (this.schema?.collections[op.collection]) {\n\t\t\t\tthis.rebuildMaterializedRecord(op.collection, op.recordId)\n\t\t\t}\n\t\t}\n\n\t\treturn { operationsRestored: operations.length, success: true }\n\t}\n\n\t// --- Testing helpers (not on interface) ---\n\n\t/**\n\t * Get all stored operations (for test assertions).\n\t */\n\tgetAllOperations(): Operation[] {\n\t\treturn [...this.operations]\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Materialization internals\n\t// ---------------------------------------------------------------------------\n\n\tprivate rebuildMaterializedRecord(collection: string, recordId: string): void {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (!collectionDef) return\n\n\t\t// Get or create collection map\n\t\tlet collectionMap = this.materializedRecords.get(collection)\n\t\tif (!collectionMap) {\n\t\t\tcollectionMap = new Map()\n\t\t\tthis.materializedRecords.set(collection, collectionMap)\n\t\t}\n\n\t\t// Get all ops for this record in HLC total order (wallTime, logical, nodeId)\n\t\t// so atomic composition and LWW converge like the merge engine.\n\t\tconst recordOps = this.operations\n\t\t\t.filter((op) => op.collection === collection && op.recordId === recordId)\n\t\t\t.sort((a, b) => {\n\t\t\t\tif (a.timestamp.wallTime !== b.timestamp.wallTime)\n\t\t\t\t\treturn a.timestamp.wallTime - b.timestamp.wallTime\n\t\t\t\tif (a.timestamp.logical !== b.timestamp.logical)\n\t\t\t\t\treturn a.timestamp.logical - b.timestamp.logical\n\t\t\t\treturn a.timestamp.nodeId < b.timestamp.nodeId\n\t\t\t\t\t? -1\n\t\t\t\t\t: a.timestamp.nodeId > b.timestamp.nodeId\n\t\t\t\t\t\t? 1\n\t\t\t\t\t\t: 0\n\t\t\t})\n\n\t\tconst parsedOps = recordOps.map((op) => ({\n\t\t\ttype: op.type,\n\t\t\tdata: op.data,\n\t\t\tatomicOps: op.atomicOps ?? null,\n\t\t}))\n\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\tif (recordData) {\n\t\t\tconst createdAt =\n\t\t\t\trecordOps.length > 0 ? (recordOps[0] as Operation).timestamp.wallTime : Date.now()\n\t\t\tconst updatedAt =\n\t\t\t\trecordOps.length > 0\n\t\t\t\t\t? (recordOps[recordOps.length - 1] as Operation).timestamp.wallTime\n\t\t\t\t\t: Date.now()\n\n\t\t\tconst materialized: MaterializedRecord = {\n\t\t\t\tid: recordId,\n\t\t\t\t...recordData,\n\t\t\t\t_created_at: createdAt,\n\t\t\t\t_updated_at: updatedAt,\n\t\t\t\t_deleted: 0,\n\t\t\t}\n\t\t\tcollectionMap.set(recordId, materialized)\n\t\t} else {\n\t\t\t// Record was deleted\n\t\t\tconst existing = collectionMap.get(recordId)\n\t\t\tif (existing) {\n\t\t\t\texisting._deleted = 1\n\t\t\t\texisting._updated_at = Date.now()\n\t\t\t} else {\n\t\t\t\tcollectionMap.set(recordId, {\n\t\t\t\t\tid: recordId,\n\t\t\t\t\t_deleted: 1,\n\t\t\t\t\t_created_at: Date.now(),\n\t\t\t\t\t_updated_at: Date.now(),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate backfillAllCollections(): void {\n\t\tif (!this.schema) return\n\n\t\t// Get all unique (collection, recordId) pairs\n\t\tconst recordKeys = new Set<string>()\n\t\tfor (const op of this.operations) {\n\t\t\tif (this.schema.collections[op.collection]) {\n\t\t\t\trecordKeys.add(`${op.collection}:::${op.recordId}`)\n\t\t\t}\n\t\t}\n\n\t\tfor (const key of recordKeys) {\n\t\t\tconst [collection, recordId] = key.split(':::') as [string, string]\n\t\t\tthis.rebuildMaterializedRecord(collection, recordId)\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Fallback materialization (no schema)\n\t// ---------------------------------------------------------------------------\n\n\tprivate materializeFromOps(collection: string): MaterializedRecord[] {\n\t\tconst collectionOps = this.operations\n\t\t\t.filter((op) => op.collection === collection)\n\t\t\t.sort((a, b) => {\n\t\t\t\tif (a.timestamp.wallTime !== b.timestamp.wallTime)\n\t\t\t\t\treturn a.timestamp.wallTime - b.timestamp.wallTime\n\t\t\t\tif (a.timestamp.logical !== b.timestamp.logical)\n\t\t\t\t\treturn a.timestamp.logical - b.timestamp.logical\n\t\t\t\treturn a.sequenceNumber - b.sequenceNumber\n\t\t\t})\n\n\t\tconst records = new Map<string, Record<string, unknown>>()\n\t\tconst deleted = new Set<string>()\n\n\t\tfor (const op of collectionOps) {\n\t\t\tswitch (op.type) {\n\t\t\t\tcase 'insert':\n\t\t\t\t\tif (op.data) {\n\t\t\t\t\t\trecords.set(op.recordId, { id: op.recordId, ...op.data })\n\t\t\t\t\t\tdeleted.delete(op.recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'update':\n\t\t\t\t\tif (op.data) {\n\t\t\t\t\t\tconst existing = records.get(op.recordId) ?? { id: op.recordId }\n\t\t\t\t\t\trecords.set(op.recordId, { ...existing, ...op.data })\n\t\t\t\t\t\tdeleted.delete(op.recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'delete':\n\t\t\t\t\tdeleted.add(op.recordId)\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tfor (const id of deleted) {\n\t\t\trecords.delete(id)\n\t\t}\n\n\t\treturn Array.from(records.values()) as MaterializedRecord[]\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Assertions\n\t// ---------------------------------------------------------------------------\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) {\n\t\t\tthrow new Error('MemoryServerStore is closed')\n\t\t}\n\t}\n\n\tprivate assertSchema(): void {\n\t\tif (!this.schema) {\n\t\t\tthrow new Error(\n\t\t\t\t'Schema not set. Call setSchema() before using queryCollection/findRecord/countCollection.',\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate assertCollection(collection: string): void {\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (!schema.collections[collection]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${collection}\". Available: ${Object.keys(schema.collections).join(', ')}`,\n\t\t\t)\n\t\t}\n\t}\n}\n","import { StorageError, quoteIdent, replayOperationsForRecord } from '@korajs/core'\nimport type {\n\tCollectionDefinition,\n\tFieldDescriptor,\n\tReplayOperation,\n\tSchemaDefinition,\n} from '@korajs/core'\n\n// Re-exported so existing server-internal imports keep working; the implementation\n// now lives in @korajs/core so the client apply pipeline and the server materialize\n// records through the exact same atomic-aware fold.\nexport { replayOperationsForRecord }\nexport type { ReplayOperation }\n\n/**\n * SQL dialect for DDL generation.\n * SQLite and PostgreSQL differ in some column types.\n */\nexport type SqlDialect = 'sqlite' | 'postgres'\n\n/**\n * Map a Kora field kind to its SQL column type for the given dialect.\n */\nfunction fieldTypeToSql(descriptor: FieldDescriptor, dialect: SqlDialect): string {\n\tswitch (descriptor.kind) {\n\t\tcase 'string':\n\t\t\treturn 'TEXT'\n\t\tcase 'number':\n\t\t\treturn dialect === 'postgres' ? 'DOUBLE PRECISION' : 'REAL'\n\t\tcase 'boolean':\n\t\t\treturn 'INTEGER'\n\t\tcase 'enum':\n\t\t\treturn 'TEXT'\n\t\tcase 'timestamp':\n\t\t\treturn dialect === 'postgres' ? 'BIGINT' : 'INTEGER'\n\t\tcase 'array':\n\t\t\treturn dialect === 'postgres' ? 'JSONB' : 'TEXT'\n\t\tcase 'object':\n\t\t\treturn dialect === 'postgres' ? 'JSONB' : 'TEXT'\n\t\tcase 'json':\n\t\t\treturn dialect === 'postgres' ? 'JSONB' : 'TEXT'\n\t\tcase 'blob':\n\t\t\t// Content-addressed BlobRef metadata is stored as JSON; the bytes live\n\t\t\t// out of band, so the column is textual, not binary.\n\t\t\treturn 'TEXT'\n\t\tcase 'secret':\n\t\t\treturn 'TEXT'\n\t\tcase 'richtext':\n\t\t\treturn dialect === 'postgres' ? 'BYTEA' : 'BLOB'\n\t}\n}\n\nfunction sqlDefaultLiteral(value: unknown): string {\n\tif (value === null) return 'NULL'\n\tif (typeof value === 'string') return `'${value}'`\n\tif (typeof value === 'number') return String(value)\n\tif (typeof value === 'boolean') return value ? '1' : '0'\n\treturn `'${JSON.stringify(value)}'`\n}\n\n/**\n * Generate DDL statements for creating a materialized collection table.\n * Includes CREATE TABLE, safe ALTER TABLE for schema evolution, and indexes.\n *\n * @param name - Collection/table name\n * @param collection - Collection definition from the schema\n * @param dialect - SQL dialect ('sqlite' or 'postgres')\n * @returns Array of DDL SQL strings\n */\nexport function generateCollectionDDL(\n\tname: string,\n\tcollection: CollectionDefinition,\n\tdialect: SqlDialect,\n): string[] {\n\tconst statements: string[] = []\n\tconst columns: string[] = ['id TEXT PRIMARY KEY NOT NULL']\n\n\tfor (const [fieldName, descriptor] of Object.entries(collection.fields)) {\n\t\tconst sqlType = fieldTypeToSql(descriptor, dialect)\n\t\tlet colDef = `${quoteIdent(fieldName)} ${sqlType}`\n\t\tif (descriptor.defaultValue !== undefined) {\n\t\t\tcolDef += ` DEFAULT ${sqlDefaultLiteral(descriptor.defaultValue)}`\n\t\t}\n\t\tif (descriptor.kind === 'enum' && descriptor.enumValues) {\n\t\t\tconst values = descriptor.enumValues.map((v) => `'${v}'`).join(', ')\n\t\t\tcolDef += ` CHECK (${quoteIdent(fieldName)} IN (${values}))`\n\t\t}\n\t\tcolumns.push(colDef)\n\t}\n\n\tconst tsType = dialect === 'postgres' ? 'BIGINT' : 'INTEGER'\n\tcolumns.push(`_created_at ${tsType} NOT NULL DEFAULT 0`)\n\tcolumns.push(`_updated_at ${tsType} NOT NULL DEFAULT 0`)\n\tcolumns.push('_deleted INTEGER NOT NULL DEFAULT 0')\n\n\tstatements.push(`CREATE TABLE IF NOT EXISTS ${quoteIdent(name)} (\\n ${columns.join(',\\n ')}\\n)`)\n\n\t// Safe ALTER TABLE for adding new columns to existing tables\n\tfor (const [fieldName, descriptor] of Object.entries(collection.fields)) {\n\t\tconst sqlType = fieldTypeToSql(descriptor, dialect)\n\t\tlet colDef = `${quoteIdent(fieldName)} ${sqlType}`\n\t\tif (descriptor.defaultValue !== undefined) {\n\t\t\tcolDef += ` DEFAULT ${sqlDefaultLiteral(descriptor.defaultValue)}`\n\t\t}\n\t\tstatements.push(`--kora:safe-alter\\nALTER TABLE ${quoteIdent(name)} ADD COLUMN ${colDef}`)\n\t}\n\n\t// User-defined indexes from schema. The index NAME stays unquoted (only ever\n\t// created/dropped by this construction); the table and column are quoted.\n\tfor (const indexField of collection.indexes) {\n\t\tstatements.push(\n\t\t\t`CREATE INDEX IF NOT EXISTS idx_${name}_${indexField} ON ${quoteIdent(name)} (${quoteIdent(indexField)})`,\n\t\t)\n\t}\n\n\t// Always index _deleted for efficient soft-delete filtering\n\tstatements.push(\n\t\t`CREATE INDEX IF NOT EXISTS idx_${name}__deleted ON ${quoteIdent(name)} (_deleted)`,\n\t)\n\n\treturn statements\n}\n\n/**\n * Generate all collection table DDL from a full schema.\n */\nexport function generateAllCollectionDDL(schema: SchemaDefinition, dialect: SqlDialect): string[] {\n\tconst statements: string[] = []\n\tfor (const [name, collection] of Object.entries(schema.collections)) {\n\t\tstatements.push(...generateCollectionDDL(name, collection, dialect))\n\t}\n\treturn statements\n}\n\nconst BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nconst BASE64_REVERSE: ReadonlyMap<string, number> = new Map(\n\tArray.from(BASE64_ALPHABET, (char, index) => [char, index]),\n)\n\nfunction base64ToBytes(base64: string): Uint8Array {\n\tconst cleaned = base64.replace(/=+$/, '')\n\tconst out = new Uint8Array(Math.floor((cleaned.length * 6) / 8))\n\tlet buffer = 0\n\tlet bits = 0\n\tlet index = 0\n\tfor (const char of cleaned) {\n\t\tconst value = BASE64_REVERSE.get(char)\n\t\tif (value === undefined) {\n\t\t\tthrow new StorageError(`Invalid base64 character \"${char}\" in tagged richtext value`, {\n\t\t\t\tchar,\n\t\t\t})\n\t\t}\n\t\tbuffer = (buffer << 6) | value\n\t\tbits += 6\n\t\tif (bits >= 8) {\n\t\t\tbits -= 8\n\t\t\tout[index] = (buffer >> bits) & 0xff\n\t\t\tindex += 1\n\t\t}\n\t}\n\treturn out\n}\n\n/**\n * Decode a richtext op-data value to something a BLOB/BYTEA column accepts.\n * Client operations carry binary richtext as the canonical tagged\n * `{ $koraBytes: base64 }` form (raw bytes cannot survive the JSON `dataJson`\n * wire field). The server cannot import the store package (dependency rules),\n * so the tiny base64 decode is duplicated here rather than shared.\n * Strings and byte views pass through unchanged.\n */\nfunction decodeRichtextColumnValue(value: unknown): unknown {\n\tif (typeof value !== 'object' || value === null || ArrayBuffer.isView(value)) {\n\t\treturn value\n\t}\n\tconst record = value as Record<string, unknown>\n\tif (Object.keys(record).length === 1 && typeof record.$koraBytes === 'string') {\n\t\treturn base64ToBytes(record.$koraBytes)\n\t}\n\t// Pre-fix operations serialized raw Uint8Arrays as numeric-key objects;\n\t// reconstruct the bytes so old dev databases keep materializing.\n\tconst keys = Object.keys(record)\n\tif (keys.length > 0 && keys.every((k, i) => k === String(i) && typeof record[k] === 'number')) {\n\t\tconst bytes = new Uint8Array(keys.length)\n\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\tconst byte = record[String(i)]\n\t\t\tbytes[i] = typeof byte === 'number' ? byte & 0xff : 0\n\t\t}\n\t\treturn bytes\n\t}\n\treturn value\n}\n\n/**\n * Serialize a field value for SQL storage.\n * Arrays become JSON strings, booleans become 0/1, etc.\n */\nexport function serializeFieldValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tif (value === null || value === undefined) return null\n\tswitch (descriptor.kind) {\n\t\tcase 'array':\n\t\tcase 'object':\n\t\tcase 'json':\n\t\tcase 'blob':\n\t\t\treturn typeof value === 'string' ? value : JSON.stringify(value)\n\t\tcase 'boolean':\n\t\t\treturn value ? 1 : 0\n\t\tcase 'richtext':\n\t\t\treturn decodeRichtextColumnValue(value)\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n\n/**\n * Deserialize a field value from SQL storage back to JavaScript types.\n */\nexport function deserializeFieldValue(value: unknown, descriptor: FieldDescriptor): unknown {\n\tif (value === null || value === undefined) return null\n\tswitch (descriptor.kind) {\n\t\tcase 'array':\n\t\tcase 'object':\n\t\tcase 'json':\n\t\tcase 'blob':\n\t\t\treturn typeof value === 'string' ? JSON.parse(value) : value\n\t\tcase 'boolean':\n\t\t\treturn value === 1 || value === true\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n\n/**\n * Validate that a field name is a valid column in the given collection schema.\n * Includes system fields (id, _created_at, _updated_at, _deleted).\n */\nexport function validateFieldName(\n\tcollectionName: string,\n\tfieldName: string,\n\tschema: SchemaDefinition,\n): void {\n\tconst collection = schema.collections[collectionName]\n\tif (!collection) {\n\t\tthrow new Error(`Unknown collection: ${collectionName}`)\n\t}\n\tconst validFields = new Set([\n\t\t'id',\n\t\t'_created_at',\n\t\t'_updated_at',\n\t\t'_deleted',\n\t\t...Object.keys(collection.fields),\n\t])\n\tif (!validFields.has(fieldName)) {\n\t\tthrow new Error(\n\t\t\t`Invalid field name \"${fieldName}\" for collection \"${collectionName}\". ` +\n\t\t\t\t`Valid fields: ${Array.from(validFields).join(', ')}`,\n\t\t)\n\t}\n}\n","import type {\n\tAtomicOp,\n\tHLCTimestamp,\n\tOperation,\n\tSchemaDefinition,\n\tTimeSource,\n\tVersionVector,\n} from '@korajs/core'\nimport { HybridLogicalClock, generateUUIDv7, quoteIdent } from '@korajs/core'\nimport type { ApplyResult } from '@korajs/sync'\nimport type { SQL } from 'drizzle-orm'\nimport { and, asc, between, count, desc, eq, gt, sql } from 'drizzle-orm'\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'\nimport { pgOperations, pgSyncState } from './drizzle-pg-schema'\nimport {\n\tdeserializeFieldValue,\n\tgenerateAllCollectionDDL,\n\treplayOperationsForRecord,\n\tserializeFieldValue,\n\tvalidateFieldName,\n} from './materialization'\nimport type {\n\tCollectionQueryOptions,\n\tConditionalApplyInput,\n\tConditionalApplyResult,\n\tDeliveredOperation,\n\tMaterializedRecord,\n\tServerStore,\n} from './server-store'\n\n/**\n * PostgreSQL-backed server store using Drizzle ORM.\n * All reads and writes go through Drizzle's typed query builder.\n *\n * When a schema is set via setSchema(), also maintains materialized\n * collection tables for efficient indexed queries (dual-write).\n */\nexport class PostgresServerStore implements ServerStore {\n\tprivate readonly nodeId: string\n\tprivate readonly db: PostgresJsDatabase\n\tprivate readonly versionVector: VersionVector = new Map()\n\tprivate readonly ready: Promise<void>\n\tprivate schema: SchemaDefinition | null = null\n\tprivate closed = false\n\t/**\n\t * Monotonic counter for this node's server-originated sequence numbers. Lazily\n\t * seeded from the persisted version vector on first use, then advanced in memory\n\t * (a synchronous `++`, atomic on the single JS thread) so concurrent conditional\n\t * applies never receive the same number. Null means \"not yet seeded\"; reset to\n\t * null after a backup import so it re-seeds from the restored version vector.\n\t */\n\tprivate sequenceCounter: number | null = null\n\t/**\n\t * Time source for HLC timestamps on server-originated operations. Injectable so a\n\t * test can freeze wall-clock time and prove the conditional-apply ordering holds\n\t * under same-millisecond commits (the case the advisory lock and clock advance\n\t * exist to make correct). Defaults to the system clock in production.\n\t */\n\tprivate readonly timeSource: TimeSource\n\n\tconstructor(db: PostgresJsDatabase, nodeId?: string, timeSource?: TimeSource) {\n\t\tthis.db = db\n\t\tthis.nodeId = nodeId ?? generateUUIDv7()\n\t\tthis.timeSource = timeSource ?? { now: () => Date.now() }\n\t\tthis.ready = this.initialize()\n\t}\n\n\tgetVersionVector(): VersionVector {\n\t\tthis.assertOpen()\n\t\treturn new Map(this.versionVector)\n\t}\n\n\t/**\n\t * Atomically reserve this node's next server-operation sequence number. The\n\t * synchronous increment cannot interleave on the single JS thread, so two\n\t * concurrent conditional applies are always handed distinct numbers.\n\t */\n\treserveSequenceNumber(): number {\n\t\tif (this.sequenceCounter === null) {\n\t\t\tthis.sequenceCounter = this.versionVector.get(this.nodeId) ?? 0\n\t\t}\n\t\tthis.sequenceCounter += 1\n\t\treturn this.sequenceCounter\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.nodeId\n\t}\n\n\tgetSchema(): SchemaDefinition | null {\n\t\treturn this.schema\n\t}\n\n\tasync setSchema(schema: SchemaDefinition): Promise<void> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.schema = schema\n\n\t\t// Generate and execute DDL for all collection tables\n\t\tconst ddlStatements = generateAllCollectionDDL(schema, 'postgres')\n\t\tfor (const stmt of ddlStatements) {\n\t\t\tif (stmt.startsWith('--kora:safe-alter')) {\n\t\t\t\tconst alterSql = stmt.replace('--kora:safe-alter\\n', '')\n\t\t\t\ttry {\n\t\t\t\t\tawait this.db.execute(sql.raw(alterSql))\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// Ignore \"already exists\" errors from safe ALTER TABLE.\n\t\t\t\t\t// Drizzle wraps the actual DB error in e.cause, so check both.\n\t\t\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\t\t\tif (\n\t\t\t\t\t\t!msg.includes('already exists') &&\n\t\t\t\t\t\t!msg.includes('duplicate column') &&\n\t\t\t\t\t\t!causeMsg.includes('already exists') &&\n\t\t\t\t\t\t!causeMsg.includes('duplicate column')\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow e\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait this.db.execute(sql.raw(stmt))\n\t\t\t}\n\t\t}\n\n\t\t// Backfill materialized tables from existing operations\n\t\tawait this.backfillAllCollections()\n\t}\n\n\tasync applyRemoteOperation(op: Operation): Promise<ApplyResult> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\t// Content-addressed dedup check\n\t\tconst existing = await this.db\n\t\t\t.select({ id: pgOperations.id })\n\t\t\t.from(pgOperations)\n\t\t\t.where(eq(pgOperations.id, op.id))\n\t\t\t.limit(1)\n\n\t\tif (existing.length > 0) {\n\t\t\treturn 'duplicate'\n\t\t}\n\n\t\tconst now = Date.now()\n\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\t// Assign the delivery sequence in commit order (see nextDeliverySeq). A rare\n\t\t\t// concurrent duplicate insert below no-ops and simply leaves a harmless gap.\n\t\t\tconst deliverySeq = await this.nextDeliverySeq(tx)\n\t\t\tconst row = this.serializeOperation(op, now, deliverySeq)\n\n\t\t\t// Insert operation with dedup\n\t\t\tawait tx.insert(pgOperations).values(row).onConflictDoNothing({ target: pgOperations.id })\n\n\t\t\t// Upsert version vector: advance max sequence number with GREATEST\n\t\t\tawait tx\n\t\t\t\t.insert(pgSyncState)\n\t\t\t\t.values({\n\t\t\t\t\tnodeId: op.nodeId,\n\t\t\t\t\tmaxSequenceNumber: op.sequenceNumber,\n\t\t\t\t\tlastSeenAt: now,\n\t\t\t\t})\n\t\t\t\t.onConflictDoUpdate({\n\t\t\t\t\ttarget: pgSyncState.nodeId,\n\t\t\t\t\tset: {\n\t\t\t\t\t\tmaxSequenceNumber: sql`GREATEST(${pgSyncState.maxSequenceNumber}, ${op.sequenceNumber})`,\n\t\t\t\t\t\tlastSeenAt: sql`${now}`,\n\t\t\t\t\t},\n\t\t\t\t})\n\n\t\t\t// Dual-write: update materialized collection table if schema is set\n\t\t\tif (this.schema?.collections[op.collection]) {\n\t\t\t\tawait this.rebuildMaterializedRecord(tx, op.collection, op.recordId)\n\t\t\t}\n\t\t})\n\n\t\t// Update in-memory version vector cache\n\t\tconst currentMax = this.versionVector.get(op.nodeId) ?? 0\n\t\tif (op.sequenceNumber > currentMax) {\n\t\t\tthis.versionVector.set(op.nodeId, op.sequenceNumber)\n\t\t}\n\n\t\treturn 'applied'\n\t}\n\n\t/**\n\t * Conditionally apply operations atomically, serialized across server instances\n\t * on the target record via a transaction-scoped advisory lock. The lock makes\n\t * the read-decide-write cycle atomic against concurrent instances, so a cap\n\t * check like `responseCount < max` cannot be passed by two admissions at once.\n\t */\n\tasync applyConditional(input: ConditionalApplyInput): Promise<ConditionalApplyResult> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(input.target.collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[input.target.collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tconst lockKey = `kora:${input.target.collection}:${input.target.id}`\n\n\t\tconst result = await this.db.transaction(async (tx) => {\n\t\t\t// Serialize this target across every server instance sharing the database.\n\t\t\t// hashtextextended maps the key to the bigint pg_advisory_xact_lock expects;\n\t\t\t// the lock releases automatically when the transaction ends.\n\t\t\tawait tx.execute(sql`SELECT pg_advisory_xact_lock(hashtextextended(${lockKey}, 0))`)\n\n\t\t\t// Idempotency: if the key record already exists (from an earlier attempt),\n\t\t\t// this set is already committed. Checked under the lock so a retry racing a\n\t\t\t// first attempt on another instance still resolves to at-most-once.\n\t\t\tif (input.idempotencyKey) {\n\t\t\t\tconst existing = (await tx.execute(\n\t\t\t\t\tsql`SELECT 1 FROM ${sql.raw(quoteIdent(input.idempotencyKey.collection))} WHERE id = ${input.idempotencyKey.id} AND _deleted = 0 LIMIT 1`,\n\t\t\t\t)) as unknown as unknown[]\n\t\t\t\tif (existing.length > 0) {\n\t\t\t\t\treturn { admitted: true, idempotent: true, applied: [] as Operation[] }\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst rows = (await tx.execute(\n\t\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(input.target.collection))} WHERE id = ${input.target.id} AND _deleted = 0`,\n\t\t\t)) as unknown as Record<string, unknown>[]\n\t\t\tconst current =\n\t\t\t\trows.length > 0\n\t\t\t\t\t? this.deserializeRow(rows[0] as Record<string, unknown>, collectionDef)\n\t\t\t\t\t: null\n\n\t\t\tif (!input.admit(current)) {\n\t\t\t\treturn { admitted: false, idempotent: false, applied: [] as Operation[] }\n\t\t\t}\n\n\t\t\t// Seed a clock past the target record's latest committed operation so the\n\t\t\t// operations built next sort strictly after every prior write to it. Under\n\t\t\t// the advisory lock this makes last-write-wins materialization agree with the\n\t\t\t// serialized commit order, so a same-millisecond commit on another instance\n\t\t\t// cannot cause the counter to be undercounted (which would admit past a cap).\n\t\t\tconst clock = new HybridLogicalClock(this.nodeId, this.timeSource)\n\t\t\tconst latest = await this.latestOperationTimestamp(\n\t\t\t\ttx,\n\t\t\t\tinput.target.collection,\n\t\t\t\tinput.target.id,\n\t\t\t)\n\t\t\tif (latest) {\n\t\t\t\tclock.advanceTo(latest)\n\t\t\t}\n\n\t\t\tconst ops = await input.buildOperations(current, { clock })\n\t\t\tconst now = Date.now()\n\t\t\tfor (const op of ops) {\n\t\t\t\tconst deliverySeq = await this.nextDeliverySeq(tx)\n\t\t\t\tconst row = this.serializeOperation(op, now, deliverySeq)\n\t\t\t\tawait tx.insert(pgOperations).values(row).onConflictDoNothing({ target: pgOperations.id })\n\t\t\t\tawait tx\n\t\t\t\t\t.insert(pgSyncState)\n\t\t\t\t\t.values({ nodeId: op.nodeId, maxSequenceNumber: op.sequenceNumber, lastSeenAt: now })\n\t\t\t\t\t.onConflictDoUpdate({\n\t\t\t\t\t\ttarget: pgSyncState.nodeId,\n\t\t\t\t\t\tset: {\n\t\t\t\t\t\t\tmaxSequenceNumber: sql`GREATEST(${pgSyncState.maxSequenceNumber}, ${op.sequenceNumber})`,\n\t\t\t\t\t\t\tlastSeenAt: sql`${now}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\tif (this.schema?.collections[op.collection]) {\n\t\t\t\t\tawait this.rebuildMaterializedRecord(tx, op.collection, op.recordId)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { admitted: true, idempotent: false, applied: ops }\n\t\t})\n\n\t\t// Advance the in-memory version vector cache after commit.\n\t\tfor (const op of result.applied) {\n\t\t\tconst currentMax = this.versionVector.get(op.nodeId) ?? 0\n\t\t\tif (op.sequenceNumber > currentMax) {\n\t\t\t\tthis.versionVector.set(op.nodeId, op.sequenceNumber)\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst rows = await this.db\n\t\t\t.select()\n\t\t\t.from(pgOperations)\n\t\t\t.where(\n\t\t\t\tand(eq(pgOperations.nodeId, nodeId), between(pgOperations.sequenceNumber, fromSeq, toSeq)),\n\t\t\t)\n\t\t\t.orderBy(asc(pgOperations.sequenceNumber))\n\n\t\treturn rows.map((row) => this.deserializeOperation(row))\n\t}\n\n\tasync getOperationCount(): Promise<number> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst result = await this.db.select({ value: count() }).from(pgOperations)\n\t\treturn result[0]?.value ?? 0\n\t}\n\n\tasync getMaxDeliverySequence(): Promise<number> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = (await this.db.execute(\n\t\t\tsql`SELECT COALESCE(MAX(delivery_seq), 0) AS m FROM operations`,\n\t\t)) as unknown as { m: number | string | bigint }[]\n\t\treturn Number(rows[0]?.m ?? 0)\n\t}\n\n\tasync getOperationsAfterDelivery(\n\t\tafterDeliverySequence: number,\n\t\tlimit: number,\n\t): Promise<DeliveredOperation[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tconst rows = await this.db\n\t\t\t.select()\n\t\t\t.from(pgOperations)\n\t\t\t.where(gt(pgOperations.deliverySeq, afterDeliverySequence))\n\t\t\t.orderBy(asc(pgOperations.deliverySeq))\n\t\t\t.limit(limit)\n\t\treturn rows.map((row) => ({\n\t\t\toperation: this.deserializeOperation(row),\n\t\t\tdeliverySequence: row.deliverySeq ?? 0,\n\t\t}))\n\t}\n\n\tasync materializeCollection(collection: string): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\t// Fast path: if schema is set, read directly from the materialized table\n\t\tif (this.schema?.collections[collection]) {\n\t\t\treturn this.queryCollection(collection)\n\t\t}\n\n\t\t// Fallback: replay operations (legacy path when schema is not set)\n\t\treturn this.materializeFromOpsLog(collection)\n\t}\n\n\tasync queryCollection(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions,\n\t): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\n\t\t// Validate field names in options\n\t\tif (options?.where) {\n\t\t\tfor (const key of Object.keys(options.where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\t\tif (options?.orderBy) {\n\t\t\tvalidateFieldName(collection, options.orderBy, schema)\n\t\t}\n\n\t\tconst query = this.buildSelectQuery(collection, options)\n\t\tconst rows = (await this.db.execute(query)) as unknown as Record<string, unknown>[]\n\n\t\treturn rows.map((row) => this.deserializeRow(row, collectionDef))\n\t}\n\n\tasync findRecord(collection: string, id: string): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tconst query = sql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id = ${id} AND _deleted = 0`\n\t\tconst rows = (await this.db.execute(query)) as unknown as Record<string, unknown>[]\n\n\t\tif (rows.length === 0) return null\n\t\treturn this.deserializeRow(rows[0] as Record<string, unknown>, collectionDef)\n\t}\n\n\tasync countCollection(collection: string, where?: Record<string, unknown>): Promise<number> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (where) {\n\t\t\tfor (const key of Object.keys(where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\n\t\tconst whereClause = this.buildWhereClause(where ?? {}, false)\n\t\tconst query = sql`SELECT COUNT(*) as cnt FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`\n\t\tconst rows = (await this.db.execute(query)) as unknown as Array<{ cnt: number | string }>\n\t\tconst cnt = rows[0]?.cnt\n\t\treturn typeof cnt === 'string' ? Number.parseInt(cnt, 10) : (cnt ?? 0)\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true\n\t}\n\n\tasync exportBackup(): Promise<Uint8Array> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst { buildServerBackup } = await import('./server-backup')\n\n\t\t// Export in delivery-sequence order (commit order), NOT sequenceNumber order.\n\t\t// sequenceNumber is per-node and interleaves nodes arbitrarily, which can place a\n\t\t// dependent operation before its dependency; restoring in that order would then\n\t\t// reassign delivery sequences non-causally, so a resumed client would receive the\n\t\t// dependent first, defer it, advance its watermark past it, and lose it. Delivery\n\t\t// order is commit order and therefore respects causality.\n\t\tconst rows = await this.db.select().from(pgOperations).orderBy(asc(pgOperations.deliverySeq))\n\t\tconst operations = rows.map((row) => this.deserializeOperation(row))\n\n\t\treturn buildServerBackup(this.nodeId, operations, this.versionVector)\n\t}\n\n\tasync importBackup(\n\t\tdata: Uint8Array,\n\t\tmerge?: boolean,\n\t): Promise<{ operationsRestored: number; success: boolean }> {\n\t\tthis.assertOpen()\n\t\tawait this.ready\n\n\t\tconst { parseServerBackup } = await import('./server-backup')\n\t\tconst { operations, versionVector } = parseServerBackup(data)\n\n\t\tif (merge) {\n\t\t\tlet restored = 0\n\t\t\tfor (const op of operations) {\n\t\t\t\tconst result = await this.applyRemoteOperation(op)\n\t\t\t\tif (result === 'applied') restored++\n\t\t\t}\n\t\t\t// Re-seed the sequence counter from the (possibly advanced) version vector,\n\t\t\t// in case the merge restored operations on this node with higher numbers.\n\t\t\tthis.sequenceCounter = null\n\t\t\treturn { operationsRestored: restored, success: true }\n\t\t}\n\n\t\tconst now = Date.now()\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\tawait tx.delete(pgOperations)\n\t\t\tawait tx.delete(pgSyncState)\n\n\t\t\tfor (const [nid, seq] of versionVector) {\n\t\t\t\tawait tx\n\t\t\t\t\t.insert(pgSyncState)\n\t\t\t\t\t.values({ nodeId: nid, maxSequenceNumber: seq, lastSeenAt: now })\n\t\t\t\t\t.onConflictDoNothing({ target: pgSyncState.nodeId })\n\t\t\t}\n\n\t\t\t// Re-assign delivery sequence from scratch in backup order, then realign the\n\t\t\t// counter so future appends continue above the restored maximum.\n\t\t\tlet deliverySeq = 0\n\t\t\tfor (const op of operations) {\n\t\t\t\tdeliverySeq += 1\n\t\t\t\tconst row = this.serializeOperation(op, now, deliverySeq)\n\t\t\t\tawait tx.insert(pgOperations).values(row).onConflictDoNothing({ target: pgOperations.id })\n\t\t\t}\n\t\t\tawait tx.execute(\n\t\t\t\tsql`INSERT INTO delivery_counter (id, value) VALUES (1, ${deliverySeq})\n\t\t\t\t\tON CONFLICT (id) DO UPDATE SET value = ${deliverySeq}`,\n\t\t\t)\n\t\t})\n\n\t\t// Rebuild in-memory version vector\n\t\tthis.versionVector.clear()\n\t\tfor (const [nid, seq] of versionVector) {\n\t\t\tthis.versionVector.set(nid, seq)\n\t\t}\n\t\t// Re-seed the sequence counter from the restored version vector.\n\t\tthis.sequenceCounter = null\n\n\t\treturn { operationsRestored: operations.length, success: true }\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Materialization internals\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * The HLC timestamp of the most recent operation on a record, by total order\n\t * (wallTime, logical, nodeId), or null when the record has no operations. Used\n\t * by {@link applyConditional} to advance its clock past the record's latest\n\t * write so newly built operations sort strictly after it.\n\t */\n\tprivate async latestOperationTimestamp(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<HLCTimestamp | null> {\n\t\tconst rows = await txOrDb\n\t\t\t.select({\n\t\t\t\twallTime: pgOperations.wallTime,\n\t\t\t\tlogical: pgOperations.logical,\n\t\t\t\ttimestampNodeId: pgOperations.timestampNodeId,\n\t\t\t})\n\t\t\t.from(pgOperations)\n\t\t\t.where(and(eq(pgOperations.collection, collection), eq(pgOperations.recordId, recordId)))\n\t\t\t.orderBy(\n\t\t\t\tdesc(pgOperations.wallTime),\n\t\t\t\tdesc(pgOperations.logical),\n\t\t\t\tdesc(pgOperations.timestampNodeId),\n\t\t\t)\n\t\t\t.limit(1)\n\n\t\tconst row = rows[0]\n\t\tif (!row) {\n\t\t\treturn null\n\t\t}\n\t\treturn { wallTime: row.wallTime, logical: row.logical, nodeId: row.timestampNodeId }\n\t}\n\n\t/**\n\t * Rebuild a single record in the materialized collection table by replaying\n\t * all operations for that record.\n\t */\n\tprivate async rebuildMaterializedRecord(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<void> {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (!collectionDef) return\n\n\t\t// Fetch all ops for this specific record, ordered by HLC\n\t\tconst ops = await txOrDb\n\t\t\t.select({\n\t\t\t\ttype: pgOperations.type,\n\t\t\t\tdata: pgOperations.data,\n\t\t\t\tatomicOps: pgOperations.atomicOps,\n\t\t\t\twallTime: pgOperations.wallTime,\n\t\t\t})\n\t\t\t.from(pgOperations)\n\t\t\t.where(and(eq(pgOperations.collection, collection), eq(pgOperations.recordId, recordId)))\n\t\t\t// HLC total order (wallTime, logical, nodeId) so atomic composition and LWW\n\t\t\t// see operations in exactly the order the merge engine converges them.\n\t\t\t.orderBy(\n\t\t\t\tasc(pgOperations.wallTime),\n\t\t\t\tasc(pgOperations.logical),\n\t\t\t\tasc(pgOperations.timestampNodeId),\n\t\t\t)\n\n\t\t// Replay to get current state\n\t\tconst parsedOps = ops.map((op) => ({\n\t\t\ttype: op.type,\n\t\t\tdata: op.data !== null ? JSON.parse(op.data) : null,\n\t\t\tatomicOps:\n\t\t\t\top.atomicOps != null ? (JSON.parse(op.atomicOps) as Record<string, AtomicOp>) : null,\n\t\t}))\n\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\tconst fieldNames = Object.keys(collectionDef.fields)\n\n\t\tif (recordData) {\n\t\t\tconst createdAt = ops.length > 0 ? (ops[0] as (typeof ops)[0]).wallTime : Date.now()\n\t\t\tconst updatedAt =\n\t\t\t\tops.length > 0 ? (ops[ops.length - 1] as (typeof ops)[0]).wallTime : Date.now()\n\n\t\t\tawait this.upsertMaterializedRecord(\n\t\t\t\ttxOrDb,\n\t\t\t\tcollection,\n\t\t\t\trecordId,\n\t\t\t\trecordData,\n\t\t\t\tfieldNames,\n\t\t\t\tcollectionDef,\n\t\t\t\tcreatedAt,\n\t\t\t\tupdatedAt,\n\t\t\t)\n\t\t} else {\n\t\t\tawait txOrDb.execute(\n\t\t\t\tsql`UPDATE ${sql.raw(quoteIdent(collection))} SET _deleted = 1, _updated_at = ${Date.now()} WHERE id = ${recordId}`,\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * UPSERT a record into the materialized collection table.\n\t */\n\tprivate async upsertMaterializedRecord(\n\t\ttxOrDb: PostgresJsDatabase,\n\t\ttableName: string,\n\t\trecordId: string,\n\t\trecordData: Record<string, unknown>,\n\t\tfieldNames: string[],\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t\tcreatedAt: number,\n\t\tupdatedAt: number,\n\t): Promise<void> {\n\t\tconst allColumns = ['id', ...fieldNames, '_created_at', '_updated_at', '_deleted']\n\t\tconst values: unknown[] = [\n\t\t\trecordId,\n\t\t\t...fieldNames.map((f) => {\n\t\t\t\tconst descriptor = collectionDef.fields[f]\n\t\t\t\treturn descriptor ? serializeFieldValue(recordData[f] ?? null, descriptor) : null\n\t\t\t}),\n\t\t\tcreatedAt,\n\t\t\tupdatedAt,\n\t\t\t0,\n\t\t]\n\n\t\tconst columnsSql = sql.raw(allColumns.map((c) => quoteIdent(c)).join(', '))\n\t\tconst valuesSql = sql.join(\n\t\t\tvalues.map((v) => sql`${v}`),\n\t\t\tsql.raw(', '),\n\t\t)\n\t\tconst updateSet = sql.raw(\n\t\t\tallColumns\n\t\t\t\t.slice(1)\n\t\t\t\t.map((c) => `${quoteIdent(c)} = excluded.${quoteIdent(c)}`)\n\t\t\t\t.join(', '),\n\t\t)\n\n\t\tawait txOrDb.execute(\n\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(tableName))} (${columnsSql}) VALUES (${valuesSql}) ON CONFLICT (id) DO UPDATE SET ${updateSet}`,\n\t\t)\n\t}\n\n\t/**\n\t * Backfill all materialized collection tables from the existing operation log.\n\t */\n\tprivate async backfillAllCollections(): Promise<void> {\n\t\tif (!this.schema) return\n\n\t\tfor (const collectionName of Object.keys(this.schema.collections)) {\n\t\t\tawait this.backfillCollection(collectionName)\n\t\t}\n\t}\n\n\t/**\n\t * Backfill a single collection's materialized table from operations.\n\t */\n\tprivate async backfillCollection(collectionName: string): Promise<void> {\n\t\tconst collectionDef = this.schema?.collections[collectionName]\n\t\tif (!collectionDef) return\n\n\t\tconst allOps = await this.db\n\t\t\t.select({\n\t\t\t\trecordId: pgOperations.recordId,\n\t\t\t\ttype: pgOperations.type,\n\t\t\t\tdata: pgOperations.data,\n\t\t\t\tatomicOps: pgOperations.atomicOps,\n\t\t\t\twallTime: pgOperations.wallTime,\n\t\t\t})\n\t\t\t.from(pgOperations)\n\t\t\t.where(eq(pgOperations.collection, collectionName))\n\t\t\t// HLC total order (wallTime, logical, nodeId) for correct atomic composition.\n\t\t\t.orderBy(\n\t\t\t\tasc(pgOperations.wallTime),\n\t\t\t\tasc(pgOperations.logical),\n\t\t\t\tasc(pgOperations.timestampNodeId),\n\t\t\t)\n\n\t\tif (allOps.length === 0) return\n\n\t\t// Group by recordId\n\t\tconst grouped = new Map<string, typeof allOps>()\n\t\tfor (const op of allOps) {\n\t\t\tlet group = grouped.get(op.recordId)\n\t\t\tif (!group) {\n\t\t\t\tgroup = []\n\t\t\t\tgrouped.set(op.recordId, group)\n\t\t\t}\n\t\t\tgroup.push(op)\n\t\t}\n\n\t\tconst fieldNames = Object.keys(collectionDef.fields)\n\n\t\t// Rebuild each record\n\t\tfor (const [recordId, recordOps] of grouped) {\n\t\t\tconst parsedOps = recordOps.map((op) => ({\n\t\t\t\ttype: op.type,\n\t\t\t\tdata: op.data !== null ? JSON.parse(op.data) : null,\n\t\t\t\tatomicOps:\n\t\t\t\t\top.atomicOps != null ? (JSON.parse(op.atomicOps) as Record<string, AtomicOp>) : null,\n\t\t\t}))\n\t\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\t\tif (recordData) {\n\t\t\t\tconst createdAt = (recordOps[0] as (typeof recordOps)[0]).wallTime\n\t\t\t\tconst updatedAt = (recordOps[recordOps.length - 1] as (typeof recordOps)[0]).wallTime\n\t\t\t\tawait this.upsertMaterializedRecord(\n\t\t\t\t\tthis.db,\n\t\t\t\t\tcollectionName,\n\t\t\t\t\trecordId,\n\t\t\t\t\trecordData,\n\t\t\t\t\tfieldNames,\n\t\t\t\t\tcollectionDef,\n\t\t\t\t\tcreatedAt,\n\t\t\t\t\tupdatedAt,\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tawait this.db.execute(\n\t\t\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(collectionName))} (id, _deleted, _created_at, _updated_at) VALUES (${recordId}, 1, ${Date.now()}, ${Date.now()}) ON CONFLICT (id) DO UPDATE SET _deleted = 1, _updated_at = ${Date.now()}`,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Query building\n\t// ---------------------------------------------------------------------------\n\n\tprivate buildSelectQuery(collection: string, options?: CollectionQueryOptions): SQL {\n\t\tconst whereClause = this.buildWhereClause(\n\t\t\toptions?.where ?? {},\n\t\t\toptions?.includeDeleted ?? false,\n\t\t)\n\n\t\tconst parts: SQL[] = [\n\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`,\n\t\t]\n\n\t\tif (options?.orderBy) {\n\t\t\tconst dir = options.orderDirection === 'desc' ? 'DESC' : 'ASC'\n\t\t\tparts.push(sql.raw(` ORDER BY ${quoteIdent(options.orderBy)} ${dir}`))\n\t\t}\n\n\t\tif (options?.limit !== undefined) {\n\t\t\tparts.push(sql` LIMIT ${options.limit}`)\n\t\t}\n\n\t\tif (options?.offset !== undefined) {\n\t\t\tparts.push(sql` OFFSET ${options.offset}`)\n\t\t}\n\n\t\treturn sql.join(parts, sql.raw(''))\n\t}\n\n\tprivate buildWhereClause(where: Record<string, unknown>, includeDeleted: boolean): SQL {\n\t\tconst conditions: SQL[] = []\n\n\t\tif (!includeDeleted) {\n\t\t\tconditions.push(sql.raw('_deleted = 0'))\n\t\t}\n\n\t\tfor (const [key, value] of Object.entries(where)) {\n\t\t\tconditions.push(sql`${sql.raw(quoteIdent(key))} = ${value}`)\n\t\t}\n\n\t\tif (conditions.length === 0) {\n\t\t\treturn sql.raw('1 = 1')\n\t\t}\n\n\t\treturn sql.join(conditions, sql.raw(' AND '))\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Row deserialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate deserializeRow(\n\t\trow: Record<string, unknown>,\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t): MaterializedRecord {\n\t\tconst record: MaterializedRecord = { id: row.id as string }\n\n\t\tfor (const [fieldName, descriptor] of Object.entries(collectionDef.fields)) {\n\t\t\tif (fieldName in row) {\n\t\t\t\trecord[fieldName] = deserializeFieldValue(row[fieldName], descriptor)\n\t\t\t}\n\t\t}\n\n\t\tif ('_created_at' in row) record._created_at = row._created_at\n\t\tif ('_updated_at' in row) record._updated_at = row._updated_at\n\n\t\treturn record\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Fallback materialization (operation replay, no schema)\n\t// ---------------------------------------------------------------------------\n\n\tprivate async materializeFromOpsLog(collection: string): Promise<MaterializedRecord[]> {\n\t\tconst rows = await this.db\n\t\t\t.select()\n\t\t\t.from(pgOperations)\n\t\t\t.where(eq(pgOperations.collection, collection))\n\t\t\t.orderBy(\n\t\t\t\tasc(pgOperations.wallTime),\n\t\t\t\tasc(pgOperations.logical),\n\t\t\t\tasc(pgOperations.sequenceNumber),\n\t\t\t)\n\n\t\tconst records = new Map<string, Record<string, unknown>>()\n\t\tconst deleted = new Set<string>()\n\n\t\tfor (const row of rows) {\n\t\t\tconst recordId = row.recordId\n\t\t\tconst data = row.data !== null ? JSON.parse(row.data) : null\n\n\t\t\tswitch (row.type) {\n\t\t\t\tcase 'insert':\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\trecords.set(recordId, { id: recordId, ...data })\n\t\t\t\t\t\tdeleted.delete(recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'update':\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\tconst existing = records.get(recordId) ?? { id: recordId }\n\t\t\t\t\t\trecords.set(recordId, { ...existing, ...data })\n\t\t\t\t\t\tdeleted.delete(recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'delete':\n\t\t\t\t\tdeleted.add(recordId)\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tfor (const id of deleted) {\n\t\t\trecords.delete(id)\n\t\t}\n\n\t\treturn Array.from(records.values()) as MaterializedRecord[]\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Initialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate async initialize(): Promise<void> {\n\t\tawait this.ensureTables()\n\n\t\t// Hydrate in-memory version vector cache\n\t\tconst rows = await this.db\n\t\t\t.select({\n\t\t\t\tnodeId: pgSyncState.nodeId,\n\t\t\t\tmaxSequenceNumber: pgSyncState.maxSequenceNumber,\n\t\t\t})\n\t\t\t.from(pgSyncState)\n\n\t\tfor (const row of rows) {\n\t\t\tthis.versionVector.set(row.nodeId, row.maxSequenceNumber)\n\t\t}\n\t}\n\n\tprivate async ensureTables(): Promise<void> {\n\t\t// Serialize all schema setup across instances with an advisory transaction lock.\n\t\t// `CREATE TABLE IF NOT EXISTS` is not atomic in Postgres: two servers cold-starting\n\t\t// against the same empty database race and one fails with a duplicate-type error.\n\t\t// Running every setup statement in one advisory-locked transaction makes concurrent\n\t\t// startup safe and also serializes the delivery-sequence backfill.\n\t\tawait this.db.transaction(async (tx) => {\n\t\t\tawait tx.execute(sql`SELECT pg_advisory_xact_lock(hashtextextended('kora:ensure-tables', 0))`)\n\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS operations (\n\t\t\t\t\tid TEXT PRIMARY KEY,\n\t\t\t\t\tnode_id TEXT NOT NULL,\n\t\t\t\t\ttype TEXT NOT NULL,\n\t\t\t\t\tcollection TEXT NOT NULL,\n\t\t\t\t\trecord_id TEXT NOT NULL,\n\t\t\t\t\tdata TEXT,\n\t\t\t\t\tprevious_data TEXT,\n\t\t\t\t\tatomic_ops TEXT,\n\t\t\t\t\twall_time BIGINT NOT NULL,\n\t\t\t\t\tlogical INTEGER NOT NULL,\n\t\t\t\t\ttimestamp_node_id TEXT NOT NULL,\n\t\t\t\t\tsequence_number INTEGER NOT NULL,\n\t\t\t\t\tcausal_deps TEXT NOT NULL DEFAULT '[]',\n\t\t\t\t\tschema_version INTEGER NOT NULL,\n\t\t\t\t\treceived_at BIGINT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\t// Backward-compatible migration: add atomic_ops to operation logs created\n\t\t\t// before atomic-op persistence. Nullable, so existing rows read as \"no atomic\n\t\t\t// ops\" and keep materializing by last-write-wins exactly as before.\n\t\t\tawait tx.execute(sql`ALTER TABLE operations ADD COLUMN IF NOT EXISTS atomic_ops TEXT`)\n\n\t\t\t// Backward-compatible migration: add the delivery_seq column for the gap-free\n\t\t\t// delivery watermark.\n\t\t\tawait tx.execute(sql`ALTER TABLE operations ADD COLUMN IF NOT EXISTS delivery_seq BIGINT`)\n\n\t\t\tawait tx.execute(\n\t\t\t\tsql`CREATE INDEX IF NOT EXISTS idx_node_seq ON operations (node_id, sequence_number)`,\n\t\t\t)\n\t\t\tawait tx.execute(sql`CREATE INDEX IF NOT EXISTS idx_collection ON operations (collection)`)\n\t\t\tawait tx.execute(sql`CREATE INDEX IF NOT EXISTS idx_received ON operations (received_at)`)\n\t\t\tawait tx.execute(\n\t\t\t\tsql`CREATE INDEX IF NOT EXISTS idx_delivery_seq ON operations (delivery_seq)`,\n\t\t\t)\n\t\t\t// Index for efficient per-record operation lookups during materialization\n\t\t\tawait tx.execute(\n\t\t\t\tsql`CREATE INDEX IF NOT EXISTS idx_collection_record ON operations (collection, record_id)`,\n\t\t\t)\n\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS sync_state (\n\t\t\t\t\tnode_id TEXT PRIMARY KEY,\n\t\t\t\t\tmax_sequence_number INTEGER NOT NULL,\n\t\t\t\t\tlast_seen_at BIGINT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\t// Counter row that assigns delivery sequences in commit order. Every append\n\t\t\t// does `UPDATE ... value = value + 1 RETURNING value` inside its transaction,\n\t\t\t// which holds an exclusive row lock until commit. So a later assigner cannot\n\t\t\t// obtain its number until the earlier one has committed: delivery-sequence\n\t\t\t// order equals commit (visibility) order, which is what makes a `> watermark`\n\t\t\t// stream provably gap-free across instances. This serializes appends through\n\t\t\t// one row (correctness over throughput, per the framework's priorities).\n\t\t\tawait tx.execute(sql`\n\t\t\t\tCREATE TABLE IF NOT EXISTS delivery_counter (\n\t\t\t\t\tid INTEGER PRIMARY KEY,\n\t\t\t\t\tvalue BIGINT NOT NULL\n\t\t\t\t)\n\t\t\t`)\n\n\t\t\t// Backfill any pre-column rows deterministically, then seed the counter to the\n\t\t\t// resulting maximum. Under the advisory lock two starting servers cannot\n\t\t\t// double-assign. The window scan touches only rows lacking a sequence, so a\n\t\t\t// fresh or already-migrated table does almost no work here.\n\t\t\tawait tx.execute(sql`\n\t\t\t\tWITH ordered AS (\n\t\t\t\t\tSELECT id, ROW_NUMBER() OVER (\n\t\t\t\t\t\tORDER BY received_at ASC, sequence_number ASC, id ASC\n\t\t\t\t\t) + COALESCE((SELECT MAX(delivery_seq) FROM operations), 0) AS rn\n\t\t\t\t\tFROM operations WHERE delivery_seq IS NULL\n\t\t\t\t)\n\t\t\t\tUPDATE operations o SET delivery_seq = ordered.rn\n\t\t\t\tFROM ordered WHERE o.id = ordered.id\n\t\t\t`)\n\t\t\tawait tx.execute(sql`\n\t\t\t\tINSERT INTO delivery_counter (id, value)\n\t\t\t\tVALUES (1, COALESCE((SELECT MAX(delivery_seq) FROM operations), 0))\n\t\t\t\tON CONFLICT (id) DO UPDATE\n\t\t\t\t\tSET value = GREATEST(delivery_counter.value, EXCLUDED.value)\n\t\t\t`)\n\t\t})\n\t}\n\n\t/**\n\t * Reserve the next delivery sequence inside an open append transaction. The\n\t * `UPDATE ... RETURNING` locks the counter row until this transaction commits,\n\t * serializing assignment into commit order (see the counter table comment).\n\t */\n\tprivate async nextDeliverySeq(tx: {\n\t\texecute: (query: SQL) => Promise<unknown>\n\t}): Promise<number> {\n\t\tconst rows = (await tx.execute(\n\t\t\tsql`UPDATE delivery_counter SET value = value + 1 WHERE id = 1 RETURNING value`,\n\t\t)) as unknown as { value: number | string | bigint }[]\n\t\tconst value = rows[0]?.value\n\t\tif (value === undefined || value === null) {\n\t\t\t// The counter row must always exist (ensureTables seeds it). A missing row would\n\t\t\t// silently return 0 and stamp every op with delivery_seq 0, making them invisible\n\t\t\t// to clients (a `> watermark` scan never returns 0). Fail loudly instead of\n\t\t\t// corrupting the delivery stream.\n\t\t\tthrow new Error(\n\t\t\t\t'delivery_counter row (id=1) is missing; the operations log cannot assign delivery sequences',\n\t\t\t)\n\t\t}\n\t\treturn Number(value)\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Operation serialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate serializeOperation(\n\t\top: Operation,\n\t\treceivedAt: number,\n\t\tdeliverySeq: number,\n\t): typeof pgOperations.$inferInsert {\n\t\treturn {\n\t\t\tid: op.id,\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 !== null ? JSON.stringify(op.data) : null,\n\t\t\tpreviousData: op.previousData !== null ? JSON.stringify(op.previousData) : null,\n\t\t\tatomicOps:\n\t\t\t\top.atomicOps && Object.keys(op.atomicOps).length > 0 ? JSON.stringify(op.atomicOps) : null,\n\t\t\twallTime: op.timestamp.wallTime,\n\t\t\tlogical: op.timestamp.logical,\n\t\t\ttimestampNodeId: op.timestamp.nodeId,\n\t\t\tsequenceNumber: op.sequenceNumber,\n\t\t\tcausalDeps: JSON.stringify(op.causalDeps),\n\t\t\tschemaVersion: op.schemaVersion,\n\t\t\treceivedAt,\n\t\t\tdeliverySeq,\n\t\t}\n\t}\n\n\tprivate deserializeOperation(row: typeof pgOperations.$inferSelect): Operation {\n\t\tconst atomicOps =\n\t\t\trow.atomicOps != null ? (JSON.parse(row.atomicOps) as Record<string, AtomicOp>) : undefined\n\t\treturn {\n\t\t\tid: row.id,\n\t\t\tnodeId: row.nodeId,\n\t\t\ttype: row.type as Operation['type'],\n\t\t\tcollection: row.collection,\n\t\t\trecordId: row.recordId,\n\t\t\tdata: row.data !== null ? JSON.parse(row.data) : null,\n\t\t\tpreviousData: row.previousData !== null ? JSON.parse(row.previousData) : null,\n\t\t\ttimestamp: {\n\t\t\t\twallTime: row.wallTime,\n\t\t\t\tlogical: row.logical,\n\t\t\t\tnodeId: row.timestampNodeId,\n\t\t\t},\n\t\t\tsequenceNumber: row.sequenceNumber,\n\t\t\tcausalDeps: JSON.parse(row.causalDeps),\n\t\t\tschemaVersion: row.schemaVersion,\n\t\t\t...(atomicOps ? { atomicOps } : {}),\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Assertions\n\t// ---------------------------------------------------------------------------\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) {\n\t\t\tthrow new Error('PostgresServerStore is closed')\n\t\t}\n\t}\n\n\tprivate assertSchema(): void {\n\t\tif (!this.schema) {\n\t\t\tthrow new Error(\n\t\t\t\t'Schema not set. Call setSchema() before using queryCollection/findRecord/countCollection.',\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate assertCollection(collection: string): void {\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (!schema.collections[collection]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${collection}\". Available: ${Object.keys(schema.collections).join(', ')}`,\n\t\t\t)\n\t\t}\n\t}\n}\n\n/**\n * Creates a PostgresServerStore from a PostgreSQL connection string.\n */\nexport async function createPostgresServerStore(options: {\n\tconnectionString: string\n\tnodeId?: string\n}): Promise<PostgresServerStore> {\n\tconst { postgresClient, drizzleFn } = await loadPostgresDeps()\n\tconst client = postgresClient(options.connectionString)\n\tconst db = drizzleFn(client)\n\n\treturn new PostgresServerStore(db, options.nodeId)\n}\n\nasync function loadPostgresDeps(): Promise<{\n\tpostgresClient: (connectionString: string) => unknown\n\tdrizzleFn: (client: unknown) => PostgresJsDatabase\n}> {\n\ttry {\n\t\tconst dynamicImport = new Function('specifier', 'return import(specifier)') as (\n\t\t\tspecifier: string,\n\t\t) => Promise<unknown>\n\n\t\tconst postgresMod = (await dynamicImport('postgres')) as { default: (cs: string) => unknown }\n\t\tconst drizzleMod = (await dynamicImport('drizzle-orm/postgres-js')) as {\n\t\t\tdrizzle: (client: unknown) => PostgresJsDatabase\n\t\t}\n\n\t\treturn {\n\t\t\tpostgresClient: postgresMod.default,\n\t\t\tdrizzleFn: drizzleMod.drizzle,\n\t\t}\n\t} catch {\n\t\tthrow new Error(\n\t\t\t'PostgreSQL backend requires the \"postgres\" package. Install it in your project dependencies.',\n\t\t)\n\t}\n}\n","import { bigint, index, integer, pgTable, text } from 'drizzle-orm/pg-core'\n\n/**\n * Drizzle schema for the Kora sync server's PostgreSQL database.\n *\n * Two tables:\n * - `pgOperations` — the append-only operation log (content-addressed by id)\n * - `pgSyncState` — tracks the max sequence number seen per node (version vector)\n *\n * Column structure mirrors the SQLite drizzle-schema.ts but uses pgTable.\n */\n\nexport const pgOperations = pgTable(\n\t'operations',\n\t{\n\t\tid: text('id').primaryKey(),\n\t\tnodeId: text('node_id').notNull(),\n\t\ttype: text('type').notNull(),\n\t\tcollection: text('collection').notNull(),\n\t\trecordId: text('record_id').notNull(),\n\t\tdata: text('data'), // JSON-serialized, null for deletes\n\t\tpreviousData: text('previous_data'), // JSON-serialized, null for insert/delete\n\t\tatomicOps: text('atomic_ops'), // JSON-serialized Record<field, AtomicOp>, null when none\n\t\twallTime: bigint('wall_time', { mode: 'number' }).notNull(),\n\t\tlogical: integer('logical').notNull(),\n\t\ttimestampNodeId: text('timestamp_node_id').notNull(),\n\t\tsequenceNumber: integer('sequence_number').notNull(),\n\t\tcausalDeps: text('causal_deps').notNull().default('[]'), // JSON array of op IDs\n\t\tschemaVersion: integer('schema_version').notNull(),\n\t\treceivedAt: bigint('received_at', { mode: 'number' }).notNull(),\n\t\t// Server-assigned monotonic delivery sequence, ordered by commit (assigned from\n\t\t// a counter row locked inside the append transaction, so delivery order equals\n\t\t// visibility order even across instances). Drives the gap-free server->client\n\t\t// delivery watermark. Nullable only for pre-column rows, backfilled on startup.\n\t\tdeliverySeq: bigint('delivery_seq', { mode: 'number' }),\n\t},\n\t(table) => ({\n\t\tnodeSeqIdx: index('idx_pg_node_seq').on(table.nodeId, table.sequenceNumber),\n\t\tcollectionIdx: index('idx_pg_collection').on(table.collection),\n\t\treceivedIdx: index('idx_pg_received').on(table.receivedAt),\n\t\tdeliveryIdx: index('idx_pg_delivery_seq').on(table.deliverySeq),\n\t}),\n)\n\nexport const pgSyncState = pgTable('sync_state', {\n\tnodeId: text('node_id').primaryKey(),\n\tmaxSequenceNumber: integer('max_sequence_number').notNull(),\n\tlastSeenAt: bigint('last_seen_at', { mode: 'number' }).notNull(),\n})\n","import { createRequire } from 'node:module'\nimport type { AtomicOp, Operation, SchemaDefinition, VersionVector } from '@korajs/core'\nimport { generateUUIDv7, quoteIdent } from '@korajs/core'\nimport type { ApplyResult } from '@korajs/sync'\nimport type { SQL } from 'drizzle-orm'\nimport { and, asc, between, count, eq, gt, sql } from 'drizzle-orm'\nimport type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3'\nimport { deliveryCounter, operations, syncState } from './drizzle-schema'\nimport {\n\tdeserializeFieldValue,\n\tgenerateAllCollectionDDL,\n\treplayOperationsForRecord,\n\tserializeFieldValue,\n\tvalidateFieldName,\n} from './materialization'\nimport type {\n\tCollectionQueryOptions,\n\tDeliveredOperation,\n\tMaterializedRecord,\n\tServerStore,\n} from './server-store'\n\n// better-sqlite3 is a native CJS addon that cannot be loaded via ESM import().\n// createRequire provides a CJS require() that works in both ESM and CJS contexts.\n// tsup's shims option ensures import.meta.url is available in CJS builds.\nconst esmRequire = createRequire(import.meta.url)\n\n/**\n * SQLite-backed server store using Drizzle ORM.\n * Persists operations and version vectors to a real database file,\n * surviving process restarts.\n *\n * When a schema is set via setSchema(), also maintains materialized\n * collection tables for efficient indexed queries (dual-write).\n */\nexport class SqliteServerStore implements ServerStore {\n\tprivate readonly nodeId: string\n\tprivate readonly db: BetterSQLite3Database\n\tprivate schema: SchemaDefinition | null = null\n\tprivate closed = false\n\n\tconstructor(db: BetterSQLite3Database, nodeId?: string) {\n\t\tthis.db = db\n\t\tthis.nodeId = nodeId ?? generateUUIDv7()\n\t\tthis.ensureTables()\n\t}\n\n\tgetVersionVector(): VersionVector {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db.select().from(syncState).all()\n\t\tconst vv: VersionVector = new Map()\n\t\tfor (const row of rows) {\n\t\t\tvv.set(row.nodeId, row.maxSequenceNumber)\n\t\t}\n\t\treturn vv\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.nodeId\n\t}\n\n\tgetSchema(): SchemaDefinition | null {\n\t\treturn this.schema\n\t}\n\n\tasync setSchema(schema: SchemaDefinition): Promise<void> {\n\t\tthis.assertOpen()\n\t\tthis.schema = schema\n\n\t\t// Generate and execute DDL for all collection tables\n\t\tconst ddlStatements = generateAllCollectionDDL(schema, 'sqlite')\n\t\tfor (const stmt of ddlStatements) {\n\t\t\tif (stmt.startsWith('--kora:safe-alter')) {\n\t\t\t\tconst alterSql = stmt.replace('--kora:safe-alter\\n', '')\n\t\t\t\ttry {\n\t\t\t\t\tthis.db.run(sql.raw(alterSql))\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// Ignore \"duplicate column\" errors from safe ALTER TABLE.\n\t\t\t\t\t// Drizzle wraps SQLite errors, so check both outer message and cause.\n\t\t\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\t\t\tthrow e\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.db.run(sql.raw(stmt))\n\t\t\t}\n\t\t}\n\n\t\t// Backfill materialized tables from existing operations\n\t\tawait this.backfillAllCollections()\n\t}\n\n\tasync applyRemoteOperation(op: Operation): Promise<ApplyResult> {\n\t\tthis.assertOpen()\n\n\t\tconst now = Date.now()\n\n\t\t// Use a transaction for atomicity: insert op + update version vector + materialize\n\t\tconst result = this.db.transaction((tx) => {\n\t\t\t// Content-addressed dedup: check before assigning a delivery sequence so a\n\t\t\t// duplicate never burns one (keeps the sequence gap-free on this store).\n\t\t\tconst existing = tx.all<{ id: string }>(\n\t\t\t\tsql`SELECT id FROM operations WHERE id = ${op.id} LIMIT 1`,\n\t\t\t)\n\t\t\tif (existing.length > 0) {\n\t\t\t\treturn 'duplicate' as const\n\t\t\t}\n\n\t\t\tconst row = this.serializeOperation(op, now, this.nextDeliverySeq(tx))\n\t\t\ttx.insert(operations).values(row).run()\n\n\t\t\t// Advance version vector: upsert with MAX to ensure monotonic progress\n\t\t\ttx.insert(syncState)\n\t\t\t\t.values({\n\t\t\t\t\tnodeId: op.nodeId,\n\t\t\t\t\tmaxSequenceNumber: op.sequenceNumber,\n\t\t\t\t\tlastSeenAt: now,\n\t\t\t\t})\n\t\t\t\t.onConflictDoUpdate({\n\t\t\t\t\ttarget: syncState.nodeId,\n\t\t\t\t\tset: {\n\t\t\t\t\t\tmaxSequenceNumber: sql`MAX(${syncState.maxSequenceNumber}, ${op.sequenceNumber})`,\n\t\t\t\t\t\tlastSeenAt: sql`${now}`,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\t.run()\n\n\t\t\t// Dual-write: update materialized collection table if schema is set\n\t\t\tif (this.schema?.collections[op.collection]) {\n\t\t\t\tthis.rebuildMaterializedRecord(tx, op.collection, op.recordId)\n\t\t\t}\n\n\t\t\treturn 'applied' as const\n\t\t})\n\n\t\treturn result\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\tthis.assertOpen()\n\n\t\tconst rows = this.db\n\t\t\t.select()\n\t\t\t.from(operations)\n\t\t\t.where(and(eq(operations.nodeId, nodeId), between(operations.sequenceNumber, fromSeq, toSeq)))\n\t\t\t.orderBy(asc(operations.sequenceNumber))\n\t\t\t.all()\n\n\t\treturn rows.map((row) => this.deserializeOperation(row))\n\t}\n\n\tasync getOperationCount(): Promise<number> {\n\t\tthis.assertOpen()\n\n\t\tconst result = this.db.select({ value: count() }).from(operations).all()\n\t\treturn result[0]?.value ?? 0\n\t}\n\n\tasync getMaxDeliverySequence(): Promise<number> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db.all<{ m: number | null }>(\n\t\t\tsql`SELECT MAX(delivery_seq) AS m FROM operations`,\n\t\t)\n\t\treturn rows[0]?.m ?? 0\n\t}\n\n\tasync getOperationsAfterDelivery(\n\t\tafterDeliverySequence: number,\n\t\tlimit: number,\n\t): Promise<DeliveredOperation[]> {\n\t\tthis.assertOpen()\n\t\tconst rows = this.db\n\t\t\t.select()\n\t\t\t.from(operations)\n\t\t\t.where(gt(operations.deliverySeq, afterDeliverySequence))\n\t\t\t.orderBy(asc(operations.deliverySeq))\n\t\t\t.limit(limit)\n\t\t\t.all()\n\t\treturn rows.map((row) => ({\n\t\t\toperation: this.deserializeOperation(row),\n\t\t\tdeliverySequence: row.deliverySeq ?? 0,\n\t\t}))\n\t}\n\n\tasync materializeCollection(collection: string): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\n\t\t// Fast path: if schema is set, read directly from the materialized table\n\t\tif (this.schema?.collections[collection]) {\n\t\t\treturn this.queryCollection(collection)\n\t\t}\n\n\t\t// Fallback: replay operations (legacy path when schema is not set)\n\t\treturn this.materializeFromOpsLog(collection)\n\t}\n\n\tasync queryCollection(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions,\n\t): Promise<MaterializedRecord[]> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\n\t\t// Validate field names in options\n\t\tif (options?.where) {\n\t\t\tfor (const key of Object.keys(options.where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\t\tif (options?.orderBy) {\n\t\t\tvalidateFieldName(collection, options.orderBy, schema)\n\t\t}\n\n\t\tconst query = this.buildSelectQuery(collection, options)\n\t\tconst rows = this.db.all<Record<string, unknown>>(query)\n\n\t\treturn rows.map((row) => this.deserializeRow(row, collectionDef))\n\t}\n\n\tasync findRecord(collection: string, id: string): Promise<MaterializedRecord | null> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tconst collectionDef = schema.collections[collection] as NonNullable<\n\t\t\tSchemaDefinition['collections'][string]\n\t\t>\n\t\tconst query = sql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE id = ${id} AND _deleted = 0`\n\t\tconst rows = this.db.all<Record<string, unknown>>(query)\n\n\t\tif (rows.length === 0) return null\n\t\treturn this.deserializeRow(rows[0] as Record<string, unknown>, collectionDef)\n\t}\n\n\tasync countCollection(collection: string, where?: Record<string, unknown>): Promise<number> {\n\t\tthis.assertOpen()\n\t\tthis.assertSchema()\n\t\tthis.assertCollection(collection)\n\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (where) {\n\t\t\tfor (const key of Object.keys(where)) {\n\t\t\t\tvalidateFieldName(collection, key, schema)\n\t\t\t}\n\t\t}\n\n\t\tconst whereClause = this.buildWhereClause(where ?? {}, false)\n\t\tconst query = sql`SELECT COUNT(*) as cnt FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`\n\t\tconst rows = this.db.all<{ cnt: number }>(query)\n\t\treturn rows[0]?.cnt ?? 0\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true\n\t}\n\n\tasync exportBackup(): Promise<Uint8Array> {\n\t\tthis.assertOpen()\n\n\t\tconst { buildServerBackup } = await import('./server-backup')\n\t\t// Export in delivery-sequence (commit) order so a restore reassigns delivery\n\t\t// sequences causally; an implicit scan order must not be relied on.\n\t\tconst rows = this.db.select().from(operations).orderBy(asc(operations.deliverySeq)).all()\n\t\tconst deserialized = rows.map((row) => this.deserializeOperation(row))\n\t\tconst vv = this.getVersionVector()\n\n\t\treturn buildServerBackup(this.nodeId, deserialized, vv)\n\t}\n\n\tasync importBackup(\n\t\tdata: Uint8Array,\n\t\tmerge?: boolean,\n\t): Promise<{ operationsRestored: number; success: boolean }> {\n\t\tthis.assertOpen()\n\n\t\tconst { parseServerBackup } = await import('./server-backup')\n\t\tconst { operations: ops, versionVector } = parseServerBackup(data)\n\n\t\tif (merge) {\n\t\t\tlet restored = 0\n\t\t\tfor (const op of ops) {\n\t\t\t\tconst result = await this.applyRemoteOperation(op)\n\t\t\t\tif (result === 'applied') restored++\n\t\t\t}\n\t\t\treturn { operationsRestored: restored, success: true }\n\t\t}\n\n\t\t// Replace mode: DROP and recreate\n\t\tthis.db.transaction((tx) => {\n\t\t\ttx.run(sql.raw('DELETE FROM operations'))\n\t\t\ttx.run(sql.raw('DELETE FROM sync_state'))\n\t\t\ttx.update(deliveryCounter).set({ value: 0 }).where(eq(deliveryCounter.id, 1)).run()\n\n\t\t\tfor (const [nid, seq] of versionVector) {\n\t\t\t\ttx.insert(syncState)\n\t\t\t\t\t.values({ nodeId: nid, maxSequenceNumber: seq, lastSeenAt: Date.now() })\n\t\t\t\t\t.run()\n\t\t\t}\n\n\t\t\t// Re-assign delivery sequence from scratch in backup order.\n\t\t\tlet deliverySeq = 0\n\t\t\tfor (const op of ops) {\n\t\t\t\tdeliverySeq += 1\n\t\t\t\tconst row = this.serializeOperation(op, Date.now(), deliverySeq)\n\t\t\t\ttx.insert(operations).values(row).run()\n\t\t\t}\n\t\t\ttx.update(deliveryCounter).set({ value: deliverySeq }).where(eq(deliveryCounter.id, 1)).run()\n\t\t})\n\n\t\treturn { operationsRestored: ops.length, success: true }\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Materialization internals\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * Rebuild a single record in the materialized collection table by replaying\n\t * all operations for that record. Called within the applyRemoteOperation\n\t * transaction for atomic dual-write.\n\t */\n\tprivate rebuildMaterializedRecord(\n\t\ttxOrDb: BetterSQLite3Database,\n\t\tcollection: string,\n\t\trecordId: string,\n\t): void {\n\t\tconst collectionDef = this.schema?.collections[collection]\n\t\tif (!collectionDef) return\n\n\t\t// Fetch all ops for this specific record, in HLC total order (wallTime,\n\t\t// logical, nodeId) so atomic composition and LWW converge like the merge engine.\n\t\tconst ops = txOrDb\n\t\t\t.select({\n\t\t\t\ttype: operations.type,\n\t\t\t\tdata: operations.data,\n\t\t\t\tatomicOps: operations.atomicOps,\n\t\t\t\twallTime: operations.wallTime,\n\t\t\t})\n\t\t\t.from(operations)\n\t\t\t.where(and(eq(operations.collection, collection), eq(operations.recordId, recordId)))\n\t\t\t.orderBy(asc(operations.wallTime), asc(operations.logical), asc(operations.timestampNodeId))\n\t\t\t.all()\n\n\t\t// Replay to get current state\n\t\tconst parsedOps = ops.map((op) => ({\n\t\t\ttype: op.type,\n\t\t\tdata: op.data !== null ? JSON.parse(op.data) : null,\n\t\t\tatomicOps:\n\t\t\t\top.atomicOps != null ? (JSON.parse(op.atomicOps) as Record<string, AtomicOp>) : null,\n\t\t}))\n\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\tconst fieldNames = Object.keys(collectionDef.fields)\n\n\t\tif (recordData) {\n\t\t\t// Compute timestamps from operations\n\t\t\tconst createdAt = ops.length > 0 ? (ops[0] as (typeof ops)[0]).wallTime : Date.now()\n\t\t\tconst updatedAt =\n\t\t\t\tops.length > 0 ? (ops[ops.length - 1] as (typeof ops)[0]).wallTime : Date.now()\n\n\t\t\tthis.upsertMaterializedRecord(\n\t\t\t\ttxOrDb,\n\t\t\t\tcollection,\n\t\t\t\trecordId,\n\t\t\t\trecordData,\n\t\t\t\tfieldNames,\n\t\t\t\tcollectionDef,\n\t\t\t\tcreatedAt,\n\t\t\t\tupdatedAt,\n\t\t\t)\n\t\t} else {\n\t\t\t// Record was deleted — soft-delete in materialized table\n\t\t\ttxOrDb.run(\n\t\t\t\tsql`UPDATE ${sql.raw(quoteIdent(collection))} SET _deleted = 1, _updated_at = ${Date.now()} WHERE id = ${recordId}`,\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * UPSERT a record into the materialized collection table.\n\t * Uses INSERT ... ON CONFLICT (id) DO UPDATE SET for atomic upsert.\n\t */\n\tprivate upsertMaterializedRecord(\n\t\ttxOrDb: BetterSQLite3Database,\n\t\ttableName: string,\n\t\trecordId: string,\n\t\trecordData: Record<string, unknown>,\n\t\tfieldNames: string[],\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t\tcreatedAt: number,\n\t\tupdatedAt: number,\n\t): void {\n\t\tconst allColumns = ['id', ...fieldNames, '_created_at', '_updated_at', '_deleted']\n\t\tconst values: unknown[] = [\n\t\t\trecordId,\n\t\t\t...fieldNames.map((f) => {\n\t\t\t\tconst descriptor = collectionDef.fields[f]\n\t\t\t\treturn descriptor ? serializeFieldValue(recordData[f] ?? null, descriptor) : null\n\t\t\t}),\n\t\t\tcreatedAt,\n\t\t\tupdatedAt,\n\t\t\t0, // _deleted = false\n\t\t]\n\n\t\tconst columnsSql = sql.raw(allColumns.map((c) => quoteIdent(c)).join(', '))\n\t\tconst valuesSql = sql.join(\n\t\t\tvalues.map((v) => sql`${v}`),\n\t\t\tsql.raw(', '),\n\t\t)\n\t\tconst updateSet = sql.raw(\n\t\t\tallColumns\n\t\t\t\t.slice(1)\n\t\t\t\t.map((c) => `${quoteIdent(c)} = excluded.${quoteIdent(c)}`)\n\t\t\t\t.join(', '),\n\t\t)\n\n\t\ttxOrDb.run(\n\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(tableName))} (${columnsSql}) VALUES (${valuesSql}) ON CONFLICT (id) DO UPDATE SET ${updateSet}`,\n\t\t)\n\t}\n\n\t/**\n\t * Backfill all materialized collection tables from the existing operation log.\n\t * Called when setSchema() is invoked and operations already exist.\n\t */\n\tprivate async backfillAllCollections(): Promise<void> {\n\t\tif (!this.schema) return\n\n\t\tfor (const collectionName of Object.keys(this.schema.collections)) {\n\t\t\tthis.backfillCollection(collectionName)\n\t\t}\n\t}\n\n\t/**\n\t * Backfill a single collection's materialized table from operations.\n\t */\n\tprivate backfillCollection(collectionName: string): void {\n\t\tconst collectionDef = this.schema?.collections[collectionName]\n\t\tif (!collectionDef) return\n\n\t\t// Fetch all ops for this collection, in HLC total order (wallTime, logical, nodeId).\n\t\tconst allOps = this.db\n\t\t\t.select({\n\t\t\t\trecordId: operations.recordId,\n\t\t\t\ttype: operations.type,\n\t\t\t\tdata: operations.data,\n\t\t\t\tatomicOps: operations.atomicOps,\n\t\t\t\twallTime: operations.wallTime,\n\t\t\t})\n\t\t\t.from(operations)\n\t\t\t.where(eq(operations.collection, collectionName))\n\t\t\t.orderBy(asc(operations.wallTime), asc(operations.logical), asc(operations.timestampNodeId))\n\t\t\t.all()\n\n\t\tif (allOps.length === 0) return\n\n\t\t// Group by recordId\n\t\tconst grouped = new Map<string, typeof allOps>()\n\t\tfor (const op of allOps) {\n\t\t\tlet group = grouped.get(op.recordId)\n\t\t\tif (!group) {\n\t\t\t\tgroup = []\n\t\t\t\tgrouped.set(op.recordId, group)\n\t\t\t}\n\t\t\tgroup.push(op)\n\t\t}\n\n\t\t// Rebuild each record inside a single transaction for efficiency\n\t\tconst fieldNames = Object.keys(collectionDef.fields)\n\t\tthis.db.transaction((tx) => {\n\t\t\tfor (const [recordId, recordOps] of grouped) {\n\t\t\t\tconst parsedOps = recordOps.map((op) => ({\n\t\t\t\t\ttype: op.type,\n\t\t\t\t\tdata: op.data !== null ? JSON.parse(op.data) : null,\n\t\t\t\t\tatomicOps:\n\t\t\t\t\t\top.atomicOps != null ? (JSON.parse(op.atomicOps) as Record<string, AtomicOp>) : null,\n\t\t\t\t}))\n\t\t\t\tconst recordData = replayOperationsForRecord(parsedOps)\n\n\t\t\t\tif (recordData) {\n\t\t\t\t\tconst createdAt = (recordOps[0] as (typeof recordOps)[0]).wallTime\n\t\t\t\t\tconst updatedAt = (recordOps[recordOps.length - 1] as (typeof recordOps)[0]).wallTime\n\t\t\t\t\tthis.upsertMaterializedRecord(\n\t\t\t\t\t\ttx,\n\t\t\t\t\t\tcollectionName,\n\t\t\t\t\t\trecordId,\n\t\t\t\t\t\trecordData,\n\t\t\t\t\t\tfieldNames,\n\t\t\t\t\t\tcollectionDef,\n\t\t\t\t\t\tcreatedAt,\n\t\t\t\t\t\tupdatedAt,\n\t\t\t\t\t)\n\t\t\t\t} else {\n\t\t\t\t\ttx.run(\n\t\t\t\t\t\tsql`INSERT INTO ${sql.raw(quoteIdent(collectionName))} (id, _deleted, _created_at, _updated_at) VALUES (${recordId}, 1, ${Date.now()}, ${Date.now()}) ON CONFLICT (id) DO UPDATE SET _deleted = 1, _updated_at = ${Date.now()}`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Query building\n\t// ---------------------------------------------------------------------------\n\n\tprivate buildSelectQuery(collection: string, options?: CollectionQueryOptions): SQL {\n\t\tconst whereClause = this.buildWhereClause(\n\t\t\toptions?.where ?? {},\n\t\t\toptions?.includeDeleted ?? false,\n\t\t)\n\n\t\tconst parts: SQL[] = [\n\t\t\tsql`SELECT * FROM ${sql.raw(quoteIdent(collection))} WHERE ${whereClause}`,\n\t\t]\n\n\t\tif (options?.orderBy) {\n\t\t\tconst dir = options.orderDirection === 'desc' ? 'DESC' : 'ASC'\n\t\t\tparts.push(sql.raw(` ORDER BY ${quoteIdent(options.orderBy)} ${dir}`))\n\t\t}\n\n\t\tif (options?.limit !== undefined) {\n\t\t\tparts.push(sql` LIMIT ${options.limit}`)\n\t\t}\n\n\t\tif (options?.offset !== undefined) {\n\t\t\tparts.push(sql` OFFSET ${options.offset}`)\n\t\t}\n\n\t\treturn sql.join(parts, sql.raw(''))\n\t}\n\n\tprivate buildWhereClause(where: Record<string, unknown>, includeDeleted: boolean): SQL {\n\t\tconst conditions: SQL[] = []\n\n\t\tif (!includeDeleted) {\n\t\t\tconditions.push(sql.raw('_deleted = 0'))\n\t\t}\n\n\t\tfor (const [key, value] of Object.entries(where)) {\n\t\t\tconditions.push(sql`${sql.raw(quoteIdent(key))} = ${value}`)\n\t\t}\n\n\t\tif (conditions.length === 0) {\n\t\t\treturn sql.raw('1 = 1')\n\t\t}\n\n\t\treturn sql.join(conditions, sql.raw(' AND '))\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Row deserialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate deserializeRow(\n\t\trow: Record<string, unknown>,\n\t\tcollectionDef: { fields: Record<string, import('@korajs/core').FieldDescriptor> },\n\t): MaterializedRecord {\n\t\tconst record: MaterializedRecord = { id: row.id as string }\n\n\t\tfor (const [fieldName, descriptor] of Object.entries(collectionDef.fields)) {\n\t\t\tif (fieldName in row) {\n\t\t\t\trecord[fieldName] = deserializeFieldValue(row[fieldName], descriptor)\n\t\t\t}\n\t\t}\n\n\t\t// Include metadata fields\n\t\tif ('_created_at' in row) record._created_at = row._created_at\n\t\tif ('_updated_at' in row) record._updated_at = row._updated_at\n\n\t\treturn record\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Fallback materialization (operation replay, no schema)\n\t// ---------------------------------------------------------------------------\n\n\tprivate materializeFromOpsLog(collection: string): MaterializedRecord[] {\n\t\tconst rows = this.db\n\t\t\t.select()\n\t\t\t.from(operations)\n\t\t\t.where(eq(operations.collection, collection))\n\t\t\t.orderBy(asc(operations.wallTime), asc(operations.logical), asc(operations.sequenceNumber))\n\t\t\t.all()\n\n\t\tconst records = new Map<string, Record<string, unknown>>()\n\t\tconst deleted = new Set<string>()\n\n\t\tfor (const row of rows) {\n\t\t\tconst recordId = row.recordId\n\t\t\tconst data = row.data !== null ? JSON.parse(row.data) : null\n\n\t\t\tswitch (row.type) {\n\t\t\t\tcase 'insert':\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\trecords.set(recordId, { id: recordId, ...data })\n\t\t\t\t\t\tdeleted.delete(recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'update':\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\tconst existing = records.get(recordId) ?? { id: recordId }\n\t\t\t\t\t\trecords.set(recordId, { ...existing, ...data })\n\t\t\t\t\t\tdeleted.delete(recordId)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'delete':\n\t\t\t\t\tdeleted.add(recordId)\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tfor (const id of deleted) {\n\t\t\trecords.delete(id)\n\t\t}\n\n\t\treturn Array.from(records.values()) as MaterializedRecord[]\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Table setup\n\t// ---------------------------------------------------------------------------\n\n\t/**\n\t * Create the operations and sync_state tables if they don't exist.\n\t */\n\tprivate ensureTables(): void {\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS operations (\n\t\t\t\tid TEXT PRIMARY KEY,\n\t\t\t\tnode_id TEXT NOT NULL,\n\t\t\t\ttype TEXT NOT NULL,\n\t\t\t\tcollection TEXT NOT NULL,\n\t\t\t\trecord_id TEXT NOT NULL,\n\t\t\t\tdata TEXT,\n\t\t\t\tprevious_data TEXT,\n\t\t\t\tatomic_ops TEXT,\n\t\t\t\twall_time INTEGER NOT NULL,\n\t\t\t\tlogical INTEGER NOT NULL,\n\t\t\t\ttimestamp_node_id TEXT NOT NULL,\n\t\t\t\tsequence_number INTEGER NOT NULL,\n\t\t\t\tcausal_deps TEXT NOT NULL DEFAULT '[]',\n\t\t\t\tschema_version INTEGER NOT NULL,\n\t\t\t\treceived_at INTEGER NOT NULL\n\t\t\t)\n\t\t`)\n\n\t\t// Backward-compatible migration: add atomic_ops to operation logs created\n\t\t// before atomic-op persistence. Nullable, so existing rows read as \"no atomic\n\t\t// ops\" and keep materializing by last-write-wins exactly as before. SQLite has\n\t\t// no ADD COLUMN IF NOT EXISTS, so tolerate the duplicate-column error on re-run.\n\t\ttry {\n\t\t\tthis.db.run(sql`ALTER TABLE operations ADD COLUMN atomic_ops TEXT`)\n\t\t} catch (e) {\n\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\t\t// Backward-compatible migration: add the delivery_seq column for the gap-free\n\t\t// delivery watermark. SQLite has no ADD COLUMN IF NOT EXISTS, so tolerate the\n\t\t// duplicate-column error on re-run.\n\t\ttry {\n\t\t\tthis.db.run(sql`ALTER TABLE operations ADD COLUMN delivery_seq INTEGER`)\n\t\t} catch (e) {\n\t\t\tconst msg = e instanceof Error ? e.message : ''\n\t\t\tconst causeMsg = e instanceof Error && e.cause instanceof Error ? e.cause.message : ''\n\t\t\tif (!msg.includes('duplicate column') && !causeMsg.includes('duplicate column')) {\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_node_seq ON operations (node_id, sequence_number)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_delivery_seq ON operations (delivery_seq)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE UNIQUE INDEX IF NOT EXISTS idx_delivery_seq_unique\n\t\t\tON operations (delivery_seq)\n\t\t\tWHERE delivery_seq IS NOT NULL\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_collection ON operations (collection)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_received ON operations (received_at)\n\t\t`)\n\n\t\t// Index for efficient per-record operation lookups during materialization\n\t\tthis.db.run(sql`\n\t\t\tCREATE INDEX IF NOT EXISTS idx_collection_record ON operations (collection, record_id)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS sync_state (\n\t\t\t\tnode_id TEXT PRIMARY KEY,\n\t\t\t\tmax_sequence_number INTEGER NOT NULL,\n\t\t\t\tlast_seen_at INTEGER NOT NULL\n\t\t\t)\n\t\t`)\n\n\t\tthis.db.run(sql`\n\t\t\tCREATE TABLE IF NOT EXISTS delivery_counter (\n\t\t\t\tid INTEGER PRIMARY KEY,\n\t\t\t\tvalue INTEGER NOT NULL\n\t\t\t)\n\t\t`)\n\n\t\tthis.backfillDeliverySequence()\n\t}\n\n\t/**\n\t * Assign delivery sequences to any operations written before the column existed,\n\t * then seed the durable counter from the current max. Ordered by\n\t * (received_at, sequence_number, id) so the backfill is deterministic and stable\n\t * across restarts. A one-time migration: after it runs, all rows have a value.\n\t */\n\tprivate backfillDeliverySequence(): void {\n\t\tthis.db.transaction((tx) => {\n\t\t\tconst maxRow = tx.all<{ m: number | null }>(\n\t\t\t\tsql`SELECT MAX(delivery_seq) AS m FROM operations`,\n\t\t\t)\n\t\t\tlet next = maxRow[0]?.m ?? 0\n\t\t\tconst nullRows = tx.all<{ id: string }>(\n\t\t\t\tsql`SELECT id FROM operations WHERE delivery_seq IS NULL ORDER BY received_at ASC, sequence_number ASC, id ASC`,\n\t\t\t)\n\t\t\tfor (const row of nullRows) {\n\t\t\t\tnext += 1\n\t\t\t\ttx.run(sql`UPDATE operations SET delivery_seq = ${next} WHERE id = ${row.id}`)\n\t\t\t}\n\t\t\ttx.insert(deliveryCounter)\n\t\t\t\t.values({ id: 1, value: next })\n\t\t\t\t.onConflictDoUpdate({\n\t\t\t\t\ttarget: deliveryCounter.id,\n\t\t\t\t\tset: {\n\t\t\t\t\t\tvalue: sql`MAX(${deliveryCounter.value}, ${next})`,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\t.run()\n\t\t})\n\t}\n\n\t/**\n\t * Reserve the next delivery sequence inside the append transaction. SQLite locks\n\t * the database for the write transaction, and this counter row keeps sequence\n\t * allocation shared by every SqliteServerStore instance using the same file.\n\t */\n\tprivate nextDeliverySeq(tx: BetterSQLite3Database): number {\n\t\tconst rows = tx\n\t\t\t.update(deliveryCounter)\n\t\t\t.set({ value: sql`${deliveryCounter.value} + 1` })\n\t\t\t.where(eq(deliveryCounter.id, 1))\n\t\t\t.returning({ value: deliveryCounter.value })\n\t\t\t.all()\n\t\tconst value = rows[0]?.value\n\t\tif (value === undefined || value === null) {\n\t\t\tthrow new Error(\n\t\t\t\t'delivery_counter row (id=1) is missing; the operations log cannot assign delivery sequences',\n\t\t\t)\n\t\t}\n\t\treturn value\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Operation serialization\n\t// ---------------------------------------------------------------------------\n\n\tprivate serializeOperation(\n\t\top: Operation,\n\t\treceivedAt: number,\n\t\tdeliverySeq: number,\n\t): typeof operations.$inferInsert {\n\t\treturn {\n\t\t\tid: op.id,\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 !== null ? JSON.stringify(op.data) : null,\n\t\t\tpreviousData: op.previousData !== null ? JSON.stringify(op.previousData) : null,\n\t\t\tatomicOps:\n\t\t\t\top.atomicOps && Object.keys(op.atomicOps).length > 0 ? JSON.stringify(op.atomicOps) : null,\n\t\t\twallTime: op.timestamp.wallTime,\n\t\t\tlogical: op.timestamp.logical,\n\t\t\ttimestampNodeId: op.timestamp.nodeId,\n\t\t\tsequenceNumber: op.sequenceNumber,\n\t\t\tcausalDeps: JSON.stringify(op.causalDeps),\n\t\t\tschemaVersion: op.schemaVersion,\n\t\t\treceivedAt,\n\t\t\tdeliverySeq,\n\t\t}\n\t}\n\n\tprivate deserializeOperation(row: typeof operations.$inferSelect): Operation {\n\t\tconst atomicOps =\n\t\t\trow.atomicOps != null ? (JSON.parse(row.atomicOps) as Record<string, AtomicOp>) : undefined\n\t\treturn {\n\t\t\tid: row.id,\n\t\t\tnodeId: row.nodeId,\n\t\t\ttype: row.type as Operation['type'],\n\t\t\tcollection: row.collection,\n\t\t\trecordId: row.recordId,\n\t\t\tdata: row.data !== null ? JSON.parse(row.data) : null,\n\t\t\tpreviousData: row.previousData !== null ? JSON.parse(row.previousData) : null,\n\t\t\ttimestamp: {\n\t\t\t\twallTime: row.wallTime,\n\t\t\t\tlogical: row.logical,\n\t\t\t\tnodeId: row.timestampNodeId,\n\t\t\t},\n\t\t\tsequenceNumber: row.sequenceNumber,\n\t\t\tcausalDeps: JSON.parse(row.causalDeps),\n\t\t\tschemaVersion: row.schemaVersion,\n\t\t\t...(atomicOps ? { atomicOps } : {}),\n\t\t}\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Assertions\n\t// ---------------------------------------------------------------------------\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) {\n\t\t\tthrow new Error('SqliteServerStore is closed')\n\t\t}\n\t}\n\n\tprivate assertSchema(): void {\n\t\tif (!this.schema) {\n\t\t\tthrow new Error(\n\t\t\t\t'Schema not set. Call setSchema() before using queryCollection/findRecord/countCollection.',\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate assertCollection(collection: string): void {\n\t\tconst schema = this.schema as SchemaDefinition\n\t\tif (!schema.collections[collection]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown collection \"${collection}\". Available: ${Object.keys(schema.collections).join(', ')}`,\n\t\t\t)\n\t\t}\n\t}\n}\n\n/**\n * Creates a SqliteServerStore with a file-backed or in-memory database.\n * Handles database creation, Drizzle wrapping, and table setup.\n *\n * @param options - Configuration options\n * @param options.filename - Path to SQLite database file. Defaults to ':memory:' for testing.\n * @param options.nodeId - Server node ID. Auto-generated if not provided.\n * @returns A ready-to-use SqliteServerStore\n *\n * @example\n * ```typescript\n * import { createSqliteServerStore } from '@korajs/server'\n *\n * const store = createSqliteServerStore({ filename: './kora-server.db' })\n *\n * // Optional: enable materialized collection tables for fast queries\n * await store.setSchema(mySchema)\n *\n * const server = createKoraServer({ store, port: 3001 })\n * ```\n */\nexport function createSqliteServerStore(options: {\n\tfilename?: string\n\tnodeId?: string\n}): SqliteServerStore {\n\t// better-sqlite3 is a native CJS addon — use esmRequire (from createRequire)\n\t// so this works in both ESM and CJS contexts.\n\tconst Database = esmRequire('better-sqlite3')\n\tconst { drizzle } = esmRequire('drizzle-orm/better-sqlite3')\n\n\tconst filename = options.filename ?? ':memory:'\n\tconst sqlite = new Database(filename)\n\n\t// Enable WAL mode for better concurrent read/write performance\n\tsqlite.pragma('journal_mode = WAL')\n\n\tconst db = drizzle(sqlite)\n\treturn new SqliteServerStore(db, options.nodeId)\n}\n","import { index, integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'\n\n/**\n * Drizzle schema for the Kora sync server's SQLite database.\n *\n * Two tables:\n * - `operations` — the append-only operation log (content-addressed by id)\n * - `syncState` — tracks the max sequence number seen per node (version vector)\n */\n\nexport const operations = sqliteTable(\n\t'operations',\n\t{\n\t\tid: text('id').primaryKey(),\n\t\tnodeId: text('node_id').notNull(),\n\t\ttype: text('type').notNull(),\n\t\tcollection: text('collection').notNull(),\n\t\trecordId: text('record_id').notNull(),\n\t\tdata: text('data'), // JSON-serialized, null for deletes\n\t\tpreviousData: text('previous_data'), // JSON-serialized, null for insert/delete\n\t\tatomicOps: text('atomic_ops'), // JSON-serialized Record<field, AtomicOp>, null when none\n\t\twallTime: integer('wall_time').notNull(),\n\t\tlogical: integer('logical').notNull(),\n\t\ttimestampNodeId: text('timestamp_node_id').notNull(),\n\t\tsequenceNumber: integer('sequence_number').notNull(),\n\t\tcausalDeps: text('causal_deps').notNull().default('[]'), // JSON array of op IDs\n\t\tschemaVersion: integer('schema_version').notNull(),\n\t\treceivedAt: integer('received_at').notNull(),\n\t\t// Server-assigned monotonic delivery sequence, ordered by commit. Drives the\n\t\t// gap-free server->client delivery watermark. Nullable only for rows written\n\t\t// before the column existed; those are backfilled on startup.\n\t\tdeliverySeq: integer('delivery_seq'),\n\t},\n\t(table) => ({\n\t\tnodeSeqIdx: index('idx_node_seq').on(table.nodeId, table.sequenceNumber),\n\t\tcollectionIdx: index('idx_collection').on(table.collection),\n\t\treceivedIdx: index('idx_received').on(table.receivedAt),\n\t\tdeliveryIdx: index('idx_delivery_seq').on(table.deliverySeq),\n\t}),\n)\n\nexport const syncState = sqliteTable('sync_state', {\n\tnodeId: text('node_id').primaryKey(),\n\tmaxSequenceNumber: integer('max_sequence_number').notNull(),\n\tlastSeenAt: integer('last_seen_at').notNull(),\n})\n\nexport const deliveryCounter = sqliteTable('delivery_counter', {\n\tid: integer('id').primaryKey(),\n\tvalue: integer('value').notNull(),\n})\n","import { SyncError } from '@korajs/core'\nimport type { MessageSerializer } from '@korajs/sync'\nimport type {\n\tServerCloseHandler,\n\tServerErrorHandler,\n\tServerMessageHandler,\n\tServerTransport,\n} from './server-transport'\n\nexport interface HttpPollResponse {\n\tstatus: 200 | 204 | 304 | 410\n\tbody?: string | Uint8Array\n\theaders?: Record<string, string>\n}\n\ninterface QueuedMessage {\n\tetag: string\n\tcontentType: string\n\tpayload: string | Uint8Array\n}\n\n/**\n * Server-side transport for HTTP long-polling clients.\n *\n * Incoming client messages are pushed via POST, while outbound server\n * messages are pulled via GET long-poll requests.\n */\nexport class HttpServerTransport implements ServerTransport {\n\tprivate readonly serializer: MessageSerializer\n\n\tprivate messageHandler: ServerMessageHandler | null = null\n\tprivate closeHandler: ServerCloseHandler | null = null\n\tprivate errorHandler: ServerErrorHandler | null = null\n\n\tprivate connected = true\n\tprivate nextSequence = 1\n\tprivate readonly queue: QueuedMessage[] = []\n\n\tconstructor(serializer: MessageSerializer) {\n\t\tthis.serializer = serializer\n\t}\n\n\tsend(message: import('@korajs/sync').SyncMessage): void {\n\t\tif (!this.connected) return\n\n\t\tconst encoded = this.serializer.encode(message)\n\t\tconst isBinary = encoded instanceof Uint8Array\n\t\tthis.queue.push({\n\t\t\tetag: this.makeEtag(this.nextSequence++),\n\t\t\tcontentType: isBinary ? 'application/x-protobuf' : 'application/json',\n\t\t\tpayload: encoded,\n\t\t})\n\t}\n\n\tonMessage(handler: ServerMessageHandler): void {\n\t\tthis.messageHandler = handler\n\t}\n\n\tonClose(handler: ServerCloseHandler): void {\n\t\tthis.closeHandler = handler\n\t}\n\n\tonError(handler: ServerErrorHandler): void {\n\t\tthis.errorHandler = handler\n\t}\n\n\tisConnected(): boolean {\n\t\treturn this.connected\n\t}\n\n\tclose(code = 1000, reason = 'transport closed'): void {\n\t\tif (!this.connected) return\n\t\tthis.connected = false\n\t\tthis.queue.length = 0\n\t\tthis.closeHandler?.(code, reason)\n\t}\n\n\treceive(payload: string | Uint8Array): void {\n\t\tif (!this.connected) {\n\t\t\tthrow new SyncError('HTTP server transport is closed')\n\t\t}\n\n\t\ttry {\n\t\t\tconst message = this.serializer.decode(payload)\n\t\t\tthis.messageHandler?.(message)\n\t\t} catch (error) {\n\t\t\tthis.errorHandler?.(error instanceof Error ? error : new Error(String(error)))\n\t\t}\n\t}\n\n\tpoll(ifNoneMatch?: string): HttpPollResponse {\n\t\tif (!this.connected) {\n\t\t\treturn { status: 410 }\n\t\t}\n\n\t\tconst next = this.queue[0]\n\t\tif (!next) {\n\t\t\treturn { status: 204 }\n\t\t}\n\n\t\tif (ifNoneMatch && ifNoneMatch === next.etag) {\n\t\t\treturn {\n\t\t\t\tstatus: 304,\n\t\t\t\theaders: { etag: next.etag },\n\t\t\t}\n\t\t}\n\n\t\tthis.queue.shift()\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\tbody: next.payload,\n\t\t\theaders: {\n\t\t\t\t'content-type': next.contentType,\n\t\t\t\tetag: next.etag,\n\t\t\t},\n\t\t}\n\t}\n\n\tprivate makeEtag(sequence: number): string {\n\t\treturn `W/\"${sequence}\"`\n\t}\n}\n","import { SyncError } from '@korajs/core'\nimport type { SyncMessage } from '@korajs/sync'\nimport { JsonMessageSerializer } from '@korajs/sync'\nimport type { MessageSerializer } from '@korajs/sync'\nimport type {\n\tServerCloseHandler,\n\tServerErrorHandler,\n\tServerMessageHandler,\n\tServerTransport,\n} from './server-transport'\n\n/** WebSocket ready states (mirrors ws constants) */\nconst WS_OPEN = 1\n\n/**\n * Minimal interface for a ws.WebSocket instance.\n * Allows dependency injection for testing without importing ws directly.\n */\nexport interface WsWebSocket {\n\treadyState: number\n\tsend(data: string | Uint8Array, callback?: (err?: Error) => void): void\n\tclose(code?: number, reason?: string): void\n\ton(event: string, listener: (...args: unknown[]) => void): void\n\tremoveAllListeners(): void\n}\n\n/**\n * Options for WsServerTransport.\n */\nexport interface WsServerTransportOptions {\n\t/** Message serializer. Defaults to JsonMessageSerializer. */\n\tserializer?: MessageSerializer\n}\n\n/**\n * Server-side transport wrapping a ws.WebSocket connection.\n * Created for each incoming client connection.\n */\nexport class WsServerTransport implements ServerTransport {\n\tprivate readonly ws: WsWebSocket\n\tprivate readonly serializer: MessageSerializer\n\tprivate messageHandler: ServerMessageHandler | null = null\n\tprivate closeHandler: ServerCloseHandler | null = null\n\tprivate errorHandler: ServerErrorHandler | null = null\n\n\tconstructor(ws: WsWebSocket, options?: WsServerTransportOptions) {\n\t\tthis.ws = ws\n\t\tthis.serializer = options?.serializer ?? new JsonMessageSerializer()\n\t\tthis.setupListeners()\n\t}\n\n\tsend(message: SyncMessage): void {\n\t\tif (this.ws.readyState !== WS_OPEN) {\n\t\t\tthrow new SyncError('Cannot send message: WebSocket is not open', {\n\t\t\t\treadyState: this.ws.readyState,\n\t\t\t\tmessageType: message.type,\n\t\t\t})\n\t\t}\n\n\t\tconst encoded = this.serializer.encode(message)\n\t\tthis.ws.send(encoded)\n\t}\n\n\tonMessage(handler: ServerMessageHandler): void {\n\t\tthis.messageHandler = handler\n\t}\n\n\tonClose(handler: ServerCloseHandler): void {\n\t\tthis.closeHandler = handler\n\t}\n\n\tonError(handler: ServerErrorHandler): void {\n\t\tthis.errorHandler = handler\n\t}\n\n\tisConnected(): boolean {\n\t\treturn this.ws.readyState === WS_OPEN\n\t}\n\n\tclose(code?: number, reason?: string): void {\n\t\tthis.ws.close(code ?? 1000, reason ?? 'server closing')\n\t}\n\n\tprivate setupListeners(): void {\n\t\tthis.ws.on('message', (data: unknown) => {\n\t\t\ttry {\n\t\t\t\tif (\n\t\t\t\t\ttypeof data !== 'string' &&\n\t\t\t\t\t!(data instanceof Uint8Array) &&\n\t\t\t\t\t!(data instanceof ArrayBuffer)\n\t\t\t\t) {\n\t\t\t\t\tthrow new SyncError('Unsupported WebSocket payload type', {\n\t\t\t\t\t\tpayloadType: typeof data,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tconst decoded = this.serializer.decode(data)\n\t\t\t\tthis.messageHandler?.(decoded)\n\t\t\t} catch (err) {\n\t\t\t\tthis.errorHandler?.(err instanceof Error ? err : new Error(String(err)))\n\t\t\t}\n\t\t})\n\n\t\tthis.ws.on('close', (code: unknown, reason: unknown) => {\n\t\t\tthis.closeHandler?.(Number(code) || 1006, String(reason || 'connection closed'))\n\t\t})\n\n\t\tthis.ws.on('error', (err: unknown) => {\n\t\t\tthis.errorHandler?.(err instanceof Error ? err : new Error(String(err)))\n\t\t})\n\t}\n}\n","import type {\n\tKoraEventEmitter,\n\tOperation,\n\tOperationTransform,\n\tSchemaDefinition,\n} from '@korajs/core'\nimport { applyOperationTransforms } from '@korajs/core'\nimport { SyncError, generateUUIDv7, hashBlob } from '@korajs/core'\nimport { topologicalSort } from '@korajs/core/internal'\nimport type {\n\tAwarenessUpdateMessage,\n\tBlobChunkPushMessage,\n\tBlobChunkRequestMessage,\n\tBlobChunkResponseMessage,\n\tHandshakeMessage,\n\tMessageSerializer,\n\tOperationBatchMessage,\n\tSyncMessage,\n\tWireFormat,\n\tYjsDocUpdateMessage,\n} from '@korajs/sync'\nimport { decodeBlobChunkBytes } from '@korajs/sync'\nimport {\n\ttype DeltaCursor,\n\tNegotiatedMessageSerializer,\n\tSCHEMA_MISMATCH_PREFIX,\n\ttype SyncQuerySubset,\n\tcreateDeltaCursorFromBatch,\n\tdecodeDeltaCursor,\n\tdedupeQuerySubsets,\n\tencodeDeltaCursor,\n\tisClientSchemaVersionSupported,\n\toperationMatchesQuerySubsets,\n\tsliceOperationsAfterCursor,\n\tversionVectorToWire,\n\twireToVersionVector,\n} from '@korajs/sync'\nimport { applyServerOperation } from '../apply/apply-server-operation'\nimport type { OperationValidator } from '../apply/operation-validator'\nimport { isRetriableRejection } from '../apply/rejection-taxonomy'\nimport { NoAuthProvider } from '../auth/no-auth'\nimport type { Logger } from '../logging/structured-logger'\nimport { resolveSessionScopes } from '../scopes/resolve-session-scopes'\nimport {\n\tmissingScopeFields,\n\tnormalizeScopeMap,\n\toperationExitsScopes,\n\toperationMatchesScopes,\n} from '../scopes/server-scope-filter'\nimport type { ProductionHttpRouteContext } from '../server/route-context'\nimport type { DeliveredOperation, ServerStore } from '../store/server-store'\nimport type { ServerTransport } from '../transport/server-transport'\nimport type { AuthContext, AuthProvider } from '../types'\nimport { isOperationTimestampValid } from './operation-validation'\nimport {\n\tDEFAULT_MAX_OPERATION_BYTES,\n\tDEFAULT_MAX_OPS_PER_MINUTE,\n\tSessionRateLimiter,\n\tvalidateOperationSize,\n} from './session-operation-limits'\n\nconst DEFAULT_BATCH_SIZE = 100\nconst DEFAULT_SCHEMA_VERSION = 1\n\n/**\n * Tracks auth providers we have already warned about, so the multi-tenant\n * no-scopes guardrail fires once per server (keyed by provider instance)\n * rather than once per client connection.\n */\nconst warnedUnscopedProviders = new WeakSet<AuthProvider>()\n\n/**\n * Warn once when a real (multi-user) auth provider is configured but an\n * authenticated session resolves to no sync scopes at all.\n *\n * With no scopes, `operationMatchesScopes` treats every operation as visible,\n * which is the correct zero-config behavior for a single-user local-first app.\n * But once a real auth provider is in play, \"no scopes\" means every user syncs\n * every other user's data — a silent cross-tenant data exposure. We cannot flip\n * the default to deny-all without breaking the zero-config promise, so instead\n * we surface the dangerous configuration loudly and exactly once.\n *\n * `null` auth (local-first, no auth) and `NoAuthProvider` (dev/testing) are\n * intentionally excluded: for those, unscoped sync is the intended behavior.\n */\nfunction warnIfMultiTenantWithoutScopes(\n\tauth: AuthProvider | null,\n\tresolvedScopes: unknown,\n\tschema: SchemaDefinition | null,\n): void {\n\tif (!auth || auth instanceof NoAuthProvider) {\n\t\treturn\n\t}\n\tif (resolvedScopes) {\n\t\treturn\n\t}\n\tif (!schema || Object.keys(schema.collections).length === 0) {\n\t\treturn\n\t}\n\tif (warnedUnscopedProviders.has(auth)) {\n\t\treturn\n\t}\n\twarnedUnscopedProviders.add(auth)\n\tconsole.warn(\n\t\t'[kora] An authenticated session resolved to no sync scopes, so every ' +\n\t\t\t\"user will sync every other user's data. Return per-user sync scopes \" +\n\t\t\t\"from your auth provider (for example KoraAuthProvider's resolveScopes) \" +\n\t\t\t'to isolate tenants. Note: declaring sync rules in your schema is not ' +\n\t\t\t'enough on its own — the per-user values come from the auth provider. ' +\n\t\t\t'(This warning is expected for single-tenant apps where all authenticated ' +\n\t\t\t'users are meant to share the same data.)',\n\t)\n}\n\nfunction stableStringify(value: unknown): string {\n\tif (Array.isArray(value)) {\n\t\treturn `[${value.map((item) => stableStringify(item)).join(',')}]`\n\t}\n\tif (value && typeof value === 'object') {\n\t\tconst record = value as Record<string, unknown>\n\t\tconst entries = Object.keys(record)\n\t\t\t.sort()\n\t\t\t.map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`)\n\t\treturn `{${entries.join(',')}}`\n\t}\n\treturn JSON.stringify(value)\n}\n\nfunction sameScopeMap(a: unknown, b: unknown): boolean {\n\tconst normalize = (value: unknown): unknown =>\n\t\tvalue && typeof value === 'object'\n\t\t\t? normalizeScopeMap(value as Record<string, Record<string, unknown>>)\n\t\t\t: value\n\treturn stableStringify(normalize(a) ?? null) === stableStringify(normalize(b) ?? null)\n}\n\n/**\n * Possible states for a client session.\n */\nexport type SessionState = 'connected' | 'authenticated' | 'syncing' | 'streaming' | 'closed'\n\n/**\n * Callback invoked when a session has new operations to relay to other sessions.\n */\nexport type RelayCallback = (sourceSessionId: string, operations: Operation[]) => void\n\n/**\n * Callback invoked when a session receives an awareness update to relay to other sessions.\n */\nexport type AwarenessRelayCallback = (\n\tsourceSessionId: string,\n\tmessage: AwarenessUpdateMessage,\n) => void\n\n/**\n * Callback invoked when a session receives a Yjs doc channel update to relay.\n */\nexport type YjsDocRelayCallback = (sourceSessionId: string, message: YjsDocUpdateMessage) => void\n\n/**\n * Callback invoked when a session receives a blob chunk request to route.\n */\nexport type BlobChunkRequestCallback = (\n\tsourceSessionId: string,\n\tmessage: BlobChunkRequestMessage,\n) => void\n\n/**\n * Callback invoked when a session receives a blob chunk response to route back.\n */\nexport type BlobChunkResponseCallback = (\n\tsourceSessionId: string,\n\tmessage: BlobChunkResponseMessage,\n) => void\n\n/**\n * Persist a blob chunk (or manifest) uploaded by a client, keyed by its content\n * hash. Provided by the server operator; enables central blob storage so bytes\n * survive the authoring device going offline.\n */\nexport type PersistBlobChunk = (hash: string, bytes: Uint8Array) => Promise<void> | void\n\n/**\n * Options for creating a ClientSession.\n */\nexport interface ClientSessionOptions {\n\t/** Unique session identifier */\n\tsessionId: string\n\t/** Transport for this client connection */\n\ttransport: ServerTransport\n\t/** Server-side operation store */\n\tstore: ServerStore\n\t/** Authentication provider (optional) */\n\tauth?: AuthProvider\n\t/** Message serializer */\n\tserializer?: MessageSerializer\n\t/** Event emitter for DevTools integration */\n\temitter?: KoraEventEmitter\n\t/** Structured logger used for protocol and persistence failures */\n\tlogger?: Logger\n\t/** Max operations per sync batch */\n\tbatchSize?: number\n\t/** Schema version the server expects */\n\tschemaVersion?: number\n\t/** Inclusive client schema versions accepted at handshake */\n\tsupportedSchemaVersions?: { min: number; max: number }\n\t/** Transform accepted legacy operations into the server schema before validation. */\n\toperationTransforms?: OperationTransform[]\n\t/** Called when this session has operations to relay to other sessions */\n\tonRelay?: RelayCallback\n\t/** Called when this session receives an awareness update to broadcast */\n\tonAwarenessUpdate?: AwarenessRelayCallback\n\t/** Called when this session receives a Yjs doc channel update to broadcast */\n\tonYjsDocUpdate?: YjsDocRelayCallback\n\t/** Called when this session receives a blob chunk request to route */\n\tonBlobChunkRequest?: BlobChunkRequestCallback\n\t/** Called when this session receives a blob chunk response to route back */\n\tonBlobChunkResponse?: BlobChunkResponseCallback\n\t/** Persist a client-uploaded blob chunk centrally (keyed by content hash) */\n\tpersistBlobChunk?: PersistBlobChunk\n\t/** Called when this session closes */\n\tonClose?: (sessionId: string) => void\n\t/**\n\t * Called on close with relay operations this client never acknowledged, so the\n\t * server can buffer them per node id and redeliver on the client's next\n\t * connection. Closes the window where a relay dropped just before a reconnect\n\t * would otherwise be lost (the per-session retransmit tick never fires in time).\n\t */\n\tonOrphanedRelays?: (nodeId: string, ops: Operation[]) => void\n\t/**\n\t * Called once this session reaches streaming to pull any relay operations buffered\n\t * for its node id while it was disconnected. They are re-sent through the normal\n\t * relay path (re-filtered by this session's current scope).\n\t */\n\ttakeOrphanedRelays?: (nodeId: string) => Operation[]\n\t/** Maximum serialized operation size in bytes. Defaults to 256 KiB. */\n\tmaxOperationBytes?: number\n\t/** Maximum operations accepted per minute for this session. Defaults to 600. */\n\tmaxOpsPerMinute?: number\n\t/**\n\t * Adjudicate untrusted client operations before materialization. When present,\n\t * each incoming operation is passed to this validator; a `reject` decision\n\t * sends an operation-rejected message and skips materialization.\n\t */\n\tvalidateOperation?: OperationValidator\n\t/** Trusted data-plane context handed to the validator (read state, author derived ops). */\n\tkoraContext?: ProductionHttpRouteContext\n}\n\n/**\n * Handles the sync protocol for a single connected client.\n *\n * Lifecycle: connected → (authenticated) → syncing → streaming → closed\n *\n * The session:\n * 1. Receives a handshake from the client\n * 2. Authenticates if an AuthProvider is configured\n * 3. Sends back a HandshakeResponse with the server's version vector\n * 4. Computes and sends the server's delta to the client (paginated)\n * 5. Processes incoming operation batches from the client\n * 6. Transitions to streaming for real-time bidirectional sync\n * 7. Relays new operations to other sessions via the RelayCallback\n */\nexport class ClientSession {\n\tprivate state: SessionState = 'connected'\n\tprivate clientNodeId: string | null = null\n\tprivate authContext: AuthContext | null = null\n\tprivate syncQuerySubsets: SyncQuerySubset[] = []\n\tprivate scopeExitPolicy: 'retain' | 'retract' = 'retain'\n\tprivate resumeDeltaCursor: DeltaCursor | null = null\n\n\t/**\n\t * The delivery watermark the client reported at handshake, or null when the client\n\t * does not use the delivery watermark (old client, or no watermark yet). When set,\n\t * the server drives the gap-free server->client stream from delivery sequences\n\t * instead of the version-vector delta.\n\t */\n\tprivate clientDeliveryWatermark: number | null = null\n\t/**\n\t * The highest delivery sequence this client has ACKNOWLEDGED (its confirmed\n\t * watermark, as reported in acks). Incremental streaming pushes resume from here, not\n\t * from the highest sequence sent, so a dropped or unapplied batch is always\n\t * re-included by the next push (which re-scans from the acknowledged position). This\n\t * is what makes streaming recovery independent of any bounded retransmit buffer: there\n\t * is no sent-but-unacked window that a buffer eviction could strand. Seeded from the\n\t * client's reported watermark at handshake.\n\t */\n\tprivate lastAckedDeliverySeq = 0\n\t/**\n\t * Timestamp of the last delivery-stream send attempt. Periodic retransmission uses\n\t * this as its stale window so a slow client does not receive duplicate full-stream\n\t * batches every server tick while the first batch is still being applied.\n\t */\n\tprivate lastDeliveryPushAttemptAtMs = 0\n\tprivate outstandingDelivery: {\n\t\tbase: number\n\t\tmax: number\n\t\tsentAtMs: number\n\t\trepeatCount: number\n\t} | null = null\n\t/** Serializes incremental delivery pushes so their batches never interleave. */\n\tprivate deliveryPushChain: Promise<void> = Promise.resolve()\n\n\t/**\n\t * Relay batches sent to this client but not yet acknowledged, keyed by messageId.\n\t * The client acks every operation-batch it applies; on ack the entry is cleared.\n\t * {@link retransmitPendingRelays} re-sends anything still unacked, so a relay\n\t * dropped by a lossy transport is redelivered instead of leaving the client with a\n\t * permanent version-vector gap (a lost operation) that delta sync cannot recover.\n\t * Bounded so a silent client cannot grow it without limit.\n\t */\n\tprivate readonly pendingRelays = new Map<\n\t\tstring,\n\t\t{ message: SyncMessage; ops: Operation[]; sentAtMs: number }\n\t>()\n\tprivate static readonly MAX_PENDING_RELAYS = 1000\n\n\tprivate readonly sessionId: string\n\tprivate readonly transport: ServerTransport\n\tprivate readonly store: ServerStore\n\tprivate readonly auth: AuthProvider | null\n\tprivate readonly serializer: MessageSerializer\n\tprivate readonly emitter: KoraEventEmitter | null\n\tprivate readonly logger: Logger | null\n\tprivate readonly batchSize: number\n\tprivate readonly schemaVersion: number\n\tprivate readonly supportedSchemaVersions: { min: number; max: number }\n\tprivate readonly operationTransforms: OperationTransform[]\n\tprivate readonly onRelay: RelayCallback | null\n\tprivate readonly onAwarenessUpdate: AwarenessRelayCallback | null\n\tprivate readonly onYjsDocUpdate: YjsDocRelayCallback | null\n\tprivate readonly onBlobChunkRequest: BlobChunkRequestCallback | null\n\tprivate readonly onBlobChunkResponse: BlobChunkResponseCallback | null\n\tprivate readonly persistBlobChunk: PersistBlobChunk | null\n\tprivate readonly onClose: ((sessionId: string) => void) | null\n\tprivate readonly onOrphanedRelays: ((nodeId: string, ops: Operation[]) => void) | null\n\tprivate readonly takeOrphanedRelays: ((nodeId: string) => Operation[]) | null\n\tprivate readonly maxOperationBytes: number\n\tprivate readonly maxOpsPerMinute: number\n\tprivate readonly rateLimiter: SessionRateLimiter\n\tprivate readonly validateOperation: OperationValidator | null\n\tprivate readonly koraContext: ProductionHttpRouteContext | null\n\n\tconstructor(options: ClientSessionOptions) {\n\t\tthis.sessionId = options.sessionId\n\t\tthis.transport = options.transport\n\t\tthis.store = options.store\n\t\tthis.auth = options.auth ?? null\n\t\tthis.serializer = options.serializer ?? new NegotiatedMessageSerializer('json')\n\t\tthis.emitter = options.emitter ?? null\n\t\tthis.logger = options.logger ?? null\n\t\tthis.batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE\n\t\tthis.schemaVersion = options.schemaVersion ?? DEFAULT_SCHEMA_VERSION\n\t\tconst supported = options.supportedSchemaVersions\n\t\tthis.supportedSchemaVersions = supported ?? {\n\t\t\tmin: this.schemaVersion,\n\t\t\tmax: this.schemaVersion,\n\t\t}\n\t\tthis.operationTransforms = options.operationTransforms ?? []\n\t\tthis.onRelay = options.onRelay ?? null\n\t\tthis.onAwarenessUpdate = options.onAwarenessUpdate ?? null\n\t\tthis.onYjsDocUpdate = options.onYjsDocUpdate ?? null\n\t\tthis.onBlobChunkRequest = options.onBlobChunkRequest ?? null\n\t\tthis.onBlobChunkResponse = options.onBlobChunkResponse ?? null\n\t\tthis.persistBlobChunk = options.persistBlobChunk ?? null\n\t\tthis.onClose = options.onClose ?? null\n\t\tthis.onOrphanedRelays = options.onOrphanedRelays ?? null\n\t\tthis.takeOrphanedRelays = options.takeOrphanedRelays ?? null\n\t\tthis.maxOperationBytes = options.maxOperationBytes ?? DEFAULT_MAX_OPERATION_BYTES\n\t\tthis.maxOpsPerMinute = options.maxOpsPerMinute ?? DEFAULT_MAX_OPS_PER_MINUTE\n\t\tthis.rateLimiter = new SessionRateLimiter(this.maxOpsPerMinute)\n\t\tthis.validateOperation = options.validateOperation ?? null\n\t\tthis.koraContext = options.koraContext ?? null\n\t}\n\n\t/**\n\t * Start handling messages from the client transport.\n\t */\n\tstart(): void {\n\t\tthis.transport.onMessage((msg) => this.enqueueMessage(msg))\n\t\tthis.transport.onClose((_code, _reason) => this.handleTransportClose())\n\t\tthis.transport.onError((_err) => {\n\t\t\t// Transport errors during active session cause close\n\t\t\tif (this.state !== 'closed') {\n\t\t\t\tthis.handleTransportClose()\n\t\t\t}\n\t\t})\n\t}\n\n\t/**\n\t * Relay operations from another session to this client.\n\t * Only relays if the session is in streaming state and transport is connected.\n\t */\n\trelayOperations(operations: Operation[]): void {\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\t// A delivery-watermark client is fed by the gap-free delivery stream, resumed from\n\t\t// the last sequence sent to it, so its watermark keeps advancing live and a\n\t\t// reconnect resends only what was genuinely missed. The specific operations from\n\t\t// the fan-out are only a wake-up: the push pulls everything in scope after the send\n\t\t// cursor from the delivery log, which is the authoritative, contiguous order.\n\t\tif (this.clientDeliveryWatermark !== null) {\n\t\t\tthis.pushDeliveryStream()\n\t\t\treturn\n\t\t}\n\t\tif (operations.length === 0) return\n\t\t// Visibility now requires an async record lookup (scope/subset backfill); relay\n\t\t// is fire-and-forget, so run it without blocking the caller's fan-out loop.\n\t\tvoid this.relayVisibleOperations(operations)\n\t}\n\n\t/**\n\t * Push newly-available in-scope operations to a delivery-watermark client, resuming\n\t * from the highest delivery sequence already sent. Pushes are serialized so their\n\t * batches never interleave (which would break the base/max chain).\n\t */\n\tprivate pushDeliveryStream(options: { trackStall?: boolean } = {}): void {\n\t\tthis.deliveryPushChain = this.deliveryPushChain.then(async () => {\n\t\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\t\ttry {\n\t\t\t\tconst previous = this.outstandingDelivery\n\t\t\t\tif (options.trackStall && previous && previous.max > this.lastAckedDeliverySeq) {\n\t\t\t\t\tprevious.repeatCount += 1\n\t\t\t\t\tif (previous.repeatCount >= 3) {\n\t\t\t\t\t\tthis.emitter?.emit({\n\t\t\t\t\t\t\ttype: 'sync:delivery-stalled',\n\t\t\t\t\t\t\tsessionId: this.sessionId,\n\t\t\t\t\t\t\twatermark: this.lastAckedDeliverySeq,\n\t\t\t\t\t\t\toutstandingMaxDeliverySequence: previous.max,\n\t\t\t\t\t\t\trepeatCount: previous.repeatCount,\n\t\t\t\t\t\t\treason: 'unacknowledged-delivery',\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.lastDeliveryPushAttemptAtMs = Date.now()\n\t\t\t\t// Resume from the client's last acknowledged sequence, not the last sent, so a\n\t\t\t\t// dropped or unapplied batch is re-included here. Exclude the client's own\n\t\t\t\t// operations during streaming; it already has them.\n\t\t\t\tconst result = await this.sendDeliveryStream(\n\t\t\t\t\tthis.lastAckedDeliverySeq,\n\t\t\t\t\tfalse,\n\t\t\t\t\tthis.clientNodeId ?? undefined,\n\t\t\t\t)\n\t\t\t\tif (result.sent && result.maxScanned > this.lastAckedDeliverySeq) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!this.outstandingDelivery ||\n\t\t\t\t\t\tthis.outstandingDelivery.base !== this.lastAckedDeliverySeq ||\n\t\t\t\t\t\tthis.outstandingDelivery.max !== result.maxScanned\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.outstandingDelivery = {\n\t\t\t\t\t\t\tbase: this.lastAckedDeliverySeq,\n\t\t\t\t\t\t\tmax: result.maxScanned,\n\t\t\t\t\t\t\tsentAtMs: Date.now(),\n\t\t\t\t\t\t\trepeatCount: 0,\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.outstandingDelivery.sentAtMs = Date.now()\n\t\t\t\t\t}\n\t\t\t\t} else if (result.maxScanned <= this.lastAckedDeliverySeq) {\n\t\t\t\t\tthis.outstandingDelivery = null\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// A failed push (e.g. a transient store read error) must not reject the chain\n\t\t\t\t// and stall all future pushes. The next push, or a reconnect resend from the\n\t\t\t\t// client's watermark, recovers anything this push did not deliver.\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate async relayVisibleOperations(operations: Operation[]): Promise<void> {\n\t\tconst visibleOperations: Operation[] = []\n\t\tconst retractions: Array<{ collection: string; recordId: string }> = []\n\t\tfor (const op of operations) {\n\t\t\tif (await this.operationVisibleToClient(op)) {\n\t\t\t\tvisibleOperations.push(op)\n\t\t\t} else if (await this.scopeRetractionFor(op)) {\n\t\t\t\tretractions.push({ collection: op.collection, recordId: op.recordId })\n\t\t\t}\n\t\t}\n\t\tif (visibleOperations.length === 0 && retractions.length === 0) return\n\t\t// Re-check liveness: an await may have elapsed since the caller's guard.\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\n\t\tconst serializedOps = visibleOperations.map((op) => this.serializer.encodeOperation(op))\n\t\tconst msg: SyncMessage = {\n\t\t\ttype: 'operation-batch',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\toperations: serializedOps,\n\t\t\t...(retractions.length > 0 ? { retractions } : {}),\n\t\t\tisFinal: true,\n\t\t\tbatchIndex: 0,\n\t\t}\n\t\t// Track this relay until the client acks it, so a drop can be retransmitted.\n\t\tthis.trackPendingRelay(msg, visibleOperations)\n\t\tthis.sendToClient(msg)\n\t}\n\n\t/** Record a relay batch as awaiting acknowledgment, evicting the oldest if full. */\n\tprivate trackPendingRelay(msg: SyncMessage, ops: Operation[]): void {\n\t\tif (this.pendingRelays.size >= ClientSession.MAX_PENDING_RELAYS) {\n\t\t\tconst oldest = this.pendingRelays.keys().next().value\n\t\t\tif (oldest !== undefined) {\n\t\t\t\tthis.pendingRelays.delete(oldest)\n\t\t\t}\n\t\t}\n\t\tthis.pendingRelays.set(msg.messageId, { message: msg, ops, sentAtMs: Date.now() })\n\t}\n\n\t/**\n\t * Retransmit relay batches this client has not acknowledged within `staleMs`.\n\t * Called on a periodic tick by the server (and directly by tests). Redelivering an\n\t * already-applied op is harmless: the client dedups by content-addressed id.\n\t */\n\tretransmitPendingRelays(staleMs = 0): void {\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\tif (this.clientDeliveryWatermark !== null) {\n\t\t\treturn\n\t\t}\n\t\tif (this.pendingRelays.size === 0) return\n\t\tconst cutoff = Date.now() - staleMs\n\t\tfor (const { message, sentAtMs } of this.pendingRelays.values()) {\n\t\t\tif (sentAtMs <= cutoff) {\n\t\t\t\tthis.sendToClient(message)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Wake the durable delivery stream for clients that negotiated delivery\n\t * watermarks. This is used both for dropped watermark batches and for operations\n\t * appended by another server/store instance: the session always scans from its\n\t * own acknowledged cursor and applies its visibility filter before sending.\n\t */\n\tpushDeliveryStreamIfSupported(\n\t\tstaleMs = 0,\n\t\toptions: { trackStall?: boolean; serverFrontier?: number } = {},\n\t): void {\n\t\tif (this.state !== 'streaming' || !this.transport.isConnected()) return\n\t\tif (this.clientDeliveryWatermark === null) return\n\t\tif (\n\t\t\toptions.serverFrontier !== undefined &&\n\t\t\toptions.serverFrontier <= this.lastAckedDeliverySeq\n\t\t) {\n\t\t\tthis.outstandingDelivery = null\n\t\t\treturn\n\t\t}\n\t\tif (staleMs > 0 && Date.now() - this.lastDeliveryPushAttemptAtMs < staleMs) {\n\t\t\treturn\n\t\t}\n\t\tthis.pushDeliveryStream({ trackStall: options.trackStall })\n\t}\n\n\t/**\n\t * Close this session.\n\t */\n\t/**\n\t * Hand any unacknowledged relays to the server so they survive this session and are\n\t * redelivered when this client reconnects (per-node buffer), then clear them. Called\n\t * from every session-teardown path (explicit close and transport close).\n\t */\n\tprivate flushOrphanedRelays(): void {\n\t\tif (this.onOrphanedRelays && this.clientNodeId && this.pendingRelays.size > 0) {\n\t\t\tconst ops: Operation[] = []\n\t\t\tfor (const entry of this.pendingRelays.values()) {\n\t\t\t\tops.push(...entry.ops)\n\t\t\t}\n\t\t\tif (ops.length > 0) {\n\t\t\t\tthis.onOrphanedRelays(this.clientNodeId, ops)\n\t\t\t}\n\t\t}\n\t\tthis.pendingRelays.clear()\n\t}\n\n\tclose(reason?: string): void {\n\t\tif (this.state === 'closed') return\n\t\tthis.state = 'closed'\n\t\tthis.flushOrphanedRelays()\n\n\t\tif (this.transport.isConnected()) {\n\t\t\tthis.transport.close(1000, reason ?? 'session closed')\n\t\t}\n\n\t\tthis.onClose?.(this.sessionId)\n\t}\n\n\t// --- Getters ---\n\n\tgetState(): SessionState {\n\t\treturn this.state\n\t}\n\n\tgetSessionId(): string {\n\t\treturn this.sessionId\n\t}\n\n\tgetClientNodeId(): string | null {\n\t\treturn this.clientNodeId\n\t}\n\n\tgetAuthContext(): AuthContext | null {\n\t\treturn this.authContext\n\t}\n\n\tisStreaming(): boolean {\n\t\treturn this.state === 'streaming'\n\t}\n\n\t/**\n\t * Get the transport for this session.\n\t * Used by the awareness relay to send messages to this client.\n\t */\n\tgetTransport(): ServerTransport {\n\t\treturn this.transport\n\t}\n\n\t// --- Private protocol handlers ---\n\n\tprivate messageChain: Promise<void> = Promise.resolve()\n\n\t/** Send to the client when the transport is still connected; no-op otherwise. */\n\tprivate sendToClient(message: SyncMessage): boolean {\n\t\tif (!this.transport.isConnected()) {\n\t\t\treturn false\n\t\t}\n\t\ttry {\n\t\t\tthis.transport.send(message)\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tprivate enqueueMessage(message: SyncMessage): void {\n\t\tthis.messageChain = this.messageChain\n\t\t\t.then(() => this.handleMessageAsync(message))\n\t\t\t.catch((error) => this.handleMessageFailure(error))\n\t}\n\n\tprivate async handleMessageAsync(message: SyncMessage): Promise<void> {\n\t\tswitch (message.type) {\n\t\t\tcase 'handshake':\n\t\t\t\tawait this.handleHandshake(message)\n\t\t\t\tbreak\n\t\t\tcase 'operation-batch':\n\t\t\t\tawait this.handleOperationBatch(message)\n\t\t\t\tbreak\n\t\t\tcase 'acknowledgment':\n\t\t\t\tthis.pendingRelays.delete(message.acknowledgedMessageId)\n\t\t\t\tif (message.deliverySequence !== undefined) {\n\t\t\t\t\t// Advance the confirmed watermark; the next streaming push resumes here.\n\t\t\t\t\tthis.lastAckedDeliverySeq = Math.max(this.lastAckedDeliverySeq, message.deliverySequence)\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis.outstandingDelivery &&\n\t\t\t\t\t\tthis.lastAckedDeliverySeq >= this.outstandingDelivery.max\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.outstandingDelivery = null\n\t\t\t\t\t} else if (this.outstandingDelivery) {\n\t\t\t\t\t\tthis.outstandingDelivery.repeatCount = 0\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\tcase 'error':\n\t\t\t\tbreak\n\t\t\tcase 'awareness-update':\n\t\t\t\tthis.handleAwarenessUpdate(message)\n\t\t\t\tbreak\n\t\t\tcase 'yjs-doc-update':\n\t\t\t\tthis.handleYjsDocUpdate(message)\n\t\t\t\tbreak\n\t\t\tcase 'blob-chunk-request':\n\t\t\t\tthis.onBlobChunkRequest?.(this.sessionId, message)\n\t\t\t\tbreak\n\t\t\tcase 'blob-chunk-response':\n\t\t\t\tthis.onBlobChunkResponse?.(this.sessionId, message)\n\t\t\t\tbreak\n\t\t\tcase 'blob-chunk-push':\n\t\t\t\tawait this.handleBlobChunkPush(message)\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\t/**\n\t * Persist a client-uploaded blob chunk (or manifest) centrally. The bytes are\n\t * verified to hash to the declared hash before storing, so a corrupt or\n\t * mislabeled upload is rejected rather than served later as trusted content.\n\t */\n\tprivate async handleBlobChunkPush(message: BlobChunkPushMessage): Promise<void> {\n\t\tif (!this.persistBlobChunk) {\n\t\t\treturn\n\t\t}\n\t\tconst bytes = decodeBlobChunkBytes(message.bytes)\n\t\tconst actual = await hashBlob(bytes)\n\t\tif (actual !== message.hash) {\n\t\t\t// Reject a mismatched upload rather than persisting untrusted bytes.\n\t\t\treturn\n\t\t}\n\t\tawait this.persistBlobChunk(message.hash, bytes)\n\t}\n\n\tprivate handleMessageFailure(error: unknown): void {\n\t\tconst reason = error instanceof Error ? error.message : 'Message handling failed'\n\t\tthis.logger?.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'error',\n\t\t\tevent: 'session.message_failed',\n\t\t\tsessionId: this.sessionId,\n\t\t\tnodeId: this.clientNodeId ?? undefined,\n\t\t\terror: reason,\n\t\t\tdetails: {\n\t\t\t\tstate: this.state,\n\t\t\t\terrorName: error instanceof Error ? error.name : typeof error,\n\t\t\t},\n\t\t})\n\t\tthis.sendError('SYNC_ERROR', reason, true)\n\t\tthis.close(reason)\n\t}\n\n\tprivate async handleHandshake(msg: HandshakeMessage): Promise<void> {\n\t\t// Only accept handshake in 'connected' state (prevent duplicate handshakes)\n\t\tif (this.state !== 'connected') {\n\t\t\tthis.sendError('DUPLICATE_HANDSHAKE', 'Handshake already completed', false)\n\t\t\treturn\n\t\t}\n\n\t\tthis.clientNodeId = msg.nodeId\n\t\tthis.scopeExitPolicy = msg.scopeExitPolicy ?? 'retain'\n\n\t\t// Authenticate if provider is configured\n\t\tif (this.auth) {\n\t\t\tconst token = msg.authToken ?? ''\n\t\t\tconst context = await this.auth.authenticate(token)\n\t\t\tif (!context) {\n\t\t\t\tthis.sendError('AUTH_FAILED', 'Authentication failed', false)\n\t\t\t\tthis.close('authentication failed')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.authContext = context\n\t\t\tthis.state = 'authenticated'\n\t\t}\n\n\t\t// Resolve download and upload authorization independently. The legacy `scopes`\n\t\t// contract remains shorthand for both directions.\n\t\tconst directionalScopesConfigured =\n\t\t\tthis.authContext?.downlinkScopes !== undefined || this.authContext?.uplinkScopes !== undefined\n\t\tconst downlinkAuthScopes = directionalScopesConfigured\n\t\t\t? (this.authContext?.downlinkScopes ?? this.authContext?.scopes ?? {})\n\t\t\t: this.authContext?.scopes\n\t\tconst uplinkAuthScopes = directionalScopesConfigured\n\t\t\t? (this.authContext?.uplinkScopes ?? this.authContext?.scopes ?? {})\n\t\t\t: this.authContext?.scopes\n\t\tconst rawResolvedDownlinkScopes = resolveSessionScopes(this.store.getSchema(), {\n\t\t\thandshakeScope: msg.syncScope,\n\t\t\tauthScopes: downlinkAuthScopes,\n\t\t})\n\t\tconst rawResolvedUplinkScopes = directionalScopesConfigured\n\t\t\t? uplinkAuthScopes\n\t\t\t: rawResolvedDownlinkScopes\n\t\tlet resolvedDownlinkScopes: typeof rawResolvedDownlinkScopes\n\t\tlet resolvedUplinkScopes: typeof rawResolvedUplinkScopes\n\t\ttry {\n\t\t\tresolvedDownlinkScopes = rawResolvedDownlinkScopes\n\t\t\t\t? normalizeScopeMap(rawResolvedDownlinkScopes)\n\t\t\t\t: directionalScopesConfigured\n\t\t\t\t\t? {}\n\t\t\t\t\t: undefined\n\t\t\tresolvedUplinkScopes = rawResolvedUplinkScopes\n\t\t\t\t? normalizeScopeMap(rawResolvedUplinkScopes)\n\t\t\t\t: directionalScopesConfigured\n\t\t\t\t\t? {}\n\t\t\t\t\t: undefined\n\t\t} catch (error) {\n\t\t\tthis.sendToClient({\n\t\t\t\ttype: 'error',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tcode: 'SCOPE_PREDICATE_LIMIT',\n\t\t\t\tmessage: error instanceof Error ? error.message : 'Invalid scope predicate',\n\t\t\t\tretriable: false,\n\t\t\t})\n\t\t\tthis.close('invalid scope predicate')\n\t\t\treturn\n\t\t}\n\n\t\tif (resolvedDownlinkScopes || resolvedUplinkScopes) {\n\t\t\tif (this.authContext) {\n\t\t\t\tthis.authContext = {\n\t\t\t\t\t...this.authContext,\n\t\t\t\t\tscopes: resolvedDownlinkScopes,\n\t\t\t\t\tdownlinkScopes: resolvedDownlinkScopes,\n\t\t\t\t\tuplinkScopes: resolvedUplinkScopes,\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.authContext = {\n\t\t\t\t\tuserId: msg.nodeId,\n\t\t\t\t\tscopes: resolvedDownlinkScopes,\n\t\t\t\t\tdownlinkScopes: resolvedDownlinkScopes,\n\t\t\t\t\tuplinkScopes: resolvedUplinkScopes,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\twarnIfMultiTenantWithoutScopes(this.auth, resolvedDownlinkScopes, this.store.getSchema())\n\n\t\tif (msg.syncQueries && msg.syncQueries.length > 0) {\n\t\t\tthis.syncQuerySubsets = dedupeQuerySubsets(msg.syncQueries)\n\t\t} else {\n\t\t\tthis.syncQuerySubsets = []\n\t\t}\n\n\t\tthis.resumeDeltaCursor = msg.deltaCursor ? decodeDeltaCursor(msg.deltaCursor) : null\n\t\tthis.clientDeliveryWatermark = msg.lastDeliverySequence ?? null\n\t\t// A delivery watermark is valid only for the exact server-visible view that\n\t\t// earned it. When the server resolves a different scope than the client sent\n\t\t// (common with server-auth scopes, promotions, or invite acceptance), the client\n\t\t// cannot have keyed its local watermark by that authoritative view before this\n\t\t// handshake. Reset to a full scoped backfill instead of trusting a cursor that may\n\t\t// have advanced over previously hidden operations.\n\t\tif (\n\t\t\tthis.clientDeliveryWatermark !== null &&\n\t\t\t!sameScopeMap(msg.syncScope, this.authContext?.downlinkScopes)\n\t\t) {\n\t\t\tthis.clientDeliveryWatermark = 0\n\t\t}\n\n\t\t// Only read the server's delivery frontier when the client actually uses the\n\t\t// watermark. If the client's reported watermark exceeds that frontier, the server's\n\t\t// log was rolled back (for example a backup restore reset the sequence), so resync\n\t\t// that client from the beginning rather than let it sit above a frontier that no\n\t\t// longer exists; the server advertises its max so the client resets to match.\n\t\tconst clientUsesWatermark = this.clientDeliveryWatermark !== null\n\t\tlet serverMaxDelivery = 0\n\t\tif (clientUsesWatermark) {\n\t\t\tserverMaxDelivery = await this.store.getMaxDeliverySequence()\n\t\t\tif (\n\t\t\t\tthis.clientDeliveryWatermark !== null &&\n\t\t\t\tthis.clientDeliveryWatermark > serverMaxDelivery\n\t\t\t) {\n\t\t\t\tthis.clientDeliveryWatermark = 0\n\t\t\t}\n\t\t}\n\n\t\tconst serverVector = this.store.getVersionVector()\n\t\tconst selectedWireFormat = selectWireFormat(msg.supportedWireFormats)\n\t\tthis.setSerializerWireFormat(selectedWireFormat)\n\n\t\tif (!isClientSchemaVersionSupported(msg.schemaVersion, this.supportedSchemaVersions)) {\n\t\t\tconst { min, max } = this.supportedSchemaVersions\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:schema-mismatch',\n\t\t\t\tclientSchemaVersion: msg.schemaVersion,\n\t\t\t\tserverSchemaVersion: this.schemaVersion,\n\t\t\t\tsupportedMin: min,\n\t\t\t\tsupportedMax: max,\n\t\t\t\treason: `${SCHEMA_MISMATCH_PREFIX}: client schema version ${msg.schemaVersion} not in supported range [${min}, ${max}]`,\n\t\t\t})\n\t\t\tconst response: SyncMessage = {\n\t\t\t\ttype: 'handshake-response',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tnodeId: this.store.getNodeId(),\n\t\t\t\tversionVector: versionVectorToWire(serverVector),\n\t\t\t\tschemaVersion: this.schemaVersion,\n\t\t\t\taccepted: false,\n\t\t\t\trejectReason: `${SCHEMA_MISMATCH_PREFIX}: client schema version ${msg.schemaVersion} not in supported range [${min}, ${max}]`,\n\t\t\t\tsupportedSchemaMin: min,\n\t\t\t\tsupportedSchemaMax: max,\n\t\t\t\tserverTime: Date.now(),\n\t\t\t}\n\t\t\tthis.sendToClient(response)\n\t\t\tthis.close('schema version mismatch')\n\t\t\treturn\n\t\t}\n\n\t\t// Send handshake response with server's version vector and accepted scope\n\t\tconst response: SyncMessage = {\n\t\t\ttype: 'handshake-response',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tnodeId: this.store.getNodeId(),\n\t\t\tversionVector: versionVectorToWire(serverVector),\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t\taccepted: true,\n\t\t\tselectedWireFormat,\n\t\t\tserverTime: Date.now(),\n\t\t\t// The server's highest delivery sequence, so a client whose persisted watermark\n\t\t\t// is ahead of it (server rolled back) can reset to a full resync. Sent only to\n\t\t\t// watermark-using clients.\n\t\t\t...(clientUsesWatermark ? { serverMaxDeliverySequence: serverMaxDelivery } : {}),\n\t\t\t// Advertise central blob storage so the client uploads the bytes behind\n\t\t\t// its blob fields, keeping them available after the author goes offline.\n\t\t\t...(this.persistBlobChunk ? { blobStorageEnabled: true } : {}),\n\t\t\t// Confirm the accepted scope so the client knows what data will be synced.\n\t\t\t// This may differ from what the client requested if auth scopes are narrower.\n\t\t\t...(this.authContext?.downlinkScopes\n\t\t\t\t? {\n\t\t\t\t\t\tacceptedScope: this.authContext.downlinkScopes,\n\t\t\t\t\t\tacceptedDownlinkScopes: this.authContext.downlinkScopes,\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\t...(this.authContext?.uplinkScopes\n\t\t\t\t? { acceptedUplinkScopes: this.authContext.uplinkScopes }\n\t\t\t\t: {}),\n\t\t}\n\t\tthis.sendToClient(response)\n\n\t\tthis.emitter?.emit({ type: 'sync:connected', nodeId: msg.nodeId })\n\n\t\t// Transition to syncing and send the server->client stream. A client that\n\t\t// reports a delivery watermark gets the gap-free delivery stream (resumed from\n\t\t// that watermark); an older client gets the version-vector delta. Both send only\n\t\t// operations visible in this session's scope.\n\t\tthis.state = 'syncing'\n\t\tif (this.clientDeliveryWatermark !== null) {\n\t\t\tthis.lastAckedDeliverySeq = this.clientDeliveryWatermark\n\t\t\t// Resuming from a non-zero watermark: the client already holds its own history,\n\t\t\t// so exclude its own operations. A full resync (watermark 0, e.g. a fresh or\n\t\t\t// recovered client) passes no exclusion so it recovers everything, its own\n\t\t\t// operations included.\n\t\t\tconst excludeOwn =\n\t\t\t\tthis.clientDeliveryWatermark > 0 ? (this.clientNodeId ?? undefined) : undefined\n\t\t\tthis.lastDeliveryPushAttemptAtMs = Date.now()\n\t\t\tawait this.sendDeliveryStream(this.clientDeliveryWatermark, true, excludeOwn)\n\t\t} else {\n\t\t\tconst clientVector = wireToVersionVector(msg.versionVector)\n\t\t\tawait this.sendDelta(clientVector)\n\t\t}\n\n\t\t// Transition to streaming after delta is sent\n\t\tthis.state = 'streaming'\n\n\t\t// Redeliver any relays buffered while this client's node id was disconnected\n\t\t// (dropped just before a prior reconnect). relayOperations re-filters them by\n\t\t// this session's current scope and re-tracks them for acknowledgment.\n\t\tif (this.takeOrphanedRelays && this.clientNodeId) {\n\t\t\tconst buffered = this.takeOrphanedRelays(this.clientNodeId)\n\t\t\tif (buffered.length > 0) {\n\t\t\t\tthis.relayOperations(buffered)\n\t\t\t}\n\t\t}\n\t\t// A delivery-watermark client needs no explicit drain here: an operation committed\n\t\t// during the handshake-scan-to-streaming window is picked up by the next streaming\n\t\t// push (or the retransmit tick), which resumes from the client's acknowledged\n\t\t// position. Draining here would re-scan from the not-yet-advanced acknowledged\n\t\t// position and re-send the whole handshake stream.\n\t}\n\n\tprivate async handleOperationBatch(msg: OperationBatchMessage): Promise<void> {\n\t\tconst operations = msg.operations.map((s) => this.serializer.decodeOperation(s))\n\t\tconst applied: Operation[] = []\n\t\tlet acknowledgedThrough = 0\n\t\tlet canAdvanceAck = true\n\t\tlet uniqueOperations = 0\n\t\tlet duplicateOperations = 0\n\t\tlet rejectedOperations = 0\n\n\t\tfor (const op of operations) {\n\t\t\tif (!canAdvanceAck) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (!(await this.operationAllowedFromClient(op))) {\n\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\top,\n\t\t\t\t\t'SCOPE_VIOLATION',\n\t\t\t\t\t`Operation \"${op.id}\" in collection \"${op.collection}\" is outside the accepted uplink scope. Refresh scopes before creating or explicitly resubmitting an authorized operation.`,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\trejectedOperations += 1\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (!isOperationTimestampValid(op)) {\n\t\t\t\tthis.sendError(\n\t\t\t\t\t'INVALID_TIMESTAMP',\n\t\t\t\t\t`Operation \"${op.id}\" timestamp is too far in the future`,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\tcanAdvanceAck = false\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (!this.rateLimiter.allow(1)) {\n\t\t\t\tthis.sendError(\n\t\t\t\t\t'RATE_LIMIT',\n\t\t\t\t\t`Session exceeded operation rate limit (${String(this.maxOpsPerMinute)} ops/min)`,\n\t\t\t\t\ttrue,\n\t\t\t\t)\n\t\t\t\tcanAdvanceAck = false\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst sizeCheck = validateOperationSize(op, this.maxOperationBytes)\n\t\t\tif (!sizeCheck.valid) {\n\t\t\t\tthis.sendError(\n\t\t\t\t\t'OPERATION_TOO_LARGE',\n\t\t\t\t\tsizeCheck.message ?? `Operation \"${op.id}\" is too large`,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\tcanAdvanceAck = false\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst serverOp = this.transformForServerSchema(op)\n\t\t\tif (serverOp === null) {\n\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\top,\n\t\t\t\t\t'SCHEMA_TRANSFORM_UNAVAILABLE',\n\t\t\t\t\t`Operation \"${op.id}\" cannot be transformed from schema v${op.schemaVersion} to server schema v${this.schemaVersion}.`,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\trejectedOperations += 1\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Server-side adjudication of untrusted client operations. Runs after\n\t\t\t// the built-in guards and before materialization, so a rejected op never\n\t\t\t// enters the authoritative log and never relays to other clients.\n\t\t\tif (this.validateOperation && this.koraContext) {\n\t\t\t\tlet decision: Awaited<ReturnType<OperationValidator>>\n\t\t\t\ttry {\n\t\t\t\t\tdecision = await this.validateOperation(serverOp, {\n\t\t\t\t\t\tauth: this.authContext,\n\t\t\t\t\t\tkora: this.koraContext,\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// A throwing validator must not crash ingestion or silently accept.\n\t\t\t\t\t// Treat it as a retriable rejection so the submitter can try again.\n\t\t\t\t\tconst message = error instanceof Error ? error.message : 'validator error'\n\t\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\t\tserverOp,\n\t\t\t\t\t\t'VALIDATION_ERROR',\n\t\t\t\t\t\t`Validator threw: ${message}`,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t)\n\t\t\t\t\tcanAdvanceAck = false\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (decision.action === 'reject') {\n\t\t\t\t\tconst retriable = decision.retriable ?? isRetriableRejection(decision.code)\n\t\t\t\t\tthis.sendOperationRejected(serverOp, decision.code, decision.message, retriable)\n\t\t\t\t\trejectedOperations += 1\n\t\t\t\t\tif (retriable) {\n\t\t\t\t\t\tcanAdvanceAck = false\n\t\t\t\t\t} else {\n\t\t\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (decision.action === 'ignore') {\n\t\t\t\t\t// The server took responsibility out of band; do not materialize the\n\t\t\t\t\t// raw op and do not reject. The batch ack lets the client drop it.\n\t\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// action === 'accept' falls through to normal materialization.\n\t\t\t}\n\n\t\t\tconst applyResult = await applyServerOperation(this.store, serverOp)\n\t\t\tif (applyResult.rejection) {\n\t\t\t\tthis.sendOperationRejected(\n\t\t\t\t\tserverOp,\n\t\t\t\t\tapplyResult.rejection.code,\n\t\t\t\t\tapplyResult.rejection.message,\n\t\t\t\t\tapplyResult.rejection.retriable,\n\t\t\t\t)\n\t\t\t\trejectedOperations += 1\n\t\t\t\tif (applyResult.rejection.retriable) {\n\t\t\t\t\tcanAdvanceAck = false\n\t\t\t\t} else {\n\t\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (applyResult.result === 'applied') {\n\t\t\t\tapplied.push(...applyResult.appliedOperations)\n\t\t\t\tuniqueOperations += 1\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t} else {\n\t\t\t\tduplicateOperations += 1\n\t\t\t\tacknowledgedThrough = op.sequenceNumber\n\t\t\t}\n\t\t}\n\n\t\tif (operations.length > 0) {\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:received',\n\t\t\t\toperations,\n\t\t\t\tbatchSize: operations.length,\n\t\t\t\tuniqueOperations,\n\t\t\t\tduplicateOperations,\n\t\t\t\trejectedOperations,\n\t\t\t})\n\t\t}\n\n\t\t// Send acknowledgment\n\t\tconst lastOp = operations[operations.length - 1]\n\t\tconst ack: SyncMessage = {\n\t\t\ttype: 'acknowledgment',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tacknowledgedMessageId: msg.messageId,\n\t\t\tlastSequenceNumber: lastOp ? Math.min(acknowledgedThrough, lastOp.sequenceNumber) : 0,\n\t\t}\n\t\tthis.sendToClient(ack)\n\n\t\t// Relay only newly applied operations to other sessions\n\t\tif (applied.length > 0) {\n\t\t\tthis.onRelay?.(this.sessionId, applied)\n\t\t}\n\t}\n\n\tprivate transformForServerSchema(op: Operation): Operation | null {\n\t\tif (op.schemaVersion === this.schemaVersion) {\n\t\t\treturn op\n\t\t}\n\t\treturn applyOperationTransforms(op, this.schemaVersion, this.operationTransforms)\n\t}\n\n\tprivate async sendDelta(clientVector: Map<string, number>): Promise<void> {\n\t\tconst serverVector = this.store.getVersionVector()\n\t\tconst missing: Operation[] = []\n\n\t\tfor (const [nodeId, serverSeq] of serverVector) {\n\t\t\tconst clientSeq = clientVector.get(nodeId) ?? 0\n\t\t\tif (serverSeq > clientSeq) {\n\t\t\t\tconst ops = await this.store.getOperationRange(nodeId, clientSeq + 1, serverSeq)\n\t\t\t\tfor (const op of ops) {\n\t\t\t\t\tif (await this.operationVisibleToClient(op)) {\n\t\t\t\t\t\tmissing.push(op)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (missing.length === 0) {\n\t\t\tconst emptyBatch: SyncMessage = {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\toperations: [],\n\t\t\t\tisFinal: true,\n\t\t\t\tbatchIndex: 0,\n\t\t\t\ttotalBatches: 1,\n\t\t\t}\n\t\t\tthis.sendToClient(emptyBatch)\n\t\t\treturn\n\t\t}\n\n\t\tconst sorted = topologicalSort(missing)\n\t\tconst afterCursor = sliceOperationsAfterCursor(sorted, this.resumeDeltaCursor)\n\t\tconst totalBatches = Math.ceil(afterCursor.length / this.batchSize)\n\n\t\tif (afterCursor.length === 0) {\n\t\t\tconst emptyBatch: SyncMessage = {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\toperations: [],\n\t\t\t\tisFinal: true,\n\t\t\t\tbatchIndex: this.resumeDeltaCursor?.batchIndex ?? 0,\n\t\t\t\ttotalBatches: 1,\n\t\t\t}\n\t\t\tthis.sendToClient(emptyBatch)\n\t\t\treturn\n\t\t}\n\n\t\tfor (let i = 0; i < totalBatches; i++) {\n\t\t\tconst start = i * this.batchSize\n\t\t\tconst batchOps = afterCursor.slice(start, start + this.batchSize)\n\t\t\tconst serializedOps = batchOps.map((op) => this.serializer.encodeOperation(op))\n\t\t\tconst batchCursor = createDeltaCursorFromBatch(batchOps, i)\n\n\t\t\tconst batchMsg: SyncMessage = {\n\t\t\t\ttype: 'operation-batch',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\toperations: serializedOps,\n\t\t\t\tisFinal: i === totalBatches - 1,\n\t\t\t\tbatchIndex: i,\n\t\t\t\ttotalBatches,\n\t\t\t\t...(batchCursor ? { cursor: encodeDeltaCursor(batchCursor) } : {}),\n\t\t\t}\n\t\t\tthis.sendToClient(batchMsg)\n\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:sent',\n\t\t\t\toperations: batchOps,\n\t\t\t\tbatchSize: batchOps.length,\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Send the gap-free server->client delivery stream, resuming just after\n\t * `fromDeliverySeq`. Operations are scanned in server delivery-sequence order\n\t * (commit order), scope-filtered for this session, and sent in batches that chain:\n\t * each batch's `baseDeliverySequence` equals the previous batch's\n\t * `maxDeliverySequence` (the first batch bases on `fromDeliverySeq`). The client\n\t * applies a batch only when its watermark equals the base and advances the\n\t * watermark to the max, so a dropped batch stalls the watermark and is recovered by\n\t * the next handshake resend. Because delivery-sequence order respects causal order\n\t * (a dependency is always committed, and thus sequenced, before its dependent), no\n\t * topological sort is needed and the client never defers on a missing dependency\n\t * that is itself in this stream.\n\t *\n\t * The final batch advances the watermark to the highest delivery sequence scanned,\n\t * not merely the last in-scope one, so an out-of-scope tail is not re-scanned on the\n\t * next reconnect. Returns the number of operations actually sent.\n\t */\n\tprivate async sendDeliveryStream(\n\t\tfromDeliverySeq: number,\n\t\tfinalizeWhenEmpty: boolean,\n\t\texcludeNodeId?: string,\n\t): Promise<{ sentOperations: number; maxScanned: number; sent: boolean }> {\n\t\tconst scanChunk = Math.max(this.batchSize, 1) * 5\n\t\tlet scanCursor = fromDeliverySeq\n\t\tlet maxScanned = fromDeliverySeq\n\t\tconst deliverable: Array<DeliveredOperation & { retraction?: boolean }> = []\n\n\t\twhile (true) {\n\t\t\tconst chunk = await this.store.getOperationsAfterDelivery(scanCursor, scanChunk)\n\t\t\tconst last = chunk[chunk.length - 1]\n\t\t\tif (last === undefined) break\n\t\t\tscanCursor = last.deliverySequence\n\t\t\t// maxScanned counts every operation scanned, including any excluded (own or\n\t\t\t// out-of-scope) ones, so the batch max advances the client's watermark past\n\t\t\t// them even though they are not sent.\n\t\t\tmaxScanned = scanCursor\n\t\t\tfor (const delivered of chunk) {\n\t\t\t\t// Skip the client's own operations during streaming: it already holds them,\n\t\t\t\t// so echoing them back is pure waste. They are still counted in maxScanned,\n\t\t\t\t// and a full resync (fromDeliverySeq 0) passes no excludeNodeId, so a client\n\t\t\t\t// that lost its local store still recovers its own history.\n\t\t\t\tif (excludeNodeId !== undefined && delivered.operation.nodeId === excludeNodeId) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (await this.operationVisibleToClient(delivered.operation)) {\n\t\t\t\t\tdeliverable.push(delivered)\n\t\t\t\t} else if (await this.scopeRetractionFor(delivered.operation)) {\n\t\t\t\t\tdeliverable.push({ ...delivered, retraction: true })\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (chunk.length < scanChunk) break\n\t\t}\n\n\t\tif (deliverable.length === 0) {\n\t\t\t// Nothing in scope after the cursor. On a handshake resume, send a single empty\n\t\t\t// final batch so the client advances past an out-of-scope tail and completes\n\t\t\t// initial sync. During streaming, send nothing (an empty batch every relay tick\n\t\t\t// would be pure noise); a reconnect re-scans the small tail if needed.\n\t\t\tlet sent = false\n\t\t\tif (finalizeWhenEmpty || maxScanned > fromDeliverySeq) {\n\t\t\t\tsent = this.sendDeliveryBatch([], fromDeliverySeq, maxScanned, 0, true)\n\t\t\t}\n\t\t\treturn { sentOperations: 0, maxScanned, sent }\n\t\t}\n\n\t\tconst totalBatches = Math.ceil(deliverable.length / this.batchSize)\n\t\tlet base = fromDeliverySeq\n\t\tfor (let i = 0; i < totalBatches; i++) {\n\t\t\tconst slice = deliverable.slice(i * this.batchSize, (i + 1) * this.batchSize)\n\t\t\tconst lastInSlice = slice[slice.length - 1]\n\t\t\tif (lastInSlice === undefined) continue\n\t\t\tconst isFinal = i === totalBatches - 1\n\t\t\tconst lastSeq = lastInSlice.deliverySequence\n\t\t\t// The final batch carries the max scanned sequence (>= lastSeq) so the client\n\t\t\t// skips past any out-of-scope operations above the last in-scope one.\n\t\t\tconst max = isFinal ? Math.max(maxScanned, lastSeq) : lastSeq\n\t\t\tthis.sendDeliveryBatch(slice, base, max, i, isFinal)\n\t\t\tbase = max\n\t\t}\n\t\treturn {\n\t\t\tsentOperations: deliverable.filter((item) => !item.retraction).length,\n\t\t\tmaxScanned,\n\t\t\tsent: true,\n\t\t}\n\t}\n\n\t/** Build, track, and send one chained delivery-stream batch. */\n\tprivate sendDeliveryBatch(\n\t\tslice: Array<DeliveredOperation & { retraction?: boolean }>,\n\t\tbase: number,\n\t\tmax: number,\n\t\tbatchIndex: number,\n\t\tisFinal: boolean,\n\t): boolean {\n\t\tconst batchMsg: SyncMessage = {\n\t\t\ttype: 'operation-batch',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\toperations: slice\n\t\t\t\t.filter((delivered) => !delivered.retraction)\n\t\t\t\t.map((delivered) => this.serializer.encodeOperation(delivered.operation)),\n\t\t\t...(slice.some((delivered) => delivered.retraction)\n\t\t\t\t? {\n\t\t\t\t\t\tretractions: slice\n\t\t\t\t\t\t\t.filter((delivered) => delivered.retraction)\n\t\t\t\t\t\t\t.map((delivered) => ({\n\t\t\t\t\t\t\t\tcollection: delivered.operation.collection,\n\t\t\t\t\t\t\t\trecordId: delivered.operation.recordId,\n\t\t\t\t\t\t\t})),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\tisFinal,\n\t\t\tbatchIndex,\n\t\t\tbaseDeliverySequence: base,\n\t\t\tmaxDeliverySequence: max,\n\t\t}\n\t\t// Delivery batches are NOT tracked in the bounded pending-relay buffer: recovery of\n\t\t// a dropped or unapplied batch is by re-scan from the client's acknowledged\n\t\t// position (the next push or the retransmit tick), which cannot be defeated by a\n\t\t// buffer eviction. The client re-acks a duplicate and stalls on a gap, so re-sends\n\t\t// are always safe.\n\t\tconst sent = this.sendToClient(batchMsg)\n\t\tconst sentOperations = slice.filter((delivered) => !delivered.retraction)\n\t\tif (sentOperations.length > 0) {\n\t\t\tthis.emitter?.emit({\n\t\t\t\ttype: 'sync:sent',\n\t\t\t\toperations: sentOperations.map((delivered) => delivered.operation),\n\t\t\t\tbatchSize: sentOperations.length,\n\t\t\t})\n\t\t}\n\t\treturn sent\n\t}\n\n\tprivate async operationVisibleToClient(op: Operation): Promise<boolean> {\n\t\tconst scopes = this.authContext?.downlinkScopes ?? this.authContext?.scopes\n\t\tconst subsets = this.syncQuerySubsets\n\t\t// A partial update (or a delete) may not carry the scope / query-subset fields\n\t\t// in its own data. Judging visibility from the bare op would wrongly hide such\n\t\t// an operation, so backfill those fields from the materialized record (including\n\t\t// a soft-deleted one) whenever they are missing. Only look up when needed so the\n\t\t// common case (inserts, or ops that already carry the fields) stays lookup-free.\n\t\tconst needsBackfill =\n\t\t\tmissingScopeFields(op, scopes).length > 0 || (subsets !== undefined && subsets.length > 0)\n\t\tconst fullRecord = needsBackfill\n\t\t\t? await this.lookupRecordFields(op.collection, op.recordId)\n\t\t\t: undefined\n\n\t\tif (!operationMatchesScopes(op, scopes, fullRecord)) {\n\t\t\treturn false\n\t\t}\n\t\treturn operationMatchesQuerySubsets(op, subsets, fullRecord)\n\t}\n\n\t/** Upload authorization is independent from the client's downloaded/query view. */\n\tprivate async operationAllowedFromClient(op: Operation): Promise<boolean> {\n\t\tconst scopes = this.authContext?.uplinkScopes ?? this.authContext?.scopes\n\t\tconst needsBackfill = missingScopeFields(op, scopes).length > 0\n\t\tconst fullRecord = needsBackfill\n\t\t\t? await this.lookupRecordFields(op.collection, op.recordId)\n\t\t\t: undefined\n\t\treturn operationMatchesScopes(op, scopes, fullRecord)\n\t}\n\n\tprivate async scopeRetractionFor(op: Operation): Promise<boolean> {\n\t\tif (this.scopeExitPolicy !== 'retract') return false\n\t\tconst scopes = this.authContext?.downlinkScopes ?? this.authContext?.scopes\n\t\tif (!scopes) return false\n\t\tconst resultingRecord = await this.lookupRecordFields(op.collection, op.recordId)\n\t\treturn operationExitsScopes(op, scopes, resultingRecord)\n\t}\n\n\t/**\n\t * Read a record's current field values from the materialized store for scope /\n\t * query-subset backfill. Includes soft-deleted rows so a relayed delete (whose op\n\t * carries no fields) is still judged against the record's actual scope. Returns\n\t * undefined when the record cannot be read (never materialized, or no schema).\n\t */\n\tprivate async lookupRecordFields(\n\t\tcollection: string,\n\t\trecordId: string,\n\t): Promise<Record<string, unknown> | undefined> {\n\t\ttry {\n\t\t\tconst rows = await this.store.queryCollection(collection, {\n\t\t\t\twhere: { id: recordId },\n\t\t\t\tincludeDeleted: true,\n\t\t\t\tlimit: 1,\n\t\t\t})\n\t\t\treturn rows[0]\n\t\t} catch {\n\t\t\treturn undefined\n\t\t}\n\t}\n\n\tprivate handleAwarenessUpdate(msg: AwarenessUpdateMessage): void {\n\t\t// Relay awareness updates to the server for broadcasting to other clients.\n\t\t// Awareness is purely ephemeral -- no persistence.\n\t\tthis.onAwarenessUpdate?.(this.sessionId, msg)\n\t}\n\n\tprivate handleYjsDocUpdate(msg: YjsDocUpdateMessage): void {\n\t\tthis.onYjsDocUpdate?.(this.sessionId, msg)\n\t}\n\n\tprivate sendError(code: string, message: string, retriable: boolean): void {\n\t\tconst errorMsg: SyncMessage = {\n\t\t\ttype: 'error',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tcode,\n\t\t\tmessage,\n\t\t\tretriable,\n\t\t}\n\t\tthis.sendToClient(errorMsg)\n\t}\n\n\t/**\n\t * Reject one specific client operation, tied to its id, so the submitter can\n\t * divert it out of its pending queue into a durable rejected store rather than\n\t * losing it or retrying forever. The op is NOT materialized, so no other\n\t * replica ever sees it.\n\t */\n\tprivate sendOperationRejected(\n\t\top: Operation,\n\t\tcode: string,\n\t\tmessage: string,\n\t\tretriable: boolean,\n\t): void {\n\t\tconst rejectedMsg: SyncMessage = {\n\t\t\ttype: 'operation-rejected',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\toperationId: op.id,\n\t\t\tcollection: op.collection,\n\t\t\trecordId: op.recordId,\n\t\t\tcode,\n\t\t\tmessage,\n\t\t\tretriable,\n\t\t}\n\t\tthis.sendToClient(rejectedMsg)\n\t}\n\n\tprivate setSerializerWireFormat(format: WireFormat): void {\n\t\tif (typeof this.serializer.setWireFormat === 'function') {\n\t\t\tthis.serializer.setWireFormat(format)\n\t\t}\n\t}\n\n\tprivate handleTransportClose(): void {\n\t\tif (this.state === 'closed') return\n\t\tthis.state = 'closed'\n\t\tthis.flushOrphanedRelays()\n\t\tthis.emitter?.emit({ type: 'sync:disconnected', reason: 'transport closed' })\n\t\tthis.onClose?.(this.sessionId)\n\t}\n}\n\nfunction selectWireFormat(supportedWireFormats?: WireFormat[]): WireFormat {\n\tif (supportedWireFormats?.includes('protobuf')) {\n\t\treturn 'protobuf'\n\t}\n\n\treturn 'json'\n}\n","import type { Operation } from '@korajs/core'\nimport { buildMergeRelationLookup, checkReferentialIntegrityOnDelete } from '@korajs/merge'\nimport type { ApplyResult } from '@korajs/sync'\nimport { validateIncomingOperationConstraints } from '../constraints/operation-constraint-validator'\nimport { createServerReferentialContext } from '../constraints/server-referential-context'\nimport type { ServerStore } from '../store/server-store'\nimport { type OperationRejection, isRetriableRejection } from './rejection-taxonomy'\nimport {\n\tcreateServerSideEffectOperation,\n\tnextServerSequenceNumber,\n} from './server-side-effect-operation'\n\nexport interface ApplyServerOperationResult {\n\t/** Result of applying the primary operation */\n\tresult: ApplyResult\n\t/** Primary op when applied, plus any server-generated side-effect operations */\n\tappliedOperations: Operation[]\n\t/** Rejection reason when the operation was not applied */\n\trejection?: OperationRejection\n}\n\n/**\n * Applies an incoming client operation with Tier 2 constraints and referential integrity.\n * Cascade/set-null side effects are persisted as server-originated operations in the op log.\n */\nexport async function applyServerOperation(\n\tstore: ServerStore,\n\top: Operation,\n\trelationLookup?: ReturnType<typeof buildMergeRelationLookup>,\n): Promise<ApplyServerOperationResult> {\n\tconst schema = store.getSchema()\n\tconst lookup = relationLookup ?? (schema ? buildMergeRelationLookup(schema) : new Map())\n\n\tconst shapeCheck = validateOperationShape(op, schema)\n\tif (!shapeCheck.valid) {\n\t\treturn {\n\t\t\tresult: 'skipped',\n\t\t\tappliedOperations: [],\n\t\t\trejection: {\n\t\t\t\tcode: shapeCheck.code ?? 'SCHEMA_VALIDATION_ERROR',\n\t\t\t\tmessage: shapeCheck.message ?? `Operation \"${op.id}\" does not match the server schema`,\n\t\t\t\tretriable: false,\n\t\t\t},\n\t\t}\n\t}\n\n\tconst constraintCheck = await validateIncomingOperationConstraints(store, op, schema)\n\tif (!constraintCheck.valid) {\n\t\tconst code = constraintCheck.code ?? 'CONSTRAINT_VIOLATION'\n\t\treturn {\n\t\t\tresult: 'skipped',\n\t\t\tappliedOperations: [],\n\t\t\trejection: {\n\t\t\t\tcode,\n\t\t\t\tmessage: constraintCheck.message ?? `Operation \"${op.id}\" violates a schema constraint`,\n\t\t\t\tretriable: isRetriableRejection(code),\n\t\t\t},\n\t\t}\n\t}\n\n\tif (op.type === 'delete' && schema) {\n\t\tconst refCtx = createServerReferentialContext(store)\n\t\tconst referential = await checkReferentialIntegrityOnDelete(op, schema, refCtx, lookup)\n\n\t\tif (!referential.allowed) {\n\t\t\treturn {\n\t\t\t\tresult: 'skipped',\n\t\t\t\tappliedOperations: [],\n\t\t\t\trejection: {\n\t\t\t\t\tcode: 'REFERENTIAL_INTEGRITY',\n\t\t\t\t\tmessage: `Operation \"${op.id}\" violates referential integrity on \"${op.collection}\"`,\n\t\t\t\t\tretriable: isRetriableRejection('REFERENTIAL_INTEGRITY'),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\tconst primaryResult = await store.applyRemoteOperation(op)\n\t\tif (primaryResult !== 'applied') {\n\t\t\treturn { result: primaryResult, appliedOperations: [] }\n\t\t}\n\n\t\tconst appliedOperations: Operation[] = [op]\n\n\t\tfor (const effect of referential.sideEffectOps) {\n\t\t\t// Allocate each side-effect's sequence number individually. On a store\n\t\t\t// that reserves atomically (Postgres), this keeps a concurrent conditional\n\t\t\t// apply from being handed the same server sequence number; on a serialized\n\t\t\t// store, each allocation reads the version vector the prior apply advanced.\n\t\t\tconst sideOp = await createServerSideEffectOperation(\n\t\t\t\tstore,\n\t\t\t\top,\n\t\t\t\teffect,\n\t\t\t\top.schemaVersion,\n\t\t\t\tnextServerSequenceNumber(store),\n\t\t\t)\n\t\t\tconst sideResult = await store.applyRemoteOperation(sideOp)\n\t\t\tif (sideResult === 'applied') {\n\t\t\t\tappliedOperations.push(sideOp)\n\t\t\t}\n\t\t}\n\n\t\treturn { result: 'applied', appliedOperations }\n\t}\n\n\tconst result = await store.applyRemoteOperation(op)\n\treturn {\n\t\tresult,\n\t\tappliedOperations: result === 'applied' ? [op] : [],\n\t}\n}\n\nfunction validateOperationShape(\n\top: Operation,\n\tschema: ReturnType<ServerStore['getSchema']>,\n): { valid: true } | { valid: false; code: string; message: string } {\n\tif (!schema) {\n\t\treturn { valid: true }\n\t}\n\n\tconst collection = schema.collections[op.collection]\n\tif (!collection) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: 'UNKNOWN_COLLECTION',\n\t\t\tmessage: `Operation \"${op.id}\" targets unknown collection \"${op.collection}\".`,\n\t\t}\n\t}\n\n\tconst declaredFields = new Set(Object.keys(collection.fields))\n\tconst systemPreviousFields = new Set(['id', '_created_at', '_updated_at', '_deleted'])\n\tconst invalidDataField = firstInvalidField(op.data, declaredFields)\n\tif (invalidDataField) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: 'SCHEMA_VALIDATION_ERROR',\n\t\t\tmessage: `Operation \"${op.id}\" contains undeclared field \"${invalidDataField}\" in data for collection \"${op.collection}\".`,\n\t\t}\n\t}\n\n\tconst invalidPreviousField = firstInvalidField(\n\t\top.previousData,\n\t\tdeclaredFields,\n\t\tsystemPreviousFields,\n\t)\n\tif (invalidPreviousField) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tcode: 'SCHEMA_VALIDATION_ERROR',\n\t\t\tmessage: `Operation \"${op.id}\" contains undeclared field \"${invalidPreviousField}\" in previousData for collection \"${op.collection}\".`,\n\t\t}\n\t}\n\n\tif (op.atomicOps) {\n\t\tfor (const field of Object.keys(op.atomicOps)) {\n\t\t\tif (!declaredFields.has(field)) {\n\t\t\t\treturn {\n\t\t\t\t\tvalid: false,\n\t\t\t\t\tcode: 'SCHEMA_VALIDATION_ERROR',\n\t\t\t\t\tmessage: `Operation \"${op.id}\" contains undeclared atomic field \"${field}\" for collection \"${op.collection}\".`,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { valid: true }\n}\n\nfunction firstInvalidField(\n\tvalue: unknown,\n\tdeclaredFields: Set<string>,\n\textraAllowedFields?: Set<string>,\n): string | null {\n\tif (value === null || value === undefined) {\n\t\treturn null\n\t}\n\tif (typeof value !== 'object' || Array.isArray(value)) {\n\t\treturn null\n\t}\n\tfor (const field of Object.keys(value)) {\n\t\tif (!declaredFields.has(field) && !extraAllowedFields?.has(field)) {\n\t\t\treturn field\n\t\t}\n\t}\n\treturn null\n}\n","import type { Operation, SchemaDefinition } from '@korajs/core'\nimport { checkConstraints } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\nimport { createServerConstraintContext } from './server-constraint-context'\n\nexport interface OperationConstraintValidation {\n\tvalid: boolean\n\tcode?: string\n\tmessage?: string\n}\n\n/**\n * Validates an incoming operation against Tier 2 schema constraints on the server.\n * Deletes are skipped (removal cannot violate capacity/unique on the deleted row).\n */\nexport async function validateIncomingOperationConstraints(\n\tstore: ServerStore,\n\top: Operation,\n\tschema: SchemaDefinition | null,\n): Promise<OperationConstraintValidation> {\n\tif (!schema) {\n\t\treturn { valid: true }\n\t}\n\n\tif (op.type === 'delete') {\n\t\treturn { valid: true }\n\t}\n\n\tconst collectionDef = schema.collections[op.collection]\n\tif (!collectionDef || collectionDef.constraints.length === 0) {\n\t\treturn { valid: true }\n\t}\n\n\tconst candidate = await projectCandidateRecord(store, op)\n\tif (candidate === null) {\n\t\treturn { valid: true }\n\t}\n\n\tconst ctx = createServerConstraintContext(store)\n\tconst violations = await checkConstraints(\n\t\tcandidate,\n\t\top.recordId,\n\t\top.collection,\n\t\tcollectionDef,\n\t\tctx,\n\t)\n\n\tif (violations.length === 0) {\n\t\treturn { valid: true }\n\t}\n\n\tconst first = violations[0]\n\tif (first === undefined) {\n\t\treturn { valid: true }\n\t}\n\treturn {\n\t\tvalid: false,\n\t\tcode: 'CONSTRAINT_VIOLATION',\n\t\tmessage: first.message,\n\t}\n}\n\nasync function projectCandidateRecord(\n\tstore: ServerStore,\n\top: Operation,\n): Promise<Record<string, unknown> | null> {\n\tif (op.data === null) {\n\t\treturn null\n\t}\n\n\tconst existing = await store.findRecord(op.collection, op.recordId)\n\tconst base = existing ? { ...existing } : {}\n\n\tif (op.type === 'insert') {\n\t\treturn { ...op.data, id: op.recordId }\n\t}\n\n\treturn { ...base, ...op.data, id: op.recordId }\n}\n","import type { ConstraintContext } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\n\n/**\n * Adapts {@link ServerStore} materialized tables for Tier 2 constraint checks.\n */\nexport function createServerConstraintContext(store: ServerStore): ConstraintContext {\n\treturn {\n\t\tasync queryRecords(\n\t\t\tcollection: string,\n\t\t\twhere: Record<string, unknown>,\n\t\t): Promise<Record<string, unknown>[]> {\n\t\t\tconst rows = await store.queryCollection(collection, { where })\n\t\t\treturn rows.map((row) => ({ ...row }))\n\t\t},\n\t\tasync countRecords(collection: string, where: Record<string, unknown>): Promise<number> {\n\t\t\treturn store.countCollection(collection, where)\n\t\t},\n\t}\n}\n","import type { ReferentialMergeContext } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\n\n/**\n * Adapts {@link ServerStore} materialized tables for referential integrity checks.\n */\nexport function createServerReferentialContext(store: ServerStore): ReferentialMergeContext {\n\treturn {\n\t\tasync queryRecords(\n\t\t\tcollection: string,\n\t\t\twhere: Record<string, unknown>,\n\t\t): Promise<Record<string, unknown>[]> {\n\t\t\tconst rows = await store.queryCollection(collection, { where })\n\t\t\treturn rows.map((row) => ({ ...row }))\n\t\t},\n\t\tasync recordExists(collection: string, recordId: string): Promise<boolean> {\n\t\t\tconst row = await store.findRecord(collection, recordId)\n\t\t\treturn row !== null && row._deleted !== 1\n\t\t},\n\t}\n}\n","import { HybridLogicalClock, createOperation } from '@korajs/core'\nimport type { Operation } from '@korajs/core'\nimport type { SideEffectOp } from '@korajs/merge'\nimport type { ServerStore } from '../store/server-store'\n\n/**\n * Converts a merge-package referential side effect into a server-originated operation.\n */\nexport async function createServerSideEffectOperation(\n\tstore: ServerStore,\n\tparentOp: Operation,\n\teffect: SideEffectOp,\n\tschemaVersion: number,\n\tsequenceNumber: number,\n): Promise<Operation> {\n\tconst nodeId = store.getNodeId()\n\tconst clock = new HybridLogicalClock(nodeId)\n\tclock.receive(parentOp.timestamp)\n\n\treturn createOperation(\n\t\t{\n\t\t\tnodeId,\n\t\t\ttype: effect.type === 'delete' ? 'delete' : 'update',\n\t\t\tcollection: effect.collection,\n\t\t\trecordId: effect.recordId,\n\t\t\tdata: effect.data,\n\t\t\tpreviousData: effect.previousData,\n\t\t\tsequenceNumber,\n\t\t\tcausalDeps: [parentOp.id],\n\t\t\tschemaVersion,\n\t\t},\n\t\tclock,\n\t)\n}\n\n/**\n * Allocate the next sequence number for server-originated operations.\n */\nexport function nextServerSequenceNumber(store: ServerStore): number {\n\t// Prefer the store's atomic reservation when it serves writes concurrently (the\n\t// Postgres conditional path), so two in-flight server operations never collide on\n\t// a sequence number. Serialized stores fall back to the version vector, which is\n\t// safe because only one server operation is ever in flight at a time.\n\tif (store.reserveSequenceNumber) {\n\t\treturn store.reserveSequenceNumber()\n\t}\n\tconst nodeId = store.getNodeId()\n\tconst current = store.getVersionVector().get(nodeId) ?? 0\n\treturn current + 1\n}\n","import type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Auth provider that accepts all connections.\n * Returns a default anonymous context for any token.\n * Useful for development and testing.\n */\nexport class NoAuthProvider implements AuthProvider {\n\tasync authenticate(_token: string): Promise<AuthContext> {\n\t\treturn { userId: 'anonymous' }\n\t}\n}\n","import type { ScopeMap } from '@korajs/core'\nimport { type SchemaDefinition, buildScopeMap } from '@korajs/core'\n\nexport interface ResolveSessionScopesOptions {\n\t/** Scope map sent by the client during handshake */\n\thandshakeScope?: ScopeMap\n\t/** Scope map from the auth provider (server-controlled) */\n\tauthScopes?: ScopeMap\n\t/** Flat scope values used to derive schema sync rules */\n\tscopeValues?: Record<string, unknown>\n}\n\n/**\n * Resolve the effective per-session sync scope map.\n *\n * Combines schema sync rules, auth scopes, and client handshake scopes into\n * a single unified model. Auth scopes take precedence over handshake scopes\n * per collection; schema sync rules define which collections participate in\n * partial sync.\n */\nexport function resolveSessionScopes(\n\tschema: SchemaDefinition | null,\n\toptions: ResolveSessionScopesOptions,\n): ScopeMap | undefined {\n\tconst { handshakeScope, authScopes, scopeValues } = options\n\n\tlet resolved: ScopeMap | undefined\n\n\tif (schema && scopeValues && Object.keys(scopeValues).length > 0) {\n\t\tresolved = buildScopeMap(schema, scopeValues)\n\t} else if (handshakeScope) {\n\t\tresolved = { ...handshakeScope }\n\t} else if (authScopes) {\n\t\tresolved = { ...authScopes }\n\t}\n\n\tif (schema && !resolved && scopeValues) {\n\t\tresolved = buildScopeMap(schema, scopeValues)\n\t}\n\n\tif (authScopes) {\n\t\tresolved = mergeScopeMaps(resolved, authScopes, 'auth')\n\t}\n\n\tif (handshakeScope) {\n\t\tresolved = mergeScopeMaps(resolved, handshakeScope, 'handshake')\n\t}\n\n\treturn resolved && Object.keys(resolved).length > 0 ? resolved : undefined\n}\n\nfunction mergeScopeMaps(\n\tbase: ScopeMap | undefined,\n\toverlay: ScopeMap,\n\tsource: 'auth' | 'handshake',\n): ScopeMap {\n\tconst merged: ScopeMap = { ...(base ?? {}) }\n\n\tfor (const [collection, overlayScope] of Object.entries(overlay)) {\n\t\tif (source === 'auth') {\n\t\t\tmerged[collection] = { ...(merged[collection] ?? {}), ...overlayScope }\n\t\t} else {\n\t\t\tmerged[collection] = { ...(overlayScope ?? {}), ...(merged[collection] ?? {}) }\n\t\t}\n\t}\n\n\treturn merged\n}\n","import type { Operation } from '@korajs/core'\n\n/**\n * Per-collection scope map from auth context.\n */\nexport type ScopeMap = Record<string, Record<string, unknown>>\n\nexport const DEFAULT_MAX_SCOPE_PREDICATE_VALUES = 100\n\n/** Canonicalize bounded `$in` predicates so equivalent authorization has one signature. */\nexport function normalizeScopeMap(\n\tscopes: ScopeMap,\n\tmaxValues = DEFAULT_MAX_SCOPE_PREDICATE_VALUES,\n): ScopeMap {\n\tconst normalized: ScopeMap = {}\n\tfor (const collection of Object.keys(scopes).sort()) {\n\t\tconst predicate: Record<string, unknown> = {}\n\t\tfor (const field of Object.keys(scopes[collection] ?? {}).sort()) {\n\t\t\tconst expected = scopes[collection]?.[field]\n\t\t\tif (\n\t\t\t\texpected &&\n\t\t\t\ttypeof expected === 'object' &&\n\t\t\t\t!Array.isArray(expected) &&\n\t\t\t\t'$in' in expected\n\t\t\t) {\n\t\t\t\tconst values = (expected as { $in?: unknown }).$in\n\t\t\t\tif (!Array.isArray(values))\n\t\t\t\t\tthrow new Error(`Invalid $in predicate for ${collection}.${field}`)\n\t\t\t\tconst unique = [...new Map(values.map((value) => [stableValueKey(value), value])).values()]\n\t\t\t\tif (unique.length > maxValues)\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Scope predicate for ${collection}.${field} exceeds the ${maxValues}-value limit`,\n\t\t\t\t\t)\n\t\t\t\tpredicate[field] = {\n\t\t\t\t\t$in: unique.sort((a, b) => stableValueKey(a).localeCompare(stableValueKey(b))),\n\t\t\t\t}\n\t\t\t} else predicate[field] = expected\n\t\t}\n\t\tnormalized[collection] = predicate\n\t}\n\treturn normalized\n}\n\nfunction stableValueKey(value: unknown): string {\n\tif (Array.isArray(value)) return `[${value.map(stableValueKey).join(',')}]`\n\tif (value && typeof value === 'object')\n\t\treturn `{${Object.keys(value as Record<string, unknown>)\n\t\t\t.sort()\n\t\t\t.map(\n\t\t\t\t(key) =>\n\t\t\t\t\t`${JSON.stringify(key)}:${stableValueKey((value as Record<string, unknown>)[key])}`,\n\t\t\t)\n\t\t\t.join(',')}}`\n\treturn JSON.stringify(value)\n}\n\n/**\n * Returns true if an operation is visible to a session based on its scopes.\n *\n * Rules:\n * - No scopes configured => visible\n * - Collection missing from scope map => hidden\n * - All scoped field/value pairs must match the operation snapshot\n */\nexport function operationMatchesScopes(\n\top: Operation,\n\tscopes: ScopeMap | undefined,\n\tfullRecord?: Record<string, unknown> | null,\n): boolean {\n\tif (!scopes) return true\n\n\tconst collectionScope = scopes[op.collection]\n\tif (!collectionScope) return false\n\tif (Object.keys(collectionScope).length === 0) return true\n\n\tconst snapshot = buildSnapshot(op, fullRecord)\n\tif (!snapshot) return false\n\n\tfor (const [field, expected] of Object.entries(collectionScope)) {\n\t\tif (!matchesPredicate(snapshot[field], expected)) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n/** True when an update moved a previously visible record outside the scope. */\nexport function operationExitsScopes(\n\top: Operation,\n\tscopes: ScopeMap | undefined,\n\tresultingRecord?: Record<string, unknown> | null,\n): boolean {\n\tif (!scopes || op.type !== 'update' || !op.previousData) return false\n\tif (operationMatchesScopes(op, scopes, resultingRecord)) return false\n\tconst previousSnapshot = {\n\t\t...(resultingRecord ?? {}),\n\t\t...(op.data ?? {}),\n\t\t...op.previousData,\n\t}\n\treturn operationMatchesScopes(\n\t\t{ ...op, type: 'insert', data: previousSnapshot, previousData: null },\n\t\tscopes,\n\t\tpreviousSnapshot,\n\t)\n}\n\nfunction matchesPredicate(actual: unknown, expected: unknown): boolean {\n\tif (expected && typeof expected === 'object' && !Array.isArray(expected) && '$in' in expected) {\n\t\tconst values = (expected as { $in?: unknown }).$in\n\t\treturn Array.isArray(values) && values.some((value) => Object.is(actual, value))\n\t}\n\treturn Object.is(actual, expected)\n}\n\n/**\n * Returns the scope fields (for `op.collection`) that a bare operation does NOT\n * carry in its own `data`/`previousData`. When any are missing, the caller must\n * backfill them from the materialized record before scope-checking, otherwise a\n * partial update (or a delete) that does not restate the scope field is wrongly\n * judged out of scope and dropped from relay/delta — silently diverging tenants.\n */\nexport function missingScopeFields(op: Operation, scopes: ScopeMap | undefined): string[] {\n\tif (!scopes) return []\n\tconst collectionScope = scopes[op.collection]\n\tif (!collectionScope) return []\n\tif (Object.keys(collectionScope).length === 0) return []\n\tconst snapshot = buildSnapshot(op)\n\treturn Object.keys(collectionScope).filter((field) => !snapshot || !(field in snapshot))\n}\n\nfunction buildSnapshot(\n\top: Operation,\n\tfullRecord?: Record<string, unknown> | null,\n): Record<string, unknown> | null {\n\tconst previous = asRecord(op.previousData)\n\tconst next = asRecord(op.data)\n\n\tif (!previous && !next && !fullRecord) return null\n\n\treturn {\n\t\t...(fullRecord ?? {}),\n\t\t...(previous ?? {}),\n\t\t...(next ?? {}),\n\t}\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n\tif (typeof value !== 'object' || value === null || Array.isArray(value)) {\n\t\treturn null\n\t}\n\n\treturn value as Record<string, unknown>\n}\n","import { MAX_LOGICAL } from '@korajs/core'\nimport type { Operation } from '@korajs/core'\n\n/** Max allowed future skew for operation timestamps at server ingest (1 minute). */\nexport const SERVER_MAX_TIMESTAMP_FUTURE_MS = 60_000\n\n/**\n * Returns false when an operation's HLC timestamp is structurally invalid or\n * unreasonably far in the future.\n *\n * Structural checks matter because operations are content-addressed and\n * immutable: a timestamp with a non-integer/negative field or a logical\n * counter past the 5-digit serialization cap would poison the shared log\n * forever (its serialized form no longer sorts like HybridLogicalClock.compare),\n * so it must never be accepted at ingest.\n */\nexport function isOperationTimestampValid(op: Operation, now: number = Date.now()): boolean {\n\tconst { wallTime, logical } = op.timestamp\n\tif (!Number.isInteger(wallTime) || wallTime < 0) {\n\t\treturn false\n\t}\n\tif (!Number.isInteger(logical) || logical < 0 || logical > MAX_LOGICAL) {\n\t\treturn false\n\t}\n\treturn wallTime <= now + SERVER_MAX_TIMESTAMP_FUTURE_MS\n}\n","import type { Operation } from '@korajs/core'\n\n/** Default maximum serialized size of a single operation at server ingest (256 KiB). */\nexport const DEFAULT_MAX_OPERATION_BYTES = 256 * 1024\n\n/** Default maximum operations accepted per client session per minute. */\nexport const DEFAULT_MAX_OPS_PER_MINUTE = 600\n\n/**\n * Approximate UTF-8 byte length of an operation payload for rate/size guards.\n */\nexport function measureOperationBytes(op: Operation): number {\n\treturn Buffer.byteLength(JSON.stringify(op), 'utf8')\n}\n\nexport interface OperationSizeValidation {\n\tvalid: boolean\n\tbytes: number\n\tmessage?: string\n}\n\n/**\n * Returns false when an operation exceeds the configured byte limit.\n */\nexport function validateOperationSize(\n\top: Operation,\n\tmaxBytes: number = DEFAULT_MAX_OPERATION_BYTES,\n): OperationSizeValidation {\n\tconst bytes = measureOperationBytes(op)\n\tif (bytes <= maxBytes) {\n\t\treturn { valid: true, bytes }\n\t}\n\treturn {\n\t\tvalid: false,\n\t\tbytes,\n\t\tmessage: `Operation \"${op.id}\" exceeds max size (${String(bytes)} > ${String(maxBytes)} bytes)`,\n\t}\n}\n\n/**\n * Simple sliding-window rate limiter for per-session operation ingest.\n */\nexport class SessionRateLimiter {\n\tprivate windowStartMs = Date.now()\n\tprivate count = 0\n\n\tconstructor(private readonly maxOpsPerMinute: number = DEFAULT_MAX_OPS_PER_MINUTE) {}\n\n\tget limit(): number {\n\t\treturn this.maxOpsPerMinute\n\t}\n\n\t/** Record N operations and return false when the limit is exceeded. */\n\tallow(count = 1): boolean {\n\t\tconst now = Date.now()\n\t\tif (now - this.windowStartMs >= 60_000) {\n\t\t\tthis.windowStartMs = now\n\t\t\tthis.count = 0\n\t\t}\n\t\tthis.count += count\n\t\treturn this.count <= this.maxOpsPerMinute\n\t}\n\n\treset(): void {\n\t\tthis.windowStartMs = Date.now()\n\t\tthis.count = 0\n\t}\n}\n","import type { BlobRef, KoraEventEmitter, Operation, OperationTransform } from '@korajs/core'\nimport { SyncError, generateUUIDv7, isBlobRef } from '@korajs/core'\nimport { SimpleEventEmitter } from '@korajs/core/internal'\nimport type { AwarenessUpdateMessage, MessageSerializer, YjsDocUpdateMessage } from '@korajs/sync'\nimport { JsonMessageSerializer } from '@korajs/sync'\nimport {\n\ttype ApplyServerOperationResult,\n\tapplyServerOperation,\n} from '../apply/apply-server-operation'\nimport type { OperationValidator } from '../apply/operation-validator'\nimport { AwarenessRelay } from '../awareness/awareness-relay'\nimport { ServerMetricsCollector, estimateByteSize } from '../diagnostics/server-metrics-collector'\nimport type { Logger } from '../logging/structured-logger'\nimport { createDefaultLogger } from '../logging/structured-logger'\nimport { BlobChunkRelay } from '../richtext/blob-chunk-relay'\nimport { YjsDocRelay } from '../richtext/yjs-doc-relay'\nimport { ClientSession } from '../session/client-session'\nimport type { ServerStore } from '../store/server-store'\nimport { HttpServerTransport } from '../transport/http-server-transport'\nimport type { ServerTransport } from '../transport/server-transport'\nimport { WsServerTransport } from '../transport/ws-server-transport'\nimport type {\n\tAuthProvider,\n\tHttpSyncRequest,\n\tHttpSyncResponse,\n\tKoraSyncServerConfig,\n\tServerStatus,\n} from '../types'\nimport { type ProductionHttpRouteContext, createRouteContext } from './route-context'\n\nconst DEFAULT_MAX_CONNECTIONS = 0 // unlimited\nconst DEFAULT_BATCH_SIZE = 100\nconst DEFAULT_SCHEMA_VERSION = 1\nconst DEFAULT_HOST = '0.0.0.0'\nconst DEFAULT_PATH = '/'\nconst DEFAULT_RELAY_RETRANSMIT_INTERVAL_MS = 2000\nconst DEFAULT_DELIVERY_POLL_INTERVAL_MS = 2000\n\n/**\n * Minimal interface for a ws.WebSocketServer instance.\n * Allows dependency injection for testing without importing ws directly.\n */\nexport interface WsServerLike {\n\ton(event: string, listener: (...args: unknown[]) => void): void\n\tclose(callback?: (err?: Error) => void): void\n\taddress(): { port: number } | string | null\n}\n\n/**\n * Constructor type for creating a WebSocket server.\n */\nexport type WsServerConstructor = new (options: {\n\tport?: number\n\thost?: string\n\tpath?: string\n}) => WsServerLike\n\nfunction validateIntervalOption(name: string, value: number): number {\n\tif (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) {\n\t\tthrow new SyncError(`${name} must be a non-negative integer number of milliseconds`, {\n\t\t\t[name]: value,\n\t\t})\n\t}\n\treturn value\n}\n\n/**\n * Self-hosted sync server. Accepts WebSocket connections from clients,\n * handles the sync protocol, stores operations, and relays changes\n * between connected clients.\n *\n * Two modes of operation:\n * 1. **Standalone**: Call `start()` with a port — creates its own WebSocket server.\n * 2. **Attach**: Call `handleConnection(transport)` — attach to an existing HTTP server.\n */\nexport class KoraSyncServer {\n\tprivate readonly store: ServerStore\n\tprivate readonly auth: AuthProvider | null\n\tprivate readonly serializer: MessageSerializer\n\tprivate readonly emitter: KoraEventEmitter | null\n\tprivate readonly maxConnections: number\n\tprivate readonly batchSize: number\n\tprivate readonly relayRetransmitIntervalMs: number\n\tprivate readonly deliveryPollIntervalMs: number\n\tprivate readonly schemaVersion: number\n\tprivate readonly supportedSchemaVersions: { min: number; max: number }\n\tprivate readonly operationTransforms: OperationTransform[]\n\tprivate readonly port: number | undefined\n\tprivate readonly host: string\n\tprivate readonly path: string\n\tprivate readonly logger: Logger\n\tprivate readonly metrics: ServerMetricsCollector\n\n\tprivate readonly awarenessRelay = new AwarenessRelay()\n\tprivate readonly yjsDocRelay = new YjsDocRelay()\n\tprivate readonly blobChunkRelay: BlobChunkRelay\n\tprivate readonly persistBlobChunk:\n\t\t| ((hash: string, bytes: Uint8Array) => Promise<void> | void)\n\t\t| null\n\tprivate readonly maxOperationBytes: number | undefined\n\tprivate readonly maxOpsPerMinute: number | undefined\n\tprivate readonly validateOperation: OperationValidator | undefined\n\tprivate readonly koraContext: ProductionHttpRouteContext\n\tprivate readonly sessions = new Map<string, ClientSession>()\n\tprivate readonly httpClients = new Map<\n\t\tstring,\n\t\t{ sessionId: string; transport: HttpServerTransport }\n\t>()\n\tprivate readonly httpSessionToClient = new Map<string, string>()\n\t// Informational value reported by getStatus(). Keep in sync with the\n\t// @korajs/server package version on release; it is not used for protocol negotiation.\n\tprivate readonly serverVersion = '1.0.0-beta.0'\n\tprivate wsServer: WsServerLike | null = null\n\tprivate running = false\n\t/**\n\t * Periodic tick that retransmits relay batches connected clients have not\n\t * acknowledged, so a relay dropped by a lossy transport is redelivered instead of\n\t * leaving that client with a permanent version-vector gap (a lost operation).\n\t */\n\tprivate relayRetransmitTimer: ReturnType<typeof setInterval> | null = null\n\tprivate deliveryPollTimer: ReturnType<typeof setInterval> | null = null\n\tprivate lastObservedDeliverySequence = 0\n\tprivate deliveryPollInFlight = false\n\t/**\n\t * Relay operations a client never acknowledged before it disconnected, buffered by\n\t * client node id so they can be redelivered on its next connection. Bounded per\n\t * node and expired by age so a client that never returns cannot grow this forever.\n\t */\n\tprivate readonly orphanedRelaysByNode = new Map<\n\t\tstring,\n\t\t{ ops: Operation[]; bufferedAtMs: number }\n\t>()\n\tprivate static readonly MAX_ORPHANED_RELAY_OPS_PER_NODE = 5000\n\tprivate static readonly ORPHANED_RELAY_TTL_MS = 5 * 60_000\n\n\tconstructor(config: KoraSyncServerConfig) {\n\t\tthis.store = config.store\n\t\tconst storeSchemaVersion = this.store.getSchema()?.version\n\t\tif (\n\t\t\tconfig.schemaVersion !== undefined &&\n\t\t\tstoreSchemaVersion !== undefined &&\n\t\t\tconfig.schemaVersion !== storeSchemaVersion\n\t\t) {\n\t\t\tthrow new SyncError('Sync schema version does not match the configured store schema.', {\n\t\t\t\tsyncSchemaVersion: config.schemaVersion,\n\t\t\t\tstoreSchemaVersion,\n\t\t\t})\n\t\t}\n\t\tthis.auth = config.auth ?? null\n\t\tthis.serializer = config.serializer ?? new JsonMessageSerializer()\n\t\tthis.emitter = config.emitter ?? null\n\t\tthis.maxConnections = config.maxConnections ?? DEFAULT_MAX_CONNECTIONS\n\t\tthis.batchSize = config.batchSize ?? DEFAULT_BATCH_SIZE\n\t\tthis.relayRetransmitIntervalMs = validateIntervalOption(\n\t\t\t'relayRetransmitIntervalMs',\n\t\t\tconfig.relayRetransmitIntervalMs ?? DEFAULT_RELAY_RETRANSMIT_INTERVAL_MS,\n\t\t)\n\t\tthis.deliveryPollIntervalMs = validateIntervalOption(\n\t\t\t'deliveryPollIntervalMs',\n\t\t\tconfig.deliveryPollIntervalMs ?? DEFAULT_DELIVERY_POLL_INTERVAL_MS,\n\t\t)\n\t\tthis.schemaVersion = config.schemaVersion ?? storeSchemaVersion ?? DEFAULT_SCHEMA_VERSION\n\t\tthis.supportedSchemaVersions = config.supportedSchemaVersions ?? {\n\t\t\tmin: this.schemaVersion,\n\t\t\tmax: this.schemaVersion,\n\t\t}\n\t\tthis.operationTransforms = config.operationTransforms ?? []\n\t\tthis.port = config.port\n\t\tthis.host = config.host ?? DEFAULT_HOST\n\t\tthis.path = config.path ?? DEFAULT_PATH\n\t\tthis.logger = config.logger ?? createDefaultLogger()\n\t\tthis.metrics = config.metricsCollector ?? new ServerMetricsCollector()\n\t\tthis.metrics.setSchemaVersion(this.schemaVersion)\n\t\tthis.blobChunkRelay = new BlobChunkRelay(config.resolveBlobChunk)\n\t\tthis.persistBlobChunk = config.persistBlobChunk ?? null\n\t\tthis.maxOperationBytes = config.maxOperationBytes\n\t\tthis.maxOpsPerMinute = config.maxOpsPerMinute\n\t\tthis.validateOperation = config.validateOperation\n\t\t// One trusted data-plane context, shared by custom HTTP routes (via\n\t\t// production-server) and by the operation validator. It holds no per-request\n\t\t// state; the closures only reach back into `this` when actually invoked.\n\t\tthis.koraContext = createRouteContext(this, this.store)\n\n\t\t// If no external emitter was provided, create an internal one for\n\t\t// subscribing to session events for metrics and logging.\n\t\tif (!this.emitter) {\n\t\t\tthis.emitter = new SimpleEventEmitter()\n\t\t}\n\t}\n\n\tprivate ensureBackgroundTimersStarted(): void {\n\t\tif (this.relayRetransmitIntervalMs > 0 && !this.relayRetransmitTimer) {\n\t\t\tthis.relayRetransmitTimer = setInterval(() => {\n\t\t\t\tthis.retransmitPendingRelays(this.relayRetransmitIntervalMs)\n\t\t\t}, this.relayRetransmitIntervalMs)\n\t\t\tthis.relayRetransmitTimer.unref?.()\n\t\t}\n\n\t\tif (this.deliveryPollIntervalMs > 0 && !this.deliveryPollTimer) {\n\t\t\tthis.deliveryPollTimer = setInterval(() => {\n\t\t\t\tvoid this.pollDeliveryLog()\n\t\t\t}, this.deliveryPollIntervalMs)\n\t\t\tthis.deliveryPollTimer.unref?.()\n\t\t}\n\t}\n\n\t/**\n\t * Retransmit relay batches that connected clients have not acknowledged within\n\t * `staleMs`. Called on a periodic tick and directly by tests. Redelivering an\n\t * already-applied operation is harmless (clients dedup by content-addressed id).\n\t */\n\tretransmitPendingRelays(staleMs = 0): void {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tsession.retransmitPendingRelays(staleMs)\n\t\t}\n\t\tthis.expireOrphanedRelays()\n\t}\n\n\t/**\n\t * Check whether the authoritative delivery log advanced without passing through\n\t * this server instance, then wake delivery-watermark sessions to scan from their\n\t * own acknowledged cursors. Session-level filtering remains the only fan-out path.\n\t */\n\tasync pollDeliveryLog(): Promise<void> {\n\t\tif (this.deliveryPollInFlight) return\n\t\tthis.deliveryPollInFlight = true\n\t\ttry {\n\t\t\tconst maxDeliverySequence = await this.store.getMaxDeliverySequence()\n\t\t\tif (maxDeliverySequence <= this.lastObservedDeliverySequence) {\n\t\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\t\tsession.pushDeliveryStreamIfSupported(this.deliveryPollIntervalMs, {\n\t\t\t\t\t\ttrackStall: true,\n\t\t\t\t\t\tserverFrontier: maxDeliverySequence,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.lastObservedDeliverySequence = maxDeliverySequence\n\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\tsession.pushDeliveryStreamIfSupported(0, {\n\t\t\t\t\tserverFrontier: maxDeliverySequence,\n\t\t\t\t})\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'delivery_poll.failed',\n\t\t\t\tdetails: { error: error instanceof Error ? error.message : String(error) },\n\t\t\t})\n\t\t} finally {\n\t\t\tthis.deliveryPollInFlight = false\n\t\t}\n\t}\n\n\t/**\n\t * Buffer relay operations a disconnected client never acknowledged, keyed by its\n\t * node id, deduped by operation id and bounded by count. Redelivered when the\n\t * client reconnects (see {@link takeOrphanedRelays}).\n\t */\n\tprivate bufferOrphanedRelays(nodeId: string, ops: Operation[]): void {\n\t\tif (ops.length === 0) return\n\t\tconst existing = this.orphanedRelaysByNode.get(nodeId)\n\t\tconst merged = existing ? existing.ops : []\n\t\tconst seen = new Set(merged.map((op) => op.id))\n\t\tfor (const op of ops) {\n\t\t\tif (!seen.has(op.id)) {\n\t\t\t\tmerged.push(op)\n\t\t\t\tseen.add(op.id)\n\t\t\t}\n\t\t}\n\t\t// Keep only the most recent ops if the buffer is oversized.\n\t\tconst bounded =\n\t\t\tmerged.length > KoraSyncServer.MAX_ORPHANED_RELAY_OPS_PER_NODE\n\t\t\t\t? merged.slice(merged.length - KoraSyncServer.MAX_ORPHANED_RELAY_OPS_PER_NODE)\n\t\t\t\t: merged\n\t\tthis.orphanedRelaysByNode.set(nodeId, { ops: bounded, bufferedAtMs: Date.now() })\n\t}\n\n\t/** Remove and return a node's buffered orphaned relay operations, if any. */\n\tprivate takeOrphanedRelays(nodeId: string): Operation[] {\n\t\tconst entry = this.orphanedRelaysByNode.get(nodeId)\n\t\tif (!entry) return []\n\t\tthis.orphanedRelaysByNode.delete(nodeId)\n\t\treturn entry.ops\n\t}\n\n\t/** Drop buffered orphaned relays older than the TTL (client never returned). */\n\tprivate expireOrphanedRelays(): void {\n\t\tif (this.orphanedRelaysByNode.size === 0) return\n\t\tconst cutoff = Date.now() - KoraSyncServer.ORPHANED_RELAY_TTL_MS\n\t\tfor (const [nodeId, entry] of this.orphanedRelaysByNode) {\n\t\t\tif (entry.bufferedAtMs <= cutoff) {\n\t\t\t\tthis.orphanedRelaysByNode.delete(nodeId)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * The trusted, scoped data-plane context (`apply` / `query` / `findById`).\n\t * Shared with the production server so HTTP routes, the operation validator,\n\t * and `server.kora` are all the same object over the same pipeline.\n\t */\n\tgetKoraContext(): ProductionHttpRouteContext {\n\t\treturn this.koraContext\n\t}\n\n\t/**\n\t * Subscribe to session-level events for metrics collection and logging.\n\t * Called when a new session is created.\n\t */\n\tprivate attachSessionEvents(sessionId: string, sessionEmitter: KoraEventEmitter): void {\n\t\tsessionEmitter.on('sync:connected', (event) => {\n\t\t\tthis.metrics.recordHandshake(sessionId, event.nodeId)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.handshake',\n\t\t\t\tsessionId,\n\t\t\t\tnodeId: event.nodeId,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:received', (event) => {\n\t\t\tconst byteSize = estimateByteSize(event.operations)\n\t\t\tthis.metrics.recordReceived(sessionId, event.batchSize, byteSize, {\n\t\t\t\tunique: event.uniqueOperations ?? event.batchSize,\n\t\t\t\tduplicates: event.duplicateOperations ?? 0,\n\t\t\t\trejected: event.rejectedOperations ?? 0,\n\t\t\t})\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.received',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:sent', (event) => {\n\t\t\tconst byteSize = estimateByteSize(event.operations)\n\t\t\tthis.metrics.recordSent(sessionId, event.batchSize, byteSize)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.sent',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:disconnected', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.disconnected',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: { reason: event.reason },\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:schema-mismatch', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'session.schema_mismatch',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: {\n\t\t\t\t\tclientSchemaVersion: event.clientSchemaVersion,\n\t\t\t\t\tserverSchemaVersion: event.serverSchemaVersion,\n\t\t\t\t\tsupportedMin: event.supportedMin,\n\t\t\t\t\tsupportedMax: event.supportedMax,\n\t\t\t\t\treason: event.reason,\n\t\t\t\t},\n\t\t\t})\n\t\t})\n\t}\n\n\t/**\n\t * Get the metrics collector for external access (e.g., HTTP endpoints).\n\t */\n\tgetMetricsCollector(): ServerMetricsCollector {\n\t\treturn this.metrics\n\t}\n\n\t/**\n\t * Get the logger for external access (e.g., event streaming).\n\t */\n\tgetLogger(): Logger {\n\t\treturn this.logger\n\t}\n\n\t/**\n\t * Start the WebSocket server in standalone mode.\n\t *\n\t * @param wsServerImpl - Optional WebSocket server constructor for testing\n\t */\n\tasync start(wsServerImpl?: WsServerConstructor): Promise<void> {\n\t\tif (this.running) {\n\t\t\tthrow new SyncError('Server is already running', { port: this.port })\n\t\t}\n\n\t\tif (!wsServerImpl && this.port === undefined) {\n\t\t\tthrow new SyncError(\n\t\t\t\t'Port is required for standalone mode. Provide port in config or use handleConnection() for attach mode.',\n\t\t\t\t{},\n\t\t\t)\n\t\t}\n\n\t\tif (wsServerImpl) {\n\t\t\tthis.wsServer = new wsServerImpl({\n\t\t\t\tport: this.port,\n\t\t\t\thost: this.host,\n\t\t\t\tpath: this.path,\n\t\t\t})\n\t\t} else {\n\t\t\t// Dynamic import of ws — only needed in standalone mode\n\t\t\tconst { WebSocketServer } = await import('ws')\n\t\t\tthis.wsServer = new WebSocketServer({\n\t\t\t\tport: this.port,\n\t\t\t\thost: this.host,\n\t\t\t\tpath: this.path,\n\t\t\t})\n\t\t}\n\n\t\tthis.wsServer.on('connection', (ws: unknown) => {\n\t\t\tconst transport = new WsServerTransport(\n\t\t\t\tws as import('../transport/ws-server-transport').WsWebSocket,\n\t\t\t\t{\n\t\t\t\t\tserializer: this.serializer,\n\t\t\t\t},\n\t\t\t)\n\t\t\tthis.handleConnection(transport)\n\t\t})\n\n\t\tthis.running = true\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'server.started',\n\t\t\tdetails: { port: this.port, host: this.host, path: this.path },\n\t\t})\n\t}\n\n\t/**\n\t * Stop the server. Closes all sessions and the WebSocket server.\n\t */\n\tasync stop(): Promise<void> {\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'server.stopping',\n\t\t\tdetails: { connectedClients: this.sessions.size },\n\t\t})\n\n\t\t// Stop the relay retransmit tick and drop buffered orphaned relays.\n\t\tif (this.relayRetransmitTimer) {\n\t\t\tclearInterval(this.relayRetransmitTimer)\n\t\t\tthis.relayRetransmitTimer = null\n\t\t}\n\t\tif (this.deliveryPollTimer) {\n\t\t\tclearInterval(this.deliveryPollTimer)\n\t\t\tthis.deliveryPollTimer = null\n\t\t}\n\t\tthis.orphanedRelaysByNode.clear()\n\n\t\t// Clean up awareness relay\n\t\tthis.awarenessRelay.clear()\n\t\tthis.yjsDocRelay.clear()\n\t\tthis.blobChunkRelay.clear()\n\n\t\t// Close all active sessions (works in both standalone and attach mode)\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tsession.close('server shutting down')\n\t\t}\n\t\tthis.sessions.clear()\n\t\tthis.httpClients.clear()\n\t\tthis.httpSessionToClient.clear()\n\n\t\t// Close WebSocket server (standalone mode only)\n\t\tif (this.wsServer) {\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tthis.wsServer?.close(() => resolve())\n\t\t\t})\n\t\t\tthis.wsServer = null\n\t\t}\n\n\t\tthis.running = false\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'server.stopped',\n\t\t})\n\t}\n\n\t/**\n\t * Handle one HTTP sync request for a long-polling client.\n\t *\n\t * A stable `clientId` identifies the logical connection across requests.\n\t */\n\tasync handleHttpRequest(request: HttpSyncRequest): Promise<HttpSyncResponse> {\n\t\tif (!request.clientId || request.clientId.trim().length === 0) {\n\t\t\treturn { status: 400 }\n\t\t}\n\n\t\tconst client = this.getOrCreateHttpClient(request.clientId)\n\n\t\tif (request.method === 'POST') {\n\t\t\tif (request.body === undefined) {\n\t\t\t\treturn { status: 400 }\n\t\t\t}\n\n\t\t\tconst payload = normalizeHttpBody(request.body, request.contentType)\n\t\t\tclient.transport.receive(payload)\n\t\t\treturn { status: 202 }\n\t\t}\n\n\t\tif (request.method === 'GET') {\n\t\t\tconst polled = client.transport.poll(request.ifNoneMatch)\n\t\t\treturn {\n\t\t\t\tstatus: polled.status,\n\t\t\t\tbody: polled.body,\n\t\t\t\theaders: polled.headers,\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tstatus: 405,\n\t\t\theaders: { allow: 'GET, POST' },\n\t\t}\n\t}\n\n\t/**\n\t * Handle an incoming client connection (attach mode).\n\t * Creates a new ClientSession for the transport.\n\t *\n\t * @param transport - The server transport for the new connection\n\t * @returns The session ID\n\t */\n\thandleConnection(transport: ServerTransport): string {\n\t\t// Check max connections\n\t\tif (this.maxConnections > 0 && this.sessions.size >= this.maxConnections) {\n\t\t\ttransport.send({\n\t\t\t\ttype: 'error',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tcode: 'MAX_CONNECTIONS',\n\t\t\t\tmessage: `Server has reached maximum connections (${this.maxConnections})`,\n\t\t\t\tretriable: true,\n\t\t\t})\n\t\t\ttransport.close(4029, 'max connections reached')\n\t\t\tthis.metrics.recordError()\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'connection.rejected',\n\t\t\t\tdetails: { reason: 'max_connections', max: this.maxConnections },\n\t\t\t})\n\t\t\tthrow new SyncError('Maximum connections reached', {\n\t\t\t\tcurrent: this.sessions.size,\n\t\t\t\tmax: this.maxConnections,\n\t\t\t})\n\t\t}\n\n\t\tthis.ensureBackgroundTimersStarted()\n\n\t\tconst sessionId = generateUUIDv7()\n\t\tthis.metrics.recordConnection(sessionId)\n\n\t\t// Create a per-session emitter so we can track events with session context.\n\t\t// The session emits events on this emitter, and we listen here for metrics + logging.\n\t\tconst sessionEmitter = new SimpleEventEmitter()\n\n\t\tsessionEmitter.on('sync:connected', (event) => {\n\t\t\tthis.metrics.recordHandshake(sessionId, event.nodeId)\n\t\t\tthis.metrics.updateSessionState(sessionId, 'authenticated')\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.handshake',\n\t\t\t\tsessionId,\n\t\t\t\tnodeId: event.nodeId,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:received', (event) => {\n\t\t\tconst byteSize = estimateOperationByteSize(event.operations)\n\t\t\tthis.metrics.recordReceived(sessionId, event.batchSize, byteSize, {\n\t\t\t\tunique: event.uniqueOperations ?? event.batchSize,\n\t\t\t\tduplicates: event.duplicateOperations ?? 0,\n\t\t\t\trejected: event.rejectedOperations ?? 0,\n\t\t\t})\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.received',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:sent', (event) => {\n\t\t\tconst byteSize = estimateOperationByteSize(event.operations)\n\t\t\tthis.metrics.recordSent(sessionId, event.batchSize, byteSize)\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'operations.sent',\n\t\t\t\tsessionId,\n\t\t\t\tcount: event.batchSize,\n\t\t\t\tbytes: byteSize,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:disconnected', () => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'info',\n\t\t\t\tevent: 'session.disconnected',\n\t\t\t\tsessionId,\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:schema-mismatch', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'session.schema_mismatch',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: {\n\t\t\t\t\tclientSchemaVersion: event.clientSchemaVersion,\n\t\t\t\t\tserverSchemaVersion: event.serverSchemaVersion,\n\t\t\t\t\tsupportedMin: event.supportedMin,\n\t\t\t\t\tsupportedMax: event.supportedMax,\n\t\t\t\t\treason: event.reason,\n\t\t\t\t},\n\t\t\t})\n\t\t})\n\n\t\tsessionEmitter.on('sync:delivery-stalled', (event) => {\n\t\t\tthis.logger.log({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tlevel: 'warn',\n\t\t\t\tevent: 'session.delivery_stalled',\n\t\t\t\tsessionId,\n\t\t\t\tdetails: {\n\t\t\t\t\twatermark: event.watermark,\n\t\t\t\t\toutstandingMaxDeliverySequence: event.outstandingMaxDeliverySequence,\n\t\t\t\t\trepeatCount: event.repeatCount,\n\t\t\t\t\treason: event.reason,\n\t\t\t\t},\n\t\t\t})\n\t\t})\n\n\t\tconst session = new ClientSession({\n\t\t\tsessionId,\n\t\t\ttransport,\n\t\t\tstore: this.store,\n\t\t\tauth: this.auth ?? undefined,\n\t\t\tserializer: this.serializer,\n\t\t\temitter: sessionEmitter,\n\t\t\tlogger: this.logger,\n\t\t\tbatchSize: this.batchSize,\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t\tsupportedSchemaVersions: this.supportedSchemaVersions,\n\t\t\toperationTransforms: this.operationTransforms,\n\t\t\tonRelay: (sourceSessionId, operations) => {\n\t\t\t\tthis.handleRelay(sourceSessionId, operations)\n\t\t\t},\n\t\t\tonAwarenessUpdate: (sourceSessionId, message) => {\n\t\t\t\tthis.handleAwarenessRelay(sourceSessionId, message)\n\t\t\t},\n\t\t\tonYjsDocUpdate: (sourceSessionId, message) => {\n\t\t\t\tthis.handleYjsDocRelay(sourceSessionId, message)\n\t\t\t},\n\t\t\tonBlobChunkRequest: (sourceSessionId, message) => {\n\t\t\t\tthis.blobChunkRelay.handleRequest(sourceSessionId, message)\n\t\t\t},\n\t\t\tonBlobChunkResponse: (sourceSessionId, message) => {\n\t\t\t\tthis.blobChunkRelay.handleResponse(sourceSessionId, message)\n\t\t\t},\n\t\t\t...(this.persistBlobChunk ? { persistBlobChunk: this.persistBlobChunk } : {}),\n\t\t\t// Only forward when configured, so an unset server value leaves the\n\t\t\t// session on its own documented default rather than `undefined`.\n\t\t\t...(this.maxOperationBytes !== undefined\n\t\t\t\t? { maxOperationBytes: this.maxOperationBytes }\n\t\t\t\t: {}),\n\t\t\t...(this.maxOpsPerMinute !== undefined ? { maxOpsPerMinute: this.maxOpsPerMinute } : {}),\n\t\t\t...(this.validateOperation\n\t\t\t\t? { validateOperation: this.validateOperation, koraContext: this.koraContext }\n\t\t\t\t: {}),\n\t\t\tonClose: (sid) => {\n\t\t\t\tthis.handleSessionClose(sid)\n\t\t\t},\n\t\t\tonOrphanedRelays: (nodeId, ops) => {\n\t\t\t\tthis.bufferOrphanedRelays(nodeId, ops)\n\t\t\t},\n\t\t\ttakeOrphanedRelays: (nodeId) => this.takeOrphanedRelays(nodeId),\n\t\t})\n\n\t\tthis.sessions.set(sessionId, session)\n\t\tthis.yjsDocRelay.addClient(sessionId, transport)\n\t\tthis.blobChunkRelay.addClient(sessionId, transport)\n\t\tsession.start()\n\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'session.connected',\n\t\t\tsessionId,\n\t\t\tdetails: { totalSessions: this.sessions.size },\n\t\t})\n\n\t\treturn sessionId\n\t}\n\n\t/**\n\t * Get the current server status.\n\t */\n\tasync getStatus(): Promise<ServerStatus> {\n\t\tconst totalOps = await this.store.getOperationCount()\n\t\tconst snapshot = this.metrics.getSnapshot(totalOps)\n\t\treturn {\n\t\t\trunning: this.running,\n\t\t\tconnectedClients: snapshot.connectedClients,\n\t\t\tport: this.port ?? null,\n\t\t\ttotalOperations: snapshot.totalOperations,\n\t\t\tuptime: snapshot.uptime,\n\t\t\tversion: this.serverVersion,\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t\tconnectedNodeIds: snapshot.connectedNodeIds,\n\t\t\tpeakConnections: snapshot.peakConnections,\n\t\t\tconnectionsTotal: snapshot.connectionsTotal,\n\t\t\toperationsReceived: snapshot.operationsReceived,\n\t\t\toperationsSent: snapshot.operationsSent,\n\t\t\terrorCount: snapshot.errorCount,\n\t\t}\n\t}\n\n\t/**\n\t * Apply a server-originated operation (for example one created by a custom\n\t * HTTP route) through the same validated pipeline that incoming client\n\t * operations use — Tier 2 constraints, referential integrity, and cascade\n\t * side effects — then relay every applied operation to connected clients.\n\t *\n\t * Because the operation did not come from a client session, it is relayed to\n\t * ALL sessions (there is no source session to exclude). Each session still\n\t * applies its own per-scope visibility filter in `relayOperations`, so a\n\t * client only receives the operation if it falls within that client's scope.\n\t *\n\t * @param op - A fully-formed, server-originated operation to apply\n\t * @returns The apply result, including any server-generated side-effect ops\n\t */\n\tasync applyLocalOperation(op: Operation): Promise<ApplyServerOperationResult> {\n\t\tconst result = await applyServerOperation(this.store, op)\n\n\t\tif (result.result === 'applied' && result.appliedOperations.length > 0) {\n\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\tsession.relayOperations(result.appliedOperations)\n\t\t\t}\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Relay already-applied, server-originated operations to every connected client.\n\t * Used by the conditional route apply, which commits its operations atomically\n\t * through the store (bypassing {@link applyLocalOperation}) and then fans them\n\t * out. Each session still enforces its own per-scope visibility filter.\n\t *\n\t * @param operations - Operations that have already been committed to the store\n\t */\n\trelayServerOperations(operations: Operation[]): void {\n\t\tif (operations.length === 0) {\n\t\t\treturn\n\t\t}\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tsession.relayOperations(operations)\n\t\t}\n\t}\n\n\t/**\n\t * Collect every blob reference still reachable from live records on the server.\n\t *\n\t * This is the live set for garbage-collecting the server's central blob store:\n\t * pass the result to `collectBlobGarbage(blobStore, liveRefs)` from\n\t * `@korajs/store` to reclaim bytes no record references any more. Only\n\t * collections that declare a `blob` field are scanned.\n\t *\n\t * @returns Every live blob reference across all collections\n\t */\n\tasync getLiveBlobRefs(): Promise<BlobRef[]> {\n\t\tconst schema = this.store.getSchema()\n\t\tif (!schema) {\n\t\t\treturn []\n\t\t}\n\t\tconst refs: BlobRef[] = []\n\t\tfor (const [name, collection] of Object.entries(schema.collections)) {\n\t\t\tconst hasBlobField = Object.values(collection.fields).some((field) => field.kind === 'blob')\n\t\t\tif (!hasBlobField) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst records = await this.store.materializeCollection(name)\n\t\t\tfor (const record of records) {\n\t\t\t\tfor (const value of Object.values(record)) {\n\t\t\t\t\tif (isBlobRef(value)) {\n\t\t\t\t\t\trefs.push(value)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn refs\n\t}\n\n\t/**\n\t * Get the number of currently connected clients.\n\t */\n\tgetConnectionCount(): number {\n\t\treturn this.sessions.size\n\t}\n\n\t// --- Private ---\n\n\tprivate handleRelay(sourceSessionId: string, operations: Operation[]): void {\n\t\tconst targetCount = this.sessions.size - 1\n\t\tconst byteSize = estimateOperationByteSize(operations)\n\t\tthis.metrics.recordSent(\n\t\t\tsourceSessionId,\n\t\t\toperations.length * targetCount,\n\t\t\tbyteSize * targetCount,\n\t\t)\n\t\tthis.logger.log({\n\t\t\ttimestamp: Date.now(),\n\t\t\tlevel: 'info',\n\t\t\tevent: 'operations.relayed',\n\t\t\tsessionId: sourceSessionId,\n\t\t\tcount: operations.length,\n\t\t\tbytes: byteSize * targetCount,\n\t\t\tdetails: { targetSessions: targetCount },\n\t\t})\n\n\t\tfor (const [sessionId, session] of this.sessions) {\n\t\t\tif (sessionId === sourceSessionId) continue\n\t\t\tsession.relayOperations(operations)\n\t\t}\n\t}\n\n\tprivate handleSessionClose(sessionId: string): void {\n\t\tthis.metrics.recordDisconnection(sessionId)\n\t\tthis.awarenessRelay.removeClient(sessionId)\n\t\tthis.yjsDocRelay.removeClient(sessionId)\n\t\tthis.blobChunkRelay.removeClient(sessionId)\n\n\t\tthis.sessions.delete(sessionId)\n\n\t\tconst clientId = this.httpSessionToClient.get(sessionId)\n\t\tif (clientId) {\n\t\t\tthis.httpSessionToClient.delete(sessionId)\n\t\t\tthis.httpClients.delete(clientId)\n\t\t}\n\t}\n\n\tprivate handleAwarenessRelay(sourceSessionId: string, message: AwarenessUpdateMessage): void {\n\t\t// Register client with awareness relay if not already done\n\t\tconst session = this.sessions.get(sourceSessionId)\n\t\tif (!session) return\n\n\t\tconst transport = session.getTransport()\n\t\tif (!this.awarenessRelay.getClientCount() || !transport) {\n\t\t\t// First awareness update from this client -- register\n\t\t}\n\t\tthis.awarenessRelay.addClient(sourceSessionId, message.clientId, transport)\n\t\tthis.awarenessRelay.handleUpdate(sourceSessionId, message)\n\t}\n\n\tprivate handleYjsDocRelay(sourceSessionId: string, message: YjsDocUpdateMessage): void {\n\t\tif (!this.sessions.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\t\tthis.yjsDocRelay.handleUpdate(sourceSessionId, message)\n\t}\n\n\tprivate getOrCreateHttpClient(clientId: string): {\n\t\tsessionId: string\n\t\ttransport: HttpServerTransport\n\t} {\n\t\tconst existing = this.httpClients.get(clientId)\n\t\tif (existing) {\n\t\t\treturn existing\n\t\t}\n\n\t\tconst transport = new HttpServerTransport(this.serializer)\n\t\tconst sessionId = this.handleConnection(transport)\n\t\tconst client = { sessionId, transport }\n\n\t\tthis.httpClients.set(clientId, client)\n\t\tthis.httpSessionToClient.set(sessionId, clientId)\n\n\t\treturn client\n\t}\n}\n\n/**\n * Estimate the total byte size of serialized operations.\n * Used for bandwidth tracking.\n */\nfunction estimateOperationByteSize(operations: Operation[]): number {\n\tlet total = 0\n\tfor (const op of operations) {\n\t\ttotal += JSON.stringify(op).length\n\t}\n\treturn total\n}\n\nfunction normalizeHttpBody(body: string | Uint8Array, contentType?: string): string | Uint8Array {\n\tif (body instanceof Uint8Array) {\n\t\treturn body\n\t}\n\n\tif (contentType?.includes('application/x-protobuf')) {\n\t\treturn new TextEncoder().encode(body)\n\t}\n\n\treturn body\n}\n","import { generateUUIDv7 } from '@korajs/core'\nimport type { AwarenessStateWire, AwarenessUpdateMessage, SyncMessage } from '@korajs/sync'\nimport type { ServerTransport } from '../transport/server-transport'\n\n/**\n * Tracks a single client's awareness registration.\n */\ninterface AwarenessClient {\n\t/** Session ID for this client */\n\tsessionId: string\n\t/** Client-assigned awareness ID (numeric, unique per client) */\n\tclientId: number\n\t/** Transport for sending messages to this client */\n\ttransport: ServerTransport\n\t/** Current awareness state, if any */\n\tstate: AwarenessStateWire | null\n}\n\n/**\n * Server-side awareness relay. Broadcasts ephemeral awareness states\n * (cursor positions, user presence) between connected clients.\n *\n * Awareness data is never persisted. The relay simply forwards awareness\n * updates from one client to all other connected clients, and broadcasts\n * removal notifications when a client disconnects.\n */\nexport class AwarenessRelay {\n\tprivate readonly clients = new Map<string, AwarenessClient>()\n\n\t/**\n\t * Register a client for awareness broadcasting.\n\t *\n\t * @param sessionId - Unique session identifier\n\t * @param clientId - Client-assigned awareness ID\n\t * @param transport - Transport for sending messages to this client\n\t */\n\taddClient(sessionId: string, clientId: number, transport: ServerTransport): void {\n\t\tthis.clients.set(sessionId, {\n\t\t\tsessionId,\n\t\t\tclientId,\n\t\t\ttransport,\n\t\t\tstate: null,\n\t\t})\n\n\t\t// Send this client all existing awareness states so it catches up\n\t\tconst existingStates: Record<string, AwarenessStateWire | null> = {}\n\t\tlet hasStates = false\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === sessionId) continue\n\t\t\tif (client.state) {\n\t\t\t\texistingStates[String(client.clientId)] = client.state\n\t\t\t\thasStates = true\n\t\t\t}\n\t\t}\n\n\t\tif (hasStates) {\n\t\t\tconst catchUpMsg: SyncMessage = {\n\t\t\t\ttype: 'awareness-update',\n\t\t\t\tmessageId: generateUUIDv7(),\n\t\t\t\tclientId: 0, // Server-sourced\n\t\t\t\tstates: existingStates,\n\t\t\t}\n\t\t\ttransport.send(catchUpMsg)\n\t\t}\n\t}\n\n\t/**\n\t * Remove a client and broadcast its removal to all remaining clients.\n\t *\n\t * @param sessionId - Session ID of the disconnecting client\n\t */\n\tremoveClient(sessionId: string): void {\n\t\tconst client = this.clients.get(sessionId)\n\t\tif (!client) return\n\n\t\tthis.clients.delete(sessionId)\n\n\t\t// Only broadcast removal if the client had an awareness state\n\t\tif (client.state === null) return\n\n\t\tconst removalStates: Record<string, AwarenessStateWire | null> = {\n\t\t\t[String(client.clientId)]: null,\n\t\t}\n\n\t\tconst msg: SyncMessage = {\n\t\t\ttype: 'awareness-update',\n\t\t\tmessageId: generateUUIDv7(),\n\t\t\tclientId: client.clientId,\n\t\t\tstates: removalStates,\n\t\t}\n\n\t\tthis.broadcastExcept(sessionId, msg)\n\t}\n\n\t/**\n\t * Handle an incoming awareness update from a client.\n\t * Stores the state and relays to all other connected clients.\n\t *\n\t * @param sessionId - Session ID of the sending client\n\t * @param message - The awareness update message\n\t */\n\thandleUpdate(sessionId: string, message: AwarenessUpdateMessage): void {\n\t\tconst sender = this.clients.get(sessionId)\n\t\tif (!sender) return\n\n\t\t// Update stored state for this client\n\t\tconst senderState = message.states[String(message.clientId)]\n\t\tif (senderState !== undefined) {\n\t\t\tsender.state = senderState\n\t\t}\n\n\t\t// Relay to all other clients\n\t\tthis.broadcastExcept(sessionId, message)\n\t}\n\n\t/**\n\t * Get the number of registered awareness clients.\n\t */\n\tgetClientCount(): number {\n\t\treturn this.clients.size\n\t}\n\n\t/**\n\t * Remove all clients and clear all state.\n\t */\n\tclear(): void {\n\t\tthis.clients.clear()\n\t}\n\n\t// --- Private ---\n\n\tprivate broadcastExcept(excludeSessionId: string, message: SyncMessage): void {\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === excludeSessionId) continue\n\t\t\tif (!client.transport.isConnected()) continue\n\n\t\t\tclient.transport.send(message)\n\t\t}\n\t}\n}\n","import type { AuthContext, SessionState } from '../types'\n\n/**\n * Snapshot of server-side sync metrics at a point in time.\n */\nexport interface ServerMetricsSnapshot {\n\tconnectedClients: number\n\tconnectedNodeIds: string[]\n\tpeakConnections: number\n\tconnectionsTotal: number\n\toperationsReceived: number\n\tbatchesReceived: number\n\tuniqueOperationsReceived: number\n\tduplicateOperationsReceived: number\n\trejectedOperations: number\n\toperationsSent: number\n\tbytesReceived: number\n\tbytesSent: number\n\tclients: ClientMetrics[]\n\tuptime: number\n\ttotalOperations: number\n\terrorCount: number\n\tschemaVersion: number\n}\n\n/**\n * Per-client metrics tracked by the server.\n */\nexport interface ClientMetrics {\n\tsessionId: string\n\tnodeId: string | null\n\tstate: SessionState\n\tconnectedAt: number\n\toperationsReceived: number\n\tbatchesReceived: number\n\tuniqueOperationsReceived: number\n\tduplicateOperationsReceived: number\n\trejectedOperations: number\n\toperationsSent: number\n\tauthContext: AuthContext | null\n}\n\n/**\n * Collects and aggregates server-side sync metrics.\n *\n * Tracks connected clients, throughput, error counts, and per-session\n * metadata. Designed to be hooked into KoraSyncServer lifecycle events.\n */\n/**\n * Estimate the byte size of a batch of operations.\n * Used for bandwidth tracking in sync events.\n * Each operation is approximated by JSON-serializing and measuring length.\n */\nexport function estimateByteSize(operations: Array<unknown>): number {\n\tlet total = 0\n\tfor (const op of operations) {\n\t\ttotal += JSON.stringify(op).length\n\t}\n\treturn total\n}\n\nexport class ServerMetricsCollector {\n\tprivate startedAt = Date.now()\n\n\tprivate peakConnections = 0\n\tprivate connectionsTotal = 0\n\tprivate operationsReceived = 0\n\tprivate batchesReceived = 0\n\tprivate uniqueOperationsReceived = 0\n\tprivate duplicateOperationsReceived = 0\n\tprivate rejectedOperations = 0\n\tprivate operationsSent = 0\n\tprivate bytesReceived = 0\n\tprivate bytesSent = 0\n\tprivate errorCount = 0\n\tprivate schemaVersion = 1\n\n\tprivate readonly clientMetrics = new Map<string, ClientMetrics>()\n\n\t/** Record a new client connection. */\n\trecordConnection(sessionId: string): void {\n\t\tthis.connectionsTotal++\n\t\tthis.clientMetrics.set(sessionId, {\n\t\t\tsessionId,\n\t\t\tnodeId: null,\n\t\t\tstate: 'connected',\n\t\t\tconnectedAt: Date.now(),\n\t\t\toperationsReceived: 0,\n\t\t\tbatchesReceived: 0,\n\t\t\tuniqueOperationsReceived: 0,\n\t\t\tduplicateOperationsReceived: 0,\n\t\t\trejectedOperations: 0,\n\t\t\toperationsSent: 0,\n\t\t\tauthContext: null,\n\t\t})\n\t\tthis.peakConnections = Math.max(this.peakConnections, this.clientMetrics.size)\n\t}\n\n\t/** Record a client disconnection. */\n\trecordDisconnection(sessionId: string): void {\n\t\tthis.clientMetrics.delete(sessionId)\n\t}\n\n\t/** Update the node ID after a handshake completes. */\n\trecordHandshake(sessionId: string, nodeId: string): void {\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.nodeId = nodeId\n\t\t}\n\t}\n\n\t/** Update session state. */\n\tupdateSessionState(sessionId: string, state: SessionState): void {\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.state = state\n\t\t}\n\t}\n\n\t/** Record authentication context for a session. */\n\trecordAuth(sessionId: string, authContext: AuthContext | null): void {\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.authContext = authContext\n\t\t}\n\t}\n\n\t/** Record operations received from a client. */\n\trecordReceived(\n\t\tsessionId: string,\n\t\tcount: number,\n\t\tbyteSize: number,\n\t\toutcomes: { unique: number; duplicates: number; rejected: number } = {\n\t\t\tunique: count,\n\t\t\tduplicates: 0,\n\t\t\trejected: 0,\n\t\t},\n\t): void {\n\t\tthis.operationsReceived += count\n\t\tthis.batchesReceived += 1\n\t\tthis.uniqueOperationsReceived += outcomes.unique\n\t\tthis.duplicateOperationsReceived += outcomes.duplicates\n\t\tthis.rejectedOperations += outcomes.rejected\n\t\tthis.bytesReceived += byteSize\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.operationsReceived += count\n\t\t\tclient.batchesReceived += 1\n\t\t\tclient.uniqueOperationsReceived += outcomes.unique\n\t\t\tclient.duplicateOperationsReceived += outcomes.duplicates\n\t\t\tclient.rejectedOperations += outcomes.rejected\n\t\t}\n\t}\n\n\t/** Record operations sent to a client. */\n\trecordSent(sessionId: string, count: number, byteSize: number): void {\n\t\tthis.operationsSent += count\n\t\tthis.bytesSent += byteSize\n\t\tconst client = this.clientMetrics.get(sessionId)\n\t\tif (client) {\n\t\t\tclient.operationsSent += count\n\t\t}\n\t}\n\n\t/** Record an error. */\n\trecordError(): void {\n\t\tthis.errorCount++\n\t}\n\n\t/** Set the schema version. */\n\tsetSchemaVersion(version: number): void {\n\t\tthis.schemaVersion = version\n\t}\n\n\t/** Return a full snapshot of current metrics. */\n\tgetSnapshot(totalOperations: number): ServerMetricsSnapshot {\n\t\treturn {\n\t\t\tconnectedClients: this.clientMetrics.size,\n\t\t\tconnectedNodeIds: Array.from(this.clientMetrics.values())\n\t\t\t\t.filter((c) => c.nodeId !== null)\n\t\t\t\t.map((c) => c.nodeId as string),\n\t\t\tpeakConnections: this.peakConnections,\n\t\t\tconnectionsTotal: this.connectionsTotal,\n\t\t\toperationsReceived: this.operationsReceived,\n\t\t\tbatchesReceived: this.batchesReceived,\n\t\t\tuniqueOperationsReceived: this.uniqueOperationsReceived,\n\t\t\tduplicateOperationsReceived: this.duplicateOperationsReceived,\n\t\t\trejectedOperations: this.rejectedOperations,\n\t\t\toperationsSent: this.operationsSent,\n\t\t\tbytesReceived: this.bytesReceived,\n\t\t\tbytesSent: this.bytesSent,\n\t\t\tclients: Array.from(this.clientMetrics.values()),\n\t\t\tuptime: Date.now() - this.startedAt,\n\t\t\ttotalOperations,\n\t\t\terrorCount: this.errorCount,\n\t\t\tschemaVersion: this.schemaVersion,\n\t\t}\n\t}\n\n\t/** Reset all metrics. */\n\treset(): void {\n\t\tthis.startedAt = Date.now()\n\t\tthis.peakConnections = 0\n\t\tthis.connectionsTotal = 0\n\t\tthis.operationsReceived = 0\n\t\tthis.batchesReceived = 0\n\t\tthis.uniqueOperationsReceived = 0\n\t\tthis.duplicateOperationsReceived = 0\n\t\tthis.rejectedOperations = 0\n\t\tthis.operationsSent = 0\n\t\tthis.bytesReceived = 0\n\t\tthis.bytesSent = 0\n\t\tthis.errorCount = 0\n\t\tthis.clientMetrics.clear()\n\t}\n}\n","import {\n\ttype BlobChunkRequestMessage,\n\ttype BlobChunkResponseMessage,\n\tencodeBlobChunkBytes,\n} from '@korajs/sync'\nimport type { ServerTransport } from '../transport/server-transport'\n\n/**\n * Resolves a blob chunk by content hash from server-side storage. Optional: when\n * provided, the server can answer chunk requests directly from its own store\n * (central-store deployment). When absent, the server acts as a pure relay,\n * forwarding chunk requests to peer sessions and their responses back.\n */\nexport type ResolveBlobChunk = (hash: string) => Promise<Uint8Array | null>\n\ninterface RelayClient {\n\tsessionId: string\n\ttransport: ServerTransport\n}\n\n/**\n * Routes out-of-band blob chunk transfer between connected clients (and,\n * optionally, a server-side blob store).\n *\n * The server never stores or inspects blob bytes on the relay path: a\n * `blob-chunk-request` is forwarded to peer sessions, and the first peer to\n * answer with the bytes has its `blob-chunk-response` routed back to the\n * original requester by `requestId`. Blob bytes never enter the operation log;\n * only the `BlobRef` reference inside a record does.\n *\n * Not persisted — this is an ephemeral side channel, like the Yjs doc relay.\n */\nexport class BlobChunkRelay {\n\tprivate readonly clients = new Map<string, RelayClient>()\n\t/** requestId -> the session that originated the request (to route the answer back). */\n\tprivate readonly pending = new Map<string, string>()\n\tprivate readonly resolveBlobChunk: ResolveBlobChunk | null\n\n\tconstructor(resolveBlobChunk?: ResolveBlobChunk) {\n\t\tthis.resolveBlobChunk = resolveBlobChunk ?? null\n\t}\n\n\taddClient(sessionId: string, transport: ServerTransport): void {\n\t\tthis.clients.set(sessionId, { sessionId, transport })\n\t}\n\n\tremoveClient(sessionId: string): void {\n\t\tthis.clients.delete(sessionId)\n\t\t// Drop any requests this session was waiting on; their answers can no\n\t\t// longer be delivered.\n\t\tfor (const [requestId, originSessionId] of this.pending) {\n\t\t\tif (originSessionId === sessionId) {\n\t\t\t\tthis.pending.delete(requestId)\n\t\t\t}\n\t\t}\n\t}\n\n\tgetClientCount(): number {\n\t\treturn this.clients.size\n\t}\n\n\tgetPendingCount(): number {\n\t\treturn this.pending.size\n\t}\n\n\tclear(): void {\n\t\tthis.clients.clear()\n\t\tthis.pending.clear()\n\t}\n\n\t/**\n\t * Handle an inbound chunk request from a session. Tries the server's own\n\t * store first (if configured), otherwise forwards the request to peer\n\t * sessions and remembers who to route the answer back to.\n\t */\n\thandleRequest(sourceSessionId: string, message: BlobChunkRequestMessage): void {\n\t\tif (!this.clients.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\n\t\tif (this.resolveBlobChunk) {\n\t\t\tvoid this.resolveBlobChunk(message.hash).then(\n\t\t\t\t(bytes) => {\n\t\t\t\t\tif (bytes !== null) {\n\t\t\t\t\t\tthis.sendResponseTo(sourceSessionId, message.requestId, encodeBlobChunkBytes(bytes))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tthis.forwardRequestToPeers(sourceSessionId, message)\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\t// A store read error is treated as \"not held here\": fall back to peers\n\t\t\t\t\t// rather than crashing the connection.\n\t\t\t\t\tthis.forwardRequestToPeers(sourceSessionId, message)\n\t\t\t\t},\n\t\t\t)\n\t\t\treturn\n\t\t}\n\n\t\tthis.forwardRequestToPeers(sourceSessionId, message)\n\t}\n\n\t/**\n\t * Handle an inbound chunk response from a peer. Routes it back to the session\n\t * that originally requested it. A \"not held\" answer (bytes === null) is\n\t * ignored so a peer without the chunk does not preempt one that has it; the\n\t * requester's own per-request timeout bounds the wait.\n\t */\n\thandleResponse(sourceSessionId: string, message: BlobChunkResponseMessage): void {\n\t\tif (!this.clients.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\t\tif (message.bytes === null) {\n\t\t\treturn\n\t\t}\n\t\tconst originSessionId = this.pending.get(message.requestId)\n\t\tif (!originSessionId) {\n\t\t\treturn\n\t\t}\n\t\tthis.pending.delete(message.requestId)\n\t\tthis.sendResponseTo(originSessionId, message.requestId, message.bytes)\n\t}\n\n\tprivate forwardRequestToPeers(sourceSessionId: string, message: BlobChunkRequestMessage): void {\n\t\tthis.pending.set(message.requestId, sourceSessionId)\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === sourceSessionId) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (!client.transport.isConnected()) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tclient.transport.send(message)\n\t\t}\n\t}\n\n\tprivate sendResponseTo(sessionId: string, requestId: string, bytes: string): void {\n\t\tconst client = this.clients.get(sessionId)\n\t\tif (!client || !client.transport.isConnected()) {\n\t\t\treturn\n\t\t}\n\t\tconst response: BlobChunkResponseMessage = {\n\t\t\ttype: 'blob-chunk-response',\n\t\t\tmessageId: generateResponseId(requestId),\n\t\t\trequestId,\n\t\t\tbytes,\n\t\t}\n\t\tclient.transport.send(response)\n\t}\n}\n\n/**\n * Derive a deterministic wire messageId for a routed response. The correlation\n * that matters is `requestId`; `messageId` only needs to be a non-empty string,\n * so deriving it avoids a clock/random dependency in the relay.\n */\nfunction generateResponseId(requestId: string): string {\n\treturn `blob-resp-${requestId}`\n}\n","import type { SyncMessage, YjsDocUpdateMessage } from '@korajs/sync'\nimport type { ServerTransport } from '../transport/server-transport'\n\ninterface RelayClient {\n\tsessionId: string\n\ttransport: ServerTransport\n}\n\n/**\n * Relays ephemeral Yjs doc channel updates between connected clients.\n * Not persisted — durable richtext state still flows through the operation log.\n */\nexport class YjsDocRelay {\n\tprivate readonly clients = new Map<string, RelayClient>()\n\n\taddClient(sessionId: string, transport: ServerTransport): void {\n\t\tthis.clients.set(sessionId, { sessionId, transport })\n\t}\n\n\tremoveClient(sessionId: string): void {\n\t\tthis.clients.delete(sessionId)\n\t}\n\n\thandleUpdate(sourceSessionId: string, message: YjsDocUpdateMessage): void {\n\t\tif (!this.clients.has(sourceSessionId)) {\n\t\t\treturn\n\t\t}\n\t\tthis.broadcastExcept(sourceSessionId, message)\n\t}\n\n\tgetClientCount(): number {\n\t\treturn this.clients.size\n\t}\n\n\tclear(): void {\n\t\tthis.clients.clear()\n\t}\n\n\tprivate broadcastExcept(excludeSessionId: string, message: SyncMessage): void {\n\t\tfor (const [, client] of this.clients) {\n\t\t\tif (client.sessionId === excludeSessionId) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (!client.transport.isConnected()) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tclient.transport.send(message)\n\t\t}\n\t}\n}\n","import {\n\ttype AtomicOp,\n\tHybridLogicalClock,\n\ttype Operation,\n\tcreateOperation,\n\tgenerateUUIDv7,\n\tisAtomicOp,\n\tresolveAtomicOp,\n\ttoAtomicOp,\n} from '@korajs/core'\nimport { isRetriableRejection } from '../apply/rejection-taxonomy'\nimport { type RoutePredicate, evaluateRoutePredicate } from '../apply/route-predicate'\nimport { nextServerSequenceNumber } from '../apply/server-side-effect-operation'\nimport type { ScopeMap } from '../scopes/server-scope-filter'\nimport { operationMatchesScopes } from '../scopes/server-scope-filter'\nimport type {\n\tCollectionQueryOptions,\n\tConditionalApplyInput,\n\tConditionalApplyResult,\n\tMaterializedRecord,\n\tServerStore,\n} from '../store/server-store'\nimport type { KoraSyncServer } from './kora-sync-server'\n\n/**\n * A mutation a custom HTTP route asks the server to apply on the data plane.\n *\n * `recordId` is optional for inserts (a UUID v7 is generated when omitted) and\n * required for updates and deletes. For updates, `data` holds only the changed\n * fields; the server reads the current record to capture the previous values so\n * the change three-way merges correctly with concurrent client edits.\n */\nexport interface RouteMutation {\n\tcollection: string\n\ttype: 'insert' | 'update' | 'delete'\n\trecordId?: string\n\tdata?: Record<string, unknown> | null\n}\n\n/**\n * Scope the route derived from the request's authenticated actor. When present,\n * it is enforced exactly like a sync session's scope: `apply()` rejects a\n * mutation whose resulting record falls outside the scope, and `query()` /\n * `findById()` only return records inside it. Omit it for genuinely public\n * routes (for example a signup endpoint) where no per-actor isolation applies.\n */\nexport interface RouteScopeOptions {\n\tscope?: ScopeMap\n}\n\n/** Result of {@link ProductionHttpRouteContext.apply}. */\nexport type RouteApplyResult =\n\t| { ok: true; operation: Operation; record: MaterializedRecord | null }\n\t| { ok: false; code: string; message: string; retriable: boolean }\n\n/**\n * A conditional, multi-collection admission gate applied atomically per instance.\n *\n * The gate reads the current state of the target record (`collection` + `id`),\n * checks the `if` predicate against it, and only then applies the `update` to the\n * target plus every mutation in `also` as one set. If the predicate fails it\n * applies nothing and returns the structured `reject`. `idempotencyKey` names a\n * record whose prior existence proves the set already committed, so a retry\n * returns the earlier outcome instead of applying the set (and its non-idempotent\n * counter increments) again.\n *\n * Atomicity note: within one server instance the check and the writes do not\n * interleave with other route mutations. Cross-instance, race-free admission and\n * all-or-nothing across a mid-set crash require the store-level conditional\n * transaction (a Postgres `WHERE ... < cap` commit), which is the next increment.\n */\nexport interface RouteConditionalApply {\n\t/** Collection of the record the predicate reads and the `update` targets. */\n\tcollection: string\n\t/** Id of the target record. */\n\tid: string\n\t/** Admission predicate evaluated against the target's current state. */\n\tif?: RoutePredicate\n\t/** Partial update applied to the target record when the predicate holds. */\n\tupdate?: Record<string, unknown> | null\n\t/** Additional mutations committed atomically with the target update. */\n\talso?: RouteMutation[]\n\t/** Structured rejection returned when the predicate does not hold. */\n\treject?: { code: string; message: string }\n\t/**\n\t * Names a record whose existence means this set already committed. When it is\n\t * present the set is skipped and the prior outcome returned. Use a stable,\n\t * client-generated id (for example the accepted record's own id).\n\t */\n\tidempotencyKey?: { collection: string; id: string }\n}\n\n/** Result of {@link ProductionHttpRouteContext.applyConditional}. */\nexport type RouteConditionalResult =\n\t| {\n\t\t\tok: true\n\t\t\t/** True when the set was already committed and this call was a no-op. */\n\t\t\tidempotent: boolean\n\t\t\toperations: Operation[]\n\t\t\trecords: (MaterializedRecord | null)[]\n\t }\n\t| { ok: false; code: string; message: string; retriable: boolean }\n\n/**\n * Scoped, validated data-plane access handed to custom HTTP route handlers.\n *\n * Every mutation goes through the same pipeline as sync (Tier 2 constraints,\n * referential integrity, materialization, and fan-out to connected clients), so\n * REST endpoints cannot accidentally bypass validation, constraints, or tenant\n * isolation the way hand-rolled store writes can.\n */\nexport interface ProductionHttpRouteContext {\n\t/**\n\t * Apply a mutation through the validated server pipeline and relay the\n\t * resulting operation(s) to connected clients.\n\t */\n\tapply(mutation: RouteMutation, options?: RouteScopeOptions): Promise<RouteApplyResult>\n\t/**\n\t * Conditionally apply a multi-collection mutation set as one admission gate:\n\t * read the target, check the predicate, and commit the update plus every `also`\n\t * mutation only if it holds, with at-most-once semantics via `idempotencyKey`.\n\t */\n\tapplyConditional(\n\t\tspec: RouteConditionalApply,\n\t\toptions?: RouteScopeOptions,\n\t): Promise<RouteConditionalResult>\n\t/** Read materialized records from a collection, optionally scoped. */\n\tquery(\n\t\tcollection: string,\n\t\toptions?: CollectionQueryOptions & RouteScopeOptions,\n\t): Promise<MaterializedRecord[]>\n\t/** Read a single materialized record by id, optionally scoped. */\n\tfindById(\n\t\tcollection: string,\n\t\tid: string,\n\t\toptions?: RouteScopeOptions,\n\t): Promise<MaterializedRecord | null>\n}\n\n/**\n * Returns true when a materialized record satisfies the scope declared for its\n * collection. A collection absent from the scope map is treated as out of scope\n * (hidden), mirroring `operationMatchesScopes` on the write path.\n */\nfunction recordMatchesScope(\n\tcollection: string,\n\trecord: MaterializedRecord,\n\tscope: ScopeMap,\n): boolean {\n\tconst collectionScope = scope[collection]\n\tif (!collectionScope) {\n\t\treturn false\n\t}\n\tfor (const [field, expected] of Object.entries(collectionScope)) {\n\t\tif (record[field] !== expected) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n/** Picks only the given keys from a record (used to capture previousData). */\nfunction pickFields(record: Record<string, unknown>, keys: string[]): Record<string, unknown> {\n\tconst picked: Record<string, unknown> = {}\n\tfor (const key of keys) {\n\t\tif (key in record) {\n\t\t\tpicked[key] = record[key]\n\t\t}\n\t}\n\treturn picked\n}\n\n/**\n * Build a server-originated operation for a route mutation, reading current\n * materialized state so updates and deletes carry accurate previous values.\n *\n * `currentOverride`, when provided, supplies that current state instead of reading\n * it from the store. The conditional apply passes the record it read under the\n * cross-instance lock, so an atomic-op update (for example `op.increment`) resolves\n * against the authoritative locked value rather than a stale read.\n *\n * `clockOverride`, when provided, stamps the operation instead of a fresh clock. The\n * cross-instance conditional apply passes a clock the store advanced past the target\n * record's latest write, so the operation sorts strictly after it and last-write-wins\n * materialization matches the serialized commit order.\n */\nasync function buildRouteOperation(\n\tstore: ServerStore,\n\tmutation: RouteMutation,\n\tcurrentOverride?: { record: MaterializedRecord | null },\n\tclockOverride?: HybridLogicalClock,\n): Promise<Operation> {\n\tconst nodeId = store.getNodeId()\n\tconst clock = clockOverride ?? new HybridLogicalClock(nodeId)\n\tconst schemaVersion = store.getSchema()?.version ?? 1\n\tconst sequenceNumber = nextServerSequenceNumber(store)\n\n\tif (mutation.type === 'insert') {\n\t\treturn createOperation(\n\t\t\t{\n\t\t\t\tnodeId,\n\t\t\t\ttype: 'insert',\n\t\t\t\tcollection: mutation.collection,\n\t\t\t\trecordId: mutation.recordId ?? generateUUIDv7(),\n\t\t\t\tdata: mutation.data ?? {},\n\t\t\t\tpreviousData: null,\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps: [],\n\t\t\t\tschemaVersion,\n\t\t\t},\n\t\t\tclock,\n\t\t)\n\t}\n\n\tif (!mutation.recordId) {\n\t\tthrow new RouteMutationError(\n\t\t\t'MISSING_RECORD_ID',\n\t\t\t`A ${mutation.type} mutation on \"${mutation.collection}\" requires a recordId.`,\n\t\t)\n\t}\n\n\tconst current = currentOverride\n\t\t? currentOverride.record\n\t\t: await store.findRecord(mutation.collection, mutation.recordId)\n\n\tif (mutation.type === 'update') {\n\t\tconst rawData = mutation.data ?? {}\n\t\t// Resolve atomic-op sentinels (op.increment, op.max, ...) exactly as the\n\t\t// client's update path does: `data` carries the concrete resolved value for\n\t\t// materialization, and `atomicOps` carries the intent so concurrent atomic\n\t\t// writes compose in the merge engine instead of last-write-wins.\n\t\tconst data: Record<string, unknown> = {}\n\t\tconst atomicOps: Record<string, AtomicOp> = {}\n\t\tfor (const key of Object.keys(rawData)) {\n\t\t\tconst value = rawData[key]\n\t\t\tif (isAtomicOp(value)) {\n\t\t\t\tdata[key] = resolveAtomicOp(current ? current[key] : undefined, value)\n\t\t\t\tatomicOps[key] = toAtomicOp(value)\n\t\t\t} else {\n\t\t\t\tdata[key] = value\n\t\t\t}\n\t\t}\n\t\treturn createOperation(\n\t\t\t{\n\t\t\t\tnodeId,\n\t\t\t\ttype: 'update',\n\t\t\t\tcollection: mutation.collection,\n\t\t\t\trecordId: mutation.recordId,\n\t\t\t\tdata,\n\t\t\t\tpreviousData: current ? pickFields(current, Object.keys(rawData)) : {},\n\t\t\t\tsequenceNumber,\n\t\t\t\tcausalDeps: [],\n\t\t\t\tschemaVersion,\n\t\t\t\t...(Object.keys(atomicOps).length > 0 ? { atomicOps } : {}),\n\t\t\t},\n\t\t\tclock,\n\t\t)\n\t}\n\n\t// delete\n\treturn createOperation(\n\t\t{\n\t\t\tnodeId,\n\t\t\ttype: 'delete',\n\t\t\tcollection: mutation.collection,\n\t\t\trecordId: mutation.recordId,\n\t\t\tdata: null,\n\t\t\tpreviousData: current ? { ...current } : null,\n\t\t\tsequenceNumber,\n\t\t\tcausalDeps: [],\n\t\t\tschemaVersion,\n\t\t},\n\t\tclock,\n\t)\n}\n\n/** Internal error carrying a stable code for route-context failures. */\nclass RouteMutationError extends Error {\n\tconstructor(\n\t\treadonly code: string,\n\t\tmessage: string,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'RouteMutationError'\n\t}\n}\n\n/**\n * Create the scoped, validated data-plane context handed to custom HTTP route\n * handlers as `request.kora`.\n *\n * Mutations are serialized so concurrent requests cannot race on server\n * sequence-number allocation: each `apply()` builds and applies its operation\n * before the next begins.\n */\nexport function createRouteContext(\n\tserver: KoraSyncServer,\n\tstore: ServerStore,\n): ProductionHttpRouteContext {\n\t// Promise chain that serializes apply() so sequence allocation + apply is\n\t// atomic per mutation, even under concurrent in-flight requests.\n\tlet mutationTail: Promise<unknown> = Promise.resolve()\n\n\tfunction serialize<T>(work: () => Promise<T>): Promise<T> {\n\t\tconst run = mutationTail.then(work, work)\n\t\t// Keep the tail from rejecting so one failed mutation does not poison the\n\t\t// chain for subsequent ones.\n\t\tmutationTail = run.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t)\n\t\treturn run\n\t}\n\n\t// Build a route operation and check scope, WITHOUT applying it. Splitting\n\t// preparation from commit lets applyConditional validate an entire mutation set\n\t// before committing any of it, so a scope violation or malformed mutation in\n\t// `also` cannot leave the target update (for example a counter increment)\n\t// committed while the rest is rejected.\n\ttype RouteRejection = { ok: false; code: string; message: string; retriable: boolean }\n\ttype PreparedMutation = { ok: true; op: Operation } | { ok: false; rejection: RouteRejection }\n\tasync function prepareMutation(\n\t\tmutation: RouteMutation,\n\t\tscope: ScopeMap | undefined,\n\t): Promise<PreparedMutation> {\n\t\tlet op: Operation\n\t\ttry {\n\t\t\top = await buildRouteOperation(store, mutation)\n\t\t} catch (error) {\n\t\t\tif (error instanceof RouteMutationError) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\trejection: {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\tcode: error.code,\n\t\t\t\t\t\tmessage: error.message,\n\t\t\t\t\t\tretriable: isRetriableRejection(error.code),\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\tif (scope && !operationMatchesScopes(op, scope)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\trejection: {\n\t\t\t\t\tok: false,\n\t\t\t\t\tcode: 'SCOPE_VIOLATION',\n\t\t\t\t\tmessage: `Mutation on \"${mutation.collection}\" is outside the provided scope.`,\n\t\t\t\t\tretriable: isRetriableRejection('SCOPE_VIOLATION'),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\treturn { ok: true, op }\n\t}\n\n\t// Apply a prepared operation and read back the resulting record.\n\tasync function commitOperation(op: Operation, collection: string): Promise<RouteApplyResult> {\n\t\tconst result = await server.applyLocalOperation(op)\n\t\tif (result.result !== 'applied') {\n\t\t\tconst code = result.rejection?.code ?? 'NOT_APPLIED'\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tcode,\n\t\t\t\tmessage:\n\t\t\t\t\tresult.rejection?.message ??\n\t\t\t\t\t`Operation on \"${collection}\" was not applied (${result.result}).`,\n\t\t\t\t// Prefer the pipeline's own classification when present; fall back\n\t\t\t\t// to classifying the code so this stays correct if new codes appear.\n\t\t\t\tretriable: result.rejection?.retriable ?? isRetriableRejection(code),\n\t\t\t}\n\t\t}\n\n\t\tconst record = await store.findRecord(collection, op.recordId)\n\t\treturn { ok: true, operation: op, record }\n\t}\n\n\t// The un-serialized core of a single mutation. Both apply() and\n\t// applyConditional() call this inside a serialized block, so it must NOT\n\t// serialize itself (that would deadlock the promise-chain tail).\n\tasync function rawApply(\n\t\tmutation: RouteMutation,\n\t\tscope: ScopeMap | undefined,\n\t): Promise<RouteApplyResult> {\n\t\tconst prepared = await prepareMutation(mutation, scope)\n\t\tif (!prepared.ok) {\n\t\t\treturn prepared.rejection\n\t\t}\n\t\treturn commitOperation(prepared.op, mutation.collection)\n\t}\n\n\t// Cross-instance conditional apply, delegating admission and atomicity to the\n\t// store (the Postgres advisory-lock transaction). The store owns the\n\t// read-decide-write cycle so a cap check is race-free across instances; this\n\t// bridge translates the route spec into the store's callback shape, validates\n\t// scope on each built operation while still inside the locked transaction (so a\n\t// violation rolls everything back), then relays the committed set to clients.\n\tasync function runConditionalViaStore(\n\t\tstoreApplyConditional: (input: ConditionalApplyInput) => Promise<ConditionalApplyResult>,\n\t\tspec: RouteConditionalApply,\n\t\toptions: RouteScopeOptions | undefined,\n\t): Promise<RouteConditionalResult> {\n\t\tconst scope = options?.scope\n\n\t\t// Assemble the set: the target update (when given) first, then every `also`.\n\t\tconst mutations: RouteMutation[] = []\n\t\tconst hasTargetUpdate = spec.update !== undefined && spec.update !== null\n\t\tif (hasTargetUpdate) {\n\t\t\tmutations.push({\n\t\t\t\tcollection: spec.collection,\n\t\t\t\ttype: 'update',\n\t\t\t\trecordId: spec.id,\n\t\t\t\tdata: spec.update,\n\t\t\t})\n\t\t}\n\t\tif (spec.also) {\n\t\t\tmutations.push(...spec.also)\n\t\t}\n\n\t\tlet result: ConditionalApplyResult\n\t\ttry {\n\t\t\tresult = await storeApplyConditional({\n\t\t\t\ttarget: { collection: spec.collection, id: spec.id },\n\t\t\t\t...(spec.idempotencyKey ? { idempotencyKey: spec.idempotencyKey } : {}),\n\t\t\t\tadmit: (current) =>\n\t\t\t\t\tspec.if && Object.keys(spec.if).length > 0\n\t\t\t\t\t\t? evaluateRoutePredicate(current, spec.if)\n\t\t\t\t\t\t: true,\n\t\t\t\tbuildOperations: async (current, context) => {\n\t\t\t\t\tconst ops: Operation[] = []\n\t\t\t\t\tfor (let i = 0; i < mutations.length; i++) {\n\t\t\t\t\t\tconst mutation = mutations[i] as RouteMutation\n\t\t\t\t\t\t// The target update (index 0 when present) resolves its atomic ops\n\t\t\t\t\t\t// against the locked `current`; `also` mutations address distinct\n\t\t\t\t\t\t// records and read their own current state from the store. Every op\n\t\t\t\t\t\t// is stamped with the store-provided clock so the set sorts strictly\n\t\t\t\t\t\t// after the target's latest committed write.\n\t\t\t\t\t\tconst useLockedCurrent = i === 0 && hasTargetUpdate\n\t\t\t\t\t\tconst op = await buildRouteOperation(\n\t\t\t\t\t\t\tstore,\n\t\t\t\t\t\t\tmutation,\n\t\t\t\t\t\t\tuseLockedCurrent ? { record: current } : undefined,\n\t\t\t\t\t\t\tcontext.clock,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t// Validate scope inside the locked transaction. Throwing here rolls\n\t\t\t\t\t\t// the transaction back, so a violation in any mutation applies nothing.\n\t\t\t\t\t\tif (scope && !operationMatchesScopes(op, scope)) {\n\t\t\t\t\t\t\tthrow new RouteMutationError(\n\t\t\t\t\t\t\t\t'SCOPE_VIOLATION',\n\t\t\t\t\t\t\t\t`Mutation on \"${mutation.collection}\" is outside the provided scope.`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tops.push(op)\n\t\t\t\t\t}\n\t\t\t\t\treturn ops\n\t\t\t\t},\n\t\t\t})\n\t\t} catch (error) {\n\t\t\t// A malformed mutation or scope violation surfaced from inside the locked\n\t\t\t// transaction (which rolled back) becomes a structured rejection, not a 500.\n\t\t\tif (error instanceof RouteMutationError) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tcode: error.code,\n\t\t\t\t\tmessage: error.message,\n\t\t\t\t\tretriable: isRetriableRejection(error.code),\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\t// Predicate failed under the lock: nothing was applied.\n\t\tif (!result.admitted) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tcode: spec.reject?.code ?? 'CONDITION_NOT_MET',\n\t\t\t\tmessage:\n\t\t\t\t\tspec.reject?.message ??\n\t\t\t\t\t`Admission condition not met on \"${spec.collection}\" record \"${spec.id}\".`,\n\t\t\t\tretriable: false,\n\t\t\t}\n\t\t}\n\n\t\t// Idempotent hit: the set committed on an earlier attempt. Return the anchor's\n\t\t// committed state without re-applying (so counter increments run at most once).\n\t\tif (result.idempotent) {\n\t\t\tconst records: (MaterializedRecord | null)[] = spec.idempotencyKey\n\t\t\t\t? [await store.findRecord(spec.idempotencyKey.collection, spec.idempotencyKey.id)]\n\t\t\t\t: []\n\t\t\treturn { ok: true, idempotent: true, operations: [], records }\n\t\t}\n\n\t\t// Admitted and committed. Fan the operations out to connected clients (each\n\t\t// session re-applies its own scope filter), then read back each record.\n\t\tserver.relayServerOperations(result.applied)\n\t\tconst records: (MaterializedRecord | null)[] = []\n\t\tfor (const op of result.applied) {\n\t\t\trecords.push(await store.findRecord(op.collection, op.recordId))\n\t\t}\n\t\treturn { ok: true, idempotent: false, operations: result.applied, records }\n\t}\n\n\treturn {\n\t\tapply(mutation, options): Promise<RouteApplyResult> {\n\t\t\treturn serialize(() => rawApply(mutation, options?.scope))\n\t\t},\n\n\t\tapplyConditional(spec, options): Promise<RouteConditionalResult> {\n\t\t\t// Prefer the store's cross-instance conditional apply when available (the\n\t\t\t// Postgres store): it serializes the admission on the target across every\n\t\t\t// server instance via an advisory lock, so a cap check is race-free even\n\t\t\t// under concurrent admissions on different instances. Stores without it\n\t\t\t// (single-process SQLite / in-memory) use the per-instance serialized path\n\t\t\t// below, which is correct because there is only one instance.\n\t\t\tconst storeApplyConditional = store.applyConditional\n\t\t\tif (storeApplyConditional) {\n\t\t\t\treturn runConditionalViaStore(storeApplyConditional.bind(store), spec, options)\n\t\t\t}\n\t\t\treturn serialize(async () => {\n\t\t\t\t// Idempotency: if the anchor record already exists, this set was\n\t\t\t\t// committed by an earlier attempt. Return the prior outcome without\n\t\t\t\t// re-applying (so counter increments run at most once).\n\t\t\t\tif (spec.idempotencyKey) {\n\t\t\t\t\tconst existing = await store.findRecord(\n\t\t\t\t\t\tspec.idempotencyKey.collection,\n\t\t\t\t\t\tspec.idempotencyKey.id,\n\t\t\t\t\t)\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\treturn { ok: true, idempotent: true, operations: [], records: [existing] }\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Admission predicate against the target's current materialized state.\n\t\t\t\tif (spec.if && Object.keys(spec.if).length > 0) {\n\t\t\t\t\tconst target = await store.findRecord(spec.collection, spec.id)\n\t\t\t\t\tif (!evaluateRoutePredicate(target, spec.if)) {\n\t\t\t\t\t\tconst code = spec.reject?.code ?? 'CONDITION_NOT_MET'\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tcode,\n\t\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\tspec.reject?.message ??\n\t\t\t\t\t\t\t\t`Admission condition not met on \"${spec.collection}\" record \"${spec.id}\".`,\n\t\t\t\t\t\t\tretriable: false,\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Build the atomic set: the target update (when given) then every\n\t\t\t\t// `also` mutation. Mutations in one set should address distinct records;\n\t\t\t\t// a mutation's previous-value capture reads the pre-set state.\n\t\t\t\tconst mutations: RouteMutation[] = []\n\t\t\t\tif (spec.update !== undefined && spec.update !== null) {\n\t\t\t\t\tmutations.push({\n\t\t\t\t\t\tcollection: spec.collection,\n\t\t\t\t\t\ttype: 'update',\n\t\t\t\t\t\trecordId: spec.id,\n\t\t\t\t\t\tdata: spec.update,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tif (spec.also) {\n\t\t\t\t\tmutations.push(...spec.also)\n\t\t\t\t}\n\n\t\t\t\t// Pre-build and scope-validate the WHOLE set before committing any of\n\t\t\t\t// it, so a validation failure applies nothing.\n\t\t\t\tconst prepared: { op: Operation; collection: string }[] = []\n\t\t\t\tfor (const mutation of mutations) {\n\t\t\t\t\tconst p = await prepareMutation(mutation, options?.scope)\n\t\t\t\t\tif (!p.ok) {\n\t\t\t\t\t\treturn p.rejection\n\t\t\t\t\t}\n\t\t\t\t\tprepared.push({ op: p.op, collection: mutation.collection })\n\t\t\t\t}\n\n\t\t\t\tconst operations: Operation[] = []\n\t\t\t\tconst records: (MaterializedRecord | null)[] = []\n\t\t\t\tfor (const { op, collection } of prepared) {\n\t\t\t\t\tconst result = await commitOperation(op, collection)\n\t\t\t\t\tif (!result.ok) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\tcode: result.code,\n\t\t\t\t\t\t\tmessage: result.message,\n\t\t\t\t\t\t\tretriable: result.retriable,\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\toperations.push(result.operation)\n\t\t\t\t\trecords.push(result.record)\n\t\t\t\t}\n\n\t\t\t\treturn { ok: true, idempotent: false, operations, records }\n\t\t\t})\n\t\t},\n\n\t\tasync query(collection, options): Promise<MaterializedRecord[]> {\n\t\t\tconst { scope, ...queryOptions } = options ?? {}\n\t\t\tconst records = await store.queryCollection(collection, queryOptions)\n\t\t\tif (!scope) {\n\t\t\t\treturn records\n\t\t\t}\n\t\t\treturn records.filter((record) => recordMatchesScope(collection, record, scope))\n\t\t},\n\n\t\tasync findById(collection, id, options): Promise<MaterializedRecord | null> {\n\t\t\tconst record = await store.findRecord(collection, id)\n\t\t\tif (!record) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (options?.scope && !recordMatchesScope(collection, record, options.scope)) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn record\n\t\t},\n\t}\n}\n","/**\n * Predicate evaluation for conditional route mutations.\n *\n * A predicate is a small, total comparison language evaluated against the current\n * materialized state of a single record at admission time. It is deliberately not\n * a general query language: it exists so a server route can express an atomic\n * admission guard (for example \"accept this response only while the form is still\n * below its cap\") without pulling a query DSL into the write path.\n */\n\n/**\n * Comparison operators applied to one field. All operators present on a field\n * must hold for the field to match. Numeric operators (`$lt`, `$lte`, `$gt`,\n * `$gte`) require the record value to be a number; a non-numeric value fails.\n */\nexport interface RoutePredicateOperators {\n\t$eq?: unknown\n\t$ne?: unknown\n\t$lt?: number\n\t$lte?: number\n\t$gt?: number\n\t$gte?: number\n\t$in?: readonly unknown[]\n}\n\n/** A predicate: every listed field must satisfy all of its operators. */\nexport type RoutePredicate = Record<string, RoutePredicateOperators>\n\nfunction evaluateField(actual: unknown, operators: RoutePredicateOperators): boolean {\n\tif ('$eq' in operators && !Object.is(actual, operators.$eq)) {\n\t\treturn false\n\t}\n\tif ('$ne' in operators && Object.is(actual, operators.$ne)) {\n\t\treturn false\n\t}\n\tif (\n\t\toperators.$in !== undefined &&\n\t\t!operators.$in.some((candidate) => Object.is(actual, candidate))\n\t) {\n\t\treturn false\n\t}\n\n\tconst numericChecks: [keyof RoutePredicateOperators, (a: number, b: number) => boolean][] = [\n\t\t['$lt', (a, b) => a < b],\n\t\t['$lte', (a, b) => a <= b],\n\t\t['$gt', (a, b) => a > b],\n\t\t['$gte', (a, b) => a >= b],\n\t]\n\tfor (const [operator, compare] of numericChecks) {\n\t\tconst bound = operators[operator]\n\t\tif (bound === undefined) {\n\t\t\tcontinue\n\t\t}\n\t\tif (typeof actual !== 'number' || typeof bound !== 'number') {\n\t\t\treturn false\n\t\t}\n\t\tif (!compare(actual, bound)) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n/**\n * Evaluates a predicate against a record. A `null` record (the target does not\n * exist) satisfies only an empty predicate; any field condition fails, since a\n * missing record cannot meet a comparison.\n *\n * @param record - The current materialized record, or `null` if absent\n * @param predicate - The field conditions that must all hold\n * @returns `true` when every field condition is satisfied\n */\nexport function evaluateRoutePredicate(\n\trecord: Record<string, unknown> | null,\n\tpredicate: RoutePredicate,\n): boolean {\n\tconst fields = Object.keys(predicate)\n\tif (fields.length === 0) {\n\t\treturn true\n\t}\n\tif (record === null) {\n\t\treturn false\n\t}\n\tfor (const field of fields) {\n\t\tconst operators = predicate[field]\n\t\tif (operators && !evaluateField(record[field], operators)) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n","import type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Options for creating a TokenAuthProvider.\n */\nexport interface TokenAuthProviderOptions {\n\t/**\n\t * Validate a token and return an AuthContext if valid, or null if rejected.\n\t * This is where you implement your auth logic (JWT verification, database lookup, etc.).\n\t */\n\tvalidate: (token: string) => Promise<AuthContext | null>\n}\n\n/**\n * Token-based auth provider that delegates validation to a user-provided function.\n *\n * @example\n * ```typescript\n * const auth = new TokenAuthProvider({\n * validate: async (token) => {\n * const user = await verifyJWT(token)\n * return user ? { userId: user.id } : null\n * }\n * })\n * ```\n */\nexport class TokenAuthProvider implements AuthProvider {\n\tprivate readonly validate: (token: string) => Promise<AuthContext | null>\n\n\tconstructor(options: TokenAuthProviderOptions) {\n\t\tthis.validate = options.validate\n\t}\n\n\tasync authenticate(token: string): Promise<AuthContext | null> {\n\t\treturn this.validate(token)\n\t}\n}\n","import type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Validates a Kora auth JWT and returns identity claims.\n * This interface matches the signature of TokenManager.validateToken()\n * from @korajs/auth without requiring a direct import.\n */\ninterface TokenValidator {\n\tvalidateToken(token: string): {\n\t\tsub: string\n\t\tdev: string\n\t\ttype: string\n\t} | null\n\tvalidateTokenWithRevocation?(token: string): Promise<{\n\t\tsub: string\n\t\tdev: string\n\t\ttype: string\n\t} | null>\n}\n\n/**\n * Looks up a user by ID. Returns null if the user doesn't exist.\n * This interface matches InMemoryUserStore.findById() from @korajs/auth\n * without requiring a direct import.\n */\ninterface UserLookup {\n\tfindById(userId: string): Promise<{\n\t\tid: string\n\t\temail: string\n\t\tname: string\n\t} | null>\n}\n\n/**\n * Optional device touch callback for updating last-seen timestamps.\n */\ninterface DeviceToucher {\n\ttouchDevice(deviceId: string): Promise<void>\n}\n\n/**\n * Configuration for creating a KoraAuthProvider.\n */\nexport interface KoraAuthProviderOptions {\n\t/**\n\t * Token validator that verifies JWT signatures and returns claims.\n\t * Typically a `TokenManager` instance from `@korajs/auth/server`.\n\t * If the validator also implements `validateTokenWithRevocation`, the sync\n\t * server uses it so signed-out sessions and revoked devices are rejected.\n\t */\n\ttokenValidator: TokenValidator\n\n\t/**\n\t * User lookup for verifying the user still exists.\n\t * Typically an `InMemoryUserStore` instance from `@korajs/auth/server`.\n\t */\n\tuserLookup: UserLookup\n\n\t/**\n\t * Optional device tracker for updating last-seen timestamps.\n\t * Typically the same `InMemoryUserStore` if it implements `touchDevice`.\n\t */\n\tdeviceTracker?: DeviceToucher\n\n\t/**\n\t * Optional scope resolver. Called with the user ID to determine\n\t * which collections/records the user can sync.\n\t */\n\tresolveScopes?: (userId: string) => Promise<Record<string, Record<string, unknown>>>\n}\n\n/**\n * Auth provider that bridges `@korajs/auth` token management with the\n * sync server's authentication layer.\n *\n * Validates access tokens issued by `@korajs/auth`'s `TokenManager`,\n * verifies the user still exists, and optionally computes per-user\n * sync scopes. This is the recommended way to connect @korajs/auth\n * to @korajs/server.\n *\n * @example\n * ```typescript\n * import { TokenManager, InMemoryUserStore } from '@korajs/auth/server'\n * import { KoraAuthProvider, KoraSyncServer } from '@korajs/server'\n *\n * const tokenManager = new TokenManager({ secret: 'my-secret' })\n * const userStore = new InMemoryUserStore()\n *\n * const auth = new KoraAuthProvider({\n * tokenValidator: tokenManager,\n * userLookup: userStore,\n * deviceTracker: userStore,\n * resolveScopes: async (userId) => ({\n * forms: { userId },\n * responses: { formOwnerId: userId },\n * }),\n * })\n *\n * const server = new KoraSyncServer({ store, auth })\n * ```\n */\nexport class KoraAuthProvider implements AuthProvider {\n\tprivate readonly tokenValidator: TokenValidator\n\tprivate readonly userLookup: UserLookup\n\tprivate readonly deviceTracker: DeviceToucher | undefined\n\tprivate readonly resolveScopes:\n\t\t| ((userId: string) => Promise<Record<string, Record<string, unknown>>>)\n\t\t| undefined\n\n\tconstructor(options: KoraAuthProviderOptions) {\n\t\tthis.tokenValidator = options.tokenValidator\n\t\tthis.userLookup = options.userLookup\n\t\tthis.deviceTracker = options.deviceTracker\n\t\tthis.resolveScopes = options.resolveScopes\n\t}\n\n\tasync authenticate(token: string): Promise<AuthContext | null> {\n\t\t// Validate the JWT signature and expiration\n\t\tconst payload = this.tokenValidator.validateTokenWithRevocation\n\t\t\t? await this.tokenValidator.validateTokenWithRevocation(token)\n\t\t\t: this.tokenValidator.validateToken(token)\n\t\tif (payload === null) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Only accept access tokens for sync authentication\n\t\tif (payload.type !== 'access') {\n\t\t\treturn null\n\t\t}\n\n\t\t// Verify the user still exists (may have been deleted since token was issued)\n\t\tconst user = await this.userLookup.findById(payload.sub)\n\t\tif (user === null) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Update device last-seen timestamp\n\t\tif (this.deviceTracker) {\n\t\t\tawait this.deviceTracker.touchDevice(payload.dev)\n\t\t}\n\n\t\t// Compute sync scopes if a resolver is configured\n\t\tconst scopes = this.resolveScopes ? await this.resolveScopes(payload.sub) : undefined\n\n\t\treturn {\n\t\t\tuserId: payload.sub,\n\t\t\tscopes,\n\t\t\tmetadata: {\n\t\t\t\tdeviceId: payload.dev,\n\t\t\t\temail: user.email,\n\t\t\t\tname: user.name,\n\t\t\t},\n\t\t}\n\t}\n}\n","import type { AuthContext, AuthProvider } from '../types'\n\n/**\n * Configuration for creating a MixedAuthProvider.\n */\nexport interface MixedAuthProviderOptions {\n\t/**\n\t * Primary auth provider that validates tokens from authenticated users.\n\t * Typically a `KoraAuthProvider`, `TokenAuthProvider`, or the result of\n\t * `authRoutes.toSyncAuthProvider()`.\n\t */\n\tprimary: AuthProvider\n\n\t/**\n\t * Scopes to apply to anonymous connections.\n\t * Each key is a collection name; the value is a filter object\n\t * (use `{}` for unrestricted access to that collection).\n\t *\n\t * @example\n\t * ```typescript\n\t * // Anonymous users can only sync the 'responses' collection\n\t * anonymousScopes: { responses: {} }\n\t *\n\t * // Anonymous users can read published forms\n\t * anonymousScopes: { forms: { status: 'published' } }\n\t * ```\n\t */\n\tanonymousScopes: Record<string, Record<string, unknown>>\n\n\t/**\n\t * Prefix for generated anonymous user IDs.\n\t * A unique suffix is appended to each connection.\n\t * @default 'anon'\n\t */\n\tanonymousPrefix?: string\n}\n\n/**\n * Auth provider that supports both authenticated and anonymous connections.\n *\n * When a client connects with a valid token, the primary auth provider\n * handles authentication normally. When a client connects without a token\n * (or with an invalid one), the connection is accepted as anonymous with\n * restricted sync scopes.\n *\n * This is the recommended pattern for apps that need public data access\n * alongside authenticated users — for example, a form builder where\n * authenticated users create forms but anyone can submit responses.\n *\n * @example\n * ```typescript\n * import { MixedAuthProvider, KoraAuthProvider } from '@korajs/server'\n *\n * const auth = new MixedAuthProvider({\n * primary: authRoutes.toSyncAuthProvider(),\n * anonymousScopes: {\n * // Anonymous users can only sync the 'responses' collection\n * responses: {},\n * },\n * })\n *\n * const server = new KoraSyncServer({ store, auth })\n * ```\n *\n * @example\n * ```typescript\n * // On the client, return an empty token for unauthenticated users:\n * const app = createApp({\n * schema,\n * sync: {\n * url: 'wss://my-server.com/kora',\n * auth: async () => ({\n * token: (await authClient.getAccessToken()) ?? '',\n * }),\n * },\n * })\n * ```\n */\nexport class MixedAuthProvider implements AuthProvider {\n\tprivate readonly primary: AuthProvider\n\tprivate readonly anonymousScopes: Record<string, Record<string, unknown>>\n\tprivate readonly anonymousPrefix: string\n\tprivate anonymousCounter = 0\n\n\tconstructor(options: MixedAuthProviderOptions) {\n\t\tthis.primary = options.primary\n\t\tthis.anonymousScopes = options.anonymousScopes\n\t\tthis.anonymousPrefix = options.anonymousPrefix ?? 'anon'\n\t}\n\n\tasync authenticate(token: string): Promise<AuthContext> {\n\t\t// Try authenticated path first when a token is provided\n\t\tif (token) {\n\t\t\tconst ctx = await this.primary.authenticate(token)\n\t\t\tif (ctx) return ctx\n\t\t}\n\n\t\t// Fall back to scoped anonymous access\n\t\tthis.anonymousCounter++\n\t\treturn {\n\t\t\tuserId: `${this.anonymousPrefix}-${Date.now()}-${this.anonymousCounter}`,\n\t\t\tscopes: this.anonymousScopes,\n\t\t}\n\t}\n}\n","import type { KoraSyncServerConfig } from '../types'\nimport { KoraSyncServer } from './kora-sync-server'\n\n/**\n * Factory function to create a KoraSyncServer.\n *\n * @param config - Server configuration\n * @returns A new KoraSyncServer instance\n *\n * @example\n * ```typescript\n * const server = createKoraServer({\n * store: new MemoryServerStore(),\n * port: 3000,\n * })\n * await server.start()\n * ```\n */\nexport function createKoraServer(config: KoraSyncServerConfig): KoraSyncServer {\n\treturn new KoraSyncServer(config)\n}\n","import type { BlobRef } from '@korajs/core'\nimport type { ServerStore } from '../store/server-store'\nimport { WsServerTransport } from '../transport/ws-server-transport'\nimport type { KoraSyncServerConfig } from '../types'\nimport { KoraSyncServer } from './kora-sync-server'\nimport type { ProductionHttpRouteContext } from './route-context'\n\n/**\n * Configuration for the production server that serves both\n * static files and WebSocket sync on a single port.\n */\nexport interface ProductionServerConfig {\n\t/** Server-side operation store */\n\tstore: ServerStore\n\t/** Port to listen on. Defaults to 3001 or process.env.PORT. */\n\tport?: number\n\t/** Directory containing built static files. Defaults to './dist'. */\n\tstaticDir?: string\n\t/** WebSocket sync path. Defaults to '/kora-sync'. */\n\tsyncPath?: string\n\t/** Additional KoraSyncServer options */\n\tsyncOptions?: Omit<KoraSyncServerConfig, 'store' | 'port' | 'host' | 'path'>\n\t/**\n\t * Cross-Origin-Embedder-Policy for static and route responses. Defaults to\n\t * `credentialless`, which keeps third-party embeds usable while allowing\n\t * capable browsers to enable cross-origin isolation. Use `require-corp` only\n\t * when every embedded resource explicitly opts in with CORP/CORS headers.\n\t */\n\tcrossOriginEmbedderPolicy?: 'credentialless' | 'require-corp' | 'unsafe-none'\n\t/**\n\t * Optional HTTP route handlers mounted before static file serving.\n\t *\n\t * This is intentionally framework-agnostic so packages such as\n\t * `@korajs/auth` can plug into the production server without requiring\n\t * Express, Hono, or another HTTP framework.\n\t */\n\thttpRoutes?: ProductionHttpRoute[]\n\t/**\n\t * Optional token protection for operational endpoints.\n\t *\n\t * When a token is omitted, the matching endpoint group remains public for\n\t * backward compatibility. Production apps should set at least adminToken and\n\t * backupToken.\n\t */\n\toperationalAuth?: ProductionOperationalAuth\n}\n\nexport interface ProductionOperationalAuth {\n\t/** Protects /__kora, /__kora/status, and /__kora/events. */\n\tadminToken?: string\n\t/** Protects /__kora/metrics. Falls back to adminToken when omitted. */\n\tmetricsToken?: string\n\t/** Protects /__kora/backup/*. Falls back to adminToken when omitted. */\n\tbackupToken?: string\n}\n\nexport interface ProductionHttpRouteRequest {\n\tmethod: string\n\tpath: string\n\tbody?: unknown\n\theaders?: Record<string, string | string[] | undefined>\n\tquery?: Record<string, string | string[] | undefined>\n\tip?: string\n\t/**\n\t * Scoped, validated data-plane access. Use `kora.apply()` to mutate through\n\t * the same pipeline as sync (constraints, referential integrity, fan-out) and\n\t * `kora.query()` / `kora.findById()` to read materialized state, instead of\n\t * writing to the store directly and bypassing those guarantees.\n\t */\n\tkora: ProductionHttpRouteContext\n}\n\nexport interface ProductionHttpRouteResponse {\n\tstatus: number\n\tbody?: unknown\n\theaders?: Record<string, string>\n}\n\nexport interface ProductionHttpRoute {\n\t/** URL path prefix, for example `/auth`. */\n\tpath: string\n\thandle(request: ProductionHttpRouteRequest): Promise<ProductionHttpRouteResponse>\n}\n\n/**\n * A production server handle returned by createProductionServer.\n */\nexport interface ProductionServer {\n\t/** Start listening. Returns the URL the server is available at. */\n\tstart(): Promise<string>\n\t/** Stop the server gracefully. */\n\tstop(): Promise<void>\n\t/**\n\t * Trusted, scoped data-plane access for server-side callers that have no HTTP\n\t * request — background jobs, scheduled tasks, seeding scripts.\n\t *\n\t * `kora.apply()` runs the mutation through the exact same validated pipeline as\n\t * sync (Tier 2 constraints, referential integrity, materialization, and fan-out\n\t * to connected clients), and `kora.query()` / `kora.findById()` read\n\t * materialized state. This is the same context handed to custom HTTP routes as\n\t * `request.kora`, so a job and a request share one code path and one set of\n\t * guarantees instead of the job writing to the store directly and silently\n\t * bypassing validation.\n\t */\n\tkora: ProductionHttpRouteContext\n\t/**\n\t * Every blob reference still reachable from a live record across all\n\t * collections that declare a `blob` field. This is the live set for\n\t * garbage-collecting the server's central blob store: pass it to\n\t * `collectBlobGarbage(blobStore, refs)` from `@korajs/store` on a schedule to\n\t * reclaim bytes no record points at any more.\n\t *\n\t * @returns Every live blob reference the server can currently see.\n\t */\n\tgetLiveBlobRefs(): Promise<BlobRef[]>\n}\n\n// MIME types for static file serving\nconst MIME_TYPES: Record<string, string> = {\n\t'.html': 'text/html',\n\t'.js': 'text/javascript',\n\t'.css': 'text/css',\n\t'.json': 'application/json',\n\t'.png': 'image/png',\n\t'.jpg': 'image/jpeg',\n\t'.svg': 'image/svg+xml',\n\t'.ico': 'image/x-icon',\n\t'.wasm': 'application/wasm',\n\t'.woff': 'font/woff',\n\t'.woff2': 'font/woff2',\n\t'.map': 'application/json',\n}\n\n/**\n * Creates a production server that serves both static files and WebSocket sync\n * on a single port, plus built-in dashboard and observability endpoints.\n *\n * @param config - Production server configuration\n * @returns A ProductionServer instance\n *\n * @example\n * ```typescript\n * const server = createProductionServer({\n * store: createSqliteServerStore({ filename: './kora-server.db' }),\n * })\n * const url = await server.start()\n * ```\n */\nexport function createProductionServer(config: ProductionServerConfig): ProductionServer {\n\tconst port = config.port ?? (Number(process.env.PORT) || 3001)\n\tconst staticDir = config.staticDir ?? './dist'\n\tconst syncPath = config.syncPath ?? '/kora-sync'\n\tconst crossOriginEmbedderPolicy = config.crossOriginEmbedderPolicy ?? 'credentialless'\n\n\tconst syncServer = new KoraSyncServer({\n\t\tstore: config.store,\n\t\tenableDashboard: true,\n\t\t...config.syncOptions,\n\t})\n\n\t// Scoped, validated data-plane access handed to every custom HTTP route as\n\t// `request.kora`, exposed on the handle as `server.kora`, and used by the\n\t// operation validator. One shared context (it holds no per-request state).\n\tconst routeContext = syncServer.getKoraContext()\n\n\tlet httpServer: import('node:http').Server | null = null\n\n\tfunction getOperationalToken(kind: 'admin' | 'metrics' | 'backup'): string | undefined {\n\t\tconst auth = config.operationalAuth\n\t\tif (!auth) return undefined\n\t\tif (kind === 'metrics') return auth.metricsToken || auth.adminToken\n\t\tif (kind === 'backup') return auth.backupToken || auth.adminToken\n\t\treturn auth.adminToken\n\t}\n\n\tfunction extractRequestToken(req: import('node:http').IncomingMessage): string | null {\n\t\tconst authorization = req.headers.authorization\n\t\tif (authorization?.startsWith('Bearer ')) {\n\t\t\treturn authorization.slice('Bearer '.length).trim()\n\t\t}\n\n\t\tconst headerNames = ['x-kora-admin-token', 'x-kora-metrics-token', 'x-kora-backup-token']\n\t\tfor (const name of headerNames) {\n\t\t\tconst value = req.headers[name]\n\t\t\tif (typeof value === 'string' && value.length > 0) return value\n\t\t\tif (Array.isArray(value) && typeof value[0] === 'string' && value[0].length > 0) {\n\t\t\t\treturn value[0]\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t}\n\n\tfunction isOperationalRequestAllowed(\n\t\treq: import('node:http').IncomingMessage,\n\t\tkind: 'admin' | 'metrics' | 'backup',\n\t): boolean {\n\t\tconst expected = getOperationalToken(kind)\n\t\tif (!expected) return true\n\t\treturn extractRequestToken(req) === expected\n\t}\n\n\tfunction rejectUnauthorized(res: import('node:http').ServerResponse): void {\n\t\tres.writeHead(401, {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t'WWW-Authenticate': 'Bearer realm=\"kora\"',\n\t\t})\n\t\tres.end(JSON.stringify({ error: 'Unauthorized' }))\n\t}\n\n\t/**\n\t * Format the metrics snapshot as Prometheus exposition format.\n\t * Zero-dependency — no prom-client needed.\n\t */\n\tfunction formatPrometheusMetrics(): string {\n\t\tconst status = syncServer.getMetricsCollector().getSnapshot(0)\n\t\tconst lines: string[] = [\n\t\t\t'# HELP kora_connected_clients Current number of connected clients',\n\t\t\t'# TYPE kora_connected_clients gauge',\n\t\t\t`kora_connected_clients ${status.connectedClients}`,\n\t\t\t'',\n\t\t\t'# HELP kora_peak_connections Peak number of simultaneous connections since server start',\n\t\t\t'# TYPE kora_peak_connections gauge',\n\t\t\t`kora_peak_connections ${status.peakConnections}`,\n\t\t\t'',\n\t\t\t'# HELP kora_connections_total Total number of connections handled since server start',\n\t\t\t'# TYPE kora_connections_total counter',\n\t\t\t`kora_connections_total ${status.connectionsTotal}`,\n\t\t\t'',\n\t\t\t'# HELP kora_operations_received_total Total operations received from clients',\n\t\t\t'# TYPE kora_operations_received_total counter',\n\t\t\t`kora_operations_received_total ${status.operationsReceived}`,\n\t\t\t'',\n\t\t\t'# HELP kora_operation_batches_received_total Total operation batches received from clients',\n\t\t\t'# TYPE kora_operation_batches_received_total counter',\n\t\t\t`kora_operation_batches_received_total ${status.batchesReceived}`,\n\t\t\t'',\n\t\t\t'# HELP kora_unique_operations_received_total Newly materialized operations received from clients',\n\t\t\t'# TYPE kora_unique_operations_received_total counter',\n\t\t\t`kora_unique_operations_received_total ${status.uniqueOperationsReceived}`,\n\t\t\t'',\n\t\t\t'# HELP kora_duplicate_operations_received_total Duplicate operations received from clients',\n\t\t\t'# TYPE kora_duplicate_operations_received_total counter',\n\t\t\t`kora_duplicate_operations_received_total ${status.duplicateOperationsReceived}`,\n\t\t\t'',\n\t\t\t'# HELP kora_rejected_operations_total Operations rejected before authoritative materialization',\n\t\t\t'# TYPE kora_rejected_operations_total counter',\n\t\t\t`kora_rejected_operations_total ${status.rejectedOperations}`,\n\t\t\t'',\n\t\t\t'# HELP kora_operations_sent_total Total operations sent to clients',\n\t\t\t'# TYPE kora_operations_sent_total counter',\n\t\t\t`kora_operations_sent_total ${status.operationsSent}`,\n\t\t\t'',\n\t\t\t'# HELP kora_bytes_received_total Total bytes received from clients',\n\t\t\t'# TYPE kora_bytes_received_total counter',\n\t\t\t`kora_bytes_received_total ${status.bytesReceived}`,\n\t\t\t'',\n\t\t\t'# HELP kora_bytes_sent_total Total bytes sent to clients',\n\t\t\t'# TYPE kora_bytes_sent_total counter',\n\t\t\t`kora_bytes_sent_total ${status.bytesSent}`,\n\t\t\t'',\n\t\t\t'# HELP kora_errors_total Total errors since server start',\n\t\t\t'# TYPE kora_errors_total counter',\n\t\t\t`kora_errors_total ${status.errorCount}`,\n\t\t\t'',\n\t\t\t'# HELP kora_uptime_seconds Server uptime in seconds',\n\t\t\t'# TYPE kora_uptime_seconds gauge',\n\t\t\t`kora_uptime_seconds ${Math.floor(status.uptime / 1000)}`,\n\t\t\t'',\n\t\t\t'# HELP kora_schema_version Schema version the server expects',\n\t\t\t'# TYPE kora_schema_version gauge',\n\t\t\t`kora_schema_version ${status.schemaVersion}`,\n\t\t\t'',\n\t\t]\n\t\treturn lines.join('\\n')\n\t}\n\n\tfunction readBodyBuffer(req: import('node:http').IncomingMessage): Promise<Buffer> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst chunks: Buffer[] = []\n\t\t\treq.on('data', (chunk: Buffer) => chunks.push(chunk))\n\t\t\treq.on('end', () => resolve(Buffer.concat(chunks)))\n\t\t\t// A raw http.IncomingMessage starts paused: attaching 'data'/'end'\n\t\t\t// listeners alone does not put it in flowing mode. Without an\n\t\t\t// explicit resume(), 'data' never fires, 'end' fires immediately with\n\t\t\t// zero chunks, and every POST body silently reads back as empty —\n\t\t\t// which is exactly what broke httpRoutes handlers (including\n\t\t\t// @korajs/auth's signup/signin) reading `req.body`. Guard with\n\t\t\t// `readableFlowing` so this stays a no-op if the stream is already\n\t\t\t// flowing (e.g. a future caller that reads it differently).\n\t\t\tif (!req.readableFlowing) {\n\t\t\t\treq.resume()\n\t\t\t}\n\t\t\t// If the client disconnects mid-upload, `end` never fires; resolve\n\t\t\t// with whatever arrived instead of leaving the request hung forever.\n\t\t\treq.on('error', () => resolve(Buffer.concat(chunks)))\n\t\t})\n\t}\n\n\tasync function readJsonBody(req: import('node:http').IncomingMessage): Promise<unknown> {\n\t\tconst buffer = await readBodyBuffer(req)\n\t\tif (buffer.byteLength === 0) return undefined\n\t\ttry {\n\t\t\treturn JSON.parse(buffer.toString('utf8')) as unknown\n\t\t} catch {\n\t\t\treturn undefined\n\t\t}\n\t}\n\n\tfunction matchesRoutePrefix(pathname: string, prefix: string): boolean {\n\t\tconst normalizedPrefix = normalizeRoutePath(prefix)\n\t\treturn pathname === normalizedPrefix || pathname.startsWith(`${normalizedPrefix}/`)\n\t}\n\n\tfunction normalizeRoutePath(path: string): string {\n\t\tconst prefixed = path.startsWith('/') ? path : `/${path}`\n\t\treturn prefixed.length > 1 ? prefixed.replace(/\\/+$/, '') : prefixed\n\t}\n\n\tfunction getClientIp(req: import('node:http').IncomingMessage): string | undefined {\n\t\tconst forwarded = req.headers['x-forwarded-for']\n\t\tif (typeof forwarded === 'string' && forwarded.length > 0) {\n\t\t\treturn forwarded.split(',')[0]?.trim()\n\t\t}\n\t\treturn req.socket.remoteAddress\n\t}\n\n\tfunction getQuery(url: URL): Record<string, string | string[] | undefined> {\n\t\tconst query: Record<string, string | string[] | undefined> = {}\n\t\tfor (const [key, value] of url.searchParams) {\n\t\t\tconst existing = query[key]\n\t\t\tif (existing === undefined) {\n\t\t\t\tquery[key] = value\n\t\t\t} else if (Array.isArray(existing)) {\n\t\t\t\texisting.push(value)\n\t\t\t} else {\n\t\t\t\tquery[key] = [existing, value]\n\t\t\t}\n\t\t}\n\t\treturn query\n\t}\n\n\tfunction writeJsonResponse(\n\t\tres: import('node:http').ServerResponse,\n\t\tresult: ProductionHttpRouteResponse,\n\t): void {\n\t\tconst headers = {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t...(result.headers ?? {}),\n\t\t}\n\t\tres.writeHead(result.status, headers)\n\t\tres.end(JSON.stringify(result.body ?? null))\n\t}\n\n\treturn {\n\t\tkora: routeContext,\n\n\t\tgetLiveBlobRefs(): Promise<BlobRef[]> {\n\t\t\treturn syncServer.getLiveBlobRefs()\n\t\t},\n\n\t\tasync start(): Promise<string> {\n\t\t\tconst { createServer } = await import('node:http')\n\t\t\tconst { createReadStream, existsSync, statSync } = await import('node:fs')\n\t\t\tconst { extname, join, resolve } = await import('node:path')\n\t\t\tconst { WebSocketServer } = await import('ws')\n\n\t\t\tconst distDir = resolve(staticDir)\n\n\t\t\thttpServer = createServer(async (req, res) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait handleRequest(req, res)\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// http.createServer never awaits its request listener, so a\n\t\t\t\t\t// callback that rejects becomes an unhandled promise rejection\n\t\t\t\t\t// process-wide, and Node's default `--unhandled-rejections=throw`\n\t\t\t\t\t// crashes the entire server. One bad request (malformed body,\n\t\t\t\t\t// a buggy custom httpRoute handler, anything unexpected) must\n\t\t\t\t\t// only fail that one response, never take the whole process\n\t\t\t\t\t// down with it.\n\t\t\t\t\tconsole.error('[kora] Unhandled error in HTTP request handler:', error)\n\t\t\t\t\tif (!res.headersSent) {\n\t\t\t\t\t\tres.writeHead(500, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify({ error: 'Internal server error' }))\n\t\t\t\t\t} else if (!res.writableEnded) {\n\t\t\t\t\t\tres.end()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tasync function handleRequest(\n\t\t\t\treq: import('node:http').IncomingMessage,\n\t\t\t\tres: import('node:http').ServerResponse,\n\t\t\t): Promise<void> {\n\t\t\t\t// COOP/COEP headers required for SharedArrayBuffer (OPFS persistence)\n\t\t\t\tres.setHeader('Cross-Origin-Opener-Policy', 'same-origin')\n\t\t\t\tres.setHeader('Cross-Origin-Embedder-Policy', crossOriginEmbedderPolicy)\n\n\t\t\t\tconst url = new URL(req.url || '/', `http://${req.headers.host}`)\n\n\t\t\t\t// ── Health check ──────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/health') {\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'application/json' })\n\t\t\t\t\tres.end(\n\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\tstatus: 'ok',\n\t\t\t\t\t\t\tversion: status.version,\n\t\t\t\t\t\t\tuptime: status.uptime,\n\t\t\t\t\t\t\tconnectedClients: status.connectedClients,\n\t\t\t\t\t\t\ttotalOperations: status.totalOperations,\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Status endpoint ───────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/status') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'admin')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'application/json' })\n\t\t\t\t\tres.end(JSON.stringify(status, null, 2))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Prometheus metrics endpoint ───────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/metrics') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'metrics')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'text/plain; version=0.0.4' })\n\t\t\t\t\tres.end(formatPrometheusMetrics())\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Server-Sent Events endpoint ───────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/events') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'admin')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tres.writeHead(200, {\n\t\t\t\t\t\t'Content-Type': 'text/event-stream',\n\t\t\t\t\t\t'Cache-Control': 'no-cache',\n\t\t\t\t\t\tConnection: 'keep-alive',\n\t\t\t\t\t\t'X-Accel-Buffering': 'no',\n\t\t\t\t\t})\n\n\t\t\t\t\t// Send initial status event\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.write(`event: status\\ndata: ${JSON.stringify(status)}\\n\\n`)\n\n\t\t\t\t\t// Poll metrics periodically and push as SSE events\n\t\t\t\t\tconst interval = setInterval(async () => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst s = await syncServer.getStatus()\n\t\t\t\t\t\t\tres.write(`event: status\\ndata: ${JSON.stringify(s)}\\n\\n`)\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Connection may have closed\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 2000)\n\n\t\t\t\t\t// Clean up on connection close\n\t\t\t\t\treq.on('close', () => {\n\t\t\t\t\t\tclearInterval(interval)\n\t\t\t\t\t})\n\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Dashboard HTML ────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora' || url.pathname === '/__kora/') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'admin')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst status = await syncServer.getStatus()\n\t\t\t\t\tres.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })\n\t\t\t\t\tres.end(renderDashboardHtml(status))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Backup export ─────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/backup/export' && req.method === 'POST') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'backup')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst backup = await config.store.exportBackup()\n\t\t\t\t\t\tres.writeHead(200, {\n\t\t\t\t\t\t\t'Content-Type': 'application/octet-stream',\n\t\t\t\t\t\t\t'Content-Disposition': `attachment; filename=\"kora-backup-${Date.now()}.kora\"`,\n\t\t\t\t\t\t\t'Content-Length': String(backup.byteLength),\n\t\t\t\t\t\t})\n\t\t\t\t\t\tres.end(Buffer.from(backup))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tres.writeHead(500, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify({ error: 'Backup failed', message: (error as Error).message }))\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Backup import ─────────────────────────────────────────────\n\t\t\t\tif (url.pathname === '/__kora/backup/import' && req.method === 'POST') {\n\t\t\t\t\tif (!isOperationalRequestAllowed(req, 'backup')) {\n\t\t\t\t\t\trejectUnauthorized(res)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst body = await readBodyBuffer(req)\n\t\t\t\t\t\tconst merge = url.searchParams.get('merge') === 'true'\n\t\t\t\t\t\tconst result = await config.store.importBackup(\n\t\t\t\t\t\t\tnew Uint8Array(body.buffer, body.byteOffset, body.byteLength),\n\t\t\t\t\t\t\tmerge,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tres.writeHead(result.success ? 200 : 400, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify(result))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tres.writeHead(500, { 'Content-Type': 'application/json' })\n\t\t\t\t\t\tres.end(JSON.stringify({ error: 'Restore failed', message: (error as Error).message }))\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Custom HTTP routes (auth, webhooks, app APIs) ─────────────\n\t\t\t\tconst customRoute = config.httpRoutes?.find((route) =>\n\t\t\t\t\tmatchesRoutePrefix(url.pathname, route.path),\n\t\t\t\t)\n\t\t\t\tif (customRoute) {\n\t\t\t\t\tconst result = await customRoute.handle({\n\t\t\t\t\t\tmethod: req.method ?? 'GET',\n\t\t\t\t\t\tpath: url.pathname,\n\t\t\t\t\t\tbody: await readJsonBody(req),\n\t\t\t\t\t\theaders: req.headers,\n\t\t\t\t\t\tquery: getQuery(url),\n\t\t\t\t\t\tip: getClientIp(req),\n\t\t\t\t\t\tkora: routeContext,\n\t\t\t\t\t})\n\t\t\t\t\twriteJsonResponse(res, result)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// ── Static file serving ───────────────────────────────────────\n\t\t\t\tlet filePath = join(distDir, url.pathname)\n\n\t\t\t\t// SPA fallback: serve index.html for non-file routes\n\t\t\t\tif (!extname(filePath)) {\n\t\t\t\t\tconst indexPath = join(filePath, 'index.html')\n\t\t\t\t\tif (existsSync(indexPath)) {\n\t\t\t\t\t\tfilePath = indexPath\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfilePath = join(distDir, 'index.html')\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!existsSync(filePath)) {\n\t\t\t\t\tfilePath = join(distDir, 'index.html')\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst stat = statSync(filePath)\n\t\t\t\t\tif (stat.isDirectory()) {\n\t\t\t\t\t\tfilePath = join(filePath, 'index.html')\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\tfilePath = join(distDir, 'index.html')\n\t\t\t\t}\n\n\t\t\t\tif (!existsSync(filePath)) {\n\t\t\t\t\tres.writeHead(404)\n\t\t\t\t\tres.end('Not Found')\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst ext = extname(filePath)\n\t\t\t\tconst contentType = MIME_TYPES[ext] || 'application/octet-stream'\n\t\t\t\tres.writeHead(200, { 'Content-Type': contentType })\n\t\t\t\tcreateReadStream(filePath).pipe(res)\n\t\t\t}\n\n\t\t\tconst wss = new WebSocketServer({ noServer: true })\n\n\t\t\thttpServer.on('upgrade', (req, socket, head) => {\n\t\t\t\tconst url = new URL(req.url || '/', `http://${req.headers.host}`)\n\t\t\t\tif (url.pathname === syncPath) {\n\t\t\t\t\twss.handleUpgrade(req, socket, head, (ws) => {\n\t\t\t\t\t\tconst transport = new WsServerTransport(ws)\n\t\t\t\t\t\tsyncServer.handleConnection(transport)\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tsocket.destroy()\n\t\t\t\t}\n\t\t\t})\n\n\t\t\treturn new Promise<string>((resolve, reject) => {\n\t\t\t\tconst onError = (error: Error) => {\n\t\t\t\t\treject(error)\n\t\t\t\t}\n\t\t\t\thttpServer?.once('error', onError)\n\t\t\t\thttpServer?.listen(port, '0.0.0.0', () => {\n\t\t\t\t\thttpServer?.off('error', onError)\n\t\t\t\t\tresolve(`http://localhost:${port}`)\n\t\t\t\t})\n\t\t\t})\n\t\t},\n\n\t\tasync stop(): Promise<void> {\n\t\t\tawait syncServer.stop()\n\t\t\tif (httpServer) {\n\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\thttpServer?.close(() => resolve())\n\t\t\t\t})\n\t\t\t\thttpServer = null\n\t\t\t}\n\t\t},\n\t}\n}\n\n/**\n * Render a minimal self-contained dashboard HTML page.\n * Shows server status with live-updating metrics via SSE.\n */\nfunction renderDashboardHtml(status: {\n\tversion: string\n\tuptime: number\n\tconnectedClients: number\n\ttotalOperations: number\n\tschemaVersion: number\n\tpeakConnections: number\n\tconnectionsTotal: number\n\toperationsReceived: number\n\toperationsSent: number\n\terrorCount: number\n}): string {\n\tconst version = status.version\n\tconst uptime = formatUptime(status.uptime)\n\treturn `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Kora Dashboard</title>\n<style>\n * { box-sizing: border-box; margin: 0; padding: 0 }\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0f172a; color: #e2e8f0; padding: 2rem }\n h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.25rem }\n .subtitle { color: #64748b; margin-bottom: 2rem; font-size: 0.875rem }\n .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 2rem }\n .card { background: #1e293b; border: 1px solid #334155; border-radius: 0.75rem; padding: 1.25rem }\n .card .label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: #64748b; margin-bottom: 0.5rem }\n .card .value { font-size: 1.75rem; font-weight: 700; color: #38bdf8 }\n .card .value.green { color: #4ade80 }\n .card .value.red { color: #f87171 }\n .card .value.yellow { color: #fbbf24 }\n .section-title { font-size: 1rem; font-weight: 600; margin-bottom: 0.75rem; margin-top: 1.5rem }\n table { width: 100%; border-collapse: collapse; font-size: 0.875rem }\n th { text-align: left; padding: 0.5rem 0.75rem; color: #64748b; font-weight: 500; border-bottom: 1px solid #334155 }\n td { padding: 0.5rem 0.75rem; border-bottom: 1px solid #1e293b }\n .status-dot { display: inline-block; width: 0.5rem; height: 0.5rem; border-radius: 50%; margin-right: 0.375rem }\n .status-dot.running { background: #4ade80 }\n .status-dot.stopped { background: #f87171 }\n</style>\n</head>\n<body>\n<h1>Kora Sync Server</h1>\n<p class=\"subtitle\">v${version} &middot; <span class=\"status-dot running\"></span>Running</p>\n<div class=\"grid\">\n <div class=\"card\"><div class=\"label\">Uptime</div><div class=\"value\">${uptime}</div></div>\n <div class=\"card\"><div class=\"label\">Connected Clients</div><div class=\"value\" id=\"connectedClients\">${status.connectedClients}</div></div>\n <div class=\"card\"><div class=\"label\">Total Operations</div><div class=\"value\" id=\"totalOperations\">${status.totalOperations}</div></div>\n <div class=\"card\"><div class=\"label\">Peak Connections</div><div class=\"value green\" id=\"peakConnections\">${status.peakConnections}</div></div>\n <div class=\"card\"><div class=\"label\">Ops Received</div><div class=\"value\" id=\"opsReceived\">${status.operationsReceived}</div></div>\n <div class=\"card\"><div class=\"label\">Ops Sent</div><div class=\"value\" id=\"opsSent\">${status.operationsSent}</div></div>\n <div class=\"card\"><div class=\"label\">Errors</div><div class=\"value ${status.errorCount > 0 ? 'red' : 'green'}\" id=\"errors\">${status.errorCount}</div></div>\n <div class=\"card\"><div class=\"label\">Schema Version</div><div class=\"value\">${status.schemaVersion}</div></div>\n</div>\n<script>\n(function() {\n const es = new EventSource('/__kora/events');\n es.addEventListener('status', (e) => {\n const s = JSON.parse(e.data);\n for (const [id, val] of Object.entries({\n connectedClients: s.connectedClients,\n totalOperations: s.totalOperations,\n peakConnections: s.peakConnections,\n opsReceived: s.operationsReceived,\n opsSent: s.operationsSent,\n errors: s.errorCount,\n })) {\n const el = document.getElementById(id);\n if (el) { el.textContent = String(val); el.className = 'value' + (id === 'errors' && val > 0 ? ' red' : id === 'errors' ? ' green' : ''); }\n }\n });\n es.onerror = () => { setTimeout(() => document.location.reload(), 5000); };\n})();\n</script>\n</body>\n</html>`\n}\n\nfunction formatUptime(ms: number): string {\n\tconst seconds = Math.floor(ms / 1000)\n\tconst minutes = Math.floor(seconds / 60)\n\tconst hours = Math.floor(minutes / 60)\n\tconst parts: string[] = []\n\tif (hours > 0) parts.push(`${hours}h`)\n\tif (minutes % 60 > 0) parts.push(`${minutes % 60}m`)\n\tparts.push(`${seconds % 60}s`)\n\treturn parts.join(' ')\n}\n"],"mappings":"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","names":["count","index","count","operations","generateUUIDv7","quoteIdent","generateUUIDv7","quoteIdent","operations","generateUUIDv7","quoteIdent","and","asc","between","count","eq","gt","sql","index","integer","text","generateUUIDv7","sql","and","eq","between","asc","count","gt","quoteIdent","SyncError","generateUUIDv7","HybridLogicalClock","count","operations","generateUUIDv7","response","SyncError","generateUUIDv7","JsonMessageSerializer","generateUUIDv7","operations","count","HybridLogicalClock","createOperation","generateUUIDv7","HybridLogicalClock","createOperation","generateUUIDv7","records","operations","DEFAULT_BATCH_SIZE","DEFAULT_SCHEMA_VERSION","SyncError","JsonMessageSerializer","generateUUIDv7","operations","resolve"]}