docfy export

Boots the project's own Nest app and writes the OpenAPI document, without binding a port or needing live infrastructure.

Why it exists

The one thing SwaggerModule.createDocument() structurally needs is a fully-initialized Nest app: its DI container has to resolve every provider before route and DTO metadata exists to introspect.

That does not require .listen(). No port gets bound.

In practice it usually doesn't need live infrastructure either: most TypeOrmModule, ioredis, and kafkajs clients connect lazily rather than blocking bootstrap, so export tends to work with the database, Redis, and Kafka all stopped.

Usage

Provide a small entry file (the same lines your main.ts already has, minus .listen()):

ts
// docfy-export.ts
import { NestFactory } from '@nestjs/core';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { AppModule } from './app.module';

export default async function () {
  const app = await NestFactory.create(AppModule, { logger: false });
  const config = new DocumentBuilder().setTitle('My API').setVersion('1.0.0').build();
  const document = SwaggerModule.createDocument(app, config);
  return { app, document }; // `app` gets closed for you afterward
}
bash
npx nestjs-docfy export --entry docfy-export.ts --out openapi.json

Informational output always goes to stderr, never stdout, so it's safe to pipe: npx nestjs-docfy export --entry docfy-export.ts > openapi.json.

The entry file contract

The default export is an async function returning { app, document }. export runs it in a spawned child process, serializes document, and calls app.close() for you afterward.

A .ts entry needs ts-node as a devDependency of your project (and tsconfig-paths too, for path aliases like @app/common).

Options

OptionDefaultDescription
--entry <path>(required).ts/.js file whose default export returns { app, document }
--out <path>stdoutWhere to write the document
--root <path>.Project root — where ts-node/tsconfig-paths are resolved from
--quietfalseSuppress informational output
When this doesn't help

A provider with a genuinely eager, hard-failing connection in its constructor or onModuleInit won't benefit from skipping infra this way. Nothing in export can change how your own providers connect. It only avoids the one thing NestJS itself doesn't need: an open port.