fastify-plugin

repository·main·Indexed 42 days ago

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

A utility for Fastify developers to manage plugin encapsulation, declare dependencies, and enforce Fastify version requirements. Version 6.0.0 allows developers to wrap plugin functions to break encapsulation, share decorations and hooks with the parent instance, and define metadata such as semver ranges for Fastify compatibility.

Tokens
1.9K
Snippets
8
Records
8
Agent score
4%

What's inside fastify-plugin

  1. Keep a plugin encapsulated using the encapsulate option

    main

    By default, fastify-plugin breaks encapsulation so the plugin is accessible in the parent context. If you want to set metadata (like name or dependencies) but keep the plugin's decorators and state private to its own scope, set encapsulate: true in the options object.

    const fp = require('fastify-plugin')
    
    function plugin (fastify, opts, done) {
      // the decorator is not accessible outside this plugin
      fastify.decorate('util', function() {})
      done()
    }
    
    module.exports = fp(plugin, {
      name: 'my-encapsulated-plugin',
      fastify: '5.x',
      decorators: {
        fastify: ['plugin1', 'plugin2'],
        reply: ['compress']
      },
      dependencies: ['plugin1-name', 'plugin2-name'],
      encapsulate: true
    })
  2. Wrap a Fastify plugin with fastify-plugin

    main

    To make your plugin accessible in the same context where it is required (breaking encapsulation), wrap your plugin function with fp(). You can use either a callback-style function or an async function.

    const fp = require('fastify-plugin')
    
    // Using a callback
    module.exports = fp(function (fastify, opts, done) {
      // your plugin code
      done()
    })
    
    // Using an async function
    module.exports = fp(async function (fastify, opts) {
      // Wait for an async function to fulfill promise before proceeding
      await exampleAsyncFunction()
    })
  3. Use fastify-plugin with TypeScript named imports

    main

    When you provide a name option to fastify-plugin, it automatically attaches the plugin function to itself using a camel-cased version of that name. This facilitates better compatibility with TypeScript named imports when consuming the plugin.

    // If you wrap a plugin with name: 'my-awesome-plugin'
    const fp = require('fastify-plugin')
    async function plugin (fastify, opts) {}
    const wrapped = fp(plugin, { name: 'my-awesome-plugin' })
    
    // The plugin is also available as:
    // wrapped.myAwesomePlugin
  4. Configure plugin metadata and dependencies

    main

    When calling fp(plugin, options), you can pass an options object to declare requirements and metadata. This allows Fastify to validate the dependency graph and ensure compatibility.

    Key options:

    • fastify: A semver range string representing the minimum required Fastify version.
    • name: A string used to identify the plugin in the dependency graph to prevent collisions.
    • decorators: An object specifying which fastify or reply decorators your plugin expects to be present.
    • dependencies: An array of plugin names that must be registered before this plugin.
    const fp = require('fastify-plugin')
    
    function plugin (fastify, opts, done) {
      // your plugin code
      done()
    }
    
    module.exports = fp(plugin, {
      fastify: '5.x',
      name: 'your-plugin-name',
      decorators: {
        fastify: ['plugin1', 'plugin2'],
        reply: ['compress']
      },
      dependencies: ['plugin1-name', 'plugin2-name']
    })
  5. Fix TypeScript type inference for plugins

    main

    When using fastify-plugin in TypeScript, the compiler may struggle to infer whether you are providing a FastifyPluginCallback or a FastifyPluginAsync based on argument length alone. To avoid errors, explicitly type your plugin functions using one of the following patterns:

    For Callback Plugins:

    // Assign type directly
    const pluginCallback: FastifyPluginCallback = (fastify, options, done) => { }
    fp(pluginCallback)
    
    // Or inline with explicit types
    fp((fastify: FastifyInstance, options: FastifyPluginOptions, done: (error?: FastifyError) => void): void => { })

    For Async Plugins:

    // Assign type directly
    const pluginAsync: FastifyPluginAsync = async (fastify, options) => { }
    fp(pluginAsync)
    
    // Or inline with explicit types
    fp(async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise<void> => { })
    // Callback example
    const pluginCallback: FastifyPluginCallback = (fastify, options, done) => { }
    fp(pluginCallback)
    
    // Async example
    const pluginAsync: FastifyPluginAsync = async (fastify, options) => { }
    fp(pluginAsync)
  6. Configure fastify-plugin options

    main

    The plugin function accepts an optional options object to configure how the plugin is wrapped:

    • name (string): The name of the plugin. If not provided, a unique auto-generated name is created.
    • encapsulate (boolean): If set to true, the plugin will behave like a standard Fastify plugin and create a new encapsulation context. If false (default), it will skip encapsulation to share decorations with the parent.
    • fastify (string): A version string for the Fastify instance (used for metadata).

    If you pass a string instead of an object, it is treated as the fastify version string.

    const fp = require('fastify-plugin')
    
    async function myPlugin (fastify, opts) {
      // ...
    }
    
    // Example with custom name and encapsulation enabled
    module.exports = fp(myPlugin, {
      name: 'my-custom-plugin',
      encapsulate: true
    })
  7. Wrap a plugin with fastify-plugin

    main

    Use the plugin function (also exported as fastifyPlugin) to wrap a Fastify plugin. This ensures the plugin is not encapsulated, allowing it to share decorations, hooks, and utilities with the parent Fastify instance.

    By default, fastify-plugin prevents encapsulation unless you explicitly set encapsulate: true in the options object. It also handles automatic naming and TypeScript compatibility for named imports.

    const fp = require('fastify-plugin')
    
    async function myPlugin (fastify, opts) {
      fastify.decorate('hello', 'world')
    }
    
    module.exports = fp(myPlugin)