Skip to content

Commit a0bfe2b

Browse files
jaypeawing328
authored andcommitted
WIP: new javascript flowtyped generator (#176)
New Javascript flowtyped generator
1 parent c01f4bf commit a0bfe2b

35 files changed

+9209
-2
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,4 @@ after_success:
128128
- if [ $DOCKER_HUB_USERNAME ]; then echo "$DOCKER_HUB_PASSWORD" | docker login --username=$DOCKER_HUB_USERNAME --password-stdin && docker build -t $DOCKER_CODEGEN_CLI_IMAGE_NAME ./modules/openapi-generator-cli && if [ ! -z "$TRAVIS_TAG" ]; then docker tag $DOCKER_CODEGEN_CLI_IMAGE_NAME:latest $DOCKER_CODEGEN_CLI_IMAGE_NAME:$TRAVIS_TAG; fi && if [ ! -z "$TRAVIS_TAG" ] || [ "$TRAVIS_BRANCH" = "master" ]; then docker push $DOCKER_CODEGEN_CLI_IMAGE_NAME && echo "Pushed to $DOCKER_CODEGEN_CLI_IMAGE_NAME"; fi; fi
129129

130130
env:
131-
- DOCKER_GENERATOR_IMAGE_NAME=openapitools/openapi-generator-online DOCKER_CODEGEN_CLI_IMAGE_NAME=openapitools/openapi-generator-cli
131+
- DOCKER_GENERATOR_IMAGE_NAME=openapitools/openapi-generator-online DOCKER_CODEGEN_CLI_IMAGE_NAME=openapitools/openapi-generator-cli NODE_ENV=test

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ OpenAPI Generator allows generation of API client libraries (SDK generation), se
4646

4747
| | Languages/Frameworks |
4848
|-|-|
49-
**API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C#** (.net 2.0, 3.5 or later), **C++** (cpprest, Qt5, Tizen), **Clojure**, **Dart**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured), **Kotlin**, **Lua**, **Node.js** (ES5, ES6, AngularJS with Google Closure Compiler annotations) **Objective-C**, **Perl**, **PHP**, **PowerShell**, **Python**, **R**, **Ruby**, **Rust** (rust, rust-server), **Scala** (akka, http4s, scalaz, swagger-async-httpclient), **Swift** (2.x, 3.x, 4.x), **Typescript** (AngularJS, Angular (2.x - 6.x), Aurelia, Fetch, Inversify, jQuery, Node)
49+
**API clients** | **ActionScript**, **Ada**, **Apex**, **Bash**, **C#** (.net 2.0, 3.5 or later), **C++** (cpprest, Qt5, Tizen), **Clojure**, **Dart**, **Elixir**, **Elm**, **Eiffel**, **Erlang**, **Go**, **Groovy**, **Haskell** (http-client, Servant), **Java** (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured), **Kotlin**, **Lua**, **Node.js** (ES5, ES6, AngularJS with Google Closure Compiler annotations, Flow types) **Objective-C**, **Perl**, **PHP**, **PowerShell**, **Python**, **R**, **Ruby**, **Rust** (rust, rust-server), **Scala** (akka, http4s, scalaz, swagger-async-httpclient), **Swift** (2.x, 3.x, 4.x), **Typescript** (AngularJS, Angular (2.x - 6.x), Aurelia, Fetch, Inversify, jQuery, Node)
5050
**Server stubs** | **Ada**, **C#** (ASP.NET Core, NancyFx), **C++** (Pistache, Restbed), **Erlang**, **Go**, **Haskell** (Servant), **Java** (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, RestEasy, Play Framework, [PKMST](https://github.com/ProKarma-Inc/pkmst-getting-started-examples)), **Kotlin**, **PHP** (Lumen, Slim, Silex, [Symfony](https://symfony.com/), [Zend Expressive](https://github.com/zendframework/zend-expressive)), **Python** (Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Rust** (rust-server), **Scala** ([Finch](https://github.com/finagle/finch), [Lagom](https://github.com/lagom/lagom), Scalatra)
5151
**API documentation generators** | **HTML**, **Confluence Wiki**
5252
**Configuration files** | [**Apache2**](https://httpd.apache.org/)
@@ -477,6 +477,7 @@ Here is a list of template creators:
477477
* Java (Rest-assured): @viclovsky
478478
* Javascript/NodeJS: @jfiala
479479
* Javascript (Closure-annotated Angular) @achew22
480+
* Javascript (Flow types) @jaypea
480481
* JMeter: @davidkiss
481482
* Kotlin: @jimschubert
482483
* Lua: @daurnimator

bin/javascript-flowtyped-petstore.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/bin/sh
2+
3+
SCRIPT="$0"
4+
echo "# START SCRIPT: $SCRIPT"
5+
6+
while [ -h "$SCRIPT" ] ; do
7+
ls=`ls -ld "$SCRIPT"`
8+
link=`expr "$ls" : '.*-> \(.*\)$'`
9+
if expr "$link" : '/.*' > /dev/null; then
10+
SCRIPT="$link"
11+
else
12+
SCRIPT=`dirname "$SCRIPT"`/"$link"
13+
fi
14+
done
15+
16+
if [ ! -d "${APP_DIR}" ]; then
17+
APP_DIR=`dirname "$SCRIPT"`/..
18+
APP_DIR=`cd "${APP_DIR}"; pwd`
19+
fi
20+
21+
executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar"
22+
23+
if [ ! -f "$executable" ]
24+
then
25+
mvn -B clean package
26+
fi
27+
28+
# if you've executed sbt assembly previously it will use that instead.
29+
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
30+
ags="generate -t modules/openapi-generator/src/main/resources/Javascript-Flowtyped -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g javascript-flowtyped -o samples/client/petstore/javascript-flowtyped -DappName=PetstoreClient $@"
31+
32+
java $JAVA_OPTS -jar $executable $ags
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
/*
2+
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
3+
* Copyright 2018 SmartBear Software
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.openapitools.codegen.languages;
19+
20+
import io.swagger.v3.oas.models.OpenAPI;
21+
import io.swagger.v3.oas.models.media.ArraySchema;
22+
import io.swagger.v3.oas.models.media.Schema;
23+
import io.swagger.v3.oas.models.info.Info;
24+
import io.swagger.v3.parser.util.SchemaTypeUtil;
25+
import org.openapitools.codegen.*;
26+
import org.apache.commons.lang3.StringUtils;
27+
import org.openapitools.codegen.utils.ModelUtils;
28+
29+
import java.text.SimpleDateFormat;
30+
import java.util.*;
31+
32+
public class JavascriptFlowtypedClientCodegen extends AbstractTypeScriptClientCodegen {
33+
private static final SimpleDateFormat SNAPSHOT_SUFFIX_FORMAT = new SimpleDateFormat("yyyyMMddHHmm");
34+
35+
public static final String NPM_NAME = "npmName";
36+
public static final String NPM_VERSION = "npmVersion";
37+
public static final String NPM_REPOSITORY = "npmRepository";
38+
public static final String SNAPSHOT = "snapshot";
39+
40+
protected String npmName = null;
41+
protected String npmVersion = "1.0.0";
42+
protected String npmRepository = null;
43+
44+
public JavascriptFlowtypedClientCodegen() {
45+
super();
46+
47+
// clear import mapping (from default generator) as TS does not use it
48+
// at the moment
49+
importMapping.clear();
50+
51+
setReservedWordsLowerCase(Arrays.asList(
52+
// local variable names used in API methods (endpoints)
53+
"varLocalPath", "queryParameters", "headerParams", "formParams", "useFormData", "varLocalDeferred",
54+
"requestOptions",
55+
// Typescript reserved words
56+
"abstract", "arguments", "boolean", "break", "byte",
57+
"case", "catch", "char", "class", "const",
58+
"continue", "debugger", "default", "delete", "do",
59+
"double", "else", "enum", "eval", "export",
60+
"extends", "false", "final", "finally", "float",
61+
"for", "function", "goto", "if", "implements",
62+
"import", "in", "instanceof", "int", "interface",
63+
"let", "long", "native", "new", "null",
64+
"package", "private", "protected", "public", "return",
65+
"short", "static", "super", "switch", "synchronized",
66+
"this", "throw", "throws", "transient", "true",
67+
"try", "typeof", "var", "void", "volatile",
68+
"while", "with", "yield",
69+
"Array", "Date", "eval", "function", "hasOwnProperty",
70+
"Infinity", "isFinite", "isNaN", "isPrototypeOf",
71+
"Math", "NaN", "Number", "Object",
72+
"prototype", "String", "toString", "undefined", "valueOf"));
73+
74+
languageSpecificPrimitives = new HashSet<String>(
75+
Arrays.asList("string", "boolean", "number", "Array", "Object", "Date", "File", "Blob")
76+
);
77+
78+
instantiationTypes.put("array", "Array");
79+
instantiationTypes.put("list", "Array");
80+
instantiationTypes.put("map", "Object");
81+
typeMapping.clear();
82+
typeMapping.put("array", "Array");
83+
typeMapping.put("map", "Object");
84+
typeMapping.put("List", "Array");
85+
typeMapping.put("boolean", "boolean");
86+
typeMapping.put("string", "string");
87+
typeMapping.put("int", "number");
88+
typeMapping.put("float", "number");
89+
typeMapping.put("number", "number");
90+
typeMapping.put("DateTime", "Date");
91+
typeMapping.put("date", "Date");
92+
typeMapping.put("long", "number");
93+
typeMapping.put("short", "number");
94+
typeMapping.put("char", "string");
95+
typeMapping.put("double", "number");
96+
typeMapping.put("object", "Object");
97+
typeMapping.put("integer", "number");
98+
// file, binary not supported in JS client right now, using String as a workaround
99+
typeMapping.put("file", "string");
100+
typeMapping.put("binary", "string");
101+
typeMapping.put("ByteArray", "string");
102+
typeMapping.put("UUID", "string");
103+
104+
defaultIncludes = new HashSet<String>(languageSpecificPrimitives);
105+
outputFolder = "generated-code/javascript-flowtyped";
106+
embeddedTemplateDir = templateDir = "Javascript-Flowtyped";
107+
108+
this.cliOptions.add(new CliOption(NPM_NAME, "The name under which you want to publish generated npm package"));
109+
this.cliOptions.add(new CliOption(NPM_VERSION, "The version of your npm package"));
110+
this.cliOptions.add(new CliOption(NPM_REPOSITORY, "Use this property to set an url your private npmRepo in the package.json"));
111+
this.cliOptions.add(new CliOption(SNAPSHOT, "When setting this property to true the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm", SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
112+
113+
}
114+
115+
@Override
116+
public CodegenType getTag() {
117+
return CodegenType.CLIENT;
118+
}
119+
120+
@Override
121+
protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) {
122+
codegenModel.additionalPropertiesType = getTypeDeclaration((Schema) schema.getAdditionalProperties());
123+
addImport(codegenModel, codegenModel.additionalPropertiesType);
124+
}
125+
126+
@Override
127+
public void processOpts() {
128+
super.processOpts();
129+
supportingFiles.add(new SupportingFile("index.mustache", "src", "index.js"));
130+
supportingFiles.add(new SupportingFile("api.mustache", "src", "api.js"));
131+
supportingFiles.add(new SupportingFile("configuration.mustache", "src", "configuration.js"));
132+
supportingFiles.add(new SupportingFile("gitignore", "", ".gitignore"));
133+
134+
addNpmPackageGeneration();
135+
}
136+
137+
@Override
138+
public String getTypeDeclaration(Schema p) {
139+
Schema inner;
140+
if (ModelUtils.isArraySchema(p)) {
141+
inner = ((ArraySchema) p).getItems();
142+
return this.getSchemaType(p) + "<" + this.getTypeDeclaration(inner) + ">";
143+
} else if (ModelUtils.isMapSchema(p)) {
144+
inner = (Schema) p.getAdditionalProperties();
145+
return "{ [key: string]: " + this.getTypeDeclaration(inner) + "; }";
146+
} else if (ModelUtils.isFileSchema(p)) {
147+
return "any";
148+
} else if (ModelUtils.isBinarySchema(p)) {
149+
return "any";
150+
} else {
151+
return super.getTypeDeclaration(p);
152+
}
153+
}
154+
155+
private void addNpmPackageGeneration() {
156+
if (additionalProperties.containsKey(NPM_NAME)) {
157+
this.setNpmName(additionalProperties.get(NPM_NAME).toString());
158+
}
159+
160+
if (additionalProperties.containsKey(NPM_VERSION)) {
161+
this.setNpmVersion(additionalProperties.get(NPM_VERSION).toString());
162+
}
163+
164+
if (additionalProperties.containsKey(SNAPSHOT) && Boolean.valueOf(additionalProperties.get(SNAPSHOT).toString())) {
165+
this.setNpmVersion(npmVersion + "-SNAPSHOT." + SNAPSHOT_SUFFIX_FORMAT.format(new Date()));
166+
}
167+
additionalProperties.put(NPM_VERSION, npmVersion);
168+
169+
if (additionalProperties.containsKey(NPM_REPOSITORY)) {
170+
this.setNpmRepository(additionalProperties.get(NPM_REPOSITORY).toString());
171+
}
172+
173+
//Files for building our lib
174+
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
175+
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json"));
176+
supportingFiles.add(new SupportingFile("flowconfig.mustache", "", ".flowconfig"));
177+
supportingFiles.add(new SupportingFile("babelrc", "", ".babelrc"));
178+
}
179+
180+
@Override
181+
public void preprocessOpenAPI(OpenAPI openAPI) {
182+
super.preprocessOpenAPI(openAPI);
183+
184+
if (openAPI.getInfo() != null) {
185+
Info info = openAPI.getInfo();
186+
if (StringUtils.isBlank(npmName) && info.getTitle() != null) {
187+
// when projectName is not specified, generate it from info.title
188+
npmName = sanitizeName(dashize(info.getTitle()));
189+
}
190+
if (StringUtils.isBlank(npmVersion)) {
191+
// when projectVersion is not specified, use info.version
192+
npmVersion = escapeUnsafeCharacters(escapeQuotationMark(info.getVersion()));
193+
}
194+
}
195+
196+
// default values
197+
if (StringUtils.isBlank(npmName)) {
198+
npmName = "openapi-js-client";
199+
}
200+
if (StringUtils.isBlank(npmVersion)) {
201+
npmVersion = "1.0.0";
202+
}
203+
204+
additionalProperties.put(NPM_NAME, npmName);
205+
additionalProperties.put(NPM_VERSION, npmVersion);
206+
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
207+
}
208+
209+
@Override
210+
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
211+
// process enum in models
212+
List<Object> models = (List<Object>) postProcessModelsEnum(objs).get("models");
213+
for (Object _mo : models) {
214+
Map<String, Object> mo = (Map<String, Object>) _mo;
215+
CodegenModel cm = (CodegenModel) mo.get("model");
216+
cm.imports = new TreeSet(cm.imports);
217+
// name enum with model name, e.g. StatusEnum => Pet.StatusEnum
218+
for (CodegenProperty var : cm.vars) {
219+
if (Boolean.TRUE.equals(var.isEnum)) {
220+
var.datatypeWithEnum = var.datatypeWithEnum.replace(var.enumName, cm.classname + "" + var.enumName);
221+
}
222+
}
223+
if (cm.parent != null) {
224+
for (CodegenProperty var : cm.allVars) {
225+
if (Boolean.TRUE.equals(var.isEnum)) {
226+
var.datatypeWithEnum = var.datatypeWithEnum
227+
.replace(var.enumName, cm.classname + "" + var.enumName);
228+
}
229+
}
230+
}
231+
}
232+
233+
return objs;
234+
}
235+
236+
@Override
237+
public String escapeQuotationMark(String input) {
238+
// remove ', " to avoid code injection
239+
return input.replace("\"", "").replace("'", "");
240+
}
241+
242+
@Override
243+
public String escapeUnsafeCharacters(String input) {
244+
return input.replace("*/", "*_/").replace("/*", "/_*");
245+
}
246+
247+
@Override
248+
public String getName() {
249+
return "javascript-flowtyped";
250+
}
251+
252+
@Override
253+
public String getHelp() {
254+
return "Generates a Javascript client library (beta) using Flow types and Fetch API.";
255+
}
256+
257+
public String getNpmName() {
258+
return npmName;
259+
}
260+
261+
public void setNpmName(String npmName) {
262+
this.npmName = npmName;
263+
}
264+
265+
public String getNpmVersion() {
266+
return npmVersion;
267+
}
268+
269+
public void setNpmVersion(String npmVersion) {
270+
this.npmVersion = npmVersion;
271+
}
272+
273+
public String getNpmRepository() {
274+
return npmRepository;
275+
}
276+
277+
public void setNpmRepository(String npmRepository) {
278+
this.npmRepository = npmRepository;
279+
}
280+
281+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
## {{npmName}}@{{npmVersion}}
2+
3+
This generator creates Flow typed JavaScript client that utilizes [Fetch API](https://fetch.spec.whatwg.org/). The generated Node module can be used in the following environments:
4+
5+
Environment
6+
* Node.js
7+
* Webpack
8+
* Browserify
9+
10+
Language level
11+
* ES6
12+
13+
Module system
14+
* ES6 module system
15+
16+
### Building
17+
18+
To build an compile the flow typed sources to javascript use:
19+
```
20+
npm install
21+
npm run build
22+
```
23+
24+
### Publishing
25+
26+
First build the package then run ```npm publish```
27+
28+
### Consuming
29+
30+
navigate to the folder of your consuming project and run one of the following commands.
31+
32+
_published:_
33+
34+
```
35+
npm install {{npmName}}@{{npmVersion}} --save
36+
```
37+
38+
_unPublished (not recommended):_
39+
40+
```
41+
npm install PATH_TO_GENERATED_PACKAGE --save

0 commit comments

Comments
 (0)