swagger-typescript-api 11.1.1 → 11.1.3

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/cli/index.js CHANGED
File without changes
package/index.d.ts CHANGED
@@ -315,6 +315,7 @@ export enum RequestContentKind {
315
315
  FORM_DATA = "FORM_DATA",
316
316
  IMAGE = "IMAGE",
317
317
  OTHER = "OTHER",
318
+ TEXT = "TEXT",
318
319
  }
319
320
 
320
321
  export interface RequestResponseInfo {
package/index.js CHANGED
@@ -308,7 +308,9 @@ const main = async () => {
308
308
  } catch (e) {
309
309
  console.error(e);
310
310
  process.exit(1);
311
+ return;
311
312
  }
313
+ process.exit(0);
312
314
  };
313
315
 
314
316
  main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swagger-typescript-api",
3
- "version": "11.1.1",
3
+ "version": "11.1.3",
4
4
  "description": "Generate typescript/javascript api from swagger schema",
5
5
  "scripts": {
6
6
  "cli:json": "node index.js -r -d -p ./swagger-test-cli.json -n swagger-test-cli.ts",
@@ -38,6 +38,7 @@
38
38
  "test:--enum-names-as-values": "node tests/spec/enumNamesAsValues/test.js",
39
39
  "test:--default-response": "node tests/spec/defaultResponse/test.js",
40
40
  "test:--js": "node tests/spec/js/test.js",
41
+ "test:jsSingleHttpClientModular": "node tests/spec/jsSingleHttpClientModular/test.js",
41
42
  "test:--js--axios": "node tests/spec/jsAxios/test.js",
42
43
  "test:--axios": "node tests/spec/axios/test.js",
43
44
  "test:--another-array-type": "node tests/spec/another-array-type/test.js",
@@ -46,11 +47,16 @@
46
47
  "test:--type-suffix--type-prefix": "node tests/spec/typeSuffixPrefix/test.js",
47
48
  "test:--dot-path-params": "node tests/spec/dot-path-params/test.js",
48
49
  "test:--primitive-type-constructs": "node tests/spec/primitive-type-constructs/test.js",
49
- "test:--cli": "node index.js -p tests/spec/cli/schema.json -o tests/spec/cli -n schema.ts --extract-response-body --extract-response-error --api-class-name MySuperApi --type-prefix Prefix",
50
+ "test:--cli": "node index.js -p tests/spec/cli/schema.json -o tests/spec/cli -n schema.ts --extract-response-body --extract-response-error --api-class-name MySuperApi --type-prefix Prefix && node tests/spec/cli/test.js",
50
51
  "test:partialBaseTemplate": "node tests/spec/partialBaseTemplate/test.js",
51
52
  "test:partialDefaultTemplate": "node tests/spec/partialDefaultTemplate/test.js",
52
53
  "test:--patch": "node tests/spec/patch/test.js",
53
- "test:deprecated": "node tests/spec/deprecated/test.js"
54
+ "test:deprecated": "node tests/spec/deprecated/test.js",
55
+ "test:nullableRefTest3.0": "node tests/spec/nullable-3.0/test.js",
56
+ "test:nullableRefTest2.0": "node tests/spec/nullable-2.0/test.js",
57
+ "test:additionalProperties2.0": "node tests/spec/additional-properties-2.0/test.js",
58
+ "test:enums2.0": "node tests/spec/enums-2.0/test.js",
59
+ "test:another-query-params": "node tests/spec/another-query-params/test.js"
54
60
  },
55
61
  "author": "acacode",
56
62
  "license": "MIT",
@@ -61,6 +67,7 @@
61
67
  "@types/node": "^18.11.7",
62
68
  "@types/prettier": "^2.7.1",
63
69
  "all-contributors-cli": "^6.20.0",
70
+ "axios": "^1.1.3",
64
71
  "cross-env": "^7.0.3",
65
72
  "git-diff": "^2.0.6",
66
73
  "husky": "^4.3.6",
package/src/index.js CHANGED
File without changes
@@ -149,7 +149,7 @@ class SchemaParser {
149
149
  });
150
150
  },
