Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

@loro-dev/unisqlite

Package Overview
Dependencies
Maintainers
2
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@loro-dev/unisqlite - npm Package Compare versions

Comparing version
0.4.0
to
0.5.0
+1
dist/node2.cjs.map
{"version":3,"file":"node2.cjs","names":["BaseAdapter","Database"],"sources":["../src/adapters/logger.ts","../src/adapters/node.ts"],"sourcesContent":["/**\n * Debug Logger for UniSQLite\n *\n * Uses the `debug` package for conditional logging.\n * Enable logs by setting DEBUG env var:\n *\n * - `unisqlite:*` - Enable all unisqlite logs\n * - `unisqlite:node` - Node.js adapter logs only\n *\n * In Node.js:\n * DEBUG=unisqlite:* node app.js\n */\n\nimport debug from \"debug\";\n\nconst NAMESPACE = \"unisqlite\";\n\n// Package version - will be output on initialization\nexport const VERSION = \"0.4.0\";\n\n/**\n * Logger interface with log, warn, and error methods\n */\nexport interface Logger {\n log: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n}\n\n/**\n * Create a namespaced debug logger with log/warn/error methods\n */\nfunction createModuleLogger(name: string): Logger {\n const logDebug = debug(`${NAMESPACE}:${name}`);\n const warnDebug = debug(`${NAMESPACE}:${name}:warn`);\n const errorDebug = debug(`${NAMESPACE}:${name}:error`);\n\n // Enable error logs by default (they go to stderr)\n errorDebug.enabled = true;\n\n return {\n log: logDebug as (...args: unknown[]) => void,\n warn: warnDebug as (...args: unknown[]) => void,\n error: errorDebug as (...args: unknown[]) => void,\n };\n}\n\n// Pre-created logger for node adapter\nexport const nodeLogger = createModuleLogger(\"node\");\n\n/**\n * Create a custom debug logger\n */\nexport function createDebugLogger(name: string): Logger {\n return createModuleLogger(name);\n}\n\n/**\n * Enable debug logging programmatically\n * This is useful for enabling logs without setting localStorage/env\n *\n * @param namespaces - Debug namespaces to enable (default: \"unisqlite:*\")\n *\n * @example\n * // Enable all unisqlite logs\n * enableDebug(\"unisqlite:*\");\n *\n * // Enable only node adapter logs\n * enableDebug(\"unisqlite:node\");\n */\nexport function enableDebug(namespaces: string = \"unisqlite:*\"): void {\n debug.enable(namespaces);\n}\n\n/**\n * Disable all debug logging\n */\nexport function disableDebug(): void {\n debug.disable();\n}\n","import { BaseAdapter } from \"./base.js\";\nimport type {\n QueryResult,\n RunResult,\n SQLiteParams,\n SQLiteValue,\n UniStoreConnection,\n UniStoreOptions,\n ConnectionType,\n} from \"../types.js\";\nimport Database from \"better-sqlite3\";\nimport { nodeLogger as logger, VERSION } from \"./logger.js\";\n\nexport class NodeAdapter extends BaseAdapter {\n private db: Database.Database;\n private _closed: boolean = false;\n\n constructor(options: UniStoreOptions) {\n super(options);\n logger.log(`UniSQLite v${VERSION} - Opening database: ${options.path}`);\n // Open database with WAL mode for better concurrency\n this.db = new Database(options.path, { fileMustExist: false });\n this.db.pragma(\"journal_mode = WAL\");\n this.db.pragma(\"busy_timeout = 5000\"); // 5 second timeout for locks\n logger.log(\"Database opened with WAL mode\");\n }\n\n private normalizeParams(params?: SQLiteParams): unknown[] {\n if (!params) return [];\n if (Array.isArray(params)) return params;\n // Convert object params to array format for better-sqlite3\n // This is a simplified conversion - in practice you'd need to handle named parameters\n return Object.values(params);\n }\n\n private convertBuffersToUint8Array<T>(value: T): T {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (Buffer.isBuffer(value)) {\n return new Uint8Array(value) as T;\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => this.convertBuffersToUint8Array(item)) as T;\n }\n\n if (typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n result[key] = this.convertBuffersToUint8Array(val);\n }\n return result as T;\n }\n\n return value;\n }\n\n private checkConnection(): void {\n if (this._closed || !this.db.open) {\n throw new Error(\"Database connection is closed\");\n }\n }\n\n async query<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<T[]> {\n this.checkConnection();\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n return this.convertBuffersToUint8Array(rows);\n }\n\n async queryRaw<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<QueryResult<T>> {\n this.checkConnection();\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n const columns = stmt.columns().map((col) => col.name);\n\n return {\n rows: this.convertBuffersToUint8Array(rows),\n columns,\n rowsAffected: 0,\n lastInsertRowId: 0,\n };\n }\n\n async run(sql: string, params?: SQLiteParams): Promise<RunResult> {\n this.checkConnection();\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const info = stmt.run(paramsArray);\n\n return {\n rowsAffected: info.changes,\n lastInsertRowId: info.lastInsertRowid as number,\n };\n }\n\n async exec(sql: string): Promise<void> {\n this.checkConnection();\n this.db.exec(sql);\n }\n\n transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T> {\n this.checkConnection();\n // better-sqlite3 supports synchronous transactions\n this.db.exec(\"BEGIN\");\n const transactionAdapter = new SyncTransactionAdapter(this.db);\n return (async () => {\n try {\n const result = await fn(transactionAdapter);\n this.db.exec(\"COMMIT\");\n return result;\n } catch (error) {\n this.db.exec(\"ROLLBACK\");\n throw error;\n }\n })();\n }\n\n /**\n * Execute an async transaction with manual transaction management.\n * This allows async operations within the transaction but comes with timeout support\n * to prevent long-running transactions from blocking the database.\n *\n * @param fn Transaction function that can contain async operations\n * @param options Transaction options including timeout (default: 30000ms)\n */\n async asyncTransaction<T>(fn: (tx: UniStoreConnection) => Promise<T>, options?: { timeoutMs?: number }): Promise<T> {\n this.checkConnection();\n\n const timeoutMs = options?.timeoutMs ?? 30000; // Default 30 seconds\n let alreadyInTransaction = false;\n\n // Manual transaction management using BEGIN/COMMIT/ROLLBACK\n try {\n this.db.exec(\"BEGIN IMMEDIATE\");\n } catch (e) {\n if ((e as Error).message.includes(\"cannot start a transaction within a transaction\")) {\n alreadyInTransaction = true;\n } else {\n throw e;\n }\n }\n\n let timeoutHandle: NodeJS.Timeout | undefined;\n let transactionCompleted = false;\n\n try {\n // Set up timeout\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n if (!transactionCompleted) {\n reject(new Error(`Async transaction timeout after ${timeoutMs}ms`));\n }\n }, timeoutMs);\n });\n\n const transactionAdapter = new AsyncTransactionAdapter(this.db);\n\n // Race between transaction execution and timeout\n const result = await Promise.race([fn(transactionAdapter), timeoutPromise]);\n\n transactionCompleted = true;\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n\n // If we get here, the transaction completed successfully\n if (!alreadyInTransaction) {\n this.db.exec(\"COMMIT\");\n }\n return result;\n } catch (error) {\n transactionCompleted = true;\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n\n try {\n this.db.exec(\"ROLLBACK\");\n } catch (rollbackError) {\n logger.error(\"Rollback failed:\", rollbackError);\n }\n\n throw error;\n }\n }\n\n getConnectionType(): ConnectionType {\n return \"direct\";\n }\n\n async close(): Promise<void> {\n if (!this._closed && this.db.open) {\n this.db.close();\n this._closed = true;\n }\n }\n\n get isOpen(): boolean {\n return !this._closed && this.db.open;\n }\n}\n\nabstract class BaseTransactionAdapter implements UniStoreConnection {\n public readonly inTransaction = true;\n\n constructor(protected db: Database.Database) {}\n\n private normalizeParams(params?: SQLiteParams): unknown[] {\n if (!params) return [];\n if (Array.isArray(params)) return params;\n return Object.values(params);\n }\n\n private convertBuffersToUint8Array<T>(value: T): T {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (Buffer.isBuffer(value)) {\n return new Uint8Array(value) as T;\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => this.convertBuffersToUint8Array(item)) as T;\n }\n\n if (typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n result[key] = this.convertBuffersToUint8Array(val);\n }\n return result as T;\n }\n\n return value;\n }\n\n // Synchronous database methods for use in transactions\n query<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<T[]> {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n const result = this.convertBuffersToUint8Array(rows);\n return Promise.resolve(result);\n }\n\n queryRaw<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<QueryResult<T>> {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n const columns = stmt.columns().map((col) => col.name);\n\n const result = {\n rows: this.convertBuffersToUint8Array(rows),\n columns,\n rowsAffected: 0,\n lastInsertRowId: 0,\n };\n return Promise.resolve(result);\n }\n\n run(sql: string, params?: SQLiteParams): Promise<RunResult> {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const info = stmt.run(paramsArray);\n\n const result = {\n rowsAffected: info.changes,\n lastInsertRowId: info.lastInsertRowid as number,\n };\n return Promise.resolve(result);\n }\n\n exec(sql: string): Promise<void> {\n this.db.exec(sql);\n return Promise.resolve();\n }\n\n // Synchronous versions for use in sync transactions\n querySync<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): T[] {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n return this.convertBuffersToUint8Array(rows);\n }\n\n runSync(sql: string, params?: SQLiteParams): RunResult {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const info = stmt.run(paramsArray);\n\n return {\n rowsAffected: info.changes,\n lastInsertRowId: info.lastInsertRowid as number,\n };\n }\n\n execSync(sql: string): void {\n this.db.exec(sql);\n }\n\n abstract getConnectionType(): ConnectionType;\n abstract transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T>;\n abstract asyncTransaction<T>(\n fn: (tx: UniStoreConnection) => Promise<T>,\n options?: { timeoutMs?: number }\n ): Promise<T>;\n\n async close(): Promise<void> {\n // No-op for transaction\n }\n}\n\nclass SyncTransactionAdapter extends BaseTransactionAdapter {\n getConnectionType(): ConnectionType {\n return \"syncTxn\";\n }\n\n async transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T> {\n // For syncTxn, we can execute the transaction using itself as the connection\n // This allows nested operations within the same transaction\n return await fn(this);\n }\n\n async asyncTransaction<T>(\n _fn: (tx: UniStoreConnection) => Promise<T>,\n _options?: { timeoutMs?: number }\n ): Promise<T> {\n // syncTxn connections cannot run asyncTransaction\n throw new Error(\n \"asyncTransaction is not supported in syncTxn connections. Use transaction() instead or create a direct connection.\"\n );\n }\n}\n\nclass AsyncTransactionAdapter extends BaseTransactionAdapter {\n getConnectionType(): ConnectionType {\n return \"asyncTxn\";\n }\n\n async transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T> {\n // For asyncTxn, we can execute the transaction using itself as the connection\n // This allows nested operations within the same transaction\n return await fn(this);\n }\n\n async asyncTransaction<T>(fn: (tx: UniStoreConnection) => Promise<T>, _options?: { timeoutMs?: number }): Promise<T> {\n // For asyncTxn, we can execute asyncTransaction using itself as the connection\n // This allows nested async operations within the same transaction\n return await fn(this);\n }\n}\n"],"mappings":"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"}
{"version":3,"file":"node2.mjs","names":[],"sources":["../src/adapters/logger.ts","../src/adapters/node.ts"],"sourcesContent":["/**\n * Debug Logger for UniSQLite\n *\n * Uses the `debug` package for conditional logging.\n * Enable logs by setting DEBUG env var:\n *\n * - `unisqlite:*` - Enable all unisqlite logs\n * - `unisqlite:node` - Node.js adapter logs only\n *\n * In Node.js:\n * DEBUG=unisqlite:* node app.js\n */\n\nimport debug from \"debug\";\n\nconst NAMESPACE = \"unisqlite\";\n\n// Package version - will be output on initialization\nexport const VERSION = \"0.4.0\";\n\n/**\n * Logger interface with log, warn, and error methods\n */\nexport interface Logger {\n log: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n}\n\n/**\n * Create a namespaced debug logger with log/warn/error methods\n */\nfunction createModuleLogger(name: string): Logger {\n const logDebug = debug(`${NAMESPACE}:${name}`);\n const warnDebug = debug(`${NAMESPACE}:${name}:warn`);\n const errorDebug = debug(`${NAMESPACE}:${name}:error`);\n\n // Enable error logs by default (they go to stderr)\n errorDebug.enabled = true;\n\n return {\n log: logDebug as (...args: unknown[]) => void,\n warn: warnDebug as (...args: unknown[]) => void,\n error: errorDebug as (...args: unknown[]) => void,\n };\n}\n\n// Pre-created logger for node adapter\nexport const nodeLogger = createModuleLogger(\"node\");\n\n/**\n * Create a custom debug logger\n */\nexport function createDebugLogger(name: string): Logger {\n return createModuleLogger(name);\n}\n\n/**\n * Enable debug logging programmatically\n * This is useful for enabling logs without setting localStorage/env\n *\n * @param namespaces - Debug namespaces to enable (default: \"unisqlite:*\")\n *\n * @example\n * // Enable all unisqlite logs\n * enableDebug(\"unisqlite:*\");\n *\n * // Enable only node adapter logs\n * enableDebug(\"unisqlite:node\");\n */\nexport function enableDebug(namespaces: string = \"unisqlite:*\"): void {\n debug.enable(namespaces);\n}\n\n/**\n * Disable all debug logging\n */\nexport function disableDebug(): void {\n debug.disable();\n}\n","import { BaseAdapter } from \"./base.js\";\nimport type {\n QueryResult,\n RunResult,\n SQLiteParams,\n SQLiteValue,\n UniStoreConnection,\n UniStoreOptions,\n ConnectionType,\n} from \"../types.js\";\nimport Database from \"better-sqlite3\";\nimport { nodeLogger as logger, VERSION } from \"./logger.js\";\n\nexport class NodeAdapter extends BaseAdapter {\n private db: Database.Database;\n private _closed: boolean = false;\n\n constructor(options: UniStoreOptions) {\n super(options);\n logger.log(`UniSQLite v${VERSION} - Opening database: ${options.path}`);\n // Open database with WAL mode for better concurrency\n this.db = new Database(options.path, { fileMustExist: false });\n this.db.pragma(\"journal_mode = WAL\");\n this.db.pragma(\"busy_timeout = 5000\"); // 5 second timeout for locks\n logger.log(\"Database opened with WAL mode\");\n }\n\n private normalizeParams(params?: SQLiteParams): unknown[] {\n if (!params) return [];\n if (Array.isArray(params)) return params;\n // Convert object params to array format for better-sqlite3\n // This is a simplified conversion - in practice you'd need to handle named parameters\n return Object.values(params);\n }\n\n private convertBuffersToUint8Array<T>(value: T): T {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (Buffer.isBuffer(value)) {\n return new Uint8Array(value) as T;\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => this.convertBuffersToUint8Array(item)) as T;\n }\n\n if (typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n result[key] = this.convertBuffersToUint8Array(val);\n }\n return result as T;\n }\n\n return value;\n }\n\n private checkConnection(): void {\n if (this._closed || !this.db.open) {\n throw new Error(\"Database connection is closed\");\n }\n }\n\n async query<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<T[]> {\n this.checkConnection();\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n return this.convertBuffersToUint8Array(rows);\n }\n\n async queryRaw<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<QueryResult<T>> {\n this.checkConnection();\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n const columns = stmt.columns().map((col) => col.name);\n\n return {\n rows: this.convertBuffersToUint8Array(rows),\n columns,\n rowsAffected: 0,\n lastInsertRowId: 0,\n };\n }\n\n async run(sql: string, params?: SQLiteParams): Promise<RunResult> {\n this.checkConnection();\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const info = stmt.run(paramsArray);\n\n return {\n rowsAffected: info.changes,\n lastInsertRowId: info.lastInsertRowid as number,\n };\n }\n\n async exec(sql: string): Promise<void> {\n this.checkConnection();\n this.db.exec(sql);\n }\n\n transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T> {\n this.checkConnection();\n // better-sqlite3 supports synchronous transactions\n this.db.exec(\"BEGIN\");\n const transactionAdapter = new SyncTransactionAdapter(this.db);\n return (async () => {\n try {\n const result = await fn(transactionAdapter);\n this.db.exec(\"COMMIT\");\n return result;\n } catch (error) {\n this.db.exec(\"ROLLBACK\");\n throw error;\n }\n })();\n }\n\n /**\n * Execute an async transaction with manual transaction management.\n * This allows async operations within the transaction but comes with timeout support\n * to prevent long-running transactions from blocking the database.\n *\n * @param fn Transaction function that can contain async operations\n * @param options Transaction options including timeout (default: 30000ms)\n */\n async asyncTransaction<T>(fn: (tx: UniStoreConnection) => Promise<T>, options?: { timeoutMs?: number }): Promise<T> {\n this.checkConnection();\n\n const timeoutMs = options?.timeoutMs ?? 30000; // Default 30 seconds\n let alreadyInTransaction = false;\n\n // Manual transaction management using BEGIN/COMMIT/ROLLBACK\n try {\n this.db.exec(\"BEGIN IMMEDIATE\");\n } catch (e) {\n if ((e as Error).message.includes(\"cannot start a transaction within a transaction\")) {\n alreadyInTransaction = true;\n } else {\n throw e;\n }\n }\n\n let timeoutHandle: NodeJS.Timeout | undefined;\n let transactionCompleted = false;\n\n try {\n // Set up timeout\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n if (!transactionCompleted) {\n reject(new Error(`Async transaction timeout after ${timeoutMs}ms`));\n }\n }, timeoutMs);\n });\n\n const transactionAdapter = new AsyncTransactionAdapter(this.db);\n\n // Race between transaction execution and timeout\n const result = await Promise.race([fn(transactionAdapter), timeoutPromise]);\n\n transactionCompleted = true;\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n\n // If we get here, the transaction completed successfully\n if (!alreadyInTransaction) {\n this.db.exec(\"COMMIT\");\n }\n return result;\n } catch (error) {\n transactionCompleted = true;\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n\n try {\n this.db.exec(\"ROLLBACK\");\n } catch (rollbackError) {\n logger.error(\"Rollback failed:\", rollbackError);\n }\n\n throw error;\n }\n }\n\n getConnectionType(): ConnectionType {\n return \"direct\";\n }\n\n async close(): Promise<void> {\n if (!this._closed && this.db.open) {\n this.db.close();\n this._closed = true;\n }\n }\n\n get isOpen(): boolean {\n return !this._closed && this.db.open;\n }\n}\n\nabstract class BaseTransactionAdapter implements UniStoreConnection {\n public readonly inTransaction = true;\n\n constructor(protected db: Database.Database) {}\n\n private normalizeParams(params?: SQLiteParams): unknown[] {\n if (!params) return [];\n if (Array.isArray(params)) return params;\n return Object.values(params);\n }\n\n private convertBuffersToUint8Array<T>(value: T): T {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (Buffer.isBuffer(value)) {\n return new Uint8Array(value) as T;\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => this.convertBuffersToUint8Array(item)) as T;\n }\n\n if (typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n result[key] = this.convertBuffersToUint8Array(val);\n }\n return result as T;\n }\n\n return value;\n }\n\n // Synchronous database methods for use in transactions\n query<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<T[]> {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n const result = this.convertBuffersToUint8Array(rows);\n return Promise.resolve(result);\n }\n\n queryRaw<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<QueryResult<T>> {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n const columns = stmt.columns().map((col) => col.name);\n\n const result = {\n rows: this.convertBuffersToUint8Array(rows),\n columns,\n rowsAffected: 0,\n lastInsertRowId: 0,\n };\n return Promise.resolve(result);\n }\n\n run(sql: string, params?: SQLiteParams): Promise<RunResult> {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const info = stmt.run(paramsArray);\n\n const result = {\n rowsAffected: info.changes,\n lastInsertRowId: info.lastInsertRowid as number,\n };\n return Promise.resolve(result);\n }\n\n exec(sql: string): Promise<void> {\n this.db.exec(sql);\n return Promise.resolve();\n }\n\n // Synchronous versions for use in sync transactions\n querySync<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): T[] {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n return this.convertBuffersToUint8Array(rows);\n }\n\n runSync(sql: string, params?: SQLiteParams): RunResult {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const info = stmt.run(paramsArray);\n\n return {\n rowsAffected: info.changes,\n lastInsertRowId: info.lastInsertRowid as number,\n };\n }\n\n execSync(sql: string): void {\n this.db.exec(sql);\n }\n\n abstract getConnectionType(): ConnectionType;\n abstract transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T>;\n abstract asyncTransaction<T>(\n fn: (tx: UniStoreConnection) => Promise<T>,\n options?: { timeoutMs?: number }\n ): Promise<T>;\n\n async close(): Promise<void> {\n // No-op for transaction\n }\n}\n\nclass SyncTransactionAdapter extends BaseTransactionAdapter {\n getConnectionType(): ConnectionType {\n return \"syncTxn\";\n }\n\n async transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T> {\n // For syncTxn, we can execute the transaction using itself as the connection\n // This allows nested operations within the same transaction\n return await fn(this);\n }\n\n async asyncTransaction<T>(\n _fn: (tx: UniStoreConnection) => Promise<T>,\n _options?: { timeoutMs?: number }\n ): Promise<T> {\n // syncTxn connections cannot run asyncTransaction\n throw new Error(\n \"asyncTransaction is not supported in syncTxn connections. Use transaction() instead or create a direct connection.\"\n );\n }\n}\n\nclass AsyncTransactionAdapter extends BaseTransactionAdapter {\n getConnectionType(): ConnectionType {\n return \"asyncTxn\";\n }\n\n async transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T> {\n // For asyncTxn, we can execute the transaction using itself as the connection\n // This allows nested operations within the same transaction\n return await fn(this);\n }\n\n async asyncTransaction<T>(fn: (tx: UniStoreConnection) => Promise<T>, _options?: { timeoutMs?: number }): Promise<T> {\n // For asyncTxn, we can execute asyncTransaction using itself as the connection\n // This allows nested async operations within the same transaction\n return await fn(this);\n }\n}\n"],"mappings":"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"}
/**
* Debug Logger for UniSQLite
*
* Uses the `debug` package for conditional logging.
* Enable logs by setting DEBUG env var:
*
* - `unisqlite:*` - Enable all unisqlite logs
* - `unisqlite:node` - Node.js adapter logs only
*
* In Node.js:
* DEBUG=unisqlite:* node app.js
*/
import debug from "debug";
const NAMESPACE = "unisqlite";
// Package version - will be output on initialization
export const VERSION = "0.4.0";
/**
* Logger interface with log, warn, and error methods
*/
export interface Logger {
log: (...args: unknown[]) => void;
warn: (...args: unknown[]) => void;
error: (...args: unknown[]) => void;
}
/**
* Create a namespaced debug logger with log/warn/error methods
*/
function createModuleLogger(name: string): Logger {
const logDebug = debug(`${NAMESPACE}:${name}`);
const warnDebug = debug(`${NAMESPACE}:${name}:warn`);
const errorDebug = debug(`${NAMESPACE}:${name}:error`);
// Enable error logs by default (they go to stderr)
errorDebug.enabled = true;
return {
log: logDebug as (...args: unknown[]) => void,
warn: warnDebug as (...args: unknown[]) => void,
error: errorDebug as (...args: unknown[]) => void,
};
}
// Pre-created logger for node adapter
export const nodeLogger = createModuleLogger("node");
/**
* Create a custom debug logger
*/
export function createDebugLogger(name: string): Logger {
return createModuleLogger(name);
}
/**
* Enable debug logging programmatically
* This is useful for enabling logs without setting localStorage/env
*
* @param namespaces - Debug namespaces to enable (default: "unisqlite:*")
*
* @example
* // Enable all unisqlite logs
* enableDebug("unisqlite:*");
*
* // Enable only node adapter logs
* enableDebug("unisqlite:node");
*/
export function enableDebug(namespaces: string = "unisqlite:*"): void {
debug.enable(namespaces);
}
/**
* Disable all debug logging
*/
export function disableDebug(): void {
debug.disable();
}
+5
-5

@@ -1,8 +0,8 @@

