axigen 0.1.0 → 1.1.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 +157 -27
- package/dist/cli/index.mjs +155 -36
- package/dist/index.d.mts +50 -1
- package/dist/index.d.ts +50 -1
- package/dist/index.js +155 -35
- package/dist/index.mjs +155 -35
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -1,109 +1,239 @@
|
|
|
1
1
|
# axigen
|
|
2
2
|
|
|
3
|
-
> Generate typed Axios client functions from OpenAPI / Swagger
|
|
3
|
+
> Generate typed Axios client functions from your OpenAPI / Swagger spec — in one command.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/axigen)
|
|
6
6
|
[](./LICENSE)
|
|
7
|
+
[](https://nodejs.org)
|
|
7
8
|
|
|
8
|
-
##
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
**axigen** reads your OpenAPI (or Swagger) spec and generates fully-typed Axios wrapper functions, so you never have to write boilerplate API calls by hand again.
|
|
12
|
+
|
|
13
|
+
- ✅ Supports OpenAPI 3.x and Swagger 2.x (YAML or JSON)
|
|
14
|
+
- ✅ Generates typed request/response interfaces
|
|
15
|
+
- ✅ Works with your own Axios instance
|
|
16
|
+
- ✅ TypeScript and JavaScript output
|
|
17
|
+
- ✅ JSDoc comments from your spec's summaries
|
|
18
|
+
- ✅ Filter endpoints by tag
|
|
19
|
+
- ✅ Zero runtime dependencies in generated code
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
9
22
|
|
|
10
23
|
```bash
|
|
11
24
|
npm install -D axigen
|
|
12
|
-
#
|
|
25
|
+
# or
|
|
13
26
|
pnpm add -D axigen
|
|
27
|
+
# or
|
|
28
|
+
yarn add -D axigen
|
|
14
29
|
```
|
|
15
30
|
|
|
16
|
-
##
|
|
31
|
+
## Quick Start
|
|
17
32
|
|
|
18
|
-
|
|
33
|
+
**1. Create a config file:**
|
|
19
34
|
|
|
20
35
|
```bash
|
|
21
36
|
npx axigen init
|
|
22
37
|
```
|
|
23
38
|
|
|
24
|
-
|
|
39
|
+
**2. Edit `axigen.config.js`:**
|
|
25
40
|
|
|
26
41
|
```js
|
|
27
42
|
/** @type {import('axigen').AxigenConfig} */
|
|
28
43
|
module.exports = {
|
|
44
|
+
// Path to your OpenAPI spec (YAML or JSON)
|
|
29
45
|
input: "./openapi.yaml",
|
|
46
|
+
|
|
30
47
|
output: {
|
|
48
|
+
// Generated Axios client functions
|
|
31
49
|
client: "./src/api/client.ts",
|
|
50
|
+
// Generated TypeScript types
|
|
32
51
|
types: "./src/api/types.ts",
|
|
33
52
|
},
|
|
53
|
+
|
|
54
|
+
// Import path to your Axios instance inside your project
|
|
34
55
|
axiosInstancePath: "../lib/axios",
|
|
56
|
+
|
|
35
57
|
language: "ts",
|
|
36
58
|
jsdoc: true,
|
|
37
59
|
};
|
|
38
60
|
```
|
|
39
61
|
|
|
40
|
-
|
|
62
|
+
**3. Run:**
|
|
41
63
|
|
|
42
64
|
```bash
|
|
43
65
|
npx axigen generate
|
|
44
|
-
#
|
|
66
|
+
# or simply:
|
|
45
67
|
npx axigen
|
|
46
68
|
```
|
|
47
69
|
|
|
48
|
-
|
|
70
|
+
---
|
|
49
71
|
|
|
50
|
-
|
|
72
|
+
## Example
|
|
73
|
+
|
|
74
|
+
Given this OpenAPI spec:
|
|
51
75
|
|
|
52
76
|
```yaml
|
|
53
77
|
paths:
|
|
78
|
+
/users:
|
|
79
|
+
get:
|
|
80
|
+
operationId: getUsers
|
|
81
|
+
summary: List all users
|
|
82
|
+
parameters:
|
|
83
|
+
- name: page
|
|
84
|
+
in: query
|
|
85
|
+
schema:
|
|
86
|
+
type: integer
|
|
87
|
+
- name: limit
|
|
88
|
+
in: query
|
|
89
|
+
schema:
|
|
90
|
+
type: integer
|
|
91
|
+
|
|
54
92
|
/users/{userId}:
|
|
55
93
|
get:
|
|
56
94
|
operationId: getUserById
|
|
95
|
+
summary: Get a user by ID
|
|
96
|
+
parameters:
|
|
97
|
+
- name: userId
|
|
98
|
+
in: path
|
|
99
|
+
required: true
|
|
100
|
+
schema:
|
|
101
|
+
type: string
|
|
102
|
+
|
|
103
|
+
put:
|
|
104
|
+
operationId: updateUser
|
|
105
|
+
summary: Update a user
|
|
57
106
|
parameters:
|
|
58
107
|
- name: userId
|
|
59
108
|
in: path
|
|
60
109
|
required: true
|
|
110
|
+
schema:
|
|
111
|
+
type: string
|
|
112
|
+
requestBody:
|
|
113
|
+
required: true
|
|
114
|
+
content:
|
|
115
|
+
application/json:
|
|
116
|
+
schema:
|
|
117
|
+
$ref: "#/components/schemas/UpdateUserBody"
|
|
61
118
|
```
|
|
62
119
|
|
|
63
|
-
|
|
120
|
+
axigen generates:
|
|
64
121
|
|
|
65
122
|
```ts
|
|
123
|
+
// src/api/client.ts — auto-generated by axigen, do not edit
|
|
124
|
+
|
|
125
|
+
import type { AxiosResponse } from "axios";
|
|
126
|
+
import { axiosInstance } from "../lib/axios";
|
|
127
|
+
import type {
|
|
128
|
+
GetUsersQueryParams,
|
|
129
|
+
GetUsersResponse,
|
|
130
|
+
GetUserByIdPathParams,
|
|
131
|
+
GetUserByIdResponse,
|
|
132
|
+
UpdateUserPathParams,
|
|
133
|
+
UpdateUserBody,
|
|
134
|
+
UpdateUserResponse,
|
|
135
|
+
} from "./types";
|
|
136
|
+
|
|
66
137
|
/**
|
|
67
|
-
*
|
|
138
|
+
* List all users
|
|
139
|
+
* `GET /users`
|
|
140
|
+
*/
|
|
141
|
+
export async function getUsers(params?: GetUsersQueryParams): Promise<AxiosResponse<GetUsersResponse>> {
|
|
142
|
+
return axiosInstance.get("/users", { params });
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Get a user by ID
|
|
68
147
|
* `GET /users/{userId}`
|
|
69
148
|
*/
|
|
70
149
|
export async function getUserById(userId: GetUserByIdPathParams["userId"]): Promise<AxiosResponse<GetUserByIdResponse>> {
|
|
71
150
|
return axiosInstance.get(`/users/${userId}`);
|
|
72
151
|
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Update a user
|
|
155
|
+
* `PUT /users/{userId}`
|
|
156
|
+
*/
|
|
157
|
+
export async function updateUser(userId: UpdateUserPathParams["userId"], data: UpdateUserBody): Promise<AxiosResponse<UpdateUserResponse>> {
|
|
158
|
+
return axiosInstance.put(`/users/${userId}`, data);
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Configuration
|
|
165
|
+
|
|
166
|
+
| Option | Type | Default | Description |
|
|
167
|
+
| --------------------- | -------------- | --------------- | ----------------------------------------------------- |
|
|
168
|
+
| `input` | `string` | — | Path to your OpenAPI spec file (YAML or JSON) |
|
|
169
|
+
| `output.client` | `string` | — | Output path for the generated client functions |
|
|
170
|
+
| `output.types` | `string` | — | Output path for generated TypeScript types (optional) |
|
|
171
|
+
| `axiosInstancePath` | `string` | — | Import path to your Axios instance |
|
|
172
|
+
| `axiosInstanceExport` | `string` | `axiosInstance` | Named export of your Axios instance |
|
|
173
|
+
| `language` | `'ts' \| 'js'` | `'ts'` | Output language |
|
|
174
|
+
| `jsdoc` | `boolean` | `true` | Add JSDoc comments to generated functions |
|
|
175
|
+
| `tags` | `string[]` | — | Only generate endpoints matching these tags |
|
|
176
|
+
|
|
177
|
+
### Axios Instance
|
|
178
|
+
|
|
179
|
+
axigen does not create an Axios instance for you — it imports the one you already have in your project. For example:
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
// src/lib/axios.ts
|
|
183
|
+
import axios from "axios";
|
|
184
|
+
|
|
185
|
+
export const axiosInstance = axios.create({
|
|
186
|
+
baseURL: "https://api.example.com/v1",
|
|
187
|
+
headers: {
|
|
188
|
+
"Content-Type": "application/json",
|
|
189
|
+
},
|
|
190
|
+
});
|
|
73
191
|
```
|
|
74
192
|
|
|
75
|
-
|
|
193
|
+
Then in your config:
|
|
194
|
+
|
|
195
|
+
```js
|
|
196
|
+
axiosInstancePath: '../lib/axios',
|
|
197
|
+
axiosInstanceExport: 'axiosInstance', // default, can be omitted
|
|
198
|
+
```
|
|
76
199
|
|
|
77
|
-
|
|
78
|
-
| --------------------- | -------------- | --------------- | ----------------------------------- |
|
|
79
|
-
| `input` | `string` | — | مسیر فایل OpenAPI (yaml یا json) |
|
|
80
|
-
| `output.client` | `string` | — | مسیر خروجی فایل توابع |
|
|
81
|
-
| `output.types` | `string` | — | مسیر خروجی فایل types (اختیاری) |
|
|
82
|
-
| `axiosInstancePath` | `string` | — | مسیر import مربوط به axios instance |
|
|
83
|
-
| `axiosInstanceExport` | `string` | `axiosInstance` | نام export |
|
|
84
|
-
| `language` | `'ts' \| 'js'` | `'ts'` | زبان خروجی |
|
|
85
|
-
| `jsdoc` | `boolean` | `true` | اضافه کردن JSDoc |
|
|
86
|
-
| `tags` | `string[]` | — | فیلتر بر اساس تگ |
|
|
200
|
+
---
|
|
87
201
|
|
|
88
|
-
##
|
|
202
|
+
## CLI
|
|
89
203
|
|
|
90
204
|
```bash
|
|
205
|
+
# Generate client from config (default command)
|
|
91
206
|
axigen generate [--config <path>] [--cwd <path>]
|
|
207
|
+
|
|
208
|
+
# Create a starter config file
|
|
92
209
|
axigen init
|
|
210
|
+
|
|
211
|
+
# Show version
|
|
93
212
|
axigen --version
|
|
213
|
+
|
|
214
|
+
# Show help
|
|
94
215
|
axigen --help
|
|
95
216
|
```
|
|
96
217
|
|
|
97
|
-
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Programmatic Usage
|
|
221
|
+
|
|
222
|
+
You can also use axigen directly in Node.js scripts:
|
|
98
223
|
|
|
99
224
|
```ts
|
|
100
225
|
import { generate, loadConfig } from "axigen";
|
|
101
226
|
|
|
102
227
|
const config = await loadConfig(process.cwd());
|
|
103
228
|
const result = await generate(config, process.cwd());
|
|
104
|
-
|
|
229
|
+
|
|
230
|
+
console.log(`✓ Generated ${result.endpointCount} endpoints`);
|
|
231
|
+
console.log(` client → ${result.clientPath}`);
|
|
232
|
+
console.log(` types → ${result.typesPath}`);
|
|
105
233
|
```
|
|
106
234
|
|
|
107
|
-
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## License
|
|
108
238
|
|
|
109
239
|
MIT
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
#!/usr/bin/env node
|
|
3
2
|
|
|
4
3
|
// src/cli/index.ts
|
|
5
4
|
import { Command } from "commander";
|
|
@@ -67,9 +66,52 @@ function validateConfig(raw, filePath) {
|
|
|
67
66
|
axiosInstanceExport: typeof cfg.axiosInstanceExport === "string" ? cfg.axiosInstanceExport : "axiosInstance",
|
|
68
67
|
language: cfg.language === "js" ? "js" : "ts",
|
|
69
68
|
jsdoc: cfg.jsdoc !== false,
|
|
70
|
-
tags: Array.isArray(cfg.tags) ? cfg.tags : void 0
|
|
69
|
+
tags: Array.isArray(cfg.tags) ? cfg.tags : void 0,
|
|
70
|
+
functionName: validateFunctionNameConfig(cfg.functionName, filePath)
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
|
+
function validateFunctionNameConfig(raw, filePath) {
|
|
74
|
+
if (raw === void 0 || raw === null) return void 0;
|
|
75
|
+
if (typeof raw !== "object") {
|
|
76
|
+
throw new Error(`Config error: "functionName" must be an object`);
|
|
77
|
+
}
|
|
78
|
+
const fn = raw;
|
|
79
|
+
const result = {};
|
|
80
|
+
if (fn.transforms !== void 0) {
|
|
81
|
+
if (!Array.isArray(fn.transforms)) {
|
|
82
|
+
throw new Error(`Config error: "functionName.transforms" must be an array`);
|
|
83
|
+
}
|
|
84
|
+
result.transforms = fn.transforms.map((t, i) => {
|
|
85
|
+
if (!t || typeof t !== "object") {
|
|
86
|
+
throw new Error(`Config error: "functionName.transforms[${i}]" must be an object`);
|
|
87
|
+
}
|
|
88
|
+
const transform = t;
|
|
89
|
+
if (typeof transform.match !== "string") {
|
|
90
|
+
throw new Error(`Config error: "functionName.transforms[${i}].match" must be a string regex pattern`);
|
|
91
|
+
}
|
|
92
|
+
if (typeof transform.replacement !== "string") {
|
|
93
|
+
throw new Error(`Config error: "functionName.transforms[${i}].replacement" must be a string`);
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
new RegExp(transform.match, transform.flags ?? "g");
|
|
97
|
+
} catch {
|
|
98
|
+
throw new Error(`Config error: "functionName.transforms[${i}].match" is not a valid regex: ${transform.match}`);
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
match: transform.match,
|
|
102
|
+
flags: typeof transform.flags === "string" ? transform.flags : "g",
|
|
103
|
+
replacement: transform.replacement
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
if (fn.appendMethod !== void 0) {
|
|
108
|
+
if (typeof fn.appendMethod !== "boolean" && !Array.isArray(fn.appendMethod)) {
|
|
109
|
+
throw new Error(`Config error: "functionName.appendMethod" must be a boolean or an array of HTTP methods`);
|
|
110
|
+
}
|
|
111
|
+
result.appendMethod = fn.appendMethod;
|
|
112
|
+
}
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
73
115
|
|
|
74
116
|
// src/generate.ts
|
|
75
117
|
import fs3 from "fs";
|
|
@@ -244,6 +286,7 @@ function generateTypesFile(endpoints, schemas = {}) {
|
|
|
244
286
|
lines.push(`// This file is auto-generated by axigen. DO NOT EDIT.`);
|
|
245
287
|
lines.push(`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
246
288
|
lines.push("");
|
|
289
|
+
const declaredInComponents = new Set(Object.keys(schemas));
|
|
247
290
|
if (Object.keys(schemas).length > 0) {
|
|
248
291
|
lines.push("// \u2500\u2500\u2500 Component Schemas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
249
292
|
lines.push("");
|
|
@@ -255,48 +298,118 @@ function generateTypesFile(endpoints, schemas = {}) {
|
|
|
255
298
|
lines.push("");
|
|
256
299
|
}
|
|
257
300
|
}
|
|
258
|
-
|
|
259
|
-
lines.push("");
|
|
301
|
+
const endpointLines = [];
|
|
260
302
|
for (const ep of endpoints) {
|
|
261
303
|
const baseName = operationToTypeName(ep.operationId);
|
|
262
304
|
if (ep.pathParams.length > 0) {
|
|
263
|
-
|
|
305
|
+
endpointLines.push(`export interface ${baseName}PathParams {`);
|
|
264
306
|
for (const p of ep.pathParams) {
|
|
265
307
|
const type = schemaToTSType(p.schema);
|
|
266
308
|
const comment = p.description ? ` /** ${p.description} */
|
|
267
309
|
` : "";
|
|
268
|
-
|
|
310
|
+
endpointLines.push(`${comment} ${p.name}: ${type}`);
|
|
269
311
|
}
|
|
270
|
-
|
|
271
|
-
|
|
312
|
+
endpointLines.push(`}`);
|
|
313
|
+
endpointLines.push("");
|
|
272
314
|
}
|
|
273
315
|
if (ep.queryParams.length > 0) {
|
|
274
|
-
|
|
316
|
+
endpointLines.push(`export interface ${baseName}QueryParams {`);
|
|
275
317
|
for (const p of ep.queryParams) {
|
|
276
318
|
const optional = !p.required ? "?" : "";
|
|
277
319
|
const type = schemaToTSType(p.schema);
|
|
278
320
|
const comment = p.description ? ` /** ${p.description} */
|
|
279
321
|
` : "";
|
|
280
|
-
|
|
322
|
+
endpointLines.push(`${comment} ${p.name}${optional}: ${type}`);
|
|
281
323
|
}
|
|
282
|
-
|
|
283
|
-
|
|
324
|
+
endpointLines.push(`}`);
|
|
325
|
+
endpointLines.push("");
|
|
284
326
|
}
|
|
285
327
|
if (ep.bodySchema) {
|
|
286
|
-
|
|
287
|
-
|
|
328
|
+
const refName = getRefName(ep.bodySchema);
|
|
329
|
+
if (refName && declaredInComponents.has(refName)) {
|
|
330
|
+
if (`${baseName}Body` !== refName) {
|
|
331
|
+
endpointLines.push(`export type ${baseName}Body = ${refName}`);
|
|
332
|
+
endpointLines.push("");
|
|
333
|
+
}
|
|
334
|
+
} else {
|
|
335
|
+
endpointLines.push(`export type ${baseName}Body = ${schemaToTSType(ep.bodySchema)}`);
|
|
336
|
+
endpointLines.push("");
|
|
337
|
+
}
|
|
288
338
|
}
|
|
289
339
|
if (ep.responseSchema) {
|
|
290
|
-
|
|
291
|
-
|
|
340
|
+
const refName = getRefName(ep.responseSchema);
|
|
341
|
+
if (refName && declaredInComponents.has(refName)) {
|
|
342
|
+
if (`${baseName}Response` !== refName) {
|
|
343
|
+
endpointLines.push(`export type ${baseName}Response = ${refName}`);
|
|
344
|
+
endpointLines.push("");
|
|
345
|
+
}
|
|
346
|
+
} else {
|
|
347
|
+
endpointLines.push(`export type ${baseName}Response = ${schemaToTSType(ep.responseSchema)}`);
|
|
348
|
+
endpointLines.push("");
|
|
349
|
+
}
|
|
292
350
|
}
|
|
293
351
|
}
|
|
352
|
+
if (endpointLines.length > 0) {
|
|
353
|
+
lines.push("// \u2500\u2500\u2500 Endpoint Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
354
|
+
lines.push("");
|
|
355
|
+
lines.push(...endpointLines);
|
|
356
|
+
}
|
|
294
357
|
return lines.join("\n");
|
|
295
358
|
}
|
|
359
|
+
function getRefName(schema) {
|
|
360
|
+
if (schema.$ref) return refToTypeName(schema.$ref);
|
|
361
|
+
return void 0;
|
|
362
|
+
}
|
|
296
363
|
function operationToTypeName(operationId) {
|
|
297
364
|
return operationId.charAt(0).toUpperCase() + operationId.slice(1);
|
|
298
365
|
}
|
|
299
366
|
|
|
367
|
+
// src/generator/function-name.ts
|
|
368
|
+
function resolveFunctionName(operationId, method, config) {
|
|
369
|
+
if (!config) return operationId;
|
|
370
|
+
let name = operationId;
|
|
371
|
+
if (config.transforms && config.transforms.length > 0) {
|
|
372
|
+
for (const transform of config.transforms) {
|
|
373
|
+
name = applyTransform(name, transform);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
if (shouldAppendMethod(method, config.appendMethod)) {
|
|
377
|
+
const suffix = method.charAt(0).toUpperCase() + method.slice(1).toLowerCase();
|
|
378
|
+
name = name + suffix;
|
|
379
|
+
}
|
|
380
|
+
return name;
|
|
381
|
+
}
|
|
382
|
+
function applyTransform(input, transform) {
|
|
383
|
+
const flags = transform.flags ?? "g";
|
|
384
|
+
const regex = new RegExp(transform.match, flags);
|
|
385
|
+
const { replacement } = transform;
|
|
386
|
+
const upperMatch = replacement.match(/^upper:\$(\d+)$/);
|
|
387
|
+
if (upperMatch) {
|
|
388
|
+
const groupIndex = parseInt(upperMatch[1], 10);
|
|
389
|
+
return input.replace(regex, (...args) => {
|
|
390
|
+
const captured = args[groupIndex];
|
|
391
|
+
return captured ? captured.toUpperCase() : "";
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
const lowerMatch = replacement.match(/^lower:\$(\d+)$/);
|
|
395
|
+
if (lowerMatch) {
|
|
396
|
+
const groupIndex = parseInt(lowerMatch[1], 10);
|
|
397
|
+
return input.replace(regex, (...args) => {
|
|
398
|
+
const captured = args[groupIndex];
|
|
399
|
+
return captured ? captured.toLowerCase() : "";
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
return input.replace(regex, replacement);
|
|
403
|
+
}
|
|
404
|
+
function shouldAppendMethod(method, appendMethod) {
|
|
405
|
+
if (!appendMethod) return false;
|
|
406
|
+
if (appendMethod === true) return true;
|
|
407
|
+
if (Array.isArray(appendMethod)) {
|
|
408
|
+
return appendMethod.map((m) => m.toLowerCase()).includes(method.toLowerCase());
|
|
409
|
+
}
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
412
|
+
|
|
300
413
|
// src/generator/axios.ts
|
|
301
414
|
function generateClientFile(opts) {
|
|
302
415
|
const { endpoints, config, typesRelativePath } = opts;
|
|
@@ -307,7 +420,7 @@ function generateClientFile(opts) {
|
|
|
307
420
|
lines.push(`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
308
421
|
lines.push("");
|
|
309
422
|
if (isTS) {
|
|
310
|
-
lines.push(`import type { AxiosResponse } from 'axios'`);
|
|
423
|
+
lines.push(`import type { AxiosRequestConfig, AxiosResponse } from 'axios'`);
|
|
311
424
|
}
|
|
312
425
|
lines.push(`import { ${instanceExport} } from '${config.axiosInstancePath}'`);
|
|
313
426
|
if (isTS && typesRelativePath) {
|
|
@@ -319,13 +432,15 @@ function generateClientFile(opts) {
|
|
|
319
432
|
lines.push("");
|
|
320
433
|
lines.push("");
|
|
321
434
|
for (const ep of endpoints) {
|
|
322
|
-
const fn = buildFunction(ep, isTS, instanceExport, config
|
|
435
|
+
const fn = buildFunction(ep, isTS, instanceExport, config);
|
|
323
436
|
lines.push(fn);
|
|
324
437
|
lines.push("");
|
|
325
438
|
}
|
|
326
439
|
return lines.join("\n");
|
|
327
440
|
}
|
|
328
|
-
function buildFunction(ep, isTS, instanceExport,
|
|
441
|
+
function buildFunction(ep, isTS, instanceExport, config) {
|
|
442
|
+
const jsdoc = config.jsdoc !== false;
|
|
443
|
+
const fnName = resolveFunctionName(ep.operationId, ep.method, config.functionName);
|
|
329
444
|
const typeName = operationToTypeName(ep.operationId);
|
|
330
445
|
const lines = [];
|
|
331
446
|
if (jsdoc) {
|
|
@@ -340,9 +455,8 @@ function buildFunction(ep, isTS, instanceExport, jsdoc) {
|
|
|
340
455
|
}
|
|
341
456
|
const params = buildParams(ep, typeName, isTS);
|
|
342
457
|
const returnType = isTS ? buildReturnType(ep, typeName) : "";
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
const callLines = buildAxiosCall(ep, instanceExport, typeName, isTS);
|
|
458
|
+
lines.push(`export async function ${fnName}(${params})${returnType} {`);
|
|
459
|
+
const callLines = buildAxiosCall(ep, instanceExport);
|
|
346
460
|
for (const l of callLines) {
|
|
347
461
|
lines.push(` ${l}`);
|
|
348
462
|
}
|
|
@@ -365,31 +479,36 @@ function buildParams(ep, typeName, isTS) {
|
|
|
365
479
|
const type = isTS ? `: ${typeName}QueryParams` : "";
|
|
366
480
|
parts.push(`params${optional}${type}`);
|
|
367
481
|
}
|
|
482
|
+
if (isTS) {
|
|
483
|
+
parts.push(`config?: AxiosRequestConfig`);
|
|
484
|
+
parts.push(`options?: AxiosRequestConfig`);
|
|
485
|
+
} else {
|
|
486
|
+
parts.push(`config`);
|
|
487
|
+
parts.push(`options`);
|
|
488
|
+
}
|
|
368
489
|
return parts.join(", ");
|
|
369
490
|
}
|
|
370
491
|
function buildReturnType(ep, typeName) {
|
|
371
492
|
const responseType = ep.responseSchema ? `${typeName}Response` : "unknown";
|
|
372
493
|
return `: Promise<AxiosResponse<${responseType}>>`;
|
|
373
494
|
}
|
|
374
|
-
function buildAxiosCall(ep, instanceExport
|
|
495
|
+
function buildAxiosCall(ep, instanceExport) {
|
|
375
496
|
const lines = [];
|
|
376
497
|
const interpolatedPath = ep.pathParams.length > 0 ? "`" + ep.path.replace(/\{(\w+)\}/g, "${$1}") + "`" : `'${ep.path}'`;
|
|
377
498
|
const hasBody = !!ep.bodySchema;
|
|
378
499
|
const hasQuery = ep.queryParams.length > 0;
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
500
|
+
if (hasQuery) {
|
|
501
|
+
lines.push(`const mergedConfig: AxiosRequestConfig = { ...config, params: { ...params, ...config?.params } }`);
|
|
502
|
+
}
|
|
503
|
+
const configArg = hasQuery ? "mergedConfig" : "config";
|
|
504
|
+
if (hasBody) {
|
|
505
|
+
lines.push(
|
|
506
|
+
`return ${instanceExport}({ method: '${ep.method.toUpperCase()}', url: ${interpolatedPath}, data, ...${configArg} }, options)`
|
|
507
|
+
);
|
|
386
508
|
} else {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
} else {
|
|
391
|
-
lines.push(`return ${instanceExport}.${method}(${interpolatedPath}, ${bodyArg})`);
|
|
392
|
-
}
|
|
509
|
+
lines.push(
|
|
510
|
+
`return ${instanceExport}({ method: '${ep.method.toUpperCase()}', url: ${interpolatedPath}, ...${configArg} }, options)`
|
|
511
|
+
);
|
|
393
512
|
}
|
|
394
513
|
return lines;
|
|
395
514
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -74,17 +74,66 @@ interface SchemaObject {
|
|
|
74
74
|
default?: unknown;
|
|
75
75
|
example?: unknown;
|
|
76
76
|
}
|
|
77
|
+
interface FunctionNameTransform {
|
|
78
|
+
/**
|
|
79
|
+
* Regex pattern to match parts of the operationId.
|
|
80
|
+
* Example: to convert "product-variant-create" to "productVariantCreate"
|
|
81
|
+
* use: { match: '-([a-z])', replacement: (_, c) => c.toUpperCase() }
|
|
82
|
+
*
|
|
83
|
+
* Defined as a string pattern (flags supported via `flags` field).
|
|
84
|
+
*/
|
|
85
|
+
match: string;
|
|
86
|
+
/** Regex flags (e.g. 'g', 'gi'). Defaults to 'g'. */
|
|
87
|
+
flags?: string;
|
|
88
|
+
/**
|
|
89
|
+
* Replacement string. Supports capture groups via $1, $2, etc.
|
|
90
|
+
* Example: to capitalize the first char after a dash: use a replacer function
|
|
91
|
+
* defined as a template string like "upper:$1" — see docs for special tokens.
|
|
92
|
+
*
|
|
93
|
+
* Special tokens:
|
|
94
|
+
* "upper:$1" → uppercase capture group 1
|
|
95
|
+
* "lower:$1" → lowercase capture group 1
|
|
96
|
+
* any other string is used as-is (standard String.replace replacement)
|
|
97
|
+
*/
|
|
98
|
+
replacement: string;
|
|
99
|
+
}
|
|
100
|
+
interface FunctionNameConfig {
|
|
101
|
+
/**
|
|
102
|
+
* One or more regex transforms applied in order to the raw operationId.
|
|
103
|
+
* Each transform is applied to the result of the previous one.
|
|
104
|
+
*/
|
|
105
|
+
transforms?: FunctionNameTransform[];
|
|
106
|
+
/**
|
|
107
|
+
* Append the HTTP method to the end of the function name.
|
|
108
|
+
* Can be set globally or per-method.
|
|
109
|
+
*
|
|
110
|
+
* Examples:
|
|
111
|
+
* appendMethod: true → always append
|
|
112
|
+
* appendMethod: ['post','put'] → append only for these methods
|
|
113
|
+
*/
|
|
114
|
+
appendMethod?: boolean | HttpMethod[];
|
|
115
|
+
}
|
|
77
116
|
interface AxigenConfig {
|
|
117
|
+
/** Path to the OpenAPI spec file (YAML or JSON) */
|
|
78
118
|
input: string;
|
|
79
119
|
output: {
|
|
120
|
+
/** Output path for generated Axios client functions */
|
|
80
121
|
client: string;
|
|
122
|
+
/** Output path for generated TypeScript types (optional) */
|
|
81
123
|
types?: string;
|
|
82
124
|
};
|
|
125
|
+
/** Import path to the user's Axios instance */
|
|
83
126
|
axiosInstancePath: string;
|
|
127
|
+
/** Named export of the Axios instance (default: "axiosInstance") */
|
|
84
128
|
axiosInstanceExport?: string;
|
|
129
|
+
/** Output language (default: "ts") */
|
|
85
130
|
language?: "ts" | "js";
|
|
131
|
+
/** Add JSDoc comments to generated functions (default: true) */
|
|
86
132
|
jsdoc?: boolean;
|
|
133
|
+
/** Only generate endpoints matching these tags */
|
|
87
134
|
tags?: string[];
|
|
135
|
+
/** Controls how generated function names are derived from operationIds */
|
|
136
|
+
functionName?: FunctionNameConfig;
|
|
88
137
|
}
|
|
89
138
|
interface ParsedEndpoint {
|
|
90
139
|
operationId: string;
|
|
@@ -121,7 +170,7 @@ declare function extractEndpoints(spec: OpenAPISpec, filterTags?: string[]): Par
|
|
|
121
170
|
interface GenerateClientOptions {
|
|
122
171
|
endpoints: ParsedEndpoint[];
|
|
123
172
|
config: AxigenConfig;
|
|
124
|
-
/**
|
|
173
|
+
/** Relative path to the types file from the client file */
|
|
125
174
|
typesRelativePath?: string;
|
|
126
175
|
}
|
|
127
176
|
declare function generateClientFile(opts: GenerateClientOptions): string;
|
package/dist/index.d.ts
CHANGED
|
@@ -74,17 +74,66 @@ interface SchemaObject {
|
|
|
74
74
|
default?: unknown;
|
|
75
75
|
example?: unknown;
|
|
76
76
|
}
|
|
77
|
+
interface FunctionNameTransform {
|
|
78
|
+
/**
|
|
79
|
+
* Regex pattern to match parts of the operationId.
|
|
80
|
+
* Example: to convert "product-variant-create" to "productVariantCreate"
|
|
81
|
+
* use: { match: '-([a-z])', replacement: (_, c) => c.toUpperCase() }
|
|
82
|
+
*
|
|
83
|
+
* Defined as a string pattern (flags supported via `flags` field).
|
|
84
|
+
*/
|
|
85
|
+
match: string;
|
|
86
|
+
/** Regex flags (e.g. 'g', 'gi'). Defaults to 'g'. */
|
|
87
|
+
flags?: string;
|
|
88
|
+
/**
|
|
89
|
+
* Replacement string. Supports capture groups via $1, $2, etc.
|
|
90
|
+
* Example: to capitalize the first char after a dash: use a replacer function
|
|
91
|
+
* defined as a template string like "upper:$1" — see docs for special tokens.
|
|
92
|
+
*
|
|
93
|
+
* Special tokens:
|
|
94
|
+
* "upper:$1" → uppercase capture group 1
|
|
95
|
+
* "lower:$1" → lowercase capture group 1
|
|
96
|
+
* any other string is used as-is (standard String.replace replacement)
|
|
97
|
+
*/
|
|
98
|
+
replacement: string;
|
|
99
|
+
}
|
|
100
|
+
interface FunctionNameConfig {
|
|
101
|
+
/**
|
|
102
|
+
* One or more regex transforms applied in order to the raw operationId.
|
|
103
|
+
* Each transform is applied to the result of the previous one.
|
|
104
|
+
*/
|
|
105
|
+
transforms?: FunctionNameTransform[];
|
|
106
|
+
/**
|
|
107
|
+
* Append the HTTP method to the end of the function name.
|
|
108
|
+
* Can be set globally or per-method.
|
|
109
|
+
*
|
|
110
|
+
* Examples:
|
|
111
|
+
* appendMethod: true → always append
|
|
112
|
+
* appendMethod: ['post','put'] → append only for these methods
|
|
113
|
+
*/
|
|
114
|
+
appendMethod?: boolean | HttpMethod[];
|
|
115
|
+
}
|
|
77
116
|
interface AxigenConfig {
|
|
117
|
+
/** Path to the OpenAPI spec file (YAML or JSON) */
|
|
78
118
|
input: string;
|
|
79
119
|
output: {
|
|
120
|
+
/** Output path for generated Axios client functions */
|
|
80
121
|
client: string;
|
|
122
|
+
/** Output path for generated TypeScript types (optional) */
|
|
81
123
|
types?: string;
|
|
82
124
|
};
|
|
125
|
+
/** Import path to the user's Axios instance */
|
|
83
126
|
axiosInstancePath: string;
|
|
127
|
+
/** Named export of the Axios instance (default: "axiosInstance") */
|
|
84
128
|
axiosInstanceExport?: string;
|
|
129
|
+
/** Output language (default: "ts") */
|
|
85
130
|
language?: "ts" | "js";
|
|
131
|
+
/** Add JSDoc comments to generated functions (default: true) */
|
|
86
132
|
jsdoc?: boolean;
|
|
133
|
+
/** Only generate endpoints matching these tags */
|
|
87
134
|
tags?: string[];
|
|
135
|
+
/** Controls how generated function names are derived from operationIds */
|
|
136
|
+
functionName?: FunctionNameConfig;
|
|
88
137
|
}
|
|
89
138
|
interface ParsedEndpoint {
|
|
90
139
|
operationId: string;
|
|
@@ -121,7 +170,7 @@ declare function extractEndpoints(spec: OpenAPISpec, filterTags?: string[]): Par
|
|
|
121
170
|
interface GenerateClientOptions {
|
|
122
171
|
endpoints: ParsedEndpoint[];
|
|
123
172
|
config: AxigenConfig;
|
|
124
|
-
/**
|
|
173
|
+
/** Relative path to the types file from the client file */
|
|
125
174
|
typesRelativePath?: string;
|
|
126
175
|
}
|
|
127
176
|
declare function generateClientFile(opts: GenerateClientOptions): string;
|
package/dist/index.js
CHANGED
|
@@ -212,6 +212,7 @@ function generateTypesFile(endpoints, schemas = {}) {
|
|
|
212
212
|
lines.push(`// This file is auto-generated by axigen. DO NOT EDIT.`);
|
|
213
213
|
lines.push(`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
214
214
|
lines.push("");
|
|
215
|
+
const declaredInComponents = new Set(Object.keys(schemas));
|
|
215
216
|
if (Object.keys(schemas).length > 0) {
|
|
216
217
|
lines.push("// \u2500\u2500\u2500 Component Schemas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
217
218
|
lines.push("");
|
|
@@ -223,48 +224,118 @@ function generateTypesFile(endpoints, schemas = {}) {
|
|
|
223
224
|
lines.push("");
|
|
224
225
|
}
|
|
225
226
|
}
|
|
226
|
-
|
|
227
|
-
lines.push("");
|
|
227
|
+
const endpointLines = [];
|
|
228
228
|
for (const ep of endpoints) {
|
|
229
229
|
const baseName = operationToTypeName(ep.operationId);
|
|
230
230
|
if (ep.pathParams.length > 0) {
|
|
231
|
-
|
|
231
|
+
endpointLines.push(`export interface ${baseName}PathParams {`);
|
|
232
232
|
for (const p of ep.pathParams) {
|
|
233
233
|
const type = schemaToTSType(p.schema);
|
|
234
234
|
const comment = p.description ? ` /** ${p.description} */
|
|
235
235
|
` : "";
|
|
236
|
-
|
|
236
|
+
endpointLines.push(`${comment} ${p.name}: ${type}`);
|
|
237
237
|
}
|
|
238
|
-
|
|
239
|
-
|
|
238
|
+
endpointLines.push(`}`);
|
|
239
|
+
endpointLines.push("");
|
|
240
240
|
}
|
|
241
241
|
if (ep.queryParams.length > 0) {
|
|
242
|
-
|
|
242
|
+
endpointLines.push(`export interface ${baseName}QueryParams {`);
|
|
243
243
|
for (const p of ep.queryParams) {
|
|
244
244
|
const optional = !p.required ? "?" : "";
|
|
245
245
|
const type = schemaToTSType(p.schema);
|
|
246
246
|
const comment = p.description ? ` /** ${p.description} */
|
|
247
247
|
` : "";
|
|
248
|
-
|
|
248
|
+
endpointLines.push(`${comment} ${p.name}${optional}: ${type}`);
|
|
249
249
|
}
|
|
250
|
-
|
|
251
|
-
|
|
250
|
+
endpointLines.push(`}`);
|
|
251
|
+
endpointLines.push("");
|
|
252
252
|
}
|
|
253
253
|
if (ep.bodySchema) {
|
|
254
|
-
|
|
255
|
-
|
|
254
|
+
const refName = getRefName(ep.bodySchema);
|
|
255
|
+
if (refName && declaredInComponents.has(refName)) {
|
|
256
|
+
if (`${baseName}Body` !== refName) {
|
|
257
|
+
endpointLines.push(`export type ${baseName}Body = ${refName}`);
|
|
258
|
+
endpointLines.push("");
|
|
259
|
+
}
|
|
260
|
+
} else {
|
|
261
|
+
endpointLines.push(`export type ${baseName}Body = ${schemaToTSType(ep.bodySchema)}`);
|
|
262
|
+
endpointLines.push("");
|
|
263
|
+
}
|
|
256
264
|
}
|
|
257
265
|
if (ep.responseSchema) {
|
|
258
|
-
|
|
259
|
-
|
|
266
|
+
const refName = getRefName(ep.responseSchema);
|
|
267
|
+
if (refName && declaredInComponents.has(refName)) {
|
|
268
|
+
if (`${baseName}Response` !== refName) {
|
|
269
|
+
endpointLines.push(`export type ${baseName}Response = ${refName}`);
|
|
270
|
+
endpointLines.push("");
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
endpointLines.push(`export type ${baseName}Response = ${schemaToTSType(ep.responseSchema)}`);
|
|
274
|
+
endpointLines.push("");
|
|
275
|
+
}
|
|
260
276
|
}
|
|
261
277
|
}
|
|
278
|
+
if (endpointLines.length > 0) {
|
|
279
|
+
lines.push("// \u2500\u2500\u2500 Endpoint Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
280
|
+
lines.push("");
|
|
281
|
+
lines.push(...endpointLines);
|
|
282
|
+
}
|
|
262
283
|
return lines.join("\n");
|
|
263
284
|
}
|
|
285
|
+
function getRefName(schema) {
|
|
286
|
+
if (schema.$ref) return refToTypeName(schema.$ref);
|
|
287
|
+
return void 0;
|
|
288
|
+
}
|
|
264
289
|
function operationToTypeName(operationId) {
|
|
265
290
|
return operationId.charAt(0).toUpperCase() + operationId.slice(1);
|
|
266
291
|
}
|
|
267
292
|
|
|
293
|
+
// src/generator/function-name.ts
|
|
294
|
+
function resolveFunctionName(operationId, method, config) {
|
|
295
|
+
if (!config) return operationId;
|
|
296
|
+
let name = operationId;
|
|
297
|
+
if (config.transforms && config.transforms.length > 0) {
|
|
298
|
+
for (const transform of config.transforms) {
|
|
299
|
+
name = applyTransform(name, transform);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (shouldAppendMethod(method, config.appendMethod)) {
|
|
303
|
+
const suffix = method.charAt(0).toUpperCase() + method.slice(1).toLowerCase();
|
|
304
|
+
name = name + suffix;
|
|
305
|
+
}
|
|
306
|
+
return name;
|
|
307
|
+
}
|
|
308
|
+
function applyTransform(input, transform) {
|
|
309
|
+
const flags = transform.flags ?? "g";
|
|
310
|
+
const regex = new RegExp(transform.match, flags);
|
|
311
|
+
const { replacement } = transform;
|
|
312
|
+
const upperMatch = replacement.match(/^upper:\$(\d+)$/);
|
|
313
|
+
if (upperMatch) {
|
|
314
|
+
const groupIndex = parseInt(upperMatch[1], 10);
|
|
315
|
+
return input.replace(regex, (...args) => {
|
|
316
|
+
const captured = args[groupIndex];
|
|
317
|
+
return captured ? captured.toUpperCase() : "";
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
const lowerMatch = replacement.match(/^lower:\$(\d+)$/);
|
|
321
|
+
if (lowerMatch) {
|
|
322
|
+
const groupIndex = parseInt(lowerMatch[1], 10);
|
|
323
|
+
return input.replace(regex, (...args) => {
|
|
324
|
+
const captured = args[groupIndex];
|
|
325
|
+
return captured ? captured.toLowerCase() : "";
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
return input.replace(regex, replacement);
|
|
329
|
+
}
|
|
330
|
+
function shouldAppendMethod(method, appendMethod) {
|
|
331
|
+
if (!appendMethod) return false;
|
|
332
|
+
if (appendMethod === true) return true;
|
|
333
|
+
if (Array.isArray(appendMethod)) {
|
|
334
|
+
return appendMethod.map((m) => m.toLowerCase()).includes(method.toLowerCase());
|
|
335
|
+
}
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
|
|
268
339
|
// src/generator/axios.ts
|
|
269
340
|
function generateClientFile(opts) {
|
|
270
341
|
const { endpoints, config, typesRelativePath } = opts;
|
|
@@ -275,7 +346,7 @@ function generateClientFile(opts) {
|
|
|
275
346
|
lines.push(`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
276
347
|
lines.push("");
|
|
277
348
|
if (isTS) {
|
|
278
|
-
lines.push(`import type { AxiosResponse } from 'axios'`);
|
|
349
|
+
lines.push(`import type { AxiosRequestConfig, AxiosResponse } from 'axios'`);
|
|
279
350
|
}
|
|
280
351
|
lines.push(`import { ${instanceExport} } from '${config.axiosInstancePath}'`);
|
|
281
352
|
if (isTS && typesRelativePath) {
|
|
@@ -287,13 +358,15 @@ function generateClientFile(opts) {
|
|
|
287
358
|
lines.push("");
|
|
288
359
|
lines.push("");
|
|
289
360
|
for (const ep of endpoints) {
|
|
290
|
-
const fn = buildFunction(ep, isTS, instanceExport, config
|
|
361
|
+
const fn = buildFunction(ep, isTS, instanceExport, config);
|
|
291
362
|
lines.push(fn);
|
|
292
363
|
lines.push("");
|
|
293
364
|
}
|
|
294
365
|
return lines.join("\n");
|
|
295
366
|
}
|
|
296
|
-
function buildFunction(ep, isTS, instanceExport,
|
|
367
|
+
function buildFunction(ep, isTS, instanceExport, config) {
|
|
368
|
+
const jsdoc = config.jsdoc !== false;
|
|
369
|
+
const fnName = resolveFunctionName(ep.operationId, ep.method, config.functionName);
|
|
297
370
|
const typeName = operationToTypeName(ep.operationId);
|
|
298
371
|
const lines = [];
|
|
299
372
|
if (jsdoc) {
|
|
@@ -308,9 +381,8 @@ function buildFunction(ep, isTS, instanceExport, jsdoc) {
|
|
|
308
381
|
}
|
|
309
382
|
const params = buildParams(ep, typeName, isTS);
|
|
310
383
|
const returnType = isTS ? buildReturnType(ep, typeName) : "";
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
const callLines = buildAxiosCall(ep, instanceExport, typeName, isTS);
|
|
384
|
+
lines.push(`export async function ${fnName}(${params})${returnType} {`);
|
|
385
|
+
const callLines = buildAxiosCall(ep, instanceExport);
|
|
314
386
|
for (const l of callLines) {
|
|
315
387
|
lines.push(` ${l}`);
|
|
316
388
|
}
|
|
@@ -333,31 +405,36 @@ function buildParams(ep, typeName, isTS) {
|
|
|
333
405
|
const type = isTS ? `: ${typeName}QueryParams` : "";
|
|
334
406
|
parts.push(`params${optional}${type}`);
|
|
335
407
|
}
|
|
408
|
+
if (isTS) {
|
|
409
|
+
parts.push(`config?: AxiosRequestConfig`);
|
|
410
|
+
parts.push(`options?: AxiosRequestConfig`);
|
|
411
|
+
} else {
|
|
412
|
+
parts.push(`config`);
|
|
413
|
+
parts.push(`options`);
|
|
414
|
+
}
|
|
336
415
|
return parts.join(", ");
|
|
337
416
|
}
|
|
338
417
|
function buildReturnType(ep, typeName) {
|
|
339
418
|
const responseType = ep.responseSchema ? `${typeName}Response` : "unknown";
|
|
340
419
|
return `: Promise<AxiosResponse<${responseType}>>`;
|
|
341
420
|
}
|
|
342
|
-
function buildAxiosCall(ep, instanceExport
|
|
421
|
+
function buildAxiosCall(ep, instanceExport) {
|
|
343
422
|
const lines = [];
|
|
344
423
|
const interpolatedPath = ep.pathParams.length > 0 ? "`" + ep.path.replace(/\{(\w+)\}/g, "${$1}") + "`" : `'${ep.path}'`;
|
|
345
424
|
const hasBody = !!ep.bodySchema;
|
|
346
425
|
const hasQuery = ep.queryParams.length > 0;
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
426
|
+
if (hasQuery) {
|
|
427
|
+
lines.push(`const mergedConfig: AxiosRequestConfig = { ...config, params: { ...params, ...config?.params } }`);
|
|
428
|
+
}
|
|
429
|
+
const configArg = hasQuery ? "mergedConfig" : "config";
|
|
430
|
+
if (hasBody) {
|
|
431
|
+
lines.push(
|
|
432
|
+
`return ${instanceExport}({ method: '${ep.method.toUpperCase()}', url: ${interpolatedPath}, data, ...${configArg} }, options)`
|
|
433
|
+
);
|
|
354
434
|
} else {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
} else {
|
|
359
|
-
lines.push(`return ${instanceExport}.${method}(${interpolatedPath}, ${bodyArg})`);
|
|
360
|
-
}
|
|
435
|
+
lines.push(
|
|
436
|
+
`return ${instanceExport}({ method: '${ep.method.toUpperCase()}', url: ${interpolatedPath}, ...${configArg} }, options)`
|
|
437
|
+
);
|
|
361
438
|
}
|
|
362
439
|
return lines;
|
|
363
440
|
}
|
|
@@ -482,9 +559,52 @@ function validateConfig(raw, filePath) {
|
|
|
482
559
|
axiosInstanceExport: typeof cfg.axiosInstanceExport === "string" ? cfg.axiosInstanceExport : "axiosInstance",
|
|
483
560
|
language: cfg.language === "js" ? "js" : "ts",
|
|
484
561
|
jsdoc: cfg.jsdoc !== false,
|
|
485
|
-
tags: Array.isArray(cfg.tags) ? cfg.tags : void 0
|
|
562
|
+
tags: Array.isArray(cfg.tags) ? cfg.tags : void 0,
|
|
563
|
+
functionName: validateFunctionNameConfig(cfg.functionName, filePath)
|
|
486
564
|
};
|
|
487
565
|
}
|
|
566
|
+
function validateFunctionNameConfig(raw, filePath) {
|
|
567
|
+
if (raw === void 0 || raw === null) return void 0;
|
|
568
|
+
if (typeof raw !== "object") {
|
|
569
|
+
throw new Error(`Config error: "functionName" must be an object`);
|
|
570
|
+
}
|
|
571
|
+
const fn = raw;
|
|
572
|
+
const result = {};
|
|
573
|
+
if (fn.transforms !== void 0) {
|
|
574
|
+
if (!Array.isArray(fn.transforms)) {
|
|
575
|
+
throw new Error(`Config error: "functionName.transforms" must be an array`);
|
|
576
|
+
}
|
|
577
|
+
result.transforms = fn.transforms.map((t, i) => {
|
|
578
|
+
if (!t || typeof t !== "object") {
|
|
579
|
+
throw new Error(`Config error: "functionName.transforms[${i}]" must be an object`);
|
|
580
|
+
}
|
|
581
|
+
const transform = t;
|
|
582
|
+
if (typeof transform.match !== "string") {
|
|
583
|
+
throw new Error(`Config error: "functionName.transforms[${i}].match" must be a string regex pattern`);
|
|
584
|
+
}
|
|
585
|
+
if (typeof transform.replacement !== "string") {
|
|
586
|
+
throw new Error(`Config error: "functionName.transforms[${i}].replacement" must be a string`);
|
|
587
|
+
}
|
|
588
|
+
try {
|
|
589
|
+
new RegExp(transform.match, transform.flags ?? "g");
|
|
590
|
+
} catch {
|
|
591
|
+
throw new Error(`Config error: "functionName.transforms[${i}].match" is not a valid regex: ${transform.match}`);
|
|
592
|
+
}
|
|
593
|
+
return {
|
|
594
|
+
match: transform.match,
|
|
595
|
+
flags: typeof transform.flags === "string" ? transform.flags : "g",
|
|
596
|
+
replacement: transform.replacement
|
|
597
|
+
};
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
if (fn.appendMethod !== void 0) {
|
|
601
|
+
if (typeof fn.appendMethod !== "boolean" && !Array.isArray(fn.appendMethod)) {
|
|
602
|
+
throw new Error(`Config error: "functionName.appendMethod" must be a boolean or an array of HTTP methods`);
|
|
603
|
+
}
|
|
604
|
+
result.appendMethod = fn.appendMethod;
|
|
605
|
+
}
|
|
606
|
+
return result;
|
|
607
|
+
}
|
|
488
608
|
// Annotate the CommonJS export names for ESM import in node:
|
|
489
609
|
0 && (module.exports = {
|
|
490
610
|
extractEndpoints,
|
package/dist/index.mjs
CHANGED
|
@@ -171,6 +171,7 @@ function generateTypesFile(endpoints, schemas = {}) {
|
|
|
171
171
|
lines.push(`// This file is auto-generated by axigen. DO NOT EDIT.`);
|
|
172
172
|
lines.push(`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
173
173
|
lines.push("");
|
|
174
|
+
const declaredInComponents = new Set(Object.keys(schemas));
|
|
174
175
|
if (Object.keys(schemas).length > 0) {
|
|
175
176
|
lines.push("// \u2500\u2500\u2500 Component Schemas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
176
177
|
lines.push("");
|
|
@@ -182,48 +183,118 @@ function generateTypesFile(endpoints, schemas = {}) {
|
|
|
182
183
|
lines.push("");
|
|
183
184
|
}
|
|
184
185
|
}
|
|
185
|
-
|
|
186
|
-
lines.push("");
|
|
186
|
+
const endpointLines = [];
|
|
187
187
|
for (const ep of endpoints) {
|
|
188
188
|
const baseName = operationToTypeName(ep.operationId);
|
|
189
189
|
if (ep.pathParams.length > 0) {
|
|
190
|
-
|
|
190
|
+
endpointLines.push(`export interface ${baseName}PathParams {`);
|
|
191
191
|
for (const p of ep.pathParams) {
|
|
192
192
|
const type = schemaToTSType(p.schema);
|
|
193
193
|
const comment = p.description ? ` /** ${p.description} */
|
|
194
194
|
` : "";
|
|
195
|
-
|
|
195
|
+
endpointLines.push(`${comment} ${p.name}: ${type}`);
|
|
196
196
|
}
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
endpointLines.push(`}`);
|
|
198
|
+
endpointLines.push("");
|
|
199
199
|
}
|
|
200
200
|
if (ep.queryParams.length > 0) {
|
|
201
|
-
|
|
201
|
+
endpointLines.push(`export interface ${baseName}QueryParams {`);
|
|
202
202
|
for (const p of ep.queryParams) {
|
|
203
203
|
const optional = !p.required ? "?" : "";
|
|
204
204
|
const type = schemaToTSType(p.schema);
|
|
205
205
|
const comment = p.description ? ` /** ${p.description} */
|
|
206
206
|
` : "";
|
|
207
|
-
|
|
207
|
+
endpointLines.push(`${comment} ${p.name}${optional}: ${type}`);
|
|
208
208
|
}
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
endpointLines.push(`}`);
|
|
210
|
+
endpointLines.push("");
|
|
211
211
|
}
|
|
212
212
|
if (ep.bodySchema) {
|
|
213
|
-
|
|
214
|
-
|
|
213
|
+
const refName = getRefName(ep.bodySchema);
|
|
214
|
+
if (refName && declaredInComponents.has(refName)) {
|
|
215
|
+
if (`${baseName}Body` !== refName) {
|
|
216
|
+
endpointLines.push(`export type ${baseName}Body = ${refName}`);
|
|
217
|
+
endpointLines.push("");
|
|
218
|
+
}
|
|
219
|
+
} else {
|
|
220
|
+
endpointLines.push(`export type ${baseName}Body = ${schemaToTSType(ep.bodySchema)}`);
|
|
221
|
+
endpointLines.push("");
|
|
222
|
+
}
|
|
215
223
|
}
|
|
216
224
|
if (ep.responseSchema) {
|
|
217
|
-
|
|
218
|
-
|
|
225
|
+
const refName = getRefName(ep.responseSchema);
|
|
226
|
+
if (refName && declaredInComponents.has(refName)) {
|
|
227
|
+
if (`${baseName}Response` !== refName) {
|
|
228
|
+
endpointLines.push(`export type ${baseName}Response = ${refName}`);
|
|
229
|
+
endpointLines.push("");
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
endpointLines.push(`export type ${baseName}Response = ${schemaToTSType(ep.responseSchema)}`);
|
|
233
|
+
endpointLines.push("");
|
|
234
|
+
}
|
|
219
235
|
}
|
|
220
236
|
}
|
|
237
|
+
if (endpointLines.length > 0) {
|
|
238
|
+
lines.push("// \u2500\u2500\u2500 Endpoint Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
239
|
+
lines.push("");
|
|
240
|
+
lines.push(...endpointLines);
|
|
241
|
+
}
|
|
221
242
|
return lines.join("\n");
|
|
222
243
|
}
|
|
244
|
+
function getRefName(schema) {
|
|
245
|
+
if (schema.$ref) return refToTypeName(schema.$ref);
|
|
246
|
+
return void 0;
|
|
247
|
+
}
|
|
223
248
|
function operationToTypeName(operationId) {
|
|
224
249
|
return operationId.charAt(0).toUpperCase() + operationId.slice(1);
|
|
225
250
|
}
|
|
226
251
|
|
|
252
|
+
// src/generator/function-name.ts
|
|
253
|
+
function resolveFunctionName(operationId, method, config) {
|
|
254
|
+
if (!config) return operationId;
|
|
255
|
+
let name = operationId;
|
|
256
|
+
if (config.transforms && config.transforms.length > 0) {
|
|
257
|
+
for (const transform of config.transforms) {
|
|
258
|
+
name = applyTransform(name, transform);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (shouldAppendMethod(method, config.appendMethod)) {
|
|
262
|
+
const suffix = method.charAt(0).toUpperCase() + method.slice(1).toLowerCase();
|
|
263
|
+
name = name + suffix;
|
|
264
|
+
}
|
|
265
|
+
return name;
|
|
266
|
+
}
|
|
267
|
+
function applyTransform(input, transform) {
|
|
268
|
+
const flags = transform.flags ?? "g";
|
|
269
|
+
const regex = new RegExp(transform.match, flags);
|
|
270
|
+
const { replacement } = transform;
|
|
271
|
+
const upperMatch = replacement.match(/^upper:\$(\d+)$/);
|
|
272
|
+
if (upperMatch) {
|
|
273
|
+
const groupIndex = parseInt(upperMatch[1], 10);
|
|
274
|
+
return input.replace(regex, (...args) => {
|
|
275
|
+
const captured = args[groupIndex];
|
|
276
|
+
return captured ? captured.toUpperCase() : "";
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
const lowerMatch = replacement.match(/^lower:\$(\d+)$/);
|
|
280
|
+
if (lowerMatch) {
|
|
281
|
+
const groupIndex = parseInt(lowerMatch[1], 10);
|
|
282
|
+
return input.replace(regex, (...args) => {
|
|
283
|
+
const captured = args[groupIndex];
|
|
284
|
+
return captured ? captured.toLowerCase() : "";
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
return input.replace(regex, replacement);
|
|
288
|
+
}
|
|
289
|
+
function shouldAppendMethod(method, appendMethod) {
|
|
290
|
+
if (!appendMethod) return false;
|
|
291
|
+
if (appendMethod === true) return true;
|
|
292
|
+
if (Array.isArray(appendMethod)) {
|
|
293
|
+
return appendMethod.map((m) => m.toLowerCase()).includes(method.toLowerCase());
|
|
294
|
+
}
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
|
|
227
298
|
// src/generator/axios.ts
|
|
228
299
|
function generateClientFile(opts) {
|
|
229
300
|
const { endpoints, config, typesRelativePath } = opts;
|
|
@@ -234,7 +305,7 @@ function generateClientFile(opts) {
|
|
|
234
305
|
lines.push(`// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
235
306
|
lines.push("");
|
|
236
307
|
if (isTS) {
|
|
237
|
-
lines.push(`import type { AxiosResponse } from 'axios'`);
|
|
308
|
+
lines.push(`import type { AxiosRequestConfig, AxiosResponse } from 'axios'`);
|
|
238
309
|
}
|
|
239
310
|
lines.push(`import { ${instanceExport} } from '${config.axiosInstancePath}'`);
|
|
240
311
|
if (isTS && typesRelativePath) {
|
|
@@ -246,13 +317,15 @@ function generateClientFile(opts) {
|
|
|
246
317
|
lines.push("");
|
|
247
318
|
lines.push("");
|
|
248
319
|
for (const ep of endpoints) {
|
|
249
|
-
const fn = buildFunction(ep, isTS, instanceExport, config
|
|
320
|
+
const fn = buildFunction(ep, isTS, instanceExport, config);
|
|
250
321
|
lines.push(fn);
|
|
251
322
|
lines.push("");
|
|
252
323
|
}
|
|
253
324
|
return lines.join("\n");
|
|
254
325
|
}
|
|
255
|
-
function buildFunction(ep, isTS, instanceExport,
|
|
326
|
+
function buildFunction(ep, isTS, instanceExport, config) {
|
|
327
|
+
const jsdoc = config.jsdoc !== false;
|
|
328
|
+
const fnName = resolveFunctionName(ep.operationId, ep.method, config.functionName);
|
|
256
329
|
const typeName = operationToTypeName(ep.operationId);
|
|
257
330
|
const lines = [];
|
|
258
331
|
if (jsdoc) {
|
|
@@ -267,9 +340,8 @@ function buildFunction(ep, isTS, instanceExport, jsdoc) {
|
|
|
267
340
|
}
|
|
268
341
|
const params = buildParams(ep, typeName, isTS);
|
|
269
342
|
const returnType = isTS ? buildReturnType(ep, typeName) : "";
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
const callLines = buildAxiosCall(ep, instanceExport, typeName, isTS);
|
|
343
|
+
lines.push(`export async function ${fnName}(${params})${returnType} {`);
|
|
344
|
+
const callLines = buildAxiosCall(ep, instanceExport);
|
|
273
345
|
for (const l of callLines) {
|
|
274
346
|
lines.push(` ${l}`);
|
|
275
347
|
}
|
|
@@ -292,31 +364,36 @@ function buildParams(ep, typeName, isTS) {
|
|
|
292
364
|
const type = isTS ? `: ${typeName}QueryParams` : "";
|
|
293
365
|
parts.push(`params${optional}${type}`);
|
|
294
366
|
}
|
|
367
|
+
if (isTS) {
|
|
368
|
+
parts.push(`config?: AxiosRequestConfig`);
|
|
369
|
+
parts.push(`options?: AxiosRequestConfig`);
|
|
370
|
+
} else {
|
|
371
|
+
parts.push(`config`);
|
|
372
|
+
parts.push(`options`);
|
|
373
|
+
}
|
|
295
374
|
return parts.join(", ");
|
|
296
375
|
}
|
|
297
376
|
function buildReturnType(ep, typeName) {
|
|
298
377
|
const responseType = ep.responseSchema ? `${typeName}Response` : "unknown";
|
|
299
378
|
return `: Promise<AxiosResponse<${responseType}>>`;
|
|
300
379
|
}
|
|
301
|
-
function buildAxiosCall(ep, instanceExport
|
|
380
|
+
function buildAxiosCall(ep, instanceExport) {
|
|
302
381
|
const lines = [];
|
|
303
382
|
const interpolatedPath = ep.pathParams.length > 0 ? "`" + ep.path.replace(/\{(\w+)\}/g, "${$1}") + "`" : `'${ep.path}'`;
|
|
304
383
|
const hasBody = !!ep.bodySchema;
|
|
305
384
|
const hasQuery = ep.queryParams.length > 0;
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
385
|
+
if (hasQuery) {
|
|
386
|
+
lines.push(`const mergedConfig: AxiosRequestConfig = { ...config, params: { ...params, ...config?.params } }`);
|
|
387
|
+
}
|
|
388
|
+
const configArg = hasQuery ? "mergedConfig" : "config";
|
|
389
|
+
if (hasBody) {
|
|
390
|
+
lines.push(
|
|
391
|
+
`return ${instanceExport}({ method: '${ep.method.toUpperCase()}', url: ${interpolatedPath}, data, ...${configArg} }, options)`
|
|
392
|
+
);
|
|
313
393
|
} else {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
} else {
|
|
318
|
-
lines.push(`return ${instanceExport}.${method}(${interpolatedPath}, ${bodyArg})`);
|
|
319
|
-
}
|
|
394
|
+
lines.push(
|
|
395
|
+
`return ${instanceExport}({ method: '${ep.method.toUpperCase()}', url: ${interpolatedPath}, ...${configArg} }, options)`
|
|
396
|
+
);
|
|
320
397
|
}
|
|
321
398
|
return lines;
|
|
322
399
|
}
|
|
@@ -441,9 +518,52 @@ function validateConfig(raw, filePath) {
|
|
|
441
518
|
axiosInstanceExport: typeof cfg.axiosInstanceExport === "string" ? cfg.axiosInstanceExport : "axiosInstance",
|
|
442
519
|
language: cfg.language === "js" ? "js" : "ts",
|
|
443
520
|
jsdoc: cfg.jsdoc !== false,
|
|
444
|
-
tags: Array.isArray(cfg.tags) ? cfg.tags : void 0
|
|
521
|
+
tags: Array.isArray(cfg.tags) ? cfg.tags : void 0,
|
|
522
|
+
functionName: validateFunctionNameConfig(cfg.functionName, filePath)
|
|
445
523
|
};
|
|
446
524
|
}
|
|
525
|
+
function validateFunctionNameConfig(raw, filePath) {
|
|
526
|
+
if (raw === void 0 || raw === null) return void 0;
|
|
527
|
+
if (typeof raw !== "object") {
|
|
528
|
+
throw new Error(`Config error: "functionName" must be an object`);
|
|
529
|
+
}
|
|
530
|
+
const fn = raw;
|
|
531
|
+
const result = {};
|
|
532
|
+
if (fn.transforms !== void 0) {
|
|
533
|
+
if (!Array.isArray(fn.transforms)) {
|
|
534
|
+
throw new Error(`Config error: "functionName.transforms" must be an array`);
|
|
535
|
+
}
|
|
536
|
+
result.transforms = fn.transforms.map((t, i) => {
|
|
537
|
+
if (!t || typeof t !== "object") {
|
|
538
|
+
throw new Error(`Config error: "functionName.transforms[${i}]" must be an object`);
|
|
539
|
+
}
|
|
540
|
+
const transform = t;
|
|
541
|
+
if (typeof transform.match !== "string") {
|
|
542
|
+
throw new Error(`Config error: "functionName.transforms[${i}].match" must be a string regex pattern`);
|
|
543
|
+
}
|
|
544
|
+
if (typeof transform.replacement !== "string") {
|
|
545
|
+
throw new Error(`Config error: "functionName.transforms[${i}].replacement" must be a string`);
|
|
546
|
+
}
|
|
547
|
+
try {
|
|
548
|
+
new RegExp(transform.match, transform.flags ?? "g");
|
|
549
|
+
} catch {
|
|
550
|
+
throw new Error(`Config error: "functionName.transforms[${i}].match" is not a valid regex: ${transform.match}`);
|
|
551
|
+
}
|
|
552
|
+
return {
|
|
553
|
+
match: transform.match,
|
|
554
|
+
flags: typeof transform.flags === "string" ? transform.flags : "g",
|
|
555
|
+
replacement: transform.replacement
|
|
556
|
+
};
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
if (fn.appendMethod !== void 0) {
|
|
560
|
+
if (typeof fn.appendMethod !== "boolean" && !Array.isArray(fn.appendMethod)) {
|
|
561
|
+
throw new Error(`Config error: "functionName.appendMethod" must be a boolean or an array of HTTP methods`);
|
|
562
|
+
}
|
|
563
|
+
result.appendMethod = fn.appendMethod;
|
|
564
|
+
}
|
|
565
|
+
return result;
|
|
566
|
+
}
|
|
447
567
|
export {
|
|
448
568
|
extractEndpoints,
|
|
449
569
|
generate,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "axigen",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Generate typed Axios client functions from OpenAPI / Swagger specs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openapi",
|
|
@@ -37,7 +37,11 @@
|
|
|
37
37
|
"dev": "tsx src/cli/index.ts",
|
|
38
38
|
"typecheck": "tsc --noEmit",
|
|
39
39
|
"lint": "eslint src --ext .ts",
|
|
40
|
-
"prepublishOnly": "npm run build && npm run typecheck"
|
|
40
|
+
"prepublishOnly": "npm run build && npm run typecheck",
|
|
41
|
+
"release": "standard-version",
|
|
42
|
+
"release:minor": "standard-version --release-as minor",
|
|
43
|
+
"release:major": "standard-version --release-as major",
|
|
44
|
+
"release:patch": "standard-version --release-as patch"
|
|
41
45
|
},
|
|
42
46
|
"dependencies": {
|
|
43
47
|
"chalk": "^5.3.0",
|
|
@@ -48,6 +52,7 @@
|
|
|
48
52
|
"devDependencies": {
|
|
49
53
|
"@types/js-yaml": "^4.0.9",
|
|
50
54
|
"@types/node": "^20.19.43",
|
|
55
|
+
"standard-version": "^9.5.0",
|
|
51
56
|
"tsup": "^8.0.2",
|
|
52
57
|
"tsx": "^4.7.0",
|
|
53
58
|
"typescript": "^5.3.3"
|