@moccona/apicodegen 0.0.1 → 0.0.2
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 +49 -0
- package/npm/index.cjs +121 -45
- package/npm/index.cjs.map +1 -1
- package/npm/index.d.cts +2 -2
- package/npm/index.d.ts +2 -2
- package/npm/index.js +121 -45
- package/npm/index.js.map +1 -1
- package/npm/vite/index.d.ts +29 -0
- package/{bin/cli.cjs → npm/vite/index.js} +394 -283
- package/npm/vite/index.js.map +1 -0
- package/package.json +19 -16
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# @moccona/apicodegen
|
|
2
|
+
|
|
3
|
+
`@moccona/apicodegen` is a command-line tool for generating TypeScript code from OpenAPI documentation. It provides a simple and efficient way to automate the process of creating API clients.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
To install `@moccona/apicodegen`, you can use npm or yarn:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install -g @moccona/apicodegen
|
|
11
|
+
|
|
12
|
+
or
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
yarn global add @moccona/apicodegen
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
### Basic Command
|
|
21
|
+
|
|
22
|
+
The basic command to generate TypeScript code from an OpenAPI documentation URL is as follows:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
apicodegen <docURL> --output ./output.ts
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- `<docURL>`: The URL of the OpenAPI documentation file.
|
|
29
|
+
- `--output`: The path where the generated TypeScript code will be saved. Default is `./output.ts`.
|
|
30
|
+
- `--adaptor`: The adaptor for API calls. Default is `fetch`.
|
|
31
|
+
- `--baseURL`: The base path of the API endpoint.
|
|
32
|
+
- `--verbose`: Enable verbose logging.
|
|
33
|
+
- `--importClientSource`: The source from which the request tool will be imported.
|
|
34
|
+
|
|
35
|
+
## Example
|
|
36
|
+
|
|
37
|
+
To generate TypeScript code from an OpenAPI documentation file located at `https://api.example.com/openapi.json` and save it to `./src/api.ts`, you can run:
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
apicodegen https://api.example.com/openapi.json --output ./src/api.ts
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Contributing
|
|
44
|
+
|
|
45
|
+
Contributions are welcome! Please read the [contributing guidelines](./CONTRIBUTING.md) before submitting a pull request.
|
|
46
|
+
|
|
47
|
+
## License
|
|
48
|
+
|
|
49
|
+
This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
|
package/npm/index.cjs
CHANGED
|
@@ -260,10 +260,10 @@ var Base = class _Base {
|
|
|
260
260
|
* @param [operationId] - Unique identifier for the operation.
|
|
261
261
|
* @returns - The generated function name.
|
|
262
262
|
*/
|
|
263
|
-
static pathToFnName(path, method,
|
|
264
|
-
const name = this.camelCase(this.normalize(path));
|
|
263
|
+
static pathToFnName(path, method, _operationId = "") {
|
|
264
|
+
const name = this.normalize(this.camelCase(this.normalize(path)));
|
|
265
265
|
const suffix = method ? this.capitalize(this.upperCamelCase(`using_${method}`)) : "";
|
|
266
|
-
return
|
|
266
|
+
return name + suffix;
|
|
267
267
|
}
|
|
268
268
|
/**
|
|
269
269
|
* Normalizes a string by replacing special characters and avoiding TypeScript keywords.
|
|
@@ -274,7 +274,7 @@ var Base = class _Base {
|
|
|
274
274
|
if (typescriptKeywords.has(text)) {
|
|
275
275
|
text += "_";
|
|
276
276
|
}
|
|
277
|
-
return text.replace(/[/\-_{}():\s
|
|
277
|
+
return text.replace(/[/\-_{}():\s`,*<>$#.]/gm, "_").replace(/^\d./gm, "").replaceAll("...", "");
|
|
278
278
|
}
|
|
279
279
|
/**
|
|
280
280
|
* Capitalizes the first character of a string.
|
|
@@ -484,7 +484,7 @@ var Generator = class _Generator {
|
|
|
484
484
|
* @param path - The base path string containing placeholders.
|
|
485
485
|
* @param parameters - Array of parameter objects defining the parameters.
|
|
486
486
|
* @param basePath - Optional base path to prepend (default: "").
|
|
487
|
-
* @returns A TypeScript template
|
|
487
|
+
* @returns A TypeScript template expressi
|
|
488
488
|
*/
|
|
489
489
|
static toUrlTemplate(path, parameters, basePath = "") {
|
|
490
490
|
const queryParameters = parameters.filter(
|
|
@@ -492,7 +492,7 @@ var Generator = class _Generator {
|
|
|
492
492
|
);
|
|
493
493
|
if (queryParameters.length > 0) {
|
|
494
494
|
const queryString = queryParameters.map(
|
|
495
|
-
(qp, index) => `${index === 0 ? "?" : "&"}${encodeURIComponent(qp.name)}={${qp.name}}`
|
|
495
|
+
(qp, index) => `${index === 0 ? "?" : "&"}${encodeURIComponent(qp.name)}={${Base.camelCase(Base.normalize(qp.name))}}`
|
|
496
496
|
).join("");
|
|
497
497
|
path += queryString;
|
|
498
498
|
}
|
|
@@ -607,7 +607,7 @@ var Generator = class _Generator {
|
|
|
607
607
|
case "boolean" /* boolean */:
|
|
608
608
|
return import_typescript.factory.createToken(import_typescript.SyntaxKind.BooleanKeyword);
|
|
609
609
|
case "file" /* file */:
|
|
610
|
-
return import_typescript.factory.createTypeReferenceNode(import_typescript.factory.createIdentifier("
|
|
610
|
+
return import_typescript.factory.createTypeReferenceNode(import_typescript.factory.createIdentifier("Blob"));
|
|
611
611
|
default:
|
|
612
612
|
const {
|
|
613
613
|
format: format2,
|
|
@@ -626,7 +626,7 @@ var Generator = class _Generator {
|
|
|
626
626
|
return import_typescript.factory.createToken(import_typescript.SyntaxKind.BooleanKeyword);
|
|
627
627
|
case "blob" /* blob */:
|
|
628
628
|
case "binary" /* binary */:
|
|
629
|
-
return import_typescript.factory.createTypeReferenceNode(import_typescript.factory.createIdentifier("
|
|
629
|
+
return import_typescript.factory.createTypeReferenceNode(import_typescript.factory.createIdentifier("Blob"));
|
|
630
630
|
default:
|
|
631
631
|
}
|
|
632
632
|
if (enum_) {
|
|
@@ -650,13 +650,13 @@ var Generator = class _Generator {
|
|
|
650
650
|
);
|
|
651
651
|
}
|
|
652
652
|
if (allOf) {
|
|
653
|
-
return import_typescript.factory.
|
|
653
|
+
return import_typescript.factory.createIntersectionTypeNode(
|
|
654
654
|
allOf.map((schema2) => this.toTypeNode(schema2))
|
|
655
655
|
);
|
|
656
656
|
}
|
|
657
657
|
if (type2 && typeof type2 === "string") {
|
|
658
658
|
return import_typescript.factory.createTypeReferenceNode(
|
|
659
|
-
type2 !== "unknown" ? import_typescript.factory.createIdentifier(Base.upperCamelCase(type2)) : type2
|
|
659
|
+
type2 !== "unknown" && type2 !== "null" ? import_typescript.factory.createIdentifier(Base.upperCamelCase(type2)) : type2
|
|
660
660
|
);
|
|
661
661
|
}
|
|
662
662
|
}
|
|
@@ -730,16 +730,11 @@ var Generator = class _Generator {
|
|
|
730
730
|
)
|
|
731
731
|
);
|
|
732
732
|
statements.push(fdDeclaration);
|
|
733
|
-
parameters.
|
|
734
|
-
(parameter) => parameter.ref !== void 0 && (parameter.in === "formData" /* formData */ || parameter.schema && this.isBinarySchema(parameter.schema))
|
|
735
|
-
).forEach((parameter) => {
|
|
733
|
+
parameters.forEach((parameter) => {
|
|
736
734
|
statements.push(
|
|
737
735
|
import_typescript.factory.createExpressionStatement(
|
|
738
736
|
import_typescript.factory.createBinaryExpression(
|
|
739
|
-
import_typescript.factory.
|
|
740
|
-
import_typescript.factory.createIdentifier("req"),
|
|
741
|
-
import_typescript.factory.createStringLiteral(parameter.name)
|
|
742
|
-
),
|
|
737
|
+
import_typescript.factory.createIdentifier(parameter.name),
|
|
743
738
|
import_typescript.factory.createToken(import_typescript.SyntaxKind.AmpersandAmpersandToken),
|
|
744
739
|
import_typescript.factory.createCallExpression(
|
|
745
740
|
import_typescript.factory.createPropertyAccessExpression(
|
|
@@ -783,7 +778,13 @@ var Generator = class _Generator {
|
|
|
783
778
|
import_typescript.factory.createStringLiteral(key),
|
|
784
779
|
import_typescript.factory.createIdentifier("file"),
|
|
785
780
|
import_typescript.factory.createPropertyAccessExpression(
|
|
786
|
-
import_typescript.factory.
|
|
781
|
+
import_typescript.factory.createAsExpression(
|
|
782
|
+
import_typescript.factory.createIdentifier("file"),
|
|
783
|
+
import_typescript.factory.createTypeReferenceNode(
|
|
784
|
+
import_typescript.factory.createIdentifier("File"),
|
|
785
|
+
void 0
|
|
786
|
+
)
|
|
787
|
+
),
|
|
787
788
|
import_typescript.factory.createIdentifier("name")
|
|
788
789
|
)
|
|
789
790
|
]
|
|
@@ -868,25 +869,28 @@ var Generator = class _Generator {
|
|
|
868
869
|
);
|
|
869
870
|
const shouldParseResponseToJSON = "application/json" === response?.type;
|
|
870
871
|
const isRequestBodyBinary = requestBody?.schema && requestBody.schema.type === "array" /* array */ && this.isBinarySchema(requestBody.schema);
|
|
871
|
-
const
|
|
872
|
-
(p) => p.in === "formData" /* formData */
|
|
872
|
+
const parametersShouldPutInFormData = parameters.filter(
|
|
873
|
+
(p) => p.in === "formData" /* formData */ || p.schema && this.isBinarySchema(p.schema)
|
|
873
874
|
);
|
|
874
|
-
const
|
|
875
|
-
(p) => p
|
|
875
|
+
const parametersShouldNotPutInFormData = parameters.filter(
|
|
876
|
+
(p) => !parametersShouldPutInFormData.includes(p)
|
|
876
877
|
);
|
|
877
|
-
const isRequestBodyContainsBinary = requestBody?.schema && "properties" in requestBody.schema && Object.values(requestBody.schema
|
|
878
|
+
const isRequestBodyContainsBinary = requestBody?.schema && "properties" in requestBody.schema && Object.values(requestBody.schema?.properties ?? {}).some(
|
|
878
879
|
(p) => this.isBinarySchema(p)
|
|
879
880
|
);
|
|
880
881
|
const hasBinaryInParameters = parameters.some(
|
|
881
882
|
(p) => p?.schema && this.isBinarySchema(p.schema)
|
|
882
883
|
);
|
|
883
|
-
const shouldPutParametersOrBodyInFormData = isFormDataRequest || isRequestBodyBinary || hasBinaryInParameters || isRequestBodyContainsBinary ||
|
|
884
|
+
const shouldPutParametersOrBodyInFormData = isFormDataRequest || isRequestBodyBinary || hasBinaryInParameters || isRequestBodyContainsBinary || parametersShouldPutInFormData.length > 0;
|
|
884
885
|
return import_typescript.factory.createBlock([
|
|
885
|
-
...shouldPutParametersOrBodyInFormData ? this.toFormDataStatement(
|
|
886
|
+
...shouldPutParametersOrBodyInFormData ? this.toFormDataStatement(
|
|
887
|
+
parametersShouldPutInFormData,
|
|
888
|
+
requestBody?.schema
|
|
889
|
+
) : [],
|
|
886
890
|
...adapter.client(
|
|
887
891
|
uri,
|
|
888
892
|
method,
|
|
889
|
-
|
|
893
|
+
parametersShouldNotPutInFormData,
|
|
890
894
|
requestBody,
|
|
891
895
|
response,
|
|
892
896
|
adapter,
|
|
@@ -1222,7 +1226,7 @@ var FetchAdapter = class extends Adapter {
|
|
|
1222
1226
|
],
|
|
1223
1227
|
void 0,
|
|
1224
1228
|
import_typescript3.factory.createToken(import_typescript3.SyntaxKind.EqualsGreaterThanToken),
|
|
1225
|
-
import_typescript3.factory.createAsExpression(
|
|
1229
|
+
response?.schema ? import_typescript3.factory.createAsExpression(
|
|
1226
1230
|
import_typescript3.factory.createParenthesizedExpression(
|
|
1227
1231
|
import_typescript3.factory.createAwaitExpression(
|
|
1228
1232
|
import_typescript3.factory.createCallExpression(
|
|
@@ -1236,6 +1240,17 @@ var FetchAdapter = class extends Adapter {
|
|
|
1236
1240
|
)
|
|
1237
1241
|
),
|
|
1238
1242
|
response?.schema ? Generator.toTypeNode(response.schema) : import_typescript3.factory.createToken(import_typescript3.SyntaxKind.UnknownKeyword)
|
|
1243
|
+
) : import_typescript3.factory.createParenthesizedExpression(
|
|
1244
|
+
import_typescript3.factory.createAwaitExpression(
|
|
1245
|
+
import_typescript3.factory.createCallExpression(
|
|
1246
|
+
import_typescript3.factory.createPropertyAccessExpression(
|
|
1247
|
+
import_typescript3.factory.createIdentifier("response"),
|
|
1248
|
+
import_typescript3.factory.createIdentifier("json")
|
|
1249
|
+
),
|
|
1250
|
+
void 0,
|
|
1251
|
+
[]
|
|
1252
|
+
)
|
|
1253
|
+
)
|
|
1239
1254
|
)
|
|
1240
1255
|
)
|
|
1241
1256
|
]
|
|
@@ -1346,13 +1361,25 @@ var V2 = class {
|
|
|
1346
1361
|
enum: enum_,
|
|
1347
1362
|
format: format2,
|
|
1348
1363
|
allOf: allOf?.map(
|
|
1349
|
-
(s) => Base.isRef(s) ? {
|
|
1364
|
+
(s) => Base.isRef(s) ? {
|
|
1365
|
+
...s,
|
|
1366
|
+
ref: s.$ref,
|
|
1367
|
+
type: Base.upperCamelCase(Base.ref2name(s.$ref, this.doc))
|
|
1368
|
+
} : this.toBaseSchema(s, enums)
|
|
1350
1369
|
),
|
|
1351
1370
|
anyOf: anyOf?.map(
|
|
1352
|
-
(s) => Base.isRef(s) ? {
|
|
1371
|
+
(s) => Base.isRef(s) ? {
|
|
1372
|
+
...s,
|
|
1373
|
+
ref: s.$ref,
|
|
1374
|
+
type: Base.upperCamelCase(Base.ref2name(s.$ref, this.doc))
|
|
1375
|
+
} : this.toBaseSchema(s, enums)
|
|
1353
1376
|
),
|
|
1354
1377
|
oneOf: oneOf?.map(
|
|
1355
|
-
(s) => Base.isRef(s) ? {
|
|
1378
|
+
(s) => Base.isRef(s) ? {
|
|
1379
|
+
...s,
|
|
1380
|
+
ref: s.$ref,
|
|
1381
|
+
type: Base.upperCamelCase(Base.ref2name(s.$ref, this.doc))
|
|
1382
|
+
} : this.toBaseSchema(s, enums)
|
|
1356
1383
|
),
|
|
1357
1384
|
properties: Object.keys(properties).reduce((acc, p) => {
|
|
1358
1385
|
const propSchema = properties[p];
|
|
@@ -1382,7 +1409,8 @@ var V2 = class {
|
|
|
1382
1409
|
type,
|
|
1383
1410
|
items,
|
|
1384
1411
|
enum: enum_,
|
|
1385
|
-
properties
|
|
1412
|
+
properties,
|
|
1413
|
+
schema
|
|
1386
1414
|
} = parameter;
|
|
1387
1415
|
if (enum_) {
|
|
1388
1416
|
const type2 = Base.upperCamelCase(upLevelSchemaKey) + Base.upperCamelCase(name);
|
|
@@ -1404,17 +1432,36 @@ var V2 = class {
|
|
|
1404
1432
|
}
|
|
1405
1433
|
};
|
|
1406
1434
|
}
|
|
1435
|
+
if (items) {
|
|
1436
|
+
return {
|
|
1437
|
+
name,
|
|
1438
|
+
required,
|
|
1439
|
+
description,
|
|
1440
|
+
in: parameter.in,
|
|
1441
|
+
schema: {
|
|
1442
|
+
type,
|
|
1443
|
+
items
|
|
1444
|
+
}
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
if (schema && Base.isRef(schema)) {
|
|
1448
|
+
return {
|
|
1449
|
+
name,
|
|
1450
|
+
required,
|
|
1451
|
+
description,
|
|
1452
|
+
in: parameter.in,
|
|
1453
|
+
schema: {
|
|
1454
|
+
type: Base.upperCamelCase(Base.ref2name(schema.$ref))
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1407
1458
|
return {
|
|
1408
1459
|
name,
|
|
1409
1460
|
required,
|
|
1410
1461
|
description,
|
|
1411
1462
|
in: parameter.in,
|
|
1412
|
-
schema:
|
|
1463
|
+
schema: {
|
|
1413
1464
|
type,
|
|
1414
|
-
items
|
|
1415
|
-
} : {
|
|
1416
|
-
type,
|
|
1417
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
1418
1465
|
properties
|
|
1419
1466
|
}
|
|
1420
1467
|
};
|
|
@@ -1493,6 +1540,7 @@ var V2 = class {
|
|
|
1493
1540
|
if (code in responses2) {
|
|
1494
1541
|
const response = responses2[code];
|
|
1495
1542
|
const responseSchema = this.getResponseByRef(response);
|
|
1543
|
+
const inBodyOnlyHasBody = inBody && inBody.length === 1 && inBody[0].in === "body" && inBody[0].name === "body";
|
|
1496
1544
|
methodApis.push({
|
|
1497
1545
|
method,
|
|
1498
1546
|
operationId,
|
|
@@ -1501,7 +1549,12 @@ var V2 = class {
|
|
|
1501
1549
|
description: description_,
|
|
1502
1550
|
parameters: uniqueParameterName.map((name) => notInBody.find((p) => p.name === name)).filter(Boolean),
|
|
1503
1551
|
responses: responseSchema,
|
|
1504
|
-
requestBody: inBody.length > 0 ? [
|
|
1552
|
+
requestBody: inBody.length > 0 ? inBodyOnlyHasBody ? [
|
|
1553
|
+
{
|
|
1554
|
+
type: "application/json" /* JSON */,
|
|
1555
|
+
schema: inBody[0].schema
|
|
1556
|
+
}
|
|
1557
|
+
] : [
|
|
1505
1558
|
{
|
|
1506
1559
|
type: "application/json" /* JSON */,
|
|
1507
1560
|
schema: {
|
|
@@ -1709,13 +1762,25 @@ var V3 = class {
|
|
|
1709
1762
|
enum: enum_,
|
|
1710
1763
|
format: format2,
|
|
1711
1764
|
allOf: allOf?.map(
|
|
1712
|
-
(s) => Base.isRef(s) ? {
|
|
1765
|
+
(s) => Base.isRef(s) ? {
|
|
1766
|
+
...s,
|
|
1767
|
+
ref: s.$ref,
|
|
1768
|
+
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1769
|
+
} : this.toBaseSchema(s, enums)
|
|
1713
1770
|
),
|
|
1714
1771
|
anyOf: anyOf?.map(
|
|
1715
|
-
(s) => Base.isRef(s) ? {
|
|
1772
|
+
(s) => Base.isRef(s) ? {
|
|
1773
|
+
...s,
|
|
1774
|
+
ref: s.$ref,
|
|
1775
|
+
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1776
|
+
} : this.toBaseSchema(s, enums)
|
|
1716
1777
|
),
|
|
1717
1778
|
oneOf: oneOf?.map(
|
|
1718
|
-
(s) => Base.isRef(s) ? {
|
|
1779
|
+
(s) => Base.isRef(s) ? {
|
|
1780
|
+
...s,
|
|
1781
|
+
ref: s.$ref,
|
|
1782
|
+
type: Base.capitalize(Base.ref2name(s.$ref, this.doc))
|
|
1783
|
+
} : this.toBaseSchema(s, enums)
|
|
1719
1784
|
),
|
|
1720
1785
|
properties: Object.keys(properties).reduce((acc, p) => {
|
|
1721
1786
|
const propSchema = properties[p];
|
|
@@ -2012,13 +2077,25 @@ var V3_1 = class {
|
|
|
2012
2077
|
enum: enum_,
|
|
2013
2078
|
format: format2,
|
|
2014
2079
|
allOf: allOf?.map(
|
|
2015
|
-
(s) => Base.isRef(s) ? {
|
|
2080
|
+
(s) => Base.isRef(s) ? {
|
|
2081
|
+
...s,
|
|
2082
|
+
ref: s.$ref,
|
|
2083
|
+
type: Base.upperCamelCase(Base.ref2name(s.$ref, this.doc))
|
|
2084
|
+
} : this.toBaseSchema(s, enums)
|
|
2016
2085
|
),
|
|
2017
2086
|
anyOf: anyOf?.map(
|
|
2018
|
-
(s) => Base.isRef(s) ? {
|
|
2087
|
+
(s) => Base.isRef(s) ? {
|
|
2088
|
+
...s,
|
|
2089
|
+
ref: s.$ref,
|
|
2090
|
+
type: Base.upperCamelCase(Base.ref2name(s.$ref, this.doc))
|
|
2091
|
+
} : this.toBaseSchema(s, enums)
|
|
2019
2092
|
),
|
|
2020
2093
|
oneOf: oneOf?.map(
|
|
2021
|
-
(s) => Base.isRef(s) ? {
|
|
2094
|
+
(s) => Base.isRef(s) ? {
|
|
2095
|
+
...s,
|
|
2096
|
+
ref: s.$ref,
|
|
2097
|
+
type: Base.upperCamelCase(Base.ref2name(s.$ref, this.doc))
|
|
2098
|
+
} : this.toBaseSchema(s, enums)
|
|
2022
2099
|
),
|
|
2023
2100
|
properties: Object.keys(properties).reduce((acc, p) => {
|
|
2024
2101
|
const propSchema = properties[p];
|
|
@@ -2275,13 +2352,12 @@ function apiCodeGenPlugin(options) {
|
|
|
2275
2352
|
await tsc();
|
|
2276
2353
|
} catch (error) {
|
|
2277
2354
|
logger2.error(error);
|
|
2278
|
-
process.exit(1);
|
|
2279
2355
|
}
|
|
2280
2356
|
return {
|
|
2281
2357
|
...config,
|
|
2282
2358
|
server: {
|
|
2283
2359
|
...config.server ?? {},
|
|
2284
|
-
proxy: proxies
|
|
2360
|
+
proxy: Object.assign({}, config.server?.proxy ?? {}, proxies)
|
|
2285
2361
|
}
|
|
2286
2362
|
};
|
|
2287
2363
|
}
|