X Enterprises

fastify-xconfig

Fastify plugin that orchestrates CORS, rate limiting, multipart, health check, Prisma, and utility decorators in a single registration.

fastify-xconfig

Opinionated Fastify plugin that bootstraps a complete API server in one register call: CORS, rate limiting, multipart body parsing, back-pressure monitoring, opt-in Bugsnag error tracking and Prisma, fancy error responses, a /health endpoint with system metrics, and utility decorators under a single fastify.xConfig namespace. Register it once at app startup before route plugins.

Installation

npm install @xenterprises/fastify-xconfig fastify@5
# if using Prisma:
npm install @prisma/client

Quick Start

Bare registration works — Prisma and Bugsnag are opt-in and simply stay disabled when their options are omitted:

import Fastify from "fastify";
import xConfig from "@xenterprises/fastify-xconfig";

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

await fastify.register(xConfig, {
  environment: process.env.NODE_ENV, // the plugin never reads env itself
});

fastify.xConfig.slugify("Hello World");   // "hello-world"
fastify.xConfig.randomUUID();             // "a1b2c3d4-..."
fastify.xConfig.formatBytes(1048576);     // "1 MB"

await fastify.listen({ port: 3000 });

A full registration with integrations and middleware tuned:

import { PrismaClient } from "@prisma/client";

await fastify.register(xConfig, {
  environment: process.env.NODE_ENV,
  prisma: { client: PrismaClient },                 // enables fastify.prisma
  bugsnag: { apiKey: process.env.BUGSNAG_API_KEY }, // enables fastify.bugsnag
  cors: { origin: ["https://app.example.com"], credentials: true },
  rateLimit: { max: 100, timeWindow: "1 minute" },
  multipart: { limits: { fileSize: 52428800 } },
  fancyErrors: true,
});

Options

All configuration is passed at registration. The plugin never reads process.env — the consumer owns env access and passes values in.

NameTypeDefaultRequiredDescription
environmentstring"development"NoDrives stack traces in error responses and the /health payload
professionalbooleanfalseNoSuppress route listing on startup when true
fancyErrorsbooleantrueNoEnable formatted error responses with status codes
prismaobject{} (disabled)NoPrisma integration config (see below)
bugsnagobject{} (disabled)NoBugsnag error tracking config (see below)
corsobjectlocalhost originsNoCORS config forwarded to @fastify/cors
rateLimitobject@fastify/rate-limit defaultsNoRate limiting config forwarded to @fastify/rate-limit
multipartobject@fastify/multipart defaultsNoMultipart config forwarded to @fastify/multipart
underPressureobject@fastify/under-pressure defaultsNoBack-pressure config forwarded to @fastify/under-pressure

Every middleware option bag accepts active: false to disable that middleware entirely.

prisma Options

NameTypeDefaultRequiredDescription
clientPrismaClient class or instanceNoOmit prisma entirely to leave Prisma disabled. Pass your generated PrismaClient class (instantiated with the remaining options) or an instance you created
activebooleanNoOnly active: true is meaningful: it makes client required, throwing at registration when missing. active: false also disables Prisma
...restobjectNoPassed directly to new PrismaClient(...) when client is a class

bugsnag Options

NameTypeDefaultRequiredDescription
apiKeystringNoOmit bugsnag entirely to leave Bugsnag disabled. Provide a key to enable it
activebooleanNoOnly active: true is meaningful: it makes apiKey required, throwing at registration when missing. active: false also disables Bugsnag

cors Options

NameTypeDefaultRequiredDescription
activebooleantrueNoEnable or disable CORS
originstring|string[]["http://localhost:3000", "http://localhost:3001"]NoAllowed origins — static localhost-only default; deployed apps MUST pass cors.origin explicitly
credentialsbooleantrueNoAllow credentials
methodsstring[]["GET","POST","PUT","DELETE","OPTIONS"]NoAllowed HTTP methods

Methods

Utility decorators live under a single fastify.xConfig namespace:

