{"version":3,"file":"index.mjs","names":["FRESH_VERSION_FLAG","resolvePath","FRESH_VERSION_FLAG","#includeValues","#limit","#yielded","#txn","#handleCommitError","#name","MsgpackEncoder","#abortTransaction","#abandonTransaction","TRANSACTION_LOG_ENTRY_HEADER_SIZE"],"sources":["../src/load-binding.ts","../src/backup.ts","../src/util.ts","../src/dbi.ts","../src/dbi-iterator.ts","../src/encoding.ts","../src/store.ts","../src/transaction.ts","../src/database.ts","../src/parse-transaction-log.ts","../src/transaction-log-reader.ts","../src/index.ts"],"sourcesContent":["import type { BackupInfo, BackupOptions, RestoreOptions } from './backup.js';\nimport type { RangeOptions } from './dbi.js';\nimport type { BufferWithDataView, Key } from './encoding.js';\nimport type { StatsAll, StatsDefault, StatsHistogramData } from './stats.js';\nimport type { StoreContext } from './store.js';\nexport type {\n\tGetStatsMethod,\n\tStatsAll,\n\tStatsAllExtras,\n\tStatsBasics,\n\tStatsCurated,\n\tStatsCuratedExtras,\n\tStatsDefault,\n\tStatsHistogramData,\n\tStatsValue,\n} from './stats.js';\nimport { execSync } from 'node:child_process';\nimport { readdirSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport type NativeTransactionOptions = {\n\t/**\n\t * Whether to disable snapshots.\n\t *\n\t * @default false\n\t */\n\tdisableSnapshot?: boolean;\n\n\t/**\n\t * When `true`, an `IsBusy` conflict at commit time is resolved with the\n\t * `RETRY_NOW` sentinel value instead of being rejected. The native layer\n\t * may park on a VT slot before resolving, so the JS retry fires only after\n\t * the conflicting transaction has committed and released its write intent.\n\t *\n\t * Use together with `verificationTable: true` on the database.\n\t *\n\t * @default false\n\t */\n\tcoordinatedRetry?: boolean;\n};\n\nexport type NativeTransaction = {\n\tid: number;\n\tnew (context: NativeDatabase, options?: NativeTransactionOptions): NativeTransaction;\n\tabort(): void;\n\tcommit(resolve: (retrySignal?: number) => void, reject: (err: Error) => void): void;\n\tcommitSync(): void;\n\t// Note that keyLengthOrKeyBuffer can be the length of the key if it was written into the shared buffer, or a direct buffer\n\tget(\n\t\tkeyLengthOrKeyBuffer: number | Buffer,\n\t\tresolve: (value: Buffer | number) => void,\n\t\treject: (err: Error) => void,\n\t\ttxnIdIgnored?: number,\n\t\texpectedVersion?: number\n\t): number;\n\tgetCount(options?: RangeOptions): number;\n\tgetSync(keyLengthOrKeyBuffer: number | Buffer): Buffer | number | undefined;\n\tgetTimestamp(): number;\n\tputSync(key: Key, value: Buffer | Uint8Array, txnId?: number): void;\n\tremoveSync(key: Key): void;\n\tsetTimestamp(timestamp?: number): void;\n\tuseLog(name: string | number): TransactionLog;\n};\n\nexport type LogBuffer = Buffer & { dataView: DataView; logId: number; size: number };\n\nexport type TransactionLogQueryOptions = {\n\tstart?: number;\n\tend?: number;\n\texactStart?: boolean;\n\tstartFromLastFlushed?: boolean;\n\treadUncommitted?: boolean;\n\texclusiveStart?: boolean;\n};\n\nexport type TransactionEntry = { timestamp: number; data: Buffer; endTxn: boolean };\n\n/**\n * A position within a transaction log, identifying a log file by its sequence\n * number and a byte `offset` within that file.\n */\nexport type TransactionLogPosition = { sequence: number; offset: number };\n\n/**\n * A detailed statistics snapshot for a single transaction log store, returned\n * by {@link TransactionLog.getStats}. All sizes are in bytes; timestamps are\n * milliseconds since the Unix epoch.\n *\n * Memory note: `memory.mappedBytes` is virtual address space — the active write\n * file is mapped at the full configured `maxFileSize` on POSIX, so it does not\n * reflect resident memory. `memory.overlayBytes` (POSIX only; 0 on Windows) is\n * the file-backed portion and is the closer proxy for real consumption.\n */\nexport type TransactionLogStats = {\n\tname: string;\n\tpath: string;\n\tfileCount: number;\n\tcurrentSequenceNumber: number;\n\toldestSequenceNumber: number;\n\ttotalSizeBytes: number;\n\tcurrentFileSize: number;\n\tpendingTransactions: number;\n\tuncommittedTransactions: number;\n\treplayGapBytes: number;\n\tmemory: {\n\t\tmappedBytes: number;\n\t\toverlayBytes: number;\n\t\tactiveMaps: number;\n\t};\n\tnextLogPosition: TransactionLogPosition;\n\tlastFlushedPosition: TransactionLogPosition;\n\tlastCommittedPosition: TransactionLogPosition | null;\n\tpurge: {\n\t\toldestFileAgeMs: number;\n\t\tpurgeableFiles: number;\n\t\tretainedUnflushedFiles: number;\n\t\tlastPurgeMs: number;\n\t};\n\ttotals: {\n\t\ttransactionsWritten: number;\n\t\tentriesWritten: number;\n\t\tbytesWritten: number;\n\t\trotations: number;\n\t\tfilesPurged: number;\n\t\tbytesPurged: number;\n\t\tpurgeRuns: number;\n\t\tdatabaseFlushes: number;\n\t\twriteFailures: number;\n\t};\n\tconfig: {\n\t\tmaxFileSize: number;\n\t\tretentionMs: number;\n\t\tmaxAgeThreshold: number;\n\t};\n};\n\nexport type TransactionLog = {\n\tnew (db: NativeDatabase, name: string): TransactionLog;\n\taddEntry(data: Buffer | Uint8Array, txnId?: number): void;\n\tgetLogFileSize(sequenceId?: number): number;\n\tgetStats(): TransactionLogStats;\n\tname: string;\n\tpath: string;\n\tquery(options?: TransactionLogQueryOptions): IterableIterator<TransactionEntry>;\n\t_currentLogBuffer: LogBuffer;\n\t_findPosition(timestamp: number): number;\n\t_getLastCommittedPosition(): Buffer;\n\t_getLastFlushed(): number;\n\t_getMemoryMapOfFile(sequenceId: number): LogBuffer | undefined;\n\t_lastCommittedPosition: Float64Array;\n\t_logBuffers: Map<number, WeakRef<LogBuffer>>;\n};\n\n/**\n * Shape of options that can be passed to the native iterator constructor for\n * the rare case of advanced RocksDB ReadOptions overrides. Common iterator\n * options are passed via the bitmask `flags` argument instead.\n */\nexport type NativeIteratorAdvancedOptions = {\n\tadaptiveReadahead?: boolean;\n\tasyncIO?: boolean;\n\tautoReadaheadSize?: boolean;\n\tbackgroundPurgeOnIteratorCleanup?: boolean;\n\tfillCache?: boolean;\n\treadaheadSize?: number;\n\ttailing?: boolean;\n};\n\n/**\n * The result of a single native iterator step. A number value matches one of\n * the `ITERATOR_RESULT_*` constants. The slow-path object is returned when\n * the data does not fit in the shared key/value buffers, or when the decoder\n * needs a stable value buffer.\n */\nexport type NativeIteratorResult = number | { key: Buffer; value?: Buffer };\n\nexport declare class NativeIteratorCls {\n\tconstructor(\n\t\tcontext: StoreContext,\n\t\tflags: number,\n\t\tstartKeyEnd: number,\n\t\tendKeyStart: number,\n\t\tendKeyEnd: number,\n\t\toptions?: NativeIteratorAdvancedOptions\n\t);\n\tnext(): NativeIteratorResult;\n\treturn(): void;\n\tthrow(err?: unknown): void;\n}\n\nexport type NativeDatabaseMode = 'optimistic' | 'pessimistic';\n\nexport type NativeDatabaseOptions = {\n\tdbWriteBufferSize?: number;\n\tdisableWAL?: boolean;\n\tenableStats?: boolean;\n\tmaxWriteBufferNumber?: number;\n\tmaxWriteBufferSizeToMaintain?: number;\n\tmode?: NativeDatabaseMode;\n\tname?: string;\n\tnoBlockCache?: boolean;\n\tparallelismThreads?: number;\n\treadOnly?: boolean;\n\tstatsLevel?: (typeof stats.StatsLevel)[keyof typeof stats.StatsLevel];\n\ttransactionLogMaxAgeThreshold?: number;\n\ttransactionLogMaxSize?: number;\n\ttransactionLogRetentionMs?: number;\n\ttransactionLogsPath?: string;\n\t/**\n\t * When true, transaction writes to this column family invalidate the\n\t * VerificationTable slot for each written key at write time (not at\n\t * commit time). Enable only for column families whose records are\n\t * cached (e.g. the primary CF of a table). Default: false.\n\t */\n\tverificationTable?: boolean;\n\twriteBufferSize?: number;\n};\n\ntype ResolveCallback<T> = (value: T) => void;\ntype RejectCallback = (err: Error) => void;\n\nexport type UserSharedBufferCallback = () => void;\n\nexport type PurgeLogsOptions = {\n\tbefore?: number;\n\tdestroy?: boolean;\n\t/**\n\t * When `true`, count the entries in each purged log file (extra work) and\n\t * return `PurgedLog[]` instead of the default `string[]` of file paths.\n\t */\n\tincludeEntryCounts?: boolean;\n\tname?: string;\n};\n\n/**\n * A purged transaction log file and the number of entries it held, returned by\n * `purgeLogs()` when `includeEntryCounts` is `true`.\n */\nexport type PurgedLog = { path: string; entries: number };\n\nexport type NativeDatabase = {\n\tnew (): NativeDatabase;\n\taddListener(event: string, callback: (...args: any[]) => void): void;\n\tbackup(\n\t\tresolve: ResolveCallback<number>,\n\t\treject: RejectCallback,\n\t\tbackupDir: string,\n\t\toptions?: BackupOptions\n\t): void;\n\tclear(resolve: ResolveCallback<void>, reject: RejectCallback): void;\n\tclearSync(): void;\n\tclose(): void;\n\tcompact(resolve: ResolveCallback<void>, reject: RejectCallback, start?: Key, end?: Key): void;\n\tcompactSync(start?: Key, end?: Key): void;\n\tcolumns: string[];\n\tcreateCheckpoint(\n\t\tresolve: ResolveCallback<void>,\n\t\treject: RejectCallback,\n\t\ttargetPath: string\n\t): void;\n\tdestroy(): void;\n\tdrop(resolve: ResolveCallback<void>, reject: RejectCallback): void;\n\tdropSync(): void;\n\tflush(resolve: ResolveCallback<void>, reject: RejectCallback): void;\n\tflushSync(): void;\n\tnotify(event: string | BufferWithDataView, args?: any[]): boolean;\n\t// Note that keyLengthOrKeyBuffer can be the length of the key if it was written into the shared buffer, or a direct buffer\n\tget(\n\t\tkeyLengthOrKeyBuffer: number | Buffer,\n\t\tresolve: ResolveCallback<Buffer | number>,\n\t\treject: RejectCallback,\n\t\ttxnId?: number,\n\t\texpectedVersion?: number\n\t): number;\n\tgetCount(options?: RangeOptions, txnId?: number): number;\n\tgetDBIntProperty(propertyName: string): number | undefined;\n\tgetDBProperty(propertyName: string): string | undefined;\n\tgetMonotonicTimestamp(): number;\n\tgetOldestSnapshotTimestamp(): number;\n\tgetStat(statName: string): number | StatsHistogramData;\n\tgetStats(all?: false): StatsDefault;\n\tgetStats(all: true): StatsAll;\n\tgetSync(\n\t\tkeyLengthOrKeyBuffer: number | Buffer,\n\t\tflags: number,\n\t\ttxnId?: number,\n\t\texpectedVersion?: number\n\t): Buffer;\n\tgetUserSharedBuffer(\n\t\tkey: BufferWithDataView,\n\t\tdefaultBuffer: ArrayBuffer,\n\t\tcallback?: UserSharedBufferCallback\n\t): ArrayBuffer;\n\thasLock(key: BufferWithDataView): boolean;\n\tlisteners(event: string | BufferWithDataView): number;\n\tlistLogs(): string[];\n\topened: boolean;\n\topen(path: string, options?: NativeDatabaseOptions): void;\n\tpopulateVersion(keyLengthOrKeyBuffer: number | Buffer, version: number): void;\n\tpurgeLogs(options: PurgeLogsOptions & { includeEntryCounts: true }): PurgedLog[];\n\tpurgeLogs(options?: PurgeLogsOptions & { includeEntryCounts?: false }): string[];\n\tpurgeLogs(options?: PurgeLogsOptions): string[] | PurgedLog[];\n\tputSync(key: BufferWithDataView, value: any, txnId?: number): void;\n\tremoveListener(event: string | BufferWithDataView, callback: () => void): boolean;\n\tremoveSync(key: BufferWithDataView, txnId?: number): void;\n\t// Provide a buffer that is used as the default/shared buffer for keys, where functions that provide a key can do so by assigning the key to the shared buffer and providing the length.\n\t// A null value will reset the buffer.\n\tsetDefaultKeyBuffer(buffer: Buffer | Uint8Array | null): void;\n\t// Provide a buffer that is used as the default/shared buffer for value, where functions that use or return a value can do so by assigning the value to the shared buffer and providing/returning the length.\n\t// A null value will reset the buffer.\n\tsetDefaultValueBuffer(buffer: Buffer | Uint8Array | null): void;\n\t// Provide a Uint32Array(2)-backed buffer used by iterators to communicate\n\t// the key length (index 0) and value length (index 1) of each iteration\n\t// step without per-iteration NAPI property accesses.\n\tsetIteratorState(buffer: Buffer | Uint8Array): void;\n\ttryLock(key: BufferWithDataView, callback?: () => void): boolean;\n\tunlock(key: BufferWithDataView): void;\n\tuseLog(name: string): TransactionLog;\n\tverifyVersion(keyLengthOrKeyBuffer: number | Buffer, version: number): boolean;\n\twithLock(key: BufferWithDataView, callback: () => void | Promise<void>): Promise<void>;\n};\n\nexport type RocksDatabaseConfig = {\n\tblockCacheSize?: number;\n\t/**\n\t * Number of slots in the process-global verification table. Each slot is\n\t * 8 bytes; the default of 128K slots is 1 MB. Set to 0 to disable.\n\t *\n\t * Must be configured before the first database is opened. Once the table\n\t * is materialized, attempts to change this value will throw.\n\t */\n\tverificationTableEntries?: number;\n\tcompactOnClose?: boolean;\n\t/**\n\t * Total memtable memory limit (bytes) shared across every database opened\n\t * in this process. When set, RocksDB uses a single `WriteBufferManager` so\n\t * write buffers are bounded process-wide rather than per database. 0 (the\n\t * default) disables the manager.\n\t *\n\t * Can be updated at runtime; the new size takes effect on the existing\n\t * manager via `SetBufferSize`.\n\t */\n\twriteBufferManagerSize?: number;\n\t/**\n\t * When `true`, memtable memory is \"charged\" against the shared block cache\n\t * so the block cache and write buffers draw from a single pool. During\n\t * write bursts the cache shrinks to make room for memtables; once\n\t * memtables flush, the cache can grow back into the reclaimed space.\n\t *\n\t * Has no effect when the block cache is disabled (size 0) or\n\t * `writeBufferManagerSize` is 0. Must be set on the same `config()` call\n\t * that first enables the manager — changing it after the manager has been\n\t * created has no effect on the running instance.\n\t *\n\t * @default false\n\t */\n\twriteBufferManagerCostToCache?: boolean;\n\t/**\n\t * When `true`, writes are stalled once the manager's `buffer_size` is\n\t * exceeded, providing a hard cap on memtable memory. When `false`,\n\t * memtables are allowed to grow past the limit and flushes are simply\n\t * scheduled more aggressively. Off by default to favor write throughput\n\t * over hard memory bounding.\n\t *\n\t * @default false\n\t */\n\twriteBufferManagerAllowStall?: boolean;\n};\n\nconst nativeExtRE = /\\.node$/;\nconst req = createRequire(import.meta.url);\n\n/**\n * Locates the native binding in the `build` directory, then the `prebuilds`\n * directory.\n *\n * @returns The path to the native binding.\n */\nfunction locateBinding(): string {\n\tconst baseDir = dirname(dirname(fileURLToPath(import.meta.url)));\n\n\t// check build directory\n\tfor (const type of ['Release', 'Debug'] as const) {\n\t\ttry {\n\t\t\tconst dir = join(baseDir, 'build', type);\n\t\t\tconst files = readdirSync(dir);\n\t\t\tfor (const file of files) {\n\t\t\t\tif (nativeExtRE.test(file)) {\n\t\t\t\t\treturn resolve(dir, file);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* v8 ignore next -- @preserve */\n\t\t} catch {}\n\t}\n\n\t// determine the Linux C runtime\n\tlet runtime = '';\n\tif (process.platform === 'linux') {\n\t\tlet isMusl = false;\n\t\ttry {\n\t\t\tisMusl = readFileSync('/usr/bin/ldd', 'utf8').includes('musl');\n\t\t} catch {\n\t\t\t// `/usr/bin/ldd` likely doesn't exist\n\t\t\tif (typeof process.report?.getReport === 'function') {\n\t\t\t\tprocess.report.excludeEnv = true;\n\t\t\t\tconst report = process.report.getReport() as unknown as {\n\t\t\t\t\theader?: { glibcVersionRuntime?: string };\n\t\t\t\t\tsharedObjects?: string[];\n\t\t\t\t};\n\t\t\t\tisMusl =\n\t\t\t\t\t(!report?.header || !report.header.glibcVersionRuntime) &&\n\t\t\t\t\tArray.isArray(report?.sharedObjects) &&\n\t\t\t\t\treport.sharedObjects.some(\n\t\t\t\t\t\t(obj) => obj.includes('libc.musl-') || obj.includes('ld-musl-')\n\t\t\t\t\t);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tisMusl =\n\t\t\t\t\tisMusl || execSync('ldd --version', { encoding: 'utf8', stdio: 'pipe' }).includes('musl');\n\t\t\t} catch {\n\t\t\t\t// ldd may not exist on some systems such as Docker Hardened Images\n\t\t\t}\n\t\t}\n\t\truntime = isMusl ? '-musl' : '-glibc';\n\t}\n\n\t// the following lines are non-trivial to test, so we'll ignore them\n\t/* v8 ignore next 10 -- @preserve */\n\n\t// check node_modules\n\ttry {\n\t\treturn require.resolve(`@harperfast/rocksdb-js-${process.platform}-${process.arch}${runtime}`);\n\t} catch {}\n\n\tthrow new Error('Unable to locate rocksdb-js native binding');\n}\n\nexport type RegistryStatusDB = {\n\tpath: string;\n\trefCount: number;\n\tcolumnFamilies: string[];\n\ttransactions: number;\n\tclosables: number;\n\tlocks: number;\n\tuserSharedBuffers: number;\n\tlistenerCallbacks: number;\n};\n\nexport type RegistryStatus = RegistryStatusDB[];\n\nconst bindingPath = locateBinding();\n// console.log(`Loading binding from ${bindingPath}`);\nconst binding = req(bindingPath);\n\nexport const config: (options: RocksDatabaseConfig) => void = binding.config;\nexport const FRESH_VERSION_FLAG: number = binding.constants.FRESH_VERSION_FLAG;\nexport const addGlobalListener: (event: string, callback: (...args: any[]) => void) => void =\n\tbinding.addListener;\nexport const removeGlobalListener: (event: string, callback: (...args: any[]) => void) => boolean =\n\tbinding.removeListener;\nexport const globalListenerCount: (event: string) => number = binding.listenerCount;\nexport const globalNotify: (event: string, args?: any[]) => boolean = binding.notify;\nexport const constants: {\n\tALWAYS_CREATE_NEW_BUFFER_FLAG: number;\n\tNOT_IN_MEMORY_CACHE_FLAG: number;\n\tONLY_IF_IN_MEMORY_CACHE_FLAG: number;\n\tPOPULATE_VERSION_FLAG: number;\n\tFRESH_VERSION_FLAG: number;\n\t/**\n\t * Sentinel value resolved (not rejected) by `commit()` when\n\t * `coordinatedRetry: true` and the transaction encountered an IsBusy\n\t * conflict. JS should retry the transaction body immediately.\n\t */\n\tRETRY_NOW_VALUE: number;\n\tTRANSACTION_LOG_TOKEN: number;\n\tTRANSACTION_LOG_ENTRY_HEADER_SIZE: number;\n\tTRANSACTION_LOG_FILE_HEADER_SIZE: number;\n\tITERATOR_REVERSE_FLAG: number;\n\tITERATOR_INCLUSIVE_END_FLAG: number;\n\tITERATOR_EXCLUSIVE_START_FLAG: number;\n\tITERATOR_INCLUDE_VALUES_FLAG: number;\n\tITERATOR_NEEDS_STABLE_VALUE_BUFFER_FLAG: number;\n\tITERATOR_CONTEXT_IS_TRANSACTION_FLAG: number;\n\tITERATOR_RESULT_DONE: number;\n\tITERATOR_RESULT_FAST: number;\n} = binding.constants;\nexport const NativeDatabase: NativeDatabase = binding.Database;\nexport const NativeIterator: typeof NativeIteratorCls = binding.Iterator;\nexport const NativeTransaction: NativeTransaction = binding.Transaction;\nexport const TransactionLog: TransactionLog = binding.TransactionLog;\nexport const registryStatus: () => RegistryStatus = binding.registryStatus;\nexport const shutdown: () => void = binding.shutdown;\nexport const currentThreadId: () => number = binding.currentThreadId;\n\n/**\n * Advises the kernel that the file-backed pages of every mapped transaction log\n * are cold (Linux MADV_COLD), so they are reclaimed first under memory pressure\n * without being freed — useful during replication catch-up, where a full read of\n * the logs would otherwise inflate the container's reclaimable cache toward its\n * cgroup limit. No-op on kernels < 5.4, macOS, and Windows.\n *\n * The transaction log registry is a process-global singleton shared across all\n * worker threads, so a single call cools every worker's maps. Call it on an\n * interval from one thread (e.g. an `unref()`ed timer on the main thread).\n *\n * @returns the number of maps cooled and total file-backed bytes advised.\n */\nexport const coolTransactionLogs: () => { maps: number; bytes: number } =\n\tbinding.coolTransactionLogs;\n\n/**\n * Number of live transaction-log memory maps across the process. Internal —\n * used by tests to verify that releasing a frozen log's external buffer unmaps\n * the underlying mapping rather than leaving it retained.\n */\nexport const transactionLogMapCount: () => number = binding.transactionLogMapCount;\n\n// Module-level backup management functions. These operate on a backup directory\n// and do not require an open database. Wrapped by the `backups` namespace in\n// `backup.ts`; creating a backup is a `RocksDatabase` instance method.\nexport const nativeBackupRestore: (\n\tresolve: ResolveCallback<void>,\n\treject: RejectCallback,\n\tbackupDir: string,\n\tdbDir: string,\n\twalDir: string,\n\toptions?: { backupId?: number; keepLogFiles?: boolean; mode?: RestoreOptions['mode'] }\n) => void = binding.backupRestore;\nexport const nativeBackupList: (\n\tresolve: ResolveCallback<BackupInfo[]>,\n\treject: RejectCallback,\n\tbackupDir: string\n) => void = binding.backupList;\nexport const nativeBackupDelete: (\n\tresolve: ResolveCallback<void>,\n\treject: RejectCallback,\n\tbackupDir: string,\n\tbackupId: number\n) => void = binding.backupDelete;\nexport const nativeBackupPurge: (\n\tresolve: ResolveCallback<void>,\n\treject: RejectCallback,\n\tbackupDir: string,\n\tkeepCount: number\n) => void = binding.backupPurge;\nexport const nativeBackupVerify: (\n\tresolve: ResolveCallback<void>,\n\treject: RejectCallback,\n\tbackupDir: string,\n\tbackupId: number,\n\tverifyWithChecksum: boolean\n) => void = binding.backupVerify;\n\nexport const stats: {\n\tStatsLevel: {\n\t\tDisableAll: number;\n\t\tExceptTickers: number;\n\t\tExceptHistogramOrTimers: number;\n\t\tExceptTimers: number;\n\t\tExceptDetailedTimers: number;\n\t\tExceptTimeForMutex: number;\n\t\tAll: number;\n\t};\n} = binding.stats;\n\nexport const version: string = binding.version;\n","import {\n\tnativeBackupDelete,\n\tnativeBackupList,\n\tnativeBackupPurge,\n\tnativeBackupRestore,\n\tnativeBackupVerify,\n} from './load-binding.js';\nimport { mkdir } from 'node:fs/promises';\nimport { resolve as resolvePath } from 'node:path';\n\n/**\n * Options for creating a backup via `db.backup()`.\n *\n * Backups are whole-database: every column family, the manifest, and (unless\n * `backupLogFiles` is disabled) the write-ahead log are captured. A backup is\n * not scoped to an individual `Store`.\n */\nexport interface BackupOptions {\n\t/**\n\t * Flush the memtable before backing up. Defaults to `true` when the database\n\t * was opened with `disableWAL` (otherwise unflushed data would be lost from\n\t * the backup), and `false` otherwise.\n\t */\n\tflushBeforeBackup?: boolean;\n\n\t/**\n\t * Arbitrary application metadata stored with the backup and returned by\n\t * `backups.list()`.\n\t */\n\tmetadata?: string;\n\n\t/**\n\t * Share table/blob files between backups in the same directory to enable\n\t * incremental backups. Defaults to `true`.\n\t */\n\tshareTableFiles?: boolean;\n\n\t/**\n\t * Distinguish shared files by checksum to avoid collisions across databases.\n\t * Defaults to `true`. Only relevant when `shareTableFiles` is enabled.\n\t */\n\tshareFilesWithChecksum?: boolean;\n\n\t/**\n\t * Include write-ahead log files in the backup. Defaults to `true`.\n\t */\n\tbackupLogFiles?: boolean;\n\n\t/**\n\t * `fsync` backup files for crash consistency. Defaults to `true`.\n\t */\n\tsync?: boolean;\n\n\t/**\n\t * Number of background threads used to copy files. Defaults to `1`.\n\t */\n\tmaxBackgroundOperations?: number;\n}\n\n/**\n * The level of incremental restore to perform.\n *\n * - `purgeAllFiles` (default): purge the destination directory and restore all\n *   files from the backup. Destructive but always correct.\n * - `keepLatestDbSessionIdFiles`: efficiently restore a healthy database,\n *   reusing existing files that match the backup.\n * - `verifyChecksum`: reuse existing destination files whose checksums match the\n *   backup, replacing only mismatched/corrupt files.\n */\nexport type RestoreMode = 'purgeAllFiles' | 'keepLatestDbSessionIdFiles' | 'verifyChecksum';\n\n/**\n * Options for restoring a backup via `backups.restore()`.\n */\nexport interface RestoreOptions {\n\t/**\n\t * The backup id to restore. Defaults to the latest non-corrupt backup.\n\t */\n\tbackupId?: number;\n\n\t/**\n\t * Directory to restore write-ahead log files into. Defaults to the database\n\t * directory.\n\t */\n\twalDir?: string;\n\n\t/**\n\t * Keep existing log files in `walDir` rather than overwriting them. Defaults\n\t * to `false`.\n\t */\n\tkeepLogFiles?: boolean;\n\n\t/**\n\t * The restore strategy. Defaults to `purgeAllFiles`, which is destructive.\n\t */\n\tmode?: RestoreMode;\n}\n\n/**\n * Information about a single backup, as returned by `backups.list()`.\n */\nexport interface BackupInfo {\n\t/** The backup id (monotonically increasing integer). */\n\tbackupId: number;\n\t/** Creation time in seconds since the epoch. */\n\ttimestamp: number;\n\t/** Total size in bytes of the backed-up file payloads. */\n\tsize: number;\n\t/** Number of files in the backup (some may be shared with other backups). */\n\tnumberFiles: number;\n\t/** Application metadata supplied when the backup was created. */\n\tappMetadata: string;\n}\n\n/**\n * Backup management operations that act on a backup directory and do not\n * require an open database. To create a backup, use the `db.backup()` instance\n * method instead (it needs a live database for a consistent snapshot).\n *\n * @example\n * ```typescript\n * import { backups } from '@harperfast/rocksdb-js';\n *\n * const id = await db.backup('/path/to/backups');\n * db.close();\n * await backups.restore('/path/to/backups', '/path/to/restored-db');\n * ```\n */\nexport const backups = {\n\t/**\n\t * Restores a database from a backup directory into a (closed) database\n\t * directory. The default mode purges the destination directory, so it must\n\t * not point at a live database.\n\t */\n\tasync restore(backupDir: string, dbDir: string, options?: RestoreOptions): Promise<void> {\n\t\t// Normalize before comparing so trailing slashes or relative/absolute\n\t\t// variants of the same directory can't slip past the guard and let a\n\t\t// destructive restore purge the backup directory itself.\n\t\tif (resolvePath(backupDir) === resolvePath(dbDir)) {\n\t\t\tthrow new Error('Backup directory and database directory must be different');\n\t\t}\n\n\t\tconst walDir = options?.walDir ?? dbDir;\n\t\tawait mkdir(dbDir, { recursive: true });\n\t\tif (walDir !== dbDir) {\n\t\t\tawait mkdir(walDir, { recursive: true });\n\t\t}\n\n\t\treturn new Promise((resolve, reject) =>\n\t\t\tnativeBackupRestore(resolve, reject, backupDir, dbDir, walDir, {\n\t\t\t\tbackupId: options?.backupId,\n\t\t\t\tkeepLogFiles: options?.keepLogFiles,\n\t\t\t\tmode: options?.mode,\n\t\t\t})\n\t\t);\n\t},\n\n\t/**\n\t * Lists the non-corrupt backups in a backup directory, ordered by id.\n\t */\n\tlist(backupDir: string): Promise<BackupInfo[]> {\n\t\treturn new Promise((resolve, reject) => nativeBackupList(resolve, reject, backupDir));\n\t},\n\n\t/**\n\t * Deletes a specific backup. Shared files are reference-counted and only\n\t * removed once no remaining backup references them.\n\t */\n\tdelete(backupDir: string, backupId: number): Promise<void> {\n\t\treturn new Promise((resolve, reject) =>\n\t\t\tnativeBackupDelete(resolve, reject, backupDir, backupId)\n\t\t);\n\t},\n\n\t/**\n\t * Deletes all but the newest `keepCount` backups.\n\t */\n\tpurge(backupDir: string, keepCount: number): Promise<void> {\n\t\treturn new Promise((resolve, reject) =>\n\t\t\tnativeBackupPurge(resolve, reject, backupDir, keepCount)\n\t\t);\n\t},\n\n\t/**\n\t * Verifies a backup's file sizes, and optionally their checksums (which\n\t * requires reading all backed-up data).\n\t */\n\tverify(\n\t\tbackupDir: string,\n\t\tbackupId: number,\n\t\toptions?: { verifyWithChecksum?: boolean }\n\t): Promise<void> {\n\t\treturn new Promise((resolve, reject) =>\n\t\t\tnativeBackupVerify(resolve, reject, backupDir, backupId, options?.verifyWithChecksum ?? false)\n\t\t);\n\t},\n};\n","export type MaybePromise<T> = T | Promise<T>;\n\nexport type MaybePromiseFunction<T> = () => MaybePromise<T>;\n\n/**\n * Parses a duration string into milliseconds.\n *\n * @param duration - The duration string to parse.\n * @returns The duration in milliseconds.\n *\n * @example\n * ```typescript\n * parseDuration('1s'); // 1000\n * parseDuration('1m'); // 60000\n * parseDuration('1h'); // 3600000\n * parseDuration('1d'); // 86400000\n * parseDuration('1ms'); // 1\n * parseDuration('1s 1ms'); // 1001\n * parseDuration('1m 1s'); // 61000\n * parseDuration('foo'); // throws error\n *\n * parseDuration(1000); // 1000\n * parseDuration(60000); // 60000\n * parseDuration(3600000); // 3600000\n * parseDuration(86400000); // 86400000\n * parseDuration(NaN); // throws error\n * ```\n */\nexport function parseDuration(duration: number | string): number {\n\tif (typeof duration === 'number') {\n\t\tif (isNaN(duration) || !isFinite(duration)) {\n\t\t\tthrow new Error(`Invalid duration: ${duration}`);\n\t\t}\n\t\treturn duration;\n\t}\n\n\tlet result = 0;\n\tfor (const part of duration.split(' ')) {\n\t\tconst m = part.match(/^(\\d+)\\s*(ms|s|m|h|d)?$/);\n\t\tif (!m) {\n\t\t\tthrow new Error(`Invalid duration: ${duration}`);\n\t\t}\n\n\t\tconst [, value, unit] = m;\n\t\tlet num = parseInt(value, 10);\n\t\tswitch (unit) {\n\t\t\tcase 's':\n\t\t\t\tnum *= 1000;\n\t\t\t\tbreak;\n\t\t\tcase 'm':\n\t\t\t\tnum *= 1000 * 60;\n\t\t\t\tbreak;\n\t\t\tcase 'h':\n\t\t\t\tnum *= 1000 * 60 * 60;\n\t\t\t\tbreak;\n\t\t\tcase 'd':\n\t\t\t\tnum *= 1000 * 60 * 60 * 24;\n\t\t\t\tbreak;\n\t\t}\n\t\tresult += num;\n\t}\n\treturn result;\n}\n\n/**\n * Helper function handling `MaybePromise` results.\n *\n * If the result originates from a function that could throw an error, wrap it\n * in a function so this function can catch any errors and use a unified error\n * handling mechanism.\n */\nexport function when<T>(\n\tsubject: MaybePromise<T> | MaybePromiseFunction<T>,\n\tcallback?: (value: T) => MaybePromise<T>,\n\terrback?: (reason: any) => T\n): MaybePromise<T> {\n\ttry {\n\t\tlet result: MaybePromise<T>;\n\n\t\tif (typeof subject === 'function') {\n\t\t\tresult = (subject as MaybePromiseFunction<T>)();\n\t\t} else {\n\t\t\tresult = subject;\n\t\t}\n\n\t\tif (result instanceof Promise) {\n\t\t\treturn result.then(callback, errback) as T;\n\t\t}\n\n\t\treturn callback ? callback(result as T) : (result as T);\n\t} catch (error) {\n\t\treturn errback ? errback(error) : Promise.reject(error);\n\t}\n}\n\n/**\n * Polyfill for `Promise.withResolvers`.\n *\n * Note: This can be removed once Node.js 18 and 20 are no longer supported.\n *\n * @returns A tuple of `resolve`, `reject`, and `promise`.\n */\nexport function withResolvers<T>(): {\n\tresolve: (value: T) => void;\n\treject: (reason: any) => void;\n\tpromise: Promise<T>;\n} {\n\tlet resolve, reject;\n\tconst promise = new Promise<T>((res, rej) => {\n\t\tresolve = res;\n\t\treject = rej;\n\t});\n\treturn { resolve, reject, promise };\n}\n","import type { BufferWithDataView, Key } from './encoding.js';\nimport { FRESH_VERSION_FLAG } from './load-binding.js';\nimport type { NativeTransaction, TransactionLog } from './load-binding.js';\nimport type { GetOptions, PutOptions, Store, StoreContext, StoreGetOptions } from './store.js';\nimport type { Transaction } from './transaction.js';\nimport { type MaybePromise, when } from './util.js';\n\nexport interface RocksDBOptions {\n\t/**\n\t * When `true`, RocksDB will do some enhancements for prefetching the data.\n\t * Defaults to `true`. Note that RocksDB defaults this to `false`.\n\t */\n\tadaptiveReadahead?: boolean;\n\n\t/**\n\t * When `true`, RocksDB will prefetch some data async and apply it if reads\n\t * are sequential and its internal automatic prefetching. Defaults to\n\t * `true`. Note that RocksDB defaults this to `false`.\n\t */\n\tasyncIO?: boolean;\n\n\t/**\n\t * When `true`, RocksDB will auto-tune the readahead size during scans\n\t * internally based on the block cache data when block caching is enabled,\n\t * an end key (e.g. upper bound) is set, and prefix is the same as the start\n\t * key. Defaults to `true`.\n\t */\n\tautoReadaheadSize?: boolean;\n\n\t/**\n\t * When `true`, after the iterator is closed, a background job is scheduled\n\t * to flush the job queue and delete obsolete files. Defaults to `true`.\n\t * Note that RocksDB defaults this to `false`.\n\t */\n\tbackgroundPurgeOnIteratorCleanup?: boolean;\n\n\t/**\n\t * When `true`, the iterator will fill the block cache. Filling the block\n\t * cache is not desirable for bulk scans and could impact eviction order.\n\t * Defaults to `false`. Note that RocksDB defaults this to `true`.\n\t */\n\tfillCache?: boolean;\n\n\t/**\n\t * The RocksDB readahead size. RocksDB does auto-readahead for iterators\n\t * when there is more than two reads for a table file. The readahead\n\t * starts at 8KB and doubles on every additional read up to 256KB. This\n\t * option can help if most of the range scans are large and if a larger\n\t * readahead than that enabled by auto-readahead is needed. Using a large\n\t * readahead size (> 2MB) can typically improve the performance of forward\n\t * iteration on spinning disks. Defaults to `0`.\n\t */\n\treadaheadSize?: number;\n\n\t/**\n\t * When `true`, creates a \"tailing iterator\" which is a special iterator\n\t * that has a view of the complete database including newly added data and\n\t * is optimized for sequential reads. This will return records that were\n\t * inserted into the database after the creation of the iterator. Defaults\n\t * to `false`.\n\t */\n\ttailing?: boolean;\n}\n\nexport interface RangeOptions extends RocksDBOptions {\n\t/**\n\t * The range end key, otherwise known as the \"upper bound\". Defaults to\n\t * the last key in the database.\n\t */\n\tend?: Key | Uint8Array;\n\n\t/**\n\t * When `true`, the iterator will exclude the first key if it matches the start key.\n\t * Defaults to `false`.\n\t */\n\texclusiveStart?: boolean;\n\n\t/**\n\t * When `true`, the iterator will include the last key if it matches the end\n\t * key. Defaults to `false`.\n\t */\n\tinclusiveEnd?: boolean;\n\n\t/**\n\t * The range start key, otherwise known as the \"lower bound\". Defaults to\n\t * the first key in the database.\n\t */\n\tstart?: Key | Uint8Array;\n}\n\nexport interface IteratorOptions extends RangeOptions {\n\t// decoder?: (value: any) => any,\n\n\t// exactMatch?: boolean;\n\n\t/**\n\t * The maximum number of entries to yield. When set, iteration stops after\n\t * `limit` entries regardless of the range bounds. Values <= 0 yield nothing.\n\t * Unset means no limit.\n\t */\n\tlimit?: number;\n\n\t/**\n\t * A specific key to match which may result in zero, one, or many values.\n\t */\n\tkey?: Key;\n\n\t// offset?: number;\n\n\t/**\n\t * When `true`, only returns the number of values for the given query.\n\t */\n\tonlyCount?: boolean;\n\n\t/**\n\t * When `true`, the iterator will iterate in reverse order. Defaults to\n\t * `false`.\n\t */\n\treverse?: boolean;\n\n\t// snapshot?: boolean;\n\n\t/**\n\t * When `true`, decodes and returns the value. When `false`, the value is\n\t * omitted. Defaults to `true`.\n\t */\n\tvalues?: boolean;\n\n\t/**\n\t * When `true`, the iterator will only return the values.\n\t */\n\tvaluesOnly?: boolean;\n}\n\nexport interface DBITransactional {\n\ttransaction?: Transaction;\n}\n\n/**\n * The base class for all database operations. This base class is shared by\n * `RocksDatabase` and `Transaction`.\n *\n * This class is not meant to be used directly.\n */\nexport class DBI<T extends DBITransactional | unknown = unknown> {\n\t/**\n\t * The RocksDB context for `get()`, `put()`, and `remove()`.\n\t */\n\t_context: StoreContext;\n\n\t/**\n\t * The database store instance. The store instance is tied to the database\n\t * instance and shared with transaction instances.\n\t */\n\tstore: Store;\n\n\t/**\n\t * Initializes the DBI context.\n\t *\n\t * @param store - The store instance.\n\t * @param transaction - The transaction instance.\n\t */\n\tconstructor(store: Store, transaction?: NativeTransaction) {\n\t\tif (new.target === DBI) {\n\t\t\tthrow new Error('DBI is an abstract class and cannot be instantiated directly');\n\t\t}\n\n\t\t// this ideally should not be public, but JavaScript doesn't support\n\t\t// protected properties\n\t\tthis.store = store;\n\n\t\tthis._context = transaction || store.db;\n\t}\n\n\t/**\n\t * Adds a listener for the given key.\n\t *\n\t * @param event - The event name to add the listener for.\n\t * @param callback - The callback to add.\n\t */\n\taddListener(event: string, callback: (...args: any[]) => void): this {\n\t\tthis.store.db.addListener(event, callback);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Retrieves the value for the given key, then returns the decoded value.\n\t */\n\tget(key: Key, options?: GetOptions & T): MaybePromise<any | undefined> {\n\t\tif (this.store.decoderCopies) {\n\t\t\treturn when(\n\t\t\t\t() => this.getBinaryFast(key, options),\n\t\t\t\t(result) => {\n\t\t\t\t\tif (result === undefined || result === FRESH_VERSION_FLAG) {\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (options?.skipDecode) {\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this.store.decodeValue(result as BufferWithDataView);\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\treturn when(\n\t\t\t() => this.getBinary(key, options),\n\t\t\t(result) =>\n\t\t\t\tresult === undefined || result === FRESH_VERSION_FLAG\n\t\t\t\t\t? result\n\t\t\t\t\t: this.store.encoding === 'binary' || !this.store.decoder || options?.skipDecode\n\t\t\t\t\t\t? result\n\t\t\t\t\t\t: this.store.decodeValue(result as BufferWithDataView)\n\t\t);\n\t}\n\n\t/**\n\t * Retrieves the binary data for the given key. This is just like `get()`,\n\t * but bypasses the decoder.\n\t *\n\t * Note: Used by HDBreplication.\n\t */\n\tgetBinary(key: Key, options?: GetOptions & T): MaybePromise<Buffer | number | undefined> {\n\t\tif (!this.store.isOpen()) {\n\t\t\treturn Promise.reject(new Error('Database not open'));\n\t\t}\n\n\t\treturn this.store.get(this._context, key, true, options as StoreGetOptions);\n\t}\n\n\t/**\n\t * Synchronously retrieves the binary data for the given key.\n\t */\n\tgetBinarySync(key: Key, options?: GetOptions & T): Buffer | number | undefined {\n\t\tif (!this.store.isOpen()) {\n\t\t\tthrow new Error('Database not open');\n\t\t}\n\n\t\treturn this.store.getSync(this._context, key, true, options);\n\t}\n\n\t/**\n\t * Retrieves the binary data for the given key using a preallocated,\n\t * reusable buffer. Data in the buffer is only valid until the next get\n\t * operation (including cursor operations).\n\t *\n\t * Note: The reusable buffer slightly differs from a typical buffer:\n\t * - `.length` is set to the size of the value\n\t * - `.byteLength` is set to the size of the full allocated memory area for\n\t *   the buffer (usually much larger).\n\t */\n\tgetBinaryFast(key: Key, options?: GetOptions & T): MaybePromise<Buffer | number | undefined> {\n\t\tif (!this.store.isOpen()) {\n\t\t\treturn Promise.reject(new Error('Database not open'));\n\t\t}\n\n\t\treturn this.store.get(this._context, key, false, options as StoreGetOptions);\n\t}\n\n\t/**\n\t * Synchronously retrieves the binary data for the given key using a\n\t * preallocated, reusable buffer. Data in the buffer is only valid until the\n\t * next get operation (including cursor operations).\n\t */\n\tgetBinaryFastSync(key: Key, options?: GetOptions & T): Buffer | number | undefined {\n\t\tif (!this.store.isOpen()) {\n\t\t\tthrow new Error('Database not open');\n\t\t}\n\n\t\treturn this.store.getSync(this._context, key, false, options);\n\t}\n\n\t/**\n\t * Retrieves all keys within a range.\n\t */\n\tgetKeys(options?: IteratorOptions & T): any | undefined {\n\t\treturn this.store.getKeys(this._context, options);\n\t}\n\n\t/**\n\t * Retrieves the number of keys within a range.\n\t *\n\t * @param options - The range options.\n\t * @returns The number of keys within the range.\n\t *\n\t * @example\n\t * ```typescript\n\t * const total = db.getKeysCount();\n\t * const range = db.getKeysCount({ start: 'a', end: 'z' });\n\t * ```\n\t */\n\tgetKeysCount(options?: RangeOptions & T): number {\n\t\treturn this.store.getKeysCount(this._context, options);\n\t}\n\n\t/**\n\t * Retrieves a range of keys and their values.\n\t *\n\t * @param options - The iterator options.\n\t * @returns A range iterable.\n\t *\n\t * @example\n\t * ```typescript\n\t * for (const { key, value } of db.getRange()) {\n\t *   console.log({ key, value });\n\t * }\n\t *\n\t * for (const { key, value } of db.getRange({ start: 'a', end: 'z' })) {\n\t *   console.log({ key, value });\n\t * }\n\t * ```\n\t */\n\tgetRange(options?: IteratorOptions & T): any | undefined {\n\t\treturn this.store.getRange(this._context, options);\n\t}\n\n\t/**\n\t * Synchronously retrieves the value for the given key, then returns the\n\t * decoded value.\n\t */\n\tgetSync(key: Key, options?: GetOptions & T): any | undefined {\n\t\tif (this.store.decoderCopies) {\n\t\t\tconst bytes = this.getBinaryFastSync(key, options);\n\t\t\treturn bytes === undefined || bytes === FRESH_VERSION_FLAG\n\t\t\t\t? bytes\n\t\t\t\t: this.store.decodeValue(bytes as BufferWithDataView);\n\t\t}\n\n\t\tif (this.store.encoding === 'binary') {\n\t\t\treturn this.getBinarySync(key, options);\n\t\t}\n\n\t\tif (this.store.decoder) {\n\t\t\tconst result = this.getBinarySync(key, options);\n\t\t\treturn !result || result === FRESH_VERSION_FLAG\n\t\t\t\t? result\n\t\t\t\t: this.store.decodeValue(result as BufferWithDataView);\n\t\t}\n\n\t\tif (!this.store.isOpen()) {\n\t\t\tthrow new Error('Database not open');\n\t\t}\n\n\t\treturn this.store.decodeValue(this.store.getSync(this._context, key, true, options));\n\t}\n\n\t/**\n\t * Gets the number of listeners for the given key.\n\t *\n\t * @param event - The event name to get the listeners for.\n\t * @returns The number of listeners for the given key.\n\t */\n\tlisteners(event: string | BufferWithDataView): number {\n\t\treturn this.store.db.listeners(event);\n\t}\n\n\t/**\n\t * Notifies an event for the given key.\n\t *\n\t * @param event - The event name to emit the event for.\n\t * @param args - The arguments to emit.\n\t * @returns `true` if there were listeners, `false` otherwise.\n\t */\n\tnotify(event: string, ...args: any[]): boolean {\n\t\treturn this.store.db.notify(event, args);\n\t}\n\n\t/**\n\t * Alias for `removeListener()`.\n\t *\n\t * @param event - The event name to remove the listener for.\n\t * @param callback - The callback to remove.\n\t */\n\toff(event: string, callback: (...args: any[]) => void): this {\n\t\tthis.store.db.removeListener(event, callback);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Alias for `addListener()`.\n\t *\n\t * @param event - The event name to add the listener for.\n\t * @param callback - The callback to add.\n\t */\n\ton(event: string, callback: (...args: any[]) => void): this {\n\t\tthis.store.db.addListener(event, callback);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds a one-time listener, then automatically removes it.\n\t *\n\t * @param event - The event name to add the listener for.\n\t * @param callback - The callback to add.\n\t */\n\tonce(event: string, callback: (...args: any[]) => void): this {\n\t\tconst wrapper = (...args: any[]) => {\n\t\t\tthis.removeListener(event, wrapper);\n\t\t\tcallback(...args);\n\t\t};\n\t\tthis.store.db.addListener(event, wrapper);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Stores a value for the given key.\n\t *\n\t * @param key - The key to store the value for.\n\t * @param value - The value to store.\n\t * @param options - The put options.\n\t * @returns The key and value.\n\t *\n\t * @example\n\t * ```typescript\n\t * await db.put('a', 'b');\n\t * ```\n\t */\n\tasync put(key: Key, value: any, options?: PutOptions & T): Promise<void> {\n\t\treturn this.store.putSync(this._context, key, value, options);\n\t}\n\n\t/**\n\t * Synchronously stores a value for the given key.\n\t *\n\t * @param key - The key to store the value for.\n\t * @param value - The value to store.\n\t * @param options - The put options.\n\t * @returns The key and value.\n\t *\n\t * @example\n\t * ```typescript\n\t * db.putSync('a', 'b');\n\t * ```\n\t */\n\tputSync(key: Key, value: any, options?: PutOptions & T): void {\n\t\treturn this.store.putSync(this._context, key, value, options);\n\t}\n\n\t/**\n\t * Removes a value for the given key. If the key does not exist, it will\n\t * not error.\n\t *\n\t * @param key - The key to remove the value for.\n\t * @param options - The remove options.\n\t * @returns The key and value.\n\t *\n\t * @example\n\t * ```typescript\n\t * await db.remove('a');\n\t * ```\n\t */\n\tasync remove(key: Key, options?: T): Promise<void> {\n\t\treturn this.store.removeSync(this._context, key, options);\n\t}\n\n\t/**\n\t * Removes a value for the given key. If the key does not exist, it will\n\t * not error.\n\t *\n\t * @param key - The key to remove the value for.\n\t * @param options - The remove options.\n\t * @returns The key and value.\n\t *\n\t * @example\n\t * ```typescript\n\t * db.removeSync('a');\n\t * ```\n\t */\n\tremoveSync(key: Key, options?: T): void {\n\t\treturn this.store.removeSync(this._context, key, options);\n\t}\n\n\t/**\n\t * Removes an event listener. You must specify the exact same callback that was\n\t * used in `addListener()`.\n\t *\n\t * @param event - The event name to remove the listener for.\n\t * @param callback - The callback to remove.\n\t */\n\tremoveListener(event: string, callback: (value?: any) => void): boolean {\n\t\treturn this.store.db.removeListener(event, callback);\n\t}\n\n\t/**\n\t * Get or create a transaction log instance.\n\t *\n\t * @param name - The name of the transaction log.\n\t * @returns The transaction log.\n\t */\n\tuseLog(name: string | number): TransactionLog {\n\t\treturn this.store.useLog(this._context, name);\n\t}\n}\n","import type { BufferWithDataView, Key } from './encoding.js';\nimport { constants, type NativeIteratorCls, type NativeIteratorResult } from './load-binding.js';\nimport { ITERATOR_STATE, KEY_BUFFER, type Store, VALUE_BUFFER } from './store.js';\n\nconst { ITERATOR_RESULT_DONE, ITERATOR_RESULT_FAST } = constants;\n\nexport interface DBIteratorValue<T> {\n\tkey: Key;\n\tvalue: T;\n}\n\nconst DONE_RESULT: IteratorResult<DBIteratorValue<unknown>> = Object.freeze({\n\tdone: true,\n\tvalue: undefined as unknown,\n}) as IteratorResult<DBIteratorValue<unknown>>;\n\n/**\n * Wraps the `NativeIterator` C++ binding, decoding keys and values from the\n * shared key/value buffers (fast path) or from per-iteration buffers (slow\n * fallback path used for oversized data or stable-buffer decoders).\n *\n * The native `next()` returns a primitive signal (and writes lengths to the\n * shared `ITERATOR_STATE` buffer) instead of constructing a JS result object,\n * so this class is responsible for building the `IteratorResult`.\n */\nexport class DBIterator<T> implements Iterator<DBIteratorValue<T>> {\n\titerator: InstanceType<typeof NativeIteratorCls>;\n\tstore: Store;\n\t#includeValues: boolean;\n\t// When set, iteration stops after this many entries. The native iterator has no\n\t// notion of a count bound, so the limit is enforced here in the JS layer.\n\t#limit: number | undefined;\n\t#yielded = 0;\n\n\tconstructor(\n\t\titerator: InstanceType<typeof NativeIteratorCls>,\n\t\tstore: Store,\n\t\tincludeValues: boolean,\n\t\tlimit?: number\n\t) {\n\t\tthis.iterator = iterator;\n\t\tthis.store = store;\n\t\tthis.#includeValues = includeValues;\n\t\t// Normalize a nullish limit to `undefined` (no limit). A caller passing `null` must not be\n\t\t// read as a 0 limit by the `#yielded >= this.#limit` check below (null coerces to 0).\n\t\tthis.#limit = limit ?? undefined;\n\t}\n\n\t[Symbol.iterator](): Iterator<DBIteratorValue<T>> {\n\t\treturn this;\n\t}\n\n\tnext(): IteratorResult<DBIteratorValue<T>> {\n\t\tif (this.#limit !== undefined && this.#yielded >= this.#limit) {\n\t\t\t// Reached the requested limit: release the native iterator and stop.\n\t\t\tthis.iterator.return?.();\n\t\t\treturn DONE_RESULT as IteratorResult<DBIteratorValue<T>>;\n\t\t}\n\n\t\tconst result: NativeIteratorResult = this.iterator.next();\n\n\t\tif (result === ITERATOR_RESULT_DONE) {\n\t\t\treturn DONE_RESULT as IteratorResult<DBIteratorValue<T>>;\n\t\t}\n\n\t\tthis.#yielded++;\n\t\tconst includeValues = this.#includeValues;\n\t\tconst value: Partial<DBIteratorValue<T>> = {};\n\n\t\tif (result === ITERATOR_RESULT_FAST) {\n\t\t\t// Fast path: key bytes are in the shared KEY_BUFFER, value bytes\n\t\t\t// are in the shared VALUE_BUFFER, and lengths are in ITERATOR_STATE.\n\t\t\tvalue.key = this.store.readKey(KEY_BUFFER, 0, ITERATOR_STATE[0]);\n\t\t\tif (includeValues) {\n\t\t\t\tVALUE_BUFFER.end = ITERATOR_STATE[1];\n\t\t\t\tvalue.value = this.store.decodeValue(VALUE_BUFFER) as T;\n\t\t\t}\n\t\t} else {\n\t\t\t// Slow path: data didn't fit in shared buffers (or decoder needs\n\t\t\t// stable buffer). The native side allocated fresh buffers for us.\n\t\t\tconst slow = result as { key: Buffer; value?: Buffer };\n\t\t\tvalue.key = this.store.decodeKey(slow.key);\n\t\t\tif (includeValues && slow.value !== undefined) {\n\t\t\t\tvalue.value = this.store.decodeValue(slow.value as BufferWithDataView) as T;\n\t\t\t}\n\t\t}\n\n\t\treturn { done: false, value: value as DBIteratorValue<T> };\n\t}\n\n\treturn(value?: any): IteratorResult<DBIteratorValue<T>, any> {\n\t\tthis.iterator.return?.();\n\t\treturn { done: true, value };\n\t}\n\n\tthrow(err: unknown): IteratorResult<DBIteratorValue<T>, any> {\n\t\tthis.iterator.throw?.(err);\n\t\tthrow err;\n\t}\n}\n","import * as orderedBinary from 'ordered-binary';\n\nexport type Key = Key[] | string | symbol | number | boolean | Uint8Array | Buffer | null;\n\nexport interface BufferWithDataView extends Buffer {\n\tdataView: DataView;\n\tstart: number;\n\tend: number;\n}\n\nexport type EncoderFunction = new (options?: any) => Encoder;\n\nexport interface Encoder {\n\tcopyBuffers?: boolean;\n\tdecode?: (buffer: BufferWithDataView, options?: { end: number }) => any;\n\tencode?: (value: any, mode?: number) => Buffer; // | string;\n\tEncoder?: EncoderFunction;\n\tfreezeData?: boolean;\n\tname?: string;\n\tneedsStableBuffer?: boolean;\n\trandomAccessStructure?: boolean;\n\treadKey?: (buffer: Buffer, start: number, end: number, inSequence?: boolean) => any;\n\tstructuredClone?: boolean;\n\tstructures?: any[];\n\tuseFloat32?: boolean;\n\twriteKey?: (key: any, target: Buffer, position: number, inSequence?: boolean) => number;\n}\n\nexport type Encoding = 'binary' | 'ordered-binary' | 'msgpack' | false;\n\nexport interface KeyEncoder {\n\treadKey?: ReadKeyFunction<Key>;\n\twriteKey?: WriteKeyFunction;\n}\n\nexport type KeyEncoding = 'binary' | 'ordered-binary' | 'uint32';\n\nexport type ReadKeyFunction<T> = (source: BufferWithDataView, start: number, end?: number) => T;\nexport type WriteKeyFunction = (key: Key, target: BufferWithDataView, start: number) => number;\n\n/**\n * Initializes the key encoder functions.\n *\n * @param keyEncoding - The key encoding to use.\n * @param keyEncoder - The key encoder to use.\n * @returns The key encoder.\n */\nexport function initKeyEncoder(\n\trequestedKeyEncoding?: KeyEncoding | undefined,\n\tkeyEncoder?: KeyEncoder | undefined\n): { keyEncoding: KeyEncoding; readKey: ReadKeyFunction<Key>; writeKey: WriteKeyFunction } {\n\tconst keyEncoding: KeyEncoding = requestedKeyEncoding ?? 'ordered-binary';\n\n\tif (keyEncoder) {\n\t\tconst { readKey, writeKey } = keyEncoder;\n\t\tif (!readKey || !writeKey) {\n\t\t\tthrow new Error('Custom key encoder must provide both readKey and writeKey');\n\t\t}\n\t\treturn { keyEncoding, readKey, writeKey };\n\t}\n\n\tif (keyEncoding === 'binary') {\n\t\treturn {\n\t\t\tkeyEncoding,\n\t\t\treadKey(source: BufferWithDataView, start: number, end?: number): Uint8Array {\n\t\t\t\treturn Uint8Array.prototype.slice.call(source, start, end);\n\t\t\t},\n\t\t\twriteKey(key: Key, target: BufferWithDataView, start: number): number {\n\t\t\t\tconst keyBuffer = key instanceof Buffer ? key : Buffer.from(String(key));\n\t\t\t\ttarget.set(keyBuffer, start);\n\t\t\t\treturn keyBuffer.length + start;\n\t\t\t},\n\t\t};\n\t}\n\n\tif (keyEncoding === 'uint32') {\n\t\treturn {\n\t\t\tkeyEncoding,\n\t\t\treadKey(source: BufferWithDataView, start: number, _end?: number): number {\n\t\t\t\tif (!source.dataView) {\n\t\t\t\t\tsource.dataView = new DataView(source.buffer);\n\t\t\t\t}\n\t\t\t\treturn source.dataView.getUint32(start, true);\n\t\t\t},\n\t\t\twriteKey(key: Key, target: BufferWithDataView, start: number): number {\n\t\t\t\tconst keyNumber = Number(key);\n\t\t\t\tif (isNaN(keyNumber)) {\n\t\t\t\t\tthrow new TypeError('Key is not a number');\n\t\t\t\t}\n\t\t\t\ttarget.dataView.setUint32(start, keyNumber, true);\n\t\t\t\treturn start + 4;\n\t\t\t},\n\t\t};\n\t}\n\n\tif (keyEncoding === 'ordered-binary') {\n\t\treturn {\n\t\t\tkeyEncoding,\n\t\t\treadKey: orderedBinary.readKey,\n\t\t\twriteKey: orderedBinary.writeKey as WriteKeyFunction,\n\t\t};\n\t}\n\n\tthrow new Error(`Invalid key encoding: ${keyEncoding}`);\n}\n\n/**\n * Creates a fixed-size buffer with a data view, start, and end properties.\n *\n * Note: It uses `Buffer.allocUnsafe()` because it's the fastest by using\n * Node.js's preallocated memory pool, though the memory is not zeroed out.\n *\n * @param size - The size of the buffer.\n * @returns The buffer with a data view.\n */\nexport function createFixedBuffer(size: number): BufferWithDataView {\n\tconst buffer = Buffer.allocUnsafeSlow(size) as BufferWithDataView;\n\tbuffer.dataView = new DataView(buffer.buffer);\n\tbuffer.start = 0;\n\tbuffer.end = 0;\n\treturn buffer;\n}\n","import type { BackupOptions } from './backup.js';\nimport { DBIterator, type DBIteratorValue } from './dbi-iterator.js';\nimport type { DBITransactional, IteratorOptions, RangeOptions } from './dbi.js';\nimport {\n\ttype BufferWithDataView,\n\tcreateFixedBuffer,\n\ttype Encoder,\n\tEncoding,\n\tinitKeyEncoder,\n\ttype Key,\n\ttype KeyEncoding,\n\ttype ReadKeyFunction,\n\ttype WriteKeyFunction,\n} from './encoding.js';\nimport {\n\tconstants,\n\tNativeDatabase,\n\ttype NativeDatabaseOptions,\n\tNativeIterator,\n\tNativeTransaction,\n\tstats,\n\ttype TransactionLog,\n\ttype UserSharedBufferCallback,\n} from './load-binding.js';\nimport { parseDuration } from './util.js';\nimport { ExtendedIterable } from '@harperfast/extended-iterable';\nimport { mkdir } from 'node:fs/promises';\n\nconst {\n\tONLY_IF_IN_MEMORY_CACHE_FLAG,\n\tNOT_IN_MEMORY_CACHE_FLAG,\n\tALWAYS_CREATE_NEW_BUFFER_FLAG,\n\tFRESH_VERSION_FLAG,\n\tPOPULATE_VERSION_FLAG,\n\tITERATOR_REVERSE_FLAG,\n\tITERATOR_INCLUSIVE_END_FLAG,\n\tITERATOR_EXCLUSIVE_START_FLAG,\n\tITERATOR_INCLUDE_VALUES_FLAG,\n\tITERATOR_NEEDS_STABLE_VALUE_BUFFER_FLAG,\n\tITERATOR_CONTEXT_IS_TRANSACTION_FLAG,\n} = constants;\nconst KEY_BUFFER_SIZE = 4096;\n\nexport const KEY_BUFFER: BufferWithDataView = createFixedBuffer(KEY_BUFFER_SIZE);\nexport const VALUE_BUFFER: BufferWithDataView = createFixedBuffer(64 * 1024);\n\n/**\n * Backing buffer for the shared iterator state. Layout (Uint32Array view):\n *   [0] = key length written into KEY_BUFFER by the most recent iterator step\n *   [1] = value length written into VALUE_BUFFER by the most recent step\n */\nexport const ITERATOR_STATE_BUFFER: Buffer = Buffer.allocUnsafeSlow(8);\nexport const ITERATOR_STATE: Uint32Array = new Uint32Array(\n\tITERATOR_STATE_BUFFER.buffer,\n\tITERATOR_STATE_BUFFER.byteOffset,\n\t2\n);\n\nconst MAX_KEY_SIZE = 1024 * 1024; // 1MB\nconst RESET_BUFFER_MODE = 1024;\nconst REUSE_BUFFER_MODE = 512;\nconst SAVE_BUFFER_SIZE = 8192;\n// const WRITE_BUFFER_SIZE = 65536;\n\nexport type StoreContext = NativeDatabase | NativeTransaction;\nexport type StoreGetOptions = GetOptions & DBITransactional;\nexport type StoreIteratorOptions = IteratorOptions & DBITransactional;\nexport type StorePutOptions = PutOptions & DBITransactional;\nexport type StoreRangeOptions = RangeOptions & DBITransactional;\nexport type StoreRemoveOptions = DBITransactional | unknown;\n\nexport type CompactOptions = {\n\tstart?: Key;\n\tend?: Key;\n};\n\n/**\n * Options for the `Store` class.\n */\nexport interface StoreOptions extends Omit<\n\tNativeDatabaseOptions,\n\t'mode' | 'transactionLogRetentionMs'\n> {\n\tdecoder?: Encoder | null;\n\tencoder?: Encoder | null;\n\tencoding?: Encoding;\n\tfreezeData?: boolean;\n\tkeyEncoder?: { readKey?: ReadKeyFunction<Key>; writeKey?: WriteKeyFunction };\n\tkeyEncoding?: KeyEncoding;\n\t// mapSize?: number;\n\t// maxDbs?: number;\n\t// maxFreeSpaceToLoad?: number;\n\t// maxFreeSpaceToRetain?: number;\n\t// maxReaders?: number;\n\tmaxKeySize?: number;\n\t// noReadAhead?: boolean;\n\t// noSync?: boolean;\n\t// overlappingSync?: boolean;\n\t// pageSize?: number;\n\tpessimistic?: boolean;\n\n\t/**\n\t * If `true`, the encoder will use a random access structure.\n\t */\n\trandomAccessStructure?: boolean;\n\n\t/**\n\t * When `true`, the database is opened in read-only mode. Write operations\n\t * will throw an error with code `ERR_DATABASE_READONLY`.\n\t */\n\treadOnly?: boolean;\n\n\tsharedStructuresKey?: symbol;\n\n\t/**\n\t * A string containing the amount of time or the number of milliseconds to\n\t * retain transaction logs before purging.\n\t *\n\t * @default '3d' (3 days)\n\t */\n\ttransactionLogRetention?: number | string;\n\n\t// trackMetrics?: boolean;\n}\n\n/**\n * Options for the `getUserSharedBuffer()` method.\n */\nexport type UserSharedBufferOptions = { callback?: UserSharedBufferCallback };\n\n/**\n * The return type of `getUserSharedBuffer()`.\n */\nexport type ArrayBufferWithNotify = ArrayBuffer & { cancel: () => void; notify: () => void };\n\n/**\n * A store wraps the `NativeDatabase` binding and database settings so that a\n * single database instance can be shared between the main `RocksDatabase`\n * instance and the `Transaction` instance.\n *\n * This store should not be shared between `RocksDatabase` instances.\n */\nexport class Store {\n\t/**\n\t * The database instance.\n\t */\n\tdb: NativeDatabase;\n\n\t/**\n\t * The decoder instance. This is commonly the same as the `encoder`\n\t * instance.\n\t */\n\tdecoder: Encoder | null;\n\n\t/**\n\t * Whether the decoder copies the buffer when encoding values.\n\t */\n\tdecoderCopies: boolean = false;\n\n\t/**\n\t * Whether to disable the write ahead log.\n\t */\n\tdisableWAL: boolean;\n\n\t/**\n\t * Whether to enable RocksDB statistics.\n\t */\n\tenableStats: boolean;\n\n\t/**\n\t * Reusable buffer for encoding values using `writeKey()` when the custom\n\t * encoder does not provide a `encode()` method.\n\t */\n\tencodeBuffer: BufferWithDataView;\n\n\t/**\n\t * The encoder instance.\n\t */\n\tencoder: Encoder | null;\n\n\t/**\n\t * The encoding used to encode values. Defaults to `'msgpack'` in\n\t * `RocksDatabase.open()`.\n\t */\n\tencoding: Encoding | null;\n\n\t/**\n\t * Encoder specific option used to signal that the data should be frozen.\n\t */\n\tfreezeData: boolean;\n\n\t/**\n\t * Reusable buffer for encoding keys.\n\t */\n\tkeyBuffer: BufferWithDataView;\n\n\t/**\n\t * The key encoding to use for keys. Defaults to `'ordered-binary'`.\n\t */\n\tkeyEncoding: KeyEncoding;\n\n\t/**\n\t * The maximum key size.\n\t */\n\tmaxKeySize: number;\n\n\t/**\n\t * The maximum number of memtables that can be queued per column family\n\t * before writes stall. Higher values absorb write bursts while flushes catch\n\t * up, at the cost of memory.\n\t */\n\tmaxWriteBufferNumber?: number;\n\n\t/**\n\t * The bytes of recent memtable history to retain in memory for transaction\n\t * conflict checking. `-1` derives the value from\n\t * `maxWriteBufferNumber * writeBufferSize`.\n\t */\n\tmaxWriteBufferSizeToMaintain?: number;\n\n\t/**\n\t * The total memtable budget in bytes across all column families. When the\n\t * sum of memtables reaches this size, RocksDB flushes the largest one. `0`\n\t * disables the global trigger so per-CF `writeBufferSize` drives flushing.\n\t */\n\tdbWriteBufferSize?: number;\n\n\t/**\n\t * The name of the store (e.g. the column family). Defaults to `'default'`.\n\t */\n\tname: string;\n\n\t/**\n\t * Whether to disable the block cache.\n\t */\n\tnoBlockCache?: boolean;\n\n\t/**\n\t * The number of threads to use for parallel operations. This is a RocksDB\n\t * option. When undefined, the native layer picks\n\t * `max(1, hardware_concurrency() / 2)`.\n\t */\n\tparallelismThreads?: number;\n\n\t/**\n\t * The path to the database.\n\t */\n\tpath: string;\n\n\t/**\n\t * Whether to use pessimistic locking for transactions. When `true`,\n\t * transactions will fail as soon as a conflict is detected. When `false`,\n\t * transactions will only fail when `commit()` is called.\n\t */\n\tpessimistic: boolean;\n\n\t/**\n\t * Whether the database is open in readonly mode. When `true`, write\n\t * operations will throw an error with code `ERR_DATABASE_READONLY`.\n\t */\n\treadOnly: boolean;\n\n\t/**\n\t * Encoder specific flag used to signal that the encoder should use a random\n\t * access structure.\n\t */\n\trandomAccessStructure: boolean;\n\n\t/**\n\t * The function used to encode keys.\n\t */\n\treadKey: ReadKeyFunction<Key>;\n\n\t/**\n\t * The key used to store shared structures.\n\t */\n\tsharedStructuresKey?: symbol;\n\n\t/**\n\t * The level of statistics to capture.\n\t */\n\tstatsLevel?: (typeof stats.StatsLevel)[keyof typeof stats.StatsLevel];\n\n\t/**\n\t * The threshold for the transaction log file's last modified time to be\n\t * older than the retention period before it is rotated to the next sequence\n\t * number. A threshold of 0 means ignore age check.\n\t */\n\ttransactionLogMaxAgeThreshold?: number;\n\n\t/**\n\t * The maximum size of a transaction log before it is rotated to the next\n\t * sequence number.\n\t */\n\ttransactionLogMaxSize?: number;\n\n\t/**\n\t * A string containing the amount of time or the number of milliseconds to\n\t * retain transaction logs before purging.\n\t *\n\t * @default '3d' (3 days)\n\t */\n\ttransactionLogRetention?: number | string;\n\n\t/**\n\t * The path to the transaction logs directory.\n\t */\n\ttransactionLogsPath?: string;\n\n\t/**\n\t * Whether this store's column family participates in the VerificationTable.\n\t */\n\tverificationTable?: boolean;\n\n\t/**\n\t * The per-column-family memtable size in bytes at which the memtable is\n\t * sealed and flushed.\n\t */\n\twriteBufferSize?: number;\n\n\t/**\n\t * The function used to encode keys using the shared `keyBuffer`.\n\t */\n\twriteKey: WriteKeyFunction;\n\n\t/**\n\t * Initializes the store with a new `NativeDatabase` instance.\n\t *\n\t * @param path - The path to the database.\n\t * @param options - The options for the store.\n\t */\n\tconstructor(path: string, options?: StoreOptions) {\n\t\tif (!path || typeof path !== 'string') {\n\t\t\tthrow new TypeError('Invalid database path');\n\t\t}\n\n\t\tif (options !== undefined && options !== null && typeof options !== 'object') {\n\t\t\tthrow new TypeError('Database options must be an object');\n\t\t}\n\n\t\tconst { keyEncoding, readKey, writeKey } = initKeyEncoder(\n\t\t\toptions?.keyEncoding,\n\t\t\toptions?.keyEncoder\n\t\t);\n\n\t\tthis.db = new NativeDatabase();\n\t\tthis.dbWriteBufferSize = options?.dbWriteBufferSize;\n\t\tthis.decoder = options?.decoder ?? null;\n\t\tthis.disableWAL = options?.disableWAL ?? false;\n\t\tthis.enableStats = options?.enableStats ?? false;\n\t\tthis.encodeBuffer = createFixedBuffer(SAVE_BUFFER_SIZE);\n\t\tthis.encoder = options?.encoder ?? null;\n\t\tthis.encoding = options?.encoding ?? null;\n\t\tthis.freezeData = options?.freezeData ?? false;\n\t\tthis.keyBuffer = KEY_BUFFER;\n\t\tthis.keyEncoding = keyEncoding;\n\t\tthis.maxKeySize = options?.maxKeySize ?? MAX_KEY_SIZE;\n\t\tthis.maxWriteBufferNumber = options?.maxWriteBufferNumber;\n\t\tthis.maxWriteBufferSizeToMaintain = options?.maxWriteBufferSizeToMaintain;\n\t\tthis.name = options?.name ?? 'default';\n\t\tthis.noBlockCache = options?.noBlockCache;\n\t\tthis.parallelismThreads = options?.parallelismThreads;\n\t\tthis.path = path;\n\t\tthis.pessimistic = options?.pessimistic ?? false;\n\t\tthis.readOnly = options?.readOnly ?? false;\n\t\tthis.randomAccessStructure = options?.randomAccessStructure ?? false;\n\t\tthis.readKey = readKey;\n\t\tthis.sharedStructuresKey = options?.sharedStructuresKey;\n\t\tthis.statsLevel = options?.statsLevel;\n\t\tthis.transactionLogMaxAgeThreshold = options?.transactionLogMaxAgeThreshold;\n\t\tthis.transactionLogMaxSize = options?.transactionLogMaxSize;\n\t\tthis.transactionLogRetention = options?.transactionLogRetention;\n\t\tthis.transactionLogsPath = options?.transactionLogsPath;\n\t\tthis.verificationTable = options?.verificationTable;\n\t\tthis.writeBufferSize = options?.writeBufferSize;\n\t\tthis.writeKey = writeKey;\n\t}\n\n\t/**\n\t * Closes the database.\n\t */\n\tclose(): void {\n\t\tthis.db.close();\n\t}\n\n\t/**\n\t * Compacts the entire key range of the database asynchronously.\n\t * This triggers manual compaction which removes tombstones and reclaims space.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * await db.compact();\n\t * ```\n\t */\n\tcompact(options?: CompactOptions): Promise<void> {\n\t\tlet startBuffer: Buffer | undefined;\n\t\tlet endBuffer: Buffer | undefined;\n\n\t\tif (options?.start !== undefined) {\n\t\t\tconst start = this.encodeKey(options.start);\n\t\t\tstartBuffer = Buffer.from(start.subarray(start.start, start.end));\n\t\t}\n\t\tif (options?.end !== undefined) {\n\t\t\tconst end = this.encodeKey(options.end);\n\t\t\tendBuffer = Buffer.from(end.subarray(end.start, end.end));\n\t\t}\n\n\t\treturn new Promise((resolve, reject) =>\n\t\t\tthis.db.compact(resolve, reject, startBuffer, endBuffer)\n\t\t);\n\t}\n\n\t/**\n\t * Creates a backup of the entire database (all column families) into the\n\t * given directory and resolves with the new backup id. Parent directories\n\t * are created as needed. See `backups` for restore and management.\n\t *\n\t * @example\n\t * ```typescript\n\t * const id = await db.backup('/path/to/backups');\n\t * ```\n\t */\n\tasync backup(backupDir: string, options?: BackupOptions): Promise<number> {\n\t\tawait mkdir(backupDir, { recursive: true });\n\t\treturn new Promise((resolve, reject) => this.db.backup(resolve, reject, backupDir, options));\n\t}\n\n\t/**\n\t * Compacts the entire key range of the database synchronously.\n\t * This triggers manual compaction which removes tombstones and reclaims space.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * db.compactSync();\n\t * ```\n\t */\n\tcompactSync(options?: CompactOptions): void {\n\t\tlet startBuffer: Buffer | undefined;\n\t\tlet endBuffer: Buffer | undefined;\n\n\t\tif (options?.start !== undefined) {\n\t\t\tconst start = this.encodeKey(options.start);\n\t\t\tstartBuffer = Buffer.from(start.subarray(start.start, start.end));\n\t\t}\n\t\tif (options?.end !== undefined) {\n\t\t\tconst end = this.encodeKey(options.end);\n\t\t\tendBuffer = Buffer.from(end.subarray(end.start, end.end));\n\t\t}\n\n\t\tthis.db.compactSync(startBuffer, endBuffer);\n\t}\n\n\t/**\n\t * Decodes a key from the database.\n\t *\n\t * @param key - The key to decode.\n\t * @returns The decoded key.\n\t */\n\tdecodeKey(key: Buffer): Key {\n\t\treturn this.readKey(key as BufferWithDataView, 0, key.length);\n\t}\n\n\t/**\n\t * Decodes a value from the database.\n\t *\n\t * @param value - The value to decode.\n\t * @returns The decoded value.\n\t */\n\tdecodeValue(value: BufferWithDataView): any {\n\t\tif (value?.length > 0 && typeof this.decoder?.decode === 'function') {\n\t\t\treturn this.decoder.decode(value, { end: value.end });\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Encodes a key for the database.\n\t *\n\t * @param key - The key to encode.\n\t * @returns The encoded key.\n\t */\n\tencodeKey(key: Key): BufferWithDataView {\n\t\tif (key === undefined) {\n\t\t\tthrow new Error('Key is required');\n\t\t}\n\n\t\tconst bytesWritten = this.writeKey(key, this.keyBuffer, 0);\n\t\tif (bytesWritten === 0) {\n\t\t\tthrow new Error('Zero length key is not allowed');\n\t\t}\n\n\t\tthis.keyBuffer.end = bytesWritten;\n\n\t\treturn this.keyBuffer;\n\t}\n\n\t/**\n\t * Encodes a value for the database.\n\t *\n\t * @param value - The value to encode.\n\t * @returns The encoded value.\n\t */\n\tencodeValue(value: any): BufferWithDataView | Uint8Array {\n\t\tif (value && value['\\x10binary-data\\x02']) {\n\t\t\treturn value['\\x10binary-data\\x02'];\n\t\t}\n\n\t\tif (typeof this.encoder?.encode === 'function') {\n\t\t\tif (this.encoder.copyBuffers) {\n\t\t\t\treturn this.encoder.encode(value, REUSE_BUFFER_MODE | RESET_BUFFER_MODE);\n\t\t\t}\n\n\t\t\tconst valueBuffer = this.encoder.encode(value);\n\t\t\tif (typeof valueBuffer === 'string') {\n\t\t\t\treturn Buffer.from(valueBuffer);\n\t\t\t}\n\t\t\treturn valueBuffer;\n\t\t}\n\n\t\tif (typeof value === 'string') {\n\t\t\treturn Buffer.from(value);\n\t\t}\n\n\t\tif (value instanceof Uint8Array) {\n\t\t\treturn value;\n\t\t}\n\n\t\tthrow new Error(`Invalid value put in database (${typeof value}), consider using an encoder`);\n\t}\n\n\tget(\n\t\tcontext: StoreContext,\n\t\tkey: Key,\n\t\talwaysCreateNewBuffer: boolean = false,\n\t\toptions?: StoreGetOptions\n\t): any | undefined {\n\t\tconst keyParam = getKeyParam(this.encodeKey(key));\n\t\tlet flags = 0;\n\t\tif (alwaysCreateNewBuffer) {\n\t\t\t// used by getBinary to force a new safe long-lived buffer\n\t\t\tflags |= ALWAYS_CREATE_NEW_BUFFER_FLAG;\n\t\t}\n\t\tif (options?.populateVersion) {\n\t\t\tflags |= POPULATE_VERSION_FLAG;\n\t\t}\n\t\tconst txnId = this.getTxnId(options);\n\t\tconst expectedVersion = options?.expectedVersion;\n\t\t// getSync is the fast path, which can return immediately if the entry is in memory cache, but we want to fail otherwise\n\t\tconst result = context.getSync(\n\t\t\tkeyParam,\n\t\t\tflags | ONLY_IF_IN_MEMORY_CACHE_FLAG,\n\t\t\ttxnId,\n\t\t\texpectedVersion\n\t\t);\n\t\tif (typeof result === 'number') {\n\t\t\t// return a number indicates it is using the default buffer\n\t\t\tif (result === NOT_IN_MEMORY_CACHE_FLAG) {\n\t\t\t\t// is not in memory cache, use async get since this will involve disk access\n\t\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t\t// We still use the same shared buffer for the key, the native side will make a copy for the async task\n\t\t\t\t\tcontext.get(keyParam, resolve, reject, txnId, expectedVersion);\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (result === FRESH_VERSION_FLAG) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\t// continue with fast path\n\t\t\tVALUE_BUFFER.end = result;\n\t\t\treturn VALUE_BUFFER;\n\t\t} // else it is undefined or it is a new buffer\n\t\treturn result;\n\t}\n\n\tgetCount(context: StoreContext, options?: StoreRangeOptions): number {\n\t\toptions = { ...options };\n\n\t\tif (options?.start !== undefined) {\n\t\t\tconst start = this.encodeKey(options.start);\n\t\t\toptions.start = Buffer.from(start.subarray(start.start, start.end));\n\t\t}\n\n\t\tif (options?.end !== undefined) {\n\t\t\tconst end = this.encodeKey(options.end);\n\t\t\toptions.end = Buffer.from(end.subarray(end.start, end.end));\n\t\t}\n\n\t\treturn context.getCount(options, this.getTxnId(options));\n\t}\n\n\tgetKeys(context: StoreContext, options?: StoreIteratorOptions): any | undefined {\n\t\treturn this.getRange(context, { ...options, values: false }).map((item) => item.key);\n\t}\n\n\tgetKeysCount(context: StoreContext, options?: StoreRangeOptions): number {\n\t\treturn this.getCount(context, options);\n\t}\n\n\tgetRange(\n\t\tcontext: StoreContext,\n\t\toptions?: StoreIteratorOptions\n\t): ExtendedIterable<DBIteratorValue<any>> {\n\t\tif (!this.db.opened) {\n\t\t\tthrow new Error('Database not open');\n\t\t}\n\n\t\t// Resolve start/end keys, honoring the `key` shortcut for single-key\n\t\t// matches and swapping start/end when iterating in reverse.\n\t\tlet startUnencoded = options?.key ?? options?.start;\n\t\tlet endUnencoded = options?.key ?? options?.end;\n\n\t\tconst includeValues = options?.values ?? true;\n\t\tconst reverse = options?.reverse ?? false;\n\n\t\tlet exclusiveStart = options?.exclusiveStart ?? false;\n\t\tlet inclusiveEnd = options?.inclusiveEnd ?? false;\n\t\tif (options?.key !== undefined) {\n\t\t\tinclusiveEnd = true;\n\t\t}\n\n\t\tif (reverse) {\n\t\t\tconst tmp = startUnencoded;\n\t\t\tstartUnencoded = endUnencoded;\n\t\t\tendUnencoded = tmp;\n\t\t\t// preserve previous default behavior: reverse iteration treats\n\t\t\t// missing exclusiveStart/inclusiveEnd as `true`\n\t\t\texclusiveStart = options?.exclusiveStart ?? true;\n\t\t\tinclusiveEnd = options?.inclusiveEnd ?? true;\n\t\t}\n\n\t\t// Encode both keys back-to-back into the shared key buffer. Each key\n\t\t// is identified to the native side by its (start, end) offsets.\n\t\tconst keyBuffer = this.keyBuffer;\n\t\tlet startKeyEnd = 0;\n\t\tlet endKeyStart = 0;\n\t\tlet endKeyEnd = 0;\n\n\t\tif (startUnencoded !== undefined) {\n\t\t\tstartKeyEnd = this.writeKey(startUnencoded, keyBuffer, 0);\n\t\t\tif (startKeyEnd === 0) {\n\t\t\t\tthrow new Error('Zero length key is not allowed');\n\t\t\t}\n\t\t}\n\n\t\tif (endUnencoded !== undefined) {\n\t\t\tif (endUnencoded === startUnencoded) {\n\t\t\t\t// `key` shortcut: reuse the encoded start key bytes\n\t\t\t\tendKeyStart = 0;\n\t\t\t\tendKeyEnd = startKeyEnd;\n\t\t\t} else {\n\t\t\t\tendKeyStart = startKeyEnd;\n\t\t\t\tendKeyEnd = this.writeKey(endUnencoded, keyBuffer, endKeyStart);\n\t\t\t\tif (endKeyEnd === endKeyStart) {\n\t\t\t\t\tthrow new Error('Zero length key is not allowed');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet flags = 0;\n\t\tif (reverse) flags |= ITERATOR_REVERSE_FLAG;\n\t\tif (exclusiveStart) flags |= ITERATOR_EXCLUSIVE_START_FLAG;\n\t\tif (inclusiveEnd) flags |= ITERATOR_INCLUSIVE_END_FLAG;\n\t\tif (includeValues) flags |= ITERATOR_INCLUDE_VALUES_FLAG;\n\t\tif (includeValues && !this.decoderCopies) {\n\t\t\tflags |= ITERATOR_NEEDS_STABLE_VALUE_BUFFER_FLAG;\n\t\t}\n\t\t// Tell the native constructor whether `context` is a Transaction (vs.\n\t\t// the database) so it can skip a napi_instanceof check. The store\n\t\t// holds the canonical NativeDatabase reference, so identity comparison\n\t\t// is sufficient.\n\t\tif (context !== this.db) {\n\t\t\tflags |= ITERATOR_CONTEXT_IS_TRANSACTION_FLAG;\n\t\t}\n\n\t\t// Only pass the advanced ReadOptions object on the rare path where any\n\t\t// of the underlying RocksDB iterator options are actually overridden.\n\t\tconst advancedOptions =\n\t\t\toptions !== undefined &&\n\t\t\t(options.adaptiveReadahead !== undefined ||\n\t\t\t\toptions.asyncIO !== undefined ||\n\t\t\t\toptions.autoReadaheadSize !== undefined ||\n\t\t\t\toptions.backgroundPurgeOnIteratorCleanup !== undefined ||\n\t\t\t\toptions.fillCache !== undefined ||\n\t\t\t\toptions.readaheadSize !== undefined ||\n\t\t\t\toptions.tailing !== undefined)\n\t\t\t\t? options\n\t\t\t\t: undefined;\n\n\t\treturn new ExtendedIterable(\n\t\t\t// @ts-expect-error ExtendedIterable v1 constructor type definition is incorrect\n\t\t\tnew DBIterator(\n\t\t\t\tnew NativeIterator(context, flags, startKeyEnd, endKeyStart, endKeyEnd, advancedOptions),\n\t\t\t\tthis,\n\t\t\t\tincludeValues,\n\t\t\t\toptions?.limit\n\t\t\t)\n\t\t);\n\t}\n\n\tgetSync(\n\t\tcontext: StoreContext,\n\t\tkey: Key,\n\t\talwaysCreateNewBuffer: boolean = false,\n\t\toptions?: StoreGetOptions\n\t): any | undefined {\n\t\tconst keyParam = getKeyParam(this.encodeKey(key));\n\t\tlet flags = 0;\n\t\tif (alwaysCreateNewBuffer) {\n\t\t\tflags |= ALWAYS_CREATE_NEW_BUFFER_FLAG;\n\t\t}\n\t\tif (options?.populateVersion) {\n\t\t\tflags |= POPULATE_VERSION_FLAG;\n\t\t}\n\t\t// we are using the shared buffer for keys, so we just pass in the key ending point (much faster than passing in a buffer)\n\t\tconst result = context.getSync(\n\t\t\tkeyParam,\n\t\t\tflags,\n\t\t\tthis.getTxnId(options),\n\t\t\toptions?.expectedVersion\n\t\t);\n\t\tif (typeof result === 'number') {\n\t\t\tif (result === FRESH_VERSION_FLAG) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\t// return a number indicates it is using the default buffer\n\t\t\tVALUE_BUFFER.end = result;\n\t\t\treturn VALUE_BUFFER;\n\t\t} // else it is undefined or it is a new buffer\n\t\treturn result;\n\t}\n\n\t/**\n\t * Checks if the data method options object contains a transaction ID and\n\t * returns it.\n\t */\n\tgetTxnId(options?: DBITransactional | unknown): number | undefined {\n\t\tlet txnId: number | undefined;\n\t\tif (!this.readOnly && (options as DBITransactional)?.transaction) {\n\t\t\ttxnId = (options as DBITransactional).transaction!.id;\n\t\t\tif (txnId === undefined) {\n\t\t\t\tthrow new TypeError('Invalid transaction');\n\t\t\t}\n\t\t}\n\t\treturn txnId;\n\t}\n\n\t/**\n\t * Gets or creates a buffer that can be shared across worker threads.\n\t *\n\t * @param key - The key to get or create the buffer for.\n\t * @param defaultBuffer - The default buffer to copy and use if the buffer\n\t * does not exist.\n\t * @param [options] - The options for the buffer.\n\t * @param [options.callback] - A optional callback is called when `notify()`\n\t * on the returned buffer is called.\n\t * @returns An `ArrayBuffer` that is internally backed by a rocksdb-js\n\t * managed buffer. The buffer also has `notify()` and `cancel()` methods\n\t * that can be used to notify the specified `options.callback`.\n\t */\n\tgetUserSharedBuffer(\n\t\tkey: Key,\n\t\tdefaultBuffer: ArrayBuffer,\n\t\toptions?: UserSharedBufferOptions\n\t): ArrayBufferWithNotify {\n\t\tconst encodedKey = this.encodeKey(key);\n\n\t\tif (options !== undefined && typeof options !== 'object') {\n\t\t\tthrow new TypeError('Options must be an object');\n\t\t}\n\n\t\tconst buffer = this.db.getUserSharedBuffer(\n\t\t\tencodedKey,\n\t\t\tdefaultBuffer,\n\t\t\toptions?.callback\n\t\t) as ArrayBufferWithNotify;\n\n\t\t// note: the notification methods need to re-encode the key because\n\t\t// encodeKey() uses a shared key buffer\n\t\tbuffer.notify = (...args: any[]) => {\n\t\t\treturn this.db.notify(this.encodeKey(key), args);\n\t\t};\n\t\tbuffer.cancel = () => {\n\t\t\tif (options?.callback) {\n\t\t\t\tthis.db.removeListener(this.encodeKey(key), options.callback);\n\t\t\t}\n\t\t};\n\t\treturn buffer;\n\t}\n\n\t/**\n\t * Checks if a lock exists.\n\t * @param key The lock key.\n\t * @returns `true` if the lock exists, `false` otherwise\n\t */\n\thasLock(key: Key): boolean {\n\t\treturn this.db.hasLock(this.encodeKey(key));\n\t}\n\n\t/**\n\t * Checks if the database is open.\n\t *\n\t * @returns `true` if the database is open, `false` otherwise.\n\t */\n\tisOpen(): boolean {\n\t\treturn this.db.opened;\n\t}\n\n\t/**\n\t * Lists all transaction log names.\n\t *\n\t * @returns an array of transaction log names.\n\t */\n\tlistLogs(): string[] {\n\t\treturn this.db.listLogs();\n\t}\n\n\t/**\n\t * Opens the database. This must be called before any database operations\n\t * are performed.\n\t */\n\topen(): boolean {\n\t\tif (this.db.opened) {\n\t\t\treturn true;\n\t\t}\n\n\t\tthis.db.open(this.path, {\n\t\t\tdbWriteBufferSize: this.dbWriteBufferSize,\n\t\t\tdisableWAL: this.disableWAL,\n\t\t\tenableStats: this.enableStats,\n\t\t\tmaxWriteBufferNumber: this.maxWriteBufferNumber,\n\t\t\tmaxWriteBufferSizeToMaintain: this.maxWriteBufferSizeToMaintain,\n\t\t\tmode: this.pessimistic ? 'pessimistic' : 'optimistic',\n\t\t\tname: this.name,\n\t\t\tnoBlockCache: this.noBlockCache,\n\t\t\tparallelismThreads: this.parallelismThreads,\n\t\t\treadOnly: this.readOnly,\n\t\t\tstatsLevel: this.statsLevel,\n\t\t\ttransactionLogMaxAgeThreshold: this.transactionLogMaxAgeThreshold,\n\t\t\ttransactionLogMaxSize: this.transactionLogMaxSize,\n\t\t\ttransactionLogRetentionMs: this.transactionLogRetention\n\t\t\t\t? parseDuration(this.transactionLogRetention)\n\t\t\t\t: undefined,\n\t\t\ttransactionLogsPath: this.transactionLogsPath,\n\t\t\tverificationTable: this.verificationTable,\n\t\t\twriteBufferSize: this.writeBufferSize,\n\t\t});\n\n\t\treturn false;\n\t}\n\n\tputSync(context: StoreContext, key: Key, value: any, options?: StorePutOptions): void {\n\t\tif (!this.db.opened) {\n\t\t\tthrow new Error('Database not open');\n\t\t}\n\n\t\t// IMPORTANT!\n\t\t// We MUST encode the value before the key because if the `sharedStructuresKey`\n\t\t// is set, it will be used by `getStructures()` and `saveStructures()` which in\n\t\t// turn will encode the `sharedStructuresKey` into the shared `keyBuffer`\n\t\t// overwriting this method's encoded key!\n\t\tconst valueBuffer = this.encodeValue(value);\n\n\t\tcontext.putSync(this.encodeKey(key), valueBuffer, this.getTxnId(options));\n\t}\n\n\tremoveSync(context: StoreContext, key: Key, options?: StoreRemoveOptions): void {\n\t\tif (!this.db.opened) {\n\t\t\tthrow new Error('Database not open');\n\t\t}\n\n\t\tcontext.removeSync(this.encodeKey(key), this.getTxnId(options));\n\t}\n\n\t/**\n\t * Attempts to acquire a lock for a given key. If the lock is available,\n\t * the function returns `true` and the optional callback is never called.\n\t * If the lock is not available, the function returns `false` and the\n\t * callback is queued until the lock is released.\n\t *\n\t * @param key - The key to lock.\n\t * @param onUnlocked - A callback to call when the lock is released.\n\t * @returns `true` if the lock was acquired, `false` otherwise.\n\t */\n\ttryLock(key: Key, onUnlocked?: () => void): boolean {\n\t\tif (onUnlocked !== undefined && typeof onUnlocked !== 'function') {\n\t\t\tthrow new TypeError('Callback must be a function');\n\t\t}\n\n\t\treturn this.db.tryLock(this.encodeKey(key), onUnlocked);\n\t}\n\n\t/**\n\t * Releases the lock on the given key and calls any queued `onUnlocked`\n\t * callback handlers.\n\t *\n\t * @param key - The key to unlock.\n\t */\n\tunlock(key: Key): void {\n\t\treturn this.db.unlock(this.encodeKey(key));\n\t}\n\n\t/**\n\t * Gets or creates a transaction log instance.\n\t *\n\t * @param context - The context to use for the transaction log.\n\t * @param name - The name of the transaction log.\n\t * @returns The transaction log.\n\t */\n\tuseLog(context: StoreContext, name: string | number): TransactionLog {\n\t\tif (typeof name !== 'string' && typeof name !== 'number') {\n\t\t\tthrow new TypeError('Log name must be a string or number');\n\t\t}\n\t\tif (typeof name === 'string' && /[\\t\\n\\r\\\\/]/.test(name)) {\n\t\t\tthrow new Error(`Invalid transaction log name \"${name}\"`);\n\t\t}\n\t\treturn context.useLog(String(name));\n\t}\n\n\t/**\n\t * Checks the process-global verification table for a fresh version match\n\t * on `key`. Returns `true` when the table currently records `version` for\n\t * this database+column-family. Provides a fast cache-freshness check\n\t * before falling back to a full read.\n\t */\n\tverifyVersion(key: Key, version: number): boolean {\n\t\tconst keyParam = getKeyParam(this.encodeKey(key));\n\t\treturn this.db.verifyVersion(keyParam, version);\n\t}\n\n\t/**\n\t * Seeds the verification-table slot for `key` with `version`. Has no\n\t * effect if the slot is currently lock-tagged or the table is disabled.\n\t * Useful after a full read where the caller already knows the version.\n\t */\n\tpopulateVersion(key: Key, version: number): void {\n\t\tconst keyParam = getKeyParam(this.encodeKey(key));\n\t\tthis.db.populateVersion(keyParam, version);\n\t}\n\n\t/**\n\t * Acquires a lock on the given key and calls the callback.\n\t *\n\t * @param key - The key to lock.\n\t * @param callback - The callback to call when the lock is acquired.\n\t * @returns A promise that resolves when the lock is acquired.\n\t */\n\twithLock(key: Key, callback: () => void | Promise<void>): Promise<void> {\n\t\tif (typeof callback !== 'function') {\n\t\t\treturn Promise.reject(new TypeError('Callback must be a function'));\n\t\t}\n\n\t\treturn this.db.withLock(this.encodeKey(key), callback);\n\t}\n}\n\n/**\n * Ensure that they key has been copied into our shared buffer, and return the ending position\n * @param keyBuffer\n */\nfunction getKeyParam(keyBuffer: BufferWithDataView): number | Buffer {\n\tif (keyBuffer.buffer === KEY_BUFFER.buffer) {\n\t\tif (keyBuffer.end >= 0) {\n\t\t\treturn keyBuffer.end;\n\t\t}\n\t\tif (keyBuffer.byteOffset === 0) {\n\t\t\treturn keyBuffer.byteLength;\n\t\t}\n\t}\n\tif (keyBuffer.length > KEY_BUFFER.length) {\n\t\t// for larger key buffers, we pass it straight in\n\t\treturn keyBuffer;\n\t}\n\tKEY_BUFFER.set(keyBuffer);\n\treturn keyBuffer.length;\n}\n\nexport interface GetOptions {\n\t/**\n\t * When set, the native layer checks the verification table before reading.\n\t * If the slot holds this version, returns `FRESH_VERSION_FLAG` immediately\n\t * (the cached value is still valid). After a DB read, also seeds the slot\n\t * with the version extracted from the value.\n\t */\n\texpectedVersion?: number;\n\n\t/**\n\t * When `true`, after a DB read the native layer automatically seeds the\n\t * verification-table slot with the version extracted from the value.\n\t * Eliminates the need for a separate `populateVersion` call on cold reads.\n\t *\n\t * @default false\n\t */\n\tpopulateVersion?: boolean;\n\n\t/**\n\t * Whether to skip decoding the value.\n\t *\n\t * @default false\n\t */\n\tskipDecode?: boolean;\n}\n\nexport interface PutOptions {\n\tappend?: boolean;\n\tinstructedWrite?: boolean;\n\tnoDupData?: boolean;\n\tnoOverwrite?: boolean;\n}\n","import { DBI } from './dbi';\nimport { constants, NativeTransaction, type NativeTransactionOptions } from './load-binding.js';\nimport { Store } from './store.js';\n\n/**\n * Sentinel value returned by `commit()` when `coordinatedRetry: true` and the\n * transaction encountered an IsBusy conflict. The native layer parks on VT\n * slots and resolves only after the conflicting transaction releases its write\n * intent, so callers should retry immediately without any backoff delay.\n */\nexport const RETRY_NOW: number = constants.RETRY_NOW_VALUE;\n\nexport class TransactionAlreadyAbortedError extends Error {\n\treadonly code = 'ERR_ALREADY_ABORTED';\n}\n\nexport class TransactionIsBusyError extends Error {\n\treadonly code = 'ERR_BUSY';\n\treadonly hasLog: boolean;\n\treadonly txn: Transaction;\n\n\tconstructor(error: Error, txn: Transaction) {\n\t\tsuper(error.message);\n\t\tthis.hasLog = (error as Error & { hasLog?: boolean }).hasLog ?? false;\n\t\tthis.txn = txn;\n\t}\n}\n\nexport class TransactionAbandonedError extends Error {\n\treadonly code = 'ERR_TRANSACTION_ABANDONED';\n\treadonly hasLog: boolean;\n\treadonly txn: Transaction;\n\n\tconstructor(error: Error, txn: Transaction) {\n\t\tsuper(error.message);\n\t\tthis.hasLog = (error as Error & { hasLog?: boolean }).hasLog ?? false;\n\t\tthis.txn = txn;\n\t}\n}\n\n/**\n * Provides transaction level operations to a transaction callback.\n */\nexport class Transaction extends DBI {\n\t#txn: NativeTransaction;\n\n\t/**\n\t * Create a new transaction.\n\t *\n\t * @param store - The base store interface for this transaction.\n\t * @param options - The options for the transaction.\n\t */\n\tconstructor(store: Store, options?: NativeTransactionOptions) {\n\t\tif (store.readOnly) {\n\t\t\tsuper(store);\n\t\t\tthis.#txn = { id: 0 } as NativeTransaction;\n\t\t\tthis.abort = this.commitSync = this.setTimestamp = () => {};\n\t\t\tthis.commit = async () => {};\n\t\t\tthis.getTimestamp = () => 0;\n\t\t} else {\n\t\t\tconst txn = new NativeTransaction(store.db, options);\n\t\t\tsuper(store, txn);\n\t\t\tthis.#txn = txn;\n\t\t}\n\t}\n\n\t/**\n\t * Abort the transaction.\n\t */\n\tabort(): void {\n\t\ttry {\n\t\t\tthis.#txn.abort();\n\t\t} catch (err) {\n\t\t\tif (err instanceof Error && 'code' in err && err.code === 'ERR_TRANSACTION_ABANDONED') {\n\t\t\t\tthrow new TransactionAbandonedError(err, this);\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\t/**\n\t * Commit the transaction.\n\t *\n\t * Returns `RETRY_NOW` when `coordinatedRetry: true` and an IsBusy conflict\n\t * was detected. The caller should retry the transaction body immediately.\n\t */\n\tasync commit(): Promise<typeof RETRY_NOW | void> {\n\t\ttry {\n\t\t\tconst result = await new Promise<number | void>((resolve, reject) => {\n\t\t\t\tthis.notify('beforecommit');\n\t\t\t\tthis.#txn.commit(resolve, reject);\n\t\t\t});\n\t\t\tif (result === RETRY_NOW) {\n\t\t\t\treturn RETRY_NOW;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow this.#handleCommitError(err);\n\t\t} finally {\n\t\t\tthis.notify('aftercommit', { next: null, last: null, txnId: this.#txn.id });\n\t\t}\n\t}\n\n\t/**\n\t * Commit the transaction synchronously.\n\t */\n\tcommitSync(): void {\n\t\ttry {\n\t\t\tthis.notify('beforecommit');\n\t\t\tthis.#txn.commitSync();\n\t\t} catch (err) {\n\t\t\tthrow this.#handleCommitError(err);\n\t\t} finally {\n\t\t\tthis.notify('aftercommit', { next: null, last: null, txnId: this.#txn.id });\n\t\t}\n\t}\n\n\t/**\n\t * Detect if error is an already aborted or busy error and return the appropriate error class.\n\t *\n\t * @param err - The error to check.\n\t * @returns The specialized error.\n\t */\n\t#handleCommitError(err: unknown): Error {\n\t\tif (err instanceof Error && 'code' in err) {\n\t\t\tif (err.code === 'ERR_ALREADY_ABORTED') {\n\t\t\t\treturn new TransactionAlreadyAbortedError(err.message);\n\t\t\t}\n\t\t\tif (err.code === 'ERR_BUSY') {\n\t\t\t\treturn new TransactionIsBusyError(err, this);\n\t\t\t}\n\t\t}\n\t\treturn err as Error;\n\t}\n\n\t/**\n\t * Returns the transaction start timestamp in seconds. Defaults to the time at which\n\t * the transaction was created.\n\t *\n\t * @returns The transaction start timestamp in seconds.\n\t */\n\tgetTimestamp(): number {\n\t\treturn this.#txn.getTimestamp();\n\t}\n\n\t/**\n\t * Get the transaction id.\n\t */\n\tget id(): number {\n\t\treturn this.#txn.id;\n\t}\n\n\t/**\n\t * Set the transaction start timestamp in seconds.\n\t *\n\t * @param timestamp - The timestamp to set in seconds.\n\t */\n\tsetTimestamp(timestamp?: number): void {\n\t\tthis.#txn.setTimestamp(timestamp);\n\t}\n}\n","import type { BackupOptions } from './backup.js';\nimport { DBI, type DBITransactional } from './dbi.js';\nimport type { BufferWithDataView, Encoder, EncoderFunction, Key } from './encoding.js';\nimport {\n\taddGlobalListener,\n\tconfig,\n\tglobalListenerCount,\n\tglobalNotify,\n\tremoveGlobalListener,\n\ttype PurgedLog,\n\ttype PurgeLogsOptions,\n\ttype RocksDatabaseConfig,\n\ttype NativeTransactionOptions,\n} from './load-binding.js';\nimport type { StatsAll, StatsDefault, StatsValue } from './stats.js';\nimport {\n\ttype ArrayBufferWithNotify,\n\tCompactOptions,\n\tITERATOR_STATE_BUFFER,\n\tKEY_BUFFER,\n\tStore,\n\ttype StoreOptions,\n\ttype UserSharedBufferOptions,\n\tVALUE_BUFFER,\n} from './store.js';\nimport {\n\tRETRY_NOW,\n\tTransaction,\n\tTransactionAbandonedError,\n\tTransactionAlreadyAbortedError,\n\tTransactionIsBusyError,\n} from './transaction.js';\nimport { Encoder as MsgpackEncoder } from 'msgpackr';\nimport { existsSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport * as orderedBinary from 'ordered-binary';\n\nexport type TransactionCallback<T> = (txn: Transaction, attempt: number) => T | PromiseLike<T>;\n\nexport interface RocksDatabaseOptions extends StoreOptions {\n\t/**\n\t * The column family name.\n\t *\n\t * @default 'default'\n\t */\n\tname?: string;\n}\n\nexport interface TransactionOptions extends NativeTransactionOptions {\n\t/**\n\t * The maximum number of times to retry the transaction.\n\t *\n\t * @default 3\n\t */\n\tmaxRetries?: number;\n\n\t/**\n\t * Whether to retry the transaction if it fails with `IsBusy`.\n\t *\n\t * @default `true` when the transaction is bound to a transaction log, otherwise `false`\n\t */\n\tretryOnBusy?: boolean;\n}\n\nexport type RocksDBStat = StatsValue;\nexport type RocksDBStats = StatsDefault | StatsAll;\n\n/**\n * The main class for interacting with a RocksDB database.\n *\n * Before using this class, you must open the database first.\n *\n * @example\n * ```typescript\n * const db = RocksDatabase.open('/path/to/database');\n * await db.put('key', 'value');\n * const value = await db.get('key');\n * db.close();\n * ```\n */\nexport class RocksDatabase extends DBI<DBITransactional> {\n\t/**\n\t * The name of the database.\n\t */\n\t#name: string;\n\n\tconstructor(pathOrStore: string | Store, options?: RocksDatabaseOptions) {\n\t\tif (typeof pathOrStore === 'string') {\n\t\t\tsuper(new Store(pathOrStore, options));\n\t\t} else if (pathOrStore instanceof Store) {\n\t\t\tsuper(pathOrStore);\n\t\t} else {\n\t\t\tthrow new TypeError('Invalid database path or store');\n\t\t}\n\t\tthis.#name = options?.name ?? 'default';\n\t}\n\n\t/**\n\t * Removes all data from the database asynchronously.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * await db.clear();\n\t * ```\n\t */\n\tclear(): Promise<void> {\n\t\tif (this.store.encoder?.structures !== undefined) {\n\t\t\tthis.store.encoder.structures = [];\n\t\t}\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.store.db.clear(resolve, reject);\n\t\t});\n\t}\n\n\t/**\n\t * Removes all entries from the database synchronously.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * db.clearSync();\n\t * ```\n\t */\n\tclearSync(): void {\n\t\tif (this.store.encoder?.structures !== undefined) {\n\t\t\tthis.store.encoder.structures = [];\n\t\t}\n\n\t\tthis.store.db.clearSync();\n\t}\n\n\t/**\n\t * Closes the database.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * db.close();\n\t * ```\n\t */\n\tclose(): void {\n\t\tthis.store.close();\n\t}\n\n\t/**\n\t * Compacts the entire key range of the database asynchronously.\n\t * This triggers manual compaction which removes tombstones and reclaims space.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * await db.compact();\n\t * ```\n\t */\n\tcompact(options?: CompactOptions): Promise<void> {\n\t\treturn this.store.compact(options);\n\t}\n\n\t/**\n\t * Creates a backup of the entire database (all column families) into the\n\t * given directory, creating parent directories as needed, and resolves with\n\t * the new backup id. Use the `backups` namespace to restore, list, delete,\n\t * purge, or verify backups.\n\t *\n\t * When the database was opened with `disableWAL`, the memtable is flushed\n\t * before the backup by default so unflushed data is not lost.\n\t *\n\t * @example\n\t * ```typescript\n\t * import { backups } from '@harperfast/rocksdb-js';\n\t *\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * const id = await db.backup('/path/to/backups');\n\t * ```\n\t */\n\tbackup(backupDir: string, options?: BackupOptions): Promise<number> {\n\t\treturn this.store.backup(backupDir, options);\n\t}\n\n\t/**\n\t * Creates a hardlinked, point-in-time, fully independent copy of the entire\n\t * database (all column families) at `targetPath` and resolves once written.\n\t *\n\t * Unlike a backup, a checkpoint is a normal, writable sibling database: open\n\t * it with {@link RocksDatabase.open} and it diverges independently from the\n\t * source. SST and blob files are hardlinked when `targetPath` is on the same\n\t * filesystem as the database and copied otherwise (other files such as the\n\t * MANIFEST are always copied), so the operation is near-instant on the same\n\t * filesystem. The memtable is flushed so the checkpoint includes the latest\n\t * writes even when the WAL is disabled.\n\t *\n\t * Parent directories are created as needed. `targetPath` itself must not\n\t * already exist (RocksDB creates the checkpoint directory) and rejects with\n\t * `Create checkpoint failed: target path exists` if it does. The caller is\n\t * responsible for eventual cleanup of the directory.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * await db.createCheckpoint('/path/to/checkpoint');\n\t * const branch = RocksDatabase.open('/path/to/checkpoint');\n\t * ```\n\t */\n\tcreateCheckpoint(targetPath: string): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tif (existsSync(targetPath)) {\n\t\t\t\treject(new Error('Create checkpoint failed: target path exists'));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Create parent directories as needed (a throw here rejects the promise),\n\t\t\t// then hand off to the native worker synchronously so it registers its\n\t\t\t// in-flight operation before this call returns.\n\t\t\tmkdirSync(dirname(targetPath), { recursive: true });\n\t\t\tthis.store.db.createCheckpoint(resolve, reject, targetPath);\n\t\t});\n\t}\n\n\t/**\n\t * Compacts the entire key range of the database synchronously.\n\t * This triggers manual compaction which removes tombstones and reclaims space.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * db.compactSync();\n\t * ```\n\t */\n\tcompactSync(options?: CompactOptions): void {\n\t\treturn this.store.compactSync(options);\n\t}\n\n\t/**\n\t * Returns the list of column families in the RocksDB database.\n\t */\n\tget columns(): string[] {\n\t\treturn this.store.db.columns;\n\t}\n\n\t/**\n\t * Set global database settings.\n\t *\n\t * @param options - The options for the database.\n\t *\n\t * @example\n\t * ```typescript\n\t * RocksDatabase.config({ blockCacheSize: 1024 * 1024 });\n\t * ```\n\t */\n\tstatic config(options: RocksDatabaseConfig): void {\n\t\tconfig(options);\n\t}\n\n\t/**\n\t * Registers a process-wide event listener. Internal events emitted by the\n\t * native binding use namespaced keys (e.g. `'transactionLog:warning'`).\n\t *\n\t * Listeners are not tied to any specific database — they fire for every\n\t * matching event emitted in this process.\n\t *\n\t * @example\n\t * ```typescript\n\t * RocksDatabase.on('transactionLog:warning', (warning) => {\n\t *   console.warn(warning);\n\t * });\n\t * ```\n\t */\n\tstatic on(event: string, callback: (...args: any[]) => void): void {\n\t\taddGlobalListener(event, callback);\n\t}\n\n\t/**\n\t * Alias for {@link RocksDatabase.on}, mirroring the Node `EventEmitter` API.\n\t */\n\tstatic addListener(event: string, callback: (...args: any[]) => void): void {\n\t\taddGlobalListener(event, callback);\n\t}\n\n\t/**\n\t * Removes a previously-registered process-wide event listener. The\n\t * callback identity must match the one passed to {@link RocksDatabase.on}.\n\t *\n\t * @returns `true` if a matching listener was removed.\n\t */\n\tstatic off(event: string, callback: (...args: any[]) => void): boolean {\n\t\treturn removeGlobalListener(event, callback);\n\t}\n\n\t/**\n\t * Alias for {@link RocksDatabase.off}, mirroring the Node `EventEmitter` API.\n\t */\n\tstatic removeListener(event: string, callback: (...args: any[]) => void): boolean {\n\t\treturn removeGlobalListener(event, callback);\n\t}\n\n\t/**\n\t * Returns the number of process-wide listeners registered for the given event.\n\t */\n\tstatic listenerCount(event: string): number {\n\t\treturn globalListenerCount(event);\n\t}\n\n\t/**\n\t * Emits a process-wide event. Mostly intended for tests and as a peer to\n\t * {@link RocksDatabase.on} — native code should call `emitGlobalEvent` in\n\t * `napi/global_events.h` directly rather than round-tripping through JS.\n\t *\n\t * @returns `true` if there was at least one listener.\n\t */\n\tstatic notify(event: string, ...args: any[]): boolean {\n\t\treturn globalNotify(event, args);\n\t}\n\n\t// committed\n\n\tdestroy(): void {\n\t\tthis.store.db.destroy();\n\t}\n\n\tasync drop(): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.store.db.drop(resolve, reject);\n\t\t});\n\t}\n\n\tdropSync(): void {\n\t\treturn this.store.db.dropSync();\n\t}\n\n\tget encoder(): Encoder | null {\n\t\treturn this.store.encoder;\n\t}\n\n\t/**\n\t * Flushes the underlying database by performing a commit or clearing any buffered operations.\n\t *\n\t * @return {void} Does not return a value.\n\t */\n\tflush(): Promise<void> {\n\t\treturn new Promise((resolve, reject) => this.store.db.flush(resolve, reject));\n\t}\n\n\t/**\n\t * Synchronously flushes the underlying database by performing a commit or clearing any buffered operations.\n\t *\n\t * @return {void} Does not return a value.\n\t */\n\tflushSync(): void {\n\t\treturn this.store.db.flushSync();\n\t}\n\n\t// flushed\n\n\t/**\n\t * Gets a RocksDB database property as an integer.\n\t *\n\t * @param propertyName - The name of the property to retrieve (e.g., 'rocksdb.num-blob-files').\n\t * @returns The property value as a number.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * const blobFiles = db.getDBIntProperty('rocksdb.num-blob-files');\n\t * const numKeys = db.getDBIntProperty('rocksdb.estimate-num-keys');\n\t * ```\n\t */\n\tgetDBIntProperty(propertyName: string): number | undefined {\n\t\treturn this.store.db.getDBIntProperty(propertyName);\n\t}\n\n\t/**\n\t * Gets a RocksDB database property as a string.\n\t *\n\t * @param propertyName - The name of the property to retrieve (e.g., 'rocksdb.levelstats').\n\t * @returns The property value as a string.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * const levelStats = db.getDBProperty('rocksdb.levelstats');\n\t * const stats = db.getDBProperty('rocksdb.stats');\n\t * ```\n\t */\n\tgetDBProperty(propertyName: string): string | undefined {\n\t\treturn this.store.db.getDBProperty(propertyName);\n\t}\n\n\t/**\n\t * Retrieves the estimated number of keys in the database.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * const estimated = db.getEstimatedKeyCount();\n\t * console.log(estimated);\n\t * ```\n\t */\n\tgetEstimatedKeyCount(): number {\n\t\treturn this.getDBIntProperty('rocksdb.estimate-num-keys') ?? 0;\n\t}\n\n\t/**\n\t * Returns the current timestamp as a monotonically increasing timestamp in\n\t * milliseconds represented as a decimal number.\n\t *\n\t * @returns The current monotonic timestamp in milliseconds.\n\t */\n\tgetMonotonicTimestamp(): number {\n\t\treturn this.store.db.getMonotonicTimestamp();\n\t}\n\n\t/**\n\t * Returns a number representing a unix timestamp of the oldest unreleased\n\t * snapshot.\n\t *\n\t * @returns The oldest snapshot timestamp.\n\t */\n\tgetOldestSnapshotTimestamp(): number {\n\t\treturn this.store.db.getOldestSnapshotTimestamp();\n\t}\n\n\t/**\n\t * Gets a RocksDB statistic.\n\t *\n\t * @param statName - The name of the statistic to retrieve.\n\t * @returns The statistic value.\n\t */\n\tgetStat(statName: string): RocksDBStat {\n\t\treturn this.store.db.getStat(statName);\n\t}\n\n\t/**\n\t * Gets the RocksDB statistics. The RocksDB ticker/histogram stats require\n\t * statistics to be enabled, but the result always includes a summarized,\n\t * aggregate set of `txnlog.*` keys (across all of this database's transaction\n\t * logs), regardless of whether statistics are enabled. For detailed per-log\n\t * statistics, including memory-map usage, use `log.getStats()` on the log\n\t * returned by {@link RocksDatabase#useLog}.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * const stats = db.getStats();\n\t * stats['txnlog.totalSizeBytes']; // bytes across all transaction logs\n\t * ```\n\t */\n\tgetStats(all?: false): StatsDefault;\n\tgetStats(all: true): StatsAll;\n\tgetStats(all = false): StatsDefault | StatsAll {\n\t\treturn all ? this.store.db.getStats(true) : this.store.db.getStats(false);\n\t}\n\n\t/**\n\t * Gets or creates a buffer that can be shared across worker threads.\n\t *\n\t * @param key - The key to get or create the buffer for.\n\t * @param defaultBuffer - The default buffer to copy and use if the buffer\n\t * does not exist.\n\t * @param [options] - The options for the buffer.\n\t * @param [options.callback] - A optional callback that receives\n\t * key-specific events.\n\t * @returns An `ArrayBuffer` that is internally backed by a shared block of\n\t * memory. The buffer also has `notify()` and `cancel()` methods that can be\n\t * used to notify the specified `options.callback`.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * const buffer = db.getUserSharedBuffer('foo', new ArrayBuffer(10));\n\t */\n\tgetUserSharedBuffer(\n\t\tkey: Key,\n\t\tdefaultBuffer: ArrayBuffer,\n\t\toptions?: UserSharedBufferOptions\n\t): ArrayBufferWithNotify {\n\t\treturn this.store.getUserSharedBuffer(key, defaultBuffer, options);\n\t}\n\n\t/**\n\t * Returns whether the database has a lock for the given key.\n\t *\n\t * @param key - The key to check.\n\t * @returns `true` if the database has a lock for the given key, `false`\n\t * otherwise.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * db.hasLock('foo'); // false\n\t * db.tryLock('foo', () => {});\n\t * db.hasLock('foo'); // true\n\t * ```\n\t */\n\thasLock(key: Key): boolean {\n\t\treturn this.store.hasLock(key);\n\t}\n\n\tasync ifNoExists(_key: Key): Promise<void> {\n\t\t//\n\t}\n\n\t/**\n\t * Checks the process-global verification table for a fresh version match\n\t * on `key`. Returns `true` when the table currently records `version`. Use\n\t * this as a fast cache-freshness check before falling back to a full read:\n\t *\n\t * ```typescript\n\t * if (db.verifyVersion(key, cachedEntry.version)) {\n\t *   return cachedEntry.value;\n\t * }\n\t * const value = db.getSync(key);\n\t * db.populateVersion(key, extractVersion(value));\n\t * ```\n\t */\n\tverifyVersion(key: Key, version: number): boolean {\n\t\treturn this.store.verifyVersion(key, version);\n\t}\n\n\t/**\n\t * Seeds the verification-table slot for `key` with `version`. Has no\n\t * effect if the slot is currently lock-tagged or if the verification\n\t * table is disabled.\n\t */\n\tpopulateVersion(key: Key, version: number): void {\n\t\tthis.store.populateVersion(key, version);\n\t}\n\n\t/**\n\t * Returns whether the database is open.\n\t *\n\t * @returns `true` if the database is open, `false` otherwise.\n\t */\n\tisOpen(): boolean {\n\t\treturn this.store.isOpen();\n\t}\n\n\t/**\n\t * Lists all transaction log names.\n\t *\n\t * @returns an array of transaction log names.\n\t */\n\tlistLogs(): string[] {\n\t\treturn this.store.listLogs();\n\t}\n\n\t/**\n\t * The name of the database.\n\t */\n\tget name(): string {\n\t\treturn this.#name;\n\t}\n\n\t/**\n\t * Whether the database is open in readonly mode.\n\t */\n\tget readOnly(): boolean {\n\t\treturn this.store.readOnly;\n\t}\n\n\t/**\n\t * Sugar method for opening a database.\n\t *\n\t * @param pathOrStore - The filesystem path to the database or a custom store.\n\t * @param options - The options for the database.\n\t * @returns A new RocksDatabase instance.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * ```\n\t */\n\tstatic open(pathOrStore: string | Store, options?: RocksDatabaseOptions): RocksDatabase {\n\t\treturn new RocksDatabase(pathOrStore, options).open();\n\t}\n\n\t/**\n\t * Opens the database. This function returns immediately if the database is\n\t * already open.\n\t *\n\t * @returns A new RocksDatabase instance.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = new RocksDatabase('/path/to/database');\n\t * db.open();\n\t * ```\n\t */\n\topen(): RocksDatabase {\n\t\tconst { store } = this;\n\n\t\tif (store.open()) {\n\t\t\t// already open\n\t\t\treturn this;\n\t\t}\n\n\t\tstore.db.setDefaultValueBuffer(VALUE_BUFFER);\n\t\tstore.db.setDefaultKeyBuffer(KEY_BUFFER);\n\t\tstore.db.setIteratorState(ITERATOR_STATE_BUFFER);\n\n\t\t/**\n\t\t * The encoder initialization precedence is:\n\t\t * 1. encoder.Encoder\n\t\t * 2. encoder.encode()\n\t\t * 3. encoding === `msgpack`\n\t\t * 4. encoding === `ordered-binary`\n\t\t * 5. encoder.writeKey()\n\t\t */\n\t\tlet EncoderClass: EncoderFunction | undefined = store.encoder?.Encoder;\n\t\tif (store.encoding === false) {\n\t\t\tstore.encoder = null;\n\t\t\tEncoderClass = undefined;\n\t\t} else if (typeof EncoderClass === 'function') {\n\t\t\tstore.encoder = null;\n\t\t} else if (\n\t\t\ttypeof store.encoder?.encode !== 'function' &&\n\t\t\t(!store.encoding || store.encoding === 'msgpack')\n\t\t) {\n\t\t\tstore.encoding = 'msgpack';\n\t\t\tEncoderClass = MsgpackEncoder;\n\t\t}\n\n\t\tif (EncoderClass) {\n\t\t\tconst opts: Record<string, any> = {\n\t\t\t\tcopyBuffers: true,\n\t\t\t\tfreezeData: store.freezeData,\n\t\t\t\trandomAccessStructure: store.randomAccessStructure,\n\t\t\t};\n\t\t\tconst { sharedStructuresKey } = store;\n\t\t\tif (sharedStructuresKey) {\n\t\t\t\topts.getStructures = (): any => {\n\t\t\t\t\tconst buffer = this.getBinarySync(sharedStructuresKey);\n\t\t\t\t\treturn buffer && store.decoder?.decode\n\t\t\t\t\t\t? store.decoder.decode(buffer as BufferWithDataView)\n\t\t\t\t\t\t: undefined;\n\t\t\t\t};\n\t\t\t\topts.saveStructures = (\n\t\t\t\t\tstructures: any,\n\t\t\t\t\tisCompatible: boolean | ((existingStructures: any) => boolean)\n\t\t\t\t) => {\n\t\t\t\t\treturn this.transactionSync(\n\t\t\t\t\t\t(txn: Transaction, _attempt: number) => {\n\t\t\t\t\t\t\t// note: we need to get a fresh copy of the shared structures,\n\t\t\t\t\t\t\t// so we don't want to use the transaction's getBinarySync()\n\t\t\t\t\t\t\tconst existingStructuresBuffer = this.getBinarySync(sharedStructuresKey);\n\t\t\t\t\t\t\tconst existingStructures =\n\t\t\t\t\t\t\t\texistingStructuresBuffer && store.decoder?.decode\n\t\t\t\t\t\t\t\t\t? store.decoder.decode(existingStructuresBuffer as BufferWithDataView)\n\t\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\t\tif (typeof isCompatible == 'function') {\n\t\t\t\t\t\t\t\tif (!isCompatible(existingStructures)) {\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (existingStructures && existingStructures.length !== isCompatible) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttxn.putSync(sharedStructuresKey, structures);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ retryOnBusy: true }\n\t\t\t\t\t);\n\t\t\t\t};\n\t\t\t}\n\t\t\tstore.encoder = new EncoderClass({ ...opts, ...store.encoder });\n\t\t\tstore.decoder = store.encoder;\n\t\t} else if (typeof store.encoder?.encode === 'function') {\n\t\t\tif (!store.decoder) {\n\t\t\t\tstore.decoder = store.encoder;\n\t\t\t}\n\t\t} else if (store.encoding === 'ordered-binary') {\n\t\t\tstore.encoder = { readKey: orderedBinary.readKey, writeKey: orderedBinary.writeKey };\n\t\t\tstore.decoder = store.encoder;\n\t\t}\n\n\t\tif (typeof store.encoder?.writeKey === 'function' && !store.encoder?.encode) {\n\t\t\t// define a fallback encode method that uses writeKey to encode values\n\t\t\tstore.encoder = {\n\t\t\t\t...store.encoder,\n\t\t\t\tencode: (value: any, _mode?: number): Buffer => {\n\t\t\t\t\tconst bytesWritten = store.writeKey(value, store.encodeBuffer, 0);\n\t\t\t\t\treturn store.encodeBuffer.subarray(0, bytesWritten);\n\t\t\t\t},\n\t\t\t\tcopyBuffers: true,\n\t\t\t};\n\t\t}\n\n\t\tif (store.encoder) {\n\t\t\tstore.encoder.name = this.#name;\n\t\t}\n\n\t\tif (store.decoder && store.decoder.needsStableBuffer !== true) {\n\t\t\tstore.decoderCopies = true;\n\t\t}\n\n\t\tif (store.decoder?.readKey && !store.decoder.decode) {\n\t\t\tstore.decoder.decode = (buffer: BufferWithDataView): any => {\n\t\t\t\tif (store.decoder?.readKey) {\n\t\t\t\t\treturn store.decoder.readKey(buffer, 0, buffer.end);\n\t\t\t\t}\n\t\t\t\treturn buffer;\n\t\t\t};\n\t\t\tstore.decoderCopies = true;\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Returns the path to the database.\n\t */\n\tget path(): string {\n\t\treturn this.store.path;\n\t}\n\n\t/**\n\t * Purges transaction logs.\n\t *\n\t * By default returns the paths of the deleted log files. Pass\n\t * `includeEntryCounts: true` to instead return, for each deleted file, its\n\t * path and the number of entries it held (`{ path, entries }`).\n\t */\n\tpurgeLogs(options: PurgeLogsOptions & { includeEntryCounts: true }): PurgedLog[];\n\tpurgeLogs(options?: PurgeLogsOptions & { includeEntryCounts?: false }): string[];\n\tpurgeLogs(options?: PurgeLogsOptions): string[] | PurgedLog[];\n\tpurgeLogs(options?: PurgeLogsOptions): string[] | PurgedLog[] {\n\t\treturn this.store.db.purgeLogs(options);\n\t}\n\n\t/**\n\t * The status of the database.\n\t */\n\tget status(): 'open' | 'closed' {\n\t\treturn this.store.isOpen() ? 'open' : 'closed';\n\t}\n\n\t/**\n\t * Executes all operations in the callback as a single transaction.\n\t *\n\t * @param callback - A async function that receives the transaction as an argument.\n\t * @returns A promise that resolves the `callback` return value.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * await db.transaction(async (txn) => {\n\t *   await txn.put('key', 'value');\n\t * });\n\t * ```\n\t */\n\tasync transaction<T>(\n\t\tcallback: TransactionCallback<T>,\n\t\toptions?: TransactionOptions\n\t): Promise<T | void> {\n\t\tif (typeof callback !== 'function') {\n\t\t\tthrow new TypeError('Callback must be a function');\n\t\t}\n\n\t\tconst maxRetries = options?.maxRetries ?? 3;\n\t\tconst txn = new Transaction(this.store, options);\n\t\tlet result: T | PromiseLike<T>;\n\n\t\tthis.notify('begin-transaction');\n\n\t\tfor (let attempt = 1; attempt <= maxRetries; attempt++) {\n\t\t\ttry {\n\t\t\t\tresult = await callback(txn, attempt);\n\t\t\t} catch (callbackErr) {\n\t\t\t\treturn this.#abortTransaction(txn, callbackErr);\n\t\t\t}\n\n\t\t\tlet commitResult: typeof RETRY_NOW | void;\n\t\t\ttry {\n\t\t\t\tcommitResult = await txn.commit();\n\t\t\t} catch (commitErr) {\n\t\t\t\tif (commitErr instanceof TransactionAlreadyAbortedError) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tcommitErr instanceof TransactionIsBusyError &&\n\t\t\t\t\t(options?.retryOnBusy ?? commitErr.hasLog) &&\n\t\t\t\t\tattempt < maxRetries\n\t\t\t\t) {\n\t\t\t\t\t// retry the transaction\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tthis.#abandonTransaction(txn, commitErr);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (commitResult !== RETRY_NOW) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\t// coordinatedRetry: the conflict resolved, retry immediately — but only\n\t\t\t// if attempts remain. On the final attempt a RETRY_NOW must not fall\n\t\t\t// out of the loop silently (that would resolve undefined and leave the\n\t\t\t// transaction un-aborted); abandon it like an exhausted ERR_BUSY retry.\n\t\t\tif (attempt >= maxRetries) {\n\t\t\t\tthis.#abandonTransaction(\n\t\t\t\t\ttxn,\n\t\t\t\t\tnew Error(`Transaction did not commit after ${maxRetries} coordinated retries`)\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Executes all operations in the callback as a single transaction.\n\t *\n\t * @param callback - A function that receives the transaction as an\n\t * argument. If the callback return promise-like value, it is awaited\n\t * before committing the transaction. Otherwise, the callback is treated as\n\t * synchronous.\n\t * @returns The `callback` return value.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * await db.transaction(async (txn) => {\n\t *   await txn.put('key', 'value');\n\t * });\n\t * ```\n\t */\n\ttransactionSync<T>(\n\t\tcallback: TransactionCallback<T>,\n\t\toptions?: TransactionOptions\n\t): T | PromiseLike<T> | void {\n\t\tif (typeof callback !== 'function') {\n\t\t\tthrow new TypeError('Callback must be a function');\n\t\t}\n\n\t\tconst maxRetries = options?.maxRetries ?? 3;\n\n\t\tconst isRetryable = (err: Error | unknown, attempt: number) => {\n\t\t\treturn (\n\t\t\t\terr instanceof TransactionIsBusyError &&\n\t\t\t\t(options?.retryOnBusy ?? err.hasLog) &&\n\t\t\t\tattempt <= maxRetries\n\t\t\t);\n\t\t};\n\n\t\tconst runAttempt = (attempt: number): T | PromiseLike<T> | void => {\n\t\t\tconst txn = new Transaction(this.store, options);\n\t\t\tlet result: T | PromiseLike<T>;\n\n\t\t\ttry {\n\t\t\t\tresult = callback(txn, attempt);\n\t\t\t} catch (callbackErr) {\n\t\t\t\treturn this.#abortTransaction(txn, callbackErr);\n\t\t\t}\n\n\t\t\t// despite being 'sync', we need to support async operations\n\t\t\tif (typeof (result as PromiseLike<T>)?.then === 'function') {\n\t\t\t\treturn (result as PromiseLike<T>).then((value: T | undefined) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\ttxn.commitSync();\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t} catch (commitErr) {\n\t\t\t\t\t\tif (commitErr instanceof TransactionAlreadyAbortedError) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isRetryable(commitErr, attempt)) {\n\t\t\t\t\t\t\treturn runAttempt(attempt + 1) as PromiseLike<T>;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.#abandonTransaction(txn, commitErr);\n\t\t\t\t\t}\n\t\t\t\t}) as PromiseLike<T>;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\ttxn.commitSync();\n\t\t\t\treturn result;\n\t\t\t} catch (commitErr) {\n\t\t\t\tif (commitErr instanceof TransactionAlreadyAbortedError) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (isRetryable(commitErr, attempt)) {\n\t\t\t\t\treturn runAttempt(attempt + 1);\n\t\t\t\t}\n\t\t\t\tthis.#abandonTransaction(txn, commitErr);\n\t\t\t}\n\t\t};\n\n\t\tthis.notify('begin-transaction');\n\t\treturn runAttempt(1);\n\t}\n\n\t#abortTransaction(txn: Transaction, callbackErr: Error | unknown): void {\n\t\t// either a user error or a already aborted/committed error\n\t\ttry {\n\t\t\t// in the event of a user error, we need to abort the transaction\n\t\t\ttxn.abort();\n\t\t} catch (abortErr) {\n\t\t\tif (abortErr instanceof TransactionAlreadyAbortedError) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t// rethrow the user error\n\t\tthrow callbackErr;\n\t}\n\n\t#abandonTransaction(txn: Transaction, commitErr: Error | unknown): void {\n\t\ttry {\n\t\t\ttxn.abort();\n\t\t} catch (abortErr) {\n\t\t\tif (abortErr instanceof TransactionAbandonedError) {\n\t\t\t\tthrow abortErr;\n\t\t\t}\n\t\t}\n\n\t\t// rethrow the original error\n\t\tthrow commitErr;\n\t}\n\n\t/**\n\t * Attempts to acquire a lock for a given key. If the lock is available,\n\t * the function returns `true` and the optional callback is never called.\n\t * If the lock is not available, the function returns `false` and the\n\t * callback is queued until the lock is released.\n\t *\n\t * @param key - The key to lock.\n\t * @param onUnlocked - A callback to call when the lock is released.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * db.tryLock('foo', () => {\n\t *   console.log('lock acquired');\n\t * });\n\t * ```\n\t * @returns `true` if the lock was acquired, `false` otherwise.\n\t */\n\ttryLock(key: Key, onUnlocked?: () => void): boolean {\n\t\treturn this.store.tryLock(key, onUnlocked);\n\t}\n\n\t/**\n\t * Releases the lock on the given key and calls any queued `onUnlocked`\n\t * callback handlers.\n\t *\n\t * @param key - The key to unlock.\n\t * @returns `true` if the lock was released or `false` if the lock did not\n\t * exist.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * db.tryLock('foo', () => {});\n\t * db.unlock('foo'); // returns `true`\n\t * db.unlock('foo'); // already unlocked, returns `false`\n\t * ```\n\t */\n\tunlock(key: Key): void {\n\t\treturn this.store.unlock(key);\n\t}\n\n\t/**\n\t * Excecutes a function using a thread-safe lock to ensure mutual\n\t * exclusion.\n\t *\n\t * @param callback - A callback to call when the lock is acquired.\n\t * @returns A promise that resolves when the lock is acquired.\n\t *\n\t * @example\n\t * ```typescript\n\t * const db = RocksDatabase.open('/path/to/database');\n\t * await db.withLock(async (waited) => {\n\t *   console.log('lock acquired', waited);\n\t * });\n\t * ```\n\t */\n\twithLock(key: Key, callback: () => void | Promise<void>): Promise<void> | undefined {\n\t\treturn this.store.withLock(key, callback);\n\t}\n}\n","import { constants } from './load-binding.js';\nimport { closeSync, openSync, readSync, type Stats, statSync } from 'node:fs';\n\nconst { TRANSACTION_LOG_TOKEN, TRANSACTION_LOG_ENTRY_HEADER_SIZE } = constants;\n\n// Transaction log files did not exist before this date, so any timestamp that\n// predates it indicates corruption.\nconst MIN_VALID_TIMESTAMP = Date.UTC(2026, 0, 27); // 2026-01-27\n\n// Currently only bit 0 (TRANSACTION_LOG_ENTRY_LAST_FLAG) is defined.\nconst VALID_FLAGS_MASK = 0x01;\n\ninterface LogEntry {\n\tanomalies?: string[];\n\tdata?: Buffer;\n\tflags: number;\n\tlength: number;\n\ttimestamp?: number;\n}\n\ninterface TransactionLog {\n\tanomalies: string[];\n\tentries: LogEntry[];\n\tentryAnomalyCount: number;\n\ttimestamp: number;\n\tsize: number;\n\tversion: number;\n}\n\n/**\n * Loads an entire transaction log file into memory.\n * @param path - The path to the transaction log file.\n * @returns The transaction log.\n */\nexport function parseTransactionLog(\n\tpath: string,\n\toptions: { skipData?: boolean } = {}\n): TransactionLog {\n\tlet stats: Stats;\n\ttry {\n\t\tstats = statSync(path);\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n\t\t\tthrow new Error('Transaction log file does not exist');\n\t\t}\n\t\tthrow error;\n\t}\n\n\tlet { size } = stats;\n\tif (size === 0) {\n\t\tthrow new Error('Transaction log file is too small');\n\t}\n\n\tconst fileHandle = openSync(path, 'r');\n\tlet fileOffset = 0;\n\n\tconst read = (numBytes: number) => {\n\t\tconst buffer = Buffer.allocUnsafe(numBytes);\n\t\tconst bytesRead = readSync(fileHandle, buffer, 0, numBytes, fileOffset);\n\t\tfileOffset += bytesRead;\n\t\tif (bytesRead !== numBytes) {\n\t\t\t// Only hex-dump the bytes actually read, capped at 64. A corrupt length\n\t\t\t// can request a huge read; dumping the whole (largely uninitialized)\n\t\t\t// buffer can exceed V8's max string length and mask the real error.\n\t\t\tconst previewBytes = Math.min(bytesRead, 64);\n\t\t\tconst preview = buffer.subarray(0, previewBytes).toString('hex');\n\t\t\tthrow new Error(\n\t\t\t\t`Expected to read ${numBytes} bytes but only read ${bytesRead}, file offset: ${fileOffset.toString(16)}, file size: ${size}, file path: ${path}, buffer (first ${previewBytes} bytes): ${preview}`\n\t\t\t);\n\t\t}\n\t\treturn buffer;\n\t};\n\n\ttry {\n\t\t// read the file header\n\t\tconst token = read(4).readUInt32BE(0);\n\t\tif (token !== TRANSACTION_LOG_TOKEN) {\n\t\t\tthrow new Error('Invalid token');\n\t\t}\n\n\t\tconst version = read(1).readUInt8(0);\n\t\tif (version !== 1) {\n\t\t\tthrow new Error(`Unsupported transaction log file version: ${version}`);\n\t\t}\n\n\t\tconst timestamp = read(8).readDoubleBE(0);\n\t\tconst anomalies: string[] = [];\n\t\tif (!Number.isFinite(timestamp) || timestamp < MIN_VALID_TIMESTAMP) {\n\t\t\tanomalies.push(`Header timestamp ${timestamp} predates 2026-01-27 (possible corruption)`);\n\t\t}\n\n\t\t// read the entries\n\t\tconst entries: LogEntry[] = [];\n\t\tlet entryAnomalyCount = 0;\n\n\t\twhile (fileOffset < size) {\n\t\t\tconst timestamp = read(8).readDoubleBE(0);\n\t\t\tif (timestamp === 0) {\n\t\t\t\t// if we encounter zero padding, we can stop reading the entries since the next entry will start at the next 8-byte boundary, which is the same as the current file offset.\n\t\t\t\tsize = fileOffset - 8;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst length = read(4).readUInt32BE(0);\n\t\t\tconst flags = read(1).readUInt8(0);\n\t\t\t// Validate the declared length against the bytes actually remaining\n\t\t\t// before allocating. A torn/corrupt entry can claim a length far larger\n\t\t\t// than the file (e.g. a partial write that left header bytes pointing\n\t\t\t// past the data), which would otherwise drive an unbounded allocUnsafe\n\t\t\t// and OOM the process during log replay.\n\t\t\tconst remaining = size - fileOffset;\n\t\t\tif (length > remaining) {\n\t\t\t\tconst entryOffset = fileOffset - TRANSACTION_LOG_ENTRY_HEADER_SIZE;\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Corrupt entry at offset ${entryOffset.toString(16)}: declared length ${length} exceeds ${remaining} bytes remaining (file size: ${size})`\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst data = read(length);\n\n\t\t\tconst entryAnomalies: string[] = [];\n\t\t\tif (!Number.isFinite(timestamp) || timestamp < MIN_VALID_TIMESTAMP) {\n\t\t\t\tentryAnomalies.push(`timestamp ${timestamp} predates 2026-01-27 (possible corruption)`);\n\t\t\t}\n\t\t\tif ((flags & ~VALID_FLAGS_MASK) !== 0) {\n\t\t\t\tentryAnomalies.push(\n\t\t\t\t\t`flags 0x${flags.toString(16).padStart(2, '0')} contains undefined bits (expected 0x00 or 0x01)`\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst entry: LogEntry = {\n\t\t\t\ttimestamp,\n\t\t\t\tlength,\n\t\t\t\tflags,\n\t\t\t\tdata: options.skipData ? undefined : Buffer.from(data),\n\t\t\t};\n\t\t\tif (entryAnomalies.length > 0) {\n\t\t\t\tentry.anomalies = entryAnomalies;\n\t\t\t\tentryAnomalyCount += entryAnomalies.length;\n\t\t\t}\n\t\t\tentries.push(entry);\n\t\t}\n\n\t\treturn { anomalies, entries, entryAnomalyCount, timestamp, size, version };\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\terror.message = `Invalid transaction log file: ${error.message}`;\n\t\t}\n\t\tthrow error;\n\t} finally {\n\t\tcloseSync(fileHandle);\n\t}\n}\n","import {\n\tconstants,\n\ttype LogBuffer,\n\tTransactionEntry,\n\tTransactionLog,\n\tTransactionLogQueryOptions,\n} from './load-binding.js';\n\nconst FLOAT_TO_UINT32 = new Float64Array(1);\nconst UINT32_FROM_FLOAT = new Uint32Array(FLOAT_TO_UINT32.buffer);\n\nconst { TRANSACTION_LOG_FILE_HEADER_SIZE, TRANSACTION_LOG_ENTRY_HEADER_SIZE } = constants;\n\n/**\n * Returns an iterable for transaction entries within the specified range of timestamps\n * This iterable can be iterated over multiple times, and subsequent iterations will continue\n * from where the last iteration left off, allowing for iteration through the log file\n * to resume after more transactions have been committed.\n * @param start\n * @param end\n * @param exactStart - if this is true, the function will try to find the transaction that\n * exactly matches the start timestamp, and then return all subsequent transactions in the log\n * regardless of whether their timestamp is before or after the start\n */\nObject.defineProperty(TransactionLog.prototype, 'query', {\n\tvalue(\n\t\tthis: TransactionLog,\n\t\t{\n\t\t\tstart,\n\t\t\tend,\n\t\t\texactStart,\n\t\t\tstartFromLastFlushed,\n\t\t\treadUncommitted,\n\t\t\texclusiveStart,\n\t\t}: TransactionLogQueryOptions = {}\n\t): IterableIterator<TransactionEntry> {\n\t\tif (!this._lastCommittedPosition) {\n\t\t\t// if this is the first time we are querying the log, initialize the last committed position and memory map cache\n\t\t\tconst lastCommittedPosition = this._getLastCommittedPosition();\n\t\t\tthis._lastCommittedPosition = new Float64Array(lastCommittedPosition.buffer);\n\t\t\tthis._logBuffers = new Map<number, WeakRef<LogBuffer>>();\n\t\t}\n\t\tend ??= Number.MAX_VALUE;\n\n\t\tconst transactionLog = this;\n\t\tlet { logId: latestLogId, size } = loadLastPosition(this, !!readUncommitted);\n\t\tlet logId = latestLogId;\n\t\tlet position = 0;\n\t\tlet dataView: DataView;\n\t\tlet logBuffer: LogBuffer | undefined = this._currentLogBuffer; // try the current one first\n\t\tlet foundExactStart = false;\n\n\t\tif (start === undefined && !startFromLastFlushed) {\n\t\t\t// if no start timestamp is specified, start from the last committed position\n\t\t\tposition = size;\n\t\t\tif (position === 0) {\n\t\t\t\t// if the file is empty, start after the header\n\t\t\t\tposition = TRANSACTION_LOG_FILE_HEADER_SIZE;\n\t\t\t}\n\t\t\tstart = 0;\n\t\t} else {\n\t\t\tif (startFromLastFlushed) {\n\t\t\t\t// read from the last flushed position\n\t\t\t\tFLOAT_TO_UINT32[0] = this._getLastFlushed();\n\t\t\t\tif (FLOAT_TO_UINT32[0] === 0) {\n\t\t\t\t\t// no flushes have ever occurred, go to the beginning (which is actually after the file header)\n\t\t\t\t\tFLOAT_TO_UINT32[0] = this._findPosition(0);\n\t\t\t\t}\n\t\t\t\tstart ??= 0; // if no start timestamp is specified, include all\n\t\t\t} else {\n\t\t\t\t// otherwise, find the log file that contains the start timestamp, and find the position within that file\n\t\t\t\tFLOAT_TO_UINT32[0] = this._findPosition(start!);\n\t\t\t}\n\t\t\t// extract the log file ID from the 64-bit float returned by _findPosition, which is stored in the high 32 bits of the float\n\t\t\tlogId = UINT32_FROM_FLOAT[1];\n\t\t\t// and position from the low 32 bits of the float\n\t\t\tposition = UINT32_FROM_FLOAT[0];\n\t\t\tif (position === 0) {\n\t\t\t\t// if the file is empty, start after the header\n\t\t\t\tposition = TRANSACTION_LOG_FILE_HEADER_SIZE;\n\t\t\t}\n\t\t}\n\n\t\tif (logBuffer === undefined || logBuffer.logId !== logId) {\n\t\t\t// if the current log buffer is not the one we want, load the memory map\n\t\t\tlogBuffer = getLogMemoryMap(this, logId);\n\n\t\t\t// if this is the latest, cache for easy access, unless...\n\t\t\t// if we are reading uncommitted, we might be a log file ahead of the committed transaction\n\t\t\t// also, it is pointless to cache the latest log file in a memory map on Windows, because it is not growable\n\t\t\tif (logBuffer && latestLogId === logId && !readUncommitted) {\n\t\t\t\tthis._currentLogBuffer = logBuffer;\n\t\t\t}\n\n\t\t\tif (logBuffer === undefined) {\n\t\t\t\t// create a fake log buffer if we don't have any log buffer yet\n\t\t\t\tlogBuffer = Buffer.alloc(0) as unknown as LogBuffer;\n\t\t\t\tlogBuffer.logId = 0;\n\t\t\t\tlogBuffer.size = 0;\n\t\t\t\tlogBuffer.dataView = new DataView(logBuffer.buffer);\n\t\t\t\t// the outer size variable was set from loadLastPosition() above, but if we\n\t\t\t\t// couldn't acquire a memory map for that logId (e.g. the committed-position\n\t\t\t\t// references a logId that doesn't exist on disk — purged, never created, or\n\t\t\t\t// torn write of the position word), reading at any non-zero size would read\n\t\t\t\t// past the empty buffer. force size to match the empty buffer; the iterator's\n\t\t\t\t// position-vs-size logic then routes through the existing advance-to-next-log\n\t\t\t\t// path, which correctly returns done when no log file can be mapped.\n\t\t\t\tsize = 0;\n\t\t\t}\n\t\t}\n\n\t\tdataView = logBuffer.dataView;\n\n\t\tif (latestLogId !== logId) {\n\t\t\tsize = logBuffer.size;\n\t\t\tif (size === undefined) {\n\t\t\t\tsize = logBuffer.size = this.getLogFileSize(logId);\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\t[Symbol.iterator](): IterableIterator<TransactionEntry> {\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tnext() {\n\t\t\t\tlet timestamp: number;\n\t\t\t\tif (position >= size) {\n\t\t\t\t\t// our position is beyond the size limit, get the updated\n\t\t\t\t\t// size in case we can keep reading further from the same block\n\t\t\t\t\tconst { logId: latestLogId, size: latestSize } = loadLastPosition(\n\t\t\t\t\t\ttransactionLog,\n\t\t\t\t\t\t!!readUncommitted\n\t\t\t\t\t);\n\t\t\t\t\tsize = latestSize;\n\t\t\t\t\tif (latestLogId > logBuffer!.logId) {\n\t\t\t\t\t\t// if it is not the latest log, get the file size\n\t\t\t\t\t\tsize =\n\t\t\t\t\t\t\tlogBuffer!.size ??\n\t\t\t\t\t\t\t(logBuffer!.size = transactionLog.getLogFileSize(logBuffer!.logId));\n\t\t\t\t\t\tif (position >= size) {\n\t\t\t\t\t\t\t// we can't read any further in this block, go to the next block\n\t\t\t\t\t\t\tconst nextLogBuffer = getLogMemoryMap(transactionLog, logBuffer!.logId + 1)!;\n\t\t\t\t\t\t\tif (nextLogBuffer) {\n\t\t\t\t\t\t\t\tdataView = nextLogBuffer.dataView;\n\t\t\t\t\t\t\t\tlogBuffer = nextLogBuffer;\n\t\t\t\t\t\t\t\tif (latestLogId > logBuffer!.logId) {\n\t\t\t\t\t\t\t\t\t// it is non-current log file, we can safely use or cache the size\n\t\t\t\t\t\t\t\t\tsize =\n\t\t\t\t\t\t\t\t\t\tlogBuffer!.size ??\n\t\t\t\t\t\t\t\t\t\t(logBuffer!.size = transactionLog.getLogFileSize(logBuffer!.logId));\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tsize = latestSize; // use the latest position from loadLastPosition\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tposition = TRANSACTION_LOG_FILE_HEADER_SIZE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\twhile (position < size) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\ttimestamp = dataView.getFloat64(position);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t(error as Error).message += ` at position ${position.toString(16)} of log ${\n\t\t\t\t\t\t\tlogBuffer!.logId\n\t\t\t\t\t\t} (size=${size}, log buffer length=${logBuffer!.length})`;\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tif (!timestamp) {\n\t\t\t\t\t\t// we have gone beyond the last transaction and reached the end\n\t\t\t\t\t\treturn { done: true, value: undefined };\n\t\t\t\t\t}\n\n\t\t\t\t\t// Corruption bound: a committed read can't legitimately extend past\n\t\t\t\t\t// the committed `size` (a true entry boundary); an uncommitted read is\n\t\t\t\t\t// bounded only by the physically mapped buffer. In both cases the bound\n\t\t\t\t\t// is also clamped to `logBuffer.length` — if committed `size` over-reports\n\t\t\t\t\t// the mapped buffer (e.g. a truncated/torn file), an unclamped `size`\n\t\t\t\t\t// would let `position` advance past the buffer and `subarray` silently\n\t\t\t\t\t// return a truncated frame instead of throwing. A torn/corrupt entry\n\t\t\t\t\t// can declare a length far past this bound — without the checks below,\n\t\t\t\t\t// `position` runs past the buffer, `subarray` hands back a misframed\n\t\t\t\t\t// (garbage) transaction, and the advance-to-next-log path can\n\t\t\t\t\t// dereference an undefined buffer. Fail loudly with a bounded error.\n\t\t\t\t\tconst limit = readUncommitted ? logBuffer!.length : Math.min(size, logBuffer!.length);\n\t\t\t\t\tif (position + TRANSACTION_LOG_ENTRY_HEADER_SIZE > limit) {\n\t\t\t\t\t\tthrow new RangeError(\n\t\t\t\t\t\t\t`Corrupt transaction log: truncated entry header at position ${position.toString(16)} of log ${\n\t\t\t\t\t\t\t\tlogBuffer!.logId\n\t\t\t\t\t\t\t} (available=${limit - position})`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst length = dataView.getUint32(position + 8);\n\t\t\t\t\tif (position + TRANSACTION_LOG_ENTRY_HEADER_SIZE + length > limit) {\n\t\t\t\t\t\tthrow new RangeError(\n\t\t\t\t\t\t\t`Corrupt transaction log entry at position ${position.toString(16)} of log ${\n\t\t\t\t\t\t\t\tlogBuffer!.logId\n\t\t\t\t\t\t\t}: declared length ${length} overruns the log (limit=${limit})`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tposition += TRANSACTION_LOG_ENTRY_HEADER_SIZE;\n\t\t\t\t\tlet matchesRange: boolean;\n\t\t\t\t\tif (foundExactStart) {\n\t\t\t\t\t\t// already found the exact start, only need to match on remaining conditions\n\t\t\t\t\t\tmatchesRange = (!exclusiveStart || timestamp !== start) && timestamp < end;\n\t\t\t\t\t} else if (exactStart) {\n\t\t\t\t\t\t// in exact start mode, we are look for the exact identifying timestamp of the first transaction\n\t\t\t\t\t\tif (timestamp === start) {\n\t\t\t\t\t\t\tmatchesRange = !exclusiveStart;\n\t\t\t\t\t\t\t// after finding this transaction, match all remaining (but still respecting end and exclusiveStart\n\t\t\t\t\t\t\tfoundExactStart = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmatchesRange = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// no exact start, so just match on conditions\n\t\t\t\t\t\tmatchesRange =\n\t\t\t\t\t\t\t(exclusiveStart ? timestamp > start! : timestamp >= start!) && timestamp < end;\n\t\t\t\t\t}\n\t\t\t\t\tconst entryStart = position;\n\t\t\t\t\tposition += length;\n\t\t\t\t\tif (matchesRange) {\n\t\t\t\t\t\t// fits in the same block, just subarray the data out\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tdone: false,\n\t\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\t\ttimestamp,\n\t\t\t\t\t\t\t\tendTxn: Boolean(logBuffer![entryStart - 1] & 1),\n\t\t\t\t\t\t\t\tdata: logBuffer!.subarray(entryStart, position),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\tif (position >= size) {\n\t\t\t\t\t\t// move to the next log file\n\t\t\t\t\t\tconst { logId: latestLogId, size: latestSize } = loadLastPosition(\n\t\t\t\t\t\t\ttransactionLog,\n\t\t\t\t\t\t\t!!readUncommitted\n\t\t\t\t\t\t);\n\t\t\t\t\t\tsize = latestSize;\n\t\t\t\t\t\tif (latestLogId > logBuffer!.logId) {\n\t\t\t\t\t\t\tconst nextLogBuffer = getLogMemoryMap(transactionLog, logBuffer!.logId + 1);\n\t\t\t\t\t\t\tif (!nextLogBuffer) {\n\t\t\t\t\t\t\t\t// the next log file can't be mapped (purged, mid-rotation,\n\t\t\t\t\t\t\t\t// 0-byte at mmap time, FS race); stop cleanly rather than\n\t\t\t\t\t\t\t\t// dereferencing an undefined buffer\n\t\t\t\t\t\t\t\treturn { done: true, value: undefined };\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlogBuffer = nextLogBuffer;\n\t\t\t\t\t\t\tdataView = logBuffer.dataView;\n\t\t\t\t\t\t\tsize = logBuffer.size;\n\t\t\t\t\t\t\tif (size == undefined) {\n\t\t\t\t\t\t\t\tsize = transactionLog.getLogFileSize(logBuffer.logId);\n\t\t\t\t\t\t\t\tif (!readUncommitted) {\n\t\t\t\t\t\t\t\t\tlogBuffer.size = size;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tposition = TRANSACTION_LOG_FILE_HEADER_SIZE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { done: true, value: undefined };\n\t\t\t},\n\t\t};\n\t},\n});\n\nfunction getLogMemoryMap(transactionLog: TransactionLog, logId: number): LogBuffer | undefined {\n\tif (logId <= 0) {\n\t\treturn;\n\t}\n\tlet logBuffer = transactionLog._logBuffers!.get(logId)?.deref();\n\tif (logBuffer) {\n\t\t// if we have a cached buffer, return it\n\t\treturn logBuffer;\n\t}\n\ttry {\n\t\tlogBuffer = transactionLog._getMemoryMapOfFile(logId);\n\t} catch (error) {\n\t\t(error as Error).message += ` (log file ID: ${logId})`;\n\t\tthrow error;\n\t}\n\tif (!logBuffer) {\n\t\treturn;\n\t}\n\tlogBuffer.logId = logId;\n\tlogBuffer.dataView = new DataView(logBuffer.buffer);\n\ttransactionLog._logBuffers!.set(logId, new WeakRef(logBuffer)); // add to cache\n\tlet maxMisses = 3;\n\tfor (const [logId, reference] of transactionLog._logBuffers!) {\n\t\t// clear out any references that have been collected\n\t\tif (reference.deref() === undefined) {\n\t\t\ttransactionLog._logBuffers!.delete(logId);\n\t\t} else if (--maxMisses === 0) {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn logBuffer;\n}\n\nfunction loadLastPosition(\n\ttransactionLog: TransactionLog,\n\treadUncommitted: boolean\n): { logId: number; size: number } {\n\t// atomically copy the full 64-bit last committed position word to a local variable so we can read it without memory tearing\n\tFLOAT_TO_UINT32[0] = transactionLog._lastCommittedPosition![0];\n\tlet logId = UINT32_FROM_FLOAT[1];\n\tlet size = 0;\n\n\tif (readUncommitted) {\n\t\t// if we are reading uncommitted transactions, we need to read the entire log file to find the latest position\n\t\tlet nextSize = 0;\n\t\tlet nextLogId = logId || 1;\n\t\twhile (true) {\n\t\t\tnextSize = transactionLog.getLogFileSize(nextLogId);\n\t\t\tif (nextSize === 0) {\n\t\t\t\t// if the size is zero, there is no next log file, we are done\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tsize = nextSize;\n\t\t\t\tlogId = nextLogId++;\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// otherwise, just use the last committed position, which indicates the latest committed transaction in the log\n\t\tsize = UINT32_FROM_FLOAT[0];\n\t}\n\treturn { logId, size };\n}\n","import { version } from './load-binding.js';\n\nexport {\n\tbackups,\n\ttype BackupInfo,\n\ttype BackupOptions,\n\ttype RestoreMode,\n\ttype RestoreOptions,\n} from './backup.js';\nexport {\n\tRocksDatabase,\n\ttype RocksDatabaseOptions,\n\ttype RocksDBStat,\n\ttype RocksDBStats,\n} from './database.js';\nexport { DBIterator } from './dbi-iterator.js';\nexport { DBI, type IteratorOptions } from './dbi.js';\nexport type { Key } from './encoding.js';\nexport type * from './stats.js';\nexport {\n\tconstants,\n\tcoolTransactionLogs,\n\tcurrentThreadId,\n\tregistryStatus,\n\tstats,\n\tshutdown,\n\tTransactionLog,\n\ttype TransactionEntry,\n\ttype TransactionLogPosition,\n\ttype TransactionLogStats,\n} from './load-binding.js';\nexport * from './parse-transaction-log.js';\nexport {\n\tStore,\n\ttype StoreContext,\n\ttype StoreGetOptions,\n\ttype StoreIteratorOptions,\n\ttype StorePutOptions,\n\ttype StoreRangeOptions,\n\ttype StoreRemoveOptions,\n} from './store.js';\nexport { Transaction } from './transaction.js';\n\nimport './transaction-log-reader.js';\n\nexport const versions: { rocksdb: string; 'rocksdb-js': string } = {\n\trocksdb: version,\n\t'rocksdb-js': 'ROCKSDB_JS_VERSION',\n};\n"],"mappings":"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"}