or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

decorators.mddocument-builder.mdindex.mdinterfaces.mdswagger-module.mdtype-helpers.md

swagger-module.mddocs/

0

# SwaggerModule

1

2

The **SwaggerModule** class is the main integration point between NestJS applications and Swagger UI. It provides static methods for creating OpenAPI documents from your NestJS application metadata and setting up interactive Swagger UI documentation interfaces.

3

4

## Class Overview

5

6

```typescript { .api }

7

import { SwaggerModule } from '@nestjs/swagger';

8

9

class SwaggerModule {

10

static createDocument(

11

app: INestApplication,

12

config: Omit<OpenAPIObject, 'paths'>,

13

options?: SwaggerDocumentOptions

14

): OpenAPIObject;

15

16

static setup(

17

path: string,

18

app: INestApplication,

19

documentOrFactory: OpenAPIObject | (() => OpenAPIObject),

20

options?: SwaggerCustomOptions

21

): void;

22

23

static loadPluginMetadata(

24

metadataFn: () => Promise<Record<string, any>>

25

): Promise<void>;

26

}

27

```

28

29

## Document Creation

30

31

### createDocument { .api }

32

33

```typescript

34

static createDocument(

35

app: INestApplication,

36

config: Omit<OpenAPIObject, 'paths'>,

37

options?: SwaggerDocumentOptions

38

): OpenAPIObject

39

```

40

41

Creates a complete OpenAPI document by scanning the NestJS application for controllers, decorators, and metadata, then combining it with the provided configuration.

42

43

**Parameters:**

44

- `app`: The NestJS application instance

45

- `config`: OpenAPI document configuration (typically from DocumentBuilder)

46

- `options`: Optional document generation options

47

48

**Type Definitions:**

49

```typescript

50

interface SwaggerDocumentOptions {

51

include?: Function[];

52

extraModels?: Function[];

53

ignoreGlobalPrefix?: boolean;

54

deepScanRoutes?: boolean;

55

operationIdFactory?: OperationIdFactory;

56

linkNameFactory?: (controllerKey: string, methodKey: string, fieldKey: string) => string;

57

autoTagControllers?: boolean;

58

}

59

60

type OperationIdFactory = (

61

controllerKey: string,

62

methodKey: string,

63

version?: string

64

) => string;

65

```

66

67

**Basic Usage:**

68

```typescript

69

import { NestFactory } from '@nestjs/core';

70

import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';

71

import { AppModule } from './app.module';

72

73

async function bootstrap() {

74

const app = await NestFactory.create(AppModule);

75

76

const config = new DocumentBuilder()

77

.setTitle('My API')

78

.setDescription('API description')

79

.setVersion('1.0')

80

.build();

81

82

const document = SwaggerModule.createDocument(app, config);

83

84

// Document now contains all paths, schemas, and operations

85

console.log(document.paths); // All endpoint definitions

86

console.log(document.components); // All schema definitions

87

}

88

```

89

90

**Advanced Usage with Options:**

91

```typescript

92

import { ProductModule, UserModule } from './modules';

93

import { BaseDto, ErrorDto } from './common/dto';

94

95

const document = SwaggerModule.createDocument(app, config, {

96

// Only include specific modules

97

include: [ProductModule, UserModule],

98

99

// Add extra models that aren't automatically discovered

100

extraModels: [BaseDto, ErrorDto],

101

102

// Scan imported modules deeply

103

deepScanRoutes: true,

104

105

// Custom operation ID generation

106

operationIdFactory: (controllerKey, methodKey, version) => {

107

return `${controllerKey.toLowerCase()}_${methodKey}_v${version || '1'}`;

108

},

109

110

// Custom link name generation for OpenAPI links

111

linkNameFactory: (controllerKey, methodKey, fieldKey) => {

112

return `link_${controllerKey}_${methodKey}_${fieldKey}`;

113

},

114

115

// Disable automatic tag generation from controller names

116

autoTagControllers: false,

117

118

// Ignore global prefix for this documentation

119

ignoreGlobalPrefix: true

120

});

121

```

122

123

## Swagger UI Setup

124

125

### setup { .api }

126

127

