fastify-xswagger
fastify-xswagger
Route-scoped Swagger/OpenAPI documentation for Fastify v5. Define one or more doc scopes — each scoped to a route prefix with its own Swagger UI, access level (public or Basic-Auth-protected), and title. Docs are isolated per scope so /public and /admin routes never bleed into each other.
Installation
npm install @xenterprises/fastify-xswagger
Quick Start
import Fastify from "fastify";
import xSwagger from "@xenterprises/fastify-xswagger";
const fastify = Fastify({ logger: true });
fastify.get("/public/users", {
schema: { tags: ["users"], description: "List users" },
}, async () => ({ users: [] }));
fastify.get("/admin/settings", {
schema: { tags: ["admin"], description: "Get settings" },
}, async () => ({ settings: {} }));
await fastify.register(xSwagger, {
docs: [
{ prefix: "/public", access: "public", title: "Public API" },
{ prefix: "/admin", access: "private", title: "Admin API" },
],
auth: {
username: process.env.DOCS_USER,
password: process.env.DOCS_PASSWORD,
},
disableInProduction: "public",
});
await fastify.listen({ port: 3000 });
// Public docs: http://localhost:3000/public/documentation
// Admin docs: http://localhost:3000/admin/documentation (Basic Auth required)
Options
Plugin Options
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
docs | DocConfig[] | — | Yes | Array of doc configurations (at least one required) |
auth | { username, password } | — | When private docs exist | Basic Auth credentials for private doc access |
disableInProduction | boolean | 'public' | false | No | Controls which docs are disabled when NODE_ENV=production |
docsPath | string | '/documentation' | No | Path appended to each prefix for the Swagger UI |
active | boolean | true | No | Set false to disable the plugin entirely |
DocConfig
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
prefix | string | — | Yes | Route prefix to document (e.g. '/api', '/admin') |
title | string | — | Yes | Title shown in the Swagger UI header |
access | 'public' | 'private' | — | Yes | 'private' requires Basic Auth to view the docs |
version | string | '1.0.0' | No | API version shown in the spec info |
description | string | Auto-generated | No | Description shown in the spec info |
Environment Controls
The disableInProduction option controls doc availability when NODE_ENV === 'production':
| Value | Development | Production |
|---|---|---|
false | All docs enabled | All docs enabled |
true | All docs enabled | All docs disabled |
'public' | All docs enabled | Only private docs enabled |
Accessors
fastify.xswagger.config
- config — Read-only config summary (environment, doc count, auth status).
fastify.xswagger.docs
- docs[key].spec() — Per-doc instance properties and live OpenAPI spec accessor.
Error Reference
All errors use the [xSwagger] prefix.
| Error | Trigger |
|---|---|
[xSwagger] At least one doc configuration is required | docs missing, empty, or not an array |
[xSwagger] docs[N].prefix is required and must be a string | Missing or non-string prefix |
[xSwagger] docs[N].title is required and must be a string | Missing or non-string title |
[xSwagger] docs[N].access must be 'public' or 'private' | Invalid access level |
[xSwagger] docs[N].version must be a string | Non-string version |
[xSwagger] docs[N].description must be a string | Non-string description |
[xSwagger] auth.username and auth.password are required when using private docs | Private docs without valid auth |
[xSwagger] docsPath must be a non-empty string | Invalid docsPath |
[xSwagger] disableInProduction must be true, false, or 'public' | Invalid disableInProduction value |
Environment Variables
| Variable | Required | Description |
|---|---|---|
NODE_ENV | No | Set to 'production' to activate disableInProduction behavior |
DOCS_USER | When private docs | Username for Basic Auth — pass as auth.username |
DOCS_PASSWORD | When private docs | Password for Basic Auth — pass as auth.password |
Exported Constants
import xSwagger, {
ACCESS_LEVELS, // { PUBLIC: 'public', PRIVATE: 'private' }
DEFAULT_DOCS_PATH, // '/documentation'
DISABLE_MODES, // { ALL: true, PUBLIC_ONLY: 'public', NONE: false }
DEFAULT_VERSION, // '1.0.0'
} from "@xenterprises/fastify-xswagger";
How It Works
On registration all options are validated at startup. For each enabled doc config (after disableInProduction + NODE_ENV evaluation), @fastify/swagger and @fastify/swagger-ui are registered inside an encapsulated Fastify scope so their decorators don't conflict across instances. A transform function filters the generated OpenAPI spec to include only routes whose paths start with the doc's prefix. Private docs receive an onRequest hook that validates Basic credentials using crypto.timingSafeEqual to prevent timing attacks. The fastify.xswagger decorator exposes a config summary and per-doc instances — auth credentials are never stored in the exposed config.
AI Context
package: "@xenterprises/fastify-xswagger"
type: fastify-plugin
use-when: Route-scoped Swagger/OpenAPI docs — multiple doc scopes per prefix, public or Basic-Auth-protected, environment-aware
decorator: fastify.xswagger (config, docs[key].spec())
env: NODE_ENV, DOCS_USER, DOCS_PASSWORD (optional)
disableInProduction: false (all on) | true (all off) | "public" (only private docs in production)
docs-path: {prefix}/documentation (configurable via docsPath)
