Skip to content

Commit

Permalink
Added alias support for queries and mutations (#26)
Browse files Browse the repository at this point in the history
* Fix escaped string array (#6)

* Update Spek version

* Fix print wrong escaped character, Fix #4

* Rewrite the GraphQLPrintSpek for preetty print test

* Bump hotfix version

* Update build status link

* Migrate kotlin v1.1.1 (#7)

* bump to kotlin v1.1.1

* Add type alias for more readable code

* Change the package name to me.lazmaid.kraph

* Fix build failed dur to hamkrest error

* Update spek version

* Update ENV for release

* Update README

* Refactor arguments (#9)

* WIP

* Split the print logic into sealed class

* Update UTs

* Add exception message

* Refactor

* Add Test Coverage (#11)

* Add Test Coverage

* Update spek version

* Fix test result path

* Add codecov YAML

* Add onlyIf

* Update config

* Fix travis command

* Add coverage badge

* Fix wrong download badge

* Bump version to 0.5.1

* Support boolean type in Argument (#15)

* Add support for boolean type

* Add Tests

* Fix typo in README (#16)

missing "h" in the example call to `println(query.toGrapQueryString())`

* Added basic fragment support (#17)

* improve readme

* Allow using field with a block in place of field object

* Update readme to include new changes

* Cheap implementation of fragment that doesn't use actual GraphQL Fragments

* Add fragment docs to readme

* Fix tests

* Change function to 'defineFragment'

* Update Kotlin and library dependcies (#18)

* Update .gitignore

* Update dependecies

* Add secondary constructor for DataEntry.NonDecimalNUmber

* Add Test for DataEntry classes

* Fix failed UTs

* Added partial request printing functions (#19)

* improve readme

* Allow using field with a block in place of field object

* Update readme to include new changes

* Cheap implementation of fragment that doesn't use actual GraphQL Fragments

* Add fragment docs to readme

* Fix tests

* Add separate methods to print the different parts of the request separately

* Use spaces instead of newlines for request format

* Rewrite printing operations to optionally escape quotes

* update readme a bit

* Change function to 'defineFragment'

* Use an enum to choose print format and write tests to cover all formats

* Add note about variables

* Update version (#20)

* add support for variables (#23)

* add support for variables

* add support for variables

* Added alias support for queries and mutations

* Checked errors from CI Build and added an example for usage

* Resolve error with arguments in RequestSpek.kt

* Resolve error in BuilderSpek.kt

* Replace /n on """ in the BuilderSpek.kt

* Change equalTo to requestString

* Change other test mutation with alias

* Added documentation about alias for field and fieldObject

* Resolved conflicts

* Check CI error
  • Loading branch information
PaulProject authored and VerachadW committed Oct 5, 2019
1 parent c1e689d commit 2b39841
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 27 deletions.
34 changes: 31 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,12 @@ First, let's see what Kraph provides for you.
technically no differences, `fieldObject` may be chosen for clarity to indicate
that a field must contain another set of nested fields as an argument.
Both of them take a `Map<String, Any>` that maps Kotlin data types to the
GraphQL data types for input objects.
GraphQL data types for input objects. You can also specify an alias using `alias` to change
the name of the returned field.
```graphql
query {
users {
name
nick: name
email
avatarUrl(size: 100)
}
Expand All @@ -114,14 +115,41 @@ First, let's see what Kraph provides for you.
Kraph {
query {
fieldObject("users") {
field("name")
field("name", alias = "nick")
field("email")
field("avatarUrl", args = mapOf("size" to 100))
}
}
}
```

- `fragment` provides a mechanism for creating GraphQL Fragments. To use a fragment
in a query requires two steps. The first is to define the fragment, letting
Kraph know how to handle it later:
```graphql
fragment UserFragment on User {
name
email
avatarUrl(size: 100)
}
```
```kotlin
Kraph.defineFragment("UserFragment") {
field("name")
field("email")
field("avatarUrl", mapOf("size" to 100))
}
```
Then, when you are creating your query, you can simply use the fragment and
its fields will be expanded:
```graphql
query {
users {
...UserFragment
}
}
```

- `fragment` provides a mechanism for creating GraphQL Fragments. To use a fragment
in a query requires two steps. The first is to define the fragment, letting
Kraph know how to handle it later:
Expand Down
16 changes: 8 additions & 8 deletions core/src/main/kotlin/me/lazmaid/kraph/Kraph.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ class Kraph(f: Kraph.() -> Unit) {
inner open class FieldBuilder {
internal val fields = arrayListOf<Field>()

fun fieldObject(name: String, args: Map<String, Any>? = null, builder: FieldBlock) {
addField(name, args, builder)
fun fieldObject(name: String, alias: String? = null, args: Map<String, Any>? = null, builder: FieldBlock) {
addField(name, alias, args, builder)
}

fun field(name: String, args: Map<String, Any>? = null, builder: FieldBlock? = null) {
addField(name, args, builder)
fun field(name: String, alias: String? = null, args: Map<String, Any>? = null, builder: FieldBlock? = null) {
addField(name, alias, args, builder)
}

fun fragment(name: String) {
Expand Down Expand Up @@ -87,16 +87,16 @@ class Kraph(f: Kraph.() -> Unit) {
fields += CursorConnection(name, Argument(argsMap), SelectionSet(selection.fields))
}

fun func(name: String, args: Map<String, Any>, builder: FieldBlock) {
fields += Mutation(name, InputArgument(args), createSelectionSet(name, builder))
fun func(name: String, alias: String? = null, args: Map<String, Any>, builder: FieldBlock) {
fields += Mutation(name, alias, InputArgument(args), createSelectionSet(name, builder))
}

protected fun addField(name: String, args: Map<String, Any>? = null, builder: FieldBlock? = null) {
protected fun addField(name: String, alias: String? = null, args: Map<String, Any>? = null, builder: FieldBlock? = null) {
val argNode = args?.let(::Argument)
val selectionSet = builder?.let {
createSelectionSet(name, builder)
}
fields += Field(name, arguments = argNode, selectionSet = selectionSet)
fields += Field(name, alias, arguments = argNode, selectionSet = selectionSet)
}
}

Expand Down
4 changes: 3 additions & 1 deletion core/src/main/kotlin/me/lazmaid/kraph/lang/Field.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ package me.lazmaid.kraph.lang

internal open class Field(
internal val name: String,
internal val alias: String? = null,
internal val arguments: Argument? = null,
internal var selectionSet: SelectionSet? = null
) : GraphQLNode() {
override fun print(
format: PrintFormat,
previousLevel: Int
): String {
val alias = alias?.let { "$it: " } ?: ""
val selectionSetPart = selectionSet?.print(format, previousLevel)?.let{ " $it" } ?: ""
val argumentsPart = arguments?.print(format, previousLevel)?.let{ " $it" } ?: ""
return "$name$argumentsPart$selectionSetPart"
return "$alias$name$argumentsPart$selectionSetPart"
}
}
4 changes: 2 additions & 2 deletions core/src/main/kotlin/me/lazmaid/kraph/lang/relay/Node.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import me.lazmaid.kraph.lang.SelectionSet
* Created by VerachadW on 10/2/2016 AD.
*/

internal class Node(name: String, additionalFields: List<Field>) : Field(name) {
internal class Node(name: String, alias: String?, additionalFields: List<Field>) : Field(name, alias) {
init {
selectionSet = SelectionSet(additionalFields.toMutableList().apply {
add(0, Field("id"))
add(0, Field("id"))
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ import me.lazmaid.kraph.lang.SelectionSet
* Created by VerachadW on 10/2/2016 AD.
*/

internal class Mutation(name: String, arguments: InputArgument, selectionSet: SelectionSet) : Field(name, arguments, selectionSet)
internal class Mutation(name: String, alias: String? = null, arguments: InputArgument, selectionSet: SelectionSet) : Field(name, alias, arguments, selectionSet)
49 changes: 41 additions & 8 deletions core/src/test/kotlin/me/lazmaid/kraph/test/BuilderSpek.kt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,23 @@ class BuilderSpek : Spek({
assertThat(query.toGraphQueryString(), equalTo("query getAllNotes {\n notes {\n id\n content\n author {\n name\n email\n }\n avatarUrl (size: 100)\n }\n}"))
}
}
given("sample query with aliases") {
val query = Kraph {
query("getAllNotes") {
fieldObject("notes", alias = "aliasedNotes") {
field("id", alias = "aliasedId")
}
}
}
it("should be able to print the request for network call") {
assertThat(
query.toRequestString(),
equalTo(
"{\"query\": \"query getAllNotes { aliasedNotes: notes { aliasedId: id } }\", \"variables\": null, \"operationName\": \"getAllNotes\"}"
)
)
}
}
given("sample query with no field in selection set") {
it("should throw NoFieldsInSelectionSetException") {
assertThat({
Expand All @@ -95,7 +112,7 @@ class BuilderSpek : Spek({
given("sample mutation") {
val query = Kraph {
mutation {
func("registerUser", mapOf("email" to "abcd@efgh.com", "password" to "abcd1234", "age" to 30)) {
func("registerUser", args = mapOf("email" to "abcd@efgh.com", "password" to "abcd1234", "age" to 30)) {
field("id")
field("token")
}
Expand Down Expand Up @@ -132,6 +149,22 @@ class BuilderSpek : Spek({
assertThat(query.document.operation.selectionSet.fields[0].selectionSet!!.fields[1].name, equalTo("token"))
}
}
given("sample mutation with alias") {
val query = Kraph {
mutation {
func("registerUser", alias = "aliasedRegisterUser", args = mapOf("email" to "abcd@efgh.com")) {
field("id")
}
}
}
it("should be able to print the request for network call") {
assertThat(query.toRequestString(),
equalTo(
"{\"query\": \"mutation { aliasedRegisterUser: registerUser (input: { email: \\\"abcd@efgh.com\\\" }) { id } }\", \"variables\": null, \"operationName\": null}"
)
)
}
}
given("sample mutation with no field in selection set") {
it("should throw NoFieldsInSelectionSetException") {
assertThat({
Expand Down Expand Up @@ -205,17 +238,17 @@ class BuilderSpek : Spek({
given("sample query with cursor cursorConnection without arguments") {
it("should throw IllegalArgumentException with message \"There must be at least 1 argument for Cursor Connection\"") {
assertThat({
Kraph {
query {
cursorConnection("users") {
edges {
node {
field("title")
Kraph {
query {
cursorConnection("users") {
edges {
node {
field("title")
}
}
}
}
}
}
}, throws<IllegalArgumentException>(cursorEmptyArgumentsMessageMatcher))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class GraphQLPrintSpek : Spek({
given("name RegisterUser with email and password and type of registrarion as argument and payload contains id and token") {
val argNode = InputArgument(mapOf("email" to "abcd@efgh.com", "password" to "abcd1234", "type" to Type.EMAIL))
val setNode = SelectionSet(listOf(Field("id"), Field("token")))
val node = Mutation("RegisterUser", argNode, setNode)
val node = Mutation("RegisterUser", arguments = argNode, selectionSet = setNode)
it("should print correctly in NORMAL mode") {
assertThat(node.print(PrintFormat.NORMAL, 0), equalTo("RegisterUser (input: { email: \"abcd@efgh.com\", password: \"abcd1234\", type: EMAIL }) { id token }"))
}
Expand All @@ -148,7 +148,7 @@ class GraphQLPrintSpek : Spek({
val tests = listOf(
Triple(Field("id"), "name id", Expectation("id", "id", "id")),
Triple(
Field("avatarSize", Argument(mapOf("size" to 20))),
Field("avatarSize", arguments = Argument(mapOf("size" to 20))),
"name avatarSize and size argument with value as 20",
Expectation(
"avatarSize (size: 20)",
Expand All @@ -166,7 +166,7 @@ class GraphQLPrintSpek : Spek({
)
),
Triple(
Field("user", Argument(mapOf("id" to 10)), SelectionSet(listOf(Field("name"), Field("email")))),
Field("user", arguments = Argument(mapOf("id" to 10)), selectionSet = SelectionSet(listOf(Field("name"), Field("email")))),
"name user and id argument with value as 10 and containing name and email",
Expectation(
"user (id: 10) { name email }",
Expand Down
2 changes: 1 addition & 1 deletion core/src/test/kotlin/me/lazmaid/kraph/test/RequestSpek.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class RequestSpek : Spek({
describe("Kraph Query Request format printers") {
val query = Kraph {
query("GetUserId") {
field("user", mapOf("name" to variable("name", "User", "{\"name\": \"UserName\"}"))) {
field("user", args = mapOf("name" to variable("name", "User", "{\"name\": \"UserName\"}"))) {
field("id")
}
}
Expand Down
18 changes: 18 additions & 0 deletions sample/src/main/kotlin/KraphExample.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,23 @@ fun main(args: Array<String>) {
println("Query: ${mutation.toGraphQueryString()}")
println("Request Body: ${ mutation.toRequestString() }")

// Sample query with alias
val alias = Kraph {
query {
fieldObject("notes", "example") {
field("id")
field("createdDate")
field("content")
fieldObject("author") {
field("name")
field("avatarUrl", args = mapOf("size" to 100))
}
}
}
}

println("Query: ${alias.toGraphQueryString()}")
println("Request Body: ${ alias.toRequestString() }")


}

0 comments on commit 2b39841

Please sign in to comment.