-
Notifications
You must be signed in to change notification settings - Fork 362
Client Generation - Allow schema to be on the classpath #1136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Client Generation - Allow schema to be on the classpath #1136
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for raising this.
@@ -32,7 +37,7 @@ fun generateClient( | |||
allowDeprecated: Boolean = false, | |||
customScalarsMap: List<GraphQLScalar> = emptyList(), | |||
serializer: GraphQLSerializer = GraphQLSerializer.JACKSON, | |||
schema: File, | |||
schema: String, // this is the file location, not the contents |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets rename this field to schemaPath: String
and drop the comment
|
||
private fun getSchemaReader(schemaPath: String): Reader = | ||
if (schemaPath.startsWith("classpath://")) { | ||
val resource = object {}.javaClass.getResource(URI(schemaPath).path) ?: throw RuntimeException("specified GraphQL schema not found, $schemaPath") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think anonymous objects like this might be throwing some detekt violations -> instead lets move the logic of reading from classpath to the GraphQLClientGenerator
(i.e. change its constructor from accepting type registry to a path and initialize type registry in init block)
private val graphQLSchema: TypeDefinitionRegistry
init {
graphQLSchema = parseSchema(schemaPath)
}
private fun parseSchema(path: String): TypeDefinitionRegistry {
val schemaFile = File(path)
return if (schemaFile.isFile) {
SchemaParser().parse(schemaFile)
} else {
val schemaInputStream = this.javaClass.classLoader.getResourceAsStream(path) ?: throw RuntimeException("specified schema file=$path does not exist")
SchemaParser().parse(schemaInputStream)
}
}
we'll need some unit tests around this
val generator = GraphQLClientGenerator(graphQLSchema, config) | ||
return generator.generate(queries) | ||
} | ||
|
||
private fun getSchemaReader(schemaPath: String): Reader = | ||
if (schemaPath.startsWith("classpath://")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
classpath://
is not a valid URL protocol so we should not code against this (yes Spring supports it but it is non-standard)
val graphQLSchemaFile = schemaFile ?: File(project.build.directory, "schema.graphql") | ||
validateGraphQLSchemaExists(graphQLSchemaFile) | ||
|
||
val schemaPath = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can rewrite this as
val schemaPath = | |
val schemaPath = schemaFile ?: File(project.build.directory, "schema.graphql").path |
which avoids the !!
@@ -66,7 +66,7 @@ abstract class AbstractGenerateClientTask : DefaultTask() { | |||
*/ | |||
@InputFile | |||
@Optional | |||
val schemaFile: RegularFileProperty = project.objects.fileProperty() | |||
val schemaFile: Property<String> = project.objects.property(String::class.java) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there already is schemaFileName
property for that use case, this should remain a RegularFileProperty
@@ -147,13 +147,10 @@ abstract class AbstractGenerateClientTask : DefaultTask() { | |||
logger.debug("generating GraphQL client") | |||
|
|||
val graphQLSchema = when { | |||
schemaFile.isPresent -> schemaFile.get().asFile | |||
schemaFileName.isPresent -> File(schemaFileName.get()) | |||
schemaFile.isPresent -> schemaFile.get() as String |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets rename the enclosing variable graphQLSchema
-> graphQLSchemaPath
@@ -37,7 +37,7 @@ interface GenerateClientParameters : WorkParameters { | |||
/** Type of JSON serializer that will be used to generate the data classes. */ | |||
val serializer: Property<GraphQLSerializer> | |||
/** GraphQL schema file that will be used to generate client code. */ | |||
val schemaFile: Property<File> | |||
val schemaFile: Property<String> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets also update javadoc to reflect this is a path to a schema file
val schemaFile: Property<String> | |
val schemaPath: Property<String> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we also add a unit test for GraphQLClientGenerator
to verify it will blow up with the exception when invalid path is specified?
@@ -32,7 +31,7 @@ fun generateClient( | |||
allowDeprecated: Boolean = false, | |||
customScalarsMap: List<GraphQLScalar> = emptyList(), | |||
serializer: GraphQLSerializer = GraphQLSerializer.JACKSON, | |||
schema: File, | |||
schemaPath: String, // this is the file location, not the contents |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets remove the comment as it is unnecessary
schemaPath: String, // this is the file location, not the contents | |
schemaPath: String, |
SchemaParser().parse(schemaFileStream) | ||
} | ||
} | ||
internal fun testSchema(): String = "testSchema.graphql" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since this is a constant string lets change it to
internal fun testSchema(): String = "testSchema.graphql" | |
internal const val TEST_SCHEMA = "testSchema.graphql" |
@@ -104,15 +104,15 @@ class GraphQLGradlePlugin : Plugin<Project> { | |||
introspectSchemaTask.headers.convention(project.provider { extension.clientExtension.headers }) | |||
introspectSchemaTask.timeoutConfig.convention(project.provider { extension.clientExtension.timeoutConfig }) | |||
generateClientTask.dependsOn(introspectSchemaTask.path) | |||
generateClientTask.schemaFile.convention(introspectSchemaTask.outputFile) | |||
generateClientTask.schemaFile.convention(introspectSchemaTask.outputFile.get()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets revert changes in this file as we should rely on the provider
return if (schemaFile.isFile) { | ||
SchemaParser().parse(schemaFile) | ||
} else { | ||
val schemaInputStream = this.javaClass.classLoader.getResourceAsStream(path) ?: throw RuntimeException("specified schema file=$path does not exist") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets extract this exception to explicit SchemaUnavailableException
(or something like that) under com.expediagroup.graphql.plugin.client.generator.exceptions
I put the test next to the parameterized IT test, hopefully that makes sense. Thanks for being so responsive, it has been a pleasure contributing this! learned a few things as well along the way. One thing is the user no longer needs to specify classpath:// ; not sure if we should require that on the 2nd path; what do you think? |
Nah, current logic of just checking if it is a file and/or resource on classpath should be fine. We could technically go fancy with support for URLs (so you could point to a http resource) but that might be an overkill. |
…#1136) * Client Generation - Allow schema SDL to be on the classpath * Suggestions and Refactors * Minor touchup * More improvements to the code, remove redundant edits
📝 Description
Simply allow loading the schema file from your classpath, this allows you to include a maven dependency that stores your graphql SDLs as a package.
I would love to understand how to test this for Gradle as well since it changed, I have tested for maven only so far!
Feedback appreciated :)
🔗 Related Issues