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():
// 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
}npx nestjs-docfy export --entry docfy-export.ts --out openapi.jsonInformational output always goes to stderr, never stdout — 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
| Option | Default | Description |
|---|---|---|
--entry <path> | (required) | .ts/.js file whose default export returns { app, document } |
--out <path> | stdout | Where to write the document |
--root <path> | . | Project root — where ts-node/tsconfig-paths are resolved from |
--quiet | false | Suppress informational output |
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.