diff --git a/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/DefaultRestMethodBuilder.java b/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/DefaultRestMethodBuilder.java new file mode 100644 index 000000000..23dd99524 --- /dev/null +++ b/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/DefaultRestMethodBuilder.java @@ -0,0 +1,21 @@ +package cz.habarta.typescript.generator; + +import cz.habarta.typescript.generator.parser.MethodParameterModel; +import cz.habarta.typescript.generator.parser.RestMethodModel; +import cz.habarta.typescript.generator.parser.RestQueryParam; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.List; + +public class DefaultRestMethodBuilder implements RestMethodBuilder{ + + @Override + public RestMethodModel build(Class originClass, String name, Type returnType, Method originalMethod, + Class rootResource, String httpMethod, String path, + List pathParams, List queryParams, + MethodParameterModel entityParam, List comments) { + + return new RestMethodModel(originClass, name, returnType, originalMethod, rootResource, httpMethod, path, + pathParams, queryParams, entityParam, comments); + } +} diff --git a/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/RestMethodBuilder.java b/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/RestMethodBuilder.java new file mode 100644 index 000000000..dcc36d791 --- /dev/null +++ b/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/RestMethodBuilder.java @@ -0,0 +1,16 @@ +package cz.habarta.typescript.generator; + +import cz.habarta.typescript.generator.parser.MethodParameterModel; +import cz.habarta.typescript.generator.parser.RestMethodModel; +import cz.habarta.typescript.generator.parser.RestQueryParam; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.List; + +public interface RestMethodBuilder { + + RestMethodModel build(Class originClass, String name, Type returnType, Method originalMethod, + Class rootResource, String httpMethod, String path, List pathParams, List queryParams, MethodParameterModel entityParam, + List comments); + +} diff --git a/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/Settings.java b/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/Settings.java index 6d42a3f5c..6558264d3 100644 --- a/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/Settings.java +++ b/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/Settings.java @@ -110,6 +110,7 @@ public class Settings { public boolean restOptionsTypeIsGeneric; private List restApplicationParserFactories; public TypeProcessor customTypeProcessor = null; + public RestMethodBuilder customRestMethodBuilder = null; public boolean sortDeclarations = false; public boolean sortTypeDeclarations = false; public boolean noFileComment = false; @@ -231,6 +232,12 @@ public void loadCustomTypeProcessor(ClassLoader classLoader, String customTypePr } } + public void loadCustomRestMethodBuilder(ClassLoader classLoader, String customRestMethodBuilder) { + if (customRestMethodBuilder != null) { + this.customRestMethodBuilder = loadInstance(classLoader, customRestMethodBuilder, RestMethodBuilder.class); + } + } + public void loadExtensions(ClassLoader classLoader, List extensions, List extensionsWithConfiguration) { this.extensions = new ArrayList<>(); this.extensions.addAll(loadInstances(classLoader, extensions, EmitterExtension.class)); diff --git a/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/parser/JaxrsApplicationParser.java b/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/parser/JaxrsApplicationParser.java index c0c8c6ec3..461231178 100644 --- a/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/parser/JaxrsApplicationParser.java +++ b/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/parser/JaxrsApplicationParser.java @@ -233,7 +233,7 @@ private void parseResourceMethod(Result result, ResourceContext context, Class comments = Swagger.getOperationComments(swaggerOperation); // create method - model.getMethods().add(new RestMethodModel(resourceClass, method.getName(), resolvedModelReturnType, method, + model.getMethods().add(restMethodBuilder.build(resourceClass, method.getName(), resolvedModelReturnType, method, context.rootResource, httpMethod.value(), context.path, pathParams, queryParams, entityParameter, comments)); } // JAX-RS specification - 3.4.1 Sub Resources diff --git a/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/parser/RestApplicationParser.java b/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/parser/RestApplicationParser.java index 4dfceaea2..83dacfafa 100644 --- a/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/parser/RestApplicationParser.java +++ b/typescript-generator-core/src/main/java/cz/habarta/typescript/generator/parser/RestApplicationParser.java @@ -1,6 +1,8 @@ package cz.habarta.typescript.generator.parser; +import cz.habarta.typescript.generator.DefaultRestMethodBuilder; +import cz.habarta.typescript.generator.RestMethodBuilder; import cz.habarta.typescript.generator.Settings; import cz.habarta.typescript.generator.TypeProcessor; import cz.habarta.typescript.generator.util.Utils; @@ -17,6 +19,7 @@ public abstract class RestApplicationParser { protected final Predicate isClassNameExcluded; protected final TypeProcessor commonTypeProcessor; protected final RestApplicationModel model; + protected final RestMethodBuilder restMethodBuilder; public static abstract class Factory { @@ -33,6 +36,9 @@ public RestApplicationParser(Settings settings, TypeProcessor commonTypeProcesso this.isClassNameExcluded = settings.getExcludeFilter(); this.commonTypeProcessor = commonTypeProcessor; this.model = model; + this.restMethodBuilder = settings.customRestMethodBuilder == null ? + new DefaultRestMethodBuilder() : + settings.customRestMethodBuilder; } public RestApplicationModel getModel() { diff --git a/typescript-generator-core/src/test/java/cz/habarta/typescript/generator/JaxrsApplicationTest.java b/typescript-generator-core/src/test/java/cz/habarta/typescript/generator/JaxrsApplicationTest.java index 9709b1580..860ded2ae 100644 --- a/typescript-generator-core/src/test/java/cz/habarta/typescript/generator/JaxrsApplicationTest.java +++ b/typescript-generator-core/src/test/java/cz/habarta/typescript/generator/JaxrsApplicationTest.java @@ -5,7 +5,10 @@ import cz.habarta.typescript.generator.compiler.ModelCompiler; import cz.habarta.typescript.generator.parser.BeanModel; import cz.habarta.typescript.generator.parser.JaxrsApplicationParser; +import cz.habarta.typescript.generator.parser.MethodParameterModel; import cz.habarta.typescript.generator.parser.Model; +import cz.habarta.typescript.generator.parser.RestMethodModel; +import cz.habarta.typescript.generator.parser.RestQueryParam; import cz.habarta.typescript.generator.parser.SourceType; import cz.habarta.typescript.generator.type.JGenericArrayType; import cz.habarta.typescript.generator.type.JTypeWithNullability; @@ -40,6 +43,7 @@ import java.io.File; import java.io.InputStream; import java.io.Reader; +import java.lang.reflect.Method; import java.lang.reflect.Type; import java.net.URI; import java.util.ArrayList; @@ -704,6 +708,18 @@ public void testGenericResources() { Assertions.assertTrue(output.contains("interface AccountDto")); } + @Test + public void testCustomREstMethodBuilder() { + final Settings settings = TestUtils.settings(); + settings.generateJaxrsApplicationClient = true; + settings.outputFileType = TypeScriptFileType.implementationFile; + settings.customRestMethodBuilder = new CustomRestMethodBuilder(); + final String output = new TypeScriptGenerator(settings).generateTypeScript(Input.from(AccountResource.class)); + Assertions.assertTrue(!output.contains("get(testParam: ID): RestResponse")); + Assertions.assertTrue(output.contains("get(testParam: string): RestResponse")); + Assertions.assertTrue(output.contains("interface AccountDto")); + } + public static class AccountDto { public Integer id; public String name; @@ -728,4 +744,16 @@ public static void main(String[] args) { System.out.println("Jersey started."); } + public class CustomRestMethodBuilder implements RestMethodBuilder{ + + @Override + public RestMethodModel build(Class originClass, String name, Type returnType, + Method originalMethod, Class rootResource, String httpMethod, + String path, List pathParams, List queryParams, + MethodParameterModel entityParam, List comments) { + + return new RestMethodModel(originClass, name, returnType, originalMethod, rootResource, httpMethod, path, + Arrays.asList(new MethodParameterModel("testParam", String.class)), queryParams, entityParam, comments); + } + } } diff --git a/typescript-generator-gradle-plugin/src/main/java/cz/habarta/typescript/generator/gradle/GenerateTask.java b/typescript-generator-gradle-plugin/src/main/java/cz/habarta/typescript/generator/gradle/GenerateTask.java index a8fb841a1..8135cc6e9 100644 --- a/typescript-generator-gradle-plugin/src/main/java/cz/habarta/typescript/generator/gradle/GenerateTask.java +++ b/typescript-generator-gradle-plugin/src/main/java/cz/habarta/typescript/generator/gradle/GenerateTask.java @@ -101,6 +101,7 @@ public class GenerateTask extends DefaultTask { public String restNamespacingAnnotation; public String restResponseType; public String restOptionsType; + public String customRestMethodBuilder; public String customTypeProcessor; public boolean sortDeclarations; public boolean sortTypeDeclarations; @@ -190,6 +191,7 @@ private Settings createSettings(URLClassLoader classLoader) { settings.setRestNamespacingAnnotation(classLoader, restNamespacingAnnotation); settings.restResponseType = restResponseType; settings.setRestOptionsType(restOptionsType); + settings.loadCustomRestMethodBuilder(classLoader, customRestMethodBuilder); settings.loadCustomTypeProcessor(classLoader, customTypeProcessor); settings.sortDeclarations = sortDeclarations; settings.sortTypeDeclarations = sortTypeDeclarations; diff --git a/typescript-generator-maven-plugin/src/main/java/cz/habarta/typescript/generator/maven/GenerateMojo.java b/typescript-generator-maven-plugin/src/main/java/cz/habarta/typescript/generator/maven/GenerateMojo.java index 8c6ad8f49..7170d54cd 100644 --- a/typescript-generator-maven-plugin/src/main/java/cz/habarta/typescript/generator/maven/GenerateMojo.java +++ b/typescript-generator-maven-plugin/src/main/java/cz/habarta/typescript/generator/maven/GenerateMojo.java @@ -16,6 +16,7 @@ import cz.habarta.typescript.generator.OptionalProperties; import cz.habarta.typescript.generator.OptionalPropertiesDeclaration; import cz.habarta.typescript.generator.Output; +import cz.habarta.typescript.generator.RestMethodBuilder; import cz.habarta.typescript.generator.RestNamespacing; import cz.habarta.typescript.generator.Settings; import cz.habarta.typescript.generator.StringQuotes; @@ -625,6 +626,15 @@ public class GenerateMojo extends AbstractMojo { @Parameter private String customTypeProcessor; + /** + * Specifies custom class implementing {@link RestMethodBuilder}. + * This allows to customize how Rest methods are mapped to TypeScript. + * For example, it is possible to implement RestMethodBuilder to filter or add some query parameters or + * change the returned type, etc. + */ + @Parameter + private String customRestMethodBuilder; + /** * If true TypeScript declarations (interfaces, properties) will be sorted alphabetically. */ @@ -949,6 +959,7 @@ private Settings createSettings(URLClassLoader classLoader) { settings.restResponseType = restResponseType; settings.setRestOptionsType(restOptionsType); settings.loadCustomTypeProcessor(classLoader, customTypeProcessor); + settings.loadCustomRestMethodBuilder(classLoader, customRestMethodBuilder); settings.sortDeclarations = sortDeclarations; settings.sortTypeDeclarations = sortTypeDeclarations; settings.noFileComment = noFileComment; diff --git a/typescript-generator-spring/src/main/java/cz/habarta/typescript/generator/spring/SpringApplicationParser.java b/typescript-generator-spring/src/main/java/cz/habarta/typescript/generator/spring/SpringApplicationParser.java index 99b36662f..517d13d0c 100644 --- a/typescript-generator-spring/src/main/java/cz/habarta/typescript/generator/spring/SpringApplicationParser.java +++ b/typescript-generator-spring/src/main/java/cz/habarta/typescript/generator/spring/SpringApplicationParser.java @@ -348,7 +348,7 @@ private void parseControllerMethod(JaxrsApplicationParser.Result result, JaxrsAp final Type modelReturnType = parseReturnType(controllerClass, method); foundType(result, modelReturnType, controllerClass, method.getName()); - model.getMethods().add(new RestMethodModel(controllerClass, method.getName(), modelReturnType, method, + model.getMethods().add(restMethodBuilder.build(controllerClass, method.getName(), modelReturnType, method, controllerClass, httpMethod.name(), context.path, pathParams, queryParams, entityParameter, null)); } } diff --git a/typescript-generator-spring/src/test/java/cz/habarta/typescript/generator/spring/SpringTest.java b/typescript-generator-spring/src/test/java/cz/habarta/typescript/generator/spring/SpringTest.java index a2a932bef..ab70a0c36 100644 --- a/typescript-generator-spring/src/test/java/cz/habarta/typescript/generator/spring/SpringTest.java +++ b/typescript-generator-spring/src/test/java/cz/habarta/typescript/generator/spring/SpringTest.java @@ -2,16 +2,23 @@ package cz.habarta.typescript.generator.spring; import cz.habarta.typescript.generator.Input; +import cz.habarta.typescript.generator.RestMethodBuilder; import cz.habarta.typescript.generator.Settings; import cz.habarta.typescript.generator.TestUtils; import cz.habarta.typescript.generator.TypeScriptFileType; import cz.habarta.typescript.generator.TypeScriptGenerator; +import cz.habarta.typescript.generator.parser.MethodParameterModel; +import cz.habarta.typescript.generator.parser.RestMethodModel; +import cz.habarta.typescript.generator.parser.RestQueryParam; import cz.habarta.typescript.generator.util.Utils; import io.swagger.annotations.ApiOperation; import io.swagger.v3.oas.annotations.Operation; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import java.lang.reflect.Method; +import java.lang.reflect.Type; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -35,7 +42,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; - public class SpringTest { @Test @@ -169,6 +175,17 @@ public void testInheritance() { Assertions.assertFalse(output.contains("uriEncoding`test/b`")); } + @Test + public void testCustomRestMethodBuilder() { + final Settings settings = TestUtils.settings(); + settings.outputFileType = TypeScriptFileType.implementationFile; + settings.generateSpringApplicationClient = true; + settings.customRestMethodBuilder = new CustomRestMethodBuilder(); + final String output = new TypeScriptGenerator(settings).generateTypeScript(Input.from(Controller3.class)); + Assertions.assertTrue(output.contains("testName(data: Data1, queryParams: { testParam1: string; testParam2?: number; }): RestResponse")); + Assertions.assertTrue(output.contains("interface Data1")); + } + @RestController @RequestMapping("/owners/{ownerId}") public static class Controller1 { @@ -488,4 +505,20 @@ public String shouldBeExcluded() { } } + public class CustomRestMethodBuilder implements RestMethodBuilder{ + + @Override + public RestMethodModel build(Class originClass, String name, Type returnType, + Method originalMethod, Class rootResource, String httpMethod, + String path, List pathParams, List queryParams, + MethodParameterModel entityParam, List comments) { + + RestQueryParam.Single queryParam1 = new RestQueryParam.Single(new MethodParameterModel("testParam1", String.class), true); + RestQueryParam.Single queryParam2 = new RestQueryParam.Single(new MethodParameterModel("testParam2", Integer.class), false); + + return new RestMethodModel(originClass, "testName", returnType, originalMethod, rootResource, httpMethod, path, + pathParams, Arrays.asList(queryParam1, queryParam2), entityParam, comments); + } + } + }