Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
31 changes: 31 additions & 0 deletions bin/nodejs-petstore-google-cloud-functions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/sh

SCRIPT="$0"

while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done

if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi

executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"

if [ ! -f "$executable" ]
then
mvn clean package
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 --additional-properties=googleCloudFunctions=true -o samples/server/petstore/nodejs-google-cloud-functions"

java $JAVA_OPTS -Dservice -jar $executable $ags
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,16 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig

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

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

protected String apiVersion = "1.0.0";
protected int serverPort = 8080;
protected String projectName = "swagger-server";

protected boolean googleCloudFunctions;
protected String exportedName;

public NodeJSServerCodegen() {
super();

Expand Down Expand Up @@ -76,27 +82,15 @@ public NodeJSServerCodegen() {
additionalProperties.put("apiVersion", apiVersion);
additionalProperties.put("serverPort", serverPort);

/*
* Supporting Files. You can write single files for the generator with the
* entire object tree available. If the input file has a suffix of `.mustache
* it will be processed by the template engine. Otherwise, it will be copied
*/
// supportingFiles.add(new SupportingFile("controller.mustache",
// "controllers",
// "controller.js")
// );
supportingFiles.add(new SupportingFile("swagger.mustache",
"api",
"swagger.yaml")
);
writeOptional(outputFolder, new SupportingFile("index.mustache", "", "index.js"));
writeOptional(outputFolder, new SupportingFile("package.mustache", "", "package.json"));
writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md"));
if (System.getProperty("noservice") == null) {
apiTemplateFiles.put(
"service.mustache", // the template to use
"Service.js"); // the extension for each file to write
}
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."));
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."));
}

@Override
Expand Down Expand Up @@ -171,6 +165,22 @@ public String apiFileFolder() {
return outputFolder + File.separator + apiPackage().replace('.', File.separatorChar);
}

public boolean getGoogleCloudFunctions() {
return googleCloudFunctions;
}

public void setGoogleCloudFunctions(boolean value) {
googleCloudFunctions = value;
}

public String getExportedName() {
return exportedName;
}

public void setExportedName(String name) {
exportedName = name;
}

@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -240,6 +250,46 @@ private static List<Map<String, Object>> sortOperationsByPath(List<CodegenOperat
return opsByPathList;
}

@Override
public void processOpts() {
super.processOpts();

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

if (additionalProperties.containsKey(EXPORTED_NAME)) {
setExportedName((String)additionalProperties.get(EXPORTED_NAME));
}

/*
* Supporting Files. You can write single files for the generator with the
* entire object tree available. If the input file has a suffix of `.mustache
* it will be processed by the template engine. Otherwise, it will be copied
*/
// supportingFiles.add(new SupportingFile("controller.mustache",
// "controllers",
// "controller.js")
// );
supportingFiles.add(new SupportingFile("swagger.mustache",
"api",
"swagger.yaml")
);
if (getGoogleCloudFunctions()) {
writeOptional(outputFolder, new SupportingFile("index-gcf.mustache", "", "index.js"));
} else {
writeOptional(outputFolder, new SupportingFile("index.mustache", "", "index.js"));
}
writeOptional(outputFolder, new SupportingFile("package.mustache", "", "package.json"));
writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md"));
if (System.getProperty("noservice") == null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of using noservice, what about using selective generation as mentioned in https://github.com/swagger-api/swagger-codegen#selective-generation? Would that meet your need?

I prefer not to introduce another system property if the same output can already be achieved.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually this comes from the original NodeJSCodegen.java, I just moved the code location. I'm not adding new.

Also, the noservice is for a different purpose from the selective generation.

The nodejs-server codegen generates two files per API. For the example of petstore, it generates files like controllers/Pet.js and controllers/PetService.js (see https://github.com/swagger-api/swagger-codegen/tree/master/samples/server/petstore/nodejs/controllers).

When this noservice is specified, it omits the generation of PetService.js file or any other -Service.js files. Only Pet.js or those files.

Copy link
Contributor

Choose a reason for hiding this comment

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

@jmuk thanks for the clarification. I'll review and let you know if I've further question.

apiTemplateFiles.put(
"service.mustache", // the template to use
"Service.js"); // the extension for each file to write
}
}

@Override
public void preprocessSwagger(Swagger swagger) {
String host = swagger.getHost();
Expand All @@ -262,6 +312,22 @@ public void preprocessSwagger(Swagger swagger) {
}
}

if (getGoogleCloudFunctions()) {
// Note that Cloud Functions don't allow customizing port name, simply checking host
// is good enough.
if (!host.endsWith(".cloudfunctions.net")) {
LOGGER.warn("Host " + host + " seems not matching with cloudfunctions.net URL.");
}
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
Map<String, Path> paths = swagger.getPaths();
if(paths != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict';
Copy link
Contributor

Choose a reason for hiding this comment

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

@jmuk we'll move this file to nodejs/google-cloud-functions/index.mustache (and update the code accordingly). so that all nodejs (server) related files are under the folder.

Are you OK with the proposed change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, I don't care the exact file location as long as the code works. But thank you for telling me!

Copy link
Contributor

Choose a reason for hiding this comment

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

I found that this file is the same as index-gcf.mustache so I simply removed it via #4808. I did some tests and the generator is still working properly with or without the option for Google cloud function.


var swaggerTools = require('swagger-tools');
var jsyaml = require('js-yaml');
var fs = require('fs');

// swaggerRouter configuration
var options = {
controllers: './controllers',
useStubs: false
};

// The Swagger document (require it, build it programmatically, fetch it from a URL, ...)
var spec = fs.readFileSync('./api/swagger.yaml', 'utf8');
var swaggerDoc = jsyaml.safeLoad(spec);

function toPromise(f, req, res) {
return new Promise(function(resolve, reject) {
f(req, res, function(err) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}

exports.{{exportedName}} = function(req, res) {
swaggerTools.initializeMiddleware(swaggerDoc, function(middleware) {
var metadata = middleware.swaggerMetadata();
var validator = middleware.swaggerValidator();
var router = middleware.swaggerRouter(options);
req.url = swaggerDoc.basePath + req.url;
toPromise(metadata, req, res).then(function() {
return toPromise(validator, req, res);
}).then(function() {
return toPromise(router, req, res);
}).catch(function(err) {
console.error(err);
res.status(res.statusCode || 400).send(err);
});
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Overview
This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.

{{^googleCloudFunctions}}
### Running the server
To run the server, run:

Expand All @@ -15,5 +16,12 @@ To view the Swagger UI interface:
```
open http://localhost:{{serverPort}}/docs
```
{{/googleCloudFunctions}}
{{#googleCloudFunctions}}
### Deploying the function
To deploy this module into Google Cloud Functions, you will have to use Google Cloud SDK commandline tool.

See [Google Cloud Functions quick start guide](https://cloud.google.com/functions/docs/quickstart) and [Deploying Cloud Functions](https://cloud.google.com/functions/docs/deploying/) for the details.
{{/googleCloudFunctions}}

This project leverages the mega-awesome [swagger-tools](https://github.com/apigee-127/swagger-tools) middleware which does most all the work.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict';

var swaggerTools = require('swagger-tools');
var jsyaml = require('js-yaml');
var fs = require('fs');

// swaggerRouter configuration
var options = {
controllers: './controllers',
useStubs: false
};

// The Swagger document (require it, build it programmatically, fetch it from a URL, ...)
var spec = fs.readFileSync('./api/swagger.yaml', 'utf8');
var swaggerDoc = jsyaml.safeLoad(spec);

function toPromise(f, req, res) {
return new Promise(function(resolve, reject) {
f(req, res, function(err) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}

exports.{{exportedName}} = function(req, res) {
swaggerTools.initializeMiddleware(swaggerDoc, function(middleware) {
var metadata = middleware.swaggerMetadata();
var validator = middleware.swaggerValidator();
var router = middleware.swaggerRouter(options);
req.url = swaggerDoc.basePath + req.url;
toPromise(metadata, req, res).then(function() {
return toPromise(validator, req, res);
}).then(function() {
return toPromise(router, req, res);
}).catch(function(err) {
console.error(err);
res.status(res.statusCode || 400).send(err);
});
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
"version": "{{appVersion}}",
"description": "{{{appDescription}}}",
"main": "index.js",
{{^googleCloudFunctions}}
"scripts": {
"prestart": "npm install",
"start": "node index.js"
},
},
{{/googleCloudFunctions}}
"keywords": [
"swagger"
],
"license": "Unlicense",
"private": true,
"dependencies": {
{{^googleCloudFunctions}}
"connect": "^3.2.0",
{{/googleCloudFunctions}}
"js-yaml": "^3.3.0",
"swagger-tools": "0.10.1"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ protected CodegenConfig getCodegenConfig() {
protected void setExpectations() {
new Expectations(clientCodegen) {{
clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(NodeJSServerOptionsProvider.SORT_PARAMS_VALUE));
clientCodegen.setGoogleCloudFunctions(Boolean.valueOf(NodeJSServerOptionsProvider.GOOGLE_CLOUD_FUNCTIONS));
clientCodegen.setExportedName(NodeJSServerOptionsProvider.EXPORTED_NAME);
times = 1;
}};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package io.swagger.codegen.options;

import io.swagger.codegen.CodegenConstants;

import io.swagger.codegen.languages.NodeJSServerCodegen;
import com.google.common.collect.ImmutableMap;

import java.util.Map;

public class NodeJSServerOptionsProvider implements OptionsProvider {
public static final String SORT_PARAMS_VALUE = "false";
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
public static final String GOOGLE_CLOUD_FUNCTIONS = "false";
public static final String EXPORTED_NAME = "exported";

@Override
public String getLanguage() {
Expand All @@ -20,6 +22,8 @@ public Map<String, String> createOptions() {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE)
.put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE)
.put(NodeJSServerCodegen.GOOGLE_CLOUD_FUNCTIONS, GOOGLE_CLOUD_FUNCTIONS)
.put(NodeJSServerCodegen.EXPORTED_NAME, EXPORTED_NAME)
.build();
}

Expand Down
11 changes: 11 additions & 0 deletions samples/server/petstore/nodejs-google-cloud-functions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Swagger generated server

## Overview
This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.

### Deploying the function
To deploy this module into Google Cloud Functions, you will have to use Google Cloud SDK commandline tool.

See [Google Cloud Functions quick start guide](https://cloud.google.com/functions/docs/quickstart) and [Deploying Cloud Functions](https://cloud.google.com/functions/docs/deploying/) for the details.

This project leverages the mega-awesome [swagger-tools](https://github.com/apigee-127/swagger-tools) middleware which does most all the work.
Loading