npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

fastify-route-preset

v2.0.0

Published

A Fastify plugin for applying reusable route configurations through preset-based modifications.

Readme

fastify-route-preset

CI NPM version Checked with Biome MIT License

A Fastify plugin that streamlines route configuration through preset-based modifications. Define reusable route patterns and apply them consistently across your application using onRoute hooks.

Overview

This plugin enables you to create preset configurations that can be applied to multiple routes, eliminating repetitive route setup and ensuring consistency across your API endpoints.

Installation

npm install fastify-route-preset

Compatibility

| Plugin Version | Fastify Version | |:--------------:|:---------------:| | >=1.x | ^5.x |

Usage

The fastify-route-preset plugin works by leveraging Fastify's onRoute hook to intercept route registration and apply preset configurations. This allows you to define common route properties once and reuse them across multiple routes, promoting consistency and reducing code duplication.

import Fastify from 'fastify'
import fastifyRoutePreset from 'fastify-route-preset'

const fastify = Fastify()

// Register the plugin
fastify.register(fastifyRoutePreset, {
  onPresetRoute: (routeOptions, presetOptions) => {
    // Merge preset schema with route schema
    routeOptions.schema = {
      ...presetOptions.schema,
      ...routeOptions.schema,
    }
  }
})

// Apply preset to route group
fastify.register(async function (fastify) {
  fastify.get('/users', async (request, reply) => {
    return { users: [] }
  })
  
  fastify.post('/users', async (request, reply) => {
    return { created: true }
  })
}, {
  preset: {
    schema: { 
      tags: ['users'],
      security: [{ bearerAuth: [] }]
    }
  }
})

await fastify.listen({ port: 3000 })

// Result: Both routes will have the preset schema applied
// [
//   {
//     method: 'GET',
//     url: '/users',
//     schema: {
//       tags: [ 'users' ],
//       security: [ { bearerAuth: [] } ]
//     }
//   },
//   {
//     method: 'POST',
//     url: '/users',
//     schema: {
//       tags: [ 'users' ],
//       security: [ { bearerAuth: [] } ]
//     }
//   }
// ]

In this example, instead of manually adding tags: ['users'] and security: [{ bearerAuth: [] }] to each route, the preset automatically applies these properties to all routes within the registration context.

Using with @fastify/autoload

The fastify-route-preset plugin works seamlessly with @fastify/autoload for automatic route discovery and registration. You can define presets in your route files using the autoConfig export, making it easy to organize and configure routes across your application.

Route File Configuration

Create route files with the autoConfig export to define presets:

// routes/user.js
export default async function (fastify) {
  fastify.get('/', (_req, reply) => {
    reply.send('hello world')
  })

  fastify.post('/', (_req, reply) => {
    reply.send('hello world')
  })
}

export const autoConfig = {
  prefix: '/user',
  preset: {
    schema: { tags: ['user'] },
    constraints: { version: '1.0.0' },
  },
}

// index.js
// Register autoload to automatically discover and load routes
fastify.register(fastifyAutoload, {
  dir: join(__dirname, 'routes'),
  dirNameRoutePrefix: false,
})

The resulting routes will have the preset configurations automatically applied:

// Generated routes for user.js:
// GET /user/ - with tags: ['user'], version: '1.0.0'
// POST /user/ - with tags: ['user'], version: '1.0.0'

Ignoring Preset for Specific Routes

Presets are applied by default; set skipPreset: true to opt out

fastify.get('/ignore', { config: { skipPreset: true } }, () => {})

Skip HEAD Routes Globally

If you want to exclude all HEAD routes from preset application, use the skipHeadRoutes plugin option (default is false)

fastify.register(fastifyRoutePreset, {
  skipHeadRoutes: true, // Skip preset application for all HEAD routes
  onPresetRoute: (routeOptions, presetOptions) => {
    // This will not be called for HEAD routes
    routeOptions.schema = {
      ...presetOptions.schema,
      ...routeOptions.schema,
    }
  }
})

Note: This affects auto-exposed HEAD routes only when Fastify is created with exposeHeadRoutes: true (default in v5). If exposeHeadRoutes is false, only explicitly declared HEAD routes are affected.

Advanced Usage

Multiple Handlers

Apply multiple transformations by providing an array of handlers:

const presetSchema = (routeOptions, presetOptions) => {
  if (presetOptions.schema) {
    routeOptions.schema = {
      ...presetOptions.schema,
      ...routeOptions.schema,
    }
  }
}

const presetConstraint = (routeOptions, presetOptions) => {
  if (presetOptions.constraints) {
    routeOptions.constraints = {
      ...presetOptions.constraints,
      ...routeOptions.constraints,
    }
  }
}

const presetPreHandler = (routeOptions, presetOptions) => {
  if (presetOptions.preHandler) {
    const existingPreHandler = routeOptions.preHandler || []
    routeOptions.preHandler = [
      ...(Array.isArray(existingPreHandler) ? existingPreHandler : [existingPreHandler]),
      ...(Array.isArray(presetOptions.preHandler)
        ? presetOptions.preHandler
        : [presetOptions.preHandler]),
    ]
  }
}

// Register the plugin
fastify.register(fastifyRoutePreset, {
  onPresetRoute: [
    // Handler 1: Apply schema defaults
    presetSchema,
    // Handler 2: Apply constraints
    presetConstraint,
    // Handler 3: Apply hooks
    presetPreHandler,
  ],
})

Complex Preset Example

// Register routes with comprehensive preset
fastify.register(async function (fastify) {
  fastify.get('/admin/users', {
    handler: async (request, reply) => {
      return { adminUsers: [] }
    }
  })
  
  fastify.delete('/admin/users/:id', {
    handler: async (request, reply) => {
      return { deleted: true }
    }
  })
}, {
  preset: {
    schema: {
      tags: ['admin'],
      security: [{ adminAuth: [] }]
    },
    constraints: {
      version: '2.0.0'
    },
    preHandler: [
      async (request, reply) => {
        // Admin authentication logic
        if (!request.user?.isAdmin) {
          throw new Error('Admin required')
        }
      }
    ]
  }
})

API Reference

Plugin Registration Options

interface FastifyRoutePresetOptions {
  onPresetRoute: OnPresetRoute | OnPresetRoute[]
}

type OnPresetRoute = (
  routeOptions: RouteOptions,
  presetOptions: any
) => void

Parameters:

  • onPresetRoute: Function or array of functions called when registering routes with presets
    • routeOptions: Fastify route options object (mutable)
    • presetOptions: Preset configuration object

Route Registration

When registering routes, include a preset option:

fastify.register(routePlugin, {
  preset: {
    // Your preset configuration
    schema: { /* OpenAPI schema */ },
    constraints: { /* route constraints */ },
    preHandler: [ /* hooks */ ],
    // ... any other route options
  }
})

Common Use Cases

API Versioning

import v1Routes from './routes/v1.js'

fastify.register(v1Routes, {
  preset: {
    constraints: { version: '1.0.0' },
    schema: { tags: ['v1'] }
  }
})

Authentication Presets

import { authMiddleware } from './middleware/auth.js'
import protectedRoutes from './routes/protected.js'

fastify.register(protectedRoutes, {
  preset: {
    preHandler: [authMiddleware],
    schema: {
      security: [{ bearerAuth: [] }]
    }
  }
})

Documentation Grouping

import userRoutes from './routes/users.js'

fastify.register(userRoutes, {
  preset: {
    schema: {
      tags: ['users'],
      description: 'User management endpoints'
    }
  }
})

Contributing

Contributions are welcome!

License

MIT