Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/sbt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ addSbtPlugin("io.github.kobylynskyi" % "sbt-graphql-java-codegen" % "1.6.0-NOT-Y
| `graphqlGenerateToString` | Boolean | False | Specifies whether generated model classes should have toString method defined. |
| `graphqlModelNamePrefix` | String | Empty | Sets the prefix for GraphQL model classes (type, input, interface, enum, union). |
| `graphqlModelNameSuffix` | String | Empty | Sets the suffix for GraphQL model classes (type, input, interface, enum, union). |
| `graphqlModelValidationAnnotation` | String | @javax.validation.<br>constraints.NotNull | Annotation for mandatory (NonNull) fields. Can be null/empty. |
| `graphqlModelValidationAnnotation` | String | @javax.validation.<br>constraints.NotNull | Annotation for mandatory (NonNull) fields. Can be None/empty. |
| `graphqlGenerateParameterizedFieldsResolvers` | Boolean | True | If true, then generate separate `Resolver` interface for parametrized fields. If false, then add field to the type definition and ignore field parameters. |
| `graphqlGenerateExtensionFieldsResolvers` | Boolean | False | Specifies whether all fields in extensions (<code>extend type</code> and <code>extend interface</code>) should be present in Resolver interface instead of the type class itself. |
| `graphqlGenerateRequests` | Boolean | False | Specifies whether client-side classes should be generated for each query, mutation and subscription. This includes: `Request` class (contains input data) and `ResponseProjection` class (contains response fields). |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,68 +17,54 @@ object GraphQLCodegenSbtPlugin extends AutoPlugin {
// configuration points, like the built-in `version`, `libraryDependencies`, or `compile`
val graphql = taskKey[Seq[File]]("Generate GraphQL code.")
val graphqlSchemaPaths = settingKey[Seq[String]]("Locations of GraphQL schemas.")
val graphqlModelNamePrefix = settingKey[String]("Suffix to append to the model class names.")
val graphqlModelNameSuffix = settingKey[String]("Suffix to append to the model class names.")
val graphqlApiPackageName = settingKey[String]("Java package to use when generating the API classes.")
val graphqlModelPackageName = settingKey[String]("Java package to use when generating the model classes.")
val graphqlModelNamePrefix = settingKey[Option[String]]("Suffix to append to the model class names.")
val graphqlModelNameSuffix = settingKey[Option[String]]("Suffix to append to the model class names.")
val graphqlApiPackageName = settingKey[Option[String]]("Java package to use when generating the API classes.")
val graphqlModelPackageName = settingKey[Option[String]]("Java package to use when generating the model classes.")
val graphqlGenerateBuilder = settingKey[Boolean]("Specifies whether generated model classes should have builder.")
val graphqlGenerateApis = settingKey[Boolean]("Specifies whether api classes should be generated as well as model classes.")
val graphqlGenerateEqualsAndHashCode = settingKey[Boolean]("Specifies whether generated model classes should have equals and hashCode methods defined.")
val graphqlGenerateToString = settingKey[Boolean]("Specifies whether generated model classes should have toString method defined.")
val graphqlGenerateAsyncApi = settingKey[Boolean]("If true, then wrap type into java.util.concurrent.CompletableFuture or subscriptionReturnType")
val graphqlModelValidationAnnotation = settingKey[String]("Annotation for mandatory (NonNull) fields. Can be null/empty.")
val graphqlModelValidationAnnotation = settingKey[Option[String]]("Annotation for mandatory (NonNull) fields. Can be None/empty.")
val graphqlGenerateParameterizedFieldsResolvers = settingKey[Boolean]("If true, then generate separate Resolver interface for parametrized fields. If false, then add field to the type definition and ignore field parameters.")
val graphqlGenerateExtensionFieldsResolvers = settingKey[Boolean]("Specifies whether all fields in extensions (extend type and extend interface) should be present in Resolver interface instead of the type class itself.")
val graphqlGenerateDataFetchingEnvArgInApis = settingKey[Boolean]("If true, then graphql.schema.DataFetchingEnvironment env will be added as a last argument to all methods of root type resolvers and field resolvers.")
val graphqlGenerateRequests = settingKey[Boolean]("Specifies whether client-side classes should be generated for each query, mutation and subscription. This includes: Request class (contains input data) and ResponseProjection class (contains response fields).")
val graphqlRequestSuffix = settingKey[Option[String]]("Specifies whether client-side classes should be generated for each query, mutation and subscription. This includes: Request class (contains input data) and ResponseProjection class (contains response fields).")
val graphqlResponseProjectionSuffix = settingKey[Option[String]]("Specifies whether client-side classes should be generated for each query, mutation and subscription. This includes: Request class (contains input data) and ResponseProjection class (contains response fields).")

val graphqlRequestSuffix = settingKey[String]("Specifies whether client-side classes should be generated for each query, mutation and subscription. This includes: Request class (contains input data) and ResponseProjection class (contains response fields).")
val graphqlResponseProjectionSuffix = settingKey[String]("Specifies whether client-side classes should be generated for each query, mutation and subscription. This includes: Request class (contains input data) and ResponseProjection class (contains response fields).")

// default values for the tasks and settings
lazy val baseGraphQLSettings: Seq[Def.Setting[_]] = Seq(
graphql := {
Codegen(
(sourceManaged in graphql).value,
(graphqlSchemaPaths in graphql).value,
sourceDirectory.value / "resources",
(graphqlModelNamePrefix in graphql).value,
(graphqlModelNameSuffix in graphql).value,
(graphqlApiPackageName in graphql).value,
(graphqlModelPackageName in graphql).value,
(graphqlGenerateBuilder in graphql).value,
(graphqlGenerateApis in graphql).value,
(graphqlModelValidationAnnotation in graphql).value,
(graphqlGenerateEqualsAndHashCode in graphql).value,
(graphqlGenerateToString in graphql).value,
(graphqlGenerateAsyncApi in graphql).value,
(graphqlGenerateParameterizedFieldsResolvers in graphql).value,
(graphqlGenerateExtensionFieldsResolvers in graphql).value,
(graphqlGenerateDataFetchingEnvArgInApis in graphql).value,
(graphqlGenerateRequests in graphql).value,
(graphqlRequestSuffix in graphql).value,
(graphqlResponseProjectionSuffix in graphql).value
graphqlSchemaPaths.value,
Some(sourceDirectory.value / "resources"),
graphqlModelNamePrefix.value,
graphqlModelNameSuffix.value,
graphqlApiPackageName.value,
graphqlModelPackageName.value,
graphqlGenerateBuilder.value,
graphqlGenerateApis.value,
graphqlModelValidationAnnotation.value,
graphqlGenerateEqualsAndHashCode.value,
graphqlGenerateToString.value,
graphqlGenerateAsyncApi.value,
graphqlGenerateParameterizedFieldsResolvers.value,
graphqlGenerateExtensionFieldsResolvers.value,
graphqlGenerateDataFetchingEnvArgInApis.value,
graphqlGenerateRequests.value,
graphqlRequestSuffix.value,
graphqlResponseProjectionSuffix.value
)
},
graphqlSchemaPaths in graphql := Seq((sourceDirectory.value / "resources/schema.graphql").getCanonicalPath),
graphqlGenerateBuilder in graphql := DefaultMappingConfigValues.DEFAULT_BUILDER,
graphqlGenerateApis in graphql := DefaultMappingConfigValues.DEFAULT_GENERATE_APIS,
graphqlModelValidationAnnotation in graphql := DefaultMappingConfigValues.DEFAULT_VALIDATION_ANNOTATION,
graphqlGenerateEqualsAndHashCode in graphql := DefaultMappingConfigValues.DEFAULT_EQUALS_AND_HASHCODE,
graphqlGenerateToString in graphql := DefaultMappingConfigValues.DEFAULT_TO_STRING,
graphqlGenerateAsyncApi in graphql := DefaultMappingConfigValues.DEFAULT_GENERATE_ASYNC_APIS,
graphqlGenerateParameterizedFieldsResolvers in graphql := DefaultMappingConfigValues.DEFAULT_GENERATE_PARAMETERIZED_FIELDS_RESOLVERS,
graphqlGenerateExtensionFieldsResolvers in graphql := DefaultMappingConfigValues.DEFAULT_GENERATE_EXTENSION_FIELDS_RESOLVERS,
graphqlGenerateDataFetchingEnvArgInApis in graphql := DefaultMappingConfigValues.DEFAULT_GENERATE_DATA_FETCHING_ENV,
graphqlGenerateRequests in graphql := DefaultMappingConfigValues.DEFAULT_GENERATE_REQUESTS,
graphqlRequestSuffix in graphql := DefaultMappingConfigValues.DEFAULT_REQUEST_SUFFIX,
graphqlResponseProjectionSuffix in graphql := DefaultMappingConfigValues.DEFAULT_RESPONSE_PROJECTION_SUFFIX,
graphqlSchemaPaths := Seq((sourceDirectory.value / "resources/schema.graphql").getCanonicalPath),

// This follows the output directory structure recommended by sbt team
// https://github.com/sbt/sbt/issues/1664#issuecomment-213057686
sourceManaged in graphql := crossTarget.value / "src_managed_graphql",
managedSourceDirectories in Compile += (sourceManaged in graphql).value,
Compile / sourceGenerators += graphql.taskValue
managedSourceDirectories += (sourceManaged in graphql).value,
sourceGenerators += graphql.taskValue
)
}

Expand All @@ -88,63 +74,84 @@ object GraphQLCodegenSbtPlugin extends AutoPlugin {
// This plugin is automatically enabled for projects which are JvmPlugin.
override def trigger = allRequirements

override val globalSettings = Seq(
graphqlModelNamePrefix := None,
graphqlModelNameSuffix := None,
graphqlApiPackageName := None,
graphqlModelPackageName := None,
graphqlGenerateBuilder := DefaultMappingConfigValues.DEFAULT_BUILDER,
graphqlGenerateApis := DefaultMappingConfigValues.DEFAULT_GENERATE_APIS,
graphqlModelValidationAnnotation := Some(DefaultMappingConfigValues.DEFAULT_VALIDATION_ANNOTATION),
graphqlGenerateEqualsAndHashCode := DefaultMappingConfigValues.DEFAULT_EQUALS_AND_HASHCODE,
graphqlGenerateToString := DefaultMappingConfigValues.DEFAULT_TO_STRING,
graphqlGenerateAsyncApi := DefaultMappingConfigValues.DEFAULT_GENERATE_ASYNC_APIS,
graphqlGenerateParameterizedFieldsResolvers := DefaultMappingConfigValues.DEFAULT_GENERATE_PARAMETERIZED_FIELDS_RESOLVERS,
graphqlGenerateExtensionFieldsResolvers := DefaultMappingConfigValues.DEFAULT_GENERATE_EXTENSION_FIELDS_RESOLVERS,
graphqlGenerateDataFetchingEnvArgInApis := DefaultMappingConfigValues.DEFAULT_GENERATE_DATA_FETCHING_ENV,
graphqlGenerateRequests := DefaultMappingConfigValues.DEFAULT_GENERATE_REQUESTS,
graphqlRequestSuffix := Some(DefaultMappingConfigValues.DEFAULT_REQUEST_SUFFIX),
graphqlResponseProjectionSuffix := Some(DefaultMappingConfigValues.DEFAULT_RESPONSE_PROJECTION_SUFFIX)
)

// a group of settings that are automatically added to projects.
override val projectSettings =
inConfig(Compile)(baseGraphQLSettings) ++
inConfig(Test)(baseGraphQLSettings)
inConfig(Compile)(baseGraphQLSettings)
// For now we skip compiling schemas under src/test because the plugin will
// fail if no schemas are found at the expected location
// ++ inConfig(Test)(baseGraphQLSettings)
}

object Codegen {
def apply(
outputDir: File,
graphqlSchemaPaths: Seq[String],
schemasRootDir: File,
graphqlModelNamePrefix: String,
graphqlModelNameSuffix: String,
graphqlApiPackageName: String,
graphqlModelPackageName: String,
schemasRootDir: Option[File],
graphqlModelNamePrefix: Option[String],
graphqlModelNameSuffix: Option[String],
graphqlApiPackageName: Option[String],
graphqlModelPackageName: Option[String],
graphqlGenerateBuilder: Boolean,
graphqlGenerateApis: Boolean,
graphqlModelValidationAnnotation: String,
graphqlModelValidationAnnotation: Option[String],
graphqlGenerateEqualsAndHashCode: Boolean,
graphqlGenerateToString: Boolean,
graphqlGenerateAsyncApi: Boolean,
graphqlGenerateParameterizedFieldsResolvers: Boolean,
graphqlGenerateExtensionFieldsResolvers: Boolean,
graphqlGenerateDataFetchingEnvArgInApis: Boolean,
graphqlGenerateRequests: Boolean,
graphqlRequestSuffix: String,
graphqlResponseProjectionSuffix: String): Seq[File] = {
graphqlRequestSuffix: Option[String],
graphqlResponseProjectionSuffix: Option[String]): Seq[File] = {

val mappingConfig = new MappingConfig();
mappingConfig.setModelNamePrefix(graphqlModelNamePrefix);
mappingConfig.setModelNameSuffix(graphqlModelNameSuffix);
mappingConfig.setApiPackageName(graphqlApiPackageName);
mappingConfig.setModelPackageName(graphqlModelPackageName);
mappingConfig.setModelNamePrefix(graphqlModelNamePrefix.getOrElse(null));
mappingConfig.setModelNameSuffix(graphqlModelNameSuffix.getOrElse(null));
mappingConfig.setApiPackageName(graphqlApiPackageName.getOrElse(null));
mappingConfig.setModelPackageName(graphqlModelPackageName.getOrElse(null));
mappingConfig.setGenerateBuilder(graphqlGenerateBuilder);
mappingConfig.setGenerateApis(graphqlGenerateApis);
mappingConfig.setModelValidationAnnotation(graphqlModelValidationAnnotation);
mappingConfig.setModelValidationAnnotation(graphqlModelValidationAnnotation.getOrElse(null));
mappingConfig.setGenerateEqualsAndHashCode(graphqlGenerateEqualsAndHashCode);
mappingConfig.setGenerateToString(graphqlGenerateToString);
mappingConfig.setGenerateAsyncApi(graphqlGenerateAsyncApi);
mappingConfig.setGenerateParameterizedFieldsResolvers(graphqlGenerateParameterizedFieldsResolvers);
mappingConfig.setGenerateExtensionFieldsResolvers(graphqlGenerateExtensionFieldsResolvers);
mappingConfig.setGenerateDataFetchingEnvironmentArgumentInApis(graphqlGenerateDataFetchingEnvArgInApis);
mappingConfig.setGenerateRequests(graphqlGenerateRequests);
mappingConfig.setRequestSuffix(graphqlRequestSuffix);
mappingConfig.setResponseProjectionSuffix(graphqlResponseProjectionSuffix);
mappingConfig.setRequestSuffix(graphqlRequestSuffix.getOrElse(null));
mappingConfig.setResponseProjectionSuffix(graphqlResponseProjectionSuffix.getOrElse(null));

val mappingConfigSupplier = null;
val generatedSources = new GraphQLCodegen(getSchemas(graphqlSchemaPaths, schemasRootDir), outputDir, mappingConfig, mappingConfigSupplier).generate();

JavaConverters.collectionAsScalaIterableConverter(generatedSources).asScala.toSeq
}

private def getSchemas(graphqlSchemaPaths: Seq[String], schemasRootDir: File): java.util.List[String] = {
private def getSchemas(graphqlSchemaPaths: Seq[String], schemasRootDir: Option[File]): java.util.List[String] = {
if (!graphqlSchemaPaths.isEmpty) {
return JavaConverters.seqAsJavaList(graphqlSchemaPaths);
}
val finder = new SchemaFinder(schemasRootDir.toPath);
val finder = new SchemaFinder(schemasRootDir.get.toPath);
return finder.findSchemas();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
lazy val root = (project in file("."))
.settings(
version := "0.1",
scalaVersion := "2.13.2",
libraryDependencies += "javax.validation" % "validation-api" % "2.0.1.Final",
graphqlApiPackageName := Some("io.github.kobylynskyi.graphql.test.api"),
graphqlModelPackageName := Some("io.github.kobylynskyi.graphql.test.model")
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
sys.props.get("plugin.version") match {
case Some(x) => addSbtPlugin("io.github.kobylynskyi" % "sbt-graphql-java-codegen" % x)
case _ => sys.error("""|The system property 'plugin.version' is not defined.
|Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#
# Schemas must have at least a query root type
#
schema {
query: Query
}

# This is the type that will be the root of our query, and the
# entry point into our schema.
type Query {
getPosts: [Post]

getUser(
id : ID!
): User

getPost(
id: ID!
): Post
}

type Post {
id: ID!
title: String!
# Content if provided by author
content: String
# The URL if this is external content
url: String
author: User
}

type User {
id: ID!
username: String!
email: String!
posts: [Post]
}
3 changes: 3 additions & 0 deletions plugins/sbt/src/sbt-test/sbt-graphql-java-codegen/simple/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# check if the file gets created
> compile
$ exists target/scala-2.13/src_managed_graphql/io/github/kobylynskyi/graphql/test/model/User.java