{"_id":"@alexmchan/memocache","_rev":"19-f041ff47ca40f3f09002e2cd44e5e743","name":"@alexmchan/memocache","dist-tags":{"latest":"2.0.0"},"versions":{"0.1.1":{"name":"@alexmchan/memocache","version":"0.1.1","_id":"@alexmchan/memocache@0.1.1","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"dist":{"shasum":"4d8b4e18ee9d044a045f85d4465644bff70cfe2a","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.1.1.tgz","fileCount":31,"integrity":"sha512-9Ci2mS6iESrZ6T3ffCnfbqhlm8TIdge1yNudy+fAyhL8DpOuDTdcjCEOXcG7qxalMloI135Fa3J/y1/F6x5ArQ==","signatures":[{"sig":"MEYCIQCISD0uJOyjF1PAp7fgwqySilKIkN9nptFpPQpmghLnTgIhAIfnXt6DbxRl8XO4VKKmSUuKpnDnRovcgSnGVPAArm+K","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":76542},"main":"dist/index.js","_from":"file:alexmchan-memocache-0.1.1.tgz","exports":{".":{"import":"./dist/index.js"},"./package.json":"./package.json"},"private":false,"scripts":{"test":"vitest","build":"tsup","typecheck":"tsc --noEmit","test:watch":"nodemon --watch src --watch tests -e js,ts,jsx,tsx --exec 'npm run test'","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/private/var/folders/dg/bhvk07y57y3561hpfc91bj5w0000gp/T/08f4d2ee1d8687f60d0fd43b07beece7/alexmchan-memocache-0.1.1.tgz","_integrity":"sha512-9Ci2mS6iESrZ6T3ffCnfbqhlm8TIdge1yNudy+fAyhL8DpOuDTdcjCEOXcG7qxalMloI135Fa3J/y1/F6x5ArQ==","_npmVersion":"10.8.2","description":"This package provides a flexible and extensible caching solution for Node.js applications. It supports multiple storage backends and offers features like TTL (Time-To-Live), automatic background revalidation, and function memoization.","directories":{},"_nodeVersion":"20.17.0","dependencies":{"ioredis":"^5.4.1","superjson":"^2.2.1","@libsql/client":"^0.14.0","@upstash/redis":"^1.34.3","@isaacs/ttlcache":"^1.4.1","vite-tsconfig-paths":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.2","nodemon":"^3.1.7","@types/node":"^22.7.4","@arethetypeswrong/cli":"^0.16.4"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.1.1_1728695345500_0.15508436258465896","host":"s3://npm-registry-packages"}},"0.1.2":{"name":"@alexmchan/memocache","version":"0.1.2","_id":"@alexmchan/memocache@0.1.2","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"dist":{"shasum":"a4b9d38e0b0f978c00e46ee524bb22bb01364ad8","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.1.2.tgz","fileCount":31,"integrity":"sha512-sYSXSOWy4xprIBqNxenTwPHs/n2nZWgAWXsowB1bAGn0mFIaS1DWHM7Dcjd0/BdrcgvXEz7aHNW8ojJLOBnFaA==","signatures":[{"sig":"MEYCIQCk8I/feJVfjIU2EI0ygW5ruBrBFSNYNh6qHt7OCKBEcAIhAN7XXvLagtdCafw3y3xQtXBxC6tqMLwtS4f/AZzwqTD3","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":76553},"main":"dist/index.js","_from":"file:alexmchan-memocache-0.1.2.tgz","exports":{".":{"import":"./dist/index.js"},"./package.json":"./package.json"},"private":false,"scripts":{"test":"vitest","build":"tsup","typecheck":"tsc --noEmit","test:watch":"nodemon --watch src --watch tests -e js,ts,jsx,tsx --exec 'npm run test'","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/private/var/folders/dg/bhvk07y57y3561hpfc91bj5w0000gp/T/2656c05d033aaa522ac027d8b759557a/alexmchan-memocache-0.1.2.tgz","_integrity":"sha512-sYSXSOWy4xprIBqNxenTwPHs/n2nZWgAWXsowB1bAGn0mFIaS1DWHM7Dcjd0/BdrcgvXEz7aHNW8ojJLOBnFaA==","_npmVersion":"10.8.2","description":"This package provides a flexible and extensible caching solution for Node.js applications. It supports multiple storage backends and offers features like TTL (Time-To-Live), automatic background revalidation, and function memoization.","directories":{},"_nodeVersion":"20.17.0","dependencies":{"ioredis":"^5.4.1","superjson":"^2.2.1","@libsql/client":"^0.14.0","@upstash/redis":"^1.34.3","@isaacs/ttlcache":"^1.4.1","vite-tsconfig-paths":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.2","nodemon":"^3.1.7","@types/node":"^22.7.4","@arethetypeswrong/cli":"^0.16.4"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.1.2_1728695566988_0.9315177717951852","host":"s3://npm-registry-packages"}},"0.1.3":{"name":"@alexmchan/memocache","version":"0.1.3","_id":"@alexmchan/memocache@0.1.3","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"dist":{"shasum":"d8828ea5a37a0626323fa0fd7ade9e9cec116276","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.1.3.tgz","fileCount":31,"integrity":"sha512-eRgoQ+zhort4DYiR20ps322yq5Qz9pmuNdl9x3MtfmeQQ2JYSCtRsaTMwBWKjN3dxrT5zgviRCJJjU2FudiLaw==","signatures":[{"sig":"MEQCIDMkcVnWLhEfc4g3IRKjlW+ZsrRWWI+yDvWk4MYb73tZAiBjhr1bfKSOXgsQaCXjdZIaUMyC/jhgaoVWwDhvkNnEvg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":76627},"main":"dist/index.js","_from":"file:alexmchan-memocache-0.1.3.tgz","exports":{".":{"import":"./dist/index.js"},"./package.json":"./package.json"},"private":false,"scripts":{"test":"vitest","build":"tsup","typecheck":"tsc --noEmit","test:watch":"nodemon --watch src --watch tests -e js,ts,jsx,tsx --exec 'npm run test'","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/private/var/folders/dg/bhvk07y57y3561hpfc91bj5w0000gp/T/7c378b705b67b0f8dcc0bd6219fe387a/alexmchan-memocache-0.1.3.tgz","_integrity":"sha512-eRgoQ+zhort4DYiR20ps322yq5Qz9pmuNdl9x3MtfmeQQ2JYSCtRsaTMwBWKjN3dxrT5zgviRCJJjU2FudiLaw==","_npmVersion":"10.8.2","description":"This package provides a flexible and extensible caching solution for Node.js applications. It supports multiple storage backends and offers features like TTL (Time-To-Live), automatic background revalidation, and function memoization.","directories":{},"_nodeVersion":"20.17.0","dependencies":{"ioredis":"^5.4.1","superjson":"^2.2.1","@libsql/client":"^0.14.0","@upstash/redis":"^1.34.3","@isaacs/ttlcache":"^1.4.1","vite-tsconfig-paths":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.2","nodemon":"^3.1.7","@types/node":"^22.7.4","@arethetypeswrong/cli":"^0.16.4"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.1.3_1728695687632_0.9879417750294925","host":"s3://npm-registry-packages"}},"0.1.4":{"name":"@alexmchan/memocache","version":"0.1.4","_id":"@alexmchan/memocache@0.1.4","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexanderchan/memocache#readme","bugs":{"url":"https://github.com/alexanderchan/memocache/issues"},"dist":{"shasum":"f86289d015290ccaeea73252cb752ce05f83bc16","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.1.4.tgz","fileCount":31,"integrity":"sha512-oRAvsLS5RDXcis785iMses8kVUPQ3R9Pxt/6DFumd6wGL7dbW94REFvIGWuWu7jtYMCnAayDTlPAvPq1hqTe1g==","signatures":[{"sig":"MEUCIQCD5zb2dap0msvEYKAaHI5PAl9I7PPOGH/TsQCHRsV0RwIgUgFWp28Wk8oihiP8aSopP8scMJiOrXA32yptgSmHmLM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":76787},"main":"dist/index.js","_from":"file:alexmchan-memocache-0.1.4.tgz","exports":{".":{"import":"./dist/index.js"},"./package.json":"./package.json"},"private":false,"scripts":{"test":"vitest","build":"tsup","typecheck":"tsc --noEmit","test:watch":"nodemon --watch src --watch tests -e js,ts,jsx,tsx --exec 'npm run test'","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/private/var/folders/dg/bhvk07y57y3561hpfc91bj5w0000gp/T/feec8364591131d5db8ffde62e3ef69f/alexmchan-memocache-0.1.4.tgz","_integrity":"sha512-oRAvsLS5RDXcis785iMses8kVUPQ3R9Pxt/6DFumd6wGL7dbW94REFvIGWuWu7jtYMCnAayDTlPAvPq1hqTe1g==","repository":{"url":"git+https://github.com/alexanderchan/memocache.git","type":"git"},"_npmVersion":"10.8.2","description":"This package provides a flexible and extensible caching solution for Node.js applications. It supports multiple storage backends and offers features like TTL (Time-To-Live), automatic background revalidation, and function memoization.","directories":{},"_nodeVersion":"20.17.0","dependencies":{"ioredis":"^5.4.1","superjson":"^2.2.1","@libsql/client":"^0.14.0","@upstash/redis":"^1.34.3","@isaacs/ttlcache":"^1.4.1","vite-tsconfig-paths":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.2","nodemon":"^3.1.7","@types/node":"^22.7.4","@arethetypeswrong/cli":"^0.16.4"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.1.4_1728695968363_0.5990884052950234","host":"s3://npm-registry-packages"}},"0.1.5":{"name":"@alexmchan/memocache","version":"0.1.5","_id":"@alexmchan/memocache@0.1.5","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexanderchan/memocache#readme","bugs":{"url":"https://github.com/alexanderchan/memocache/issues"},"dist":{"shasum":"92578c2e059dea28c6fb284ff7c5d1587dd8f358","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.1.5.tgz","fileCount":32,"integrity":"sha512-gVwo0x8agCBNPodClN/6pZ3cYX1hSU5kCg9UEZ5bFbbzNSse6MQodTqnAQzJAHFaJKOzIIVdFesSslHfRFPf0g==","signatures":[{"sig":"MEYCIQCko3KjDQOjxLSDx0I01PXadzzMMX/fAG6/OGEJwSDUmgIhAMKpEiAhB5uLDlzn4RoJ3ITooBCV2le/1iQ7oK5v5wmZ","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":91522},"main":"dist/index.js","_from":"file:alexmchan-memocache-0.1.5.tgz","exports":{".":{"import":"./dist/index.js"},"./package.json":"./package.json"},"private":false,"scripts":{"test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest --watch","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/private/var/folders/dg/bhvk07y57y3561hpfc91bj5w0000gp/T/445be258488f4e0306e0d04dbdb5ab2e/alexmchan-memocache-0.1.5.tgz","_integrity":"sha512-gVwo0x8agCBNPodClN/6pZ3cYX1hSU5kCg9UEZ5bFbbzNSse6MQodTqnAQzJAHFaJKOzIIVdFesSslHfRFPf0g==","repository":{"url":"git+https://github.com/alexanderchan/memocache.git","type":"git"},"_npmVersion":"10.8.2","directories":{},"_nodeVersion":"20.17.0","dependencies":{"ioredis":"^5.4.1","superjson":"^2.2.1","@libsql/client":"^0.14.0","@upstash/redis":"^1.34.3","@isaacs/ttlcache":"^1.4.1","just-memoize-last":"^3.2.0","vite-tsconfig-paths":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.2","nodemon":"^3.1.7","typescript":"^5.6.2","@types/node":"^22.7.4","@arethetypeswrong/cli":"^0.16.4"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.1.5_1728756149353_0.4521101201011337","host":"s3://npm-registry-packages"}},"0.2.0":{"name":"@alexmchan/memocache","version":"0.2.0","_id":"@alexmchan/memocache@0.2.0","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexanderchan/memocache#readme","bugs":{"url":"https://github.com/alexanderchan/memocache/issues"},"dist":{"shasum":"6a9a87e1a6476bd540af8ee976c4416fbaca8e69","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.2.0.tgz","fileCount":32,"integrity":"sha512-B06nmIp2F9VmE3WrMnJ1RIW0ye+uC7uBwvLORnkv0UKz/9O+bMX0aUvrkDKGRRaGdCBzf4GfahjKy5iiiu4ytw==","signatures":[{"sig":"MEUCIH05zDA5OLZR4H+ZAgaYSiV4a4nG41g7MBukUTD4aBe/AiEA7FuHBV0FCqOkHiyAXGjyr4kbTr73Yt5nwvGDO8Klvuw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":96738},"main":"dist/index.js","_from":"file:alexmchan-memocache-0.2.0.tgz","exports":{".":{"import":"./dist/index.js"},"./package.json":"./package.json"},"private":false,"scripts":{"test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest --watch","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/private/var/folders/dg/bhvk07y57y3561hpfc91bj5w0000gp/T/82b708e0212a1e47f28afce9c3c5c671/alexmchan-memocache-0.2.0.tgz","_integrity":"sha512-B06nmIp2F9VmE3WrMnJ1RIW0ye+uC7uBwvLORnkv0UKz/9O+bMX0aUvrkDKGRRaGdCBzf4GfahjKy5iiiu4ytw==","repository":{"url":"git+https://github.com/alexanderchan/memocache.git","type":"git"},"_npmVersion":"10.8.2","directories":{},"_nodeVersion":"20.17.0","dependencies":{"ioredis":"^5.4.1","superjson":"^2.2.1","@libsql/client":"^0.14.0","@upstash/redis":"^1.34.3","@isaacs/ttlcache":"^1.4.1","just-memoize-last":"^3.2.0","vite-tsconfig-paths":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.2","nodemon":"^3.1.7","typescript":"^5.6.2","@types/node":"^22.7.4","@arethetypeswrong/cli":"^0.16.4"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.2.0_1728774198244_0.3310056155494161","host":"s3://npm-registry-packages"}},"0.2.1":{"name":"@alexmchan/memocache","version":"0.2.1","_id":"@alexmchan/memocache@0.2.1","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexanderchan/memocache#readme","bugs":{"url":"https://github.com/alexanderchan/memocache/issues"},"dist":{"shasum":"70290d666809ba3e689fae46b4fc323ff45abebd","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.2.1.tgz","fileCount":36,"integrity":"sha512-8u/5h1M51ka8k0DKLKQLbPd9iic0Uon8kik13pV8T8XH3q1q1sMCIi4c5Wjvmj8o6mpVQv2Y95iPI2BSqFSkiQ==","signatures":[{"sig":"MEYCIQCeEydxjze0hfY1vIQa4r/lK5VOMimguxytRdcT2/JXfgIhAO5KihRr2sA4A41slMzjMGX0QK90bWB1YOW/dwXHxzB/","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":108003},"main":"dist/index.js","_from":"file:alexmchan-memocache-0.2.1.tgz","exports":{".":{"import":"./dist/index.js"},"./package.json":"./package.json"},"private":false,"scripts":{"lint":"eslint .","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest --watch","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/private/var/folders/dg/bhvk07y57y3561hpfc91bj5w0000gp/T/eccaf5c86bbce2d97727557058b0c8cc/alexmchan-memocache-0.2.1.tgz","_integrity":"sha512-8u/5h1M51ka8k0DKLKQLbPd9iic0Uon8kik13pV8T8XH3q1q1sMCIi4c5Wjvmj8o6mpVQv2Y95iPI2BSqFSkiQ==","repository":{"url":"git+https://github.com/alexanderchan/memocache.git","type":"git"},"_npmVersion":"10.8.2","directories":{},"_nodeVersion":"20.17.0","dependencies":{"ioredis":"^5.4.1","superjson":"^2.2.1","@libsql/client":"^0.14.0","@upstash/redis":"^1.34.3","@isaacs/ttlcache":"^1.4.1","just-memoize-last":"^3.2.0","vite-tsconfig-paths":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.2","nodemon":"^3.1.7","typescript":"^5.6.2","typescript-eslint":"^8.8.1","@repo/eslint-config":"^0.2.0","@arethetypeswrong/cli":"^0.16.4"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.2.1_1728859904564_0.6776064319984987","host":"s3://npm-registry-packages"}},"0.2.2":{"name":"@alexmchan/memocache","version":"0.2.2","_id":"@alexmchan/memocache@0.2.2","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexanderchan/memocache#readme","bugs":{"url":"https://github.com/alexanderchan/memocache/issues"},"dist":{"shasum":"b01c4d9e2581b00bc6cb6c9446e97d1a0e476bfd","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.2.2.tgz","fileCount":34,"integrity":"sha512-rB4+sM4rsJ0OsowFSzy9Z9sJBuiaDbF9O86etDQElPBNoFBqK1rbp2OckvUYKV/H5TinT6IbdFwSTPUVsQ0WQQ==","signatures":[{"sig":"MEUCIBSyS+dziAWqbgFQZp6Bg1IuHucAcpbu8tFGqj+I+LHMAiEA9I6LjBZ/NA9fjupGv2cgFSLKQDWeAlZR6HMRdNLDgZ8=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":91579},"main":"dist/index.js","_from":"file:alexmchan-memocache-0.2.2.tgz","exports":{".":{"import":"./dist/index.js"},"./package.json":"./package.json"},"private":false,"scripts":{"lint":"eslint .","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest --watch","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/tmp/33ad974cacaf7a2937f0cad42bbbf292/alexmchan-memocache-0.2.2.tgz","_integrity":"sha512-rB4+sM4rsJ0OsowFSzy9Z9sJBuiaDbF9O86etDQElPBNoFBqK1rbp2OckvUYKV/H5TinT6IbdFwSTPUVsQ0WQQ==","repository":{"url":"git+https://github.com/alexanderchan/memocache.git","type":"git"},"_npmVersion":"10.8.2","directories":{},"_nodeVersion":"20.17.0","dependencies":{"ioredis":"^5.4.1","superjson":"^2.2.1","@libsql/client":"^0.14.0","@upstash/redis":"^1.34.3","@isaacs/ttlcache":"^1.4.1","just-memoize-last":"^3.2.0","vite-tsconfig-paths":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.2","nodemon":"^3.1.7","typescript":"^5.6.3","typescript-eslint":"^8.8.1","@repo/eslint-config":"^0.2.0","@arethetypeswrong/cli":"^0.16.4"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.2.2_1728915172042_0.8156969747740719","host":"s3://npm-registry-packages"}},"0.2.3":{"name":"@alexmchan/memocache","version":"0.2.3","_id":"@alexmchan/memocache@0.2.3","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexanderchan/memocache#readme","bugs":{"url":"https://github.com/alexanderchan/memocache/issues"},"dist":{"shasum":"3f4dc65696699f0dde3b319ca06574951eb564c0","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.2.3.tgz","fileCount":35,"integrity":"sha512-qZG49JqqFqX3FTWeeL7uOG2nKvlkA9wqSJX8c9UNdkTvoWb0W9ZClceZrrZBzkhW41+CGlHxYUWTUrFGZwnAKQ==","signatures":[{"sig":"MEQCIAWa0XEagVSgCfyGLqtce+9lp2FKMz7UAYNxvuBOr5nJAiAywucRV2NnaG3uxioUg+bOz/9pQplm1ty2PEE3A/Vwig==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":109281},"main":"dist/index.js","_from":"file:alexmchan-memocache-0.2.3.tgz","exports":{".":{"import":"./dist/index.js"},"./package.json":"./package.json"},"private":false,"scripts":{"lint":"eslint .","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest --watch","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/tmp/3fe17d1985d2599bec292968a9c4c41a/alexmchan-memocache-0.2.3.tgz","_integrity":"sha512-qZG49JqqFqX3FTWeeL7uOG2nKvlkA9wqSJX8c9UNdkTvoWb0W9ZClceZrrZBzkhW41+CGlHxYUWTUrFGZwnAKQ==","repository":{"url":"git+https://github.com/alexanderchan/memocache.git","type":"git"},"_npmVersion":"10.8.2","description":"--- title: Usage description: Learn how to use the Memocache package to cache data in your Node.js applications. ---","directories":{},"_nodeVersion":"20.17.0","dependencies":{"ioredis":"^5.4.1","superjson":"^2.2.1","@libsql/client":"^0.14.0","@upstash/redis":"^1.34.3","@isaacs/ttlcache":"^1.4.1","just-memoize-last":"^3.2.0","vite-tsconfig-paths":"^5.0.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.2","nodemon":"^3.1.7","typescript":"^5.6.3","typescript-eslint":"^8.8.1","@repo/eslint-config":"^0.2.0","@arethetypeswrong/cli":"^0.16.4"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.2.3_1728915962669_0.5396508006690637","host":"s3://npm-registry-packages"}},"0.2.4":{"name":"@alexmchan/memocache","version":"0.2.4","_id":"@alexmchan/memocache@0.2.4","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexanderchan/memocache#readme","bugs":{"url":"https://github.com/alexanderchan/memocache/issues"},"dist":{"shasum":"5ef4aeac84345115364edb0dc02979126805bd1a","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.2.4.tgz","fileCount":35,"integrity":"sha512-eAvs9BsLGS5CcDF6xrGj8i36xCSDlq/CIQAsIiWOQu6C1TNRkR9bl0e8bXlV1+ZX5dDqB51X2P4VVwqwPxn7Yw==","signatures":[{"sig":"MEYCIQD5CGhxJDcx1feMqnSCqXaeC74vuSUoW5PQ25eLqIlvyAIhANvABm5+f66puBLHvOR/XDtY4km+3w5UL7/yrVGsd5WY","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":109296},"main":"dist/index.js","_from":"file:alexmchan-memocache-0.2.4.tgz","exports":{".":{"import":"./dist/index.js"},"./package.json":"./package.json"},"private":false,"scripts":{"lint":"eslint .","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest --watch","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/tmp/43ba4ab60558be40c6e32f3d27eba571/alexmchan-memocache-0.2.4.tgz","_integrity":"sha512-eAvs9BsLGS5CcDF6xrGj8i36xCSDlq/CIQAsIiWOQu6C1TNRkR9bl0e8bXlV1+ZX5dDqB51X2P4VVwqwPxn7Yw==","repository":{"url":"git+https://github.com/alexanderchan/memocache.git","type":"git"},"_npmVersion":"10.8.2","description":"--- title: Usage description: Learn how to use the Memocache package to cache data in your Node.js applications. ---","directories":{},"_nodeVersion":"20.17.0","dependencies":{"ioredis":"^5.4.1","superjson":"^2.2.1","@libsql/client":"^0.14.0","@upstash/redis":"^1.34.3","@isaacs/ttlcache":"^1.4.1","just-memoize-last":"^3.2.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.2","typescript":"^5.6.3","typescript-eslint":"^8.8.1","@repo/eslint-config":"^0.2.0","vite-tsconfig-paths":"^5.0.1","@arethetypeswrong/cli":"^0.16.4"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.2.4_1728921888279_0.9118276444664704","host":"s3://npm-registry-packages"}},"0.2.6":{"name":"@alexmchan/memocache","version":"0.2.6","_id":"@alexmchan/memocache@0.2.6","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexanderchan/memocache#readme","bugs":{"url":"https://github.com/alexanderchan/memocache/issues"},"dist":{"shasum":"200f573ea6b75376fb0596d6d4a33ca2ead2ab8b","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.2.6.tgz","fileCount":35,"integrity":"sha512-ZCS9WhhS4otzR46J2LlWWtJlT9OoV9YvzH89rwWgaXS4Rc2XKauGtaH5ZiAAn24Oiqz6zzxGpgvTlDU2uBtXpA==","signatures":[{"sig":"MEYCIQDdV1warEc4AFoJx/s30Qh0cY/eSTFMLkzP4Sx60kXLIAIhAJ2PgYHRDK4POYhft1+6El965ZTIMZZfjOZ8FVMjZeMu","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":109423},"main":"dist/index.js","_from":"file:alexmchan-memocache-0.2.6.tgz","exports":{".":{"import":"./dist/index.js"},"./package.json":"./package.json"},"private":false,"scripts":{"lint":"eslint .","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest --watch","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/tmp/1697932bde595e199a61b003a46f5a0e/alexmchan-memocache-0.2.6.tgz","_integrity":"sha512-ZCS9WhhS4otzR46J2LlWWtJlT9OoV9YvzH89rwWgaXS4Rc2XKauGtaH5ZiAAn24Oiqz6zzxGpgvTlDU2uBtXpA==","repository":{"url":"git+https://github.com/alexanderchan/memocache.git","type":"git"},"_npmVersion":"10.8.2","description":"--- title: Usage description: Learn how to use the Memocache package to cache data in your Node.js applications. ---","directories":{},"_nodeVersion":"20.17.0","dependencies":{"ioredis":"^5.4.1","superjson":"^2.2.1","@libsql/client":"^0.14.0","@upstash/redis":"^1.34.3","@isaacs/ttlcache":"^1.4.1","just-memoize-last":"^3.2.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.2","typescript":"^5.6.3","typescript-eslint":"^8.8.1","@repo/eslint-config":"^0.2.0","vite-tsconfig-paths":"^5.0.1","@arethetypeswrong/cli":"^0.16.4"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.2.6_1728922539827_0.8601362211640535","host":"s3://npm-registry-packages"}},"0.7.0":{"name":"@alexmchan/memocache","version":"0.7.0","_id":"@alexmchan/memocache@0.7.0","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexmchan/memocache#readme","bugs":{"url":"https://github.com/alexmchan/memocache/issues"},"dist":{"shasum":"fc73dcfe92f6bc794d444e04417a4f90f3026433","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.7.0.tgz","fileCount":38,"integrity":"sha512-94jJKFxBBCGXBCuhzJmq+KmjUO0jsIFieaoDeE7AA9FJ3IdsG3tQBSyPLd+6+8Oj0FKumi2Dq2aC7qoXJC5wwA==","signatures":[{"sig":"MEYCIQDMv0y2X4IMBN4uTV4iotLky/PvAKIWPb9q5vYCWph7IwIhAP9TMF1b91KunN9gmybbrzmztS2+oqu6EHQejC+x+ry1","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":173706},"main":"dist/index.js","type":"module","_from":"file:alexmchan-memocache-0.7.0.tgz","types":"dist/index.d.ts","exports":{".":{"import":"./dist/index.js","default":"./dist/index.cjs"}},"private":false,"scripts":{"lint":"eslint .","test":"vitest run","build":"tsup","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","test:watch":"vitest --watch","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/private/var/folders/dg/bhvk07y57y3561hpfc91bj5w0000gp/T/47d6e3debd54c6fc91f44bf5cb85bdf8/alexmchan-memocache-0.7.0.tgz","_integrity":"sha512-94jJKFxBBCGXBCuhzJmq+KmjUO0jsIFieaoDeE7AA9FJ3IdsG3tQBSyPLd+6+8Oj0FKumi2Dq2aC7qoXJC5wwA==","repository":{"url":"git+https://github.com/alexmchan/memocache.git","type":"git"},"_npmVersion":"10.8.2","description":"--- title: Usage description: Learn how to use the Memocache package to cache data in your Node.js applications. ---","directories":{},"_nodeVersion":"20.17.0","dependencies":{"superjson":"^2.2.1","@libsql/client":"^0.14.0","@isaacs/ttlcache":"^1.4.1","just-memoize-last":"^3.2.0","@alexmchan/memocache-common":"^0.7.0"},"publishConfig":{"registry":"https://npm.pkg.github.com"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.3","ioredis":"^5.4.1","typescript":"^5.6.3","testcontainers":"^10.13.2","typescript-eslint":"^8.9.0","@repo/eslint-config":"^0.2.0","vite-tsconfig-paths":"^5.0.1","@arethetypeswrong/cli":"^0.16.4","@testcontainers/redis":"^10.13.2","@alexmchan/memocache-store-redis":"^0.7.0"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.7.0_1729258975002_0.2822230355741826","host":"s3://npm-registry-packages"}},"0.8.0":{"name":"@alexmchan/memocache","version":"0.8.0","_id":"@alexmchan/memocache@0.8.0","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexmchan/memocache#readme","bugs":{"url":"https://github.com/alexmchan/memocache/issues"},"dist":{"shasum":"cbf46dd882e189a5d6657aed8503901d1113a865","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.8.0.tgz","fileCount":38,"integrity":"sha512-cc9vP/rSyP3PYOGyM/a4OSPF/hkNDLJ+XycwysyRK13OrUEIuHzeYnvd4MaDtpbu2GNTyRUVhcM2QeggGYW72w==","signatures":[{"sig":"MEYCIQC34/++S6rVa2S7j3y8V0MJKX+8v5HNtfESORJpduN+ggIhANMJd6uuAFID+8PBhhJKopi/09zOIPY6C92JtfeuI/D5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":179182},"main":"dist/index.js","type":"module","_from":"file:alexmchan-memocache-0.8.0.tgz","types":"dist/index.d.ts","exports":{".":{"import":"./dist/index.js","default":"./dist/index.cjs"}},"private":false,"scripts":{"lint":"eslint .","test":"vitest run","build":"tsup","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","test:watch":"vitest --watch","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/private/var/folders/7z/p1d5g8xj233bp74pfgx6fykh0000gp/T/ed5a3913af715c10fa0a833a74446cb0/alexmchan-memocache-0.8.0.tgz","_integrity":"sha512-cc9vP/rSyP3PYOGyM/a4OSPF/hkNDLJ+XycwysyRK13OrUEIuHzeYnvd4MaDtpbu2GNTyRUVhcM2QeggGYW72w==","repository":{"url":"git+https://github.com/alexmchan/memocache.git","type":"git"},"_npmVersion":"10.9.2","description":"--- title: Usage description: Learn how to use the Memocache package to cache data in your Node.js applications. ---","directories":{},"_nodeVersion":"22.13.0","dependencies":{"superjson":"^2.2.1","@libsql/client":"^0.14.0","@isaacs/ttlcache":"^1.4.1","just-memoize-last":"^3.2.0","@alexmchan/memocache-common":"^0.7.0"},"publishConfig":{"registry":"https://npm.pkg.github.com"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.3","ioredis":"^5.4.1","typescript":"^5.6.3","testcontainers":"^10.13.2","typescript-eslint":"^8.9.0","@repo/eslint-config":"^0.2.0","vite-tsconfig-paths":"^5.0.1","@arethetypeswrong/cli":"^0.16.4","@testcontainers/redis":"^10.13.2","@alexmchan/memocache-store-redis":"^0.7.0"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.8.0_1739548510650_0.02182306751801355","host":"s3://npm-registry-packages-npm-production"}},"0.8.1":{"name":"@alexmchan/memocache","version":"0.8.1","_id":"@alexmchan/memocache@0.8.1","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexmchan/memocache#readme","bugs":{"url":"https://github.com/alexmchan/memocache/issues"},"dist":{"shasum":"94690a81b54855b0a28ffa29b06ecc50f0de2418","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.8.1.tgz","fileCount":38,"integrity":"sha512-4W/yy2H9lxk3H99TduOeX+jSYpAfj4KAlze0GHSzZ/AMC9SLmeWCWXFQqNH1uoBze84rbKIdacn+5WFNfmVxAQ==","signatures":[{"sig":"MEUCIQCXDwj2AV+oa1+bTf2/fsrc62QktjsMMXXVJHhqGCrCvQIgSegq7BvY58iu2VkOGaBxzR4gxnqbrBDjCbRT9bG7wB0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":179436},"main":"dist/index.js","type":"module","_from":"file:alexmchan-memocache-0.8.1.tgz","types":"dist/index.d.ts","exports":{".":{"import":"./dist/index.js","default":"./dist/index.cjs"}},"private":false,"scripts":{"lint":"eslint .","test":"vitest run","build":"tsup","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","test:watch":"vitest --watch","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/private/var/folders/7z/p1d5g8xj233bp74pfgx6fykh0000gp/T/883c8543bae2bd80392fef6172898b7b/alexmchan-memocache-0.8.1.tgz","_integrity":"sha512-4W/yy2H9lxk3H99TduOeX+jSYpAfj4KAlze0GHSzZ/AMC9SLmeWCWXFQqNH1uoBze84rbKIdacn+5WFNfmVxAQ==","repository":{"url":"git+https://github.com/alexmchan/memocache.git","type":"git"},"_npmVersion":"10.9.2","description":"--- title: Usage description: Learn how to use the Memocache package to cache data in your Node.js applications. ---","directories":{},"_nodeVersion":"22.13.0","dependencies":{"superjson":"^2.2.1","@libsql/client":"^0.14.0","@isaacs/ttlcache":"^1.4.1","just-memoize-last":"^3.2.0","@alexmchan/memocache-common":"^0.7.0"},"publishConfig":{"registry":"https://npm.pkg.github.com"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.3","ioredis":"^5.4.1","typescript":"^5.6.3","testcontainers":"^10.13.2","typescript-eslint":"^8.9.0","@repo/eslint-config":"^0.2.0","vite-tsconfig-paths":"^5.0.1","@arethetypeswrong/cli":"^0.16.4","@testcontainers/redis":"^10.13.2","@alexmchan/memocache-store-redis":"^0.7.0"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.8.1_1742784846832_0.35223144802727835","host":"s3://npm-registry-packages-npm-production"}},"0.8.2":{"name":"@alexmchan/memocache","version":"0.8.2","_id":"@alexmchan/memocache@0.8.2","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexmchan/memocache#readme","bugs":{"url":"https://github.com/alexmchan/memocache/issues"},"dist":{"shasum":"3360970448fc7c581f5c873587ee355ea5f0e071","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.8.2.tgz","fileCount":38,"integrity":"sha512-8kjxMmlLQAVOUm4696rUtZ7MZM8lDF2I0sC7Yu2n6RE/8A6XDsnvpxP6zUrDcOCd8YOAdB7UKvZEU8QP7Wm3XA==","signatures":[{"sig":"MEUCIQCxP3rHPNN0Z6ze3HpmNRPsSRucb1D9rHJI8MY9x7CCrgIgZB/DnrVRPSKXLYb+Pq/nBddtEUWfwCoDNGq159+g/6A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":179470},"main":"dist/index.js","type":"module","_from":"file:alexmchan-memocache-0.8.2.tgz","types":"dist/index.d.ts","exports":{".":{"import":"./dist/index.js","default":"./dist/index.cjs"}},"private":false,"scripts":{"lint":"eslint .","test":"vitest run","build":"tsup","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","test:watch":"vitest --watch","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/private/var/folders/7z/p1d5g8xj233bp74pfgx6fykh0000gp/T/7a56164ce8eb442674b3881291217a35/alexmchan-memocache-0.8.2.tgz","_integrity":"sha512-8kjxMmlLQAVOUm4696rUtZ7MZM8lDF2I0sC7Yu2n6RE/8A6XDsnvpxP6zUrDcOCd8YOAdB7UKvZEU8QP7Wm3XA==","repository":{"url":"git+https://github.com/alexmchan/memocache.git","type":"git"},"_npmVersion":"10.9.2","description":"--- title: Usage description: Learn how to use the Memocache package to cache data in your Node.js applications. ---","directories":{},"_nodeVersion":"22.13.0","dependencies":{"superjson":"^2.2.1","@libsql/client":"^0.14.0","@isaacs/ttlcache":"^1.4.1","just-memoize-last":"^3.2.0","@alexmchan/memocache-common":"^0.7.0"},"publishConfig":{"registry":"https://npm.pkg.github.com"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^2.1.3","ioredis":"^5.4.1","typescript":"^5.6.3","testcontainers":"^10.13.2","typescript-eslint":"^8.9.0","@repo/eslint-config":"^0.2.0","vite-tsconfig-paths":"^5.0.1","@arethetypeswrong/cli":"^0.16.4","@testcontainers/redis":"^10.13.2","@alexmchan/memocache-store-redis":"^0.7.0"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.8.2_1742784994788_0.5047945028101193","host":"s3://npm-registry-packages-npm-production"}},"0.9.0":{"name":"@alexmchan/memocache","version":"0.9.0","_id":"@alexmchan/memocache@0.9.0","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexmchan/memocache#readme","bugs":{"url":"https://github.com/alexmchan/memocache/issues"},"dist":{"shasum":"a13ff3bc6ff533e83bef4327832cd89d265324b2","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.9.0.tgz","fileCount":38,"integrity":"sha512-26gzi2PNjjELOKIfoBF4rgXEERPR2oWEGG8t81MPIS3/MtWwJumVB3L3GHAgBoM+grkQsCBaHtLP20KnmledJw==","signatures":[{"sig":"MEQCIB1YATcmvoTgNvrep18h4Pd7NdDdLmbDEUB+44vLMOAnAiBIh/b4RsTihZkQJyzL2PLeRrAJaV43109IgEOQddxPaQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":186743},"main":"dist/index.js","type":"module","_from":"file:alexmchan-memocache-0.9.0.tgz","types":"dist/index.d.ts","exports":{".":{"import":"./dist/index.js","default":"./dist/index.cjs"}},"private":false,"scripts":{"lint":"eslint .","test":"vitest run","build":"tsup","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","test:watch":"vitest --watch","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/private/var/folders/7z/p1d5g8xj233bp74pfgx6fykh0000gp/T/9f0c4de032bed9f2f0fd6891e8505c5e/alexmchan-memocache-0.9.0.tgz","_integrity":"sha512-26gzi2PNjjELOKIfoBF4rgXEERPR2oWEGG8t81MPIS3/MtWwJumVB3L3GHAgBoM+grkQsCBaHtLP20KnmledJw==","repository":{"url":"git+https://github.com/alexmchan/memocache.git","type":"git"},"_npmVersion":"10.9.2","description":"--- title: Usage description: Learn how to use the Memocache package to cache data in your Node.js applications. ---","directories":{},"_nodeVersion":"22.13.0","dependencies":{"superjson":"^2.2.1","@libsql/client":"^0.14.0","@isaacs/ttlcache":"^1.4.1","just-memoize-last":"^3.2.0","@alexmchan/memocache-common":"^0.7.0"},"publishConfig":{"registry":"https://npm.pkg.github.com"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^3.0.9","ioredis":"^5.4.1","typescript":"^5.6.3","testcontainers":"^10.13.2","typescript-eslint":"^8.9.0","@repo/eslint-config":"^0.2.0","vite-tsconfig-paths":"^5.0.1","@arethetypeswrong/cli":"^0.16.4","@testcontainers/redis":"^10.13.2","@alexmchan/memocache-store-redis":"^0.7.0"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.9.0_1742788387286_0.3003643005416017","host":"s3://npm-registry-packages-npm-production"}},"0.10.0":{"name":"@alexmchan/memocache","version":"0.10.0","_id":"@alexmchan/memocache@0.10.0","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexmchan/memocache#readme","bugs":{"url":"https://github.com/alexmchan/memocache/issues"},"dist":{"shasum":"c9c043fde2c184e085ac18f6d26f1ff170697fa9","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-0.10.0.tgz","fileCount":34,"integrity":"sha512-1GazGxY4XdDzuQ5e07UQXOO2l5Ltmp82XDGG1fdBpmbbzLfC+BFLj1iZTuO1Tv+MRzU6ozsVYGHBt/06wGvaSA==","signatures":[{"sig":"MEYCIQCK8DgJ6XHCe4Ght0VCv+LV2FFzlgmmqq+vdIegm8QS0QIhAPik37phZJ4dKvapN2TCr/iiYnCslfB+6jSpUGEDM6U/","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":146445},"main":"dist/index.js","type":"module","_from":"file:alexmchan-memocache-0.10.0.tgz","types":"dist/index.d.ts","exports":{".":{"import":"./dist/index.js","default":"./dist/index.cjs"}},"private":false,"scripts":{"lint":"eslint .","test":"vitest run","build":"tsup","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","test:watch":"vitest --watch","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/private/var/folders/7z/p1d5g8xj233bp74pfgx6fykh0000gp/T/684fa4d503bd5a85ba20246cbd758734/alexmchan-memocache-0.10.0.tgz","_integrity":"sha512-1GazGxY4XdDzuQ5e07UQXOO2l5Ltmp82XDGG1fdBpmbbzLfC+BFLj1iZTuO1Tv+MRzU6ozsVYGHBt/06wGvaSA==","repository":{"url":"git+https://github.com/alexmchan/memocache.git","type":"git"},"_npmVersion":"10.9.2","description":"--- title: Usage description: Learn how to use the Memocache package to cache data in your Node.js applications. ---","directories":{},"_nodeVersion":"22.13.0","dependencies":{"superjson":"^2.2.1","@libsql/client":"^0.14.0","@isaacs/ttlcache":"^1.4.1","just-memoize-last":"^3.2.0","@alexmchan/memocache-common":"^0.7.0"},"publishConfig":{"registry":"https://npm.pkg.github.com"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^3.0.9","ioredis":"^5.4.1","typescript":"^5.6.3","testcontainers":"^10.13.2","typescript-eslint":"^8.9.0","@repo/eslint-config":"^0.2.0","vite-tsconfig-paths":"^5.0.1","@arethetypeswrong/cli":"^0.16.4","@testcontainers/redis":"^10.13.2"},"_npmOperationalInternal":{"tmp":"tmp/memocache_0.10.0_1744039275220_0.3001672581791386","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@alexmchan/memocache","version":"1.0.0","_id":"@alexmchan/memocache@1.0.0","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"homepage":"https://github.com/alexmchan/memocache#readme","bugs":{"url":"https://github.com/alexmchan/memocache/issues"},"dist":{"shasum":"a6513914229f1cd3db7572636694b1af2bb2eca7","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-1.0.0.tgz","fileCount":55,"integrity":"sha512-gYr5VbsUJON9lR6mSwWGP8mFXA/wnk5FUkDOI2h+toKUk8N7hJWGjRsNOMBQ43tjnZk1jraoEXj/AW6iJRqrgQ==","signatures":[{"sig":"MEYCIQC/QBQnE+CRVANNM5ouDpj56zFeKs7keeSgUDbX/WpEwwIhAMDSrNBs0Q68A94UzH9X92HP4kFpuWMR5yOubmUoa0El","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":343980},"main":"dist/index.js","type":"module","_from":"file:alexmchan-memocache-1.0.0.tgz","types":"dist/index.d.ts","exports":{".":{"import":"./dist/index.js","default":"./dist/index.cjs"}},"private":false,"scripts":{"lint":"biome check .","test":"vitest run","build":"tsup","coverage":"vitest run --coverage","lint:fix":"biome check --write .","typecheck":"tsc --noEmit","test:watch":"vitest --watch","check-exports":"yarn pack --out ./ignore-package.tgz && yarn attw ./ignore-package.tgz && rm ./ignore-package.tgz"},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"_resolved":"/private/var/folders/r7/v6yxz7l93hj4jz_lp08p8fbh0000gn/T/f46dbc08db7db606f607d627ceefb7c2/alexmchan-memocache-1.0.0.tgz","_integrity":"sha512-gYr5VbsUJON9lR6mSwWGP8mFXA/wnk5FUkDOI2h+toKUk8N7hJWGjRsNOMBQ43tjnZk1jraoEXj/AW6iJRqrgQ==","repository":{"url":"git+https://github.com/alexmchan/memocache.git","type":"git"},"_npmVersion":"11.6.0","description":"--- title: Usage description: Learn how to use the Memocache package to cache data in your Node.js applications. ---","directories":{},"_nodeVersion":"22.14.0","dependencies":{"superjson":"^2.2.6","@libsql/client":"^0.17.0","@isaacs/ttlcache":"^2.1.4","just-memoize-last":"^3.2.0","@alexmchan/memocache-common":"^1.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.0","ioredis":"^5.10.0","typescript":"^5.9.3","testcontainers":"^11.12.0","@vitest/coverage-v8":"^4.1.0","vite-tsconfig-paths":"^6.1.1","@arethetypeswrong/cli":"^0.18.2","@testcontainers/redis":"^11.12.0"},"_npmOperationalInternal":{"tmp":"tmp/memocache_1.0.0_1773520545583_0.014012596205056571","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@alexmchan/memocache","version":"2.0.0","private":false,"dependencies":{"@isaacs/ttlcache":"^2.1.4","just-memoize-last":"^3.2.0","superjson":"^2.2.6","@alexmchan/memocache-common":"^2.0.0"},"devDependencies":{"@arethetypeswrong/cli":"^0.18.2","@testcontainers/redis":"^11.12.0","ioredis":"^5.10.0","testcontainers":"^11.12.0","tsup":"^8.5.1","typescript":"^5.9.3","vite-tsconfig-paths":"^6.1.1","@vitest/coverage-v8":"^4.1.0","vitest":"^4.1.0"},"repository":{"type":"git","url":"git+https://github.com/alexmchan/memocache.git"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"type":"module","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"default":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"build":"tsup","check-exports":"pnpm pack --out ./ignore-package.tgz && pnpm exec attw ./ignore-package.tgz && rm ./ignore-package.tgz","typecheck":"tsc --noEmit","test":"vitest run","coverage":"vitest run --coverage","lint":"biome check .","lint:fix":"biome check --write .","test:watch":"vitest --watch"},"_id":"@alexmchan/memocache@2.0.0","description":"--- title: Usage description: Learn how to use the Memocache package to cache data in your Node.js applications. ---","bugs":{"url":"https://github.com/alexmchan/memocache/issues"},"homepage":"https://github.com/alexmchan/memocache#readme","_integrity":"sha512-n5UJoNqAWRhPqm4JnkaQqHjc32BRVfpx1sF7r6DqDMwkCG304HuJfJ7BL2iBBeaEqEDVndHg8UrWgk4aPe+SPg==","_resolved":"/private/var/folders/r7/v6yxz7l93hj4jz_lp08p8fbh0000gn/T/fbf0568f12f6377073ec0bdeeab90eab/alexmchan-memocache-2.0.0.tgz","_from":"file:alexmchan-memocache-2.0.0.tgz","_nodeVersion":"24.16.0","_npmVersion":"11.13.0","dist":{"integrity":"sha512-n5UJoNqAWRhPqm4JnkaQqHjc32BRVfpx1sF7r6DqDMwkCG304HuJfJ7BL2iBBeaEqEDVndHg8UrWgk4aPe+SPg==","shasum":"c2b4ef0e90c067f7aadf7d4112835a4bfd8588e5","tarball":"https://registry.npmjs.org/@alexmchan/memocache/-/memocache-2.0.0.tgz","fileCount":7,"unpackedSize":88965,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCQV4uMxOra0rj4k01cj2WBQ1Hb3rErObh8AlOTd9z53wIgU2eBuYzPDejfJ2B5/g3lH6rZyBlCOd8N7zZfpGeJZi0="}]},"_npmUser":{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"},"directories":{},"maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/memocache_2.0.0_1784073624661_0.6987109328103325"},"_hasShrinkwrap":false}},"time":{"created":"2024-10-12T01:09:05.404Z","modified":"2026-07-15T00:00:24.990Z","0.1.1":"2024-10-12T01:09:05.683Z","0.1.2":"2024-10-12T01:12:47.220Z","0.1.3":"2024-10-12T01:14:47.882Z","0.1.4":"2024-10-12T01:19:28.576Z","0.1.5":"2024-10-12T18:02:29.581Z","0.2.0":"2024-10-12T23:03:18.505Z","0.2.1":"2024-10-13T22:51:44.777Z","0.2.2":"2024-10-14T14:12:52.245Z","0.2.3":"2024-10-14T14:26:02.870Z","0.2.4":"2024-10-14T16:04:48.432Z","0.2.6":"2024-10-14T16:15:39.989Z","0.7.0":"2024-10-18T13:42:55.217Z","0.8.0":"2025-02-14T15:55:10.801Z","0.8.1":"2025-03-24T02:54:07.038Z","0.8.2":"2025-03-24T02:56:34.968Z","0.9.0":"2025-03-24T03:53:07.456Z","0.10.0":"2025-04-07T15:21:15.381Z","1.0.0":"2026-03-14T20:35:45.746Z","2.0.0":"2026-07-15T00:00:24.828Z"},"bugs":{"url":"https://github.com/alexmchan/memocache/issues"},"homepage":"https://github.com/alexmchan/memocache#readme","repository":{"type":"git","url":"git+https://github.com/alexmchan/memocache.git"},"description":"--- title: Usage description: Learn how to use the Memocache package to cache data in your Node.js applications. ---","maintainers":[{"name":"alexanderchan","email":"alexander.m.chan@gmail.com"}],"readme":"---\ntitle: Usage\ndescription: Learn how to use the Memocache package to cache data in your Node.js applications.\n---\n\n# memocache\n\nThis package provides a flexible and extensible caching solution for Node.js applications. It supports multiple storage backends and offers features like TTL (Time-To-Live), automatic background revalidation, and function memoization.\n\n## Features\n\n- Multiple storage backend support (e.g., in-memory TTL store, Redis, SQLite)\n- Automatic promotion/backfill into higher-priority stores after a fresh lower-tier hit\n- Configurable TTL (Time-To-Live) for cache entries\n- Automatic background revalidation of stale data\n- Function memoization with automatic cache key generation `const cachedFunction = createCachedFunction(anyFunction)` with automatic typed arguments and return values\n- Supports middleware for encryption and metrics of cache stores\n\n## Installation\n\n```bash\npnpm install @alexmchan/memocache\n```\n\n## Usage\n\n### Basic Usage with In-Memory TTL Store\n\nThe default store is an **in-memory TTL (Time-To-Live) cache** — entries are held in process memory and automatically expire after a configurable duration. This is the simplest setup: no external services required, zero latency, perfect for single-server apps or development.\n\n> **Memory note:** The store caps at 3,000,000 entries by count, not by byte size. Memory usage depends on the size of your cached values. Small objects like user profiles, roles, and permission checks are ideal — a few hundred bytes each means millions of entries fit comfortably in a typical Node.js process. Avoid caching large payloads (e.g. full HTML, binary data) in the TTL store without reducing the entry cap accordingly.\n\n```typescript\nimport { createCache, createTTLStore } from '@alexmchan/memocache'\nimport { Time } from '@alexmchan/memocache'\n\n// Items live in memory for up to 5 minutes, then are evicted automatically\nconst store = createTTLStore({\n  defaultTTL: 5 * Time.Minute,\n})\n\nexport const cache = createCache({\n  defaultFresh: 30 * Time.Second,\n  stores: [store],\n})\n\nconst { createCachedFunction } = cache\n\n// your fetch function\nfunction fetchSomething(arg) {\n  return `Result for ${arg}`\n}\n\n// Create a cached version of a function\nconst cachedFetchSomething = createCachedFunction(fetchSomething)\n\n// Use the cached function\nconsole.log(await cachedFetchSomething('example')) // fetchSomething is called once\nconsole.log(await cachedFetchSomething('example')) // fetchSomething is not called cached value is returned\n```\n\n## How it works\n\n1. Data is read from the stores, if it is not found we call the function to get the data.\n\n2. If the data exists in the store, we check if it is stale we return the value in the store and then call the function to get the fresh data.\n\n3. If a fresh hit is found in a lower-priority store, the value is asynchronously backfilled into higher-priority stores.\n\n4. If the data is past it's time to live it will be expired from the store\n\n![A diagram of how the caching works](https://raw.githubusercontent.com/alexanderchan/memocache/refs/heads/main/docs/src/assets/overview-diagram-1.svg)\n\n<!--\nthis diagram is in docs/src/assets/overview-diagram.svg\nand can be generated from the script in docs `generate:diagrams`\n -->\n\n## Motivation\n\nThere can be a lot of wrapper code to use a cache. This package provides a simple to use cache that supports stale while revalidation. The typical pattern for caching requires:\n\n- finding a good key to use for the cache, typically the parameters to the function\n- checking if the key exists in the cache\n- if the key does not exist, fetching the data and storing it in the cache\n- if the key does exist, returning the data from the cache\n- optionally:\n  - setting a TTL on the cached value\n  - setting a stale while revalidation policy\n  - setting a cache store\n  - setting up encrypted caches\n\nOne may also want to write back to multiple stores such as an in memory TTL Cache, a local sqlite instance, or Redis. This package provides a simple to use API that supports all of these features.\n\nWe use the stable stringified hash popularized by react-query to generate the cache key and a sha256 hash of any function code. This allows for easy generation of the cache key based on the function signature and arguments allowing us to easily memoize functions.\n\nThis also supports the stale while revalidate pattern allowing to return stale data while fetching fresh data in the background.\n\n```ts\n// with memocache\nconst { createCachedFunction } = createCache({\n  stores: [createTTLStore()],\n})\n\n// Create a cached version of a function\nconst cachedFunction = createCachedFunction(async ({ id, name }) => {\n  // some expensive operation or fetch\n  return `Result for ${id} and ${name}`\n})\n\n// The old way without memocache to help\n\nfunction doSomething({ id, name }) {\n  // check the cache\n  const key = JSON.stringify({ id, name })\n  const cachedValue = cache.get(key)\n  if (cachedValue) {\n    return cachedValue\n  }\n\n  // some expensive operation or fetch\n  const result = await doSomethingVeryExpensive(`Result for ${id} and ${name}`)\n\n  // we have to wait here or we need to find a way to signal to the platform for serverless that the\n  try {\n    await cache.set(key, result, timeToLive)\n  } catch (e) {\n    //...\n  }\n  // now repeat for all available cache's and we still need\n  // to add stale while revalidate\n  // and serverless support\n  return result\n}\n```\n\nWith this method it's easy to wrap a function and have it read/write from multiple stores. When a lower-priority store returns a fresh hit, memocache will also promote that value back into earlier stores in the background so subsequent reads can hit the faster tiers.\n\n## API Reference\n\n### `createCache(options: CacheOptions)`\n\nCreates a new cache instance.\n\n- `options.stores`: An array of `CacheStore` instances\n- `options.defaultTTL`: Default Time-To-Live for cache entries\n- `options.defaultFresh`: Revalidate stale data after this time\n- `options.context`: (Optional) A custom context for managing async operations\n\n#### `fresh` vs `ttl` mental model\n\n```\nTimeline: [0 ─── fresh ─── ttl ─── ∞]\n  [0, fresh]   → serve from cache (no revalidation)\n  [fresh, ttl] → serve stale data + revalidate in background\n  [ttl, ∞]     → cache miss, fetch fresh data\n```\n\n- **`fresh`** (`defaultFresh`): How long cached data is considered fresh. Within this window, the cached value is returned immediately with no background fetch.\n- **`ttl`** (`defaultTTL`): How long cached data is kept at all. Between `fresh` and `ttl`, stale data is served while a background revalidation runs. Past `ttl`, the entry is expired and fresh data must be fetched.\n\nReturns an object with the following methods:\n\n- `createCachedFunction<T>(fn, options)`: Creates a memoized version of a function\n- `cacheQuery<T>({ queryFn, queryKey, options })`: Executes a cache query\n- `dispose()`: Disposes of the cache and its stores\n\n### `createCachedFunction(fn, options)`\n\nCreates a memoized version of a function.\n\n- `fn`: The function to memoize\n- `options`(optional): `CacheQueryOptions` Options for the memoized function\n- `options.cachePrefix`: A prefix will be auto generated based on the function contents for convenience and will add only fractions of a millisecond, however for very very large functions this might be a concern so one can specify a prefix such as `/api/todos` to scope the function to a known value. Note that any change to the function code will also change the cache key unless this value is set.\n- `options.ttl`: Time-To-Live for cache entries in ms\n- `options.fresh`: Revalidate stale data after this time in ms\n\n> 🟡 Make sure that any identifiers that might be inferred from auth such as customerId are passed in as arguments to the function to ensure that the cache key is unique per user so that one user doesn't see another user's data. Alternatively, specify your own cache keys with cacheQuery.\n\n### `cacheQuery({ queryFn, queryKey, options })`\n\nExecutes a cache query with a specific set of keys. This resembles the `useQuery` api. As an added bonus, the react-query [eslint plugin](https://tanstack.com/query/latest/docs/eslint/eslint-plugin-query) will also help validate that external values are included in the querykey.\n\n```ts\nfunction exampleFunction({ storeId, customerId }) {\n  return cacheQuery({\n    queryKey: ['/items', { storeId, customerId }],\n    queryFn: async () => {\n      return fetchItems({ storeId, customerId })\n    },\n  })\n}\n```\n\n### `invalidate({ queryKey: any[] })`\n\nRemoves data from all cache stores for the given query key.\n\n```ts\nawait cache.invalidate({ queryKey: ['/items', { storeId, customerId }] })\n```\n\n### `setCacheData({ queryKey, value, ttl? })`\n\nManually sets data in all cache stores, wrapped in the `{ value, age }` envelope expected by `cacheQuery`.\n\n- `queryKey`: The cache key array\n- `value`: The value to store\n- `ttl` (optional): Time-To-Live in milliseconds\n\n```ts\nawait cache.setCacheData({\n  queryKey: ['/items', { storeId }],\n  value: cachedItems,\n  ttl: 5 * Time.Minute,\n})\n```\n\n### Invalidating a Cache Entry\n\nTo invalidate a cache entry, there's a `.invalidate()` method on the memoized function that can be called with the same signature as the original function.\n\n```typescript\nconst { createCachedFunction } = createCache({\n  stores: [sqliteStore],\n})\n\nconst myCachedFunction = createCachedFunction(async ({ example }) => {\n  return `Result for ${example}`\n})\n\nawait myCachedFunction({ example: 'example' })\nawait myCachedFunction.invalidate({ example: 'example' })\n```\n\n## Stores\n\n### TTL Store\n\nCreates an in-memory TTL store based on `@isaacs/ttl-cache`.\n\n```typescript\nconst store = createTTLStore({\n  defaultTTL: 5 * Time.Minute,\n})\n```\n\n### SQLite Store\n\nFor SQLite storage, use the [@alexmchan/memocache-store-sqlite](https://github.com/alexmchan/memocache/tree/main/packages/store-sqlite) package — backed by the standard-library `node:sqlite` module with zero external dependencies (Node.js >= 24).\n\n```bash\npnpm install @alexmchan/memocache-store-sqlite\n```\n\n```typescript\nimport { createCache } from '@alexmchan/memocache'\nimport { Time } from '@alexmchan/memocache-common'\nimport { createSqliteStore } from '@alexmchan/memocache-store-sqlite'\n\nconst sqliteStore = createSqliteStore({\n  location: ':memory:', // or './cache.db'\n  cleanupInterval: 5 * Time.Minute,\n  defaultTTL: 10 * Time.Minute,\n})\n\nconst cache = createCache({\n  stores: [sqliteStore],\n  defaultFresh: 1 * Time.Minute,\n  defaultTTL: 5 * Time.Minute,\n})\n\n// Use cache as in the previous example\n```\n\n### Redis Store `createRedisStore`\n\nAn [ioredis](https://github.com/redis/ioredis) based store.\n\n```\npnpm install @alexmchan/memocache-store-redis\n```\n\n```typescript\nimport { createRedisStore } from '@alexmchan/memocache-store-redis'\nimport { Redis } from 'ioredis'\n\nconst redisStore = createRedisStore({\n  redisClient: new Redis({\n    host: 'localhost',\n    port: 6379,\n  }),\n  defaultTTL: 5 * Time.Minute,\n})\n```\n\n### Upstash Redis Store `createUpstashRedisStore`\n\nAn [Upstash](https://github.com/upstash/redis-js) Redis store (also [`@vercel/kv`](https://github.com/vercel/storage/blob/main/packages/kv/src/index.ts) since it's a proxy of Upstash).\n\n```typescript\nimport { createUpstashRedisStore } from '@alexmchan/memocache-store-redis'\nimport { Redis } from '@upstash/redis'\nconst redisRestStore = createUpstashRedisStore({\n  redisClient: new Redis({\n    url: process.env.UPSTASH_REDIS_REST_URL,\n    token: process.env.UPSTASH_REDIS_REST_TOKEN,\n  }),\n  defaultTTL: 5 * Time.Minute,\n})\n```\n\n## Middleware\n\nMiddleware wraps the store definition and returns a new store that can be used in the cache. Middleware can be used to add additional functionality to the store, such as logging, metrics, or encryption. See the `encryption` middleware for an example of how to use middleware.\n\n### Encrypted middleware\n\nAttach encryption to any store. This middleware encrypts the value before storing it in the store and decrypts it when retrieving it.\n\nA hash of the key/salt is used to encrypt the value and a part of the cache. Changing the key or salt will effectively invalidate the cache values.\n\n```ts\nconst ttlStore = createTTLStore({ defaultTTL: 60 * Time.Second })\n\nconst encryptedStore = createEncryptedStore({\n  key: 'this is secret sauce',\n  salt: 'this is salty',\n  store: ttlStore,\n})\n\nexport const { createCachedFunction, cacheQuery } = createCache({\n  stores: [encryptedStore],\n})\n```\n\n### Metrics\n\nAttach metrics to any store. This middleware logs the time taken to get, set, and delete values from the store.\n\n```ts\nconst ttlStore = createTTLStore({ defaultTTL: 60 * Time.Second })\nconst metricsSqliteStore = createMetricsStore({\n  store: ttlStore,\n})\n\n// output to the logger\n// Metric {\n//   metric: \"cache.read\",\n//   key: \"[\\\"hello/80c56980e62840587ea4c2f103f23f08e042bd8cea808025219e4e7d1b7c996d\\\",[{\\\"message\\\":\\\"world\\\"}]]\",\n//   hit: true,\n//   latency: 1,\n// }\n```\n\n## Advanced Features\n\n### Context\n\nFor serverless functions, the context object can be used to manage asynchronous operations. The context object has a `waitUntil` method that can be used to enqueue asynchronous tasks to be performed during the lifecycle of the request.\n\nThe job of the context is to wait on any asynchronous operations that need to be completed before the function can return so it is left up to the implementer to decide what to do with the context. The context will be provided with promise(s) that need to be completed.\n\nAs described in the Vercel documentation:\n\n> The waitUntil() method enqueues an asynchronous task to be performed during the lifecycle of the request. You can use it for anything that can be done after the response is sent, such as logging, sending analytics, or updating a cache, without blocking the response from being sent. waitUntil() is available in the Node.js and Edge Runtime. Promises passed to waitUntil() will have the same timeout as the function itself. If the function times out, the promises will be cancelled.\n\n> To use waitUntil() in your function, import the waitUntil() method from @vercel/functions package. For more information, see the @vercel/functions reference.\n\n```ts\nexport interface Context {\n  waitUntil: (p: Promise<unknown>) => void\n}\n```\n\n```ts\nimport { Context } from './context'\nimport { waitUntil } from '@vercel/functions'\n\ncreateCache({\n  context: {\n    waitUntil,\n    [Symbol.asyncDispose]() {\n      // cleanup\n    },\n  },\n  // ...\n})\n```\n\nVendor specific documentation:\n\n- [Vercel Serverless](https://vercel.com/docs/functions/functions-api-reference#waituntil)\n- [Vercel Edge and Middleware](https://vercel.com/docs/functions/edge-middleware/middleware-api#waituntil)\n- [Cloudflare Workers](https://developers.cloudflare.com/workers/runtime-apis/context/)\n- [AWS response streaming](https://aws.amazon.com/blogs/compute/introducing-aws-lambda-response-streaming/)\n- [AWS Lambda event loops](https://dev.to/dvddpl/event-loops-and-idle-connections-why-is-my-lambda-not-returning-and-then-timing-out-2oo7)\n\nTo be tested implementation of a cache flushing waitable context:\n\n```ts\n//**----------------------------------------------------\n/* This is a simple context and only for serverless environments\n/* where the list of waitables won't grow indefinitely\n/*--------------------------------------------------**/\n\nfunction createSimpleContext() {\n  const waitables: Promise<unknown>[] = []\n  const context = {\n    waitables,\n    waitUntil(p) {\n      waitables.push(p)\n\n      if (waitables.length > 1000) {\n        this.flushCache()\n      }\n    },\n\n    async flushCache() {\n      await Promise.allSettled(waitables)\n      waitables.length = 0\n    },\n\n    [Symbol.asyncDispose]() {\n      return this.flushCache()\n    },\n  }\n\n  return context\n}\n\nasync function handler(event, context) {\n  using simpleContext = createSimpleContext()\n  using cache = createCache({\n    stores: [store],\n    context: simpleContext,\n  })\n  // do work, ideally return using streaming response otherwise the user response will wait on the flushCache\n\n  // without `using` we have to wait for all promises to finish\n  await simpleContext.flushCache()\n}\n```\n\n## Concepts\n\n### Stores\n\nStores are the underlying data structure that the cache uses to store the data. The cache uses the store to get, set, and delete data. The store can be anything that implements the `Store` interface and could be an in-memory store, an SQLite store, a Redis store, etc.\n\n### Default TTL\n\nThe time to live will be taken in the order of:\n\n1. The default TTL of function if defined\n2. The default TTL of the store if defined\n3. The default TTL of the cache if defined\n\nThis allows for overriding of the per function TTL, but otherwise we can have different TTLs for the stores so that something that has a larger capacity such as a disk store can have a longer TTL than a memory store.\n\n### `Time` Constants\n\nConstants for time units in milliseconds.\n\n- `Time.Millisecond`\n- `Time.Second`\n- `Time.Minute`\n- `Time.Hour`\n- `Time.Day`\n- `Time.Week`\n\nUsage `5 * Time.Minute` or `10 * Time.Second`, mirrors [`go's Time durations`](https://github.com/golang/go/blob/b521ebb55a9b26c8824b219376c7f91f7cda6ec2/src/time/time.go#L930).\n\nOr choose any time library for `millisecond` durations\n\n```typescript\nimport { Duration } from 'effect'\n\nconst defaultTTL = Duration.decode('10 minutes').value.millis\n```\n\n### Build your own store\n\nThe store interface is the following\n\n```typescript\nexport interface CacheStore extends AsyncDisposable {\n  /** Set a value in the store, ttl in milliseconds */\n  set(key: string, value: any, ttl?: number): Promise<any>\n  get(key: string): Promise<any>\n  delete(key: string): Promise<unknown>\n\n  /** Remove all values from the store */\n  clear?(): Promise<any>\n  /** dispose of any resources or connections when the cache is no longer in use */\n  dispose?(): Promise<any>\n}\n```\n\n## Optimizations and advanced usage\n\n### Calling the memoized function\n\nAlthough it will work, it is better to setup and export the memozied function outside of the function that uses it to avoid creating the cache key on every call since we create a hash of the function.toString() to generate a unique cache key. Hashing is normally hardware accelerated and should add less than a few fractions of a ms (less than the encryption numbers in the benchmarks and only when the function is called for the first time).\n\n```ts\n// ok but slower\nexport function useExampleFn() {\n  const exampleFn = () => 'example'\n  const memoizedFn = createCachedFunction(exampleFn)\n\n  return memoizedFn()\n}\n\n// good, especially with many memoized functions\nexport const memoizedFn = createCachedFunction(exampleFn)\n\n// good, doesn't require any function hashing\nconst memoizedFn = createCachedFunction(exampleFn, {\n  cachePrefix: '/api/todos',\n})\n```\n\n### Fine tuning the cache key\n\nThe created cache's `cacheQuery` function is an API that allows for more fine tuning of the cache key. This can be useful if the default cache key is not sufficient or additional keys are needed to use to help invalidate or scope the cache.\n\nThis also allows for different queries to update the same cache key.\n\n```ts\nimport { cacheQuery } from 'your/path/to/cache'\n\nfunction exampleGetItems() {\n  return cacheQuery({\n    queryKey: ['/items', { customerId, storeId }],\n    queryFn: async () => {\n      return fetchItems({ storeId })\n    },\n  })\n}\n```\n\nNote that a similar behaviour could be achieved to add additional keys by wrapping the the memoized function with the extra keys needed to invalidate the cache.\n\n```ts\nconst memoizedFn = createCachedFunction(({ storeId, customerId }) =>\n  exampleFn({ storeId }),\n)\n```\n\n### Bypassing the cache\n\nTo bypass the cache just call the original function directly.\n\n```ts\nconst exampleOriginalFn = async (parameter) => {\n  return `Result for ${parameter}`\n}\nconst memoizedFn = createCachedFunction(exampleOriginalFn)\nexampleOriginalFn('example') // bypasses the cache\n```\n\n## Large cache keys\n\nIf there are large payloads in the memoized function calls, these are stored as a part of the cache key. Some middleware could be utilized if this is the case to hash the key payload and store the hash as the key instead.\n\nThe encryption middlware hashes the key by default and is an option to use that for larger keys.\n\n## Dispose support\n\nThe cache supports automatic disposing of the cache with the [using](https://www.totaltypescript.com/typescript-5-2-new-keyword-using) and its stores from `typescript >= 5.2`. This is useful for cleaning up resources when the cache is no longer needed rather than calling the dispose manually.\n\n```typescript\nasync function main() {\n  // initialize stores and dispose of when done\n  await using cache = createCache({\n    stores: [store],\n  })\n\n  // we can also manually dispose of all stores if we don't have the `using` keyword available\n  await cache.dispose()\n}\n```\n\n## References\n\nThis was inspired by the apis and code [@unkey/cache](https://www.npmjs.com/package/@unkey/cache) and [react-query](https://tanstack.com/query). Laravel also has a similar [caching](https://laravel.com/docs/master/cache) api.\n\nThe primary difference to `@unkey/cache` is that this package is more focused on providing an even more simple api so that each function that is called doesn't need to generate it's own store itself and to allow per function based cache invalidation and configuration of stale and expiry times.\n\n## Benchmarks\n\nRun the `src/__tests__/benchmark.ts` script to get a rough idea of the performance of the different stores on your platform.\n\nPerforms a read write of the same key multiple times and outputs the average time taken.\n\n```\nTTL store average time: 0.000ms\nSQLite in memory store average time: 0.037ms\nMemoized encrypted TTL store average time: 0.034ms\nNon-memoized encrypted TTL store average time: 0.039ms // this is more the overhead of the encryption\nRedis store average time: 0.241ms // Redis on localhost\nSQLite disk store average time: 0.531ms // SQLite on disk\nUpstash redis from local to remote: 118.711ms // Redis on upstash over https from local -- hopefully faster from aws?\n```\n\n","readmeFilename":"README.md"}