{"id":48285484,"url":"https://github.com/helloscoopa/run-cache","last_synced_at":"2026-04-04T22:55:58.677Z","repository":{"id":256218527,"uuid":"854631110","full_name":"helloscoopa/run-cache","owner":"helloscoopa","description":"RunCache is a dependency-free, lightweight runtime caching library for JavaScript and TypeScript.","archived":false,"fork":false,"pushed_at":"2026-02-14T05:55:34.000Z","size":409,"stargazers_count":13,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-02-14T13:47:38.609Z","etag":null,"topics":["caching","javascript","library","memory-cache","npm-package","performance","productivity","runtime-cache","typescript"],"latest_commit_sha":null,"homepage":"https://runcache.gitbook.io","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/helloscoopa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-09-09T14:09:23.000Z","updated_at":"2026-02-14T05:55:37.000Z","dependencies_parsed_at":"2025-05-12T15:44:13.501Z","dependency_job_id":"0c58f557-afa7-4f04-8bea-974431766a9b","html_url":"https://github.com/helloscoopa/run-cache","commit_stats":null,"previous_names":["helloscoopa/run-cache"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/helloscoopa/run-cache","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helloscoopa%2Frun-cache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helloscoopa%2Frun-cache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helloscoopa%2Frun-cache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helloscoopa%2Frun-cache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/helloscoopa","download_url":"https://codeload.github.com/helloscoopa/run-cache/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helloscoopa%2Frun-cache/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31418273,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T20:09:54.854Z","status":"ssl_error","status_checked_at":"2026-04-04T20:09:44.350Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["caching","javascript","library","memory-cache","npm-package","performance","productivity","runtime-cache","typescript"],"created_at":"2026-04-04T22:55:58.000Z","updated_at":"2026-04-04T22:55:58.659Z","avatar_url":"https://github.com/helloscoopa.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![npm-version](https://img.shields.io/npm/v/run-cache)](https://www.npmjs.com/package/run-cache)\n[![license](https://img.shields.io/github/license/helloscoopa/run-cache)](https://github.com/helloscoopa/run-cache?tab=MIT-1-ov-file)\n[![ci-build](https://img.shields.io/github/actions/workflow/status/helloscoopa/run-cache/build.yml?label=build)](https://github.com/helloscoopa/run-cache/actions/workflows/build.yml)\n[![ci-tests](https://img.shields.io/github/actions/workflow/status/helloscoopa/run-cache/tests.yml?label=tests)](https://github.com/helloscoopa/run-cache/actions/workflows/tests.yml)\n\n# RunCache\n\nA dependency-free, lightweight runtime caching library for JavaScript and TypeScript applications. RunCache allows you to cache string values with configurable time-to-live (TTL) settings and supports automatic value regeneration through source functions.\n\n## Key Features\n\n- **Zero Dependencies:** Lightweight implementation with no external dependencies\n- **In-Memory Performance:** Fast, efficient runtime cache for optimal application performance\n- **Source Function Support:** Cache values generated from synchronous or asynchronous functions\n- **Automatic Refetching:** Configure cache entries to automatically refresh on expiration\n- **Comprehensive Event System:** Subscribe to cache events including expiry, refetch, and refetch failures\n- **Pattern Matching:** Use wildcard patterns to operate on groups of related cache keys\n- **Eviction Policies:** Configure size limits with LRU (Least Recently Used) or LFU (Least Frequently Used) eviction strategies\n- **Middleware Support:** Add custom processing for intercepting and transforming cache operations\n- **Tag-based Invalidation:** Group related cache entries with tags for efficient batch invalidation\n- **Dependency Tracking:** Establish relationships between cache entries with automatic cascading invalidation\n- **TypeScript Support:** Full type definitions included\n\n## Installation\n\n```bash\nnpm install run-cache\n```\n\n## Quick Start\n\n```typescript\nimport { RunCache } from \"run-cache\";\n\n// Basic caching\nawait RunCache.set({ key: \"user-profile\", value: JSON.stringify({ name: \"John Doe\" }) });\nconst profile = await RunCache.get(\"user-profile\");\n\n// Cache with expiration (TTL in milliseconds)\nawait RunCache.set({ \n  key: \"api-data\", \n  value: JSON.stringify({ data: [1, 2, 3] }),\n  ttl: 60000 // 1 minute\n});\n\n// Cache with automatic refresh\nawait RunCache.set({\n  key: \"weather-data\",\n  sourceFn: async () =\u003e JSON.stringify(await fetchWeatherData()),\n  ttl: 300000, // 5 minutes\n  autoRefetch: true\n});\n\n// Using wildcard patterns\nawait RunCache.set({ key: \"user-1\", value: \"Alice\" });\nawait RunCache.set({ key: \"user-2\", value: \"Bob\" });\nconst users = await RunCache.get(\"user-*\"); // Returns array of all matching values\n```\n\n## Cache Eviction Policies\n\nRunCache supports configurable cache eviction policies to manage memory usage by automatically removing entries when the cache reaches a defined size limit.\n\n### Available Eviction Policies\n\n- **NONE**: No automatic eviction (default). Cache entries are only removed via TTL or manual deletion.\n- **LRU (Least Recently Used)**: Removes the least recently accessed entries when the cache exceeds its maximum size.\n- **LFU (Least Frequently Used)**: Removes the least frequently accessed entries when the cache exceeds its maximum size. When entries have the same access frequency, the oldest entry is removed first.\n\n### Configuring Eviction Policies\n\n```typescript\nimport { RunCache, EvictionPolicy } from \"run-cache\";\n\n// Configure the cache with a max size of 100 entries and LRU eviction policy\nRunCache.configure({\n  maxEntries: 100,\n  evictionPolicy: EvictionPolicy.LRU\n});\n\n// Add entries to the cache\nfor (let i = 0; i \u003c 150; i++) {\n  await RunCache.set({ key: `item-${i}`, value: `value-${i}` });\n}\n\n// Only the 100 most recently used entries will be retained\n// The oldest 50 entries will be automatically evicted\n\n// Change to LFU eviction policy\nRunCache.configure({\n  evictionPolicy: EvictionPolicy.LFU\n});\n\n// Get the current configuration\nconst config = RunCache.getConfig();\nconsole.log(config); // { maxEntries: 100, evictionPolicy: \"lfu\" }\n```\n\n## Tag-based Invalidation\n\nRunCache supports tagging cache entries and invalidating groups of related entries using tags.\n\n```typescript\n// Set entries with tags\nawait RunCache.set({ \n  key: \"user:123:profile\", \n  value: JSON.stringify({ name: \"John Doe\" }),\n  tags: [\"user:123\", \"profile\"]\n});\n\nawait RunCache.set({ \n  key: \"user:123:settings\", \n  value: JSON.stringify({ theme: \"dark\" }),\n  tags: [\"user:123\", \"settings\"]\n});\n\nawait RunCache.set({ \n  key: \"user:123:posts\", \n  value: JSON.stringify([{ id: 1, title: \"Hello\" }]),\n  tags: [\"user:123\", \"posts\"]\n});\n\n// Later, when user data changes, invalidate all related cache entries with a single call\nRunCache.invalidateByTag(\"user:123\");\n\n// This removes all three entries with the \"user:123\" tag\n\n// You can also listen for tag invalidation events\nRunCache.onTagInvalidation((event) =\u003e {\n  console.log(`Cache entry ${event.key} was invalidated by tag: ${event.tag}`);\n});\n```\n\n## Dependency Tracking\n\nRunCache enables establishing dependency relationships between cache entries with automatic cascading invalidation.\n\n```typescript\n// Set the primary data cache\nawait RunCache.set({ \n  key: \"user:123:profile\", \n  value: JSON.stringify({ name: \"John Doe\" })\n});\n\n// Set dependent caches that rely on the profile data\nawait RunCache.set({ \n  key: \"user:123:dashboard\", \n  value: JSON.stringify({ widgets: [...] }),\n  dependencies: [\"user:123:profile\"]\n});\n\nawait RunCache.set({ \n  key: \"user:123:recommendations\", \n  value: JSON.stringify([...]),\n  dependencies: [\"user:123:profile\"]\n});\n\n// Create multi-level dependencies\nawait RunCache.set({ \n  key: \"home:feed\", \n  value: JSON.stringify([...]),\n  dependencies: [\"user:123:recommendations\"]\n});\n\n// Check if one entry depends on another (directly or indirectly)\nconst isDependency = await RunCache.isDependencyOf(\"home:feed\", \"user:123:profile\");\nconsole.log(isDependency); // true\n\n// When the primary data changes, invalidate dependent entries with cascading effect\nRunCache.invalidateByDependency(\"user:123:profile\");\n\n// This will invalidate all dependent entries, including nested dependencies:\n// - user:123:dashboard\n// - user:123:recommendations\n// - home:feed (because it depends on user:123:recommendations)\n\n// You can also listen for dependency invalidation events\nRunCache.onDependencyInvalidation((event) =\u003e {\n  console.log(`Cache entry ${event.key} was invalidated due to dependency on: ${event.dependencyKey}`);\n});\n```\n\n## API Reference\n\n### Cache Management\n\n#### Setting Cache Entries\n\n```typescript\nawait RunCache.set({\n  key: string,                         // Required: Unique identifier for the cache entry\n  value?: string,                      // Optional: String value to cache (required if no sourceFn)\n  ttl?: number,                        // Optional: Time-to-live in milliseconds\n  autoRefetch?: boolean,               // Optional: Automatically refetch on expiry (requires ttl and sourceFn)\n  sourceFn?: () =\u003e string | Promise\u003cstring\u003e, // Optional: Function to generate cache value (required if no value)\n  tags?: string[],                     // Optional: Array of tags for tag-based invalidation\n  dependencies?: string[]              // Optional: Array of cache keys this entry depends on\n});\n```\n\n#### Retrieving Cache Entries\n\n```typescript\n// Get a single cache entry\nconst value = await RunCache.get(\"cache-key\");\n\n// Get multiple entries using wildcards (returns an array)\nconst values = await RunCache.get(\"user-*\");\n```\n\n#### Refreshing Cache\n\n```typescript\n// Manually refresh a cache entry (requires a sourceFn)\nawait RunCache.refetch(\"cache-key\");\n\n// Refresh multiple entries using wildcards\nawait RunCache.refetch(\"api-data-*\");\n```\n\n#### Removing Cache Entries\n\n```typescript\n// Remove a specific entry\nRunCache.delete(\"cache-key\");\n\n// Remove multiple entries using wildcards\nRunCache.delete(\"temp-*\");\n\n// Remove all cache entries\nRunCache.flush();\n```\n\n#### Tag and Dependency Management\n\n```typescript\n// Invalidate all entries with a specific tag\nRunCache.invalidateByTag(\"user:123\");\n\n// Invalidate all entries dependent on a specific key\nRunCache.invalidateByDependency(\"user:123:profile\");\n\n// Check if one key depends on another\nconst isDependency = await RunCache.isDependencyOf(\"dashboard:123\", \"user:123\");\n```\n\n#### Checking Cache Status\n\n```typescript\n// Check if a valid (non-expired) cache entry exists\nconst exists = await RunCache.has(\"cache-key\");\n\n// Check if any matching cache entries exist\nconst hasItems = await RunCache.has(\"session-*\");\n```\n\n#### Cache Configuration\n\n```typescript\n// Configure cache settings\nRunCache.configure({\n  maxEntries: 1000,                  // Maximum number of entries before eviction\n  evictionPolicy: EvictionPolicy.LRU  // Eviction policy to use\n});\n\n// Get current configuration\nconst config = RunCache.getConfig();\n```\n\n### Event System\n\nRunCache provides a comprehensive event system to monitor cache lifecycle events.\n\n#### Expiry Events\n\n```typescript\n// Global expiry event\nRunCache.onExpiry((event) =\u003e {\n  console.log(`Cache key ${event.key} expired at ${new Date(event.updatedAt + event.ttl).toISOString()}`);\n});\n\n// Specific key expiry\nRunCache.onKeyExpiry(\"api-data\", (event) =\u003e {\n  console.log(`API data cache expired`);\n});\n\n// Pattern-based expiry events\nRunCache.onKeyExpiry(\"user-*\", (event) =\u003e {\n  console.log(`User cache ${event.key} expired`);\n});\n```\n\n#### Refetch Events\n\n```typescript\n// Global refetch event\nRunCache.onRefetch((event) =\u003e {\n  console.log(`Cache key ${event.key} was refreshed`);\n});\n\n// Specific key refetch\nRunCache.onKeyRefetch(\"weather-data\", (event) =\u003e {\n  console.log(`Weather data was refreshed`);\n});\n\n// Pattern-based refetch events\nRunCache.onKeyRefetch(\"stats-*\", (event) =\u003e {\n  console.log(`Statistics for ${event.key} were refreshed`);\n});\n```\n\n#### Refetch Failure Events\n\n```typescript\n// Global refetch failure event\nRunCache.onRefetchFailure((event) =\u003e {\n  console.error(`Failed to refresh cache key ${event.key}`);\n});\n\n// Specific key refetch failure\nRunCache.onKeyRefetchFailure(\"api-data\", (event) =\u003e {\n  console.error(`API data refresh failed`);\n});\n\n// Pattern-based refetch failure events\nRunCache.onKeyRefetchFailure(\"external-*\", (event) =\u003e {\n  console.error(`External data refresh failed for ${event.key}`);\n});\n```\n\n#### Tag Invalidation Events\n\n```typescript\n// Global tag invalidation event\nRunCache.onTagInvalidation((event) =\u003e {\n  console.log(`Cache key ${event.key} was invalidated by tag: ${event.tag}`);\n});\n\n// Specific key tag invalidation\nRunCache.onKeyTagInvalidation(\"user:profile:*\", (event) =\u003e {\n  console.log(`User profile cache was invalidated by tag: ${event.tag}`);\n});\n```\n\n#### Dependency Invalidation Events\n\n```typescript\n// Global dependency invalidation event\nRunCache.onDependencyInvalidation((event) =\u003e {\n  console.log(`Cache key ${event.key} was invalidated due to dependency on: ${event.dependencyKey}`);\n});\n\n// Specific key dependency invalidation\nRunCache.onKeyDependencyInvalidation(\"dashboard:*\", (event) =\u003e {\n  console.log(`Dashboard cache was invalidated due to dependency on: ${event.dependencyKey}`);\n});\n```\n\n#### Managing Event Listeners\n\n```typescript\n// Remove all event listeners\nRunCache.clearEventListeners();\n\n// Remove listeners for a specific event type\nRunCache.clearEventListeners({\n  event: EVENT.EXPIRE\n});\n\n// Remove listeners for a specific key\nRunCache.clearEventListeners({\n  event: EVENT.REFETCH,\n  key: \"api-data\"\n});\n\n// Remove listeners using wildcard patterns\nRunCache.clearEventListeners({\n  event: EVENT.REFETCH_FAILURE,\n  key: \"external-*\"\n});\n```\n\n### Middleware\n\nRunCache supports middleware functions that can intercept and transform cache operations. This allows for powerful customizations like validation, normalization, encryption, or custom business logic.\n\n#### Adding Middleware\n\n```typescript\nimport { RunCache } from \"run-cache\";\n\n// Add a simple logging middleware\nRunCache.use(async (value, context, next) =\u003e {\n  console.log(`${context.operation} operation for key: ${context.key}`);\n  return next(value);\n});\n```\n\n#### Encryption Middleware Example\n\n```typescript\nimport { RunCache } from \"run-cache\";\nimport { encrypt, decrypt } from \"./your-crypto-lib\";\n\n// Add encryption middleware\nRunCache.use(async (value, context, next) =\u003e {\n  if (context.operation === 'set' \u0026\u0026 value) {\n    // Encrypt value before storing in cache\n    return next(encrypt(value));\n  } else if (context.operation === 'get' || context.operation === 'refetch') {\n    // Decrypt value after retrieving from cache\n    const encrypted = await next(value);\n    return encrypted ? decrypt(encrypted) : undefined;\n  }\n  return next(value);\n});\n\n// Use cache normally - encryption/decryption happens transparently\nawait RunCache.set({ key: \"sensitive-data\", value: \"secret-value\" });\nconst value = await RunCache.get(\"sensitive-data\"); // Returns decrypted \"secret-value\"\n```\n\n#### Chaining Multiple Middleware\n\nMiddleware functions are executed in the order they are added:\n\n```typescript\n// First middleware validates input\nRunCache.use(async (value, context, next) =\u003e {\n  if (context.operation === 'set' \u0026\u0026 (!value || value.length \u003c 3)) {\n    throw new Error(\"Value must be at least 3 characters\");\n  }\n  return next(value);\n});\n\n// Second middleware adds a timestamp\nRunCache.use(async (value, context, next) =\u003e {\n  if (context.operation === 'set' \u0026\u0026 value) {\n    return next(`${value}|${Date.now()}`);\n  } else if (context.operation === 'get' \u0026\u0026 value) {\n    const result = await next(value);\n    return result?.split('|')[0]; // Remove timestamp on get\n  }\n  return next(value);\n});\n```\n\n#### Clearing Middleware\n\n```typescript\n// Remove all middleware\nRunCache.clearMiddleware();\n```\n\nFor more detailed information on middleware, see the [middleware documentation](./docs/middleware.md).\n\n## Wildcard Pattern Matching\n\nRunCache supports wildcard pattern matching for operating on multiple related cache keys simultaneously. Use the `*` character as a wildcard in your key patterns.\n\n### Pattern Matching Examples\n\n```typescript\n// Cache multiple related entries\nawait RunCache.set({ key: \"user:1:profile\", value: \"Alice's data\" });\nawait RunCache.set({ key: \"user:2:profile\", value: \"Bob's data\" });\nawait RunCache.set({ key: \"user:1:preferences\", value: \"Alice's preferences\" });\nawait RunCache.set({ key: \"user:2:preferences\", value: \"Bob's preferences\" });\n\n// Get all user profiles\nconst profiles = await RunCache.get(\"user:*:profile\");\n\n// Get all data for user 1\nconst user1Data = await RunCache.get(\"user:1:*\");\n\n// Delete all preference data\nRunCache.delete(\"user:*:preferences\");\n\n// Check if any user 2 data exists\nconst hasUser2Data = await RunCache.has(\"user:2:*\");\n\n// Refresh all profile data\nawait RunCache.refetch(\"user:*:profile\");\n```\n\nWildcard support is implemented for all key-based operations:\n- `get`: Returns an array of values for matching keys\n- `delete`: Removes all matching keys\n- `refetch`: Refreshes all matching keys\n- `has`: Returns true if any matching key exists\n- Event listeners: Registers callbacks for keys matching patterns\n- `clearEventListeners`: Removes listeners for keys matching patterns\n\n## Resource Management\n\nRunCache is designed to properly manage resources throughout the application lifecycle.\n\n### Automatic Cleanup on Termination\n\nRunCache automatically registers handlers for SIGTERM and SIGINT signals in Node.js environments to ensure proper cleanup of all resources when the application is shutting down. This prevents memory leaks and ensures a clean shutdown.\n\n### Manual Shutdown\n\nYou can also manually trigger a complete shutdown of the cache:\n\n```typescript\n// Manually shut down the cache, clearing all entries, intervals, and event listeners\nRunCache.shutdown();\n```\n\nThe `shutdown` method performs the following cleanup:\n- Clears all cache entries and their associated intervals\n- Removes all event listeners\n- Resets the cache configuration to default values\n\nThis is particularly useful in long-running applications or when you need to release resources manually.\n\n## Debugging and Logging\n\nRunCache provides built-in debug logging to help with debugging and monitoring cache behavior.\n\n### debug Logging\n\nEnable debug logging to see detailed information about all cache operations:\n\n```typescript\n// Enable debug logging when configuring the cache\nRunCache.configure({\n  debug: true\n});\n```\n\nWhen debug mode is enabled, RunCache logs detailed information about:\n- Cache operations (set, get, delete, etc.)\n- Entry expiration and eviction\n- Refetch operations and failures\n- Configuration changes\n\nAll logs include timestamps and log levels for easy filtering.\n\n```typescript\n// Example of enabling debug logging for debugging\nRunCache.configure({ debug: true });\n\n// Perform some cache operations\nawait RunCache.set({ key: \"user-1\", value: \"Alice\" });\nawait RunCache.get(\"user-1\");\n\n// Disable debug logging when done debugging\nRunCache.configure({ debug: false });\n```\n\n### Log Levels\n\nLogs are output at different levels depending on their importance:\n- `info`: General information about cache operations\n- `debug`: Detailed information useful for debugging\n- `warn`: Warnings about potential issues\n- `error`: Errors that occurred during operations\n\nThis is useful when you want to filter logs in complex applications.\n\n## Persistent Storage\n\nRunCache now supports persisting cache data across application restarts using storage adapters. This allows you to maintain your cache state between sessions, improving user experience and reducing unnecessary API calls.\n\n### Available Storage Adapters\n\nRunCache includes three built-in storage adapters:\n\n1. **LocalStorageAdapter**: For browser environments, uses the browser's localStorage API\n2. **IndexedDBAdapter**: For browser environments, uses the browser's IndexedDB API for larger datasets\n3. **FilesystemAdapter**: For Node.js environments, stores cache data in the filesystem\n\n### Using Storage Adapters\n\nTo use a storage adapter, first import the adapter you want to use, then configure RunCache with it:\n\n```typescript\nimport { RunCache, LocalStorageAdapter } from 'run-cache';\n\n// Configure RunCache with LocalStorage persistence\nRunCache.configure({\n  storageAdapter: new LocalStorageAdapter({\n    storageKey: 'my-app-cache' // Optional custom key\n  })\n});\n```\n\n### Auto-Saving and Manual Control\n\nYou can configure automatic saving at regular intervals:\n\n```typescript\n// Save cache to storage every 5 minutes (300,000 ms)\nRunCache.setupAutoSave(300000);\n\n// Disable auto-saving\nRunCache.setupAutoSave(0);\n```\n\nYou can also manually control when to save and load:\n\n```typescript\n// Manually save cache state\nawait RunCache.saveToStorage();\n\n// Manually load cache state\nawait RunCache.loadFromStorage();\n```\n\n### Adapter Configuration Options\n\nEach adapter accepts the following common options:\n\n```typescript\ninterface StorageAdapterConfig {\n  // Storage key/filename to use\n  storageKey?: string; // Default: \"run-cache-data\"\n  \n  // Auto-save interval in milliseconds\n  autoSaveInterval?: number; // Default: 0 (disabled)\n  \n  // Whether to load cache automatically when adapter is initialized\n  autoLoadOnInit?: boolean; // Default: true\n}\n```\n\nThe FilesystemAdapter also accepts an additional option:\n\n```typescript\n// Custom file path (FilesystemAdapter only)\nnew FilesystemAdapter({\n  filePath: '/custom/path/to/cache.json'\n});\n```\n\n### Recovery Mechanism\n\nWhen the application restarts, the cache state is automatically restored if:\n\n1. A storage adapter is configured when initializing RunCache\n2. The adapter contains valid cached data\n\nThis recovery happens automatically when you configure RunCache with a storage adapter. Any cache entries with TTL values will have their expiry timers properly restored based on their original expiration time.\n\n### Example: Full Cache Persistence Setup\n\n```typescript\nimport { RunCache, LocalStorageAdapter } from 'run-cache';\n\n// Configure RunCache with persistence\nRunCache.configure({\n  maxEntries: 1000,\n  evictionPolicy: EvictionPolicy.LRU,\n  storageAdapter: new LocalStorageAdapter({\n    storageKey: 'my-app-cache'\n  })\n});\n\n// Set up auto-save every minute\nRunCache.setupAutoSave(60000);\n\n// When the app shuts down, the cache will be saved automatically\n// When the app starts up, the cache will be loaded automatically\n```\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhelloscoopa%2Frun-cache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhelloscoopa%2Frun-cache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhelloscoopa%2Frun-cache/lists"}