@harperfast/rocksdb-js 1.4.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -1
- package/dist/index.cjs +59 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -0
- package/dist/index.d.mts +42 -0
- package/dist/index.mjs +59 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["#includeValues","#txn","#handleCommitError","#name","MsgpackEncoder","#abortTransaction","#abandonTransaction","TRANSACTION_LOG_ENTRY_HEADER_SIZE"],"sources":["../src/load-binding.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 { RangeOptions } from './dbi.js';\nimport type { BufferWithDataView, Key } from './encoding.js';\nimport type { StoreContext } from './store.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\nexport type NativeTransaction = {\n\tid: number;\n\tnew (context: NativeDatabase, options?: NativeTransactionOptions): NativeTransaction;\n\tabort(): void;\n\tcommit(resolve: () => 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) => void,\n\t\treject: (err: Error) => void\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\nexport type TransactionLog = {\n\tnew (db: NativeDatabase, name: string): TransactionLog;\n\taddEntry(data: Buffer | Uint8Array, txnId?: number): void;\n\tgetLogFileSize(sequenceId?: number): number;\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\twriteBufferSize?: number;\n};\n\ntype ResolveCallback<T> = (value: T) => void;\ntype RejectCallback = (err: Error) => void;\n\nexport type UserSharedBufferCallback = () => void;\n\nexport type PurgeLogsOptions = { before?: number; destroy?: boolean; name?: string };\n\nexport type StatsHistogramData = {\n\taverage: number;\n\tcount: number;\n\tmax: number;\n\tmedian: number;\n\tmin: number;\n\tpercentile95: number;\n\tpercentile99: number;\n\tstandardDeviation: number;\n\tsum: number;\n};\n\nexport type NativeDatabase = {\n\tnew (): NativeDatabase;\n\taddListener(event: string, callback: (...args: any[]) => void): 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\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>,\n\t\treject: RejectCallback,\n\t\ttxnId?: 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?: boolean): Record<string, number | StatsHistogramData>;\n\tgetSync(keyLengthOrKeyBuffer: number | Buffer, flags: number, txnId?: number): 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\tpurgeLogs(options?: PurgeLogsOptions): string[];\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\twithLock(key: BufferWithDataView, callback: () => void | Promise<void>): Promise<void>;\n};\n\nexport type RocksDatabaseConfig = {\n\tblockCacheSize?: 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 constants: {\n\tALWAYS_CREATE_NEW_BUFFER_FLAG: number;\n\tNOT_IN_MEMORY_CACHE_FLAG: number;\n\tONLY_IF_IN_MEMORY_CACHE_FLAG: 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;\nexport const stats: {\n\thistograms: string[];\n\ttickers: string[];\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;\nexport const version: string = binding.version;\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 type { NativeTransaction, TransactionLog } from './load-binding.js';\nimport type { GetOptions, PutOptions, Store, StoreContext } 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// limit?: 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) {\n\t\t\t\t\t\treturn undefined;\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\n\t\t\t\t\t? undefined\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 | 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, this.store.getTxnId(options));\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 | 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 | 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, this.store.getTxnId(options));\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 | 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 ? undefined : 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 ? this.store.decodeValue(result as BufferWithDataView) : undefined;\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\n\tconstructor(\n\t\titerator: InstanceType<typeof NativeIteratorCls>,\n\t\tstore: Store,\n\t\tincludeValues: boolean\n\t) {\n\t\tthis.iterator = iterator;\n\t\tthis.store = store;\n\t\tthis.#includeValues = includeValues;\n\t}\n\n\t[Symbol.iterator](): Iterator<DBIteratorValue<T>> {\n\t\treturn this;\n\t}\n\n\tnext(): IteratorResult<DBIteratorValue<T>> {\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\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 { 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';\n\nconst {\n\tONLY_IF_IN_MEMORY_CACHE_FLAG,\n\tNOT_IN_MEMORY_CACHE_FLAG,\n\tALWAYS_CREATE_NEW_BUFFER_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 * 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.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 * 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\ttxnId?: number\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 (this.readOnly) {\n\t\t\ttxnId = undefined;\n\t\t}\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(keyParam, flags | ONLY_IF_IN_MEMORY_CACHE_FLAG, txnId);\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);\n\t\t\t\t});\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)\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\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(keyParam, flags, this.getTxnId(options));\n\t\tif (typeof result === 'number') {\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\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 * 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 * 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 { NativeTransaction, type NativeTransactionOptions } from './load-binding.js';\nimport { Store } from './store.js';\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\tasync commit(): Promise<void> {\n\t\ttry {\n\t\t\tawait new Promise<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} 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 { DBI, type DBITransactional } from './dbi.js';\nimport type { BufferWithDataView, Encoder, EncoderFunction, Key } from './encoding.js';\nimport {\n\tconfig,\n\ttype StatsHistogramData,\n\ttype PurgeLogsOptions,\n\ttype RocksDatabaseConfig,\n\ttype NativeTransactionOptions,\n} from './load-binding.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\tTransaction,\n\tTransactionAbandonedError,\n\tTransactionAlreadyAbortedError,\n\tTransactionIsBusyError,\n} from './transaction.js';\nimport { Encoder as MsgpackEncoder } from 'msgpackr';\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 = number | StatsHistogramData;\nexport type RocksDBStats = Record<string, RocksDBStat>;\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 * 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// 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. Requires statistics to be enabled.\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 * ```\n\t */\n\tgetStats(all = false): RocksDBStats {\n\t\treturn this.store.db.getStats(all);\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 * 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\tpurgeLogs(options?: PurgeLogsOptions): string[] {\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\ttry {\n\t\t\t\tawait txn.commit();\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 (\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}\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. 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 : size;\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\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 {\n\tconstants,\n\tcurrentThreadId,\n\tregistryStatus,\n\tstats,\n\ttype StatsHistogramData,\n\tshutdown,\n\ttype TransactionEntry,\n\tTransactionLog,\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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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["#includeValues","#txn","#handleCommitError","#name","MsgpackEncoder","#abortTransaction","#abandonTransaction","TRANSACTION_LOG_ENTRY_HEADER_SIZE"],"sources":["../src/load-binding.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 { RangeOptions } from './dbi.js';\nimport type { BufferWithDataView, Key } from './encoding.js';\nimport type { StoreContext } from './store.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\nexport type NativeTransaction = {\n\tid: number;\n\tnew (context: NativeDatabase, options?: NativeTransactionOptions): NativeTransaction;\n\tabort(): void;\n\tcommit(resolve: () => 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) => void,\n\t\treject: (err: Error) => void\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\nexport type TransactionLog = {\n\tnew (db: NativeDatabase, name: string): TransactionLog;\n\taddEntry(data: Buffer | Uint8Array, txnId?: number): void;\n\tgetLogFileSize(sequenceId?: number): number;\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\twriteBufferSize?: number;\n};\n\ntype ResolveCallback<T> = (value: T) => void;\ntype RejectCallback = (err: Error) => void;\n\nexport type UserSharedBufferCallback = () => void;\n\nexport type PurgeLogsOptions = { before?: number; destroy?: boolean; name?: string };\n\nexport type StatsHistogramData = {\n\taverage: number;\n\tcount: number;\n\tmax: number;\n\tmedian: number;\n\tmin: number;\n\tpercentile95: number;\n\tpercentile99: number;\n\tstandardDeviation: number;\n\tsum: number;\n};\n\nexport type NativeDatabase = {\n\tnew (): NativeDatabase;\n\taddListener(event: string, callback: (...args: any[]) => void): 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\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>,\n\t\treject: RejectCallback,\n\t\ttxnId?: 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?: boolean): Record<string, number | StatsHistogramData>;\n\tgetSync(keyLengthOrKeyBuffer: number | Buffer, flags: number, txnId?: number): 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\tpurgeLogs(options?: PurgeLogsOptions): string[];\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\twithLock(key: BufferWithDataView, callback: () => void | Promise<void>): Promise<void>;\n};\n\nexport type RocksDatabaseConfig = {\n\tblockCacheSize?: 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 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\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;\nexport const stats: {\n\thistograms: string[];\n\ttickers: string[];\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;\nexport const version: string = binding.version;\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 type { NativeTransaction, TransactionLog } from './load-binding.js';\nimport type { GetOptions, PutOptions, Store, StoreContext } 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// limit?: 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) {\n\t\t\t\t\t\treturn undefined;\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\n\t\t\t\t\t? undefined\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 | 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, this.store.getTxnId(options));\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 | 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 | 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, this.store.getTxnId(options));\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 | 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 ? undefined : 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 ? this.store.decodeValue(result as BufferWithDataView) : undefined;\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\n\tconstructor(\n\t\titerator: InstanceType<typeof NativeIteratorCls>,\n\t\tstore: Store,\n\t\tincludeValues: boolean\n\t) {\n\t\tthis.iterator = iterator;\n\t\tthis.store = store;\n\t\tthis.#includeValues = includeValues;\n\t}\n\n\t[Symbol.iterator](): Iterator<DBIteratorValue<T>> {\n\t\treturn this;\n\t}\n\n\tnext(): IteratorResult<DBIteratorValue<T>> {\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\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 { 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';\n\nconst {\n\tONLY_IF_IN_MEMORY_CACHE_FLAG,\n\tNOT_IN_MEMORY_CACHE_FLAG,\n\tALWAYS_CREATE_NEW_BUFFER_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 * 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.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 * 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\ttxnId?: number\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 (this.readOnly) {\n\t\t\ttxnId = undefined;\n\t\t}\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(keyParam, flags | ONLY_IF_IN_MEMORY_CACHE_FLAG, txnId);\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);\n\t\t\t\t});\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)\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\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(keyParam, flags, this.getTxnId(options));\n\t\tif (typeof result === 'number') {\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\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 * 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 * 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 { NativeTransaction, type NativeTransactionOptions } from './load-binding.js';\nimport { Store } from './store.js';\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\tasync commit(): Promise<void> {\n\t\ttry {\n\t\t\tawait new Promise<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} 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 { 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 StatsHistogramData,\n\ttype PurgeLogsOptions,\n\ttype RocksDatabaseConfig,\n\ttype NativeTransactionOptions,\n} from './load-binding.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\tTransaction,\n\tTransactionAbandonedError,\n\tTransactionAlreadyAbortedError,\n\tTransactionIsBusyError,\n} from './transaction.js';\nimport { Encoder as MsgpackEncoder } from 'msgpackr';\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 = number | StatsHistogramData;\nexport type RocksDBStats = Record<string, RocksDBStat>;\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 * 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. Requires statistics to be enabled.\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 * ```\n\t */\n\tgetStats(all = false): RocksDBStats {\n\t\treturn this.store.db.getStats(all);\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 * 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\tpurgeLogs(options?: PurgeLogsOptions): string[] {\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\ttry {\n\t\t\t\tawait txn.commit();\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 (\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}\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. 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 : size;\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\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 {\n\tconstants,\n\tcurrentThreadId,\n\tregistryStatus,\n\tstats,\n\ttype StatsHistogramData,\n\tshutdown,\n\ttype TransactionEntry,\n\tTransactionLog,\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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"}
|