@penkov/swagger-code-gen 1.3.1 → 1.3.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/dist/method.js CHANGED
@@ -9,7 +9,9 @@ export class Method {
9
9
  this.method = method;
10
10
  this.tags = option(def.tags).getOrElseValue([]);
11
11
  this.summary = def.summary;
12
- const parameters = Collection.from(def.parameters)
12
+ this.description = def.description;
13
+ this.operationId = option(def.operationId);
14
+ const parameters = Collection.from(option(def.parameters).getOrElseValue([]))
13
15
  .map(p => Parameter.fromDefinition(p, schemasTypes, options))
14
16
  .sort((a, b) => {
15
17
  const r1 = a.required ? 1 : 0;
@@ -41,12 +43,15 @@ export class Method {
41
43
  .orElseValue(mimeTypes.headOption)
42
44
  .map(mt => SchemaFactory.build('body', body[mt].schema, schemasTypes, options));
43
45
  });
46
+ this.bodyDescription = option(def.requestBody).flatMap(body => option(body.description));
44
47
  const statusCodes = Collection.from(Object.keys(def.responses))
45
48
  .map(x => parseInt(x));
46
49
  const successCode = statusCodes
47
50
  .filter(code => code / 100 === 2)
48
51
  .minByOption(identity);
49
- const respDef = successCode.map(_ => def.responses[_]).getOrElseValue(def.responses[statusCodes.head]);
52
+ const respDef = successCode.map(_ => def.responses[_])
53
+ .orElse(() => option(def.responses['default']))
54
+ .getOrElseValue(def.responses[statusCodes.head]);
50
55
  const mimeTypes = option(respDef.content)
51
56
  .map(content => Collection.from(Object.keys(content)).toMap(mimeType => [mimeType, content[mimeType]])).getOrElseValue(HashMap.empty);
52
57
  this.response = mimeTypes.get('application/json')
@@ -63,12 +68,13 @@ export class Method {
63
68
  asProperty: Property.fromDefinition('UNKNOWN', { type: 'any' }, schemasTypes, options),
64
69
  responseType: 'any'
65
70
  }));
71
+ this.wrapParamsInObject = this.parameters.size > 2 || (this.body.isDefined) && this.parameters.nonEmpty;
66
72
  }
67
73
  get endpointName() {
68
- return `${this.method}${Method.pathToName(this.path)}`;
74
+ return this.operationId.getOrElse(() => `${this.method}${Method.pathToName(this.path)}`);
69
75
  }