const e=require(`./chunk.cjs`),t=require(`./base.cjs`);let n=require(`debug`);n=e.t(n);const r=`unisqlite`;function i(e){let t=(0,n.default)(`${r}:${e}`),i=(0,n.default)(`${r}:${e}:warn`),a=(0,n.default)(`${r}:${e}:error`);return a.enabled=!0,{log:t,warn:i,error:a}}const a=i(`host`),o=i(`txn`),s=i(`adapter`);var c=class e{constructor(e){this.options=e,this.abortController=null,this._isHost=!1,this._isStarted=!1,this.releaseResolver=null,this.hostReadyResolver=null,this.hostReadyPromise=null,this.lockName=`sqlite:host:${e.dbName}`,this.txnLockName=`sqlite:txn:${e.dbName}`}static isSupported(){return typeof navigator<`u`&&navigator.locks!==void 0}get isHost(){return this._isHost}async start(){if(!this._isStarted){if(!e.isSupported()){a.warn(`Web Locks API not supported. Running in local-only mode.`),this._isStarted=!0,this._isHost=!0,this.options.onBecomeHost().catch(e=>{a.error(`Error in onBecomeHost callback:`,e),this._isHost=!1});return}this.options.checkVisibility&&!this.options.checkVisibility()||(this._isStarted=!0,this.hostReadyPromise=new Promise(e=>{this.hostReadyResolver=e}),this.tryAcquireHost().catch(e=>{a.error(`Error in host election:`,e)}))}}async waitForHost(){if(!this._isHost&&(this.hostReadyPromise||(await this.start(),this.hostReadyPromise)))return this.hostReadyPromise}async tryAcquireHost(){this.abortController=new AbortController;try{await navigator.locks.request(this.lockName,{mode:`exclusive`,signal:this.abortController.signal},async e=>{if(e){this._isHost=!0,a.log(`Tab ${this.options.tabId} became Host for ${this.options.dbName}`);try{await this.options.onBecomeHost()}catch(e){throw a.error(`Error in onBecomeHost callback:`,e),this._isHost=!1,e}this.hostReadyResolver&&(this.hostReadyResolver(),this.hostReadyResolver=null,this.hostReadyPromise=null),await new Promise(e=>{this.releaseResolver=e,this.abortController.signal.addEventListener(`abort`,()=>{e()})}),this._isHost=!1,this.releaseResolver=null,a.log(`Tab ${this.options.tabId} lost Host role for ${this.options.dbName}`);try{this.options.onLoseHost()}catch(e){a.error(`Error in onLoseHost callback:`,e)}}})}catch(e){if(e.name===`AbortError`)return;throw a.error(`Error acquiring Host lock:`,e),e}finally{this._isStarted=!1,this.abortController=null}}releaseHost(){this.releaseResolver&&=(this.releaseResolver(),null),this.abortController&&=(this.abortController.abort(),null)}async acquireTransactionLock(){if(!e.isSupported())return()=>{};let t=new AbortController,n=null,r=null,i=new Promise(e=>{r=e});return navigator.locks.request(this.txnLockName,{mode:`exclusive`,signal:t.signal},async e=>{e&&(r?.(),await new Promise(e=>{n=e}))}).catch(e=>{e.name!==`AbortError`&&a.error(`Error acquiring transaction lock:`,e),r?.()}),await i,()=>{n?n():t.abort()}}async hasTransactionLock(){if(!e.isSupported())return!1;try{return(await navigator.locks.query()).held?.some(e=>e.name===this.txnLockName)??!1}catch{return!1}}async close(){this.releaseHost()}},l=class{constructor(){this.listeners=new Set,this.boundHandler=this.handleVisibilityChange.bind(this),typeof document<`u`&&document.addEventListener(`visibilitychange`,this.boundHandler)}handleVisibilityChange(){let e=this.isVisible();this.listeners.forEach(t=>{try{t(e)}catch(e){console.error(`Error in visibility change listener:`,e)}})}isVisible(){return typeof document>`u`?!0:document.visibilityState===`visible`}onVisibilityChange(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}destroy(){typeof document<`u`&&document.removeEventListener(`visibilitychange`,this.boundHandler),this.listeners.clear()}};function u(e){return e instanceof Error?{name:e.name,message:e.message,stack:e.stack}:{name:`Error`,message:String(e)}}function d(e){let t=Error(e.message);return t.name=e.name,e.stack&&(t.stack=e.stack),t}function f(e){return e.t===`req`||e.t===`txn_begin`||e.t===`txn_exec`||e.t===`txn_commit`||e.t===`txn_rollback`||e.t===`txn_heartbeat`}function p(e){return e.t===`res`||e.t===`txn_ack`||e.t===`txn_result`||e.t===`txn_done`||e.t===`txn_error`}function m(){return crypto.randomUUID()}function h(){return crypto.randomUUID()}function g(){return crypto.randomUUID()}var _=class{constructor(e,t,n=3e4){this.dbName=e,this.tabId=t,this.defaultTimeoutMs=n,this.pending=new Map,this.closed=!1,this.channel=new BroadcastChannel(`sqlite:rpc:${e}`),this.channel.onmessage=this.handleMessage.bind(this)}handleMessage(e){if(this.closed)return;let t=e.data;!t||typeof t.t!=`string`||(p(t)?this.handleResponse(t):f(t)&&this.requestHandler&&`from`in t&&t.from!==this.tabId&&this.handleRequest(t))}handleResponse(e){if(`to`in e&&e.to!==this.tabId||!(`id`in e))return;let t=this.pending.get(e.id);if(t)switch(clearTimeout(t.timer),this.pending.delete(e.id),e.t){case`res`:e.ok?t.resolve(e.result):t.reject(d(e.error));break;case`txn_ack`:case`txn_done`:t.resolve(void 0);break;case`txn_result`:e.ok?t.resolve(e.result):t.reject(d(e.error));break;case`txn_error`:t.reject(d(e.error));break}}async handleRequest(e){if(this.requestHandler)try{let t=await this.requestHandler(e);this.sendResponse(e,t)}catch(t){this.sendErrorResponse(e,t)}}sendResponse(e,t){if(this.closed)return;let n=`from`in e?e.from:void 0,r=`id`in e?e.id:void 0;if(!(!n||!r))switch(e.t){case`req`:this.channel.postMessage({t:`res`,to:n,id:r,ok:!0,result:t});break;case`txn_begin`:this.channel.postMessage({t:`txn_ack`,to:n,id:r,txnId:e.txnId});break;case`txn_exec`:this.channel.postMessage({t:`txn_result`,to:n,id:r,txnId:e.txnId,ok:!0,result:t});break;case`txn_commit`:case`txn_rollback`:this.channel.postMessage({t:`txn_done`,to:n,id:r,txnId:e.txnId});break;case`txn_heartbeat`:break}}sendErrorResponse(e,t){if(this.closed)return;let n=`from`in e?e.from:void 0,r=`id`in e?e.id:void 0;if(!n||!r)return;let i=u(t);switch(e.t){case`req`:this.channel.postMessage({t:`res`,to:n,id:r,ok:!1,error:i});break;case`txn_begin`:case`txn_exec`:case`txn_commit`:case`txn_rollback`:this.channel.postMessage({t:`txn_error`,to:n,id:r,txnId:e.txnId,error:i});break}}setRequestHandler(e){this.requestHandler=e}async request(e,t,n){let r=m(),i=n??this.defaultTimeoutMs;return new Promise((n,a)=>{let o=setTimeout(()=>{this.pending.delete(r),a(Error(`RPC timeout after ${i}ms for ${e}`))},i);this.pending.set(r,{resolve:n,reject:a,timer:o}),this.channel.postMessage({t:`req`,from:this.tabId,id:r,op:e,payload:t})})}async txnBegin(e,t=`immediate`,n){let r=m(),i=n??this.defaultTimeoutMs;return new Promise((n,a)=>{let o=setTimeout(()=>{this.pending.delete(r),a(Error(`Transaction begin timeout after ${i}ms`))},i);this.pending.set(r,{resolve:n,reject:a,timer:o}),this.channel.postMessage({t:`txn_begin`,from:this.tabId,id:r,txnId:e,mode:t})})}async txnExec(e,t,n,r){let i=m(),a=r??1e4;return new Promise((r,o)=>{let s=setTimeout(()=>{this.pending.delete(i),o(Error(`Transaction SQL timeout after ${a}ms`))},a);this.pending.set(i,{resolve:r,reject:o,timer:s}),this.channel.postMessage({t:`txn_exec`,from:this.tabId,id:i,txnId:e,op:t,payload:n})})}async txnCommit(e,t){let n=m(),r=t??1e4;return new Promise((t,i)=>{let a=setTimeout(()=>{this.pending.delete(n),i(Error(`Transaction commit timeout after ${r}ms`))},r);this.pending.set(n,{resolve:t,reject:i,timer:a}),this.channel.postMessage({t:`txn_commit`,from:this.tabId,id:n,txnId:e})})}async txnRollback(e,t){let n=m(),r=t??1e4;return new Promise((t,i)=>{let a=setTimeout(()=>{this.pending.delete(n),i(Error(`Transaction rollback timeout after ${r}ms`))},r);this.pending.set(n,{resolve:t,reject:i,timer:a}),this.channel.postMessage({t:`txn_rollback`,from:this.tabId,id:n,txnId:e})})}txnHeartbeat(e){this.closed||this.channel.postMessage({t:`txn_heartbeat`,from:this.tabId,txnId:e})}close(){this.closed=!0,this.channel.close();for(let e of this.pending.values())clearTimeout(e.timer),e.reject(Error(`RPC channel closed`));this.pending.clear()}};const v=new Map,y=new Map;var b=class e{constructor(e,t){this.dbName=e,this.config=t,this.workerQueue=Promise.resolve(),this.activeStorageBackend=`memory`,this.closed=!1}static async create(t){let n=new e(t.dbName,t.config);return await n.initialize(),n}async initialize(){console.log(`Loading SQLite WASM using strategy: ${this.config.loadStrategy}`);let e=await this.loadSQLiteWasm(),t={print:console.log,printErr:console.error};if(this.config.locateFile)t.locateFile=this.config.locateFile;else if(typeof window<`u`){let e=window;e.sqlite3InitModuleState?.locateFile&&(t.locateFile=e.sqlite3InitModuleState.locateFile)}if(console.log(`Initializing SQLite WASM module...`),this.sqlite3=await e(t),!this.sqlite3)throw Error(`Failed to initialize SQLite WASM module`);let n=this.sqlite3;console.log(`SQLite WASM module initialized successfully`);let r=this.config.storageBackend??`auto`,i=this.dbName===`:memory:`?`:memory:`:`/unisqlite/${this.dbName}`;r===`memory`||this.dbName===`:memory:`?(console.log(`Using in-memory database`),this.db=new n.oo1.DB(`:memory:`),this.activeStorageBackend=`memory`):await this.tryCreatePersistentDatabase(n,i,r)||(console.log(`All persistent storage backends failed, using in-memory database`),this.db=new n.oo1.DB(`:memory:`),this.activeStorageBackend=`memory`);try{await this.execInternal(`PRAGMA journal_mode=WAL`),console.log(`Enabled WAL mode`)}catch(e){console.warn(`Could not enable WAL mode:`,e)}}async query(e,t){return(await this.executeSql(e,t)).rows}async queryRaw(e,t){return await this.executeSql(e,t)}async run(e,t){let n=await this.executeSql(e,t);return{rowsAffected:n.rowsAffected??0,lastInsertRowId:n.lastInsertRowId??0}}async exec(e){await this.execInternal(e)}async execRaw(e){await this.execInternal(e,{bypassQueue:!0})}async executeSqlRaw(e,t){return await this.executeSql(e,t,{bypassQueue:!0})}getActiveStorageBackend(){return this.activeStorageBackend}getActiveOpfsVfs(){return this.activeOpfsVfs}isWorkerDbActive(){return!!this.workerPromiser&&this.workerDbId!==void 0}async close(){if(!this.closed){if(this.closed=!0,this.workerPromiser){let e=this.workerPromiser,t=this.workerDbId;try{t!==void 0&&await this.enqueueWorker(async()=>{await e(`close`,{dbId:t})})}catch(e){console.warn(`Failed to close SQLite worker database:`,e)}finally{this.workerDbId=void 0;let t=e.worker;t?.terminate&&t.terminate(),this.workerPromiser=void 0}}this.db&&=(this.db.close(),void 0)}}enqueueWorker(e){let t=async()=>e(),n=this.workerQueue.then(t,t);return this.workerQueue=n.then(()=>void 0,()=>void 0),n}normalizeParams(e){if(!e)return;if(Array.isArray(e))return e;let t=Object.keys(e),n=e;return t.map(e=>n[e])}async execInternal(e,t){if(this.isWorkerDbActive()){let n=async()=>{if(!this.workerPromiser||this.workerDbId===void 0)throw Error(`Database not initialized`);await this.workerPromiser(`exec`,{dbId:this.workerDbId,sql:e})};t?.bypassQueue?await n():await this.enqueueWorker(n);return}if(!this.db)throw Error(`Database not initialized`);this.db.exec(e)}async executeSql(e,t,n){try{if(this.isWorkerDbActive()){let r=async()=>{if(!this.workerPromiser||this.workerDbId===void 0)throw Error(`Database not initialized`);let n=this.normalizeParams(t),r={dbId:this.workerDbId,sql:e,rowMode:`object`,resultRows:[],columnNames:[],countChanges:!0};n&&(r.bind=n);let i=await this.workerPromiser(`exec`,r),a=i.result??i,o=Array.isArray(a.resultRows)?a.resultRows:[],s=Array.isArray(a.columnNames)?a.columnNames:[],c=typeof a.changeCount==`number`?a.changeCount:0,l={dbId:this.workerDbId,sql:`SELECT last_insert_rowid() AS lastInsertRowId`,rowMode:`object`,resultRows:[],columnNames:[]},u=await this.workerPromiser(`exec`,l),d=u.result??u,f=Array.isArray(d.resultRows)?d.resultRows:[];return{rows:o,columns:s,rowsAffected:c,lastInsertRowId:Number(f[0]?.lastInsertRowId??0)}};return n?.bypassQueue?await r():await this.enqueueWorker(r)}if(!this.db||!this.sqlite3)throw Error(`Database not initialized`);let r=this.normalizeParams(t),i=[],a=[],o=this.db.prepare(e);try{let e=o;r&&o.bind(r);let t=typeof e.getColumnCount==`function`?e.getColumnCount():typeof e.columnCount==`number`?e.columnCount:0;if(t>0)if(typeof e.getColumnNames==`function`)a=e.getColumnNames();else for(let e=0;e<t;e++)a.push(o.getColumnName(e));for(;o.step();){let e={};for(let n=0;n<t;n++)e[a[n]]=o.get(n);i.push(e)}return{rows:i,columns:a,rowsAffected:this.db.changes(),lastInsertRowId:Number(this.sqlite3.capi.sqlite3_last_insert_rowid(this.db.pointer)||0)}}finally{o.finalize()}}catch(e){let t=e instanceof Error?e.message:String(e),n=Error(`SQLite error: ${t}`);throw e instanceof Error&&(n.cause=e),n}}async loadSQLiteWasm(){let e=`${this.config.loadStrategy}-${this.config.wasmUrl||this.config.cdnBaseUrl}-${this.config.version}`;if(v.has(e))return v.get(e);let t=this.loadSQLiteWasmInternal();return v.set(e,t),t}async loadSQLiteWasmInternal(){let{loadStrategy:e,wasmUrl:t,cdnBaseUrl:n,version:r,bundlerFriendly:i}=this.config;switch(e){case`npm`:return await this.loadFromNpm();case`cdn`:return await this.loadFromCdn(n,r,i);case`url`:if(!t)throw Error(`wasmUrl must be provided when using 'url' loading strategy`);return await this.loadFromUrl(t);case`module`:return await this.loadAsModule();case`global`:default:return this.loadFromGlobal()}}async loadFromNpm(){try{let e=await import(`@sqlite.org/sqlite-wasm`);return e.default||e}catch(e){return console.warn(`Failed to load SQLite WASM from npm, falling back to CDN:`,e),this.loadFromCdn(this.config.cdnBaseUrl,this.config.version,this.config.bundlerFriendly)}}async loadFromCdn(e,t,n){let r=n?`sqlite3-bundler-friendly.mjs`:`index.mjs`,i=[`https://cdn.jsdelivr.net/npm/@sqlite.org/sqlite-wasm@${t}/${r}`,`https://cdn.jsdelivr.net/npm/@sqlite.org/sqlite-wasm@${t}/dist/${r}`],a;for(let e of i)try{console.log(`Trying to load SQLite WASM from: ${e}`);let t=await import(e);return console.log(`Successfully loaded SQLite WASM from: ${e}`),t.default||t}catch(t){a=t,console.warn(`Failed to load SQLite WASM from ${e}:`,t)}let o=a instanceof Error?a.message:String(a);throw Error(`Failed to load SQLite WASM from any CDN source. Last error: ${o}`)}async loadFromUrl(e){let t=await import(e);return t.default||t.sqlite3InitModule}async loadAsModule(){if(globalThis.importScripts!==void 0)throw Error(`ES6 module loading not supported in Web Worker context`);for(let e of[`./sqlite3.mjs`,`./sqlite3-bundler-friendly.mjs`,`/sqlite3.mjs`])try{let t=await import(e);return t.default||t.sqlite3InitModule}catch(t){console.warn(`Failed to load SQLite WASM from ${e}:`,t)}throw Error(`Could not load SQLite WASM as ES6 module from any known path`)}loadFromGlobal(){if(typeof window<`u`){let e=window;if(e.sqlite3InitModule)return e.sqlite3InitModule}throw Error(`SQLite WASM module not found globally. Please:
const e=require(`./chunk.cjs`),t=require(`./base.cjs`);let n=require(`debug`);n=e.t(n);const r=`unisqlite`,i=`0.4.0`;function a(e){let t=(0,n.default)(`${r}:${e}`),i=(0,n.default)(`${r}:${e}:warn`),a=(0,n.default)(`${r}:${e}:error`);return a.enabled=!0,{log:t,warn:i,error:a}}const o=a(`host`),s=a(`txn`),c=a(`adapter`),l=a(`wasm`),u=a(`visibility`);var d=class e{constructor(e){this.options=e,this.abortController=null,this._isHost=!1,this._isStarted=!1,this.releaseResolver=null,this.hostReadyResolver=null,this.hostReadyPromise=null,this.lockName=`sqlite:host:${e.dbName}`,this.txnLockName=`sqlite:txn:${e.dbName}`}static isSupported(){return typeof navigator<`u`&&navigator.locks!==void 0}get isHost(){return this._isHost}async start(){if(!this._isStarted){if(!e.isSupported()){o.warn(`Web Locks API not supported. Running in local-only mode.`),this._isStarted=!0,this._isHost=!0,this.options.onBecomeHost().catch(e=>{o.error(`Error in onBecomeHost callback:`,e),this._isHost=!1});return}this.options.checkVisibility&&!this.options.checkVisibility()||(this._isStarted=!0,this.hostReadyPromise=new Promise(e=>{this.hostReadyResolver=e}),this.tryAcquireHost().catch(e=>{o.error(`Error in host election:`,e)}))}}async waitForHost(){if(!this._isHost&&(this.hostReadyPromise||(await this.start(),this.hostReadyPromise)))return this.hostReadyPromise}async tryAcquireHost(){this.abortController=new AbortController;try{await navigator.locks.request(this.lockName,{mode:`exclusive`,signal:this.abortController.signal},async e=>{if(e){this._isHost=!0,o.log(`Tab ${this.options.tabId} became Host for ${this.options.dbName}`);try{await this.options.onBecomeHost()}catch(e){throw o.error(`Error in onBecomeHost callback:`,e),this._isHost=!1,e}this.hostReadyResolver&&(this.hostReadyResolver(),this.hostReadyResolver=null,this.hostReadyPromise=null),await new Promise(e=>{this.releaseResolver=e,this.abortController.signal.addEventListener(`abort`,()=>{e()})}),this._isHost=!1,this.releaseResolver=null,o.log(`Tab ${this.options.tabId} lost Host role for ${this.options.dbName}`);try{this.options.onLoseHost()}catch(e){o.error(`Error in onLoseHost callback:`,e)}}})}catch(e){if(e.name===`AbortError`)return;throw o.error(`Error acquiring Host lock:`,e),e}finally{this._isStarted=!1,this.abortController=null}}releaseHost(){this.releaseResolver&&=(this.releaseResolver(),null),this.abortController&&=(this.abortController.abort(),null)}async acquireTransactionLock(){if(!e.isSupported())return()=>{};let t=new AbortController,n=null,r=null,i=new Promise(e=>{r=e});return navigator.locks.request(this.txnLockName,{mode:`exclusive`,signal:t.signal},async e=>{e&&(r?.(),await new Promise(e=>{n=e}))}).catch(e=>{e.name!==`AbortError`&&o.error(`Error acquiring transaction lock:`,e),r?.()}),await i,()=>{n?n():t.abort()}}async hasTransactionLock(){if(!e.isSupported())return!1;try{return(await navigator.locks.query()).held?.some(e=>e.name===this.txnLockName)??!1}catch{return!1}}async close(){this.releaseHost()}},f=class{constructor(){this.listeners=new Set,this.boundHandler=this.handleVisibilityChange.bind(this),typeof document<`u`&&document.addEventListener(`visibilitychange`,this.boundHandler)}handleVisibilityChange(){let e=this.isVisible();this.listeners.forEach(t=>{try{t(e)}catch(e){u.error(`Error in visibility change listener:`,e)}})}isVisible(){return typeof document>`u`?!0:document.visibilityState===`visible`}onVisibilityChange(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}destroy(){typeof document<`u`&&document.removeEventListener(`visibilitychange`,this.boundHandler),this.listeners.clear()}};function p(e){return e instanceof Error?{name:e.name,message:e.message,stack:e.stack}:{name:`Error`,message:String(e)}}function m(e){let t=Error(e.message);return t.name=e.name,e.stack&&(t.stack=e.stack),t}function h(e){return e.t===`req`||e.t===`txn_begin`||e.t===`txn_exec`||e.t===`txn_commit`||e.t===`txn_rollback`||e.t===`txn_heartbeat`}function g(e){return e.t===`res`||e.t===`txn_ack`||e.t===`txn_result`||e.t===`txn_done`||e.t===`txn_error`}function _(){return crypto.randomUUID()}function v(){return crypto.randomUUID()}function y(){return crypto.randomUUID()}var b=class{constructor(e,t,n=3e4){this.dbName=e,this.tabId=t,this.defaultTimeoutMs=n,this.pending=new Map,this.closed=!1,this.channel=new BroadcastChannel(`sqlite:rpc:${e}`),this.channel.onmessage=this.handleMessage.bind(this)}handleMessage(e){if(this.closed)return;let t=e.data;!t||typeof t.t!=`string`||(g(t)?this.handleResponse(t):h(t)&&this.requestHandler&&`from`in t&&t.from!==this.tabId&&this.handleRequest(t))}handleResponse(e){if(`to`in e&&e.to!==this.tabId||!(`id`in e))return;let t=this.pending.get(e.id);if(t)switch(clearTimeout(t.timer),this.pending.delete(e.id),e.t){case`res`:e.ok?t.resolve(e.result):t.reject(m(e.error));break;case`txn_ack`:case`txn_done`:t.resolve(void 0);break;case`txn_result`:e.ok?t.resolve(e.result):t.reject(m(e.error));break;case`txn_error`:t.reject(m(e.error));break}}async handleRequest(e){if(this.requestHandler)try{let t=await this.requestHandler(e);this.sendResponse(e,t)}catch(t){this.sendErrorResponse(e,t)}}sendResponse(e,t){if(this.closed)return;let n=`from`in e?e.from:void 0,r=`id`in e?e.id:void 0;if(!(!n||!r))switch(e.t){case`req`:this.channel.postMessage({t:`res`,to:n,id:r,ok:!0,result:t});break;case`txn_begin`:this.channel.postMessage({t:`txn_ack`,to:n,id:r,txnId:e.txnId});break;case`txn_exec`:this.channel.postMessage({t:`txn_result`,to:n,id:r,txnId:e.txnId,ok:!0,result:t});break;case`txn_commit`:case`txn_rollback`:this.channel.postMessage({t:`txn_done`,to:n,id:r,txnId:e.txnId});break;case`txn_heartbeat`:break}}sendErrorResponse(e,t){if(this.closed)return;let n=`from`in e?e.from:void 0,r=`id`in e?e.id:void 0;if(!n||!r)return;let i=p(t);switch(e.t){case`req`:this.channel.postMessage({t:`res`,to:n,id:r,ok:!1,error:i});break;case`txn_begin`:case`txn_exec`:case`txn_commit`:case`txn_rollback`:this.channel.postMessage({t:`txn_error`,to:n,id:r,txnId:e.txnId,error:i});break}}setRequestHandler(e){this.requestHandler=e}async request(e,t,n){let r=_(),i=n??this.defaultTimeoutMs;return new Promise((n,a)=>{let o=setTimeout(()=>{this.pending.delete(r),a(Error(`RPC timeout after ${i}ms for ${e}`))},i);this.pending.set(r,{resolve:n,reject:a,timer:o}),this.channel.postMessage({t:`req`,from:this.tabId,id:r,op:e,payload:t})})}async txnBegin(e,t=`immediate`,n){let r=_(),i=n??this.defaultTimeoutMs;return new Promise((n,a)=>{let o=setTimeout(()=>{this.pending.delete(r),a(Error(`Transaction begin timeout after ${i}ms`))},i);this.pending.set(r,{resolve:n,reject:a,timer:o}),this.channel.postMessage({t:`txn_begin`,from:this.tabId,id:r,txnId:e,mode:t})})}async txnExec(e,t,n,r){let i=_(),a=r??1e4;return new Promise((r,o)=>{let s=setTimeout(()=>{this.pending.delete(i),o(Error(`Transaction SQL timeout after ${a}ms`))},a);this.pending.set(i,{resolve:r,reject:o,timer:s}),this.channel.postMessage({t:`txn_exec`,from:this.tabId,id:i,txnId:e,op:t,payload:n})})}async txnCommit(e,t){let n=_(),r=t??1e4;return new Promise((t,i)=>{let a=setTimeout(()=>{this.pending.delete(n),i(Error(`Transaction commit timeout after ${r}ms`))},r);this.pending.set(n,{resolve:t,reject:i,timer:a}),this.channel.postMessage({t:`txn_commit`,from:this.tabId,id:n,txnId:e})})}async txnRollback(e,t){let n=_(),r=t??1e4;return new Promise((t,i)=>{let a=setTimeout(()=>{this.pending.delete(n),i(Error(`Transaction rollback timeout after ${r}ms`))},r);this.pending.set(n,{resolve:t,reject:i,timer:a}),this.channel.postMessage({t:`txn_rollback`,from:this.tabId,id:n,txnId:e})})}txnHeartbeat(e){this.closed||this.channel.postMessage({t:`txn_heartbeat`,from:this.tabId,txnId:e})}close(){this.closed=!0,this.channel.close();for(let e of this.pending.values())clearTimeout(e.timer),e.reject(Error(`RPC channel closed`));this.pending.clear()}};const x=new Map,S=new Map;var C=class e{constructor(e,t){this.dbName=e,this.config=t,this.workerQueue=Promise.resolve(),this.activeStorageBackend=`memory`,this.closed=!1}static async create(t){let n=new e(t.dbName,t.config);return await n.initialize(),n}async initialize(){l.log(`UniSQLite v0.4.0 - Loading SQLite WASM using strategy: ${this.config.loadStrategy}`);let e=await this.loadSQLiteWasm(),t={print:(...e)=>l.log(...e),printErr:(...e)=>l.error(...e)};if(this.config.locateFile)t.locateFile=this.config.locateFile;else if(typeof window<`u`){let e=window;e.sqlite3InitModuleState?.locateFile&&(t.locateFile=e.sqlite3InitModuleState.locateFile)}if(l.log(`Initializing SQLite WASM module...`),this.sqlite3=await e(t),!this.sqlite3)throw Error(`Failed to initialize SQLite WASM module`);let n=this.sqlite3;l.log(`SQLite WASM module initialized successfully`);let r=this.config.storageBackend??`auto`,i=this.dbName===`:memory:`?`:memory:`:`/unisqlite/${this.dbName}`;r===`memory`||this.dbName===`:memory:`?(l.log(`Using in-memory database`),this.db=new n.oo1.DB(`:memory:`),this.activeStorageBackend=`memory`):await this.tryCreatePersistentDatabase(n,i,r)||(l.log(`All persistent storage backends failed, using in-memory database`),this.db=new n.oo1.DB(`:memory:`),this.activeStorageBackend=`memory`);try{await this.execInternal(`PRAGMA journal_mode=WAL`),l.log(`Enabled WAL mode`)}catch(e){l.warn(`Could not enable WAL mode:`,e)}}async query(e,t){return(await this.executeSql(e,t)).rows}async queryRaw(e,t){return await this.executeSql(e,t)}async run(e,t){let n=await this.executeSql(e,t);return{rowsAffected:n.rowsAffected??0,lastInsertRowId:n.lastInsertRowId??0}}async exec(e){await this.execInternal(e)}async execRaw(e){await this.execInternal(e,{bypassQueue:!0})}async executeSqlRaw(e,t){return await this.executeSql(e,t,{bypassQueue:!0})}getActiveStorageBackend(){return this.activeStorageBackend}getActiveOpfsVfs(){return this.activeOpfsVfs}isWorkerDbActive(){return!!this.workerPromiser&&this.workerDbId!==void 0}async close(){if(!this.closed){if(this.closed=!0,this.workerPromiser){let e=this.workerPromiser,t=this.workerDbId;try{t!==void 0&&await this.enqueueWorker(async()=>{await e(`close`,{dbId:t})})}catch(e){l.warn(`Failed to close SQLite worker database:`,e)}finally{this.workerDbId=void 0;let t=e.worker;t?.terminate&&t.terminate(),this.workerPromiser=void 0}}this.db&&=(this.db.close(),void 0)}}enqueueWorker(e){let t=async()=>e(),n=this.workerQueue.then(t,t);return this.workerQueue=n.then(()=>void 0,()=>void 0),n}normalizeParams(e){if(!e)return;if(Array.isArray(e))return e;let t=Object.keys(e),n=e;return t.map(e=>n[e])}async execInternal(e,t){if(this.isWorkerDbActive()){let n=async()=>{if(!this.workerPromiser||this.workerDbId===void 0)throw Error(`Database not initialized`);await this.workerPromiser(`exec`,{dbId:this.workerDbId,sql:e})};t?.bypassQueue?await n():await this.enqueueWorker(n);return}if(!this.db)throw Error(`Database not initialized`);this.db.exec(e)}async executeSql(e,t,n){try{if(this.isWorkerDbActive()){let r=async()=>{if(!this.workerPromiser||this.workerDbId===void 0)throw Error(`Database not initialized`);let n=this.normalizeParams(t),r={dbId:this.workerDbId,sql:e,rowMode:`object`,resultRows:[],columnNames:[],countChanges:!0};n&&(r.bind=n);let i=await this.workerPromiser(`exec`,r),a=i.result??i,o=Array.isArray(a.resultRows)?a.resultRows:[],s=Array.isArray(a.columnNames)?a.columnNames:[],c=typeof a.changeCount==`number`?a.changeCount:0,l={dbId:this.workerDbId,sql:`SELECT last_insert_rowid() AS lastInsertRowId`,rowMode:`object`,resultRows:[],columnNames:[]},u=await this.workerPromiser(`exec`,l),d=u.result??u,f=Array.isArray(d.resultRows)?d.resultRows:[];return{rows:o,columns:s,rowsAffected:c,lastInsertRowId:Number(f[0]?.lastInsertRowId??0)}};return n?.bypassQueue?await r():await this.enqueueWorker(r)}if(!this.db||!this.sqlite3)throw Error(`Database not initialized`);let r=this.normalizeParams(t),i=[],a=[],o=this.db.prepare(e);try{let e=o;r&&o.bind(r);let t=typeof e.getColumnCount==`function`?e.getColumnCount():typeof e.columnCount==`number`?e.columnCount:0;if(t>0)if(typeof e.getColumnNames==`function`)a=e.getColumnNames();else for(let e=0;e<t;e++)a.push(o.getColumnName(e));for(;o.step();){let e={};for(let n=0;n<t;n++)e[a[n]]=o.get(n);i.push(e)}return{rows:i,columns:a,rowsAffected:this.db.changes(),lastInsertRowId:Number(this.sqlite3.capi.sqlite3_last_insert_rowid(this.db.pointer)||0)}}finally{o.finalize()}}catch(e){let t=e instanceof Error?e.message:String(e),n=Error(`SQLite error: ${t}`);throw e instanceof Error&&(n.cause=e),n}}async loadSQLiteWasm(){let e=`${this.config.loadStrategy}-${this.config.wasmUrl||this.config.cdnBaseUrl}-${this.config.version}`;if(x.has(e))return x.get(e);let t=this.loadSQLiteWasmInternal();return x.set(e,t),t}async loadSQLiteWasmInternal(){let{loadStrategy:e,wasmUrl:t,cdnBaseUrl:n,version:r,bundlerFriendly:i}=this.config;switch(e){case`npm`:return await this.loadFromNpm();case`cdn`:return await this.loadFromCdn(n,r,i);case`url`:if(!t)throw Error(`wasmUrl must be provided when using 'url' loading strategy`);return await this.loadFromUrl(t);case`module`:return await this.loadAsModule();case`global`:default:return this.loadFromGlobal()}}async loadFromNpm(){try{let e=await import(`@sqlite.org/sqlite-wasm`);return e.default||e}catch(e){return l.warn(`Failed to load SQLite WASM from npm, falling back to CDN:`,e),this.loadFromCdn(this.config.cdnBaseUrl,this.config.version,this.config.bundlerFriendly)}}async loadFromCdn(e,t,n){let r=n?`sqlite3-bundler-friendly.mjs`:`index.mjs`,i=[`https://cdn.jsdelivr.net/npm/@sqlite.org/sqlite-wasm@${t}/${r}`,`https://cdn.jsdelivr.net/npm/@sqlite.org/sqlite-wasm@${t}/dist/${r}`],a;for(let e of i)try{l.log(`Trying to load SQLite WASM from: ${e}`);let t=await import(e);return l.log(`Successfully loaded SQLite WASM from: ${e}`),t.default||t}catch(t){a=t,l.warn(`Failed to load SQLite WASM from ${e}:`,t)}let o=a instanceof Error?a.message:String(a);throw Error(`Failed to load SQLite WASM from any CDN source. Last error: ${o}`)}async loadFromUrl(e){let t=await import(e);return t.default||t.sqlite3InitModule}async loadAsModule(){if(globalThis.importScripts!==void 0)throw Error(`ES6 module loading not supported in Web Worker context`);for(let e of[`./sqlite3.mjs`,`./sqlite3-bundler-friendly.mjs`,`/sqlite3.mjs`])try{let t=await import(e);return t.default||t.sqlite3InitModule}catch(t){l.warn(`Failed to load SQLite WASM from ${e}:`,t)}throw Error(`Could not load SQLite WASM as ES6 module from any known path`)}loadFromGlobal(){if(typeof window<`u`){let e=window;if(e.sqlite3InitModule)return e.sqlite3InitModule}throw Error(`SQLite WASM module not found globally. Please:
1. Install via npm: npm install @sqlite.org/sqlite-wasm
2. Or set loadStrategy to 'cdn' for automatic CDN loading
3. Or include SQLite WASM script in your HTML before using UniSqlite`)}async loadSQLiteWorkerPromiserFactory(){let e=`worker-${this.config.loadStrategy}-${this.config.wasmUrl||this.config.cdnBaseUrl}-${this.config.version}`;if(y.has(e))return y.get(e);let t=this.loadSQLiteWorkerPromiserFactoryInternal();return y.set(e,t),t}async loadSQLiteWorkerPromiserFactoryInternal(){let{loadStrategy:e,wasmUrl:t,cdnBaseUrl:n,version:r,bundlerFriendly:i}=this.config;switch(e){case`npm`:return await this.loadWorkerPromiserFromNpm();case`cdn`:return await this.loadWorkerPromiserFromCdn(n,r,i);case`url`:if(!t)throw Error(`wasmUrl must be provided when using 'url' loading strategy`);return await this.loadWorkerPromiserFromUrl(t);case`module`:return await this.loadWorkerPromiserAsModule();case`global`:default:return this.loadWorkerPromiserFromGlobal()}}async loadWorkerPromiserFromNpm(){try{let e=(await import(`@sqlite.org/sqlite-wasm`)).sqlite3Worker1Promiser;if(typeof e==`function`)return e;throw Error(`sqlite3Worker1Promiser export not found`)}catch(e){return console.warn(`Failed to load SQLite WASM worker promiser from npm, falling back to CDN:`,e),this.loadWorkerPromiserFromCdn(this.config.cdnBaseUrl,this.config.version,this.config.bundlerFriendly)}}async loadWorkerPromiserFromCdn(e,t,n){let r=n?`sqlite3-bundler-friendly.mjs`:`index.mjs`,i=[`${e}@${t}/${r}`,`${e}@${t}/dist/${r}`],a;for(let e of i)try{console.log(`Trying to load SQLite WASM worker promiser from: ${e}`);let t=(await import(e)).sqlite3Worker1Promiser;if(typeof t==`function`)return console.log(`Successfully loaded SQLite WASM worker promiser from: ${e}`),t;throw Error(`sqlite3Worker1Promiser export not found`)}catch(t){a=t,console.warn(`Failed to load SQLite WASM worker promiser from ${e}:`,t)}let o=a instanceof Error?a.message:String(a);throw Error(`Failed to load sqlite3Worker1Promiser from any CDN source. Last error: ${o}`)}async loadWorkerPromiserFromUrl(e){let t=(await import(e)).sqlite3Worker1Promiser;if(typeof t!=`function`)throw Error(`sqlite3Worker1Promiser export not found in module loaded from ${e}`);return t}async loadWorkerPromiserAsModule(){if(globalThis.importScripts!==void 0)throw Error(`ES6 module loading not supported in Web Worker context`);for(let e of[`./sqlite3.mjs`,`./sqlite3-bundler-friendly.mjs`,`/sqlite3.mjs`])try{let t=(await import(e)).sqlite3Worker1Promiser;if(typeof t==`function`)return t}catch(t){console.warn(`Failed to load SQLite WASM worker promiser from ${e}:`,t)}throw Error(`Could not load sqlite3Worker1Promiser as ES6 module from any known path`)}loadWorkerPromiserFromGlobal(){let e=globalThis;if(typeof e.sqlite3Worker1Promiser==`function`)return e.sqlite3Worker1Promiser;throw Error(`SQLite WASM worker promiser not found globally. Please:
3. Or include SQLite WASM script in your HTML before using UniSqlite`)}async loadSQLiteWorkerPromiserFactory(){let e=`worker-${this.config.loadStrategy}-${this.config.wasmUrl||this.config.cdnBaseUrl}-${this.config.version}`;if(S.has(e))return S.get(e);let t=this.loadSQLiteWorkerPromiserFactoryInternal();return S.set(e,t),t}async loadSQLiteWorkerPromiserFactoryInternal(){let{loadStrategy:e,wasmUrl:t,cdnBaseUrl:n,version:r,bundlerFriendly:i}=this.config;switch(e){case`npm`:return await this.loadWorkerPromiserFromNpm();case`cdn`:return await this.loadWorkerPromiserFromCdn(n,r,i);case`url`:if(!t)throw Error(`wasmUrl must be provided when using 'url' loading strategy`);return await this.loadWorkerPromiserFromUrl(t);case`module`:return await this.loadWorkerPromiserAsModule();case`global`:default:return this.loadWorkerPromiserFromGlobal()}}async loadWorkerPromiserFromNpm(){try{let e=(await import(`@sqlite.org/sqlite-wasm`)).sqlite3Worker1Promiser;if(typeof e==`function`)return e;throw Error(`sqlite3Worker1Promiser export not found`)}catch(e){return l.warn(`Failed to load SQLite WASM worker promiser from npm, falling back to CDN:`,e),this.loadWorkerPromiserFromCdn(this.config.cdnBaseUrl,this.config.version,this.config.bundlerFriendly)}}async loadWorkerPromiserFromCdn(e,t,n){let r=n?`sqlite3-bundler-friendly.mjs`:`index.mjs`,i=[`${e}@${t}/${r}`,`${e}@${t}/dist/${r}`],a;for(let e of i)try{l.log(`Trying to load SQLite WASM worker promiser from: ${e}`);let t=(await import(e)).sqlite3Worker1Promiser;if(typeof t==`function`)return l.log(`Successfully loaded SQLite WASM worker promiser from: ${e}`),t;throw Error(`sqlite3Worker1Promiser export not found`)}catch(t){a=t,l.warn(`Failed to load SQLite WASM worker promiser from ${e}:`,t)}let o=a instanceof Error?a.message:String(a);throw Error(`Failed to load sqlite3Worker1Promiser from any CDN source. Last error: ${o}`)}async loadWorkerPromiserFromUrl(e){let t=(await import(e)).sqlite3Worker1Promiser;if(typeof t!=`function`)throw Error(`sqlite3Worker1Promiser export not found in module loaded from ${e}`);return t}async loadWorkerPromiserAsModule(){if(globalThis.importScripts!==void 0)throw Error(`ES6 module loading not supported in Web Worker context`);for(let e of[`./sqlite3.mjs`,`./sqlite3-bundler-friendly.mjs`,`/sqlite3.mjs`])try{let t=(await import(e)).sqlite3Worker1Promiser;if(typeof t==`function`)return t}catch(t){l.warn(`Failed to load SQLite WASM worker promiser from ${e}:`,t)}throw Error(`Could not load sqlite3Worker1Promiser as ES6 module from any known path`)}loadWorkerPromiserFromGlobal(){let e=globalThis;if(typeof e.sqlite3Worker1Promiser==`function`)return e.sqlite3Worker1Promiser;throw Error(`SQLite WASM worker promiser not found globally. Please:
1. Install via npm: npm install @sqlite.org/sqlite-wasm and set loadStrategy to 'npm'
2. Or set loadStrategy to 'cdn' for automatic CDN loading
3. Or include SQLite WASM worker promiser script in your HTML before using UniSqlite`)}async tryCreatePersistentDatabase(e,t,n){if(n===`opfs`||n===`auto`){let r=this.config.opfsVfsType??`auto`,i=r===`auto`?e.oo1.OpfsDb?[`opfs`]:[`opfs-sahpool`,`opfs`]:r===`sahpool`?[`opfs-sahpool`]:[`opfs`];for(let n of i)if(await this.tryCreateOpfsDatabase(e,t,n))return!0;if(n===`opfs`)throw Error(this.getOpfsUnavailableError())}if(n===`localStorage`||n===`auto`){if(e.oo1.JsStorageDb)if(this.dbName===`local`||this.dbName===`session`)try{return console.log(`Creating localStorage-backed database:`,this.dbName),this.db=new e.oo1.JsStorageDb(this.dbName),this.activeStorageBackend=`localStorage`,console.log(`Successfully created localStorage-backed database`),!0}catch(e){if(console.warn(`localStorage database creation failed:`,e),n===`localStorage`)throw Error(`localStorage database creation failed: ${e instanceof Error?e.message:String(e)}`)}else if(n===`localStorage`)throw Error(`localStorage storage backend requires path to be 'local' or 'session', got '${this.dbName}'. Use storageBackend: 'opfs' for custom database names with persistence.`);else console.log(`Skipping localStorage: path '${this.dbName}' is not 'local' or 'session'`);else if(n===`localStorage`)throw Error(`JsStorageDb is not available in this environment.`)}return!1}getOpfsUnavailableError(){return`OPFS is not available.
3. Or include SQLite WASM worker promiser script in your HTML before using UniSqlite`)}async tryCreatePersistentDatabase(e,t,n){if(n===`opfs`||n===`auto`){let r=this.config.opfsVfsType??`auto`,i=r===`auto`?e.oo1.OpfsDb?[`opfs`]:[`opfs-sahpool`,`opfs`]:r===`sahpool`?[`opfs-sahpool`]:[`opfs`];for(let n of i)if(await this.tryCreateOpfsDatabase(e,t,n))return!0;if(n===`opfs`)throw Error(this.getOpfsUnavailableError())}if(n===`localStorage`||n===`auto`){if(e.oo1.JsStorageDb)if(this.dbName===`local`||this.dbName===`session`)try{return l.log(`Creating localStorage-backed database:`,this.dbName),this.db=new e.oo1.JsStorageDb(this.dbName),this.activeStorageBackend=`localStorage`,l.log(`Successfully created localStorage-backed database`),!0}catch(e){if(l.warn(`localStorage database creation failed:`,e),n===`localStorage`)throw Error(`localStorage database creation failed: ${e instanceof Error?e.message:String(e)}`)}else if(n===`localStorage`)throw Error(`localStorage storage backend requires path to be 'local' or 'session', got '${this.dbName}'. Use storageBackend: 'opfs' for custom database names with persistence.`);else l.log(`Skipping localStorage: path '${this.dbName}' is not 'local' or 'session'`);else if(n===`localStorage`)throw Error(`JsStorageDb is not available in this environment.`)}return!1}getOpfsUnavailableError(){return`OPFS is not available.

@@ -14,5 +14,5 @@ SQLite WASM OPFS backends only work in Worker contexts. When running on the main thread, UniSQLite will try to use SQLite WASM's wrapped-worker API (sqlite3Worker1Promiser) under the hood.

- For VFS 'opfs': COOP/COEP headers are set and SharedArrayBuffer is available
- Your sqlite load strategy can load sqlite3Worker1Promiser (use sqlite.loadStrategy = 'npm' or 'cdn', or provide it globally)`}async tryCreateOpfsDatabase(e,t,n){if(n===`opfs`){if(e.oo1.OpfsDb)try{return console.log(`Creating OPFS-backed database (OpfsDb):`,t),this.db=new e.oo1.OpfsDb(t),this.workerDbId=void 0,this.activeStorageBackend=`opfs`,this.activeOpfsVfs=`opfs`,console.log(`Successfully created OPFS-backed database (OpfsDb)`),!0}catch(e){console.warn(`OPFS database creation via OpfsDb failed:`,e)}return await this.tryCreateWrappedWorkerOpfsDatabase(t,n)}if(await this.ensureSahpoolVfs(e))try{return console.log(`Creating SAHPool OPFS-backed database:`,t),this.db=new e.oo1.DB(t,`c`,`opfs-sahpool`),this.workerDbId=void 0,this.activeStorageBackend=`opfs`,this.activeOpfsVfs=`opfs-sahpool`,console.log(`Successfully created SAHPool OPFS-backed database`),!0}catch(e){console.warn(`SAHPool OPFS database creation failed:`,e)}return await this.tryCreateWrappedWorkerOpfsDatabase(t,n)}async ensureSahpoolVfs(e){if(globalThis.importScripts===void 0)return!1;let t=`opfs-sahpool`;try{if(e.capi.sqlite3_vfs_find?.(t))return!0}catch(e){console.warn(`SAHPool VFS lookup failed:`,e)}if(typeof e.installOpfsSAHPoolVfs!=`function`)return!1;try{await e.installOpfsSAHPoolVfs({name:t,directory:`/unisqlite-sahpool`})}catch(e){return console.warn(`SAHPool VFS installation failed:`,e),!1}try{return!!e.capi.sqlite3_vfs_find?.(t)}catch{return!0}}createWorkerFromConfig(){if(!this.config.workerUrl||typeof Worker>`u`)return;let e=typeof this.config.workerUrl==`string`?this.config.workerUrl:this.config.workerUrl.href;try{return new Worker(e,{type:`module`})}catch(e){console.warn(`Failed to create Worker from custom workerUrl:`,e);return}}createWorkerFromCdn(e){if(typeof Worker>`u`||typeof Blob>`u`||typeof URL>`u`)return;let t=this.config.cdnBaseUrl,n=this.config.version;if(!t||!n)return;let r=`${`${t}@${n}/sqlite-wasm/jswasm`}/sqlite3-bundler-friendly.mjs`,i=e.installSahpool?[` if (typeof sqlite3.installOpfsSAHPoolVfs === "function") {`,` await sqlite3.installOpfsSAHPoolVfs({ name: "opfs-sahpool", directory: "/unisqlite-sahpool" });`,` }`].join(`
- Your sqlite load strategy can load sqlite3Worker1Promiser (use sqlite.loadStrategy = 'npm' or 'cdn', or provide it globally)`}async tryCreateOpfsDatabase(e,t,n){if(n===`opfs`){if(e.oo1.OpfsDb)try{return l.log(`Creating OPFS-backed database (OpfsDb):`,t),this.db=new e.oo1.OpfsDb(t),this.workerDbId=void 0,this.activeStorageBackend=`opfs`,this.activeOpfsVfs=`opfs`,l.log(`Successfully created OPFS-backed database (OpfsDb)`),!0}catch(e){l.warn(`OPFS database creation via OpfsDb failed:`,e)}return await this.tryCreateWrappedWorkerOpfsDatabase(t,n)}if(await this.ensureSahpoolVfs(e))try{return l.log(`Creating SAHPool OPFS-backed database:`,t),this.db=new e.oo1.DB(t,`c`,`opfs-sahpool`),this.workerDbId=void 0,this.activeStorageBackend=`opfs`,this.activeOpfsVfs=`opfs-sahpool`,l.log(`Successfully created SAHPool OPFS-backed database`),!0}catch(e){l.warn(`SAHPool OPFS database creation failed:`,e)}return await this.tryCreateWrappedWorkerOpfsDatabase(t,n)}async ensureSahpoolVfs(e){if(globalThis.importScripts===void 0)return!1;let t=`opfs-sahpool`;try{if(e.capi.sqlite3_vfs_find?.(t))return!0}catch(e){l.warn(`SAHPool VFS lookup failed:`,e)}if(typeof e.installOpfsSAHPoolVfs!=`function`)return!1;try{await e.installOpfsSAHPoolVfs({name:t,directory:`/unisqlite-sahpool`})}catch(e){return l.warn(`SAHPool VFS installation failed:`,e),!1}try{return!!e.capi.sqlite3_vfs_find?.(t)}catch{return!0}}createWorkerFromConfig(){if(!this.config.workerUrl||typeof Worker>`u`)return;let e=typeof this.config.workerUrl==`string`?this.config.workerUrl:this.config.workerUrl.href;try{return new Worker(e,{type:`module`})}catch(e){l.warn(`Failed to create Worker from custom workerUrl:`,e);return}}createWorkerFromCdn(e){if(typeof Worker>`u`||typeof Blob>`u`||typeof URL>`u`)return;let t=this.config.cdnBaseUrl,n=this.config.version;if(!t||!n)return;let r=`${`${t}@${n}/sqlite-wasm/jswasm`}/sqlite3-bundler-friendly.mjs`,i=e.installSahpool?[` if (typeof sqlite3.installOpfsSAHPoolVfs === "function") {`,` await sqlite3.installOpfsSAHPoolVfs({ name: "opfs-sahpool", directory: "/unisqlite-sahpool" });`,` }`].join(`
`):``,a=[`import sqlite3InitModule from ${JSON.stringify(r)};`,`sqlite3InitModule().then(async (sqlite3) => {`,` try {`,i||` // no-op`,` } catch (e) {`,` console.warn("SAHPool VFS installation failed:", e);`,` }`,` sqlite3.initWorker1API();`,`});`,``].join(`
`),o=new Blob([a],{type:`text/javascript`}),s=URL.createObjectURL(o),c=new Worker(s,{type:`module`});return c.addEventListener(`message`,()=>{URL.revokeObjectURL(s)},{once:!0}),c.addEventListener(`error`,()=>{URL.revokeObjectURL(s)},{once:!0}),c}async getOrCreateWorkerPromiser(e){if(this.workerPromiser)return this.workerPromiser;if(this.workerPromiserInitPromise)return await this.workerPromiserInitPromise;let t=await this.loadSQLiteWorkerPromiserFactory(),n=this.config.storageBackend===`opfs`||this.config.opfsVfsType===`opfs`||this.config.opfsVfsType===`sahpool`,r=this.config.loadStrategy===`global`&&!n?5e3:2e4;this.workerPromiserInitPromise=new Promise((n,i)=>{let a=!1,o=setTimeout(()=>{a||(a=!0,i(Error(`SQLite worker initialization timed out after ${r}ms`)))},r),s=(e,t)=>{a||(a=!0,clearTimeout(o),e(t))},c=e=>{s(i,e instanceof Error?e:Error(String(e)))},l;try{l=t({...e?.worker?{worker:e.worker}:{},onready:e=>{if(typeof e==`function`){s(n,e);return}if(typeof l==`function`){s(n,l);return}if(l&&typeof l.then==`function`){l.then(e=>s(n,e),e=>c(e));return}c(Error(`sqlite3Worker1Promiser did not provide a usable promiser`))},onerror:e=>{let t=e instanceof Error?e.message:String(e);c(Error(`SQLite worker error: ${t}`))}}),l&&typeof l.then==`function`&&l.then(e=>s(n,e),e=>c(e))}catch(e){c(e)}});let i=await this.workerPromiserInitPromise;return this.workerPromiser=i,i}async tryCreateWrappedWorkerOpfsDatabase(e,t){try{let n=!this.workerPromiser&&!this.workerPromiserInitPromise?(()=>{let e=this.createWorkerFromConfig()??(t===`opfs-sahpool`?this.createWorkerFromCdn({installSahpool:!0}):this.createWorkerFromCdn({installSahpool:!1}));return e?{worker:e}:void 0})():void 0,r=await(await this.getOrCreateWorkerPromiser(n))(`open`,{filename:`file:${e}`,vfs:t}),i=r.dbId??r.result?.dbId;if(i===void 0)throw Error(`SQLite worker did not return a dbId`);if(typeof i!=`number`&&typeof i!=`string`)throw Error(`SQLite worker returned an invalid dbId (type=${typeof i})`);return this.db=void 0,this.workerDbId=i,this.activeStorageBackend=`opfs`,this.activeOpfsVfs=t,console.log(`Successfully created OPFS-backed database via wrapped worker (${t}):`,e),!0}catch(e){return console.warn(`Wrapped-worker OPFS database creation failed (vfs=${t}):`,e),!1}}},x=class{constructor(e,t,n){this.dbHost=e,this.hostElection=t,this.activeTxn=null,this.txnQueue=[],this.heartbeatTimers=new Map,this.txnPending=!1,this.rpcQueue=[],this.txnTimeoutMs=n?.txnTimeoutMs??3e4,this.opTimeoutMs=n?.opTimeoutMs??1e4,this.maxQueueSize=n?.maxQueueSize??10,this.heartbeatTimeoutMs=n?.heartbeatTimeoutMs??15e3}startWatchdog(){this.watchdogTimer||=setInterval(()=>{if(this.activeTxn){let e=Date.now()-this.activeTxn.lastActivityAt;e>this.txnTimeoutMs&&(o.warn(`Transaction ${this.activeTxn.txnId} timed out after ${e}ms, rolling back`),this.forceRollback())}let e=Date.now(),t=this.txnQueue.filter(t=>e-t.enqueuedAt>this.txnTimeoutMs);for(let e of t){let t=this.txnQueue.indexOf(e);t!==-1&&(this.txnQueue.splice(t,1),e.reject(Error(`Transaction queue wait timeout`)))}},5e3)}stopWatchdog(){this.watchdogTimer&&=(clearInterval(this.watchdogTimer),void 0)}getActiveTransaction(){return this.activeTxn}hasActiveTransaction(){return this.activeTxn!==null}isTransactionBlocking(){return this.activeTxn!==null||this.txnPending}async waitForTransactionSlot(){if(this.isTransactionBlocking())return new Promise((e,t)=>{this.rpcQueue.push({resolve:e,reject:t})})}async beginTransaction(e,t,n=`immediate`){if(this.activeTxn||this.txnPending){if(this.txnQueue.length>=this.maxQueueSize)throw Error(`Transaction queue full`);await new Promise((r,i)=>{this.txnQueue.push({txnId:e,originTabId:t,mode:n,resolve:r,reject:i,enqueuedAt:Date.now()})})}this.txnPending=!0;try{this.txnLockRelease=await this.hostElection.acquireTransactionLock();let r=n===`deferred`?`BEGIN`:n===`exclusive`?`BEGIN EXCLUSIVE`:`BEGIN IMMEDIATE`;await this.dbHost.execRaw(r),this.activeTxn={txnId:e,originTabId:t,startedAt:Date.now(),lastActivityAt:Date.now(),mode:n},this.resetHeartbeatTimer(e)}catch(e){throw this.txnLockRelease?.(),this.txnLockRelease=void 0,this.txnPending=!1,this.processQueue(),this.processRpcQueue(),e}finally{this.txnPending=!1}}async execInTransaction(e,t){return this.validateActiveTxn(e),this.activeTxn.lastActivityAt=Date.now(),this.resetHeartbeatTimer(e),await t()}recordHeartbeat(e){this.activeTxn?.txnId===e&&(this.activeTxn.lastActivityAt=Date.now(),this.resetHeartbeatTimer(e))}async commitTransaction(e){this.validateActiveTxn(e);try{await this.dbHost.execRaw(`COMMIT`)}finally{this.endTransaction()}}async rollbackTransaction(e){this.validateActiveTxn(e);try{await this.dbHost.execRaw(`ROLLBACK`)}finally{this.endTransaction()}}forceRollback(){if(this.activeTxn){try{this.dbHost.execRaw(`ROLLBACK`).catch(e=>{o.error(`Force rollback failed:`,e)})}catch(e){o.error(`Force rollback failed:`,e)}this.endTransaction()}}endTransaction(){if(this.activeTxn){let e=this.heartbeatTimers.get(this.activeTxn.txnId);e&&(clearTimeout(e),this.heartbeatTimers.delete(this.activeTxn.txnId)),this.activeTxn=null}this.txnLockRelease&&=(this.txnLockRelease(),void 0),this.processQueue(),this.processRpcQueue()}processQueue(){this.txnQueue.length>0&&!this.activeTxn&&!this.txnPending&&this.txnQueue.shift().resolve()}processRpcQueue(){if(this.activeTxn||this.txnPending)return;let e=this.rpcQueue;this.rpcQueue=[];for(let{resolve:t}of e)t()}resetHeartbeatTimer(e){let t=this.heartbeatTimers.get(e);t&&clearTimeout(t);let n=setTimeout(()=>{this.activeTxn?.txnId===e&&(o.warn(`No heartbeat for transaction ${e} in ${this.heartbeatTimeoutMs}ms, rolling back`),this.forceRollback())},this.heartbeatTimeoutMs);this.heartbeatTimers.set(e,n)}validateActiveTxn(e){if(!this.activeTxn)throw Error(`No active transaction (expected ${e})`);if(this.activeTxn.txnId!==e)throw Error(`Transaction ID mismatch: expected ${this.activeTxn.txnId}, got ${e}`);let t=Date.now()-this.activeTxn.lastActivityAt;if(t>this.txnTimeoutMs)throw this.forceRollback(),Error(`Transaction ${e} timed out after ${t}ms`)}async close(){this.stopWatchdog(),this.activeTxn&&this.forceRollback();for(let e of this.txnQueue)e.reject(Error(`Transaction session manager closed`));this.txnQueue=[];for(let e of this.rpcQueue)e.reject(Error(`Transaction session manager closed`));this.rpcQueue=[];for(let e of this.heartbeatTimers.values())clearTimeout(e);this.heartbeatTimers.clear()}},S=class{constructor(e,t,n=5e3){this.rpcChannel=e,this.txnId=t,this.heartbeatIntervalMs=n,this.committed=!1,this.rolledBack=!1,this.startHeartbeat()}startHeartbeat(){this.heartbeatInterval=setInterval(()=>{!this.committed&&!this.rolledBack&&this.rpcChannel.txnHeartbeat(this.txnId)},this.heartbeatIntervalMs)}stopHeartbeat(){this.heartbeatInterval&&=(clearInterval(this.heartbeatInterval),void 0)}ensureActive(){if(this.committed)throw Error(`Transaction already committed`);if(this.rolledBack)throw Error(`Transaction already rolled back`)}async query(e,t){return this.ensureActive(),(await this.rpcChannel.txnExec(this.txnId,`query`,{sql:e,params:t})).rows}async queryRaw(e,t){return this.ensureActive(),await this.rpcChannel.txnExec(this.txnId,`queryRaw`,{sql:e,params:t})}async run(e,t){this.ensureActive();let n=await this.rpcChannel.txnExec(this.txnId,`run`,{sql:e,params:t});return{rowsAffected:n.rowsAffected??0,lastInsertRowId:n.lastInsertRowId??0}}async exec(e){this.ensureActive(),await this.rpcChannel.txnExec(this.txnId,`exec`,{sql:e})}async transaction(e){this.ensureActive();let t=e(this);return t instanceof Promise?await t:t}async asyncTransaction(e,t){return this.ensureActive(),await e(this)}getConnectionType(){return`asyncTxn`}async close(){}async _commit(){this.ensureActive(),this.stopHeartbeat();try{await this.rpcChannel.txnCommit(this.txnId),this.committed=!0}catch(e){throw this.rolledBack=!0,e}}async _rollback(){if(!(this.committed||this.rolledBack)){this.stopHeartbeat();try{await this.rpcChannel.txnRollback(this.txnId)}finally{this.rolledBack=!0}}}isCommitted(){return this.committed}isRolledBack(){return this.rolledBack}},C=class{constructor(e,t){this.dbHost=e,this.isAsync=t}async query(e,t){return(await this.dbHost.executeSqlRaw(e,t)).rows}async queryRaw(e,t){return await this.dbHost.executeSqlRaw(e,t)}async run(e,t){let n=await this.dbHost.executeSqlRaw(e,t);return{rowsAffected:n.rowsAffected??0,lastInsertRowId:n.lastInsertRowId??0}}async exec(e){await this.dbHost.execRaw(e)}async transaction(e){let t=e(this);return t instanceof Promise?await t:t}async asyncTransaction(e){return await e(this)}getConnectionType(){return this.isAsync?`asyncTxn`:`syncTxn`}async close(){}},w=class e extends t.t{constructor(e){let t=e.path??e.name??`default`;super({...e,path:t}),this.dbHost=null,this.txnSessionManager=null,this.initialized=!1,this.closed=!1,this.options={...e,path:t},this.tabId=h(),this.sqliteConfig={loadStrategy:`global`,storageBackend:`auto`,opfsVfsType:`auto`,cdnBaseUrl:`https://cdn.jsdelivr.net/npm/@sqlite.org/sqlite-wasm`,version:`3.50.1-build1`,bundlerFriendly:!1,...e.sqlite},c.isSupported()||(s.warn(`Web Locks API not supported. Falling back to memory-only storage.`),this.sqliteConfig.storageBackend=`memory`),this.visibilityManager=new l,this.rpcChannel=new _(t,this.tabId),this.hostElection=new c({dbName:t,tabId:this.tabId,onBecomeHost:()=>this.becomeHost(),onLoseHost:()=>this.loseHost(),checkVisibility:()=>this.visibilityManager.isVisible()}),this.visibilityUnsubscribe=this.visibilityManager.onVisibilityChange(e=>{this.handleVisibilityChange(e)})}static async create(t){let n=new e(t);return await n.initialize(),n}getTabId(){return this.tabId}get isHost(){return this.hostElection.isHost}async initialize(){if(!this.initialized){if(this.initPromise)return this.initPromise;this.initPromise=this.doInitialize(),await this.initPromise,this.initialized=!0}}async doInitialize(){this.becomeHostPromise=new Promise(e=>{this.becomeHostResolver=e}),await this.hostElection.start();let e=new Promise(e=>{setTimeout(()=>e(`timeout`),500)});await Promise.race([this.becomeHostPromise.then(()=>`host`),e])===`host`||this.hostElection.isHost&&await this.becomeHostPromise}async becomeHost(){s.log(`Tab ${this.tabId} becoming Host for ${this.options.path}`),this.dbHost=await b.create({dbName:this.options.path,config:this.sqliteConfig}),this.txnSessionManager=new x(this.dbHost,this.hostElection),this.txnSessionManager.startWatchdog(),this.rpcChannel.setRequestHandler(this.handleRequest.bind(this)),this.becomeHostResolver&&=(this.becomeHostResolver(),void 0)}loseHost(){s.log(`Tab ${this.tabId} losing Host for ${this.options.path}`),this.rpcChannel.setRequestHandler(void 0),this.txnSessionManager&&=(this.txnSessionManager.close(),null),this.dbHost&&=(this.dbHost.close(),null)}handleVisibilityChange(e){e&&!this.hostElection.isHost&&!this.closed&&this.hostElection.start()}async handleRequest(e){if(!this.dbHost)throw Error(`Not Host`);switch(e.t){case`req`:return await this.handleRpcRequest(e);case`txn_begin`:return await this.handleTxnBegin(e);case`txn_exec`:return await this.handleTxnExec(e);case`txn_commit`:return await this.handleTxnCommit(e);case`txn_rollback`:return await this.handleTxnRollback(e);case`txn_heartbeat`:this.handleTxnHeartbeat(e);return;default:throw Error(`Unknown request type: ${e.t}`)}}async handleRpcRequest(e){let{op:t,payload:n}=e,{sql:r,params:i}=n;switch(this.txnSessionManager&&await this.txnSessionManager.waitForTransactionSlot(),t){case`query`:return{rows:await this.dbHost.query(r,i),columns:[]};case`queryRaw`:return await this.dbHost.queryRaw(r,i);case`run`:return await this.dbHost.run(r,i);case`exec`:return await this.dbHost.exec(r),null;default:throw Error(`Unknown RPC operation: ${String(t)}`)}}async handleTxnBegin(e){await this.txnSessionManager.beginTransaction(e.txnId,e.from,e.mode)}async handleTxnExec(e){let{txnId:t,op:n,payload:r}=e,{sql:i,params:a}=r;return await this.txnSessionManager.execInTransaction(t,async()=>{switch(n){case`query`:return{rows:await this.dbHost.query(i,a),columns:[]};case`queryRaw`:return await this.dbHost.queryRaw(i,a);case`run`:return await this.dbHost.run(i,a);case`exec`:return await this.dbHost.exec(i),null;default:throw Error(`Unknown transaction operation: ${String(n)}`)}})}async handleTxnCommit(e){await this.txnSessionManager.commitTransaction(e.txnId)}async handleTxnRollback(e){await this.txnSessionManager.rollbackTransaction(e.txnId)}handleTxnHeartbeat(e){this.txnSessionManager?.recordHeartbeat(e.txnId)}async query(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.dbHost.query(e,t):(await this.rpcChannel.request(`query`,{sql:e,params:t})).rows}async queryRaw(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.dbHost.queryRaw(e,t):await this.rpcChannel.request(`queryRaw`,{sql:e,params:t})}async run(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.dbHost.run(e,t):await this.rpcChannel.request(`run`,{sql:e,params:t})}async exec(e){if(await this.initialize(),this.isHost&&this.dbHost){await this.dbHost.exec(e);return}await this.rpcChannel.request(`exec`,{sql:e})}async transaction(e){return await this.initialize(),this.isHost&&this.dbHost?await this.executeLocalTransaction(e,!1):await this.executeRemoteTransaction(e)}async asyncTransaction(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.executeLocalAsyncTransaction(e,t):await this.executeRemoteTransaction(e,t)}getConnectionType(){return`direct`}async close(){this.closed||(this.closed=!0,this.visibilityUnsubscribe?.(),await this.hostElection.close(),this.rpcChannel.close(),this.visibilityManager.destroy(),this.txnSessionManager&&=(await this.txnSessionManager.close(),null),this.dbHost&&=(await this.dbHost.close(),null))}async executeLocalTransaction(e,t){await this.dbHost.execRaw(`BEGIN`);let n=new C(this.dbHost,t);try{let t=e(n),r=t instanceof Promise?await t:t;return await this.dbHost.execRaw(`COMMIT`),r}catch(e){try{await this.dbHost.execRaw(`ROLLBACK`)}catch(e){console.error(`Rollback failed:`,e)}throw e}}async executeLocalAsyncTransaction(e,t){let n=t?.timeoutMs??3e4;await this.dbHost.execRaw(`BEGIN IMMEDIATE`);let r=new C(this.dbHost,!0),i,a=!1;try{let t=new Promise((e,t)=>{i=setTimeout(()=>{a||t(Error(`Async transaction timeout after ${n}ms`))},n)}),o=await Promise.race([e(r),t]);return a=!0,i&&clearTimeout(i),await this.dbHost.execRaw(`COMMIT`),o}catch(e){a=!0,i&&clearTimeout(i);try{await this.dbHost.execRaw(`ROLLBACK`)}catch(e){console.error(`Rollback failed:`,e)}throw e}}async executeRemoteTransaction(e,t){let n=g(),r=t?.timeoutMs??3e4;await this.rpcChannel.txnBegin(n,`immediate`,r);let i=new S(this.rpcChannel,n),a,o=!1;try{let t=new Promise((e,t)=>{a=setTimeout(()=>{o||t(Error(`Remote transaction timeout after ${r}ms`))},r)}),n=e(i),s=n instanceof Promise?n:Promise.resolve(n),c=await Promise.race([s,t]);return o=!0,a&&clearTimeout(a),await i._commit(),c}catch(e){o=!0,a&&clearTimeout(a);try{await i._rollback()}catch(e){console.error(`Remote rollback failed:`,e)}throw e}}getSQLiteInfo(){let e=this.isHost?this.dbHost!==null:this.initialized&&!this.closed;return{config:this.sqliteConfig,isInitialized:this.initialized,isHost:this.isHost,isReady:e,tabId:this.tabId,hasDatabase:this.dbHost!==null,usesWorker:this.dbHost?.isWorkerDbActive()??!1,activeStorageBackend:this.dbHost?.getActiveStorageBackend()??`unknown`,activeOpfsVfs:this.dbHost?.getActiveOpfsVfs()}}getActiveStorageBackend(){return this.dbHost?.getActiveStorageBackend()??`unknown`}};Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return f}});
`),o=new Blob([a],{type:`text/javascript`}),s=URL.createObjectURL(o),c=new Worker(s,{type:`module`});return c.addEventListener(`message`,()=>{URL.revokeObjectURL(s)},{once:!0}),c.addEventListener(`error`,()=>{URL.revokeObjectURL(s)},{once:!0}),c}async getOrCreateWorkerPromiser(e){if(this.workerPromiser)return this.workerPromiser;if(this.workerPromiserInitPromise)return await this.workerPromiserInitPromise;let t=await this.loadSQLiteWorkerPromiserFactory(),n=this.config.storageBackend===`opfs`||this.config.opfsVfsType===`opfs`||this.config.opfsVfsType===`sahpool`,r=this.config.loadStrategy===`global`&&!n?5e3:2e4;this.workerPromiserInitPromise=new Promise((n,i)=>{let a=!1,o=setTimeout(()=>{a||(a=!0,i(Error(`SQLite worker initialization timed out after ${r}ms`)))},r),s=(e,t)=>{a||(a=!0,clearTimeout(o),e(t))},c=e=>{s(i,e instanceof Error?e:Error(String(e)))},l;try{l=t({...e?.worker?{worker:e.worker}:{},onready:e=>{if(typeof e==`function`){s(n,e);return}if(typeof l==`function`){s(n,l);return}if(l&&typeof l.then==`function`){l.then(e=>s(n,e),e=>c(e));return}c(Error(`sqlite3Worker1Promiser did not provide a usable promiser`))},onerror:e=>{let t=e instanceof Error?e.message:String(e);c(Error(`SQLite worker error: ${t}`))}}),l&&typeof l.then==`function`&&l.then(e=>s(n,e),e=>c(e))}catch(e){c(e)}});let i=await this.workerPromiserInitPromise;return this.workerPromiser=i,i}async tryCreateWrappedWorkerOpfsDatabase(e,t){try{let n=!this.workerPromiser&&!this.workerPromiserInitPromise?(()=>{let e=this.createWorkerFromConfig()??(t===`opfs-sahpool`?this.createWorkerFromCdn({installSahpool:!0}):this.createWorkerFromCdn({installSahpool:!1}));return e?{worker:e}:void 0})():void 0,r=await(await this.getOrCreateWorkerPromiser(n))(`open`,{filename:`file:${e}`,vfs:t}),i=r.dbId??r.result?.dbId;if(i===void 0)throw Error(`SQLite worker did not return a dbId`);if(typeof i!=`number`&&typeof i!=`string`)throw Error(`SQLite worker returned an invalid dbId (type=${typeof i})`);return this.db=void 0,this.workerDbId=i,this.activeStorageBackend=`opfs`,this.activeOpfsVfs=t,l.log(`Successfully created OPFS-backed database via wrapped worker (${t}):`,e),!0}catch(e){return l.warn(`Wrapped-worker OPFS database creation failed (vfs=${t}):`,e),!1}}},w=class{constructor(e,t,n){this.dbHost=e,this.hostElection=t,this.activeTxn=null,this.txnQueue=[],this.heartbeatTimers=new Map,this.txnPending=!1,this.rpcQueue=[],this.txnTimeoutMs=n?.txnTimeoutMs??3e4,this.opTimeoutMs=n?.opTimeoutMs??1e4,this.maxQueueSize=n?.maxQueueSize??10,this.heartbeatTimeoutMs=n?.heartbeatTimeoutMs??15e3}startWatchdog(){this.watchdogTimer||=setInterval(()=>{if(this.activeTxn){let e=Date.now()-this.activeTxn.lastActivityAt;e>this.txnTimeoutMs&&(s.warn(`Transaction ${this.activeTxn.txnId} timed out after ${e}ms, rolling back`),this.forceRollback())}let e=Date.now(),t=this.txnQueue.filter(t=>e-t.enqueuedAt>this.txnTimeoutMs);for(let e of t){let t=this.txnQueue.indexOf(e);t!==-1&&(this.txnQueue.splice(t,1),e.reject(Error(`Transaction queue wait timeout`)))}},5e3)}stopWatchdog(){this.watchdogTimer&&=(clearInterval(this.watchdogTimer),void 0)}getActiveTransaction(){return this.activeTxn}hasActiveTransaction(){return this.activeTxn!==null}isTransactionBlocking(){return this.activeTxn!==null||this.txnPending}async waitForTransactionSlot(){if(this.isTransactionBlocking())return new Promise((e,t)=>{this.rpcQueue.push({resolve:e,reject:t})})}async beginTransaction(e,t,n=`immediate`){if(this.activeTxn||this.txnPending){if(this.txnQueue.length>=this.maxQueueSize)throw Error(`Transaction queue full`);await new Promise((r,i)=>{this.txnQueue.push({txnId:e,originTabId:t,mode:n,resolve:r,reject:i,enqueuedAt:Date.now()})})}this.txnPending=!0;try{this.txnLockRelease=await this.hostElection.acquireTransactionLock();let r=n===`deferred`?`BEGIN`:n===`exclusive`?`BEGIN EXCLUSIVE`:`BEGIN IMMEDIATE`;await this.dbHost.execRaw(r),this.activeTxn={txnId:e,originTabId:t,startedAt:Date.now(),lastActivityAt:Date.now(),mode:n},this.resetHeartbeatTimer(e)}catch(e){throw this.txnLockRelease?.(),this.txnLockRelease=void 0,this.txnPending=!1,this.processQueue(),this.processRpcQueue(),e}finally{this.txnPending=!1}}async execInTransaction(e,t){return this.validateActiveTxn(e),this.activeTxn.lastActivityAt=Date.now(),this.resetHeartbeatTimer(e),await t()}recordHeartbeat(e){this.activeTxn?.txnId===e&&(this.activeTxn.lastActivityAt=Date.now(),this.resetHeartbeatTimer(e))}async commitTransaction(e){this.validateActiveTxn(e);try{await this.dbHost.execRaw(`COMMIT`)}finally{this.endTransaction()}}async rollbackTransaction(e){this.validateActiveTxn(e);try{await this.dbHost.execRaw(`ROLLBACK`)}finally{this.endTransaction()}}forceRollback(){if(this.activeTxn){try{this.dbHost.execRaw(`ROLLBACK`).catch(e=>{s.error(`Force rollback failed:`,e)})}catch(e){s.error(`Force rollback failed:`,e)}this.endTransaction()}}endTransaction(){if(this.activeTxn){let e=this.heartbeatTimers.get(this.activeTxn.txnId);e&&(clearTimeout(e),this.heartbeatTimers.delete(this.activeTxn.txnId)),this.activeTxn=null}this.txnLockRelease&&=(this.txnLockRelease(),void 0),this.processQueue(),this.processRpcQueue()}processQueue(){this.txnQueue.length>0&&!this.activeTxn&&!this.txnPending&&this.txnQueue.shift().resolve()}processRpcQueue(){if(this.activeTxn||this.txnPending)return;let e=this.rpcQueue;this.rpcQueue=[];for(let{resolve:t}of e)t()}resetHeartbeatTimer(e){let t=this.heartbeatTimers.get(e);t&&clearTimeout(t);let n=setTimeout(()=>{this.activeTxn?.txnId===e&&(s.warn(`No heartbeat for transaction ${e} in ${this.heartbeatTimeoutMs}ms, rolling back`),this.forceRollback())},this.heartbeatTimeoutMs);this.heartbeatTimers.set(e,n)}validateActiveTxn(e){if(!this.activeTxn)throw Error(`No active transaction (expected ${e})`);if(this.activeTxn.txnId!==e)throw Error(`Transaction ID mismatch: expected ${this.activeTxn.txnId}, got ${e}`);let t=Date.now()-this.activeTxn.lastActivityAt;if(t>this.txnTimeoutMs)throw this.forceRollback(),Error(`Transaction ${e} timed out after ${t}ms`)}async close(){this.stopWatchdog(),this.activeTxn&&this.forceRollback();for(let e of this.txnQueue)e.reject(Error(`Transaction session manager closed`));this.txnQueue=[];for(let e of this.rpcQueue)e.reject(Error(`Transaction session manager closed`));this.rpcQueue=[];for(let e of this.heartbeatTimers.values())clearTimeout(e);this.heartbeatTimers.clear()}},T=class{constructor(e,t,n=5e3){this.rpcChannel=e,this.txnId=t,this.heartbeatIntervalMs=n,this.committed=!1,this.rolledBack=!1,this.startHeartbeat()}startHeartbeat(){this.heartbeatInterval=setInterval(()=>{!this.committed&&!this.rolledBack&&this.rpcChannel.txnHeartbeat(this.txnId)},this.heartbeatIntervalMs)}stopHeartbeat(){this.heartbeatInterval&&=(clearInterval(this.heartbeatInterval),void 0)}ensureActive(){if(this.committed)throw Error(`Transaction already committed`);if(this.rolledBack)throw Error(`Transaction already rolled back`)}async query(e,t){return this.ensureActive(),(await this.rpcChannel.txnExec(this.txnId,`query`,{sql:e,params:t})).rows}async queryRaw(e,t){return this.ensureActive(),await this.rpcChannel.txnExec(this.txnId,`queryRaw`,{sql:e,params:t})}async run(e,t){this.ensureActive();let n=await this.rpcChannel.txnExec(this.txnId,`run`,{sql:e,params:t});return{rowsAffected:n.rowsAffected??0,lastInsertRowId:n.lastInsertRowId??0}}async exec(e){this.ensureActive(),await this.rpcChannel.txnExec(this.txnId,`exec`,{sql:e})}async transaction(e){this.ensureActive();let t=e(this);return t instanceof Promise?await t:t}async asyncTransaction(e,t){return this.ensureActive(),await e(this)}getConnectionType(){return`asyncTxn`}async close(){}async _commit(){this.ensureActive(),this.stopHeartbeat();try{await this.rpcChannel.txnCommit(this.txnId),this.committed=!0}catch(e){throw this.rolledBack=!0,e}}async _rollback(){if(!(this.committed||this.rolledBack)){this.stopHeartbeat();try{await this.rpcChannel.txnRollback(this.txnId)}finally{this.rolledBack=!0}}}isCommitted(){return this.committed}isRolledBack(){return this.rolledBack}},E=class{constructor(e,t){this.dbHost=e,this.isAsync=t}async query(e,t){return(await this.dbHost.executeSqlRaw(e,t)).rows}async queryRaw(e,t){return await this.dbHost.executeSqlRaw(e,t)}async run(e,t){let n=await this.dbHost.executeSqlRaw(e,t);return{rowsAffected:n.rowsAffected??0,lastInsertRowId:n.lastInsertRowId??0}}async exec(e){await this.dbHost.execRaw(e)}async transaction(e){let t=e(this);return t instanceof Promise?await t:t}async asyncTransaction(e){return await e(this)}getConnectionType(){return this.isAsync?`asyncTxn`:`syncTxn`}async close(){}},D=class e extends t.t{constructor(e){let t=e.path??e.name??`default`;super({...e,path:t}),this.dbHost=null,this.txnSessionManager=null,this.initialized=!1,this.closed=!1,this.options={...e,path:t},this.tabId=v(),this.sqliteConfig={loadStrategy:`global`,storageBackend:`auto`,opfsVfsType:`auto`,cdnBaseUrl:`https://cdn.jsdelivr.net/npm/@sqlite.org/sqlite-wasm`,version:`3.50.1-build1`,bundlerFriendly:!1,...e.sqlite},d.isSupported()||(c.warn(`Web Locks API not supported. Falling back to memory-only storage.`),this.sqliteConfig.storageBackend=`memory`),this.visibilityManager=new f,this.rpcChannel=new b(t,this.tabId),this.hostElection=new d({dbName:t,tabId:this.tabId,onBecomeHost:()=>this.becomeHost(),onLoseHost:()=>this.loseHost(),checkVisibility:()=>this.visibilityManager.isVisible()}),this.visibilityUnsubscribe=this.visibilityManager.onVisibilityChange(e=>{this.handleVisibilityChange(e)})}static async create(t){let n=new e(t);return await n.initialize(),n}getTabId(){return this.tabId}get isHost(){return this.hostElection.isHost}async initialize(){if(!this.initialized){if(this.initPromise)return this.initPromise;this.initPromise=this.doInitialize(),await this.initPromise,this.initialized=!0}}async doInitialize(){this.becomeHostPromise=new Promise(e=>{this.becomeHostResolver=e}),await this.hostElection.start();let e=new Promise(e=>{setTimeout(()=>e(`timeout`),500)});await Promise.race([this.becomeHostPromise.then(()=>`host`),e])===`host`||this.hostElection.isHost&&await this.becomeHostPromise}async becomeHost(){c.log(`Tab ${this.tabId} becoming Host for ${this.options.path}`),this.dbHost=await C.create({dbName:this.options.path,config:this.sqliteConfig}),this.txnSessionManager=new w(this.dbHost,this.hostElection),this.txnSessionManager.startWatchdog(),this.rpcChannel.setRequestHandler(this.handleRequest.bind(this)),this.becomeHostResolver&&=(this.becomeHostResolver(),void 0)}loseHost(){c.log(`Tab ${this.tabId} losing Host for ${this.options.path}`),this.rpcChannel.setRequestHandler(void 0),this.txnSessionManager&&=(this.txnSessionManager.close(),null),this.dbHost&&=(this.dbHost.close(),null)}handleVisibilityChange(e){e&&!this.hostElection.isHost&&!this.closed&&this.hostElection.start()}async handleRequest(e){if(!this.dbHost)throw Error(`Not Host`);switch(e.t){case`req`:return await this.handleRpcRequest(e);case`txn_begin`:return await this.handleTxnBegin(e);case`txn_exec`:return await this.handleTxnExec(e);case`txn_commit`:return await this.handleTxnCommit(e);case`txn_rollback`:return await this.handleTxnRollback(e);case`txn_heartbeat`:this.handleTxnHeartbeat(e);return;default:throw Error(`Unknown request type: ${e.t}`)}}async handleRpcRequest(e){let{op:t,payload:n}=e,{sql:r,params:i}=n;switch(this.txnSessionManager&&await this.txnSessionManager.waitForTransactionSlot(),t){case`query`:return{rows:await this.dbHost.query(r,i),columns:[]};case`queryRaw`:return await this.dbHost.queryRaw(r,i);case`run`:return await this.dbHost.run(r,i);case`exec`:return await this.dbHost.exec(r),null;default:throw Error(`Unknown RPC operation: ${String(t)}`)}}async handleTxnBegin(e){await this.txnSessionManager.beginTransaction(e.txnId,e.from,e.mode)}async handleTxnExec(e){let{txnId:t,op:n,payload:r}=e,{sql:i,params:a}=r;return await this.txnSessionManager.execInTransaction(t,async()=>{switch(n){case`query`:return{rows:await this.dbHost.query(i,a),columns:[]};case`queryRaw`:return await this.dbHost.queryRaw(i,a);case`run`:return await this.dbHost.run(i,a);case`exec`:return await this.dbHost.exec(i),null;default:throw Error(`Unknown transaction operation: ${String(n)}`)}})}async handleTxnCommit(e){await this.txnSessionManager.commitTransaction(e.txnId)}async handleTxnRollback(e){await this.txnSessionManager.rollbackTransaction(e.txnId)}handleTxnHeartbeat(e){this.txnSessionManager?.recordHeartbeat(e.txnId)}async query(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.dbHost.query(e,t):(await this.rpcChannel.request(`query`,{sql:e,params:t})).rows}async queryRaw(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.dbHost.queryRaw(e,t):await this.rpcChannel.request(`queryRaw`,{sql:e,params:t})}async run(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.dbHost.run(e,t):await this.rpcChannel.request(`run`,{sql:e,params:t})}async exec(e){if(await this.initialize(),this.isHost&&this.dbHost){await this.dbHost.exec(e);return}await this.rpcChannel.request(`exec`,{sql:e})}async transaction(e){return await this.initialize(),this.isHost&&this.dbHost?await this.executeLocalTransaction(e,!1):await this.executeRemoteTransaction(e)}async asyncTransaction(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.executeLocalAsyncTransaction(e,t):await this.executeRemoteTransaction(e,t)}getConnectionType(){return`direct`}async close(){this.closed||(this.closed=!0,this.visibilityUnsubscribe?.(),await this.hostElection.close(),this.rpcChannel.close(),this.visibilityManager.destroy(),this.txnSessionManager&&=(await this.txnSessionManager.close(),null),this.dbHost&&=(await this.dbHost.close(),null))}async executeLocalTransaction(e,t){await this.dbHost.execRaw(`BEGIN`);let n=new E(this.dbHost,t);try{let t=e(n),r=t instanceof Promise?await t:t;return await this.dbHost.execRaw(`COMMIT`),r}catch(e){try{await this.dbHost.execRaw(`ROLLBACK`)}catch(e){c.error(`Rollback failed:`,e)}throw e}}async executeLocalAsyncTransaction(e,t){let n=t?.timeoutMs??3e4;await this.dbHost.execRaw(`BEGIN IMMEDIATE`);let r=new E(this.dbHost,!0),i,a=!1;try{let t=new Promise((e,t)=>{i=setTimeout(()=>{a||t(Error(`Async transaction timeout after ${n}ms`))},n)}),o=await Promise.race([e(r),t]);return a=!0,i&&clearTimeout(i),await this.dbHost.execRaw(`COMMIT`),o}catch(e){a=!0,i&&clearTimeout(i);try{await this.dbHost.execRaw(`ROLLBACK`)}catch(e){c.error(`Rollback failed:`,e)}throw e}}async executeRemoteTransaction(e,t){let n=y(),r=t?.timeoutMs??3e4;await this.rpcChannel.txnBegin(n,`immediate`,r);let i=new T(this.rpcChannel,n),a,o=!1;try{let t=new Promise((e,t)=>{a=setTimeout(()=>{o||t(Error(`Remote transaction timeout after ${r}ms`))},r)}),n=e(i),s=n instanceof Promise?n:Promise.resolve(n),c=await Promise.race([s,t]);return o=!0,a&&clearTimeout(a),await i._commit(),c}catch(e){o=!0,a&&clearTimeout(a);try{await i._rollback()}catch(e){c.error(`Remote rollback failed:`,e)}throw e}}getSQLiteInfo(){let e=this.isHost?this.dbHost!==null:this.initialized&&!this.closed;return{config:this.sqliteConfig,isInitialized:this.initialized,isHost:this.isHost,isReady:e,tabId:this.tabId,hasDatabase:this.dbHost!==null,usesWorker:this.dbHost?.isWorkerDbActive()??!1,activeStorageBackend:this.dbHost?.getActiveStorageBackend()??`unknown`,activeOpfsVfs:this.dbHost?.getActiveOpfsVfs()}}getActiveStorageBackend(){return this.dbHost?.getActiveStorageBackend()??`unknown`}};Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return D}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return h}});
//# sourceMappingURL=browser2.cjs.map

@@ -1,8 +0,8 @@

import{t as e}from"./base.mjs";import t from"debug";const n=`unisqlite`;function r(e){let r=t(`${n}:${e}`),i=t(`${n}:${e}:warn`),a=t(`${n}:${e}:error`);return a.enabled=!0,{log:r,warn:i,error:a}}const i=r(`host`),a=r(`txn`),o=r(`adapter`);var s=class e{constructor(e){this.options=e,this.abortController=null,this._isHost=!1,this._isStarted=!1,this.releaseResolver=null,this.hostReadyResolver=null,this.hostReadyPromise=null,this.lockName=`sqlite:host:${e.dbName}`,this.txnLockName=`sqlite:txn:${e.dbName}`}static isSupported(){return typeof navigator<`u`&&navigator.locks!==void 0}get isHost(){return this._isHost}async start(){if(!this._isStarted){if(!e.isSupported()){i.warn(`Web Locks API not supported. Running in local-only mode.`),this._isStarted=!0,this._isHost=!0,this.options.onBecomeHost().catch(e=>{i.error(`Error in onBecomeHost callback:`,e),this._isHost=!1});return}this.options.checkVisibility&&!this.options.checkVisibility()||(this._isStarted=!0,this.hostReadyPromise=new Promise(e=>{this.hostReadyResolver=e}),this.tryAcquireHost().catch(e=>{i.error(`Error in host election:`,e)}))}}async waitForHost(){if(!this._isHost&&(this.hostReadyPromise||(await this.start(),this.hostReadyPromise)))return this.hostReadyPromise}async tryAcquireHost(){this.abortController=new AbortController;try{await navigator.locks.request(this.lockName,{mode:`exclusive`,signal:this.abortController.signal},async e=>{if(e){this._isHost=!0,i.log(`Tab ${this.options.tabId} became Host for ${this.options.dbName}`);try{await this.options.onBecomeHost()}catch(e){throw i.error(`Error in onBecomeHost callback:`,e),this._isHost=!1,e}this.hostReadyResolver&&(this.hostReadyResolver(),this.hostReadyResolver=null,this.hostReadyPromise=null),await new Promise(e=>{this.releaseResolver=e,this.abortController.signal.addEventListener(`abort`,()=>{e()})}),this._isHost=!1,this.releaseResolver=null,i.log(`Tab ${this.options.tabId} lost Host role for ${this.options.dbName}`);try{this.options.onLoseHost()}catch(e){i.error(`Error in onLoseHost callback:`,e)}}})}catch(e){if(e.name===`AbortError`)return;throw i.error(`Error acquiring Host lock:`,e),e}finally{this._isStarted=!1,this.abortController=null}}releaseHost(){this.releaseResolver&&=(this.releaseResolver(),null),this.abortController&&=(this.abortController.abort(),null)}async acquireTransactionLock(){if(!e.isSupported())return()=>{};let t=new AbortController,n=null,r=null,a=new Promise(e=>{r=e});return navigator.locks.request(this.txnLockName,{mode:`exclusive`,signal:t.signal},async e=>{e&&(r?.(),await new Promise(e=>{n=e}))}).catch(e=>{e.name!==`AbortError`&&i.error(`Error acquiring transaction lock:`,e),r?.()}),await a,()=>{n?n():t.abort()}}async hasTransactionLock(){if(!e.isSupported())return!1;try{return(await navigator.locks.query()).held?.some(e=>e.name===this.txnLockName)??!1}catch{return!1}}async close(){this.releaseHost()}},c=class{constructor(){this.listeners=new Set,this.boundHandler=this.handleVisibilityChange.bind(this),typeof document<`u`&&document.addEventListener(`visibilitychange`,this.boundHandler)}handleVisibilityChange(){let e=this.isVisible();this.listeners.forEach(t=>{try{t(e)}catch(e){console.error(`Error in visibility change listener:`,e)}})}isVisible(){return typeof document>`u`?!0:document.visibilityState===`visible`}onVisibilityChange(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}destroy(){typeof document<`u`&&document.removeEventListener(`visibilitychange`,this.boundHandler),this.listeners.clear()}};function l(e){return e instanceof Error?{name:e.name,message:e.message,stack:e.stack}:{name:`Error`,message:String(e)}}function u(e){let t=Error(e.message);return t.name=e.name,e.stack&&(t.stack=e.stack),t}function d(e){return e.t===`req`||e.t===`txn_begin`||e.t===`txn_exec`||e.t===`txn_commit`||e.t===`txn_rollback`||e.t===`txn_heartbeat`}function f(e){return e.t===`res`||e.t===`txn_ack`||e.t===`txn_result`||e.t===`txn_done`||e.t===`txn_error`}function p(){return crypto.randomUUID()}function m(){return crypto.randomUUID()}function h(){return crypto.randomUUID()}var g=class{constructor(e,t,n=3e4){this.dbName=e,this.tabId=t,this.defaultTimeoutMs=n,this.pending=new Map,this.closed=!1,this.channel=new BroadcastChannel(`sqlite:rpc:${e}`),this.channel.onmessage=this.handleMessage.bind(this)}handleMessage(e){if(this.closed)return;let t=e.data;!t||typeof t.t!=`string`||(f(t)?this.handleResponse(t):d(t)&&this.requestHandler&&`from`in t&&t.from!==this.tabId&&this.handleRequest(t))}handleResponse(e){if(`to`in e&&e.to!==this.tabId||!(`id`in e))return;let t=this.pending.get(e.id);if(t)switch(clearTimeout(t.timer),this.pending.delete(e.id),e.t){case`res`:e.ok?t.resolve(e.result):t.reject(u(e.error));break;case`txn_ack`:case`txn_done`:t.resolve(void 0);break;case`txn_result`:e.ok?t.resolve(e.result):t.reject(u(e.error));break;case`txn_error`:t.reject(u(e.error));break}}async handleRequest(e){if(this.requestHandler)try{let t=await this.requestHandler(e);this.sendResponse(e,t)}catch(t){this.sendErrorResponse(e,t)}}sendResponse(e,t){if(this.closed)return;let n=`from`in e?e.from:void 0,r=`id`in e?e.id:void 0;if(!(!n||!r))switch(e.t){case`req`:this.channel.postMessage({t:`res`,to:n,id:r,ok:!0,result:t});break;case`txn_begin`:this.channel.postMessage({t:`txn_ack`,to:n,id:r,txnId:e.txnId});break;case`txn_exec`:this.channel.postMessage({t:`txn_result`,to:n,id:r,txnId:e.txnId,ok:!0,result:t});break;case`txn_commit`:case`txn_rollback`:this.channel.postMessage({t:`txn_done`,to:n,id:r,txnId:e.txnId});break;case`txn_heartbeat`:break}}sendErrorResponse(e,t){if(this.closed)return;let n=`from`in e?e.from:void 0,r=`id`in e?e.id:void 0;if(!n||!r)return;let i=l(t);switch(e.t){case`req`:this.channel.postMessage({t:`res`,to:n,id:r,ok:!1,error:i});break;case`txn_begin`:case`txn_exec`:case`txn_commit`:case`txn_rollback`:this.channel.postMessage({t:`txn_error`,to:n,id:r,txnId:e.txnId,error:i});break}}setRequestHandler(e){this.requestHandler=e}async request(e,t,n){let r=p(),i=n??this.defaultTimeoutMs;return new Promise((n,a)=>{let o=setTimeout(()=>{this.pending.delete(r),a(Error(`RPC timeout after ${i}ms for ${e}`))},i);this.pending.set(r,{resolve:n,reject:a,timer:o}),this.channel.postMessage({t:`req`,from:this.tabId,id:r,op:e,payload:t})})}async txnBegin(e,t=`immediate`,n){let r=p(),i=n??this.defaultTimeoutMs;return new Promise((n,a)=>{let o=setTimeout(()=>{this.pending.delete(r),a(Error(`Transaction begin timeout after ${i}ms`))},i);this.pending.set(r,{resolve:n,reject:a,timer:o}),this.channel.postMessage({t:`txn_begin`,from:this.tabId,id:r,txnId:e,mode:t})})}async txnExec(e,t,n,r){let i=p(),a=r??1e4;return new Promise((r,o)=>{let s=setTimeout(()=>{this.pending.delete(i),o(Error(`Transaction SQL timeout after ${a}ms`))},a);this.pending.set(i,{resolve:r,reject:o,timer:s}),this.channel.postMessage({t:`txn_exec`,from:this.tabId,id:i,txnId:e,op:t,payload:n})})}async txnCommit(e,t){let n=p(),r=t??1e4;return new Promise((t,i)=>{let a=setTimeout(()=>{this.pending.delete(n),i(Error(`Transaction commit timeout after ${r}ms`))},r);this.pending.set(n,{resolve:t,reject:i,timer:a}),this.channel.postMessage({t:`txn_commit`,from:this.tabId,id:n,txnId:e})})}async txnRollback(e,t){let n=p(),r=t??1e4;return new Promise((t,i)=>{let a=setTimeout(()=>{this.pending.delete(n),i(Error(`Transaction rollback timeout after ${r}ms`))},r);this.pending.set(n,{resolve:t,reject:i,timer:a}),this.channel.postMessage({t:`txn_rollback`,from:this.tabId,id:n,txnId:e})})}txnHeartbeat(e){this.closed||this.channel.postMessage({t:`txn_heartbeat`,from:this.tabId,txnId:e})}close(){this.closed=!0,this.channel.close();for(let e of this.pending.values())clearTimeout(e.timer),e.reject(Error(`RPC channel closed`));this.pending.clear()}};const _=new Map,v=new Map;var y=class e{constructor(e,t){this.dbName=e,this.config=t,this.workerQueue=Promise.resolve(),this.activeStorageBackend=`memory`,this.closed=!1}static async create(t){let n=new e(t.dbName,t.config);return await n.initialize(),n}async initialize(){console.log(`Loading SQLite WASM using strategy: ${this.config.loadStrategy}`);let e=await this.loadSQLiteWasm(),t={print:console.log,printErr:console.error};if(this.config.locateFile)t.locateFile=this.config.locateFile;else if(typeof window<`u`){let e=window;e.sqlite3InitModuleState?.locateFile&&(t.locateFile=e.sqlite3InitModuleState.locateFile)}if(console.log(`Initializing SQLite WASM module...`),this.sqlite3=await e(t),!this.sqlite3)throw Error(`Failed to initialize SQLite WASM module`);let n=this.sqlite3;console.log(`SQLite WASM module initialized successfully`);let r=this.config.storageBackend??`auto`,i=this.dbName===`:memory:`?`:memory:`:`/unisqlite/${this.dbName}`;r===`memory`||this.dbName===`:memory:`?(console.log(`Using in-memory database`),this.db=new n.oo1.DB(`:memory:`),this.activeStorageBackend=`memory`):await this.tryCreatePersistentDatabase(n,i,r)||(console.log(`All persistent storage backends failed, using in-memory database`),this.db=new n.oo1.DB(`:memory:`),this.activeStorageBackend=`memory`);try{await this.execInternal(`PRAGMA journal_mode=WAL`),console.log(`Enabled WAL mode`)}catch(e){console.warn(`Could not enable WAL mode:`,e)}}async query(e,t){return(await this.executeSql(e,t)).rows}async queryRaw(e,t){return await this.executeSql(e,t)}async run(e,t){let n=await this.executeSql(e,t);return{rowsAffected:n.rowsAffected??0,lastInsertRowId:n.lastInsertRowId??0}}async exec(e){await this.execInternal(e)}async execRaw(e){await this.execInternal(e,{bypassQueue:!0})}async executeSqlRaw(e,t){return await this.executeSql(e,t,{bypassQueue:!0})}getActiveStorageBackend(){return this.activeStorageBackend}getActiveOpfsVfs(){return this.activeOpfsVfs}isWorkerDbActive(){return!!this.workerPromiser&&this.workerDbId!==void 0}async close(){if(!this.closed){if(this.closed=!0,this.workerPromiser){let e=this.workerPromiser,t=this.workerDbId;try{t!==void 0&&await this.enqueueWorker(async()=>{await e(`close`,{dbId:t})})}catch(e){console.warn(`Failed to close SQLite worker database:`,e)}finally{this.workerDbId=void 0;let t=e.worker;t?.terminate&&t.terminate(),this.workerPromiser=void 0}}this.db&&=(this.db.close(),void 0)}}enqueueWorker(e){let t=async()=>e(),n=this.workerQueue.then(t,t);return this.workerQueue=n.then(()=>void 0,()=>void 0),n}normalizeParams(e){if(!e)return;if(Array.isArray(e))return e;let t=Object.keys(e),n=e;return t.map(e=>n[e])}async execInternal(e,t){if(this.isWorkerDbActive()){let n=async()=>{if(!this.workerPromiser||this.workerDbId===void 0)throw Error(`Database not initialized`);await this.workerPromiser(`exec`,{dbId:this.workerDbId,sql:e})};t?.bypassQueue?await n():await this.enqueueWorker(n);return}if(!this.db)throw Error(`Database not initialized`);this.db.exec(e)}async executeSql(e,t,n){try{if(this.isWorkerDbActive()){let r=async()=>{if(!this.workerPromiser||this.workerDbId===void 0)throw Error(`Database not initialized`);let n=this.normalizeParams(t),r={dbId:this.workerDbId,sql:e,rowMode:`object`,resultRows:[],columnNames:[],countChanges:!0};n&&(r.bind=n);let i=await this.workerPromiser(`exec`,r),a=i.result??i,o=Array.isArray(a.resultRows)?a.resultRows:[],s=Array.isArray(a.columnNames)?a.columnNames:[],c=typeof a.changeCount==`number`?a.changeCount:0,l={dbId:this.workerDbId,sql:`SELECT last_insert_rowid() AS lastInsertRowId`,rowMode:`object`,resultRows:[],columnNames:[]},u=await this.workerPromiser(`exec`,l),d=u.result??u,f=Array.isArray(d.resultRows)?d.resultRows:[];return{rows:o,columns:s,rowsAffected:c,lastInsertRowId:Number(f[0]?.lastInsertRowId??0)}};return n?.bypassQueue?await r():await this.enqueueWorker(r)}if(!this.db||!this.sqlite3)throw Error(`Database not initialized`);let r=this.normalizeParams(t),i=[],a=[],o=this.db.prepare(e);try{let e=o;r&&o.bind(r);let t=typeof e.getColumnCount==`function`?e.getColumnCount():typeof e.columnCount==`number`?e.columnCount:0;if(t>0)if(typeof e.getColumnNames==`function`)a=e.getColumnNames();else for(let e=0;e<t;e++)a.push(o.getColumnName(e));for(;o.step();){let e={};for(let n=0;n<t;n++)e[a[n]]=o.get(n);i.push(e)}return{rows:i,columns:a,rowsAffected:this.db.changes(),lastInsertRowId:Number(this.sqlite3.capi.sqlite3_last_insert_rowid(this.db.pointer)||0)}}finally{o.finalize()}}catch(e){let t=e instanceof Error?e.message:String(e),n=Error(`SQLite error: ${t}`);throw e instanceof Error&&(n.cause=e),n}}async loadSQLiteWasm(){let e=`${this.config.loadStrategy}-${this.config.wasmUrl||this.config.cdnBaseUrl}-${this.config.version}`;if(_.has(e))return _.get(e);let t=this.loadSQLiteWasmInternal();return _.set(e,t),t}async loadSQLiteWasmInternal(){let{loadStrategy:e,wasmUrl:t,cdnBaseUrl:n,version:r,bundlerFriendly:i}=this.config;switch(e){case`npm`:return await this.loadFromNpm();case`cdn`:return await this.loadFromCdn(n,r,i);case`url`:if(!t)throw Error(`wasmUrl must be provided when using 'url' loading strategy`);return await this.loadFromUrl(t);case`module`:return await this.loadAsModule();case`global`:default:return this.loadFromGlobal()}}async loadFromNpm(){try{let e=await import(`@sqlite.org/sqlite-wasm`);return e.default||e}catch(e){return console.warn(`Failed to load SQLite WASM from npm, falling back to CDN:`,e),this.loadFromCdn(this.config.cdnBaseUrl,this.config.version,this.config.bundlerFriendly)}}async loadFromCdn(e,t,n){let r=n?`sqlite3-bundler-friendly.mjs`:`index.mjs`,i=[`https://cdn.jsdelivr.net/npm/@sqlite.org/sqlite-wasm@${t}/${r}`,`https://cdn.jsdelivr.net/npm/@sqlite.org/sqlite-wasm@${t}/dist/${r}`],a;for(let e of i)try{console.log(`Trying to load SQLite WASM from: ${e}`);let t=await import(e);return console.log(`Successfully loaded SQLite WASM from: ${e}`),t.default||t}catch(t){a=t,console.warn(`Failed to load SQLite WASM from ${e}:`,t)}let o=a instanceof Error?a.message:String(a);throw Error(`Failed to load SQLite WASM from any CDN source. Last error: ${o}`)}async loadFromUrl(e){let t=await import(e);return t.default||t.sqlite3InitModule}async loadAsModule(){if(globalThis.importScripts!==void 0)throw Error(`ES6 module loading not supported in Web Worker context`);for(let e of[`./sqlite3.mjs`,`./sqlite3-bundler-friendly.mjs`,`/sqlite3.mjs`])try{let t=await import(e);return t.default||t.sqlite3InitModule}catch(t){console.warn(`Failed to load SQLite WASM from ${e}:`,t)}throw Error(`Could not load SQLite WASM as ES6 module from any known path`)}loadFromGlobal(){if(typeof window<`u`){let e=window;if(e.sqlite3InitModule)return e.sqlite3InitModule}throw Error(`SQLite WASM module not found globally. Please:
import{t as e}from"./base.mjs";import t from"debug";const n=`unisqlite`;function r(e){let r=t(`${n}:${e}`),i=t(`${n}:${e}:warn`),a=t(`${n}:${e}:error`);return a.enabled=!0,{log:r,warn:i,error:a}}const i=r(`host`),a=r(`txn`),o=r(`adapter`),s=r(`wasm`),c=r(`visibility`);var l=class e{constructor(e){this.options=e,this.abortController=null,this._isHost=!1,this._isStarted=!1,this.releaseResolver=null,this.hostReadyResolver=null,this.hostReadyPromise=null,this.lockName=`sqlite:host:${e.dbName}`,this.txnLockName=`sqlite:txn:${e.dbName}`}static isSupported(){return typeof navigator<`u`&&navigator.locks!==void 0}get isHost(){return this._isHost}async start(){if(!this._isStarted){if(!e.isSupported()){i.warn(`Web Locks API not supported. Running in local-only mode.`),this._isStarted=!0,this._isHost=!0,this.options.onBecomeHost().catch(e=>{i.error(`Error in onBecomeHost callback:`,e),this._isHost=!1});return}this.options.checkVisibility&&!this.options.checkVisibility()||(this._isStarted=!0,this.hostReadyPromise=new Promise(e=>{this.hostReadyResolver=e}),this.tryAcquireHost().catch(e=>{i.error(`Error in host election:`,e)}))}}async waitForHost(){if(!this._isHost&&(this.hostReadyPromise||(await this.start(),this.hostReadyPromise)))return this.hostReadyPromise}async tryAcquireHost(){this.abortController=new AbortController;try{await navigator.locks.request(this.lockName,{mode:`exclusive`,signal:this.abortController.signal},async e=>{if(e){this._isHost=!0,i.log(`Tab ${this.options.tabId} became Host for ${this.options.dbName}`);try{await this.options.onBecomeHost()}catch(e){throw i.error(`Error in onBecomeHost callback:`,e),this._isHost=!1,e}this.hostReadyResolver&&(this.hostReadyResolver(),this.hostReadyResolver=null,this.hostReadyPromise=null),await new Promise(e=>{this.releaseResolver=e,this.abortController.signal.addEventListener(`abort`,()=>{e()})}),this._isHost=!1,this.releaseResolver=null,i.log(`Tab ${this.options.tabId} lost Host role for ${this.options.dbName}`);try{this.options.onLoseHost()}catch(e){i.error(`Error in onLoseHost callback:`,e)}}})}catch(e){if(e.name===`AbortError`)return;throw i.error(`Error acquiring Host lock:`,e),e}finally{this._isStarted=!1,this.abortController=null}}releaseHost(){this.releaseResolver&&=(this.releaseResolver(),null),this.abortController&&=(this.abortController.abort(),null)}async acquireTransactionLock(){if(!e.isSupported())return()=>{};let t=new AbortController,n=null,r=null,a=new Promise(e=>{r=e});return navigator.locks.request(this.txnLockName,{mode:`exclusive`,signal:t.signal},async e=>{e&&(r?.(),await new Promise(e=>{n=e}))}).catch(e=>{e.name!==`AbortError`&&i.error(`Error acquiring transaction lock:`,e),r?.()}),await a,()=>{n?n():t.abort()}}async hasTransactionLock(){if(!e.isSupported())return!1;try{return(await navigator.locks.query()).held?.some(e=>e.name===this.txnLockName)??!1}catch{return!1}}async close(){this.releaseHost()}},u=class{constructor(){this.listeners=new Set,this.boundHandler=this.handleVisibilityChange.bind(this),typeof document<`u`&&document.addEventListener(`visibilitychange`,this.boundHandler)}handleVisibilityChange(){let e=this.isVisible();this.listeners.forEach(t=>{try{t(e)}catch(e){c.error(`Error in visibility change listener:`,e)}})}isVisible(){return typeof document>`u`?!0:document.visibilityState===`visible`}onVisibilityChange(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}destroy(){typeof document<`u`&&document.removeEventListener(`visibilitychange`,this.boundHandler),this.listeners.clear()}};function d(e){return e instanceof Error?{name:e.name,message:e.message,stack:e.stack}:{name:`Error`,message:String(e)}}function f(e){let t=Error(e.message);return t.name=e.name,e.stack&&(t.stack=e.stack),t}function p(e){return e.t===`req`||e.t===`txn_begin`||e.t===`txn_exec`||e.t===`txn_commit`||e.t===`txn_rollback`||e.t===`txn_heartbeat`}function m(e){return e.t===`res`||e.t===`txn_ack`||e.t===`txn_result`||e.t===`txn_done`||e.t===`txn_error`}function h(){return crypto.randomUUID()}function g(){return crypto.randomUUID()}function _(){return crypto.randomUUID()}var v=class{constructor(e,t,n=3e4){this.dbName=e,this.tabId=t,this.defaultTimeoutMs=n,this.pending=new Map,this.closed=!1,this.channel=new BroadcastChannel(`sqlite:rpc:${e}`),this.channel.onmessage=this.handleMessage.bind(this)}handleMessage(e){if(this.closed)return;let t=e.data;!t||typeof t.t!=`string`||(m(t)?this.handleResponse(t):p(t)&&this.requestHandler&&`from`in t&&t.from!==this.tabId&&this.handleRequest(t))}handleResponse(e){if(`to`in e&&e.to!==this.tabId||!(`id`in e))return;let t=this.pending.get(e.id);if(t)switch(clearTimeout(t.timer),this.pending.delete(e.id),e.t){case`res`:e.ok?t.resolve(e.result):t.reject(f(e.error));break;case`txn_ack`:case`txn_done`:t.resolve(void 0);break;case`txn_result`:e.ok?t.resolve(e.result):t.reject(f(e.error));break;case`txn_error`:t.reject(f(e.error));break}}async handleRequest(e){if(this.requestHandler)try{let t=await this.requestHandler(e);this.sendResponse(e,t)}catch(t){this.sendErrorResponse(e,t)}}sendResponse(e,t){if(this.closed)return;let n=`from`in e?e.from:void 0,r=`id`in e?e.id:void 0;if(!(!n||!r))switch(e.t){case`req`:this.channel.postMessage({t:`res`,to:n,id:r,ok:!0,result:t});break;case`txn_begin`:this.channel.postMessage({t:`txn_ack`,to:n,id:r,txnId:e.txnId});break;case`txn_exec`:this.channel.postMessage({t:`txn_result`,to:n,id:r,txnId:e.txnId,ok:!0,result:t});break;case`txn_commit`:case`txn_rollback`:this.channel.postMessage({t:`txn_done`,to:n,id:r,txnId:e.txnId});break;case`txn_heartbeat`:break}}sendErrorResponse(e,t){if(this.closed)return;let n=`from`in e?e.from:void 0,r=`id`in e?e.id:void 0;if(!n||!r)return;let i=d(t);switch(e.t){case`req`:this.channel.postMessage({t:`res`,to:n,id:r,ok:!1,error:i});break;case`txn_begin`:case`txn_exec`:case`txn_commit`:case`txn_rollback`:this.channel.postMessage({t:`txn_error`,to:n,id:r,txnId:e.txnId,error:i});break}}setRequestHandler(e){this.requestHandler=e}async request(e,t,n){let r=h(),i=n??this.defaultTimeoutMs;return new Promise((n,a)=>{let o=setTimeout(()=>{this.pending.delete(r),a(Error(`RPC timeout after ${i}ms for ${e}`))},i);this.pending.set(r,{resolve:n,reject:a,timer:o}),this.channel.postMessage({t:`req`,from:this.tabId,id:r,op:e,payload:t})})}async txnBegin(e,t=`immediate`,n){let r=h(),i=n??this.defaultTimeoutMs;return new Promise((n,a)=>{let o=setTimeout(()=>{this.pending.delete(r),a(Error(`Transaction begin timeout after ${i}ms`))},i);this.pending.set(r,{resolve:n,reject:a,timer:o}),this.channel.postMessage({t:`txn_begin`,from:this.tabId,id:r,txnId:e,mode:t})})}async txnExec(e,t,n,r){let i=h(),a=r??1e4;return new Promise((r,o)=>{let s=setTimeout(()=>{this.pending.delete(i),o(Error(`Transaction SQL timeout after ${a}ms`))},a);this.pending.set(i,{resolve:r,reject:o,timer:s}),this.channel.postMessage({t:`txn_exec`,from:this.tabId,id:i,txnId:e,op:t,payload:n})})}async txnCommit(e,t){let n=h(),r=t??1e4;return new Promise((t,i)=>{let a=setTimeout(()=>{this.pending.delete(n),i(Error(`Transaction commit timeout after ${r}ms`))},r);this.pending.set(n,{resolve:t,reject:i,timer:a}),this.channel.postMessage({t:`txn_commit`,from:this.tabId,id:n,txnId:e})})}async txnRollback(e,t){let n=h(),r=t??1e4;return new Promise((t,i)=>{let a=setTimeout(()=>{this.pending.delete(n),i(Error(`Transaction rollback timeout after ${r}ms`))},r);this.pending.set(n,{resolve:t,reject:i,timer:a}),this.channel.postMessage({t:`txn_rollback`,from:this.tabId,id:n,txnId:e})})}txnHeartbeat(e){this.closed||this.channel.postMessage({t:`txn_heartbeat`,from:this.tabId,txnId:e})}close(){this.closed=!0,this.channel.close();for(let e of this.pending.values())clearTimeout(e.timer),e.reject(Error(`RPC channel closed`));this.pending.clear()}};const y=new Map,b=new Map;var x=class e{constructor(e,t){this.dbName=e,this.config=t,this.workerQueue=Promise.resolve(),this.activeStorageBackend=`memory`,this.closed=!1}static async create(t){let n=new e(t.dbName,t.config);return await n.initialize(),n}async initialize(){s.log(`UniSQLite v0.4.0 - Loading SQLite WASM using strategy: ${this.config.loadStrategy}`);let e=await this.loadSQLiteWasm(),t={print:(...e)=>s.log(...e),printErr:(...e)=>s.error(...e)};if(this.config.locateFile)t.locateFile=this.config.locateFile;else if(typeof window<`u`){let e=window;e.sqlite3InitModuleState?.locateFile&&(t.locateFile=e.sqlite3InitModuleState.locateFile)}if(s.log(`Initializing SQLite WASM module...`),this.sqlite3=await e(t),!this.sqlite3)throw Error(`Failed to initialize SQLite WASM module`);let n=this.sqlite3;s.log(`SQLite WASM module initialized successfully`);let r=this.config.storageBackend??`auto`,i=this.dbName===`:memory:`?`:memory:`:`/unisqlite/${this.dbName}`;r===`memory`||this.dbName===`:memory:`?(s.log(`Using in-memory database`),this.db=new n.oo1.DB(`:memory:`),this.activeStorageBackend=`memory`):await this.tryCreatePersistentDatabase(n,i,r)||(s.log(`All persistent storage backends failed, using in-memory database`),this.db=new n.oo1.DB(`:memory:`),this.activeStorageBackend=`memory`);try{await this.execInternal(`PRAGMA journal_mode=WAL`),s.log(`Enabled WAL mode`)}catch(e){s.warn(`Could not enable WAL mode:`,e)}}async query(e,t){return(await this.executeSql(e,t)).rows}async queryRaw(e,t){return await this.executeSql(e,t)}async run(e,t){let n=await this.executeSql(e,t);return{rowsAffected:n.rowsAffected??0,lastInsertRowId:n.lastInsertRowId??0}}async exec(e){await this.execInternal(e)}async execRaw(e){await this.execInternal(e,{bypassQueue:!0})}async executeSqlRaw(e,t){return await this.executeSql(e,t,{bypassQueue:!0})}getActiveStorageBackend(){return this.activeStorageBackend}getActiveOpfsVfs(){return this.activeOpfsVfs}isWorkerDbActive(){return!!this.workerPromiser&&this.workerDbId!==void 0}async close(){if(!this.closed){if(this.closed=!0,this.workerPromiser){let e=this.workerPromiser,t=this.workerDbId;try{t!==void 0&&await this.enqueueWorker(async()=>{await e(`close`,{dbId:t})})}catch(e){s.warn(`Failed to close SQLite worker database:`,e)}finally{this.workerDbId=void 0;let t=e.worker;t?.terminate&&t.terminate(),this.workerPromiser=void 0}}this.db&&=(this.db.close(),void 0)}}enqueueWorker(e){let t=async()=>e(),n=this.workerQueue.then(t,t);return this.workerQueue=n.then(()=>void 0,()=>void 0),n}normalizeParams(e){if(!e)return;if(Array.isArray(e))return e;let t=Object.keys(e),n=e;return t.map(e=>n[e])}async execInternal(e,t){if(this.isWorkerDbActive()){let n=async()=>{if(!this.workerPromiser||this.workerDbId===void 0)throw Error(`Database not initialized`);await this.workerPromiser(`exec`,{dbId:this.workerDbId,sql:e})};t?.bypassQueue?await n():await this.enqueueWorker(n);return}if(!this.db)throw Error(`Database not initialized`);this.db.exec(e)}async executeSql(e,t,n){try{if(this.isWorkerDbActive()){let r=async()=>{if(!this.workerPromiser||this.workerDbId===void 0)throw Error(`Database not initialized`);let n=this.normalizeParams(t),r={dbId:this.workerDbId,sql:e,rowMode:`object`,resultRows:[],columnNames:[],countChanges:!0};n&&(r.bind=n);let i=await this.workerPromiser(`exec`,r),a=i.result??i,o=Array.isArray(a.resultRows)?a.resultRows:[],s=Array.isArray(a.columnNames)?a.columnNames:[],c=typeof a.changeCount==`number`?a.changeCount:0,l={dbId:this.workerDbId,sql:`SELECT last_insert_rowid() AS lastInsertRowId`,rowMode:`object`,resultRows:[],columnNames:[]},u=await this.workerPromiser(`exec`,l),d=u.result??u,f=Array.isArray(d.resultRows)?d.resultRows:[];return{rows:o,columns:s,rowsAffected:c,lastInsertRowId:Number(f[0]?.lastInsertRowId??0)}};return n?.bypassQueue?await r():await this.enqueueWorker(r)}if(!this.db||!this.sqlite3)throw Error(`Database not initialized`);let r=this.normalizeParams(t),i=[],a=[],o=this.db.prepare(e);try{let e=o;r&&o.bind(r);let t=typeof e.getColumnCount==`function`?e.getColumnCount():typeof e.columnCount==`number`?e.columnCount:0;if(t>0)if(typeof e.getColumnNames==`function`)a=e.getColumnNames();else for(let e=0;e<t;e++)a.push(o.getColumnName(e));for(;o.step();){let e={};for(let n=0;n<t;n++)e[a[n]]=o.get(n);i.push(e)}return{rows:i,columns:a,rowsAffected:this.db.changes(),lastInsertRowId:Number(this.sqlite3.capi.sqlite3_last_insert_rowid(this.db.pointer)||0)}}finally{o.finalize()}}catch(e){let t=e instanceof Error?e.message:String(e),n=Error(`SQLite error: ${t}`);throw e instanceof Error&&(n.cause=e),n}}async loadSQLiteWasm(){let e=`${this.config.loadStrategy}-${this.config.wasmUrl||this.config.cdnBaseUrl}-${this.config.version}`;if(y.has(e))return y.get(e);let t=this.loadSQLiteWasmInternal();return y.set(e,t),t}async loadSQLiteWasmInternal(){let{loadStrategy:e,wasmUrl:t,cdnBaseUrl:n,version:r,bundlerFriendly:i}=this.config;switch(e){case`npm`:return await this.loadFromNpm();case`cdn`:return await this.loadFromCdn(n,r,i);case`url`:if(!t)throw Error(`wasmUrl must be provided when using 'url' loading strategy`);return await this.loadFromUrl(t);case`module`:return await this.loadAsModule();case`global`:default:return this.loadFromGlobal()}}async loadFromNpm(){try{let e=await import(`@sqlite.org/sqlite-wasm`);return e.default||e}catch(e){return s.warn(`Failed to load SQLite WASM from npm, falling back to CDN:`,e),this.loadFromCdn(this.config.cdnBaseUrl,this.config.version,this.config.bundlerFriendly)}}async loadFromCdn(e,t,n){let r=n?`sqlite3-bundler-friendly.mjs`:`index.mjs`,i=[`https://cdn.jsdelivr.net/npm/@sqlite.org/sqlite-wasm@${t}/${r}`,`https://cdn.jsdelivr.net/npm/@sqlite.org/sqlite-wasm@${t}/dist/${r}`],a;for(let e of i)try{s.log(`Trying to load SQLite WASM from: ${e}`);let t=await import(e);return s.log(`Successfully loaded SQLite WASM from: ${e}`),t.default||t}catch(t){a=t,s.warn(`Failed to load SQLite WASM from ${e}:`,t)}let o=a instanceof Error?a.message:String(a);throw Error(`Failed to load SQLite WASM from any CDN source. Last error: ${o}`)}async loadFromUrl(e){let t=await import(e);return t.default||t.sqlite3InitModule}async loadAsModule(){if(globalThis.importScripts!==void 0)throw Error(`ES6 module loading not supported in Web Worker context`);for(let e of[`./sqlite3.mjs`,`./sqlite3-bundler-friendly.mjs`,`/sqlite3.mjs`])try{let t=await import(e);return t.default||t.sqlite3InitModule}catch(t){s.warn(`Failed to load SQLite WASM from ${e}:`,t)}throw Error(`Could not load SQLite WASM as ES6 module from any known path`)}loadFromGlobal(){if(typeof window<`u`){let e=window;if(e.sqlite3InitModule)return e.sqlite3InitModule}throw Error(`SQLite WASM module not found globally. Please:
1. Install via npm: npm install @sqlite.org/sqlite-wasm
2. Or set loadStrategy to 'cdn' for automatic CDN loading
3. Or include SQLite WASM script in your HTML before using UniSqlite`)}async loadSQLiteWorkerPromiserFactory(){let e=`worker-${this.config.loadStrategy}-${this.config.wasmUrl||this.config.cdnBaseUrl}-${this.config.version}`;if(v.has(e))return v.get(e);let t=this.loadSQLiteWorkerPromiserFactoryInternal();return v.set(e,t),t}async loadSQLiteWorkerPromiserFactoryInternal(){let{loadStrategy:e,wasmUrl:t,cdnBaseUrl:n,version:r,bundlerFriendly:i}=this.config;switch(e){case`npm`:return await this.loadWorkerPromiserFromNpm();case`cdn`:return await this.loadWorkerPromiserFromCdn(n,r,i);case`url`:if(!t)throw Error(`wasmUrl must be provided when using 'url' loading strategy`);return await this.loadWorkerPromiserFromUrl(t);case`module`:return await this.loadWorkerPromiserAsModule();case`global`:default:return this.loadWorkerPromiserFromGlobal()}}async loadWorkerPromiserFromNpm(){try{let e=(await import(`@sqlite.org/sqlite-wasm`)).sqlite3Worker1Promiser;if(typeof e==`function`)return e;throw Error(`sqlite3Worker1Promiser export not found`)}catch(e){return console.warn(`Failed to load SQLite WASM worker promiser from npm, falling back to CDN:`,e),this.loadWorkerPromiserFromCdn(this.config.cdnBaseUrl,this.config.version,this.config.bundlerFriendly)}}async loadWorkerPromiserFromCdn(e,t,n){let r=n?`sqlite3-bundler-friendly.mjs`:`index.mjs`,i=[`${e}@${t}/${r}`,`${e}@${t}/dist/${r}`],a;for(let e of i)try{console.log(`Trying to load SQLite WASM worker promiser from: ${e}`);let t=(await import(e)).sqlite3Worker1Promiser;if(typeof t==`function`)return console.log(`Successfully loaded SQLite WASM worker promiser from: ${e}`),t;throw Error(`sqlite3Worker1Promiser export not found`)}catch(t){a=t,console.warn(`Failed to load SQLite WASM worker promiser from ${e}:`,t)}let o=a instanceof Error?a.message:String(a);throw Error(`Failed to load sqlite3Worker1Promiser from any CDN source. Last error: ${o}`)}async loadWorkerPromiserFromUrl(e){let t=(await import(e)).sqlite3Worker1Promiser;if(typeof t!=`function`)throw Error(`sqlite3Worker1Promiser export not found in module loaded from ${e}`);return t}async loadWorkerPromiserAsModule(){if(globalThis.importScripts!==void 0)throw Error(`ES6 module loading not supported in Web Worker context`);for(let e of[`./sqlite3.mjs`,`./sqlite3-bundler-friendly.mjs`,`/sqlite3.mjs`])try{let t=(await import(e)).sqlite3Worker1Promiser;if(typeof t==`function`)return t}catch(t){console.warn(`Failed to load SQLite WASM worker promiser from ${e}:`,t)}throw Error(`Could not load sqlite3Worker1Promiser as ES6 module from any known path`)}loadWorkerPromiserFromGlobal(){let e=globalThis;if(typeof e.sqlite3Worker1Promiser==`function`)return e.sqlite3Worker1Promiser;throw Error(`SQLite WASM worker promiser not found globally. Please:
3. Or include SQLite WASM script in your HTML before using UniSqlite`)}async loadSQLiteWorkerPromiserFactory(){let e=`worker-${this.config.loadStrategy}-${this.config.wasmUrl||this.config.cdnBaseUrl}-${this.config.version}`;if(b.has(e))return b.get(e);let t=this.loadSQLiteWorkerPromiserFactoryInternal();return b.set(e,t),t}async loadSQLiteWorkerPromiserFactoryInternal(){let{loadStrategy:e,wasmUrl:t,cdnBaseUrl:n,version:r,bundlerFriendly:i}=this.config;switch(e){case`npm`:return await this.loadWorkerPromiserFromNpm();case`cdn`:return await this.loadWorkerPromiserFromCdn(n,r,i);case`url`:if(!t)throw Error(`wasmUrl must be provided when using 'url' loading strategy`);return await this.loadWorkerPromiserFromUrl(t);case`module`:return await this.loadWorkerPromiserAsModule();case`global`:default:return this.loadWorkerPromiserFromGlobal()}}async loadWorkerPromiserFromNpm(){try{let e=(await import(`@sqlite.org/sqlite-wasm`)).sqlite3Worker1Promiser;if(typeof e==`function`)return e;throw Error(`sqlite3Worker1Promiser export not found`)}catch(e){return s.warn(`Failed to load SQLite WASM worker promiser from npm, falling back to CDN:`,e),this.loadWorkerPromiserFromCdn(this.config.cdnBaseUrl,this.config.version,this.config.bundlerFriendly)}}async loadWorkerPromiserFromCdn(e,t,n){let r=n?`sqlite3-bundler-friendly.mjs`:`index.mjs`,i=[`${e}@${t}/${r}`,`${e}@${t}/dist/${r}`],a;for(let e of i)try{s.log(`Trying to load SQLite WASM worker promiser from: ${e}`);let t=(await import(e)).sqlite3Worker1Promiser;if(typeof t==`function`)return s.log(`Successfully loaded SQLite WASM worker promiser from: ${e}`),t;throw Error(`sqlite3Worker1Promiser export not found`)}catch(t){a=t,s.warn(`Failed to load SQLite WASM worker promiser from ${e}:`,t)}let o=a instanceof Error?a.message:String(a);throw Error(`Failed to load sqlite3Worker1Promiser from any CDN source. Last error: ${o}`)}async loadWorkerPromiserFromUrl(e){let t=(await import(e)).sqlite3Worker1Promiser;if(typeof t!=`function`)throw Error(`sqlite3Worker1Promiser export not found in module loaded from ${e}`);return t}async loadWorkerPromiserAsModule(){if(globalThis.importScripts!==void 0)throw Error(`ES6 module loading not supported in Web Worker context`);for(let e of[`./sqlite3.mjs`,`./sqlite3-bundler-friendly.mjs`,`/sqlite3.mjs`])try{let t=(await import(e)).sqlite3Worker1Promiser;if(typeof t==`function`)return t}catch(t){s.warn(`Failed to load SQLite WASM worker promiser from ${e}:`,t)}throw Error(`Could not load sqlite3Worker1Promiser as ES6 module from any known path`)}loadWorkerPromiserFromGlobal(){let e=globalThis;if(typeof e.sqlite3Worker1Promiser==`function`)return e.sqlite3Worker1Promiser;throw Error(`SQLite WASM worker promiser not found globally. Please:
1. Install via npm: npm install @sqlite.org/sqlite-wasm and set loadStrategy to 'npm'
2. Or set loadStrategy to 'cdn' for automatic CDN loading
3. Or include SQLite WASM worker promiser script in your HTML before using UniSqlite`)}async tryCreatePersistentDatabase(e,t,n){if(n===`opfs`||n===`auto`){let r=this.config.opfsVfsType??`auto`,i=r===`auto`?e.oo1.OpfsDb?[`opfs`]:[`opfs-sahpool`,`opfs`]:r===`sahpool`?[`opfs-sahpool`]:[`opfs`];for(let n of i)if(await this.tryCreateOpfsDatabase(e,t,n))return!0;if(n===`opfs`)throw Error(this.getOpfsUnavailableError())}if(n===`localStorage`||n===`auto`){if(e.oo1.JsStorageDb)if(this.dbName===`local`||this.dbName===`session`)try{return console.log(`Creating localStorage-backed database:`,this.dbName),this.db=new e.oo1.JsStorageDb(this.dbName),this.activeStorageBackend=`localStorage`,console.log(`Successfully created localStorage-backed database`),!0}catch(e){if(console.warn(`localStorage database creation failed:`,e),n===`localStorage`)throw Error(`localStorage database creation failed: ${e instanceof Error?e.message:String(e)}`)}else if(n===`localStorage`)throw Error(`localStorage storage backend requires path to be 'local' or 'session', got '${this.dbName}'. Use storageBackend: 'opfs' for custom database names with persistence.`);else console.log(`Skipping localStorage: path '${this.dbName}' is not 'local' or 'session'`);else if(n===`localStorage`)throw Error(`JsStorageDb is not available in this environment.`)}return!1}getOpfsUnavailableError(){return`OPFS is not available.
3. Or include SQLite WASM worker promiser script in your HTML before using UniSqlite`)}async tryCreatePersistentDatabase(e,t,n){if(n===`opfs`||n===`auto`){let r=this.config.opfsVfsType??`auto`,i=r===`auto`?e.oo1.OpfsDb?[`opfs`]:[`opfs-sahpool`,`opfs`]:r===`sahpool`?[`opfs-sahpool`]:[`opfs`];for(let n of i)if(await this.tryCreateOpfsDatabase(e,t,n))return!0;if(n===`opfs`)throw Error(this.getOpfsUnavailableError())}if(n===`localStorage`||n===`auto`){if(e.oo1.JsStorageDb)if(this.dbName===`local`||this.dbName===`session`)try{return s.log(`Creating localStorage-backed database:`,this.dbName),this.db=new e.oo1.JsStorageDb(this.dbName),this.activeStorageBackend=`localStorage`,s.log(`Successfully created localStorage-backed database`),!0}catch(e){if(s.warn(`localStorage database creation failed:`,e),n===`localStorage`)throw Error(`localStorage database creation failed: ${e instanceof Error?e.message:String(e)}`)}else if(n===`localStorage`)throw Error(`localStorage storage backend requires path to be 'local' or 'session', got '${this.dbName}'. Use storageBackend: 'opfs' for custom database names with persistence.`);else s.log(`Skipping localStorage: path '${this.dbName}' is not 'local' or 'session'`);else if(n===`localStorage`)throw Error(`JsStorageDb is not available in this environment.`)}return!1}getOpfsUnavailableError(){return`OPFS is not available.

@@ -14,5 +14,5 @@ SQLite WASM OPFS backends only work in Worker contexts. When running on the main thread, UniSQLite will try to use SQLite WASM's wrapped-worker API (sqlite3Worker1Promiser) under the hood.

- For VFS 'opfs': COOP/COEP headers are set and SharedArrayBuffer is available
- Your sqlite load strategy can load sqlite3Worker1Promiser (use sqlite.loadStrategy = 'npm' or 'cdn', or provide it globally)`}async tryCreateOpfsDatabase(e,t,n){if(n===`opfs`){if(e.oo1.OpfsDb)try{return console.log(`Creating OPFS-backed database (OpfsDb):`,t),this.db=new e.oo1.OpfsDb(t),this.workerDbId=void 0,this.activeStorageBackend=`opfs`,this.activeOpfsVfs=`opfs`,console.log(`Successfully created OPFS-backed database (OpfsDb)`),!0}catch(e){console.warn(`OPFS database creation via OpfsDb failed:`,e)}return await this.tryCreateWrappedWorkerOpfsDatabase(t,n)}if(await this.ensureSahpoolVfs(e))try{return console.log(`Creating SAHPool OPFS-backed database:`,t),this.db=new e.oo1.DB(t,`c`,`opfs-sahpool`),this.workerDbId=void 0,this.activeStorageBackend=`opfs`,this.activeOpfsVfs=`opfs-sahpool`,console.log(`Successfully created SAHPool OPFS-backed database`),!0}catch(e){console.warn(`SAHPool OPFS database creation failed:`,e)}return await this.tryCreateWrappedWorkerOpfsDatabase(t,n)}async ensureSahpoolVfs(e){if(globalThis.importScripts===void 0)return!1;let t=`opfs-sahpool`;try{if(e.capi.sqlite3_vfs_find?.(t))return!0}catch(e){console.warn(`SAHPool VFS lookup failed:`,e)}if(typeof e.installOpfsSAHPoolVfs!=`function`)return!1;try{await e.installOpfsSAHPoolVfs({name:t,directory:`/unisqlite-sahpool`})}catch(e){return console.warn(`SAHPool VFS installation failed:`,e),!1}try{return!!e.capi.sqlite3_vfs_find?.(t)}catch{return!0}}createWorkerFromConfig(){if(!this.config.workerUrl||typeof Worker>`u`)return;let e=typeof this.config.workerUrl==`string`?this.config.workerUrl:this.config.workerUrl.href;try{return new Worker(e,{type:`module`})}catch(e){console.warn(`Failed to create Worker from custom workerUrl:`,e);return}}createWorkerFromCdn(e){if(typeof Worker>`u`||typeof Blob>`u`||typeof URL>`u`)return;let t=this.config.cdnBaseUrl,n=this.config.version;if(!t||!n)return;let r=`${`${t}@${n}/sqlite-wasm/jswasm`}/sqlite3-bundler-friendly.mjs`,i=e.installSahpool?[` if (typeof sqlite3.installOpfsSAHPoolVfs === "function") {`,` await sqlite3.installOpfsSAHPoolVfs({ name: "opfs-sahpool", directory: "/unisqlite-sahpool" });`,` }`].join(`
- Your sqlite load strategy can load sqlite3Worker1Promiser (use sqlite.loadStrategy = 'npm' or 'cdn', or provide it globally)`}async tryCreateOpfsDatabase(e,t,n){if(n===`opfs`){if(e.oo1.OpfsDb)try{return s.log(`Creating OPFS-backed database (OpfsDb):`,t),this.db=new e.oo1.OpfsDb(t),this.workerDbId=void 0,this.activeStorageBackend=`opfs`,this.activeOpfsVfs=`opfs`,s.log(`Successfully created OPFS-backed database (OpfsDb)`),!0}catch(e){s.warn(`OPFS database creation via OpfsDb failed:`,e)}return await this.tryCreateWrappedWorkerOpfsDatabase(t,n)}if(await this.ensureSahpoolVfs(e))try{return s.log(`Creating SAHPool OPFS-backed database:`,t),this.db=new e.oo1.DB(t,`c`,`opfs-sahpool`),this.workerDbId=void 0,this.activeStorageBackend=`opfs`,this.activeOpfsVfs=`opfs-sahpool`,s.log(`Successfully created SAHPool OPFS-backed database`),!0}catch(e){s.warn(`SAHPool OPFS database creation failed:`,e)}return await this.tryCreateWrappedWorkerOpfsDatabase(t,n)}async ensureSahpoolVfs(e){if(globalThis.importScripts===void 0)return!1;let t=`opfs-sahpool`;try{if(e.capi.sqlite3_vfs_find?.(t))return!0}catch(e){s.warn(`SAHPool VFS lookup failed:`,e)}if(typeof e.installOpfsSAHPoolVfs!=`function`)return!1;try{await e.installOpfsSAHPoolVfs({name:t,directory:`/unisqlite-sahpool`})}catch(e){return s.warn(`SAHPool VFS installation failed:`,e),!1}try{return!!e.capi.sqlite3_vfs_find?.(t)}catch{return!0}}createWorkerFromConfig(){if(!this.config.workerUrl||typeof Worker>`u`)return;let e=typeof this.config.workerUrl==`string`?this.config.workerUrl:this.config.workerUrl.href;try{return new Worker(e,{type:`module`})}catch(e){s.warn(`Failed to create Worker from custom workerUrl:`,e);return}}createWorkerFromCdn(e){if(typeof Worker>`u`||typeof Blob>`u`||typeof URL>`u`)return;let t=this.config.cdnBaseUrl,n=this.config.version;if(!t||!n)return;let r=`${`${t}@${n}/sqlite-wasm/jswasm`}/sqlite3-bundler-friendly.mjs`,i=e.installSahpool?[` if (typeof sqlite3.installOpfsSAHPoolVfs === "function") {`,` await sqlite3.installOpfsSAHPoolVfs({ name: "opfs-sahpool", directory: "/unisqlite-sahpool" });`,` }`].join(`
`):``,a=[`import sqlite3InitModule from ${JSON.stringify(r)};`,`sqlite3InitModule().then(async (sqlite3) => {`,` try {`,i||` // no-op`,` } catch (e) {`,` console.warn("SAHPool VFS installation failed:", e);`,` }`,` sqlite3.initWorker1API();`,`});`,``].join(`
`),o=new Blob([a],{type:`text/javascript`}),s=URL.createObjectURL(o),c=new Worker(s,{type:`module`});return c.addEventListener(`message`,()=>{URL.revokeObjectURL(s)},{once:!0}),c.addEventListener(`error`,()=>{URL.revokeObjectURL(s)},{once:!0}),c}async getOrCreateWorkerPromiser(e){if(this.workerPromiser)return this.workerPromiser;if(this.workerPromiserInitPromise)return await this.workerPromiserInitPromise;let t=await this.loadSQLiteWorkerPromiserFactory(),n=this.config.storageBackend===`opfs`||this.config.opfsVfsType===`opfs`||this.config.opfsVfsType===`sahpool`,r=this.config.loadStrategy===`global`&&!n?5e3:2e4;this.workerPromiserInitPromise=new Promise((n,i)=>{let a=!1,o=setTimeout(()=>{a||(a=!0,i(Error(`SQLite worker initialization timed out after ${r}ms`)))},r),s=(e,t)=>{a||(a=!0,clearTimeout(o),e(t))},c=e=>{s(i,e instanceof Error?e:Error(String(e)))},l;try{l=t({...e?.worker?{worker:e.worker}:{},onready:e=>{if(typeof e==`function`){s(n,e);return}if(typeof l==`function`){s(n,l);return}if(l&&typeof l.then==`function`){l.then(e=>s(n,e),e=>c(e));return}c(Error(`sqlite3Worker1Promiser did not provide a usable promiser`))},onerror:e=>{let t=e instanceof Error?e.message:String(e);c(Error(`SQLite worker error: ${t}`))}}),l&&typeof l.then==`function`&&l.then(e=>s(n,e),e=>c(e))}catch(e){c(e)}});let i=await this.workerPromiserInitPromise;return this.workerPromiser=i,i}async tryCreateWrappedWorkerOpfsDatabase(e,t){try{let n=!this.workerPromiser&&!this.workerPromiserInitPromise?(()=>{let e=this.createWorkerFromConfig()??(t===`opfs-sahpool`?this.createWorkerFromCdn({installSahpool:!0}):this.createWorkerFromCdn({installSahpool:!1}));return e?{worker:e}:void 0})():void 0,r=await(await this.getOrCreateWorkerPromiser(n))(`open`,{filename:`file:${e}`,vfs:t}),i=r.dbId??r.result?.dbId;if(i===void 0)throw Error(`SQLite worker did not return a dbId`);if(typeof i!=`number`&&typeof i!=`string`)throw Error(`SQLite worker returned an invalid dbId (type=${typeof i})`);return this.db=void 0,this.workerDbId=i,this.activeStorageBackend=`opfs`,this.activeOpfsVfs=t,console.log(`Successfully created OPFS-backed database via wrapped worker (${t}):`,e),!0}catch(e){return console.warn(`Wrapped-worker OPFS database creation failed (vfs=${t}):`,e),!1}}},b=class{constructor(e,t,n){this.dbHost=e,this.hostElection=t,this.activeTxn=null,this.txnQueue=[],this.heartbeatTimers=new Map,this.txnPending=!1,this.rpcQueue=[],this.txnTimeoutMs=n?.txnTimeoutMs??3e4,this.opTimeoutMs=n?.opTimeoutMs??1e4,this.maxQueueSize=n?.maxQueueSize??10,this.heartbeatTimeoutMs=n?.heartbeatTimeoutMs??15e3}startWatchdog(){this.watchdogTimer||=setInterval(()=>{if(this.activeTxn){let e=Date.now()-this.activeTxn.lastActivityAt;e>this.txnTimeoutMs&&(a.warn(`Transaction ${this.activeTxn.txnId} timed out after ${e}ms, rolling back`),this.forceRollback())}let e=Date.now(),t=this.txnQueue.filter(t=>e-t.enqueuedAt>this.txnTimeoutMs);for(let e of t){let t=this.txnQueue.indexOf(e);t!==-1&&(this.txnQueue.splice(t,1),e.reject(Error(`Transaction queue wait timeout`)))}},5e3)}stopWatchdog(){this.watchdogTimer&&=(clearInterval(this.watchdogTimer),void 0)}getActiveTransaction(){return this.activeTxn}hasActiveTransaction(){return this.activeTxn!==null}isTransactionBlocking(){return this.activeTxn!==null||this.txnPending}async waitForTransactionSlot(){if(this.isTransactionBlocking())return new Promise((e,t)=>{this.rpcQueue.push({resolve:e,reject:t})})}async beginTransaction(e,t,n=`immediate`){if(this.activeTxn||this.txnPending){if(this.txnQueue.length>=this.maxQueueSize)throw Error(`Transaction queue full`);await new Promise((r,i)=>{this.txnQueue.push({txnId:e,originTabId:t,mode:n,resolve:r,reject:i,enqueuedAt:Date.now()})})}this.txnPending=!0;try{this.txnLockRelease=await this.hostElection.acquireTransactionLock();let r=n===`deferred`?`BEGIN`:n===`exclusive`?`BEGIN EXCLUSIVE`:`BEGIN IMMEDIATE`;await this.dbHost.execRaw(r),this.activeTxn={txnId:e,originTabId:t,startedAt:Date.now(),lastActivityAt:Date.now(),mode:n},this.resetHeartbeatTimer(e)}catch(e){throw this.txnLockRelease?.(),this.txnLockRelease=void 0,this.txnPending=!1,this.processQueue(),this.processRpcQueue(),e}finally{this.txnPending=!1}}async execInTransaction(e,t){return this.validateActiveTxn(e),this.activeTxn.lastActivityAt=Date.now(),this.resetHeartbeatTimer(e),await t()}recordHeartbeat(e){this.activeTxn?.txnId===e&&(this.activeTxn.lastActivityAt=Date.now(),this.resetHeartbeatTimer(e))}async commitTransaction(e){this.validateActiveTxn(e);try{await this.dbHost.execRaw(`COMMIT`)}finally{this.endTransaction()}}async rollbackTransaction(e){this.validateActiveTxn(e);try{await this.dbHost.execRaw(`ROLLBACK`)}finally{this.endTransaction()}}forceRollback(){if(this.activeTxn){try{this.dbHost.execRaw(`ROLLBACK`).catch(e=>{a.error(`Force rollback failed:`,e)})}catch(e){a.error(`Force rollback failed:`,e)}this.endTransaction()}}endTransaction(){if(this.activeTxn){let e=this.heartbeatTimers.get(this.activeTxn.txnId);e&&(clearTimeout(e),this.heartbeatTimers.delete(this.activeTxn.txnId)),this.activeTxn=null}this.txnLockRelease&&=(this.txnLockRelease(),void 0),this.processQueue(),this.processRpcQueue()}processQueue(){this.txnQueue.length>0&&!this.activeTxn&&!this.txnPending&&this.txnQueue.shift().resolve()}processRpcQueue(){if(this.activeTxn||this.txnPending)return;let e=this.rpcQueue;this.rpcQueue=[];for(let{resolve:t}of e)t()}resetHeartbeatTimer(e){let t=this.heartbeatTimers.get(e);t&&clearTimeout(t);let n=setTimeout(()=>{this.activeTxn?.txnId===e&&(a.warn(`No heartbeat for transaction ${e} in ${this.heartbeatTimeoutMs}ms, rolling back`),this.forceRollback())},this.heartbeatTimeoutMs);this.heartbeatTimers.set(e,n)}validateActiveTxn(e){if(!this.activeTxn)throw Error(`No active transaction (expected ${e})`);if(this.activeTxn.txnId!==e)throw Error(`Transaction ID mismatch: expected ${this.activeTxn.txnId}, got ${e}`);let t=Date.now()-this.activeTxn.lastActivityAt;if(t>this.txnTimeoutMs)throw this.forceRollback(),Error(`Transaction ${e} timed out after ${t}ms`)}async close(){this.stopWatchdog(),this.activeTxn&&this.forceRollback();for(let e of this.txnQueue)e.reject(Error(`Transaction session manager closed`));this.txnQueue=[];for(let e of this.rpcQueue)e.reject(Error(`Transaction session manager closed`));this.rpcQueue=[];for(let e of this.heartbeatTimers.values())clearTimeout(e);this.heartbeatTimers.clear()}},x=class{constructor(e,t,n=5e3){this.rpcChannel=e,this.txnId=t,this.heartbeatIntervalMs=n,this.committed=!1,this.rolledBack=!1,this.startHeartbeat()}startHeartbeat(){this.heartbeatInterval=setInterval(()=>{!this.committed&&!this.rolledBack&&this.rpcChannel.txnHeartbeat(this.txnId)},this.heartbeatIntervalMs)}stopHeartbeat(){this.heartbeatInterval&&=(clearInterval(this.heartbeatInterval),void 0)}ensureActive(){if(this.committed)throw Error(`Transaction already committed`);if(this.rolledBack)throw Error(`Transaction already rolled back`)}async query(e,t){return this.ensureActive(),(await this.rpcChannel.txnExec(this.txnId,`query`,{sql:e,params:t})).rows}async queryRaw(e,t){return this.ensureActive(),await this.rpcChannel.txnExec(this.txnId,`queryRaw`,{sql:e,params:t})}async run(e,t){this.ensureActive();let n=await this.rpcChannel.txnExec(this.txnId,`run`,{sql:e,params:t});return{rowsAffected:n.rowsAffected??0,lastInsertRowId:n.lastInsertRowId??0}}async exec(e){this.ensureActive(),await this.rpcChannel.txnExec(this.txnId,`exec`,{sql:e})}async transaction(e){this.ensureActive();let t=e(this);return t instanceof Promise?await t:t}async asyncTransaction(e,t){return this.ensureActive(),await e(this)}getConnectionType(){return`asyncTxn`}async close(){}async _commit(){this.ensureActive(),this.stopHeartbeat();try{await this.rpcChannel.txnCommit(this.txnId),this.committed=!0}catch(e){throw this.rolledBack=!0,e}}async _rollback(){if(!(this.committed||this.rolledBack)){this.stopHeartbeat();try{await this.rpcChannel.txnRollback(this.txnId)}finally{this.rolledBack=!0}}}isCommitted(){return this.committed}isRolledBack(){return this.rolledBack}},S=class{constructor(e,t){this.dbHost=e,this.isAsync=t}async query(e,t){return(await this.dbHost.executeSqlRaw(e,t)).rows}async queryRaw(e,t){return await this.dbHost.executeSqlRaw(e,t)}async run(e,t){let n=await this.dbHost.executeSqlRaw(e,t);return{rowsAffected:n.rowsAffected??0,lastInsertRowId:n.lastInsertRowId??0}}async exec(e){await this.dbHost.execRaw(e)}async transaction(e){let t=e(this);return t instanceof Promise?await t:t}async asyncTransaction(e){return await e(this)}getConnectionType(){return this.isAsync?`asyncTxn`:`syncTxn`}async close(){}},C=class t extends e{constructor(e){let t=e.path??e.name??`default`;super({...e,path:t}),this.dbHost=null,this.txnSessionManager=null,this.initialized=!1,this.closed=!1,this.options={...e,path:t},this.tabId=m(),this.sqliteConfig={loadStrategy:`global`,storageBackend:`auto`,opfsVfsType:`auto`,cdnBaseUrl:`https://cdn.jsdelivr.net/npm/@sqlite.org/sqlite-wasm`,version:`3.50.1-build1`,bundlerFriendly:!1,...e.sqlite},s.isSupported()||(o.warn(`Web Locks API not supported. Falling back to memory-only storage.`),this.sqliteConfig.storageBackend=`memory`),this.visibilityManager=new c,this.rpcChannel=new g(t,this.tabId),this.hostElection=new s({dbName:t,tabId:this.tabId,onBecomeHost:()=>this.becomeHost(),onLoseHost:()=>this.loseHost(),checkVisibility:()=>this.visibilityManager.isVisible()}),this.visibilityUnsubscribe=this.visibilityManager.onVisibilityChange(e=>{this.handleVisibilityChange(e)})}static async create(e){let n=new t(e);return await n.initialize(),n}getTabId(){return this.tabId}get isHost(){return this.hostElection.isHost}async initialize(){if(!this.initialized){if(this.initPromise)return this.initPromise;this.initPromise=this.doInitialize(),await this.initPromise,this.initialized=!0}}async doInitialize(){this.becomeHostPromise=new Promise(e=>{this.becomeHostResolver=e}),await this.hostElection.start();let e=new Promise(e=>{setTimeout(()=>e(`timeout`),500)});await Promise.race([this.becomeHostPromise.then(()=>`host`),e])===`host`||this.hostElection.isHost&&await this.becomeHostPromise}async becomeHost(){o.log(`Tab ${this.tabId} becoming Host for ${this.options.path}`),this.dbHost=await y.create({dbName:this.options.path,config:this.sqliteConfig}),this.txnSessionManager=new b(this.dbHost,this.hostElection),this.txnSessionManager.startWatchdog(),this.rpcChannel.setRequestHandler(this.handleRequest.bind(this)),this.becomeHostResolver&&=(this.becomeHostResolver(),void 0)}loseHost(){o.log(`Tab ${this.tabId} losing Host for ${this.options.path}`),this.rpcChannel.setRequestHandler(void 0),this.txnSessionManager&&=(this.txnSessionManager.close(),null),this.dbHost&&=(this.dbHost.close(),null)}handleVisibilityChange(e){e&&!this.hostElection.isHost&&!this.closed&&this.hostElection.start()}async handleRequest(e){if(!this.dbHost)throw Error(`Not Host`);switch(e.t){case`req`:return await this.handleRpcRequest(e);case`txn_begin`:return await this.handleTxnBegin(e);case`txn_exec`:return await this.handleTxnExec(e);case`txn_commit`:return await this.handleTxnCommit(e);case`txn_rollback`:return await this.handleTxnRollback(e);case`txn_heartbeat`:this.handleTxnHeartbeat(e);return;default:throw Error(`Unknown request type: ${e.t}`)}}async handleRpcRequest(e){let{op:t,payload:n}=e,{sql:r,params:i}=n;switch(this.txnSessionManager&&await this.txnSessionManager.waitForTransactionSlot(),t){case`query`:return{rows:await this.dbHost.query(r,i),columns:[]};case`queryRaw`:return await this.dbHost.queryRaw(r,i);case`run`:return await this.dbHost.run(r,i);case`exec`:return await this.dbHost.exec(r),null;default:throw Error(`Unknown RPC operation: ${String(t)}`)}}async handleTxnBegin(e){await this.txnSessionManager.beginTransaction(e.txnId,e.from,e.mode)}async handleTxnExec(e){let{txnId:t,op:n,payload:r}=e,{sql:i,params:a}=r;return await this.txnSessionManager.execInTransaction(t,async()=>{switch(n){case`query`:return{rows:await this.dbHost.query(i,a),columns:[]};case`queryRaw`:return await this.dbHost.queryRaw(i,a);case`run`:return await this.dbHost.run(i,a);case`exec`:return await this.dbHost.exec(i),null;default:throw Error(`Unknown transaction operation: ${String(n)}`)}})}async handleTxnCommit(e){await this.txnSessionManager.commitTransaction(e.txnId)}async handleTxnRollback(e){await this.txnSessionManager.rollbackTransaction(e.txnId)}handleTxnHeartbeat(e){this.txnSessionManager?.recordHeartbeat(e.txnId)}async query(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.dbHost.query(e,t):(await this.rpcChannel.request(`query`,{sql:e,params:t})).rows}async queryRaw(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.dbHost.queryRaw(e,t):await this.rpcChannel.request(`queryRaw`,{sql:e,params:t})}async run(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.dbHost.run(e,t):await this.rpcChannel.request(`run`,{sql:e,params:t})}async exec(e){if(await this.initialize(),this.isHost&&this.dbHost){await this.dbHost.exec(e);return}await this.rpcChannel.request(`exec`,{sql:e})}async transaction(e){return await this.initialize(),this.isHost&&this.dbHost?await this.executeLocalTransaction(e,!1):await this.executeRemoteTransaction(e)}async asyncTransaction(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.executeLocalAsyncTransaction(e,t):await this.executeRemoteTransaction(e,t)}getConnectionType(){return`direct`}async close(){this.closed||(this.closed=!0,this.visibilityUnsubscribe?.(),await this.hostElection.close(),this.rpcChannel.close(),this.visibilityManager.destroy(),this.txnSessionManager&&=(await this.txnSessionManager.close(),null),this.dbHost&&=(await this.dbHost.close(),null))}async executeLocalTransaction(e,t){await this.dbHost.execRaw(`BEGIN`);let n=new S(this.dbHost,t);try{let t=e(n),r=t instanceof Promise?await t:t;return await this.dbHost.execRaw(`COMMIT`),r}catch(e){try{await this.dbHost.execRaw(`ROLLBACK`)}catch(e){console.error(`Rollback failed:`,e)}throw e}}async executeLocalAsyncTransaction(e,t){let n=t?.timeoutMs??3e4;await this.dbHost.execRaw(`BEGIN IMMEDIATE`);let r=new S(this.dbHost,!0),i,a=!1;try{let t=new Promise((e,t)=>{i=setTimeout(()=>{a||t(Error(`Async transaction timeout after ${n}ms`))},n)}),o=await Promise.race([e(r),t]);return a=!0,i&&clearTimeout(i),await this.dbHost.execRaw(`COMMIT`),o}catch(e){a=!0,i&&clearTimeout(i);try{await this.dbHost.execRaw(`ROLLBACK`)}catch(e){console.error(`Rollback failed:`,e)}throw e}}async executeRemoteTransaction(e,t){let n=h(),r=t?.timeoutMs??3e4;await this.rpcChannel.txnBegin(n,`immediate`,r);let i=new x(this.rpcChannel,n),a,o=!1;try{let t=new Promise((e,t)=>{a=setTimeout(()=>{o||t(Error(`Remote transaction timeout after ${r}ms`))},r)}),n=e(i),s=n instanceof Promise?n:Promise.resolve(n),c=await Promise.race([s,t]);return o=!0,a&&clearTimeout(a),await i._commit(),c}catch(e){o=!0,a&&clearTimeout(a);try{await i._rollback()}catch(e){console.error(`Remote rollback failed:`,e)}throw e}}getSQLiteInfo(){let e=this.isHost?this.dbHost!==null:this.initialized&&!this.closed;return{config:this.sqliteConfig,isInitialized:this.initialized,isHost:this.isHost,isReady:e,tabId:this.tabId,hasDatabase:this.dbHost!==null,usesWorker:this.dbHost?.isWorkerDbActive()??!1,activeStorageBackend:this.dbHost?.getActiveStorageBackend()??`unknown`,activeOpfsVfs:this.dbHost?.getActiveOpfsVfs()}}getActiveStorageBackend(){return this.dbHost?.getActiveStorageBackend()??`unknown`}};export{g as a,m as c,f as d,l as f,y as i,h as l,s as m,x as n,u as o,c as p,b as r,p as s,C as t,d as u};
`),o=new Blob([a],{type:`text/javascript`}),s=URL.createObjectURL(o),c=new Worker(s,{type:`module`});return c.addEventListener(`message`,()=>{URL.revokeObjectURL(s)},{once:!0}),c.addEventListener(`error`,()=>{URL.revokeObjectURL(s)},{once:!0}),c}async getOrCreateWorkerPromiser(e){if(this.workerPromiser)return this.workerPromiser;if(this.workerPromiserInitPromise)return await this.workerPromiserInitPromise;let t=await this.loadSQLiteWorkerPromiserFactory(),n=this.config.storageBackend===`opfs`||this.config.opfsVfsType===`opfs`||this.config.opfsVfsType===`sahpool`,r=this.config.loadStrategy===`global`&&!n?5e3:2e4;this.workerPromiserInitPromise=new Promise((n,i)=>{let a=!1,o=setTimeout(()=>{a||(a=!0,i(Error(`SQLite worker initialization timed out after ${r}ms`)))},r),s=(e,t)=>{a||(a=!0,clearTimeout(o),e(t))},c=e=>{s(i,e instanceof Error?e:Error(String(e)))},l;try{l=t({...e?.worker?{worker:e.worker}:{},onready:e=>{if(typeof e==`function`){s(n,e);return}if(typeof l==`function`){s(n,l);return}if(l&&typeof l.then==`function`){l.then(e=>s(n,e),e=>c(e));return}c(Error(`sqlite3Worker1Promiser did not provide a usable promiser`))},onerror:e=>{let t=e instanceof Error?e.message:String(e);c(Error(`SQLite worker error: ${t}`))}}),l&&typeof l.then==`function`&&l.then(e=>s(n,e),e=>c(e))}catch(e){c(e)}});let i=await this.workerPromiserInitPromise;return this.workerPromiser=i,i}async tryCreateWrappedWorkerOpfsDatabase(e,t){try{let n=!this.workerPromiser&&!this.workerPromiserInitPromise?(()=>{let e=this.createWorkerFromConfig()??(t===`opfs-sahpool`?this.createWorkerFromCdn({installSahpool:!0}):this.createWorkerFromCdn({installSahpool:!1}));return e?{worker:e}:void 0})():void 0,r=await(await this.getOrCreateWorkerPromiser(n))(`open`,{filename:`file:${e}`,vfs:t}),i=r.dbId??r.result?.dbId;if(i===void 0)throw Error(`SQLite worker did not return a dbId`);if(typeof i!=`number`&&typeof i!=`string`)throw Error(`SQLite worker returned an invalid dbId (type=${typeof i})`);return this.db=void 0,this.workerDbId=i,this.activeStorageBackend=`opfs`,this.activeOpfsVfs=t,s.log(`Successfully created OPFS-backed database via wrapped worker (${t}):`,e),!0}catch(e){return s.warn(`Wrapped-worker OPFS database creation failed (vfs=${t}):`,e),!1}}},S=class{constructor(e,t,n){this.dbHost=e,this.hostElection=t,this.activeTxn=null,this.txnQueue=[],this.heartbeatTimers=new Map,this.txnPending=!1,this.rpcQueue=[],this.txnTimeoutMs=n?.txnTimeoutMs??3e4,this.opTimeoutMs=n?.opTimeoutMs??1e4,this.maxQueueSize=n?.maxQueueSize??10,this.heartbeatTimeoutMs=n?.heartbeatTimeoutMs??15e3}startWatchdog(){this.watchdogTimer||=setInterval(()=>{if(this.activeTxn){let e=Date.now()-this.activeTxn.lastActivityAt;e>this.txnTimeoutMs&&(a.warn(`Transaction ${this.activeTxn.txnId} timed out after ${e}ms, rolling back`),this.forceRollback())}let e=Date.now(),t=this.txnQueue.filter(t=>e-t.enqueuedAt>this.txnTimeoutMs);for(let e of t){let t=this.txnQueue.indexOf(e);t!==-1&&(this.txnQueue.splice(t,1),e.reject(Error(`Transaction queue wait timeout`)))}},5e3)}stopWatchdog(){this.watchdogTimer&&=(clearInterval(this.watchdogTimer),void 0)}getActiveTransaction(){return this.activeTxn}hasActiveTransaction(){return this.activeTxn!==null}isTransactionBlocking(){return this.activeTxn!==null||this.txnPending}async waitForTransactionSlot(){if(this.isTransactionBlocking())return new Promise((e,t)=>{this.rpcQueue.push({resolve:e,reject:t})})}async beginTransaction(e,t,n=`immediate`){if(this.activeTxn||this.txnPending){if(this.txnQueue.length>=this.maxQueueSize)throw Error(`Transaction queue full`);await new Promise((r,i)=>{this.txnQueue.push({txnId:e,originTabId:t,mode:n,resolve:r,reject:i,enqueuedAt:Date.now()})})}this.txnPending=!0;try{this.txnLockRelease=await this.hostElection.acquireTransactionLock();let r=n===`deferred`?`BEGIN`:n===`exclusive`?`BEGIN EXCLUSIVE`:`BEGIN IMMEDIATE`;await this.dbHost.execRaw(r),this.activeTxn={txnId:e,originTabId:t,startedAt:Date.now(),lastActivityAt:Date.now(),mode:n},this.resetHeartbeatTimer(e)}catch(e){throw this.txnLockRelease?.(),this.txnLockRelease=void 0,this.txnPending=!1,this.processQueue(),this.processRpcQueue(),e}finally{this.txnPending=!1}}async execInTransaction(e,t){return this.validateActiveTxn(e),this.activeTxn.lastActivityAt=Date.now(),this.resetHeartbeatTimer(e),await t()}recordHeartbeat(e){this.activeTxn?.txnId===e&&(this.activeTxn.lastActivityAt=Date.now(),this.resetHeartbeatTimer(e))}async commitTransaction(e){this.validateActiveTxn(e);try{await this.dbHost.execRaw(`COMMIT`)}finally{this.endTransaction()}}async rollbackTransaction(e){this.validateActiveTxn(e);try{await this.dbHost.execRaw(`ROLLBACK`)}finally{this.endTransaction()}}forceRollback(){if(this.activeTxn){try{this.dbHost.execRaw(`ROLLBACK`).catch(e=>{a.error(`Force rollback failed:`,e)})}catch(e){a.error(`Force rollback failed:`,e)}this.endTransaction()}}endTransaction(){if(this.activeTxn){let e=this.heartbeatTimers.get(this.activeTxn.txnId);e&&(clearTimeout(e),this.heartbeatTimers.delete(this.activeTxn.txnId)),this.activeTxn=null}this.txnLockRelease&&=(this.txnLockRelease(),void 0),this.processQueue(),this.processRpcQueue()}processQueue(){this.txnQueue.length>0&&!this.activeTxn&&!this.txnPending&&this.txnQueue.shift().resolve()}processRpcQueue(){if(this.activeTxn||this.txnPending)return;let e=this.rpcQueue;this.rpcQueue=[];for(let{resolve:t}of e)t()}resetHeartbeatTimer(e){let t=this.heartbeatTimers.get(e);t&&clearTimeout(t);let n=setTimeout(()=>{this.activeTxn?.txnId===e&&(a.warn(`No heartbeat for transaction ${e} in ${this.heartbeatTimeoutMs}ms, rolling back`),this.forceRollback())},this.heartbeatTimeoutMs);this.heartbeatTimers.set(e,n)}validateActiveTxn(e){if(!this.activeTxn)throw Error(`No active transaction (expected ${e})`);if(this.activeTxn.txnId!==e)throw Error(`Transaction ID mismatch: expected ${this.activeTxn.txnId}, got ${e}`);let t=Date.now()-this.activeTxn.lastActivityAt;if(t>this.txnTimeoutMs)throw this.forceRollback(),Error(`Transaction ${e} timed out after ${t}ms`)}async close(){this.stopWatchdog(),this.activeTxn&&this.forceRollback();for(let e of this.txnQueue)e.reject(Error(`Transaction session manager closed`));this.txnQueue=[];for(let e of this.rpcQueue)e.reject(Error(`Transaction session manager closed`));this.rpcQueue=[];for(let e of this.heartbeatTimers.values())clearTimeout(e);this.heartbeatTimers.clear()}},C=class{constructor(e,t,n=5e3){this.rpcChannel=e,this.txnId=t,this.heartbeatIntervalMs=n,this.committed=!1,this.rolledBack=!1,this.startHeartbeat()}startHeartbeat(){this.heartbeatInterval=setInterval(()=>{!this.committed&&!this.rolledBack&&this.rpcChannel.txnHeartbeat(this.txnId)},this.heartbeatIntervalMs)}stopHeartbeat(){this.heartbeatInterval&&=(clearInterval(this.heartbeatInterval),void 0)}ensureActive(){if(this.committed)throw Error(`Transaction already committed`);if(this.rolledBack)throw Error(`Transaction already rolled back`)}async query(e,t){return this.ensureActive(),(await this.rpcChannel.txnExec(this.txnId,`query`,{sql:e,params:t})).rows}async queryRaw(e,t){return this.ensureActive(),await this.rpcChannel.txnExec(this.txnId,`queryRaw`,{sql:e,params:t})}async run(e,t){this.ensureActive();let n=await this.rpcChannel.txnExec(this.txnId,`run`,{sql:e,params:t});return{rowsAffected:n.rowsAffected??0,lastInsertRowId:n.lastInsertRowId??0}}async exec(e){this.ensureActive(),await this.rpcChannel.txnExec(this.txnId,`exec`,{sql:e})}async transaction(e){this.ensureActive();let t=e(this);return t instanceof Promise?await t:t}async asyncTransaction(e,t){return this.ensureActive(),await e(this)}getConnectionType(){return`asyncTxn`}async close(){}async _commit(){this.ensureActive(),this.stopHeartbeat();try{await this.rpcChannel.txnCommit(this.txnId),this.committed=!0}catch(e){throw this.rolledBack=!0,e}}async _rollback(){if(!(this.committed||this.rolledBack)){this.stopHeartbeat();try{await this.rpcChannel.txnRollback(this.txnId)}finally{this.rolledBack=!0}}}isCommitted(){return this.committed}isRolledBack(){return this.rolledBack}},w=class{constructor(e,t){this.dbHost=e,this.isAsync=t}async query(e,t){return(await this.dbHost.executeSqlRaw(e,t)).rows}async queryRaw(e,t){return await this.dbHost.executeSqlRaw(e,t)}async run(e,t){let n=await this.dbHost.executeSqlRaw(e,t);return{rowsAffected:n.rowsAffected??0,lastInsertRowId:n.lastInsertRowId??0}}async exec(e){await this.dbHost.execRaw(e)}async transaction(e){let t=e(this);return t instanceof Promise?await t:t}async asyncTransaction(e){return await e(this)}getConnectionType(){return this.isAsync?`asyncTxn`:`syncTxn`}async close(){}},T=class t extends e{constructor(e){let t=e.path??e.name??`default`;super({...e,path:t}),this.dbHost=null,this.txnSessionManager=null,this.initialized=!1,this.closed=!1,this.options={...e,path:t},this.tabId=g(),this.sqliteConfig={loadStrategy:`global`,storageBackend:`auto`,opfsVfsType:`auto`,cdnBaseUrl:`https://cdn.jsdelivr.net/npm/@sqlite.org/sqlite-wasm`,version:`3.50.1-build1`,bundlerFriendly:!1,...e.sqlite},l.isSupported()||(o.warn(`Web Locks API not supported. Falling back to memory-only storage.`),this.sqliteConfig.storageBackend=`memory`),this.visibilityManager=new u,this.rpcChannel=new v(t,this.tabId),this.hostElection=new l({dbName:t,tabId:this.tabId,onBecomeHost:()=>this.becomeHost(),onLoseHost:()=>this.loseHost(),checkVisibility:()=>this.visibilityManager.isVisible()}),this.visibilityUnsubscribe=this.visibilityManager.onVisibilityChange(e=>{this.handleVisibilityChange(e)})}static async create(e){let n=new t(e);return await n.initialize(),n}getTabId(){return this.tabId}get isHost(){return this.hostElection.isHost}async initialize(){if(!this.initialized){if(this.initPromise)return this.initPromise;this.initPromise=this.doInitialize(),await this.initPromise,this.initialized=!0}}async doInitialize(){this.becomeHostPromise=new Promise(e=>{this.becomeHostResolver=e}),await this.hostElection.start();let e=new Promise(e=>{setTimeout(()=>e(`timeout`),500)});await Promise.race([this.becomeHostPromise.then(()=>`host`),e])===`host`||this.hostElection.isHost&&await this.becomeHostPromise}async becomeHost(){o.log(`Tab ${this.tabId} becoming Host for ${this.options.path}`),this.dbHost=await x.create({dbName:this.options.path,config:this.sqliteConfig}),this.txnSessionManager=new S(this.dbHost,this.hostElection),this.txnSessionManager.startWatchdog(),this.rpcChannel.setRequestHandler(this.handleRequest.bind(this)),this.becomeHostResolver&&=(this.becomeHostResolver(),void 0)}loseHost(){o.log(`Tab ${this.tabId} losing Host for ${this.options.path}`),this.rpcChannel.setRequestHandler(void 0),this.txnSessionManager&&=(this.txnSessionManager.close(),null),this.dbHost&&=(this.dbHost.close(),null)}handleVisibilityChange(e){e&&!this.hostElection.isHost&&!this.closed&&this.hostElection.start()}async handleRequest(e){if(!this.dbHost)throw Error(`Not Host`);switch(e.t){case`req`:return await this.handleRpcRequest(e);case`txn_begin`:return await this.handleTxnBegin(e);case`txn_exec`:return await this.handleTxnExec(e);case`txn_commit`:return await this.handleTxnCommit(e);case`txn_rollback`:return await this.handleTxnRollback(e);case`txn_heartbeat`:this.handleTxnHeartbeat(e);return;default:throw Error(`Unknown request type: ${e.t}`)}}async handleRpcRequest(e){let{op:t,payload:n}=e,{sql:r,params:i}=n;switch(this.txnSessionManager&&await this.txnSessionManager.waitForTransactionSlot(),t){case`query`:return{rows:await this.dbHost.query(r,i),columns:[]};case`queryRaw`:return await this.dbHost.queryRaw(r,i);case`run`:return await this.dbHost.run(r,i);case`exec`:return await this.dbHost.exec(r),null;default:throw Error(`Unknown RPC operation: ${String(t)}`)}}async handleTxnBegin(e){await this.txnSessionManager.beginTransaction(e.txnId,e.from,e.mode)}async handleTxnExec(e){let{txnId:t,op:n,payload:r}=e,{sql:i,params:a}=r;return await this.txnSessionManager.execInTransaction(t,async()=>{switch(n){case`query`:return{rows:await this.dbHost.query(i,a),columns:[]};case`queryRaw`:return await this.dbHost.queryRaw(i,a);case`run`:return await this.dbHost.run(i,a);case`exec`:return await this.dbHost.exec(i),null;default:throw Error(`Unknown transaction operation: ${String(n)}`)}})}async handleTxnCommit(e){await this.txnSessionManager.commitTransaction(e.txnId)}async handleTxnRollback(e){await this.txnSessionManager.rollbackTransaction(e.txnId)}handleTxnHeartbeat(e){this.txnSessionManager?.recordHeartbeat(e.txnId)}async query(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.dbHost.query(e,t):(await this.rpcChannel.request(`query`,{sql:e,params:t})).rows}async queryRaw(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.dbHost.queryRaw(e,t):await this.rpcChannel.request(`queryRaw`,{sql:e,params:t})}async run(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.dbHost.run(e,t):await this.rpcChannel.request(`run`,{sql:e,params:t})}async exec(e){if(await this.initialize(),this.isHost&&this.dbHost){await this.dbHost.exec(e);return}await this.rpcChannel.request(`exec`,{sql:e})}async transaction(e){return await this.initialize(),this.isHost&&this.dbHost?await this.executeLocalTransaction(e,!1):await this.executeRemoteTransaction(e)}async asyncTransaction(e,t){return await this.initialize(),this.isHost&&this.dbHost?await this.executeLocalAsyncTransaction(e,t):await this.executeRemoteTransaction(e,t)}getConnectionType(){return`direct`}async close(){this.closed||(this.closed=!0,this.visibilityUnsubscribe?.(),await this.hostElection.close(),this.rpcChannel.close(),this.visibilityManager.destroy(),this.txnSessionManager&&=(await this.txnSessionManager.close(),null),this.dbHost&&=(await this.dbHost.close(),null))}async executeLocalTransaction(e,t){await this.dbHost.execRaw(`BEGIN`);let n=new w(this.dbHost,t);try{let t=e(n),r=t instanceof Promise?await t:t;return await this.dbHost.execRaw(`COMMIT`),r}catch(e){try{await this.dbHost.execRaw(`ROLLBACK`)}catch(e){o.error(`Rollback failed:`,e)}throw e}}async executeLocalAsyncTransaction(e,t){let n=t?.timeoutMs??3e4;await this.dbHost.execRaw(`BEGIN IMMEDIATE`);let r=new w(this.dbHost,!0),i,a=!1;try{let t=new Promise((e,t)=>{i=setTimeout(()=>{a||t(Error(`Async transaction timeout after ${n}ms`))},n)}),o=await Promise.race([e(r),t]);return a=!0,i&&clearTimeout(i),await this.dbHost.execRaw(`COMMIT`),o}catch(e){a=!0,i&&clearTimeout(i);try{await this.dbHost.execRaw(`ROLLBACK`)}catch(e){o.error(`Rollback failed:`,e)}throw e}}async executeRemoteTransaction(e,t){let n=_(),r=t?.timeoutMs??3e4;await this.rpcChannel.txnBegin(n,`immediate`,r);let i=new C(this.rpcChannel,n),a,s=!1;try{let t=new Promise((e,t)=>{a=setTimeout(()=>{s||t(Error(`Remote transaction timeout after ${r}ms`))},r)}),n=e(i),o=n instanceof Promise?n:Promise.resolve(n),c=await Promise.race([o,t]);return s=!0,a&&clearTimeout(a),await i._commit(),c}catch(e){s=!0,a&&clearTimeout(a);try{await i._rollback()}catch(e){o.error(`Remote rollback failed:`,e)}throw e}}getSQLiteInfo(){let e=this.isHost?this.dbHost!==null:this.initialized&&!this.closed;return{config:this.sqliteConfig,isInitialized:this.initialized,isHost:this.isHost,isReady:e,tabId:this.tabId,hasDatabase:this.dbHost!==null,usesWorker:this.dbHost?.isWorkerDbActive()??!1,activeStorageBackend:this.dbHost?.getActiveStorageBackend()??`unknown`,activeOpfsVfs:this.dbHost?.getActiveOpfsVfs()}}getActiveStorageBackend(){return this.dbHost?.getActiveStorageBackend()??`unknown`}};export{v as a,g as c,m as d,d as f,x as i,_ as l,l as m,C as n,f as o,u as p,S as r,h as s,T as t,p as u};
//# sourceMappingURL=browser2.mjs.map

@@ -1,2 +0,2 @@

const e=require(`./cloudflare-do2.cjs`);async function t(e){let t=n();switch(t){case`node`:let{NodeAdapter:n}=await Promise.resolve().then(()=>require(`./node2.cjs`));return new n(e);case`browser`:let{BrowserAdapter:r}=await Promise.resolve().then(()=>require(`./browser3.cjs`));return r.create(e);case`cloudflare`:let{CloudflareDOAdapter:i}=await Promise.resolve().then(()=>require(`./cloudflare-do.cjs`));return new i(e);default:throw Error(`Unsupported platform: ${t}`)}}function n(){if(typeof globalThis<`u`){if(globalThis.process?.versions?.node)return`node`;if(globalThis.navigator?.userAgent===`Cloudflare-Workers`)return`cloudflare`;if(globalThis.navigator?.userAgent)return`browser`}return`unknown`}exports.CloudflareDOAdapter=e.t,exports.createCloudflareDOAdapter=e.n,exports.openStore=t;
const e=require(`./cloudflare-do2.cjs`);async function t(e){let t=n();switch(t){case`node`:let{NodeAdapter:n}=await Promise.resolve().then(()=>require(`./node3.cjs`));return new n(e);case`browser`:let{BrowserAdapter:r}=await Promise.resolve().then(()=>require(`./browser3.cjs`));return r.create(e);case`cloudflare`:let{CloudflareDOAdapter:i}=await Promise.resolve().then(()=>require(`./cloudflare-do.cjs`));return new i(e);default:throw Error(`Unsupported platform: ${t}`)}}function n(){if(typeof globalThis<`u`){if(globalThis.process?.versions?.node)return`node`;if(globalThis.navigator?.userAgent===`Cloudflare-Workers`)return`cloudflare`;if(globalThis.navigator?.userAgent)return`browser`}return`unknown`}exports.CloudflareDOAdapter=e.t,exports.createCloudflareDOAdapter=e.n,exports.openStore=t;
//# sourceMappingURL=index.cjs.map

@@ -1,2 +0,2 @@

import{n as e,t}from"./cloudflare-do2.mjs";async function n(e){let t=r();switch(t){case`node`:let{NodeAdapter:n}=await import(`./node2.mjs`);return new n(e);case`browser`:let{BrowserAdapter:r}=await import(`./browser3.mjs`);return r.create(e);case`cloudflare`:let{CloudflareDOAdapter:i}=await import(`./cloudflare-do.mjs`);return new i(e);default:throw Error(`Unsupported platform: ${t}`)}}function r(){if(typeof globalThis<`u`){if(globalThis.process?.versions?.node)return`node`;if(globalThis.navigator?.userAgent===`Cloudflare-Workers`)return`cloudflare`;if(globalThis.navigator?.userAgent)return`browser`}return`unknown`}export{t as CloudflareDOAdapter,e as createCloudflareDOAdapter,n as openStore};
import{n as e,t}from"./cloudflare-do2.mjs";async function n(e){let t=r();switch(t){case`node`:let{NodeAdapter:n}=await import(`./node3.mjs`);return new n(e);case`browser`:let{BrowserAdapter:r}=await import(`./browser3.mjs`);return r.create(e);case`cloudflare`:let{CloudflareDOAdapter:i}=await import(`./cloudflare-do.mjs`);return new i(e);default:throw Error(`Unsupported platform: ${t}`)}}function r(){if(typeof globalThis<`u`){if(globalThis.process?.versions?.node)return`node`;if(globalThis.navigator?.userAgent===`Cloudflare-Workers`)return`cloudflare`;if(globalThis.navigator?.userAgent)return`browser`}return`unknown`}export{t as CloudflareDOAdapter,e as createCloudflareDOAdapter,n as openStore};
//# sourceMappingURL=index.mjs.map

@@ -1,2 +0,2 @@

const e=require(`./node3.cjs`);function t(t){return new e.t(t)}exports.NodeAdapter=e.t,exports.openNodeStore=t;
const e=require(`./node2.cjs`);function t(t){return new e.t(t)}exports.NodeAdapter=e.t,exports.openNodeStore=t;
//# sourceMappingURL=node.cjs.map

@@ -1,2 +0,2 @@

import{t as e}from"./node3.mjs";function t(t){return new e(t)}export{e as NodeAdapter,t as openNodeStore};
import{t as e}from"./node2.mjs";function t(t){return new e(t)}export{e as NodeAdapter,t as openNodeStore};
//# sourceMappingURL=node.mjs.map

@@ -1,1 +0,2 @@

const e=require(`./node3.cjs`);exports.NodeAdapter=e.t;
const e=require(`./chunk.cjs`),t=require(`./base.cjs`);let n=require(`debug`);n=e.t(n);let r=require(`better-sqlite3`);r=e.t(r);const i=`unisqlite`,a=`0.4.0`;function o(e){let t=(0,n.default)(`${i}:${e}`),r=(0,n.default)(`${i}:${e}:warn`),a=(0,n.default)(`${i}:${e}:error`);return a.enabled=!0,{log:t,warn:r,error:a}}const s=o(`node`);var c=class extends t.t{constructor(e){super(e),this._closed=!1,s.log(`UniSQLite v0.4.0 - Opening database: ${e.path}`),this.db=new r.default(e.path,{fileMustExist:!1}),this.db.pragma(`journal_mode = WAL`),this.db.pragma(`busy_timeout = 5000`),s.log(`Database opened with WAL mode`)}normalizeParams(e){return e?Array.isArray(e)?e:Object.values(e):[]}convertBuffersToUint8Array(e){if(e==null)return e;if(Buffer.isBuffer(e))return new Uint8Array(e);if(Array.isArray(e))return e.map(e=>this.convertBuffersToUint8Array(e));if(typeof e==`object`){let t={};for(let[n,r]of Object.entries(e))t[n]=this.convertBuffersToUint8Array(r);return t}return e}checkConnection(){if(this._closed||!this.db.open)throw Error(`Database connection is closed`)}async query(e,t){this.checkConnection();let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r);return this.convertBuffersToUint8Array(i)}async queryRaw(e,t){this.checkConnection();let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r),a=n.columns().map(e=>e.name);return{rows:this.convertBuffersToUint8Array(i),columns:a,rowsAffected:0,lastInsertRowId:0}}async run(e,t){this.checkConnection();let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.run(r);return{rowsAffected:i.changes,lastInsertRowId:i.lastInsertRowid}}async exec(e){this.checkConnection(),this.db.exec(e)}transaction(e){this.checkConnection(),this.db.exec(`BEGIN`);let t=new u(this.db);return(async()=>{try{let n=await e(t);return this.db.exec(`COMMIT`),n}catch(e){throw this.db.exec(`ROLLBACK`),e}})()}async asyncTransaction(e,t){this.checkConnection();let n=t?.timeoutMs??3e4,r=!1;try{this.db.exec(`BEGIN IMMEDIATE`)}catch(e){if(e.message.includes(`cannot start a transaction within a transaction`))r=!0;else throw e}let i,a=!1;try{let t=new Promise((e,t)=>{i=setTimeout(()=>{a||t(Error(`Async transaction timeout after ${n}ms`))},n)}),o=new d(this.db),s=await Promise.race([e(o),t]);return a=!0,i&&clearTimeout(i),r||this.db.exec(`COMMIT`),s}catch(e){a=!0,i&&clearTimeout(i);try{this.db.exec(`ROLLBACK`)}catch(e){s.error(`Rollback failed:`,e)}throw e}}getConnectionType(){return`direct`}async close(){!this._closed&&this.db.open&&(this.db.close(),this._closed=!0)}get isOpen(){return!this._closed&&this.db.open}},l=class{constructor(e){this.db=e,this.inTransaction=!0}normalizeParams(e){return e?Array.isArray(e)?e:Object.values(e):[]}convertBuffersToUint8Array(e){if(e==null)return e;if(Buffer.isBuffer(e))return new Uint8Array(e);if(Array.isArray(e))return e.map(e=>this.convertBuffersToUint8Array(e));if(typeof e==`object`){let t={};for(let[n,r]of Object.entries(e))t[n]=this.convertBuffersToUint8Array(r);return t}return e}query(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r),a=this.convertBuffersToUint8Array(i);return Promise.resolve(a)}queryRaw(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r),a=n.columns().map(e=>e.name),o={rows:this.convertBuffersToUint8Array(i),columns:a,rowsAffected:0,lastInsertRowId:0};return Promise.resolve(o)}run(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.run(r),a={rowsAffected:i.changes,lastInsertRowId:i.lastInsertRowid};return Promise.resolve(a)}exec(e){return this.db.exec(e),Promise.resolve()}querySync(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r);return this.convertBuffersToUint8Array(i)}runSync(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.run(r);return{rowsAffected:i.changes,lastInsertRowId:i.lastInsertRowid}}execSync(e){this.db.exec(e)}async close(){}},u=class extends l{getConnectionType(){return`syncTxn`}async transaction(e){return await e(this)}async asyncTransaction(e,t){throw Error(`asyncTransaction is not supported in syncTxn connections. Use transaction() instead or create a direct connection.`)}},d=class extends l{getConnectionType(){return`asyncTxn`}async transaction(e){return await e(this)}async asyncTransaction(e,t){return await e(this)}};Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return c}});
//# sourceMappingURL=node2.cjs.map

@@ -1,1 +0,2 @@

import{t as e}from"./node3.mjs";export{e as NodeAdapter};
import{t as e}from"./base.mjs";import t from"debug";import n from"better-sqlite3";const r=`unisqlite`;function i(e){let n=t(`${r}:${e}`),i=t(`${r}:${e}:warn`),a=t(`${r}:${e}:error`);return a.enabled=!0,{log:n,warn:i,error:a}}const a=i(`node`);var o=class extends e{constructor(e){super(e),this._closed=!1,a.log(`UniSQLite v0.4.0 - Opening database: ${e.path}`),this.db=new n(e.path,{fileMustExist:!1}),this.db.pragma(`journal_mode = WAL`),this.db.pragma(`busy_timeout = 5000`),a.log(`Database opened with WAL mode`)}normalizeParams(e){return e?Array.isArray(e)?e:Object.values(e):[]}convertBuffersToUint8Array(e){if(e==null)return e;if(Buffer.isBuffer(e))return new Uint8Array(e);if(Array.isArray(e))return e.map(e=>this.convertBuffersToUint8Array(e));if(typeof e==`object`){let t={};for(let[n,r]of Object.entries(e))t[n]=this.convertBuffersToUint8Array(r);return t}return e}checkConnection(){if(this._closed||!this.db.open)throw Error(`Database connection is closed`)}async query(e,t){this.checkConnection();let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r);return this.convertBuffersToUint8Array(i)}async queryRaw(e,t){this.checkConnection();let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r),a=n.columns().map(e=>e.name);return{rows:this.convertBuffersToUint8Array(i),columns:a,rowsAffected:0,lastInsertRowId:0}}async run(e,t){this.checkConnection();let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.run(r);return{rowsAffected:i.changes,lastInsertRowId:i.lastInsertRowid}}async exec(e){this.checkConnection(),this.db.exec(e)}transaction(e){this.checkConnection(),this.db.exec(`BEGIN`);let t=new c(this.db);return(async()=>{try{let n=await e(t);return this.db.exec(`COMMIT`),n}catch(e){throw this.db.exec(`ROLLBACK`),e}})()}async asyncTransaction(e,t){this.checkConnection();let n=t?.timeoutMs??3e4,r=!1;try{this.db.exec(`BEGIN IMMEDIATE`)}catch(e){if(e.message.includes(`cannot start a transaction within a transaction`))r=!0;else throw e}let i,o=!1;try{let t=new Promise((e,t)=>{i=setTimeout(()=>{o||t(Error(`Async transaction timeout after ${n}ms`))},n)}),a=new l(this.db),s=await Promise.race([e(a),t]);return o=!0,i&&clearTimeout(i),r||this.db.exec(`COMMIT`),s}catch(e){o=!0,i&&clearTimeout(i);try{this.db.exec(`ROLLBACK`)}catch(e){a.error(`Rollback failed:`,e)}throw e}}getConnectionType(){return`direct`}async close(){!this._closed&&this.db.open&&(this.db.close(),this._closed=!0)}get isOpen(){return!this._closed&&this.db.open}},s=class{constructor(e){this.db=e,this.inTransaction=!0}normalizeParams(e){return e?Array.isArray(e)?e:Object.values(e):[]}convertBuffersToUint8Array(e){if(e==null)return e;if(Buffer.isBuffer(e))return new Uint8Array(e);if(Array.isArray(e))return e.map(e=>this.convertBuffersToUint8Array(e));if(typeof e==`object`){let t={};for(let[n,r]of Object.entries(e))t[n]=this.convertBuffersToUint8Array(r);return t}return e}query(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r),a=this.convertBuffersToUint8Array(i);return Promise.resolve(a)}queryRaw(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r),a=n.columns().map(e=>e.name),o={rows:this.convertBuffersToUint8Array(i),columns:a,rowsAffected:0,lastInsertRowId:0};return Promise.resolve(o)}run(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.run(r),a={rowsAffected:i.changes,lastInsertRowId:i.lastInsertRowid};return Promise.resolve(a)}exec(e){return this.db.exec(e),Promise.resolve()}querySync(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r);return this.convertBuffersToUint8Array(i)}runSync(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.run(r);return{rowsAffected:i.changes,lastInsertRowId:i.lastInsertRowid}}execSync(e){this.db.exec(e)}async close(){}},c=class extends s{getConnectionType(){return`syncTxn`}async transaction(e){return await e(this)}async asyncTransaction(e,t){throw Error(`asyncTransaction is not supported in syncTxn connections. Use transaction() instead or create a direct connection.`)}},l=class extends s{getConnectionType(){return`asyncTxn`}async transaction(e){return await e(this)}async asyncTransaction(e,t){return await e(this)}};export{o as t};
//# sourceMappingURL=node2.mjs.map

