X Enterprises

fastify-xswagger

Route-scoped Swagger/OpenAPI documentation for Fastify with Basic Auth access control and environment-aware availability.

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

NameTypeDefaultRequiredDescription
docsDocConfig[]YesArray of doc configurations (at least one required)
auth{ username, password }When private docs existBasic Auth credentials for private doc access
disableInProductionboolean | 'public'falseNoControls which docs are disabled when NODE_ENV=production
docsPathstring'/documentation'NoPath appended to each prefix for the Swagger UI
activebooleantrueNoSet false to disable the plugin entirely

DocConfig

NameTypeDefaultRequiredDescription
prefixstringYesRoute prefix to document (e.g. '/api', '/admin')
titlestringYesTitle shown in the Swagger UI header
access'public' | 'private'Yes'private' requires Basic Auth to view the docs
versionstring'1.0.0'NoAPI version shown in the spec info
descriptionstringAuto-generatedNoDescription shown in the spec info

Environment Controls

The disableInProduction option controls doc availability when NODE_ENV === 'production':

ValueDevelopmentProduction
falseAll docs enabledAll docs enabled
trueAll docs enabledAll docs disabled
'public'All docs enabledOnly 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.

ErrorTrigger
[xSwagger] At least one doc configuration is requireddocs missing, empty, or not an array
[xSwagger] docs[N].prefix is required and must be a stringMissing or non-string prefix
[xSwagger] docs[N].title is required and must be a stringMissing or non-string title
[xSwagger] docs[N].access must be 'public' or 'private'Invalid access level
[xSwagger] docs[N].version must be a stringNon-string version
[xSwagger] docs[N].description must be a stringNon-string description
[xSwagger] auth.username and auth.password are required when using private docsPrivate docs without valid auth
[xSwagger] docsPath must be a non-empty stringInvalid docsPath
[xSwagger] disableInProduction must be true, false, or 'public'Invalid disableInProduction value

Environment Variables

VariableRequiredDescription
NODE_ENVNoSet to 'production' to activate disableInProduction behavior
DOCS_USERWhen private docsUsername for Basic Auth — pass as auth.username
DOCS_PASSWORDWhen private docsPassword 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)
Copyright © 2026