Skip to content

Commit

Permalink
feat: viewAsync reply decorator
Browse files Browse the repository at this point in the history
Closes #394
Closes #412
  • Loading branch information
mweberxyz committed Mar 22, 2024
1 parent 2fa7ee8 commit e8e6dbe
Show file tree
Hide file tree
Showing 8 changed files with 600 additions and 160 deletions.
327 changes: 187 additions & 140 deletions README.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions benchmark/fastify-ejs-view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use strict'

require('./setup.js')({
engine: { ejs: require('ejs') },
route: (req, reply) => { reply.view('index.ejs', { text: 'text' }) }
})
2 changes: 1 addition & 1 deletion benchmark/fastify.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

require('./setup.js')({
engine: { ejs: require('ejs') },
route: (req, reply) => { reply.view('index.ejs', { text: 'text' }) }
route: (req, reply) => { return reply.viewAsync('index.ejs', { text: 'text' }) }
})
49 changes: 30 additions & 19 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ async function fastifyView (fastify, opts) {
}
const charset = opts.charset || 'utf-8'
const propertyName = opts.propertyName || 'view'
const asyncPropertyName = opts.asyncPropertyName || `${propertyName}Async`
const engine = opts.engine[type]
const globalOptions = opts.options || {}
const templatesDir = resolveTemplateDir(opts)
Expand Down Expand Up @@ -106,6 +107,28 @@ async function fastifyView (fastify, opts) {

const renderer = renders[type] ? renders[type] : renders._default

async function asyncRender (page) {
if (!page) {
throw new Error('Missing page')
}

let result = await renderer.apply(this, arguments)

if (minify && !isPathExcludedMinification(this)) {
result = await minify(result, globalOptions.htmlMinifierOptions)
}

if (!this.getHeader('Content-Type')) {
this.header('Content-Type', 'text/html; charset=' + charset)
}

return result
}

const fakeRequest = {
getHeader: () => true
}

function viewDecorator (page) {
const args = Array.from(arguments)

Expand All @@ -114,11 +137,7 @@ async function fastifyView (fastify, opts) {
done = args.pop()
}

let promise = !page ? Promise.reject(new Error('Missing page')) : renderer.apply(this, args)

if (minify) {
promise = promise.then((result) => minify(result, globalOptions.htmlMinifierOptions))
}
const promise = asyncRender.apply(fakeRequest, args)

if (typeof done === 'function') {
promise.then(done.bind(null, null), done)
Expand All @@ -134,27 +153,19 @@ async function fastifyView (fastify, opts) {

fastify.decorate(propertyName, viewDecorator)

fastify.decorateReply(propertyName, async function (page) {
if (!page) {
this.send(new Error('Missing page'))
}
fastify.decorateReply(propertyName, async function (page, data, opts) {
try {
const result = await renderer.apply(this, arguments)
if (!this.getHeader('Content-Type')) {
this.header('Content-Type', 'text/html; charset=' + charset)
}

if (minify && !isPathExcludedMinification(this)) {
this.send(await minify(result, globalOptions.htmlMinifierOptions))
} else {
this.send(result)
}
const html = await asyncRender.call(this, page, data, opts)
this.send(html)
} catch (err) {
this.send(err)
}

return this
})

fastify.decorateReply(asyncPropertyName, asyncRender)

if (!fastify.hasReplyDecorator('locals')) {
fastify.decorateReply('locals', null)

Expand Down
68 changes: 68 additions & 0 deletions test/test-ejs-async.js
Original file line number Diff line number Diff line change
Expand Up @@ -506,3 +506,71 @@ test('reply.view with promise error', t => {
})
})
})

test('reply.viewAsync with ejs engine and async: true (global option)', t => {
t.plan(6)
const fastify = Fastify()
const ejs = require('ejs')

fastify.register(require('../index'), {
engine: { ejs },
options: { async: true },
templates: 'templates'
})

fastify.get('/', async (req, reply) => {
return reply.viewAsync('ejs-async.ejs')
})

fastify.listen({ port: 0 }, err => {
t.error(err)

sget({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port
}, async (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.equal(response.headers['content-length'], '' + body.length)
t.equal(response.headers['content-type'], 'text/html; charset=utf-8')
t.equal(await ejs.render(fs.readFileSync('./templates/ejs-async.ejs', 'utf8'), {}, { async: true }), body.toString())
fastify.close()
})
})
})

test('reply.viewAsync with ejs engine, async: true (global option), and html-minifier-terser', t => {
t.plan(6)
const fastify = Fastify()
const ejs = require('ejs')

fastify.register(require('../index'), {
engine: { ejs },
options: {
async: true,
useHtmlMinifier: minifier,
htmlMinifierOptions: minifierOpts
},
templates: 'templates'
})

fastify.get('/', (req, reply) => {
return reply.viewAsync('ejs-async.ejs')
})

fastify.listen({ port: 0 }, err => {
t.error(err)

sget({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port
}, async (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.equal(response.headers['content-length'], '' + body.length)
t.equal(response.headers['content-type'], 'text/html; charset=utf-8')
t.equal(await minifier.minify(await ejs.render(fs.readFileSync('./templates/ejs-async.ejs', 'utf8'), {}, { async: true }), minifierOpts), body.toString())
fastify.close()
})
})
})
Loading

0 comments on commit e8e6dbe

Please sign in to comment.