Introduction
OpenAPI schemas can generate client SDKs, type definitions, and mock servers. This enables type-safe API clients and ensures frontend/backend stay in sync.
Key Concepts
- Schema Export: Save OpenAPI spec as JSON/YAML
- Code Generation: Generate typed clients from schema
- Schema Validation: Validate requests/responses against spec
- Mock Server: Generate mock API from schema
Real World Context
Schema generation enables:
- Type-safe frontend API clients
- Mobile app SDK generation
- Contract testing
- Documentation portals
Deep Dive
Export OpenAPI Schema
Write the generated OpenAPI document to a JSON file during bootstrap for downstream tooling.
typescriptasync function bootstrap() { const app = await NestFactory.create(AppModule); const config = new DocumentBuilder() .setTitle('API') .setVersion('1.0') .build(); const document = SwaggerModule.createDocument(app, config); // Export to file const fs = require('fs'); fs.writeFileSync('./openapi.json', JSON.stringify(document, null, 2)); SwaggerModule.setup('api', app, document); await app.listen(3000); }
The exported openapi.json can be consumed by code generators, linters, and CI validation tools.
Generate TypeScript Client
Use openapi-generator-cli to produce a fully typed API client from the exported schema.
bashnpm install -g openapi-generator-cli # Generate TypeScript Axios client openapi-generator-cli generate \ -i openapi.json \ -g typescript-axios \ -o ./generated/api-client
The -g typescript-axios flag selects the Axios-based TypeScript generator; other options include typescript-fetch and typescript-node.
Usage of Generated Client
Import the generated API class and configuration to make type-safe requests with full autocomplete.
typescriptimport { UsersApi, Configuration } from './generated/api-client'; const config = new Configuration({ basePath: 'http://localhost:3000', accessToken: 'your-jwt-token', }); const usersApi = new UsersApi(config); // Type-safe API calls const users = await usersApi.usersControllerFindAll(); const user = await usersApi.usersControllerFindOne({ id: '123' });
Method names follow the pattern controllerNameMethodName, derived from your NestJS controller and method names.
Programmatic Schema Access
Create a standalone script that boots the app, extracts the schema, and shuts down without starting the HTTP server.
typescript// Script to generate schema on build import { NestFactory } from '@nestjs/core'; import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; import { AppModule } from './app.module'; import * as fs from 'fs'; async function generateSchema() { const app = await NestFactory.create(AppModule, { logger: false }); await app.init(); const config = new DocumentBuilder() .setTitle('API') .setVersion('1.0') .build(); const document = SwaggerModule.createDocument(app, config); fs.writeFileSync('./dist/openapi.json', JSON.stringify(document, null, 2)); await app.close(); console.log('OpenAPI schema generated'); } generateSchema();
Using app.init() instead of app.listen() loads all modules without binding a port, which is faster for CI.
NPM Script Integration
Automate schema generation and client code generation as part of your build pipeline.
json// package.json { "scripts": { "build": "nest build", "postbuild": "ts-node scripts/generate-schema.ts", "generate:client": "openapi-generator-cli generate -i dist/openapi.json -g typescript-axios -o ../frontend/src/api" } }
The postbuild hook ensures the schema is always regenerated after compilation.
Schema Validation Middleware
Add request and response validation against the OpenAPI spec to catch contract violations in development.
typescriptimport * as OpenApiValidator from 'express-openapi-validator'; app.use( OpenApiValidator.middleware({ apiSpec: './openapi.json', validateRequests: true, validateResponses: true, }), );
Enabling validateResponses catches cases where your code returns fields not documented in the schema.
Common Pitfalls
- Stale schema: Regenerate on every build.
- Missing models: Ensure all DTOs are included.
- Version mismatch: Keep schema version in sync with API.
Best Practices
- Generate schema as part of build process
- Version schemas alongside API versions
- Use generated clients in frontend projects
- Validate requests/responses in development
- Store schemas in version control
Summary
OpenAPI schemas enable type-safe client generation. Export schemas during build, generate clients with openapi-generator-cli, and validate requests/responses. This ensures frontend and backend stay synchronized.
Code Examples
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const config = new DocumentBuilder()
.setTitle('API')
.setVersion('1.0')
.build();
const document = SwaggerModule.createDocument(app, config);
// Export to file
const fs = require('fs');
fs.writeFileSync('./openapi.json', JSON.stringify(document, null, 2));
SwaggerModule.setup('api', app, document);
await app.listen(3000);
}