OpenAPI TypeScript Request - AI Agent Guide
OpenAPI TypeScript Request is a powerful code generator that converts Swagger2/OpenAPI3/Apifox specifications into TypeScript/JavaScript client code with advanced features like React Query integration, mock services, type labels, and multi-client support.
Core Capabilities:
Generate TypeScript/JavaScript request functions from OpenAPI specs
Support multiple HTTP clients (axios, fetch, uniapp, taro, node-fetch)
Generate React Query / Vue Query hooks
Create mock services with realistic data
Generate Chinese type labels for forms
Support enum descriptions and translations
Generate JSON Schemas for validation
1. Project Type Detection
// Detect from package.json dependencies
if ( has ( "react" ) && has ( "@tanstack/react-query" ) ) {
recommend : { isGenReactQuery : true , reactQueryMode : "react" }
}
else if ( has ( "vue" ) && has ( "@tanstack/vue-query" ) ) {
recommend : { isGenReactQuery : true , reactQueryMode : "vue" }
}
else if ( has ( "@tarojs/taro" ) || has ( "@dcloudio/uni-app" ) ) {
recommend : { requestLibPath : "@/request" }
}
else if ( isNodeProject ) {
recommend : { requestLibPath : "node-fetch" }
}
2. Complete Configuration Reference
Configuration
Type
Default
Description
When to Use
schemaPath
string
-
OpenAPI/Swagger spec URL or file path
Use when providing OpenAPI spec URL/file path (mutually exclusive with apifoxConfig)
apifoxConfig
object
-
Apifox configuration
Use when fetching spec from Apifox (mutually exclusive with schemaPath)
serversPath
string
"./src/apis"
Output directory for generated files
Custom output location
requestLibPath
string
"axios"
HTTP client library path
Custom request client
full
boolean
true
Full replacement vs incremental
Incremental updates
enableLogging
boolean
false
Enable debug logging
Troubleshooting
Configuration
Type
Default
Description
When to Use
priorityRule
"include"|"exclude"|"both"
"include"
Filter strategy
Large APIs
filterCaseInsensitive
boolean
false
Case-insensitive tag/path matching
Mixed case APIs
includeTags
(string|RegExp)[]
-
Only generate these tags
Selective generation
includePaths
(string|RegExp)[]
-
Only generate these paths
Path-based filtering
excludeTags
(string|RegExp)[]
-
Skip these tags
Exclude unwanted APIs
excludePaths
(string|RegExp)[]
-
Skip these paths
Exclude specific endpoints
Configuration
Type
Default
Description
When to Use
isGenJavaScript
boolean
false
Generate JS instead of TS
JS-only projects
isGenReactQuery
boolean
false
Generate React/Vue Query hooks
Query-based apps
reactQueryMode
"react"|"vue"
"react"
Query hook framework
Vue projects
isDisplayTypeLabel
boolean
false
Generate Chinese field labels
Form applications
isGenJsonSchemas
boolean
false
Generate JSON Schema validation
Data validation
isOnlyGenTypeScriptType
boolean
false
Only types, no request functions
Type-only needs
isCamelCase
boolean
true
Use camelCase naming
Consistent naming
isSupportParseEnumDesc
boolean
false
Parse enum descriptions
Labeled enums
supportParseEnumDescByReg
string | RegExp
-
Custom regex for parsing enum descriptions. If set, replaces default parseDescriptionEnum method. Example: /([^\s=<>/&;]+(?:\s+[^\s=<>/&;]+)*)\s*=\s*(\d+)/g matches "普通 = 0" or "SampleMaker = 1"
Custom enum description formats
isSplitTypesByModule
boolean
false
Split types by module, generates {module}.type.ts, common.type.ts, enum.ts, types.ts
Large projects with many types
Configuration
Type
Default
Description
When to Use
requestOptionsType
string
"{ [key: string]: unknown }"
Type for request options
Custom options
requestImportStatement
string
-
Custom import statement
Custom request setup
apiPrefix
string|function
-
API path prefix
Namespaced APIs
dataFields
string[]
-
Response data field path
Nested response data
Configuration
Type
Default
Description
When to Use
isTranslateToEnglishTag
boolean
false
Translate Chinese tags to English
Chinese API docs
nullable
boolean
false
Use null instead of optional
Strict null checks
Configuration
Type
Default
Description
When to Use
mockFolder
string
-
Mock data output directory
Development with mocks
authorization
string
-
API documentation auth token
Protected docs
timeout
number
60000
Request timeout in ms
Slow APIs
Configuration
Type
Default
Description
When to Use
namespace
string
"API"
TypeScript namespace
Custom namespace
templatesFolder
string
-
Custom template directory
Custom templates
apifoxConfig
object
-
Apifox-specific configuration
Apifox integration
describe
string
-
description information
Using cli interactive operation mode
3. Feature Requirements Mapping
User Need
Configuration
Additional Notes
"生成中文字段标签"
isDisplayTypeLabel: true
For form field labels
"支持小程序开发"
requestLibPath: "@/request"
UniApp/Taro support
"生成React Hooks"
isGenReactQuery: true
Auto-generates query hooks
"生成Mock数据"
mockFolder: "./mocks"
Uses mockjs for fake data
"只要类型定义"
isOnlyGenTypeScriptType: true
Skip request functions
"增量更新代码"
full: false
Preserve manual modifications
"过滤大型API"
includeTags: ["user", "order"]
Performance optimization
"自定义请求客户端"
requestLibPath: "@/utils/request"
Custom request setup
"支持文件上传"
Check OpenAPI for multipart
Auto-detects file uploads
"翻译中文标签"
isTranslateToEnglishTag: true
Chinese to English tags
"解析枚举描述"
isSupportParseEnumDesc: true
Enum with descriptions
"自定义枚举解析正则"
supportParseEnumDescByReg: /pattern/g
Custom enum description parsing
"生成JSON验证"
isGenJsonSchemas: true
Schema validation
"前缀API路径"
apiPrefix: "'api'"
Add prefix to paths
"按模块拆分类型"
isSplitTypesByModule: true
Large projects, better code organization
📋 Common Configuration Scenarios
Scenario 1: React + TypeScript Production App
{
schemaPath : "https://api.example.com/openapi.json" ,
serversPath : "./src/apis" ,
isGenReactQuery : true ,
reactQueryMode : "react" ,
isDisplayTypeLabel : true ,
isGenJsonSchemas : true ,
isCamelCase : true ,
requestLibPath : "axios" ,
nullable : false ,
enableLogging : false
}
Scenario 2: Vue + TypeScript Project
{
schemaPath : "./openapi.yaml" ,
serversPath : "./src/api" ,
isGenReactQuery : true ,
reactQueryMode : "vue" ,
isDisplayTypeLabel : true ,
isCamelCase : true ,
requestLibPath : "axios" ,
}
Scenario 3: UniApp/Taro Mini Program
{
schemaPath : "https://api.example.com/swagger.json" ,
serversPath : "./src/apis" ,
requestLibPath : "@/request" ,
isGenJavaScript : false ,
isCamelCase : true ,
apiPrefix : "'api'" ,
requestOptionsType : "{ [key: string]: any }" ,
}
Scenario 4: Node.js Backend Integration
{
schemaPath : "./api-spec.json" ,
serversPath : "./src/clients" ,
requestLibPath : "node-fetch" ,
isGenJavaScript : true ,
isOnlyGenTypeScriptType : false ,
requestImportStatement : "const request = require('node-fetch');" ,
requestOptionsType : "RequestInit" ,
}
Scenario 5: Quick Prototyping with Mocks
{
schemaPath : "https://petstore.swagger.io/v2/swagger.json" ,
serversPath : "./src/apis" ,
mockFolder : "./mocks" ,
isGenJavaScript : true ,
isDisplayTypeLabel : false ,
isGenReactQuery : false ,
enableLogging : true
}
Scenario 6: International Project (Chinese API)
{
schemaPath : "./openapi.json" ,
serversPath : "./src/apis" ,
isTranslateToEnglishTag : true ,
isDisplayTypeLabel : true ,
isSupportParseEnumDesc : true ,
// Custom regex for parsing enum descriptions like "普通 = 0" or "SampleMaker = 1"
supportParseEnumDescByReg : / ( [ ^ \s = < > / & ; ] + (?: \s + [ ^ \s = < > / & ; ] + ) * ) \s * = \s * ( \d + ) / g,
isCamelCase : true ,
filterCaseInsensitive : true ,
}
Scenario 7: Large API with Filtering
{
schemaPath : "https://large-api.example.com/openapi.json" ,
serversPath : "./src/apis" ,
priorityRule : "include" ,
includeTags : [ "user" , "order" , "product" ] ,
filterCaseInsensitive : true ,
isGenReactQuery : true ,
isDisplayTypeLabel : true ,
full : false , // Incremental updates for large APIs
enableLogging : true
}
Scenario 8: Type-Only Generation
{
schemaPath : "./openapi.json" ,
serversPath : "./src/types" ,
isOnlyGenTypeScriptType : true ,
isDisplayTypeLabel : true ,
isGenJsonSchemas : true ,
namespace : "APITypes" ,
isCamelCase : true ,
}
Scenario 9: Custom Request Client
{
schemaPath : "https://api.example.com/openapi.json" ,
serversPath : "./src/apis" ,
requestLibPath : "@/utils/httpClient" ,
requestImportStatement : "import { httpClient as request } from '@/utils/httpClient';" ,
requestOptionsType : "CustomRequestOptions" ,
apiPrefix : ( params ) => `api/${ params . namespace . toLowerCase ( ) } ` ,
isGenReactQuery : true ,
}
Scenario 10: Apifox Integration
{
apifoxConfig : {
projectId : "your-project-id" ,
apifoxToken : "your-apifox-token" ,
local : "zh-CN" ,
selectedTags : [ "user" , "order" ] ,
oasVersion : "3.0" ,
exportFormat : "JSON" ,
branchId : 123 , // Optional: branch id
moduleId : 456 // Optional: module id
} ,
serversPath : "./src/apis" ,
isGenReactQuery : true ,
isDisplayTypeLabel : true ,
isSupportParseEnumDesc : true ,
}
Scenario 11: Large Project with Module-Based Type Splitting
{
schemaPath : "./openapi.json" ,
serversPath : "./src/apis" ,
isSplitTypesByModule : true , // Split types by module
isGenReactQuery : true ,
isDisplayTypeLabel : true ,
isCamelCase : true ,
// Generates:
// - {module}.type.ts (module-specific types)
// - common.type.ts (shared types)
// - enum.ts (all enums)
// - types.ts (unified export)
}
⚠️ Configuration Conflicts & Rules
❌ Incompatible Combinations
isGenJavaScript: true + isDisplayTypeLabel: true (TypeScript types needed for labels)
isOnlyGenTypeScriptType: true + isGenReactQuery: true (no functions = no hooks)
isGenJavaScript: true + isGenJsonSchemas: true (schemas require TypeScript)
isOnlyGenTypeScriptType: true + mockFolder (no functions = no mocks)
schemaPath + apifoxConfig (use one or the other, not both)
priorityRule: "include" without includeTags/includePaths (nothing to include)
priorityRule: "exclude" without excludeTags/excludePaths (nothing to exclude)
Large APIs without filtering (includeTags/excludeTags) = slow generation
enableLogging: true in production = excessive log output
Too many includeTags (>20) = defeats filtering purpose
✅ Recommended Combinations
React projects : isGenReactQuery + isDisplayTypeLabel + isGenJsonSchemas
Vue projects : isGenReactQuery + reactQueryMode: 'vue' + isDisplayTypeLabel
Form-heavy apps : isDisplayTypeLabel + isSupportParseEnumDesc
Large APIs : priorityRule: "include" + includeTags + filterCaseInsensitive
Development : mockFolder + enableLogging + full: false
International : isTranslateToEnglishTag + isDisplayTypeLabel + isSupportParseEnumDesc
Type-only libraries : isOnlyGenTypeScriptType + isGenJsonSchemas + namespace
Large projects : isSplitTypesByModule: true + isGenReactQuery + isDisplayTypeLabel
🔧 Advanced Customization Hooks
1. Custom Function Naming (customFunctionName)
// RESTful naming convention
hook: {
customFunctionName: ( data : APIDataType ) => {
const method = data . method ;
const resource = data . path . split ( '/' ) . filter ( Boolean ) . pop ( ) ;
return `${ method } ${ upperFirst ( resource ) } ` ;
// Result: GET /users/{id} → getUsersId
} ;
}
// Use operationId with fallback
hook: {
customFunctionName: ( data : APIDataType ) => {
if ( data . operationId ) {
return camelCase ( data . operationId . replace ( / [ ^ a - z A - Z 0 - 9 ] / g, '_' ) ) ;
}
return `${ data . method } ${ upperFirst ( camelCase ( data . path ) ) } ` ;
} ;
}
// Domain-specific naming
hook: {
customFunctionName: ( data : APIDataType ) => {
const segments = data . path . split ( '/' ) . filter ( Boolean ) ;
const version = segments . find ( ( s ) => s . match ( / ^ v \d + $ / ) ) ; // v1, v2, etc.
const resource = segments [ segments . length - 1 ] ;
const action = data . method ;
return version
? `${ action } ${ upperFirst ( resource ) } ${ upperFirst ( version ) } `
: `${ action } ${ upperFirst ( resource ) } ` ;
} ;
}
2. Custom Type Names (customTypeName)
// Add suffix to distinguish request/response types
hook: {
customTypeName: ( data : APIDataType ) => {
const baseName = upperFirst ( camelCase ( data . operationId || data . path ) ) ;
if ( data . requestBody ) return `${ baseName } Request` ;
if ( data . responses ) return `${ baseName } Response` ;
return baseName ;
} ;
}
3. Custom Type Generation (customType)
// Convert numbers to string for precision
hook: {
customType: ( { schemaObject, namespace, originGetType } ) => {
if ( schemaObject . type === 'number' && ! schemaObject . format ) {
return 'string' ; // Use string for large numbers
}
// Convert date-time to Date objects
if ( schemaObject . type === 'string' && schemaObject . format === 'date-time' ) {
return 'Date' ;
}
return originGetType ( schemaObject , namespace ) ;
} ;
}
// Handle custom formats
hook: {
customType: ( { schemaObject, namespace, originGetType, schemas } ) => {
// Custom decimal type
if ( schemaObject . type === 'string' && schemaObject . format === 'decimal' ) {
return 'Decimal' ;
}
// Custom enum handling
if ( schemaObject . enum && schemaObject [ 'x-enum-labels' ] ) {
return `${ namespace } .${ upperFirst ( schemaObject . title || 'CustomEnum' ) } ` ;
}
return originGetType ( schemaObject , namespace , schemas ) ;
} ;
}
4. Custom Class Names (customClassName)
// Convert Chinese tags to English
hook: {
customClassName: ( tagName : string ) => {
const chineseToEnglish = {
用户管理 : 'UserManagement' ,
订单管理 : 'OrderManagement' ,
商品管理 : 'ProductManagement' ,
} ;
return chineseToEnglish [ tagName ] || upperFirst ( camelCase ( tagName ) ) ;
} ;
}
// Add Controller suffix
hook: {
customClassName: ( tagName : string ) => {
const cleanName = upperFirst (
camelCase ( tagName . replace ( / [ ^ a - z A - Z 0 - 9 ] / g, '' ) )
) ;
return cleanName . endsWith ( 'Controller' )
? cleanName
: `${ cleanName } Controller` ;
} ;
}
5. Custom File Organization (customFileNames)
// Group by feature instead of by tag
hook: {
customFileNames: ( operationObject , apiPath , apiMethod ) => {
const pathSegments = apiPath . split ( '/' ) . filter ( Boolean ) ;
const feature = pathSegments [ 0 ] ; // First path segment
return [ feature ] ;
} ;
}
// Version-based organization
hook: {
customFileNames: ( operationObject , apiPath , apiMethod ) => {
const segments = apiPath . split ( '/' ) . filter ( Boolean ) ;
const version = segments . find ( ( s ) => s . match ( / ^ v \d + $ / ) ) ;
const resource = segments [ segments . length - 1 ] ;
return version ? [ `${ version } /${ resource } ` ] : [ resource ] ;
} ;
}
// Method-based file splitting
hook: {
customFileNames: ( operationObject , apiPath , apiMethod ) => {
const tags = operationObject . tags || [ 'default' ] ;
const method = apiMethod . toLowerCase ( ) ;
return tags . map ( ( tag ) => `${ camelCase ( tag ) } .${ method } ` ) ;
} ;
}
6. Custom Options Default Values (customOptionsDefaultValue)
// Add timeout and retry logic
hook: {
customOptionsDefaultValue: ( operationObject ) => {
const isFileUpload =
operationObject . requestBody ?. content ?. [ 'multipart/form-data' ] ;
return {
timeout : isFileUpload ? 30000 : 10000 ,
retries : isFileUpload ? 1 : 3 ,
validateStatus : ( status : number ) => status < 400 ,
} ;
} ;
}
// Add authentication headers
hook: {
customOptionsDefaultValue: ( operationObject ) => {
const requiresAuth = operationObject . security ?. length > 0 ;
return requiresAuth
? {
headers : {
Authorization : 'Bearer ${token}' ,
} ,
}
: { } ;
} ;
}
7. OpenAPI Data Transformation (afterOpenApiDataInited)
// Add custom extensions to all operations
hook: {
afterOpenApiDataInited: ( openAPIData ) => {
// Add rate limiting info
Object . values ( openAPIData . paths || { } ) . forEach ( ( pathItem ) => {
Object . values ( pathItem ) . forEach ( ( operation ) => {
if ( operation . operationId ) {
operation [ 'x-rate-limit' ] = operation [ 'x-rate-limit' ] || '100/hour' ;
}
} ) ;
} ) ;
return openAPIData ;
} ;
}
// Filter out deprecated endpoints
hook: {
afterOpenApiDataInited: ( openAPIData ) => {
Object . keys ( openAPIData . paths || { } ) . forEach ( ( path ) => {
Object . keys ( openAPIData . paths [ path ] ) . forEach ( ( method ) => {
const operation = openAPIData . paths [ path ] [ method ] ;
if ( operation . deprecated ) {
delete openAPIData . paths [ path ] [ method ] ;
}
} ) ;
} ) ;
return openAPIData ;
} ;
}
// Custom service controller template
hook: {
customTemplates : {
[ TypescriptFileType . serviceController ] : ( apis , context ) => {
return `
// Auto-generated API client
import request from '${ context . requestLibPath } ';
import type * as API from './types';
${ apis . map ( api => `
/** ${ api . summary || api . path } */
export const ${ api . functionName } = async (${ api . params } ) => {
return request<${ api . responseType } >(\`${ api . path } \`, {
method: '${ api . method . toUpperCase ( ) } ',
${ api . data ? `data: ${ api . data } ,` : '' }
...options
});
};
` ) . join ( '\n' ) }
` ;
}
}
}
📁 Generated File Structure
Default Structure (isSplitTypesByModule: false)
src/apis/
├── index.ts # Main entry point with all exports
├── types.ts # TypeScript type definitions
├── [controller].ts # API functions grouped by tags
├── displayTypeLabel.ts # Chinese field labels (if enabled)
├── displayEnumLabel.ts # Enum translations (if enabled)
├── schema.ts # JSON Schemas (if enabled)
├── reactquery.ts # React Query hooks (if enabled)
└── mocks/ # Mock data files (if enabled)
├── [endpoint].mock.ts
└── ...
Module-Based Structure (isSplitTypesByModule: true)
src/apis/
├── index.ts # Main entry point with all exports
├── types.ts # Unified type exports
├── enum.ts # All enum type definitions
├── common.type.ts # Shared/common types used by multiple modules
├── [module].type.ts # Module-specific types (e.g., user.type.ts, order.type.ts)
├── [controller].ts # API functions grouped by tags
├── displayTypeLabel.ts # Chinese field labels (if enabled)
├── displayEnumLabel.ts # Enum translations (if enabled)
├── schema.ts # JSON Schemas (if enabled)
├── reactquery.ts # React Query hooks (if enabled)
└── mocks/ # Mock data files (if enabled)
├── [endpoint].mock.ts
└── ...
🚀 Performance Optimization Tips
For Large APIs (100+ endpoints)
{
// Filter by specific tags only
priorityRule : "include" ,
includeTags : [ "user" , "order" , "product" ] ,
// Or exclude administrative endpoints
priorityRule : "exclude" ,
excludeTags : [ "admin" , "internal" ] ,
// Enable case-insensitive filtering
filterCaseInsensitive : true
}
{
// Generate JavaScript for faster iteration
isGenJavaScript : true ,
// Skip heavy features during development
isDisplayTypeLabel : false ,
isGenJsonSchemas : false ,
// Enable mocks for offline development
mockFolder : "./mocks"
}
Common Issues & Solutions
Issue
Likely Cause
Solution
"Missing request method"
Invalid requestLibPath
Ensure the import path exists
"Type conflicts"
Duplicate type names
Use namespace or filter tags
"Build errors"
TypeScript version mismatch
Check typescript peer dependency
"Empty generation"
Restrictive filters
Review includeTags/excludeTags
"Performance slow"
Large API without filtering
Add tag/path filters
✅ OpenAPI spec is valid JSON/YAML
✅ serversPath directory exists
✅ Request library is installed
✅ TypeScript configured if using TS features
✅ Tags/paths filters are not too restrictive
Core Configuration (GenerateServiceProps)
See src/index.ts:27 for complete interface definition.
Main generator: src/generator/serviceGenarator.ts
Type definitions: src/type.ts
Configuration options: src/generator/config.ts
Utility functions: src/util.ts
# NPX usage
npx --package=openapi-ts-request -- openapi -i ./openapi.json -o ./apis
# PNPM usage
pnpm --package=openapi-ts-request@latest dlx openapi -i ./openapi.json -o ./apis
# Global installation
npm i -g openapi-ts-request
openapi --input https://api.example.com/openapi.json --output ./src/apis
🎯 Best Practices for AI Agents
Always validate OpenAPI spec first before generating
Check project dependencies to recommend appropriate client
Start with minimal config then add features incrementally
Use filtering for large APIs to improve performance
Test generated code with actual API endpoints
Prefer TypeScript unless explicitly requested otherwise
Enable type labels for form-heavy applications
Use mocks during development phase
This guide is optimized for AI agents to understand and effectively use openapi-ts-request. For human-readable documentation, see README.md