70
76
  get pathWithSubstitutions() {
71
- const paramPrefix = `${this.parameters.size > 2 ? 'params.' : ''}`;
77
+ const paramPrefix = `${this.wrapParamsInObject ? 'params.' : ''}`;
72
78
  return this.path.replace(/\{(\w+?)\}/g, (matched, group) => {
73
79
  const remappedName = this.parameters.find(p => p.name === group && p.in === 'path')
74
80
  .map(_ => _.uniqueName)
package/dist/parameter.js CHANGED
@@ -1,13 +1,14 @@
1
1
  import { SchemaEnum, SchemaFactory, SchemaObject } from './schemas.js';
2
- import { Collection, identity, option } from 'scats';
2
+ import { Collection, identity, none, option } from 'scats';
3
3
  import { Method } from './method.js';
4
4
  import { Property } from './property.js';
5
5
  export class Parameter {
6
- constructor(name, uniqueName, inValue, jsType, required, description) {
6
+ constructor(name, uniqueName, inValue, jsType, required, defaultValue, description) {
7
7
  this.name = name;
8
8
  this.uniqueName = uniqueName;
9
9
  this.jsType = jsType;
10
10
  this.required = required;
11
+ this.defaultValue = defaultValue;
11
12
  this.description = description;
12
13
  this.in = inValue;
13
14
  }
@@ -15,14 +16,33 @@ export class Parameter {
15
16
  const name = Parameter.toJSName(def.name);
16
17
  const inValue = def.in;
17
18
  const desc = option(def.description);
18
- const required = option(def.required).exists(identity);
19
+ let defaultValue = none;
19
20
  const schema = SchemaFactory.build(def.name, def.schema, schemas, options);
20
21
  let jsType;
21
22
  if (schema instanceof SchemaObject) {
22
23
  jsType = schema.type;
23
24
  }
24
25
  else if (schema instanceof SchemaEnum) {
25
- jsType = schema.name;
26
+ if (schemas.containsKey(schema.name)) {
27
+ jsType = schema.name;
28
+ }
29
+ else if (schema.type === 'string') {
30
+ jsType = `${schema.values.map(x => `'${x}'`).mkString(' | ')}`;
31
+ }
32
+ else if (schema.type === 'integer') {
33
+ jsType = `${schema.values.map(x => `${x}`).mkString(' | ')}`;
34
+ }
35
+ else {
36
+ jsType = schema.type;
37
+ }
38
+ defaultValue = schema.defaultValue.map(x => {
39
+ if (schema.type === 'string') {
40
+ return `'${x}'`;
41
+ }
42
+ else {
43
+ return x;
44
+ }
45
+ });
26
46
  }
27
47
  else if (schema instanceof Property) {
28
48
  jsType = schema.jsType;
@@ -30,7 +50,8 @@ export class Parameter {
30
50
  else {
31
51
  throw new Error('Unknown schema type');
32
52
  }
33
- return new Parameter(name, name, inValue, jsType, required, desc);
53
+ const required = option(def.required).exists(identity) || defaultValue.nonEmpty;
54
+ return new Parameter(name, name, inValue, jsType, required, defaultValue, desc);
34
55
  }
35
56
  static toJSName(path) {
36
57
  const tokens = Collection.from(path.split(/\W/)).filter(t => t.length > 0);
@@ -39,6 +60,6 @@ export class Parameter {
39
60
  }).mkString();
40
61
  }
41
62
  copy(p) {
42
- return new Parameter(option(p.name).getOrElseValue(this.name), option(p.uniqueName).getOrElseValue(this.uniqueName), option(p.in).getOrElseValue(this.in), option(p.jsType).getOrElseValue(this.jsType), option(p.required).getOrElseValue(this.required), option(p.description).getOrElseValue(this.description));
63
+ return new Parameter(option(p.name).getOrElseValue(this.name), option(p.uniqueName).getOrElseValue(this.uniqueName), option(p.in).getOrElseValue(this.in), option(p.jsType).getOrElseValue(this.jsType), option(p.required).getOrElseValue(this.required), option(p.defaultValue).getOrElseValue(this.defaultValue), option(p.description).getOrElseValue(this.description));
43
64
  }
44
65
  }
package/dist/schemas.js CHANGED
@@ -37,15 +37,16 @@ export class SchemaFactory {
37
37
  }
38
38
  }
39
39
  export class SchemaEnum {
40
- constructor(name, title, type, values) {
40
+ constructor(name, title, type, defaultValue, values) {
41
41
  this.name = name;
42
42
  this.title = title;
43
43
  this.type = type;
44
+ this.defaultValue = defaultValue;
44
45
  this.values = values;
45
46
  this.schemaType = 'enum';
46
47
  }
47
48
  static fromDefinition(name, def) {
48
- return new SchemaEnum(name, def.title, def.type, option(def.enum).map(Collection.from).getOrElseValue(Nil));
49
+ return new SchemaEnum(name, def.title, def.type, option(def.default), option(def.enum).map(Collection.from).getOrElseValue(Nil));
49
50
  }
50
51
  }
51
52
  export class SchemaObject {
@@ -11,8 +11,9 @@
11
11
  *********************************************************
12
12
  *********************************************************/
13
13
  import fetch, {Request, Response} from 'node-fetch';
14
+ import {option, Option} from 'scats';
14
15
  <% if (scats) {%>
15
- import {option, Option, Collection, Try, TryLike, none} from 'scats';
16
+ import {Collection, Try, TryLike, none} from 'scats';
16
17
  <% } %>
17
18
 
18
19
  export interface RequestOptions {
@@ -1,22 +1,27 @@
1
1
  /**
2
2
  * <%= method.method.toUpperCase() %> <%= method.path %>
3
- <% if (method.parameters.size > 2) { -%>
3
+ <% if (method.summary) { -%>
4
+ * @summary <%= method.summary %>
5
+ <% } -%>
6
+ <% if (method.description) { -%>
7
+ * @description <%= method.description %>
8
+ <% } -%>
9
+ <% if (method.wrapParamsInObject) { -%>
4
10
  * @param {Object} params
5
11
  <% } -%>
6
12
  <% method.parameters.foreach(p => { -%>
7
- * @param {<%= p.jsType %>} <%= method.parameters.size > 2 ? 'params.' : '' %><%= p.uniqueName %> <%= p.description.getOrElseValue('')%>
13
+ * @param {<%= p.jsType %>} <%= method.wrapParamsInObject ? 'params.' : '' %><%= p.uniqueName %> <%= p.description.getOrElseValue('')%>
8
14
  <% }); -%>
9
15
  <%_ if (method.body.nonEmpty) { -%>
10
- * @param {<%= method.body.get.type %>} body
16
+ * @param {<%= method.body.get.jsType %>} body <%= method.bodyDescription.getOrElseValue('') %>
11
17
  <%_ } -%>
12
18
  * @param {RequestOptions} requestOptions Additional request params
13
- * @summary <%= method.summary %>
14
19
  * @return {<%= method.response.responseType %>} <%= method.response.description %>
15
20
  */
16
21
  export async function <%= method.endpointName %>(
17
- <%_ if (method.parameters.size <= 2) { -%>
22
+ <%_ if (!method.wrapParamsInObject) { -%>
18
23
  <%_ method.parameters.foreach(p => { -%>
19
- <%= p.uniqueName %><%= p.required ? '' : '?'%>: <%- p.jsType %>,
24
+ <%= p.uniqueName %><%= p.required ? '' : '?'%>: <%- p.jsType %><%- p.defaultValue.map(x => ` = ${x}`).getOrElseValue('') %>,
20
25
  <%_ }) -%>
21
26
  <%_ } else { -%>
22
27
  params: {
@@ -26,7 +31,7 @@ export async function <%= method.endpointName %>(
26
31
  },
27
32
  <%_ } -%>
28
33
  <%_ if (method.body.nonEmpty) { -%>
29
- body: <%= method.body.get.type %>,
34
+ body: <%- method.body.get.jsType %>,
30
35
  <%_ } -%>
31
36
  requestOptions: RequestOptions = defaultRequestOptions()
32
37
  ): Promise<<%- method.response.responseType %>> {
@@ -35,17 +40,17 @@ export async function <%= method.endpointName %>(
35
40
  const queryParams = [];
36
41
  <%_ method.parameters.filter(x => x.in === 'query' && x.required).foreach(p => { -%>
37
42
  <%_ if (p.jsType === 'string') { -%>
38
- queryParams.push(`<%= p.name %>=${encodeURIComponent(<%= method.parameters.size > 2 ? 'params.' : '' %><%= p.uniqueName %>)}`);
43
+ queryParams.push(`<%= p.name %>=${encodeURIComponent(<%= method.wrapParamsInObject ? 'params.' : '' %><%= p.uniqueName %>)}`);
39
44
  <%_ } else { -%>
40
- queryParams.push(`<%= p.name %>=${<%= method.parameters.size > 2 ? 'params.' : '' %><%= p.uniqueName %>}`);
45
+ queryParams.push(`<%= p.name %>=${<%= method.wrapParamsInObject ? 'params.' : '' %><%= p.uniqueName %>}`);
41
46
  <%_ } -%>
42
47
  <%_ }) -%>
43
48
  <%_ method.parameters.filter(x => x.in === 'query' && !x.required).foreach(p => { -%>
44
- if (!!<%= method.parameters.size > 2 ? 'params.' : '' %><%= p.uniqueName %>) {
49
+ if (!!<%= method.wrapParamsInObject ? 'params.' : '' %><%= p.uniqueName %>) {
45
50
  <%_ if (p.jsType === 'string') { -%>
46
- queryParams.push(`<%= p.name %>=${encodeURIComponent(<%= method.parameters.size > 2 ? 'params.' : '' %><%= p.uniqueName %>)}`);
51
+ queryParams.push(`<%= p.name %>=${encodeURIComponent(<%= method.wrapParamsInObject ? 'params.' : '' %><%= p.uniqueName %>)}`);
47
52
  <%_ } else { -%>
48
- queryParams.push(`<%= p.name %>=${<%= method.parameters.size > 2 ? 'params.' : '' %><%= p.uniqueName %>}`);
53
+ queryParams.push(`<%= p.name %>=${<%= method.wrapParamsInObject ? 'params.' : '' %><%= p.uniqueName %>}`);
49
54
  <%_ } -%>
50
55
  }
51
56
  <%_ }) -%>
@@ -60,18 +65,20 @@ export async function <%= method.endpointName %>(
60
65
  ...option(requestOptions.headers).getOrElseValue({}),
61
66
  <%_ if (method.parameters.filter(x => x.in === 'header').nonEmpty) { -%>
62
67
  <%_ method.parameters.filter(x => x.in === 'header').foreach(p => { -%>
63
- <%= p.name %>: <%= method.parameters.size > 2 ? 'params.' : '' %><%= p.uniqueName %>
68
+ <%= p.name %>: <%= method.wrapParamsInObject ? 'params.' : '' %><%= p.uniqueName %>
64
69
  <%_ }) -%>
65
70
  <%_ } -%>
66
71
  }
67
72
  });
68
- const preprocessed = option(requestOptions.preProcessRequest).map(cb => cb(request)).getOrElseValue(request);
69
- const resp = await fetch(preprocessed);
73
+ const preProcessed = option(requestOptions.preProcessRequest).map(cb => cb(request)).getOrElseValue(request);
74
+ const resp = await fetch(preProcessed);
70
75
  if (resp.ok) {
71
- const postprocessed = option(requestOptions.postProcessResponse)
72
- .map(cb => cb(preprocessed, resp))
76
+ const postProcessed = option(requestOptions.postProcessResponse)
77
+ .map(cb => cb(preProcessed, resp))
73
78
  .getOrElseValue(resp);
74
- const json = resp.size > 0 ? await postprocessed.json() : null;
79
+ const json = option(resp.headers.get('content-length'))
80
+ .map(x => parseInt(x))
81
+ .getOrElseValue(0) > 0 ? await postProcessed.json() : null;
75
82
  return json as <%- method.response.responseType %>;
76
83
  } else {
77
84
  throw resp;
@@ -6,7 +6,7 @@ export class ApiClient {
6
6
 
7
7
  <% methods.foreach(method => { %>
8
8
  async <%= method.endpointName %>(
9
- <%_ if (method.parameters.size <= 2) { -%>
9
+ <%_ if (!method.wrapParamsInObject) { -%>
10
10
  <%_ method.parameters.foreach(p => { -%>
11
11
  <%= p.uniqueName %>: <%- p.required && !p.nullable ? p.jsType : `Option<${p.jsType}> = none` %>,
12
12
  <%_ }) -%>
@@ -18,13 +18,13 @@ export class ApiClient {
18
18
  },
19
19
  <%_ } -%>
20
20
  <%_ method.body.foreach(body => { -%>
21
- body: <%= body.type %>,
21
+ body: <%- body.jsType %>,
22
22
  <%_ }); -%>
23
23
  requestOptions: RequestOptions = this.requestOptions
24
24
  ): Promise<TryLike<<%- method.response.asProperty.scatsWrapperType %>>> {
25
25
  return (await Try.promise(() =>
26
26
  <%= method.endpointName %>(
27
- <%_ if (method.parameters.size <= 2) { -%>
27
+ <%_ if (!method.wrapParamsInObject) { -%>
28
28
  <%_ method.parameters.foreach(p => { -%>
29
29
  <%= p.uniqueName %><%- p.required && !p.nullable ? '' : `.orUndefined` %>,
30
30
  <%_ }) -%>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@penkov/swagger-code-gen",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "generate-client": "./dist/cli.mjs"
@@ -22,6 +22,7 @@
22
22
  },
23
23
  "homepage": "https://github.com/papirosko/swagger-code-gen#readme",
24
24
  "scripts": {
25
+ "test:petstore": "mkdir -p tmp && ts-node-esm ./src/cli.mjs --enableScats --url https://petstore3.swagger.io/api/v3/openapi.json tmp/petstore.ts",
25
26
  "clean": "rimraf dist",
26
27
  "lint": "eslint \"{src,test}/**/*.ts\" --fix",
27
28
  "prebuild": "npm run lint && npm run clean",