import { FastifyInstance } from 'fastify'; import fp from 'fastify-plugin'; import Caching from '@fastify/caching'; declare module 'fastify' { interface FastifyContextConfig { serverCache?: { key?: string; ttl: number; }; } } export default fp(async function (fastify: FastifyInstance) { fastify.register(Caching,{ expiresIn: 10000, privacy: Caching.privacy.PUBLIC, // TODO: default is a mem cache, should use redis cache for prod, for example }) .addHook('onRoute', (routeOptions) => { const { config } = routeOptions; if (config?.serverCache) { const { key, ttl = 10000 } = config.serverCache; // set or add our handler to the route preHandler hook Object.entries({ preHandler: (request, reply, done) => { fastify.cache.get(key || encodeURIComponent(request.raw.url), (err, cached) => { if (err) { // TODO: handle error done(); return; } if (cached?.item) { console.log('from cache'); reply.send(cached.item); } else { console.log('getting fresh data'); } done(); }); return reply; }, onSend: (request, _reply, payload, done) => { fastify.cache.set(key || encodeURIComponent(request.raw.url), payload, ttl, () => {done();}); }, }).forEach(([hook, handler]) => { if (!routeOptions[hook]) { routeOptions[hook] = [handler] return } if (Array.isArray(routeOptions[hook])) { routeOptions[hook].push(handler) return } routeOptions[hook] = [routeOptions[hook], handler] }) } }) });