```typescript

128

static setup(

129

path: string,

130

app: INestApplication,

131

documentOrFactory: OpenAPIObject | (() => OpenAPIObject),

132

options?: SwaggerCustomOptions

133

): void

134

```

135

136

Sets up Swagger UI at the specified path, serving both the interactive documentation interface and the raw OpenAPI specification in JSON/YAML formats.

137

138

**Parameters:**

139

- `path`: URL path where Swagger UI will be served

140

- `app`: The NestJS application instance

141

- `documentOrFactory`: OpenAPI document or factory function to generate it

142

- `options`: Extensive customization options for Swagger UI

143

144

**Type Definitions:**

145

```typescript

146

interface SwaggerCustomOptions {

147

useGlobalPrefix?: boolean;

148

ui?: boolean;

149

raw?: boolean | Array<'json' | 'yaml'>;

150

swaggerUrl?: string;

151

jsonDocumentUrl?: string;

152

yamlDocumentUrl?: string;

153

patchDocumentOnRequest?: <TRequest = any, TResponse = any>(

154

req: TRequest,

155

res: TResponse,

156

document: OpenAPIObject

157

) => OpenAPIObject;

158

explorer?: boolean;

159

swaggerOptions?: SwaggerUiOptions;

160

customCss?: string;

161

customCssUrl?: string | string[];

162

customJs?: string | string[];

163

customJsStr?: string | string[];

164

customfavIcon?: string;

165

customSiteTitle?: string;

166

customSwaggerUiPath?: string;

167

}

168

```

169

170

**Basic Setup:**

171

```typescript

172

const config = new DocumentBuilder()

173

.setTitle('E-Commerce API')

174

.setVersion('1.0')

175

.build();

176

177

const document = SwaggerModule.createDocument(app, config);

178

179

// Serve Swagger UI at /api-docs

180

SwaggerModule.setup('api-docs', app, document);

181

182

// Now available at:

183

// http://localhost:3000/api-docs - Swagger UI interface

184

// http://localhost:3000/api-docs-json - JSON specification

185

// http://localhost:3000/api-docs-yaml - YAML specification

186

```

187

188

**Advanced Customization:**

189

```typescript

190

SwaggerModule.setup('api-docs', app, document, {

191

// Use global prefix if app.setGlobalPrefix() was called

192

useGlobalPrefix: true,

193

194

// Customize document URLs

195

jsonDocumentUrl: '/api/v1/spec.json',

196

yamlDocumentUrl: '/api/v1/spec.yaml',

197

198

// Enable OpenAPI definition selector in UI

199

explorer: true,

200

201

// Swagger UI customization

202

swaggerOptions: {

203

// Keep authorization when page refreshes

204

persistAuthorization: true,

205

// Display request duration

206

displayRequestDuration: true,

207

// Expand operations by default

208

docExpansion: 'list',

209

// Try it out enabled by default

210

tryItOutEnabled: true,

211

// Show/hide request examples

212

requestInterceptor: (req) => {

213

console.log('Request:', req);

214

return req;

215

}

216

},

217

218

// Custom styling

219

customSiteTitle: 'E-Commerce API Documentation',

220

customfavIcon: '/favicon.ico',

221

customCss: `

222

.topbar-wrapper { display: none; }

223

.swagger-ui .info { margin: 20px 0; }

224

`,

225

customCssUrl: [

226

'https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap'

227

],

228

229

// Dynamic document patching per request

230

patchDocumentOnRequest: (req, res, document) => {

231

// Add user-specific info or filter content based on request

232

const userRole = req.headers['x-user-role'];

233

234

if (userRole !== 'admin') {

235

// Remove admin-only paths

236

const filteredPaths = {};

237

Object.keys(document.paths).forEach(path => {

238

if (!path.includes('/admin/')) {

239

filteredPaths[path] = document.paths[path];

240

}

241

});

242

document.paths = filteredPaths;

243

}

244

245

return document;

246

}

247

});

248

```

249

250

**Document Factory Pattern:**

251

