UNPKG

yq-store

Version:

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

283 lines (281 loc) 7.98 kB
/** * 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; } 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; } export interface FileStorageEntry { key: string; namespace?: string; fileName: string; createdAt: number; expiresAt?: number; isDeleted?: boolean; lastAccessed: number; dataSize: number; dataType: "object" | "array" | "string" | "buffer"; isEncryptedNamespace: boolean; } export interface FileAdapterOptions { /** * Directory for storing cache files and metadata * @default './cache' */ cacheDir?: string; /** * Default Time-To-Live (TTL) for keys in seconds * @default 0 (no expiration) */ ttl?: number; /** * Enable LRU eviction when maxItems is reached * @default false */ eviction?: boolean; /** * Maximum number of items before eviction (only used if eviction is true) * @default 1000000 */ maxItems?: number; /** * Enable debug mode to log detailed operations and performance metrics * When enabled, logs will include: * - File operations (read/write/delete) * - Cache hits/misses * - Eviction events * - Timing information * @default false */ debug?: boolean; /** * LRU eviction interval in milliseconds (only used if eviction is true) * @default 60000 (1 minute) */ evictionInterval?: number; /** * Enable soft delete mode * @default true */ softDelete?: boolean; /** * Encrypt namespace directory names * @default false */ encryptNamespace?: boolean; /** * Size of the in-memory hot cache for frequently accessed entries. * Hot cache provides O(1) access for recent items without disk I/O. * Set to 0 to disable hot caching. * @default 1000 */ hotCacheSize?: number; /** * Keep the Node.js process alive while the cacher is open. * When false, internal timers are unref'd so they don't prevent exit. * @default false */ keepAlive?: boolean; /** * SQLite configuration */ sqlite?: { journalMode?: "DELETE" | "TRUNCATE" | "PERSIST" | "MEMORY" | "WAL" | "OFF"; synchronous?: "OFF" | "NORMAL" | "FULL" | "EXTRA"; cacheSize?: number; tempStore?: "default" | "file" | "memory"; foreignKeys?: boolean; busyTimeout?: number; }; } export interface FileBatchOperation { type: "put" | "del"; key: string; value?: any; ttlSeconds?: number; namespace?: string; } /** * YqCacher - A high-performance file-based caching system * * Features: * - SQLite metadata storage with file-based data * - TTL support with automatic expiration * - Event-driven architecture * - Type-safe operations * - Batch operations support * - Namespace support for organized data storage */ export declare class YqCacher extends TypedEventEmitter<KvStoreEvents> { private storageManager; private options; private isInitialized; private evictionTimer?; private constructor(); /** * Create and initialize a new YqCacher instance */ static create(options?: FileAdapterOptions): Promise<YqCacher>; /** * Initialize the cacher (private method, called automatically by create) */ private initialize; /** * Start the LRU eviction timer */ private startEvictionTimer; /** * Store data without TTL and namespace */ set(key: string, value: any): Promise<void>; /** * Store data with TTL but without namespace */ set(key: string, value: any, ttl: number): Promise<void>; /** * Store data without TTL but with namespace */ set(key: string, value: any, namespace: string): Promise<void>; /** * Store data with both TTL and namespace */ set(key: string, value: any, ttl: number, namespace: string): Promise<void>; /** * Get data by key without namespace */ get<T = any>(key: string): Promise<T | null>; /** * Get data by key with namespace */ get<T = any>(key: string, namespace: string): Promise<T | null>; /** * Check if key exists without namespace */ has(key: string): Promise<boolean>; /** * Check if key exists with namespace */ has(key: string, namespace: string): Promise<boolean>; /** * Delete data by key without namespace */ delete(key: string): Promise<boolean>; /** * Delete data by key with namespace */ delete(key: string, namespace: string): Promise<boolean>; /** * Get all keys in the cache */ keys(): Promise<string[]>; /** * Get all keys in a specific namespace */ keys(namespace: string): Promise<string[]>; /** * Clear all entries from the cache */ clear(): Promise<void>; /** * Clear all entries in a specific namespace */ clear(namespace: string): Promise<void>; /** * Get cache size (number of entries) */ size(): Promise<number>; /** * Clear expired entries */ clearExpired(): Promise<number>; /** * Perform batch operations */ batch(operations: FileBatchOperation[]): Promise<void>; /** * Get cache statistics */ getStats(): Promise<{ totalEntries: number; totalSize: number; expiredEntries: number; hotCache: { size: number; maxSize: number; hitRate: number; }; pendingUpdates: number; }>; /** * Close the cacher and cleanup resources */ close(): Promise<void>; /** * Event listener methods (inherited from TypedEventEmitter) */ /** * Add event listener */ addEventListener<K extends keyof KvStoreEvents>(event: K, listener: KvStoreEvents[K]): this; /** * Remove event listener */ removeEventListener<K extends keyof KvStoreEvents>(event: K, listener: KvStoreEvents[K]): this; } export {};