From a802a8fb09a1dc5939a898bb8e8fc834464e306e Mon Sep 17 00:00:00 2001 From: Jean <110341611+jean-michelet@users.noreply.github.com> Date: Wed, 12 Jun 2024 12:29:53 +0200 Subject: [PATCH] Allow `autoConfig` with callback (#381) * feat: handle autoConfig callbacks * docs: document new option type * test: test prefix behavior documented in doc * fix: merge pluginConfig callback result with overrideConfig * fix: prioritize overridden prefix --- README.md | 18 ++++++++++++++++- index.js | 12 ++++++++++- test/commonjs/basic.js | 20 ++++++++++++++++++- test/commonjs/basic/foo/configPrefix.js | 13 ++++++++++++ .../basic/foo/configPrefixCallback.js | 14 +++++++++++++ test/commonjs/options.js | 12 ++++++++++- test/commonjs/options/plugins/plugin-e.js | 17 ++++++++++++++++ test/module/basic.js | 20 ++++++++++++++++++- test/module/basic/foo/configPrefix.js | 13 ++++++++++++ test/module/basic/foo/configPrefixCallback.js | 12 +++++++++++ test/module/options.js | 12 ++++++++++- test/module/options/plugins/plugin-e.js | 14 +++++++++++++ 12 files changed, 171 insertions(+), 6 deletions(-) create mode 100644 test/commonjs/basic/foo/configPrefix.js create mode 100644 test/commonjs/basic/foo/configPrefixCallback.js create mode 100644 test/commonjs/options/plugins/plugin-e.js create mode 100644 test/module/basic/foo/configPrefix.js create mode 100644 test/module/basic/foo/configPrefixCallback.js create mode 100644 test/module/options/plugins/plugin-e.js diff --git a/README.md b/README.md index 7318f6f5..dbe7b2f2 100644 --- a/README.md +++ b/README.md @@ -308,7 +308,7 @@ FASTIFY_AUTOLOAD_TYPESCRIPT=1 node --loader=my-custom-loader index.ts Each plugin can be individually configured using the following module properties: -- `plugin.autoConfig` - Configuration object which will be used as `opts` parameter +- `plugin.autoConfig` - Specifies the options to be used as the `opts` parameter. ```js module.exports = function (fastify, opts, next) { @@ -332,6 +332,22 @@ Each plugin can be individually configured using the following module properties export const autoConfig = { name: 'y' } ``` + You can also use a callback function if you need to access the parent instance: + ```js + export const autoConfig = (fastify) => { + return { name: 'y ' + fastify.rootName } + } + ``` + + However, note that the `prefix` option should be set directly on `autoConfig` for autoloading to work as expected: + ```js + export const autoConfig = (fastify) => { + return { name: 'y ' + fastify.rootName } + } + + autoConfig.prefix = '/hello' + ``` + - `plugin.autoPrefix` - Set routing prefix for plugin ```js diff --git a/index.js b/index.js index d3c42928..47cfee7e 100644 --- a/index.js +++ b/index.js @@ -282,7 +282,17 @@ async function loadPlugin ({ file, type, directoryPrefix, options, log }) { const plugin = wrapRoutes(content.default || content) const pluginConfig = (content.default && content.default.autoConfig) || content.autoConfig || {} - const pluginOptions = Object.assign({}, pluginConfig, overrideConfig) + let pluginOptions + if (typeof pluginConfig === 'function') { + pluginOptions = function (fastify) { + return { ...pluginConfig(fastify), ...overrideConfig } + } + + pluginOptions.prefix = overrideConfig.prefix ?? pluginConfig.prefix + } else { + pluginOptions = { ...pluginConfig, ...overrideConfig } + } + const pluginMeta = plugin[Symbol.for('plugin-meta')] || {} if (!encapsulate) { diff --git a/test/commonjs/basic.js b/test/commonjs/basic.js index 9ba5aec1..88186da3 100644 --- a/test/commonjs/basic.js +++ b/test/commonjs/basic.js @@ -3,7 +3,7 @@ const t = require('tap') const Fastify = require('fastify') -t.plan(101) +t.plan(107) const app = Fastify() @@ -270,4 +270,22 @@ app.ready(function (err) { t.equal(res.statusCode, 200) t.same(JSON.parse(res.payload), { works: true }) }) + + app.inject({ + url: '/configPrefix' + }, function (err, res) { + t.error(err) + + t.equal(res.statusCode, 200) + t.same(JSON.parse(res.payload), { configPrefix: true }) + }) + + app.inject({ + url: '/configPrefixCallback' + }, function (err, res) { + t.error(err) + + t.equal(res.statusCode, 200) + t.same(JSON.parse(res.payload), { configPrefixCallback: true }) + }) }) diff --git a/test/commonjs/basic/foo/configPrefix.js b/test/commonjs/basic/foo/configPrefix.js new file mode 100644 index 00000000..fc2232b2 --- /dev/null +++ b/test/commonjs/basic/foo/configPrefix.js @@ -0,0 +1,13 @@ +'use strict' + +module.exports = function (f, opts, next) { + f.get('/', (request, reply) => { + reply.send({ configPrefix: true }) + }) + + next() +} + +module.exports.autoConfig = { + prefix: '/configPrefix' +} diff --git a/test/commonjs/basic/foo/configPrefixCallback.js b/test/commonjs/basic/foo/configPrefixCallback.js new file mode 100644 index 00000000..f20ba70c --- /dev/null +++ b/test/commonjs/basic/foo/configPrefixCallback.js @@ -0,0 +1,14 @@ +'use strict' + +module.exports = function (f, opts, next) { + f.get('/', (request, reply) => { + reply.send({ configPrefixCallback: true }) + }) + + next() +} + +const options = () => ({}) +options.prefix = '/configPrefixCallback' + +module.exports.autoConfig = options diff --git a/test/commonjs/options.js b/test/commonjs/options.js index 1198db41..ea8a574d 100644 --- a/test/commonjs/options.js +++ b/test/commonjs/options.js @@ -3,10 +3,12 @@ const t = require('tap') const Fastify = require('fastify') -t.plan(19) +t.plan(22) const app = Fastify() +app.decorate('root', 'root') + app.register(require('./options/app')) app.ready(function (err) { @@ -53,6 +55,14 @@ app.ready(function (err) { t.same(JSON.parse(res.payload), { data: 'test-3' }) }) + app.inject({ + url: '/plugin-e' + }, function (err, res) { + t.error(err) + t.equal(res.statusCode, 200) + t.same(JSON.parse(res.payload), { data: 'test-4-root' }) + }) + app.inject({ url: '/plugin-y' }, function (err, res) { diff --git a/test/commonjs/options/plugins/plugin-e.js b/test/commonjs/options/plugins/plugin-e.js new file mode 100644 index 00000000..b771e66c --- /dev/null +++ b/test/commonjs/options/plugins/plugin-e.js @@ -0,0 +1,17 @@ +'use strict' + +const fp = require('fastify-plugin') + +function plugin (f, opts, next) { + f.get('/plugin-e', (request, reply) => { + reply.send({ data: opts.e }) + }) + + next() +} + +plugin.autoConfig = (fastify) => { + return { e: 'test-4-' + fastify.root } +} + +exports.default = fp(plugin, { name: 'plugin-e' }) diff --git a/test/module/basic.js b/test/module/basic.js index 1e55ad6c..9aa91e77 100644 --- a/test/module/basic.js +++ b/test/module/basic.js @@ -2,7 +2,7 @@ import t from 'tap' import fastify from 'fastify' import basicApp from './basic/app.js' -t.plan(74) +t.plan(80) const app = fastify() @@ -227,4 +227,22 @@ app.ready(function (err) { statusCode: 404 }) }) + + app.inject({ + url: '/configPrefix' + }, function (err, res) { + t.error(err) + + t.equal(res.statusCode, 200) + t.same(JSON.parse(res.payload), { configPrefix: true }) + }) + + app.inject({ + url: '/configPrefixCallback' + }, function (err, res) { + t.error(err) + + t.equal(res.statusCode, 200) + t.same(JSON.parse(res.payload), { configPrefixCallback: true }) + }) }) diff --git a/test/module/basic/foo/configPrefix.js b/test/module/basic/foo/configPrefix.js new file mode 100644 index 00000000..faf0e526 --- /dev/null +++ b/test/module/basic/foo/configPrefix.js @@ -0,0 +1,13 @@ +'use strict' + +export default function (f, opts, next) { + f.get('/', (request, reply) => { + reply.send({ configPrefix: true }) + }) + + next() +} + +export const autoConfig = { + prefix: '/configPrefix' +} diff --git a/test/module/basic/foo/configPrefixCallback.js b/test/module/basic/foo/configPrefixCallback.js new file mode 100644 index 00000000..7b3f595e --- /dev/null +++ b/test/module/basic/foo/configPrefixCallback.js @@ -0,0 +1,12 @@ +'use strict' + +export default function (f, opts, next) { + f.get('/', (request, reply) => { + reply.send({ configPrefixCallback: true }) + }) + + next() +} + +export const autoConfig = () => ({}) +autoConfig.prefix = '/configPrefixCallback' diff --git a/test/module/options.js b/test/module/options.js index 9c24e860..7dcf5a57 100644 --- a/test/module/options.js +++ b/test/module/options.js @@ -2,10 +2,12 @@ import t from 'tap' import fastify from 'fastify' import optionsApp from './options/app.js' -t.plan(19) +t.plan(22) const app = fastify() +app.decorate('root', 'root') + app.register(optionsApp) app.ready(function (err) { @@ -52,6 +54,14 @@ app.ready(function (err) { t.same(JSON.parse(res.payload), { data: 'test-3' }) }) + app.inject({ + url: '/plugin-e' + }, function (err, res) { + t.error(err) + t.equal(res.statusCode, 200) + t.same(JSON.parse(res.payload), { data: 'test-4-root' }) + }) + app.inject({ url: '/plugin-y' }, function (err, res) { diff --git a/test/module/options/plugins/plugin-e.js b/test/module/options/plugins/plugin-e.js new file mode 100644 index 00000000..f9b67be5 --- /dev/null +++ b/test/module/options/plugins/plugin-e.js @@ -0,0 +1,14 @@ +import fp from 'fastify-plugin' + +function plugin (f, opts, next) { + f.get('/plugin-e', (request, reply) => { + reply.send({ data: opts.e }) + }) + + next() +} + +export default fp(plugin, { name: 'plugin-e' }) +export const autoConfig = (fastify) => { + return { e: 'test-4-' + fastify.root } +}