A lightweight graphql calculation engine, which is used to alter execution behavior of query.
π English Documentation | π δΈζζζ‘£
GraphQL Calculator is a lightweight graphql query calculation engine. Based on directive, graphql-calculator provide graphql query with the ability of field transform, field skip and orchestration.
The name and semantics of directives are inspired from the java.util.stream.Stream
, so they are easy to understand and use.
The argument of directive must be static string value. query variables can't be used, because variable will make the semantics and validity of query ambiguous.
@skip
and @include
, and the value of expression decided whether skip the operation of field-fetched;implementation group: 'com.graphql-java-calculator', name: 'graphql-java-calculator', version: {version}
GraphQLSource
Create GraphQLSource
by DefaultGraphQLSourceBuilder
, which including wrapped graphql schema and graphql execution engine GraphQL
.
You can config script engine through Config
, and the default script engine is [aviatorscript
](https://github.com/killme2008/aviatorscript.
Validate the query by Validator
, which including graphql syntax validation.
It is recommend to create PreparsedDocumentProvider
by implementing CalculatorDocumentCachedProvider
.
More details in Example.java
and examples.graphql
Note: If customized async DataFetcher
is used, then make it implements AsyncDataFetcherInterface
,
and return the wrapped DataFetcher
and the Executor
used in async DataFetcher
by override method.
If graphql.Schema.Asyncdatafetcher
of 'graphql-java' is used, this operation can be ignored.
There are all the definitions of calculation directives:
# determine whether the field would be skipped by expression, taking query variable as script arguments
directive @skipBy(predicate: String!) on FIELD | INLINE_FRAGMENT | FRAGMENT_SPREAD
# determine whether the field would be queried by expression, taking query variable as script arguments.
directive @includeBy(predicate: String!) on FIELD | INLINE_FRAGMENT | FRAGMENT_SPREAD
# reset the annotated field by '@mock', just work for primitive type. it's easily replaced by '@map(expression)'
directive @mock(value: String!) on FIELD
# filter the list by predicate
directive @filter(predicate: String!) on FIELD
# returns a list consisting of the distinct elements of the annotated list
directive @distinct(comparator:String) on FIELD
# sort the list by specified key
directive @sort(key: String!,reversed: Boolean = false) on FIELD
# sort the list by expression result
directive @sortBy(comparator: String!, reversed: Boolean = false) on FIELD
# transform the field value by expression
directive @map(mapper:String!, dependencySources:[String!]) on FIELD
# hold the fetched value which can be acquired by calculation directives, the name is unique in query.
directive @fetchSource(name: String!, sourceConvert:String) on FIELD
# transform the argument by expression
directive @argumentTransform(argumentName:String!, operateType:ParamTransformType, expression:String, dependencySources:[String!]) repeatable on FIELD
enum ParamTransformType{
MAP
FILTER
LIST_MAP
}
Assume we have type definition as in examples.graphql, Here are some examples on how to use GraphQL Calculator on graphql query.
query basicMapValue($userIds:[Int]){
userInfoList(userIds:$userIds)
{
id
age
firstName
lastName
fullName: stringHolder @map(mapper: "firstName + lastName")
}
}
query filterUserByAge($userId:[Int]){
userInfoList(userIds: $userId)
@filter(predicate: "age>=18")
{
userId
age
firstName
lastName
}
}
query passFetchedValueToAnotherFieldArgument($itemIds:[Int]){
commodity{
itemList(itemIds: $itemIds){
# save sellerId as List<Long> with unique name "sellerIdList"
sellerId @fetchSource(name: "sellerIdList")
name
saleAmount
salePrice
}
}
consumer{
userInfoList(userIds: 1)
# transform the argument of "userInfoList" named "userIds" according to expression "sellerIdList" and expression argument,
# which mean replace userIds value by source named "sellerIdList"
@argumentTransform(argumentName: "userIds",
operateType: MAP,
expression: "sellerIdList",
dependencySources: ["sellerIdList"]
){
userId
name
age
}
}
}
This project is released under version 2.0 of the Apache License.