@paulpugovkin/api-docs-axios-ts-generator 1.0.17 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +237 -310
- package/dist/index.js +78 -0
- package/package.json +11 -22
- package/bin/cli.js +0 -6
- package/src/clean-generated-folder/cleanGeneratedFolder.js +0 -21
- package/src/collect-genereted-files/collectGeneratedFiles.js +0 -33
- package/src/generate-class/generateClass.js +0 -42
- package/src/generate-index-file-with-public-api/generateIndexFileWithPublicApi.js +0 -45
- package/src/generate-interface/generateInterface.js +0 -81
- package/src/generate-js-doc/generateJSDoc.js +0 -136
- package/src/generate-main-index-file/generateMainIndexFile.js +0 -21
- package/src/generate-method/generateMethod.js +0 -264
- package/src/generators/axiosConfigGenerator.js +0 -79
- package/src/index.js +0 -187
- package/src/map-type/mapType.js +0 -19
- package/src/parse-and-generate/parseAndGenerate.js +0 -190
- package/src/resolve-type/resolveType.js +0 -54
- package/src/update-api-docs-json/updateApiDocsJson.js +0 -33
package/README.md
CHANGED
|
@@ -1,310 +1,237 @@
|
|
|
1
|
-
# API Docs Axios TS Generator
|
|
2
|
-
|
|
3
|
-
Generate TypeScript interfaces and axios classes from OpenAPI (Swagger) specifications.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
## Installation
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
npm install -
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
###
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
│ └── index.ts
|
|
239
|
-
└── index.ts
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
## CLI options
|
|
243
|
-
|
|
244
|
-
```
|
|
245
|
-
Usage: api-docs-generator [options]
|
|
246
|
-
|
|
247
|
-
Options:
|
|
248
|
-
-V, --version output the version number
|
|
249
|
-
-c, --config <path> Path to configuration file
|
|
250
|
-
--api-docs-url <url> URL to fetch OpenAPI documentation
|
|
251
|
-
--api-docs-path <path> Local path to OpenAPI documentation file
|
|
252
|
-
--output-dir <dir> Output directory for generated files
|
|
253
|
-
--clean Clean output directory before generation
|
|
254
|
-
-h, --help display help for command
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
## Configuration examples
|
|
258
|
-
|
|
259
|
-
### Generate by tags (multiple classes)
|
|
260
|
-
|
|
261
|
-
```typescript
|
|
262
|
-
{
|
|
263
|
-
tags: {
|
|
264
|
-
include: ['api_tag_users', 'api_tag_products'],
|
|
265
|
-
},
|
|
266
|
-
groupBy: 'tag',
|
|
267
|
-
classMode: 'multiple',
|
|
268
|
-
}
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
### Generate single class
|
|
272
|
-
|
|
273
|
-
```typescript
|
|
274
|
-
{
|
|
275
|
-
groupBy: 'all',
|
|
276
|
-
classMode: 'single',
|
|
277
|
-
}
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
### Exclude tags
|
|
281
|
-
|
|
282
|
-
```typescript
|
|
283
|
-
{
|
|
284
|
-
tags: {
|
|
285
|
-
exclude: ['api_tag_internal', 'api_tag_admin'],
|
|
286
|
-
},
|
|
287
|
-
}
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
### Generate with axios configuration
|
|
291
|
-
|
|
292
|
-
```typescript
|
|
293
|
-
{
|
|
294
|
-
options: {
|
|
295
|
-
generateAxiosConfig: true,
|
|
296
|
-
},
|
|
297
|
-
axios: {
|
|
298
|
-
baseURL: 'https://api.example.com',
|
|
299
|
-
timeout: 30000,
|
|
300
|
-
headers: {
|
|
301
|
-
'Content-Type': 'application/json',
|
|
302
|
-
'X-API-Key': 'your-api-key',
|
|
303
|
-
},
|
|
304
|
-
},
|
|
305
|
-
}
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
## License
|
|
309
|
-
|
|
310
|
-
MIT
|
|
1
|
+
# API Docs Axios TS Generator
|
|
2
|
+
|
|
3
|
+
Generate TypeScript interfaces and axios classes from OpenAPI (Swagger) specifications.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Generate TypeScript interfaces from OpenAPI schemas
|
|
8
|
+
- Generate axios classes with API methods
|
|
9
|
+
- Flexible configuration via TypeScript file
|
|
10
|
+
- Tag filtering (include/exclude)
|
|
11
|
+
- Generation modes: single class or multiple by tags
|
|
12
|
+
- Automatic axios configuration generation
|
|
13
|
+
- Support for spreading user axios configurations
|
|
14
|
+
- JSDoc comments for methods
|
|
15
|
+
- Backward compatibility with CLI arguments
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install --save-dev @paulpugovkin/api-docs-axios-ts-generator
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Add script to your `package.json`:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"scripts": {
|
|
28
|
+
"generate-services": "api-docs-generator --config api-docs-generator.config.js"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Now generate your API client:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm run generate-services
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
### Create configuration file
|
|
42
|
+
|
|
43
|
+
A default configuration file `api-docs-generator.config.js` is automatically created in your project root during installation. You can modify this file to suit your needs.
|
|
44
|
+
|
|
45
|
+
If you need to create it manually, see the template at `src/templates/default.config.template.js` or the [Configuration](#configuration) reference below.
|
|
46
|
+
|
|
47
|
+
## Generated API usage
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { UsersApi, ProductsApi } from './generated';
|
|
51
|
+
|
|
52
|
+
// Use API
|
|
53
|
+
const usersApi = new UsersApi();
|
|
54
|
+
const productsApi = new ProductsApi();
|
|
55
|
+
|
|
56
|
+
// Get user
|
|
57
|
+
const user = await usersApi.getUserById(123);
|
|
58
|
+
|
|
59
|
+
// With custom axios configuration
|
|
60
|
+
const user = await usersApi.getUserById(123, {
|
|
61
|
+
headers: {
|
|
62
|
+
'X-Custom-Header': 'value',
|
|
63
|
+
},
|
|
64
|
+
timeout: 5000,
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Configuration
|
|
69
|
+
|
|
70
|
+
### Main parameters
|
|
71
|
+
|
|
72
|
+
| Parameter | Type | Required | Description |
|
|
73
|
+
|-----------|------|--------------|------------|
|
|
74
|
+
| `apiDocsUrl` | `string` | No* | URL to fetch OpenAPI specification |
|
|
75
|
+
| `apiDocsPath` | `string` | No* | Local path to OpenAPI specification file |
|
|
76
|
+
| `outputDir` | `string` | Yes | Output directory for generated files |
|
|
77
|
+
|
|
78
|
+
*One of `apiDocsUrl` or `apiDocsPath` is required.
|
|
79
|
+
|
|
80
|
+
### Tag filtering
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
tags: {
|
|
84
|
+
include?: string[]; // Tags to include
|
|
85
|
+
exclude?: string[]; // Tags to exclude
|
|
86
|
+
prefix?: string; // Tag prefix (default "api_tag_")
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Grouping modes
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
groupBy: 'tag' | 'all' | 'path';
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
- `'tag'` - grouping by tags (multiple classes)
|
|
97
|
+
- `'all'` - all methods in one class
|
|
98
|
+
- `'path'` - grouping by API paths
|
|
99
|
+
|
|
100
|
+
### Class generation modes
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
classMode: 'single' | 'multiple';
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
- `'single'` - one class for all methods
|
|
107
|
+
- `'multiple'` - multiple classes by grouping
|
|
108
|
+
|
|
109
|
+
### Naming options
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
naming: {
|
|
113
|
+
className?: (tag: string) => string;
|
|
114
|
+
interfaceName?: (name: string) => string;
|
|
115
|
+
methodName?: (operationId: string) => string;
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Import options
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
imports: {
|
|
123
|
+
axiosPath?: string; // Path to import axios (default 'axios')
|
|
124
|
+
baseUrlPath?: string; // Path to import BASE_URL
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Generation options
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
options: {
|
|
132
|
+
generateJSDoc?: boolean; // Generate JSDoc (default true)
|
|
133
|
+
generateIndexFiles?: boolean; // Generate index files (default true)
|
|
134
|
+
cleanOutputDir?: boolean; // Clean output directory (default true)
|
|
135
|
+
generateAxiosConfig?: boolean; // Generate axios configuration (default true)
|
|
136
|
+
allowAxiosConfigSpread?: boolean; // Allow spreading axios configs (default true)
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Axios settings
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
axios: {
|
|
144
|
+
baseURL?: string;
|
|
145
|
+
timeout?: number;
|
|
146
|
+
headers?: Record<string, string>;
|
|
147
|
+
withCredentials?: boolean;
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Generated files structure
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
outputDir/
|
|
155
|
+
├── config/
|
|
156
|
+
│ └── axios/
|
|
157
|
+
│ └── axios.ts # Axios configuration with interceptors
|
|
158
|
+
├── interfaces/
|
|
159
|
+
│ ├── User.ts
|
|
160
|
+
│ ├── Product.ts
|
|
161
|
+
│ └── index.ts
|
|
162
|
+
├── classes/
|
|
163
|
+
│ ├── UsersApi.ts
|
|
164
|
+
│ ├── ProductsApi.ts
|
|
165
|
+
│ └── index.ts
|
|
166
|
+
└── index.ts
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## CLI options
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
Usage: api-docs-generator [options]
|
|
173
|
+
|
|
174
|
+
Options:
|
|
175
|
+
-V, --version output the version number
|
|
176
|
+
-c, --config <path> Path to configuration file
|
|
177
|
+
--api-docs-url <url> URL to fetch OpenAPI documentation
|
|
178
|
+
--api-docs-path <path> Local path to OpenAPI documentation file
|
|
179
|
+
--output-dir <dir> Output directory for generated files
|
|
180
|
+
--clean Clean output directory before generation
|
|
181
|
+
-h, --help display help for command
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Configuration examples
|
|
185
|
+
|
|
186
|
+
### Generate by tags (multiple classes)
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
{
|
|
190
|
+
tags: {
|
|
191
|
+
include: ['api_tag_users', 'api_tag_products'],
|
|
192
|
+
},
|
|
193
|
+
groupBy: 'tag',
|
|
194
|
+
classMode: 'multiple',
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Generate single class
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
{
|
|
202
|
+
groupBy: 'all',
|
|
203
|
+
classMode: 'single',
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Exclude tags
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
{
|
|
211
|
+
tags: {
|
|
212
|
+
exclude: ['api_tag_internal', 'api_tag_admin'],
|
|
213
|
+
},
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Generate with axios configuration
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
{
|
|
221
|
+
options: {
|
|
222
|
+
generateAxiosConfig: true,
|
|
223
|
+
},
|
|
224
|
+
axios: {
|
|
225
|
+
baseURL: 'https://api.example.com',
|
|
226
|
+
timeout: 30000,
|
|
227
|
+
headers: {
|
|
228
|
+
'Content-Type': 'application/json',
|
|
229
|
+
'X-API-Key': 'your-api-key',
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
MIT
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var h=(t,o)=>()=>(o||t((o={exports:{}}).exports,o),o.exports);var M=h((at,E)=>{var N=require("fs"),B=require("path");function Ce(t){N.existsSync(t)&&(N.rmSync(t,{recursive:!0}),console.log(`Deleted: ${t}`)),N.mkdirSync(t,{recursive:!0}),N.mkdirSync(B.join(t,"interfaces"),{recursive:!0}),N.mkdirSync(B.join(t,"classes"),{recursive:!0}),console.log("Recreated necessary directories.")}E.exports={cleanGeneratedFolder:Ce}});var _=h((ct,G)=>{var k=require("fs"),Ue=require("path");async function ve(t,o){try{console.log(`Fetching API docs from: ${t}`);let e=await fetch(t);if(!e.ok)throw new Error(`HTTP error! status: ${e.status}`);let s=await e.json();k.mkdirSync(Ue.dirname(o),{recursive:!0}),k.writeFileSync(o,JSON.stringify(s,null,2),{encoding:"utf-8"}),console.log(`Updated and saved API docs to: ${o}`)}catch(e){console.error(`Failed to fetch or save the OpenAPI docs: ${e.message}`)}}G.exports={updateApiDocsJson:ve}});var W=h((pt,J)=>{function Ne(t){return{string:"string",integer:"number",boolean:"boolean",array:"any[]",object:"Record<string, any>",binary:"File"}[t]||"any"}J.exports={mapType:Ne}});var I=h((lt,Q)=>{var{mapType:Te}=W();function R(t,o,e){if(t.$ref){let i=t.$ref.split("/").pop();return e.add(i),i}return t.type==="array"?`Array<${R(t.items||{},o,e)}>`:t.type==="object"?t.properties?"{"+Object.entries(t.properties).map(([s,i])=>`${s}: ${R(i,o,e)}`).join("; ")+"}":"Record<string, any>":t.enum?t.enum.map(s=>`"${s}"`).join(" | "):t.oneOf?t.oneOf.map(i=>R(i,o,e)).join(" | "):t.type?Te(t.type):"any"}Q.exports={resolveType:R}});var H=h((ut,K)=>{var{resolveType:Re}=I(),z=require("path");function Ie(t){return t&&t.charAt(0).toUpperCase()+t.slice(1)}function Fe(t,o,e){let s={},i=[];for(let n of t)if(n.$ref){let a=n.$ref.split("/").pop();e.add(a),i.push(a)}else n.properties&&(s={...s,...n.properties});return{mergedProperties:s,extendsInterfaces:i}}function Le(t,o,e){let s=[];for(let i of t)if(i.$ref){let n=i.$ref.split("/").pop();e.add(n),s.push(n)}return s}function Be(t,o,e,s){let i=new Set,n=o.properties||{},a=[];if(o.allOf){let c=Fe(o.allOf,e,i);n={...n,...c.mergedProperties},a=c.extendsInterfaces}if(o.oneOf){let c=Le(o.oneOf,e,i);a.push(...c)}let m=[];for(let[c,f]of Object.entries(n)){let u=Re(f,e,i);m.push(` ${c}: ${u};`)}let g=s?.outputDir?z.relative(z.join(s.outputDir,"interfaces"),s.outputDir):"./",r=Array.from(i).sort().map(c=>`import type { ${c} } from '${g}';`).join(`
|
|
3
|
+
`),p=a.length?` extends ${a.join(", ")}`:"";return`${r}
|
|
4
|
+
|
|
5
|
+
export interface ${Ie(t)}${p} {
|
|
6
|
+
${m.join(`
|
|
7
|
+
`)}
|
|
8
|
+
}
|
|
9
|
+
`}K.exports={generateInterface:Be}});var X=h((dt,V)=>{var{resolveType:ft}=I();function Ee(t){let o="",e="",s=t.parameters||[],i=t.summary||"",n=["/**"];if(t.requestBody){let r=t.requestBody.content||{};if(r["application/json"]){let p=r["application/json"].schema||{};if(p.oneOf)o=p.oneOf.map(c=>c.$ref.split("/").pop()).join(" | ");else if(p.$ref){let c=p.$ref.split("/").pop();c&&(o=c)}}r["multipart/form-data"]&&(e="FormData")}i&&n.push(` * @description ${i}`),e&&n.push(` * @param {${e}} data - \u0442\u0435\u043B\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0430`),o&&n.push(` * @param {${o}} values - \u0442\u0435\u043B\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0430`);let a={},m=[];return s.forEach(r=>{if(r.in==="query")if(r.name.includes(".")){let[p,c]=r.name.split(".");a[p]||(a[p]=[]),a[p].push({propertyName:c,description:r.description||"",type:r.schema.type||"string",required:r.required||!1})}else a[r.name]||(a[r.name]=[]),a[r.name].push({description:r.description||"",type:r.schema.type||"string",required:r.required||!1});else m.push({name:r.name,description:r.description||"",type:r.schema.type||"string",required:r.required||!1})}),Object.keys(a).length>0&&(n.push(" * @param {object} queryParams"),Object.keys(a).forEach(r=>{let c=a[r].sort((f,u)=>(u.required?1:0)-(f.required?1:0));if(c.length===1&&c[0].propertyName===void 0){let f=c[0],u=f.type==="integer"?"number":f.type;n.push(` * @param {${u}} queryParams.${r} - ${f.description}`)}else n.push(` * @param {object} queryParams.${r} - Query parameter`),c.forEach(f=>{let{propertyName:u,description:P,type:A}=f,b=A==="integer"?"number":A;n.push(` * @param {${b}} queryParams.${r}.${u} - ${P}`)})})),m.sort((r,p)=>(p.required?1:0)-(r.required?1:0)).forEach(r=>{let p=r.type==="integer"?"number":r.type;n.push(` * @param {${p}} ${r.name} - ${r.description}`)}),n.push(" * @param {AxiosRequestConfig} config - \u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044F axios"),n.push(" */"),n.join(`
|
|
10
|
+
`)}V.exports={generateJSDoc:Ee}});var Z=h((gt,Y)=>{var mt=require("path"),{resolveType:S}=I(),{generateJSDoc:Me}=X();function ke(t,o,e,s,i,n,a={}){let m=a?.options?.allowAxiosConfigSpread!==!1;[...e.matchAll(/\{(\w+)\}/g)].map(l=>l[1]).forEach(l=>{e=e.replace(`{${l}}`,`\${${l}}`)});let r=[],p=[],c=[],f={},u=null,P="",A=!1;for(let l of o.parameters||[]){let d=l.name,$=l.in,q=l.required||!1,O=l.schema||{},Se=O.$ref||O.properties;if($==="path"){let x=S(O,i,n);r.push(`${d}: ${x}`)}else if($==="query")if(Se){let x=S(O,i,n);q?(r.push(`${d}: ${x}`),p.push(`...${d}`)):(c.push(`${d}?: ${x}`),p.push(`...(${d} || {})`))}else if(d.includes(".")){let[x,we]=d.split(".");f[x]=f[x]||[];let De=S(O,i,n);f[x].push(`${we}?: ${De}`)}else{let x=S(O,i,n);q?(p.push(d),r.push(`${d}: ${x}`)):c.push(`${d}?: ${x}`)}}for(let[l,d]of Object.entries(f))c.push(`${l}?: { ${d.join(", ")} }`);let F=["post","put","patch","delete"].includes(s.toLowerCase())&&o.requestBody&&o.requestBody.content&&Object.keys(o.requestBody.content).length>0;if(F){let l=o.requestBody.content||{};if(l["application/json"]){let d=l["application/json"].schema||{};if(d.oneOf)u=`values: ${S(d,i,n)}`;else if(d.$ref){let $=d.$ref.split("/").pop();n.add($),u=`values: ${$}`}else d.properties?u=`values: { ${Object.entries(d.properties).map(([q,O])=>`${q}: ${S(O,i,n)}`).join(", ")} }`:u="values: any";P="values"}else if(l["multipart/form-data"]){A=!0;let d=l["multipart/form-data"].schema||{};if(d.properties)for(let[$,q]of Object.entries(d.properties)){let O=S(q,i,n);q.format==="binary"&&(O="File")}u="data: FormData",P="data"}}let L="void";if(o.responses){for(let[l,d]of Object.entries(o.responses))if(d.content){let $=Object.values(d.content)[0].schema||{};if($.$ref){let q=$.$ref.split("/").pop();L=q,n.add(q)}}}let je=`Promise<AxiosResponse<${L}>>`,C=c.length?"queryParams":null,qe=C?`${C}: { ${c.join(", ")} }`:"",U=p.length>0||c.length>0,Oe=Me(o),Pe=`(${[...r,u,qe,"config?: AxiosRequestConfig"].filter(Boolean).join(", ")}): ${je}`,Ae=`${t}${Pe}`,be=`const fullURL = \`\${BASE_URL}${e}\`;`,y="",v=()=>{let l=[];return p.length>0&&l.push(...p),C&&(l.length>0?l.push(`...${C}`):l.push(`...${C}`)),l.length>0?`{ ${l.join(", ")} }`:"{}"};if(s.toLowerCase()==="delete")u?U?y=`return axios.delete(fullURL, { data: values, ...config, params: ${v()} });`:y="return axios.delete(fullURL, { data: values, ...config });":U?y=`return axios.delete(fullURL, { ...config, params: ${v()} });`:y="return axios.delete(fullURL, config);";else if(s.toLowerCase()==="get")U?y=`return axios.get(fullURL, { ...config, params: ${v()} });`:y="return axios.get(fullURL, config);";else if(F)if(U){let l=v();y=`return axios.${s}(fullURL, ${A?"data":P}, { ...config, params: ${l} });`}else y=`return axios.${s}(fullURL, ${A?"data":P}, config);`;else if(U){let l=v();y=`return axios.${s}(fullURL, null, { ...config, params: ${l} });`}else y=`return axios.${s}(fullURL, null, config);`;return`
|
|
11
|
+
${Oe}
|
|
12
|
+
${Ae} {
|
|
13
|
+
${be}
|
|
14
|
+
${y}
|
|
15
|
+
}
|
|
16
|
+
`}Y.exports={generateMethod:ke}});var oe=h((ht,te)=>{var ee=require("path");function Ge(t,o,e,s){let i=`import type { AxiosResponse, AxiosRequestConfig } from "axios";
|
|
17
|
+
`,n=s?.imports?.axiosPath||"axios",a=s?.imports?.baseUrlPath||"./config/axios/axios",m=s?.outputDir?ee.relative(ee.join(s.outputDir,"classes"),s.outputDir):"../../",g="";e&&e.size>0&&(g=Array.from(e).sort().map(u=>`import { ${u} } from '${m}';`).join(`
|
|
18
|
+
`));let r=`
|
|
19
|
+
import axios from '${n}'`,p=`
|
|
20
|
+
import { BASE_URL } from '${a}'`,c=`${i}${g}${r}${p}`,f=o.join(`
|
|
21
|
+
`);return`${c}
|
|
22
|
+
|
|
23
|
+
export class ${t} {
|
|
24
|
+
${f}
|
|
25
|
+
}
|
|
26
|
+
`}te.exports={generateClass:Ge}});var ae=h((yt,ie)=>{var D=require("fs"),w=require("path"),{generateInterface:_e}=H(),{generateMethod:se}=Z(),{generateClass:re}=oe();function ne(t){D.existsSync(t)||D.mkdirSync(t,{recursive:!0})}function Je(t,o){let e=o?.tags?.prefix||"api_tag_";for(let s of t)if(s.includes(e))return s;return""}function We(t,o){let{include:e,exclude:s,prefix:i}=o?.tags||{};if(e&&e.length>0)return e.includes(t);if(s&&s.length>0)return!s.includes(t);let n=i||"api_tag_";return t.includes(n)}function Qe(t,o){let e={},s=o?.tags?.prefix||"api_tag_";for(let i of t){if(!i.tag)continue;let n=o?.naming?.className?o.naming.className(i.tag):i.tag.replace(s,"");e[n]||(e[n]=[]),e[n].push(i)}return e}async function ze(t,o){let e=JSON.parse(D.readFileSync(t,{encoding:"utf-8"})),s=o.outputDir||w.resolve(process.cwd(),"generated"),i=o.interfacesDir||w.join(s,"interfaces"),n=o.classesDir||w.join(s,"classes");ne(i),ne(n);let a=e?.components?.schemas||{};if(e?.components?.schemas)for(let[r,p]of Object.entries(a)){let c=_e(r,p,a,o);D.writeFileSync(w.join(i,`${r}.ts`),c,{encoding:"utf-8"})}let m=[];if(e?.paths){for(let[r,p]of Object.entries(e.paths))for(let[c,f]of Object.entries(p))if(f?.tags){let u=Je(f.tags,o);if(!u||!We(u,o))continue;m.push({operationId:f.operationId,methodDetails:f,pathKey:r,methodType:c,tag:u})}}if((o.groupBy||"tag")==="all"||o.classMode==="single"){let r=o?.naming?.className?o.naming.className("all"):"ApiClient",p=new Set,c=m.map(u=>se(u.operationId,u.methodDetails,u.pathKey,u.methodType,a,p,o)),f=re(r,c,p,o);D.writeFileSync(w.join(n,`${r}.ts`),f,{encoding:"utf-8"})}else{let r=Qe(m,o);for(let[p,c]of Object.entries(r)){let f=new Set,u=c.map(b=>se(b.operationId,b.methodDetails,b.pathKey,b.methodType,a,f,o)),P=o?.naming?.className?o.naming.className(c[0].tag):p+"Api",A=re(P,u,f,o);D.writeFileSync(w.join(n,`${P}.ts`),A,{encoding:"utf-8"})}}console.log(`Generated ${m.length} API methods.`),console.log(`Generated ${Object.keys(a).length} interfaces.`)}ie.exports={parseAndGenerate:ze}});var ue=h(($t,le)=>{var ce=require("fs"),pe=require("path");function Ke(t,o){let e=[];function s(i){let n=ce.readdirSync(i,{withFileTypes:!0});for(let a of n){let m=pe.join(i,a.name);if(a.isDirectory())s(m);else if(a.isFile()&&a.name.endsWith(".ts")&&a.name!=="index.ts"){let r=pe.relative(t,m).replace(/\\/g,"/").replace(/\.ts$/,"");e.push(`export * from './${r}';`)}}}s(t),ce.writeFileSync(o,e.join(`
|
|
27
|
+
`),{encoding:"utf-8"}),console.log(`Generated ${o} with ${e.length} exports.`)}le.exports={generateIndexFileWithOpenApi:Ke}});var de=h((xt,fe)=>{var He=require("fs"),Ve=require("path");function Xe(t){let o=Ve.join(t,"index.ts"),e=["export * from './interfaces/';","export * from './classes/';"];He.writeFileSync(o,e.join(`
|
|
28
|
+
`),{encoding:"utf-8"}),console.log(`Generated main index.ts at ${o}.`)}fe.exports={generateMainIndexFile:Xe}});var ye=h((jt,he)=>{var me=require("fs"),ge=require("path");function Ye(t,o){let e=ge.join(o,"config","axios");me.mkdirSync(e,{recursive:!0});let s=t.axios||{},i=s.baseURL||"",n=s.timeout||3e4,a=s.headers||{"Content-Type":"application/json"},m=s.withCredentials||!1,g=`import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
|
|
29
|
+
|
|
30
|
+
export const BASE_URL = '${i}';
|
|
31
|
+
|
|
32
|
+
const axiosConfig: AxiosRequestConfig = {
|
|
33
|
+
baseURL: BASE_URL,
|
|
34
|
+
timeout: ${n},
|
|
35
|
+
headers: ${JSON.stringify(a,null,2)},
|
|
36
|
+
withCredentials: ${m},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const axiosInstance: AxiosInstance = axios.create(axiosConfig);
|
|
40
|
+
|
|
41
|
+
// \u041F\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0447\u0438\u043A \u0437\u0430\u043F\u0440\u043E\u0441\u043E\u0432
|
|
42
|
+
axiosInstance.interceptors.request.use(
|
|
43
|
+
(config) => {
|
|
44
|
+
// \u041C\u043E\u0436\u043D\u043E \u0434\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0442\u043E\u043A\u0435\u043D \u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0430\u0446\u0438\u0438
|
|
45
|
+
// const token = localStorage.getItem('token');
|
|
46
|
+
// if (token) {
|
|
47
|
+
// config.headers.Authorization = \`Bearer \${token}\`;
|
|
48
|
+
// }
|
|
49
|
+
return config;
|
|
50
|
+
},
|
|
51
|
+
(error) => {
|
|
52
|
+
return Promise.reject(error);
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// \u041F\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0447\u0438\u043A \u043E\u0442\u0432\u0435\u0442\u043E\u0432
|
|
57
|
+
axiosInstance.interceptors.response.use(
|
|
58
|
+
(response) => {
|
|
59
|
+
return response;
|
|
60
|
+
},
|
|
61
|
+
(error) => {
|
|
62
|
+
// \u041E\u0431\u0440\u0430\u0431\u043E\u0442\u043A\u0430 \u043E\u0448\u0438\u0431\u043E\u043A
|
|
63
|
+
if (error.response) {
|
|
64
|
+
// \u0421\u0435\u0440\u0432\u0435\u0440 \u043E\u0442\u0432\u0435\u0442\u0438\u043B \u0441\u043E \u0441\u0442\u0430\u0442\u0443\u0441\u043E\u043C, \u043E\u0442\u043B\u0438\u0447\u043D\u044B\u043C \u043E\u0442 2xx
|
|
65
|
+
console.error('Response error:', error.response.status, error.response.data);
|
|
66
|
+
} else if (error.request) {
|
|
67
|
+
// \u0417\u0430\u043F\u0440\u043E\u0441 \u0431\u044B\u043B \u0441\u0434\u0435\u043B\u0430\u043D, \u043D\u043E \u043E\u0442\u0432\u0435\u0442 \u043D\u0435 \u043F\u043E\u043B\u0443\u0447\u0435\u043D
|
|
68
|
+
console.error('Request error:', error.request);
|
|
69
|
+
} else {
|
|
70
|
+
// \u041F\u0440\u043E\u0438\u0437\u043E\u0448\u043B\u0430 \u043E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u0438 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0435 \u0437\u0430\u043F\u0440\u043E\u0441\u0430
|
|
71
|
+
console.error('Error:', error.message);
|
|
72
|
+
}
|
|
73
|
+
return Promise.reject(error);
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
export default axiosInstance;
|
|
78
|
+
`;me.writeFileSync(ge.join(e,"axios.ts"),g,{encoding:"utf-8"}),console.log(`Generated axios config at: ${e}/axios.ts`)}he.exports={generateAxiosConfig:Ye}});var{program:xe}=require("commander"),{cleanGeneratedFolder:Ze}=M(),{updateApiDocsJson:et}=_(),{parseAndGenerate:tt}=ae(),{generateIndexFileWithOpenApi:$e}=ue(),{generateMainIndexFile:ot}=de(),{generateAxiosConfig:st}=ye(),T=require("fs"),j=require("path");async function rt(t,o={}){let e=j.resolve(t);if(!T.existsSync(e))throw new Error(`Configuration file not found: ${e}`);let s=j.extname(e),i;try{if(s===".js"){let a=e;i=require(a)}else if(s===".json"){let a=T.readFileSync(e,"utf8");i=JSON.parse(a)}else if(s===".ts"){let a=require("typescript"),m=T.readFileSync(e,"utf8"),g=a.transpileModule(m,{compilerOptions:{module:1,target:99,esModuleInterop:!0}}),r=e.replace(".ts",".js");T.writeFileSync(r,g.outputText),i=require(r)}else throw new Error("Unsupported configuration file format. Use .js, .json, or .ts")}catch(a){throw new Error(`Failed to load configuration: ${a.message}`)}let n={...i};return Object.keys(o).forEach(a=>{o[a]!==void 0&&(n[a]=o[a])}),n}xe.version("1.0.0").description("Generate TypeScript API client from OpenAPI documentation").option("-c, --config <path>","Path to configuration file").option("--api-docs-url <url>","URL to fetch the OpenAPI documentation").option("--api-docs-path <path>","Local path to OpenAPI documentation file").option("--output-dir <dir>","Output directory for generated files").option("--clean","Clean output directory before generation").parse(process.argv);async function nt(){let t=xe.opts(),o=t.config;if(!o){let r=["api-docs-generator.config.js","api-docs-generator.config.json","api-docs-generator.config.ts"];for(let p of r){let c=j.join(process.cwd(),p);if(T.existsSync(c)){o=c,console.log(`Auto-detected configuration file: ${p}`);break}}}let e=null;if(o)try{e=await rt(o,{apiDocsUrl:t.apiDocsUrl,apiDocsPath:t.apiDocsPath,outputDir:t.outputDir})}catch(r){console.error(`Failed to load configuration: ${r.message}`),process.exit(1)}else{let r=t.apiDocsUrl,p=t.outputDir||j.resolve(process.cwd(),"generated");r||(console.error("Error: API documentation URL is required."),console.error("Please specify --api-docs-url or --api-docs-path, or create a configuration file."),console.error('Run "api-docs-generator --help" for more information.'),process.exit(1)),e={apiDocsUrl:r,outputDir:p,interfacesDir:j.join(p,"interfaces"),classesDir:j.join(p,"classes"),groupBy:"tag",classMode:"multiple",options:{cleanOutputDir:t.clean!==void 0?t.clean:!0,generateAxiosConfig:!1,generateIndexFiles:!0}}}console.log(`Using API Docs URL: ${e.apiDocsUrl}`),console.log(`Output directory: ${e.outputDir||"Not specified - using default"}`);let s=e.outputDir||j.resolve(process.cwd(),"generated"),i=e.interfacesDir||j.join(s,"interfaces"),n=e.classesDir||j.join(s,"classes"),a=j.join(i,"index.ts"),m=j.join(n,"index.ts");e.options?.cleanOutputDir!==!1&&Ze(s),e.apiDocsUrl&&await et(e.apiDocsUrl,"api-docs.json");let g=e.apiDocsPath||"api-docs.json";await tt(g,e),e.options?.generateAxiosConfig&&st(e,s),e.options?.generateIndexFiles!==!1&&(await $e(i,a),await $e(n,m),await ot(s)),console.log("Generation completed successfully.")}nt().catch(t=>console.error("Error during generation:",t));
|