Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor nodejs generated code structure #4909

Merged
merged 4 commits into from
Mar 5, 2017
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bin/nodejs-petstore-server.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ fi

# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l nodejs-server -o samples/server/petstore/nodejs"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/nodejs -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l nodejs-server -o samples/server/petstore/nodejs"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make it easier to test template changes, the bin script is now loading templates directly from the file system instead of the compiled jar


java $JAVA_OPTS -Dservice -jar $executable $ags
67 changes: 0 additions & 67 deletions modules/swagger-codegen/XhhGitIgnore/sdk_unit_testing_binary.json

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@
import java.math.BigDecimal;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Pattern;

public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig {

private static final Logger LOGGER = LoggerFactory.getLogger(NodeJSServerCodegen.class);

protected String implFolder = "service";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will adjust PR to make this configurable.

public static final String GOOGLE_CLOUD_FUNCTIONS = "googleCloudFunctions";
public static final String EXPORTED_NAME = "exportedName";

Expand Down Expand Up @@ -81,16 +82,19 @@ public NodeJSServerCodegen() {
*/
additionalProperties.put("apiVersion", apiVersion);
additionalProperties.put("serverPort", serverPort);
additionalProperties.put("implFolder", implFolder);

supportingFiles.add(new SupportingFile("writer.mustache", ("utils").replace(".", "/"), "writer.js"));

cliOptions.add(CliOption.newBoolean(GOOGLE_CLOUD_FUNCTIONS,
"When specified, it will generate the code which runs within Google Cloud Functions "
+ "instead of standalone Node.JS server. See "
+ "https://cloud.google.com/functions/docs/quickstart for the details of how to "
+ "deploy the generated code."));
"When specified, it will generate the code which runs within Google Cloud Functions "
+ "instead of standalone Node.JS server. See "
+ "https://cloud.google.com/functions/docs/quickstart for the details of how to "
+ "deploy the generated code."));
cliOptions.add(new CliOption(EXPORTED_NAME,
"When the generated code will be deployed to Google Cloud Functions, this option can be "
+ "used to update the name of the exported function. By default, it refers to the "
+ "basePath. This does not affect normal standalone nodejs server code."));
"When the generated code will be deployed to Google Cloud Functions, this option can be "
+ "used to update the name of the exported function. By default, it refers to the "
+ "basePath. This does not affect normal standalone nodejs server code."));
}

@Override
Expand Down Expand Up @@ -145,15 +149,35 @@ public String toApiFilename(String name) {
return toApiName(name);
}


@Override
public String apiFilename(String templateName, String tag) {
String result = super.apiFilename(templateName, tag);

if ( templateName.equals("service.mustache") ) {
String stringToMatch = File.separator + "controllers" + File.separator;
String replacement = File.separator + implFolder + File.separator;
result = result.replaceAll(Pattern.quote(stringToMatch), replacement);
}
return result;
}

private String implFileFolder(String output) {
return outputFolder + "/" + output + "/" + apiPackage().replace('.', '/');
}

