@asiones/api-client-generator
v2.8.7
Published
Generate API client code from Swagger JSON
Maintainers
Readme
API Client Generator
A TypeScript tool to generate API client code from Swagger JSON specifications using Zod for type validation and TS-Morph for code generation.
✨ Features
- 🚀 Incremental Updates - Smart diff-based generation with WebStorm integration
- 🔧 Full Overwrite Mode - Complete regeneration with automatic backup
- 🌐 URL Support - Download Swagger specs from URLs with basic authentication
- 📦 Template System - NPM package includes template files for initialization
- 🎯 Type-Safe - Generates TypeScript interfaces with Zod validation
- 🔄 Smart Dependencies - Automatic type dependency resolution and imports
- 📝 Complete Coverage - Supports all HTTP methods (GET, POST, PUT, DELETE)
- 🎬 Server Actions - Generates Next.js server actions with error handling
- 🏗️ Modular Structure - Organized by API tags with proper file structure
- 🤖 Virtual Response Types - Handles unknown responses with unified type system
📦 Installation
npm install -g @asiones/api-client-generatorOr use with npx:
npx @asiones/api-client-generator <swagger-json-path> <output-path>🚀 Usage
Basic Commands
# Incremental update (default)
api-client-generator ./swagger.json ./output
# Full overwrite with backup
api-client-generator ./swagger.json ./output --overwrite
# Using npx
npx @asiones/api-client-generator ./swagger.json ./outputCommand Options
--overwrite,-o: Overwrite mode - removes existing folders and regenerates from template (creates backup)--username <user>: Username for HTTP basic authentication (when downloading from URL)--password <pass>: Password for HTTP basic authentication (when downloading from URL)--help,-h: Show help message
URL Download Support
Download Swagger specifications directly from URLs:
# From URL without authentication
api-client-generator https://api.example.com/swagger.json ./output
# From URL with basic authentication
api-client-generator https://api.example.com/swagger.json ./output --username myuser --password mypass🔄 Response Type Handling
Unified Virtual Response System
The generator now uses a unified approach for handling all response types:
- Known Responses: API responses with defined schemas generate typed response schemas
- 204 No Content: Generates
EmptyResponsetype usingApiResponseWithDataSchema(z.any()) - Unknown Responses: Generates
UnknownResponsetype usingApiResponseWithDataSchema(z.any()) - All Empty Responses: Use
ApiResponseWithDataSchemainstead of plainApiResponseSchema
This ensures consistent type structure across all response scenarios while maintaining type safety.
Generated Response Types
// For known API responses
export const UserProfileResponseSchema = ApiResponseWithDataSchema(UserProfileSchema);
export type UserProfileResponse = z.infer<typeof UserProfileResponseSchema>;
// For unknown/empty responses
export const UnknownResponseSchema = ApiResponseWithDataSchema(z.any());
export type UnknownResponse = z.infer<typeof UnknownResponseSchema>;
export const EmptyResponseSchema = ApiResponseWithDataSchema(z.any());
export type EmptyResponse = z.infer<typeof EmptyResponseSchema>;🔄 Generation Modes
1. Incremental Mode (Default)
Smart generation that only updates changed files:
api-client-generator ./swagger.json ./outputFeatures:
- Detects file changes using hash comparison
- Opens WebStorm merge tools for review
- Preserves manual modifications
- Only processes changed files
Requirements for Incremental Mode:
- WebStorm installed and configured
- Command line tools enabled:
Tools > Create Command-line Launcher
2. Overwrite Mode
Complete regeneration with backup:
api-client-generator ./swagger.json ./output --overwriteFeatures:
- Creates timestamped backup (
.backup-YYYY-MM-DD-HH-mm-ss) - Removes src, types, utils, actions folders
- Copies fresh template files
- Performs complete generation
📁 Generated Structure
output/
├── template/ # Template files (copied from NPM package)
│ ├── src/index.ts.template
│ ├── types/utils.ts.template
│ └── utils/index.ts.template
├── types/ # Generated type definitions
│ ├── utils.ts # Common response types
│ ├── common.ts # Shared types
│ ├── user.ts # User-related types
│ └── analysis.ts # Analysis-related types
├── src/ # API client classes
│ ├── index.ts # Main API client with all sub-clients
│ ├── client.ts # Base HTTP client
│ ├── user-client.ts # User API methods
│ └── analysis-client.ts # Analysis API methods
├── utils/ # Utility functions
│ └── index.ts # Action result handlers
└── actions/ # Next.js server actions
├── user.ts # User server actions
└── analysis.ts # Analysis server actions📝 Generated Code Examples
1. Type Definitions (types/user.ts)
import { z } from 'zod';
import { ApiResponseSchema, ApiResponseWithDataSchema } from './utils';
// Schema definition
export const UserProfileSchema = z.object({
id: z.number(),
username: z.string(),
email: z.string(),
avatar: z.string().optional(),
});
// Response schema
export const UserProfileResponseSchema = ApiResponseWithDataSchema(UserProfileSchema);
// TypeScript types
export type UserProfile = z.infer<typeof UserProfileSchema>;
export type UserProfileResponse = z.infer<typeof UserProfileResponseSchema>;2. API Client (src/user-client.ts)
import type { ApiClient } from './client';
import type { UserProfile, UserProfileResponse } from '../types/user';
export class UserClient {
private client: ApiClient;
constructor(client: ApiClient) {
this.client = client;
}
/**
* Get user profile
*/
getProfile(): Promise<UserProfileResponse> {
return this.client.get<UserProfileResponse>('/api/user/profile');
}
/**
* Update user profile
*/
updateProfile(params: UserProfile): Promise<UserProfileResponse> {
return this.client.put<UserProfileResponse>('/api/user/profile', params);
}
}3. Server Actions (actions/user.ts)
'use server'
import { getApiClient } from '@/src';
import { handleActionResult } from '@/utils';
import type { UserProfile } from '@/types/user';
const api = getApiClient()
/**
* Get user profile
*/
export async function fetchGetProfileAction() {
return handleActionResult(await api.user.getProfile())
}
/**
* Update user profile
*/
export async function fetchUpdateProfileAction(params: UserProfile) {
return handleActionResult(await api.user.updateProfile(params))
}4. Main Client (src/index.ts)
import { ApiClient, type ApiClientConfig } from './client';
import { UserClient } from './user-client';
import { AnalysisClient } from './analysis-client';
export class EasyJobApiClient {
private readonly client: ApiClient;
// Auto-generated client properties
user: UserClient;
analysis: AnalysisClient;
constructor(config: ApiClientConfig) {
this.client = new ApiClient({
...config,
getTokenFn: async () => '',
refreshTokenFn: async () => '',
onUnauthorized: async () => '',
});
// Auto-generated client initialization
this.user = new UserClient(this.client);
this.analysis = new AnalysisClient(this.client);
}
}
export function getApiClient(configParam?: ApiClientConfig): EasyJobApiClient {
// Client configuration logic
return new EasyJobApiClient(finalConfig);
}🎯 Smart Features
Template System
- NPM package includes template files
- Missing files are automatically copied from templates
- Templates use
.templateextension and are renamed to.ts
Type Organization
- Types are organized by API tags (first path segment after
/api/) - Common types are placed in
common.ts - Cross-file dependencies are automatically resolved
Naming Conventions
- Swagger definition
user.Profile→UserProfile - API path
/api/user/profile→ methodgetProfile - Client classes:
{Tag}Client(e.g.,UserClient)
Query Parameters
- Automatically generates query parameter types
- Naming:
{Tag}{Path}QueryParams - Supports optional and required parameters
⚙️ Configuration
Path Aliases Support
The generator reads tsconfig.json for path alias configuration:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@types/*": ["./types/*"]
}
}
}WebStorm Integration
For incremental updates, ensure WebStorm command-line tools are configured:
- Install WebStorm
- Enable command-line launcher:
Tools > Create Command-line Launcher - Verify:
webstorm --helpshould work in terminal
🔧 Requirements
- Node.js 18+
- TypeScript 5.0+
- Dependencies: ts-morph ^26.0.0, zod ^3.22.4
- WebStorm (for incremental mode)
📋 API Support
HTTP Methods
- ✅ GET - Query parameters and path parameters
- ✅ POST - Request body and response handling
- ✅ PUT - Full resource updates
- ✅ DELETE - Resource deletion
Response Types
- ✅ Standard API responses with data
- ✅ Paginated responses
- ✅ Empty responses (204 No Content)
- ✅ Unknown responses (unified virtual types)
- ✅ Error responses
Type Features
- ✅ Nested object types
- ✅ Array types with item validation
- ✅ Enum types
- ✅ Optional properties
- ✅ Union types (oneOf/anyOf)
- ✅ Merged types (allOf)
🐛 Troubleshooting
Common Issues
WebStorm not found
# Ensure WebStorm CLI is installed webstorm --helpTemplate files missing
# Check NPM package installation npm list @asiones/api-client-generatorType import errors
- Verify
tsconfig.jsonpath aliases - Check file structure matches expected layout
- Verify
Generation fails
- Validate Swagger JSON format
- Check URL accessibility and authentication
- Ensure output directory is writable
- Check Node.js version (18+ required)
Debug Mode
# Enable detailed logging
DEBUG=1 api-client-generator ./swagger.json ./output📄 License
MIT
🤝 Contributing
- Fork the repository
- Create your feature branch
- Commit your changes
- Push to the branch
- Create a Pull Request
📞 Support
- 🐛 Issues: GitHub Issues
- 📧 Email: [email protected]
- 📖 Documentation: Full Documentation
