Kotlin > Ktor > KGraphQL Tutorial 1st Step



デンマークのaPureBase社がメンテしている、[KGraphQL](https://github.com/aPureBase/KGraphQL) を試してみました。
https://kgraphql.io/

KGraphQLについては以下の説明があります。

>KGraphQL is a Kotlin implementation of GraphQL. It provides a rich DSL to set up the GraphQL schema.
KGraphQLは、GraphQLのKotlin実装です。 GraphQLスキーマをセットアップするための豊富なDSLを提供します。


Ktorのサポートもあり、かなり簡単な手順でGraphQLをKtorプロジェクトへ導入することができました。

今回はチュートリアルを追いながら実際に手元で試してみました。


# チュートリアル開始

公式のチュートリアルに沿って進みます。

[Ktor Tutorial - KGraphQL](https://kgraphql.io/Tutorials/ktor/)


ソースは以下に置いてます
https://github.com/sugasaki/ktor-kgraphql-hello-world


## gradle


gradle.properties

以下を追加

```:gradle.properties
kgraphql_version=0.17.13
```


build.gradle.ktsに追加

```Kotlin:build.gradle.kts
val kgraphql_version: String by project // <-- Add this line

dependencies {
    ...
    implementation("com.apurebase:kgraphql:$kgraphql_version") // <-- Add these two lines
    implementation("com.apurebase:kgraphql-ktor:$kgraphql_version") // <-- Add these two lines
}

tasks {
    compileKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
    compileTestKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
}
```


## Application

Application.kt

```Kotlin:Application.kt
fun Application.module(testing: Boolean = false) {
    install(GraphQL) {
        playground = true
        schema { 
            query("hello") {
                resolver { -> "World" }
            }
        }
    }
}
```





## Hello workld!!

実行して、以下のアドレスにアクセスします。

http://0.0.0.0:8080/graphql


![スクリーンショット 2021-08-12 19.00.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/aa02443b-9890-9b43-4670-fde9a581a920.png "スクリーンショット 2021-08-12 19.00.18.png")


左側に以下を入力して、真ん中の実行ボタンを押します。

```query
{
  hello
}
```

以下のように応答があればOK！

```json:return
{
  "data": {
    "hello": "World"
  }
}
```



## Star Wars Tutorial


次のTutorialにすすみます 。
[Star Wars Tutorial](https://kgraphql.io/Tutorials/starwars/)

これはKtor用には作られていないので、Tutorial通りに進めてもうまくいかないのでちょっと工夫が必要でした。


### Domain

まずは核となるドメインモデルを作成します。

```Kotlin:Domain.kt
enum class Episode {
    NEWHOPE, EMPIRE, JEDI
}

interface Character {
    val id: String
    val name: String?
    val friends: List<Character>
    val appearsIn: Set<Episode>
}

data class Human(
    override val id: String,
    override val name: String?,
    override val friends: List<Character>,
    override val appearsIn: Set<Episode>,
    val homePlanet: String,
    val height: Double
) : Character

data class Droid(
    override val id: String,
    override val name: String?,
    override val friends: List<Character>,
    override val appearsIn: Set<Episode>,
    val primaryFunction: String
) : Character

val luke = Human("2000", "Luke Skywalker", emptyList(), Episode.values().toSet(), "Tatooine", 1.72)
val r2d2 = Droid("2001", "R2-D2", emptyList(), Episode.values().toSet(), "Astromech")
```


### Schema

次にSchemaクラスを作成します。

GraphQLSchema.kt

```Kotlin:GraphQLSchema.kt
import com.apurebase.kgraphql.schema.dsl.SchemaBuilder

fun SchemaBuilder.jediSchema() {
    type<Droid>()
    type<Human>()
    enum<Episode>()

    // create query "hero" which returns instance of Character
    query("hero") {
        resolver { episode: Episode ->
            when (episode) {
                Episode.NEWHOPE, Episode.JEDI -> r2d2
                Episode.EMPIRE -> luke
            }
        }
    }

    // create query "heroes" which returns list of luke and r2d2
    query("heroes") {
        resolver { -> listOf(luke, r2d2) }
    }
}
```

### Application.module

Application.moduleにスキーマを追加します。

```Kotlin:Application.kt
fun Application.module(testing: Boolean = false) {
    install(GraphQL) {
        playground = true

        schema {
            query("hello") {
                resolver { -> "World" }
            }

            configure {
                useDefaultPrettyPrinter = true
            }
            jediSchema()
        }
    }
}
```



### 検証

#### exp1

```:query
{
  hero(episode: JEDI){
      id
      name
  }
}
```

return

```json:return
{
  "data": {
    "hero": {
      "id": "2001",
      "name": "R2-D2"
    }
  }
}
```


#### exp2

```:query
{
  hero(episode: JEDI) {
    id
    name
    ... on Droid {
      primaryFunction
    }
    ... on Human {
      height
    }
  }
}
```

return

```json:return
{
  "data": {
    "hero": {
      "id": "2001",
      "name": "R2-D2",
      "primaryFunction": "Astromech"
    }
  }
}
```


#### exp3

すべてのheroを照会します。

```:query
{
  heroes {
    id
    name
    ... on Droid {
      primaryFunction
    }
    ... on Human {
      height
    }
  }
}
```

return

```json:return
{
  "data": {
    "heroes": [
      {
        "id": "2000",
        "name": "Luke Skywalker",
        "height": 1.72
      },
      {
        "id": "2001",
        "name": "R2-D2",
        "primaryFunction": "Astromech"
      }
    ]
  }
}
```


![スクリーンショット 2021-08-12 19.28.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/e2b86365-c6c3-6d77-98cc-b9752816c4ff.png "スクリーンショット 2021-08-12 19.28.46.png")



# 参考リンク

[Ktor Tutorial - KGraphQL](https://kgraphql.io/Tutorials/ktor/)
[Star Wars Tutorial](https://kgraphql.io/Tutorials/starwars/)


Kotlinで使える GraphQLライブラリ
https://graphql.org/code/#java-kotlin