/**
* Escapes a reserved word as defined in the `reservedWords` array. Handle escaping
* those terms here. This logic is only called if a variable matches the reseved words
* those terms here. This logic is only called if a variable matches the reserved words
*
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
return "_" + name; // add an underscore to the name
if(this.reservedWords().contains(name)) {
name = "_" + name;
}
return name;
}

/**
Expand Down Expand Up @@ -256,7 +280,7 @@ public void processOpts() {

if (additionalProperties.containsKey(GOOGLE_CLOUD_FUNCTIONS)) {
setGoogleCloudFunctions(
Boolean.valueOf(additionalProperties.get(GOOGLE_CLOUD_FUNCTIONS).toString()));
Boolean.valueOf(additionalProperties.get(GOOGLE_CLOUD_FUNCTIONS).toString()));
}

if (additionalProperties.containsKey(EXPORTED_NAME)) {
Expand All @@ -273,8 +297,8 @@ public void processOpts() {
// "controller.js")
// );
supportingFiles.add(new SupportingFile("swagger.mustache",
"api",
"swagger.yaml")
"api",
"swagger.yaml")
);
if (getGoogleCloudFunctions()) {
writeOptional(outputFolder, new SupportingFile("index-gcf.mustache", "", "index.js"));
Expand Down Expand Up @@ -307,7 +331,12 @@ public void preprocessSwagger(Swagger swagger) {
if (info.getTitle() != null) {
// when info.title is defined, use it for projectName
// used in package.json
projectName = dashize(info.getTitle());
projectName = info.getTitle()
.replaceAll("[^a-zA-Z0-9]", "-")
.replaceAll("^[-]*", "")
.replaceAll("[-]*$", "")
.replaceAll("[-]{2,}", "-")
.toLowerCase();
this.additionalProperties.put("projectName", projectName);
}
}
Expand All @@ -318,14 +347,14 @@ public void preprocessSwagger(Swagger swagger) {
if (!host.endsWith(".cloudfunctions.net")) {
LOGGER.warn("Host " + host + " seems not matching with cloudfunctions.net URL.");
}
if (!additionalProperties.containsKey(EXPORTED_NAME)) {
if (!additionalProperties.containsKey(EXPORTED_NAME)) {
String basePath = swagger.getBasePath();
if (basePath == null || basePath.equals("/")) {
LOGGER.warn("Cannot find the exported name properly. Using 'openapi' as the exported name");
basePath = "/openapi";
}
additionalProperties.put(EXPORTED_NAME, basePath.substring(1));
}
}
}

// need vendor extensions for x-swagger-router-controller
Expand Down Expand Up @@ -353,7 +382,7 @@ public void preprocessSwagger(Swagger swagger) {
}
}

@Override
@Override
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
Swagger swagger = (Swagger)objs.get("swagger");
if(swagger != null) {
Expand All @@ -362,7 +391,7 @@ public Map<String, Object> postProcessSupportingFileData(Map<String, Object> obj
module.addSerializer(Double.class, new JsonSerializer<Double>() {
@Override
public void serialize(Double val, JsonGenerator jgen,
SerializerProvider provider) throws IOException, JsonProcessingException {
SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeNumber(new BigDecimal(val));
}
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
'use strict';

var url = require('url');
require('../utils/writer.js');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pull in utility functions for writeJson

{{#operations}}

var {{classname}} = require('./{{classname}}Service');
var {{classname}} = require('../{{implFolder}}/{{classname}}Service');
{{#operation}}

module.exports.{{nickname}} = function {{nickname}} (req, res, next) {
{{classname}}.{{nickname}}(req.swagger.params, res, next);
{{#allParams}}
var {{paramName}} = req.swagger.params['{{baseName}}'].value;
{{/allParams}}
{{classname}}.{{nickname}}({{#allParams}}{{paramName}}{{#hasMore}},{{/hasMore}}{{/allParams}})
.then(function (response) {
writeJson(res, response);
})
.catch(function (response) {
writeJson(res, response);
});
};
{{/operation}}
{{/operations}}
68 changes: 35 additions & 33 deletions modules/swagger-codegen/src/main/resources/nodejs/service.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,42 @@

{{#operations}}
{{#operation}}
exports.{{{operationId}}} = function(args, res, next) {
/**
{{#summary}}
* {{{summary}}}
{{/summary}}
{{#notes}}
* {{{notes}}}
{{/notes}}
*
{{#allParams}}
* {{paramName}} {{{dataType}}} {{{description}}}{{^required}} (optional){{/required}}
{{/allParams}}
{{^returnType}}
* no response value expected for this operation
{{/returnType}}
{{#returnType}}
* returns {{{returnType}}}
{{/returnType}}
**/

/**
{{#summary}}
* {{{summary}}}
{{/summary}}
{{#notes}}
* {{{notes}}}
{{/notes}}
*
{{#allParams}}
* {{paramName}} {{{dataType}}} {{{description}}}{{^required}} (optional){{/required}}
{{/allParams}}
{{^returnType}}
* no response value expected for this operation
{{/returnType}}
{{#returnType}}
* returns {{{returnType}}}
{{/returnType}}
**/
exports.{{{operationId}}} = function({{#allParams}}{{paramName}}{{#hasMore}},{{/hasMore}}{{/allParams}}) {
return new Promise(function(resolve, reject) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No more req, res, only using Promise lib.

{{#returnType}}
var examples = {};
{{#examples}}
examples['{{contentType}}'] = {{{example}}};
{{/examples}}
if (Object.keys(examples).length > 0) {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(examples[Object.keys(examples)[0]] || {}, null, 2));
} else {
res.end();
}
{{/returnType}}
{{^returnType}}
res.end();
{{/returnType}}
var examples = {};
{{#examples}}
examples['{{contentType}}'] = {{{example}}};
{{/examples}}
if (Object.keys(examples).length > 0) {
resolve(examples[Object.keys(examples)[0]]);
} else {
resolve();
}
{{/returnType}}
{{^returnType}}
resolve();
{{/returnType}}
});
}

{{/operation}}
Expand Down
Loading