diff --git a/README.md b/README.md index de501881..2f4a0e82 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,40 @@ fastify.register(autoLoad, { }) ``` +### `appendAutoPrefix` (optional) - Default: `false` + +Controls how `autoPrefix` from a plugin file is combined with the directory-derived prefix. + +- `false` (default): `autoPrefix` replaces the directory-derived prefix for that plugin. +- `true`: the directory-derived prefix is kept, and `autoPrefix` is appended after it. + +Example directory: + +```text +routes/ + children/ + new-routes.js // exports autoPrefix = '/batch' +``` + +With default behavior (`appendAutoPrefix: false`), the route is loaded as: + +```text +/your-parent-prefix/batch/entity +``` + +With `appendAutoPrefix: true`, the route is loaded as: + +```text +/your-parent-prefix/children/batch/entity +``` + +```js +fastify.register(autoLoad, { + dir: path.join(__dirname, 'routes'), + appendAutoPrefix: true +}) +``` + ### `matchFilter` (optional) Filter matching any path that should be loaded. Can be a RegExp, a string, or a function returning a boolean. @@ -225,6 +259,8 @@ Any option specified here will override `plugin.autoConfig` options specified in When setting both `options.prefix` and `plugin.autoPrefix` they will be concatenated. +By default, `plugin.autoPrefix` replaces directory-derived prefixes. Set `appendAutoPrefix: true` to keep directory prefixes and append `plugin.autoPrefix` after them. + ```js // index.js fastify.register(autoLoad, { @@ -409,6 +445,8 @@ autoConfig.prefix = '/hello' Set routing prefix for plugin. +`plugin.autoPrefix` overrides directory-derived prefixes by default. Use the global `appendAutoPrefix` option to append `plugin.autoPrefix` to directory prefixes instead. + ```js module.exports = function (fastify, opts, next) { fastify.get('/', (request, reply) => { diff --git a/index.js b/index.js index ffaa2cbe..1d130676 100644 --- a/index.js +++ b/index.js @@ -11,7 +11,8 @@ const defaults = { indexPattern: /^index(?:\.ts|\.js|\.cjs|\.mjs|\.cts|\.mts)$/iu, autoHooksPattern: /^[_.]?auto_?hooks(?:\.ts|\.js|\.cjs|\.mjs|\.cts|\.mts)$/iu, dirNameRoutePrefix: true, - encapsulate: true + encapsulate: true, + appendAutoPrefix: false } const fastifyAutoload = async function autoload (fastify, options) { @@ -101,7 +102,7 @@ async function loadPlugin ({ file, type, directoryPrefix, options, log }) { plugin.autoConfig = undefined } - handlePrefixConfig({ plugin, pluginOptions, content, directoryPrefix }) + handlePrefixConfig({ plugin, pluginOptions, content, directoryPrefix, appendAutoPrefix: options.appendAutoPrefix }) return { plugin, @@ -258,16 +259,18 @@ function loadPluginOptions (content, overrideConfig) { return { ...pluginConfig, ...overrideConfig } } -function handlePrefixConfig ({ plugin, pluginOptions, content, directoryPrefix }) { +function handlePrefixConfig ({ plugin, pluginOptions, content, directoryPrefix, appendAutoPrefix }) { if (pluginOptions.prefix?.endsWith('/')) { pluginOptions.prefix = pluginOptions.prefix.slice(0, -1) } + const autoPrefix = plugin.autoPrefix ?? content.autoPrefix + let prefix - if (plugin.autoPrefix !== undefined) { - prefix = plugin.autoPrefix - } else if (content.autoPrefix !== undefined) { - prefix = content.autoPrefix + if (appendAutoPrefix && autoPrefix !== undefined && directoryPrefix) { + prefix = `${directoryPrefix}/${autoPrefix}` + } else if (autoPrefix !== undefined) { + prefix = autoPrefix } else { prefix = directoryPrefix } diff --git a/test/issues/205/routes/children/new-routes.js b/test/issues/205/routes/children/new-routes.js new file mode 100644 index 00000000..9a9d6750 --- /dev/null +++ b/test/issues/205/routes/children/new-routes.js @@ -0,0 +1,7 @@ +'use strict' + +module.exports = async function (app) { + app.get('/entity', async () => ({ ok: true })) +} + +module.exports.autoPrefix = '/batch' diff --git a/test/issues/205/test.js b/test/issues/205/test.js new file mode 100644 index 00000000..1c298251 --- /dev/null +++ b/test/issues/205/test.js @@ -0,0 +1,60 @@ +'use strict' + +const { after, before, describe, it } = require('node:test') +const assert = require('node:assert') +const path = require('node:path') +const Fastify = require('fastify') +const autoLoad = require('../../../') + +describe('Issue 205: append autoPrefix to directory prefixes without breaking defaults', function () { + describe('default behavior', function () { + const app = Fastify() + + before(async function () { + app.register(autoLoad, { + dir: path.join(__dirname, 'routes'), + options: { prefix: '/hooked-plugin' } + }) + await app.ready() + }) + + after(async function () { + await app.close() + }) + + it('keeps autoPrefix overriding directory prefixes by default', async function () { + const overridden = await app.inject({ method: 'GET', url: '/hooked-plugin/batch/entity' }) + assert.strictEqual(overridden.statusCode, 200) + assert.deepStrictEqual(overridden.json(), { ok: true }) + + const appended = await app.inject({ method: 'GET', url: '/hooked-plugin/children/batch/entity' }) + assert.strictEqual(appended.statusCode, 404) + }) + }) + + describe('appendAutoPrefix: true', function () { + const app = Fastify() + + before(async function () { + app.register(autoLoad, { + dir: path.join(__dirname, 'routes'), + options: { prefix: '/hooked-plugin' }, + appendAutoPrefix: true + }) + await app.ready() + }) + + after(async function () { + await app.close() + }) + + it('concatenates directory prefixes before plugin autoPrefix', async function () { + const appended = await app.inject({ method: 'GET', url: '/hooked-plugin/children/batch/entity' }) + assert.strictEqual(appended.statusCode, 200) + assert.deepStrictEqual(appended.json(), { ok: true }) + + const overridden = await app.inject({ method: 'GET', url: '/hooked-plugin/batch/entity' }) + assert.strictEqual(overridden.statusCode, 404) + }) + }) +}) diff --git a/types/index.d.ts b/types/index.d.ts index 3107dfae..cac1c6ba 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -9,6 +9,7 @@ declare namespace fastifyAutoload { export interface AutoloadPluginOptions { dir: string dirNameRoutePrefix?: boolean | RewritePrefix + appendAutoPrefix?: boolean ignoreFilter?: Filter matchFilter?: Filter ignorePattern?: RegExp