diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java index e6d906804f9..b5ccea1606c 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptNodeClientCodegen.java @@ -18,8 +18,10 @@ package org.openapitools.codegen.languages; import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.responses.ApiResponse; + import org.openapitools.codegen.*; import org.openapitools.codegen.utils.ModelUtils; import org.slf4j.Logger; @@ -112,7 +114,7 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen } return camelize(name) + apiSuffix; } - + @Override public String toApiFilename(String name) { if (name.length() == 0) { @@ -150,7 +152,7 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen return modelPackage() + "/" + camelize(toModelName(name), true); } - + @Override public Map postProcessAllModels(Map objs) { Map result = super.postProcessAllModels(objs); @@ -167,7 +169,7 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen } return result; } - + private List> toTsImports(CodegenModel cm, Set imports) { List> tsImports = new ArrayList<>(); for (String im : imports) { @@ -180,31 +182,31 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen } return tsImports; } - + @Override public Map postProcessOperationsWithModels(Map operations, List allModels) { Map objs = (Map) operations.get("operations"); - + // The api.mustache template requires all of the auth methods for the whole api // Loop over all the operations and pick out each unique auth method Map authMethodsMap = new HashMap<>(); for (CodegenOperation op : (List) objs.get("operation")) { - if(op.hasAuthMethods){ - for(CodegenSecurity sec : op.authMethods){ + if (op.hasAuthMethods) { + for (CodegenSecurity sec : op.authMethods) { authMethodsMap.put(sec.name, sec); } } } - + // If there wer any auth methods specified add them to the operations context if (!authMethodsMap.isEmpty()) { operations.put("authMethods", authMethodsMap.values()); operations.put("hasAuthMethods", true); } - + // Add filename information for api imports objs.put("apiFilename", getApiFilenameFromClassname(objs.get("classname").toString())); - + // Add additional filename information for model imports in the apis List> imports = (List>) operations.get("imports"); for (Map im : imports) { @@ -231,7 +233,7 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen supportingFiles.add(new SupportingFile("api.mustache", getIndexDirectory(), "api.ts")); supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh")); supportingFiles.add(new SupportingFile("gitignore", "", ".gitignore")); - + if (additionalProperties.containsKey(NPM_NAME)) { addNpmPackageGeneration(); } @@ -247,7 +249,7 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen supportingFiles.add(new SupportingFile("package.mustache", getPackageRootDirectory(), "package.json")); supportingFiles.add(new SupportingFile("tsconfig.mustache", getPackageRootDirectory(), "tsconfig.json")); } - + private String getIndexDirectory() { String indexPackage = modelPackage.substring(0, Math.max(0, modelPackage.lastIndexOf('.'))); return indexPackage.replace('.', File.separatorChar); @@ -270,7 +272,7 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen } return type; } - + private boolean isLanguagePrimitive(String type) { return languageSpecificPrimitives.contains(type); } @@ -289,14 +291,24 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen String indexPackage = modelPackage.substring(0, Math.max(0, modelPackage.lastIndexOf('.'))); return indexPackage.replace('.', File.separatorChar); } - + private String getApiFilenameFromClassname(String classname) { String name = classname.substring(0, classname.length() - apiSuffix.length()); return toApiFilename(name); } - + private String getModelnameFromModelFilename(String filename) { String name = filename.substring((modelPackage() + File.separator).length()); return camelize(name); } +@Override + protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) { + super.addAdditionPropertiesToCodeGenModel(codegenModel, schema); + Schema additionalProperties = ModelUtils.getAdditionalProperties(schema); + codegenModel.additionalPropertiesType = getSchemaType(additionalProperties); + if ("array".equalsIgnoreCase(codegenModel.additionalPropertiesType)) { + codegenModel.additionalPropertiesType += '<' + getSchemaType(((ArraySchema) additionalProperties).getItems()) + '>'; + } + addImport(codegenModel, codegenModel.additionalPropertiesType); + } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptnode/TypeScriptNodeModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptnode/TypeScriptNodeModelTest.java index d3a11b970c0..efc0d377b92 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptnode/TypeScriptNodeModelTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptnode/TypeScriptNodeModelTest.java @@ -18,9 +18,11 @@ package org.openapitools.codegen.typescript.typescriptnode; import com.google.common.collect.Sets; + import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.*; import io.swagger.v3.parser.util.SchemaTypeUtil; + import org.openapitools.codegen.CodegenModel; import org.openapitools.codegen.CodegenProperty; import org.openapitools.codegen.DefaultCodegen; @@ -206,6 +208,54 @@ public class TypeScriptNodeModelTest { Assert.assertEquals(Sets.intersection(cm.imports, Sets.newHashSet("Children")).size(), 1); } + @Test(description = "convert an array additional properties model") + public void arrayModelAdditionalPropertiesArrayTest() { + final Schema schema = new Schema() + .description("a map model") + .additionalProperties(new ArraySchema().type("array").items(new Schema().type("string"))); + final DefaultCodegen codegen = new TypeScriptNodeClientCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", schema); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel("sample", schema); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a map model"); + Assert.assertEquals(cm.additionalPropertiesType, "Array"); + } + + @Test(description = "convert an string additional properties model") + public void arrayModelAdditionalPropertiesStringTest() { + final Schema schema = new Schema() + .description("a map model") + .additionalProperties(new Schema().type("string")); + final DefaultCodegen codegen = new TypeScriptNodeClientCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", schema); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel("sample", schema); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a map model"); + Assert.assertEquals(cm.additionalPropertiesType, "string"); + } + + @Test(description = "convert an complex additional properties model") + public void arrayModelAdditionalPropertiesComplexTest() { + final Schema schema = new Schema() + .description("a map model") + .additionalProperties(new Schema().type("object").$ref("#/definitions/Children")); + final DefaultCodegen codegen = new TypeScriptNodeClientCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", schema); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel("sample", schema); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a map model"); + Assert.assertEquals(cm.additionalPropertiesType, "Children"); + } + @Test(description = "prepend imports with ./ by default") public void defaultFromModelTest() { final OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/petstore.yaml"); diff --git a/samples/client/petstore/typescript-redux-query/builds/default/.openapi-generator/VERSION b/samples/client/petstore/typescript-redux-query/builds/default/.openapi-generator/VERSION index e4955748d3e..58592f031f6 100644 --- a/samples/client/petstore/typescript-redux-query/builds/default/.openapi-generator/VERSION +++ b/samples/client/petstore/typescript-redux-query/builds/default/.openapi-generator/VERSION @@ -1 +1 @@ -4.2.2-SNAPSHOT \ No newline at end of file +4.2.3-SNAPSHOT \ No newline at end of file