UNPKG

yq-store

Version:

A high-performance, persistent and in-memory key-value store with TTL support, built for Node.js applications.

1,317 lines (1,314 loc) 34.8 kB
/** * @fileoverview A high-performance, persistent, zero-dependency Key-Value store * with advanced querying and type-safe events. */ /** * Defines the configuration options for creating a new KvStore instance. */ export interface KvStoreOptions { /** * The interval in milliseconds for the store to automatically perform * compaction. Compaction is the process of rewriting the database file to * permanently remove data from expired, deleted, or updated keys. * This saves disk space and speeds up initial load times. * * @remarks * This is a global setting for database maintenance and is different from * the 'ttlSeconds' parameter on the `set` method, which applies a * Time-To-Live expiration to an individual key. * * Set to 0 to disable automatic compaction. * @default 3600000 (1 hour) */ compactionInterval?: number; /** * The default Time-To-Live (TTL) for keys in seconds. If set, each key will * automatically expire after this duration. If not set, keys will persist * until deleted. * * @remarks * This is a per-key setting and overrides the global `compactionInterval`. * If a key-specific TTL is set, it takes precedence over the global setting. * * Set to 0 to disable expiration for a key. * @default 0 (no expiration) */ ttl?: number; /** * Enable soft delete mode. When enabled, deleted entries are marked as deleted * but not physically removed from the database until compaction or manual cleanup. * When disabled, deleted entries are immediately removed from the database. * * @default true */ softDelete?: boolean; /** * Storage configuration. */ storage?: { /** * Storage type * - 'memory': In-memory SQLite database (':memory:') * - 'persistence': File-based SQLite database * @default 'persistence' */ type?: "memory" | "persistence"; /** * Maximum number of entries before LRU eviction kicks in * @default 50000 for memory mode, 1000000 for persistence mode */ maxEntries?: number; /** * Maximum memory usage in bytes (only applies to memory mode) * @default 104857600 (100MB) */ maxMemory?: number; /** * LRU eviction interval in milliseconds * @default 60000 (1 minute) */ evictionInterval?: number; /** * Enable LRU eviction when maxItems is reached * @default false */ eviction?: boolean; /** * Persistence storage configuration */ persistence?: { /** * Directory path for storing the persistent database files. If not specified, * defaults to the system's temporary directory (os.tmpdir()). The database * filename will be an MD5 hash of __dirname if dbFileName is not provided. * * @remarks * For production use, it's recommended to specify a custom directory path * to ensure data persistence across system reboots. * * @default os.tmpdir() */ dbDir?: string; /** * Custom database file name (without extension) * @default auto-generated */ dbFileName?: string; /** * SQLite configuration */ sqlite?: { /** * Journal mode for SQLite * @default 'WAL' */ journalMode?: "DELETE" | "TRUNCATE" | "PERSIST" | "MEMORY" | "WAL" | "OFF"; /** * Synchronous mode for SQLite * @default 'NORMAL' */ synchronous?: "OFF" | "NORMAL" | "FULL" | "EXTRA"; /** * Cache size in pages (negative value = KB) * @default -10000 (10MB) */ cacheSize?: number; /** * Temporary storage location * @default 'memory' */ tempStore?: "default" | "file" | "memory"; /** * Enable foreign key constraints * @default false */ foreignKeys?: boolean; /** * Busy timeout in milliseconds * @default 30000 */ busyTimeout?: number; }; /** * Vacuum configuration */ vacuum?: { /** * Enable vacuum * @default true */ enabled?: boolean; /** * Vacuum mode * @default 'incremental' */ mode?: "none" | "incremental" | "full"; }; }; }; /** * Logging configuration */ logging?: { /** * Enable logging * @default false */ enabled?: boolean; /** * Log directory path * @default './logs' */ logDir?: string; }; /** * Debug mode configuration */ debug?: { /** * Enable debug mode for detailed logging and performance metrics * @default false */ enabled?: boolean; /** * Enable performance timing logs * @default false */ timing?: boolean; /** * Enable SQL query logging * @default false */ sqlLogging?: boolean; }; /** * Keep the Node.js process alive while the store is open. * * When `false` (default), internal timers (compaction, eviction, LRU updates) * are unref'd so they don't prevent the process from exiting naturally. * The store will still work correctly, but the process can exit when there's * no other work to do. * * When `true`, the internal timers will keep the process alive until * `store.close()` is called explicitly. * * @default false */ keepAlive?: boolean; } /** * Defines the mapping of event names to their listener function signatures. * This ensures full type safety when using `store.on()` or `store.emit()`. */ export interface KvStoreEvents<T = unknown> { /** Emitted when the store has successfully initialized and is ready for use. */ ready: () => void; /** Emitted when the database is ready for operations. */ "db:ready": () => void; /** Emitted when a new key-value pair is successfully set. */ set: (key: string, value: T) => void; /** Emitted when a key is successfully deleted (either directly or via expiration). */ delete: (key: string) => void; /** Emitted when a key is found to be expired during a `get` or query operation. */ expire: (key: string) => void; /** Emitted when entries are evicted due to LRU or memory limits. */ evict: (key: string | number) => void; /** Emitted when a compaction process is about to begin. */ "compact:start": () => void; /** Emitted when a compaction process has successfully completed. */ "compact:end": (stats: { newSize: number; keysProcessed: number; }) => void; /** Emitted when a recoverable error occurs, such as a corrupted line in the DB file. */ error: (error: Error) => void; /** Emitted when the database file is closed and all resources are cleaned up. */ close: () => void; } /** * Represents the structure of a single entry in the append-only log file. */ export type LogEntry<T> = { key: string; value: T; expiresAt?: number; tombstone?: never; } | { key: string; value?: never; expiresAt?: never; tombstone: true; }; /** * In-memory metadata for a key, pointing to its location on disk. */ export interface IndexMeta { offset: number; size: number; expiresAt?: number; db?: string; } /** * Default namespace used when no namespace is specified */ export declare const DEFAULT_NAMESPACE = "_default"; /** * Maximum safe integer for expires_at (never expires) * Using Number.MAX_SAFE_INTEGER (2^53 - 1) for JavaScript compatibility * This represents ~285 million years from epoch, which is effectively "never" */ export declare const NEVER_EXPIRES = 9007199254740991; /** * Options for key-based operations (get, delete, has) */ export interface KeyOptions { /** * Namespace to scope the operation to * @default '_default' */ namespace?: string; } /** * Options for set operations */ export interface SetOptions extends KeyOptions { /** * Time-to-live in seconds. After this duration, the key will expire. * Set to 0 or undefined for no expiration. */ ttl?: number; } /** * Options for listing and querying operations */ export interface ListOptions extends KeyOptions { /** * Filter keys that start with this prefix */ prefix?: string; /** * Filter keys that end with this suffix */ suffix?: string; /** * Maximum number of results to return * @default 100 */ limit?: number; /** * Number of results to skip (for pagination) * @default 0 */ offset?: number; } /** * Options for size/count operations */ export interface SizeOptions extends KeyOptions { /** * Filter keys that start with this prefix */ prefix?: string; /** * Filter keys that end with this suffix */ suffix?: string; } /** * Entry type for bulk set operations */ export interface BulkSetEntry<T = unknown> { key: string; value: T; ttl?: number; } /** * Statistics for a single namespace */ export interface NamespaceStats { /** * Namespace name */ namespace: string; /** * Count of active (non-deleted, non-expired) entries */ activeCount: number; /** * Count of soft-deleted entries */ deletedCount: number; /** * Count of expired entries (not yet cleaned up) */ expiredCount: number; /** * Total size in bytes (approximate) */ sizeBytes: number; } /** * Global store statistics */ export interface StoreStats { /** * Statistics per namespace */ namespaces: NamespaceStats[]; /** * Total active entries across all namespaces */ totalActive: number; /** * Total deleted entries across all namespaces */ totalDeleted: number; /** * Total expired entries across all namespaces */ totalExpired: number; /** * Total size in bytes across all namespaces */ totalSizeBytes: number; } /** * Size type for getSize operations */ export type SizeType = "active" | "deleted" | "expired" | "all"; /** * Batch operation types */ export interface PutBatchOperation<T = unknown> { type: "put"; key: string; value: T; ttl?: number; namespace?: string; } export interface DelBatchOperation { type: "del"; key: string; namespace?: string; } export type BatchOperation<T = unknown> = PutBatchOperation<T> | DelBatchOperation; /** * Storage entry returned from storage manager */ export interface StorageEntry<T = unknown> { key: string; namespace: string; value: T; createdAt: number; expiresAt?: number; isDeleted: boolean; lastAccessed: number; } /** * Namespaced store interface - provides a namespace-scoped view of the store */ export interface INamespacedStore { /** * The namespace name */ readonly name: string; /** * Store a value */ set<T>(key: string, value: T, ttl?: number): Promise<void>; /** * Retrieve a value */ get<T>(key: string): Promise<T | null>; /** * Delete a key */ delete(key: string): Promise<boolean>; /** * Check if a key exists */ has(key: string): Promise<boolean>; /** * Get multiple values at once */ getMany<T>(keys: string[]): Promise<Map<string, T>>; /** * Set multiple values at once */ setMany<T>(entries: BulkSetEntry<T>[]): Promise<void>; /** * Delete multiple keys at once */ deleteMany(keys: string[]): Promise<number>; /** * List all keys in this namespace */ listKeys(options?: Omit<ListOptions, "namespace">): Promise<string[]>; /** * List all key-value pairs in this namespace */ list<T>(options?: Omit<ListOptions, "namespace">): Promise<Array<{ key: string; value: T; }>>; /** * Get the count of entries */ getSize(type?: SizeType): Promise<number>; /** * Clear all entries in this namespace */ clear(): Promise<number>; /** * Get statistics for this namespace */ getStats(): Promise<NamespaceStats>; } /** * Performance metrics for monitoring */ export interface StorageMetrics { operations: { get: { count: number; totalMs: number; }; set: { count: number; totalMs: number; }; delete: { count: number; totalMs: number; }; has: { count: number; totalMs: number; }; }; cache: { hits: number; misses: number; }; errors: { count: number; lastError?: Error; }; } /** * Current schema version - increment when schema changes */ export declare const SCHEMA_VERSION = 1; /** * Schema validation result */ export interface SchemaValidationResult { isValid: boolean; currentVersion?: number; expectedVersion: number; missingColumns: string[]; extraColumns: string[]; message?: string; } /** * Migration options */ export interface MigrationOptions { /** * Path to the database file */ dbPath: string; /** * Create a backup before migration * @default true */ backup?: boolean; /** * Dry run - only check what would be migrated without making changes * @default false */ dryRun?: boolean; /** * Verbose logging * @default false */ verbose?: boolean; } /** * Migration result */ export interface MigrationResult { success: boolean; fromVersion: number | null; toVersion: number; changes: string[]; backupPath?: string; error?: string; } /** * Schema check result */ export interface SchemaCheckResult { needsMigration: boolean; validation: SchemaValidationResult; dbPath: string; exists: boolean; } /** * Check database schema without making changes */ export declare function checkSchema(dbPath: string): Promise<SchemaCheckResult>; /** * Migrate database schema to the latest version */ export declare function migrate(options: MigrationOptions): Promise<MigrationResult>; /** * Find all yq-store database files in a directory */ export declare function findDatabases(dir: string, pattern?: string): string[]; /** * A high-performance, persistent Key-Value store with SQLite backend. * Supports TTL, namespaces, soft deletes, compaction, and type-safe event handling. * * @example * ```typescript * const store = await YqStore.create({ * storage: { type: 'persistence' }, * compactionInterval: 3600000, * softDelete: true * }); * * // Simple usage * await store.set('key', { data: 'value' }, 60); // TTL of 60 seconds * const value = await store.get('key'); * * // With namespace * await store.set('john', { name: 'John' }, { namespace: 'users' }); * const user = await store.get('john', { namespace: 'users' }); * * // Namespace proxy (recommended for repeated use) * const users = store.ns('users'); * await users.set('jane', { name: 'Jane' }); * await users.get('jane'); * * await store.close(); * ``` */ export declare class YqStore { private readonly options; private readonly emitter; private readonly engine; private readonly namespaceCache; private compactionTimer?; private evictionTimer?; private isCompacting; private isClosing; private dbName; private constructor(); /** * Creates and initializes a new YqStore instance. * * @param options - Configuration options for the store * @returns Promise that resolves to an initialized YqStore instance */ static create(options?: KvStoreOptions): Promise<YqStore>; private initialize; on<E extends keyof KvStoreEvents>(event: E, listener: KvStoreEvents[E]): this; off<E extends keyof KvStoreEvents>(event: E, listener: KvStoreEvents[E]): this; addEventListener<E extends keyof KvStoreEvents>(event: E, listener: KvStoreEvents[E]): this; removeEventListener<E extends keyof KvStoreEvents>(event: E, listener: KvStoreEvents[E]): this; /** * Checks if a key exists in the store and is not expired. * * @param key - The key to check for existence * @param options - Optional namespace options * @returns Promise that resolves to true if the key exists and is valid */ has(key: string, options?: KeyOptions): Promise<boolean>; /** * Retrieves a value from the store by its key. * * @template T - The expected type of the stored value * @param key - The key to retrieve the value for * @param options - Optional namespace options * @returns Promise that resolves to the stored value or null if not found/expired * * @example * ```typescript * const user = await store.get<User>('user:123'); * const user = await store.get<User>('john', { namespace: 'users' }); * ``` */ get<T>(key: string, options?: KeyOptions): Promise<T | null>; /** * Stores a value in the store with optional TTL and namespace. * * @template T - The type of the value being stored * @param key - The key to store the value under * @param value - The value to store * @param ttlOrOptions - TTL in seconds (backward compatible) or SetOptions object * * @example * ```typescript * // Backward compatible * await store.set('key', value); * await store.set('key', value, 60); // TTL 60 seconds * * // New options API * await store.set('key', value, { ttl: 60 }); * await store.set('key', value, { namespace: 'users' }); * await store.set('key', value, { ttl: 60, namespace: 'users' }); * ``` */ set<T>(key: string, value: T, ttlOrOptions?: number | SetOptions): Promise<void>; /** * Deletes a key from the store. * * @param key - The key to delete * @param options - Optional namespace options * @returns Promise that resolves to true if the key was deleted */ delete(key: string, options?: KeyOptions): Promise<boolean>; /** * Get multiple values at once (10-100x faster than individual gets) * * @example * ```typescript * const values = await store.getMany(['key1', 'key2', 'key3']); * const values = await store.getMany(['key1', 'key2'], { namespace: 'users' }); * ``` */ getMany<T>(keys: string[], options?: KeyOptions): Promise<Map<string, T>>; /** * Set multiple values at once (uses transaction, much faster) * * @example * ```typescript * await store.setMany([ * { key: 'user1', value: { name: 'John' } }, * { key: 'user2', value: { name: 'Jane' }, ttl: 3600 } * ]); * ``` */ setMany<T>(entries: BulkSetEntry<T>[], options?: KeyOptions): Promise<void>; /** * Delete multiple keys at once * * @example * ```typescript * const count = await store.deleteMany(['key1', 'key2', 'key3']); * ``` */ deleteMany(keys: string[], options?: KeyOptions): Promise<number>; getSize(): Promise<number>; getSize(type: SizeType): Promise<number>; getSize(options: SizeOptions): Promise<number>; getSize(type: SizeType, options: SizeOptions): Promise<number>; listKeys(): Promise<string[]>; listKeys(options: ListOptions): Promise<string[]>; /** * List key-value pairs matching criteria */ list<T>(options?: ListOptions): Promise<Array<{ key: string; value: T; }>>; /** * Iterate over entries (memory efficient for large datasets) */ forEach<T>(callback: (key: string, value: T) => void | Promise<void>, options?: ListOptions): Promise<void>; /** * Get a namespace-scoped store (recommended for repeated namespace operations) * * @example * ```typescript * const users = store.ns('users'); * await users.set('john', { name: 'John' }); * const john = await users.get('john'); * await users.delete('john'); * ``` */ ns(namespace: string): INamespacedStore; /** * Alias for ns() */ namespace(namespace: string): INamespacedStore; /** * List all namespaces with active entries */ listNamespaces(): Promise<string[]>; /** * Clear all entries in a namespace */ clearNamespace(namespace: string): Promise<number>; /** * Get statistics for a namespace */ getNamespaceStats(namespace: string): Promise<NamespaceStats>; /** * Get global store statistics */ getStats(): Promise<StoreStats>; /** * Get performance metrics */ getMetrics(): StorageMetrics; /** * Reset performance metrics */ resetMetrics(): void; clearSoftDeletedEntries(): Promise<number>; clearExpiredEntries(): Promise<number>; clear(): Promise<void>; compact(): Promise<void>; private runEviction; /** * Execute batch operations atomically */ batch(operations: BatchOperation[]): Promise<void>; /** * Create a transaction for batch operations */ createTransaction(): { put<T>(key: string, value: T, ttlSeconds?: number, namespace?: string): void; del(key: string, namespace?: string): void; commit(): Promise<void>; rollback(): void; }; close(): Promise<void>; /** * Get the database file path */ getDbFilePath(): string; /** * Check if a database needs schema migration. * * @param dbPath - Path to the database file * @returns Promise resolving to schema check result * * @example * ```typescript * const result = await YqStore.checkSchema('/path/to/store.yqs'); * if (result.needsMigration) { * console.log('Migration needed:', result.validation.missingColumns); * } * ``` */ static checkSchema(dbPath: string): Promise<SchemaCheckResult>; /** * Migrate a database to the latest schema version. * * @param options - Migration options * @returns Promise resolving to migration result * * @example * ```typescript * // Basic migration with backup * const result = await YqStore.migrate({ * dbPath: '/path/to/store.yqs', * backup: true, * verbose: true * }); * * if (result.success) { * console.log('Migrated from v' + result.fromVersion + ' to v' + result.toVersion); * } * * // Dry run to preview changes * const preview = await YqStore.migrate({ * dbPath: '/path/to/store.yqs', * dryRun: true * }); * console.log('Would make changes:', preview.changes); * ``` */ static migrate(options: MigrationOptions): Promise<MigrationResult>; /** * Find all yq-store database files in a directory. * * @param dir - Directory to search * @param pattern - Glob pattern (default: '*.yqs') * @returns Array of database file paths * * @example * ```typescript * const databases = YqStore.findDatabases('/data/stores'); * for (const dbPath of databases) { * const check = await YqStore.checkSchema(dbPath); * if (check.needsMigration) { * await YqStore.migrate({ dbPath, backup: true }); * } * } * ``` */ static findDatabases(dir: string, pattern?: string): string[]; } /** * @fileoverview A generic, type-safe wrapper around Node.js's EventEmitter. */ /** * Provides a fully type-safe event emitter implementation. * @template TEvents A record mapping event names to their argument tuples. */ export declare class TypedEventEmitter<TEvents extends Record<string, any>> { private emitter; /** * Registers an event listener. Alias for `on`. * @param event The name of the event to listen for. * @param listener The callback function. */ addEventListener<E extends keyof TEvents>(event: E, listener: TEvents[E]): this; /** * Registers an event listener. * @param event The name of the event to listen for. * @param listener The callback function. */ on<E extends keyof TEvents>(event: E, listener: TEvents[E]): this; /** * Unregisters an event listener. Alias for `off`. * @param event The name of the event to stop listening to. * @param listener The callback function to remove. */ removeEventListener<E extends keyof TEvents>(event: E, listener: TEvents[E]): this; /** * Unregisters an event listener. * @param event The name of the event to stop listening to. * @param listener The callback function to remove. */ off<E extends keyof TEvents>(event: E, listener: TEvents[E]): this; /** * Emits an event, calling all registered listeners with the provided arguments. * @param event The name of the event to emit. * @param args The arguments to pass to the listeners. * @returns `true` if the event had listeners, `false` otherwise. */ emit<E extends keyof TEvents>(event: E, ...args: Parameters<TEvents[E]>): boolean; } /** * Error thrown when database schema doesn't match expected schema */ export declare class SchemaMismatchError extends Error { readonly validationResult: SchemaValidationResult; constructor(result: SchemaValidationResult); private static buildMessage; } /** * Configuration for the storage engine */ export interface StorageEngineConfig { /** * Directory for database file */ dbDir: string; /** * Database name (used for filename) */ dbName: string; /** * Use in-memory database * @default false */ inMemory?: boolean; /** * Custom database filename */ dbFileName?: string; /** * Enable soft delete mode * @default true */ softDelete?: boolean; /** * Track LRU access times * @default true */ trackLRU?: boolean; /** * Maximum entries before LRU eviction */ maxEntries?: number; /** * SQLite configuration */ sqlite?: { journalMode?: "DELETE" | "TRUNCATE" | "PERSIST" | "MEMORY" | "WAL" | "OFF"; synchronous?: "OFF" | "NORMAL" | "FULL" | "EXTRA"; cacheSize?: number; tempStore?: "default" | "file" | "memory"; busyTimeout?: number; mmapSize?: number; }; /** * Enable debug mode * @default false */ debug?: boolean; /** * Keep the Node.js process alive while the store is open. * When false, internal timers are unref'd so they don't prevent exit. * @default false */ keepAlive?: boolean; } /** * Abstract base class for storage engines * Provides common functionality and defines the interface */ export declare abstract class BaseStorageEngine { protected readonly config: Required<StorageEngineConfig>; protected readonly emitter: TypedEventEmitter<KvStoreEvents>; protected isInitialized: boolean; protected metrics: StorageMetrics; constructor(config: StorageEngineConfig, emitter: TypedEventEmitter<KvStoreEvents>); abstract initialize(): Promise<void>; abstract close(): Promise<void>; abstract set(key: string, value: unknown, ttl?: number, namespace?: string): Promise<void>; abstract get(key: string, namespace?: string): Promise<StorageEntry | null>; abstract delete(key: string, namespace?: string): Promise<boolean>; abstract has(key: string, namespace?: string): Promise<boolean>; abstract getMany(keys: string[], namespace?: string): Promise<Map<string, unknown>>; abstract setMany(entries: BulkSetEntry[], namespace?: string): Promise<void>; abstract deleteMany(keys: string[], namespace?: string): Promise<number>; abstract batch(operations: BatchOperation[]): Promise<void>; abstract listKeys(options?: ListOptions): Promise<string[]>; abstract listEntries(options?: ListOptions): Promise<StorageEntry[]>; abstract getSize(type?: SizeType, options?: SizeOptions): Promise<number>; abstract clearExpired(): Promise<number>; abstract clearDeleted(): Promise<number>; abstract clearNamespace(namespace: string): Promise<number>; abstract clearAll(): Promise<void>; abstract evictLRU(targetCount?: number): Promise<number>; abstract listNamespaces(): Promise<string[]>; abstract getNamespaceStats(namespace: string): Promise<NamespaceStats>; abstract getDbFilePath(): string; /** * Check if initialized */ protected ensureInitialized(): void; /** * Get current timestamp in milliseconds */ protected now(): number; /** * Calculate expiration timestamp */ protected calculateExpiresAt(ttlSeconds?: number): number; /** * Normalize namespace (use default if not provided) */ protected normalizeNamespace(namespace?: string): string; /** * Serialize value to binary */ protected serialize(value: unknown): Uint8Array; /** * Deserialize binary to value */ protected deserialize(data: Uint8Array): unknown; /** * Track operation metrics */ protected trackMetric(operation: "get" | "set" | "delete" | "has", durationMs: number): void; /** * Track cache hit/miss */ protected trackCacheHit(hit: boolean): void; /** * Track error */ protected trackError(error: Error): void; /** * Get current metrics */ getMetrics(): StorageMetrics; /** * Reset metrics */ resetMetrics(): void; /** * Log debug message */ protected debug(message: string, ...args: unknown[]): void; /** * Check if this is Bun runtime */ protected isBunRuntime(): boolean; /** * Validate existing database schema against expected schema. * Returns validation result with details about any mismatches. * * @param existingColumns - Array of column names from PRAGMA table_info * @param schemaVersion - Optional schema version from meta table */ protected validateSchema(existingColumns: string[], schemaVersion?: number): SchemaValidationResult; /** * SQL to check if kv_store table exists */ protected getTableExistsSQL(): string; /** * SQL to get table column info */ protected getTableInfoSQL(): string; /** * SQL to create/update schema_version meta table */ protected getSchemaVersionTableSQL(): string; /** * SQL to get current schema version */ protected getSchemaVersionSQL(): string; /** * SQL for creating the optimized table schema */ protected getCreateTableSQL(): string; /** * SQL for configuring SQLite pragmas */ protected getPragmaSQL(): string[]; } /** * High-performance storage engine for Bun runtime * * Optimizations: * - Prepared statement caching (compile once, execute many) * - Single query for get() with expiry check built-in * - Optional async LRU tracking * - Optimized schema with composite indexes * - WITHOUT ROWID for TEXT primary keys */ export declare class BunStorageEngine extends BaseStorageEngine { private db?; private statements?; private dbFilePath; private pendingAccessUpdates; private accessFlushTimer?; constructor(config: StorageEngineConfig, emitter: TypedEventEmitter<KvStoreEvents>); /** * Initialize the database and prepare statements */ initialize(): Promise<void>; /** * Prepare and cache all SQL statements */ private prepareStatements; /** * Close the database connection */ close(): Promise<void>; /** * Set a key-value pair */ set(key: string, value: unknown, ttl?: number, namespace?: string): Promise<void>; /** * Get a value by key * Single query with expiry check - no separate expired check needed */ get(key: string, namespace?: string): Promise<StorageEntry | null>; /** * Delete a key */ delete(key: string, namespace?: string): Promise<boolean>; /** * Check if a key exists */ has(key: string, namespace?: string): Promise<boolean>; /** * Get multiple values at once */ getMany(keys: string[], namespace?: string): Promise<Map<string, unknown>>; /** * Set multiple values at once */ setMany(entries: BulkSetEntry[], namespace?: string): Promise<void>; /** * Delete multiple keys at once */ deleteMany(keys: string[], namespace?: string): Promise<number>; /** * Execute batch operations atomically */ batch(operations: BatchOperation[]): Promise<void>; /** * List keys matching criteria */ listKeys(options?: ListOptions): Promise<string[]>; /** * List full entries matching criteria */ listEntries(options?: ListOptions): Promise<StorageEntry[]>; /** * Get count of entries */ getSize(type?: SizeType, options?: SizeOptions): Promise<number>; /** * Clear expired entries */ clearExpired(): Promise<number>; /** * Clear soft-deleted entries */ clearDeleted(): Promise<number>; /** * Clear all entries in a namespace */ clearNamespace(namespace: string): Promise<number>; /** * Clear all entries */ clearAll(): Promise<void>; /** * Queue an access update for batch processing */ private queueAccessUpdate; /** * Flush pending access updates in a single transaction */ private flushAccessUpdates; /** * Evict least recently used entries */ evictLRU(targetCount?: number): Promise<number>; /** * List all namespaces */ listNamespaces(): Promise<string[]>; /** * Get statistics for a namespace */ getNamespaceStats(namespace: string): Promise<NamespaceStats>; /** * Get database file path */ getDbFilePath(): string; } /** * High-performance storage engine for Node.js runtime * * Optimizations: * - Prepared statement caching (compile once, execute many) * - Single query for get() with expiry check built-in * - Optional async LRU tracking * - Optimized schema with composite indexes * - WITHOUT ROWID for TEXT primary keys */ export declare class NodeStorageEngine extends BaseStorageEngine { private db?; private statements?; private dbFilePath; private pendingAccessUpdates; private accessFlushTimer?; constructor(config: StorageEngineConfig, emitter: TypedEventEmitter<KvStoreEvents>); /** * Initialize the database and prepare statements */ initialize(): Promise<void>; /** * Prepare and cache all SQL statements */ private prepareStatements; /** * Close the database connection */ close(): Promise<void>; /** * Set a key-value pair */ set(key: string, value: unknown, ttl?: number, namespace?: string): Promise<void>; /** * Get a value by key * Single query with expiry check - no separate expired check needed */ get(key: string, namespace?: string): Promise<StorageEntry | null>; /** * Delete a key */ delete(key: string, namespace?: string): Promise<boolean>; /** * Check if a key exists */ has(key: string, namespace?: string): Promise<boolean>; /** * Get multiple values at once */ getMany(keys: string[], namespace?: string): Promise<Map<string, unknown>>; /** * Set multiple values at once */ setMany(entries: BulkSetEntry[], namespace?: string): Promise<void>; /** * Delete multiple keys at once */ deleteMany(keys: string[], namespace?: string): Promise<number>; /** * Execute batch operations atomically */ batch(operations: BatchOperation[]): Promise<void>; /** * List keys matching criteria */ listKeys(options?: ListOptions): Promise<string[]>; /** * List full entries matching criteria */ listEntries(options?: ListOptions): Promise<StorageEntry[]>; /** * Get count of entries */ getSize(type?: SizeType, options?: SizeOptions): Promise<number>; /** * Clear expired entries */ clearExpired(): Promise<number>; /** * Clear soft-deleted entries */ clearDeleted(): Promise<number>; /** * Clear all entries in a namespace */ clearNamespace(namespace: string): Promise<number>; /** * Clear all entries */ clearAll(): Promise<void>; /** * Queue an access update for batch processing */ private queueAccessUpdate; /** * Flush pending access updates in a single transaction */ private flushAccessUpdates; /** * Evict least recently used entries */ evictLRU(targetCount?: number): Promise<number>; /** * List all namespaces */ listNamespaces(): Promise<string[]>; /** * Get statistics for a namespace */ getNamespaceStats(namespace: string): Promise<NamespaceStats>; /** * Get database file path */ getDbFilePath(): string; } /** * Create the appropriate storage engine for the current runtime */ export declare function createStorageEngine(config: StorageEngineConfig, emitter: TypedEventEmitter<KvStoreEvents>): BaseStorageEngine; /** * Storage engine type for explicit selection */ export type StorageEngineType = "bun" | "node" | "auto"; /** * Create a storage engine with explicit type selection */ export declare function createStorageEngineOfType(type: StorageEngineType, config: StorageEngineConfig, emitter: TypedEventEmitter<KvStoreEvents>): BaseStorageEngine; export { YqStore as default, }; export {};