@@ -11,8 +11,18 @@ export interface OperationInfo {
11
11
responses : OpenAPIV3 . ResponsesObject ;
12
12
}
13
13
14
+ function sanitizeOperationId ( operationId : string ) : string {
15
+ return operationId . replace ( / [ ^ a - z A - Z 0 - 9 _ ] / g, '_' ) ;
16
+ }
17
+
18
+ function sanitizePropertyName ( name : string ) : string {
19
+ return / ^ [ a - z A - Z _ $ ] [ a - z A - Z 0 - 9 _ $ ] * $ / . test ( name ) ? name : `'${ name } '` ;
20
+ }
21
+
14
22
function generateAxiosMethod ( operation : OperationInfo , spec : OpenAPIV3 . Document ) : string {
15
- const { method, path, operationId, summary, description, parameters, requestBody, responses } = operation ;
23
+ const { method, path, operationId : rawOperationId , summary, description, parameters, requestBody, responses } = operation ;
24
+ const operationId = rawOperationId || `${ method . toLowerCase ( ) } ${ path . replace ( / \W + / g, '_' ) } ` ;
25
+ const sanitizedOperationId = sanitizeOperationId ( operationId ) ;
16
26
17
27
// Generate JSDoc
18
28
const jsDocLines = [ '/**' ] ;
@@ -36,7 +46,7 @@ function generateAxiosMethod(operation: OperationInfo, spec: OpenAPIV3.Document)
36
46
const responseObj = response as OpenAPIV3 . ResponseObject ;
37
47
const desc = 'description' in responseObj ? responseObj . description : '' ;
38
48
const contentType = responseObj . content ?. [ 'application/json' ] ?. schema ;
39
- const typeName = `${ operationId } Response${ code } ` ;
49
+ const typeName = `${ sanitizedOperationId } Response${ code } ` ;
40
50
41
51
if ( contentType ) {
42
52
if ( desc ) {
@@ -68,23 +78,25 @@ function generateAxiosMethod(operation: OperationInfo, spec: OpenAPIV3.Document)
68
78
69
79
// Add path and query parameters
70
80
urlParams . forEach ( p => {
71
- dataProps . push ( `${ p . name } : ${ getTypeFromParam ( p ) } ` ) ;
81
+ const safeName = sanitizePropertyName ( p . name ) ;
82
+ dataProps . push ( `${ safeName } : ${ getTypeFromParam ( p ) } ` ) ;
72
83
} ) ;
73
84
queryParams . forEach ( p => {
74
- dataProps . push ( `${ p . name } ${ p . required ? '' : '?' } : ${ getTypeFromParam ( p ) } ` ) ;
85
+ const safeName = sanitizePropertyName ( p . name ) ;
86
+ dataProps . push ( `${ safeName } ${ p . required ? '' : '?' } : ${ getTypeFromParam ( p ) } ` ) ;
75
87
} ) ;
76
88
77
89
// Add request body type if it exists
78
90
const hasData = ( parameters && parameters . length > 0 ) || operation . requestBody ;
79
91
const dataType = hasData
80
92
? requestBody
81
- ? `${ operationId } Request & { ${ dataProps . join ( '; ' ) } }`
93
+ ? `${ sanitizedOperationId } Request & { ${ dataProps . join ( '; ' ) } }`
82
94
: `{ ${ dataProps . join ( '; ' ) } }`
83
95
: 'undefined' ;
84
96
85
97
// Get response type from 2xx response
86
98
const successResponse = Object . entries ( responses ) . find ( ( [ code ] ) => code . startsWith ( '2' ) ) ;
87
- const responseType = successResponse ? `${ operationId } Response${ successResponse [ 0 ] } ` : 'any' ;
99
+ const responseType = successResponse ? `${ sanitizedOperationId } Response${ successResponse [ 0 ] } ` : 'any' ;
88
100
89
101
const urlWithParams = urlParams . length > 0
90
102
? path . replace ( / { ( \w + ) } / g, '${data.$1}' )
@@ -116,7 +128,7 @@ function generateAxiosMethod(operation: OperationInfo, spec: OpenAPIV3.Document)
116
128
117
129
return `
118
130
${ jsDocLines . join ( '\n ' ) }
119
- async ${ operationId } (data${ hasData ? `: ${ dataType } ` : '?: undefined' } , headers?: Record<string, string>): Promise<AxiosResponse<${ responseType } >> {
131
+ async ${ sanitizedOperationId } (data${ hasData ? `: ${ dataType } ` : '?: undefined' } , headers?: Record<string, string>): Promise<AxiosResponse<${ responseType } >> {
120
132
${ methodBody }
121
133
}` ;
122
134
}
@@ -150,7 +162,7 @@ export function generateApiClient(spec: OpenAPIV3.Document): string {
150
162
operations . push ( {
151
163
method : method . toUpperCase ( ) ,
152
164
path,
153
- operationId : operation . operationId || `${ method } ${ path . replace ( / \W + / g, '_' ) } ` ,
165
+ operationId : sanitizeOperationId ( operation . operationId || `${ method } ${ path . replace ( / \W + / g, '_' ) } ` ) ,
154
166
summary : operation . summary ,
155
167
description : operation . description ,
156
168
parameters : [ ...( pathItem . parameters || [ ] ) , ...( operation . parameters || [ ] ) ] as OpenAPIV3 . ParameterObject [ ] ,
@@ -174,11 +186,13 @@ export function generateApiClient(spec: OpenAPIV3.Document): string {
174
186
}
175
187
} ) ;
176
188
189
+ const title = spec . info . title . toLowerCase ( ) . replace ( / \s + / g, '-' ) ;
190
+
177
191
// Generate the client class
178
192
return `import axios, { AxiosInstance, AxiosResponse } from 'axios';
179
193
import {
180
194
${ Array . from ( usedTypes ) . join ( ',\n ' ) }
181
- } from './types ';
195
+ } from './${ title } .schema ';
182
196
183
197
export class ApiClient {
184
198
private axios: AxiosInstance;
0 commit comments