@@ -1,2 +0,1 @@

const e=require(`./chunk.cjs`),t=require(`./base.cjs`);let n=require(`better-sqlite3`);n=e.t(n);var r=class extends t.t{constructor(e){super(e),this._closed=!1,this.db=new n.default(e.path,{fileMustExist:!1}),this.db.pragma(`journal_mode = WAL`),this.db.pragma(`busy_timeout = 5000`)}normalizeParams(e){return e?Array.isArray(e)?e:Object.values(e):[]}convertBuffersToUint8Array(e){if(e==null)return e;if(Buffer.isBuffer(e))return new Uint8Array(e);if(Array.isArray(e))return e.map(e=>this.convertBuffersToUint8Array(e));if(typeof e==`object`){let t={};for(let[n,r]of Object.entries(e))t[n]=this.convertBuffersToUint8Array(r);return t}return e}checkConnection(){if(this._closed||!this.db.open)throw Error(`Database connection is closed`)}async query(e,t){this.checkConnection();let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r);return this.convertBuffersToUint8Array(i)}async queryRaw(e,t){this.checkConnection();let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r),a=n.columns().map(e=>e.name);return{rows:this.convertBuffersToUint8Array(i),columns:a,rowsAffected:0,lastInsertRowId:0}}async run(e,t){this.checkConnection();let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.run(r);return{rowsAffected:i.changes,lastInsertRowId:i.lastInsertRowid}}async exec(e){this.checkConnection(),this.db.exec(e)}transaction(e){this.checkConnection(),this.db.exec(`BEGIN`);let t=new a(this.db);return(async()=>{try{let n=await e(t);return this.db.exec(`COMMIT`),n}catch(e){throw this.db.exec(`ROLLBACK`),e}})()}async asyncTransaction(e,t){this.checkConnection();let n=t?.timeoutMs??3e4,r=!1;try{this.db.exec(`BEGIN IMMEDIATE`)}catch(e){if(e.message.includes(`cannot start a transaction within a transaction`))r=!0;else throw e}let i,a=!1;try{let t=new Promise((e,t)=>{i=setTimeout(()=>{a||t(Error(`Async transaction timeout after ${n}ms`))},n)}),s=new o(this.db),c=await Promise.race([e(s),t]);return a=!0,i&&clearTimeout(i),r||this.db.exec(`COMMIT`),c}catch(e){a=!0,i&&clearTimeout(i);try{this.db.exec(`ROLLBACK`)}catch(e){console.error(`Rollback failed:`,e)}throw e}}getConnectionType(){return`direct`}async close(){!this._closed&&this.db.open&&(this.db.close(),this._closed=!0)}get isOpen(){return!this._closed&&this.db.open}},i=class{constructor(e){this.db=e,this.inTransaction=!0}normalizeParams(e){return e?Array.isArray(e)?e:Object.values(e):[]}convertBuffersToUint8Array(e){if(e==null)return e;if(Buffer.isBuffer(e))return new Uint8Array(e);if(Array.isArray(e))return e.map(e=>this.convertBuffersToUint8Array(e));if(typeof e==`object`){let t={};for(let[n,r]of Object.entries(e))t[n]=this.convertBuffersToUint8Array(r);return t}return e}query(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r),a=this.convertBuffersToUint8Array(i);return Promise.resolve(a)}queryRaw(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r),a=n.columns().map(e=>e.name),o={rows:this.convertBuffersToUint8Array(i),columns:a,rowsAffected:0,lastInsertRowId:0};return Promise.resolve(o)}run(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.run(r),a={rowsAffected:i.changes,lastInsertRowId:i.lastInsertRowid};return Promise.resolve(a)}exec(e){return this.db.exec(e),Promise.resolve()}querySync(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r);return this.convertBuffersToUint8Array(i)}runSync(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.run(r);return{rowsAffected:i.changes,lastInsertRowId:i.lastInsertRowid}}execSync(e){this.db.exec(e)}async close(){}},a=class extends i{getConnectionType(){return`syncTxn`}async transaction(e){return await e(this)}async asyncTransaction(e,t){throw Error(`asyncTransaction is not supported in syncTxn connections. Use transaction() instead or create a direct connection.`)}},o=class extends i{getConnectionType(){return`asyncTxn`}async transaction(e){return await e(this)}async asyncTransaction(e,t){return await e(this)}};Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return r}});
//# sourceMappingURL=node3.cjs.map
const e=require(`./node2.cjs`);exports.NodeAdapter=e.t;