151
151
  [SCHEMA_TYPES.OBJECT]: (schema, typeName) => {
152
- const content = this.getObjectSchemaContent(schema);
152
+ const contentProperties = this.getObjectSchemaContent(schema);
153
153
 
154
154
  return this.attachParsedRef(schema, {
155
155
  ...(_.isObject(schema) ? schema : {}),
@@ -159,8 +159,8 @@ class SchemaParser {
159
159
  typeIdentifier: this.config.Ts.Keyword.Interface,
160
160
  name: typeName,
161
161
  description: this.schemaFormatters.formatDescription(schema.description),
162
- allFieldsAreOptional: !_.some(_.values(content), (part) => part.isRequired),
163
- content: content,
162
+ allFieldsAreOptional: !_.some(_.values(contentProperties), (part) => part.isRequired),
163
+ content: contentProperties,
164
164
  });
165
165
  },
166
166
  [SCHEMA_TYPES.COMPLEX]: (schema, typeName) => {
@@ -424,7 +424,7 @@ class SchemaParser {
424
424
  };
425
425
  });
426
426
 
427
- if (additionalProperties === true) {
427
+ if (additionalProperties) {
428
428
  propertiesContent.push({
429
429
  $$raw: { additionalProperties },
430
430
  description: "",
@@ -16,6 +16,7 @@ const CONTENT_KIND = {
16
16
  FORM_DATA: "FORM_DATA",
17
17
  IMAGE: "IMAGE",
18
18
  OTHER: "OTHER",
19
+ TEXT: "TEXT",
19
20
  };
20
21
 
21
22
  class SchemaRoutes {
@@ -103,25 +104,24 @@ class SchemaRoutes {
103
104
  this.logger.warn("wrong path param name", paramName);
104
105
  }
105
106
 
106
- return [
107
- ...pathParams,
108
- {
109
- $match: match,
110
- name: _.camelCase(paramName),
111
- required: true,
107
+ pathParams.push({
108
+ $match: match,
109
+ name: _.camelCase(paramName),
110
+ required: true,
111
+ type: "string",
112
+ description: "",
113
+ schema: {
112
114
  type: "string",
113
- description: "",
114
- schema: {
115
- type: "string",
116
- },
117
- in: "path",
118
115
  },
119
- ];
116
+ in: "path",
117
+ });
118
+
119
+ return pathParams;
120
120
  },
121
121
  [],
122
122
  );
123
123
 
124
- const fixedRoute = _.reduce(
124
+ let fixedRoute = _.reduce(
125
125
  pathParams,
126
126
  (fixedRoute, pathParam) => {
127
127
  return _.replace(fixedRoute, pathParam.$match, `\${${pathParam.name}}`);
@@ -129,14 +129,47 @@ class SchemaRoutes {
129
129
  routeName || "",
130
130
  );
131
131
 
132
+ const queryParamMatches = fixedRoute.match(/(\{\?.*\})/g);
133
+ const queryParams = [];
134
+
135
+ if (queryParamMatches && queryParamMatches.length) {
136
+ queryParamMatches.forEach((match) => {
137
+ fixedRoute = fixedRoute.replace(match, "");
138
+ });
139
+
140
+ _.uniq(
141
+ queryParamMatches
142
+ .join(",")
143
+ .replace(/(\{\?)|(\})|\s/g, "")
144
+ .split(","),
145
+ ).forEach((paramName) => {
146
+ if (_.includes(paramName, "-")) {
147
+ this.logger.warn("wrong query param name", paramName);
148
+ }
149
+
150
+ queryParams.push({
151
+ $match: paramName,
152
+ name: _.camelCase(paramName),
153
+ required: true,
154
+ type: "string",
155
+ description: "",
156
+ schema: {
157
+ type: "string",
158
+ },
159
+ in: "query",
160
+ });
161
+ });
162
+ }
163
+
132
164
  return {
133
165
  originalRoute: routeName || "",
134
166
  route: fixedRoute,
135
167
  pathParams,
168
+ queryParams,
136
169
  };
137
170
  };
138
171
 
139
- getRouteParams = (routeInfo, pathParams) => {
172
+ getRouteParams = (routeInfo, pathParamsFromRouteName, queryParamsFromRouteName) => {
140
173
  const { parameters } = routeInfo;
141
174
 
142
175
  const routeParams = {
@@ -186,13 +219,21 @@ class SchemaRoutes {
186
219
  });
187
220
 
188
221
  // used in case when path parameters is not declared in requestInfo.parameters ("in": "path")
189
- _.each(pathParams, (pathParam) => {
222
+ _.each(pathParamsFromRouteName, (pathParam) => {
190
223
  const alreadyExist = _.some(routeParams.path, (parameter) => parameter.name === pathParam.name);
191
224
 
192
225
  if (!alreadyExist) {
193
226
  routeParams.path.push(pathParam);
194
227
  }
195
228
  });
229
+ // used in case when path parameters is not declared in requestInfo.parameters ("in": "path")
230
+ _.each(queryParamsFromRouteName, (queryParam) => {
231
+ const alreadyExist = _.some(routeParams.query, (parameter) => parameter.name === queryParam.name);
232
+
233
+ if (!alreadyExist) {
234
+ routeParams.query.push(queryParam);
235
+ }
236
+ });
196
237
 
197
238
  return routeParams;
198
239
  };
@@ -207,7 +248,7 @@ class SchemaRoutes {
207
248
 
208
249
  getContentKind = (contentTypes) => {
209
250
  if (
210
- _.includes(contentTypes, "application/json") ||
251
+ _.some(contentTypes, (contentType) => _.startsWith(contentType, "application/json")) ||
211
252
  _.some(contentTypes, (contentType) => _.endsWith(contentType, "+json"))
212
253
  ) {
213
254
  return CONTENT_KIND.JSON;
@@ -225,6 +266,12 @@ class SchemaRoutes {
225
266
  return CONTENT_KIND.IMAGE;
226
267
  }
227
268
 
269
+ if (
270
+ _.some(contentTypes, (contentType) => _.startsWith(contentType, "text/"))
271
+ ) {
272
+ return CONTENT_KIND.TEXT;
273
+ }
274
+
228
275
  return CONTENT_KIND.OTHER;
229
276
  };
230
277
 
@@ -642,7 +689,11 @@ class SchemaRoutes {
642
689
  consumes,
643
690
  ...otherInfo
644
691
  } = routeInfo;
645
- const { route, pathParams } = this.parseRouteName(rawRouteName);
692
+ const {
693
+ route,
694
+ pathParams: pathParamsFromRouteName,
695
+ queryParams: queryParamsFromRouteName,
696
+ } = this.parseRouteName(rawRouteName);
646
697
 
647
698
  const routeId = generateId();
648
699
  const firstTag = tags && tags.length > 0 ? tags[0] : null;
@@ -655,7 +706,7 @@ class SchemaRoutes {
655
706
  hasSecurity = security.length > 0;
656
707
  }
657
708
 
658
- const routeParams = this.getRouteParams(routeInfo, pathParams);
709
+ const routeParams = this.getRouteParams(routeInfo, pathParamsFromRouteName, queryParamsFromRouteName);
659
710
 
660
711
  const pathArgs = routeParams.path.map((pathArgSchema) => ({
661
712
  name: pathArgSchema.name,
@@ -1,49 +1,60 @@
1
- const ts = require("typescript");
2
-
3
- function translate(fileName, content, options) {
4
- const output = {};
5
- const host = ts.createCompilerHost(options, true);
6
- const fileNames = [fileName];
7
- const originalSourceFileGet = host.getSourceFile.bind(host);
8
- host.getSourceFile = (sourceFileName, languageVersion, onError, shouldCreateNewSourceFile) => {
9
- if (sourceFileName !== fileName)
10
- return originalSourceFileGet(sourceFileName, languageVersion, onError, shouldCreateNewSourceFile);
11
-
12
- return ts.createSourceFile(sourceFileName, content, languageVersion, true, ts.ScriptKind.External);
13
- };
14
-
15
- host.writeFile = (fileName, contents) => {
16
- output[fileName] = contents;
17
- };
18
-
19
- ts.createProgram(fileNames, options, host).emit();
20
-
21
- return output;
22
- }
23
-
24
- module.exports = {
25
- translate: (fileName, sourceTypeScript) => {
26
- const translated = translate(fileName, sourceTypeScript, {
27
- module: "ESNext",
28
- noImplicitReturns: true,
29
- alwaysStrict: true,
30
- target: ts.ScriptTarget.ESNext,
31
- declaration: true,
32
- noImplicitAny: false,
33
- sourceMap: false,
34
- removeComments: false,
35
- disableSizeLimit: true,
36
- esModuleInterop: true,
37
- emitDecoratorMetadata: true,
38
- skipLibCheck: true,
39
- });
40
-
41
- const sourceFileName = fileName.replace(ts.Extension.Ts, ts.Extension.Js);
42
- const declarationFileName = fileName.replace(ts.Extension.Ts, ts.Extension.Dts);
43
-
44
- return {
45
- sourceContent: translated[sourceFileName],
46
- declarationContent: translated[declarationFileName],
47
- };
48
- },
49
- };
1
+ const ts = require("typescript");
2
+
3
+ function translate(fileName, content, options) {
4
+ const output = {};
5
+ const host = ts.createCompilerHost(options, true);
6
+ const fileNames = [fileName];
7
+ const originalSourceFileGet = host.getSourceFile.bind(host);
8
+ host.getSourceFile = (sourceFileName, languageVersion, onError, shouldCreateNewSourceFile) => {
9
+ if (sourceFileName !== fileName)
10
+ return originalSourceFileGet(sourceFileName, languageVersion, onError, shouldCreateNewSourceFile);
11
+
12
+ return ts.createSourceFile(sourceFileName, content, languageVersion, true, ts.ScriptKind.External);
13
+ };
14
+
15
+ host.writeFile = (fileName, contents) => {
16
+ output[fileName] = contents;
17
+ };
18
+
19
+ ts.createProgram(fileNames, options, host).emit();
20
+
21
+ return output;
22
+ }
23
+
24
+ module.exports = {
25
+ translate: (fileName, sourceTypeScript) => {
26
+ const translated = translate(fileName, sourceTypeScript, {
27
+ module: "ESNext",
28
+ noImplicitReturns: true,
29
+ alwaysStrict: true,
30
+ target: ts.ScriptTarget.ESNext,
31
+ declaration: true,
32
+ noImplicitAny: false,
33
+ sourceMap: false,
34
+ removeComments: false,
35
+ disableSizeLimit: true,
36
+ esModuleInterop: true,
37
+ emitDecoratorMetadata: true,
38
+ skipLibCheck: true,
39
+ });
40
+
41
+ const sourceFileName = fileName.replace(ts.Extension.Ts, ts.Extension.Js);
42
+ const declarationFileName = fileName.replace(ts.Extension.Ts, ts.Extension.Dts);
43
+ const sourceContent = translated[sourceFileName];
44
+ const tsImportRows = sourceTypeScript.split("\n").filter((line) => line.startsWith("import "));
45
+ const declarationContent = translated[declarationFileName]
46
+ .split("\n")
47
+ .map((line) => {
48
+ if (line.startsWith("import ")) {
49
+ return tsImportRows.shift();
50
+ }
51
+ return line;
52
+ })
53
+ .join("\n");
54
+
55
+ return {
56
+ sourceContent: sourceContent,
57
+ declarationContent: declarationContent,
58
+ };
59
+ },
60
+ };
@@ -33,6 +33,7 @@ export enum ContentType {
33
33
  Json = "application/json",
34
34
  FormData = "multipart/form-data",
35
35
  UrlEncoded = "application/x-www-form-urlencoded",
36
+ Text = "text/plain",
36
37
  }
37
38
 
38
39
  export class HttpClient<SecurityDataType = unknown> {
@@ -114,6 +115,10 @@ export class HttpClient<SecurityDataType = unknown> {
114
115
  body = this.createFormData(body as Record<string, unknown>);
115
116
  }
116
117
 
118
+ if (type === ContentType.Text && body && body !== null && typeof body !== "string") {
119
+ body = JSON.stringify(body);
120
+ }
121
+
117
122
  return this.instance.request({
118
123
  ...requestParams,
119
124
  headers: {
@@ -45,6 +45,7 @@ export enum ContentType {
45
45
  Json = "application/json",
46
46
  FormData = "multipart/form-data",
47
47
  UrlEncoded = "application/x-www-form-urlencoded",
48
+ Text = "text/plain",
48
49
  }
49
50
 
50
51
  export class HttpClient<SecurityDataType = unknown> {
@@ -102,6 +103,7 @@ export class HttpClient<SecurityDataType = unknown> {
102
103
 
103
104
  private contentFormatters: Record<ContentType, (input: any) => any> = {
104
105
  [ContentType.Json]: (input:any) => input !== null && (typeof input === "object" || typeof input === "string") ? JSON.stringify(input) : input,
106
+ [ContentType.Text]: (input:any) => input !== null && typeof input !== "string" ? JSON.stringify(input) : input,
105
107
  [ContentType.FormData]: (input: any) =>
106
108
  Object.keys(input || {}).reduce((formData, key) => {
107
109
  const property = input[key];
@@ -50,6 +50,7 @@ const requestContentKind = {
50
50
  "JSON": "ContentType.Json",
51
51
  "URL_ENCODED": "ContentType.UrlEncoded",
52
52
  "FORM_DATA": "ContentType.FormData",
53
+ "TEXT": "ContentType.Text",
53
54
  }
54
55
  // RequestParams["format"]
55
56
  const responseContentKind = {
@@ -50,6 +50,7 @@ const requestContentKind = {
50
50
  "JSON": "ContentType.Json",
51
51
  "URL_ENCODED": "ContentType.UrlEncoded",
52
52
  "FORM_DATA": "ContentType.FormData",
53
+ "TEXT": "ContentType.Text",
53
54
  }
54
55
  // RequestParams["format"]
55
56
  const responseContentKind = {