{"_id":"@abdokouta/react-cache","_rev":"5-d694a8e68858eb4086af86609ab19bf5","name":"@abdokouta/react-cache","dist-tags":{"latest":"1.2.1"},"versions":{"1.0.0":{"name":"@abdokouta/react-cache","version":"1.0.0","keywords":["react","cache","redis","laravel","tagging","memory-cache","upstash"],"author":{"name":"Pixielity"},"license":"MIT","_id":"@abdokouta/react-cache@1.0.0","maintainers":[{"name":"abdokouta","email":"akouta66@gmail.com"}],"homepage":"https://github.com/pixielity-inc/react-cache#readme","bugs":{"url":"https://github.com/pixielity-inc/react-cache/issues"},"dist":{"shasum":"049f00ca7668180c0866a6a459c0267747228b58","tarball":"https://registry.npmjs.org/@abdokouta/react-cache/-/react-cache-1.0.0.tgz","fileCount":56,"integrity":"sha512-EHHsfQRYr3X7o8RLDOmPettxKwmxlrv73/XAyC6hzix10kX0ionSZB59tBq4Bw/CLbfkvGHNtVAHAatZHpBqxw==","signatures":[{"sig":"MEUCIFA24hXxgUMKQ6BGBAwEIRAgy/zo5+vZcUcUgAAsXV9XAiEAva2ZtHAXdAPZNvMwFOhVZ3PYHXsxv9pYuzj743paDKQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":531867},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","gitHead":"ca1f5dcb2033e089d7322cc16108bbd479525451","scripts":{"dev":"tsup --watch","test":"vitest --run","build":"tsup","format":"prettier --write \"src/**/*.{ts,tsx,js,jsx,json}\"","test:ui":"vitest --ui","test:watch":"vitest","test:coverage":"vitest --run --coverage"},"_npmUser":{"name":"abdokouta","email":"akouta66@gmail.com"},"prettier":"@nesvel/prettier-config","repository":{"url":"git+https://github.com/pixielity-inc/react-cache.git","type":"git"},"_npmVersion":"10.9.4","description":"Laravel-inspired caching system with multiple drivers (Memory, Redis, Null) for React","directories":{},"_nodeVersion":"22.22.1","dependencies":{"@abdokouta/react-di":"^2.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.2","prettier":"^3.8.1","@vitest/ui":"^4.1.2","typescript":"^6.0.2","@types/react":"^19.2.14","@nesvel/tsup-config":"^1.0.3","@nesvel/eslint-config":"^1.0.5","@nesvel/prettier-config":"^1.0.3","@nesvel/typescript-config":"^1.0.4"},"peerDependencies":{"react":"^18.0.0","@abdokouta/react-redis":"^1.0.0"},"peerDependenciesMeta":{"react":{"optional":true},"@abdokouta/react-redis":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/react-cache_1.0.0_1774938115188_0.2844518214258438","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@abdokouta/react-cache","version":"1.0.1","keywords":["react","cache","redis","laravel","tagging","memory-cache","upstash"],"author":{"name":"Pixielity"},"license":"MIT","_id":"@abdokouta/react-cache@1.0.1","maintainers":[{"name":"abdokouta","email":"akouta66@gmail.com"}],"homepage":"https://github.com/pixielity-inc/react-cache#readme","bugs":{"url":"https://github.com/pixielity-inc/react-cache/issues"},"dist":{"shasum":"992cef0de50b8e07f52371a911dbb64d4a8238e7","tarball":"https://registry.npmjs.org/@abdokouta/react-cache/-/react-cache-1.0.1.tgz","fileCount":58,"integrity":"sha512-kadu7mES0Qnhiq9Koh9jI4VRY/Pw/wMqMVO5VtFsOtndREqKbpzxwGR6tairGTQESD4rJ0kD20AYpRtFc1qGkg==","signatures":[{"sig":"MEUCIQDPuA78cURsEruE+Y859l3AVV0/PZnrK+t1DOzk7x0QNwIgMGlyqg3u9RYGzPHfY222ztqBdp/YwglyolHjzPMNcbg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":535744},"main":"dist/index.js","_from":"file:abdokouta-react-cache-1.0.1.tgz","types":"dist/index.d.ts","module":"dist/index.mjs","scripts":{"dev":"tsup --watch","test":"vitest --run","build":"tsup","format":"prettier --write \"src/**/*.{ts,tsx,js,jsx,json}\"","test:ui":"vitest --ui","test:watch":"vitest","test:coverage":"vitest --run --coverage"},"_npmUser":{"name":"abdokouta","email":"akouta66@gmail.com"},"prettier":"@nesvel/prettier-config","_resolved":"/private/var/folders/7_/q437v6xs4sqf5p4755wbbzvh0000gn/T/db2aac3590133f9dd478635cba7c8025/abdokouta-react-cache-1.0.1.tgz","_integrity":"sha512-kadu7mES0Qnhiq9Koh9jI4VRY/Pw/wMqMVO5VtFsOtndREqKbpzxwGR6tairGTQESD4rJ0kD20AYpRtFc1qGkg==","repository":{"url":"git+https://github.com/pixielity-inc/react-cache.git","type":"git"},"_npmVersion":"10.9.4","description":"Laravel-inspired caching system with multiple drivers (Memory, Redis, Null) for React","directories":{},"_nodeVersion":"22.22.1","dependencies":{"@abdokouta/react-di":"^2.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.2","prettier":"^3.8.1","@vitest/ui":"^4.1.2","typescript":"^6.0.2","@types/react":"^19.2.14","@nesvel/tsup-config":"^1.0.3","@nesvel/eslint-config":"^1.0.5","@nesvel/prettier-config":"^1.0.3","@nesvel/typescript-config":"^1.0.4"},"peerDependencies":{"react":"^18.0.0","@abdokouta/react-redis":"^1.0.0"},"peerDependenciesMeta":{"react":{"optional":true},"@abdokouta/react-redis":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/react-cache_1.0.1_1774943766650_0.10164355056344743","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@abdokouta/react-cache","version":"1.0.2","keywords":["react","cache","redis","laravel","tagging","memory-cache","upstash","dependency-injection","di"],"author":{"url":"https://github.com/abdokouta","name":"Abdelrhman Kouta","email":"abdelrhman@pixielity.com"},"license":"MIT","_id":"@abdokouta/react-cache@1.0.2","maintainers":[{"name":"abdokouta","email":"akouta66@gmail.com"}],"homepage":"https://github.com/abdokouta/cache#readme","bugs":{"url":"https://github.com/abdokouta/cache/issues"},"dist":{"shasum":"4ac5b6ee0a9df86b256f4f3c3c73686ec42c3ca4","tarball":"https://registry.npmjs.org/@abdokouta/react-cache/-/react-cache-1.0.2.tgz","fileCount":10,"integrity":"sha512-8QUgnmJDC826Q+R4hUnSgEWZOCDyfm4Jrrbt+ZyRLjZjyHzU3BMgCu2ncGOw//BWIaAg1Zmrt1LgxynimpyxDw==","signatures":[{"sig":"MEQCIGzg9wulEhmz8ng/06Lz6Dff6L78mjeW7Ui9OLnFSMv2AiAGUSOwnwRIuOB5bEny/07E2F/16Bgis5k5lFq37yPVcg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":433378},"main":"./dist/index.js","type":"module","_from":"file:abdokouta-react-cache-1.0.2.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=18.0.0","pnpm":">=9.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings 0","test":"vitest run","build":"tsup","clean":"rm -rf dist node_modules/.cache","format":"prettier --write .","release":"pnpm publish --access public --no-git-checks","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"abdokouta","email":"akouta66@gmail.com"},"_resolved":"/private/var/folders/7_/q437v6xs4sqf5p4755wbbzvh0000gn/T/ea7004d8581bd8eacff505d1eccc2a54/abdokouta-react-cache-1.0.2.tgz","_integrity":"sha512-8QUgnmJDC826Q+R4hUnSgEWZOCDyfm4Jrrbt+ZyRLjZjyHzU3BMgCu2ncGOw//BWIaAg1Zmrt1LgxynimpyxDw==","repository":{"url":"git+https://github.com/abdokouta/cache.git","type":"git","directory":"packages/cache"},"_npmVersion":"11.12.1","description":"Laravel-inspired caching system with multiple drivers (Memory, Redis, Null) for React","directories":{},"sideEffects":false,"_nodeVersion":"22.22.1","dependencies":{"@abdokouta/react-di":"^2.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.2","prettier":"^3.8.1","@vitest/ui":"^4.1.2","typescript":"^6.0.2","@types/react":"^19.2.14","@nesvel/tsup-config":"^1.0.3","@nesvel/eslint-config":"^1.0.5","@nesvel/prettier-config":"^1.0.3","@nesvel/typescript-config":"^1.0.4"},"peerDependencies":{"react":"^18.0.0 || ^19.0.0","@abdokouta/react-redis":"^1.0.0"},"peerDependenciesMeta":{"react":{"optional":true},"@abdokouta/react-redis":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/react-cache_1.0.2_1774953695712_0.6479524398062606","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@abdokouta/react-cache","version":"1.2.0","keywords":["react","cache","redis","laravel","tagging","memory-cache","upstash","dependency-injection","di"],"author":{"url":"https://github.com/abdokouta","name":"Abdelrhman Kouta","email":"abdelrhman@pixielity.com"},"license":"MIT","_id":"@abdokouta/react-cache@1.2.0","maintainers":[{"name":"abdokouta","email":"akouta66@gmail.com"}],"homepage":"https://github.com/abdokouta/cache#readme","bugs":{"url":"https://github.com/abdokouta/cache/issues"},"dist":{"shasum":"335b93093354f3162342f8f19b51f46726875670","tarball":"https://registry.npmjs.org/@abdokouta/react-cache/-/react-cache-1.2.0.tgz","fileCount":10,"integrity":"sha512-c/tmxBXoTpjy4HSxc0JSMcGZ6/U/b9fSdF+TeQiREnzWBil+bFf2ZhH4uscNP2DL59DUdR0th3erguhP5mz9GQ==","signatures":[{"sig":"MEUCIQDgZ1fDDMqI/8JmOgBknkr3VxtGvWyof1ZvanE9M6fhyQIgUb6JjRskpiAXtNtdkxL29KavLiX5bNlh2sDbAN+uEeE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":377247},"main":"./dist/index.js","type":"module","_from":"file:abdokouta-react-cache-1.2.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=18.0.0","pnpm":">=9.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings 0","test":"vitest run --passWithNoTests","build":"tsup","clean":"rm -rf dist node_modules/.cache","format":"prettier --write .","release":"pnpm publish --access public --no-git-checks","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"abdokouta","email":"akouta66@gmail.com"},"_resolved":"/tmp/b465f9bff1c0d5f83eb5b09d416422b2/abdokouta-react-cache-1.2.0.tgz","_integrity":"sha512-c/tmxBXoTpjy4HSxc0JSMcGZ6/U/b9fSdF+TeQiREnzWBil+bFf2ZhH4uscNP2DL59DUdR0th3erguhP5mz9GQ==","repository":{"url":"git+https://github.com/abdokouta/cache.git","type":"git","directory":"packages/cache"},"_npmVersion":"10.9.7","description":"Laravel-inspired caching system with multiple drivers (Memory, Redis, Null) for React","directories":{},"sideEffects":false,"_nodeVersion":"22.22.2","dependencies":{"@abdokouta/react-redis":"^1.1.2","@abdokouta/ts-container":"^1.2.0","@abdokouta/react-support":"^2.1.0","@abdokouta/ts-container-react":"^1.2.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","jsdom":"^29.0.1","eslint":"10.2.0","vitest":"^4.1.2","prettier":"^3.8.1","@eslint/js":"10.0.1","@vitest/ui":"^4.1.2","typescript":"^6.0.2","@types/react":"^19.2.14","typescript-eslint":"^8.58.0","@nesvel/tsup-config":"^1.0.3","@nesvel/eslint-config":"^1.0.5","@nesvel/prettier-config":"^1.0.3","@nesvel/typescript-config":"^1.0.4"},"peerDependencies":{"react":"^18.0.0 || ^19.0.0"},"peerDependenciesMeta":{"react":{"optional":true},"@abdokouta/react-redis":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/react-cache_1.2.0_1775457742757_0.32702697305640416","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@abdokouta/react-cache","version":"1.2.1","description":"Laravel-inspired caching system with multiple drivers (Memory, Redis, Null) for React","license":"MIT","author":{"name":"Abdelrhman Kouta","email":"abdelrhman@pixielity.com","url":"https://github.com/abdokouta"},"repository":{"type":"git","url":"git+https://github.com/abdokouta/cache.git","directory":"packages/cache"},"bugs":{"url":"https://github.com/abdokouta/cache/issues"},"homepage":"https://github.com/abdokouta/cache#readme","keywords":["react","cache","redis","laravel","tagging","memory-cache","upstash","dependency-injection","di"],"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","dependencies":{"@upstash/redis":"^1.37.0"},"peerDependencies":{"@abdokouta/ts-container":"^1.2.0","@abdokouta/ts-container-react":"^1.2.0","@abdokouta/react-support":"^2.1.0","@abdokouta/react-redis":"^1.1.2","react":"^18.0.0 || ^19.0.0"},"peerDependenciesMeta":{"@abdokouta/ts-container":{"optional":false},"@abdokouta/react-support":{"optional":false},"@abdokouta/ts-container-react":{"optional":true},"@abdokouta/react-redis":{"optional":true},"react":{"optional":true}},"devDependencies":{"@eslint/js":"10.0.1","eslint":"10.2.0","@nesvel/eslint-config":"^1.0.5","@nesvel/prettier-config":"^1.0.3","@nesvel/tsup-config":"^1.0.3","@nesvel/typescript-config":"^1.0.4","@types/react":"^19.2.14","@vitest/ui":"^4.1.2","jsdom":"^29.0.1","prettier":"^3.8.1","tsup":"^8.5.1","typescript":"^6.0.2","typescript-eslint":"^8.58.0","vitest":"^4.1.2"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"engines":{"node":">=18.0.0","pnpm":">=9.0.0"},"sideEffects":false,"scripts":{"build":"tsup","dev":"tsup --watch","clean":"rm -rf dist node_modules/.cache","typecheck":"tsc --noEmit","lint":"eslint . --max-warnings 0","lint:fix":"eslint . --fix","format":"prettier --write .","format:check":"prettier --check .","test":"vitest run --passWithNoTests","test:watch":"vitest","test:coverage":"vitest run --coverage","release":"pnpm publish --access public --no-git-checks"},"_id":"@abdokouta/react-cache@1.2.1","_integrity":"sha512-aQGtmGWRGdxapsXrqlSBdMC5+bOmWcRo8pzi4zXs8SaSR8IqUDr0PBp9q9As6sDzDWLTdwf4d/JQ3whhsaOO7g==","_resolved":"/private/var/folders/7_/q437v6xs4sqf5p4755wbbzvh0000gn/T/ebc2bd6ea424cfda466ecdb438424acb/abdokouta-react-cache-1.2.1.tgz","_from":"file:abdokouta-react-cache-1.2.1.tgz","_nodeVersion":"22.22.2","_npmVersion":"10.9.7","dist":{"integrity":"sha512-aQGtmGWRGdxapsXrqlSBdMC5+bOmWcRo8pzi4zXs8SaSR8IqUDr0PBp9q9As6sDzDWLTdwf4d/JQ3whhsaOO7g==","shasum":"33dd3cc046236fa237ff118475cc403a709f109b","tarball":"https://registry.npmjs.org/@abdokouta/react-cache/-/react-cache-1.2.1.tgz","fileCount":10,"unpackedSize":381612,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQC8c4WOgBdkfeSTOwPvzCtbjHIyIWbYLc83EADqIcpOVAIgDDaW1RA53xeB+V3CcAKX4tHWsV6tehm+QYTbjGcsn0U="}]},"_npmUser":{"name":"abdokouta","email":"akouta66@gmail.com"},"directories":{},"maintainers":[{"name":"abdokouta","email":"akouta66@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/react-cache_1.2.1_1775461446366_0.21426874417393327"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-31T06:21:55.066Z","modified":"2026-04-06T07:44:06.614Z","1.0.0":"2026-03-31T06:21:55.336Z","1.0.1":"2026-03-31T07:56:06.854Z","1.0.2":"2026-03-31T10:41:35.930Z","1.2.0":"2026-04-06T06:42:22.937Z","1.2.1":"2026-04-06T07:44:06.509Z"},"bugs":{"url":"https://github.com/abdokouta/cache/issues"},"author":{"name":"Abdelrhman Kouta","email":"abdelrhman@pixielity.com","url":"https://github.com/abdokouta"},"license":"MIT","homepage":"https://github.com/abdokouta/cache#readme","keywords":["react","cache","redis","laravel","tagging","memory-cache","upstash","dependency-injection","di"],"repository":{"type":"git","url":"git+https://github.com/abdokouta/cache.git","directory":"packages/cache"},"description":"Laravel-inspired caching system with multiple drivers (Memory, Redis, Null) for React","maintainers":[{"name":"abdokouta","email":"akouta66@gmail.com"}],"readme":"<p align=\"center\">\n  <img src=\".github/assets/banner.svg\" alt=\"@abdokouta/react-cache\" width=\"100%\" />\n</p>\n\n<p align=\"center\">\n  <a href=\"https://www.npmjs.com/package/@abdokouta/react-cache\"><img src=\"https://img.shields.io/npm/v/@abdokouta/react-cache.svg?style=flat-square\" alt=\"npm version\" /></a>\n  <a href=\"https://www.npmjs.com/package/@abdokouta/react-cache\"><img src=\"https://img.shields.io/npm/dm/@abdokouta/react-cache.svg?style=flat-square\" alt=\"npm downloads\" /></a>\n  <a href=\"https://github.com/abdokouta/cache/blob/main/LICENSE\"><img src=\"https://img.shields.io/npm/l/@abdokouta/react-cache.svg?style=flat-square\" alt=\"license\" /></a>\n  <a href=\"https://github.com/abdokouta/cache\"><img src=\"https://img.shields.io/github/stars/abdokouta/cache?style=flat-square\" alt=\"stars\" /></a>\n</p>\n\n<p align=\"center\">\n  Laravel-inspired caching system with multiple drivers for React applications.<br/>\n  Built on top of <a href=\"https://www.npmjs.com/package/@abdokouta/ts-container\">@abdokouta/ts-container</a> for seamless dependency injection.\n</p>\n\n---\n\n## Table of Contents\n\n- [Features](#features)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Configuration](#configuration)\n  - [Basic Configuration](#basic-configuration)\n  - [Using defineConfig](#using-defineconfig)\n  - [Environment Variables](#environment-variables)\n- [Cache Drivers](#cache-drivers)\n  - [Memory Store](#memory-store)\n  - [Redis Store](#redis-store)\n  - [Null Store](#null-store)\n- [Usage](#usage)\n  - [Basic Operations](#basic-operations)\n  - [Remember Pattern](#remember-pattern)\n  - [Multiple Stores](#multiple-stores)\n  - [Increment & Decrement](#increment--decrement)\n  - [Cache Tagging](#cache-tagging)\n- [React Hooks](#react-hooks)\n  - [useCache](#usecache)\n  - [useCachedQuery](#usecachedquery)\n- [API Reference](#api-reference)\n  - [CacheService](#cacheservice)\n  - [Store Interface](#store-interface)\n  - [TaggedCache](#taggedcache)\n- [Custom Stores](#custom-stores)\n- [TypeScript](#typescript)\n- [Laravel Comparison](#laravel-comparison)\n- [Requirements](#requirements)\n- [License](#license)\n\n---\n\n## Features\n\n- **Multiple Drivers** — Memory, Redis, and Null stores out of the box\n- **Laravel-Inspired API** — `remember`, `rememberForever`, `pull`, `tags`, and\n  more\n- **Cache Tagging** — Group related cache entries and flush them together\n  (Redis)\n- **React Hooks** — `useCache()` and `useCachedQuery()` for component-level\n  caching\n- **Dependency Injection** — First-class DI support via `@abdokouta/ts-container`\n- **Type-Safe Configuration** — `defineConfig()` helper with full autocomplete\n- **TTL Support** — Per-operation and per-store default TTL\n- **Key Prefixing** — Global and per-store prefixes to avoid collisions\n- **LRU Eviction** — Memory store supports max size with automatic eviction\n- **Lazy Initialization** — Stores are created on first use\n- **Zero Config** — Works with sensible defaults, customize when needed\n\n---\n\n## Installation\n\n```bash\n# npm\nnpm install @abdokouta/react-cache @abdokouta/ts-container\n\n# pnpm\npnpm add @abdokouta/react-cache @abdokouta/ts-container\n\n# yarn\nyarn add @abdokouta/react-cache @abdokouta/ts-container\n```\n\nFor Redis support, also install:\n\n```bash\npnpm add @abdokouta/react-redis\n```\n\n---\n\n## Quick Start\n\n```typescript\nimport { Module } from '@abdokouta/ts-container';\nimport { CacheModule } from '@abdokouta/react-cache';\n\n@Module({\n  imports: [\n    CacheModule.forRoot({\n      default: 'memory',\n      stores: {\n        memory: {\n          driver: 'memory',\n          maxSize: 1000,\n          ttl: 300,\n        },\n      },\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\nThen use it anywhere via DI or hooks:\n\n```typescript\nimport { useCache } from '@abdokouta/react-cache';\n\nfunction UserProfile({ userId }: { userId: string }) {\n  const cache = useCache();\n\n  useEffect(() => {\n    async function load() {\n      const user = await cache.remember(`user:${userId}`, 3600, () =>\n        fetch(`/api/users/${userId}`).then((r) => r.json())\n      );\n      setUser(user);\n    }\n    load();\n  }, [userId]);\n\n  // ...\n}\n```\n\n---\n\n## Configuration\n\n### Basic Configuration\n\nThe configuration object follows the same structure as Laravel's\n`config/cache.php`:\n\n```typescript\nimport { CacheModule } from '@abdokouta/react-cache';\n\nCacheModule.forRoot({\n  // Default store used when none is specified\n  default: 'memory',\n\n  // All available stores\n  stores: {\n    memory: {\n      driver: 'memory',\n      maxSize: 1000,\n      ttl: 300, // 5 minutes\n      prefix: 'mem_',\n    },\n    redis: {\n      driver: 'redis',\n      connection: redisClient,\n      prefix: 'cache_',\n      ttl: 3600, // 1 hour\n    },\n    null: {\n      driver: 'null',\n    },\n  },\n\n  // Global key prefix (applied to all stores)\n  prefix: 'myapp_',\n});\n```\n\n### Using defineConfig\n\nFor type-safe configuration with IDE autocomplete, use the `defineConfig`\nhelper:\n\n```typescript\n// cache.config.ts\nimport { defineConfig } from '@abdokouta/react-cache';\n\nexport default defineConfig({\n  default: 'memory',\n  stores: {\n    memory: {\n      driver: 'memory',\n      maxSize: 1000,\n      ttl: 300,\n    },\n    redis: {\n      driver: 'redis',\n      connection: redisClient,\n      prefix: 'cache_',\n      ttl: 3600,\n    },\n  },\n  prefix: 'app_',\n});\n```\n\n### Environment Variables\n\nThe included `config/cache.config.ts` supports Vite environment variables:\n\n| Variable                      | Description                | Default    |\n| ----------------------------- | -------------------------- | ---------- |\n| `VITE_CACHE_DRIVER`           | Default cache driver       | `'memory'` |\n| `CACHE_PREFIX`                | Global key prefix          | `'app_'`   |\n| `VITE_CACHE_MEMORY_MAX_SIZE`  | Memory store max entries   | `1000`     |\n| `VITE_CACHE_MEMORY_TTL`       | Memory store TTL (seconds) | `300`      |\n| `VITE_REDIS_CACHE_CONNECTION` | Redis connection name      | `'cache'`  |\n| `VITE_CACHE_REDIS_PREFIX`     | Redis key prefix           | `'cache_'` |\n| `VITE_CACHE_REDIS_TTL`        | Redis TTL (seconds)        | `3600`     |\n\n---\n\n## Cache Drivers\n\n### Memory Store\n\nFast in-memory cache using JavaScript `Map`. Data is lost on page refresh or\nprocess restart.\n\n```typescript\n{\n  driver: 'memory',\n  maxSize: 1000,   // Max entries before LRU eviction (optional)\n  ttl: 300,        // Default TTL in seconds (optional)\n  prefix: 'mem_',  // Key prefix (optional)\n}\n```\n\n| Option    | Type       | Default     | Description                        |\n| --------- | ---------- | ----------- | ---------------------------------- |\n| `driver`  | `'memory'` | —           | Required driver identifier         |\n| `maxSize` | `number`   | `undefined` | Max entries (unlimited if omitted) |\n| `ttl`     | `number`   | `300`       | Default TTL in seconds             |\n| `prefix`  | `string`   | `''`        | Key prefix                         |\n\nBest for: development, client-side caching, temporary data.\n\n### Redis Store\n\nPersistent cache backed by Redis. Supports tagging, distributed caching, and\natomic operations.\n\n```typescript\n{\n  driver: 'redis',\n  connection: redisClient,  // RedisConnection instance\n  prefix: 'cache_',         // Key prefix (optional)\n  ttl: 3600,                // Default TTL in seconds (optional)\n}\n```\n\n| Option       | Type              | Default | Description                |\n| ------------ | ----------------- | ------- | -------------------------- |\n| `driver`     | `'redis'`         | —       | Required driver identifier |\n| `connection` | `RedisConnection` | —       | Redis client instance      |\n| `ttl`        | `number`          | `300`   | Default TTL in seconds     |\n| `prefix`     | `string`          | `''`    | Key prefix                 |\n\nBest for: production, distributed systems, when persistence or tagging is\nneeded.\n\n### Null Store\n\nNo-op store that never caches anything. All writes succeed, all reads return\n`undefined`.\n\n```typescript\n{\n  driver: 'null',\n}\n```\n\nBest for: testing, disabling cache, benchmarking without cache overhead.\n\n---\n\n## Usage\n\n### Basic Operations\n\n```typescript\nconst cache = useCache();\n\n// Store a value (TTL in seconds)\nawait cache.put('user:123', { name: 'John' }, 3600);\n\n// Retrieve a value\nconst user = await cache.get('user:123');\n\n// Retrieve with a default\nconst name = await cache.get('user:name', 'Guest');\n\n// Check existence\nif (await cache.has('user:123')) {\n  // ...\n}\n\n// Store multiple values\nawait cache.putMany({ 'user:1': user1, 'user:2': user2 }, 3600);\n\n// Retrieve multiple values\nconst users = await cache.many(['user:1', 'user:2']);\n\n// Store only if key doesn't exist\nconst added = await cache.add('user:123', user, 3600);\n\n// Store indefinitely (no expiration)\nawait cache.forever('config:app', appConfig);\n\n// Remove a value\nawait cache.forget('user:123');\n\n// Get and remove in one call\nconst token = await cache.pull('auth:token');\n\n// Clear everything\nawait cache.flush();\n```\n\n### Remember Pattern\n\nThe `remember` method retrieves from cache or executes a callback and stores the\nresult — the most common caching pattern:\n\n```typescript\n// Cache for 1 hour, fetch from DB on miss\nconst user = await cache.remember('user:123', 3600, async () => {\n  return await database.users.findById(123);\n});\n\n// Cache forever\nconst config = await cache.rememberForever('app:config', async () => {\n  return await loadConfigFromFile();\n});\n```\n\n### Multiple Stores\n\nSwitch between stores at runtime:\n\n```typescript\nconst cache = useCache();\n\n// Use default store\nawait cache.put('key', 'value', 3600);\n\n// Use a specific store\nconst redisCache = cache.store('redis');\nawait redisCache.put('key', 'value', 3600);\n\nconst memoryCache = cache.store('memory');\nawait memoryCache.put('key', 'value', 300);\n\n// Or via the hook\nconst redis = useCache('redis');\n```\n\n### Increment & Decrement\n\nAtomic counter operations:\n\n```typescript\nawait cache.increment('page:views'); // 1\nawait cache.increment('page:views', 10); // 11\nawait cache.decrement('stock:item:42'); // -1\nawait cache.decrement('stock:item:42', 5); // -6\n```\n\n### Cache Tagging\n\nGroup related cache entries with tags for bulk invalidation. Tagging is only\navailable with the Redis store.\n\n```typescript\nconst cache = useCache('redis');\n\n// Store with tags\nawait cache.tags(['users', 'premium']).put('user:123', user, 3600);\nawait cache.tags(['users']).put('user:456', user2, 3600);\nawait cache.tags(['posts']).put('post:1', post, 3600);\n\n// Retrieve tagged items\nconst user = await cache.tags(['users', 'premium']).get('user:123');\n\n// Flush all entries tagged with 'users'\nawait cache.tags(['users']).flush();\n// user:123 and user:456 are now gone, post:1 is untouched\n\n// Flush specific tag combination\nawait cache.tags(['users', 'premium']).flush();\n```\n\nHow tagging works under the hood:\n\n1. Each tag gets a unique namespace ID stored in Redis\n2. Cache keys are prefixed with the combined namespace (e.g.,\n   `abc123|def456:user:123`)\n3. Flushing a tag regenerates its namespace ID, making all old keys inaccessible\n4. Expired entries are tracked in Redis sorted sets for cleanup\n\n---\n\n## React Hooks\n\n### useCache\n\nAccess the cache service from any React component:\n\n```typescript\nimport { useCache } from '@abdokouta/react-cache';\n\nfunction Dashboard() {\n  const cache = useCache();\n\n  const loadStats = async () => {\n    return cache.remember('dashboard:stats', 600, async () => {\n      const res = await fetch('/api/stats');\n      return res.json();\n    });\n  };\n\n  // ...\n}\n\n// Use a specific store\nfunction Widget() {\n  const memoryCache = useCache('memory');\n  // ...\n}\n```\n\n### useCachedQuery\n\nA React Query-like hook that caches async query results:\n\n```typescript\nimport { useCachedQuery } from '@abdokouta/react-cache';\n\nfunction UserProfile({ userId }: { userId: string }) {\n  const { data, isLoading, error, refetch, invalidate } = useCachedQuery({\n    key: `user:${userId}`,\n    queryFn: async () => {\n      const res = await fetch(`/api/users/${userId}`);\n      return res.json();\n    },\n    ttl: 3600,\n  });\n\n  if (isLoading) return <div>Loading...</div>;\n  if (error) return <div>Error: {error.message}</div>;\n\n  return (\n    <div>\n      <h1>{data.name}</h1>\n      <button onClick={refetch}>Refresh</button>\n      <button onClick={invalidate}>Clear Cache & Refresh</button>\n    </div>\n  );\n}\n```\n\n#### Options\n\n| Option            | Type               | Default       | Description                             |\n| ----------------- | ------------------ | ------------- | --------------------------------------- |\n| `key`             | `string`           | —             | Cache key (required)                    |\n| `queryFn`         | `() => Promise<T>` | —             | Async function to fetch data (required) |\n| `ttl`             | `number`           | `300`         | TTL in seconds                          |\n| `storeName`       | `string`           | default store | Which store to use                      |\n| `enabled`         | `boolean`          | `true`        | Enable/disable the query                |\n| `refetchOnMount`  | `boolean`          | `false`       | Force refetch on mount                  |\n| `refetchInterval` | `number`           | —             | Auto-refetch interval (ms)              |\n\n#### Return Value\n\n| Property     | Type                  | Description                  |\n| ------------ | --------------------- | ---------------------------- |\n| `data`       | `T \\| undefined`      | The cached/fetched data      |\n| `isLoading`  | `boolean`             | Loading state                |\n| `error`      | `Error \\| null`       | Error state                  |\n| `refetch`    | `() => Promise<void>` | Re-run query (uses cache)    |\n| `invalidate` | `() => Promise<void>` | Clear cache and re-run query |\n\n---\n\n## API Reference\n\n### CacheService\n\nThe main service providing all cache operations.\n\n| Method                | Signature                                              | Description                      |\n| --------------------- | ------------------------------------------------------ | -------------------------------- |\n| `get`                 | `get<T>(key, defaultValue?): Promise<T \\| undefined>`  | Retrieve a cached value          |\n| `many`                | `many<T>(keys): Promise<Record<string, T>>`            | Retrieve multiple values         |\n| `put`                 | `put<T>(key, value, ttl?): Promise<boolean>`           | Store a value                    |\n| `putMany`             | `putMany<T>(values, ttl?): Promise<boolean>`           | Store multiple values            |\n| `add`                 | `add<T>(key, value, ttl?): Promise<boolean>`           | Store only if key doesn't exist  |\n| `has`                 | `has(key): Promise<boolean>`                           | Check if key exists              |\n| `increment`           | `increment(key, value?): Promise<number>`              | Increment a numeric value        |\n| `decrement`           | `decrement(key, value?): Promise<number>`              | Decrement a numeric value        |\n| `forever`             | `forever<T>(key, value): Promise<boolean>`             | Store indefinitely               |\n| `remember`            | `remember<T>(key, ttl, callback): Promise<T>`          | Get or compute and store         |\n| `rememberForever`     | `rememberForever<T>(key, callback): Promise<T>`        | Get or compute and store forever |\n| `pull`                | `pull<T>(key, defaultValue?): Promise<T \\| undefined>` | Get and remove                   |\n| `forget`              | `forget(key): Promise<boolean>`                        | Remove a value                   |\n| `flush`               | `flush(): Promise<boolean>`                            | Clear all values                 |\n| `tags`                | `tags(names): TaggedCache`                             | Get tagged cache (Redis only)    |\n| `store`               | `store(name?): CacheService`                           | Switch to a different store      |\n| `getDefaultStoreName` | `getDefaultStoreName(): string`                        | Get default store name           |\n| `getStoreNames`       | `getStoreNames(): string[]`                            | List all configured stores       |\n| `hasStore`            | `hasStore(name): boolean`                              | Check if store is configured     |\n| `getPrefix`           | `getPrefix(): string`                                  | Get global key prefix            |\n\n### Store Interface\n\nAll stores implement this interface:\n\n```typescript\ninterface Store {\n  get(key: string): Promise<any>;\n  many(keys: string[]): Promise<Record<string, any>>;\n  put(key: string, value: any, seconds: number): Promise<boolean>;\n  putMany(values: Record<string, any>, seconds: number): Promise<boolean>;\n  increment(key: string, value?: number): Promise<number | boolean>;\n  decrement(key: string, value?: number): Promise<number | boolean>;\n  forever(key: string, value: any): Promise<boolean>;\n  forget(key: string): Promise<boolean>;\n  flush(): Promise<boolean>;\n  getPrefix(): string;\n}\n```\n\n### TaggedCache\n\nReturned by `cache.tags([...])`. Same API as Store with tag-scoped keys:\n\n```typescript\ninterface TaggedCache {\n  get<T>(key: string): Promise<T | undefined>;\n  many(keys: string[]): Promise<Record<string, any>>;\n  put(key: string, value: any, ttl?: number): Promise<boolean>;\n  putMany(values: Record<string, any>, ttl?: number): Promise<boolean>;\n  increment(key: string, value?: number): Promise<number | boolean>;\n  decrement(key: string, value?: number): Promise<number | boolean>;\n  forever(key: string, value: any): Promise<boolean>;\n  forget(key: string): Promise<boolean>;\n  flush(): Promise<boolean>;\n  getTags(): TagSet;\n}\n```\n\n---\n\n## Custom Stores\n\nImplement the `Store` interface to create your own cache driver:\n\n```typescript\nimport type { Store } from '@abdokouta/react-cache';\n\nexport class LocalStorageStore implements Store {\n  async get(key: string): Promise<any> {\n    const item = localStorage.getItem(key);\n    return item ? JSON.parse(item) : undefined;\n  }\n\n  async put(key: string, value: any, seconds: number): Promise<boolean> {\n    localStorage.setItem(\n      key,\n      JSON.stringify({ value, expires: Date.now() + seconds * 1000 })\n    );\n    return true;\n  }\n\n  // ... implement remaining methods\n}\n```\n\n---\n\n## TypeScript\n\nThe package is fully typed. All interfaces and types are exported:\n\n```typescript\nimport type {\n  CacheModuleOptions,\n  CacheServiceInterface,\n  Store,\n  TaggableStore,\n  TaggedCache,\n  TagSet,\n  MemoryStoreConfig,\n  RedisStoreConfig,\n  NullStoreConfig,\n  RedisConnection,\n  CacheDriver,\n  StoreConfig,\n  UseCachedQueryOptions,\n  UseCachedQueryResult,\n} from '@abdokouta/react-cache';\n```\n\n---\n\n## Laravel Comparison\n\nIf you're coming from Laravel, here's how the API maps:\n\n| Laravel                             | react-cache                        |\n| ----------------------------------- | ---------------------------------- |\n| `Cache::get('key')`                 | `cache.get('key')`                 |\n| `Cache::put('key', $val, 3600)`     | `cache.put('key', val, 3600)`      |\n| `Cache::remember('key', 3600, fn)`  | `cache.remember('key', 3600, fn)`  |\n| `Cache::rememberForever('key', fn)` | `cache.rememberForever('key', fn)` |\n| `Cache::forget('key')`              | `cache.forget('key')`              |\n| `Cache::pull('key')`                | `cache.pull('key')`                |\n| `Cache::flush()`                    | `cache.flush()`                    |\n| `Cache::has('key')`                 | `cache.has('key')`                 |\n| `Cache::add('key', $val, 3600)`     | `cache.add('key', val, 3600)`      |\n| `Cache::forever('key', $val)`       | `cache.forever('key', val)`        |\n| `Cache::increment('key')`           | `cache.increment('key')`           |\n| `Cache::decrement('key')`           | `cache.decrement('key')`           |\n| `Cache::store('redis')`             | `cache.store('redis')`             |\n| `Cache::tags(['users'])->get()`     | `cache.tags(['users']).get()`      |\n| `config/cache.php`                  | `defineConfig({...})`              |\n\n---\n\n## Requirements\n\n- Node.js >= 18.0.0\n- React 18 or 19\n- `@abdokouta/ts-container` (dependency injection)\n- `@abdokouta/react-redis` (optional, for Redis driver)\n\n---\n\n## License\n\n[MIT](LICENSE) © [Abdelrhman Kouta](https://github.com/abdokouta)\n","readmeFilename":"README.md"}