mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-07-04 22:50:53 +00:00
Add a Javascript (Closure) Angular generator.
This commit is contained in:
parent
564fa04f7c
commit
b950271940
@ -0,0 +1,206 @@
|
||||
package io.swagger.codegen.languages;
|
||||
|
||||
import io.swagger.codegen.CodegenModel;
|
||||
import io.swagger.codegen.*;
|
||||
import io.swagger.models.properties.*;
|
||||
|
||||
import java.util.TreeSet;
|
||||
import java.util.*;
|
||||
import java.io.File;
|
||||
|
||||
public class JavascriptClosureAngularClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
public JavascriptClosureAngularClientCodegen() {
|
||||
super();
|
||||
|
||||
supportsInheritance = false;
|
||||
reservedWords = new HashSet<String>(Arrays.asList("abstract",
|
||||
"continue", "for", "new", "switch", "assert", "default", "if",
|
||||
"package", "synchronized", "do", "goto", "private",
|
||||
"this", "break", "double", "implements", "protected", "throw",
|
||||
"byte", "else", "import", "public", "throws", "case", "enum",
|
||||
"instanceof", "return", "transient", "catch", "extends", "int",
|
||||
"short", "try", "char", "final", "interface", "static", "void",
|
||||
"class", "finally", "const", "super", "while"));
|
||||
|
||||
languageSpecificPrimitives = new HashSet<String>(Arrays.asList(
|
||||
"string",
|
||||
"boolean",
|
||||
"number",
|
||||
"Object",
|
||||
"Blob",
|
||||
"Date"));
|
||||
instantiationTypes.put("array", "Array");
|
||||
|
||||
typeMapping = new HashMap<String, String>();
|
||||
typeMapping.put("Array", "Array");
|
||||
typeMapping.put("array", "Array");
|
||||
typeMapping.put("List", "Array");
|
||||
typeMapping.put("boolean", "boolean");
|
||||
typeMapping.put("string", "string");
|
||||
typeMapping.put("int", "number");
|
||||
typeMapping.put("float", "number");
|
||||
typeMapping.put("number", "number");
|
||||
typeMapping.put("long", "number");
|
||||
typeMapping.put("short", "number");
|
||||
typeMapping.put("char", "string");
|
||||
typeMapping.put("double", "number");
|
||||
typeMapping.put("object", "Object");
|
||||
typeMapping.put("Object", "Object");
|
||||
typeMapping.put("File", "Blob");
|
||||
typeMapping.put("file", "Blob");
|
||||
typeMapping.put("integer", "number");
|
||||
typeMapping.put("Map", "Object");
|
||||
typeMapping.put("map", "Object");
|
||||
typeMapping.put("DateTime", "Date");
|
||||
|
||||
outputFolder = "generated-code/javascript-closure-angular";
|
||||
modelTemplateFiles.put("model.mustache", ".js");
|
||||
apiTemplateFiles.put("api.mustache", ".js");
|
||||
embeddedTemplateDir = templateDir = "Javascript-Closure-Angular";
|
||||
apiPackage = "API.Client";
|
||||
modelPackage = "API.Client";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "javascript-closure-angular";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a Javascript AngularJS client library annotated with Google Closure Compiler annotations" +
|
||||
"(https://developers.google.com/closure/compiler/docs/js-for-compiler?hl=en)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
return "_" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + "/" + apiPackage().replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
public String modelFileFolder() {
|
||||
return outputFolder + "/" + modelPackage().replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVarName(String name) {
|
||||
// replace - with _ e.g. created-at => created_at
|
||||
name = name.replaceAll("-", "_");
|
||||
|
||||
// if it's all uppper case, do nothing
|
||||
if (name.matches("^[A-Z_]*$"))
|
||||
return name;
|
||||
|
||||
// camelize the variable name
|
||||
// pet_id => PetId
|
||||
name = camelize(name, true);
|
||||
|
||||
// for reserved word or word starting with number, append _
|
||||
if (reservedWords.contains(name) || name.matches("^\\d.*"))
|
||||
name = escapeReservedWord(name);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toParamName(String name) {
|
||||
// should be the same as variable name
|
||||
return toVarName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelName(String name) {
|
||||
// model name cannot use reserved keyword, e.g. return
|
||||
if (reservedWords.contains(name))
|
||||
throw new RuntimeException(name
|
||||
+ " (reserved word) cannot be used as a model name");
|
||||
|
||||
// camelize the model name
|
||||
// phone_number => PhoneNumber
|
||||
return camelize(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
// should be the same as the model name
|
||||
return toModelName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(Property p) {
|
||||
if (p instanceof ArrayProperty) {
|
||||
ArrayProperty ap = (ArrayProperty) p;
|
||||
Property inner = ap.getItems();
|
||||
return getSwaggerType(p) + "<!" + getTypeDeclaration(inner) + ">";
|
||||
} else if (p instanceof MapProperty) {
|
||||
MapProperty mp = (MapProperty) p;
|
||||
Property inner = mp.getAdditionalProperties();
|
||||
return "Object<!string, "+ getTypeDeclaration(inner) + ">";
|
||||
} else if (p instanceof FileProperty) {
|
||||
return "Object";
|
||||
}
|
||||
String type = super.getTypeDeclaration(p);
|
||||
if (type.equals("boolean") ||
|
||||
type.equals("Date") ||
|
||||
type.equals("number") ||
|
||||
type.equals("string")) {
|
||||
return type;
|
||||
}
|
||||
return apiPackage + "." + type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSwaggerType(Property p) {
|
||||
String swaggerType = super.getSwaggerType(p);
|
||||
String type = null;
|
||||
if (typeMapping.containsKey(swaggerType)) {
|
||||
type = typeMapping.get(swaggerType);
|
||||
if (languageSpecificPrimitives.contains(type))
|
||||
return type;
|
||||
} else
|
||||
type = swaggerType;
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
|
||||
List<Object> models = (List<Object>) objs.get("models");
|
||||
for (Object _mo : models) {
|
||||
Map<String, Object> mo = (Map<String, Object>) _mo;
|
||||
CodegenModel cm = (CodegenModel) mo.get("model");
|
||||
cm.imports = new TreeSet(cm.imports);
|
||||
for (CodegenProperty var : cm.vars) {
|
||||
// handle default value for enum, e.g. available => StatusEnum.available
|
||||
if (var.isEnum && var.defaultValue != null && !"null".equals(var.defaultValue)) {
|
||||
var.defaultValue = var.datatypeWithEnum + "." + var.defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||
if (objs.get("imports") instanceof List) {
|
||||
List<Map<String, String>> imports = (ArrayList<Map<String, String>>)objs.get("imports");
|
||||
Collections.sort(imports, new Comparator<Map<String, String>>() {
|
||||
public int compare(Map<String, String> o1, Map<String, String> o2) {
|
||||
return o1.get("import").compareTo(o2.get("import"));
|
||||
}
|
||||
});
|
||||
objs.put("imports", imports);
|
||||
}
|
||||
return objs;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
/**
|
||||
* @fileoverview AUTOMATICALLY GENERATED service for {{package}}.{{classname}}.
|
||||
* Do not edit this file by hand or your changes will be lost next time it is
|
||||
* generated.{{#appDescription}}
|
||||
*
|
||||
* {{ appDescription }}{{/appDescription}}{{#version}}
|
||||
* Version: {{version}}{{/version}}{{#appContact}}
|
||||
* Contact: {{appContact}}{{/appContact}}
|
||||
* Generated at: {{generatedDate}}
|
||||
* Generated by: {{generatorClass}}
|
||||
*/{{#licenseInfo}}
|
||||
/**
|
||||
* @license {{licenseInfo}}{{#licenseUrl}}
|
||||
* {{licenseUrl}}{{/licenseUrl}}
|
||||
*/
|
||||
{{/licenseInfo}}
|
||||
|
||||
goog.provide('{{package}}.{{classname}}');
|
||||
|
||||
{{#imports}}
|
||||
goog.require('{{import}}');
|
||||
{{/imports}}
|
||||
{{#operations}}
|
||||
|
||||
/**
|
||||
{{#description}}
|
||||
* {{&description}}
|
||||
{{/description}}
|
||||
* @constructor
|
||||
* @param {!angular.$http} $http
|
||||
* @param {!angular.$injector} $injector
|
||||
* @struct
|
||||
*/
|
||||
{{package}}.{{classname}} = function($http, $injector) {
|
||||
/** @private {!string} */
|
||||
this.basePath_ = $injector.has('{{classname}}BasePath') ?
|
||||
/** @type {!string} */ ($injector.get('{{classname}}BasePath')) :
|
||||
'{{basePath}}';
|
||||
|
||||
/** @private {!Object<string, string>} */
|
||||
this.defaultHeaders_ = $injector.has('{{classname}}DefaultHeaders') ?
|
||||
/** @type {!Object<string, string>} */ (
|
||||
$injector.get('{{classname}}DefaultHeaders')) :
|
||||
{};
|
||||
|
||||
/** @private {!angular.$http} */
|
||||
this.http_ = $http;
|
||||
}
|
||||
{{package}}.{{classname}}.$inject = ['$http', '$injector'];
|
||||
{{#operation}}
|
||||
|
||||
/**
|
||||
* {{summary}}
|
||||
* {{notes}}{{#allParams}}
|
||||
* @param {!{{{dataType}}}{{^required}}={{/required}}} {{^required}}opt_{{/required}}{{paramName}} {{description}}{{/allParams}}
|
||||
* @param {!angular.$http.Config=} opt_extraHttpRequestParams Extra HTTP parameters to send.
|
||||
* @return {!angular.$q.Promise{{#returnType}}<!{{{returnType}}}>{{/returnType}}}
|
||||
*/
|
||||
{{package}}.{{classname}}.prototype.{{nickname}} = function({{#allParams}}{{^required}}opt_{{/required}}{{paramName}}, {{/allParams}}opt_extraHttpRequestParams) {
|
||||
/** @const {!string} */
|
||||
var path = this.basePath_ + '{{path}}'{{#pathParams}}
|
||||
.replace('{' + '{{baseName}}' + '}', String({{^required}}opt_{{/required}}{{paramName}})){{/pathParams}};
|
||||
{{#required}}
|
||||
|
||||
// verify required parameter '{{paramName}}' is set
|
||||
if (!{{paramName}}) {
|
||||
throw new Error('Missing required parameter {{paramName}} when calling {{nickname}}');
|
||||
}
|
||||
{{/required}}
|
||||
|
||||
/** @type {!Object<string,string>} */
|
||||
var queryParameters = {};
|
||||
{{#queryParams}}
|
||||
if ({{^required}}opt_{{/required}}{{paramName}} !== undefined) {
|
||||
queryParameters['{{baseName}}'] = String({{^required}}opt_{{/required}}{{paramName}});
|
||||
}
|
||||
{{/queryParams}}
|
||||
|
||||
/** @type {!Object<string,string>} */
|
||||
var headerParams = angular.copy(this.defaultHeaders_);
|
||||
{{#headerParams}}
|
||||
if ({{^required}}opt_{{/required}}{{paramName}} !== undefined) {
|
||||
headerParams['{{baseName}}'] = {{^required}}opt_{{/required}}{{paramName}};
|
||||
}
|
||||
{{/headerParams}}
|
||||
{{#hasFormParams}}
|
||||
|
||||
/** @type {!FormData} */
|
||||
var formParams = new FormData();
|
||||
{{/hasFormParams}}
|
||||
{{#formParams}}
|
||||
if ({{^required}}opt_{{/required}}{{paramName}} !== undefined) {
|
||||
var {{paramName}}_ = /** @type {?} */ ({{^required}}opt_{{/required}}{{paramName}});
|
||||
if ({{paramName}}_ instanceof Blob) {
|
||||
formParams.append('{{baseName}}', {{paramName}}_);
|
||||
} else if (typeof {{paramName}}_ === 'string') {
|
||||
formParams.append('{{baseName}}', {{paramName}}_);
|
||||
} else {
|
||||
throw new Error('Forms parameter {{^required}}opt_{{/required}}{{paramName}} is required to be a string or a Blob (https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob)');
|
||||
}
|
||||
}
|
||||
{{/formParams}}
|
||||
{{#allParams}}
|
||||
{{/allParams}}
|
||||
|
||||
/** @type {!angular.$http.Config} */
|
||||
var httpRequestConfig = /** @type {!angular.$http.Config} */ ({
|
||||
url: path,
|
||||
json: {{#hasFormParams}}false{{/hasFormParams}}{{^hasFormParams}}true{{/hasFormParams}},{{#bodyParam}}
|
||||
data: {{paramName}},{{/bodyParam}}{{#hasFormParams}}
|
||||
data: formParams,{{/hasFormParams}}
|
||||
params: queryParameters,
|
||||
headers: headerParams
|
||||
});
|
||||
|
||||
if (opt_extraHttpRequestParams) {
|
||||
// If an opt_extraHttpRequestParams object is passed in, override values
|
||||
// set the generated config with the passed in values.
|
||||
httpRequestConfig = angular.merge(httpRequestConfig, opt_extraHttpRequestParams);
|
||||
}
|
||||
|
||||
// This whole block is to work around a limitation in closure compiler. It
|
||||
// would be better to call the $http service directly as a function, but that
|
||||
// isn't permitted since it has methods attached to it. Manually confirmed to
|
||||
// compile down to just a single method even with only SIMPLE optimization on.
|
||||
// https://github.com/google/closure-compiler/blob/90769b826df65eabfb0211517b0d6d85c0c1c60b/contrib/externs/angular-1.4.js#L1393
|
||||
switch ('{{httpMethod}}') {
|
||||
case 'GET':
|
||||
return this.http_.get(path, httpRequestConfig);
|
||||
case 'HEAD':
|
||||
return this.http_.head(path, httpRequestConfig);
|
||||
case 'POST':
|
||||
return this.http_.post(path, {}, httpRequestConfig);
|
||||
case 'PUT':
|
||||
return this.http_.put(path, {}, httpRequestConfig);
|
||||
case 'DELETE':
|
||||
return this.http_.delete(path, httpRequestConfig);
|
||||
case 'PATCH':
|
||||
return this.http_.patch(path, {}, httpRequestConfig);
|
||||
}
|
||||
}
|
||||
{{/operation}}
|
||||
{{/operations}}
|
@ -0,0 +1,40 @@
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
goog.provide('{{package}}.{{name}}');
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
/**
|
||||
{{#description}}
|
||||
* {{{description}}}
|
||||
{{/description}}
|
||||
* @record
|
||||
*/
|
||||
{{package}}.{{classname}} = function() {}
|
||||
{{#vars}}
|
||||
|
||||
/**
|
||||
{{#description}}
|
||||
* {{{description}}}
|
||||
{{/description}}
|
||||
{{! Explicitly force types to be non-nullable using !. This is redundant but valid }}
|
||||
* @type {!{{{datatype}}}}
|
||||
* @export
|
||||
*/
|
||||
{{package}}.{{classname}}.prototype.{{name}};
|
||||
{{/vars}}
|
||||
|
||||
{{#hasEnums}}
|
||||
{{#vars}}
|
||||
{{#isEnum}}
|
||||
/** @enum {string} */
|
||||
{{package}}.{{classname}}.{{datatypeWithEnum}} = { {{#allowableValues}}{{#values}}
|
||||
{{.}}: '{{.}}',{{/values}}{{/allowableValues}}
|
||||
}
|
||||
{{/isEnum}}
|
||||
{{/vars}}
|
||||
{{/hasEnums}}
|
||||
{{/model}}
|
||||
{{/models}}
|
@ -10,6 +10,7 @@ io.swagger.codegen.languages.JavaJerseyServerCodegen
|
||||
io.swagger.codegen.languages.JavaCXFServerCodegen
|
||||
io.swagger.codegen.languages.JavaInflectorServerCodegen
|
||||
io.swagger.codegen.languages.JavascriptClientCodegen
|
||||
io.swagger.codegen.languages.JavascriptClosureAngularClientCodegen
|
||||
io.swagger.codegen.languages.JMeterCodegen
|
||||
io.swagger.codegen.languages.NodeJSServerCodegen
|
||||
io.swagger.codegen.languages.ObjcClientCodegen
|
||||
|
@ -0,0 +1,30 @@
|
||||
package io.swagger.codegen.options;
|
||||
|
||||
import io.swagger.codegen.CodegenConstants;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class JavascriptClosureAnularClientOptionsProvider implements OptionsProvider {
|
||||
public static final String SORT_PARAMS_VALUE = "false";
|
||||
public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true";
|
||||
|
||||
@Override
|
||||
public String getLanguage() {
|
||||
return "javascript-closure-angular";
|
||||
}
|
||||
|
||||
@Override
|
||||
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)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isServer() {
|
||||
return false;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user