Skip to content

Commit

Permalink
Add fixes for es6 generator
Browse files Browse the repository at this point in the history
1. Don't use property initializers

The ES6 Javascript generator used property initializers, as
described [here](https://tc39.github.io/proposal-class-public-fields/).

This is not standard ES6. In particular, create-react-app chokes on it
(see [this issue](swagger-api/swagger-codegen#8024),
which is fixed by this commit).

This commit instead reverts back to using prototypes, as in the non-es6
JS generator.

2. Add missing pom.xml files

This allows us to run `mvn integration-test` in these folders.

3. Add missing double-quotes around enum field names.

This avoids errors due to fields that contain illegal characters.

4. Fix support for multiple inheritance

The previous implementation was broken. I added static "initialize"
methods, which supports multiple inheritance.

5. Comment out some broken tests.

There were tests for OuterBoolean etc, which are not generated
as part of index.js in the generated petstore clients. Hence, these
tests threw an error. The actual tests were already commented out
anyway. I just commented out one more line to avoid an error.

6. Remove some empty lines in generates JS files.
  • Loading branch information
delenius committed Jun 14, 2018
1 parent 680a2bc commit 35313ac
Show file tree
Hide file tree
Showing 92 changed files with 3,107 additions and 4,038 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import querystring from "querystring";
* @alias module:{{#invokerPackage}}{{invokerPackage}}/{{/invokerPackage}}ApiClient
* @class
*/{{/emitJSDoc}}
export default class ApiClient {
class ApiClient {
constructor() {
{{#emitJSDoc}}/**
* The base URL against which to resolve every API call's (relative) path.
Expand Down Expand Up @@ -221,43 +221,6 @@ export default class ApiClient {
return newParams;
}

{{#emitJSDoc}}/**
* Enumeration of collection format separator strategies.
* @enum {String}
* @readonly
*/{{/emitJSDoc}}
static CollectionFormatEnum = {
{{#emitJSDoc}}/**
* Comma-separated values. Value: <code>csv</code>
* @const
*/{{/emitJSDoc}}
CSV: ',',

{{#emitJSDoc}}/**
* Space-separated values. Value: <code>ssv</code>
* @const
*/{{/emitJSDoc}}
SSV: ' ',

{{#emitJSDoc}}/**
* Tab-separated values. Value: <code>tsv</code>
* @const
*/{{/emitJSDoc}}
TSV: '\t',

{{#emitJSDoc}}/**
* Pipe(|)-separated values. Value: <code>pipes</code>
* @const
*/{{/emitJSDoc}}
PIPES: '|',

{{#emitJSDoc}}/**
* Native array. Value: <code>multi</code>
* @const
*/{{/emitJSDoc}}
MULTI: 'multi'
};

{{#emitJSDoc}}/**
* Builds a string representation of an array-type actual parameter, according to the given collection format.
* @param {Array} param An array parameter.
Expand Down Expand Up @@ -597,8 +560,46 @@ export default class ApiClient {
};
}

{{#emitJSDoc}}/**
* Enumeration of collection format separator strategies.
* @enum {String}
* @readonly
*/{{/emitJSDoc}}
ApiClient.CollectionFormatEnum = {
{{#emitJSDoc}}/**
* Comma-separated values. Value: <code>csv</code>
* @const
*/{{/emitJSDoc}}
CSV: ',',

{{#emitJSDoc}}/**
* Space-separated values. Value: <code>ssv</code>
* @const
*/{{/emitJSDoc}}
SSV: ' ',

{{#emitJSDoc}}/**
* Tab-separated values. Value: <code>tsv</code>
* @const
*/{{/emitJSDoc}}
TSV: '\t',

{{#emitJSDoc}}/**
* Pipe(|)-separated values. Value: <code>pipes</code>
* @const
*/{{/emitJSDoc}}
PIPES: '|',

{{#emitJSDoc}}/**
* Native array. Value: <code>multi</code>
* @const
*/{{/emitJSDoc}}
MULTI: 'multi'
};

{{#emitJSDoc}}/**
* The default API client implementation.
* @type {module:{{#invokerPackage}}{{invokerPackage}}/{{/invokerPackage}}ApiClient}
*/{{/emitJSDoc}}
ApiClient.instance = new ApiClient();
export default ApiClient;
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
{{>licenseInfo}}

import ApiClient from '../ApiClient';
{{#imports}}import {{import}} from './{{import}}';
{{/imports}}

{{#models}}{{#model}}
{{#isEnum}}{{>partial_model_enum_class}}{{/isEnum}}{{^isEnum}}{{>partial_model_generic}}{{/isEnum}}
{{/model}}{{/models}}
{{/imports}}{{#models}}{{#model}}{{#isEnum}}{{>partial_model_enum_class}}{{/isEnum}}{{^isEnum}}{{>partial_model_generic}}{{/isEnum}}{{/model}}{{/models}}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default class {{classname}} {
* value: {{{value}}}
* @const
*/{{/emitJSDoc}}
{{name}} = {{{value}}};
"{{name}}" = {{{value}}};

{{/enumVars}}{{/allowableValues}}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,54 +1,50 @@

{{#models}}{{#model}}

{{#emitJSDoc}}/**
* The {{classname}} model module.
* @module {{#invokerPackage}}{{invokerPackage}}/{{/invokerPackage}}{{#modelPackage}}{{modelPackage}}/{{/modelPackage}}{{classname}}
* @version {{projectVersion}}
*/{{/emitJSDoc}}
export default class {{classname}} {{#parent}}{{^parentModel}}{{#vendorExtensions.x-isArray}}extends Array {{/vendorExtensions.x-isArray}}{{/parentModel}}{{/parent}}{
{{#models}}{{#model}}{{#emitJSDoc}}/**
* The {{classname}} model module.
* @module {{#invokerPackage}}{{invokerPackage}}/{{/invokerPackage}}{{#modelPackage}}{{modelPackage}}/{{/modelPackage}}{{classname}}
* @version {{projectVersion}}
*/{{/emitJSDoc}}
class {{classname}} {{#parent}}{{^parentModel}}{{#vendorExtensions.x-isArray}}extends Array {{/vendorExtensions.x-isArray}}{{/parentModel}}{{/parent}}{
{{#emitJSDoc}}/**
* Constructs a new <code>{{classname}}</code>.{{#description}}
* {{description}}{{/description}}
* @alias module:{{#invokerPackage}}{{invokerPackage}}/{{/invokerPackage}}{{#modelPackage}}{{modelPackage}}/{{/modelPackage}}{{classname}}
* @class{{#useInheritance}}{{#parent}}
* @extends {{#parentModel}}module:{{#invokerPackage}}{{invokerPackage}}/{{/invokerPackage}}{{#modelPackage}}{{modelPackage}}/{{/modelPackage}}{{classname}}{{/parentModel}}{{^parentModel}}{{#vendorExtensions.x-isArray}}Array{{/vendorExtensions.x-isArray}}{{#vendorExtensions.x-isMap}}Object{{/vendorExtensions.x-isMap}}{{/parentModel}}{{/parent}}{{#interfaces}}
* @implements module:{{#invokerPackage}}{{invokerPackage}}/{{/invokerPackage}}{{#modelPackage}}{{modelPackage}}/{{/modelPackage}}{{.}}{{/interfaces}}{{/useInheritance}}{{#vendorExtensions.x-all-required}}
* @param {{name}} {{=< >=}}{<&vendorExtensions.x-jsdoc-type>}<={{ }}=> {{#description}}{{{description}}}{{/description}}{{/vendorExtensions.x-all-required}}
*/{{/emitJSDoc}}

constructor({{#vendorExtensions.x-all-required}}{{name}}{{^-last}}, {{/-last}}{{/vendorExtensions.x-all-required}}) {
{{#parent}}{{^parentModel}}{{#vendorExtensions.x-isArray}}
* Constructs a new <code>{{classname}}</code>.{{#description}}
* {{description}}{{/description}}
* @alias module:{{#invokerPackage}}{{invokerPackage}}/{{/invokerPackage}}{{#modelPackage}}{{modelPackage}}/{{/modelPackage}}{{classname}}{{#useInheritance}}{{#parent}}
* @extends {{#parentModel}}module:{{#invokerPackage}}{{invokerPackage}}/{{/invokerPackage}}{{#modelPackage}}{{modelPackage}}/{{/modelPackage}}{{classname}}{{/parentModel}}{{^parentModel}}{{#vendorExtensions.x-isArray}}Array{{/vendorExtensions.x-isArray}}{{#vendorExtensions.x-isMap}}Object{{/vendorExtensions.x-isMap}}{{/parentModel}}{{/parent}}{{#interfaces}}
* @implements module:{{#invokerPackage}}{{invokerPackage}}/{{/invokerPackage}}{{#modelPackage}}{{modelPackage}}/{{/modelPackage}}{{.}}{{/interfaces}}{{/useInheritance}}{{#vendorExtensions.x-all-required}}
* @param {{name}} {{=< >=}}{<&vendorExtensions.x-jsdoc-type>}<={{ }}=> {{#description}}{{{description}}}{{/description}}{{/vendorExtensions.x-all-required}}
*/{{/emitJSDoc}}
constructor({{#vendorExtensions.x-all-required}}{{name}}{{^-last}}, {{/-last}}{{/vendorExtensions.x-all-required}}) { {{#parent}}{{^parentModel}}{{#vendorExtensions.x-isArray}}
super();
{{/vendorExtensions.x-isArray}}{{/parentModel}}{{/parent}}

{{#useInheritance}}
{{#parentModel}}{{classname}}.call(this{{#vendorExtensions.x-all-required}}, {{name}}{{/vendorExtensions.x-all-required}});{{/parentModel}}
{{#interfaceModels}}{{classname}}.call(this{{#vendorExtensions.x-all-required}}, {{name}}{{/vendorExtensions.x-all-required}});{{/interfaceModels}}
{{/useInheritance}}

{{#vars}}{{#required}}this['{{baseName}}'] = {{name}};{{/required}}{{/vars}}
{{/vendorExtensions.x-isArray}}{{/parentModel}}{{/parent}}{{#useInheritance}}
{{#interfaceModels}}{{classname}}.initialize(this{{#vendorExtensions.x-all-required}}, {{name}}{{/vendorExtensions.x-all-required}});{{/interfaceModels}}{{/useInheritance}}
{{classname}}.initialize(this{{#vendorExtensions.x-all-required}}, {{name}}{{/vendorExtensions.x-all-required}});
}

{{#parent}}{{^parentModel}}return this;{{/parentModel}}{{/parent}}
{{#emitJSDoc}}/**
* Initializes the fields of this object.
* This method is used by the constructors of any subclasses, in order to implement multiple inheritance (mix-ins).
* Only for internal use.
*/{{/emitJSDoc}}
static initialize(obj{{#vendorExtensions.x-all-required}}, {{name}}{{/vendorExtensions.x-all-required}}) {
{{#vars}}{{#required}}obj['{{baseName}}'] = {{name}};
{{/required}}{{/vars}}
}

{{#emitJSDoc}}/**
* Constructs a <code>{{classname}}</code> from a plain JavaScript object, optionally creating a new instance.
* Copies all relevant properties from <code>data</code> to <code>obj</code> if supplied or a new instance if not.
* @param {Object} data The plain JavaScript object bearing properties of interest.
* @param {{=< >=}}{module:<#invokerPackage><invokerPackage>/</invokerPackage><#modelPackage><modelPackage>/</modelPackage><classname>}<={{ }}=> obj Optional instance to populate.
* @return {{=< >=}}{module:<#invokerPackage><invokerPackage>/</invokerPackage><#modelPackage><modelPackage>/</modelPackage><classname>}<={{ }}=> The populated <code>{{classname}}</code> instance.
*/{{/emitJSDoc}}
* Constructs a <code>{{classname}}</code> from a plain JavaScript object, optionally creating a new instance.
* Copies all relevant properties from <code>data</code> to <code>obj</code> if supplied or a new instance if not.
* @param {Object} data The plain JavaScript object bearing properties of interest.
* @param {{=< >=}}{module:<#invokerPackage><invokerPackage>/</invokerPackage><#modelPackage><modelPackage>/</modelPackage><classname>}<={{ }}=> obj Optional instance to populate.
* @return {{=< >=}}{module:<#invokerPackage><invokerPackage>/</invokerPackage><#modelPackage><modelPackage>/</modelPackage><classname>}<={{ }}=> The populated <code>{{classname}}</code> instance.
*/{{/emitJSDoc}}
static constructFromObject(data, obj) {
if (data){{! TODO: support polymorphism: discriminator property on data determines class to instantiate.}} {
obj = obj || new {{classname}}();

{{#parent}}{{^parentModel}}ApiClient.constructFromObject(data, obj, '{{vendorExtensions.x-itemType}}');{{/parentModel}}
{{/parent}}
obj = obj || new {{classname}}();{{#parent}}{{^parentModel}}

{{#useInheritance}}{{#parentModel}}{{classname}}.constructFromObject(data, obj);{{/parentModel}}
{{#interfaces}}{{.}}.constructFromObject(data, obj);{{/interfaces}}
{{/useInheritance}}
ApiClient.constructFromObject(data, obj, '{{vendorExtensions.x-itemType}}');
{{/parentModel}}{{/parent}}{{#useInheritance}}{{#parentModel}}
{{classname}}.constructFromObject(data, obj);{{/parentModel}}{{#interfaces}}
{{.}}.constructFromObject(data, obj);{{/interfaces}}{{/useInheritance}}

{{#vars}}
if (data.hasOwnProperty('{{baseName}}')) {
Expand All @@ -59,61 +55,49 @@ export default class {{classname}} {{#parent}}{{^parentModel}}{{#vendorExtension
return obj;
}

{{#vars}}
{{#emitJSDoc}}/**{{#description}}
* {{{description}}}{{/description}}
* @member {{=< >=}}{<&vendorExtensions.x-jsdoc-type>}<={{ }}=> {{baseName}}{{#defaultValue}}
* @default {{{defaultValue}}}{{/defaultValue}}
*/{{/emitJSDoc}}
{{baseName}} = {{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}undefined{{/defaultValue}};
{{/vars}}

{{#useInheritance}}{{#interfaceModels}}
// Implement {{classname}} interface:
{{#allVars}}{{#emitJSDoc}}/**{{#description}}
* {{{description}}}{{/description}}
* @member {{=< >=}}{<&vendorExtensions.x-jsdoc-type>}<={{ }}=> {{baseName}}{{#defaultValue}}
* @default {{{defaultValue}}}{{/defaultValue}}
*/{{/emitJSDoc}}
{{baseName}} = {{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}undefined{{/defaultValue}};
{{/allVars}}
{{/interfaceModels}}{{/useInheritance}}


{{#emitModelMethods}}{{#vars}}
{{#emitJSDoc}}/**{{#description}}
* Returns {{{description}}}{{/description}}{{#minimum}}
* minimum: {{minimum}}{{/minimum}}{{#maximum}}
* maximum: {{maximum}}{{/maximum}}
* @return {{=< >=}}{<&vendorExtensions.x-jsdoc-type>}<={{ }}=>
*/{{/emitJSDoc}}
{{#emitModelMethods}}{{#vars}}{{#emitJSDoc}}/**{{#description}}
* Returns {{{description}}}{{/description}}{{#minimum}}
* minimum: {{minimum}}{{/minimum}}{{#maximum}}
* maximum: {{maximum}}{{/maximum}}
* @return {{=< >=}}{<&vendorExtensions.x-jsdoc-type>}<={{ }}=>
*/{{/emitJSDoc}}
{{getter}}() {
return this.{{baseName}};
}

{{#emitJSDoc}}/**{{#description}}
* Sets {{{description}}}{{/description}}
* @param {{=< >=}}{<&vendorExtensions.x-jsdoc-type>}<={{ }}=> {{name}}{{#description}} {{{description}}}{{/description}}
*/{{/emitJSDoc}}
* Sets {{{description}}}{{/description}}
* @param {{=< >=}}{<&vendorExtensions.x-jsdoc-type>}<={{ }}=> {{name}}{{#description}} {{{description}}}{{/description}}
*/{{/emitJSDoc}}
{{setter}}({{name}}) {
this['{{baseName}}'] = {{name}};
}
{{/vars}}{{/emitModelMethods}}
{{/vars}}{{/emitModelMethods}}{{/model}}
}

{{#vars}}{{#emitJSDoc}}/**{{#description}}
* {{{description}}}{{/description}}
* @member {{=< >=}}{<&vendorExtensions.x-jsdoc-type>}<={{ }}=> {{baseName}}{{#defaultValue}}
* @default {{{defaultValue}}}{{/defaultValue}}
*/{{/emitJSDoc}}
{{classname}}.prototype['{{baseName}}'] = {{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}undefined{{/defaultValue}};

{{#vars}}
{{#isEnum}}
{{^isContainer}}
{{/vars}}

{{#useInheritance}}{{#interfaceModels}}// Implement {{classname}} interface:
{{#allVars}}{{#emitJSDoc}}/**{{#description}}
* {{{description}}}{{/description}}
* @member {{=< >=}}{<&vendorExtensions.x-jsdoc-type>}<={{ }}=> {{baseName}}{{#defaultValue}}
* @default {{{defaultValue}}}{{/defaultValue}}
*/{{/emitJSDoc}}
{{classname}}.prototype['{{baseName}}'] = {{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}undefined{{/defaultValue}};
{{/allVars}}{{/interfaceModels}}{{/useInheritance}}

{{#vars}}{{#isEnum}}{{^isContainer}}
{{>partial_model_inner_enum}}
{{/isContainer}}
{{/isEnum}}
{{#items.isEnum}}
{{#items}}
{{^isContainer}}
{{/isContainer}}{{/isEnum}}{{#items.isEnum}}{{#items}}{{^isContainer}}
{{>partial_model_inner_enum}}
{{/isContainer}}
{{/items}}
{{/items.isEnum}}
{{/vars}}
{{/isContainer}}{{/items}}{{/items.isEnum}}{{/vars}}

{{/model}}{{/models}}
}
export default {{classname}};
{{/models}}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{{#emitJSDoc}}/**
* Allowed values for the <code>{{baseName}}</code> property.
* @enum {{=<% %>=}}{<%datatype%>}<%={{ }}=%>
* @readonly
*/{{/emitJSDoc}}
{{classname}}['{{datatypeWithEnum}}'] = {
{{#allowableValues}}{{#enumVars}}
{{#emitJSDoc}}/**
* Allowed values for the <code>{{baseName}}</code> property.
* @enum {{=<% %>=}}{<%datatype%>}<%={{ }}=%>
* @readonly
*/{{/emitJSDoc}}
static {{datatypeWithEnum}} = {
{{#allowableValues}}{{#enumVars}}
{{#emitJSDoc}}/**
* value: {{{value}}}
* @const
*/{{/emitJSDoc}}
"{{name}}": {{{value}}}{{^-last}},
{{/-last}}
{{/enumVars}}{{/allowableValues}}
};
* value: {{{value}}}
* @const
*/{{/emitJSDoc}}
"{{name}}": {{{value}}}{{^-last}},
{{/-last}}
{{/enumVars}}{{/allowableValues}}
};
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.0.2-SNAPSHOT
3.0.0-SNAPSHOT
45 changes: 45 additions & 0 deletions samples/client/petstore/javascript-es6/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.openapitools</groupId>
<artifactId>openapi-petstore-javascript-es6</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>OpenAPI Petstore JS Client</name>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>npm-install</id>
<phase>pre-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>npm</executable>
<arguments>
<argument>install</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>mocha</id>
<phase>integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>npm</executable>
<arguments>
<argument>test</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Loading

0 comments on commit 35313ac

Please sign in to comment.