The plugin also registers @fastify/sensible, so its decorators (reply.notFound(), fastify.httpErrors, …) are available.

Routes registered by the plugin:

  • GET /health — System health check with memory, CPU, disk, and dependency metrics

fastify.prisma

When Prisma is enabled (prisma.client provided), fastify.prisma holds the connected PrismaClient instance. It is disconnected automatically via an onClose hook.

const user = await fastify.prisma.user.findUnique({ where: { id: userId } });

Error Reference

Registration fails fast. Every error is an Error whose message names the plugin, the option, and a correct usage example:

Error messageCause
xconfig: option `environment` must be a string, e.g. `app.register(xConfig, { environment: "production" })`environment option is not a string
xconfig: option `professional` must be a boolean, e.g. `app.register(xConfig, { professional: true })`professional option is not a boolean
xconfig: option `fancyErrors` must be a boolean, e.g. `app.register(xConfig, { fancyErrors: false })`fancyErrors option is not a boolean
xconfig: option `prisma.client` is required when `prisma.active` is true — pass your generated PrismaClient class or an instance, e.g. `app.register(xConfig, { prisma: { client: new PrismaClient() } })` — or omit `prisma` to leave it disabledprisma.active: true but no prisma.client provided
xconfig: option `prisma.client` must be a PrismaClient class or instanceprisma.client is neither a class nor an instance
xconfig: option `bugsnag.apiKey` is required when `bugsnag.active` is true, e.g. `app.register(xConfig, { bugsnag: { apiKey: '...' } })` — or omit `bugsnag` to leave it disabledbugsnag.active: true but no bugsnag.apiKey provided
xconfig: option `bugsnag.apiKey` must be a stringbugsnag.apiKey is present but not a string

At runtime, with fancyErrors enabled (default), route errors are returned as { status, message, stack? }; stack is included only when environment is not "production". With fancyErrors: false, Fastify's default error handler is used.

Environment Variables

The plugin never reads process.env. The consumer sets env vars and passes the values into app.register(xConfig, { ... }) — none of these are inputs the plugin reads itself:

VariableConsumer passes it viaDescription
NODE_ENVenvironment option"production" disables error stack traces in fancy error responses
CORS_ORIGINcors.originAllowed origins (default is static localhost-only, no env fallback)
RATE_LIMIT_MAXrateLimit.maxMax requests per window
RATE_LIMIT_TIME_WINDOWrateLimit.timeWindowRate limit time window
BUGSNAG_API_KEYbugsnag.apiKeyBugsnag project API key (enables the integration)
DATABASE_URLyour own PrismaClient constructorDatabase connection string — read by Prisma, never by this plugin

How It Works

xConfig is a fastify-plugin-wrapped orchestrator that registers sub-plugins in dependency order: Prisma (opt-in; decorates fastify.prisma + onClose disconnect), CORS/under-pressure/rate-limit/multipart middleware (each skippable via active: false), opt-in Bugsnag integration (decorates fastify.bugsnag), a custom errorHandler for fancy error formatting, @fastify/sensible HTTP utilities, the fastify.xConfig utility namespace (echo, slugify, generateUUID, randomUUID, formatBytes), a GET /health route with memory/CPU/disk and database health checks, and finally a lifecycle hook that logs all registered routes on startup unless professional: true. All decorators and routes are hoisted to the parent scope via fastify-plugin.

AI Context

package: "@xenterprises/fastify-xconfig"
type: fastify-plugin
use-when: Bootstrap a Fastify app with CORS, rate limiting, multipart, opt-in Prisma/Bugsnag, health check, and utility decorators in one registration
decorators: fastify.xConfig (echo, slugify, generateUUID, randomUUID, formatBytes), fastify.prisma (opt-in), fastify.bugsnag (opt-in)
routes: GET /health (memory, CPU, disk, DB metrics)
env: plugin never reads process.env — consumer passes values via options (environment, cors.origin, rateLimit.*, bugsnag.apiKey, prisma.client)
register-before: route plugins — xConfig must be registered first
Copyright © 2026