### Install fastify-plugin Source: https://github.com/fastify/fastify-plugin/blob/main/README.md Install the fastify-plugin package using npm. ```sh npm i fastify-plugin ``` -------------------------------- ### Fastify Plugin with Version Constraint Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/api-reference/fastify-plugin.md This example shows how to specify a required Fastify version ('5.x') for the plugin. The plugin will only load if the installed Fastify version matches the specified semver range. ```javascript const fp = require('fastify-plugin') module.exports = fp(function (fastify, opts, done) { fastify.decorate('myUtility', () => 'hello') done() }, { fastify: '5.x' }) ``` -------------------------------- ### Basic Plugin Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/INDEX.md A simple example of a Fastify plugin using fp. This plugin decorates the fastify instance with a 'util' function. ```javascript fp(async (fastify) => { fastify.decorate('util', () => 'hello') }) ``` -------------------------------- ### Main fastifyPlugin Function Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/README.md Illustrates the usage of the main `fastifyPlugin` function to wrap a Fastify plugin. This example shows how to decorate the Fastify instance with a database utility. ```javascript const fp = require('fastify-plugin') module.exports = fp(async (fastify, opts) => { fastify.decorate('db', database) }, { fastify: '5.x', name: 'database' }) ``` -------------------------------- ### Complete Fastify Plugin Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/configuration.md A comprehensive example of a Fastify plugin using fastify-plugin. It includes configuration for name, version, dependencies, decorators, and encapsulation. ```javascript const fp = require('fastify-plugin') module.exports = fp(async function (fastify, opts) { // Initialization code fastify.decorate('db', createDatabaseConnection(opts)) }, { // Plugin identification name: 'database-plugin', // Version constraint fastify: '^5.0.0', // Dependencies dependencies: ['config-plugin'], decorators: { fastify: ['config'] }, // Encapsulation encapsulate: false }) ``` -------------------------------- ### Plugin Library Development Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/OVERVIEW.md Using fastify-plugin to publish an npm package with requirements. ```javascript // index.js module.exports = require('fastify-plugin')( require('./plugin'), { name: '@myorg/my-plugin', fastify: '^5.0.0' } ) ``` -------------------------------- ### Mixed Encapsulation Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/examples.md This example illustrates how to register both global and encapsulated plugins. Global plugins are accessible everywhere, while encapsulated plugins are scoped. ```javascript const fp = require('fastify-plugin') const fastify = require('fastify')() // Global plugin fastify.register(fp(async (fastify) => { fastify.decorate('global', 'accessible everywhere') }, { name: 'global' })) // Encapsulated plugin fastify.register(fp(async (fastify) => { fastify.decorate('scoped', 'only in this scope') }, { name: 'scoped', encapsulate: true })) // Outer routes - only have 'global' fastify.get('/outer', (request, reply) => { reply.send({ global: fastify.global }) // fastify.scoped is undefined }) // Inner routes - have both decorations fastify.register(fp(async (fastify) => { fastify.get('/inner', (request, reply) => { reply.send({ global: fastify.global, scoped: fastify.scoped // Only available here }) }) }, { name: 'inner-routes', encapsulate: true })) ``` -------------------------------- ### Dependency Management Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/OVERVIEW.md Expressing complex plugin dependencies with fastify-plugin. ```javascript fp(plugin, { name: 'analytics', dependencies: ['database', 'config'], decorators: { fastify: ['db', 'settings'] } }) ``` -------------------------------- ### Fastify Plugin Error Handling Examples Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/OVERVIEW.md Examples demonstrating common error types in fastify-plugin. ```javascript fp('not-a-function') ``` ```javascript fp(fn, null) ``` ```javascript fp(fn, { fastify: 5 }) ``` -------------------------------- ### Plugin Naming Configuration Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/OVERVIEW.md Examples of how to name plugins using fastify-plugin. ```javascript function myPlugin(fastify, opts, done) { done() } fp(myPlugin) // name: 'myPlugin' ``` ```javascript fp(anon => {}) // name: 'myfile-auto-0' (extracted from stack trace) ``` ```javascript fp(plugin, { name: 'my-awesome-plugin' }) ``` -------------------------------- ### TypeScript Plugin Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/README.md An example of creating a Fastify plugin with TypeScript, including generic type parameters for options and the Fastify instance, and specifying version requirements. ```typescript import fp from 'fastify-plugin' import { FastifyPluginAsync } from 'fastify' const plugin: FastifyPluginAsync<{ port: number }> = async (fastify, opts) => { fastify.listen({ port: opts.port }) } export default fp(plugin, { fastify: '5.x' }) ``` -------------------------------- ### fastify-plugin Configuration Options Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/README.md Shows how to configure a plugin with various options including Fastify version constraints, name, dependencies, required decorators, and encapsulation settings. ```javascript fp(plugin, { fastify: '^5.0.0', name: 'my-plugin', dependencies: ['auth-plugin'], decorators: { fastify: ['config'] }, encapsulate: false }) ``` -------------------------------- ### Fastify Version Mismatch Error Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/errors.md Demonstrates a version mismatch error when a plugin expects a specific Fastify version range that is not met by the installed version. Ensure the installed Fastify version aligns with the plugin's requirements. ```javascript // plugin.js const fp = require('fastify-plugin') module.exports = fp(async (fastify, opts) => { fastify.log.info('Plugin initialized') }, { fastify: '^4.0.0', name: 'my-plugin' }) // app.js const Fastify = require('fastify') const myPlugin = require('./plugin') const fastify = Fastify() fastify.register(myPlugin) // If Fastify 5.0.0 is installed: // Error: fastify-plugin: my-plugin - expected '^4.0.0' fastify version, '5.0.0' is installed ``` ```javascript // Option 1: Update the version constraint module.exports = fp(async (fastify, opts) => { }, { fastify: '5.x' }) // Option 2: Install a compatible Fastify version // npm install fastify@4 ``` -------------------------------- ### Fastify Version Constraint Examples Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/examples.md Provides various syntaxes for specifying version constraints when registering plugins, including exact versions, ranges, and shorthand notations. ```javascript // Exact version fp(plugin, { fastify: '5.0.0' }) ``` ```javascript // Caret: up to next major fp(plugin, { fastify: '^5.0.0' }) // 5.0.0 to <6.0.0 ``` ```javascript // Tilde: up to next minor fp(plugin, { fastify: '~5.1.0' }) // 5.1.0 to <5.2.0 ``` ```javascript // Greater than or equal fp(plugin, { fastify: '>=5.0.0' }) ``` ```javascript // Range fp(plugin, { fastify: '>=5.0.0 <6.0.0' }) ``` ```javascript // X-range fp(plugin, { fastify: '5.x' }) ``` ```javascript // String shorthand (converted to { fastify: '5.x' }) fp(plugin, '5.x') ``` -------------------------------- ### Fastify Plugin Usage Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/types.md Demonstrates how to use fastify-plugin with PluginMetadata to define a plugin's name, dependencies, and decorator requirements. ```typescript import fp from 'fastify-plugin' import { FastifyPluginCallback } from 'fastify' const myPlugin: FastifyPluginCallback = (fastify, opts, done) => { fastify.decorate('myUtil', () => 'hello') done() } export default fp(myPlugin, { name: 'my-awesome-plugin', fastify: '^5.0.0', decorators: { fastify: ['someOtherUtil'], reply: ['compress'] }, dependencies: ['core-plugin', 'auth-plugin'], encapsulate: false }) ``` -------------------------------- ### Basic Plugin with Callback Source: https://github.com/fastify/fastify-plugin/blob/main/README.md Example of a Fastify plugin using a callback function with fastify-plugin. ```javascript const fp = require('fastify-plugin') module.exports = fp(function (fastify, opts, done) { // your plugin code done() }) ``` -------------------------------- ### Fastify Plugin with Metadata Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/OVERVIEW.md An example of a comprehensive fastify plugin including metadata like name, version requirements, dependencies, and decorators. ```javascript module.exports = fp(async (fastify, opts) => { // Full-featured plugin }, { name: 'complete-plugin', fastify: '^5.0.0', dependencies: ['base-plugin'], decorators: { fastify: ['baseFeature'] } }) ``` -------------------------------- ### Fastify Version Constraint Configuration Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/OVERVIEW.md Examples of configuring Fastify version constraints for a plugin. ```javascript fp(plugin, { fastify: '5.0.0' }) ``` ```javascript fp(plugin, { fastify: '^5.0.0' }) ``` ```javascript fp(plugin, { fastify: '~5.1.0' }) ``` ```javascript fp(plugin, { fastify: '5.x' }) ``` ```javascript fp(plugin, '5.x') ``` ```javascript fp(plugin, { fastify: '>=5.0.0' }) ``` -------------------------------- ### Basic Fastify Plugin Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/OVERVIEW.md A basic example of a fastify plugin. This pattern is used to encapsulate functionality and make it available to the Fastify instance. ```javascript const fp = require('fastify-plugin') module.exports = fp(async (fastify, opts) => { fastify.decorate('utility', () => 'hello') }) ``` -------------------------------- ### Dependency Declaration Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/OVERVIEW.md Declaring plugin dependencies and decorators using fastify-plugin. ```javascript fp(plugin, { name: 'dependent-plugin', dependencies: ['core-plugin'], decorators: { fastify: ['config', 'database'], reply: ['compress'], request: ['validate'] } }) ``` -------------------------------- ### Example of Reply Decorator Error Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/errors.md This example demonstrates a scenario where a plugin expects a 'compress' decorator on the reply object, which might be missing, leading to an error. ```javascript const fp = require('fastify-plugin') module.exports = fp(async (fastify) => { fastify.get('/', (request, reply) => { // Error if 'compress' decorator doesn't exist on reply reply.compress() }) }, { name: 'compress-consumer', decorators: { reply: ['compress'] } }) ``` -------------------------------- ### Scope Control Examples Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/OVERVIEW.md Controlling plugin scope (global vs. scoped) using fastify-plugin. ```javascript // Global plugin fp(middleware, { name: 'global-middleware' }) ``` ```javascript // Scoped plugin fp(context, { name: 'request-context', encapsulate: true }) ``` -------------------------------- ### Plugin with Options and Default Value Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/INDEX.md Example of a plugin that accepts options and uses a default value for a specific option. The 'timeout' option defaults to 1000 if not provided. ```javascript fp((fastify, opts) => { const { timeout = 1000 } = opts }, { fastify: '5.x' }) ``` -------------------------------- ### Fastify Plugin Type Inference Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/types.md Demonstrates how TypeScript infers generic types for the `fastifyPlugin` function. This example shows the inference of `Options` and `RawServer` types. ```typescript import fp from 'fastify-plugin' import { FastifyPluginAsync } from 'fastify' // TypeScript infers Options = { debug: boolean }, RawServer = http.Server const plugin: FastifyPluginAsync<{ debug: boolean }> = async (fastify, options) => { if (options.debug) { fastify.log.debug('Debug mode enabled') } } // The return type is FastifyPluginAsync<{ debug: boolean }> const wrapped = fp(plugin) ``` -------------------------------- ### Encapsulated Plugin Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/INDEX.md Shows how to register a plugin with encapsulation enabled. This creates a new scope for the plugin, isolating its routes and decorators. ```javascript fp(plugin, { name: 'scoped', encapsulate: true }) ``` -------------------------------- ### Plugin with Version Requirement Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/INDEX.md Example of registering a plugin with a specific Fastify version requirement. The plugin will only load if the Fastify version matches '5.x'. ```javascript fp(plugin, { fastify: '5.x' }) ``` -------------------------------- ### Basic Plugin with Async Function Source: https://github.com/fastify/fastify-plugin/blob/main/README.md Example of a Fastify plugin using an async function with fastify-plugin. A callback is not required for async functions. ```javascript const fp = require('fastify-plugin') // A callback function param is not required for async functions module.exports = fp(async function (fastify, opts) { // Wait for an async function to fulfill promise before proceeding await exampleAsyncFunction() }) ``` -------------------------------- ### Fastify Plugin Encapsulation Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/configuration.md Demonstrates the difference between non-encapsulated (default) and encapsulated plugins. Non-encapsulated plugins make decorators globally accessible, while encapsulated plugins keep them scoped locally. ```javascript const fp = require('fastify-plugin') // Non-encapsulated (default) fastify.register(fp((fastify, opts, done) => { fastify.decorate('util', () => {}) done() }, { name: 'public-plugin' })) // Later code can access fastify.util // Encapsulated fastify.register(fp((fastify, opts, done) => { fastify.decorate('util', () => {}) done() }, { name: 'scoped-plugin', encapsulate: true })) // Later code CANNOT access fastify.util ``` -------------------------------- ### Plugin with Typed Options in TypeScript Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/examples.md This TypeScript example defines a plugin with typed options for database configuration. It decorates the Fastify instance with a `db` object containing a `query` method. ```typescript // plugins/database.ts import fp from 'fastify-plugin' import { FastifyPluginAsync } from 'fastify' interface DatabaseOptions { host: string port: number database: string } const databasePlugin: FastifyPluginAsync = async ( fastify, options ) => { const { host, port, database } = options fastify.decorate('db', { query: async (sql: string) => { // Query implementation return [] } }) } export default fp(databasePlugin, { fastify: '5.x' }) // app.ts import fastify from 'fastify' import databasePlugin from './plugins/database' const app = fastify() app.register(databasePlugin, { host: 'localhost', port: 5432, database: 'myapp' }) app.get('/', async (request, reply) => { const data = await app.db.query('SELECT 1') reply.send(data) }) ``` -------------------------------- ### Missing Dependency Error Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/errors.md Illustrates a missing dependency error where a plugin requires another plugin to be registered first. Ensure that all plugin dependencies are registered in the correct order before the dependent plugin. ```javascript // core-plugin.js const fp = require('fastify-plugin') module.exports = fp(async (fastify) => { fastify.decorate('core', { initialized: true }) }, { name: 'core-plugin' }) // dependent-plugin.js const fp = require('fastify-plugin') module.exports = fp(async (fastify) => { // Uses core-plugin }, { name: 'dependent-plugin', dependencies: ['core-plugin'] }) // app.js const fastify = Fastify() // Error: dependency 'core-plugin' is not registered fastify.register(require('./dependent-plugin')) fastify.register(require('./core-plugin')) // Correct order: fastify.register(require('./core-plugin')) fastify.register(require('./dependent-plugin')) ``` ```javascript const fastify = Fastify() // Register in dependency order fastify.register(require('./core-plugin')) fastify.register(require('./dependent-plugin')) await fastify.ready() ``` -------------------------------- ### Requiring Specific Fastify Version Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/examples.md Illustrates how to specify a required Fastify version for a plugin using the `fastify` option. This ensures the plugin only loads if the installed Fastify version meets the specified criteria. ```javascript // plugins/modern-features.js const fp = require('fastify-plugin') module.exports = fp(async (fastify, opts) => { // Uses features only available in Fastify 5.x fastify.decorate('modernFeature', async () => { return 'Only works with Fastify 5+' }) }, { fastify: '5.x' // Will fail if Fastify 4.x or 6.x is installed }) ``` -------------------------------- ### Global Plugin for Request ID Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/examples.md This example shows a global plugin that decorates Fastify with a `requestId` function and adds a `preHandler` hook to assign a unique ID to each request. This decoration and hook are visible to all subsequent routes. ```javascript // plugins/global-middleware.js const fp = require('fastify-plugin') module.exports = fp(async (fastify, opts) => { // Decoration is visible globally fastify.decorate('requestId', () => Math.random()) // Hooks apply to all routes fastify.addHook('preHandler', async (request, reply) => { request.id = fastify.requestId() }) }) // app.js const fastify = require('fastify')() fastify.register(require('./plugins/global-middleware')) fastify.get('/route1', (request, reply) => { console.log(request.id) // Has request.id reply.send({}) }) fastify.get('/route2', (request, reply) => { console.log(request.id) // Also has request.id reply.send({}) }) ``` -------------------------------- ### ES Module Default Import Support Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/api-reference/fastify-plugin.md Shows how to use fastify-plugin with ES Modules, exporting the plugin as a default import. This example uses an async function and decorates Fastify with a utility function. ```javascript // plugin.mjs import fp from 'fastify-plugin' export default fp(async (fastify, opts) => { fastify.decorate('util', () => 'hello') }) ``` -------------------------------- ### Symbol vs. Regular Property Comparison Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/architecture.md This example demonstrates why symbols are preferred over regular properties for metadata. Symbols are hidden by default and do not pollute object enumeration, unlike regular properties. ```javascript // With symbols (current implementation) fn[Symbol.for('skip-override')] = true Object.keys(fn) // [] — metadata is hidden // With regular properties (not used) fn.skipOverride = true Object.keys(fn) // ['skipOverride'] — pollutes enumeration ``` -------------------------------- ### Encapsulated Plugin Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/api-reference/fastify-plugin.md Defines an encapsulated plugin that decorates Fastify with a private utility function. The 'encapsulate: true' option ensures the decoration is only visible within this plugin's scope. ```javascript const fp = require('fastify-plugin') module.exports = fp(function (fastify, opts, done) { // This decoration is only visible within this plugin's scope fastify.decorate('privateUtil', () => 'private') done() }, { name: 'scoped-plugin', encapsulate: true }) ``` -------------------------------- ### Missing Decorator Error Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/errors.md Shows a missing decorator error when a plugin attempts to use a decorator that has not yet been registered. Ensure that plugins providing necessary decorators are registered before the plugins that consume them. ```javascript // decorator-plugin.js const fp = require('fastify-plugin') module.exports = fp(async (fastify) => { fastify.decorate('jwt', { sign: () => {} }) }, { name: 'jwt-plugin' }) // consumer-plugin.js const fp = require('fastify-plugin') module.exports = fp(async (fastify) => { const token = fastify.jwt.sign({ sub: 'user' }) }, { name: 'consumer-plugin', decorators: { fastify: ['jwt'] } }) // app.js const fastify = Fastify() // Error: decorator 'jwt' is not present in Fastify fastify.register(require('./consumer-plugin')) fastify.register(require('./decorator-plugin')) // Correct order: fastify.register(require('./decorator-plugin')) fastify.register(require('./consumer-plugin')) ``` ```javascript const fastify = Fastify() // Option 1: Register decorator plugin first fastify.register(require('./decorator-plugin')) fastify.register(require('./consumer-plugin')) // Option 2: Add dependency in consumer plugin const fp = require('fastify-plugin') module.exports = fp(async (fastify) => { const token = fastify.jwt.sign({ sub: 'user' }) }, { name: 'consumer-plugin', dependencies: ['jwt-plugin'], // This ensures ordering decorators: { fastify: ['jwt'] } }) ``` -------------------------------- ### Early Synchronous Error Example Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/architecture.md Examples of synchronous `TypeError` exceptions thrown by fastify-plugin during the `fp()` call for immediate validation failures. ```javascript // Thrown by fastify-plugin during fp() call throw new TypeError('fastify-plugin expects a function, instead got a \'string\'') throw new TypeError('The options object should be an object') throw new TypeError('fastify-plugin expects a version string, instead got \'number\'') ``` -------------------------------- ### Fastify Plugin Integration - Initialization Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/architecture.md Fastify initializes the plugin by calling the wrapped function with `(fastify, options, done)` or awaiting its returned Promise. ```javascript // Calls the function with (fastify, options, done) or awaits Promise ``` -------------------------------- ### Plugin Registry for Multiple Plugins Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/examples.md Demonstrates a pattern for registering multiple plugins efficiently using an array of plugin configurations. This centralizes plugin registration logic within a dedicated module. ```javascript // plugins/registry.js const fp = require('fastify-plugin') const configPlugin = require('./config') const dbPlugin = require('./database') const authPlugin = require('./auth') const apiPlugin = require('./api') const plugins = [ { plugin: configPlugin, opts: {} }, { plugin: dbPlugin, opts: { url: process.env.DB_URL } }, { plugin: authPlugin, opts: {} }, { plugin: apiPlugin, opts: {} } ] module.exports = async (fastify) => { for (const { plugin, opts } of plugins) { await fastify.register(plugin, opts) } } // app.js const fastify = require('fastify')() const registerPlugins = require('./plugins/registry') await registerPlugins(fastify) await fastify.listen({ port: 3000 }) ``` -------------------------------- ### Plugin with Options Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/examples.md Shows how to create a plugin that accepts options for configuration, such as database connection details. The plugin decorates the Fastify instance with a database interface and ensures the connection is closed on application shutdown. ```javascript // plugins/database.js const fp = require('fastify-plugin') module.exports = fp(async (fastify, opts) => { const { host = 'localhost', port = 5432, database = 'myapp' } = opts const connectionString = `postgres://${host}:${port}/${database}` fastify.decorate('db', { query: async (sql) => { // Actual database implementation console.log(`Executing: ${sql}`) }, close: async () => { console.log('Database connection closed') } }) fastify.addHook('onClose', async () => { await fastify.db.close() }) }) ``` ```javascript // app.js const fastify = require('fastify')() const database = require('./plugins/database') fastify.register(database, { host: 'db.example.com', port: 5432, database: 'production' }) fastify.get('/users/:id', async (request, reply) => { const { id } = request.params const user = await fastify.db.query(`SELECT * FROM users WHERE id = ${id}`) reply.send(user) }) ``` -------------------------------- ### Fastify Plugin with Options Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/OVERVIEW.md Demonstrates how to define a plugin that accepts options. Options can be destructured and used within the plugin's logic, such as setting timeouts. ```javascript module.exports = fp(async (fastify, opts) => { const { timeout = 1000 } = opts fastify.decorate('slowOp', async () => { // Uses timeout from opts }) }) ``` -------------------------------- ### Plugin with Dependencies and Decorators Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/INDEX.md Demonstrates registering a plugin that has dependencies on other plugins and requires specific decorators. The plugin 'api' depends on 'auth' and needs the 'authenticate' decorator. ```javascript fp(plugin, { name: 'api', dependencies: ['auth'], decorators: { fastify: ['authenticate'] } }) ``` -------------------------------- ### Simple Plugin Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/README.md A basic fastify-plugin that decorates the Fastify instance with a utility object. This is the most straightforward way to create a plugin. ```javascript const fp = require('fastify-plugin') module.exports = fp(async (fastify, opts) => { fastify.decorate('util', { value: 'hello' }) }) ``` -------------------------------- ### toCamelCase Implementation Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/architecture.md A utility function to convert kebab-case strings to camelCase, handling scoped npm packages. Examples show its transformation behavior. ```javascript function toCamelCase(name) { if (name[0] === '@') { name = name.slice(1).replace('/', '-') } return name.replace(/-(.)/g, function (match, g1) { return g1.toUpperCase() }) } ``` -------------------------------- ### Configuration Options Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/README.md Configuration options for `fastifyPlugin` allow specifying version constraints, plugin names, dependencies, required decorators, and encapsulation behavior. ```APIDOC ## Configuration Options ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Configuration Options Table | Option | Type | Purpose | |--------|------|---------| | `fastify` | string | Semver version constraint (e.g., `'5.x'`) | | `name` | string | Plugin identifier for dependency resolution | | `dependencies` | string[] | Required plugin names | | `decorators` | object | Required decorators on Fastify/Reply/Request | | `encapsulate` | boolean | Whether to respect encapsulation boundary | ### Example ```javascript fp(plugin, { fastify: '^5.0.0', name: 'my-plugin', dependencies: ['auth-plugin'], decorators: { fastify: ['config'] }, encapsulate: false }) ``` ``` -------------------------------- ### Fastify Plugin Registration Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/README.md Shows how to register a fastify-plugin with a Fastify instance and await its readiness, which triggers metadata validation. ```javascript const fastify = require('fastify')() const myPlugin = require('./my-plugin') fastify.register(myPlugin) // Plugin is wrapped by fastify-plugin await fastify.ready() // Fastify validates metadata ``` -------------------------------- ### Get Plugin Name Algorithm Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/architecture.md Determines the name of a plugin. If the function has a name, it's used. Otherwise, it analyzes the call stack to extract the filename. ```javascript if (fn.name.length > 0) return fn.name const stackTraceLimit = Error.stackTraceLimit Error.stackTraceLimit = 10 try { throw new Error('anonymous function') } catch (e) { Error.stackTraceLimit = stackTraceLimit return extractPluginName(e.stack) } ``` -------------------------------- ### Try-Catch During Plugin Registration Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/errors.md This pattern shows how to wrap plugin registration and `fastify.ready()` in a try-catch block to handle various potential errors, such as version mismatches, missing dependencies, or missing decorators. ```javascript const fastify = Fastify() try { fastify.register(myPlugin) await fastify.ready() } catch (error) { if (error.message.includes('fastify version')) { console.error('Fastify version mismatch:', error.message) } else if (error.message.includes('not registered')) { console.error('Missing plugin dependency:', error.message) } else if (error.message.includes('not present')) { console.error('Missing decorator:', error.message) } process.exit(1) } ``` -------------------------------- ### Basic fastify-plugin Usage Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/00-START-HERE.md This snippet demonstrates the basic usage of fastify-plugin. It wraps a plugin function, adds metadata symbols, validates the Fastify version, and declares dependencies and required decorators. ```javascript const fp = require('fastify-plugin') // 1. Adds metadata symbols // 2. Validates Fastify version // 3. Declares dependencies module.exports = fp(async (fastify, opts) => { fastify.decorate('myUtil', () => 'hello') }, { name: 'my-plugin', // Plugin identifier fastify: '5.x', // Version requirement dependencies: ['core'], // Depends on another plugin decorators: { fastify: ['config'] // Needs 'config' decorator } }) ``` -------------------------------- ### Get Plugin Name from Named Function Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/api-reference/utility-functions.md Extracts the name from a named function. This is the primary method for obtaining a plugin's name when it's explicitly defined. ```javascript const getPluginName = require('fastify-plugin/lib/getPluginName') // Named function const namedFn = function myPlugin () {} getPluginName(namedFn) // Returns: 'myPlugin' ``` -------------------------------- ### Define Plugin Name and Dependencies Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/configuration.md Configure plugin name, dependencies, and decorator requirements. Plugin names are used for identification and dependency resolution. ```javascript const fp = require('fastify-plugin') // Auto-named from function name function myPlugin(fastify, opts, done) { done() } fp(myPlugin) // name: 'myPlugin' // Auto-named from filename fp((fastify, opts, done) => { done() }) // name: 'myfile-auto-0' (if in myfile.js) // Explicit name module.exports = fp((fastify, opts, done) => { done() }, { name: 'my-special-plugin' }) // name: 'my-special-plugin' ``` ```javascript const fp = require('fastify-plugin') module.exports = fp((fastify, opts, done) => { // Assumes 'auth-plugin' provides a decorator const isAdmin = fastify.checkAdmin() done() }, { name: 'admin-panel', dependencies: ['auth-plugin'] }) ``` ```javascript const fp = require('fastify-plugin') module.exports = fp((fastify, opts, done) => { // Uses decorators from other plugins fastify.jwt.verify(token) fastify.reply.header('X-Custom', 'value') done() }, { name: 'api-middleware', decorators: { fastify: ['jwt', 'config'], reply: ['header'] } }) ``` -------------------------------- ### Get Plugin Name from Anonymous Function (Stack Trace) Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/api-reference/utility-functions.md Extracts the name from an anonymous function by analyzing the call stack. This is used as a fallback when the function is not explicitly named. ```javascript const getPluginName = require('fastify-plugin/lib/getPluginName') // Anonymous function — extracts from stack const anonFn = () => {} getPluginName(anonFn) // Returns: e.g., 'myfile' (from myfile.js) ``` -------------------------------- ### Configurable Plugin Wrapper Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/examples.md Shows a pattern for creating configurable plugins using a factory function. The `createDatabasePlugin` function accepts configuration and returns a fastify-plugin wrapper for a database connection. ```javascript // plugins/with-defaults.js const fp = require('fastify-plugin') function createDatabasePlugin(config) { return fp(async (fastify) => { fastify.decorate('db', { url: config.url, query: async (sql) => { // Implementation } }) }, { name: 'database', fastify: '5.x' }) } // app.js const fastify = require('fastify')() const dbPlugin = require('./plugins/with-defaults') fastify.register(dbPlugin({ url: process.env.DATABASE_URL || 'postgres://localhost/db' })) ``` -------------------------------- ### Simple Decorator Plugin Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/examples.md Demonstrates creating a basic plugin that decorates the Fastify instance with a logger object. This plugin adds logging capabilities to the Fastify application. ```javascript // plugins/logger.js const fp = require('fastify-plugin') module.exports = fp(async (fastify, opts) => { fastify.decorate('logger', { info: (msg) => console.log(`[INFO] ${msg}`), error: (msg) => console.error(`[ERROR] ${msg}`) }) }) ``` ```javascript // app.js const fastify = require('fastify')() const logger = require('./plugins/logger') fastify.register(logger) fastify.get('/', (request, reply) => { fastify.logger.info('Handling request') reply.send({ hello: 'world' }) }) await fastify.listen({ port: 3000 }) ``` -------------------------------- ### Version String Shorthand for Plugin Options Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/api-reference/fastify-plugin.md Demonstrates using a version string directly as options for fastify-plugin. This is a shorthand for providing plugin metadata. ```javascript const fp = require('fastify-plugin') module.exports = fp(function (fastify, opts, done) { done() }, '5.x') // Options can be just the version string ``` -------------------------------- ### Augmenting Fastify Types for Custom Decorator Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/examples.md This TypeScript example shows how to augment the `FastifyInstance` interface to add a custom decorator (`myUtil`). This allows TypeScript to correctly type the decorator when used in `app.ts`. ```typescript // plugins/custom-decorator.ts import fp from 'fastify-plugin' declare module 'fastify' { interface FastifyInstance { myUtil: () => string } } export default fp(async (fastify) => { fastify.decorate('myUtil', () => 'hello') }) // app.ts import fastify from 'fastify' import customDecorator from './plugins/custom-decorator' const app = fastify() app.register(customDecorator) app.get('/', (request, reply) => { // TypeScript knows about app.myUtil reply.send({ message: app.myUtil() }) }) ``` -------------------------------- ### Plugin Chaining with Dependencies Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/examples.md Demonstrates how to define and register plugins with explicit dependencies, ensuring they are loaded in the correct order. The base plugin decorates Fastify with 'base', layer1 depends on 'base', and layer2 depends on 'layer1'. ```javascript const fp = require('fastify-plugin') // Base plugin const basePlugin = fp(async (fastify) => { fastify.decorate('base', { value: 'base' }) }, { name: 'base' }) // Dependent plugins const layer1 = fp(async (fastify) => { fastify.decorate('layer1', fastify.base.value + '-1') }, { name: 'layer1', dependencies: ['base'] }) const layer2 = fp(async (fastify) => { fastify.decorate('layer2', fastify.layer1 + '-2') }, { name: 'layer2', dependencies: ['layer1'] }) // app.js const fastify = require('fastify')() fastify.register(basePlugin) fastify.register(layer1) fastify.register(layer2) await fastify.ready() fastify.get('/', (request, reply) => { reply.send({ base: fastify.base, layer1: fastify.layer1, layer2: fastify.layer2 }) }) ``` -------------------------------- ### Plugin Dependencies Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/examples.md Demonstrates how to declare plugin dependencies using the `dependencies` option. This ensures that a plugin is registered only after its specified dependencies have been loaded. ```javascript // plugins/config.js const fp = require('fastify-plugin') module.exports = fp(async (fastify, opts) => { fastify.decorate('config', { apiUrl: 'https://api.example.com', dbUrl: 'postgres://localhost/db' }) }, { name: 'config-plugin' }) ``` ```javascript // plugins/auth.js const fp = require('fastify-plugin') module.exports = fp(async (fastify, opts) => { // Requires config plugin to be loaded first fastify.decorate('authenticate', async (request) => { const apiUrl = fastify.config.apiUrl // Use config to authenticate }) }, { name: 'auth-plugin', dependencies: ['config-plugin'] }) ``` ```javascript // app.js const fastify = require('fastify')() // Config must be registered first fastify.register(require('./plugins/config')) fastify.register(require('./plugins/auth')) fastify.get('/protected', async (request, reply) => { await fastify.authenticate(request) reply.send({ message: 'Authenticated' }) }) ``` -------------------------------- ### CommonJS Main Export Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/README.md Demonstrates how to wrap a plugin using the default CommonJS export of fastify-plugin. ```javascript const fp = require('fastify-plugin') const wrapped = fp(myPlugin) ``` -------------------------------- ### Fastify Plugin Named Property Generation Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/configuration.md Shows how providing a `name` option generates a camelCase property on the plugin function, useful for TypeScript named imports. This example illustrates the generation for 'my-plugin'. ```javascript const fp = require('fastify-plugin') module.exports = fp((fastify, opts, done) => { done() }, { name: 'my-plugin' }) // Plugin function has properties: // fn.default = fn // fn.myPlugin = fn // <-- Generated camelCase property ``` -------------------------------- ### Integrating with Fastify Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/OVERVIEW.md Registering a fastify-plugin wrapped plugin with Fastify. ```javascript const fastify = require('fastify')() const myPlugin = require('./my-plugin') // Register the wrapped plugin fastify.register(myPlugin) // Fastify validates metadata and initializes await fastify.ready() ``` -------------------------------- ### Plugin with Dependencies and Decorators Source: https://github.com/fastify/fastify-plugin/blob/main/README.md Specify plugin dependencies and required decorators for Fastify and Reply objects. ```javascript const fp = require('fastify-plugin') function plugin (fastify, opts, done) { // your plugin code done() } module.exports = fp(plugin, { fastify: '5.x', decorators: { fastify: ['plugin1', 'plugin2'], reply: ['compress'] }, dependencies: ['plugin1-name', 'plugin2-name'] }) ``` -------------------------------- ### fastifyPlugin(fn, options) Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/INDEX.md The main function for creating and registering plugins with Fastify. It wraps a plugin function and its options, attaching metadata and handling validation. ```APIDOC ## fastifyPlugin(fn, options) ### Description This function is the primary way to define and export a Fastify plugin. It takes a plugin function and an options object, returning the function with metadata attached for Fastify to process. ### Method `fastifyPlugin(fn, options)` ### Parameters #### Function Parameter (`fn`) - `fn` (Function | {default: Function}) - The core plugin logic, which receives `fastify` and `opts` as arguments. It can also be an object with a `default` property containing the function. #### Options Parameter (`options`) - `options` (PluginMetadata | string) - An object containing metadata and configuration for the plugin, or a string representing the plugin name. ### Returns - Input function with metadata symbols attached. ### Throws - TypeError: Thrown synchronously if the provided options fail validation. ### Configuration Options These options are part of the `options` parameter: | Option | Type | Default | Purpose | |---|---|---|---| | `fastify` | string | — | Specifies a semver version constraint for Fastify compatibility. | | `name` | string | Auto | A unique identifier for the plugin. If not provided, it's auto-generated. | | `dependencies` | string[] | [] | An array of plugin names that must be loaded before this plugin. | | `decorators` | object | {} | Defines decorators that this plugin requires from Fastify, Reply, or Request. | | `encapsulate` | boolean | false | Determines if the plugin should create a new encapsulation context. | ### Symbols Attached These symbols are attached to the returned plugin function: - `fn[Symbol.for('skip-override')]` (Boolean): Indicates if the plugin should skip being overridden. - `fn[Symbol.for('fastify.display-name')]` (String): The display name of the plugin. - `fn[Symbol.for('plugin-meta')]` (Object): An object containing the full metadata of the plugin. ``` -------------------------------- ### Symbol-Based Metadata: Plugin Meta Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/README.md Illustrates accessing the complete plugin metadata object using Symbol.for('plugin-meta'). ```javascript fn[Symbol.for('plugin-meta')] // Object: complete metadata ``` -------------------------------- ### Fastify Plugin with Version Requirement Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/OVERVIEW.md Shows how to specify version compatibility for a Fastify plugin. This ensures the plugin runs only with compatible Fastify versions. ```javascript module.exports = fp(async (fastify, opts) => { // Plugin-specific code }, { fastify: '5.x' }) ``` -------------------------------- ### Typed Fastify Plugin with Options Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/architecture.md Demonstrates how to define a typed asynchronous Fastify plugin that accepts specific options, ensuring type safety for both the plugin and its options. ```typescript const plugin: FastifyPluginAsync<{ port: number }> = async (fastify, opts) => { // opts is { port: number } } ``` -------------------------------- ### Fastify Plugin with Name and Dependencies Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/api-reference/fastify-plugin.md Configure a plugin with a specific name ('extension-plugin') and declare its dependency on another plugin ('core-plugin'). This ensures 'core-plugin' is registered before this one. ```javascript const fp = require('fastify-plugin') module.exports = fp(function (fastify, opts, done) { // This plugin depends on 'core-plugin' being registered fastify.decorate('extension', fastify.coreFeature) done() }, { name: 'extension-plugin', fastify: '5.x', dependencies: ['core-plugin'] }) ``` -------------------------------- ### Basic Fastify Plugin with Callback Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/api-reference/fastify-plugin.md Use this snippet to wrap a standard callback-based Fastify plugin. It registers a new decorator 'myUtility' on the Fastify instance. ```javascript const fp = require('fastify-plugin') module.exports = fp(function (fastify, opts, done) { fastify.decorate('myUtility', () => 'hello') done() }) ``` -------------------------------- ### Shorthand for Fastify Version Constraint Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/configuration.md The 'fastify' version can be provided directly as a string for simpler configuration. ```javascript module.exports = fp(async (fastify, opts) => { }, '5.x') // Equivalent to { fastify: '5.x' } ``` -------------------------------- ### Named Export Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/README.md Illustrates using the named export 'fastifyPlugin' from the fastify-plugin library. ```javascript const { fastifyPlugin } = require('fastify-plugin') const wrapped = fastifyPlugin(myPlugin) ``` -------------------------------- ### Decorator Dependencies Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/examples.md Shows how to declare dependencies on other decorators using the `decorators` option. This ensures that a plugin only loads if the required decorators are already available on the Fastify instance. ```javascript // plugins/validation.js const fp = require('fastify-plugin') module.exports = fp(async (fastify, opts) => { fastify.decorate('validate', (data, schema) => { // Validation logic return true }) }, { name: 'validation-plugin' }) ``` ```javascript // plugins/api.js const fp = require('fastify-plugin') module.exports = fp(async (fastify, opts) => { // Declares that it requires the 'validate' decorator fastify.post('/users', async (request, reply) => { const valid = fastify.validate(request.body, userSchema) if (!valid) return reply.status(400).send('Invalid') reply.send({ created: true }) }) }, { name: 'api-plugin', decorators: { fastify: ['validate'] // Requires 'validate' decorator } }) ``` ```javascript // app.js const fastify = require('fastify')() // Validation plugin must be registered first fastify.register(require('./plugins/validation')) fastify.register(require('./plugins/api')) await fastify.ready() ``` -------------------------------- ### Plugin with Fastify Version Check Source: https://github.com/fastify/fastify-plugin/blob/main/README.md Configure a plugin to require a specific bare-minimum Fastify version using semver ranges. ```javascript const fp = require('fastify-plugin') module.exports = fp(function (fastify, opts, done) { // your plugin code done() }, { fastify: '5.x' }) ``` -------------------------------- ### Fastify Plugin TypeScript Usage Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/configuration.md Illustrates how to import and register a named plugin in TypeScript, showing both direct import and import with Fastify. ```typescript import { myPlugin } from 'my-plugin' // Or with Fastify: import fastify from 'fastify' import myPlugin from 'my-plugin' const app = fastify() app.register(myPlugin) ``` -------------------------------- ### Async Fastify Plugin Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/api-reference/fastify-plugin.md Wrap an asynchronous Fastify plugin using this pattern. It allows for awaiting asynchronous operations before decorating the Fastify instance. ```javascript const fp = require('fastify-plugin') module.exports = fp(async function (fastify, opts) { const data = await someAsyncOperation() fastify.decorate('data', data) }) ``` -------------------------------- ### Basic Plugin Wrapper Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/OVERVIEW.md Wraps a plugin function with fastify-plugin. Use this to automatically handle plugin metadata and validation. Supports both callback-based and async plugins. ```javascript const fp = require('fastify-plugin') module.exports = fp(async (fastify, opts) => { // Plugin code }, { name: 'my-plugin', fastify: '5.x' }) ``` -------------------------------- ### Symbol-Based Metadata: Skip Override Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/README.md Demonstrates using Symbol.for('skip-override') to control plugin encapsulation behavior. ```javascript fn[Symbol.for('skip-override')] // Boolean: controls encapsulation ``` -------------------------------- ### Plugin with Name and Fastify Version Source: https://github.com/fastify/fastify-plugin/blob/main/README.md Define a plugin name for dependency graph validation and Fastify version requirements. ```javascript 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' }) ``` -------------------------------- ### Fastify Plugin Integration - Dependency Resolution Source: https://github.com/fastify/fastify-plugin/blob/main/_autodocs/architecture.md Fastify ensures that all plugins listed in `plugin-meta.dependencies` are registered before the current plugin. ```javascript // Ensures all plugins in plugin-meta.dependencies are registered ```