diff --git a/package-lock.json b/package-lock.json
index 5bfbdc5133..8693cfc2bc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1130,6 +1130,10 @@
"resolved": "packages/ts/generator-typescript-plugin-push",
"link": true
},
+ "node_modules/@hilla/generator-typescript-plugin-subtypes": {
+ "resolved": "packages/ts/generator-typescript-plugin-subtypes",
+ "link": true
+ },
"node_modules/@hilla/generator-typescript-utils": {
"resolved": "packages/ts/generator-typescript-utils",
"link": true
@@ -20390,6 +20394,78 @@
"url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
}
},
+ "packages/ts/generator-typescript-plugin-subtypes": {
+ "name": "@hilla/generator-typescript-plugin-subtypes",
+ "version": "2.3.0-alpha5",
+ "license": "Apache 2.0",
+ "dependencies": {
+ "@hilla/generator-typescript-utils": "^2.3.0-alpha5",
+ "fast-deep-equal": "^3.1.3",
+ "openapi-types": "^12.1.3",
+ "typescript": "^5.1.6"
+ },
+ "devDependencies": {
+ "@hilla/generator-typescript-core": "^2.3.0-alpha5",
+ "@hilla/generator-typescript-plugin-client": "^2.3.0-alpha5",
+ "@hilla/generator-typescript-plugin-model": "^2.3.0-alpha5",
+ "@types/chai": "^4.3.5",
+ "@types/mocha": "^10.0.1",
+ "@types/node": "^20.5.0",
+ "@types/sinon": "^10.0.16",
+ "@types/sinon-chai": "^3.2.9",
+ "c8": "^8.0.1",
+ "chai": "^4.3.7",
+ "concurrently": "^8.2.0",
+ "copyfiles": "^2.4.1",
+ "mocha": "^10.2.0",
+ "pino": "^8.15.0",
+ "rimraf": "^5.0.1",
+ "sinon": "^15.2.0",
+ "sinon-chai": "^3.7.0",
+ "type-fest": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 16.13"
+ },
+ "peerDependencies": {
+ "@hilla/generator-typescript-core": "^2.3.0-alpha5",
+ "@hilla/generator-typescript-plugin-client": "^2.3.0-alpha5",
+ "@hilla/generator-typescript-plugin-model": "^2.3.0-alpha5"
+ }
+ },
+ "packages/ts/generator-typescript-plugin-subtypes/node_modules/@types/node": {
+ "version": "20.6.3",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.3.tgz",
+ "integrity": "sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA==",
+ "dev": true
+ },
+ "packages/ts/generator-typescript-plugin-subtypes/node_modules/concurrently": {
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.1.tgz",
+ "integrity": "sha512-nVraf3aXOpIcNud5pB9M82p1tynmZkrSGQ1p6X/VY8cJ+2LMVqAgXsJxYYefACSHbTYlm92O1xuhdGTjwoEvbQ==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.2",
+ "date-fns": "^2.30.0",
+ "lodash": "^4.17.21",
+ "rxjs": "^7.8.1",
+ "shell-quote": "^1.8.1",
+ "spawn-command": "0.0.2",
+ "supports-color": "^8.1.1",
+ "tree-kill": "^1.2.2",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "conc": "dist/bin/concurrently.js",
+ "concurrently": "dist/bin/concurrently.js"
+ },
+ "engines": {
+ "node": "^14.13.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
+ }
+ },
"packages/ts/generator-typescript-utils": {
"name": "@hilla/generator-typescript-utils",
"version": "2.3.0-alpha5",
diff --git a/packages/java/engine-core/pom.xml b/packages/java/engine-core/pom.xml
index f814ade206..6a02bb515b 100644
--- a/packages/java/engine-core/pom.xml
+++ b/packages/java/engine-core/pom.xml
@@ -73,6 +73,11 @@
parser-jvm-plugin-nonnull
${project.version}
+
+ dev.hilla
+ parser-jvm-plugin-subtypes
+ ${project.version}
+
dev.hilla
parser-jvm-plugin-model
diff --git a/packages/java/engine-core/src/main/java/dev/hilla/engine/GeneratorConfiguration.java b/packages/java/engine-core/src/main/java/dev/hilla/engine/GeneratorConfiguration.java
index fbd4ce9613..9a5a22d475 100644
--- a/packages/java/engine-core/src/main/java/dev/hilla/engine/GeneratorConfiguration.java
+++ b/packages/java/engine-core/src/main/java/dev/hilla/engine/GeneratorConfiguration.java
@@ -142,7 +142,8 @@ static class PluginsProcessor extends ConfigList.Processor {
new Plugin("@hilla/generator-typescript-plugin-client"),
new Plugin("@hilla/generator-typescript-plugin-barrel"),
new Plugin("@hilla/generator-typescript-plugin-model"),
- new Plugin("@hilla/generator-typescript-plugin-push"));
+ new Plugin("@hilla/generator-typescript-plugin-push"),
+ new Plugin("@hilla/generator-typescript-plugin-subtypes"));
PluginsProcessor() {
super(DEFAULTS);
diff --git a/packages/java/engine-core/src/main/java/dev/hilla/engine/GeneratorProcessor.java b/packages/java/engine-core/src/main/java/dev/hilla/engine/GeneratorProcessor.java
index 64859f1516..47c93aad21 100644
--- a/packages/java/engine-core/src/main/java/dev/hilla/engine/GeneratorProcessor.java
+++ b/packages/java/engine-core/src/main/java/dev/hilla/engine/GeneratorProcessor.java
@@ -25,6 +25,7 @@
@NpmPackage(value = "@hilla/generator-typescript-plugin-barrel", version = "2.3.0-alpha5")
@NpmPackage(value = "@hilla/generator-typescript-plugin-model", version = "2.3.0-alpha5")
@NpmPackage(value = "@hilla/generator-typescript-plugin-push", version = "2.3.0-alpha5")
+@NpmPackage(value = "@hilla/generator-typescript-plugin-subtypes", version = "2.3.0-alpha5")
public final class GeneratorProcessor {
private static final Logger logger = LoggerFactory
.getLogger(GeneratorProcessor.class);
diff --git a/packages/java/engine-core/src/main/java/dev/hilla/engine/ParserConfiguration.java b/packages/java/engine-core/src/main/java/dev/hilla/engine/ParserConfiguration.java
index 10be8827f3..c2d9f0ff70 100644
--- a/packages/java/engine-core/src/main/java/dev/hilla/engine/ParserConfiguration.java
+++ b/packages/java/engine-core/src/main/java/dev/hilla/engine/ParserConfiguration.java
@@ -12,6 +12,7 @@
import dev.hilla.parser.plugins.backbone.BackbonePlugin;
import dev.hilla.parser.plugins.model.ModelPlugin;
import dev.hilla.parser.plugins.nonnull.NonnullPlugin;
+import dev.hilla.parser.plugins.subtypes.SubTypesPlugin;
import dev.hilla.parser.plugins.transfertypes.TransferTypesPlugin;
import dev.hilla.parser.utils.ConfigList;
@@ -188,6 +189,7 @@ static class PluginsProcessor extends ConfigList.Processor {
new Plugin(BackbonePlugin.class.getName()),
new Plugin(TransferTypesPlugin.class.getName()),
new Plugin(NonnullPlugin.class.getName()),
+ new Plugin(SubTypesPlugin.class.getName()),
new Plugin(ModelPlugin.class.getName()));
PluginsProcessor() {
diff --git a/packages/java/parser-jvm-plugin-backbone/src/main/java/dev/hilla/parser/plugins/backbone/EntityPlugin.java b/packages/java/parser-jvm-plugin-backbone/src/main/java/dev/hilla/parser/plugins/backbone/EntityPlugin.java
index a220d525eb..ebe5ea4855 100644
--- a/packages/java/parser-jvm-plugin-backbone/src/main/java/dev/hilla/parser/plugins/backbone/EntityPlugin.java
+++ b/packages/java/parser-jvm-plugin-backbone/src/main/java/dev/hilla/parser/plugins/backbone/EntityPlugin.java
@@ -67,8 +67,8 @@ public NodeDependencies scan(@Nonnull NodeDependencies nodeDependencies) {
Stream.of(EntityNode.of(ref.getClassInfo())));
}
- private void attachSchemaWithNameToOpenApi(Schema> schema, String name,
- OpenAPI openApi) {
+ public static void attachSchemaWithNameToOpenApi(Schema> schema,
+ String name, OpenAPI openApi) {
var components = openApi.getComponents();
if (components == null) {
diff --git a/packages/java/parser-jvm-plugin-subtypes/pom.xml b/packages/java/parser-jvm-plugin-subtypes/pom.xml
new file mode 100644
index 0000000000..81d2e6fee7
--- /dev/null
+++ b/packages/java/parser-jvm-plugin-subtypes/pom.xml
@@ -0,0 +1,58 @@
+
+
+ 4.0.0
+
+
+ dev.hilla
+ hilla-project
+ 2.3-SNAPSHOT
+ ../../../pom.xml
+
+
+ parser-jvm-plugin-subtypes
+ Hilla JVM Parser SubTypes Plugin
+ jar
+
+
+ ${project.parent.basedir}
+
+
+
+
+ dev.hilla
+ parser-jvm-core
+ ${project.version}
+
+
+ com.google.code.findbugs
+ jsr305
+
+
+ io.github.classgraph
+ classgraph
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ dev.hilla
+ parser-jvm-utils
+ ${project.version}
+
+
+ dev.hilla
+ parser-jvm-plugin-backbone
+ ${project.version}
+
+
+ dev.hilla
+ parser-jvm-test-utils
+ ${project.version}
+ test
+
+
+
diff --git a/packages/java/parser-jvm-plugin-subtypes/src/main/java/dev/hilla/parser/plugins/subtypes/SubTypesPlugin.java b/packages/java/parser-jvm-plugin-subtypes/src/main/java/dev/hilla/parser/plugins/subtypes/SubTypesPlugin.java
new file mode 100644
index 0000000000..339228b749
--- /dev/null
+++ b/packages/java/parser-jvm-plugin-subtypes/src/main/java/dev/hilla/parser/plugins/subtypes/SubTypesPlugin.java
@@ -0,0 +1,155 @@
+package dev.hilla.parser.plugins.subtypes;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import dev.hilla.parser.core.AbstractNode;
+import dev.hilla.parser.core.AbstractPlugin;
+import dev.hilla.parser.core.Node;
+import dev.hilla.parser.core.NodeDependencies;
+import dev.hilla.parser.core.NodePath;
+import dev.hilla.parser.core.Plugin;
+import dev.hilla.parser.core.PluginConfiguration;
+import dev.hilla.parser.models.ClassInfoModel;
+import dev.hilla.parser.models.ClassRefSignatureModel;
+import dev.hilla.parser.plugins.backbone.BackbonePlugin;
+import dev.hilla.parser.plugins.backbone.EntityPlugin;
+import dev.hilla.parser.plugins.backbone.nodes.EntityNode;
+import dev.hilla.parser.plugins.backbone.nodes.TypedNode;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.media.ComposedSchema;
+import io.swagger.v3.oas.models.media.ObjectSchema;
+import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.media.StringSchema;
+
+import javax.annotation.Nonnull;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+/**
+ * This plugin adds support for {@code @JsonTypeInfo} and {@code @JsonSubTypes}.
+ */
+public final class SubTypesPlugin extends AbstractPlugin {
+ @Override
+ public void enter(NodePath> nodePath) {
+ }
+
+ @Override
+ public void exit(NodePath> nodePath) {
+ // deal with the union nodes, which does not correspond to an existing
+ // class, but express the union of all the @JsonSubTypes
+ if (nodePath.getNode() instanceof UnionNode) {
+ var unionNode = (UnionNode) nodePath.getNode();
+ var cls = (Class>) unionNode.getSource().get();
+
+ // verify that the class has a @JsonTypeInfo annotation
+ // and then add all the @JsonSubTypes to the schema as a `oneOf`
+ if (cls.getAnnotationsByType(JsonTypeInfo.class).length > 0) {
+ var schema = (Schema>) unionNode.getTarget();
+ getJsonSubTypes(cls).map(JsonSubTypes.Type::value)
+ .forEach(c -> {
+ schema.addOneOfItem(new Schema