@fastify/autoload

repository·main·Indexed 18 days ago

https://github.com/fastify/fastify-autoload

A convenience plugin for Fastify that automates the loading of plugins and the configuration of routes based on the file system structure. It supports automatic route prefixing, dynamic route parameters via folder naming, and the application of hooks through autohooks files. Compatible with .js, .cjs, .mjs, and .ts files, it allows for fine-grained control over file selection using match and ignore filters.

Tokens
3.9K
Snippets
17
Records
21
Agent score
13%

What's inside @fastify/autoload

  1. How @fastify/autoload works

    main
    @fastify/autoload is a convenience plugin for Fastify that automatically loads all plugins found in a specified directory. It also automatically configures routes based on the folder structure, allowing you to build a routing tree that mirrors your file system.
  2. How autohooks work and how to configure them

    main

    The autohooks feature allows you to automatically apply hooks (like onRequest) or decorators to routes within a directory by placing an autohooks.js (CJS) or autohooks.mjs (ESM) file in that folder.

    Configuration Options

    • autoHooks: true (Default): Encapsulates the autohooks.js plugin with the contents of the folder containing the file. Hooks in this folder do not apply to subdirectories.
    • cascadeHooks: true: Hooks are applied cumulatively. A child directory's hooks will be applied in addition to the hooks from its parent directories.
    • overwriteHooks: true: When a new autohooks.js file is encountered in a subdirectory, it restarts the cascade, effectively ignoring the hooks from parent directories for that branch.
    // hooked-plugin/autohooks.js
    
    module.exports = async function (app, opts) {
      app.addHook('onRequest', async (req, reply) => {
        req.hookOne = 'yes';
      });
    }
  3. Use `autoConfig` to dynamically configure autoloaded plugins

    main

    An autoloaded plugin can export an autoConfig property. If autoConfig is a function, it is called with the fastify instance to generate the plugin's options. This is useful for plugins that need to access the Fastify instance (e.g., to read configuration or other plugin state) during the autoloading process.

    Note: Options passed to fastify.register(autoload, { ... }) will override values returned by autoConfig.

    // Inside an autoloaded file (e.g., plugins/my-plugin.js)
    module.exports.autoConfig = (fastify) => {
      return {
        someOption: fastify.config.value
      }
    }
    
    async function plugin(fastify, opts) {
      // ...
    }
    
    module.exports = plugin
  4. How @fastify/autoload handles route prefixes and parameters

    main

    The plugin uses the file system structure to automatically generate route prefixes.

    Directory-based Prefixes

    If dirNameRoutePrefix is enabled, a file located at plugins/users/get.js will be registered with a prefix related to users.

    Route Parameter Patterns

    If routeParams is enabled, you can use specific patterns in your filenames to represent route parameters:

    • _ (single underscore): Replaced with /:param (e.g., user_id.js becomes /:user_id).
    • __ (double underscore): Replaced with : (e.g., user__id.js becomes /:id).

    Manual Prefixing

    Plugins can define their own prefix or autoPrefix via their exported configuration or by using autoConfig to dynamically determine options based on the Fastify instance.

  5. Override TypeScript detection via environment variable

    main

    Autoload uses native type stripping in Node 23+. If you are using a custom TypeScript loader and Autoload fails to detect it, you can force TypeScript loading by setting the FASTIFY_AUTOLOAD_TYPESCRIPT environment variable to a truthy value.

    FASTIFY_AUTOLOAD_TYPESCRIPT=1 node --loader=my-custom-loader index.ts
  6. Load plugins from a directory

    main

    To use @fastify/autoload, register it with the dir option pointing to your plugins or routes directory.

    Each script file in the directory is treated as a plugin unless the directory contains an index file (e.g., index.js). In that case, only the index file and its sub-directories are loaded.

    Supported script types:

    • .js (CommonJS or ES modules based on package.json)
    • .cjs (CommonJS)
    • .mjs (ES modules)
    • .ts (TypeScript)
    const fastify = require('fastify')
    const autoload = require('@fastify/autoload')
    const path = require('path')
    
    const app = fastify()
    
    app.register(autoload, {
      dir: path.join(__dirname, 'plugins')
    })
    
    app.listen({ port: 3000 })
  7. Configure route parameters with routeParams

    main

    When routeParams: true is enabled, folders prefixed with a single underscore _ are converted into dynamic route parameters. For mixed route parameters, use a double underscore __.

    Example:

    • routes/_id/actions.js becomes /users/:id/actions (if inside a users folder).
    • routes/__country-__language/actions.js becomes /:country-:language/actions.
    fastify.register(autoLoad, {
      dir: path.join(__dirname, 'routes'),
      routeParams: true
    })
  8. Filter loaded files with matchFilter and ignoreFilter

    main

    You can control which files are loaded using filters:

    • matchFilter: A RegExp, string, or function that returns true for paths that should be loaded.
    • ignoreFilter: A RegExp, string, or function that returns true for paths that should not be loaded.
    // Only load paths where the parent folder is 'handlers'
    fastify.register(autoLoad, {
      dir: path.join(__dirname, 'plugins'),
      matchFilter: (path) => path.split("/").at(-2) === "handlers"
    })
    
    // Ignore all .spec.js files
    fastify.register(autoLoad, {
      dir: path.join(__dirname, 'plugins'),
      ignoreFilter: (path) => path.endsWith('.spec.js')
    })
  9. Use ignorePattern and scriptPattern to control file selection

    main

    Use regex patterns to include or exclude files:

    • ignorePattern: A RegExp matching files or folders to ignore.
    • scriptPattern: A Regex to override the default accepted script extensions. Note: This should only be used with a customization hooks provider (like ts-node), otherwise widening extensions will cause an error.
    // Ignore test and spec files
    fastify.register(autoLoad, {
      dir: path.join(__dirname, 'plugins'),
      ignorePattern: /^.*(?:test|spec).js$/
    })
    
    // Custom script pattern (e.g. for TypeScript)
    fastify.register(autoLoad, {
      dir: path.join(__dirname, 'plugins'),
      scriptPattern: /(?<!\.d)\.(ts|tsx)$/
    })
  10. Pass global options to all autoloaded plugins

    main

    The options key allows you to pass a global options object to every plugin loaded by Autoload. Any option specified here will override plugin.autoConfig options defined within the individual plugins.

    When using options.prefix alongside a plugin's autoPrefix, they are concatenated.

    // In app.js
    fastify.register(autoLoad, {
      dir: path.join(__dirname, 'plugins'),
      options: { prefix: '/defaultPrefix' }
    })
    
    // In /plugins/something.js
    module.exports = function (fastify, opts, next) { /* ... */ }
    module.exports.autoPrefix = '/something'
    
    // Resulting route: /defaultPrefix/something
  11. Configure individual plugin options with `plugin.autoConfig`

    main

    You can specify custom options for an autoloaded plugin by exporting an autoConfig property from the plugin file. This object will be passed as the opts parameter to the plugin function.

    Supported formats:

    • CJS: Export an object named autoConfig.
    • ESM: Export a constant named autoConfig.
    • Dynamic: Export a function that accepts the fastify instance to generate options dynamically. If using a function, you must also set autoConfig.prefix directly on the function for autoloading to work correctly.
    // CJS Example
    module.exports = function (fastify, opts, next) {
      console.log(opts.foo) // 'bar'
      next()
    }
    module.exports.autoConfig = { foo: 'bar' }