```typescript

252

// Use factory for dynamic document generation

253

SwaggerModule.setup('api-docs', app, () => {

254

const config = new DocumentBuilder()

255

.setTitle('Dynamic API')

256

.setVersion(process.env.API_VERSION || '1.0')

257

.setDescription(`Built at: ${new Date().toISOString()}`)

258

.build();

259

260

return SwaggerModule.createDocument(app, config);

261

}, {

262

customSiteTitle: 'Dynamic API Documentation'

263

});

264

```

265

266

## Selective Serving Options

267

268

### UI and Raw Document Control

269

270

```typescript

271

// Serve only Swagger UI (no raw JSON/YAML endpoints)

272

SwaggerModule.setup('docs', app, document, {

273

ui: true,

274

raw: false

275

});

276

277

// Serve only JSON specification (no UI or YAML)

278

SwaggerModule.setup('docs', app, document, {

279

ui: false,

280

raw: ['json']

281

});

282

283

// Serve UI and only YAML specification

284

SwaggerModule.setup('docs', app, document, {

285

ui: true,

286

raw: ['yaml']

287

});

288

289

// Disable everything (useful for conditional setup)

290

if (process.env.NODE_ENV !== 'production') {

291

SwaggerModule.setup('docs', app, document, {

292

ui: true,

293

raw: true

294

});

295

} else {

296

SwaggerModule.setup('docs', app, document, {

297

ui: false,

298

raw: false

299

});

300

}

301

```

302

303

## Plugin Metadata Loading

304

305

### loadPluginMetadata { .api }

306

307

```typescript

308

static loadPluginMetadata(

309

metadataFn: () => Promise<Record<string, any>>

310

): Promise<void>

311

```

312

313

Loads metadata from the Swagger TypeScript compiler plugin for enhanced automatic documentation generation.

314

315

**Usage:**

316

```typescript

317

// In your main.ts, before creating the document

318

await SwaggerModule.loadPluginMetadata(() =>

319

import('./swagger-plugin-metadata')

320

);

321

322

const document = SwaggerModule.createDocument(app, config);

323

SwaggerModule.setup('api', app, document);

324

```

325

326

## Complete Integration Examples

327

328

### Production-Ready Setup

329

330

```typescript

331

import { NestFactory } from '@nestjs/core';

332

import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';

333

import { AppModule } from './app.module';

334

335

async function bootstrap() {

336

const app = await NestFactory.create(AppModule);

337

338

// Set global prefix

339

app.setGlobalPrefix('api/v1');

340

341

// Load plugin metadata for enhanced documentation

342

if (process.env.NODE_ENV !== 'production') {

343

try {

344

await SwaggerModule.loadPluginMetadata(() =>

345

import('./swagger-plugin-metadata')

346

);

347

} catch (error) {

348

console.warn('Could not load Swagger plugin metadata:', error.message);

349

}

350

}

351

352

// Create comprehensive document configuration

353

const config = new DocumentBuilder()

354

.setTitle('E-Commerce Platform API')

355

.setDescription('Comprehensive e-commerce platform REST API')

356

.setVersion('2.0.0')

357

.setContact('API Team', 'https://example.com/contact', 'api@example.com')

358

.setLicense('MIT', 'https://opensource.org/licenses/MIT')

359

.addServer('https://api.example.com', 'Production')

360

.addServer('https://staging-api.example.com', 'Staging')

361

.addBearerAuth()

362

.addApiKey({ type: 'apiKey', in: 'header', name: 'X-API-Key' })

363

.addTag('Authentication', 'User authentication and authorization')

364

.addTag('Products', 'Product catalog management')

365

.addTag('Orders', 'Order processing and fulfillment')

366

.build();

367

368

// Generate document with advanced options

369

const document = SwaggerModule.createDocument(app, config, {

370

deepScanRoutes: true,

371

autoTagControllers: true,

372

operationIdFactory: (controllerKey, methodKey, version) =>

373

`${controllerKey}_${methodKey}${version ? `_v${version}` : ''}`,

374

});

375

376

// Setup with extensive customization

377

SwaggerModule.setup('docs', app, document, {

378

useGlobalPrefix: true,

379

explorer: true,

380

swaggerOptions: {

381

persistAuthorization: true,

382

displayRequestDuration: true,

383

filter: true,

384

showExtensions: true,

385

showCommonExtensions: true,

386

docExpansion: 'list'

387

},

388

customSiteTitle: 'E-Commerce API - Interactive Documentation',

389

customfavIcon: 'https://example.com/favicon.ico',

390

customCss: `

