|
| 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 | +} |
0 commit comments