diff --git a/index.js b/index.js index 4e9bee8..8b2b67e 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,23 @@ const { basename, dirname, extname, join, resolve } = require('node:path') const HLRU = require('hashlru') const supportedEngines = ['ejs', 'nunjucks', 'pug', 'handlebars', 'mustache', 'art-template', 'twig', 'liquid', 'dot', 'eta'] +const viewCache = Symbol('@fastify/view/cache') + +const fastifyViewCache = fp( + async function cachePlugin (fastify, opts) { + const lru = HLRU(opts?.maxCache || 100) + fastify.decorate(viewCache, lru) + }, + { + fastify: '4.x', + name: '@fastify/view/cache' + } +) + async function fastifyView (fastify, opts) { + if (fastify[viewCache] === undefined) { + await fastify.register(fastifyViewCache, opts) + } if (!opts.engine) { throw new Error('Missing engine') } @@ -19,7 +35,6 @@ async function fastifyView (fastify, opts) { const engine = opts.engine[type] const globalOptions = opts.options || {} const templatesDir = resolveTemplateDir(opts) - const lru = HLRU(opts.maxCache || 100) const includeViewExtension = opts.includeViewExtension || false const viewExt = opts.viewExt || '' const prod = typeof opts.production === 'boolean' ? opts.production : process.env.NODE_ENV === 'production' @@ -114,7 +129,7 @@ async function fastifyView (fastify, opts) { } viewDecorator.clearCache = function () { - lru.clear() + fastify[viewCache].clear() } fastify.decorate(propertyName, viewDecorator) @@ -151,7 +166,7 @@ async function fastifyView (fastify, opts) { function getPage (page, extension) { const pageLRU = `getPage-${page}-${extension}` - let result = lru.get(pageLRU) + let result = fastify[viewCache].get(pageLRU) if (typeof result === 'string') { return result @@ -160,7 +175,7 @@ async function fastifyView (fastify, opts) { const filename = basename(page, extname(page)) result = join(dirname(page), filename + getExtension(page, extension)) - lru.set(pageLRU, result) + fastify[viewCache].set(pageLRU, result) return result } @@ -202,7 +217,7 @@ async function fastifyView (fastify, opts) { if (type === 'handlebars') { data = engine.compile(data, globalOptions.compileOptions) } - lru.set(file, data) + fastify[viewCache].set(file, data) return data } @@ -217,7 +232,7 @@ async function fastifyView (fastify, opts) { isRaw = true file = file.raw } - const data = lru.get(file) + const data = fastify[viewCache].get(file) if (data && prod) { return data } @@ -231,7 +246,7 @@ async function fastifyView (fastify, opts) { // Gets partials as collection of strings from LRU cache or filesystem. const getPartials = async function (page, { partials, requestedPath }) { const cacheKey = getPartialsCacheKey(page, partials, requestedPath) - const partialsObj = lru.get(cacheKey) + const partialsObj = fastify[viewCache].get(cacheKey) if (partialsObj && prod) { return partialsObj } else { @@ -243,7 +258,7 @@ async function fastifyView (fastify, opts) { await Promise.all(partialKeys.map(async (key) => { partialsHtml[key] = await readFileSemaphore(join(templatesDir, partials[key])) })) - lru.set(cacheKey, partialsHtml) + fastify[viewCache].set(cacheKey, partialsHtml) return partialsHtml } } @@ -276,7 +291,7 @@ async function fastifyView (fastify, opts) { const compiledPage = engine.compile(html, localOptions) - lru.set(page, compiledPage) + fastify[viewCache].set(page, compiledPage) return compiledPage } @@ -326,7 +341,7 @@ async function fastifyView (fastify, opts) { // append view extension page = getPage(page, type) } - const toHtml = lru.get(page) + const toHtml = fastify[viewCache].get(page) if (toHtml && prod) { return toHtml(data) @@ -357,7 +372,7 @@ async function fastifyView (fastify, opts) { // append view extension page = getPage(page, type) } - const toHtml = lru.get(page) + const toHtml = fastify[viewCache].get(page) if (toHtml && prod) { return toHtml(data) @@ -562,8 +577,6 @@ async function fastifyView (fastify, opts) { engine.templatesSync = globalOptions.templatesSync } - lru.define = lru.set - engine.configure({ views: templatesDir, cache: prod || globalOptions.templatesSync @@ -648,3 +661,4 @@ module.exports = fp(fastifyView, { }) module.exports.default = fastifyView module.exports.fastifyView = fastifyView +module.exports.fastifyViewCache = viewCache diff --git a/package.json b/package.json index 456d2d9..4b99838 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "mustache": "^4.0.1", "nunjucks": "^3.2.1", "pino": "^8.0.0", - "proxyquire": "^2.1.3", "pug": "^3.0.0", "simple-get": "^4.0.0", "split2": "^4.0.0", diff --git a/test/test-handlebars.js b/test/test-handlebars.js index 87df07f..c49374f 100644 --- a/test/test-handlebars.js +++ b/test/test-handlebars.js @@ -6,7 +6,6 @@ const sget = require('simple-get').concat const Fastify = require('fastify') const fs = require('node:fs') const { join } = require('node:path') -const proxyquire = require('proxyquire') require('./helper').handleBarsHtmlMinifierTests(t, true) require('./helper').handleBarsHtmlMinifierTests(t, false) @@ -616,17 +615,14 @@ test('reply.view with handlebars engine with partials in production mode should t.plan(4) const fastify = Fastify() const handlebars = require('handlebars') - const POV = proxyquire('..', { - hashlru: function () { - return { - get: (key) => { - t.equal(key, 'handlebars|body:./templates/body.hbs|null-Partials') - }, - set: (key, value) => { - t.equal(key, 'handlebars|body:./templates/body.hbs|null-Partials') - t.strictSame(value, { body: fs.readFileSync('./templates/body.hbs', 'utf8') }) - } - } + const POV = require('..') + fastify.decorate(POV.fastifyViewCache, { + get: (key) => { + t.equal(key, 'handlebars|body:./templates/body.hbs|null-Partials') + }, + set: (key, value) => { + t.equal(key, 'handlebars|body:./templates/body.hbs|null-Partials') + t.strictSame(value, { body: fs.readFileSync('./templates/body.hbs', 'utf8') }) } }) @@ -921,15 +917,12 @@ test('reply.view with handlebars engine should return 500 if template fails in p t.plan(4) const fastify = Fastify() const handlebars = require('handlebars') - const POV = proxyquire('..', { - hashlru: function () { - return { - get: () => { - return () => { throw Error('Template Error') } - }, - set: () => { } - } - } + const POV = require('..') + fastify.decorate(POV.fastifyViewCache, { + get: () => { + return () => { throw Error('Template Error') } + }, + set: () => { } }) fastify.register(POV, { diff --git a/test/test-mustache.js b/test/test-mustache.js index d660072..b1925b0 100644 --- a/test/test-mustache.js +++ b/test/test-mustache.js @@ -6,7 +6,6 @@ const sget = require('simple-get').concat const Fastify = require('fastify') const fs = require('node:fs') const minifier = require('html-minifier-terser') -const proxyquire = require('proxyquire') const minifierOpts = { removeComments: true, removeCommentsFromCDATA: true, @@ -345,15 +344,13 @@ test('reply.view with mustache engine with partials in production mode should us const fastify = Fastify() const mustache = require('mustache') const data = { text: 'text' } - const POV = proxyquire('..', { - hashlru: function () { - return { - get: () => { - return '
Cached Response
' - }, - set: () => { } - } - } + const POV = require('..') + + fastify.decorate(POV.fastifyViewCache, { + get: () => { + return '
Cached Response
' + }, + set: () => { } }) fastify.register(POV, { diff --git a/test/test-pug.js b/test/test-pug.js index 484bc72..b654c2e 100644 --- a/test/test-pug.js +++ b/test/test-pug.js @@ -5,7 +5,6 @@ const test = t.test const sget = require('simple-get').concat const Fastify = require('fastify') const fs = require('node:fs') -const proxyquire = require('proxyquire') require('./helper').pugHtmlMinifierTests(t, true) require('./helper').pugHtmlMinifierTests(t, false) @@ -47,15 +46,13 @@ test('reply.view with pug engine in production mode should use cache', t => { t.plan(6) const fastify = Fastify() const pug = require('pug') - const POV = proxyquire('..', { - hashlru: function () { - return { - get: () => { - return () => '
Cached Response
' - }, - set: () => { } - } - } + const POV = require('..') + + fastify.decorate(POV.fastifyViewCache, { + get: () => { + return () => '
Cached Response
' + }, + set: () => { } }) fastify.register(POV, { diff --git a/types/index.d.ts b/types/index.d.ts index 37bddf2..a211466 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -53,6 +53,7 @@ declare namespace fastifyView { export const fastifyView: FastifyView export { fastifyView as default } + export const fastifyViewCache: Symbol } declare function fastifyView(...params: Parameters): ReturnType