{"_id":"cacheables","_rev":"18-38c12f69a445488a9f85101ace60c70d","name":"cacheables","dist-tags":{"latest":"3.0.1"},"versions":{"0.1.0":{"name":"cacheables","version":"0.1.0","keywords":["node","browser","cache","in-memory","typescript"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@0.1.0","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"3eb38f5cd6f3723c8768fd2852e8b4b954c5c290","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-0.1.0.tgz","fileCount":16,"integrity":"sha512-U4HDvGyp3a6uY3tb9YQPD4s5GqLiP85EpWxLRCr8twwGRvDlwmlWOGxMinfxQEkJh2c6vciPmP3Nntq4m5RI+g==","signatures":[{"sig":"MEYCIQCaJE/NOzPsXRqN9+rDnvBSzxeLe+PRbJusqndbtgKRwwIhAPse+H7KcNtfsfhagzGQ9csKNm4SwfafBeUSJbeXu+3n","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":20555,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg3t0dCRA9TVsSAnZWagAA81QP/2sCmcAEzsFfNXl0RMsi\n+sTkHsOLl8hNns1xNjh1NPsRoWytaf9/fUetNQf0UE/BEna89MaezrPKd4l4\nnBtGOq8nJGSn3nCbkR6k7E/I/1P3LtZ7LZm/Zeso8YHcy3Rrwq7wVbU7sDot\n/pHa+632D4EE5dJvGEYOxgT9VvlZGI2bzv+ihwQ7WZJF6T/LI2Tgq3ORzbiO\nYYSeB8rEpACyvddIzVESgmC8yWMtQLj52e8cFpLIVgeryH65VRbVWRifSbWA\nU2T+e/kLphRNIeAtXtbBBgy7VN3/a9aVMQVJguuXkhL4So4MV+ltY8lAGYHI\n3Lv3k3p8/j2bSI3MzhfcfxCnJpPXVtNGJot1xKZOe4XN69p+fm9+EEb4317h\nN7EwCc4RBfKlFxFzD4RkPcZehrsIzZ6NEgjUAwuiVYLuPPoafElDAI2Hz5LP\nGTxWHjruPlHbZpfPR6E4jhP+k3tEFG1iftPwB/xuJTByFVFy0pVEbc9yJuK+\nxiINOptN/kTsew9yK7KDBkXTIYqW7Oye13SxQn6ri7X9787XI3snFiofV18/\nHLkcrz83X9yDD0cW3frU7WR22FcFIm1FZODVvREH65qQZc2XYRQRVLnmEIbl\nxXE4BTGYIh4YFshRN0e55iBFuskT8r0xbNp25Q75EK6ZX0HeGM1qqa0Uw0hg\nBI/2\r\n=Gc35\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"03deeb8428c2878abe3ca2109167951e158b8abd","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"tsc","prepublish":"tsc"},"_npmUser":{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"_npmVersion":"7.15.1","description":"A simple in-memory cache written in Typescript with automatic cache invalidation and an elegant syntax.","directories":{},"_nodeVersion":"16.3.0","_hasShrinkwrap":false,"devDependencies":{"eslint":"^7.29.0","prettier":"^2.3.2","typescript":"^4.3.5","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0","@typescript-eslint/parser":"^4.28.1","@typescript-eslint/eslint-plugin":"^4.28.1"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_0.1.0_1625218332725_0.3292277490609963","host":"s3://npm-registry-packages"}},"0.1.1":{"name":"cacheables","version":"0.1.1","keywords":["node","browser","cache","in-memory","typescript"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@0.1.1","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"c9a36da998cb9c290b398cfe33934a19d11bf28d","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-0.1.1.tgz","fileCount":16,"integrity":"sha512-t2stzV2miaAzEZnXNBAKKJDcssk8f4Fh1l/Xm+nb10pXT17rbfZ7o2SFS49kKgqlBZA8zaxBK7bUUlcSdJT53A==","signatures":[{"sig":"MEYCIQCZlYZGFXHsTjteQkdMxFLx523Pit8ITwcKU+IreNVI6QIhAPS1Tlj5Qvb9w4DkwQl2UZjBwjoEHxBhjlQD0w9p2DNQ","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":20554,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg3t6WCRA9TVsSAnZWagAAc+sP/id1YGLmSuBHpphPf7Ch\nQGE08oWcxnYWPKudR4mb/Ed+SlISYQ8RakX1Z+HU8goxh1rSt7dWcS6q6cQ3\nM/5RHTICuhY1+XFInjKCMkgiXcYs3LiuPUyNyONcKHMXqznFzZPNmLJz/UDU\n9SyUfoHNUc5xW8irOcgOruDIKMcVW7HFAIjfNpipJ7AqUIYARGMvqks4qqq1\n0qFCrAfhBTr05Kp6gzDg9RZviQQVhn+i1ZsHw/cDKOjaVa7PRypSNbvJtNk7\nZSLQLzJKYJpQ8wb2gKBio3qzZbqmMJx3XNvoRB5KbivevaDcxyGvQ0wQCfo0\n9M2wSPnhKG5pqQUEzq+xJenwhWO+OpeFUe0z02ME5DfDdXYBLnNP8xg4uX8n\nyJPzdhwB/Vdx45utB6+Z1JdpEX22LM+Ia/zZqaQoC9ip+yy4KNIXcOcD7S2L\nBwPt/7ncONx+OZtT3HKW4R8mJ6z+Js8+Va+k+rgjjJKfzbUFopMvDVNAKyQ1\nYwEhv2ofbqPbJ6O2N0XjkJVs2nJDKACENsC0IXJggPYmZuvo30fcSvz4PSnL\nTLgWWvRNAG/KQMxZf20nl+FK6UrJplmCfk0T3bEG/tDYzs6Krxp24VSSr9ox\npjqZQTCSa+wS3X+0V1QXMJ4jRlSZGUnJMI/uQ9ZSRkrH83tYBLzHdqBwmuGL\nhAHL\r\n=wYKe\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"dceca01b84642d06951fc2c369986421ee9f0e33","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"tsc","prepublish":"tsc"},"_npmUser":{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"_npmVersion":"7.15.1","description":"A simple in-memory cache written in Typescript with automatic cache invalidation and an elegant syntax.","directories":{},"_nodeVersion":"16.3.0","_hasShrinkwrap":false,"devDependencies":{"eslint":"^7.29.0","prettier":"^2.3.2","typescript":"^4.3.5","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0","@typescript-eslint/parser":"^4.28.1","@typescript-eslint/eslint-plugin":"^4.28.1"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_0.1.1_1625218709750_0.5021256255043682","host":"s3://npm-registry-packages"}},"0.1.2":{"name":"cacheables","version":"0.1.2","keywords":["node","browser","cache","in-memory","typescript"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@0.1.2","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"d66e75f85f2c48f839c22de847b835fee9721c5a","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-0.1.2.tgz","fileCount":16,"integrity":"sha512-vTeBmwhGzpVz8wueFi6qmNHXiB2iOY+dyySbovuDDhpFX0GJlvB0cakdaLvX2szqX8DwcpmtjW58SVcr14Vzwg==","signatures":[{"sig":"MEYCIQCVdNlZNBifSIKZ5T01luNauCYZww1wQoT8QvmXMIh8RwIhAON+mUSOHwJ/iIMvoALqYTNEiTSTZosEBZbNiFVlgKz0","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":20679,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg4a6GCRA9TVsSAnZWagAAUdkP/iwRosIp2gxzZzF1vTwC\n2t0XKHsvQsZHdvvcQseoXL4PA4ZCoETcSCzQhmiYEROGIOe+9pLBvOp+blA9\nEtjrpg7IHaN71aanujvwGjN/0FqdEDbwUWEy2NkslWiTxScrDF5CXRcSKiJ5\nmmbEJy62FtTpCio73GqBPT5kr6eaofy0DvRZ5uKlOap0GqS3pme340QCcJ0z\nExj4jQb9qF5BV//Os7HeImqolDYMLlv/N195+nAIyWWhOBcbGW9tHNVYjpzd\n/xdFi+4iCAqS9RHRj6pcpO6fgJStSjRPmbpERh97sQGRQ3fxDy611c6TkW/V\nlBKIgkC7vysRQgZ9DIlshTHyqmIHoILUBPIctI6gSIE+vagkLw59fvN2tdjl\n8Q2iZfCNvO0XC21gnqegebibyapzzVZeijcl1+NgmmSvKPQeUnxwWS7lCAZn\nEdxoRKDm3Umnk2/OTOWayK4kUbRBPyz/gEeiQighncGI5JtXiXUtAO/14TQz\n7qA8bqFQgzyM8Fx+EgM+l1diYAYGse7Av793G6NQfWXYV5lUr3xsDbsFIVRU\nlr9DGXg+6SJKRfIL9qQs+03NloPWVBx0lf6ljR7zqrtzk1ARjQSO8JLGd5iA\n4uHnYGOlblYE164oeOsvKji3abqaoJOC0FyYvoIN8oJzGW3xn4HPHVPVgOap\n21c8\r\n=zqA/\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"9e4122f6135bbfd07fdc5af8c6557b80099bea38","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"tsc","prepublish":"tsc"},"_npmUser":{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"_npmVersion":"7.15.1","description":"A simple in-memory cache written in Typescript with automatic cache invalidation and an elegant syntax.","directories":{},"_nodeVersion":"16.3.0","_hasShrinkwrap":false,"devDependencies":{"eslint":"^7.29.0","prettier":"^2.3.2","typescript":"^4.3.5","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0","@typescript-eslint/parser":"^4.28.1","@typescript-eslint/eslint-plugin":"^4.28.1"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_0.1.2_1625403014286_0.31703493080534995","host":"s3://npm-registry-packages"}},"0.1.3":{"name":"cacheables","version":"0.1.3","keywords":["node","browser","cache","in-memory","typescript"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@0.1.3","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"f02bbab02a2cd580977ee75084225e20f72cd6bb","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-0.1.3.tgz","fileCount":16,"integrity":"sha512-WheE4IlNha/3w+W4sFC/Hb5n33QPWJiBflp2jlCT0SvIJra1pbG01X5kxyMyw/9nqD3lI6yu6m7txZbpJpgEsQ==","signatures":[{"sig":"MEUCIQCYHyChpdJfFiJh3jT4GyWvaZu0h1A5H5M0+1E9caVnjwIgTdDNdW/m3f5BZNdNsXCMMVBnAdwuJiQv0GpdkoyuW9s=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":21082,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg4tUCCRA9TVsSAnZWagAAB0gP/0i6i9ohuhP9+hkegSKp\n17P9NGx9rMr/l1sa2dGXVhXgjzVmmQgv43er0tPMihpiPfg/Ujy9TJYC3MuR\n6tI4M5HtP+UgmBJBlzoed3hqHotOVYHi617YSDMPqXh5FGjUjRmWJAO5tfk/\nfXLkTN+6wwYj5keoq4D2dntV8LGaYooCfjLVvCB3BC8ysXoqGh+cJelbcwth\nWqzuw8uWp5/QuJeWq0b0HBRVFR61yKROpTuniXCSrXnrkyPIwz38Yg1eaWSn\nFhJGCsFkjdNLfMInzhfirhfQCNoptc5mIMdkm1/QZ0ieJlrXbrM1RfdF6vVI\nDJsc278cTawPsdfj8HFTrlRmWH+TkYLuu/tbKIuWp7V6HM3wIy4NAC+6kVLT\nJIohw9qBdN4XcQwocr6DbJxaP/k4tJEtdVNkIxv7WOcu6tKwaHhK9zwQELlc\nUnDBwsysIricHtZX/6HIKFLMY7E6ImTwIlf0sRvb4sN44iUcG04V4ZQA6t7a\n/C4cPUL7et9TaevKQopcwCA9BHXOX9xw4PTjVoGgmE2FIktGkrZ5jUQdexzX\nr3m0z1KaDtC3DeF0PpV559cYAsWjVnsIckJ7EH6UyeBKp7EKJBtLYi4as+4U\nSpPLOPGParW/pAv4J9q2cjL01325Gw4Y9tEMY/EYJg7ec6X3QnJNSywGNPMy\nbGkd\r\n=gbaV\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"54de64df5d869eccb339a37b0f1ccea9f89abd89","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"tsc","prepublish":"tsc"},"_npmUser":{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"_npmVersion":"7.15.1","description":"A simple in-memory cache written in Typescript with automatic cache invalidation and an elegant syntax.","directories":{},"_nodeVersion":"16.3.0","_hasShrinkwrap":false,"devDependencies":{"eslint":"^7.29.0","prettier":"^2.3.2","typescript":"^4.3.5","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0","@typescript-eslint/parser":"^4.28.1","@typescript-eslint/eslint-plugin":"^4.28.1"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_0.1.3_1625478401828_0.4706792547208891","host":"s3://npm-registry-packages"}},"0.2.0":{"name":"cacheables","version":"0.2.0","keywords":["node","browser","cache","in-memory","typescript"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@0.2.0","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"d7177267153c39949894c8e96058192cb40dcf07","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-0.2.0.tgz","fileCount":19,"integrity":"sha512-QP/+L9N0CqkLj8qXHEYnRcibD8lWHqep+WUtXP1zE7DtoJR81r1vjW3ZQaZ3TpsYWniMrQIwm+vmG2XvfuKrGQ==","signatures":[{"sig":"MEYCIQDkJ1cVjCSGAVqcVC8PVr6mCYo/QUxlc4NciOfJ4QlS3QIhAPFonIQEHruyT8USYgUsgKCjrVpvkPZ7rUEIICCHUpg7","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":26410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg4wWeCRA9TVsSAnZWagAADhQP/1ou26oqKCwCBrULakQB\ngG071u9Qg1JRu68RLbg2XHLjYRuxYj9A4m7n5NrVr3ai3+6O7o6gfprDU+hC\noyoaN7aR5zXuEYqe5Bv6ndQerDSYis+cvkxDooKZjv+oGBAp2iQx7khnOo3Y\n4qg3A++vFfFXXvj/4RLyljcmPYGSvNiytNlViw59zFX4yzkFUbiSBPirX076\nBZxeqKLKcLU11XM0+QdS4WTuNDCqoMy30zO/1IJQ+pdFVHkHYHIagkWdlxL1\nj63UO/qKghggm//qbwEcDAziu3q8LLDgUzUivW1lcMlDvE+h1f1pV9Fh99Rn\n7aDLDfHKtOUuOPwWAVg7tjtE2aukLGWoeu3BFrYq8I2uPqD8iTKRguD4ueZx\nX1+u+wZv5i8llDdJk6/pfOPIBJymc2grm4wqkAq0hS4uul/t5luHa/1fXkoQ\neiAUk9opsgX1VOPD5rbMstOEYMdXzf+IR538KydJgHWWNkP/KgE/IGdi+fez\nIZevDbiqVhAnIbzMymGVB41TikCaJwbrwnjyNToEsCaTxwS72OjhPPbq1xk7\nHpOzJ2sARM7qswkjEGorYLU7gcG77o4rYxLW9Yl9i2E2VeRMMMxzf6uqzFzy\nCFECWdYwe4/HU80mxEN7zCTxkqGDfoXD1YNwM8pbelUtYkiR6dMMpOjnh8ZY\nevBh\r\n=kIpf\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"d4ed76b4b97d6af2d5fe03950b081a4063f460ed","scripts":{"test":"jest","build":"tsc","eslint":"eslint --fix src/**/*.ts","typecheck":"tsc --noEmit","prepublish":"npm run eslint && npm run typecheck && npm run build && npm test","test:watch":"jest --watch"},"_npmUser":{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"_npmVersion":"7.15.1","description":"A simple in-memory cache written in Typescript with automatic cache invalidation and an elegant syntax.","directories":{},"_nodeVersion":"16.3.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^27.0.6","eslint":"^7.29.0","ts-jest":"^27.0.3","prettier":"^2.3.2","typescript":"^4.3.5","@types/jest":"^26.0.23","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0","@typescript-eslint/parser":"^4.28.1","@typescript-eslint/eslint-plugin":"^4.28.1"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_0.2.0_1625490845616_0.8888533105276213","host":"s3://npm-registry-packages"}},"0.2.2":{"name":"cacheables","version":"0.2.2","keywords":["node","browser","cache","in-memory","typescript"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@0.2.2","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"3d6dad00a7686758cda7f88fc8b5bf273c358101","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-0.2.2.tgz","fileCount":20,"integrity":"sha512-q3+3dhX99kZYRoEZJOESIF5hBO8qyZruR7JHJYr7zdH80zZSp9cRa9bhPkzCbqfv5DJVch1H1cpehGO24sRegw==","signatures":[{"sig":"MEUCIQCwJCT9+FJ4zJknkl7dXg5LxWnTpnPl9FPQTGryxL4XcAIgF19+wvo6Cq6IOK2LgbWN2j7NJ59lGLANOmDic6uz4H4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":27347,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg4wpUCRA9TVsSAnZWagAAZf0P/1qk1SJhuitIzwwZAxjQ\nouyVzIF7BOsnv8+xdK2/cPPk9+1IX0SYtMCKwfR9New8g2Gb0xCJxBhtbJBQ\nSqkxDeCyuBeiTsjp12X7Q+GV3eIzdz4u2Vc1U9wksjlyyGT89x8e59QTSNBa\n1mXUoZEMeCcYJjQ33elYlLfz2xXJK2PF2M4Ht66bNthIebi4vqg2oCR6rE2p\nLjiTRbiazOUBEtMxloC4ZYnQEXCqQZ/2CUapIK4m2Hwj67zezcAoi+Z0ru7c\nICx1/+dwlHrE63E9Bblo/ENces1akzu+XwAZwYa1EjIdEF4eQRIM+wzKPhzs\ncUlnoOleRTqRRoKjKv0g1tGrGsnrvtXgH7HEcOGBAeAfNan4QHRiYTua4hwJ\nr4TAXJo3VfvNdEhjsdNVjvwGoneOmj+Ycgb571oiN2Es7E3aB0Nudsqt4pYu\nMsRVM6SGAjdcH/dWt09LMM5HHd2NMfErqXXP0E64YW52f3PzKqB3FoHx/aEy\nILN2hJLmiUdOXIlzvdg+Zoo0XEowxh9T/WP+Ix3XdCFJ4DREafCGVhEGb/0f\nb/V1TeUtAoO8Pr/tk/P1CGL06F+RFQgdRTKBf1JwDkLlmo0uG04FV8Kx7YMm\nYhkO+d0reTf6EijraWzhC6PhpydeGR4AQoghx6HD1mLVeqA0NFrrIB4JDGST\nCrVA\r\n=Hikk\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"f9678e04a472dfd4a39bc109ab19e3c8eaf86213","scripts":{"test":"jest","build":"tsc","eslint":"eslint --fix src/**/*.ts","typecheck":"tsc --noEmit","prepublish":"npm run eslint && npm run typecheck && npm run build && npm test","test:watch":"jest --watch"},"_npmUser":{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"_npmVersion":"6.14.13","description":"A simple in-memory cache written in Typescript with automatic cache invalidation and an elegant syntax.","directories":{},"_nodeVersion":"14.17.1","_hasShrinkwrap":false,"devDependencies":{"jest":"^27.0.6","eslint":"^7.29.0","ts-jest":"^27.0.3","prettier":"^2.3.2","typescript":"^4.3.5","@types/jest":"^26.0.23","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0","@typescript-eslint/parser":"^4.28.1","@typescript-eslint/eslint-plugin":"^4.28.1"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_0.2.2_1625492052513_0.013795663161160876","host":"s3://npm-registry-packages"}},"0.3.0":{"name":"cacheables","version":"0.3.0","keywords":["node","browser","cache","in-memory","typescript","cacheable","cacheables"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@0.3.0","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"b9bbd10f8dc2a67b2d193a06a7b3f325d9f669e3","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-0.3.0.tgz","fileCount":20,"integrity":"sha512-8Ni8vVBKaAKgvjX/A6CJk96hYqQguKA4m/IuhSOwUUSa0ulHeP3uzlz7d0O3AAlefpUb+w7Hy6QP2QDND7cR0g==","signatures":[{"sig":"MEYCIQCA6mSNnFBrvi2hRb34EeQezCVPN8TUXjlO1MLLOv8cCgIhAO9sohhA2GIXfzdqnegUbozzfdptlYTkS+/o45MPY2x/","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":30167,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg6K7eCRA9TVsSAnZWagAABSEQAI5e5e2uypRzBgvYIb1v\n7Ru5pcfNV7UA5xwV0VTzWILVP/LFmw3987o1739Kt/2JqiOlz7vWUcgupWu8\njb/EdsAwwiuno/tDM2lOaMWKCX4ejGHd4GTNRkv7JlwdnsLBi5QVRCIkOkXt\nJ9+f6DvKUgxVDZL2ZrPyWsHaahm1okaOlM6y+P7QcfxQAB9oig61PSzPbpJp\nfrK6135mIYyxHOxwEvbK9BmCBKGBP50xrP+4Lh9wNvEPte8AEh0r/2A6lxRx\nw2j74PLt1gEZ5/IsVga67BIWm5fmBddXTsGYK6VmCxqsAVxGSHLgScI3iAHC\nQiJqGcJLynbXeH/T5LHiGnhO/aYd0KX9YygtbJa8G+lQuaQr2lyTgejUbP5M\nsAk29zwHZ9fR6eDIK2ZAaODZC/35texUWHfmmxKQ/khEv9UWEesdZlZlXF43\nt8V1P/bwxI/J5pBS/D7Vsas8pVrtkAcuTZyK1wZzk+iSoTJ1ZkMMCCfr2PJS\nwwPQca+ozc9/VUtUe+Q2TT13apsgcnMh3fH2C0DvzLG2SM2BEZX3/R74AMNj\n/5sfO54zATkrf26pXgfR8cCkTyVdPhBVlDni9Y50lfItvtoNDjBYxFxdNF2z\nUPjpYUrFE6lHnffkxG0bEkffSj0s2smRcQnbf3foFeSq8jgCDXx2DtPV0sRU\nK26i\r\n=tnka\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"65cdb5966158f79de4fc18bd878af466e8d0bc37","scripts":{"test":"jest","build":"tsc","eslint":"eslint --fix src/**/*.ts","typecheck":"tsc --noEmit","prepublish":"npm run eslint && npm run typecheck && npm run build && npm test","test:watch":"jest --watch"},"_npmUser":{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"_npmVersion":"6.14.13","description":"A simple in-memory cache written in Typescript with automatic cache invalidation and an elegant syntax.","directories":{},"_nodeVersion":"14.17.1","_hasShrinkwrap":false,"devDependencies":{"jest":"^27.0.6","eslint":"^7.29.0","ts-jest":"^27.0.3","prettier":"^2.3.2","typescript":"^4.3.5","@types/jest":"^26.0.23","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0","@typescript-eslint/parser":"^4.28.1","@typescript-eslint/eslint-plugin":"^4.28.1"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_0.3.0_1625861853786_0.2666856944250964","host":"s3://npm-registry-packages"}},"0.3.1":{"name":"cacheables","version":"0.3.1","keywords":["node","browser","cache","in-memory","typescript","cacheable","cacheables"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@0.3.1","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"a752504cf577059dde20606d16ed440fafce808a","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-0.3.1.tgz","fileCount":20,"integrity":"sha512-Z/Vqf5bjkYaAoEy6VQuFgeI8aoEAJesjYwxj6LspjZ/E0us2e1Er76kdq3xHgYUZKYnq6Z1kjpTDJn82zDqUbQ==","signatures":[{"sig":"MEYCIQCxAPXXqVq67ixXqftWevK38IqehxZj5+wKM4R6rjn0uAIhAMBtWPdQfQ+7Qi9EMUFjeETEmLKps9p4rbLoRcOCgsGr","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":30330,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg6LyjCRA9TVsSAnZWagAA3vwQAICKzS2MDDY35qCN7A4j\nkL6E7nVZD5Cp9oQ/88pg5K3PoLn6oSEuS5bp++B0ZY2E+hmUCkGhM/I/mu0a\nbN8GBpUIS/XETxvvkJx1QspEEClYMLRSyIWq0DRL9jVtgaABDY9gevWoC0dE\nQM+r4UcwUMnbXzApxJH20WjpmuU3bhxK0E0dU8LoJwVAHXiEkx0jxZS0xLDK\nqE2fs4nKekqAjxB2MQQoN4aU0aenBfFBb4/CM/DYSyz6TVnc2tnJZXfnV+XG\nNVq5/RRtKEjSV6yFqpMLU1hHv1qpPS+WCDLCdVTwb2J76CedgF59vcWrF5+v\njQ+c1kOu5XSS10MmCWO3d2vhd6+VDL84AR/vLjR5WhRdyOxudm6Dx3ZGMNCI\nruZLRT2gF5/NbY4EuuSN+cvGRr2xijWbwXsWS3sUUNFMZRgsfoJnSj3ER+3I\njumwPv8uYaAyhWEDjfmV8PvuHbMolcKtJe9B/6Q9wKHOc5D7J0uhH4w2pi0/\nv73DWLj5Xj433ONQjrAIXABL9/yEphxG1xTRnrdk7zaBNlx15YOAgONtbP5o\ni7To4V7wvT+HlS9lQh7N40Y4QNlW019qRIkHFWljTJc9rmi2ZZwL8A2tigVj\nB+CzKo28erwB6TXo359aV9K/sis/UKsteUWHqRMse+5O10t9FCCp2mAHFpMi\nMFmR\r\n=yoVK\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"b5b94abf351c3f901a674ad9bbd6fea60a788a23","scripts":{"test":"jest","build":"tsc","eslint":"eslint --fix src/**/*.ts","typecheck":"tsc --noEmit","prepublish":"npm run eslint && npm run typecheck && npm run build && npm test","test:watch":"jest --watch"},"_npmUser":{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"_npmVersion":"6.14.13","description":"A simple in-memory cache written in Typescript with automatic cache invalidation and an elegant syntax.","directories":{},"_nodeVersion":"14.17.1","_hasShrinkwrap":false,"devDependencies":{"jest":"^27.0.6","eslint":"^7.29.0","ts-jest":"^27.0.3","prettier":"^2.3.2","typescript":"^4.3.5","@types/jest":"^26.0.23","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0","@typescript-eslint/parser":"^4.28.1","@typescript-eslint/eslint-plugin":"^4.28.1"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_0.3.1_1625865378596_0.703059383325364","host":"s3://npm-registry-packages"}},"0.3.2":{"name":"cacheables","version":"0.3.2","keywords":["node","browser","cache","in-memory","typescript","cacheable","cacheables"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@0.3.2","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"d71d26fc92ded706d1df9efabe860d81f7abda47","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-0.3.2.tgz","fileCount":20,"integrity":"sha512-OLYlqhMsQ9anif9UCeu7g/4nLXekN6Ho1/Ez5fWP6OpR0Z5OM/uAj8dzzfhGWNU8ekNF6WwJZU17by9CY5FC7g==","signatures":[{"sig":"MEUCIQDnvzD2OXg0tNNkiKgydti7KUt9ZZL4BCKTEdf+OmiOagIgAywvDf+UbPup5ttgQtiH4KHbX/uSMAVM1puRrQP8ufI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":30698,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg6L7rCRA9TVsSAnZWagAA6WMQAIIDQx4ThQ/hjdP3yh9+\nG/+nACEDNHkKw1UX13fcEtkxfKezjfnZzVb3hwD43Vqt2Eh1/ehHt+dCfAiY\nUZ4u4Bj6TX4V0u4l8HjsSfwLLeqCtqz6g4yl65mll5/IE1INk6CFB/GZmavT\nEVuTi+xG1vTQTAGP3BUSpK6xtPUogQljX6kEy06lA67gQJYkV85NLxhLszEO\n+vTUQ/2/7ZpzajVmP1uR+3MyV0NDUupyWB0FLxfy1HHUdUppwdD8TxdDUyTS\n05ICuoaG0TpzKt8/ybuKPsuF6fQ4iOPAdjkneguFTez58RwLMWmG50yhGugO\ncYNKq0O/BNg4Idi41+B3uV4coraz5UGvfvbLvAni9knw7uxKC0z1e1SS4SvD\nLFbFTtoa9jm6FnzTe1mpmHoGrkIoJ5T8e0nTfK7ELWkGtlNfuM1iQRef3nH2\n7Z1U/q5uaOCIm7BHTWdo3M7zwuJAuykpfh52XuJ8CrdTzyMIUFiQdApDS33P\nMa3z5wj6y/QF9fFpWegqHKtkpWzcTqUy7Lfm2ZknPykRUAqJneMJb3/lDM+i\n/EGB6WZ3oP5cZ6J+6Do2KKIK01ABHig72FMZKhXt4eIjaPGowLrAX+TavS7w\nTp9XaqmwFJLak0P3RKbPsNnnM4ko6VHG9J16j8hBEMnOTJmt1uW+xGdYrsnY\niJ8N\r\n=7wDj\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"7efa476f175743882de6232ef526b9ec39963c16","scripts":{"test":"jest","build":"tsc","eslint":"eslint --fix src/**/*.ts","typecheck":"tsc --noEmit","prepublish":"npm run eslint && npm run typecheck && npm run build && npm test","test:watch":"jest --watch"},"_npmUser":{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"_npmVersion":"6.14.13","description":"A simple in-memory cache written in Typescript with automatic cache invalidation and an elegant syntax.","directories":{},"_nodeVersion":"14.17.1","_hasShrinkwrap":false,"devDependencies":{"jest":"^27.0.6","eslint":"^7.29.0","ts-jest":"^27.0.3","prettier":"^2.3.2","typescript":"^4.3.5","@types/jest":"^26.0.23","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0","@typescript-eslint/parser":"^4.28.1","@typescript-eslint/eslint-plugin":"^4.28.1"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_0.3.2_1625865962723_0.03389776065484118","host":"s3://npm-registry-packages"}},"1.1.0":{"name":"cacheables","version":"1.1.0","keywords":["node","browser","cache","in-memory","typescript","cacheable","cacheables"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@1.1.0","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"373d6a14d717d4f671b0bdc77cd5d7ce9d9e0638","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-1.1.0.tgz","fileCount":21,"integrity":"sha512-24pb06gUN4I5XCYcIKFn0aFww+XNT1fXaBAWpjWwLtXAaeWp0pz9mamcxdZdmmEOrT7YVKd0QkmT92D07W/BlQ==","signatures":[{"sig":"MEYCIQDE7SEaiOdXQfmfz6GAkVbbHEGEKpyOWlPKwD692CymhgIhAOwOTqhL6C7gZxArJGvRzB4cURRibf5tN/xui31NZRmA","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":48579},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"aeb097672c8f479e8d2c89275ad0152a9275e4d2","scripts":{"test":"jest","build":"tsc","eslint":"eslint --fix src/**/*.ts","typecheck":"tsc --noEmit","prepublish":"npm run eslint && npm run typecheck && npm run build && npm test","test:watch":"jest --watch"},"_npmUser":{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"_npmVersion":"6.14.15","description":"A simple in-memory cache written in Typescript with automatic cache invalidation and an elegant syntax.","directories":{},"_nodeVersion":"14.18.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^27.0.6","eslint":"^7.29.0","ts-jest":"^27.0.3","prettier":"^2.3.2","typescript":"^4.3.5","@types/jest":"^26.0.23","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0","@typescript-eslint/parser":"^4.28.1","@typescript-eslint/eslint-plugin":"^4.28.1"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_1.1.0_1634296954863_0.19407083969037187","host":"s3://npm-registry-packages"}},"1.1.1":{"name":"cacheables","version":"1.1.1","keywords":["node","browser","cache","in-memory","typescript","cacheable","cacheables"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@1.1.1","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"04db312477ff2f27dabc9577b6f901470006cf1f","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-1.1.1.tgz","fileCount":21,"integrity":"sha512-zVgYS3IhlhnaIiF+L6o/GB28RFYDGLDJaTTJwCXodRwDeUhyeWyld+tbJavcbP8bP2PbNRKr3sFEuoO/YNPnJw==","signatures":[{"sig":"MEUCIQCaAlLutmkkJEi80HmeDRH0LjeB7nexgrfBGELNIVqtFwIgLNiNuKAIuN75R2HLTxON0qQ2zV4yMApKsjVSP50AWvg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":48969},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"7b55c0e91202682d431fee5e8c80c8107f53926c","scripts":{"size":"size-limit","test":"jest","build":"tsc","eslint":"eslint --fix src/**/*.ts","typecheck":"tsc --noEmit","prepublish":"npm run eslint && npm run typecheck && npm run build && npm test","test:watch":"jest --watch"},"_npmUser":{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"size-limit":[{"path":"./dist/index.js"}],"_npmVersion":"6.14.15","description":"A simple in-memory cache written in Typescript with automatic cache invalidation and an elegant syntax.","directories":{},"_nodeVersion":"14.18.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^27.0.6","eslint":"^7.29.0","ts-jest":"^27.0.3","prettier":"^2.3.2","size-limit":"^6.0.3","typescript":"^4.3.5","@types/jest":"^26.0.23","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0","@typescript-eslint/parser":"^4.28.1","@size-limit/preset-small-lib":"^6.0.3","@typescript-eslint/eslint-plugin":"^4.28.1"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_1.1.1_1634298943762_0.060981367801594244","host":"s3://npm-registry-packages"}},"1.1.2":{"name":"cacheables","version":"1.1.2","keywords":["node","browser","cache","in-memory","typescript","cacheable","cacheables"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@1.1.2","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"814143749fe57af95228f5a46381742315b3218c","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-1.1.2.tgz","fileCount":21,"integrity":"sha512-KcoZs5KmawERyWl/RcU57Q5/sKRgA0yy69RfsCXQBcttdO3YbLRLEqh8TJtolrFotucNqhGYQQFWatCPPyXeAw==","signatures":[{"sig":"MEQCIGGALjqQfGJzXQ9QLwki5NfokTNti61TYB4sMTEbdWMzAiAzLQBvS8oDuv3IjnOti4E7Ba98ZW5bGJCJ486rq/yiYA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":48976},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"f2372852baec4b6d7dcbbdbaf774495f3043007e","scripts":{"size":"size-limit","test":"jest","build":"tsc","eslint":"eslint --fix src/**/*.ts","typecheck":"tsc --noEmit","prepublish":"npm run eslint && npm run typecheck && npm run build && npm test","test:watch":"jest --watch"},"_npmUser":{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"size-limit":[{"path":"./dist/index.js"}],"_npmVersion":"6.14.15","description":"A simple in-memory cache written in Typescript with automatic cache invalidation and an elegant syntax.","directories":{},"_nodeVersion":"14.18.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^27.0.6","eslint":"^7.29.0","ts-jest":"^27.0.3","prettier":"^2.3.2","size-limit":"^6.0.3","typescript":"^4.3.5","@types/jest":"^26.0.23","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0","@typescript-eslint/parser":"^4.28.1","@size-limit/preset-small-lib":"^6.0.3","@typescript-eslint/eslint-plugin":"^4.28.1"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_1.1.2_1634381291722_0.2545555054264117","host":"s3://npm-registry-packages"}},"1.2.2":{"name":"cacheables","version":"1.2.2","keywords":["node","browser","cache","in-memory","typescript","cacheable","cacheables"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@1.2.2","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"79dc903296453b76771ddb94646acdae33207416","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-1.2.2.tgz","fileCount":21,"integrity":"sha512-OFYfH4OaycyIqGEqkOzjiYZOKEiyQqv/+K84u6Wzv8P5rUA3BJm+2s0NExe5G6XY9AMOykEZYg2RqVlv1l27HQ==","signatures":[{"sig":"MEUCIHMzVm8FlvvAH+qtaWIcZsNcVUfS3JkTeZprSa1oi7LFAiEAiwwpclOiZPmy40Cf6Gs/nOL56k+J/fi4cpLsvorll+8=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":50137,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh2lWcCRA9TVsSAnZWagAAjrAP/1SiXNXqEtWUsy/584gi\nIwWloKJDI60NTX2xkQnnfk/MbiUL96dCWvXyXseG45DSs+Zm+jtaD48CijtZ\n15pxuOzDp+j9+yNaHECuDhUaV8I3K04pEz43BrNbhrOVLIQ6xY+epO4jdfNX\nUhk/GIaPZG53lct3WI6D3QzhEZSGVBaUGWN8/POs3OxfimA6bbKsCKnySCpW\nAJNOijdQfbs4m0AUS3RQIj92AUKHu+F2lRgB5IiaXpjTv++PTfmSsD+EnIwR\njsgfpwiqCVTHC9tyoR+2AY8h60uuL7F/Nagdie1PrT+k+wehcNks1t2DADl1\nXuuRRAR3JTeluhIrTX3lcoqXtX/V5uVsR2JfgGOEj1ICynkdqiexDfSW0j3k\nQ8tJx8Nyv3Idv+ufZbGafeCGypeB1gQYWqNIosw5BNaJJiLLUE7ALu+4M6Ao\nmJhx91RpIhqSBsdU89NmcUOcBQzQraD2sB/pU5SfXXFsbT7CH+1Diwo1qRHK\nVgjZ+pJBg6I0USnTI9k2xMjxwJ2f0umeQUqdUfm4t0lEBTh8E7P8NNbhuns4\nIsuV/XFGNu13EV9XrunlLOsERaqH4HhxOpHsYxaB6SG4lCwHgxfD/4pk7Vxo\ngZNhc3Wn0si/ZBhe/fQJM09XgI40dbCUylHbjQa38GLS2K9DKClAA+7XfCvH\n3Zrl\r\n=AAxD\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"502476b695337b6af2d2338198def8af7429b3b3","scripts":{"size":"size-limit","test":"jest","build":"tsc","eslint":"eslint --fix src/**/*.ts","typecheck":"tsc --noEmit","prepublish":"npm run eslint && npm run typecheck && npm run build && npm test","test:watch":"jest --watch"},"_npmUser":{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"size-limit":[{"path":"./dist/index.js"}],"_npmVersion":"6.14.15","description":"A simple in-memory cache written in Typescript with automatic cache invalidation and an elegant syntax.","directories":{},"_nodeVersion":"14.18.1","_hasShrinkwrap":false,"devDependencies":{"jest":"^27.0.6","eslint":"^7.29.0","ts-jest":"^27.0.3","prettier":"^2.3.2","size-limit":"^6.0.3","typescript":"^4.3.5","@types/jest":"^26.0.23","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0","@typescript-eslint/parser":"^4.28.1","@size-limit/preset-small-lib":"^6.0.3","@typescript-eslint/eslint-plugin":"^4.28.1"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_1.2.2_1636627325485_0.3407300281554373","host":"s3://npm-registry-packages"}},"2.0.0":{"name":"cacheables","version":"2.0.0","keywords":["node","browser","cache","in-memory","typescript","cacheable","cacheables"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@2.0.0","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"305c7d23f1c30544d05edd9e835e39c4a62c4839","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-2.0.0.tgz","fileCount":28,"integrity":"sha512-PLxJ2og8n0mNzXiEQ8ythJI6r/IP7hiOUZz7Cqhb+IoPuVHu5st+IvagQVzT8aEggDvHp3dhoHOLypNy8c+dbA==","signatures":[{"sig":"MEUCIEuf7dGMo7LqS6WiR6idITjEVNWhs7lZJtwgi2zaJ0SrAiEAjUKzmNE+Jc762B2uSafXj7z/q2+LjFqAakEHnja81x8=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":60798},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"types":"./dist/mjs/index.d.ts","import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"a1ea3a37d5c009509673e91573f352c1039632ad","scripts":{"size":"size-limit","test":"jest","build":"rimraf dist && tsc -p tsconfig.mjs.json && tsc -p tsconfig.cjs.json && tsx ./fixup-packages.ts","eslint":"eslint --fix src/**/*.ts","typecheck":"tsc --noEmit","prepublish":"npm run eslint && npm run typecheck && npm test && npm run build","test:watch":"jest --watch"},"_npmUser":{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"size-limit":[{"path":"./dist/mjs/index.js"}],"_npmVersion":"10.5.2","description":"A simple in-memory cache written in Typescript with automatic cache invalidation and an elegant syntax.","directories":{},"_nodeVersion":"20.13.1","_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.11.2","jest":"^29.7.0","eslint":"^8.56.0","rimraf":"^5.0.7","ts-jest":"^29.1.4","prettier":"^3.3.1","size-limit":"^11.1.4","typescript":"^5.4.5","@types/jest":"^29.5.12","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.3","@typescript-eslint/parser":"^7.12.0","@size-limit/preset-small-lib":"^11.1.4","@typescript-eslint/eslint-plugin":"^7.12.0"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_2.0.0_1717582547937_0.7661885704171034","host":"s3://npm-registry-packages"}},"3.0.0":{"name":"cacheables","version":"3.0.0","keywords":["node","browser","cache","in-memory","typescript","remember","cacheables","multilayer","multi-tier","stale-while-revalidate","swr","redis","s3"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","_id":"cacheables@3.0.0","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"homepage":"https://github.com/grischaerbe/cacheables#readme","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"dist":{"shasum":"7344ba50da5e718c4518928ad0b0a733f3724f55","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-3.0.0.tgz","fileCount":9,"integrity":"sha512-GNwVpQE6KB+wGIPqvm6kA0BUJ4LtfoxJ26bqSqtyUgEgcra5L1CLZXvV/sHSqhiNkfgZBNJkFbKwyLiNcwx63w==","signatures":[{"sig":"MEQCIFM3MNvaDn4A8L0+fohkMpkYyAvPnZ+YyeaCG3oGTNvPAiBwVMaRbATnlblli5aW4fTDbEP+U9VOTaH+aEL4aynUpQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/cacheables@3.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":103296},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.cts","module":"./dist/index.mjs","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"23295a03d3bc717689244121eea15483c95842d7","scripts":{"attw":"attw --pack .","lint":"eslint src/**/*.ts","size":"size-limit","test":"vitest run","build":"tsdown","eslint":"eslint --fix src/**/*.ts","publint":"publint","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:6684519e-37cb-4ebc-bf64-ac37763cffc6"}},"repository":{"url":"git+https://github.com/grischaerbe/cacheables.git","type":"git"},"size-limit":[{"path":"./dist/index.mjs"}],"_npmVersion":"11.11.0","description":"A small, typed cache with multilayer storage buckets, five cache policies (incl. stale-while-revalidate) and concurrency-safe deduplication. Zero dependencies, browser + Node.","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.2.1","tsdown":"^0.21.10","vitest":"^4.0.10","publint":"^0.3.18","prettier":"^3.8.3","@eslint/js":"^10.0.1","size-limit":"^12.1.0","typescript":"^5.9.3","typescript-eslint":"^8.59.1","@arethetypeswrong/cli":"^0.18.2","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@size-limit/preset-small-lib":"^12.1.0"},"_npmOperationalInternal":{"tmp":"tmp/cacheables_3.0.0_1777500390251_0.9798852029556855","host":"s3://npm-registry-packages-npm-production"}},"3.0.1":{"name":"cacheables","version":"3.0.1","description":"A small, typed cache with multilayer storage buckets, five cache policies (incl. stale-while-revalidate) and concurrency-safe deduplication. Zero dependencies, browser + Node.","type":"module","main":"./dist/index.cjs","module":"./dist/index.mjs","types":"./dist/index.d.cts","engines":{"node":">=18"},"sideEffects":false,"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"size":"size-limit","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","eslint":"eslint --fix src/**/*.ts","lint":"eslint src/**/*.ts","format:check":"prettier --check .","build":"tsdown","publint":"publint","attw":"attw --pack ."},"repository":{"type":"git","url":"git+https://github.com/grischaerbe/cacheables.git"},"size-limit":[{"path":"./dist/index.mjs"}],"keywords":["node","browser","cache","in-memory","typescript","remember","cacheables","multilayer","multi-tier","stale-while-revalidate","swr","redis","s3"],"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"homepage":"https://github.com/grischaerbe/cacheables#readme","devDependencies":{"@arethetypeswrong/cli":"^0.18.2","@eslint/js":"^10.0.1","@size-limit/preset-small-lib":"^12.1.0","eslint":"^10.2.1","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","prettier":"^3.8.3","publint":"^0.3.18","size-limit":"^12.1.0","tsdown":"^0.21.10","typescript":"^5.9.3","typescript-eslint":"^8.59.1","vitest":"^4.0.10"},"gitHead":"d6be5f0ed3004fe6b9528b77b631da2132d29b7f","_id":"cacheables@3.0.1","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-+DoeJl3aoxtottqecxyGylkjzNXhPCrbFLa6RPZ7p4F2QMBCcGLuSq8u83/FqCy/TwzqfNOxLrkLddcKORJd/g==","shasum":"a88730f1eba14b15d4dd2bd599f9f561a6eeedda","tarball":"https://registry.npmjs.org/cacheables/-/cacheables-3.0.1.tgz","fileCount":9,"unpackedSize":105007,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/cacheables@3.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFzfn2GhEI8NbUBU1y/KnPkoRv8VbS0TYgETGe8hXcjZAiBw1P7DU0dVR9fXhR2LrWpJTfb/g/7VSdeqp8ReH4b2Kw=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:6684519e-37cb-4ebc-bf64-ac37763cffc6"}},"directories":{},"maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cacheables_3.0.1_1777503347960_0.09485416718240502"},"_hasShrinkwrap":false}},"time":{"created":"2021-07-02T09:32:12.725Z","modified":"2026-04-29T22:55:48.369Z","0.1.0":"2021-07-02T09:32:12.931Z","0.1.1":"2021-07-02T09:38:29.940Z","0.1.2":"2021-07-04T12:50:14.417Z","0.1.3":"2021-07-05T09:46:41.940Z","0.2.0":"2021-07-05T13:14:05.756Z","0.2.2":"2021-07-05T13:34:12.622Z","0.3.0":"2021-07-09T20:17:34.061Z","0.3.1":"2021-07-09T21:16:18.826Z","0.3.2":"2021-07-09T21:26:02.857Z","1.1.0":"2021-10-15T11:22:35.020Z","1.1.1":"2021-10-15T11:55:43.904Z","1.1.2":"2021-10-16T10:48:11.967Z","1.2.2":"2021-11-11T10:42:05.659Z","2.0.0":"2024-06-05T10:15:48.119Z","3.0.0":"2026-04-29T22:06:30.408Z","3.0.1":"2026-04-29T22:55:48.096Z"},"bugs":{"url":"https://github.com/grischaerbe/cacheables/issues"},"author":{"name":"Grischa Erbe","email":"grischa.erbe@googlemail.com"},"license":"MIT","homepage":"https://github.com/grischaerbe/cacheables#readme","keywords":["node","browser","cache","in-memory","typescript","remember","cacheables","multilayer","multi-tier","stale-while-revalidate","swr","redis","s3"],"repository":{"type":"git","url":"git+https://github.com/grischaerbe/cacheables.git"},"description":"A small, typed cache with multilayer storage buckets, five cache policies (incl. stale-while-revalidate) and concurrency-safe deduplication. Zero dependencies, browser + Node.","maintainers":[{"name":"grischaerbe","email":"grischa.erbe@googlemail.com"}],"readme":"# Cacheables\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n![Language](https://img.shields.io/github/languages/top/grischaerbe/cacheables)\n![Build](https://img.shields.io/github/actions/workflow/status/grischaerbe/cacheables/ci.yml?branch=master)\n\nA small, typed cache with composable storage buckets and a handful of cache policies, written in TypeScript.\n\n- **Wrap any async call** with `cache.remember(...)` — `remember` is both getter and setter.\n- **Multilayer storage**: stack a fast in-memory L1 with any L2 you write (filesystem, Redis, S3, …). Reads cascade L1 → Ln; on any hit, missing layers are back-filled.\n- **Five cache policies**, including `stale-while-revalidate`, with concurrency-safe deduplication where it makes sense.\n- **Fully typed**, with a generic `TView` parameter for the bucket's user-facing projection (a URL from a filesystem bucket, a presigned link from S3, …) surfaced via `cache.resolve(...)`.\n- **Required namespace prefix** so multiple instances can share a bucket without collisions.\n- Works in browser and Node.js. **No dependencies.**\n\n```ts\nimport { Cacheable, MemoryBucket } from 'cacheables'\n\nconst cache = new Cacheable('app', { buckets: [new MemoryBucket()] })\n\nconst data = await cache.remember(() => fetchData(), 'key')\n```\n\n- [Installation](#installation)\n- [Usage](#usage)\n- [API](#api)\n  - [new Cacheable(namespace, options)](#new-cacheablenamespace-options-cacheabletview)\n  - [cache.remember(resource, key)](#cacherememberresource-key-promiset)\n  - [cache.resolve(resource, key)](#cacheresolveresource-key-promisetview)\n  - [cache.delete(key) / cache.clear()](#cachedeletekey-promisevoid--cacheclear-promisevoid)\n- [Buckets](#buckets)\n- [Cache Policies](#cache-policies)\n  - [`cache-only` (default)](#cache-only-default)\n  - [`network-only`](#network-only)\n  - [`network-only-non-concurrent`](#network-only-non-concurrent)\n  - [`max-age`](#max-age)\n  - [`stale-while-revalidate`](#stale-while-revalidate)\n- [Logger](#logger)\n- [Namespacing](#namespacing)\n- [Migrating from v2 → v3](#migrating-from-v2--v3)\n- [License](#license)\n\n## Installation\n\n```bash\nnpm install cacheables\n```\n\n## Usage\n\n```ts\nimport { Cacheable, MemoryBucket } from 'cacheables'\n\nconst apiUrl = 'https://goweather.herokuapp.com/weather/Karlsruhe'\n\n// 'weather-data' is the namespace — every key is stored under `weather-data:<key>`.\n// `buckets` is the layered storage stack; the first entry is L1.\n// `policy: 'max-age'` returns the cached value while it is younger than\n// `maxAge` (in ms), and re-fetches when it has aged past that.\nconst cache = new Cacheable('weather-data', {\n  buckets: [new MemoryBucket()],\n  policy: 'max-age',\n  maxAge: 5_000,\n})\n\n// `remember` is both getter and setter: on a miss it calls the resource\n// and writes to every bucket; on a hit it returns the cached value.\nconst getWeather = () =>\n  cache.remember(() => fetch(apiUrl).then((r) => r.json()), 'karlsruhe')\n\nawait getWeather() // miss — fetched\nawait getWeather() // hit — cached\n```\n\n## API\n\n### `new Cacheable(namespace, options): Cacheable<TView>`\n\n```ts\nnew Cacheable<TView = void>(\n  namespace: string,\n  options: CacheableOptions<TView>,\n)\n\ntype CacheableOptions<TView = void> = {\n  buckets: IBucket<TView>[] // REQUIRED, L1 first\n  logger?: ILogger // default: undefined (no logging)\n} & (\n  | { policy?: 'cache-only' } // default\n  | { policy: 'network-only' }\n  | { policy: 'network-only-non-concurrent' }\n  | { policy: 'max-age'; maxAge: number }\n  | { policy: 'stale-while-revalidate'; maxAge?: number }\n)\n```\n\n`namespace` is prefixed onto every key as `${namespace}:${key}`, isolating instances that share a bucket. `buckets` must be a non-empty array (the constructor throws `Error('At least one bucket is required')` otherwise); the first bucket is L1, the rest form deeper layers.\n\n### `cache.remember(resource, key): Promise<T>`\n\nReturns the cached value if present (subject to policy); otherwise calls `resource()` and writes to every bucket.\n\n### `cache.resolve(resource, key): Promise<TView>`\n\nSame fresh-or-fetch behavior as `remember`, but returns the L1 bucket's view instead of the producer's value. Use this when the bucket produces a domain-specific projection that callers actually need — a filesystem bucket exposing a local URL after caching the bytes, a CDN bucket returning a presigned link, an IndexedDB bucket returning an `ObjectURL`:\n\n```ts\nimport { Cacheable, type IBucket, type BucketEntryMeta } from 'cacheables'\n\ninterface UrlView {\n  url: string\n}\n\nclass FilesystemBucket implements IBucket<UrlView> {\n  async read<T>(key: string): Promise<{ value: T } | undefined> {\n    /* read bytes back from disk */\n  }\n  async write<T>(key: string, value: T, meta: BucketEntryMeta): Promise<void> {\n    /* persist value to disk under a deterministic path AND store meta.storedAt */\n  }\n  async meta(key: string): Promise<BucketEntryMeta | undefined> {\n    /* read the sidecar */\n  }\n  async view(key: string): Promise<{ view: UrlView } | undefined> {\n    /* return { view: { url: pathFor(key) } } when the entry exists */\n  }\n  async delete(key: string): Promise<void> {\n    /* … */\n  }\n  async clear(): Promise<void> {\n    /* … */\n  }\n}\n\nconst cache = new Cacheable<UrlView>('images', {\n  buckets: [new FilesystemBucket()],\n})\n\nconst { url } = await cache.resolve(\n  () => fetch(imageUrl).then((r) => r.arrayBuffer()),\n  imageUrl,\n)\n```\n\n`resolve` runs a separate **view-cascade**: the engine probes `meta()` on every layer and, on an L1 hit where no other layer needs back-filling, calls `bucket.view()` directly without ever reading the value. A filesystem bucket holding a 5 MB ArrayBuffer never opens the file on the hot path — only the projection (URL) is materialized.\n\n`resolve` and `remember` share the same in-flight registry: a concurrent pair against the same key triggers `resource()` once. `resolve` honors the cache policy — a stale entry will trigger a producer call (or a background revalidation under `stale-while-revalidate`).\n\n### `cache.delete(key): Promise<void>` / `cache.clear(): Promise<void>`\n\n`delete` removes the entry from every bucket. `clear` wipes every bucket and the in-flight registry.\n\n## Buckets\n\nA bucket is a single storage tier — memory, Redis, disk, S3, anything you can read and write by key. A `Cacheable` instance holds an ordered list of buckets and cascades reads and writes across them.\n\n### `IBucket` contract\n\n```ts\ninterface BucketEntryMeta {\n  storedAt: number\n}\n\ninterface IBucket<TView = void> {\n  read<T>(key: string): Promise<{ value: T } | undefined>\n  write<T>(key: string, value: T, meta: BucketEntryMeta): Promise<void>\n  meta(key: string): Promise<BucketEntryMeta | undefined>\n  view(key: string): Promise<{ view: TView } | undefined>\n  delete(key: string): Promise<void>\n  clear(): Promise<void>\n}\n```\n\nThe engine carries only `BucketEntryMeta` (i.e. `storedAt`) between buckets. `TView` is what the bucket exposes through `cache.resolve(...)` — it never crosses bucket boundaries.\n\nRules:\n\n- `meta` MUST be cheap. The engine probes it on every layer for every read. A typical L2 keeps a sidecar (file, table, key/value entry) so probes don't hit the value blob.\n- `read` returns `undefined` for absence and `{ value }` for presence — the wrapper lets buckets store entries whose value is itself `undefined` without colliding with the absence signal.\n- `write` MUST persist `meta.storedAt` verbatim. The engine always supplies a meta; there is no synthesis branch.\n- `view` returns `undefined` for absence and `{ view }` for presence. The same wrapper pattern as `read` lets `TView = void` buckets distinguish \"entry present, no projection\" (`{ view: undefined }`) from \"entry absent\" (`undefined`). The engine treats absence after a meta-probe hit as a race and heals it by running the producer; absence after a successful cascade write is a strict-mode error and the engine throws.\n- `clear` MUST remove every entry the bucket manages.\n- Any throw from any bucket rejects the surrounding `remember()` / `resolve()` call.\n\n### Cascade behavior\n\n```ts\nconst cache = new Cacheable('app', {\n  buckets: [new MemoryBucket(), new FileSystemBucket()],\n  policy: 'max-age',\n  maxAge: 60_000,\n})\n```\n\n- **Read (`cache.remember`)**: probe `meta()` on every layer in parallel; the first layer satisfying the freshness predicate is the hit. Read its value, then back-fill every layer that is missing OR stale, using the hit layer's `storedAt` verbatim.\n- **Read (`cache.resolve`)**: probe `meta()` on every layer; on an L1 hit where no other layer needs back-filling, call `bucket.view()` directly without reading the value. When a deeper layer hits or upper layers need refilling, the value is read from the hit layer to fill the others, then L1's view is returned.\n- **Miss + `resource()`**: the engine mints a single `{ storedAt }` and writes to every layer in parallel — all layers converge on the same `storedAt`.\n- **Stale L1 + fresh L2** (under `max-age`): the freshness predicate filters per-layer, so the engine returns the fresh L2 value AND refreshes L1 with L2's value and `storedAt` verbatim.\n\n### Built-in `MemoryBucket`\n\nShips with the package; covers the common in-memory case.\n\n```ts\nimport { Cacheable, MemoryBucket } from 'cacheables'\n\nconst cache = new Cacheable('app', { buckets: [new MemoryBucket()] })\n```\n\n### Writing your own bucket\n\nImplement `IBucket`. The contract is small enough that filesystem, Redis, IndexedDB, or S3 buckets are easy to add.\n\n```ts\nimport type { IBucket, BucketEntryMeta } from 'cacheables'\n\nclass FileSystemBucket implements IBucket {\n  async read<T>(key: string): Promise<{ value: T } | undefined> {\n    /* … */\n  }\n  async write<T>(key: string, value: T, meta: BucketEntryMeta): Promise<void> {\n    /* persist the value AND meta.storedAt verbatim */\n  }\n  async meta(key: string): Promise<BucketEntryMeta | undefined> {\n    /* … */\n  }\n  async view(key: string): Promise<{ view: void } | undefined> {\n    /* no projection — return { view: undefined } if the entry exists */\n  }\n  async delete(key: string): Promise<void> {\n    /* … */\n  }\n  async clear(): Promise<void> {\n    /* … */\n  }\n}\n```\n\n### Bucket views (`TView`)\n\n`IBucket<TView>` is generic in `TView` — the projection the bucket exposes through `cache.resolve(...)`. A filesystem bucket caching remote bytes can publish the local URL it stored them at:\n\n```ts\nimport { Cacheable, type IBucket, type BucketEntryMeta } from 'cacheables'\n\ninterface UrlView {\n  url: string\n}\n\nclass FilesystemBucket implements IBucket<UrlView> {\n  async read<T>(key: string): Promise<{ value: T } | undefined> {\n    /* … */\n  }\n  async write<T>(key: string, value: T, meta: BucketEntryMeta): Promise<void> {\n    /* persist value to disk under a deterministic path */\n  }\n  async meta(key: string): Promise<BucketEntryMeta | undefined> {\n    /* read the sidecar */\n  }\n  async view(key: string): Promise<{ view: UrlView } | undefined> {\n    /* return { view: { url: pathFor(key) } } when the entry exists */\n  }\n  async delete(key: string): Promise<void> {\n    /* … */\n  }\n  async clear(): Promise<void> {\n    /* … */\n  }\n}\n\nconst cache = new Cacheable<UrlView>('images', {\n  buckets: [new FilesystemBucket()],\n})\n\nconst { url } = await cache.resolve(() => fetchBytes(remoteUrl), remoteUrl)\n```\n\nEvery bucket passed to the constructor must satisfy `IBucket<UrlView>`, enforced by the compiler. The built-in `MemoryBucket` is `IBucket<void>`, so it can't be used in a `Cacheable` with a non-`void` `TView` — write a bucket whose `view(key)` produces the projection you want.\n\n## Cache Policies\n\nThe policy is set once on the constructor and applies to every `remember()` and `resolve()` call on that instance. Two mechanics matter across policies:\n\n- **Freshness**: whether a cached value qualifies for return without re-fetching. Only `max-age` and `stale-while-revalidate` look at `storedAt`.\n- **In-flight deduplication**: when two callers ask for the same key concurrently, an instance keeps a per-key promise so only one `resource()` runs and both callers receive its result. `remember` and `resolve` share that registry — a concurrent pair against the same key triggers one `resource()` call. Dedup is policy-dependent (see each section below).\n\n| Policy                                                        | Returns cached value                 | Calls `resource()`                               | In-flight dedup |\n| ------------------------------------------------------------- | ------------------------------------ | ------------------------------------------------ | --------------- |\n| [`cache-only`](#cache-only-default) _(default)_               | Always, if present                   | Only on miss                                     | Yes             |\n| [`network-only`](#network-only)                               | Never                                | Every call                                       | No              |\n| [`network-only-non-concurrent`](#network-only-non-concurrent) | Never                                | Every call (one per concurrent burst)            | Yes             |\n| [`max-age`](#max-age)                                         | If `Date.now() - storedAt <= maxAge` | On miss or expiry                                | Yes             |\n| [`stale-while-revalidate`](#stale-while-revalidate)           | Always, if present (even stale)      | On miss, or in background when `maxAge` exceeded | Yes             |\n\n### `cache-only` _(default)_\n\nReturns any cached value, regardless of age. On miss, calls `resource()` once and writes to every bucket. Concurrent miss callers share one in-flight `resource()` call.\n\n```ts\nconst cache = new Cacheable('app', {\n  buckets: [new MemoryBucket()],\n  // policy: 'cache-only' (the default — can be omitted)\n})\n\nconst u = () => cache.remember(() => fetchUser(1), 'user:1')\n\nawait u() // miss — fetches once, writes\nawait u() // hit — returns cached value, no fetch\n\n// Concurrent miss: a single fetch is shared across both awaiters.\nawait Promise.all([u(), u()])\n```\n\nUse this policy when the data is effectively immutable for the lifetime of the cache (e.g. content addressed by hash), or when you invalidate keys yourself with `cache.delete(key)`.\n\n### `network-only`\n\nAlways calls `resource()`, always overwrites the cache. **No deduplication** — concurrent callers each fire their own `resource()`. The cache exists only to seed reads from sibling instances or to populate downstream layers.\n\n```ts\nconst cache = new Cacheable('app', {\n  buckets: [new MemoryBucket()],\n  policy: 'network-only',\n})\n\n// Both calls fetch in parallel; both writes land on the cache.\nawait Promise.all([\n  cache.remember(() => fetchUser(1), 'user:1'),\n  cache.remember(() => fetchUser(1), 'user:1'),\n])\n```\n\nUse this policy when stale data is unacceptable and concurrent calls must not be coalesced — for instance, side-effecting POSTs.\n\n### `network-only-non-concurrent`\n\nAlways calls `resource()`, always overwrites the cache, **but** concurrent callers share one in-flight request. Equivalent to `network-only` for serial calls; equivalent to `cache-only`'s dedup behavior for concurrent calls.\n\n```ts\nconst cache = new Cacheable('app', {\n  buckets: [new MemoryBucket()],\n  policy: 'network-only-non-concurrent',\n})\n\n// One fetch shared across the three concurrent awaiters; one write to the cache.\nconst [a, b, c] = await Promise.all([\n  cache.remember(() => fetchUser(1), 'user:1'),\n  cache.remember(() => fetchUser(1), 'user:1'),\n  cache.remember(() => fetchUser(1), 'user:1'),\n])\n// Subsequent calls fetch again; this policy never returns the previously cached value.\n```\n\nUse this policy when you always want fresh data but want concurrent callers to share a single fetch.\n\n### `max-age`\n\nReturns the cached value if `Date.now() - meta.storedAt <= maxAge`, otherwise calls `resource()` and overwrites the cache. Concurrent miss/expired callers share one in-flight `resource()`. The freshness predicate runs per-layer during the cascade probe, so a stale L1 with a fresh L2 yields a hit on L2 and a back-fill of L1.\n\n```ts\nconst cache = new Cacheable('app', {\n  buckets: [new MemoryBucket()],\n  policy: 'max-age',\n  maxAge: 5_000, // 5 seconds\n})\n\nawait cache.remember(() => fetchUser(1), 'user:1') // miss — fetches\nawait cache.remember(() => fetchUser(1), 'user:1') // hit (within 5s)\n\n// 6 seconds later …\nawait cache.remember(() => fetchUser(1), 'user:1') // expired — re-fetches, overwrites\n```\n\nMultilayer note: a stale L1 doesn't force a network call when L2 still has a fresh value:\n\n```ts\nconst cache = new Cacheable('app', {\n  buckets: [new MemoryBucket(/* short-lived */), new FileSystemBucket()],\n  policy: 'max-age',\n  maxAge: 60_000,\n})\n// L1 evicts after 10s but L2 still has a value with storedAt 30s ago:\n// the engine returns the L2 value and back-fills L1 with the same storedAt.\n```\n\nUse this policy when data has a known freshness window and a re-fetch past that window is acceptable.\n\n### `stale-while-revalidate`\n\nReturns the cached value immediately when it exists, **even if stale**. If `maxAge` is unset _or_ exceeded, fires a background `resource()` call to refresh — the current caller does not wait for it. With no cached value, it behaves like `network-only-non-concurrent` (caller waits, concurrent callers dedup).\n\n```ts\nconst cache = new Cacheable('app', {\n  buckets: [new MemoryBucket()],\n  policy: 'stale-while-revalidate',\n  maxAge: 5_000, // optional — without it, every read triggers a background revalidation\n})\n\nawait cache.remember(() => fetchUser(1), 'user:1') // miss — caller waits\n\n// Within 5s: pure cache hit, no revalidation.\nawait cache.remember(() => fetchUser(1), 'user:1')\n\n// After 5s: returns stale value immediately, kicks off a background fetch\n// that overwrites the cache when it resolves.\nconst stale = await cache.remember(() => fetchUser(1), 'user:1')\n```\n\nBackground revalidation errors are swallowed (the stale value has already been served). Concurrent stale reads share one revalidation.\n\nUse this policy when latency matters more than absolute freshness — e.g. dashboards where a slightly outdated reading beats a loading spinner.\n\n## Logger\n\nPass a `logger` to surface what the engine is doing. Without one, the engine is silent.\n\n```ts\ninterface ILogger {\n  log(message: string): void\n}\n```\n\nEvery `cache.remember(...)` and `cache.resolve(...)` emits one message, tagged `HIT` (with the layer that served it, e.g. `(L1)`) or `MISS` with the elapsed time. The format is `Cacheable \"${namespace}:${key}\": …` so two namespaces sharing one logger remain distinguishable:\n\n```\nCacheable \"weather-data:karlsruhe\": MISS 12ms\nCacheable \"weather-data:karlsruhe\": HIT (L1) 0.2ms\n```\n\nThe built-in `consoleLogger` forwards to `console.log`:\n\n```ts\nimport { Cacheable, consoleLogger, MemoryBucket } from 'cacheables'\n\nconst cache = new Cacheable('app', {\n  buckets: [new MemoryBucket()],\n  logger: consoleLogger,\n})\n```\n\nAny object with a `log(message: string)` method satisfies `ILogger`, so wrapping an existing logger is a one-liner:\n\n```ts\nimport pino from 'pino'\nimport { Cacheable, MemoryBucket, type ILogger } from 'cacheables'\n\nconst pinoLogger = pino()\nconst logger: ILogger = { log: (m) => pinoLogger.info(m) }\n\nconst cache = new Cacheable('app', { buckets: [new MemoryBucket()], logger })\n```\n\nThe `logger` field on a `Cacheable` instance is mutable — assign a new logger (or `undefined`) at runtime to flip logging on or off.\n\n## Namespacing\n\n`namespace` is the constructor's first positional argument and is required. Every bucket call sees keys prefixed with `${namespace}:`, so two instances can safely share a bucket:\n\n```ts\nconst bucket = new MemoryBucket()\nconst tenantA = new Cacheable('tenant-a', { buckets: [bucket] })\nconst tenantB = new Cacheable('tenant-b', { buckets: [bucket] })\n```\n\n`delete` respects the namespace; `clear()` wipes the entire underlying bucket — it has no notion of which keys belong to which namespace. Reach for `clear()` only when you mean _everything_.\n\n## Migrating from v2 → v3\n\nv2 was an in-memory cache with per-call options and a synchronous surface. v3 introduces pluggable storage (buckets), required namespacing, an instance-level cache policy, and a fully async API.\n\n```ts\n// v2\nimport { Cacheables } from 'cacheables'\n\nconst cache = new Cacheables({ log: true, logTiming: true })\n\nawait cache.cacheable(() => fetch(url), 'weather', {\n  cachePolicy: 'max-age',\n  maxAge: 5_000,\n})\n```\n\n```ts\n// v3\nimport { Cacheable, MemoryBucket, consoleLogger } from 'cacheables'\n\nconst cache = new Cacheable('weather', {\n  buckets: [new MemoryBucket()],\n  policy: 'max-age',\n  maxAge: 5_000,\n  logger: consoleLogger,\n})\n\nawait cache.remember(() => fetch(url).then((r) => r.json()), 'weather')\n```\n\nBreaking changes:\n\n- **Class renamed** `Cacheables` → `Cacheable`. Update imports and `new Cacheables(...)` call sites.\n- **`Cacheables.key(...)` removed.** The static key-joining helper is gone; build keys with template literals or `[...].join(':')`.\n- **Method renamed** `cache.cacheable(...)` → `cache.remember(...)`.\n- **Cache policy moved to the constructor.** v2 took `cachePolicy` and `maxAge` as a per-call third argument; v3 has no per-call options. Pass `policy` (and `maxAge` where required) once on `new Cacheable(namespace, { ... })`. The field is `policy`, not `cachePolicy`. A single instance now serves a single policy — split into multiple instances if you previously mixed policies on one cache.\n- **`buckets` is required** (replaces v2's implicit in-memory store). `new Cacheable()` no longer compiles. `new Cacheable('app', { buckets: [new MemoryBucket()] })` reproduces the v2 default.\n- **`namespace` is required and positional.** It's the constructor's first argument, prefixed onto every bucket key as `${namespace}:`. Pick one even if only one instance writes to the bucket.\n- **`enabled` option removed.** If you need to bypass the cache, call `resource()` directly instead of `cache.remember(...)`.\n- **`keys()` removed.** Enumerating heterogeneous async layers (some non-enumerable, like CDNs) has no single sensible semantic.\n- **`delete` and `clear` are async.** They now return `Promise<void>` — add `await`.\n- **`isCached` removed.** v3 has no public presence-check API; if you need one, query your bucket directly (e.g. `await bucket.meta(fullKey)`).\n- **`log` / `logTiming` replaced by `logger`.** Pass the exported `consoleLogger` singleton to restore the previous default-on logging, or implement `ILogger` to route messages elsewhere. Each `remember()` call emits a single formatted message (`Cacheable \"<namespace>:<key>\": HIT (L<n>)|MISS <Xms>`) instead of `console.time` / `timeEnd`.\n- **Options types reshaped.** v2's `CacheOptions` (constructor) and `CacheableOptions` (per-call) are gone. v3's only exported options type is `CacheableOptions` — same name as v2's per-call type, completely different shape (it now carries `buckets`, `policy`, and `logger`; `namespace` is the constructor's first positional argument). v2's `CacheOptions` is no longer exported.\n- **Buckets can throw.** Any throw from any bucket rejects `remember()`. v2's in-memory store couldn't fail, so this is a new error surface to be aware of once you wire up a custom bucket.\n\nWhat's new:\n\n- **Multilayer storage.** Pass several buckets to compose tiers (e.g. `[memory, filesystem]`); reads cascade L1 → Ln and back-fill missing layers on every hit.\n- **Bucket views.** `Cacheable<TView>` is generic; a bucket can publish a domain-specific projection (a local URL, a presigned link, an `ObjectURL`) via its `view()` method, returned by `cache.resolve(...)`. Plain `new Cacheable(namespace, { buckets })` defaults to `Cacheable<void>` and needs no type changes.\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n","readmeFilename":"README.md"}