{"_id":"@exa-ai/cache-manager","name":"@exa-ai/cache-manager","dist-tags":{"latest":"5.5.1-clone"},"versions":{"5.5.1-clone":{"name":"@exa-ai/cache-manager","version":"5.5.1-clone","description":"Cache module for Node.js","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"rimraf dist && tsc -p tsconfig.build.json","clean":"rimraf ./dist ./coverage ./node_modules ./package-lock.json ./yarn.lock ./pnpm-lock.yaml","test":"xo --fix && vitest run --coverage","test:ci":"xo --fix && vitest run","prepare":"npm run build"},"repository":{"type":"git","url":"git+https://github.com/exa-labs/cacheable.git"},"keywords":["cache","redis","lru-cache","memory cache","multiple cache"],"authors":[{"name":"Jared Wray","email":"me@jaredwray.com"},{"name":"Bryan Donovan"},{"name":"Juan Aguilar Santillana","email":"mhpoin@gmail.com"}],"license":"MIT","dependencies":{"eventemitter3":"^5.0.1","lodash.clonedeep":"^4.5.0","lru-cache":"^11.1.0","promise-coalesce":"^1.1.2"},"devDependencies":{"@faker-js/faker":"^8.4.1","@types/lodash.clonedeep":"^4.5.9","@types/node":"^20.11.30","@typescript-eslint/eslint-plugin":"^7.4.0","@typescript-eslint/parser":"^7.4.0","@vitest/coverage-v8":"^1.4.0","eslint-config-xo-typescript":"^4.0.0","rimraf":"^5.0.5","typescript":"^5.4.3","vitest":"^1.4.0","xo":"^0.58.0"},"xo":{"extends":"xo-typescript","extensions":["ts","tsx"]},"_id":"@exa-ai/cache-manager@5.5.1-clone","gitHead":"cf0214d85b1c8bb8374d51ed2212761f1d96979e","bugs":{"url":"https://github.com/exa-labs/cacheable/issues"},"homepage":"https://github.com/exa-labs/cacheable#readme","_nodeVersion":"24.2.0","_npmVersion":"11.3.0","dist":{"integrity":"sha512-Rn20FX90kCFyrEEN2wDuBE4sM6hVXZVH8AEKPYR92M2G3UiXm/ujEC8DX1fLlJvokGYr+s4Mi1ie15MpOVBX5g==","shasum":"9e04976a726cf4d077bfa246488b0cead9e6cb05","tarball":"https://registry.npmjs.org/@exa-ai/cache-manager/-/cache-manager-5.5.1-clone.tgz","fileCount":12,"unpackedSize":28005,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCID8wDHbDI0oAtg35x43TIKl8E4kAfR/rXilR8tyfmopMAiB1cGQzSaVUWnAaOznI4iPZvS6TV80G3ffHOcUOq+Ns3Q=="}]},"_npmUser":{"name":"exa-rohit","email":"rohit@exa.ai"},"directories":{},"maintainers":[{"name":"exa-rohit","email":"rohit@exa.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cache-manager_5.5.1-clone_1754013521236_0.7131654263528628"},"_hasShrinkwrap":false}},"time":{"created":"2025-08-01T01:58:41.121Z","5.5.1-clone":"2025-08-01T01:58:41.655Z","modified":"2025-08-01T01:58:41.966Z"},"maintainers":[{"name":"exa-rohit","email":"rohit@exa.ai"}],"description":"Cache module for Node.js","homepage":"https://github.com/exa-labs/cacheable#readme","keywords":["cache","redis","lru-cache","memory cache","multiple cache"],"repository":{"type":"git","url":"git+https://github.com/exa-labs/cacheable.git"},"bugs":{"url":"https://github.com/exa-labs/cacheable/issues"},"license":"MIT","readme":"# cache-manager \n[![codecov](https://codecov.io/gh/jaredwray/cache-manager/graph/badge.svg?token=lWZ9OBQ7GM)](https://codecov.io/gh/jaredwray/cache-manager)\n[![tests](https://github.com/jaredwray/cache-manager/actions/workflows/test.yml/badge.svg)](https://github.com/jaredwray/cache-manager/actions/workflows/test.yml)\n[![license](https://img.shields.io/github/license/jaredwray/cache-manager)](https://github.com/jaredwray/cache-manager/blob/main/LICENSE)\n[![npm](https://img.shields.io/npm/dm/cache-manager)](https://npmjs.com/package/cache-manager)\n![npm](https://img.shields.io/npm/v/cache-manager)\n\n# Flexible NodeJS cache module\n\nA cache module for nodejs that allows easy wrapping of functions in cache, tiered caches, and a consistent interface.\n\n## Table of Contents\n* [Features](#features)\n* [Installation](#installation)\n* [Usage Examples](#usage-examples)\n  * [Single Store](#single-store)\n  * [Multi-Store](#multi-store)\n  * [Cache Manager Options](#cache-manager-options)\n  * [Refresh cache keys in background](#refresh-cache-keys-in-background)\n  * [Error Handling](#error-handling)\n  * [Store Engines](#store-engines)\n* [Contribute](#contribute)\n* [License](#license)\n\n## Features\n\n- Made with Typescript and compatible with [ESModules](https://nodejs.org/docs/latest-v14.x/api/esm.html)\n- Easy way to wrap any function in cache.\n- Tiered caches -- data gets stored in each cache and fetched from the highest.\n  priority cache(s) first.\n- Use any cache you want, as long as it has the same API.\n- 100% test coverage via [vitest](https://github.com/vitest-dev/vitest).\n\n## Installation\n\n    pnpm install cache-manager\n\n## Usage Examples\n\n### Single Store\n\n```typescript\nimport { caching } from 'cache-manager';\n\nconst memoryCache = await caching('memory', {\n  max: 100,\n  ttl: 10 * 1000 /*milliseconds*/,\n});\n\nconst ttl = 5 * 1000; /*milliseconds*/\nawait memoryCache.set('foo', 'bar', ttl);\n\nconsole.log(await memoryCache.get('foo'));\n// >> \"bar\"\n\nawait memoryCache.del('foo');\n\nconsole.log(await memoryCache.get('foo'));\n// >> undefined\n\nconst getUser = (id: string) => new Promise.resolve({ id: id, name: 'Bob' });\n\nconst userId = 123;\nconst key = 'user_' + userId;\n\nconsole.log(await memoryCache.wrap(key, () => getUser(userId), ttl));\n// >> { id: 123, name: 'Bob' }\n```\n\nSee unit tests in [`test/caching.test.ts`](./test/caching.test.ts) for more information.\n\n#### Example setting/getting several keys with mset() and mget()\n\n```typescript\nawait memoryCache.store.mset(\n  [\n    ['foo', 'bar'],\n    ['foo2', 'bar2'],\n  ],\n  ttl,\n);\n\nconsole.log(await memoryCache.store.mget('foo', 'foo2'));\n// >> ['bar', 'bar2']\n\n// Delete keys with mdel() passing arguments...\nawait memoryCache.store.mdel('foo', 'foo2');\n```\n\n#### [Example Express App Usage](./examples/express/src/index.mts)\n\n#### Custom Stores\n\nYou can use your own custom store by creating one with the same API as the built-in memory stores.\n\n- [Example Custom Store lru-cache](./src/stores/memory.ts)\n- [Example Custom Store redis](https://github.com/jaredwray/cache-manager/packages/cache-manager-redis-yet)\n- [Example Custom Store ioredis](https://github.com/jaredwray/cache-manager/packages/cache-manager-ioredis-yet)\n\n#### Create single cache store synchronously\n\nAs `caching()` requires async functionality to resolve some stores, this is not well-suited to use for default function/constructor parameters etc.\n\nIf you need to create a cache store synchronously, you can instead use `createCache()`:\n\n```typescript\nimport { createCache, memoryStore } from 'node-cache-manager';\n\n// Create memory cache synchronously\nconst memoryCache = createCache(memoryStore(), {\n  max: 100,\n  ttl: 10 * 1000 /*milliseconds*/,\n});\n\n// Default parameter in function\nfunction myService(cache = createCache(memoryStore())) {}\n\n// Default parameter in class constructor\nconst DEFAULT_CACHE = createCache(memoryStore(), { ttl: 60 * 1000 });\n// ...\nclass MyService {\n  constructor(private cache = DEFAULT_CACHE) {}\n}\n```\n\n### Multi-Store\n\n```typescript\nimport { multiCaching } from 'cache-manager';\n\nconst multiCache = multiCaching([memoryCache, someOtherCache]);\nconst userId2 = 456;\nconst key2 = 'user_' + userId;\nconst ttl = 5;\n\n// Sets in all caches.\nawait multiCache.set('foo2', 'bar2', ttl);\n\n// Fetches from highest priority cache that has the key.\nconsole.log(await multiCache.get('foo2'));\n// >> \"bar2\"\n\n// Delete from all caches\nawait multiCache.del('foo2');\n\n// Sets multiple keys in all caches.\n// You can pass as many key, value tuples as you want\nawait multiCache.mset(\n  [\n    ['foo', 'bar'],\n    ['foo2', 'bar2'],\n  ],\n  ttl\n);\n\n// mget() fetches from highest priority cache.\n// If the first cache does not return all the keys,\n// the next cache is fetched with the keys that were not found.\n// This is done recursively until either:\n// - all have been found\n// - all caches has been fetched\nconsole.log(await multiCache.mget('key', 'key2'));\n// >> ['bar', 'bar2']\n\n// Delete keys with mdel() passing arguments...\nawait multiCache.mdel('foo', 'foo2');\n```\n\nSee unit tests in [`test/multi-caching.test.ts`](./test/multi-caching.test.ts) for more information.\n\n### Cache Manager Options\n\nThe `caching` and `multiCaching` functions accept an options object as the second parameter. The following options are available:\n* max: The maximum number of items that can be stored in the cache. If the cache is full, the least recently used item is removed.\n* ttl: The time to live in milliseconds. This is the maximum amount of time that an item can be in the cache before it is removed.\n* shouldCloneBeforeSet: If true, the value will be cloned before being set in the cache. This is set to `true` by default.\n\n```typescript\nimport { caching } from 'cache-manager';\n\nconst memoryCache = await caching('memory', {\n  max: 100,\n  ttl: 10 * 1000 /*milliseconds*/,\n  shouldCloneBeforeSet: false, // this is set true by default (optional)\n});\n```\n\n### Refresh cache keys in background\n\nBoth the `caching` and `multicaching` modules support a mechanism to refresh expiring cache keys in background when using the `wrap` function.  \nThis is done by adding a `refreshThreshold` attribute while creating the caching store or passing it to the `wrap` function.\n\nIf `refreshThreshold` is set and after retrieving a value from cache the TTL will be checked.  \nIf the remaining TTL is less than `refreshThreshold`, the system will update the value asynchronously,  \nfollowing same rules as standard fetching. In the meantime, the system will return the old value until expiration.\n\nNOTES:\n\n* In case of multicaching, the store that will be checked for refresh is the one where the key will be found first (highest priority).\n* If the threshold is low and the worker function is slow, the key may expire and you may encounter a racing condition with updating values.\n* The background refresh mechanism currently does not support providing multiple keys to `wrap` function.\n* If no `ttl` is set for the key, the refresh mechanism will not be triggered. For redis, the `ttl` is set to -1 by default.\n\nFor example, pass the refreshThreshold to `caching` like this:\n\n```typescript\nconst memoryCache = await caching('memory', {\n  max: 100,\n  ttl: 10 * 1000 /*milliseconds*/,\n  refreshThreshold: 3 * 1000 /*milliseconds*/,\n  \n  /* optional, but if not set, background refresh error will be an unhandled\n   * promise rejection, which might crash your node process */\n  onBackgroundRefreshError: (error) => { /* log or otherwise handle error */ }\n});\n```\n\nWhen a value will be retrieved from Redis with a TTL minor than 3sec, the value will be updated in the background.\n\n## Error Handling\n\nCache Manager now does not throw errors by default. Instead, all errors are evented through the `error` event. Here is an example on how to use it:\n\n```javascript\nconst memoryCache = await caching('memory', {\n  max: 100,\n  ttl: 10 * 1000 /*milliseconds*/,\n});\nmemoryCache.on('error', (error) => {\n  console.error('Cache error:', error);\n});\n```\n\n## Store Engines\n\n### Official and updated to last version\n\n- [node-cache-manager-redis-yet](https://github.com/jaredwray/cache-manager/packages/cache-manager-redis-yet) (uses [node_redis](https://github.com/NodeRedis/node_redis))\n\n- [node-cache-manager-ioredis-yet](https://github.com/jaredwray/cache-manager/packages/cache-manager-ioredis-yet) (uses [ioredis](https://github.com/luin/ioredis))\n\n### Third party\n\n- [node-cache-manager-redis](https://github.com/dial-once/node-cache-manager-redis) (uses [sol-redis-pool](https://github.com/joshuah/sol-redis-pool))\n\n- [node-cache-manager-redis-store](https://github.com/dabroek/node-cache-manager-redis-store) (uses [node_redis](https://github.com/NodeRedis/node_redis))\n\n- [node-cache-manager-ioredis](https://github.com/Tirke/node-cache-manager-ioredis) (uses [ioredis](https://github.com/luin/ioredis))\n\n- [node-cache-manager-mongodb](https://github.com/v4l3r10/node-cache-manager-mongodb)\n\n- [node-cache-manager-mongoose](https://github.com/disjunction/node-cache-manager-mongoose)\n\n- [node-cache-manager-fs-binary](https://github.com/sheershoff/node-cache-manager-fs-binary)\n\n- [node-cache-manager-fs-hash](https://github.com/rolandstarke/node-cache-manager-fs-hash)\n\n- [node-cache-manager-hazelcast](https://github.com/marudor/node-cache-manager-hazelcast)\n\n- [node-cache-manager-memcached-store](https://github.com/theogravity/node-cache-manager-memcached-store)\n\n- [node-cache-manager-memory-store](https://github.com/theogravity/node-cache-manager-memory-store)\n\n- [node-cache-manager-couchbase](https://github.com/davidepellegatta/node-cache-manager-couchbase)\n\n- [node-cache-manager-sqlite](https://github.com/maxpert/node-cache-manager-sqlite)\n\n- [@resolid/cache-manager-sqlite](https://github.com/huijiewei/cache-manager-sqlite) (uses [better-sqlite3](https://github.com/WiseLibs/better-sqlite3))\n\n## Contribute\n\nIf you would like to contribute to the project, please read how to contribute here [CONTRIBUTING.md](./CONTRIBUTING.md).\n\n## License\n\ncache-manager is licensed under the [MIT license](./LICENSE).\n","readmeFilename":"README.md","_rev":"1-04259a68dae6f3bf5e15d8d4559b9328"}