Generate the TypeScript OpenAPI client library from the NestJS backend API specifications, ensuring type-safe communication between frontend and backend applications.
Generate a TypeScript OpenAPI client from your NestJS backend specifications. Use this after modifying backend APIs to maintain type-safe communication between frontend and backend. Run with `--validate` to check specs before generation or `--watch` to auto-regenerate on changes.
/plugin marketplace add hubexab/EAF-PluginClaude/plugin install exfabrica-af-plugin@exfabrica-af-marketplaceGenerate the TypeScript OpenAPI client library from the NestJS backend API specifications, ensuring type-safe communication between frontend and backend applications.
/generate-api-client [--watch] [--validate]
This command automates the process of generating a type-safe API client for the frontend to consume the backend API. It:
@bdqt/api-client shared libraryWhen you execute this command, Claude will:
Backend API Specification Extraction
/api-docs)Specification Validation (if --validate is used)
Client Generation
Library Update
libs/api-client/src/ with generated codeVerification
/generate-api-client
Generates the API client from the current backend specification.
/generate-api-client --validate
Validates the OpenAPI spec before generating the client.
/generate-api-client --watch
Continuously regenerates the client when backend API changes are detected.
The command generates code in the libs/api-client/ workspace:
libs/api-client/
├── src/
│ ├── api/
│ │ ├── users.api.ts # Users API endpoints
│ │ ├── auth.api.ts # Authentication endpoints
│ │ └── index.ts # API exports
│ ├── models/
│ │ ├── user.model.ts # User model interface
│ │ ├── auth.model.ts # Auth-related models
│ │ └── index.ts # Model exports
│ ├── client.ts # HTTP client configuration
│ ├── configuration.ts # API configuration
│ └── index.ts # Main exports
├── package.json
└── tsconfig.json
After generation, the frontend can use the type-safe client:
// Frontend service example
import { UsersApi, CreateUserDto, User } from '@bdqt/api-client';
@Injectable()
export class UserService {
private usersApi: UsersApi;
constructor(private http: HttpClient) {
this.usersApi = new UsersApi(http);
}
async createUser(data: CreateUserDto): Promise<User> {
// Full type safety - TypeScript knows all properties
return this.usersApi.createUser(data).toPromise();
}
}
Ensure your NestJS controllers use proper decorators:
@Controller('users')
@ApiTags('users')
export class UsersController {
@Post()
@ApiOperation({ summary: 'Create a new user' })
@ApiResponse({ status: 201, description: 'User created', type: User })
@ApiResponse({ status: 400, description: 'Invalid input' })
async create(@Body() createUserDto: CreateUserDto): Promise<User> {
return this.usersService.create(createUserDto);
}
}
Ensure your NestJS backend has Swagger configured (typically in main.ts):
// apps/backend/src/main.ts
const config = new DocumentBuilder()
.setTitle('ExFabrica AF API')
.setDescription('ExFabrica Agentic Factory API')
.setVersion('1.0')
.addBearerAuth()
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api-docs', app, document);
Located in libs/api-client/openapitools.json:
{
"generator-cli": {
"version": "6.2.0",
"generators": {
"typescript-angular": {
"inputSpec": "../../apps/backend/openapi.json",
"output": "./src",
"generatorName": "typescript-axios",
"additionalProperties": {
"npmName": "@bdqt/api-client",
"supportsES6": true,
"withInterfaces": true,
"useSingleRequestParameter": true
}
}
}
}
}
🔧 Generating API Client
========================
✓ Backend API started on http://localhost:3000
✓ OpenAPI specification downloaded
✓ Specification validated (OpenAPI 3.0.3)
✓ Found 24 endpoints across 5 controllers
✓ Client code generated successfully
✓ TypeScript compilation successful
✓ Generated 24 API methods, 18 models
Summary:
--------
Endpoints: 24
Models: 18
Generated Files: 42
Size: 187 KB
Duration: 8.3s
The API client has been updated successfully! ✓
Updated workspace: @bdqt/api-client
⚠️ Validation Warnings
-----------------------
1. Missing response type for DELETE /api/users/:id
Location: UsersController.remove()
Recommendation: Add @ApiResponse decorator
2. DTO missing property descriptions
Location: CreateUserDto
Affected: email, password, firstName, lastName
Recommendation: Add @ApiProperty({ description: '...' })
3. Deprecated endpoint still in use
Location: GET /api/auth/legacy-login
Recommendation: Remove or mark with @Deprecated
Client generated successfully, but consider fixing these warnings.
When running with --watch, the command monitors:
*.controller.ts files in backend*.dto.ts files in backendOn detecting changes:
Error: Cannot start backend server
Solution: Ensure backend dependencies are installed and database is running
yarn install
docker compose up -d
Error: Invalid OpenAPI specification
Solution: Check backend controller decorators and DTOs
Error: Failed to generate TypeScript types
Solution: Update OpenAPI generator version
cd libs/api-client
yarn add -D @openapitools/openapi-generator-cli@latest
Error: Circular reference in User -> Profile -> User
Solution: Restructure models or use lazy imports
// Use string reference instead of direct import
@ApiProperty({ type: () => 'Profile' })
profile?: Profile;
Error: Cannot find 'Authorization' header type
Solution: Add authentication configuration to OpenAPI setup
.addBearerAuth({ type: 'http', scheme: 'bearer', bearerFormat: 'JWT' })
The command detects breaking changes between versions:
Breaking Changes
Non-Breaking Changes
If breaking changes are detected, you'll receive a warning and recommendations for migration.
Regenerate after backend API changes
# After modifying backend controllers/DTOs
/generate-api-client --validate
Use watch mode during active development
/generate-api-client --watch
Commit generated client with backend changes
Document your API properly
@ApiOperation({
summary: 'Create user',
description: 'Creates a new user account with the provided details'
})
@ApiResponse({
status: 201,
description: 'User successfully created',
type: User
})
Version your API
/api/v1/users)/generate-api-client --validate
/test-all
/deploy staging
# Make backend changes
/generate-api-client
# Update frontend to use new types
/test-all frontend
- task: Script@1
displayName: 'Generate API Client'
inputs:
script: |
/generate-api-client --validate
- task: Script@1
displayName: 'Verify No Changes'
inputs:
script: |
git diff --exit-code libs/api-client/
# Fails if generated code differs (means it wasn't regenerated)
Modify libs/api-client/openapitools.json for custom generation:
{
"additionalProperties": {
"npmName": "@bdqt/api-client",
"supportsES6": true,
"withInterfaces": true,
"useSingleRequestParameter": true,
"modelPropertyNaming": "camelCase",
"enumPropertyNaming": "UPPERCASE"
}
}
Generate clients for different API versions:
/generate-api-client v1
/generate-api-client v2
Each version gets its own namespace:
@bdqt/api-client/v1@bdqt/api-client/v2/test-all - Test generated client integration/deploy - Deploy after client generation/analyze-code - Verify generated code quality✓ Type Safety: Full TypeScript typing across frontend-backend boundary ✓ Auto-completion: IDE support for all API methods and models ✓ Error Prevention: Catch API mismatches at compile time ✓ Documentation: Generated client includes JSDoc from backend ✓ Consistency: Single source of truth for API contracts ✓ Productivity: No manual API client maintenance
Note: Always regenerate the client after making changes to backend API endpoints, DTOs, or authentication schemes to maintain type safety across the monorepo.