在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):muuki88/sbt-graphql开源软件地址(OpenSource Url):https://github.com/muuki88/sbt-graphql开源编程语言(OpenSource Language):Scala 100.0%开源软件介绍(OpenSource Introduction):sbt-graphql
sbt plugin to generate and validate graphql schemas written with Sangria. GoalsThis plugin is intended for testing pipelines that ensure that your graphql schema and queries are intact and match. You should also be able to compare it with another schema, e.g. the production schema, to avoid breaking changes. FeaturesAll features are based on the excellent Sangria GraphQL library
Examples for client-side code generation and for schema validation can be found in the Note: Generating server-side code from a schema is currently not supported. Look here for sangria-based solutions. UsageAdd this to your addSbtPlugin("de.mukis" % "sbt-graphql" % "<version>") In your enablePlugins(GraphQLSchemaPlugin, GraphQLQueryPlugin)
libraryDependencies ++= Seq(
"org.sangria-graphql" %% "sangria" % "1.4.2"
) Schema generationThe schema is generated by accessing the application code via a generated main class that renders
your schema. The main class accesses your code via a small code snippet defined in Example:
My schema is defined in an object called graphqlSchemaSnippet := "example.ProductSchema.schema" Now you can generate a schema with $ sbt graphqlSchemaGen You can configure the output directory in your target in graphqlSchemaGen := target.value / "graphql-build-schema" Schema definitionsYour build can contain multiple schemas. They are stored in the There is already one schemas predefined. The name in graphqlSchemaGen := "local-build" Add a schemaSchemas are defined via a
You can also define a schema from a graphqlSchemas += GraphQLSchema(
"sangria-example",
"staging schema at http://try.sangria-graphql.org/graphql",
Def.task(
GraphQLSchemaLoader
.fromIntrospection("http://try.sangria-graphql.org/graphql", streams.value.log)
.loadSchema()
).taskValue
)
// from a Json file
graphqlProductionSchema := GraphQLSchemaLoader
.fromFile((resourceManaged in Compile).value / "prod.json")
.loadSchema()
// from a GraphQL file
graphqlProductionSchema := GraphQLSchemaLoader
.fromFile((resourceManaged in Compile).value / "prod.graphql")
.loadSchema()
// from a graphql endpoint via introspection
graphqlProductionSchema := GraphQLSchemaLoader
.fromIntrospection("http://prod.your-graphql.net/graphql", streams.value.log)
.withHeaders("X-Api-Version" -> "1", "X-Api-Key" -> "4198ab84-e992-42b0-8742-225ed15a781e")
.loadSchema()
// from a graphql endpoint via introspection with post request
graphqlProductionSchema := GraphQLSchemaLoader
.fromIntrospection("http://prod.your-graphql.net/graphql", streams.value.log)
.withPost()
.loadSchema() Schema comparisonSangria provides an API for comparing two Schemas. A change can be breaking or not.
The graphqlValidateSchema <old schema> <new schema> ExampleYou can compare the $ sbt
> graphqlValidateSchema build prod Schema renderingYou can render every schema with the > graphqlRenderSchema build This will render the You can configure the target directory with target in graphqlRenderSchema := target.value / "graphql-schema" Schema release notes
$ sbt
> graphqlReleaseNotes <old schema> <new schema> ExampleYou can create release notes for the $ sbt
> graphqlReleaseNotes build prod Code GenerationA graphql query result is usually modelled with case classes, enums and traits.
Writing these query result classes is tedious and error prone. A lot of insipration came from apollo codegen. Make sure to check it out for scalajs, typescript and plain javascript projects. ConfigurationEnable the code generation plugin in your enablePlugins(GraphQLCodegenPlugin) You need a graphql schema for the code generation. The schema is necessary
to figure out the types for each query field. By default, the codegen plugin
looks for a schema at We recommend to configure a graphql schema in your // add a 'starwars' schema to the `graphqlSchemas` list
graphqlSchemas += GraphQLSchema(
"starwars",
"starwars schema at http://try.sangria-graphql.org/graphql",
Def.task(
GraphQLSchemaLoader
.fromIntrospection("http://try.sangria-graphql.org/graphql", streams.value.log)
.withHeaders("User-Agent" -> s"sbt-graphql/${version.value}")
.loadSchema()
).taskValue
)
// use this schema for the code generation
graphqlCodegenSchema := graphqlRenderSchema.toTask("starwars").value The By default, all SettingsYou can configure the output in various ways
JSON supportThe common serialization format for graphql results and input variables is JSON. sbt-graphql supports JSON decoder/encoder code generation. Supported JSON libraries and codegen styles
In your graphqlCodegenJson := JsonCodec.Circe Scalar typesThe code generation doesn't know about your additional scalar types.
sbt-graphql provides a setting Example:
which is represented as graphqlCodegenImports += "java.time.ZoneDateTime" Code Gen directiveThe plugin provides a Example - skip code generationTo skip the code generation and provide your own type. query CodeGenHeroNameQuery {
hero @codeGen(useType: "Hero") {
name
}
} You can also use the fully qualified class name to avoid clashes query CodeGenHeroNameQuery {
hero @codeGen(useType: "com.example.model.Hero") {
name
}
} Difference to scalar typesUse the code gen directive, when the code generation doesn't generate the code you need. This can have multiple reasons
The code gen directive is intended to work on object types. Scalar types represent the core building blocks of
your graphql schema like Magic #importsThis is a feature tries to replicate the apollographql/graphql-tag loader.js feature, which enables including (or actually inlining) partials into a graphql query with magic comments. ExplainedThe syntax is straightforward #import path/to/included.fragment.graphql The fragment files should be named liked this
There is a The resolving of paths works like this
ExampleI have a file fragment CharacterInfo on Character {
name
} And the actual graphql query file query HeroFragmentQuery {
hero {
...CharacterInfo
}
human(id: "Lea") {
homePlanet
...CharacterInfo
}
}
#import fragments/CharacterInfo.fragment.graphql Codegen style ApolloAs the name suggests the output is similar to the one in apollo codegen. A basic trait GraphQLQuery {
type Document
type Variables
type Data
} The For each query a new object is created with the name of the query. Example: query HeroNameQuery {
hero {
name
}
} Generated code: package graphql.codegen
import graphql.codegen.GraphQLQuery
import sangria.macros._
object HeroNameQuery {
object HeroNameQuery extends GraphQLQuery {
val document: sangria.ast.Document = graphql"""query HeroNameQuery {
hero {
name
}
}"""
case class Variables()
case class Data(hero: Hero)
case class Hero(name: Option[String])
}
} Interfaces, types and aliasesThe object types {
// contains all defined types like enums and aliases
}
// all used fragments and interfaces are generated as traits here Use case
You can now do this by defining a LimitationsYou need to copy the fragments into every You cannot nest fragments. The code generation isn't capable of naming the nested data structure. This means that you need create fragments for every nesting. Invalid query HeroNestedFragmentQuery {
hero {
...CharacterInfo
}
human(id: "Lea") {
...CharacterInfo
}
}
# This will generate code that may compile, but is not usable
fragment CharacterInfo on Character {
name
friends {
name
}
} correct query HeroNestedFragmentQuery {
hero {
...CharacterInfo
}
human(id: "Lea") {
...CharacterInfo
}
}
# create a fragment for the nested query
fragment CharacterFriends on Character {
name
}
fragment CharacterInfo on Character {
name
friends {
...CharacterFriends
}
} Codegen Style SangriaThis style generates one object with a specified Example: query HeroNameQuery {
hero {
name
}
} Generated code: object HeroNameQueryApi {
case class HeroNameQuery(hero: HeroNameQueryApi.HeroNameQuery.Hero)
object HeroNameQuery {
case class HeroNameQueryVariables()
case class Hero(name: Option[String])
}
} Query validationThe query validation uses the schema generated with To validate your graphql files run sbt graphqlValidateQueries You can change the source directory for your graphql queries with this line in
your sourceDirectory in (Test, graphqlValidateQueries) := file("path/to/graphql") DevelopingTest projectYou can try out your changes immediately with the $ cd test-project
sbt If you change code in the plugin you need to ReleasingPush a tag The |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论