391

.swagger-ui .topbar { display: none; }

392

.swagger-ui .info .title { color: #1f2937; }

393

`,

394

customCssUrl: 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600',

395

});

396

397

await app.listen(3000);

398

399

console.log(`Application is running on: ${await app.getUrl()}`);

400

console.log(`Swagger UI available at: ${await app.getUrl()}/api/v1/docs`);

401

}

402

403

bootstrap();

404

```

405

406

### Multi-Version API Setup

407

408

```typescript

409

async function setupMultiVersionDocs(app: INestApplication) {

410

// V1 API Documentation

411

const v1Config = new DocumentBuilder()

412

.setTitle('API v1')

413

.setVersion('1.0')

414

.addBearerAuth()

415

.build();

416

417

const v1Document = SwaggerModule.createDocument(app, v1Config, {

418

include: [V1Module],

419

ignoreGlobalPrefix: true

420

});

421

422

SwaggerModule.setup('docs/v1', app, v1Document);

423

424

// V2 API Documentation

425

const v2Config = new DocumentBuilder()

426

.setTitle('API v2')

427

.setVersion('2.0')

428

.addBearerAuth()

429

.addOAuth2()

430

.build();

431

432

const v2Document = SwaggerModule.createDocument(app, v2Config, {

433

include: [V2Module],

434

ignoreGlobalPrefix: true

435

});

436

437

SwaggerModule.setup('docs/v2', app, v2Document);

438

439

// Combined documentation with version selector

440

const combinedConfig = new DocumentBuilder()

441

.setTitle('Multi-Version API')

442

.setVersion('latest')

443

.addBearerAuth()

444

.build();

445

446

const combinedDocument = SwaggerModule.createDocument(app, combinedConfig, {

447

include: [V1Module, V2Module],

448

deepScanRoutes: true

449

});

450

451

SwaggerModule.setup('docs', app, combinedDocument, {

452

explorer: true,

453

swaggerOptions: {

454

urls: [

455

{ url: '/docs/v1-json', name: 'API v1' },

456

{ url: '/docs/v2-json', name: 'API v2' }

457

]

458

}

459

});

460

}

461

```

462

463

### Environment-Based Configuration

464

465

```typescript

466

function setupSwaggerBasedOnEnvironment(app: INestApplication, document: OpenAPIObject) {

467

const isDevelopment = process.env.NODE_ENV === 'development';

468

const isStaging = process.env.NODE_ENV === 'staging';

469

const isProduction = process.env.NODE_ENV === 'production';

470

471

if (isDevelopment) {

472

// Full-featured documentation for development

473

SwaggerModule.setup('api-docs', app, document, {

474

explorer: true,

475

swaggerOptions: {

476

persistAuthorization: true,

477

displayRequestDuration: true,

478

tryItOutEnabled: true

479

},

480

customSiteTitle: 'Dev API Documentation'

481

});

482

} else if (isStaging) {

483

// Limited documentation for staging

484

SwaggerModule.setup('docs', app, document, {

485

explorer: false,

486

swaggerOptions: {

487

tryItOutEnabled: false

488

},

489

customSiteTitle: 'Staging API Documentation'

490

});

491

} else if (isProduction) {

492

// Minimal or no documentation for production

493

if (process.env.ENABLE_DOCS === 'true') {

494

SwaggerModule.setup('internal-docs', app, document, {

495

ui: true,

496

raw: ['json'], // Only JSON, no YAML

497

swaggerOptions: {

498

tryItOutEnabled: false,

499

supportedSubmitMethods: [] // Disable try-it-out

500

},

501

customSiteTitle: 'Internal API Documentation'

502

});

503

}

504

// Otherwise, no Swagger setup in production

505

}

506

}

507

```

508

509

The SwaggerModule provides powerful, flexible integration between NestJS applications and Swagger UI, supporting everything from basic documentation needs to sophisticated multi-version, multi-environment setups with extensive customization options.