-
Notifications
You must be signed in to change notification settings - Fork 6k
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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"; | ||
|
||
|
@@ -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 | ||
|
@@ -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; | ||
} | ||
|
||
/** | ||
|
@@ -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)) { | ||
|
@@ -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")); | ||
|
@@ -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); | ||
} | ||
} | ||
|
@@ -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 | ||
|
@@ -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) { | ||
|
@@ -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)); | ||
} | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,21 @@ | ||
'use strict'; | ||
|
||
var url = require('url'); | ||
var utils = require('../utils/writer.js'); | ||
{{#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) { | ||
utils.writeJson(res, response); | ||
}) | ||
.catch(function (response) { | ||
utils.writeJson(res, response); | ||
}); | ||
}; | ||
{{/operation}} | ||
{{/operations}} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No more |
||
{{#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}} | ||
|
There was a problem hiding this comment.
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