Topics Plugins & Decorators The Plugin System
advanced 18 min read

The Plugin System

Create modular plugins using Fastify's encapsulation model.

Plugin System

const fp = require('fastify-plugin');\n\n// Plugin definition\nasync function myPlugin(fastify, opts) {\n  fastify.decorate('utility', {\n    greet: (name) => `Hello, ${name}!`,\n  });\n\n  fastify.get('/plugin-route', async () => {\n    return { message: fastify.utility.greet('Plugin') };\n  });\n}\n\n// Wrap with fastify-plugin to break encapsulation\nmodule.exports = fp(myPlugin, {\n  name: 'my-plugin',\n  dependencies: ['@fastify/sensible'],\n});\n\n// Register the plugin\napp.register(require('./my-plugin'), {\n  prefix: '/api',\n});

Encapsulation

Fastify plugins have full encapsulation. Decorators and hooks registered in a parent plugin are not visible to sibling plugins. Use the fastify-plugin wrapper to break encapsulation when needed.

// Context hierarchy:\n// Root (app)\n//   └── Plugin A\n//         └── Plugin A1 (child, can access A)\n//   └── Plugin B (sibling, cannot access A)\n\n// Use fastify-plugin to share across siblings\nconst sharedPlugin = fp(async (fastify) => {\n  fastify.decorate('shared', { value: 'accessible everywhere' });\n});

Examples

const Fastify = require('fastify');
const fp = require('fastify-plugin');

const app = Fastify({ logger: true });

// Plugin: adds a utility function
const utilsPlugin = fp(async (fastify) => {
  fastify.decorate('utils', {
    formatDate: (date) => date.toISOString().split('T')[0],
    capitalize: (str) => str.charAt(0).toUpperCase() + str.slice(1),
  });

  fastify.decorateRequest('requestId', null);

  fastify.addHook('onRequest', async (request) => {
    request.requestId = Math.random().toString(36).slice(2, 10);
  });
}, { name: 'utils' });

// Plugin: authentication
const authPlugin = fp(async (fastify) => {
  fastify.decorate('authenticate', async (request, reply) => {
    const token = request.headers.authorization?.split(' ')[1];
    if (!token) {
      reply.code(401).send({ error: 'Missing token' });
      return;
    }
    request.user = { id: 1, role: 'user' };
  });
}, { name: 'auth', dependencies: ['utils'] });

// Register plugins
app.register(utilsPlugin);
app.register(authPlugin);

app.get('/protected', {
  preHandler: [app.authenticate],
}, async (request) => ({
  message: 'Protected route',
  user: request.user,
  requestId: request.requestId,
}));

app.listen({ port: 3000 });

Your Notes

Sign in to take notes for this lesson.

Discussion

Sign in to join the discussion.

Flashcards

Sign in to create flashcards.