@@ -1,2 +0,1 @@

import{t as e}from"./base.mjs";import t from"better-sqlite3";var n=class extends e{constructor(e){super(e),this._closed=!1,this.db=new t(e.path,{fileMustExist:!1}),this.db.pragma(`journal_mode = WAL`),this.db.pragma(`busy_timeout = 5000`)}normalizeParams(e){return e?Array.isArray(e)?e:Object.values(e):[]}convertBuffersToUint8Array(e){if(e==null)return e;if(Buffer.isBuffer(e))return new Uint8Array(e);if(Array.isArray(e))return e.map(e=>this.convertBuffersToUint8Array(e));if(typeof e==`object`){let t={};for(let[n,r]of Object.entries(e))t[n]=this.convertBuffersToUint8Array(r);return t}return e}checkConnection(){if(this._closed||!this.db.open)throw Error(`Database connection is closed`)}async query(e,t){this.checkConnection();let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r);return this.convertBuffersToUint8Array(i)}async queryRaw(e,t){this.checkConnection();let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r),a=n.columns().map(e=>e.name);return{rows:this.convertBuffersToUint8Array(i),columns:a,rowsAffected:0,lastInsertRowId:0}}async run(e,t){this.checkConnection();let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.run(r);return{rowsAffected:i.changes,lastInsertRowId:i.lastInsertRowid}}async exec(e){this.checkConnection(),this.db.exec(e)}transaction(e){this.checkConnection(),this.db.exec(`BEGIN`);let t=new i(this.db);return(async()=>{try{let n=await e(t);return this.db.exec(`COMMIT`),n}catch(e){throw this.db.exec(`ROLLBACK`),e}})()}async asyncTransaction(e,t){this.checkConnection();let n=t?.timeoutMs??3e4,r=!1;try{this.db.exec(`BEGIN IMMEDIATE`)}catch(e){if(e.message.includes(`cannot start a transaction within a transaction`))r=!0;else throw e}let i,o=!1;try{let t=new Promise((e,t)=>{i=setTimeout(()=>{o||t(Error(`Async transaction timeout after ${n}ms`))},n)}),s=new a(this.db),c=await Promise.race([e(s),t]);return o=!0,i&&clearTimeout(i),r||this.db.exec(`COMMIT`),c}catch(e){o=!0,i&&clearTimeout(i);try{this.db.exec(`ROLLBACK`)}catch(e){console.error(`Rollback failed:`,e)}throw e}}getConnectionType(){return`direct`}async close(){!this._closed&&this.db.open&&(this.db.close(),this._closed=!0)}get isOpen(){return!this._closed&&this.db.open}},r=class{constructor(e){this.db=e,this.inTransaction=!0}normalizeParams(e){return e?Array.isArray(e)?e:Object.values(e):[]}convertBuffersToUint8Array(e){if(e==null)return e;if(Buffer.isBuffer(e))return new Uint8Array(e);if(Array.isArray(e))return e.map(e=>this.convertBuffersToUint8Array(e));if(typeof e==`object`){let t={};for(let[n,r]of Object.entries(e))t[n]=this.convertBuffersToUint8Array(r);return t}return e}query(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r),a=this.convertBuffersToUint8Array(i);return Promise.resolve(a)}queryRaw(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r),a=n.columns().map(e=>e.name),o={rows:this.convertBuffersToUint8Array(i),columns:a,rowsAffected:0,lastInsertRowId:0};return Promise.resolve(o)}run(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.run(r),a={rowsAffected:i.changes,lastInsertRowId:i.lastInsertRowid};return Promise.resolve(a)}exec(e){return this.db.exec(e),Promise.resolve()}querySync(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.all(r);return this.convertBuffersToUint8Array(i)}runSync(e,t){let n=this.db.prepare(e),r=this.normalizeParams(t),i=n.run(r);return{rowsAffected:i.changes,lastInsertRowId:i.lastInsertRowid}}execSync(e){this.db.exec(e)}async close(){}},i=class extends r{getConnectionType(){return`syncTxn`}async transaction(e){return await e(this)}async asyncTransaction(e,t){throw Error(`asyncTransaction is not supported in syncTxn connections. Use transaction() instead or create a direct connection.`)}},a=class extends r{getConnectionType(){return`asyncTxn`}async transaction(e){return await e(this)}async asyncTransaction(e,t){return await e(this)}};export{n as t};
//# sourceMappingURL=node3.mjs.map
import{t as e}from"./node2.mjs";export{e as NodeAdapter};
{
"name": "@loro-dev/unisqlite",
"type": "module",
"version": "0.4.0",
"version": "0.5.0",
"description": "Cross-platform concurrent SQLite access layer",

@@ -6,0 +6,0 @@ "author": "",

@@ -529,3 +529,3 @@ /**

} catch (rollbackError) {
console.error("Rollback failed:", rollbackError);
logger.error("Rollback failed:", rollbackError);
}

@@ -576,3 +576,3 @@ throw e;

} catch (rollbackError) {
console.error("Rollback failed:", rollbackError);
logger.error("Rollback failed:", rollbackError);
}

@@ -632,3 +632,3 @@

} catch (rollbackError) {
console.error("Remote rollback failed:", rollbackError);
logger.error("Remote rollback failed:", rollbackError);
}

@@ -635,0 +635,0 @@

@@ -17,2 +17,3 @@ /**

} from "../../types.js";
import { wasmLogger as logger, VERSION } from "./logger.js";

@@ -115,3 +116,3 @@ // =============================================================================

async initialize(): Promise<void> {
console.log(`Loading SQLite WASM using strategy: ${this.config.loadStrategy}`);
logger.log(`UniSQLite v${VERSION} - Loading SQLite WASM using strategy: ${this.config.loadStrategy}`);

@@ -121,4 +122,4 @@ const sqlite3InitModule = await this.loadSQLiteWasm();

const initOptions: SQLiteInitOptions = {
print: console.log,
printErr: console.error,
print: (...args: unknown[]) => logger.log(...args),
printErr: (...args: unknown[]) => logger.error(...args),
};

@@ -135,3 +136,3 @@

console.log("Initializing SQLite WASM module...");
logger.log("Initializing SQLite WASM module...");
this.sqlite3 = await sqlite3InitModule(initOptions);

@@ -142,3 +143,3 @@ if (!this.sqlite3) {

const sqlite3 = this.sqlite3;
console.log("SQLite WASM module initialized successfully");
logger.log("SQLite WASM module initialized successfully");

@@ -149,3 +150,3 @@ const storageBackend = this.config.storageBackend ?? "auto";

if (storageBackend === "memory" || this.dbName === ":memory:") {
console.log("Using in-memory database");
logger.log("Using in-memory database");
this.db = new sqlite3.oo1.DB(":memory:");

@@ -156,3 +157,3 @@ this.activeStorageBackend = "memory";

if (!dbCreated) {
console.log("All persistent storage backends failed, using in-memory database");
logger.log("All persistent storage backends failed, using in-memory database");
this.db = new sqlite3.oo1.DB(":memory:");

@@ -166,5 +167,5 @@ this.activeStorageBackend = "memory";

await this.execInternal("PRAGMA journal_mode=WAL");
console.log("Enabled WAL mode");
logger.log("Enabled WAL mode");
} catch (e) {
console.warn("Could not enable WAL mode:", e);
logger.warn("Could not enable WAL mode:", e);
}

@@ -239,3 +240,3 @@ }

} catch (e) {
console.warn("Failed to close SQLite worker database:", e);
logger.warn("Failed to close SQLite worker database:", e);
} finally {

@@ -478,3 +479,3 @@ this.workerDbId = undefined;

} catch (error) {
console.warn("Failed to load SQLite WASM from npm, falling back to CDN:", error);
logger.warn("Failed to load SQLite WASM from npm, falling back to CDN:", error);
return this.loadFromCdn(this.config.cdnBaseUrl!, this.config.version!, this.config.bundlerFriendly);

@@ -494,9 +495,9 @@ }

try {
console.log(`Trying to load SQLite WASM from: ${url}`);
logger.log(`Trying to load SQLite WASM from: ${url}`);
const module = await import(url);
console.log(`Successfully loaded SQLite WASM from: ${url}`);
logger.log(`Successfully loaded SQLite WASM from: ${url}`);
return (module.default || module) as SQLiteInitModule;
} catch (error) {
lastError = error;
console.warn(`Failed to load SQLite WASM from ${url}:`, error);
logger.warn(`Failed to load SQLite WASM from ${url}:`, error);
}

@@ -525,3 +526,3 @@ }

} catch (error) {
console.warn(`Failed to load SQLite WASM from ${path}:`, error);
logger.warn(`Failed to load SQLite WASM from ${path}:`, error);
}

@@ -596,3 +597,3 @@ }

} catch (error) {
console.warn("Failed to load SQLite WASM worker promiser from npm, falling back to CDN:", error);
logger.warn("Failed to load SQLite WASM worker promiser from npm, falling back to CDN:", error);
return this.loadWorkerPromiserFromCdn(this.config.cdnBaseUrl!, this.config.version!, this.config.bundlerFriendly);

@@ -613,3 +614,3 @@ }

try {
console.log(`Trying to load SQLite WASM worker promiser from: ${url}`);
logger.log(`Trying to load SQLite WASM worker promiser from: ${url}`);
const module = await import(url);

@@ -619,3 +620,3 @@ const promiser = (module as unknown as { sqlite3Worker1Promiser?: SQLiteWorker1PromiserFactory })

if (typeof promiser === "function") {
console.log(`Successfully loaded SQLite WASM worker promiser from: ${url}`);
logger.log(`Successfully loaded SQLite WASM worker promiser from: ${url}`);
return promiser;

@@ -626,3 +627,3 @@ }

lastError = error;
console.warn(`Failed to load SQLite WASM worker promiser from ${url}:`, error);
logger.warn(`Failed to load SQLite WASM worker promiser from ${url}:`, error);
}

@@ -660,3 +661,3 @@ }

} catch (error) {
console.warn(`Failed to load SQLite WASM worker promiser from ${path}:`, error);
logger.warn(`Failed to load SQLite WASM worker promiser from ${path}:`, error);
}

@@ -720,9 +721,9 @@ }

try {
console.log("Creating localStorage-backed database:", this.dbName);
logger.log("Creating localStorage-backed database:", this.dbName);
this.db = new sqlite3.oo1.JsStorageDb(this.dbName);
this.activeStorageBackend = "localStorage";
console.log("Successfully created localStorage-backed database");
logger.log("Successfully created localStorage-backed database");
return true;
} catch (e) {
console.warn("localStorage database creation failed:", e);
logger.warn("localStorage database creation failed:", e);
if (storageBackend === "localStorage") {

@@ -738,3 +739,3 @@ throw new Error(`localStorage database creation failed: ${e instanceof Error ? e.message : String(e)}`);

} else {
console.log(`Skipping localStorage: path '${this.dbName}' is not 'local' or 'session'`);
logger.log(`Skipping localStorage: path '${this.dbName}' is not 'local' or 'session'`);
}

@@ -769,3 +770,3 @@ } else if (storageBackend === "localStorage") {

try {
console.log("Creating OPFS-backed database (OpfsDb):", dbFileName);
logger.log("Creating OPFS-backed database (OpfsDb):", dbFileName);
this.db = new sqlite3.oo1.OpfsDb(dbFileName);

@@ -775,6 +776,6 @@ this.workerDbId = undefined;

this.activeOpfsVfs = "opfs";
console.log("Successfully created OPFS-backed database (OpfsDb)");
logger.log("Successfully created OPFS-backed database (OpfsDb)");
return true;
} catch (e) {
console.warn("OPFS database creation via OpfsDb failed:", e);
logger.warn("OPFS database creation via OpfsDb failed:", e);
}

@@ -789,3 +790,3 @@ }

try {
console.log("Creating SAHPool OPFS-backed database:", dbFileName);
logger.log("Creating SAHPool OPFS-backed database:", dbFileName);
this.db = new sqlite3.oo1.DB(dbFileName, "c", "opfs-sahpool");

@@ -795,6 +796,6 @@ this.workerDbId = undefined;

this.activeOpfsVfs = "opfs-sahpool";
console.log("Successfully created SAHPool OPFS-backed database");
logger.log("Successfully created SAHPool OPFS-backed database");
return true;
} catch (e) {
console.warn("SAHPool OPFS database creation failed:", e);
logger.warn("SAHPool OPFS database creation failed:", e);
}

@@ -818,3 +819,3 @@ }

} catch (e) {
console.warn("SAHPool VFS lookup failed:", e);
logger.warn("SAHPool VFS lookup failed:", e);
}

@@ -832,3 +833,3 @@

} catch (e) {
console.warn("SAHPool VFS installation failed:", e);
logger.warn("SAHPool VFS installation failed:", e);
return false;

@@ -869,3 +870,3 @@ }

} catch (e) {
console.warn("Failed to create Worker from custom workerUrl:", e);
logger.warn("Failed to create Worker from custom workerUrl:", e);
return undefined;

@@ -1050,6 +1051,6 @@ }

this.activeOpfsVfs = vfsName;
console.log(`Successfully created OPFS-backed database via wrapped worker (${vfsName}):`, dbFileName);
logger.log(`Successfully created OPFS-backed database via wrapped worker (${vfsName}):`, dbFileName);
return true;
} catch (e) {
console.warn(`Wrapped-worker OPFS database creation failed (vfs=${vfsName}):`, e);
logger.warn(`Wrapped-worker OPFS database creation failed (vfs=${vfsName}):`, e);
return false;

@@ -1056,0 +1057,0 @@ }

@@ -11,2 +11,5 @@ /**

* - `unisqlite:adapter` - Browser adapter logs only
* - `unisqlite:wasm` - SQLite WASM loading and database creation logs
* - `unisqlite:node` - Node.js adapter logs
* - `unisqlite:visibility` - Visibility manager logs
*

@@ -24,2 +27,5 @@ * In browser console:

// Package version - will be output on initialization
export const VERSION = "0.4.0";
/**

@@ -56,2 +62,4 @@ * Logger interface with log, warn, and error methods

export const adapterLogger = createModuleLogger("adapter");
export const wasmLogger = createModuleLogger("wasm");
export const visibilityLogger = createModuleLogger("visibility");

@@ -58,0 +66,0 @@ /**

@@ -9,2 +9,4 @@ /**

import { visibilityLogger as logger } from "./logger.js";
export type VisibilityChangeListener = (visible: boolean) => void;

@@ -33,3 +35,3 @@

} catch (e) {
console.error("Error in visibility change listener:", e);
logger.error("Error in visibility change listener:", e);
}

@@ -36,0 +38,0 @@ });

@@ -12,2 +12,3 @@ import { BaseAdapter } from "./base.js";

import Database from "better-sqlite3";
import { nodeLogger as logger, VERSION } from "./logger.js";

@@ -20,2 +21,3 @@ export class NodeAdapter extends BaseAdapter {

super(options);
logger.log(`UniSQLite v${VERSION} - Opening database: ${options.path}`);
// Open database with WAL mode for better concurrency

@@ -25,2 +27,3 @@ this.db = new Database(options.path, { fileMustExist: false });

this.db.pragma("busy_timeout = 5000"); // 5 second timeout for locks
logger.log("Database opened with WAL mode");
}

@@ -185,3 +188,3 @@

} catch (rollbackError) {
console.error("Rollback failed:", rollbackError);
logger.error("Rollback failed:", rollbackError);
}

@@ -188,0 +191,0 @@

{"version":3,"file":"node3.cjs","names":["BaseAdapter","Database"],"sources":["../src/adapters/node.ts"],"sourcesContent":["import { BaseAdapter } from \"./base.js\";\nimport type {\n QueryResult,\n RunResult,\n SQLiteParams,\n SQLiteValue,\n UniStoreConnection,\n UniStoreOptions,\n ConnectionType,\n} from \"../types.js\";\nimport Database from \"better-sqlite3\";\n\nexport class NodeAdapter extends BaseAdapter {\n private db: Database.Database;\n private _closed: boolean = false;\n\n constructor(options: UniStoreOptions) {\n super(options);\n // Open database with WAL mode for better concurrency\n this.db = new Database(options.path, { fileMustExist: false });\n this.db.pragma(\"journal_mode = WAL\");\n this.db.pragma(\"busy_timeout = 5000\"); // 5 second timeout for locks\n }\n\n private normalizeParams(params?: SQLiteParams): unknown[] {\n if (!params) return [];\n if (Array.isArray(params)) return params;\n // Convert object params to array format for better-sqlite3\n // This is a simplified conversion - in practice you'd need to handle named parameters\n return Object.values(params);\n }\n\n private convertBuffersToUint8Array<T>(value: T): T {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (Buffer.isBuffer(value)) {\n return new Uint8Array(value) as T;\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => this.convertBuffersToUint8Array(item)) as T;\n }\n\n if (typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n result[key] = this.convertBuffersToUint8Array(val);\n }\n return result as T;\n }\n\n return value;\n }\n\n private checkConnection(): void {\n if (this._closed || !this.db.open) {\n throw new Error(\"Database connection is closed\");\n }\n }\n\n async query<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<T[]> {\n this.checkConnection();\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n return this.convertBuffersToUint8Array(rows);\n }\n\n async queryRaw<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<QueryResult<T>> {\n this.checkConnection();\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n const columns = stmt.columns().map((col) => col.name);\n\n return {\n rows: this.convertBuffersToUint8Array(rows),\n columns,\n rowsAffected: 0,\n lastInsertRowId: 0,\n };\n }\n\n async run(sql: string, params?: SQLiteParams): Promise<RunResult> {\n this.checkConnection();\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const info = stmt.run(paramsArray);\n\n return {\n rowsAffected: info.changes,\n lastInsertRowId: info.lastInsertRowid as number,\n };\n }\n\n async exec(sql: string): Promise<void> {\n this.checkConnection();\n this.db.exec(sql);\n }\n\n transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T> {\n this.checkConnection();\n // better-sqlite3 supports synchronous transactions\n this.db.exec(\"BEGIN\");\n const transactionAdapter = new SyncTransactionAdapter(this.db);\n return (async () => {\n try {\n const result = await fn(transactionAdapter);\n this.db.exec(\"COMMIT\");\n return result;\n } catch (error) {\n this.db.exec(\"ROLLBACK\");\n throw error;\n }\n })();\n }\n\n /**\n * Execute an async transaction with manual transaction management.\n * This allows async operations within the transaction but comes with timeout support\n * to prevent long-running transactions from blocking the database.\n *\n * @param fn Transaction function that can contain async operations\n * @param options Transaction options including timeout (default: 30000ms)\n */\n async asyncTransaction<T>(fn: (tx: UniStoreConnection) => Promise<T>, options?: { timeoutMs?: number }): Promise<T> {\n this.checkConnection();\n\n const timeoutMs = options?.timeoutMs ?? 30000; // Default 30 seconds\n let alreadyInTransaction = false;\n\n // Manual transaction management using BEGIN/COMMIT/ROLLBACK\n try {\n this.db.exec(\"BEGIN IMMEDIATE\");\n } catch (e) {\n if ((e as Error).message.includes(\"cannot start a transaction within a transaction\")) {\n alreadyInTransaction = true;\n } else {\n throw e;\n }\n }\n\n let timeoutHandle: NodeJS.Timeout | undefined;\n let transactionCompleted = false;\n\n try {\n // Set up timeout\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n if (!transactionCompleted) {\n reject(new Error(`Async transaction timeout after ${timeoutMs}ms`));\n }\n }, timeoutMs);\n });\n\n const transactionAdapter = new AsyncTransactionAdapter(this.db);\n\n // Race between transaction execution and timeout\n const result = await Promise.race([fn(transactionAdapter), timeoutPromise]);\n\n transactionCompleted = true;\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n\n // If we get here, the transaction completed successfully\n if (!alreadyInTransaction) {\n this.db.exec(\"COMMIT\");\n }\n return result;\n } catch (error) {\n transactionCompleted = true;\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n\n try {\n this.db.exec(\"ROLLBACK\");\n } catch (rollbackError) {\n console.error(\"Rollback failed:\", rollbackError);\n }\n\n throw error;\n }\n }\n\n getConnectionType(): ConnectionType {\n return \"direct\";\n }\n\n async close(): Promise<void> {\n if (!this._closed && this.db.open) {\n this.db.close();\n this._closed = true;\n }\n }\n\n get isOpen(): boolean {\n return !this._closed && this.db.open;\n }\n}\n\nabstract class BaseTransactionAdapter implements UniStoreConnection {\n public readonly inTransaction = true;\n\n constructor(protected db: Database.Database) {}\n\n private normalizeParams(params?: SQLiteParams): unknown[] {\n if (!params) return [];\n if (Array.isArray(params)) return params;\n return Object.values(params);\n }\n\n private convertBuffersToUint8Array<T>(value: T): T {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (Buffer.isBuffer(value)) {\n return new Uint8Array(value) as T;\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => this.convertBuffersToUint8Array(item)) as T;\n }\n\n if (typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n result[key] = this.convertBuffersToUint8Array(val);\n }\n return result as T;\n }\n\n return value;\n }\n\n // Synchronous database methods for use in transactions\n query<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<T[]> {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n const result = this.convertBuffersToUint8Array(rows);\n return Promise.resolve(result);\n }\n\n queryRaw<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<QueryResult<T>> {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n const columns = stmt.columns().map((col) => col.name);\n\n const result = {\n rows: this.convertBuffersToUint8Array(rows),\n columns,\n rowsAffected: 0,\n lastInsertRowId: 0,\n };\n return Promise.resolve(result);\n }\n\n run(sql: string, params?: SQLiteParams): Promise<RunResult> {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const info = stmt.run(paramsArray);\n\n const result = {\n rowsAffected: info.changes,\n lastInsertRowId: info.lastInsertRowid as number,\n };\n return Promise.resolve(result);\n }\n\n exec(sql: string): Promise<void> {\n this.db.exec(sql);\n return Promise.resolve();\n }\n\n // Synchronous versions for use in sync transactions\n querySync<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): T[] {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n return this.convertBuffersToUint8Array(rows);\n }\n\n runSync(sql: string, params?: SQLiteParams): RunResult {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const info = stmt.run(paramsArray);\n\n return {\n rowsAffected: info.changes,\n lastInsertRowId: info.lastInsertRowid as number,\n };\n }\n\n execSync(sql: string): void {\n this.db.exec(sql);\n }\n\n abstract getConnectionType(): ConnectionType;\n abstract transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T>;\n abstract asyncTransaction<T>(\n fn: (tx: UniStoreConnection) => Promise<T>,\n options?: { timeoutMs?: number }\n ): Promise<T>;\n\n async close(): Promise<void> {\n // No-op for transaction\n }\n}\n\nclass SyncTransactionAdapter extends BaseTransactionAdapter {\n getConnectionType(): ConnectionType {\n return \"syncTxn\";\n }\n\n async transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T> {\n // For syncTxn, we can execute the transaction using itself as the connection\n // This allows nested operations within the same transaction\n return await fn(this);\n }\n\n async asyncTransaction<T>(\n _fn: (tx: UniStoreConnection) => Promise<T>,\n _options?: { timeoutMs?: number }\n ): Promise<T> {\n // syncTxn connections cannot run asyncTransaction\n throw new Error(\n \"asyncTransaction is not supported in syncTxn connections. Use transaction() instead or create a direct connection.\"\n );\n }\n}\n\nclass AsyncTransactionAdapter extends BaseTransactionAdapter {\n getConnectionType(): ConnectionType {\n return \"asyncTxn\";\n }\n\n async transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T> {\n // For asyncTxn, we can execute the transaction using itself as the connection\n // This allows nested operations within the same transaction\n return await fn(this);\n }\n\n async asyncTransaction<T>(fn: (tx: UniStoreConnection) => Promise<T>, _options?: { timeoutMs?: number }): Promise<T> {\n // For asyncTxn, we can execute asyncTransaction using itself as the connection\n // This allows nested async operations within the same transaction\n return await fn(this);\n }\n}\n"],"mappings":"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"}
{"version":3,"file":"node3.mjs","names":[],"sources":["../src/adapters/node.ts"],"sourcesContent":["import { BaseAdapter } from \"./base.js\";\nimport type {\n QueryResult,\n RunResult,\n SQLiteParams,\n SQLiteValue,\n UniStoreConnection,\n UniStoreOptions,\n ConnectionType,\n} from \"../types.js\";\nimport Database from \"better-sqlite3\";\n\nexport class NodeAdapter extends BaseAdapter {\n private db: Database.Database;\n private _closed: boolean = false;\n\n constructor(options: UniStoreOptions) {\n super(options);\n // Open database with WAL mode for better concurrency\n this.db = new Database(options.path, { fileMustExist: false });\n this.db.pragma(\"journal_mode = WAL\");\n this.db.pragma(\"busy_timeout = 5000\"); // 5 second timeout for locks\n }\n\n private normalizeParams(params?: SQLiteParams): unknown[] {\n if (!params) return [];\n if (Array.isArray(params)) return params;\n // Convert object params to array format for better-sqlite3\n // This is a simplified conversion - in practice you'd need to handle named parameters\n return Object.values(params);\n }\n\n private convertBuffersToUint8Array<T>(value: T): T {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (Buffer.isBuffer(value)) {\n return new Uint8Array(value) as T;\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => this.convertBuffersToUint8Array(item)) as T;\n }\n\n if (typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n result[key] = this.convertBuffersToUint8Array(val);\n }\n return result as T;\n }\n\n return value;\n }\n\n private checkConnection(): void {\n if (this._closed || !this.db.open) {\n throw new Error(\"Database connection is closed\");\n }\n }\n\n async query<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<T[]> {\n this.checkConnection();\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n return this.convertBuffersToUint8Array(rows);\n }\n\n async queryRaw<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<QueryResult<T>> {\n this.checkConnection();\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n const columns = stmt.columns().map((col) => col.name);\n\n return {\n rows: this.convertBuffersToUint8Array(rows),\n columns,\n rowsAffected: 0,\n lastInsertRowId: 0,\n };\n }\n\n async run(sql: string, params?: SQLiteParams): Promise<RunResult> {\n this.checkConnection();\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const info = stmt.run(paramsArray);\n\n return {\n rowsAffected: info.changes,\n lastInsertRowId: info.lastInsertRowid as number,\n };\n }\n\n async exec(sql: string): Promise<void> {\n this.checkConnection();\n this.db.exec(sql);\n }\n\n transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T> {\n this.checkConnection();\n // better-sqlite3 supports synchronous transactions\n this.db.exec(\"BEGIN\");\n const transactionAdapter = new SyncTransactionAdapter(this.db);\n return (async () => {\n try {\n const result = await fn(transactionAdapter);\n this.db.exec(\"COMMIT\");\n return result;\n } catch (error) {\n this.db.exec(\"ROLLBACK\");\n throw error;\n }\n })();\n }\n\n /**\n * Execute an async transaction with manual transaction management.\n * This allows async operations within the transaction but comes with timeout support\n * to prevent long-running transactions from blocking the database.\n *\n * @param fn Transaction function that can contain async operations\n * @param options Transaction options including timeout (default: 30000ms)\n */\n async asyncTransaction<T>(fn: (tx: UniStoreConnection) => Promise<T>, options?: { timeoutMs?: number }): Promise<T> {\n this.checkConnection();\n\n const timeoutMs = options?.timeoutMs ?? 30000; // Default 30 seconds\n let alreadyInTransaction = false;\n\n // Manual transaction management using BEGIN/COMMIT/ROLLBACK\n try {\n this.db.exec(\"BEGIN IMMEDIATE\");\n } catch (e) {\n if ((e as Error).message.includes(\"cannot start a transaction within a transaction\")) {\n alreadyInTransaction = true;\n } else {\n throw e;\n }\n }\n\n let timeoutHandle: NodeJS.Timeout | undefined;\n let transactionCompleted = false;\n\n try {\n // Set up timeout\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n if (!transactionCompleted) {\n reject(new Error(`Async transaction timeout after ${timeoutMs}ms`));\n }\n }, timeoutMs);\n });\n\n const transactionAdapter = new AsyncTransactionAdapter(this.db);\n\n // Race between transaction execution and timeout\n const result = await Promise.race([fn(transactionAdapter), timeoutPromise]);\n\n transactionCompleted = true;\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n\n // If we get here, the transaction completed successfully\n if (!alreadyInTransaction) {\n this.db.exec(\"COMMIT\");\n }\n return result;\n } catch (error) {\n transactionCompleted = true;\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n\n try {\n this.db.exec(\"ROLLBACK\");\n } catch (rollbackError) {\n console.error(\"Rollback failed:\", rollbackError);\n }\n\n throw error;\n }\n }\n\n getConnectionType(): ConnectionType {\n return \"direct\";\n }\n\n async close(): Promise<void> {\n if (!this._closed && this.db.open) {\n this.db.close();\n this._closed = true;\n }\n }\n\n get isOpen(): boolean {\n return !this._closed && this.db.open;\n }\n}\n\nabstract class BaseTransactionAdapter implements UniStoreConnection {\n public readonly inTransaction = true;\n\n constructor(protected db: Database.Database) {}\n\n private normalizeParams(params?: SQLiteParams): unknown[] {\n if (!params) return [];\n if (Array.isArray(params)) return params;\n return Object.values(params);\n }\n\n private convertBuffersToUint8Array<T>(value: T): T {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (Buffer.isBuffer(value)) {\n return new Uint8Array(value) as T;\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => this.convertBuffersToUint8Array(item)) as T;\n }\n\n if (typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n result[key] = this.convertBuffersToUint8Array(val);\n }\n return result as T;\n }\n\n return value;\n }\n\n // Synchronous database methods for use in transactions\n query<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<T[]> {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n const result = this.convertBuffersToUint8Array(rows);\n return Promise.resolve(result);\n }\n\n queryRaw<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): Promise<QueryResult<T>> {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n const columns = stmt.columns().map((col) => col.name);\n\n const result = {\n rows: this.convertBuffersToUint8Array(rows),\n columns,\n rowsAffected: 0,\n lastInsertRowId: 0,\n };\n return Promise.resolve(result);\n }\n\n run(sql: string, params?: SQLiteParams): Promise<RunResult> {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const info = stmt.run(paramsArray);\n\n const result = {\n rowsAffected: info.changes,\n lastInsertRowId: info.lastInsertRowid as number,\n };\n return Promise.resolve(result);\n }\n\n exec(sql: string): Promise<void> {\n this.db.exec(sql);\n return Promise.resolve();\n }\n\n // Synchronous versions for use in sync transactions\n querySync<T = Record<string, SQLiteValue>>(sql: string, params?: SQLiteParams): T[] {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const rows = stmt.all(paramsArray) as T[];\n return this.convertBuffersToUint8Array(rows);\n }\n\n runSync(sql: string, params?: SQLiteParams): RunResult {\n const stmt = this.db.prepare(sql);\n const paramsArray = this.normalizeParams(params);\n const info = stmt.run(paramsArray);\n\n return {\n rowsAffected: info.changes,\n lastInsertRowId: info.lastInsertRowid as number,\n };\n }\n\n execSync(sql: string): void {\n this.db.exec(sql);\n }\n\n abstract getConnectionType(): ConnectionType;\n abstract transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T>;\n abstract asyncTransaction<T>(\n fn: (tx: UniStoreConnection) => Promise<T>,\n options?: { timeoutMs?: number }\n ): Promise<T>;\n\n async close(): Promise<void> {\n // No-op for transaction\n }\n}\n\nclass SyncTransactionAdapter extends BaseTransactionAdapter {\n getConnectionType(): ConnectionType {\n return \"syncTxn\";\n }\n\n async transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T> {\n // For syncTxn, we can execute the transaction using itself as the connection\n // This allows nested operations within the same transaction\n return await fn(this);\n }\n\n async asyncTransaction<T>(\n _fn: (tx: UniStoreConnection) => Promise<T>,\n _options?: { timeoutMs?: number }\n ): Promise<T> {\n // syncTxn connections cannot run asyncTransaction\n throw new Error(\n \"asyncTransaction is not supported in syncTxn connections. Use transaction() instead or create a direct connection.\"\n );\n }\n}\n\nclass AsyncTransactionAdapter extends BaseTransactionAdapter {\n getConnectionType(): ConnectionType {\n return \"asyncTxn\";\n }\n\n async transaction<T>(fn: (tx: UniStoreConnection) => Promise<T> | T): Promise<T> {\n // For asyncTxn, we can execute the transaction using itself as the connection\n // This allows nested operations within the same transaction\n return await fn(this);\n }\n\n async asyncTransaction<T>(fn: (tx: UniStoreConnection) => Promise<T>, _options?: { timeoutMs?: number }): Promise<T> {\n // For asyncTxn, we can execute asyncTransaction using itself as the connection\n // This allows nested async operations within the same transaction\n return await fn(this);\n }\n}\n"],"mappings":"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"}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display