{"_id":"@atcute/cache","_rev":"5-020d2803e158cf53459a83bdc4d80354","name":"@atcute/cache","dist-tags":{"latest":"1.0.2"},"versions":{"0.1.0":{"name":"@atcute/cache","version":"0.1.0","license":"0BSD","_id":"@atcute/cache@0.1.0","maintainers":[{"name":"externdefs","email":"hi@mary.my.id"}],"homepage":"https://github.com/mary-ext/atcute#readme","bugs":{"url":"https://github.com/mary-ext/atcute/issues"},"dist":{"shasum":"5b116ca6c8e8439f0093d369e25dfcacd9221494","tarball":"https://registry.npmjs.org/@atcute/cache/-/cache-0.1.0.tgz","fileCount":28,"integrity":"sha512-19hgc5H7lyQtbVza4xyGjTpXgEgI7a2G+N0NEKj61sEDGZyeLBW4zyiAk5pkQi92zH0bAqFt77CBEqIOdT0T9A==","signatures":[{"sig":"MEUCIQDMv9B/dTvg5I0x7iAZUa2XsuFE3dEpUaWhg7yoRhPSiAIgdWxxb8YqLPg3Kg3qkiSh4oVV2VCjVG5E+OqmiHKnS1Y=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":68472},"type":"module","_from":"file:atcute-cache-0.1.0.tgz","exports":{".":"./dist/index.js"},"scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","prepublish":"rm -rf dist; pnpm run build"},"_npmUser":{"name":"externdefs","email":"hi@mary.my.id"},"_resolved":"/tmp/51ff645d52fb851f0ad4d46552790298/atcute-cache-0.1.0.tgz","_integrity":"sha512-19hgc5H7lyQtbVza4xyGjTpXgEgI7a2G+N0NEKj61sEDGZyeLBW4zyiAk5pkQi92zH0bAqFt77CBEqIOdT0T9A==","repository":{"url":"git+https://github.com/mary-ext/atcute.git","directory":"packages/clients/cache"},"_npmVersion":"10.9.4","description":"normalized cache store for AT Protocol clients","directories":{},"_nodeVersion":"22.21.1","dependencies":{"@atcute/lexicons":"^1.2.5"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.14","@atcute/bluesky":"^3.2.12"},"_npmOperationalInternal":{"tmp":"tmp/cache_0.1.0_1765089972090_0.48244535858381","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@atcute/cache","version":"0.1.1","license":"0BSD","_id":"@atcute/cache@0.1.1","maintainers":[{"name":"externdefs","email":"hi@mary.my.id"}],"dist":{"shasum":"0d3687585dcd675253c48f982035a80a5cb790aa","tarball":"https://registry.npmjs.org/@atcute/cache/-/cache-0.1.1.tgz","fileCount":28,"integrity":"sha512-FJe6IRhZdmmHn815/eOT9YuxgwZO8DPoCZr2wlw3QaSgDveklk3bsjli29zEdMhqp64M3XD5iXRiCLvzY7kFDg==","signatures":[{"sig":"MEYCIQC+FrV9Apx9Ykk/JmiKwlKYDXqmah9YF+DBsAMPjEdyKgIhAMCjiqYx5C0J7TPW+nRMAritfvLH1wdOqu9a3+Qjo6zF","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":68147},"type":"module","exports":{".":"./dist/index.js"},"scripts":{"test":"vitest run","build":"tsgo","prepublish":"rm -rf dist; pnpm run build"},"_npmUser":{"name":"externdefs","email":"hi@mary.my.id"},"repository":{"url":"https://github.com/mary-ext/atcute","directory":"packages/clients/cache"},"description":"normalized cache store for AT Protocol clients","directories":{},"_nodeVersion":"26.0.0","dependencies":{"@atcute/lexicons":"^1.3.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.5","@atcute/bluesky":"^3.3.4"},"peerDependencies":{"@atcute/lexicons":"^1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cache_0.1.1_1778205612877_0.7108510574145015","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@atcute/cache","version":"1.0.0","license":"0BSD","_id":"@atcute/cache@1.0.0","maintainers":[{"name":"externdefs","email":"hi@mary.my.id"}],"dist":{"shasum":"c61dc03681bd39a757854e9a5323dfc19fbf735b","tarball":"https://registry.npmjs.org/@atcute/cache/-/cache-1.0.0.tgz","fileCount":28,"integrity":"sha512-Aw8yFmnta0icuCJEU4Pcx15muBkY51Qf4zwFqWMBXH9DO6OcVZZeOdT3HgiLMG1ULSpNycAOFh9AMy013+FYqQ==","signatures":[{"sig":"MEUCIEwHSyN2RxppsAyhlLpFUF0FQwZoeVM1mquKLNzWfx/UAiEA+hqbLVt5DylZUyZyElAjo5m06+2j2FMVRiLMO1O2shU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":68147},"type":"module","exports":{".":"./dist/index.js"},"scripts":{"test":"vitest run","build":"tsgo","prepublish":"rm -rf dist; pnpm run build"},"_npmUser":{"name":"externdefs","email":"hi@mary.my.id"},"repository":{"url":"https://github.com/mary-ext/atcute","directory":"packages/clients/cache"},"description":"normalized cache store for AT Protocol clients","directories":{},"_nodeVersion":"26.0.0","dependencies":{"@atcute/lexicons":"^2.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.5","@atcute/bluesky":"^4.0.0"},"peerDependencies":{"@atcute/lexicons":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cache_1.0.0_1778312806996_0.11743037994299699","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@atcute/cache","version":"1.0.1","license":"0BSD","_id":"@atcute/cache@1.0.1","maintainers":[{"name":"externdefs","email":"hi@mary.my.id"}],"dist":{"shasum":"8aecbed50c55a0a64ecfd64b76deadc4b5aa5ab8","tarball":"https://registry.npmjs.org/@atcute/cache/-/cache-1.0.1.tgz","fileCount":13,"integrity":"sha512-emaHvd/HFbVA7t6AWkqjkWpkQUWE/rWqqc5T7gi9bgWIM9oo6yxYfR1o06tfWQKOdHzFHHz4xbyd0rwh1Kze0Q==","signatures":[{"sig":"MEUCIQDjbk+NoNTD8SQi72XnXIVKdiiZxH4DeCgdcf0TEVbGFQIgcYZO/pvQ7hLQwpbyyEL8rb+8ZCAOBumgGGvVPErKSrs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":28770},"type":"module","exports":{".":"./dist/index.js"},"scripts":{"test":"vitest run","build":"tsgo","prepublish":"rm -rf dist; pnpm run build"},"_npmUser":{"name":"externdefs","email":"hi@mary.my.id"},"repository":{"url":"https://github.com/mary-ext/atcute","directory":"packages/clients/cache"},"description":"normalized cache store for AT Protocol clients","directories":{},"_nodeVersion":"26.0.0","dependencies":{"@atcute/lexicons":"^2.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.9","@atcute/bluesky":"^4.0.12"},"peerDependencies":{"@atcute/lexicons":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cache_1.0.1_1782777131998_0.9145126692135503","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@atcute/cache","version":"1.0.2","description":"normalized cache store for AT Protocol clients","license":"0BSD","repository":{"url":"https://github.com/mary-ext/atcute","directory":"packages/clients/cache"},"type":"module","exports":{".":"./dist/index.js"},"publishConfig":{"access":"public"},"dependencies":{"@atcute/lexicons":"^2.0.3"},"devDependencies":{"vitest":"^4.1.10","@atcute/bluesky":"^4.0.14"},"peerDependencies":{"@atcute/lexicons":"^2.0.0"},"scripts":{"build":"tsc","test":"vitest run","prepublish":"rm -rf dist; pnpm run build"},"_nodeVersion":"26.0.0","_id":"@atcute/cache@1.0.2","dist":{"integrity":"sha512-mES4hlmK3WIisSIJ0ne1J3VINJ/lqnt2QtB16yyvwAXqcpP2AWLI69lEgzlALIjWUAq+IGHEI8J9BZyP0y5nhA==","shasum":"f3971ed045e99fd4e28217131e69ec2537764965","tarball":"https://registry.npmjs.org/@atcute/cache/-/cache-1.0.2.tgz","fileCount":13,"unpackedSize":28809,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHGXpmsHVYCeUvsoz7Gbvgg2308FBriziihOFYtosGJKAiEA7MQxuFR+GscniINbY5S5jEXijNNMVyw/cQeQYvNDER4="}]},"_npmUser":{"name":"externdefs","email":"hi@mary.my.id"},"directories":{},"maintainers":[{"name":"externdefs","email":"hi@mary.my.id"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cache_1.0.2_1784160619820_0.2356410030620124"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-07T06:46:11.989Z","modified":"2026-07-16T00:10:20.163Z","0.1.0":"2025-12-07T06:46:12.234Z","0.1.1":"2026-05-08T02:00:13.019Z","1.0.0":"2026-05-09T07:46:47.133Z","1.0.1":"2026-06-29T23:52:12.140Z","1.0.2":"2026-07-16T00:10:19.989Z"},"license":"0BSD","repository":{"url":"https://github.com/mary-ext/atcute","directory":"packages/clients/cache"},"description":"normalized cache store for AT Protocol clients","maintainers":[{"name":"externdefs","email":"hi@mary.my.id"}],"readme":"# @atcute/cache\n\n> [!WARNING] experimental package - API may change\n\nnormalized cache store for AT Protocol.\n\n```sh\nnpm install @atcute/cache\n```\n\nstores entities by their unique keys and automatically deduplicates nested references. when an\nentity appears in multiple API responses (e.g., a profile in a post author and in followers), they\nshare the same object reference in memory.\n\n## usage\n\n### setting up the cache\n\n```ts\nimport { NormalizedCache } from '@atcute/cache';\nimport { AppBskyActorDefs, AppBskyFeedDefs } from '@atcute/bluesky';\n\nconst cache = new NormalizedCache();\n\n// register entity types with key extractors\ncache.define({\n\tschema: AppBskyFeedDefs.postViewSchema,\n\tkey: (post) => post.uri,\n});\n\ncache.define({\n\tschema: AppBskyActorDefs.profileViewBasicSchema,\n\tkey: (profile) => profile.did,\n});\n```\n\n### normalizing API responses\n\n```ts\nimport { AppBskyFeedGetTimeline } from '@atcute/bluesky';\n\nconst response = await rpc.get('app.bsky.feed.getTimeline', { params: {} });\n\n// walks the response, extracts entities, and stores them\nconst timeline = cache.normalize(AppBskyFeedGetTimeline.mainSchema.output.schema, response.data);\n```\n\n### reading from cache\n\n```ts\nconst post = cache.get(AppBskyFeedDefs.postViewSchema, 'at://did:plc:.../app.bsky.feed.post/...');\nconst profile = cache.get(AppBskyActorDefs.profileViewBasicSchema, 'did:plc:...');\n\n// check if entity exists\nif (cache.has(AppBskyFeedDefs.postViewSchema, postUri)) {\n\t// ...\n}\n\n// get all cached entities of a type\nconst allPosts = cache.getAll(AppBskyFeedDefs.postViewSchema);\n```\n\n### optimistic updates\n\n```ts\n// update a post's like count immediately, before the API responds\ncache.update(AppBskyFeedDefs.postViewSchema, postUri, (post) => ({\n\t...post,\n\tviewer: { ...post.viewer, like: tempLikeUri },\n\tlikeCount: (post.likeCount ?? 0) + 1,\n}));\n```\n\n### subscribing to changes\n\n```ts\n// subscribe to a specific entity\nconst unsubscribe = cache.subscribe(AppBskyFeedDefs.postViewSchema, postUri, (post) => {\n\tconsole.log('post changed:', post);\n});\n\n// subscribe to all entities of a type\nconst unsubscribeType = cache.subscribeType(\n\tAppBskyActorDefs.profileViewBasicSchema,\n\t(key, profile) => {\n\t\tconsole.log(`profile ${key} changed:`, profile);\n\t},\n);\n\n// clean up when done\nunsubscribe();\nunsubscribeType();\n```\n\n### custom merge logic\n\n```ts\ncache.define({\n\tschema: AppBskyActorDefs.profileViewBasicSchema,\n\tkey: (profile) => profile.did,\n\t// custom merge: prefer existing avatar if new one is missing\n\tmerge: (existing, incoming) => ({\n\t\t...incoming,\n\t\tavatar: incoming.avatar ?? existing.avatar,\n\t}),\n});\n```\n","readmeFilename":""}