@gravito/stasis 3.1.0 → 3.2.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.
@@ -0,0 +1,27 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cache-events.ts", "../src/locks.ts", "../src/store.ts", "../src/types.ts", "../src/tagged-store.ts", "../src/CacheRepository.ts", "../src/RateLimiter.ts", "../src/CacheManager.ts", "../src/prediction/AccessPredictor.ts", "../src/stores/CircuitBreakerStore.ts", "../src/stores/FileStore.ts", "../src/utils/LRUCache.ts", "../src/stores/MemoryStore.ts", "../src/stores/NullStore.ts", "../src/stores/PredictiveStore.ts", "../src/stores/RedisStore.ts", "../src/stores/TieredStore.ts", "../src/index.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Cache event system types and dispatcher.\n *\n * Provides event mode definitions, event handler contracts,\n * and the core emit logic for cache lifecycle events.\n *\n * @public\n * @since 3.0.0\n */\n\n/**\n * Supported modes for emitting cache events.\n *\n * @public\n * @since 3.0.0\n */\nexport type CacheEventMode = 'sync' | 'async' | 'off'\n\n/**\n * Event handlers for cache lifecycle events.\n *\n * @public\n * @since 3.0.0\n */\nexport type CacheEvents = {\n /** Triggered on a cache hit. */\n hit?: (key: string) => void | Promise<void>\n /** Triggered on a cache miss. */\n miss?: (key: string) => void | Promise<void>\n /** Triggered when a value is written to the cache. */\n write?: (key: string) => void | Promise<void>\n /** Triggered when a value is removed from the cache. */\n forget?: (key: string) => void | Promise<void>\n /** Triggered when the entire cache is flushed. */\n flush?: () => void | Promise<void>\n}\n\n/**\n * Configuration for the cache event emitter.\n *\n * @internal\n */\nexport type CacheEventEmitterConfig = {\n mode: CacheEventMode\n throwOnError?: boolean\n onError?: (error: unknown, event: keyof CacheEvents, payload: { key?: string }) => void\n}\n\n/**\n * Emit a cache lifecycle event according to the configured mode.\n *\n * @param event - The cache event name\n * @param payload - Event payload\n * @param events - Event handler map\n * @param config - Emitter configuration\n * @internal\n */\nexport function emitCacheEvent(\n event: keyof CacheEvents,\n payload: { key?: string },\n events: CacheEvents | undefined,\n config: CacheEventEmitterConfig\n): void | Promise<void> {\n const { mode, throwOnError, onError } = config\n\n if (mode === 'off') {\n return\n }\n\n const fn = events?.[event]\n if (!fn) {\n return\n }\n\n const invoke = (): void | Promise<void> => {\n if (event === 'flush') {\n return (fn as NonNullable<CacheEvents['flush']>)()\n }\n const key = payload.key ?? ''\n return (\n fn as NonNullable<\n CacheEvents['hit'] | CacheEvents['miss'] | CacheEvents['write'] | CacheEvents['forget']\n >\n )(key)\n }\n\n const reportError = (error: unknown): void => {\n try {\n onError?.(error, event, payload)\n } catch {\n // ignore to keep cache ops safe\n }\n }\n\n if (mode === 'sync') {\n try {\n return Promise.resolve(invoke()).catch((error) => {\n reportError(error)\n if (throwOnError) {\n throw error\n }\n })\n } catch (error) {\n reportError(error)\n if (throwOnError) {\n throw error\n }\n }\n return\n }\n\n queueMicrotask(() => {\n try {\n const result = invoke()\n if (result && typeof (result as Promise<void>).catch === 'function') {\n void (result as Promise<void>).catch(reportError)\n }\n } catch (error) {\n reportError(error)\n }\n })\n}\n",
6
+ "/**\n * Error thrown when a lock cannot be acquired within the specified timeout.\n *\n * This error indicates that the maximum waiting time for a distributed lock\n * has been exceeded without successfully gaining ownership.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * try {\n * await cache.lock('resource', 10).block(5, async () => {\n * // ...\n * });\n * } catch (error) {\n * if (error instanceof LockTimeoutError) {\n * console.error('Failed to acquire lock within 5 seconds');\n * }\n * }\n * ```\n */\nexport class LockTimeoutError extends Error {\n override name = 'LockTimeoutError'\n}\n\n/**\n * Interface for a cache-backed distributed lock.\n *\n * A distributed lock ensures mutual exclusion across multiple processes or\n * instances by using a shared cache as the synchronization primitive.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const lock = cache.lock('process', 60);\n * const result = await lock.block(10, async () => {\n * // Exclusive work\n * return 42;\n * });\n * ```\n */\nexport interface CacheLock {\n /**\n * Attempt to acquire the lock immediately.\n *\n * Uses an atomic \"set if not exists\" operation in the underlying cache\n * to ensure only one owner can hold the lock at a time.\n *\n * @returns `true` if the lock was successfully acquired, `false` if it is already held.\n * @throws {Error} If the underlying cache store fails.\n *\n * @example\n * ```typescript\n * const acquired = await lock.acquire();\n * if (acquired) {\n * try {\n * // Critical section\n * } finally {\n * await lock.release();\n * }\n * }\n * ```\n */\n acquire(): Promise<boolean>\n\n /**\n * Release the lock.\n *\n * Removes the lock entry from the cache, allowing other processes to acquire it.\n * Should typically be called in a `finally` block to ensure the lock is not leaked.\n *\n * @returns A promise that resolves when the lock is released.\n * @throws {Error} If the underlying cache store fails.\n *\n * @example\n * ```typescript\n * await lock.release();\n * ```\n */\n release(): Promise<void>\n\n /**\n * Extend the lock's time-to-live (TTL).\n *\n * Increases the expiration time of the lock to prevent it from being\n * automatically released while a long-running task is still in progress.\n *\n * @param seconds - Duration in seconds to add to the current TTL.\n * @returns `true` if the lock was extended (still owned by this process), `false` otherwise.\n * @throws {Error} If the underlying cache store fails.\n *\n * @example\n * ```typescript\n * const extended = await lock.extend(30);\n * if (!extended) {\n * throw new Error('Lock lost or expired before extension');\n * }\n * ```\n */\n extend?(seconds: number): Promise<boolean>\n\n /**\n * Get the remaining time-to-live for the lock.\n *\n * Useful for monitoring or determining if a lock extension is necessary.\n *\n * @returns Remaining TTL in seconds. Returns -1 if the lock doesn't exist, or -2 if it has no TTL.\n * @throws {Error} If the underlying cache store fails.\n *\n * @example\n * ```typescript\n * const ttl = await lock.getRemainingTime();\n * if (ttl > 0 && ttl < 5) {\n * await lock.extend(10);\n * }\n * ```\n */\n getRemainingTime?(): Promise<number>\n\n /**\n * Attempt to acquire the lock and execute a callback with automatic retry.\n *\n * If the lock is currently held, this method will poll the cache at regular\n * intervals until the lock is acquired or the timeout is reached.\n *\n * @param seconds - Maximum duration to wait for the lock in seconds.\n * @param callback - Logic to execute once the lock is successfully acquired.\n * @param options - Configuration for polling and retry behavior.\n * @returns The value returned by the callback.\n * @throws {LockTimeoutError} If the lock cannot be acquired within the specified timeout.\n * @throws {Error} If the callback throws or the cache store fails.\n *\n * @example\n * ```typescript\n * const result = await lock.block(10, async () => {\n * return await performAtomicOperation();\n * });\n * ```\n */\n block<T>(seconds: number, callback: () => Promise<T> | T, options?: BlockOptions): Promise<T>\n}\n\n/**\n * Configuration for the `block()` method's retry logic.\n *\n * Defines how the lock acquisition should behave when the lock is already held,\n * including polling intervals and cancellation support.\n *\n * @public\n * @since 3.1.0\n *\n * @example\n * ```typescript\n * const options: BlockOptions = {\n * retryInterval: 250,\n * maxRetries: 10\n * };\n * ```\n */\nexport interface BlockOptions {\n /**\n * Delay between consecutive acquisition attempts.\n * @defaultValue 100\n */\n retryInterval?: number\n\n /**\n * Maximum number of times to attempt acquisition before failing.\n * @defaultValue Infinity\n */\n maxRetries?: number\n\n /**\n * Signal to allow external cancellation of the waiting process.\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n * setTimeout(() => controller.abort(), 2000);\n * await lock.block(10, task, { signal: controller.signal });\n * ```\n */\n signal?: AbortSignal\n\n /**\n * @deprecated Use `retryInterval` instead.\n */\n sleepMillis?: number\n}\n\n/**\n * Pause execution for a specified duration.\n *\n * Internal utility used for implementing polling delays in lock acquisition.\n *\n * @param ms - Duration to pause in milliseconds.\n * @returns A promise that resolves after the delay.\n * @internal\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n",
7
+ "import type { CacheLock } from './locks'\nimport type { CacheKey, CacheTtl, CacheValue } from './types'\n\n/**\n * Low-level cache storage contract.\n *\n * Defines the essential operations for cache backends. Implementations of this interface\n * (e.g., Memory, Redis, File) provide the actual persistence logic for the cache system.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * class MyStore implements CacheStore {\n * async get(key) { ... }\n * async put(key, value, ttl) { ... }\n * // ... other methods\n * }\n * ```\n */\nexport interface CacheStore {\n /**\n * Retrieve an item from the cache.\n *\n * Fetches the value associated with the given key. If the item has expired or does not exist,\n * the implementation should return null.\n *\n * @param key - Unique identifier for the cached item.\n * @returns The cached value or null if missing/expired.\n * @throws {Error} If the storage backend is unreachable or encounters a read failure.\n */\n get<T = unknown>(key: CacheKey): Promise<CacheValue<T>>\n\n /**\n * Store an item in the cache.\n *\n * Persists a value with a specific expiration time. Overwrites any existing value for the same key.\n *\n * @param key - Unique identifier for the cached item.\n * @param value - Data to be persisted.\n * @param ttl - Duration in seconds until the item expires.\n * @returns Resolves when the write operation completes.\n * @throws {Error} If the storage backend is full or encounters a write failure.\n */\n put(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<void>\n\n /**\n * Store an item if it does not already exist.\n *\n * Atomic operation to ensure a value is only stored if the key is currently vacant.\n *\n * @param key - Unique identifier for the cached item.\n * @param value - Data to be persisted.\n * @param ttl - Duration in seconds until the item expires.\n * @returns True if the item was successfully added, false if it already existed.\n * @throws {Error} If the storage backend encounters a concurrency or write failure.\n */\n add(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<boolean>\n\n /**\n * Remove an item from the cache.\n *\n * Deletes the entry associated with the specified key.\n *\n * @param key - Identifier of the item to be removed.\n * @returns True if the item existed and was removed, false otherwise.\n * @throws {Error} If the storage backend encounters a deletion failure.\n */\n forget(key: CacheKey): Promise<boolean>\n\n /**\n * Wipe all items from the cache storage.\n *\n * Clears the entire cache backend. Use with caution as this operation is destructive.\n *\n * @returns Resolves when the flush operation completes.\n * @throws {Error} If the storage backend fails to clear the data.\n */\n flush(): Promise<void>\n\n /**\n * Increment a numeric value in the cache.\n *\n * Atomically increases the value of a numeric item. If the key does not exist,\n * it is typically initialized to zero before incrementing.\n *\n * @param key - Identifier of the numeric item.\n * @param value - Amount to add to the current value.\n * @returns The updated numeric value.\n * @throws {TypeError} If the existing value is not numeric.\n * @throws {Error} If the storage backend encounters an atomic update failure.\n */\n increment(key: CacheKey, value?: number): Promise<number>\n\n /**\n * Decrement a numeric value in the cache.\n *\n * Atomically decreases the value of a numeric item. If the key does not exist,\n * it is typically initialized to zero before decrementing.\n *\n * @param key - Identifier of the numeric item.\n * @param value - Amount to subtract from the current value.\n * @returns The updated numeric value.\n * @throws {TypeError} If the existing value is not numeric.\n * @throws {Error} If the storage backend encounters an atomic update failure.\n */\n decrement(key: CacheKey, value?: number): Promise<number>\n\n /**\n * Create a distributed lock instance.\n *\n * Provides a mechanism for mutual exclusion across multiple processes or servers\n * using the cache backend as the synchronization provider.\n *\n * @param name - Unique name for the lock.\n * @param seconds - Default duration for which the lock should be held.\n * @returns A lock instance if supported by the driver, otherwise undefined.\n */\n lock?(name: string, seconds?: number): CacheLock | undefined\n\n /**\n * Get the remaining lifetime of a cached item.\n *\n * Calculates how many seconds are left before the item expires.\n *\n * @param key - Identifier of the cached item.\n * @returns Seconds remaining until expiration, or null if the key has no TTL or does not exist.\n * @throws {Error} If the storage backend encounters a read failure.\n */\n ttl?(key: CacheKey): Promise<number | null>\n}\n\n/**\n * Contract for cache stores supporting tag-based invalidation.\n *\n * Allows grouping cache entries under one or more tags, enabling bulk invalidation\n * of related items without knowing their individual keys.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * if (isTaggableStore(store)) {\n * await store.flushTags(['users']);\n * }\n * ```\n */\nexport interface TaggableStore {\n /**\n * Invalidate all items associated with specific tags.\n *\n * Effectively clears all cache entries that were stored with any of the provided tags.\n *\n * @param tags - List of tags to be flushed.\n * @returns Resolves when the tag invalidation completes.\n * @throws {Error} If the storage backend fails to process the tag flush.\n */\n flushTags(tags: readonly string[]): Promise<void>\n\n /**\n * Compute a namespaced key based on tags.\n *\n * Generates a unique internal key that incorporates tag versioning to ensure\n * proper isolation and invalidation.\n *\n * @param key - Original user-provided cache key.\n * @param tags - Tags to associate with the key.\n * @returns A derived key string used for actual storage.\n */\n tagKey(key: string, tags: readonly string[]): string\n\n /**\n * Register a key in the tag index.\n *\n * Maintains the relationship between tags and their associated keys for tracking.\n *\n * @param tags - Tags to index the key under.\n * @param taggedKey - The derived key to be indexed.\n * @returns Resolves when the indexing completes.\n */\n tagIndexAdd(tags: readonly string[], taggedKey: string): void | Promise<void>\n\n /**\n * Unregister a key from all tag indexes.\n *\n * Removes the tracking information for a specific derived key.\n *\n * @param taggedKey - The derived key to remove from indexes.\n * @returns Resolves when the removal completes.\n */\n tagIndexRemove(taggedKey: string): void | Promise<void>\n}\n\n/**\n * Validates if a cache store supports tagging operations.\n *\n * Performs a runtime check to determine if the provided store implements the `TaggableStore` interface.\n *\n * @param store - The cache store instance to evaluate.\n * @returns True if the store supports tagging, false otherwise.\n *\n * @example\n * ```typescript\n * if (isTaggableStore(myStore)) {\n * await myStore.flushTags(['users', 'posts']);\n * }\n * ```\n *\n * @public\n * @since 3.0.0\n */\nexport function isTaggableStore(store: CacheStore): store is CacheStore & TaggableStore {\n return (\n typeof (store as Partial<TaggableStore>).flushTags === 'function' &&\n typeof (store as Partial<TaggableStore>).tagKey === 'function' &&\n typeof (store as Partial<TaggableStore>).tagIndexAdd === 'function' &&\n typeof (store as Partial<TaggableStore>).tagIndexRemove === 'function'\n )\n}\n",
8
+ "/**\n * Unique identifier for a cached item.\n *\n * Used to reference and retrieve specific data entries within the cache storage.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const key: CacheKey = 'user:123:profile';\n * ```\n */\nexport type CacheKey = string\n\n/**\n * Time-to-live (TTL) configuration for cache entries.\n *\n * Defines the duration or point in time when a cache entry becomes invalid.\n * - `number`: Relative duration in seconds from the current time.\n * - `Date`: Absolute point in time for expiration.\n * - `null`: Persistent storage that never expires automatically.\n * - `undefined`: Fallback to the default TTL configured in the store or repository.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const ttl: CacheTtl = 3600; // 1 hour\n * const absoluteTtl: CacheTtl = new Date('2026-12-31');\n * ```\n */\nexport type CacheTtl = number | Date | null | undefined\n\n/**\n * Result of a cache retrieval operation.\n *\n * Represents the cached data of type `T`, or `null` if the entry is missing or has expired.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const val: CacheValue<string> = 'cached content';\n * const miss: CacheValue<number> = null;\n * ```\n */\nexport type CacheValue<T = unknown> = T | null\n\n/**\n * Validates and prepares a cache key for storage operations.\n *\n * Ensures the key meets the minimum requirements for cache storage, such as being non-empty.\n *\n * @param key - The raw string to be used as a cache key.\n * @returns The validated cache key.\n * @throws {Error} Thrown if the provided key is an empty string or falsy.\n *\n * @example\n * ```typescript\n * const key = normalizeCacheKey('user_profile_123');\n * ```\n *\n * @public\n * @since 3.0.0\n */\nexport function normalizeCacheKey(key: string): string {\n if (!key) {\n throw new Error('Cache key cannot be empty.')\n }\n return key\n}\n\n/**\n * Converts a flexible TTL definition into an absolute Unix epoch timestamp.\n *\n * Normalizes various TTL formats into a consistent millisecond-based timestamp\n * used for expiration checks.\n *\n * @param ttl - The TTL configuration to convert.\n * @param now - Reference timestamp in milliseconds for relative calculations. Defaults to current time.\n * @returns The expiration timestamp in milliseconds, `null` for permanent storage, or `undefined` for default behavior.\n *\n * @example\n * ```typescript\n * // Relative TTL (60 seconds)\n * const expiresAt = ttlToExpiresAt(60);\n *\n * // Absolute Date\n * const expiresAtDate = ttlToExpiresAt(new Date('2026-12-31'));\n * ```\n *\n * @public\n * @since 3.0.0\n */\nexport function ttlToExpiresAt(ttl: CacheTtl, now = Date.now()): number | null | undefined {\n if (ttl === undefined) {\n return undefined\n }\n if (ttl === null) {\n return null\n }\n\n if (ttl instanceof Date) {\n return ttl.getTime()\n }\n\n if (typeof ttl === 'number') {\n // seconds\n if (ttl <= 0) {\n return now // immediate expiry semantics\n }\n return now + ttl * 1000\n }\n\n return undefined\n}\n\n/**\n * Evaluates whether a cache entry has exceeded its expiration time.\n *\n * Compares the provided expiration timestamp against a reference time to determine\n * if the cached data should be considered stale.\n *\n * @param expiresAt - The expiration timestamp in milliseconds, or `null`/`undefined` for non-expiring entries.\n * @param now - Reference timestamp in milliseconds for the comparison. Defaults to current time.\n * @returns `true` if the current time has passed the expiration point; otherwise `false`.\n *\n * @example\n * ```typescript\n * const expired = isExpired(Date.now() - 1000); // true\n * const persistent = isExpired(null); // false\n * ```\n *\n * @public\n * @since 3.0.0\n */\nexport function isExpired(expiresAt: number | null | undefined, now = Date.now()): boolean {\n if (expiresAt === null) {\n return false\n }\n if (expiresAt === undefined) {\n return false\n }\n return now >= expiresAt\n}\n\n/**\n * Options for data compression within the cache.\n *\n * Defines how and when data should be compressed before storage to save space\n * and reduce I/O overhead.\n *\n * @public\n * @since 3.1.0\n *\n * @example\n * ```typescript\n * const options: CompressionOptions = {\n * enabled: true,\n * minSize: 2048,\n * level: 9\n * };\n * ```\n */\nexport type CompressionOptions = {\n /**\n * Whether to enable compression for cached values.\n *\n * @defaultValue false\n */\n enabled: boolean\n\n /**\n * Minimum size in bytes for the value to be compressed.\n * Values smaller than this threshold will be stored uncompressed.\n *\n * @defaultValue 1024\n */\n minSize?: number\n\n /**\n * Compression level for zlib (1-9).\n * Higher levels provide better compression but require more CPU.\n *\n * @defaultValue 6\n */\n level?: number\n}\n",
9
+ "import type { CacheLock } from './locks'\nimport type { CacheStore } from './store'\nimport { type CacheKey, type CacheTtl, normalizeCacheKey } from './types'\n\n/**\n * A CacheStore wrapper that prefixes keys with tag-based namespacing.\n *\n * Used internally by CacheRepository.tags() to create isolated key spaces\n * for collective cache operations (e.g., flushing all keys with a given tag).\n *\n * @internal\n */\nexport class TaggedStore implements CacheStore {\n constructor(\n private readonly store: CacheStore & {\n flushTags: (tags: readonly string[]) => Promise<void>\n tagKey: (key: string, tags: readonly string[]) => string\n tagIndexAdd: (tags: readonly string[], taggedKey: string) => void\n },\n private readonly tags: readonly string[]\n ) {}\n\n private tagged(key: CacheKey): string {\n return this.store.tagKey(normalizeCacheKey(key), this.tags)\n }\n\n async get<T = unknown>(key: CacheKey) {\n return this.store.get<T>(this.tagged(key))\n }\n\n async put(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<void> {\n const taggedKey = this.tagged(key)\n await this.store.put(taggedKey, value, ttl)\n this.store.tagIndexAdd(this.tags, taggedKey)\n }\n\n async add(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<boolean> {\n const taggedKey = this.tagged(key)\n const ok = await this.store.add(taggedKey, value, ttl)\n if (ok) {\n this.store.tagIndexAdd(this.tags, taggedKey)\n }\n return ok\n }\n\n async forget(key: CacheKey): Promise<boolean> {\n return this.store.forget(this.tagged(key))\n }\n\n async flush(): Promise<void> {\n return this.store.flushTags(this.tags)\n }\n\n async increment(key: CacheKey, value?: number): Promise<number> {\n const taggedKey = this.tagged(key)\n const next = await this.store.increment(taggedKey, value)\n this.store.tagIndexAdd(this.tags, taggedKey)\n return next\n }\n\n async decrement(key: CacheKey, value?: number): Promise<number> {\n const taggedKey = this.tagged(key)\n const next = await this.store.decrement(taggedKey, value)\n this.store.tagIndexAdd(this.tags, taggedKey)\n return next\n }\n\n lock(name: string, seconds?: number): CacheLock | undefined {\n return this.store.lock ? this.store.lock(this.tagged(name), seconds) : undefined\n }\n}\n",
10
+ "import {\n type CacheEventEmitterConfig,\n type CacheEventMode,\n type CacheEvents,\n emitCacheEvent,\n} from './cache-events'\nimport { sleep } from './locks'\nimport type { CacheStore } from './store'\nimport { isTaggableStore } from './store'\nimport { TaggedStore } from './tagged-store'\nimport { type CacheKey, type CacheTtl, type CompressionOptions, normalizeCacheKey } from './types'\n\nexport type { CacheEventMode, CacheEvents }\n\n/**\n * Options for configuring the `CacheRepository`.\n *\n * Controls behavior such as key prefixing, event emission, and background\n * refresh strategies for flexible caching.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const options: CacheRepositoryOptions = {\n * prefix: 'v1:',\n * defaultTtl: 3600,\n * eventsMode: 'async'\n * };\n * ```\n */\nexport type CacheRepositoryOptions = {\n /** Optional prefix for all cache keys. */\n prefix?: string\n /** Default time-to-live for cache entries. */\n defaultTtl?: CacheTtl\n /** Event handlers for cache operations. */\n events?: CacheEvents\n /** Mode for emitting events (sync, async, or off). */\n eventsMode?: CacheEventMode\n /** Whether to throw an error if an event handler fails. @defaultValue false */\n throwOnEventError?: boolean\n /** Callback triggered when an event handler encounters an error. */\n onEventError?: (error: unknown, event: keyof CacheEvents, payload: { key?: string }) => void\n /** Timeout for background flexible refresh in milliseconds. @defaultValue 30000 */\n refreshTimeout?: number\n /**\n * Maximum number of retries for the background flexible refresh callback.\n * @defaultValue 0\n */\n maxRetries?: number\n /**\n * Delay between retries for flexible refresh in milliseconds.\n * @defaultValue 50\n */\n retryDelay?: number\n\n /**\n * Compression settings for cached values.\n *\n * @since 3.1.0\n */\n compression?: CompressionOptions\n}\n\n/**\n * Statistics for flexible cache operations.\n *\n * Tracks the performance and reliability of background refresh operations\n * used in stale-while-revalidate patterns.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const stats: FlexibleStats = {\n * refreshCount: 10,\n * refreshFailures: 0,\n * avgRefreshTime: 15.5\n * };\n * ```\n */\nexport type FlexibleStats = {\n /** Total number of successful background refreshes. */\n refreshCount: number\n /** Total number of background refresh failures (after all retries). */\n refreshFailures: number\n /** Average time taken for a successful refresh in milliseconds. */\n avgRefreshTime: number\n}\n\n/**\n * High-level API for cache operations.\n *\n * Wraps a low-level `CacheStore` to provide developer-friendly features like\n * key prefixing, event emission, and advanced patterns like `remember` and `flexible`.\n *\n * @example\n * ```typescript\n * const cache = new CacheRepository(redisStore, { prefix: 'app:' });\n * const user = await cache.remember('user:1', 3600, () => fetchUser(1));\n * ```\n *\n * @public\n * @since 3.0.0\n */\nexport class CacheRepository {\n private refreshSemaphore = new Map<string, Promise<void>>()\n private coalesceSemaphore = new Map<string, Promise<any>>()\n private flexibleStats = { refreshCount: 0, refreshFailures: 0, totalTime: 0 }\n private eventEmitterConfig: CacheEventEmitterConfig\n\n constructor(\n protected readonly store: CacheStore,\n protected readonly options: CacheRepositoryOptions = {}\n ) {\n this.eventEmitterConfig = {\n mode: options.eventsMode ?? 'async',\n throwOnError: options.throwOnEventError,\n onError: options.onEventError,\n }\n }\n\n /**\n * Retrieve statistics about flexible cache operations.\n *\n * Useful for monitoring the health and performance of background refreshes.\n *\n * @returns Current statistics for background refresh operations.\n *\n * @example\n * ```typescript\n * const stats = cache.getFlexibleStats();\n * console.log(`Refreshed ${stats.refreshCount} times`);\n * ```\n */\n getFlexibleStats(): FlexibleStats {\n return {\n refreshCount: this.flexibleStats.refreshCount,\n refreshFailures: this.flexibleStats.refreshFailures,\n avgRefreshTime:\n this.flexibleStats.refreshCount > 0\n ? this.flexibleStats.totalTime / this.flexibleStats.refreshCount\n : 0,\n }\n }\n\n private emit(event: keyof CacheEvents, payload: { key?: string } = {}): void | Promise<void> {\n return emitCacheEvent(event, payload, this.options.events, this.eventEmitterConfig)\n }\n\n protected key(key: CacheKey): string {\n const normalized = normalizeCacheKey(key)\n const prefix = this.options.prefix ?? ''\n return prefix ? `${prefix}${normalized}` : normalized\n }\n\n protected flexibleFreshUntilKey(fullKey: string): string {\n return `__gravito:flexible:freshUntil:${fullKey}`\n }\n\n protected async putMetaKey(metaKey: string, value: unknown, ttl: CacheTtl): Promise<void> {\n await this.store.put(metaKey, value, ttl)\n }\n\n protected async forgetMetaKey(metaKey: string): Promise<void> {\n await this.store.forget(metaKey)\n }\n\n /**\n * Retrieve an item from the cache by its key.\n *\n * Fetches the value from the underlying store. If not found, returns the\n * provided default value or executes the factory function.\n *\n * @param key - The unique cache key.\n * @param defaultValue - A default value or factory function to use if the key is not found.\n * @returns The cached value, or the default value if not found.\n * @throws {Error} If the underlying store fails to retrieve the value.\n *\n * @example\n * ```typescript\n * const user = await cache.get('user:1', { name: 'Guest' });\n * const settings = await cache.get('settings', () => fetchSettings());\n * ```\n */\n async get<T = unknown>(\n key: CacheKey,\n defaultValue?: T | (() => T | Promise<T>)\n ): Promise<T | null> {\n const fullKey = this.key(key)\n const raw = await this.store.get<any>(fullKey)\n\n if (raw !== null) {\n const e = this.emit('hit', { key: fullKey })\n if (e) {\n await e\n }\n return this.decompress<T>(raw)\n }\n\n const e = this.emit('miss', { key: fullKey })\n if (e) {\n await e\n }\n if (defaultValue === undefined) {\n return null\n }\n if (typeof defaultValue === 'function') {\n return (defaultValue as () => T | Promise<T>)()\n }\n return defaultValue\n }\n\n /**\n * Determine if an item exists in the cache.\n *\n * Checks for the presence of a key without necessarily returning its value.\n *\n * @param key - The cache key.\n * @returns True if the item exists, false otherwise.\n * @throws {Error} If the underlying store fails to check existence.\n *\n * @example\n * ```typescript\n * if (await cache.has('session:active')) {\n * // ...\n * }\n * ```\n */\n async has(key: CacheKey): Promise<boolean> {\n return (await this.get(key)) !== null\n }\n\n /**\n * Determine if an item is missing from the cache.\n *\n * Inverse of `has()`, used for cleaner conditional logic.\n *\n * @param key - The cache key.\n * @returns True if the item is missing, false otherwise.\n * @throws {Error} If the underlying store fails to check existence.\n *\n * @example\n * ```typescript\n * if (await cache.missing('config:loaded')) {\n * await loadConfig();\n * }\n * ```\n */\n async missing(key: CacheKey): Promise<boolean> {\n return !(await this.has(key))\n }\n\n /**\n * Store an item in the cache for a specific duration.\n *\n * Persists the value in the underlying store with the given TTL.\n *\n * @param key - Unique cache key.\n * @param value - Value to store.\n * @param ttl - Expiration duration.\n * @throws {Error} If the underlying store fails to persist the value or serialization fails.\n *\n * @example\n * ```typescript\n * await cache.put('token', 'xyz123', 3600);\n * ```\n */\n async put(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<void> {\n const fullKey = this.key(key)\n const data = await this.compress(value)\n await this.store.put(fullKey, data, ttl)\n const e = this.emit('write', { key: fullKey })\n if (e) {\n await e\n }\n }\n\n /**\n * Store an item in the cache for a specific duration.\n *\n * Uses the repository's default TTL if none is provided.\n *\n * @param key - The unique cache key.\n * @param value - The value to store.\n * @param ttl - Optional time-to-live.\n * @throws {Error} If the underlying store fails to persist the value.\n *\n * @example\n * ```typescript\n * await cache.set('theme', 'dark');\n * ```\n */\n async set(key: CacheKey, value: unknown, ttl?: CacheTtl): Promise<void> {\n const resolved = ttl ?? this.options.defaultTtl\n await this.put(key, value, resolved)\n }\n\n /**\n * Store an item in the cache only if the key does not already exist.\n *\n * Atomic operation to prevent overwriting existing data.\n *\n * @param key - The unique cache key.\n * @param value - The value to store.\n * @param ttl - Optional time-to-live.\n * @returns True if the item was added, false otherwise.\n * @throws {Error} If the underlying store fails the atomic operation.\n *\n * @example\n * ```typescript\n * const added = await cache.add('lock:process', true, 60);\n * ```\n */\n async add(key: CacheKey, value: unknown, ttl?: CacheTtl): Promise<boolean> {\n const fullKey = this.key(key)\n const resolved = ttl ?? this.options.defaultTtl\n const ok = await this.store.add(fullKey, value, resolved)\n if (ok) {\n const e = this.emit('write', { key: fullKey })\n if (e) {\n await e\n }\n }\n return ok\n }\n\n /**\n * Store an item in the cache indefinitely.\n *\n * Sets the TTL to null, indicating the value should not expire automatically.\n *\n * @param key - The unique cache key.\n * @param value - The value to store.\n * @throws {Error} If the underlying store fails to persist the value.\n *\n * @example\n * ```typescript\n * await cache.forever('system:id', 'node-01');\n * ```\n */\n async forever(key: CacheKey, value: unknown): Promise<void> {\n await this.put(key, value, null)\n }\n\n /**\n * Get an item from the cache, or execute the given callback and store the result.\n *\n * Implements the \"Cache-Aside\" pattern, ensuring the callback is only executed\n * on a cache miss.\n *\n * @param key - The unique cache key.\n * @param ttl - Time-to-live.\n * @param callback - The callback to execute if the key is not found.\n * @returns The cached value or the result of the callback.\n * @throws {Error} If the callback or the underlying store fails.\n *\n * @example\n * ```typescript\n * const data = await cache.remember('users:all', 300, () => db.users.findMany());\n * ```\n */\n async remember<T = unknown>(\n key: CacheKey,\n ttl: CacheTtl,\n callback: () => Promise<T> | T\n ): Promise<T> {\n const fullKey = this.key(key)\n\n if (this.coalesceSemaphore.has(fullKey)) {\n return this.coalesceSemaphore.get(fullKey)\n }\n\n const promise = (async () => {\n try {\n const existing = await this.get<T>(key)\n if (existing !== null) {\n return existing\n }\n\n const value = await callback()\n await this.put(key, value, ttl)\n return value\n } finally {\n this.coalesceSemaphore.delete(fullKey)\n }\n })()\n\n this.coalesceSemaphore.set(fullKey, promise)\n return promise\n }\n\n /**\n * Get an item from the cache, or execute the given callback and store the result indefinitely.\n *\n * Similar to `remember()`, but the value is stored without an expiration time.\n *\n * @param key - The unique cache key.\n * @param callback - The callback to execute if the key is not found.\n * @returns The cached value or the result of the callback.\n * @throws {Error} If the callback or the underlying store fails.\n *\n * @example\n * ```typescript\n * const config = await cache.rememberForever('app:config', () => loadConfig());\n * ```\n */\n async rememberForever<T = unknown>(key: CacheKey, callback: () => Promise<T> | T): Promise<T> {\n return this.remember(key, null, callback)\n }\n\n /**\n * Retrieve multiple items from the cache by their keys.\n *\n * Efficiently fetches multiple values, returning a map of keys to values.\n *\n * @param keys - An array of unique cache keys.\n * @returns An object where keys are the original keys and values are the cached values.\n * @throws {Error} If the underlying store fails to retrieve values.\n *\n * @example\n * ```typescript\n * const results = await cache.many(['user:1', 'user:2']);\n * ```\n */\n async many<T = unknown>(keys: readonly CacheKey[]): Promise<Record<string, T | null>> {\n const out: Record<string, T | null> = {}\n for (const key of keys) {\n out[String(key)] = await this.get<T>(key)\n }\n return out\n }\n\n /**\n * Store multiple items in the cache for a specific duration.\n *\n * Persists multiple key-value pairs in a single operation if supported by the store.\n *\n * @param values - An object where keys are the unique cache keys and values are the values to store.\n * @param ttl - Time-to-live.\n * @throws {Error} If the underlying store fails to persist values.\n *\n * @example\n * ```typescript\n * await cache.putMany({ 'a': 1, 'b': 2 }, 60);\n * ```\n */\n async putMany(values: Record<string, unknown>, ttl: CacheTtl): Promise<void> {\n await Promise.all(Object.entries(values).map(([k, v]) => this.put(k, v, ttl)))\n }\n\n /**\n * Laravel-like flexible cache (stale-while-revalidate).\n *\n * Serves stale content while revalidating the cache in the background. This\n * minimizes latency for users by avoiding synchronous revalidation.\n *\n * @param key - The unique cache key.\n * @param ttlSeconds - How long the value is considered fresh.\n * @param staleSeconds - How long the stale value may be served while a refresh happens.\n * @param callback - The callback to execute to refresh the cache.\n * @returns The fresh or stale cached value.\n * @throws {Error} If the callback fails on a cache miss.\n *\n * @example\n * ```typescript\n * const value = await cache.flexible('stats', 60, 30, () => fetchStats());\n * ```\n */\n async flexible<T = unknown>(\n key: CacheKey,\n ttlSeconds: number,\n staleSeconds: number,\n callback: () => Promise<T> | T\n ): Promise<T> {\n const fullKey = this.key(key)\n const metaKey = this.flexibleFreshUntilKey(fullKey)\n const now = Date.now()\n const ttlMillis = Math.max(0, ttlSeconds) * 1000\n const staleMillis = Math.max(0, staleSeconds) * 1000\n\n const [freshUntil, cachedValue] = await Promise.all([\n this.store.get<number>(metaKey),\n this.store.get<T>(fullKey),\n ])\n\n if (freshUntil !== null && cachedValue !== null) {\n if (now <= freshUntil) {\n const e = this.emit('hit', { key: fullKey })\n if (e) {\n await e\n }\n return cachedValue\n }\n\n if (now <= freshUntil + staleMillis) {\n const e = this.emit('hit', { key: fullKey })\n if (e) {\n await e\n }\n void this.refreshFlexible(fullKey, metaKey, ttlSeconds, staleSeconds, callback)\n return cachedValue\n }\n }\n\n const e = this.emit('miss', { key: fullKey })\n if (e) {\n await e\n }\n const value = await callback()\n const totalTtl = ttlSeconds + staleSeconds\n await this.put(fullKey, value, totalTtl)\n await this.putMetaKey(metaKey, now + ttlMillis, totalTtl)\n return value\n }\n\n private async refreshFlexible<T>(\n fullKey: string,\n metaKey: string,\n ttlSeconds: number,\n staleSeconds: number,\n callback: () => Promise<T> | T\n ): Promise<void> {\n if (this.refreshSemaphore.has(fullKey)) {\n return\n }\n\n const refreshPromise = this.doRefresh(fullKey, metaKey, ttlSeconds, staleSeconds, callback)\n this.refreshSemaphore.set(fullKey, refreshPromise)\n\n try {\n await refreshPromise\n } finally {\n this.refreshSemaphore.delete(fullKey)\n }\n }\n\n private async doRefresh<T>(\n fullKey: string,\n metaKey: string,\n ttlSeconds: number,\n staleSeconds: number,\n callback: () => Promise<T> | T\n ): Promise<void> {\n if (!this.store.lock) {\n return\n }\n\n const lock = this.store.lock(`flexible:${metaKey}`, Math.max(1, ttlSeconds))\n if (!lock || !(await lock.acquire())) {\n return\n }\n\n const startTime = Date.now()\n try {\n const timeoutMillis = this.options.refreshTimeout ?? 30000\n const maxRetries = this.options.maxRetries ?? 0\n const retryDelay = this.options.retryDelay ?? 50\n let lastError: unknown\n let value: T | undefined\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n value = await Promise.race([\n Promise.resolve(callback()),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error('Refresh timeout')), timeoutMillis)\n ),\n ])\n break\n } catch (err) {\n lastError = err\n if (attempt < maxRetries) {\n await sleep(retryDelay)\n }\n }\n }\n\n if (value === undefined && lastError) {\n throw lastError\n }\n\n const totalTtl = ttlSeconds + staleSeconds\n const now = Date.now()\n await this.put(fullKey, value, totalTtl)\n await this.putMetaKey(metaKey, now + Math.max(0, ttlSeconds) * 1000, totalTtl)\n\n this.flexibleStats.refreshCount++\n this.flexibleStats.totalTime += Date.now() - startTime\n } catch {\n this.flexibleStats.refreshFailures++\n } finally {\n await lock.release()\n }\n }\n\n /**\n * Retrieve an item from the cache and delete it.\n *\n * Atomic-like operation to fetch and immediately remove a value, often used\n * for one-time tokens or flash messages.\n *\n * @param key - The unique cache key.\n * @param defaultValue - A default value to use if the key is not found.\n * @returns The cached value, or the default value if not found.\n * @throws {Error} If the underlying store fails to retrieve or forget the value.\n *\n * @example\n * ```typescript\n * const message = await cache.pull('flash:status');\n * ```\n */\n async pull<T = unknown>(key: CacheKey, defaultValue?: T): Promise<T | null> {\n const value = await this.get<T>(key, defaultValue as T)\n await this.forget(key)\n return value\n }\n\n /**\n * Remove an item from the cache by its key.\n *\n * Deletes the value and any associated metadata from the underlying store.\n *\n * @param key - The cache key to remove.\n * @returns True if the item existed and was removed.\n * @throws {Error} If the underlying store fails to remove the value.\n *\n * @example\n * ```typescript\n * const deleted = await cache.forget('user:session');\n * ```\n */\n async forget(key: CacheKey): Promise<boolean> {\n const fullKey = this.key(key)\n const metaKey = this.flexibleFreshUntilKey(fullKey)\n const ok = await this.store.forget(fullKey)\n await this.forgetMetaKey(metaKey)\n if (ok) {\n const e = this.emit('forget', { key: fullKey })\n if (e) {\n await e\n }\n }\n return ok\n }\n\n /**\n * Alias for `forget`.\n *\n * Provides compatibility with standard `Map`-like or `Storage` APIs.\n *\n * @param key - The cache key to remove.\n * @returns True if the item existed and was removed.\n * @throws {Error} If the underlying store fails to remove the value.\n *\n * @example\n * ```typescript\n * await cache.delete('temp:data');\n * ```\n */\n async delete(key: CacheKey): Promise<boolean> {\n return this.forget(key)\n }\n\n /**\n * Remove all items from the cache storage.\n *\n * Clears the entire underlying store. Use with caution as this affects all\n * keys regardless of prefix.\n *\n * @throws {Error} If the underlying store fails to flush.\n *\n * @example\n * ```typescript\n * await cache.flush();\n * ```\n */\n async flush(): Promise<void> {\n await this.store.flush()\n const e = this.emit('flush')\n if (e) {\n await e\n }\n }\n\n /**\n * Alias for `flush`.\n *\n * Provides compatibility with standard `Map`-like or `Storage` APIs.\n *\n * @throws {Error} If the underlying store fails to clear.\n *\n * @example\n * ```typescript\n * await cache.clear();\n * ```\n */\n async clear(): Promise<void> {\n return this.flush()\n }\n\n /**\n * Increment the value of a numeric item in the cache.\n *\n * Atomically increases the value of a key. If the key does not exist, it is\n * typically initialized to 0 before incrementing.\n *\n * @param key - The cache key.\n * @param value - The amount to increment by.\n * @returns The new value.\n * @throws {Error} If the underlying store fails the atomic increment.\n *\n * @example\n * ```typescript\n * const count = await cache.increment('page:views');\n * ```\n */\n increment(key: string, value?: number) {\n return this.store.increment(this.key(key), value)\n }\n\n /**\n * Decrement the value of a numeric item in the cache.\n *\n * Atomically decreases the value of a key.\n *\n * @param key - The cache key.\n * @param value - The amount to decrement by.\n * @returns The new value.\n * @throws {Error} If the underlying store fails the atomic decrement.\n *\n * @example\n * ```typescript\n * const remaining = await cache.decrement('stock:count');\n * ```\n */\n decrement(key: string, value?: number) {\n return this.store.decrement(this.key(key), value)\n }\n\n /**\n * Get a distributed lock instance for the given name.\n *\n * Provides a mechanism for exclusive access to resources across multiple\n * processes or servers.\n *\n * @param name - The lock name.\n * @param seconds - Optional default duration for the lock in seconds.\n * @returns A `CacheLock` instance if supported, otherwise undefined.\n *\n * @example\n * ```typescript\n * const lock = cache.lock('process:heavy', 10);\n * if (await lock.acquire()) {\n * try {\n * // ...\n * } finally {\n * await lock.release();\n * }\n * }\n * ```\n */\n lock(name: string, seconds?: number) {\n return this.store.lock ? this.store.lock(this.key(name), seconds) : undefined\n }\n\n /**\n * Create a new repository instance with the given tags.\n *\n * Enables grouping of cache entries for collective operations like flushing\n * all keys associated with specific tags.\n *\n * @param tags - An array of tag names.\n * @returns A new `CacheRepository` instance that uses the given tags.\n * @throws {Error} If the underlying store does not support tagging.\n *\n * @example\n * ```typescript\n * await cache.tags(['users', 'profiles']).put('user:1', data, 3600);\n * await cache.tags(['users']).flush();\n * ```\n */\n tags(tags: readonly string[]) {\n if (!isTaggableStore(this.store)) {\n throw new Error('This cache store does not support tags.')\n }\n return new CacheRepository(new TaggedStore(this.store, tags), this.options)\n }\n\n /**\n * Retrieve the underlying cache store.\n *\n * Provides direct access to the low-level store implementation for advanced\n * use cases or debugging.\n *\n * @returns The low-level cache store instance.\n *\n * @example\n * ```typescript\n * const store = cache.getStore();\n * ```\n */\n getStore(): CacheStore {\n return this.store\n }\n\n /**\n * Compress a value before storage if compression is enabled and thresholds are met.\n */\n private async compress(value: unknown): Promise<unknown> {\n const opts = this.options.compression\n if (!opts?.enabled || value === null || value === undefined) {\n return value\n }\n\n // Only compress strings or objects that would be JSON stringified\n const json = JSON.stringify(value)\n if (json.length < (opts.minSize ?? 1024)) {\n return value\n }\n\n const { getCompressionAdapter } = await import('@gravito/core')\n const adapter = getCompressionAdapter()\n const input = new TextEncoder().encode(json)\n const compressed = adapter.gzipSync(input, { level: opts.level ?? 6 })\n\n return {\n __gravito_compressed: true,\n data: Buffer.from(compressed).toString('base64'),\n }\n }\n\n /**\n * Decompress a value after retrieval if it was previously compressed.\n */\n private async decompress<T>(value: any): Promise<T | null> {\n if (\n value !== null &&\n typeof value === 'object' &&\n '__gravito_compressed' in value &&\n value.__gravito_compressed === true\n ) {\n const { getCompressionAdapter } = await import('@gravito/core')\n const adapter = getCompressionAdapter()\n const buffer = new Uint8Array(Buffer.from(value.data, 'base64'))\n const decompressedBytes = adapter.gunzipSync(buffer)\n const decompressed = new TextDecoder().decode(decompressedBytes)\n try {\n return JSON.parse(decompressed)\n } catch {\n return decompressed as any\n }\n }\n return value as T\n }\n}\n",
11
+ "import type { CacheStore } from './store'\n\n/**\n * Represents the response from a rate limiting attempt.\n *\n * This interface provides the necessary metadata to determine if a request\n * should be throttled and when the client can safely retry.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const res: RateLimiterResponse = { allowed: true, remaining: 4, reset: 1622548800 };\n * ```\n */\nexport interface RateLimiterResponse {\n /** Whether the request is allowed based on current usage and limits. */\n allowed: boolean\n /** Number of attempts remaining within the current time window. */\n remaining: number\n /** Epoch timestamp in seconds when the rate limit window will reset. */\n reset: number\n /** Seconds until the rate limit resets, typically used for the `Retry-After` header. */\n retryAfter?: number\n}\n\n/**\n * Detailed information about the current rate limit status.\n *\n * Used for inspecting the state of a limiter without necessarily\n * consuming an attempt or triggering a state change.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const info: RateLimitInfo = { limit: 10, remaining: 5, reset: 1622548800 };\n * ```\n */\nexport interface RateLimitInfo {\n /** Maximum number of attempts allowed within the configured window. */\n limit: number\n /** Number of attempts remaining before the limit is reached. */\n remaining: number\n /** Epoch timestamp in seconds when the rate limit window will reset. */\n reset: number\n /** Seconds until the rate limit resets, only present when the limit has been exceeded. */\n retryAfter?: number\n}\n\n/**\n * RateLimiter provides a simple mechanism for limiting request frequency.\n *\n * It uses a `CacheStore` backend to track attempt counts and handle\n * expiration. This allows for distributed rate limiting when using\n * shared stores like Redis, or local limiting with memory stores.\n *\n * @example\n * ```typescript\n * const limiter = new RateLimiter(cacheStore);\n * const status = await limiter.attempt('login:127.0.0.1', 5, 60);\n *\n * if (!status.allowed) {\n * console.log(`Too many attempts. Retry after ${status.retryAfter}s`);\n * }\n * ```\n *\n * @public\n * @since 3.0.0\n */\nexport class RateLimiter {\n /**\n * Creates a new RateLimiter instance.\n *\n * @param store - Cache backend used to persist attempt counts.\n *\n * @example\n * ```typescript\n * const limiter = new RateLimiter(new MemoryStore());\n * ```\n */\n constructor(private store: CacheStore) {}\n\n /**\n * Attempt to consume a slot in the rate limit window.\n *\n * This method checks the current attempt count for the given key. If the\n * count is below the limit, it increments the count and allows the request.\n * Otherwise, it returns a rejected status with retry information.\n *\n * @param key - The unique identifier for the rate limit (e.g., IP address or user ID).\n * @param maxAttempts - Maximum number of attempts allowed within the decay period.\n * @param decaySeconds - Duration of the rate limit window in seconds.\n * @returns A response indicating if the attempt was successful and the remaining capacity.\n * @throws {Error} If the underlying cache store fails to read or write data.\n *\n * @example\n * ```typescript\n * const response = await limiter.attempt('api-client:123', 100, 3600);\n * if (response.allowed) {\n * // Proceed with request\n * }\n * ```\n */\n async attempt(\n key: string,\n maxAttempts: number,\n decaySeconds: number\n ): Promise<RateLimiterResponse> {\n const current = await this.store.get<number>(key)\n const now = Math.floor(Date.now() / 1000)\n\n if (current === null) {\n await this.store.put(key, 1, decaySeconds)\n return {\n allowed: true,\n remaining: maxAttempts - 1,\n reset: now + decaySeconds,\n }\n }\n\n if (current >= maxAttempts) {\n const retryAfter = await this.availableIn(key, decaySeconds)\n return {\n allowed: false,\n remaining: 0,\n reset: now + retryAfter,\n retryAfter,\n }\n }\n\n const next = await this.store.increment(key)\n return {\n allowed: true,\n remaining: maxAttempts - next,\n reset: now + decaySeconds,\n }\n }\n\n /**\n * Calculate the number of seconds until the rate limit resets.\n *\n * This helper method attempts to retrieve the TTL from the store. If the\n * store does not support TTL inspection, it falls back to the provided\n * decay period.\n *\n * @param key - Unique identifier for the rate limit.\n * @param decaySeconds - Default decay period to use as a fallback.\n * @returns Number of seconds until the key expires.\n * @throws {Error} If the store fails to retrieve TTL metadata.\n */\n async availableIn(key: string, decaySeconds: number): Promise<number> {\n if (typeof this.store.ttl === 'function') {\n const remaining = await this.store.ttl(key)\n if (remaining !== null) {\n return remaining\n }\n }\n return decaySeconds\n }\n\n /**\n * Get detailed information about the current rate limit status without consuming an attempt.\n *\n * Useful for returning rate limit headers (e.g., X-RateLimit-Limit) in\n * middleware or for pre-flight checks.\n *\n * @param key - The unique identifier for the rate limit.\n * @param maxAttempts - Maximum number of attempts allowed.\n * @param decaySeconds - Duration of the rate limit window in seconds.\n * @returns Current status including limit, remaining attempts, and reset time.\n * @throws {Error} If the underlying cache store fails to retrieve data.\n *\n * @example\n * ```typescript\n * const info = await limiter.getInfo('user:42', 60, 60);\n * console.log(`Remaining: ${info.remaining}/${info.limit}`);\n * ```\n */\n async getInfo(key: string, maxAttempts: number, decaySeconds: number): Promise<RateLimitInfo> {\n const current = await this.store.get<number>(key)\n const now = Math.floor(Date.now() / 1000)\n\n if (current === null) {\n return {\n limit: maxAttempts,\n remaining: maxAttempts,\n reset: now + decaySeconds,\n }\n }\n\n const remaining = Math.max(0, maxAttempts - current)\n const retryAfter = remaining === 0 ? await this.availableIn(key, decaySeconds) : undefined\n\n return {\n limit: maxAttempts,\n remaining,\n reset: now + (retryAfter ?? decaySeconds),\n retryAfter,\n }\n }\n\n /**\n * Reset the rate limit counter for a specific key.\n *\n * Use this to manually clear a block, for example after a successful\n * login or when an administrator manually unblocks a user.\n *\n * @param key - The unique identifier to clear.\n * @throws {Error} If the store fails to delete the key.\n *\n * @example\n * ```typescript\n * await limiter.clear('login-attempts:user@example.com');\n * ```\n */\n async clear(key: string): Promise<void> {\n await this.store.forget(key)\n }\n}\n",
12
+ "import { type CacheEventMode, type CacheEvents, CacheRepository } from './CacheRepository'\nimport { RateLimiter } from './RateLimiter'\nimport type { CacheStore } from './store'\nimport type { CacheTtl } from './types'\n\n/**\n * Configuration for a specific cache store driver.\n *\n * Defines the connection parameters and behavior for different storage backends\n * like in-memory, local filesystem, or Redis.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const config: StoreConfig = { driver: 'redis', connection: 'default' };\n * ```\n */\nexport type StoreConfig =\n | { driver: 'memory'; maxItems?: number }\n | { driver: 'file'; directory: string }\n | { driver: 'redis'; connection?: string; prefix?: string }\n | { driver: 'null' }\n // legacy adapter: allow plugging any provider that matches old interface\n | { driver: 'provider' }\n | { driver: 'tiered'; local: string; remote: string }\n | {\n driver: 'circuit-breaker'\n primary: string\n maxFailures?: number\n resetTimeout?: number\n fallback?: string\n }\n\n/**\n * Global cache configuration for managing multiple named stores.\n *\n * Provides a central manifest to define default behavior, global key prefixing,\n * and the registry of available storage backends.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const config: CacheConfig = {\n * default: 'redis',\n * prefix: 'app:',\n * stores: {\n * redis: { driver: 'redis' }\n * }\n * };\n * ```\n */\nexport type CacheConfig = {\n /**\n * The name of the default store to use when no store is explicitly requested.\n */\n default?: string\n /**\n * Global prefix prepended to all cache keys across all stores to prevent collisions.\n */\n prefix?: string\n /**\n * Global default time-to-live for cache entries when not specified in write operations.\n */\n defaultTtl?: CacheTtl\n /**\n * Map of named store configurations, optionally including pre-instantiated providers.\n */\n stores?: Record<string, StoreConfig & { provider?: CacheStore }>\n}\n\n/**\n * Orchestrates multiple cache stores and provides a unified API.\n *\n * Acts as a central registry for cache repositories, supporting various drivers\n * (Memory, File, Redis). It provides both a multi-store API for targeted operations\n * and a proxy API that forwards calls to the default store.\n *\n * @example\n * ```typescript\n * const cache = new CacheManager(factory, {\n * default: 'redis',\n * stores: {\n * redis: { driver: 'redis', prefix: 'myapp:' }\n * }\n * });\n *\n * await cache.set('key', 'value', 3600);\n * const val = await cache.get('key');\n * ```\n *\n * @public\n * @since 3.0.0\n */\nexport class CacheManager {\n /**\n * Internal registry of initialized cache repositories.\n */\n private stores = new Map<string, CacheRepository>()\n\n /**\n * Initialize a new CacheManager instance.\n *\n * @param storeFactory - Factory function to create low-level store instances by name.\n * @param config - Configuration manifest for stores and global defaults.\n * @param events - Optional event handlers for cache lifecycle hooks.\n * @param eventOptions - Configuration for how events are dispatched and handled.\n */\n constructor(\n private readonly storeFactory: (name: string) => CacheStore,\n private readonly config: CacheConfig = {},\n private readonly events?: CacheEvents,\n private readonly eventOptions?: {\n mode?: CacheEventMode\n throwOnError?: boolean\n onError?: (error: unknown, event: keyof CacheEvents, payload: { key?: string }) => void\n }\n ) {}\n\n /**\n * Get a rate limiter instance for a specific store.\n *\n * Provides a specialized interface for throttling actions based on cache keys,\n * leveraging the underlying storage for persistence.\n *\n * @param name - Store name (defaults to the configured default store).\n * @returns A RateLimiter instance bound to the requested store.\n * @throws {Error} If the requested store cannot be initialized.\n *\n * @example\n * ```typescript\n * const limiter = cache.limiter('redis');\n * if (await limiter.tooManyAttempts('login:1', 5)) {\n * throw new Error('Too many attempts');\n * }\n * ```\n */\n limiter(name?: string): RateLimiter {\n // We access the underlying store directly from the repository\n return new RateLimiter(this.store(name).getStore())\n }\n\n /**\n * Resolve a named cache repository.\n *\n * Lazily initializes and caches the repository instance for the given store name.\n * If no name is provided, it falls back to the default store.\n *\n * @param name - Store name to retrieve.\n * @returns Initialized CacheRepository instance.\n * @throws {Error} If the store factory fails to create the underlying store or the driver is unsupported.\n *\n * @example\n * ```typescript\n * const redis = cache.store('redis');\n * await redis.put('key', 'value', 60);\n * ```\n */\n store(name?: string): CacheRepository {\n const storeName = name ?? this.config.default ?? 'memory'\n const existing = this.stores.get(storeName)\n if (existing) {\n return existing\n }\n\n const repo = new CacheRepository(this.storeFactory(storeName), {\n prefix: this.config.prefix,\n defaultTtl: this.config.defaultTtl,\n events: this.events,\n eventsMode: this.eventOptions?.mode,\n throwOnEventError: this.eventOptions?.throwOnError,\n onEventError: this.eventOptions?.onError,\n })\n this.stores.set(storeName, repo)\n return repo\n }\n\n // Laravel-like proxy methods (default store)\n\n /**\n * Retrieve an item from the default cache store.\n *\n * If the key is missing, the provided default value or the result of the\n * default value closure will be returned.\n *\n * @param key - Unique cache key.\n * @param defaultValue - Fallback value or factory to execute on cache miss.\n * @returns Cached value or the resolved default.\n * @throws {Error} If the underlying store driver encounters a read error or connection failure.\n *\n * @example\n * ```typescript\n * const value = await cache.get('user:1', { name: 'Guest' });\n * ```\n */\n get<T = unknown>(key: string, defaultValue?: T | (() => T | Promise<T>)) {\n return this.store().get<T>(key, defaultValue)\n }\n\n /**\n * Determine if an item exists in the default cache store.\n *\n * @param key - The unique cache key.\n * @returns True if the key exists and has not expired.\n * @throws {Error} If the underlying store driver encounters a connection error.\n *\n * @example\n * ```typescript\n * if (await cache.has('session:active')) {\n * // ...\n * }\n * ```\n */\n has(key: string) {\n return this.store().has(key)\n }\n\n /**\n * Determine if an item is missing from the default cache store.\n *\n * @param key - The unique cache key.\n * @returns True if the key does not exist or has expired.\n * @throws {Error} If the underlying store driver encounters a connection error.\n *\n * @example\n * ```typescript\n * if (await cache.missing('config:loaded')) {\n * await loadConfig();\n * }\n * ```\n */\n missing(key: string) {\n return this.store().missing(key)\n }\n\n /**\n * Store an item in the default cache store for a specific duration.\n *\n * @param key - The unique cache key.\n * @param value - The data to be cached.\n * @param ttl - Expiration time in seconds or a specific Date.\n * @returns A promise that resolves when the write is complete.\n * @throws {Error} If the value cannot be serialized or the store is read-only.\n *\n * @example\n * ```typescript\n * await cache.put('key', 'value', 60); // 60 seconds\n * ```\n */\n put(key: string, value: unknown, ttl: CacheTtl) {\n return this.store().put(key, value, ttl)\n }\n\n /**\n * Store an item in the default cache store (alias for put).\n *\n * @param key - The unique cache key.\n * @param value - The data to be cached.\n * @param ttl - Optional expiration time.\n * @returns A promise that resolves when the write is complete.\n * @throws {Error} If the underlying store driver encounters a write error.\n *\n * @example\n * ```typescript\n * await cache.set('theme', 'dark');\n * ```\n */\n set(key: string, value: unknown, ttl?: CacheTtl) {\n return this.store().set(key, value, ttl)\n }\n\n /**\n * Store an item in the default cache store only if it does not already exist.\n *\n * @param key - The unique cache key.\n * @param value - The data to be cached.\n * @param ttl - Optional expiration time.\n * @returns True if the item was added, false if it already existed.\n * @throws {Error} If the underlying store driver encounters a write error.\n *\n * @example\n * ```typescript\n * const added = await cache.add('lock:process', true, 30);\n * ```\n */\n add(key: string, value: unknown, ttl?: CacheTtl) {\n return this.store().add(key, value, ttl)\n }\n\n /**\n * Store an item in the default cache store indefinitely.\n *\n * @param key - The unique cache key.\n * @param value - The data to be cached.\n * @returns A promise that resolves when the write is complete.\n * @throws {Error} If the underlying store driver encounters a write error.\n *\n * @example\n * ```typescript\n * await cache.forever('system:version', '1.0.0');\n * ```\n */\n forever(key: string, value: unknown) {\n return this.store().forever(key, value)\n }\n\n /**\n * Get an item from the cache, or execute the callback and store the result.\n *\n * Ensures the value is cached after the first miss. This provides an atomic-like\n * \"get or set\" flow to prevent multiple concurrent fetches of the same data.\n *\n * @param key - Unique cache key.\n * @param ttl - Duration to cache the result if a miss occurs.\n * @param callback - Logic to execute to fetch fresh data.\n * @returns Cached or freshly fetched value.\n * @throws {Error} If the callback fails or the store write operation errors.\n *\n * @example\n * ```typescript\n * const user = await cache.remember('user:1', 60, async () => {\n * return await db.findUser(1);\n * });\n * ```\n */\n remember<T = unknown>(key: string, ttl: CacheTtl, callback: () => Promise<T> | T) {\n return this.store().remember<T>(key, ttl, callback)\n }\n\n /**\n * Get an item from the cache, or execute the callback and store the result forever.\n *\n * @param key - The unique cache key.\n * @param callback - The closure to execute to fetch the fresh data.\n * @returns The cached or freshly fetched value.\n * @throws {Error} If the callback throws or the store write fails.\n *\n * @example\n * ```typescript\n * const settings = await cache.rememberForever('global:settings', () => {\n * return fetchSettingsFromApi();\n * });\n * ```\n */\n rememberForever<T = unknown>(key: string, callback: () => Promise<T> | T) {\n return this.store().rememberForever<T>(key, callback)\n }\n\n /**\n * Retrieve multiple items from the default cache store by their keys.\n *\n * @param keys - An array of unique cache keys.\n * @returns An object mapping keys to their cached values (or null if missing).\n * @throws {Error} If the underlying store driver encounters a read error.\n *\n * @example\n * ```typescript\n * const values = await cache.many(['key1', 'key2']);\n * ```\n */\n many<T = unknown>(keys: readonly string[]) {\n return this.store().many<T>(keys)\n }\n\n /**\n * Store multiple items in the default cache store for a specific duration.\n *\n * @param values - An object mapping keys to the values to be stored.\n * @param ttl - Expiration time in seconds or a specific Date.\n * @returns A promise that resolves when all writes are complete.\n * @throws {Error} If the underlying store driver encounters a write error.\n *\n * @example\n * ```typescript\n * await cache.putMany({ a: 1, b: 2 }, 60);\n * ```\n */\n putMany(values: Record<string, unknown>, ttl: CacheTtl) {\n return this.store().putMany(values, ttl)\n }\n\n /**\n * Get an item from the cache, allowing stale data while refreshing in background.\n *\n * Implements the Stale-While-Revalidate pattern to minimize latency for\n * frequently accessed but expensive data.\n *\n * @param key - The unique cache key.\n * @param ttlSeconds - How long the value is considered fresh.\n * @param staleSeconds - How long to serve stale data while refreshing.\n * @param callback - The closure to execute to refresh the data.\n * @returns The cached (possibly stale) or freshly fetched value.\n * @throws {Error} If the callback throws during an initial fetch.\n *\n * @example\n * ```typescript\n * const data = await cache.flexible('stats', 60, 30, () => fetchStats());\n * ```\n */\n flexible<T = unknown>(\n key: string,\n ttlSeconds: number,\n staleSeconds: number,\n callback: () => Promise<T> | T\n ) {\n return this.store().flexible<T>(key, ttlSeconds, staleSeconds, callback)\n }\n\n /**\n * Retrieve an item from the default cache store and then delete it.\n *\n * Useful for one-time notifications or temporary tokens.\n *\n * @param key - The unique cache key.\n * @param defaultValue - Fallback value if the key is missing.\n * @returns The cached value before deletion, or the default.\n * @throws {Error} If the underlying store driver encounters a read or delete error.\n *\n * @example\n * ```typescript\n * const token = await cache.pull('temp_token');\n * ```\n */\n pull<T = unknown>(key: string, defaultValue?: T) {\n return this.store().pull<T>(key, defaultValue)\n }\n\n /**\n * Remove an item from the default cache store.\n *\n * @param key - The unique cache key.\n * @returns True if the item was removed, false otherwise.\n * @throws {Error} If the underlying store driver encounters a delete error.\n *\n * @example\n * ```typescript\n * await cache.forget('user:1');\n * ```\n */\n forget(key: string) {\n return this.store().forget(key)\n }\n\n /**\n * Remove an item from the default cache store (alias for forget).\n *\n * @param key - The unique cache key.\n * @returns True if the item was removed, false otherwise.\n * @throws {Error} If the underlying store driver encounters a delete error.\n *\n * @example\n * ```typescript\n * await cache.delete('old_key');\n * ```\n */\n delete(key: string) {\n return this.store().delete(key)\n }\n\n /**\n * Remove all items from the default cache store.\n *\n * @returns A promise that resolves when the flush is complete.\n * @throws {Error} If the underlying store driver encounters a flush error.\n *\n * @example\n * ```typescript\n * await cache.flush();\n * ```\n */\n flush() {\n return this.store().flush()\n }\n\n /**\n * Clear the entire default cache store (alias for flush).\n *\n * @returns A promise that resolves when the clear is complete.\n * @throws {Error} If the underlying store driver encounters a clear error.\n *\n * @example\n * ```typescript\n * await cache.clear();\n * ```\n */\n clear() {\n return this.store().clear()\n }\n\n /**\n * Increment the value of an integer item in the default cache store.\n *\n * @param key - Unique cache key.\n * @param value - Amount to add.\n * @returns New value after incrementing.\n * @throws {Error} If existing value is not a number or the store is read-only.\n *\n * @example\n * ```typescript\n * const count = await cache.increment('page_views');\n * ```\n */\n increment(key: string, value?: number) {\n return this.store().increment(key, value)\n }\n\n /**\n * Decrement the value of an integer item in the default cache store.\n *\n * @param key - Unique cache key.\n * @param value - Amount to subtract.\n * @returns New value after decrementing.\n * @throws {Error} If existing value is not a number or the store is read-only.\n *\n * @example\n * ```typescript\n * const remaining = await cache.decrement('stock:1');\n * ```\n */\n decrement(key: string, value?: number) {\n return this.store().decrement(key, value)\n }\n\n /**\n * Get a distributed lock instance from the default cache store.\n *\n * @param name - The unique name of the lock.\n * @param seconds - The duration the lock should be held for.\n * @returns A CacheLock instance.\n * @throws {Error} If the underlying store does not support locking.\n *\n * @example\n * ```typescript\n * const lock = cache.lock('process_data', 10);\n * if (await lock.get()) {\n * // ...\n * await lock.release();\n * }\n * ```\n */\n lock(name: string, seconds?: number) {\n return this.store().lock(name, seconds)\n }\n\n /**\n * Access a tagged cache section for grouped operations.\n *\n * Tags allow you to clear groups of cache entries simultaneously.\n * Note: This is only supported by specific drivers like 'memory'.\n *\n * @param tags - An array of tag names.\n * @returns A tagged cache repository instance.\n * @throws {Error} If the underlying store driver does not support tags.\n *\n * @example\n * ```typescript\n * await cache.tags(['users', 'profiles']).put('user:1', data, 60);\n * await cache.tags(['users']).flush(); // Clears all 'users' tagged entries\n * ```\n */\n tags(tags: readonly string[]) {\n return this.store().tags(tags)\n }\n}\n",
13
+ "/**\n * Contract for a mechanism that predicts future cache key accesses.\n *\n * Implementations observe sequential access patterns to predict which keys\n * are likely to be requested next, enabling prefetching strategies.\n *\n * @public\n * @since 3.2.0\n */\nexport interface AccessPredictor {\n /**\n * Record a cache key access to learn temporal patterns.\n *\n * @param key - Cache key currently being accessed.\n */\n record(key: string): void\n\n /**\n * Predict potential future keys based on learned access history.\n *\n * @param key - Current cache key acting as the trigger for prediction.\n * @returns Array of predicted keys, ordered by likelihood.\n */\n predict(key: string): string[]\n\n /**\n * Reset all learned transition probabilities and state.\n */\n reset(): void\n}\n\n/**\n * A simple Markov Chain predictor (Order-1).\n *\n * Records transitions (A -> B) between sequential accesses and predicts\n * B when A is next encountered. This is particularly effective for\n * predictable resource loading sequences.\n *\n * @public\n * @since 3.2.0\n *\n * @example\n * ```typescript\n * const predictor = new MarkovPredictor();\n * predictor.record('user:1');\n * predictor.record('user:1:profile');\n * const next = predictor.predict('user:1'); // ['user:1:profile']\n * ```\n */\nexport class MarkovPredictor implements AccessPredictor {\n private transitions = new Map<string, Map<string, number>>()\n private lastKey: string | null = null\n private readonly maxNodes: number\n private readonly maxEdgesPerNode: number\n\n /**\n * Initialize a new MarkovPredictor.\n *\n * @param options - Limits for internal transition graph to manage memory.\n */\n constructor(options: { maxNodes?: number; maxEdgesPerNode?: number } = {}) {\n this.maxNodes = options.maxNodes ?? 1000\n this.maxEdgesPerNode = options.maxEdgesPerNode ?? 10\n }\n\n record(key: string): void {\n if (this.lastKey && this.lastKey !== key) {\n if (!this.transitions.has(this.lastKey)) {\n if (this.transitions.size >= this.maxNodes) {\n // Simple eviction: clear everything if full.\n // In a real localized scenario we might use LRU, but for cache prediction this is often enough\n // or we could remove a random key.\n this.transitions.clear()\n }\n this.transitions.set(this.lastKey, new Map())\n }\n\n const edges = this.transitions.get(this.lastKey)!\n const count = edges.get(key) ?? 0\n edges.set(key, count + 1)\n\n // Prune edges if too many\n if (edges.size > this.maxEdgesPerNode) {\n // Remove least frequent\n let minKey = ''\n let minCount = Infinity\n for (const [k, c] of edges) {\n if (c < minCount) {\n minCount = c\n minKey = k\n }\n }\n if (minKey) {\n edges.delete(minKey)\n }\n }\n }\n\n this.lastKey = key\n }\n\n predict(key: string): string[] {\n const edges = this.transitions.get(key)\n if (!edges) {\n return []\n }\n\n // Return keys sorted by frequency (descending)\n return Array.from(edges.entries())\n .sort((a, b) => b[1] - a[1])\n .map((entry) => entry[0])\n }\n\n reset(): void {\n this.transitions.clear()\n this.lastKey = null\n }\n}\n",
14
+ "import type { CacheStore } from '../store'\nimport type { CacheKey, CacheTtl } from '../types'\n\nexport type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN'\n\n/**\n * Options for the CircuitBreakerStore.\n *\n * @public\n * @since 3.2.0\n *\n * @example\n * ```typescript\n * const options: CircuitBreakerOptions = {\n * maxFailures: 3,\n * resetTimeout: 30000,\n * fallback: new MemoryStore()\n * };\n * ```\n */\nexport type CircuitBreakerOptions = {\n /**\n * Number of consecutive failures before opening the circuit.\n * @defaultValue 5\n */\n maxFailures?: number\n /**\n * Time in milliseconds to stay in OPEN state before transitioning to HALF_OPEN.\n * @defaultValue 60000\n */\n resetTimeout?: number\n /**\n * Optional fallback store to use when the primary store is unavailable.\n */\n fallback?: CacheStore\n}\n\n/**\n * A protective wrapper for cache stores that prevents cascading failures\n * through circuit-breaking logic.\n *\n * When the primary store encounters repeated failures, the circuit opens,\n * temporarily bypassing the primary store and optionally using a fallback.\n *\n * @public\n * @since 3.2.0\n */\nexport class CircuitBreakerStore implements CacheStore {\n private state: CircuitState = 'CLOSED'\n private failures = 0\n private lastErrorTime = 0\n private options: Required<Omit<CircuitBreakerOptions, 'fallback'>> & { fallback?: CacheStore }\n\n constructor(\n private readonly primary: CacheStore,\n options: CircuitBreakerOptions = {}\n ) {\n this.options = {\n maxFailures: options.maxFailures ?? 5,\n resetTimeout: options.resetTimeout ?? 60_000,\n fallback: options.fallback,\n }\n }\n\n private async execute<T>(\n operation: (store: CacheStore) => Promise<T>,\n fallbackResult: T = null as any\n ): Promise<T> {\n if (this.state === 'OPEN') {\n if (Date.now() - this.lastErrorTime > this.options.resetTimeout) {\n this.state = 'HALF_OPEN'\n } else {\n return this.handleFallback(operation, fallbackResult)\n }\n }\n\n try {\n const result = await operation(this.primary)\n this.onSuccess()\n return result\n } catch (_error) {\n this.onFailure()\n return this.handleFallback(operation, fallbackResult)\n }\n }\n\n private onSuccess(): void {\n this.failures = 0\n this.state = 'CLOSED'\n }\n\n private onFailure(): void {\n this.failures++\n this.lastErrorTime = Date.now()\n if (this.failures >= this.options.maxFailures) {\n this.state = 'OPEN'\n }\n }\n\n private async handleFallback<T>(\n operation: (store: CacheStore) => Promise<T>,\n fallbackResult: T\n ): Promise<T> {\n if (this.options.fallback) {\n try {\n return await operation(this.options.fallback)\n } catch {\n // Fallback also failed\n }\n }\n\n return fallbackResult\n }\n\n async get<T = unknown>(key: CacheKey): Promise<T | null> {\n return this.execute((s) => s.get<T>(key))\n }\n\n async put(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<void> {\n return this.execute((s) => s.put(key, value, ttl))\n }\n\n async add(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<boolean> {\n return this.execute((s) => s.add(key, value, ttl), false)\n }\n\n async forget(key: CacheKey): Promise<boolean> {\n return this.execute((s) => s.forget(key), false)\n }\n\n async flush(): Promise<void> {\n return this.execute((s) => s.flush())\n }\n\n async increment(key: CacheKey, value?: number): Promise<number> {\n return this.execute((s) => s.increment(key, value), 0)\n }\n\n async decrement(key: CacheKey, value?: number): Promise<number> {\n return this.execute((s) => s.decrement(key, value), 0)\n }\n\n async ttl(key: CacheKey): Promise<number | null> {\n return this.execute(async (s) => (s.ttl ? s.ttl(key) : null))\n }\n\n /**\n * Returns current state for monitoring.\n *\n * @returns Current state of the circuit breaker.\n *\n * @example\n * ```typescript\n * const state = store.getState();\n * if (state === 'OPEN') {\n * console.warn('Primary cache is unavailable');\n * }\n * ```\n */\n getState(): CircuitState {\n return this.state\n }\n}\n",
15
+ "import { dirname, join } from 'node:path'\nimport {\n getRuntimeAdapter,\n type RuntimeAdapter,\n runtimeMkdir,\n runtimeReadDir,\n runtimeReadText,\n runtimeRemoveRecursive,\n runtimeRename,\n runtimeStatFull,\n runtimeWriteFileExclusive,\n} from '@gravito/core'\nimport { NativeHasher } from '@gravito/core/ffi'\nimport { type CacheLock, LockTimeoutError, sleep } from '../locks'\nimport type { CacheStore } from '../store'\nimport {\n type CacheKey,\n type CacheTtl,\n type CacheValue,\n isExpired,\n normalizeCacheKey,\n ttlToExpiresAt,\n} from '../types'\n\ntype FileEntry = {\n expiresAt: number | null\n value: unknown\n}\n\ntype LockFileEntry = {\n owner: string\n expiresAt: number\n pid: number\n}\n\n/**\n * Configuration options for the `FileStore` implementation.\n */\nexport type FileStoreOptions = {\n directory: string\n enableCleanup?: boolean\n cleanupInterval?: number\n maxFiles?: number\n useSubdirectories?: boolean\n}\n\n/**\n * A persistent filesystem-based implementation of the `CacheStore` interface.\n */\nexport class FileStore implements CacheStore {\n private cleanupTimer: ReturnType<typeof setInterval> | null = null\n private runtime: RuntimeAdapter = getRuntimeAdapter()\n\n constructor(private options: FileStoreOptions) {\n if (options.enableCleanup !== false) {\n this.startCleanupDaemon(options.cleanupInterval ?? 60_000)\n }\n }\n\n private startCleanupDaemon(interval: number): void {\n this.cleanupTimer = setInterval(() => {\n this.cleanExpiredFiles().catch(() => {})\n }, interval)\n\n if (this.cleanupTimer.unref) {\n this.cleanupTimer.unref()\n }\n }\n\n async cleanExpiredFiles(): Promise<number> {\n await this.ensureDir()\n let cleaned = 0\n const validFiles: Array<{ path: string; mtime: number }> = []\n\n const scanDir = async (dir: string) => {\n const entries = await runtimeReadDir(this.runtime, dir)\n for (const entry of entries) {\n const fullPath = join(dir, entry.name)\n if (entry.isDirectory) {\n await scanDir(fullPath)\n try {\n const { rmdir } = await import('node:fs/promises')\n await rmdir(fullPath)\n } catch {}\n } else if (entry.isFile) {\n if (!entry.name.endsWith('.json') || entry.name.startsWith('.lock-')) {\n continue\n }\n\n try {\n const raw = await runtimeReadText(this.runtime, fullPath)\n const data = JSON.parse(raw) as FileEntry\n\n if (isExpired(data.expiresAt)) {\n await runtimeRemoveRecursive(this.runtime, fullPath)\n cleaned++\n } else if (this.options.maxFiles) {\n const stats = await runtimeStatFull(this.runtime, fullPath)\n validFiles.push({ path: fullPath, mtime: stats.mtimeMs })\n }\n } catch {}\n }\n }\n }\n\n await scanDir(this.options.directory)\n\n if (this.options.maxFiles && validFiles.length > this.options.maxFiles) {\n validFiles.sort((a, b) => a.mtime - b.mtime)\n const toRemove = validFiles.slice(0, validFiles.length - this.options.maxFiles)\n\n await Promise.all(\n toRemove.map(async (f) => {\n try {\n await runtimeRemoveRecursive(this.runtime, f.path)\n cleaned++\n } catch {}\n })\n )\n }\n\n return cleaned\n }\n\n async destroy(): Promise<void> {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer)\n this.cleanupTimer = null\n }\n }\n\n private async ensureDir(): Promise<void> {\n await runtimeMkdir(this.runtime, this.options.directory, { recursive: true })\n }\n\n private async filePathForKey(key: string): Promise<string> {\n const hashed = hashKey(key)\n if (this.options.useSubdirectories) {\n const d1 = hashed.substring(0, 2)\n const d2 = hashed.substring(2, 4)\n return join(this.options.directory, d1, d2, `${hashed}.json`)\n }\n return join(this.options.directory, `${hashed}.json`)\n }\n\n async get<T = unknown>(key: CacheKey): Promise<CacheValue<T>> {\n const normalized = normalizeCacheKey(key)\n await this.ensureDir()\n const file = await this.filePathForKey(normalized)\n\n try {\n const raw = await runtimeReadText(this.runtime, file)\n const data = JSON.parse(raw) as FileEntry\n if (isExpired(data.expiresAt)) {\n await this.forget(normalized)\n return null\n }\n return data.value as T\n } catch {\n return null\n }\n }\n\n async put(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<void> {\n const normalized = normalizeCacheKey(key)\n await this.ensureDir()\n const expiresAt = ttlToExpiresAt(ttl)\n if (expiresAt !== null && expiresAt !== undefined && expiresAt <= Date.now()) {\n await this.forget(normalized)\n return\n }\n\n const file = await this.filePathForKey(normalized)\n\n if (this.options.useSubdirectories) {\n await runtimeMkdir(this.runtime, dirname(file), { recursive: true })\n }\n\n const tempFile = `${file}.tmp.${Date.now()}.${crypto.randomUUID()}`\n const payload: FileEntry = { expiresAt: expiresAt ?? null, value }\n\n try {\n await this.runtime.writeFile(tempFile, JSON.stringify(payload))\n await runtimeRename(this.runtime, tempFile, file)\n } catch (error) {\n await runtimeRemoveRecursive(this.runtime, tempFile).catch(() => {})\n throw error\n }\n }\n\n async add(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<boolean> {\n const normalized = normalizeCacheKey(key)\n const existing = await this.get(normalized)\n if (existing !== null) {\n return false\n }\n await this.put(normalized, value, ttl)\n return true\n }\n\n async forget(key: CacheKey): Promise<boolean> {\n const normalized = normalizeCacheKey(key)\n await this.ensureDir()\n const file = await this.filePathForKey(normalized)\n try {\n await runtimeRemoveRecursive(this.runtime, file)\n return true\n } catch {\n return false\n }\n }\n\n async flush(): Promise<void> {\n await this.ensureDir()\n await runtimeRemoveRecursive(this.runtime, this.options.directory)\n await this.ensureDir()\n }\n\n async increment(key: CacheKey, value = 1): Promise<number> {\n const normalized = normalizeCacheKey(key)\n const current = await this.get<number>(normalized)\n const next = (current ?? 0) + value\n await this.put(normalized, next, null)\n return next\n }\n\n async decrement(key: CacheKey, value = 1): Promise<number> {\n return this.increment(key, -value)\n }\n\n async ttl(key: CacheKey): Promise<number | null> {\n const normalized = normalizeCacheKey(key)\n const file = await this.filePathForKey(normalized)\n\n try {\n const raw = await runtimeReadText(this.runtime, file)\n const data = JSON.parse(raw) as FileEntry\n\n if (data.expiresAt === null) {\n return null\n }\n\n const remaining = Math.ceil((data.expiresAt - Date.now()) / 1000)\n return remaining > 0 ? remaining : null\n } catch {\n return null\n }\n }\n\n lock(name: string, seconds = 10): CacheLock {\n const normalizedName = normalizeCacheKey(name)\n const lockFile = join(this.options.directory, `.lock-${syncHashKey(normalizedName)}`)\n const ttlMillis = Math.max(1, seconds) * 1000\n const owner = crypto.randomUUID()\n const runtime = this.runtime\n\n const isProcessAlive = (pid: number): boolean => {\n try {\n process.kill(pid, 0)\n return true\n } catch {\n return false\n }\n }\n\n const tryAcquire = async (): Promise<boolean> => {\n await this.ensureDir()\n try {\n const lockData: LockFileEntry = {\n owner,\n expiresAt: Date.now() + ttlMillis,\n pid: process.pid,\n }\n await runtimeWriteFileExclusive(runtime, lockFile, JSON.stringify(lockData))\n return true\n } catch {\n try {\n const raw = await runtimeReadText(runtime, lockFile)\n const data = JSON.parse(raw) as LockFileEntry\n\n const isExpiredLock = !data.expiresAt || Date.now() > data.expiresAt\n const isProcessDead = data.pid && !isProcessAlive(data.pid)\n\n if (isExpiredLock || isProcessDead) {\n await runtimeRemoveRecursive(runtime, lockFile)\n }\n } catch {}\n return false\n }\n }\n\n return {\n async acquire(): Promise<boolean> {\n return tryAcquire()\n },\n async release(): Promise<void> {\n try {\n const raw = await runtimeReadText(runtime, lockFile)\n const data = JSON.parse(raw) as LockFileEntry\n if (data.owner === owner) {\n await runtimeRemoveRecursive(runtime, lockFile)\n }\n } catch {}\n },\n async block<T>(\n secondsToWait: number,\n callback: () => Promise<T> | T,\n options?: { sleepMillis?: number }\n ): Promise<T> {\n const deadline = Date.now() + Math.max(0, secondsToWait) * 1000\n const sleepMillis = options?.sleepMillis ?? 150\n\n while (Date.now() <= deadline) {\n if (await this.acquire()) {\n try {\n return await callback()\n } finally {\n await this.release()\n }\n }\n await sleep(sleepMillis)\n }\n\n throw new LockTimeoutError(\n `Failed to acquire lock '${name}' within ${secondsToWait} seconds.`\n )\n },\n }\n }\n}\n\nfunction hashKey(key: string): string {\n return NativeHasher.sha256(key)\n}\n\nfunction syncHashKey(key: string): string {\n let hash = 5381\n for (let i = 0; i < key.length; i++) {\n hash = ((hash << 5) + hash) ^ key.charCodeAt(i)\n hash = hash >>> 0\n }\n return hash.toString(16).padStart(8, '0')\n}\n",
16
+ "/**\n * A doubly linked list node for the LRU cache.\n *\n * Internal structure used to maintain the access order of cached items.\n *\n * @internal\n */\ninterface LRUNode<T> {\n /**\n * The unique identifier for the cached item.\n */\n key: string\n /**\n * The actual data stored in the cache.\n */\n value: T\n /**\n * Reference to the previous node in the access order (closer to head).\n */\n prev: LRUNode<T> | null\n /**\n * Reference to the next node in the access order (closer to tail).\n */\n next: LRUNode<T> | null\n}\n\n/**\n * A generic LRU (Least Recently Used) cache implementation.\n *\n * Uses a Map for O(1) lookups and a Doubly Linked List for O(1) updates to the access order.\n * When the cache reaches its maximum capacity, the least recently accessed item is evicted.\n *\n * @example\n * ```typescript\n * const cache = new LRUCache<number>(100, (key, value) => {\n * console.log(`Evicted: ${key} = ${value}`);\n * });\n * cache.set('key1', 42);\n * const val = cache.get('key1'); // 42\n * ```\n */\nexport class LRUCache<T> {\n private map = new Map<string, LRUNode<T>>()\n private head: LRUNode<T> | null = null\n private tail: LRUNode<T> | null = null\n\n /**\n * Creates a new LRU cache instance.\n *\n * @param maxSize - The maximum number of items allowed in the cache. Set to 0 for unlimited.\n * @param onEvict - Optional callback triggered when an item is evicted due to capacity limits.\n */\n constructor(\n private maxSize: number,\n private onEvict?: (key: string, value: T) => void\n ) {}\n\n /**\n * The current number of items stored in the cache.\n */\n get size(): number {\n return this.map.size\n }\n\n /**\n * Checks if a key exists in the cache without updating its access order.\n *\n * @param key - The identifier to look for.\n * @returns True if the key exists, false otherwise.\n */\n has(key: string): boolean {\n return this.map.has(key)\n }\n\n /**\n * Retrieves an item from the cache and marks it as most recently used.\n *\n * @param key - The identifier of the item to retrieve.\n * @returns The cached value, or undefined if not found.\n *\n * @example\n * ```typescript\n * const value = cache.get('my-key');\n * ```\n */\n get(key: string): T | undefined {\n const node = this.map.get(key)\n if (!node) {\n return undefined\n }\n this.moveToHead(node)\n return node.value\n }\n\n /**\n * Retrieves an item from the cache without updating its access order.\n *\n * Useful for inspecting the cache without affecting eviction priority.\n *\n * @param key - The identifier of the item to peek.\n * @returns The cached value, or undefined if not found.\n */\n peek(key: string): T | undefined {\n const node = this.map.get(key)\n return node?.value\n }\n\n /**\n * Adds or updates an item in the cache, marking it as most recently used.\n *\n * If the cache is at capacity, the least recently used item will be evicted.\n *\n * @param key - The identifier for the item.\n * @param value - The data to store.\n *\n * @example\n * ```typescript\n * cache.set('user:1', { name: 'Alice' });\n * ```\n */\n set(key: string, value: T): void {\n const existingNode = this.map.get(key)\n if (existingNode) {\n existingNode.value = value\n this.moveToHead(existingNode)\n return\n }\n\n if (this.maxSize > 0 && this.map.size >= this.maxSize) {\n this.evict()\n }\n\n const newNode: LRUNode<T> = {\n key,\n value,\n prev: null,\n next: this.head,\n }\n\n if (this.head) {\n this.head.prev = newNode\n }\n this.head = newNode\n\n if (!this.tail) {\n this.tail = newNode\n }\n\n this.map.set(key, newNode)\n }\n\n /**\n * Removes an item from the cache.\n *\n * @param key - The identifier of the item to remove.\n * @returns True if the item was found and removed, false otherwise.\n */\n delete(key: string): boolean {\n const node = this.map.get(key)\n if (!node) {\n return false\n }\n\n this.removeNode(node)\n this.map.delete(key)\n return true\n }\n\n /**\n * Removes all items from the cache.\n */\n clear(): void {\n this.map.clear()\n this.head = null\n this.tail = null\n }\n\n /**\n * Moves a node to the head of the linked list (most recently used).\n *\n * @param node - The node to promote.\n */\n private moveToHead(node: LRUNode<T>): void {\n if (node === this.head) {\n return\n }\n\n if (node.prev) {\n node.prev.next = node.next\n }\n if (node.next) {\n node.next.prev = node.prev\n }\n\n if (node === this.tail) {\n this.tail = node.prev\n }\n\n node.prev = null\n node.next = this.head\n\n if (this.head) {\n this.head.prev = node\n }\n this.head = node\n }\n\n /**\n * Removes a node from the linked list.\n *\n * @param node - The node to remove.\n */\n private removeNode(node: LRUNode<T>): void {\n if (node.prev) {\n node.prev.next = node.next\n } else {\n this.head = node.next\n }\n\n if (node.next) {\n node.next.prev = node.prev\n } else {\n this.tail = node.prev\n }\n\n node.prev = null\n node.next = null\n }\n\n /**\n * Evicts the least recently used item (the tail of the list).\n *\n * Triggers the `onEvict` callback if provided.\n */\n private evict(): void {\n if (!this.tail) {\n return\n }\n\n const node = this.tail\n if (this.onEvict) {\n this.onEvict(node.key, node.value)\n }\n\n this.removeNode(node)\n this.map.delete(node.key)\n }\n}\n",
17
+ "import { type CacheLock, LockTimeoutError, sleep } from '../locks'\nimport type { CacheStore, TaggableStore } from '../store'\nimport {\n type CacheKey,\n type CacheTtl,\n type CacheValue,\n isExpired,\n normalizeCacheKey,\n ttlToExpiresAt,\n} from '../types'\nimport { LRUCache } from '../utils/LRUCache'\n\ntype Entry = {\n value: unknown\n expiresAt: number | null\n}\n\ntype LockEntry = {\n owner: string\n expiresAt: number\n}\n\n/**\n * Configuration options for the `MemoryStore`.\n *\n * Used to define the behavior of the in-memory cache, such as eviction policies.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const options: MemoryStoreOptions = { maxItems: 500 };\n * ```\n */\nexport type MemoryStoreOptions = {\n /**\n * Maximum number of items to keep in memory.\n *\n * When the limit is reached, the Least Recently Used (LRU) item is evicted.\n * Set to 0 or undefined for unlimited capacity (not recommended for production).\n */\n maxItems?: number\n}\n\n/**\n * Performance and usage statistics for the `MemoryStore`.\n *\n * Provides insights into cache efficiency and capacity management.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const stats: MemoryCacheStats = {\n * hits: 100,\n * misses: 20,\n * hitRate: 0.83,\n * size: 500,\n * evictions: 5\n * };\n * ```\n */\nexport type MemoryCacheStats = {\n /** Total number of successful cache lookups. */\n hits: number\n /** Total number of failed cache lookups (key not found or expired). */\n misses: number\n /**\n * The efficiency ratio of the cache.\n *\n * Calculated as hits / (hits + misses). Ranges from 0.0 to 1.0.\n */\n hitRate: number\n /** Current number of active items stored in the cache. */\n size: number\n /** Total number of items removed to make room for new entries. */\n evictions: number\n}\n\n/**\n * Fast, non-persistent in-memory cache implementation.\n *\n * `MemoryStore` provides a high-performance backend for the `CacheStore` interface.\n * It supports TTL-based expiration, LRU eviction, basic tagging for bulk invalidation,\n * and local mutex locking for atomic operations.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const store = new MemoryStore({ maxItems: 1000 });\n * await store.put('user:1', { name: 'Alice' }, 3600);\n * const user = await store.get('user:1');\n * ```\n */\nexport class MemoryStore implements CacheStore, TaggableStore {\n private entries: LRUCache<Entry>\n private locks = new Map<string, LockEntry>()\n private stats = { hits: 0, misses: 0, evictions: 0 }\n\n private tagToKeys = new Map<string, Set<string>>()\n private keyToTags = new Map<string, Set<string>>()\n\n /**\n * Creates a new MemoryStore instance.\n *\n * @param options - Configuration for capacity and eviction.\n */\n constructor(options: MemoryStoreOptions = {}) {\n this.entries = new LRUCache<Entry>(options.maxItems ?? 0, (key) => {\n this.tagIndexRemove(key)\n this.stats.evictions++\n })\n }\n\n /**\n * Retrieves current performance metrics.\n *\n * @returns A snapshot of hits, misses, size, and eviction counts.\n *\n * @example\n * ```typescript\n * const stats = store.getStats();\n * console.log(`Cache hit rate: ${stats.hitRate * 100}%`);\n * ```\n */\n getStats(): MemoryCacheStats {\n const total = this.stats.hits + this.stats.misses\n return {\n hits: this.stats.hits,\n misses: this.stats.misses,\n hitRate: total > 0 ? this.stats.hits / total : 0,\n size: this.entries.size,\n evictions: this.stats.evictions,\n }\n }\n\n private cleanupExpired(key: string, now = Date.now()): void {\n const entry = this.entries.peek(key)\n if (!entry) {\n return\n }\n if (isExpired(entry.expiresAt, now)) {\n void this.forget(key)\n }\n }\n\n /**\n * Retrieves an item from the cache by its key.\n *\n * If the item is expired, it will be automatically removed and `null` will be returned.\n *\n * @param key - The unique identifier for the cached item.\n * @returns The cached value, or `null` if not found or expired.\n *\n * @example\n * ```typescript\n * const value = await store.get('my-key');\n * ```\n */\n async get<T = unknown>(key: CacheKey): Promise<CacheValue<T>> {\n const normalized = normalizeCacheKey(key)\n const entry = this.entries.get(normalized)\n if (!entry) {\n this.stats.misses++\n return null\n }\n\n if (isExpired(entry.expiresAt)) {\n await this.forget(normalized)\n this.stats.misses++\n return null\n }\n\n this.stats.hits++\n return entry.value as T\n }\n\n /**\n * Stores an item in the cache with a specific TTL.\n *\n * If the key already exists, it will be overwritten.\n *\n * @param key - The unique identifier for the item.\n * @param value - The data to store.\n * @param ttl - Time-to-live in seconds, or a Date object for absolute expiration.\n *\n * @example\n * ```typescript\n * await store.put('settings', { theme: 'dark' }, 3600);\n * ```\n */\n async put(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<void> {\n const normalized = normalizeCacheKey(key)\n const expiresAt = ttlToExpiresAt(ttl)\n if (expiresAt !== null && expiresAt !== undefined && expiresAt <= Date.now()) {\n await this.forget(normalized)\n return\n }\n\n this.entries.set(normalized, { value, expiresAt: expiresAt ?? null })\n }\n\n /**\n * Stores an item only if it does not already exist in the cache.\n *\n * @param key - The unique identifier for the item.\n * @param value - The data to store.\n * @param ttl - Time-to-live in seconds or absolute expiration.\n * @returns `true` if the item was added, `false` if it already existed.\n *\n * @example\n * ```typescript\n * const added = await store.add('unique-task', data, 60);\n * ```\n */\n async add(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<boolean> {\n const normalized = normalizeCacheKey(key)\n this.cleanupExpired(normalized)\n if (this.entries.has(normalized)) {\n return false\n }\n await this.put(normalized, value, ttl)\n return true\n }\n\n /**\n * Removes an item from the cache.\n *\n * @param key - The unique identifier for the item to remove.\n * @returns `true` if the item existed and was removed, `false` otherwise.\n *\n * @example\n * ```typescript\n * await store.forget('user:session');\n * ```\n */\n async forget(key: CacheKey): Promise<boolean> {\n const normalized = normalizeCacheKey(key)\n const existed = this.entries.delete(normalized)\n this.tagIndexRemove(normalized)\n return existed\n }\n\n /**\n * Removes all items from the cache and resets all internal indexes.\n *\n * @example\n * ```typescript\n * await store.flush();\n * ```\n */\n async flush(): Promise<void> {\n this.entries.clear()\n this.tagToKeys.clear()\n this.keyToTags.clear()\n }\n\n /**\n * Increments the value of an item in the cache.\n *\n * If the key does not exist, it starts from 0.\n *\n * @param key - The identifier for the numeric value.\n * @param value - The amount to increment by (defaults to 1).\n * @returns The new incremented value.\n *\n * @example\n * ```typescript\n * const count = await store.increment('page_views');\n * ```\n */\n async increment(key: CacheKey, value = 1): Promise<number> {\n const normalized = normalizeCacheKey(key)\n const current = await this.get<number>(normalized)\n const next = (current ?? 0) + value\n await this.put(normalized, next, null)\n return next\n }\n\n /**\n * Decrements the value of an item in the cache.\n *\n * @param key - The identifier for the numeric value.\n * @param value - The amount to decrement by (defaults to 1).\n * @returns The new decremented value.\n *\n * @example\n * ```typescript\n * const remaining = await store.decrement('stock_count', 5);\n * ```\n */\n async decrement(key: CacheKey, value = 1): Promise<number> {\n return this.increment(key, -value)\n }\n\n /**\n * Gets the remaining time-to-live for a cached item.\n *\n * @param key - The identifier for the cached item.\n * @returns Remaining seconds, or `null` if the item has no expiration or does not exist.\n *\n * @example\n * ```typescript\n * const secondsLeft = await store.ttl('token');\n * ```\n */\n async ttl(key: CacheKey): Promise<number | null> {\n const normalized = normalizeCacheKey(key)\n const entry = this.entries.peek(normalized)\n\n if (!entry || entry.expiresAt === null) {\n return null\n }\n\n const now = Date.now()\n if (isExpired(entry.expiresAt, now)) {\n await this.forget(normalized)\n return null\n }\n\n return Math.max(0, Math.ceil((entry.expiresAt - now) / 1000))\n }\n\n /**\n * Creates a lock instance for managing exclusive access to a resource.\n *\n * @param name - The name of the lock.\n * @param seconds - The duration the lock should be held (defaults to 10).\n * @returns A `CacheLock` instance.\n *\n * @example\n * ```typescript\n * const lock = store.lock('process-report', 30);\n * if (await lock.acquire()) {\n * try {\n * // Critical section\n * } finally {\n * await lock.release();\n * }\n * }\n * ```\n */\n lock(name: string, seconds = 10): CacheLock {\n const lockKey = `lock:${normalizeCacheKey(name)}`\n const ttlMillis = Math.max(1, seconds) * 1000\n const locks = this.locks\n\n const acquire = async (): Promise<{ ok: boolean; owner?: string }> => {\n const now = Date.now()\n const existing = locks.get(lockKey)\n if (existing && existing.expiresAt > now) {\n return { ok: false }\n }\n\n const owner = crypto.randomUUID()\n locks.set(lockKey, { owner, expiresAt: now + ttlMillis })\n return { ok: true, owner }\n }\n\n let owner: string | undefined\n\n return {\n /**\n * Attempts to acquire the lock.\n *\n * @returns `true` if acquired, `false` if already held by another process.\n */\n async acquire(): Promise<boolean> {\n const result = await acquire()\n if (!result.ok) {\n return false\n }\n owner = result.owner\n return true\n },\n\n /**\n * Releases the lock if it is held by the current owner.\n */\n async release(): Promise<void> {\n if (!owner) {\n return\n }\n const existing = locks.get(lockKey)\n if (existing?.owner === owner) {\n locks.delete(lockKey)\n }\n owner = undefined\n },\n\n /**\n * Attempts to acquire the lock and execute a callback, waiting if necessary.\n *\n * @param secondsToWait - How long to wait for the lock before timing out.\n * @param callback - The logic to execute while holding the lock.\n * @param options - Polling configuration.\n * @returns The result of the callback.\n * @throws {LockTimeoutError} If the lock cannot be acquired within the wait time.\n *\n * @example\n * ```typescript\n * await lock.block(5, async () => {\n * // This code runs exclusively\n * });\n * ```\n */\n async block<T>(\n secondsToWait: number,\n callback: () => Promise<T> | T,\n options?: { sleepMillis?: number }\n ): Promise<T> {\n const deadline = Date.now() + Math.max(0, secondsToWait) * 1000\n const sleepMillis = options?.sleepMillis ?? 150\n\n while (Date.now() <= deadline) {\n if (await this.acquire()) {\n try {\n return await callback()\n } finally {\n await this.release()\n }\n }\n await sleep(sleepMillis)\n }\n\n throw new LockTimeoutError(\n `Failed to acquire lock '${name}' within ${secondsToWait} seconds.`\n )\n },\n }\n }\n\n /**\n * Generates a tagged key for storage.\n *\n * Used internally to prefix keys with their associated tags.\n *\n * @param key - The original cache key.\n * @param tags - List of tags to associate with the key.\n * @returns A formatted string containing tags and the key.\n */\n tagKey(key: string, tags: readonly string[]): string {\n const normalizedKey = normalizeCacheKey(key)\n const normalizedTags = [...tags].map(String).filter(Boolean).sort()\n if (normalizedTags.length === 0) {\n return normalizedKey\n }\n return `tags:${normalizedTags.join('|')}:${normalizedKey}`\n }\n\n /**\n * Indexes a tagged key for bulk invalidation.\n *\n * @param tags - The tags to index.\n * @param taggedKey - The full key (including tag prefix) to store.\n */\n tagIndexAdd(tags: readonly string[], taggedKey: string): void {\n const normalizedTags = [...tags].map(String).filter(Boolean)\n if (normalizedTags.length === 0) {\n return\n }\n\n for (const tag of normalizedTags) {\n let keys = this.tagToKeys.get(tag)\n if (!keys) {\n keys = new Set<string>()\n this.tagToKeys.set(tag, keys)\n }\n keys.add(taggedKey)\n }\n\n let tagSet = this.keyToTags.get(taggedKey)\n if (!tagSet) {\n tagSet = new Set<string>()\n this.keyToTags.set(taggedKey, tagSet)\n }\n for (const tag of normalizedTags) {\n tagSet.add(tag)\n }\n }\n\n /**\n * Removes a key from the tag indexes.\n *\n * @param taggedKey - The key to remove from all tag sets.\n */\n tagIndexRemove(taggedKey: string): void {\n const tags = this.keyToTags.get(taggedKey)\n if (!tags) {\n return\n }\n\n for (const tag of tags) {\n const keys = this.tagToKeys.get(tag)\n if (!keys) {\n continue\n }\n keys.delete(taggedKey)\n if (keys.size === 0) {\n this.tagToKeys.delete(tag)\n }\n }\n\n this.keyToTags.delete(taggedKey)\n }\n\n /**\n * Invalidates all cache entries associated with any of the given tags.\n *\n * @param tags - The tags to flush.\n *\n * @example\n * ```typescript\n * await store.flushTags(['users', 'profiles']);\n * ```\n */\n async flushTags(tags: readonly string[]): Promise<void> {\n const normalizedTags = [...tags].map(String).filter(Boolean)\n if (normalizedTags.length === 0) {\n return\n }\n\n const keysToDelete = new Set<string>()\n for (const tag of normalizedTags) {\n const keys = this.tagToKeys.get(tag)\n if (!keys) {\n continue\n }\n for (const k of keys) {\n keysToDelete.add(k)\n }\n }\n\n for (const key of keysToDelete) {\n await this.forget(key)\n }\n }\n}\n",
18
+ "import type { CacheStore } from '../store'\nimport type { CacheKey, CacheTtl, CacheValue } from '../types'\n\n/**\n * A \"black-hole\" cache implementation that discards all data.\n *\n * NullStore implements the `CacheStore` interface but performs no actual storage\n * or retrieval operations. It is primarily used to disable caching globally\n * without changing application logic, or as a mock in testing environments.\n *\n * @example\n * ```typescript\n * const store = new NullStore();\n * await store.put('key', 'value', 60);\n * const value = await store.get('key'); // always returns null\n * ```\n *\n * @public\n * @since 3.0.0\n */\nexport class NullStore implements CacheStore {\n /**\n * Simulates a cache miss for any given key.\n *\n * @param _key - Identifier for the cached item.\n * @returns Always `null` regardless of requested key.\n *\n * @example\n * ```typescript\n * const value = await store.get('my-key');\n * ```\n */\n async get<T = unknown>(_key: CacheKey): Promise<CacheValue<T>> {\n return null\n }\n\n /**\n * Discards the provided value instead of storing it.\n *\n * @param _key - The identifier for the item.\n * @param _value - The data to be cached.\n * @param _ttl - Time-to-live in seconds.\n * @returns Resolves immediately after discarding the data.\n *\n * @example\n * ```typescript\n * await store.put('user:1', { id: 1 }, 3600);\n * ```\n */\n async put(_key: CacheKey, _value: unknown, _ttl: CacheTtl): Promise<void> {\n // no-op\n }\n\n /**\n * Simulates a failed attempt to add an item to the cache.\n *\n * Since NullStore does not store data, this method always indicates that\n * the item was not added.\n *\n * @param _key - The identifier for the item.\n * @param _value - The data to be cached.\n * @param _ttl - Time-to-live in seconds.\n * @returns Always returns `false`.\n *\n * @example\n * ```typescript\n * const added = await store.add('key', 'value', 60); // false\n * ```\n */\n async add(_key: CacheKey, _value: unknown, _ttl: CacheTtl): Promise<boolean> {\n return false\n }\n\n /**\n * Simulates a failed attempt to remove an item from the cache.\n *\n * Since no data is ever stored, there is nothing to remove.\n *\n * @param _key - The identifier for the item to remove.\n * @returns Always returns `false`.\n *\n * @example\n * ```typescript\n * const forgotten = await store.forget('key'); // false\n * ```\n */\n async forget(_key: CacheKey): Promise<boolean> {\n return false\n }\n\n /**\n * Performs a no-op flush operation.\n *\n * @returns Resolves immediately as there is no data to clear.\n *\n * @example\n * ```typescript\n * await store.flush();\n * ```\n */\n async flush(): Promise<void> {\n // no-op\n }\n\n /**\n * Simulates an increment operation on a non-existent key.\n *\n * @param _key - The identifier for the numeric item.\n * @param _value - The amount to increment by.\n * @returns Always returns `0`.\n *\n * @example\n * ```typescript\n * const newValue = await store.increment('counter', 1); // 0\n * ```\n */\n async increment(_key: CacheKey, _value = 1): Promise<number> {\n return 0\n }\n\n /**\n * Simulates a decrement operation on a non-existent key.\n *\n * @param _key - The identifier for the numeric item.\n * @param _value - The amount to decrement by.\n * @returns Always returns `0`.\n *\n * @example\n * ```typescript\n * const newValue = await store.decrement('counter', 1); // 0\n * ```\n */\n async decrement(_key: CacheKey, _value = 1): Promise<number> {\n return 0\n }\n}\n",
19
+ "import type { CacheLock } from '../locks'\nimport { type AccessPredictor, MarkovPredictor } from '../prediction/AccessPredictor'\nimport type { CacheStore } from '../store'\nimport type { CacheKey, CacheTtl, CacheValue } from '../types'\n\n/**\n * A CacheStore wrapper that predicts usage patterns and prefetches data.\n *\n * This store observes access patterns (A -> B) and when A is requested,\n * automatically attempts to 'touch' B in the underlying store.\n *\n * If the underlying store is a TieredStore, this effectively promotes B\n * from the remote core (e.g. Redis) to the local cache (e.g. Memory)\n * before it is explicitly requested, reducing latency.\n *\n * @public\n * @since 3.2.0\n *\n * @example\n * ```typescript\n * const store = new PredictiveStore(new TieredStore(l1, l2));\n * // Accessing 'a' will prefetch 'b' if a -> b pattern is detected\n * await store.get('a');\n * ```\n */\nexport class PredictiveStore implements CacheStore {\n private predictor: AccessPredictor\n\n constructor(\n private store: CacheStore,\n options: { predictor?: AccessPredictor } = {}\n ) {\n this.predictor = options.predictor ?? new MarkovPredictor()\n }\n\n async get<T = unknown>(key: CacheKey): Promise<CacheValue<T>> {\n // 1. Record the access to learn patterns\n this.predictor.record(key)\n\n // 2. Predict likely next keys\n const candidates = this.predictor.predict(key)\n\n // 3. Prefetch candidates in background\n if (candidates.length > 0) {\n // We use 'void' to explicitly ignore the promise (fire-and-forget)\n // This triggers the underlying store's get(), which for TieredStore\n // will cause L2 -> L1 promotion if found.\n void Promise.all(candidates.map((k) => this.store.get(k).catch(() => {})))\n }\n\n // 4. Return the requested value\n return this.store.get<T>(key)\n }\n\n async put(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<void> {\n return this.store.put(key, value, ttl)\n }\n\n async add(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<boolean> {\n return this.store.add(key, value, ttl)\n }\n\n async forget(key: CacheKey): Promise<boolean> {\n return this.store.forget(key)\n }\n\n async flush(): Promise<void> {\n if (typeof this.predictor.reset === 'function') {\n this.predictor.reset()\n }\n return this.store.flush()\n }\n\n async increment(key: CacheKey, value?: number): Promise<number> {\n return this.store.increment(key, value)\n }\n\n async decrement(key: CacheKey, value?: number): Promise<number> {\n return this.store.decrement(key, value)\n }\n\n lock(name: string, seconds?: number): CacheLock | undefined {\n return this.store.lock ? this.store.lock(name, seconds) : undefined\n }\n\n async ttl(key: CacheKey): Promise<number | null> {\n return this.store.ttl ? this.store.ttl(key) : null\n }\n}\n",
20
+ "import { Redis, type RedisClientContract } from '@gravito/plasma'\nimport { type CacheLock, LockTimeoutError, sleep } from '../locks'\nimport type { CacheStore, TaggableStore } from '../store'\nimport {\n type CacheKey,\n type CacheTtl,\n type CacheValue,\n normalizeCacheKey,\n ttlToExpiresAt,\n} from '../types'\n\n/**\n * Options for configuring the `RedisStore`.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const options: RedisStoreOptions = {\n * connection: 'primary',\n * prefix: 'cache:'\n * };\n * ```\n */\nexport type RedisStoreOptions = {\n /** The name of the Redis connection to use. */\n connection?: string\n /** Optional Redis-level prefix for keys. */\n prefix?: string\n}\n\n/**\n * RedisStore implements the `CacheStore` interface using Redis.\n *\n * It provides a distributed, persistent cache backend with support for\n * atomic increments/decrements, tagging, and distributed locking.\n *\n * @public\n * @since 3.0.0\n */\nexport class RedisStore implements CacheStore, TaggableStore {\n private connectionName?: string\n\n /**\n * Initialize a new RedisStore instance.\n *\n * @param options - Redis connection and prefix settings.\n *\n * @example\n * ```typescript\n * const store = new RedisStore({ prefix: 'app:' });\n * ```\n */\n constructor(options: RedisStoreOptions = {}) {\n this.connectionName = options.connection\n // We defer getting the connection until used, or get it now.\n // Since orbit-redis manages connections, we can get it now.\n // However, if orbit-redis isn't configured yet, this might throw if we called it in constructor?\n // Usually orbitCache is initialized after core, and Redis.configure should happen before?\n // Actually, OrbitCache.install happens, then user uses it.\n // We'll access Redis.connection() lazily or in methods to be safe,\n // but typically we can store the instance if it's a singleton manager.\n // For now, let's access via a getter to be safe.\n }\n\n private get client(): RedisClientContract {\n return Redis.connection(this.connectionName)\n }\n\n /**\n * Retrieve an item from Redis.\n *\n * @param key - Unique cache key identifier.\n * @returns Parsed JSON value or null if missing/expired.\n * @throws {Error} If Redis connection fails or read errors occur.\n */\n async get<T = unknown>(key: CacheKey): Promise<CacheValue<T>> {\n const normalized = normalizeCacheKey(key)\n const value = await this.client.get(normalized)\n\n if (value === null) {\n return null\n }\n\n // Try to parse JSON, if it fails return as string\n try {\n return JSON.parse(value) as T\n } catch {\n return value as unknown as T\n }\n }\n\n /**\n * Store an item in Redis.\n *\n * @param key - Unique cache key identifier.\n * @param value - Value to serialize and store.\n * @param ttl - Expiration duration.\n * @throws {Error} If Redis connection fails or write errors occur.\n */\n async put(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<void> {\n const normalized = normalizeCacheKey(key)\n const serialized = JSON.stringify(value)\n const expiresAt = ttlToExpiresAt(ttl)\n\n // Redis SET options\n const options: { px?: number } = {}\n\n if (expiresAt) {\n const ttlMs = Math.max(1, expiresAt - Date.now())\n options.px = ttlMs\n }\n\n await this.client.set(normalized, serialized, options)\n }\n\n async add(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<boolean> {\n const normalized = normalizeCacheKey(key)\n const serialized = JSON.stringify(value)\n const expiresAt = ttlToExpiresAt(ttl)\n\n const options: { px?: number; nx: boolean } = { nx: true }\n\n if (expiresAt) {\n const ttlMs = Math.max(1, expiresAt - Date.now())\n options.px = ttlMs\n }\n\n const result = await this.client.set(normalized, serialized, options)\n return result === 'OK'\n }\n\n async forget(key: CacheKey): Promise<boolean> {\n const normalized = normalizeCacheKey(key)\n\n const luaScript = `\n local key = KEYS[1]\n local tag_prefix = ARGV[1]\n local tags = redis.call('SMEMBERS', key .. ':tags')\n local del_result = redis.call('DEL', key)\n for _, tag in ipairs(tags) do\n redis.call('SREM', tag_prefix .. tag, key)\n end\n redis.call('DEL', key .. ':tags')\n return del_result\n `\n\n const client = this.client as unknown as {\n eval(script: string, numKeys: number, ...args: string[]): Promise<number>\n }\n\n const result = await client.eval(luaScript, 1, normalized, 'tag:')\n return result > 0\n }\n\n async flush(): Promise<void> {\n await this.client.flushdb()\n }\n\n async increment(key: CacheKey, value = 1): Promise<number> {\n const normalized = normalizeCacheKey(key)\n if (value === 1) {\n return await this.client.incr(normalized)\n }\n return await this.client.incrby(normalized, value)\n }\n\n /**\n * Decrement a numeric value in Redis.\n *\n * @param key - Unique cache key identifier.\n * @param value - Amount to subtract.\n * @returns Updated numeric value.\n * @throws {Error} If key is not numeric or Redis errors occur.\n */\n async decrement(key: CacheKey, value = 1): Promise<number> {\n const normalized = normalizeCacheKey(key)\n if (value === 1) {\n return await this.client.decr(normalized)\n }\n return await this.client.decrby(normalized, value)\n }\n\n // ============================================================================\n // Tags\n // ============================================================================\n\n tagKey(key: string, _tags: readonly string[]): string {\n // We use the key as-is, so tagging doesn't change the key name.\n // This allows accessing the same key with or without tags.\n return key\n }\n\n async tagIndexAdd(tags: readonly string[], taggedKey: string): Promise<void> {\n if (tags.length === 0) {\n return\n }\n\n const pipeline = this.client.pipeline()\n\n pipeline.sadd(`${taggedKey}:tags`, ...tags)\n\n for (const tag of tags) {\n const tagSetKey = `tag:${tag}`\n pipeline.sadd(tagSetKey, taggedKey)\n }\n\n await pipeline.exec()\n }\n\n async tagIndexRemove(taggedKey: string): Promise<void> {\n const luaScript = `\n local key = KEYS[1]\n local tag_prefix = ARGV[1]\n local tags = redis.call('SMEMBERS', key .. ':tags')\n for _, tag in ipairs(tags) do\n redis.call('SREM', tag_prefix .. tag, key)\n end\n redis.call('DEL', key .. ':tags')\n `\n\n const client = this.client as unknown as {\n eval(script: string, numKeys: number, ...args: string[]): Promise<number>\n }\n\n await client.eval(luaScript, 1, taggedKey, 'tag:')\n }\n\n async flushTags(tags: readonly string[]): Promise<void> {\n if (tags.length === 0) {\n return\n }\n\n const tagKeys = tags.map((tag) => `tag:${tag}`)\n\n // Get all keys from all tags\n // We want the UNION of keys? Or just keys in ANY of these tags?\n // Usually flushTags(['a', 'b']) means flush 'a' AND flush 'b'.\n\n // 1. Get keys\n const pipeline = this.client.pipeline()\n for (const tagKey of tagKeys) {\n pipeline.smembers(tagKey)\n }\n const results = await pipeline.exec()\n\n const keysToDelete = new Set<string>()\n\n for (const [err, keys] of results) {\n if (!err && Array.isArray(keys)) {\n for (const k of keys) {\n keysToDelete.add(k as string)\n }\n }\n }\n\n if (keysToDelete.size > 0) {\n await this.client.del(...Array.from(keysToDelete))\n }\n\n // 2. Delete the tag sets themselves\n await this.client.del(...tagKeys)\n }\n\n // ============================================================================\n // Locks\n // ============================================================================\n\n async ttl(key: CacheKey): Promise<number | null> {\n const normalized = normalizeCacheKey(key)\n const result = await this.client.ttl(normalized)\n return result < 0 ? null : result\n }\n\n lock(name: string, seconds = 10): CacheLock {\n const lockKey = `lock:${normalizeCacheKey(name)}`\n const owner = crypto.randomUUID()\n const ttlMs = Math.max(1, seconds) * 1000\n\n const client = this.client\n\n return {\n async acquire(): Promise<boolean> {\n const result = await client.set(lockKey, owner, { nx: true, px: ttlMs })\n return result === 'OK'\n },\n\n async release(): Promise<void> {\n const luaScript = `\n local current = redis.call('GET', KEYS[1])\n if current == ARGV[1] then\n return redis.call('DEL', KEYS[1])\n else\n return 0\n end\n `\n\n const evalClient = client as unknown as {\n eval(script: string, numKeys: number, ...args: string[]): Promise<number>\n }\n\n await evalClient.eval(luaScript, 1, lockKey, owner)\n },\n\n async extend(extensionSeconds: number): Promise<boolean> {\n const luaScript = `\n local current = redis.call('GET', KEYS[1])\n if current == ARGV[1] then\n return redis.call('EXPIRE', KEYS[1], ARGV[2])\n else\n return 0\n end\n `\n\n const evalClient = client as unknown as {\n eval(script: string, numKeys: number, ...args: string[]): Promise<number>\n }\n\n const result = await evalClient.eval(\n luaScript,\n 1,\n lockKey,\n owner,\n extensionSeconds.toString()\n )\n return result === 1\n },\n\n async getRemainingTime(): Promise<number> {\n return await client.ttl(lockKey)\n },\n\n async block<T>(\n secondsToWait: number,\n callback: () => Promise<T> | T,\n options?: {\n retryInterval?: number\n maxRetries?: number\n signal?: AbortSignal\n sleepMillis?: number\n }\n ): Promise<T> {\n const retryInterval = options?.retryInterval ?? options?.sleepMillis ?? 100\n const maxRetries = options?.maxRetries ?? Number.POSITIVE_INFINITY\n const signal = options?.signal\n const deadline = Date.now() + Math.max(0, secondsToWait) * 1000\n let attempt = 0\n\n while (Date.now() <= deadline && attempt < maxRetries) {\n if (signal?.aborted) {\n throw new Error(`Lock acquisition for '${name}' was aborted`)\n }\n\n if (await this.acquire()) {\n try {\n return await callback()\n } finally {\n await this.release()\n }\n }\n\n attempt++\n const delay = Math.min(retryInterval * 1.5 ** Math.min(attempt, 10), 1000)\n await sleep(delay)\n }\n\n throw new LockTimeoutError(\n `Failed to acquire lock '${name}' within ${secondsToWait} seconds.`\n )\n },\n }\n }\n}\n",
21
+ "import type { CacheStore } from '../store'\nimport type { CacheKey, CacheTtl } from '../types'\n\n/**\n * A multi-level cache store that coordinates access between a fast local L1 cache\n * and a persistent remote L2 cache.\n *\n * It implements the read-through and write-through patterns to ensure that the\n * most frequently accessed data remains in the fastest storage tier.\n *\n * @public\n * @since 3.2.0\n *\n * @example\n * ```typescript\n * const store = new TieredStore(new MemoryStore(), new RedisStore());\n * await store.put('key', 'value', 3600);\n * ```\n */\nexport class TieredStore implements CacheStore {\n /**\n * Initializes a new TieredStore.\n *\n * @param local - The L1 cache store (usually MemoryStore).\n * @param remote - The L2 cache store (usually RedisStore or FileStore).\n */\n constructor(\n private readonly local: CacheStore,\n private readonly remote: CacheStore\n ) {}\n\n async get<T = unknown>(key: CacheKey): Promise<T | null> {\n const localValue = await this.local.get<T>(key)\n if (localValue !== null) {\n return localValue\n }\n\n const remoteValue = await this.remote.get<T>(key)\n if (remoteValue !== null) {\n // Backfill L1\n const ttl = this.remote.ttl ? await this.remote.ttl(key) : null\n await this.local.put(key, remoteValue, ttl)\n }\n\n return remoteValue\n }\n\n async put(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<void> {\n await Promise.all([this.local.put(key, value, ttl), this.remote.put(key, value, ttl)])\n }\n\n async add(key: CacheKey, value: unknown, ttl: CacheTtl): Promise<boolean> {\n // We prioritize remote for 'add' as it's the source of truth for atomicity\n const ok = await this.remote.add(key, value, ttl)\n if (ok) {\n await this.local.put(key, value, ttl)\n }\n return ok\n }\n\n async forget(key: CacheKey): Promise<boolean> {\n const [localOk, remoteOk] = await Promise.all([this.local.forget(key), this.remote.forget(key)])\n return localOk || remoteOk\n }\n\n async flush(): Promise<void> {\n await Promise.all([this.local.flush(), this.remote.flush()])\n }\n\n async increment(key: CacheKey, value = 1): Promise<number> {\n const next = await this.remote.increment(key, value)\n // Sync to local\n const ttl = this.remote.ttl ? await this.remote.ttl(key) : null\n await this.local.put(key, next, ttl)\n return next\n }\n\n async decrement(key: CacheKey, value = 1): Promise<number> {\n return this.increment(key, -value)\n }\n\n async ttl(key: CacheKey): Promise<number | null> {\n if (this.remote.ttl) {\n return this.remote.ttl(key)\n }\n return this.local.ttl ? this.local.ttl(key) : null\n }\n}\n",
22
+ "import type { GravitoContext, GravitoNext, GravitoOrbit, PlanetCore } from '@gravito/core'\nimport { CacheManager } from './CacheManager'\nimport type { CacheEventMode, CacheEvents } from './CacheRepository'\nimport { MarkovPredictor } from './prediction/AccessPredictor'\nimport type { CacheStore } from './store'\nimport { CircuitBreakerStore } from './stores/CircuitBreakerStore'\nimport { FileStore } from './stores/FileStore'\nimport { MemoryStore } from './stores/MemoryStore'\nimport { NullStore } from './stores/NullStore'\nimport { PredictiveStore } from './stores/PredictiveStore'\nimport { RedisStore } from './stores/RedisStore'\nimport { TieredStore } from './stores/TieredStore'\nimport type { CacheTtl } from './types'\n\nexport * from './CacheManager'\nexport * from './CacheRepository'\nexport * from './locks'\nexport * from './prediction/AccessPredictor'\nexport * from './RateLimiter'\nexport * from './store'\nexport * from './stores/CircuitBreakerStore'\nexport * from './stores/FileStore'\nexport * from './stores/MemoryStore'\nexport * from './stores/NullStore'\nexport * from './stores/PredictiveStore'\nexport * from './stores/RedisStore'\nexport * from './stores/TieredStore'\nexport * from './types'\n\n/**\n * Interface for a low-level cache storage provider.\n *\n * Use this to implement custom storage backends that can be plugged into Stasis.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * class MyProvider implements CacheStorageProvider {\n * async get(key) { ... }\n * async set(key, value, ttl) { ... }\n * async delete(key) { ... }\n * async clear() { ... }\n * }\n * ```\n */\nexport interface CacheStorageProvider {\n /**\n * Retrieve an item from the cache.\n *\n * @param key - The unique cache key.\n * @returns The cached value, or null if not found.\n */\n get<T = unknown>(key: string): Promise<T | null>\n\n /**\n * Store an item in the cache.\n *\n * @param key - The unique cache key.\n * @param value - The value to store.\n * @param ttl - Time-to-live in seconds.\n */\n set(key: string, value: unknown, ttl?: number): Promise<void>\n\n /**\n * Delete an item from the cache.\n *\n * @param key - The cache key to remove.\n */\n delete(key: string): Promise<void>\n\n /**\n * Clear all items from the cache storage.\n */\n clear(): Promise<void>\n}\n\n/** @deprecated Use CacheStorageProvider instead */\nexport type CacheProvider = CacheStorageProvider\n\n/**\n * High-level application contract for caching operations.\n *\n * This is the public API exposed to the rest of the application via\n * the request context or service container.\n *\n * @public\n * @since 3.0.0\n */\nexport interface CacheService {\n /**\n * Retrieves an item from the cache.\n *\n * @param key - The unique identifier for the cached item.\n * @returns The cached value, or `null` if the item is missing or has expired.\n *\n * @example\n * const user = await cache.get<User>('user:123');\n */\n get<T = unknown>(key: string): Promise<T | null>\n\n /**\n * Stores an item in the cache with an optional time-to-live.\n *\n * @param key - The unique identifier for the item.\n * @param value - The value to store (must be serializable).\n * @param ttl - Time-to-live in seconds or as a `Date` object. If omitted, uses the default TTL.\n *\n * @example\n * await cache.set('key', 'value', 60);\n */\n set(key: string, value: unknown, ttl?: CacheTtl): Promise<void>\n\n /**\n * Checks if an item exists in the cache and has not expired.\n *\n * @param key - The cache key to check.\n * @returns `true` if the item exists and is valid, `false` otherwise.\n *\n * @example\n * if (await cache.has('lock:processing')) {\n * return;\n * }\n */\n has(key: string): Promise<boolean>\n\n /**\n * Stores an item in the cache only if it does not already exist.\n *\n * @param key - The unique identifier for the item.\n * @param value - The value to store.\n * @param ttl - Time-to-live in seconds or as a `Date` object.\n * @returns `true` if the item was added, `false` if it already existed.\n *\n * @example\n * const acquired = await cache.add('lock:job:1', true, 60);\n */\n add(key: string, value: unknown, ttl?: CacheTtl): Promise<boolean>\n\n /**\n * Removes an item from the cache.\n *\n * @param key - The cache key to remove.\n * @returns `true` if the item was successfully removed, `false` otherwise.\n *\n * @example\n * await cache.delete('user:session:1');\n */\n delete(key: string): Promise<boolean>\n\n /**\n * Retrieves an item from the cache and then removes it.\n *\n * This operation is atomic depending on the underlying driver support.\n *\n * @param key - The cache key to pull.\n * @param defaultValue - Optional value to return if the item is missing.\n * @returns The cached value (before deletion) or the default value.\n *\n * @example\n * const otp = await cache.pull('otp:user:1');\n */\n pull<T = unknown>(key: string, defaultValue?: T): Promise<T | null>\n\n /**\n * Retrieves an item from the cache, or executes the callback and stores the result.\n *\n * This is a \"read-through\" cache pattern.\n *\n * @param key - The cache key.\n * @param ttl - Time-to-live to use if the item is fetched from the callback.\n * @param callback - Function to retrieve the value if missing. Can be async.\n * @returns The cached or newly fetched value.\n *\n * @example\n * const user = await cache.remember('user:1', 300, async () => {\n * return await db.findUser(1);\n * });\n */\n remember<T>(key: string, ttl: CacheTtl, callback: () => Promise<T> | T): Promise<T>\n\n /**\n * Stores an item in the cache indefinitely (or until manually removed).\n *\n * @param key - The unique cache key.\n * @param callback - Function to retrieve the value if missing.\n * @returns The cached or fetched value.\n *\n * @example\n * const settings = await cache.rememberForever('app:settings', () => loadSettings());\n */\n rememberForever<T>(key: string, callback: () => Promise<T> | T): Promise<T>\n\n /**\n * Clears all items from the cache.\n *\n * @warning This will wipe the entire cache storage for the current context.\n *\n * @example\n * await cache.clear();\n */\n clear(): Promise<void>\n}\n\n/**\n * A standard in-memory implementation of `CacheStorageProvider`.\n *\n * @public\n * @since 3.0.0\n */\nexport class MemoryCacheProvider implements CacheStorageProvider {\n private store = new MemoryStore()\n\n async get<T = unknown>(key: string): Promise<T | null> {\n return this.store.get<T>(key)\n }\n\n async set(key: string, value: unknown, ttl = 60): Promise<void> {\n await this.store.put(key, value, ttl)\n }\n\n async delete(key: string): Promise<void> {\n await this.store.forget(key)\n }\n\n async clear(): Promise<void> {\n await this.store.flush()\n }\n}\n\n/**\n * Configuration for an individual cache store instance.\n *\n * @public\n * @since 3.0.0\n */\nexport type OrbitCacheStoreConfig =\n /** Simple in-memory cache using a Map. */\n | { driver: 'memory'; maxItems?: number }\n /** Local file system based cache. */\n | { driver: 'file'; directory: string }\n /** Redis-backed distributed cache. */\n | { driver: 'redis'; connection?: string; prefix?: string }\n /** No-op cache that stores nothing. */\n | { driver: 'null' }\n /** Use a custom implementation of the low-level `CacheStore` interface. */\n | { driver: 'custom'; store: CacheStore }\n /** Use an implementation of the `CacheStorageProvider` interface. */\n | { driver: 'provider'; provider: CacheStorageProvider }\n /** Multi-level cache. */\n | { driver: 'tiered'; local: string; remote: string }\n /** Predictive cache that prefetches keys based on usage patterns. */\n | { driver: 'predictive'; inner: string; maxNodes?: number }\n /** Fault tolerance layer. */\n | {\n driver: 'circuit-breaker'\n primary: string\n maxFailures?: number\n resetTimeout?: number\n fallback?: string\n }\n\n/**\n * Options for configuring the `OrbitStasis` cache orbit.\n *\n * @public\n * @since 3.0.0\n *\n * @example\n * ```typescript\n * const options: OrbitCacheOptions = {\n * default: 'redis',\n * stores: {\n * redis: { driver: 'redis', connection: 'default' }\n * }\n * };\n * ```\n */\nexport interface OrbitCacheOptions {\n /** The key used to expose the cache manager in the request context. @defaultValue 'cache' */\n exposeAs?: string\n /** The name of the default store to use for proxy methods. @defaultValue 'memory' */\n default?: string\n /** Global prefix for all cache keys across all stores. */\n prefix?: string\n /** Default time-to-live for cache entries if not specified. @defaultValue 60 */\n defaultTtl?: CacheTtl\n /** Map of named cache stores and their configurations. */\n stores?: Record<string, OrbitCacheStoreConfig>\n /** How to handle cache events (hit/miss/etc) */\n eventsMode?: CacheEventMode\n /** Whether to throw if an event listener fails. @defaultValue false */\n throwOnEventError?: boolean\n /** Custom error handler for cache events. */\n onEventError?: (error: unknown, event: keyof CacheEvents, payload: { key?: string }) => void\n\n /** @deprecated Use stores mapping with 'provider' driver. */\n provider?: CacheStorageProvider\n /** @deprecated Use defaultTtl. */\n defaultTTL?: number\n}\n\nfunction resolveStoreConfig(core: PlanetCore, options?: OrbitCacheOptions): OrbitCacheOptions {\n if (options) {\n return options\n }\n if (core.config.has('cache')) {\n return core.config.get<OrbitCacheOptions>('cache')\n }\n return {}\n}\n\nfunction createStoreFactory(config: OrbitCacheOptions): (name: string) => CacheStore {\n const stores = config.stores ?? {}\n const defaultSeconds = typeof config.defaultTtl === 'number' ? config.defaultTtl : 60\n\n return (name: string) => {\n const storeConfig = stores[name]\n const hasExplicitStores = Object.keys(stores).length > 0\n\n if (!storeConfig) {\n if (name === 'memory') {\n return new MemoryStore()\n }\n if (name === 'null') {\n return new NullStore()\n }\n if (hasExplicitStores) {\n throw new Error(`Cache store '${name}' is not defined.`)\n }\n return new MemoryStore()\n }\n\n if (storeConfig.driver === 'memory') {\n return new MemoryStore({ maxItems: storeConfig.maxItems })\n }\n\n if (storeConfig.driver === 'file') {\n return new FileStore({ directory: storeConfig.directory })\n }\n\n if (storeConfig.driver === 'redis') {\n return new RedisStore({ connection: storeConfig.connection, prefix: storeConfig.prefix })\n }\n\n if (storeConfig.driver === 'null') {\n return new NullStore()\n }\n\n if (storeConfig.driver === 'custom') {\n return storeConfig.store\n }\n\n if (storeConfig.driver === 'provider') {\n const provider = storeConfig.provider\n if (!provider) {\n throw new Error(`Cache store '${name}' is missing a provider.`)\n }\n return {\n get: (key) => provider.get(key),\n put: (key, value, ttl) =>\n provider.set(key, value, typeof ttl === 'number' ? ttl : defaultSeconds),\n add: async (key, value, ttl) => {\n const existing = await provider.get(key)\n if (existing !== null) {\n return false\n }\n await provider.set(key, value, typeof ttl === 'number' ? ttl : defaultSeconds)\n return true\n },\n forget: async (key) => {\n await provider.delete(key)\n return true\n },\n flush: () => provider.clear(),\n increment: async (key, value = 1) => {\n const current = await provider.get<number>(key)\n const next = (current ?? 0) + value\n await provider.set(key, next, defaultSeconds)\n return next\n },\n decrement: async (key, value = 1) => {\n const current = await provider.get<number>(key)\n const next = (current ?? 0) - value\n await provider.set(key, next, defaultSeconds)\n return next\n },\n } satisfies CacheStore\n }\n\n if (storeConfig.driver === 'tiered') {\n const factory = createStoreFactory(config)\n return new TieredStore(factory(storeConfig.local), factory(storeConfig.remote))\n }\n\n if (storeConfig.driver === 'predictive') {\n const factory = createStoreFactory(config)\n return new PredictiveStore(factory(storeConfig.inner), {\n predictor: new MarkovPredictor({ maxNodes: storeConfig.maxNodes }),\n })\n }\n\n if (storeConfig.driver === 'circuit-breaker') {\n const factory = createStoreFactory(config)\n const primary = factory(storeConfig.primary)\n const fallback = storeConfig.fallback ? factory(storeConfig.fallback) : undefined\n return new CircuitBreakerStore(primary, {\n maxFailures: storeConfig.maxFailures,\n resetTimeout: storeConfig.resetTimeout,\n fallback,\n })\n }\n\n throw new Error(`Unsupported cache driver '${(storeConfig as { driver?: string }).driver}'.`)\n }\n}\n\n/**\n * OrbitStasis is the core caching module for Gravito.\n *\n * It provides a robust, multi-store cache management system with support for:\n * - Pluggable backends (Memory, File, Redis).\n * - Advanced features like tags, distributed locks, and atomic increments.\n * - Stale-while-revalidate (flexible) caching strategy.\n * - Integrated rate limiting.\n *\n * @example\n * ```typescript\n * const stasis = new OrbitStasis({\n * default: 'redis',\n * stores: {\n * redis: { driver: 'redis', connection: 'default' }\n * }\n * });\n * core.addOrbit(stasis);\n * ```\n *\n * @public\n * @since 3.0.0\n */\nexport class OrbitStasis implements GravitoOrbit {\n private manager: CacheManager | undefined\n\n constructor(private options?: OrbitCacheOptions) {}\n\n install(core: PlanetCore): void {\n const resolvedConfig = resolveStoreConfig(core, this.options)\n const exposeAs = resolvedConfig.exposeAs ?? 'cache'\n const defaultStore = resolvedConfig.default ?? (resolvedConfig.provider ? 'default' : 'memory')\n const defaultTtl =\n resolvedConfig.defaultTtl ??\n (typeof resolvedConfig.defaultTTL === 'number' ? resolvedConfig.defaultTTL : undefined) ??\n 60\n const prefix = resolvedConfig.prefix ?? ''\n\n const logger = core.logger\n logger.info(`[OrbitCache] Initializing Cache (Exposed as: ${exposeAs})`)\n\n const events: CacheEvents = {\n hit: (key) => core.hooks.doAction('cache:hit', { key }),\n miss: (key) => core.hooks.doAction('cache:miss', { key }),\n write: (key) => core.hooks.doAction('cache:write', { key }),\n forget: (key) => core.hooks.doAction('cache:forget', { key }),\n flush: () => core.hooks.doAction('cache:flush', {}),\n }\n\n const onEventError =\n resolvedConfig.onEventError ??\n ((error: unknown, event: keyof CacheEvents, payload: { key?: string }) => {\n const key = payload.key ? ` (key: ${payload.key})` : ''\n logger.error(`[OrbitCache] cache event '${event}' failed${key}`, error)\n })\n\n const stores =\n resolvedConfig.stores ??\n (resolvedConfig.provider\n ? { default: { driver: 'provider' as const, provider: resolvedConfig.provider } }\n : undefined)\n\n const manager = new CacheManager(\n createStoreFactory({ ...resolvedConfig, stores }),\n {\n default: defaultStore,\n prefix,\n defaultTtl,\n },\n events,\n {\n mode: resolvedConfig.eventsMode ?? 'async',\n throwOnError: resolvedConfig.throwOnEventError,\n onError: onEventError,\n }\n )\n\n this.manager = manager\n\n core.adapter.use('*', async (c: GravitoContext, next: GravitoNext) => {\n c.set(exposeAs, manager)\n return await next()\n })\n\n core.container.instance(exposeAs, manager)\n core.hooks.doAction('cache:init', manager)\n }\n\n getCache(): CacheManager {\n if (!this.manager) {\n throw new Error('OrbitCache not installed yet.')\n }\n return this.manager\n }\n}\n\n/**\n * Helper function to create and install the OrbitStasis orbit.\n *\n * @param core - Gravito PlanetCore instance.\n * @param options - Cache configuration options.\n * @returns Initialized CacheManager.\n *\n * @example\n * ```typescript\n * const cache = orbitCache(core, { default: 'memory' });\n * ```\n */\nexport default function orbitCache(\n core: PlanetCore,\n options: OrbitCacheOptions = {}\n): CacheManager {\n const orbit = new OrbitStasis(options)\n orbit.install(core)\n return orbit.getCache()\n}\n\n/** @deprecated Use OrbitStasis instead */\nexport const OrbitCache = OrbitStasis\n\n// Module augmentation for GravitoVariables (abstraction layer)\ndeclare module '@gravito/core' {\n interface GravitoVariables {\n /** Cache manager for caching operations */\n cache?: CacheManager\n }\n}\n"
23
+ ],
24
+ "mappings": "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",
25
+ "debugId": "66831AF7E477960E64756E2164756E21",
26
+ "names": []
27
+ }