korajs 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-WALHLVVF.js +683 -0
- package/dist/chunk-WALHLVVF.js.map +1 -0
- package/dist/index.cjs +1090 -136
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +105 -7
- package/dist/index.d.ts +105 -7
- package/dist/index.js +450 -149
- package/dist/index.js.map +1 -1
- package/dist/testing.cjs +700 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +111 -0
- package/dist/testing.d.ts +111 -0
- package/dist/testing.js +13 -0
- package/dist/testing.js.map +1 -0
- package/package.json +19 -7
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/create-app.ts","../src/adapter-resolver.ts","../src/merge-aware-sync-store.ts"],"sourcesContent":["// kora — meta-package re-exporting core, store, merge, sync\n// This is the primary entry point for `import { createApp, defineSchema, t } from 'korajs'`\n\n// === createApp factory ===\nexport { createApp } from './create-app'\n\n// === App types ===\nexport type {\n\tAdapterType,\n\tKoraApp,\n\tKoraConfig,\n\tStoreOptions,\n\tSyncControl,\n\tSyncOptions,\n\tSequenceAccessor,\n\tTransactionCollectionProxy,\n\tTransactionProxy,\n\tTypedCollectionAccessor,\n\tTypedKoraApp,\n\tTypedKoraConfig,\n} from './types'\n\n// === @korajs/core re-exports ===\nexport { defineSchema, migrate, t } from '@korajs/core'\nexport { HybridLogicalClock } from '@korajs/core'\nexport { generateUUIDv7 } from '@korajs/core'\nexport { createOperation } from '@korajs/core'\nexport { KoraError } from '@korajs/core'\nexport { op } from '@korajs/core'\nexport type {\n\tAtomicOp,\n\tAtomicOpType,\n\tCollectionDefinition,\n\tConnectionQuality,\n\tConstraint,\n\tFieldDescriptor,\n\tFieldKindToType,\n\tHLCTimestamp,\n\tInferFieldType,\n\tInferInsertInput,\n\tInferRecord,\n\tInferUpdateInput,\n\tKoraEvent,\n\tKoraEventEmitter,\n\tKoraEventListener,\n\tKoraEventType,\n\tMergeStrategy,\n\tMergeTrace,\n\tMigrationDefinition,\n\tMigrationStep,\n\tOperation,\n\tSchemaDefinition,\n\tSchemaInput,\n\tSequenceConfig,\n\tTypedSchemaDefinition,\n\tVersionVector,\n} from '@korajs/core'\n\n// === @korajs/store re-exports ===\nexport { SequenceManager, Store } from '@korajs/store'\nexport { TransactionContext } from '@korajs/store'\nexport type {\n\tCollectionAccessor,\n\tCollectionRecord,\n\tStorageAdapter,\n\tStoreConfig,\n\tTransactionCollectionAccessor,\n\tTransactionContextConfig,\n} from '@korajs/store'\n\n// === @korajs/merge re-exports ===\nexport { MergeEngine } from '@korajs/merge'\nexport type { MergeInput, MergeResult } from '@korajs/merge'\n\n// === @korajs/sync re-exports ===\nexport { SyncEngine, WebSocketTransport } from '@korajs/sync'\nexport type {\n\tSyncConfig,\n\tSyncDiagnostics,\n\tSyncState,\n\tSyncStatus,\n\tSyncStatusInfo,\n\tSyncStore,\n} from '@korajs/sync'\n","import type { KoraEventEmitter, Operation, SchemaInput } from '@korajs/core'\nimport { buildScopeMap } from '@korajs/core'\nimport { SimpleEventEmitter } from '@korajs/core/internal'\nimport { Instrumenter } from '@korajs/devtools'\nimport { MergeEngine } from '@korajs/merge'\nimport { Store } from '@korajs/store'\nimport type { CollectionAccessor, StorageAdapter } from '@korajs/store'\nimport type { QueryBuilder } from '@korajs/store'\nimport {\n\tConnectionMonitor,\n\tReconnectionManager,\n\tSyncEngine,\n\tWebSocketTransport,\n} from '@korajs/sync'\nimport type { SyncStatusInfo } from '@korajs/sync'\nimport { createAdapter, detectAdapterType } from './adapter-resolver'\nimport { MergeAwareSyncStore } from './merge-aware-sync-store'\nimport type {\n\tKoraApp,\n\tKoraConfig,\n\tSequenceAccessor,\n\tSyncControl,\n\tTransactionProxy,\n\tTypedKoraApp,\n\tTypedKoraConfig,\n} from './types'\n\n/**\n * Creates a new Kora application instance.\n *\n * Wires together store, merge engine, event emitter, and optionally sync\n * into a single developer-facing `KoraApp` object. Collection accessors\n * (e.g. `app.todos`) are defined as properties for immediate use after `await app.ready`.\n *\n * @param config - Application configuration including schema and optional sync settings\n * @returns A KoraApp instance with reactive collections ready for use\n *\n * @example\n * ```typescript\n * const app = createApp({\n * schema: defineSchema({\n * version: 1,\n * collections: {\n * todos: {\n * fields: {\n * title: t.string(),\n * completed: t.boolean().default(false)\n * }\n * }\n * }\n * })\n * })\n *\n * await app.ready\n * const todo = await app.todos.insert({ title: 'Hello' })\n * ```\n */\n/**\n * Creates a new typed Kora application instance.\n * When the schema is created with `defineSchema()`, full type inference flows through\n * to collection accessors, providing autocomplete and type checking for all CRUD operations.\n */\nexport function createApp<const S extends SchemaInput>(config: TypedKoraConfig<S>): TypedKoraApp<S>\n/**\n * Creates a new Kora application instance (untyped fallback).\n */\nexport function createApp(config: KoraConfig): KoraApp\nexport function createApp(config: KoraConfig): KoraApp {\n\tconst emitter: KoraEventEmitter & { clear(): void } = new SimpleEventEmitter()\n\tconst mergeEngine = new MergeEngine()\n\n\tlet store: Store | null = null\n\tlet syncEngine: SyncEngine | null = null\n\tlet unsubscribeSync: (() => void) | null = null\n\tlet reconnectionManager: ReconnectionManager | null = null\n\tlet connectionMonitor: ConnectionMonitor | null = null\n\tlet instrumenter: Instrumenter | null = null\n\tlet intentionalDisconnect = false\n\tlet qualityInterval: ReturnType<typeof setInterval> | null = null\n\n\t// Wire DevTools instrumentation immediately (emitter exists synchronously)\n\tif (config.devtools) {\n\t\tinstrumenter = new Instrumenter(emitter, {\n\t\t\tbridgeEnabled: typeof globalThis !== 'undefined' && 'window' in globalThis,\n\t\t})\n\t}\n\n\t// Build the ready promise — resolves when the store is open and wired\n\tconst ready = initializeAsync(config, emitter, mergeEngine).then((result) => {\n\t\tstore = result.store\n\t\tsyncEngine = result.syncEngine\n\t\tunsubscribeSync = result.unsubscribeSync\n\n\t\t// Wire reconnection and connection quality after sync engine is ready\n\t\tif (config.sync && syncEngine) {\n\t\t\tconnectionMonitor = new ConnectionMonitor()\n\t\t\treconnectionManager = new ReconnectionManager({\n\t\t\t\tinitialDelay: config.sync.reconnectInterval,\n\t\t\t\tmaxDelay: config.sync.maxReconnectInterval,\n\t\t\t})\n\n\t\t\t// Track activity for connection quality\n\t\t\temitter.on('sync:sent', () => connectionMonitor?.recordActivity())\n\t\t\temitter.on('sync:received', () => connectionMonitor?.recordActivity())\n\t\t\temitter.on('sync:acknowledged', () => connectionMonitor?.recordActivity())\n\n\t\t\t// Emit quality on timer while connected\n\t\t\temitter.on('sync:connected', () => {\n\t\t\t\tif (qualityInterval !== null) clearInterval(qualityInterval)\n\t\t\t\tqualityInterval = setInterval(() => {\n\t\t\t\t\tif (connectionMonitor) {\n\t\t\t\t\t\temitter.emit({ type: 'connection:quality', quality: connectionMonitor.getQuality() })\n\t\t\t\t\t}\n\t\t\t\t}, 5000)\n\t\t\t})\n\n\t\t\t// Reset monitor and clear timer on disconnect\n\t\t\temitter.on('sync:disconnected', () => {\n\t\t\t\tconnectionMonitor?.reset()\n\t\t\t\tif (qualityInterval !== null) {\n\t\t\t\t\tclearInterval(qualityInterval)\n\t\t\t\t\tqualityInterval = null\n\t\t\t\t}\n\t\t\t})\n\n\t\t\t// Auto-reconnect on unexpected disconnect\n\t\t\tif (config.sync.autoReconnect !== false) {\n\t\t\t\tconst engine = syncEngine\n\t\t\t\temitter.on('sync:disconnected', () => {\n\t\t\t\t\tif (intentionalDisconnect) return\n\t\t\t\t\t// Ignore cascading disconnect events from failed reconnection attempts.\n\t\t\t\t\t// The reconnection manager is already retrying — don't restart it.\n\t\t\t\t\tif (reconnectionManager?.isRunning()) return\n\n\t\t\t\t\tengine.setReconnecting(true)\n\t\t\t\t\treconnectionManager?.stop()\n\t\t\t\t\treconnectionManager\n\t\t\t\t\t\t?.start(async () => {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait engine.start()\n\t\t\t\t\t\t\t\tengine.setReconnecting(false)\n\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.then(() => {\n\t\t\t\t\t\t\t// If reconnection exhausted max attempts without success, clear flag\n\t\t\t\t\t\t\tengine.setReconnecting(false)\n\t\t\t\t\t\t})\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t})\n\n\t// Build sync control\n\tconst syncControl: SyncControl | null = config.sync\n\t\t? {\n\t\t\t\tasync connect(): Promise<void> {\n\t\t\t\t\tawait ready\n\t\t\t\t\tif (syncEngine) {\n\t\t\t\t\t\tintentionalDisconnect = false\n\t\t\t\t\t\treconnectionManager?.stop()\n\t\t\t\t\t\treconnectionManager?.reset()\n\t\t\t\t\t\tawait syncEngine.start()\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tasync disconnect(): Promise<void> {\n\t\t\t\t\tawait ready\n\t\t\t\t\tif (syncEngine) {\n\t\t\t\t\t\tintentionalDisconnect = true\n\t\t\t\t\t\treconnectionManager?.stop()\n\t\t\t\t\t\tawait syncEngine.stop()\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tgetStatus(): SyncStatusInfo {\n\t\t\t\t\tif (syncEngine) {\n\t\t\t\t\t\treturn syncEngine.getStatus()\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 'offline',\n\t\t\t\t\t\tpendingOperations: 0,\n\t\t\t\t\t\tlastSyncedAt: null,\n\t\t\t\t\t\tlastSuccessfulPush: null,\n\t\t\t\t\t\tlastSuccessfulPull: null,\n\t\t\t\t\t\tconflicts: 0,\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tasync retryNow(): Promise<void> {\n\t\t\t\t\tawait ready\n\t\t\t\t\tif (syncEngine) {\n\t\t\t\t\t\tawait syncEngine.retryNow()\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\texportDiagnostics() {\n\t\t\t\t\tif (syncEngine) {\n\t\t\t\t\t\treturn syncEngine.exportDiagnostics()\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstate: 'disconnected' as const,\n\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\tstatus: 'offline' as const,\n\t\t\t\t\t\t\tpendingOperations: 0,\n\t\t\t\t\t\t\tlastSyncedAt: null,\n\t\t\t\t\t\t\tlastSuccessfulPush: null,\n\t\t\t\t\t\t\tlastSuccessfulPull: null,\n\t\t\t\t\t\t\tconflicts: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnodeId: '',\n\t\t\t\t\t\turl: config.sync?.url ?? '',\n\t\t\t\t\t\tschemaVersion: config.schema.version,\n\t\t\t\t\t\tlastSyncedAt: null,\n\t\t\t\t\t\tlastSuccessfulPush: null,\n\t\t\t\t\t\tlastSuccessfulPull: null,\n\t\t\t\t\t\tconflicts: 0,\n\t\t\t\t\t\tpendingOperations: 0,\n\t\t\t\t\t\thasInFlightBatch: false,\n\t\t\t\t\t\treconnecting: false,\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t}\n\t\t: null\n\n\t// Shared transaction executor for both transaction() and mutation()\n\tasync function executeTransaction(\n\t\tfn: (tx: TransactionProxy) => Promise<void>,\n\t\tmutationName?: string,\n\t): Promise<Operation[]> {\n\t\tawait ready\n\t\tif (!store) {\n\t\t\tthrow new Error('Store not initialized. Await app.ready before using transactions.')\n\t\t}\n\t\tconst txContext = store.createTransaction()\n\t\tif (mutationName !== undefined) {\n\t\t\ttxContext.setMutationName(mutationName)\n\t\t}\n\t\tconst collectionNames = Object.keys(config.schema.collections)\n\n\t\t// Build proxy with collection accessors as direct properties\n\t\tconst proxy: TransactionProxy = {} as TransactionProxy\n\t\tfor (const name of collectionNames) {\n\t\t\tObject.defineProperty(proxy, name, {\n\t\t\t\tget() {\n\t\t\t\t\treturn txContext.collection(name)\n\t\t\t\t},\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: false,\n\t\t\t})\n\t\t}\n\n\t\ttry {\n\t\t\tawait fn(proxy)\n\t\t\tconst { operations } = await txContext.commit()\n\n\t\t\t// Notify subscriptions and emit events after commit\n\t\t\tfor (const op of operations) {\n\t\t\t\tstore.getSubscriptionManager().notify(op.collection, op)\n\t\t\t\temitter.emit({ type: 'operation:created', operation: op })\n\t\t\t}\n\n\t\t\treturn operations\n\t\t} catch (error) {\n\t\t\ttxContext.rollback()\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t// Build sequences accessor (delegates to SequenceManager after ready)\n\tconst sequences: SequenceAccessor = {\n\t\tasync next(name, config) {\n\t\t\tawait ready\n\t\t\tif (!store) throw new Error('Store not initialized. Await app.ready before using sequences.')\n\t\t\treturn store.getSequenceManager().next(name, config)\n\t\t},\n\t\tasync current(name, config) {\n\t\t\tawait ready\n\t\t\tif (!store) throw new Error('Store not initialized. Await app.ready before using sequences.')\n\t\t\treturn store.getSequenceManager().current(name, config)\n\t\t},\n\t\tasync reset(name, config) {\n\t\t\tawait ready\n\t\t\tif (!store) throw new Error('Store not initialized. Await app.ready before using sequences.')\n\t\t\treturn store.getSequenceManager().reset(name, config)\n\t\t},\n\t}\n\n\t// Build the KoraApp object\n\tconst app: KoraApp = {\n\t\tready,\n\t\tevents: emitter,\n\t\tsync: syncControl,\n\t\tsequences,\n\t\tgetStore(): Store {\n\t\t\tif (!store) {\n\t\t\t\tthrow new Error('Store not initialized. Await app.ready before accessing the store.')\n\t\t\t}\n\t\t\treturn store\n\t\t},\n\t\tgetSyncEngine(): SyncEngine | null {\n\t\t\treturn syncEngine\n\t\t},\n\t\tasync transaction(fn: (tx: TransactionProxy) => Promise<void>): Promise<Operation[]> {\n\t\t\treturn executeTransaction(fn)\n\t\t},\n\t\tasync mutation(\n\t\t\tname: string,\n\t\t\tfn: (tx: TransactionProxy) => Promise<void>,\n\t\t): Promise<Operation[]> {\n\t\t\treturn executeTransaction(fn, name)\n\t\t},\n\t\tasync close(): Promise<void> {\n\t\t\tawait ready\n\t\t\tintentionalDisconnect = true\n\t\t\tif (qualityInterval !== null) {\n\t\t\t\tclearInterval(qualityInterval)\n\t\t\t\tqualityInterval = null\n\t\t\t}\n\t\t\treconnectionManager?.stop()\n\t\t\tif (instrumenter) {\n\t\t\t\tinstrumenter.destroy()\n\t\t\t\tinstrumenter = null\n\t\t\t}\n\t\t\tif (unsubscribeSync) {\n\t\t\t\tunsubscribeSync()\n\t\t\t\tunsubscribeSync = null\n\t\t\t}\n\t\t\tif (syncEngine) {\n\t\t\t\tawait syncEngine.stop()\n\t\t\t\tsyncEngine = null\n\t\t\t}\n\t\t\tif (store) {\n\t\t\t\tawait store.close()\n\t\t\t\tstore = null\n\t\t\t}\n\t\t\temitter.clear()\n\t\t},\n\t}\n\n\t// Define collection accessors via Object.defineProperty.\n\t// Before ready resolves, query methods return empty results.\n\tfor (const collectionName of Object.keys(config.schema.collections)) {\n\t\tObject.defineProperty(app, collectionName, {\n\t\t\tget(): CollectionAccessor {\n\t\t\t\treturn createCollectionAccessor(collectionName, () => store)\n\t\t\t},\n\t\t\tenumerable: true,\n\t\t\tconfigurable: false,\n\t\t})\n\t}\n\n\treturn app\n}\n\n/**\n * Asynchronous initialization: create adapter, open store, wire sync.\n */\nasync function initializeAsync(\n\tconfig: KoraConfig,\n\temitter: KoraEventEmitter,\n\tmergeEngine: MergeEngine,\n): Promise<{\n\tstore: Store\n\tsyncEngine: SyncEngine | null\n\tunsubscribeSync: (() => void) | null\n}> {\n\t// Resolve adapter\n\tconst adapterType = config.store?.adapter ?? detectAdapterType()\n\tconst dbName = config.store?.name ?? 'kora-db'\n\tconst adapter: StorageAdapter = await createAdapter(adapterType, dbName, config.store?.workerUrl)\n\n\t// Create and open the store\n\tconst store = new Store({\n\t\tschema: config.schema,\n\t\tadapter,\n\t\temitter,\n\t})\n\tawait store.open()\n\n\t// Wire sync if configured\n\tlet syncEngine: SyncEngine | null = null\n\tlet unsubscribeSync: (() => void) | null = null\n\n\tif (config.sync) {\n\t\tconst transport = new WebSocketTransport()\n\t\tconst mergeAwareStore = new MergeAwareSyncStore(store, mergeEngine, emitter)\n\n\t\t// Build scope map from schema scope declarations + flat scope values\n\t\tconst scopeMap = config.sync.scope ? buildScopeMap(config.schema, config.sync.scope) : undefined\n\n\t\tsyncEngine = new SyncEngine({\n\t\t\ttransport,\n\t\t\tstore: mergeAwareStore,\n\t\t\tconfig: {\n\t\t\t\turl: config.sync.url,\n\t\t\t\ttransport: config.sync.transport,\n\t\t\t\tauth: config.sync.auth,\n\t\t\t\tbatchSize: config.sync.batchSize,\n\t\t\t\tschemaVersion: config.sync.schemaVersion ?? config.schema.version,\n\t\t\t\tscopeMap,\n\t\t\t},\n\t\t\temitter,\n\t\t})\n\n\t\t// Wire local mutations → sync outbound queue\n\t\tunsubscribeSync = emitter.on('operation:created', (event) => {\n\t\t\tif (syncEngine) {\n\t\t\t\tsyncEngine.pushOperation(event.operation)\n\t\t\t}\n\t\t})\n\t}\n\n\treturn { store, syncEngine, unsubscribeSync }\n}\n\nfunction createCollectionAccessor(\n\tcollectionName: string,\n\tgetStore: () => Store | null,\n): CollectionAccessor {\n\treturn {\n\t\tasync insert(data: Record<string, unknown>) {\n\t\t\tconst currentStore = getStore()\n\t\t\tif (!currentStore) {\n\t\t\t\tthrow new Error(`Cannot mutate collection \"${collectionName}\" before app.ready resolves.`)\n\t\t\t}\n\t\t\treturn currentStore.collection(collectionName).insert(data)\n\t\t},\n\t\tasync findById(id: string) {\n\t\t\tconst currentStore = getStore()\n\t\t\tif (!currentStore) return null\n\t\t\treturn currentStore.collection(collectionName).findById(id)\n\t\t},\n\t\tasync update(id: string, data: Record<string, unknown>) {\n\t\t\tconst currentStore = getStore()\n\t\t\tif (!currentStore) {\n\t\t\t\tthrow new Error(`Cannot mutate collection \"${collectionName}\" before app.ready resolves.`)\n\t\t\t}\n\t\t\treturn currentStore.collection(collectionName).update(id, data)\n\t\t},\n\t\tasync delete(id: string) {\n\t\t\tconst currentStore = getStore()\n\t\t\tif (!currentStore) {\n\t\t\t\tthrow new Error(`Cannot mutate collection \"${collectionName}\" before app.ready resolves.`)\n\t\t\t}\n\t\t\treturn currentStore.collection(collectionName).delete(id)\n\t\t},\n\t\twhere(conditions: Record<string, unknown>) {\n\t\t\tconst currentStore = getStore()\n\t\t\tif (!currentStore) {\n\t\t\t\treturn createPendingQueryBuilder(conditions)\n\t\t\t}\n\t\t\treturn currentStore.collection(collectionName).where(conditions)\n\t\t},\n\t}\n}\n\nfunction createPendingQueryBuilder(initialWhere: Record<string, unknown>): QueryBuilder {\n\tconst descriptor = {\n\t\tcollection: '__pending__',\n\t\twhere: { ...initialWhere },\n\t\torderBy: [] as Array<{ field: string; direction: 'asc' | 'desc' }>,\n\t\tlimit: undefined as number | undefined,\n\t\toffset: undefined as number | undefined,\n\t}\n\n\tconst builder = {\n\t\twhere(conditions: Record<string, unknown>) {\n\t\t\tdescriptor.where = { ...descriptor.where, ...conditions }\n\t\t\treturn this\n\t\t},\n\t\torderBy(field: string, direction: 'asc' | 'desc' = 'asc') {\n\t\t\tdescriptor.orderBy.push({ field, direction })\n\t\t\treturn this\n\t\t},\n\t\tlimit(n: number) {\n\t\t\tdescriptor.limit = n\n\t\t\treturn this\n\t\t},\n\t\toffset(n: number) {\n\t\t\tdescriptor.offset = n\n\t\t\treturn this\n\t\t},\n\t\tasync exec() {\n\t\t\treturn []\n\t\t},\n\t\tasync count() {\n\t\t\treturn 0\n\t\t},\n\t\tsubscribe(callback: (results: Array<Record<string, unknown>>) => void) {\n\t\t\tvoid callback([])\n\t\t\treturn () => {}\n\t\t},\n\t\tgetDescriptor() {\n\t\t\treturn { ...descriptor, where: { ...descriptor.where }, orderBy: [...descriptor.orderBy] }\n\t\t},\n\t}\n\n\treturn builder as unknown as QueryBuilder\n}\n","import type { StorageAdapter } from '@korajs/store'\nimport type { AdapterType } from './types'\n\n/**\n * Detect the best storage adapter for the current environment.\n *\n * - Tauri app: 'tauri-sqlite' (native SQLite via Tauri plugin)\n * - Node.js: 'better-sqlite3'\n * - Browser with OPFS: 'sqlite-wasm'\n * - Browser without OPFS: 'indexeddb'\n */\nexport function detectAdapterType(): AdapterType {\n\t// Tauri environment — detected via __TAURI_INTERNALS__ injected by the Tauri runtime\n\tif (\n\t\ttypeof globalThis !== 'undefined' &&\n\t\ttypeof (globalThis as Record<string, unknown>).__TAURI_INTERNALS__ !== 'undefined'\n\t) {\n\t\treturn 'tauri-sqlite'\n\t}\n\n\t// Node.js environment\n\tif (typeof process !== 'undefined' && process.versions?.node) {\n\t\treturn 'better-sqlite3'\n\t}\n\n\t// Browser environment\n\tif (typeof globalThis.navigator !== 'undefined') {\n\t\t// Check for OPFS support (FileSystemHandle indicates OPFS availability)\n\t\tif (typeof (globalThis as Record<string, unknown>).FileSystemHandle !== 'undefined') {\n\t\t\treturn 'sqlite-wasm'\n\t\t}\n\t\treturn 'indexeddb'\n\t}\n\n\t// Default fallback (e.g., Deno, Bun, or other runtimes)\n\treturn 'better-sqlite3'\n}\n\n/**\n * Create a StorageAdapter for the given adapter type.\n * Uses dynamic imports so unused adapters are not bundled.\n *\n * @param type - The adapter type to create\n * @param dbName - Database name (used by all adapters)\n * @returns A configured StorageAdapter instance\n */\nexport async function createAdapter(\n\ttype: AdapterType,\n\tdbName: string,\n\tworkerUrl?: string | URL,\n): Promise<StorageAdapter> {\n\tswitch (type) {\n\t\tcase 'tauri-sqlite': {\n\t\t\t// @korajs/tauri is only installed in Tauri projects (optional peer dep).\n\t\t\t// This code path only runs when __TAURI_INTERNALS__ is detected.\n\t\t\t// Using @vite-ignore so Vite doesn't statically analyze this import —\n\t\t\t// it will still resolve it at runtime through Vite's dev server.\n\t\t\tconst { TauriSqliteAdapter } = await import(/* @vite-ignore */ '@korajs/tauri')\n\t\t\treturn new TauriSqliteAdapter({ path: `${dbName}.db` })\n\t\t}\n\t\tcase 'better-sqlite3': {\n\t\t\tconst { BetterSqlite3Adapter } = await import(\n\t\t\t\t/* @vite-ignore */ '@korajs/store/better-sqlite3'\n\t\t\t)\n\t\t\treturn new BetterSqlite3Adapter(dbName)\n\t\t}\n\t\tcase 'sqlite-wasm': {\n\t\t\tconst { SqliteWasmAdapter } = await import('@korajs/store/sqlite-wasm')\n\t\t\treturn new SqliteWasmAdapter({ dbName, workerUrl })\n\t\t}\n\t\tcase 'indexeddb': {\n\t\t\tconst { IndexedDbAdapter } = await import('@korajs/store/indexeddb')\n\t\t\treturn new IndexedDbAdapter({ dbName, workerUrl })\n\t\t}\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = type\n\t\t\tthrow new Error(`Unknown adapter type: ${_exhaustive}`)\n\t\t}\n\t}\n}\n","import type { KoraEventEmitter, Operation, VersionVector } from '@korajs/core'\nimport type { MergeEngine, MergeInput } from '@korajs/merge'\nimport type { Store } from '@korajs/store'\nimport type { ApplyResult, SyncStore } from '@korajs/sync'\n\n/**\n * Wraps a Store to interpose merge resolution before applying remote operations.\n *\n * For inserts and deletes, delegates directly to the underlying Store.\n * For updates, checks whether the remote operation's previousData conflicts\n * with the current local state. If so, runs MergeEngine to resolve and\n * applies the merged result instead.\n *\n * This keeps MergeEngine integration out of Store and SyncEngine internals.\n */\nexport class MergeAwareSyncStore implements SyncStore {\n\tconstructor(\n\t\tprivate readonly store: Store,\n\t\tprivate readonly mergeEngine: MergeEngine,\n\t\tprivate readonly emitter: KoraEventEmitter | null,\n\t) {}\n\n\tgetVersionVector(): VersionVector {\n\t\treturn this.store.getVersionVector()\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.store.getNodeId()\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\treturn this.store.getOperationRange(nodeId, fromSeq, toSeq)\n\t}\n\n\tasync applyRemoteOperation(op: Operation): Promise<ApplyResult> {\n\t\t// Only intercept updates that have previousData (needed for 3-way merge)\n\t\tif (op.type !== 'update' || !op.data || !op.previousData) {\n\t\t\treturn this.store.applyRemoteOperation(op)\n\t\t}\n\n\t\t// Look up current local record to detect conflicts\n\t\tconst schema = this.store.getSchema()\n\t\tconst collectionDef = schema.collections[op.collection]\n\t\tif (!collectionDef) {\n\t\t\treturn this.store.applyRemoteOperation(op)\n\t\t}\n\n\t\tconst accessor = this.store.collection(op.collection)\n\t\tconst currentRecord = await accessor.findById(op.recordId)\n\n\t\t// If record doesn't exist locally, delegate directly\n\t\tif (!currentRecord) {\n\t\t\treturn this.store.applyRemoteOperation(op)\n\t\t}\n\n\t\t// Check for conflicts: do any of the remote op's changed fields differ\n\t\t// from what the remote op expected them to be (previousData)?\n\t\tlet hasConflict = false\n\t\tfor (const field of Object.keys(op.data)) {\n\t\t\tconst expectedBase = op.previousData[field]\n\t\t\tconst currentLocal = currentRecord[field]\n\n\t\t\t// If the local state doesn't match what the remote expected,\n\t\t\t// it means the local side also changed this field — conflict.\n\t\t\tif (!deepEqual(expectedBase, currentLocal)) {\n\t\t\t\thasConflict = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// No conflict: safe to apply directly\n\t\tif (!hasConflict) {\n\t\t\treturn this.store.applyRemoteOperation(op)\n\t\t}\n\n\t\t// Conflict detected — run merge engine\n\t\t// Build a synthetic \"local operation\" representing the current local state changes\n\t\t// relative to the same base the remote operation used.\n\t\tthis.emitter?.emit({\n\t\t\ttype: 'merge:started',\n\t\t\toperationA: op,\n\t\t\toperationB: op,\n\t\t})\n\n\t\tconst baseState: Record<string, unknown> = { ...op.previousData }\n\t\tconst localOp: Operation = {\n\t\t\t...op,\n\t\t\t// The \"local\" operation's data is the diff between base and current local state\n\t\t\tdata: buildLocalDiff(op.previousData, currentRecord, Object.keys(op.data)),\n\t\t\tpreviousData: op.previousData,\n\t\t\tnodeId: this.store.getNodeId(),\n\t\t}\n\n\t\tconst input: MergeInput = {\n\t\t\tlocal: localOp,\n\t\t\tremote: op,\n\t\t\tbaseState,\n\t\t\tcollectionDef,\n\t\t}\n\n\t\tconst result = this.mergeEngine.mergeFields(input)\n\n\t\t// Emit merge traces\n\t\tfor (const trace of result.traces) {\n\t\t\tthis.emitter?.emit({ type: 'merge:conflict', trace })\n\t\t}\n\t\tconst firstTrace = result.traces[0]\n\t\tif (firstTrace) {\n\t\t\tthis.emitter?.emit({ type: 'merge:completed', trace: firstTrace })\n\t\t}\n\n\t\t// Create a modified operation with the merged data to apply\n\t\tconst mergedOp: Operation = {\n\t\t\t...op,\n\t\t\tdata: result.mergedData,\n\t\t}\n\n\t\treturn this.store.applyRemoteOperation(mergedOp)\n\t}\n}\n\n/**\n * Build the local diff: for each field the remote op changed,\n * extract the current local value (which may differ from both base and remote).\n */\nfunction buildLocalDiff(\n\tbaseState: Record<string, unknown>,\n\tcurrentRecord: Record<string, unknown>,\n\tfields: string[],\n): Record<string, unknown> {\n\tconst diff: Record<string, unknown> = {}\n\tfor (const field of fields) {\n\t\tdiff[field] = currentRecord[field]\n\t}\n\treturn diff\n}\n\n/**\n * Simple deep equality check for comparing field values.\n * Handles primitives, arrays, and plain objects.\n */\nfunction deepEqual(a: unknown, b: unknown): boolean {\n\tif (a === b) return true\n\tif (a === null || b === null) return false\n\tif (a === undefined || b === undefined) return false\n\tif (typeof a !== typeof b) return false\n\n\tif (Array.isArray(a) && Array.isArray(b)) {\n\t\tif (a.length !== b.length) return false\n\t\treturn a.every((val, i) => deepEqual(val, b[i]))\n\t}\n\n\tif (typeof a === 'object' && typeof b === 'object') {\n\t\tconst keysA = Object.keys(a as Record<string, unknown>)\n\t\tconst keysB = Object.keys(b as Record<string, unknown>)\n\t\tif (keysA.length !== keysB.length) return false\n\t\treturn keysA.every((key) =>\n\t\t\tdeepEqual((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key]),\n\t\t)\n\t}\n\n\treturn false\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,kBAA8B;AAC9B,sBAAmC;AACnC,sBAA6B;AAC7B,mBAA4B;AAC5B,mBAAsB;AAGtB,kBAKO;;;ACFA,SAAS,oBAAiC;AAEhD,MACC,OAAO,eAAe,eACtB,OAAQ,WAAuC,wBAAwB,aACtE;AACD,WAAO;AAAA,EACR;AAGA,MAAI,OAAO,YAAY,eAAe,QAAQ,UAAU,MAAM;AAC7D,WAAO;AAAA,EACR;AAGA,MAAI,OAAO,WAAW,cAAc,aAAa;AAEhD,QAAI,OAAQ,WAAuC,qBAAqB,aAAa;AACpF,aAAO;AAAA,IACR;AACA,WAAO;AAAA,EACR;AAGA,SAAO;AACR;AAUA,eAAsB,cACrB,MACA,QACA,WAC0B;AAC1B,UAAQ,MAAM;AAAA,IACb,KAAK,gBAAgB;AAKpB,YAAM,EAAE,mBAAmB,IAAI,MAAM;AAAA;AAAA,QAA0B;AAAA,MAAe;AAC9E,aAAO,IAAI,mBAAmB,EAAE,MAAM,GAAG,MAAM,MAAM,CAAC;AAAA,IACvD;AAAA,IACA,KAAK,kBAAkB;AACtB,YAAM,EAAE,qBAAqB,IAAI,MAAM;AAAA;AAAA,QACnB;AAAA,MACpB;AACA,aAAO,IAAI,qBAAqB,MAAM;AAAA,IACvC;AAAA,IACA,KAAK,eAAe;AACnB,YAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,2BAA2B;AACtE,aAAO,IAAI,kBAAkB,EAAE,QAAQ,UAAU,CAAC;AAAA,IACnD;AAAA,IACA,KAAK,aAAa;AACjB,YAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,yBAAyB;AACnE,aAAO,IAAI,iBAAiB,EAAE,QAAQ,UAAU,CAAC;AAAA,IAClD;AAAA,IACA,SAAS;AACR,YAAM,cAAqB;AAC3B,YAAM,IAAI,MAAM,yBAAyB,WAAW,EAAE;AAAA,IACvD;AAAA,EACD;AACD;;;AChEO,IAAM,sBAAN,MAA+C;AAAA,EACrD,YACkB,OACA,aACA,SAChB;AAHgB;AACA;AACA;AAAA,EACf;AAAA,EAHe;AAAA,EACA;AAAA,EACA;AAAA,EAGlB,mBAAkC;AACjC,WAAO,KAAK,MAAM,iBAAiB;AAAA,EACpC;AAAA,EAEA,YAAoB;AACnB,WAAO,KAAK,MAAM,UAAU;AAAA,EAC7B;AAAA,EAEA,MAAM,kBAAkB,QAAgB,SAAiB,OAAqC;AAC7F,WAAO,KAAK,MAAM,kBAAkB,QAAQ,SAAS,KAAK;AAAA,EAC3D;AAAA,EAEA,MAAM,qBAAqBA,KAAqC;AAE/D,QAAIA,IAAG,SAAS,YAAY,CAACA,IAAG,QAAQ,CAACA,IAAG,cAAc;AACzD,aAAO,KAAK,MAAM,qBAAqBA,GAAE;AAAA,IAC1C;AAGA,UAAM,SAAS,KAAK,MAAM,UAAU;AACpC,UAAM,gBAAgB,OAAO,YAAYA,IAAG,UAAU;AACtD,QAAI,CAAC,eAAe;AACnB,aAAO,KAAK,MAAM,qBAAqBA,GAAE;AAAA,IAC1C;AAEA,UAAM,WAAW,KAAK,MAAM,WAAWA,IAAG,UAAU;AACpD,UAAM,gBAAgB,MAAM,SAAS,SAASA,IAAG,QAAQ;AAGzD,QAAI,CAAC,eAAe;AACnB,aAAO,KAAK,MAAM,qBAAqBA,GAAE;AAAA,IAC1C;AAIA,QAAI,cAAc;AAClB,eAAW,SAAS,OAAO,KAAKA,IAAG,IAAI,GAAG;AACzC,YAAM,eAAeA,IAAG,aAAa,KAAK;AAC1C,YAAM,eAAe,cAAc,KAAK;AAIxC,UAAI,CAAC,UAAU,cAAc,YAAY,GAAG;AAC3C,sBAAc;AACd;AAAA,MACD;AAAA,IACD;AAGA,QAAI,CAAC,aAAa;AACjB,aAAO,KAAK,MAAM,qBAAqBA,GAAE;AAAA,IAC1C;AAKA,SAAK,SAAS,KAAK;AAAA,MAClB,MAAM;AAAA,MACN,YAAYA;AAAA,MACZ,YAAYA;AAAA,IACb,CAAC;AAED,UAAM,YAAqC,EAAE,GAAGA,IAAG,aAAa;AAChE,UAAM,UAAqB;AAAA,MAC1B,GAAGA;AAAA;AAAA,MAEH,MAAM,eAAeA,IAAG,cAAc,eAAe,OAAO,KAAKA,IAAG,IAAI,CAAC;AAAA,MACzE,cAAcA,IAAG;AAAA,MACjB,QAAQ,KAAK,MAAM,UAAU;AAAA,IAC9B;AAEA,UAAM,QAAoB;AAAA,MACzB,OAAO;AAAA,MACP,QAAQA;AAAA,MACR;AAAA,MACA;AAAA,IACD;AAEA,UAAM,SAAS,KAAK,YAAY,YAAY,KAAK;AAGjD,eAAW,SAAS,OAAO,QAAQ;AAClC,WAAK,SAAS,KAAK,EAAE,MAAM,kBAAkB,MAAM,CAAC;AAAA,IACrD;AACA,UAAM,aAAa,OAAO,OAAO,CAAC;AAClC,QAAI,YAAY;AACf,WAAK,SAAS,KAAK,EAAE,MAAM,mBAAmB,OAAO,WAAW,CAAC;AAAA,IAClE;AAGA,UAAM,WAAsB;AAAA,MAC3B,GAAGA;AAAA,MACH,MAAM,OAAO;AAAA,IACd;AAEA,WAAO,KAAK,MAAM,qBAAqB,QAAQ;AAAA,EAChD;AACD;AAMA,SAAS,eACR,WACA,eACA,QAC0B;AAC1B,QAAM,OAAgC,CAAC;AACvC,aAAW,SAAS,QAAQ;AAC3B,SAAK,KAAK,IAAI,cAAc,KAAK;AAAA,EAClC;AACA,SAAO;AACR;AAMA,SAAS,UAAU,GAAY,GAAqB;AACnD,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,MAAM,QAAQ,MAAM,KAAM,QAAO;AACrC,MAAI,MAAM,UAAa,MAAM,OAAW,QAAO;AAC/C,MAAI,OAAO,MAAM,OAAO,EAAG,QAAO;AAElC,MAAI,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,CAAC,GAAG;AACzC,QAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,WAAO,EAAE,MAAM,CAAC,KAAK,MAAM,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC;AAAA,EAChD;AAEA,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,UAAU;AACnD,UAAM,QAAQ,OAAO,KAAK,CAA4B;AACtD,UAAM,QAAQ,OAAO,KAAK,CAA4B;AACtD,QAAI,MAAM,WAAW,MAAM,OAAQ,QAAO;AAC1C,WAAO,MAAM;AAAA,MAAM,CAAC,QACnB,UAAW,EAA8B,GAAG,GAAI,EAA8B,GAAG,CAAC;AAAA,IACnF;AAAA,EACD;AAEA,SAAO;AACR;;;AF/FO,SAAS,UAAU,QAA6B;AACtD,QAAM,UAAgD,IAAI,mCAAmB;AAC7E,QAAM,cAAc,IAAI,yBAAY;AAEpC,MAAI,QAAsB;AAC1B,MAAI,aAAgC;AACpC,MAAI,kBAAuC;AAC3C,MAAI,sBAAkD;AACtD,MAAI,oBAA8C;AAClD,MAAI,eAAoC;AACxC,MAAI,wBAAwB;AAC5B,MAAI,kBAAyD;AAG7D,MAAI,OAAO,UAAU;AACpB,mBAAe,IAAI,6BAAa,SAAS;AAAA,MACxC,eAAe,OAAO,eAAe,eAAe,YAAY;AAAA,IACjE,CAAC;AAAA,EACF;AAGA,QAAM,QAAQ,gBAAgB,QAAQ,SAAS,WAAW,EAAE,KAAK,CAAC,WAAW;AAC5E,YAAQ,OAAO;AACf,iBAAa,OAAO;AACpB,sBAAkB,OAAO;AAGzB,QAAI,OAAO,QAAQ,YAAY;AAC9B,0BAAoB,IAAI,8BAAkB;AAC1C,4BAAsB,IAAI,gCAAoB;AAAA,QAC7C,cAAc,OAAO,KAAK;AAAA,QAC1B,UAAU,OAAO,KAAK;AAAA,MACvB,CAAC;AAGD,cAAQ,GAAG,aAAa,MAAM,mBAAmB,eAAe,CAAC;AACjE,cAAQ,GAAG,iBAAiB,MAAM,mBAAmB,eAAe,CAAC;AACrE,cAAQ,GAAG,qBAAqB,MAAM,mBAAmB,eAAe,CAAC;AAGzE,cAAQ,GAAG,kBAAkB,MAAM;AAClC,YAAI,oBAAoB,KAAM,eAAc,eAAe;AAC3D,0BAAkB,YAAY,MAAM;AACnC,cAAI,mBAAmB;AACtB,oBAAQ,KAAK,EAAE,MAAM,sBAAsB,SAAS,kBAAkB,WAAW,EAAE,CAAC;AAAA,UACrF;AAAA,QACD,GAAG,GAAI;AAAA,MACR,CAAC;AAGD,cAAQ,GAAG,qBAAqB,MAAM;AACrC,2BAAmB,MAAM;AACzB,YAAI,oBAAoB,MAAM;AAC7B,wBAAc,eAAe;AAC7B,4BAAkB;AAAA,QACnB;AAAA,MACD,CAAC;AAGD,UAAI,OAAO,KAAK,kBAAkB,OAAO;AACxC,cAAM,SAAS;AACf,gBAAQ,GAAG,qBAAqB,MAAM;AACrC,cAAI,sBAAuB;AAG3B,cAAI,qBAAqB,UAAU,EAAG;AAEtC,iBAAO,gBAAgB,IAAI;AAC3B,+BAAqB,KAAK;AAC1B,+BACG,MAAM,YAAY;AACnB,gBAAI;AACH,oBAAM,OAAO,MAAM;AACnB,qBAAO,gBAAgB,KAAK;AAC5B,qBAAO;AAAA,YACR,QAAQ;AACP,qBAAO;AAAA,YACR;AAAA,UACD,CAAC,EACA,KAAK,MAAM;AAEX,mBAAO,gBAAgB,KAAK;AAAA,UAC7B,CAAC;AAAA,QACH,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD,CAAC;AAGD,QAAM,cAAkC,OAAO,OAC5C;AAAA,IACA,MAAM,UAAyB;AAC9B,YAAM;AACN,UAAI,YAAY;AACf,gCAAwB;AACxB,6BAAqB,KAAK;AAC1B,6BAAqB,MAAM;AAC3B,cAAM,WAAW,MAAM;AAAA,MACxB;AAAA,IACD;AAAA,IACA,MAAM,aAA4B;AACjC,YAAM;AACN,UAAI,YAAY;AACf,gCAAwB;AACxB,6BAAqB,KAAK;AAC1B,cAAM,WAAW,KAAK;AAAA,MACvB;AAAA,IACD;AAAA,IACA,YAA4B;AAC3B,UAAI,YAAY;AACf,eAAO,WAAW,UAAU;AAAA,MAC7B;AACA,aAAO;AAAA,QACN,QAAQ;AAAA,QACR,mBAAmB;AAAA,QACnB,cAAc;AAAA,QACd,oBAAoB;AAAA,QACpB,oBAAoB;AAAA,QACpB,WAAW;AAAA,MACZ;AAAA,IACD;AAAA,IACA,MAAM,WAA0B;AAC/B,YAAM;AACN,UAAI,YAAY;AACf,cAAM,WAAW,SAAS;AAAA,MAC3B;AAAA,IACD;AAAA,IACA,oBAAoB;AACnB,UAAI,YAAY;AACf,eAAO,WAAW,kBAAkB;AAAA,MACrC;AACA,aAAO;AAAA,QACN,OAAO;AAAA,QACP,QAAQ;AAAA,UACP,QAAQ;AAAA,UACR,mBAAmB;AAAA,UACnB,cAAc;AAAA,UACd,oBAAoB;AAAA,UACpB,oBAAoB;AAAA,UACpB,WAAW;AAAA,QACZ;AAAA,QACA,QAAQ;AAAA,QACR,KAAK,OAAO,MAAM,OAAO;AAAA,QACzB,eAAe,OAAO,OAAO;AAAA,QAC7B,cAAc;AAAA,QACd,oBAAoB;AAAA,QACpB,oBAAoB;AAAA,QACpB,WAAW;AAAA,QACX,mBAAmB;AAAA,QACnB,kBAAkB;AAAA,QAClB,cAAc;AAAA,QACd,WAAW,KAAK,IAAI;AAAA,MACrB;AAAA,IACD;AAAA,EACD,IACC;AAGH,iBAAe,mBACd,IACA,cACuB;AACvB,UAAM;AACN,QAAI,CAAC,OAAO;AACX,YAAM,IAAI,MAAM,mEAAmE;AAAA,IACpF;AACA,UAAM,YAAY,MAAM,kBAAkB;AAC1C,QAAI,iBAAiB,QAAW;AAC/B,gBAAU,gBAAgB,YAAY;AAAA,IACvC;AACA,UAAM,kBAAkB,OAAO,KAAK,OAAO,OAAO,WAAW;AAG7D,UAAM,QAA0B,CAAC;AACjC,eAAW,QAAQ,iBAAiB;AACnC,aAAO,eAAe,OAAO,MAAM;AAAA,QAClC,MAAM;AACL,iBAAO,UAAU,WAAW,IAAI;AAAA,QACjC;AAAA,QACA,YAAY;AAAA,QACZ,cAAc;AAAA,MACf,CAAC;AAAA,IACF;AAEA,QAAI;AACH,YAAM,GAAG,KAAK;AACd,YAAM,EAAE,WAAW,IAAI,MAAM,UAAU,OAAO;AAG9C,iBAAWC,OAAM,YAAY;AAC5B,cAAM,uBAAuB,EAAE,OAAOA,IAAG,YAAYA,GAAE;AACvD,gBAAQ,KAAK,EAAE,MAAM,qBAAqB,WAAWA,IAAG,CAAC;AAAA,MAC1D;AAEA,aAAO;AAAA,IACR,SAAS,OAAO;AACf,gBAAU,SAAS;AACnB,YAAM;AAAA,IACP;AAAA,EACD;AAGA,QAAM,YAA8B;AAAA,IACnC,MAAM,KAAK,MAAMC,SAAQ;AACxB,YAAM;AACN,UAAI,CAAC,MAAO,OAAM,IAAI,MAAM,gEAAgE;AAC5F,aAAO,MAAM,mBAAmB,EAAE,KAAK,MAAMA,OAAM;AAAA,IACpD;AAAA,IACA,MAAM,QAAQ,MAAMA,SAAQ;AAC3B,YAAM;AACN,UAAI,CAAC,MAAO,OAAM,IAAI,MAAM,gEAAgE;AAC5F,aAAO,MAAM,mBAAmB,EAAE,QAAQ,MAAMA,OAAM;AAAA,IACvD;AAAA,IACA,MAAM,MAAM,MAAMA,SAAQ;AACzB,YAAM;AACN,UAAI,CAAC,MAAO,OAAM,IAAI,MAAM,gEAAgE;AAC5F,aAAO,MAAM,mBAAmB,EAAE,MAAM,MAAMA,OAAM;AAAA,IACrD;AAAA,EACD;AAGA,QAAM,MAAe;AAAA,IACpB;AAAA,IACA,QAAQ;AAAA,IACR,MAAM;AAAA,IACN;AAAA,IACA,WAAkB;AACjB,UAAI,CAAC,OAAO;AACX,cAAM,IAAI,MAAM,oEAAoE;AAAA,MACrF;AACA,aAAO;AAAA,IACR;AAAA,IACA,gBAAmC;AAClC,aAAO;AAAA,IACR;AAAA,IACA,MAAM,YAAY,IAAmE;AACpF,aAAO,mBAAmB,EAAE;AAAA,IAC7B;AAAA,IACA,MAAM,SACL,MACA,IACuB;AACvB,aAAO,mBAAmB,IAAI,IAAI;AAAA,IACnC;AAAA,IACA,MAAM,QAAuB;AAC5B,YAAM;AACN,8BAAwB;AACxB,UAAI,oBAAoB,MAAM;AAC7B,sBAAc,eAAe;AAC7B,0BAAkB;AAAA,MACnB;AACA,2BAAqB,KAAK;AAC1B,UAAI,cAAc;AACjB,qBAAa,QAAQ;AACrB,uBAAe;AAAA,MAChB;AACA,UAAI,iBAAiB;AACpB,wBAAgB;AAChB,0BAAkB;AAAA,MACnB;AACA,UAAI,YAAY;AACf,cAAM,WAAW,KAAK;AACtB,qBAAa;AAAA,MACd;AACA,UAAI,OAAO;AACV,cAAM,MAAM,MAAM;AAClB,gBAAQ;AAAA,MACT;AACA,cAAQ,MAAM;AAAA,IACf;AAAA,EACD;AAIA,aAAW,kBAAkB,OAAO,KAAK,OAAO,OAAO,WAAW,GAAG;AACpE,WAAO,eAAe,KAAK,gBAAgB;AAAA,MAC1C,MAA0B;AACzB,eAAO,yBAAyB,gBAAgB,MAAM,KAAK;AAAA,MAC5D;AAAA,MACA,YAAY;AAAA,MACZ,cAAc;AAAA,IACf,CAAC;AAAA,EACF;AAEA,SAAO;AACR;AAKA,eAAe,gBACd,QACA,SACA,aAKE;AAEF,QAAM,cAAc,OAAO,OAAO,WAAW,kBAAkB;AAC/D,QAAM,SAAS,OAAO,OAAO,QAAQ;AACrC,QAAM,UAA0B,MAAM,cAAc,aAAa,QAAQ,OAAO,OAAO,SAAS;AAGhG,QAAM,QAAQ,IAAI,mBAAM;AAAA,IACvB,QAAQ,OAAO;AAAA,IACf;AAAA,IACA;AAAA,EACD,CAAC;AACD,QAAM,MAAM,KAAK;AAGjB,MAAI,aAAgC;AACpC,MAAI,kBAAuC;AAE3C,MAAI,OAAO,MAAM;AAChB,UAAM,YAAY,IAAI,+BAAmB;AACzC,UAAM,kBAAkB,IAAI,oBAAoB,OAAO,aAAa,OAAO;AAG3E,UAAM,WAAW,OAAO,KAAK,YAAQ,2BAAc,OAAO,QAAQ,OAAO,KAAK,KAAK,IAAI;AAEvF,iBAAa,IAAI,uBAAW;AAAA,MAC3B;AAAA,MACA,OAAO;AAAA,MACP,QAAQ;AAAA,QACP,KAAK,OAAO,KAAK;AAAA,QACjB,WAAW,OAAO,KAAK;AAAA,QACvB,MAAM,OAAO,KAAK;AAAA,QAClB,WAAW,OAAO,KAAK;AAAA,QACvB,eAAe,OAAO,KAAK,iBAAiB,OAAO,OAAO;AAAA,QAC1D;AAAA,MACD;AAAA,MACA;AAAA,IACD,CAAC;AAGD,sBAAkB,QAAQ,GAAG,qBAAqB,CAAC,UAAU;AAC5D,UAAI,YAAY;AACf,mBAAW,cAAc,MAAM,SAAS;AAAA,MACzC;AAAA,IACD,CAAC;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,YAAY,gBAAgB;AAC7C;AAEA,SAAS,yBACR,gBACA,UACqB;AACrB,SAAO;AAAA,IACN,MAAM,OAAO,MAA+B;AAC3C,YAAM,eAAe,SAAS;AAC9B,UAAI,CAAC,cAAc;AAClB,cAAM,IAAI,MAAM,6BAA6B,cAAc,8BAA8B;AAAA,MAC1F;AACA,aAAO,aAAa,WAAW,cAAc,EAAE,OAAO,IAAI;AAAA,IAC3D;AAAA,IACA,MAAM,SAAS,IAAY;AAC1B,YAAM,eAAe,SAAS;AAC9B,UAAI,CAAC,aAAc,QAAO;AAC1B,aAAO,aAAa,WAAW,cAAc,EAAE,SAAS,EAAE;AAAA,IAC3D;AAAA,IACA,MAAM,OAAO,IAAY,MAA+B;AACvD,YAAM,eAAe,SAAS;AAC9B,UAAI,CAAC,cAAc;AAClB,cAAM,IAAI,MAAM,6BAA6B,cAAc,8BAA8B;AAAA,MAC1F;AACA,aAAO,aAAa,WAAW,cAAc,EAAE,OAAO,IAAI,IAAI;AAAA,IAC/D;AAAA,IACA,MAAM,OAAO,IAAY;AACxB,YAAM,eAAe,SAAS;AAC9B,UAAI,CAAC,cAAc;AAClB,cAAM,IAAI,MAAM,6BAA6B,cAAc,8BAA8B;AAAA,MAC1F;AACA,aAAO,aAAa,WAAW,cAAc,EAAE,OAAO,EAAE;AAAA,IACzD;AAAA,IACA,MAAM,YAAqC;AAC1C,YAAM,eAAe,SAAS;AAC9B,UAAI,CAAC,cAAc;AAClB,eAAO,0BAA0B,UAAU;AAAA,MAC5C;AACA,aAAO,aAAa,WAAW,cAAc,EAAE,MAAM,UAAU;AAAA,IAChE;AAAA,EACD;AACD;AAEA,SAAS,0BAA0B,cAAqD;AACvF,QAAM,aAAa;AAAA,IAClB,YAAY;AAAA,IACZ,OAAO,EAAE,GAAG,aAAa;AAAA,IACzB,SAAS,CAAC;AAAA,IACV,OAAO;AAAA,IACP,QAAQ;AAAA,EACT;AAEA,QAAM,UAAU;AAAA,IACf,MAAM,YAAqC;AAC1C,iBAAW,QAAQ,EAAE,GAAG,WAAW,OAAO,GAAG,WAAW;AACxD,aAAO;AAAA,IACR;AAAA,IACA,QAAQ,OAAe,YAA4B,OAAO;AACzD,iBAAW,QAAQ,KAAK,EAAE,OAAO,UAAU,CAAC;AAC5C,aAAO;AAAA,IACR;AAAA,IACA,MAAM,GAAW;AAChB,iBAAW,QAAQ;AACnB,aAAO;AAAA,IACR;AAAA,IACA,OAAO,GAAW;AACjB,iBAAW,SAAS;AACpB,aAAO;AAAA,IACR;AAAA,IACA,MAAM,OAAO;AACZ,aAAO,CAAC;AAAA,IACT;AAAA,IACA,MAAM,QAAQ;AACb,aAAO;AAAA,IACR;AAAA,IACA,UAAU,UAA6D;AACtE,WAAK,SAAS,CAAC,CAAC;AAChB,aAAO,MAAM;AAAA,MAAC;AAAA,IACf;AAAA,IACA,gBAAgB;AACf,aAAO,EAAE,GAAG,YAAY,OAAO,EAAE,GAAG,WAAW,MAAM,GAAG,SAAS,CAAC,GAAG,WAAW,OAAO,EAAE;AAAA,IAC1F;AAAA,EACD;AAEA,SAAO;AACR;;;AD3dA,IAAAC,eAAyC;AACzC,IAAAA,eAAmC;AACnC,IAAAA,eAA+B;AAC/B,IAAAA,eAAgC;AAChC,IAAAA,eAA0B;AAC1B,IAAAA,eAAmB;AA+BnB,IAAAC,gBAAuC;AACvC,IAAAA,gBAAmC;AAWnC,IAAAC,gBAA4B;AAI5B,IAAAC,eAA+C;","names":["op","op","config","import_core","import_store","import_merge","import_sync"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/create-app.ts","../src/adapter-resolver.ts","../src/app-not-ready-error.ts","../src/apply-pipeline.ts","../src/build-side-effect-entry.ts","../src/audit-bridge.ts","../src/merge-aware-sync-store.ts","../src/store-queue-storage.ts","../src/store-sync-state.ts","../src/sync-query-bridge.ts","../src/sync-status-bridge.ts","../src/validate-config.ts"],"sourcesContent":["// kora — meta-package re-exporting core, store, merge, sync\n// This is the primary entry point for `import { createApp, defineSchema, t } from 'korajs'`\n\n// === createApp factory ===\nexport { createApp } from './create-app'\n\n// === App types ===\nexport type {\n\tAdapterType,\n\tAuthSyncBinding,\n\tKoraApp,\n\tKoraConfig,\n\tStoreOptions,\n\tSyncControl,\n\tSyncOptions,\n\tSequenceAccessor,\n\tTransactionCollectionProxy,\n\tTransactionProxy,\n\tTypedCollectionAccessor,\n\tTypedKoraApp,\n\tTypedKoraConfig,\n} from './types'\n\nexport type { ReplaySnapshot } from '@korajs/store'\nexport type {\n\tAuditExportManifest,\n\tAuditExportOptions,\n\tAuditExportPayload,\n\tPersistedAuditTrace,\n} from '@korajs/store'\nexport {\n\tdecodeAuditExport,\n\treadAuditExportManifest,\n\tverifyAuditExportChecksum,\n} from '@korajs/store'\n\n// === @korajs/core re-exports ===\nexport { defineSchema, migrate, t } from '@korajs/core'\nexport { HybridLogicalClock } from '@korajs/core'\nexport { generateUUIDv7 } from '@korajs/core'\nexport { createOperation } from '@korajs/core'\nexport { KoraError } from '@korajs/core'\nexport { op } from '@korajs/core'\nexport type {\n\tAtomicOp,\n\tAtomicOpType,\n\tCollectionDefinition,\n\tConnectionQuality,\n\tConstraint,\n\tFieldDescriptor,\n\tFieldKindToType,\n\tHLCTimestamp,\n\tInferFieldType,\n\tInferInsertInput,\n\tInferRecord,\n\tInferUpdateInput,\n\tKoraEvent,\n\tKoraEventEmitter,\n\tKoraEventListener,\n\tKoraEventType,\n\tMergeStrategy,\n\tMergeTrace,\n\tMigrationDefinition,\n\tMigrationStep,\n\tOperation,\n\tSchemaDefinition,\n\tSchemaInput,\n\tSequenceConfig,\n\tSyncRuleDefinition,\n\tTypedSchemaDefinition,\n\tVersionVector,\n} from '@korajs/core'\n\n// === @korajs/store re-exports ===\nexport { SequenceManager, Store } from '@korajs/store'\nexport { TransactionContext } from '@korajs/store'\nexport {\n\texportBackup,\n\treadBackupManifest,\n\trestoreBackup,\n\tverifyBackupChecksum,\n} from '@korajs/store'\nexport type {\n\tBackupManifest,\n\tBackupOptions,\n\tBackupProgress,\n\tCollectionAccessor,\n\tCollectionRecord,\n\tRestoreOptions,\n\tRestoreResult,\n\tStorageAdapter,\n\tStoreConfig,\n\tTransactionCollectionAccessor,\n\tTransactionContextConfig,\n} from '@korajs/store'\n\n// === @korajs/merge re-exports ===\nexport { MergeEngine } from '@korajs/merge'\nexport type { MergeInput, MergeResult } from '@korajs/merge'\n\n// === @korajs/sync re-exports ===\nexport { SyncEngine, WebSocketTransport } from '@korajs/sync'\nexport type {\n\tSyncConfig,\n\tSyncDiagnostics,\n\tSyncEncryptionConfig,\n\tSyncState,\n\tSyncStatus,\n\tSyncStatusInfo,\n\tSyncStore,\n} from '@korajs/sync'\n","import type { KoraEventEmitter, Operation, SchemaInput } from '@korajs/core'\nimport { buildScopeMap } from '@korajs/core'\nimport { SimpleEventEmitter } from '@korajs/core/internal'\nimport { Instrumenter } from '@korajs/devtools'\nimport { MergeEngine } from '@korajs/merge'\nimport { Store } from '@korajs/store'\nimport type {\n\tAuditExportOptions,\n\tBackupOptions,\n\tCollectionAccessor,\n\tQueryBuilder,\n\tReplaySnapshot,\n\tRestoreOptions,\n\tRestoreResult,\n\tStorageAdapter,\n} from '@korajs/store'\nimport {\n\tConnectionMonitor,\n\tHttpLongPollingTransport,\n\tReconnectionManager,\n\tSyncEncryptor,\n\tSyncEngine,\n\tWebSocketTransport,\n} from '@korajs/sync'\nimport type { SyncTransport } from '@korajs/sync'\nimport type { SyncStatusInfo } from '@korajs/sync'\nimport { createAdapter, detectAdapterType } from './adapter-resolver'\nimport { AppNotReadyError } from './app-not-ready-error'\nimport { ApplyPipeline } from './apply-pipeline'\nimport { wireAuditPersistence } from './audit-bridge'\nimport { MergeAwareSyncStore } from './merge-aware-sync-store'\nimport { StoreQueueStorage } from './store-queue-storage'\nimport { StoreSyncStatePersistence } from './store-sync-state'\nimport { createSyncQuerySubscriptionHook } from './sync-query-bridge'\nimport { createSyncStatusBridge } from './sync-status-bridge'\nimport type {\n\tAuthSyncBinding,\n\tKoraApp,\n\tKoraConfig,\n\tKoraSyncEvent,\n\tSequenceAccessor,\n\tSyncControl,\n\tTransactionProxy,\n\tTypedKoraApp,\n\tTypedKoraConfig,\n} from './types'\nimport { validateCreateAppConfig } from './validate-config'\n\n/**\n * Creates a new Kora application instance.\n *\n * Wires together store, merge engine, event emitter, and optionally sync\n * into a single developer-facing `KoraApp` object. Collection accessors\n * (e.g. `app.todos`) are defined as properties for immediate use after `await app.ready`.\n *\n * @param config - Application configuration including schema and optional sync settings\n * @returns A KoraApp instance with reactive collections ready for use\n *\n * @example\n * ```typescript\n * const app = createApp({\n * schema: defineSchema({\n * version: 1,\n * collections: {\n * todos: {\n * fields: {\n * title: t.string(),\n * completed: t.boolean().default(false)\n * }\n * }\n * }\n * })\n * })\n *\n * await app.ready\n * const todo = await app.todos.insert({ title: 'Hello' })\n * ```\n */\n/**\n * Creates a new typed Kora application instance.\n * When the schema is created with `defineSchema()`, full type inference flows through\n * to collection accessors, providing autocomplete and type checking for all CRUD operations.\n */\nexport function createApp<const S extends SchemaInput>(config: TypedKoraConfig<S>): TypedKoraApp<S>\n/**\n * Creates a new Kora application instance (untyped fallback).\n */\nexport function createApp(config: KoraConfig): KoraApp\nexport function createApp<const S extends SchemaInput>(\n\tconfig: TypedKoraConfig<S> | KoraConfig,\n): TypedKoraApp<S> | KoraApp {\n\tvalidateCreateAppConfig(config)\n\n\tconst emitter: KoraEventEmitter & { clear(): void } = new SimpleEventEmitter()\n\tconst mergeEngine = new MergeEngine()\n\n\tif (config.onSyncEvent) {\n\t\tconst handler = config.onSyncEvent\n\t\tconst syncTypes = [\n\t\t\t'sync:connected',\n\t\t\t'sync:disconnected',\n\t\t\t'sync:schema-mismatch',\n\t\t\t'sync:auth-failed',\n\t\t\t'sync:sent',\n\t\t\t'sync:received',\n\t\t\t'sync:acknowledged',\n\t\t\t'sync:apply-failed',\n\t\t\t'sync:diagnostics',\n\t\t\t'sync:bandwidth',\n\t\t\t'sync:initial-sync-progress',\n\t\t] as const\n\t\tfor (const type of syncTypes) {\n\t\t\temitter.on(type, (event) => {\n\t\t\t\thandler(event as KoraSyncEvent)\n\t\t\t})\n\t\t}\n\t}\n\n\tlet store: Store | null = null\n\tlet syncEngine: SyncEngine | null = null\n\tlet unsubscribeSync: (() => void) | null = null\n\tlet unsubscribeAudit: (() => void) | null = null\n\tlet reconnectionManager: ReconnectionManager | null = null\n\tlet connectionMonitor: ConnectionMonitor | null = null\n\tlet instrumenter: Instrumenter | null = null\n\tlet intentionalDisconnect = false\n\tlet qualityInterval: ReturnType<typeof setInterval> | null = null\n\tlet syncStatusBridge: ReturnType<typeof createSyncStatusBridge> | null = null\n\tlet destroyDevtoolsOverlay: (() => void) | null = null\n\n\t// Wire DevTools instrumentation immediately (emitter exists synchronously)\n\tif (config.devtools) {\n\t\tinstrumenter = new Instrumenter(emitter, {\n\t\t\tbridgeEnabled: typeof globalThis !== 'undefined' && 'window' in globalThis,\n\t\t})\n\t\tif (typeof globalThis !== 'undefined' && 'window' in globalThis) {\n\t\t\tvoid import('@korajs/devtools/overlay')\n\t\t\t\t.then(({ mountKoraDevtoolsOverlay }) => {\n\t\t\t\t\tif (instrumenter) {\n\t\t\t\t\t\tdestroyDevtoolsOverlay = mountKoraDevtoolsOverlay(instrumenter)\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.catch(() => {\n\t\t\t\t\t// Overlay is optional; extension bridge still works.\n\t\t\t\t})\n\t\t}\n\t}\n\n\t// Build the ready promise — resolves when the store is open and wired\n\tconst ready = initializeAsync(config, emitter, mergeEngine).then((result) => {\n\t\tstore = result.store\n\t\tsyncEngine = result.syncEngine\n\t\tunsubscribeSync = result.unsubscribeSync\n\t\tunsubscribeAudit = result.unsubscribeAudit\n\t\tconst authBinding = result.authBinding\n\n\t\tif (config.sync) {\n\t\t\tsyncStatusBridge = createSyncStatusBridge(emitter, () => syncEngine)\n\t\t\tsyncStatusBridge.refresh()\n\t\t}\n\n\t\tif (config.sync && syncEngine && authBinding?.subscribe) {\n\t\t\tauthBinding.subscribe(() => {\n\t\t\t\tconst engine = syncEngine\n\t\t\t\tif (!engine) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tvoid (async () => {\n\t\t\t\t\tconst headers = await authBinding.auth()\n\t\t\t\t\tif (!headers.token) {\n\t\t\t\t\t\tawait engine.stop()\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tif (authBinding.resolveScopeMap) {\n\t\t\t\t\t\tconst nextScope = await authBinding.resolveScopeMap()\n\t\t\t\t\t\tengine.updateScope(nextScope)\n\t\t\t\t\t}\n\n\t\t\t\t\tconst status = engine.getStatus().status\n\t\t\t\t\tif (status !== 'offline') {\n\t\t\t\t\t\tawait engine.stop()\n\t\t\t\t\t}\n\t\t\t\t\tawait engine.start()\n\t\t\t\t})()\n\t\t\t})\n\t\t}\n\n\t\t// Wire reconnection and connection quality after sync engine is ready\n\t\tif (config.sync && syncEngine) {\n\t\t\tconnectionMonitor = new ConnectionMonitor()\n\t\t\treconnectionManager = new ReconnectionManager({\n\t\t\t\tinitialDelay: config.sync.reconnectInterval,\n\t\t\t\tmaxDelay: config.sync.maxReconnectInterval,\n\t\t\t})\n\n\t\t\t// Track activity for connection quality\n\t\t\temitter.on('sync:sent', () => connectionMonitor?.recordActivity())\n\t\t\temitter.on('sync:received', () => connectionMonitor?.recordActivity())\n\t\t\temitter.on('sync:acknowledged', () => connectionMonitor?.recordActivity())\n\n\t\t\t// Emit quality on timer while connected\n\t\t\temitter.on('sync:connected', () => {\n\t\t\t\tif (qualityInterval !== null) clearInterval(qualityInterval)\n\t\t\t\tqualityInterval = setInterval(() => {\n\t\t\t\t\tif (connectionMonitor) {\n\t\t\t\t\t\temitter.emit({ type: 'connection:quality', quality: connectionMonitor.getQuality() })\n\t\t\t\t\t}\n\t\t\t\t}, 5000)\n\t\t\t})\n\n\t\t\t// Reset monitor and clear timer on disconnect\n\t\t\temitter.on('sync:disconnected', () => {\n\t\t\t\tconnectionMonitor?.reset()\n\t\t\t\tif (qualityInterval !== null) {\n\t\t\t\t\tclearInterval(qualityInterval)\n\t\t\t\t\tqualityInterval = null\n\t\t\t\t}\n\t\t\t})\n\n\t\t\t// Reconnect immediately when the browser reports connectivity restored\n\t\t\tconst browserGlobal = globalThis as typeof globalThis & {\n\t\t\t\taddEventListener?: (type: string, listener: () => void) => void\n\t\t\t}\n\t\t\tif (typeof browserGlobal.addEventListener === 'function') {\n\t\t\t\tconst engine = syncEngine\n\t\t\t\tbrowserGlobal.addEventListener('online', () => {\n\t\t\t\t\tif (intentionalDisconnect || config.sync?.autoReconnect === false) return\n\t\t\t\t\treconnectionManager?.wake()\n\t\t\t\t\treconnectionManager?.reset()\n\t\t\t\t\tvoid engine.retryNow()\n\t\t\t\t})\n\t\t\t}\n\n\t\t\temitter.on('sync:schema-mismatch', () => {\n\t\t\t\treconnectionManager?.stop()\n\t\t\t\tintentionalDisconnect = true\n\t\t\t})\n\n\t\t\t// Auto-reconnect on unexpected disconnect\n\t\t\tif (config.sync.autoReconnect !== false) {\n\t\t\t\tconst engine = syncEngine\n\t\t\t\temitter.on('sync:disconnected', () => {\n\t\t\t\t\tif (intentionalDisconnect || engine.isSchemaBlocked()) return\n\t\t\t\t\t// Ignore cascading disconnect events from failed reconnection attempts.\n\t\t\t\t\t// The reconnection manager is already retrying — don't restart it.\n\t\t\t\t\tif (reconnectionManager?.isRunning()) return\n\n\t\t\t\t\tengine.setReconnecting(true)\n\t\t\t\t\treconnectionManager?.stop()\n\t\t\t\t\treconnectionManager\n\t\t\t\t\t\t?.start(async () => {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait engine.start()\n\t\t\t\t\t\t\t\tengine.setReconnecting(false)\n\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.then(() => {\n\t\t\t\t\t\t\t// If reconnection exhausted max attempts without success, clear flag\n\t\t\t\t\t\t\tengine.setReconnecting(false)\n\t\t\t\t\t\t})\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif (config.sync.autoConnect === true && syncEngine) {\n\t\t\t\tvoid syncEngine.start().catch(() => {\n\t\t\t\t\t// Errors surface via sync:disconnected / sync events; avoid unhandled rejection.\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t})\n\n\tconst offlineSyncStatus = (): SyncStatusInfo => ({\n\t\tstatus: 'offline',\n\t\tpendingOperations: 0,\n\t\tlastSyncedAt: null,\n\t\tlastSuccessfulPush: null,\n\t\tlastSuccessfulPull: null,\n\t\tconflicts: 0,\n\t})\n\n\t// Build sync control\n\tconst syncControl: SyncControl | null = config.sync\n\t\t? {\n\t\t\t\tget status(): SyncStatusInfo {\n\t\t\t\t\treturn syncStatusBridge?.status ?? offlineSyncStatus()\n\t\t\t\t},\n\t\t\t\tsubscribeStatus(listener: (status: SyncStatusInfo) => void): () => void {\n\t\t\t\t\tif (syncStatusBridge) {\n\t\t\t\t\t\treturn syncStatusBridge.subscribe(listener)\n\t\t\t\t\t}\n\t\t\t\t\tlistener(offlineSyncStatus())\n\t\t\t\t\treturn () => {}\n\t\t\t\t},\n\t\t\t\tasync connect(): Promise<void> {\n\t\t\t\t\tawait ready\n\t\t\t\t\tif (syncEngine) {\n\t\t\t\t\t\tintentionalDisconnect = false\n\t\t\t\t\t\treconnectionManager?.stop()\n\t\t\t\t\t\treconnectionManager?.reset()\n\t\t\t\t\t\tawait syncEngine.start()\n\t\t\t\t\t\tsyncStatusBridge?.refresh()\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tasync disconnect(): Promise<void> {\n\t\t\t\t\tawait ready\n\t\t\t\t\tif (syncEngine) {\n\t\t\t\t\t\tintentionalDisconnect = true\n\t\t\t\t\t\treconnectionManager?.stop()\n\t\t\t\t\t\tawait syncEngine.stop()\n\t\t\t\t\t\tsyncStatusBridge?.refresh()\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tgetStatus(): SyncStatusInfo {\n\t\t\t\t\tif (syncEngine) {\n\t\t\t\t\t\treturn syncEngine.getStatus()\n\t\t\t\t\t}\n\t\t\t\t\treturn offlineSyncStatus()\n\t\t\t\t},\n\t\t\t\tasync retryNow(): Promise<void> {\n\t\t\t\t\tawait ready\n\t\t\t\t\tif (syncEngine) {\n\t\t\t\t\t\tawait syncEngine.retryNow()\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tclearSchemaBlock(): void {\n\t\t\t\t\tsyncEngine?.clearSchemaBlock()\n\t\t\t\t},\n\t\t\t\texportDiagnostics() {\n\t\t\t\t\tif (syncEngine) {\n\t\t\t\t\t\treturn syncEngine.exportDiagnostics()\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstate: 'disconnected' as const,\n\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\tstatus: 'offline' as const,\n\t\t\t\t\t\t\tpendingOperations: 0,\n\t\t\t\t\t\t\tlastSyncedAt: null,\n\t\t\t\t\t\t\tlastSuccessfulPush: null,\n\t\t\t\t\t\t\tlastSuccessfulPull: null,\n\t\t\t\t\t\t\tconflicts: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnodeId: '',\n\t\t\t\t\t\turl: config.sync?.url ?? '',\n\t\t\t\t\t\tschemaVersion: config.schema.version,\n\t\t\t\t\t\tlastSyncedAt: null,\n\t\t\t\t\t\tlastSuccessfulPush: null,\n\t\t\t\t\t\tlastSuccessfulPull: null,\n\t\t\t\t\t\tconflicts: 0,\n\t\t\t\t\t\tpendingOperations: 0,\n\t\t\t\t\t\thasInFlightBatch: false,\n\t\t\t\t\t\treconnecting: false,\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t}\n\t\t: null\n\n\t// Shared transaction executor for both transaction() and mutation()\n\tasync function executeTransaction(\n\t\tfn: (tx: TransactionProxy) => Promise<void>,\n\t\tmutationName?: string,\n\t): Promise<Operation[]> {\n\t\tawait ready\n\t\tif (!store) {\n\t\t\tthrow new Error('Store not initialized. Await app.ready before using transactions.')\n\t\t}\n\t\tconst collectionNames = Object.keys(config.schema.collections)\n\n\t\treturn store.transaction(async (tx) => {\n\t\t\tif (mutationName !== undefined) {\n\t\t\t\ttx.setMutationName(mutationName)\n\t\t\t}\n\t\t\tconst proxy: TransactionProxy = {} as TransactionProxy\n\t\t\tfor (const name of collectionNames) {\n\t\t\t\tObject.defineProperty(proxy, name, {\n\t\t\t\t\tget() {\n\t\t\t\t\t\treturn tx.collection(name)\n\t\t\t\t\t},\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\tconfigurable: false,\n\t\t\t\t})\n\t\t\t}\n\t\t\tawait fn(proxy)\n\t\t})\n\t}\n\n\t// Build sequences accessor (delegates to SequenceManager after ready)\n\tconst sequences: SequenceAccessor = {\n\t\tasync next(name, config) {\n\t\t\tawait ready\n\t\t\tif (!store) throw new Error('Store not initialized. Await app.ready before using sequences.')\n\t\t\treturn store.getSequenceManager().next(name, config)\n\t\t},\n\t\tasync current(name, config) {\n\t\t\tawait ready\n\t\t\tif (!store) throw new Error('Store not initialized. Await app.ready before using sequences.')\n\t\t\treturn store.getSequenceManager().current(name, config)\n\t\t},\n\t\tasync reset(name, config) {\n\t\t\tawait ready\n\t\t\tif (!store) throw new Error('Store not initialized. Await app.ready before using sequences.')\n\t\t\treturn store.getSequenceManager().reset(name, config)\n\t\t},\n\t}\n\n\t// Build the KoraApp object\n\tconst app: KoraApp = {\n\t\tready,\n\t\tevents: emitter,\n\t\tsync: syncControl,\n\t\tsequences,\n\t\tgetStore(): Store {\n\t\t\tif (!store) {\n\t\t\t\tthrow new Error('Store not initialized. Await app.ready before accessing the store.')\n\t\t\t}\n\t\t\treturn store\n\t\t},\n\t\tgetSyncEngine(): SyncEngine | null {\n\t\t\treturn syncEngine\n\t\t},\n\t\tasync transaction(fn: (tx: TransactionProxy) => Promise<void>): Promise<Operation[]> {\n\t\t\treturn executeTransaction(fn)\n\t\t},\n\t\tasync mutation(\n\t\t\tname: string,\n\t\t\tfn: (tx: TransactionProxy) => Promise<void>,\n\t\t): Promise<Operation[]> {\n\t\t\treturn executeTransaction(fn, name)\n\t\t},\n\t\tasync close(): Promise<void> {\n\t\t\tawait ready\n\t\t\tintentionalDisconnect = true\n\t\t\tif (qualityInterval !== null) {\n\t\t\t\tclearInterval(qualityInterval)\n\t\t\t\tqualityInterval = null\n\t\t\t}\n\t\t\treconnectionManager?.stop()\n\t\t\tif (destroyDevtoolsOverlay) {\n\t\t\t\tdestroyDevtoolsOverlay()\n\t\t\t\tdestroyDevtoolsOverlay = null\n\t\t\t}\n\t\t\tif (instrumenter) {\n\t\t\t\tinstrumenter.destroy()\n\t\t\t\tinstrumenter = null\n\t\t\t}\n\t\t\tif (unsubscribeSync) {\n\t\t\t\tunsubscribeSync()\n\t\t\t\tunsubscribeSync = null\n\t\t\t}\n\t\t\tif (unsubscribeAudit) {\n\t\t\t\tunsubscribeAudit()\n\t\t\t\tunsubscribeAudit = null\n\t\t\t}\n\t\t\tif (syncEngine) {\n\t\t\t\tawait syncEngine.stop()\n\t\t\t\tsyncEngine = null\n\t\t\t}\n\t\t\tif (syncStatusBridge) {\n\t\t\t\tsyncStatusBridge.destroy()\n\t\t\t\tsyncStatusBridge = null\n\t\t\t}\n\t\t\tif (store) {\n\t\t\t\tawait store.close()\n\t\t\t\tstore = null\n\t\t\t}\n\t\t\temitter.clear()\n\t\t},\n\t\tasync exportBackup(options?: BackupOptions): Promise<Uint8Array> {\n\t\t\tawait ready\n\t\t\tif (!store) {\n\t\t\t\tthrow new Error('Store not initialized. Await app.ready before exporting backup.')\n\t\t\t}\n\t\t\treturn store.exportBackup(options)\n\t\t},\n\t\tasync importBackup(data: Uint8Array, options?: RestoreOptions): Promise<RestoreResult> {\n\t\t\tawait ready\n\t\t\tif (!store) {\n\t\t\t\tthrow new Error('Store not initialized. Await app.ready before importing backup.')\n\t\t\t}\n\t\t\treturn store.importBackup(data, options)\n\t\t},\n\t\tasync replayTo(operationId: string): Promise<ReplaySnapshot> {\n\t\t\tawait ready\n\t\t\tif (!store) {\n\t\t\t\tthrow new Error('Store not initialized. Await app.ready before replaying operations.')\n\t\t\t}\n\t\t\treturn store.replayTo(operationId)\n\t\t},\n\t\tasync exportAudit(options?: AuditExportOptions): Promise<Uint8Array> {\n\t\t\tawait ready\n\t\t\tif (!store) {\n\t\t\t\tthrow new Error('Store not initialized. Await app.ready before exporting audit data.')\n\t\t\t}\n\t\t\treturn store.exportAudit(options)\n\t\t},\n\t}\n\n\t// Define collection accessors via Object.defineProperty.\n\t// Before ready resolves, query methods return empty results.\n\tfor (const collectionName of Object.keys(config.schema.collections)) {\n\t\tObject.defineProperty(app, collectionName, {\n\t\t\tget(): CollectionAccessor {\n\t\t\t\treturn createCollectionAccessor(collectionName, () => store)\n\t\t\t},\n\t\t\tenumerable: true,\n\t\t\tconfigurable: false,\n\t\t})\n\t}\n\n\treturn app\n}\n\n/**\n * Asynchronous initialization: create adapter, open store, wire sync.\n */\nasync function initializeAsync(\n\tconfig: KoraConfig,\n\temitter: KoraEventEmitter,\n\tmergeEngine: MergeEngine,\n): Promise<{\n\tstore: Store\n\tsyncEngine: SyncEngine | null\n\tunsubscribeSync: (() => void) | null\n\tunsubscribeAudit: (() => void) | null\n\tauthBinding: AuthSyncBinding | null\n}> {\n\t// Resolve adapter\n\tconst adapterType = config.store?.adapter ?? detectAdapterType()\n\tconst dbName = config.store?.name ?? 'kora-db'\n\tconst adapter: StorageAdapter = await createAdapter(\n\t\tadapterType,\n\t\tdbName,\n\t\tconfig.store?.workerUrl,\n\t\temitter,\n\t\tconfig.store?.workerResponseTimeoutMs,\n\t\tconfig.store?.sharedWorkerUrl,\n\t)\n\n\t// Device-bound sync node id from auth token (`dev` claim), separate from user id (`sub`).\n\tconst authBinding = config.sync?.authClient\n\tconst authNodeId = authBinding?.resolveNodeId ? await authBinding.resolveNodeId() : undefined\n\n\t// Create and open the store (sync query hook uses a ref filled after SyncEngine is created)\n\tlet syncEngine: SyncEngine | null = null\n\n\tconst store = new Store({\n\t\tschema: config.schema,\n\t\tadapter,\n\t\temitter,\n\t\tdbName,\n\t\tnodeId: authNodeId,\n\t\tisolation: authNodeId ? 'shared' : config.store?.isolation,\n\t\t...(config.sync\n\t\t\t? { onQuerySubscribed: createSyncQuerySubscriptionHook(() => syncEngine) }\n\t\t\t: {}),\n\t})\n\tawait store.open()\n\n\tlet recordConflict: (() => void) | undefined\n\tconst applyPipeline = new ApplyPipeline({\n\t\tstore,\n\t\tmergeEngine,\n\t\temitter,\n\t\tonMergeConflict: () => recordConflict?.(),\n\t})\n\tstore.setLocalMutationHandler(applyPipeline)\n\tconst unsubscribeAudit = wireAuditPersistence(store, emitter)\n\n\t// Wire sync if configured\n\tlet unsubscribeSync: (() => void) | null = null\n\n\tif (config.sync) {\n\t\tconst transport = createSyncTransport(config.sync)\n\t\tconst mergeAwareStore = new MergeAwareSyncStore(store, mergeEngine, emitter, {\n\t\t\tonMergeConflict: () => recordConflict?.(),\n\t\t})\n\n\t\t// Build scope map from auth binding, flat scope values, or static config\n\t\tlet scopeMap = config.sync.scope ? buildScopeMap(config.schema, config.sync.scope) : undefined\n\t\tif (authBinding?.resolveScopeMap) {\n\t\t\tscopeMap = (await authBinding.resolveScopeMap()) ?? scopeMap\n\t\t}\n\n\t\tconst syncAuth = authBinding?.auth ?? config.sync.auth\n\n\t\tconst encryptor =\n\t\t\tconfig.sync.encryption?.enabled === true\n\t\t\t\t? await SyncEncryptor.create(config.sync.encryption)\n\t\t\t\t: undefined\n\n\t\tsyncEngine = new SyncEngine({\n\t\t\ttransport,\n\t\t\tstore: mergeAwareStore,\n\t\t\tconfig: {\n\t\t\t\turl: config.sync.url,\n\t\t\t\ttransport: config.sync.transport,\n\t\t\t\tauth: syncAuth,\n\t\t\t\tbatchSize: config.sync.batchSize,\n\t\t\t\tschemaVersion: config.sync.schemaVersion ?? config.schema.version,\n\t\t\t\tscopeMap,\n\t\t\t\tencryption: config.sync.encryption,\n\t\t\t\tstrictHandshake: config.sync.strictHandshake,\n\t\t\t\toperationTransforms: config.sync.operationTransforms,\n\t\t\t},\n\t\t\temitter,\n\t\t\tqueueStorage: new StoreQueueStorage(adapter),\n\t\t\tsyncState: new StoreSyncStatePersistence(store, scopeMap),\n\t\t\tencryptor,\n\t\t})\n\t\trecordConflict = () => syncEngine?.recordConflict()\n\n\t\t// Wire local mutations → sync outbound queue\n\t\tunsubscribeSync = emitter.on('operation:created', (event) => {\n\t\t\tif (syncEngine) {\n\t\t\t\tsyncEngine.pushOperation(event.operation)\n\t\t\t}\n\t\t})\n\t}\n\n\treturn {\n\t\tstore,\n\t\tsyncEngine,\n\t\tunsubscribeSync,\n\t\tunsubscribeAudit,\n\t\tauthBinding: config.sync?.authClient ?? null,\n\t}\n}\n\nfunction createSyncTransport(sync: NonNullable<KoraConfig['sync']>): SyncTransport {\n\tif (sync.transport === 'http') {\n\t\treturn new HttpLongPollingTransport()\n\t}\n\treturn new WebSocketTransport()\n}\n\nfunction createCollectionAccessor(\n\tcollectionName: string,\n\tgetStore: () => Store | null,\n): CollectionAccessor {\n\treturn {\n\t\tasync insert(data: Record<string, unknown>) {\n\t\t\tconst currentStore = getStore()\n\t\t\tif (!currentStore) {\n\t\t\t\tthrow new Error(`Cannot mutate collection \"${collectionName}\" before app.ready resolves.`)\n\t\t\t}\n\t\t\treturn currentStore.collection(collectionName).insert(data)\n\t\t},\n\t\tasync findById(id: string) {\n\t\t\tconst currentStore = getStore()\n\t\t\tif (!currentStore) return null\n\t\t\treturn currentStore.collection(collectionName).findById(id)\n\t\t},\n\t\tasync update(id: string, data: Record<string, unknown>) {\n\t\t\tconst currentStore = getStore()\n\t\t\tif (!currentStore) {\n\t\t\t\tthrow new Error(`Cannot mutate collection \"${collectionName}\" before app.ready resolves.`)\n\t\t\t}\n\t\t\treturn currentStore.collection(collectionName).update(id, data)\n\t\t},\n\t\tasync delete(id: string) {\n\t\t\tconst currentStore = getStore()\n\t\t\tif (!currentStore) {\n\t\t\t\tthrow new Error(`Cannot mutate collection \"${collectionName}\" before app.ready resolves.`)\n\t\t\t}\n\t\t\treturn currentStore.collection(collectionName).delete(id)\n\t\t},\n\t\twhere(conditions: Record<string, unknown>) {\n\t\t\tconst currentStore = getStore()\n\t\t\tif (!currentStore) {\n\t\t\t\treturn createPendingQueryBuilder(conditions)\n\t\t\t}\n\t\t\treturn currentStore.collection(collectionName).where(conditions)\n\t\t},\n\t}\n}\n\nfunction createPendingQueryBuilder(initialWhere: Record<string, unknown>): QueryBuilder {\n\tconst descriptor = {\n\t\tcollection: '__pending__',\n\t\twhere: { ...initialWhere },\n\t\torderBy: [] as Array<{ field: string; direction: 'asc' | 'desc' }>,\n\t\tlimit: undefined as number | undefined,\n\t\toffset: undefined as number | undefined,\n\t}\n\n\tconst builder = {\n\t\twhere(conditions: Record<string, unknown>) {\n\t\t\tdescriptor.where = { ...descriptor.where, ...conditions }\n\t\t\treturn this\n\t\t},\n\t\torderBy(field: string, direction: 'asc' | 'desc' = 'asc') {\n\t\t\tdescriptor.orderBy.push({ field, direction })\n\t\t\treturn this\n\t\t},\n\t\tlimit(n: number) {\n\t\t\tdescriptor.limit = n\n\t\t\treturn this\n\t\t},\n\t\toffset(n: number) {\n\t\t\tdescriptor.offset = n\n\t\t\treturn this\n\t\t},\n\t\tasync exec() {\n\t\t\tthrow new AppNotReadyError(\n\t\t\t\t'Cannot execute a query before app.ready. Await app.ready or use <KoraProvider app={app}>.',\n\t\t\t)\n\t\t},\n\t\tasync count() {\n\t\t\tthrow new AppNotReadyError(\n\t\t\t\t'Cannot count query results before app.ready. Await app.ready or use <KoraProvider app={app}>.',\n\t\t\t)\n\t\t},\n\t\tsubscribe(_callback: (results: Array<Record<string, unknown>>) => void) {\n\t\t\tthrow new AppNotReadyError(\n\t\t\t\t'Cannot subscribe to a query before app.ready. Await app.ready or use <KoraProvider app={app}>.',\n\t\t\t)\n\t\t},\n\t\tgetDescriptor() {\n\t\t\treturn { ...descriptor, where: { ...descriptor.where }, orderBy: [...descriptor.orderBy] }\n\t\t},\n\t}\n\n\treturn builder as unknown as QueryBuilder\n}\n","import type { KoraEventEmitter } from '@korajs/core'\nimport type { StorageAdapter } from '@korajs/store'\nimport type { AdapterType } from './types'\n\n/** Dynamic import that bundlers cannot statically analyze (optional peer packages). */\nfunction importOptionalPeer<T>(specifier: string): Promise<T> {\n\tconst dynamicImport = new Function('specifier', 'return import(specifier)') as (\n\t\ts: string,\n\t) => Promise<T>\n\treturn dynamicImport(specifier)\n}\n\n/**\n * Detect the best storage adapter for the current environment.\n *\n * - Tauri app: 'tauri-sqlite' (native SQLite via Tauri plugin)\n * - Node.js: 'better-sqlite3'\n * - Browser with OPFS: 'sqlite-wasm'\n * - Browser without OPFS: 'indexeddb'\n */\nexport function detectAdapterType(): AdapterType {\n\t// Tauri environment — detected via __TAURI_INTERNALS__ injected by the Tauri runtime\n\tif (\n\t\ttypeof globalThis !== 'undefined' &&\n\t\ttypeof (globalThis as Record<string, unknown>).__TAURI_INTERNALS__ !== 'undefined'\n\t) {\n\t\treturn 'tauri-sqlite'\n\t}\n\n\t// Node.js environment\n\tif (typeof process !== 'undefined' && process.versions?.node) {\n\t\treturn 'better-sqlite3'\n\t}\n\n\t// Browser environment\n\tif (typeof globalThis.navigator !== 'undefined') {\n\t\t// Check for OPFS support (FileSystemHandle indicates OPFS availability)\n\t\tif (typeof (globalThis as Record<string, unknown>).FileSystemHandle !== 'undefined') {\n\t\t\treturn 'sqlite-wasm'\n\t\t}\n\t\treturn 'indexeddb'\n\t}\n\n\t// Default fallback (e.g., Deno, Bun, or other runtimes)\n\treturn 'better-sqlite3'\n}\n\n/**\n * Create a StorageAdapter for the given adapter type.\n * Uses dynamic imports so unused adapters are not bundled.\n *\n * @param type - The adapter type to create\n * @param dbName - Database name (used by all adapters)\n * @returns A configured StorageAdapter instance\n */\nexport async function createAdapter(\n\ttype: AdapterType,\n\tdbName: string,\n\tworkerUrl?: string | URL,\n\temitter?: KoraEventEmitter,\n\tworkerResponseTimeoutMs?: number,\n\tsharedWorkerUrl?: string | URL,\n): Promise<StorageAdapter> {\n\tswitch (type) {\n\t\tcase 'tauri-sqlite': {\n\t\t\t// @korajs/tauri is only installed in Tauri projects (optional peer dep).\n\t\t\t// Runtime import via Function so Vite/Rollup do not pre-bundle or resolve the module.\n\t\t\tconst { TauriSqliteAdapter } = await importOptionalPeer<{\n\t\t\t\tTauriSqliteAdapter: new (options: { path: string }) => StorageAdapter\n\t\t\t}>('@korajs/tauri')\n\t\t\treturn new TauriSqliteAdapter({ path: `${dbName}.db` })\n\t\t}\n\t\tcase 'better-sqlite3': {\n\t\t\tconst { BetterSqlite3Adapter } = await import(\n\t\t\t\t/* @vite-ignore */ '@korajs/store/better-sqlite3'\n\t\t\t)\n\t\t\treturn new BetterSqlite3Adapter(dbName)\n\t\t}\n\t\tcase 'sqlite-wasm': {\n\t\t\tconst { SqliteWasmAdapter } = await import('@korajs/store/sqlite-wasm')\n\t\t\treturn new SqliteWasmAdapter({ dbName, workerUrl, sharedWorkerUrl, workerResponseTimeoutMs })\n\t\t}\n\t\tcase 'indexeddb': {\n\t\t\tconst { IndexedDbAdapter } = await import('@korajs/store/indexeddb')\n\t\t\treturn new IndexedDbAdapter({ dbName, workerUrl, emitter, workerResponseTimeoutMs })\n\t\t}\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = type\n\t\t\tthrow new Error(`Unknown adapter type: ${_exhaustive}`)\n\t\t}\n\t}\n}\n","import { KoraError } from '@korajs/core'\n\n/**\n * Thrown when collection/query APIs are used before {@link KoraApp.ready} resolves.\n */\nexport class AppNotReadyError extends KoraError {\n\tconstructor(detail: string) {\n\t\tsuper(detail, 'APP_NOT_READY', {\n\t\t\tfix: 'Await app.ready, or wrap your UI in <KoraProvider app={app}> before calling useQuery().',\n\t\t})\n\t\tthis.name = 'AppNotReadyError'\n\t}\n}\n","import type {\n\tCollectionDefinition,\n\tHLCTimestamp,\n\tKoraEventEmitter,\n\tOperation,\n\tSchemaDefinition,\n} from '@korajs/core'\nimport { HybridLogicalClock, KoraError, createOperation } from '@korajs/core'\nimport { topologicalSort } from '@korajs/core/internal'\nimport type { MergeEngine, MergeResult, ReferentialMergeContext, SideEffectOp } from '@korajs/merge'\nimport { buildMergeRelationLookup, checkReferentialIntegrityOnDelete } from '@korajs/merge'\nimport type { ConstraintContext } from '@korajs/merge'\nimport type {\n\tApplyRemoteOptions,\n\tCollectionRecord,\n\tLocalMutationHandler,\n\tStore,\n\tTransactionCommitBatch,\n\tTransactionCommitResult,\n} from '@korajs/store'\nimport { richtextStatesEqual } from '@korajs/store'\nimport {\n\texecuteDelete,\n\texecuteInsert,\n\texecuteUpdate,\n\tresolveCausalDeps,\n} from '@korajs/store/internal'\nimport type { ApplyResult } from '@korajs/sync'\nimport { buildSideEffectEntry } from './build-side-effect-entry'\n\n/**\n * Whether the operation originated locally or arrived from sync.\n */\nexport type ApplyMode = 'local' | 'remote'\n\n/**\n * Dependencies for the unified apply pipeline.\n */\nexport interface ApplyPipelineDeps {\n\treadonly store: Store\n\treadonly mergeEngine: MergeEngine\n\treadonly emitter: KoraEventEmitter | null\n\t/** Called when a field-level merge runs (updates sync conflict counter). */\n\treadonly onMergeConflict?: () => void\n}\n\n/**\n * Context passed into each apply invocation.\n */\nexport interface ApplyContext {\n\treadonly mode: ApplyMode\n\treadonly schema: SchemaDefinition\n}\n\n/**\n * Single entry point for applying remote sync operations with merge + referential integrity.\n */\nexport class ApplyPipeline implements LocalMutationHandler {\n\tprivate readonly relationLookupMap: ReturnType<typeof buildMergeRelationLookup>\n\n\tconstructor(private readonly deps: ApplyPipelineDeps) {\n\t\tthis.relationLookupMap = buildMergeRelationLookup(deps.store.getSchema())\n\t}\n\n\t/** Local insert — same persistence path as remote apply side effects. */\n\tasync insert(collection: string, data: Record<string, unknown>): Promise<CollectionRecord> {\n\t\treturn executeInsert(this.deps.store.createMutationContext(collection), data)\n\t}\n\n\t/** Local update. */\n\tasync update(\n\t\tcollection: string,\n\t\tid: string,\n\t\tdata: Record<string, unknown>,\n\t): Promise<CollectionRecord> {\n\t\treturn executeUpdate(this.deps.store.createMutationContext(collection), id, data)\n\t}\n\n\t/**\n\t * Local delete with merge-package referential integrity (same rules as remote delete).\n\t */\n\tasync delete(collection: string, id: string): Promise<void> {\n\t\tconst ctx = this.deps.store.createMutationContext(collection)\n\t\tconst causalDeps = resolveCausalDeps(ctx)\n\t\tconst operation = await createOperation(\n\t\t\t{\n\t\t\t\tnodeId: ctx.nodeId,\n\t\t\t\ttype: 'delete',\n\t\t\t\tcollection,\n\t\t\t\trecordId: id,\n\t\t\t\tdata: null,\n\t\t\t\tpreviousData: null,\n\t\t\t\tsequenceNumber: await ctx.allocateSequenceNumber(),\n\t\t\t\tcausalDeps,\n\t\t\t\tschemaVersion: ctx.schema.version,\n\t\t\t},\n\t\t\tctx.clock,\n\t\t)\n\t\tctx.causalTracker?.afterOperation(collection, operation.id, ctx.inTransaction)\n\n\t\tconst refCtx = createReferentialMergeContext(this.deps.store)\n\t\tconst check = await checkReferentialIntegrityOnDelete(\n\t\t\toperation,\n\t\t\tthis.deps.store.getSchema(),\n\t\t\trefCtx,\n\t\t\tthis.relationLookupMap,\n\t\t)\n\n\t\tfor (const trace of check.traces) {\n\t\t\tthis.deps.emitter?.emit({ type: 'merge:conflict', trace })\n\t\t}\n\n\t\tif (!check.allowed) {\n\t\t\tthrow new KoraError(\n\t\t\t\t`Cannot delete record \"${id}\" from \"${collection}\": referential restrict policy violated`,\n\t\t\t\t'REFERENTIAL_INTEGRITY',\n\t\t\t\t{ collection, recordId: id },\n\t\t\t)\n\t\t}\n\n\t\tawait executeDelete(ctx, id, {\n\t\t\tskipReferentialEnforcement: true,\n\t\t\toperation,\n\t\t})\n\n\t\tif (check.sideEffectOps.length > 0) {\n\t\t\tawait applySideEffectOps(this.deps.store, check.sideEffectOps, operation.id)\n\t\t}\n\t}\n\n\t/**\n\t * Commit a buffered transaction: merge-package delete enforcement, causal ordering, single DB txn.\n\t */\n\tasync commitTransaction(batch: TransactionCommitBatch): Promise<TransactionCommitResult> {\n\t\tconst store = this.deps.store\n\t\tconst supplemental: TransactionCommitBatch['entries'] = []\n\n\t\tfor (const entry of batch.entries) {\n\t\t\tif (entry.operation.type !== 'delete') {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst refCtx = createReferentialMergeContext(store)\n\t\t\tconst check = await checkReferentialIntegrityOnDelete(\n\t\t\t\tentry.operation,\n\t\t\t\tstore.getSchema(),\n\t\t\t\trefCtx,\n\t\t\t\tthis.relationLookupMap,\n\t\t\t)\n\n\t\t\tfor (const trace of check.traces) {\n\t\t\t\tthis.deps.emitter?.emit({ type: 'merge:conflict', trace })\n\t\t\t}\n\n\t\t\tif (!check.allowed) {\n\t\t\t\tthrow new KoraError(\n\t\t\t\t\t`Cannot delete record \"${entry.operation.recordId}\" from \"${entry.collection}\": referential restrict policy violated`,\n\t\t\t\t\t'REFERENTIAL_INTEGRITY',\n\t\t\t\t\t{ collection: entry.collection, recordId: entry.operation.recordId },\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tfor (const effect of check.sideEffectOps) {\n\t\t\t\tconst ctx = store.createMutationContext(effect.collection, { inTransaction: true })\n\t\t\t\tsupplemental.push(\n\t\t\t\t\tawait buildSideEffectEntry(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\teffect,\n\t\t\t\t\t\tentry.operation.id,\n\t\t\t\t\t\tbatch.transactionId,\n\t\t\t\t\t\tbatch.mutationName,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\tconst allEntries = [...batch.entries, ...supplemental]\n\t\tconst sortedOps = topologicalSort(allEntries.map((e) => e.operation))\n\t\tconst commandsByOpId = new Map(allEntries.map((e) => [e.operation.id, e.commands] as const))\n\n\t\tconst ctx = store.createMutationContext(\n\t\t\tbatch.entries[0]?.collection ?? Object.keys(store.getSchema().collections)[0] ?? 'todos',\n\t\t\t{ inTransaction: true },\n\t\t)\n\n\t\tawait ctx.adapter.transaction(async (tx) => {\n\t\t\tfor (const op of sortedOps) {\n\t\t\t\tconst commands = commandsByOpId.get(op.id)\n\t\t\t\tif (!commands) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tfor (const cmd of commands) {\n\t\t\t\t\tawait tx.execute(cmd.sql, cmd.params)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tconst affectedCollections = new Set<string>()\n\t\tfor (const entry of allEntries) {\n\t\t\taffectedCollections.add(entry.collection)\n\t\t}\n\n\t\treturn { operations: sortedOps, affectedCollections }\n\t}\n\n\tasync applyRemote(op: Operation): Promise<ApplyResult> {\n\t\treturn this.apply(op, { mode: 'remote', schema: this.deps.store.getSchema() })\n\t}\n\n\tasync apply(op: Operation, context: ApplyContext): Promise<ApplyResult> {\n\t\tif (context.mode === 'local') {\n\t\t\treturn this.deps.store.applyRemoteOperation(op)\n\t\t}\n\n\t\tif (op.type === 'delete') {\n\t\t\treturn this.applyRemoteDelete(op)\n\t\t}\n\n\t\tif (op.type === 'insert' && op.data) {\n\t\t\treturn this.applyRemoteInsert(op)\n\t\t}\n\n\t\tif (op.type === 'update' && op.data && op.previousData) {\n\t\t\treturn this.applyRemoteUpdate(op)\n\t\t}\n\n\t\treturn this.deps.store.applyRemoteOperation(op)\n\t}\n\n\tprivate async applyRemoteDelete(op: Operation): Promise<ApplyResult> {\n\t\tconst blocked = await this.resolveRemoteDeleteVsLocalUpdate(op)\n\t\tif (blocked) {\n\t\t\treturn 'skipped'\n\t\t}\n\n\t\tconst refCtx = createReferentialMergeContext(this.deps.store)\n\t\tconst check = await checkReferentialIntegrityOnDelete(\n\t\t\top,\n\t\t\tthis.deps.store.getSchema(),\n\t\t\trefCtx,\n\t\t\tthis.relationLookupMap,\n\t\t)\n\n\t\tfor (const trace of check.traces) {\n\t\t\tthis.deps.emitter?.emit({ type: 'merge:conflict', trace })\n\t\t}\n\n\t\tif (!check.allowed) {\n\t\t\treturn 'rejected'\n\t\t}\n\n\t\tconst result = await this.deps.store.applyRemoteOperation(op)\n\t\tif (result !== 'applied') {\n\t\t\treturn result\n\t\t}\n\n\t\tif (check.sideEffectOps.length > 0) {\n\t\t\tawait applySideEffectOps(this.deps.store, check.sideEffectOps, op.id)\n\t\t}\n\n\t\treturn 'applied'\n\t}\n\n\t/**\n\t * When a local update is newer than a remote delete, keep the record alive.\n\t */\n\tprivate async resolveRemoteDeleteVsLocalUpdate(op: Operation): Promise<boolean> {\n\t\tconst collectionDef = this.deps.store.getSchema().collections[op.collection]\n\t\tif (!collectionDef) {\n\t\t\treturn false\n\t\t}\n\n\t\tconst localOp = await this.deps.store.getLatestLocalOperationForRecord(\n\t\t\top.collection,\n\t\t\top.recordId,\n\t\t)\n\t\tif (!localOp || localOp.type !== 'update') {\n\t\t\treturn false\n\t\t}\n\n\t\tconst baseState = localOp.previousData ?? {}\n\t\tconst mergeResult = await this.deps.mergeEngine.merge({\n\t\t\tlocal: localOp,\n\t\t\tremote: op,\n\t\t\tbaseState,\n\t\t\tcollectionDef,\n\t\t})\n\n\t\tthis.emitMergeLifecycle(op, localOp, mergeResult)\n\n\t\treturn mergeResult.appliedOperation === 'local'\n\t}\n\n\tprivate async applyRemoteUpdate(op: Operation): Promise<ApplyResult> {\n\t\tconst schema = this.deps.store.getSchema()\n\t\tconst collectionDef = schema.collections[op.collection]\n\t\tif (!collectionDef) {\n\t\t\treturn this.deps.store.applyRemoteOperation(op)\n\t\t}\n\n\t\tconst accessor = this.deps.store.collection(op.collection)\n\t\tconst currentRecord = await accessor.findById(op.recordId)\n\n\t\tif (!currentRecord) {\n\t\t\tconst tombstoneResult = await this.applyRemoteUpdateOnDeletedRow(op, collectionDef)\n\t\t\tif (tombstoneResult !== null) {\n\t\t\t\treturn tombstoneResult\n\t\t\t}\n\t\t\treturn this.deps.store.applyRemoteOperation(op)\n\t\t}\n\n\t\tlet hasConflict = false\n\t\tfor (const field of Object.keys(op.data ?? {})) {\n\t\t\tconst fieldDef = collectionDef.fields[field]\n\t\t\tconst expectedBase = op.previousData?.[field]\n\t\t\tconst currentLocal = currentRecord[field]\n\n\t\t\tif (fieldDef?.kind === 'richtext') {\n\t\t\t\tif (!richtextStatesEqual(currentLocal, expectedBase)) {\n\t\t\t\t\thasConflict = true\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (!deepEqual(expectedBase, currentLocal)) {\n\t\t\t\thasConflict = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (!hasConflict) {\n\t\t\treturn this.deps.store.applyRemoteOperation(op)\n\t\t}\n\n\t\treturn this.applyMergedUpdate(op, collectionDef, currentRecord, op.previousData ?? {})\n\t}\n\n\t/**\n\t * Remote update vs local soft-delete: merge before materializing to avoid zombie rows.\n\t */\n\tprivate async applyRemoteUpdateOnDeletedRow(\n\t\top: Operation,\n\t\tcollectionDef: CollectionDefinition,\n\t): Promise<ApplyResult | null> {\n\t\tconst snapshot = await this.deps.store.findMaterializedRow(op.collection, op.recordId)\n\t\tif (!snapshot?.deleted) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst localOp = await this.deps.store.getLatestLocalOperationForRecord(\n\t\t\top.collection,\n\t\t\top.recordId,\n\t\t)\n\t\tif (!localOp || localOp.type !== 'delete') {\n\t\t\treturn null\n\t\t}\n\n\t\tconst mergeResult = await this.deps.mergeEngine.merge({\n\t\t\tlocal: localOp,\n\t\t\tremote: op,\n\t\t\tbaseState: op.previousData ?? {},\n\t\t\tcollectionDef,\n\t\t})\n\n\t\tthis.emitMergeLifecycle(op, localOp, mergeResult)\n\n\t\tif (mergeResult.appliedOperation === 'local') {\n\t\t\treturn 'skipped'\n\t\t}\n\n\t\tconst mergedOp: Operation = {\n\t\t\t...op,\n\t\t\tdata: { ...mergeResult.mergedData },\n\t\t\ttimestamp: maxTimestamp(op.timestamp, localOp.timestamp),\n\t\t}\n\n\t\tconst applyResult = await this.deps.store.applyRemoteOperation(mergedOp, {\n\t\t\treactivateIfDeleted: true,\n\t\t})\n\n\t\tif (applyResult === 'applied' && mergeResult.sideEffects.length > 0) {\n\t\t\tawait applySideEffectOps(this.deps.store, mergeResult.sideEffects, op.id)\n\t\t}\n\n\t\treturn applyResult\n\t}\n\n\tprivate async applyMergedUpdate(\n\t\top: Operation,\n\t\tcollectionDef: CollectionDefinition,\n\t\tcurrentRecord: CollectionRecord,\n\t\tbaseState: Record<string, unknown>,\n\t\tapplyOptions?: ApplyRemoteOptions,\n\t): Promise<ApplyResult> {\n\t\tconst localTimestamp = await resolveLocalTimestamp(\n\t\t\tthis.deps.store,\n\t\t\top.collection,\n\t\t\top.recordId,\n\t\t\tcurrentRecord,\n\t\t\tthis.deps.store.getNodeId(),\n\t\t)\n\t\tconst localOp: Operation = {\n\t\t\t...op,\n\t\t\tdata: buildLocalDiff(baseState, currentRecord, Object.keys(op.data ?? {})),\n\t\t\tpreviousData: op.previousData,\n\t\t\tnodeId: this.deps.store.getNodeId(),\n\t\t\ttimestamp: localTimestamp,\n\t\t}\n\n\t\tconst constraintContext = createConstraintContext(this.deps.store)\n\t\tconst mergeResult = await this.deps.mergeEngine.merge(\n\t\t\t{\n\t\t\t\tlocal: localOp,\n\t\t\t\tremote: op,\n\t\t\t\tbaseState,\n\t\t\t\tcollectionDef,\n\t\t\t},\n\t\t\tconstraintContext,\n\t\t)\n\n\t\tthis.emitMergeLifecycle(op, localOp, mergeResult)\n\n\t\tconst mergedOp: Operation = {\n\t\t\t...op,\n\t\t\tdata: mergeResult.mergedData,\n\t\t\ttimestamp: maxTimestamp(op.timestamp, localTimestamp),\n\t\t}\n\n\t\tconst applyResult = await this.deps.store.applyRemoteOperation(mergedOp, applyOptions)\n\n\t\tif (applyResult === 'applied' && mergeResult.sideEffects.length > 0) {\n\t\t\tawait applySideEffectOps(this.deps.store, mergeResult.sideEffects, op.id)\n\t\t}\n\n\t\treturn applyResult\n\t}\n\n\tprivate async applyRemoteInsert(op: Operation): Promise<ApplyResult> {\n\t\tconst collectionDef = this.deps.store.getSchema().collections[op.collection]\n\t\tif (!collectionDef || !op.data) {\n\t\t\treturn this.deps.store.applyRemoteOperation(op)\n\t\t}\n\n\t\tconst snapshot = await this.deps.store.findMaterializedRow(op.collection, op.recordId)\n\t\tif (!snapshot || snapshot.deleted) {\n\t\t\treturn this.deps.store.applyRemoteOperation(op)\n\t\t}\n\n\t\tconst localOp = await resolveLocalOpForRecord(\n\t\t\tthis.deps.store,\n\t\t\top.collection,\n\t\t\top.recordId,\n\t\t\tsnapshot.record,\n\t\t)\n\n\t\tconst mergeResult = await this.deps.mergeEngine.merge({\n\t\t\tlocal: localOp,\n\t\t\tremote: op,\n\t\t\tbaseState: {},\n\t\t\tcollectionDef,\n\t\t})\n\n\t\tthis.emitMergeLifecycle(op, localOp, mergeResult)\n\n\t\tconst mergedOp: Operation = {\n\t\t\t...op,\n\t\t\tdata: mergeResult.mergedData,\n\t\t\ttimestamp: maxTimestamp(op.timestamp, localOp.timestamp),\n\t\t}\n\n\t\treturn this.deps.store.applyRemoteOperation(mergedOp)\n\t}\n\n\tprivate emitMergeLifecycle(remote: Operation, local: Operation, mergeResult: MergeResult): void {\n\t\tthis.deps.emitter?.emit({\n\t\t\ttype: 'merge:started',\n\t\t\toperationA: remote,\n\t\t\toperationB: local,\n\t\t})\n\n\t\tconst hadMergeConflict = mergeResult.traces.some(\n\t\t\t(t) =>\n\t\t\t\tt.strategy !== 'no-conflict-local' &&\n\t\t\t\tt.strategy !== 'no-conflict-remote' &&\n\t\t\t\tt.strategy !== 'no-conflict-unchanged',\n\t\t)\n\t\tif (hadMergeConflict) {\n\t\t\tthis.deps.onMergeConflict?.()\n\t\t}\n\n\t\tfor (const trace of mergeResult.traces) {\n\t\t\tif (\n\t\t\t\ttrace.strategy !== 'no-conflict-local' &&\n\t\t\t\ttrace.strategy !== 'no-conflict-remote' &&\n\t\t\t\ttrace.strategy !== 'no-conflict-unchanged'\n\t\t\t) {\n\t\t\t\tthis.deps.emitter?.emit({ type: 'merge:conflict', trace })\n\t\t\t}\n\t\t}\n\t\tconst firstTrace = mergeResult.traces[0]\n\t\tif (firstTrace) {\n\t\t\tthis.deps.emitter?.emit({ type: 'merge:completed', trace: firstTrace })\n\t\t}\n\t}\n}\n\n/**\n * Prefer the latest local op, then any op in the log for this record, then a snapshot-derived insert.\n */\nasync function resolveLocalOpForRecord(\n\tstore: Store,\n\tcollection: string,\n\trecordId: string,\n\trecord: CollectionRecord,\n): Promise<Operation> {\n\tconst localLatest = await store.getLatestLocalOperationForRecord(collection, recordId)\n\tif (localLatest) {\n\t\treturn localLatest\n\t}\n\n\tconst anyLatest = await store.getLatestOperationForRecord(collection, recordId)\n\tif (anyLatest) {\n\t\treturn anyLatest\n\t}\n\n\treturn syntheticInsertFromSnapshot(\n\t\trecord,\n\t\tcollection,\n\t\tstore.getNodeId(),\n\t\tstore.getSchema().version,\n\t)\n}\n\nfunction syntheticInsertFromSnapshot(\n\trecord: CollectionRecord,\n\tcollection: string,\n\tnodeId: string,\n\tschemaVersion: number,\n): Operation {\n\tconst { id, createdAt, updatedAt, ...fields } = record\n\treturn {\n\t\tid: `synthetic-local-${id}`,\n\t\tnodeId,\n\t\ttype: 'insert',\n\t\tcollection,\n\t\trecordId: id,\n\t\tdata: fields,\n\t\tpreviousData: null,\n\t\ttimestamp: { wallTime: updatedAt, logical: 0, nodeId },\n\t\tsequenceNumber: 0,\n\t\tcausalDeps: [],\n\t\tschemaVersion,\n\t}\n}\n\nfunction createConstraintContext(store: Store): ConstraintContext {\n\treturn {\n\t\tasync queryRecords(collection: string, where: Record<string, unknown>) {\n\t\t\tconst rows = await store.collection(collection).where(where).exec()\n\t\t\treturn rows as Record<string, unknown>[]\n\t\t},\n\t\tasync countRecords(collection: string, where: Record<string, unknown>) {\n\t\t\treturn store.collection(collection).where(where).count()\n\t\t},\n\t}\n}\n\nfunction createReferentialMergeContext(store: Store): ReferentialMergeContext {\n\treturn {\n\t\tasync queryRecords(collection: string, where: Record<string, unknown>) {\n\t\t\tconst rows = await store.collection(collection).where(where).exec()\n\t\t\treturn rows as Record<string, unknown>[]\n\t\t},\n\t\tasync recordExists(collection: string, recordId: string) {\n\t\t\tconst row = await store.collection(collection).findById(recordId)\n\t\t\treturn row !== null\n\t\t},\n\t}\n}\n\nasync function applySideEffectOps(\n\tstore: Store,\n\tsideEffects: SideEffectOp[],\n\tparentOpId: string,\n): Promise<void> {\n\tfor (const effect of sideEffects) {\n\t\tconst ctx = store.createMutationContext(effect.collection, {\n\t\t\textraCausalDeps: [parentOpId],\n\t\t})\n\t\tif (effect.type === 'delete') {\n\t\t\tawait executeDelete(ctx, effect.recordId, { skipReferentialEnforcement: true })\n\t\t} else if (effect.type === 'update' && effect.data) {\n\t\t\tawait executeUpdate(ctx, effect.recordId, effect.data)\n\t\t}\n\t}\n}\n\nfunction buildLocalDiff(\n\tbaseState: Record<string, unknown>,\n\tcurrentRecord: Record<string, unknown>,\n\tfields: string[],\n): Record<string, unknown> {\n\tconst diff: Record<string, unknown> = {}\n\tfor (const field of fields) {\n\t\tdiff[field] = currentRecord[field]\n\t}\n\treturn diff\n}\n\nasync function resolveLocalTimestamp(\n\tstore: Store,\n\tcollection: string,\n\trecordId: string,\n\tcurrentRecord: CollectionRecord,\n\tnodeId: string,\n): Promise<HLCTimestamp> {\n\tconst latestLocal = await store.getLatestLocalOperationForRecord(collection, recordId)\n\tif (latestLocal) {\n\t\treturn latestLocal.timestamp\n\t}\n\tconst updatedAt = currentRecord.updatedAt\n\tif (typeof updatedAt === 'number') {\n\t\treturn { wallTime: updatedAt, logical: 0, nodeId }\n\t}\n\treturn { wallTime: Date.now(), logical: 0, nodeId }\n}\n\nfunction maxTimestamp(a: HLCTimestamp, b: HLCTimestamp): HLCTimestamp {\n\treturn HybridLogicalClock.compare(a, b) >= 0 ? a : b\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n\tif (a === b) return true\n\tif (a === null || b === null) return false\n\tif (a === undefined || b === undefined) return false\n\tif (typeof a !== typeof b) return false\n\n\tif (Array.isArray(a) && Array.isArray(b)) {\n\t\tif (a.length !== b.length) return false\n\t\treturn a.every((val, i) => deepEqual(val, b[i]))\n\t}\n\n\tif (typeof a === 'object' && typeof b === 'object') {\n\t\tconst keysA = Object.keys(a as Record<string, unknown>)\n\t\tconst keysB = Object.keys(b as Record<string, unknown>)\n\t\tif (keysA.length !== keysB.length) return false\n\t\treturn keysA.every((key) =>\n\t\t\tdeepEqual((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key]),\n\t\t)\n\t}\n\n\treturn false\n}\n","import { createOperation } from '@korajs/core'\nimport type { SideEffectOp } from '@korajs/merge'\nimport type { TransactionBufferedEntry } from '@korajs/store'\nimport type { LocalMutationContext } from '@korajs/store/internal'\nimport {\n\tbuildInsertQuery,\n\tbuildSoftDeleteQuery,\n\tbuildUpdateQuery,\n\tserializeOperation,\n\tserializeRecord,\n\tserializeRowVersion,\n} from '@korajs/store/internal'\n\n/**\n * Materialize a merge-package referential side effect as an operation log entry + SQL commands.\n */\nexport async function buildSideEffectEntry(\n\tctx: LocalMutationContext,\n\teffect: SideEffectOp,\n\tparentOpId: string,\n\ttransactionId?: string,\n\tmutationName?: string,\n): Promise<TransactionBufferedEntry> {\n\tconst causalDeps = [parentOpId]\n\tconst baseInput = {\n\t\tnodeId: ctx.nodeId,\n\t\tcollection: effect.collection,\n\t\trecordId: effect.recordId,\n\t\tsequenceNumber: await ctx.allocateSequenceNumber(),\n\t\tcausalDeps,\n\t\tschemaVersion: ctx.schema.version,\n\t\t...(transactionId !== undefined ? { transactionId } : {}),\n\t\t...(mutationName !== undefined ? { mutationName } : {}),\n\t}\n\n\tif (effect.type === 'delete') {\n\t\tconst operation = await createOperation(\n\t\t\t{\n\t\t\t\t...baseInput,\n\t\t\t\ttype: 'delete',\n\t\t\t\tdata: null,\n\t\t\t\tpreviousData: effect.previousData,\n\t\t\t},\n\t\t\tctx.clock,\n\t\t)\n\t\tctx.causalTracker?.afterOperation(effect.collection, operation.id, ctx.inTransaction)\n\n\t\tconst version = serializeRowVersion(operation.timestamp)\n\t\tconst deleteQuery = buildSoftDeleteQuery(\n\t\t\teffect.collection,\n\t\t\teffect.recordId,\n\t\t\toperation.timestamp.wallTime,\n\t\t\tversion,\n\t\t)\n\t\tconst opInsert = buildInsertQuery(\n\t\t\t`_kora_ops_${effect.collection}`,\n\t\t\tserializeOperation(operation) as unknown as Record<string, unknown>,\n\t\t)\n\n\t\treturn {\n\t\t\toperation,\n\t\t\tcollection: effect.collection,\n\t\t\tcommands: [\n\t\t\t\t{ sql: deleteQuery.sql, params: deleteQuery.params },\n\t\t\t\t{ sql: opInsert.sql, params: opInsert.params },\n\t\t\t\t{\n\t\t\t\t\tsql: 'INSERT OR REPLACE INTO _kora_version_vector (node_id, sequence_number) VALUES (?, ?)',\n\t\t\t\t\tparams: [ctx.nodeId, operation.sequenceNumber],\n\t\t\t\t},\n\t\t\t],\n\t\t}\n\t}\n\n\tconst operation = await createOperation(\n\t\t{\n\t\t\t...baseInput,\n\t\t\ttype: 'update',\n\t\t\tdata: effect.data,\n\t\t\tpreviousData: effect.previousData,\n\t\t},\n\t\tctx.clock,\n\t)\n\tctx.causalTracker?.afterOperation(effect.collection, operation.id, ctx.inTransaction)\n\n\tconst definition = ctx.schema.collections[effect.collection]\n\tconst serializedChanges =\n\t\teffect.data && definition\n\t\t\t? serializeRecord(effect.data, definition.fields)\n\t\t\t: (effect.data ?? {})\n\tconst version = serializeRowVersion(operation.timestamp)\n\tconst updateQuery = buildUpdateQuery(effect.collection, effect.recordId, {\n\t\t...serializedChanges,\n\t\t_updated_at: operation.timestamp.wallTime,\n\t\t_version: version,\n\t})\n\tconst opInsert = buildInsertQuery(\n\t\t`_kora_ops_${effect.collection}`,\n\t\tserializeOperation(operation) as unknown as Record<string, unknown>,\n\t)\n\n\treturn {\n\t\toperation,\n\t\tcollection: effect.collection,\n\t\tcommands: [\n\t\t\t{ sql: updateQuery.sql, params: updateQuery.params },\n\t\t\t{ sql: opInsert.sql, params: opInsert.params },\n\t\t\t{\n\t\t\t\tsql: 'INSERT OR REPLACE INTO _kora_version_vector (node_id, sequence_number) VALUES (?, ?)',\n\t\t\t\tparams: [ctx.nodeId, operation.sequenceNumber],\n\t\t\t},\n\t\t],\n\t}\n}\n","import type { KoraEvent, KoraEventEmitter } from '@korajs/core'\nimport type { Store } from '@korajs/store'\nimport { persistedAuditTraceFromEvent } from '@korajs/store'\n\nconst AUDIT_EVENT_TYPES = ['merge:completed', 'merge:conflict', 'constraint:violated'] as const\n\ntype AuditEventType = (typeof AUDIT_EVENT_TYPES)[number]\n\nfunction isAuditEvent(event: KoraEvent): event is Extract<KoraEvent, { type: AuditEventType }> {\n\treturn (AUDIT_EVENT_TYPES as readonly string[]).includes(event.type)\n}\n\n/**\n * Persist merge and constraint traces from the event bus to `_kora_audit_traces`.\n */\nexport function wireAuditPersistence(store: Store, emitter: KoraEventEmitter): () => void {\n\tconst unsubscribers = AUDIT_EVENT_TYPES.map((eventType) =>\n\t\temitter.on(eventType, (event) => {\n\t\t\tif (!isAuditEvent(event)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst trace = persistedAuditTraceFromEvent(event)\n\t\t\tvoid store.appendAuditTrace(trace).catch(() => {\n\t\t\t\t// Audit persistence must not break mutations or sync.\n\t\t\t})\n\t\t}),\n\t)\n\n\treturn () => {\n\t\tfor (const unsub of unsubscribers) {\n\t\t\tunsub()\n\t\t}\n\t}\n}\n","import type { KoraEventEmitter, Operation, VersionVector } from '@korajs/core'\nimport type { MergeEngine } from '@korajs/merge'\nimport type { Store } from '@korajs/store'\nimport type { ApplyResult, SyncStore } from '@korajs/sync'\nimport { ApplyPipeline } from './apply-pipeline'\n\nexport interface MergeAwareSyncStoreOptions {\n\t/** Increments SyncEngine conflict counter when merge runs on a conflicting update. */\n\tonMergeConflict?: () => void\n}\n\n/**\n * Wraps a Store to route remote sync operations through {@link ApplyPipeline}.\n *\n * Ensures remote deletes honor referential integrity (cascade, set-null, restrict)\n * and remote updates use the full three-tier merge engine with constraint context.\n */\nexport class MergeAwareSyncStore implements SyncStore {\n\tprivate readonly pipeline: ApplyPipeline\n\n\tconstructor(\n\t\tprivate readonly store: Store,\n\t\tmergeEngine: MergeEngine,\n\t\temitter: KoraEventEmitter | null,\n\t\toptions?: MergeAwareSyncStoreOptions,\n\t) {\n\t\tthis.pipeline = new ApplyPipeline({\n\t\t\tstore,\n\t\t\tmergeEngine,\n\t\t\temitter,\n\t\t\tonMergeConflict: options?.onMergeConflict,\n\t\t})\n\t}\n\n\tgetVersionVector(): VersionVector {\n\t\treturn this.store.getVersionVector()\n\t}\n\n\tgetNodeId(): string {\n\t\treturn this.store.getNodeId()\n\t}\n\n\tasync getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]> {\n\t\treturn this.store.getOperationRange(nodeId, fromSeq, toSeq)\n\t}\n\n\tasync applyRemoteOperation(op: Operation): Promise<ApplyResult> {\n\t\treturn this.pipeline.applyRemote(op)\n\t}\n}\n","import type { Operation } from '@korajs/core'\nimport type { StorageAdapter } from '@korajs/store'\nimport { deserializeOperation, serializeOperation } from '@korajs/store/internal'\nimport type { OperationRow } from '@korajs/store/internal'\nimport type { QueueStorage } from '@korajs/sync'\n\ninterface SyncQueueRow {\n\tid: string\n\tpayload: string\n}\n\ntype QueuePayload = OperationRow & { _collection: string }\n\n/**\n * Persists the outbound sync queue in `_kora_sync_queue` via the local StorageAdapter.\n */\nexport class StoreQueueStorage implements QueueStorage {\n\tconstructor(private readonly adapter: StorageAdapter) {}\n\n\tasync load(): Promise<Operation[]> {\n\t\tconst rows = await this.adapter.query<SyncQueueRow>(\n\t\t\t'SELECT id, payload FROM _kora_sync_queue ORDER BY rowid ASC',\n\t\t)\n\t\treturn rows.map((row) => operationFromQueuePayload(row.payload))\n\t}\n\n\tasync enqueue(op: Operation): Promise<void> {\n\t\tconst row = serializeOperation(op)\n\t\tconst payload: QueuePayload = { ...row, _collection: op.collection }\n\t\tawait this.adapter.execute(\n\t\t\t'INSERT OR REPLACE INTO _kora_sync_queue (id, payload) VALUES (?, ?)',\n\t\t\t[op.id, JSON.stringify(payload)],\n\t\t)\n\t}\n\n\tasync dequeue(ids: string[]): Promise<void> {\n\t\tif (ids.length === 0) return\n\t\tconst placeholders = ids.map(() => '?').join(', ')\n\t\tawait this.adapter.execute(`DELETE FROM _kora_sync_queue WHERE id IN (${placeholders})`, ids)\n\t}\n\n\tasync count(): Promise<number> {\n\t\tconst rows = await this.adapter.query<{ cnt: number }>(\n\t\t\t'SELECT COUNT(*) as cnt FROM _kora_sync_queue',\n\t\t)\n\t\treturn rows[0]?.cnt ?? 0\n\t}\n}\n\nfunction operationFromQueuePayload(payload: string): Operation {\n\tconst parsed = JSON.parse(payload) as QueuePayload\n\tconst op = deserializeOperation(parsed)\n\treturn {\n\t\t...op,\n\t\tcollection: parsed._collection,\n\t}\n}\n","import type { Operation, VersionVector } from '@korajs/core'\nimport { mergeVersionVectors } from '@korajs/store'\nimport type { Store } from '@korajs/store'\nimport { decodeDeltaCursor, encodeDeltaCursor, operationMatchesScope } from '@korajs/sync'\nimport type { DeltaCursor, SyncScopeMap, SyncStatePersistence } from '@korajs/sync'\n\n/**\n * Persists and queries sync acknowledgment state via the local Store.\n */\nexport class StoreSyncStatePersistence implements SyncStatePersistence {\n\tconstructor(\n\t\tprivate readonly store: Store,\n\t\tprivate readonly scope?: SyncScopeMap,\n\t) {}\n\n\tloadLastAckedServerVector(): Promise<VersionVector> {\n\t\treturn this.store.loadLastAckedServerVector()\n\t}\n\n\tsaveLastAckedServerVector(vector: VersionVector): Promise<void> {\n\t\treturn this.store.saveLastAckedServerVector(vector)\n\t}\n\n\tmergeServerVectors(a: VersionVector, b: VersionVector): VersionVector {\n\t\treturn this.store.mergeServerVectors(a, b)\n\t}\n\n\tasync countUnsyncedOperations(serverVector: VersionVector): Promise<number> {\n\t\tconst ops = await this.getUnsyncedOperations(serverVector)\n\t\treturn ops.length\n\t}\n\n\tasync getUnsyncedOperations(serverVector: VersionVector): Promise<Operation[]> {\n\t\tconst ops = await this.store.getUnsyncedOperations(serverVector)\n\t\treturn ops.filter((op) => operationMatchesScope(op, this.scope))\n\t}\n\n\tloadDeltaCursor(): Promise<DeltaCursor | null> {\n\t\treturn this.store.loadDeltaCursor().then((encoded) => decodeDeltaCursor(encoded))\n\t}\n\n\tasync saveDeltaCursor(cursor: DeltaCursor | null): Promise<void> {\n\t\tawait this.store.saveDeltaCursor(cursor ? encodeDeltaCursor(cursor) : null)\n\t}\n}\n","import type { QueryDescriptor } from '@korajs/store'\nimport type { SyncEngine } from '@korajs/sync'\nimport type { SyncQuerySubset } from '@korajs/sync'\n\n/**\n * Extract equality-only WHERE conditions for sync query subset registration.\n * Operator-based filters (e.g. `$gt`) are not representable as sync subsets yet.\n */\nexport function queryDescriptorToSyncSubset(descriptor: QueryDescriptor): SyncQuerySubset | null {\n\tconst where: Record<string, unknown> = {}\n\n\tfor (const [field, value] of Object.entries(descriptor.where)) {\n\t\tif (value === null || value === undefined) {\n\t\t\twhere[field] = value\n\t\t\tcontinue\n\t\t}\n\t\tif (typeof value !== 'object' || Array.isArray(value)) {\n\t\t\twhere[field] = value\n\t\t}\n\t}\n\n\tif (Object.keys(where).length === 0) {\n\t\treturn null\n\t}\n\n\treturn {\n\t\tcollection: descriptor.collection,\n\t\twhere,\n\t}\n}\n\n/**\n * Creates a store hook that registers live query filters with the sync engine.\n */\nexport function createSyncQuerySubscriptionHook(\n\tgetSyncEngine: () => SyncEngine | null,\n): (descriptor: QueryDescriptor) => () => void {\n\treturn (descriptor) => {\n\t\tconst subset = queryDescriptorToSyncSubset(descriptor)\n\t\tif (!subset) {\n\t\t\treturn () => {}\n\t\t}\n\n\t\tconst engine = getSyncEngine()\n\t\tif (!engine) {\n\t\t\treturn () => {}\n\t\t}\n\n\t\treturn engine.registerQuerySubset(subset)\n\t}\n}\n","import type { KoraEventEmitter, KoraEventType } from '@korajs/core'\nimport type { SyncStatusInfo } from '@korajs/sync'\n\nconst OFFLINE_STATUS: SyncStatusInfo = Object.freeze({\n\tstatus: 'offline',\n\tpendingOperations: 0,\n\tlastSyncedAt: null,\n\tlastSuccessfulPush: null,\n\tlastSuccessfulPull: null,\n\tconflicts: 0,\n})\n\n/** Sync-related events that may change {@link SyncStatusInfo}. */\nconst SYNC_STATUS_EVENT_TYPES = [\n\t'sync:connected',\n\t'sync:disconnected',\n\t'sync:schema-mismatch',\n\t'sync:auth-failed',\n\t'sync:sent',\n\t'sync:received',\n\t'sync:acknowledged',\n\t'sync:apply-failed',\n\t'sync:diagnostics',\n\t'sync:initial-sync-progress',\n] as const satisfies readonly KoraEventType[]\n\n/**\n * Event-driven sync status snapshot for non-React consumers (`app.sync.status`).\n */\nexport interface SyncStatusBridge {\n\treadonly status: SyncStatusInfo\n\tsubscribe(listener: (status: SyncStatusInfo) => void): () => void\n\trefresh(): void\n\tdestroy(): void\n}\n\n/**\n * Subscribe to sync events and expose a reactive status snapshot.\n */\nexport function createSyncStatusBridge(\n\temitter: KoraEventEmitter,\n\tgetSyncEngine: () => { getStatus(): SyncStatusInfo } | null,\n): SyncStatusBridge {\n\tlet currentStatus: SyncStatusInfo = OFFLINE_STATUS\n\tconst listeners = new Set<(status: SyncStatusInfo) => void>()\n\n\tconst refresh = (): void => {\n\t\tconst engine = getSyncEngine()\n\t\tconst next = engine ? engine.getStatus() : OFFLINE_STATUS\n\t\tconst prevSerialized = JSON.stringify(currentStatus)\n\t\tconst nextSerialized = JSON.stringify(next)\n\t\tif (prevSerialized === nextSerialized) {\n\t\t\treturn\n\t\t}\n\t\tcurrentStatus = next\n\t\tfor (const listener of listeners) {\n\t\t\tlistener(currentStatus)\n\t\t}\n\t}\n\n\tconst unsubs: Array<() => void> = []\n\tfor (const type of SYNC_STATUS_EVENT_TYPES) {\n\t\tunsubs.push(emitter.on(type, refresh))\n\t}\n\n\tconst bridge: SyncStatusBridge = {\n\t\tget status() {\n\t\t\treturn currentStatus\n\t\t},\n\t\tsubscribe(listener: (status: SyncStatusInfo) => void): () => void {\n\t\t\tlisteners.add(listener)\n\t\t\tlistener(currentStatus)\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener)\n\t\t\t}\n\t\t},\n\t\trefresh,\n\t\tdestroy(): void {\n\t\t\tfor (const unsub of unsubs) {\n\t\t\t\tunsub()\n\t\t\t}\n\t\t\tunsubs.length = 0\n\t\t\tlisteners.clear()\n\t\t},\n\t}\n\n\trefresh()\n\n\treturn bridge\n}\n","import { KoraError, SchemaValidationError } from '@korajs/core'\nimport { detectAdapterType } from './adapter-resolver'\nimport type { KoraConfig } from './types'\n\n/**\n * Fail fast on invalid createApp configuration before opening storage or sync.\n */\nexport function validateCreateAppConfig(config: KoraConfig): void {\n\tif (!config.schema) {\n\t\tthrow new SchemaValidationError('createApp requires a schema.', {\n\t\t\tfix: 'Pass schema: defineSchema({ version: 1, collections: { ... } })',\n\t\t})\n\t}\n\n\tif (config.schema.version < 1) {\n\t\tthrow new SchemaValidationError('Schema version must be at least 1.', {\n\t\t\tversion: config.schema.version,\n\t\t})\n\t}\n\n\tconst collectionNames = Object.keys(config.schema.collections)\n\tif (collectionNames.length === 0) {\n\t\tthrow new SchemaValidationError('Schema must define at least one collection.', {\n\t\t\tfix: 'Add entries under collections in defineSchema().',\n\t\t})\n\t}\n\n\tif (config.sync) {\n\t\tvalidateSyncUrl(config.sync.url, config.sync.transport ?? 'websocket')\n\t}\n\n\tconst adapter = config.store?.adapter ?? detectAdapterType()\n\tconst isBrowser =\n\t\ttypeof globalThis !== 'undefined' &&\n\t\ttypeof (globalThis as Record<string, unknown>).window !== 'undefined'\n\n\tif (\n\t\tisBrowser &&\n\t\t(adapter === 'sqlite-wasm' || adapter === 'indexeddb') &&\n\t\t!config.store?.workerUrl\n\t) {\n\t\tthrow new KoraError(\n\t\t\t'Browser storage requires store.workerUrl pointing to the SQLite WASM worker script.',\n\t\t\t'MISSING_WORKER_URL',\n\t\t\t{\n\t\t\t\tadapter,\n\t\t\t\tfix: 'Add store: { workerUrl: \"/sqlite-wasm-worker.js\" } (see create-kora-app templates).',\n\t\t\t},\n\t\t)\n\t}\n}\n\nfunction validateSyncUrl(url: string, transport: 'websocket' | 'http'): void {\n\tif (!url || url.trim().length === 0) {\n\t\tthrow new KoraError('sync.url is required when sync is configured.', 'INVALID_SYNC_URL', {\n\t\t\tfix: 'Pass sync: { url: \"wss://your-server/kora\" }.',\n\t\t})\n\t}\n\n\ttry {\n\t\tconst parsed = new URL(url)\n\t\tif (transport === 'http') {\n\t\t\tif (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n\t\t\t\tthrow new Error('bad protocol')\n\t\t\t}\n\t\t} else if (parsed.protocol !== 'ws:' && parsed.protocol !== 'wss:') {\n\t\t\tthrow new Error('bad protocol')\n\t\t}\n\t} catch {\n\t\tthrow new KoraError(\n\t\t\t`Invalid sync URL \"${url}\" for transport \"${transport}\".`,\n\t\t\t'INVALID_SYNC_URL',\n\t\t\t{\n\t\t\t\turl,\n\t\t\t\ttransport,\n\t\t\t\tfix:\n\t\t\t\t\ttransport === 'http'\n\t\t\t\t\t\t? 'Use an absolute http:// or https:// URL.'\n\t\t\t\t\t\t: 'Use an absolute ws:// or wss:// URL.',\n\t\t\t},\n\t\t)\n\t}\n}\n"],"mappings":"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","names":["import_core","import_internal","import_merge","import_store","import_sync","import_core","import_internal","import_core","operation","version","opInsert","ctx","op","t","import_store","op","import_internal","op","import_store","op","import_core","config","import_store","import_core","import_merge","import_sync"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { CollectionRecord, QueryBuilder, CollectionAccessor } from '@korajs/store';
|
|
5
|
-
export { CollectionAccessor, CollectionRecord, SequenceManager, StorageAdapter, Store, StoreConfig, TransactionCollectionAccessor, TransactionContext, TransactionContextConfig } from '@korajs/store';
|
|
1
|
+
import * as _korajs_core from '@korajs/core';
|
|
2
|
+
import { KoraEventEmitter, SequenceConfig, Operation, SchemaDefinition, KoraEvent, SchemaInput, FieldBuilder, InferRecord, InferInsertInput, InferUpdateInput } from '@korajs/core';
|
|
3
|
+
export { AtomicOp, AtomicOpType, CollectionDefinition, ConnectionQuality, Constraint, FieldDescriptor, FieldKindToType, HLCTimestamp, HybridLogicalClock, InferFieldType, InferInsertInput, InferRecord, InferUpdateInput, KoraError, KoraEvent, KoraEventEmitter, KoraEventListener, KoraEventType, MergeStrategy, MergeTrace, MigrationDefinition, MigrationStep, Operation, SchemaDefinition, SchemaInput, SequenceConfig, SyncRuleDefinition, TypedSchemaDefinition, VersionVector, createOperation, defineSchema, generateUUIDv7, migrate, op, t } from '@korajs/core';
|
|
6
4
|
import * as _korajs_sync from '@korajs/sync';
|
|
7
5
|
import { SyncStatusInfo, SyncEngine } from '@korajs/sync';
|
|
8
|
-
export { SyncConfig, SyncDiagnostics, SyncEngine, SyncState, SyncStatus, SyncStatusInfo, SyncStore, WebSocketTransport } from '@korajs/sync';
|
|
6
|
+
export { SyncConfig, SyncDiagnostics, SyncEncryptionConfig, SyncEngine, SyncState, SyncStatus, SyncStatusInfo, SyncStore, WebSocketTransport } from '@korajs/sync';
|
|
7
|
+
import * as _korajs_store from '@korajs/store';
|
|
8
|
+
import { CollectionRecord, BackupOptions, RestoreOptions, RestoreResult, ReplaySnapshot, AuditExportOptions, QueryBuilder, CollectionAccessor } from '@korajs/store';
|
|
9
|
+
export { AuditExportManifest, AuditExportOptions, AuditExportPayload, BackupManifest, BackupOptions, BackupProgress, CollectionAccessor, CollectionRecord, PersistedAuditTrace, ReplaySnapshot, RestoreOptions, RestoreResult, SequenceManager, StorageAdapter, Store, StoreConfig, TransactionCollectionAccessor, TransactionContext, TransactionContextConfig, decodeAuditExport, exportBackup, readAuditExportManifest, readBackupManifest, restoreBackup, verifyAuditExportChecksum, verifyBackupChecksum } from '@korajs/store';
|
|
9
10
|
export { MergeEngine, MergeInput, MergeResult } from '@korajs/merge';
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -24,8 +25,36 @@ interface StoreOptions {
|
|
|
24
25
|
adapter?: AdapterType;
|
|
25
26
|
/** Database name. Defaults to 'kora-db'. */
|
|
26
27
|
name?: string;
|
|
28
|
+
/**
|
|
29
|
+
* `shared` (default): one sync node id per database.
|
|
30
|
+
* `per-tab`: unique node id per browser tab (sessionStorage).
|
|
31
|
+
*/
|
|
32
|
+
isolation?: _korajs_store.StoreIsolation;
|
|
27
33
|
/** URL to the SQLite WASM worker script. Required for browser adapters (sqlite-wasm, indexeddb). */
|
|
28
34
|
workerUrl?: string | URL;
|
|
35
|
+
/** Optional SharedWorker host for multi-tab SQLite (see `@korajs/store/sqlite-wasm/shared-host`). */
|
|
36
|
+
sharedWorkerUrl?: string | URL;
|
|
37
|
+
/** Max wait for a worker RPC (e.g. `open`). Defaults to 30000ms. */
|
|
38
|
+
workerResponseTimeoutMs?: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Pre-built auth binding from `createKoraAuthSync()` in `@korajs/auth`.
|
|
42
|
+
* Wires token refresh, JWT scope maps, and device-bound sync node ids.
|
|
43
|
+
*/
|
|
44
|
+
interface AuthSyncBinding {
|
|
45
|
+
/** Returns the access token for sync handshake (empty string when signed out). */
|
|
46
|
+
auth: () => Promise<{
|
|
47
|
+
token: string;
|
|
48
|
+
}>;
|
|
49
|
+
/** Builds a scope map from the current token and schema. */
|
|
50
|
+
resolveScopeMap?: () => Promise<Record<string, Record<string, unknown>> | undefined>;
|
|
51
|
+
/**
|
|
52
|
+
* Returns the device-bound sync node id from the token `dev` claim.
|
|
53
|
+
* Separate from the user id (`sub`).
|
|
54
|
+
*/
|
|
55
|
+
resolveNodeId?: () => Promise<string | undefined>;
|
|
56
|
+
/** Notifies when auth state changes so sync can refresh scope or reconnect. */
|
|
57
|
+
subscribe?: (listener: () => void) => () => void;
|
|
29
58
|
}
|
|
30
59
|
/**
|
|
31
60
|
* Sync configuration within createApp.
|
|
@@ -39,6 +68,11 @@ interface SyncOptions {
|
|
|
39
68
|
auth?: () => Promise<{
|
|
40
69
|
token: string;
|
|
41
70
|
}>;
|
|
71
|
+
/**
|
|
72
|
+
* Pre-built auth binding from `createKoraAuthSync({ authClient, schema })`.
|
|
73
|
+
* When set, overrides `auth`, auto-builds `scopeMap`, and binds store node id to `dev`.
|
|
74
|
+
*/
|
|
75
|
+
authClient?: AuthSyncBinding;
|
|
42
76
|
/** Sync scopes per collection. */
|
|
43
77
|
scopes?: Record<string, (ctx: Record<string, unknown>) => Record<string, unknown>>;
|
|
44
78
|
/**
|
|
@@ -61,12 +95,23 @@ interface SyncOptions {
|
|
|
61
95
|
batchSize?: number;
|
|
62
96
|
/** Schema version of this client. */
|
|
63
97
|
schemaVersion?: number;
|
|
98
|
+
/** Connect to the sync server automatically after `app.ready`. Defaults to false. */
|
|
99
|
+
autoConnect?: boolean;
|
|
100
|
+
/** Wait for server ACK on each handshake delta batch before streaming. Defaults to false. */
|
|
101
|
+
strictHandshake?: boolean;
|
|
102
|
+
/** Rewrites legacy operations during sync when schema versions differ. */
|
|
103
|
+
operationTransforms?: _korajs_core.OperationTransform[];
|
|
64
104
|
/** Enable auto-reconnection on unexpected disconnect. Defaults to true. */
|
|
65
105
|
autoReconnect?: boolean;
|
|
66
106
|
/** Initial reconnection delay in ms. Defaults to 1000. */
|
|
67
107
|
reconnectInterval?: number;
|
|
68
108
|
/** Maximum reconnection delay in ms. Defaults to 30000. */
|
|
69
109
|
maxReconnectInterval?: number;
|
|
110
|
+
/**
|
|
111
|
+
* End-to-end encryption for operation payloads on the sync wire.
|
|
112
|
+
* When enabled, `data` and `previousData` are encrypted before send.
|
|
113
|
+
*/
|
|
114
|
+
encryption?: _korajs_sync.SyncEncryptionConfig;
|
|
70
115
|
}
|
|
71
116
|
/**
|
|
72
117
|
* Full configuration passed to createApp().
|
|
@@ -80,7 +125,15 @@ interface KoraConfig {
|
|
|
80
125
|
sync?: SyncOptions;
|
|
81
126
|
/** Enable DevTools instrumentation. Defaults to false. */
|
|
82
127
|
devtools?: boolean;
|
|
128
|
+
/** Called for each sync-related framework event. */
|
|
129
|
+
onSyncEvent?: (event: Extract<KoraEvent, {
|
|
130
|
+
type: `sync:${string}`;
|
|
131
|
+
}>) => void;
|
|
83
132
|
}
|
|
133
|
+
/** Sync event types delivered to {@link KoraConfig.onSyncEvent}. */
|
|
134
|
+
type KoraSyncEvent = Extract<KoraEvent, {
|
|
135
|
+
type: `sync:${string}`;
|
|
136
|
+
}>;
|
|
84
137
|
/**
|
|
85
138
|
* Typed configuration passed to createApp() when using a TypedSchemaDefinition.
|
|
86
139
|
*/
|
|
@@ -95,6 +148,8 @@ interface TypedKoraConfig<S extends SchemaInput> {
|
|
|
95
148
|
sync?: SyncOptions;
|
|
96
149
|
/** Enable DevTools instrumentation. Defaults to false. */
|
|
97
150
|
devtools?: boolean;
|
|
151
|
+
/** Called for each sync-related framework event. */
|
|
152
|
+
onSyncEvent?: (event: KoraSyncEvent) => void;
|
|
98
153
|
}
|
|
99
154
|
/**
|
|
100
155
|
* Controls for the sync subsystem exposed on the KoraApp.
|
|
@@ -104,10 +159,16 @@ interface SyncControl {
|
|
|
104
159
|
connect(): Promise<void>;
|
|
105
160
|
/** Disconnect from the sync server. */
|
|
106
161
|
disconnect(): Promise<void>;
|
|
162
|
+
/** Current sync status snapshot (updates on sync events). */
|
|
163
|
+
readonly status: SyncStatusInfo;
|
|
107
164
|
/** Get the current developer-facing sync status. */
|
|
108
165
|
getStatus(): SyncStatusInfo;
|
|
166
|
+
/** Subscribe to status changes (event-driven, no polling). */
|
|
167
|
+
subscribeStatus(listener: (status: SyncStatusInfo) => void): () => void;
|
|
109
168
|
/** Force an immediate reconnection attempt. No-op if already connected. */
|
|
110
169
|
retryNow(): Promise<void>;
|
|
170
|
+
/** Clear schema-mismatch block after upgrading schema; then call `connect()`. */
|
|
171
|
+
clearSchemaBlock(): void;
|
|
111
172
|
/** Export a diagnostics snapshot for debugging and support tickets. */
|
|
112
173
|
exportDiagnostics(): _korajs_sync.SyncDiagnostics;
|
|
113
174
|
}
|
|
@@ -218,6 +279,35 @@ interface KoraApp {
|
|
|
218
279
|
* ```
|
|
219
280
|
*/
|
|
220
281
|
mutation(name: string, fn: (tx: TransactionProxy) => Promise<void>): Promise<Operation[]>;
|
|
282
|
+
/**
|
|
283
|
+
* Export all data as a portable backup binary.
|
|
284
|
+
* Delegates to the underlying store's exportBackup.
|
|
285
|
+
*
|
|
286
|
+
* @param options - Backup options (includeRecords, collections, onProgress)
|
|
287
|
+
* @returns Backup as a Uint8Array
|
|
288
|
+
*/
|
|
289
|
+
exportBackup(options?: BackupOptions): Promise<Uint8Array>;
|
|
290
|
+
/**
|
|
291
|
+
* Restore data from a backup binary.
|
|
292
|
+
* Delegates to the underlying store's importBackup.
|
|
293
|
+
*
|
|
294
|
+
* @param data - The backup data
|
|
295
|
+
* @param options - Restore options (merge, collections, onProgress)
|
|
296
|
+
* @returns Result of the restore operation
|
|
297
|
+
*/
|
|
298
|
+
importBackup(data: Uint8Array, options?: RestoreOptions): Promise<RestoreResult>;
|
|
299
|
+
/**
|
|
300
|
+
* Rebuild an in-memory snapshot at a causal cut in the operation log.
|
|
301
|
+
* Does not mutate live data — for DevTools time-travel and audit inspection.
|
|
302
|
+
*
|
|
303
|
+
* @param operationId - Content-addressed operation id to replay through (inclusive)
|
|
304
|
+
*/
|
|
305
|
+
replayTo(operationId: string): Promise<ReplaySnapshot>;
|
|
306
|
+
/**
|
|
307
|
+
* Export the operation log and persisted merge traces as a portable audit bundle.
|
|
308
|
+
* Merge traces are recorded automatically when conflicts are resolved.
|
|
309
|
+
*/
|
|
310
|
+
exportAudit(options?: AuditExportOptions): Promise<Uint8Array>;
|
|
221
311
|
/** Dynamic collection accessors (e.g., app.todos). Typed via Object.defineProperty. */
|
|
222
312
|
[collection: string]: unknown;
|
|
223
313
|
}
|
|
@@ -260,6 +350,14 @@ type TypedKoraApp<S extends SchemaInput> = {
|
|
|
260
350
|
transaction(fn: (tx: TransactionProxy) => Promise<void>): Promise<Operation[]>;
|
|
261
351
|
/** Execute a named mutation — a transaction with a DevTools-visible name. */
|
|
262
352
|
mutation(name: string, fn: (tx: TransactionProxy) => Promise<void>): Promise<Operation[]>;
|
|
353
|
+
/** Export all data as a portable backup binary. */
|
|
354
|
+
exportBackup(options?: BackupOptions): Promise<Uint8Array>;
|
|
355
|
+
/** Restore data from a backup binary. */
|
|
356
|
+
importBackup(data: Uint8Array, options?: RestoreOptions): Promise<RestoreResult>;
|
|
357
|
+
/** Rebuild an in-memory snapshot at a causal cut in the operation log. */
|
|
358
|
+
replayTo(operationId: string): Promise<ReplaySnapshot>;
|
|
359
|
+
/** Export the operation log and persisted merge traces as a portable audit bundle. */
|
|
360
|
+
exportAudit(options?: AuditExportOptions): Promise<Uint8Array>;
|
|
263
361
|
} & {
|
|
264
362
|
readonly [C in keyof S['collections'] & string]: S['collections'][C] extends {
|
|
265
363
|
fields: infer F extends Record<string, FieldBuilder<any, any, any>>;
|
|
@@ -307,4 +405,4 @@ declare function createApp<const S extends SchemaInput>(config: TypedKoraConfig<
|
|
|
307
405
|
*/
|
|
308
406
|
declare function createApp(config: KoraConfig): KoraApp;
|
|
309
407
|
|
|
310
|
-
export { type AdapterType, type KoraApp, type KoraConfig, type SequenceAccessor, type StoreOptions, type SyncControl, type SyncOptions, type TransactionCollectionProxy, type TransactionProxy, type TypedCollectionAccessor, type TypedKoraApp, type TypedKoraConfig, createApp };
|
|
408
|
+
export { type AdapterType, type AuthSyncBinding, type KoraApp, type KoraConfig, type SequenceAccessor, type StoreOptions, type SyncControl, type SyncOptions, type TransactionCollectionProxy, type TransactionProxy, type TypedCollectionAccessor, type TypedKoraApp, type TypedKoraConfig, createApp };
|