@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 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, operationId) {
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 (operationId ? this.camelCase(this.normalize(operationId)) : name) + suffix;
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`,*<>$]/gm, "_").replaceAll("...", "");
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 expression node.
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("File"));
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("File"));
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.createUnionTypeNode(
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.filter(
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.createElementAccessExpression(
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.createIdentifier("file"),
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 inFormDataParameters = parameters.filter(
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 notInFormDataParameters = parameters.filter(
875
- (p) => p.in !== "formData" /* formData */
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.properties).some(
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 || inFormDataParameters.length > 0;
884
+ const shouldPutParametersOrBodyInFormData = isFormDataRequest || isRequestBodyBinary || hasBinaryInParameters || isRequestBodyContainsBinary || parametersShouldPutInFormData.length > 0;
884
885
  return import_typescript.factory.createBlock([
885
- ...shouldPutParametersOrBodyInFormData ? this.toFormDataStatement(inFormDataParameters, requestBody?.schema) : [],
886
+ ...shouldPutParametersOrBodyInFormData ? this.toFormDataStatement(
887
+ parametersShouldPutInFormData,
888
+ requestBody?.schema
889
+ ) : [],
886
890
  ...adapter.client(
887
891
  uri,
888
892
  method,
889
- notInFormDataParameters,
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) ? { type: Base.upperCamelCase(Base.ref2name(s.$ref, this.doc)) } : this.toBaseSchema(s, enums)
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) ? { type: Base.upperCamelCase(Base.ref2name(s.$ref, this.doc)) } : this.toBaseSchema(s, enums)
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) ? { type: Base.upperCamelCase(Base.ref2name(s.$ref, this.doc)) } : this.toBaseSchema(s, enums)
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: items ? {
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) ? { type: Base.capitalize(Base.ref2name(s.$ref, this.doc)) } : this.toBaseSchema(s, enums)
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) ? { type: Base.capitalize(Base.ref2name(s.$ref, this.doc)) } : this.toBaseSchema(s, enums)
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) ? { type: Base.capitalize(Base.ref2name(s.$ref, this.doc)) } : this.toBaseSchema(s, enums)
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) ? { type: Base.upperCamelCase(Base.ref2name(s.$ref, this.doc)) } : this.toBaseSchema(s, enums)
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) ? { type: Base.upperCamelCase(Base.ref2name(s.$ref, this.doc)) } : this.toBaseSchema(s, enums)
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) ? { type: Base.upperCamelCase(Base.ref2name(s.$ref, this.doc)) } : this.toBaseSchema(s, enums)
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
  }