GraphQL 入門

DDD + CQRS で RESTAPI を開発している過程で、クエリーの API のインターフェースで悩んでいました。
具体的には >= (以上)とか <= (以下)みたいな関係演算子等を含んだパラメータを REST API でどう受け取るのが良いのか、です。
GraphQL ならその辺りの仕様だとかベストプラクティスがありそうだと思い、とりあえずチュートリアルをやってみたのでそのメモです。 このチュートリアルでは graphql-jsExpress を使用しています。

var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');

// GraphQL schema
var schema = buildSchema(`
  # GraphQL schema において Query と Mutation は特別で、エントリーポイントになります。
  # REST でいう GET  のように副作用のない API は Query 、副作用がある場合は Mutation を使います。今回は Query だけ使います。
  type Query {
    quoteOfTheDay: String                                           # String 型で返却
    random: Float!                                                          # Not Null な Float 型で返却 
    rollDice(numDice: Int!, numSides: Int): [Int]           # サイコロの数とサイコロの目の数を受け取ってサイコロの目の配列を返却
  }
`);


// API のエンドポイント
var root = {
  quoteOfTheDay: () => {
    return Math.random() < 0.5 ? 'Take it easy' : 'Salvation lies within';
  },
  random: () => {
    return Math.random();
  },
  rollDice: function ({ numDice, numSides }) {
    var output = [];
    for (var i = 0; i < numDice; i++) {
      output.push(1 + Math.floor(Math.random() * (numSides || 6)));
    }
    return output;
  }
};

var app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true,
}));
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');

上記内容で server.js ファイルを作成し、起動。

node server.js

curl で確認。

# quoteOfTheDay クエリを実行
$ curl -X POST -H "Content-Type: application/json" -d '{"query": "{ quoteOfTheDay }"}' http://localhost:4000/graphql
{"data":{"quoteOfTheDay":"Salvation lies within"}}
# もしくは {"data":{"quoteOfTheDay":"Take it easy"}} が返ってくる。

# rollDice クエリを実行
$ curl -X POST -H "Content-Type: application/json" \
    -d '{"query": "{rollDice(numDice: 3, numSides: 6)}"}' \
    http://localhost:4000/graphql
{"data":{"rollDice":[1,2,3]}}
# さいころの目なので結果はランダム。

# 変数も使える。↓と↑は同義。
# $ が前についてあるものは変数。query キーと同階層に variables キーを用意して値を定義する。
$ curl -X POST \
    -H "Content-Type: application/json" \
    -d '{"query": "query RollDice($dice: Int!, $sides: Int) { rollDice(numDice: $dice, numSides: $sides) }", "variables": {"dice":3, "sides":6} }'  \
    http://localhost:4000/graphql
{"data":{"rollDice":[3,5,6]}}

また、下記から GraphiQLという GUI クライアントツールが使えます。 http://localhost:4000/graphqlにアクセス。
左側に ↓ をコピペして実行すると右側に結果が出力されます。

{
  quoteOfTheDay
  random
  rollDice(numDice:3)
}

全体のソースコードこちらになります。

ここまでやったところで僕が元々イメージしていたものとは大分違う気がしてたので探してみました。 GraphQL はそこまでサポートしていないのでやりたい場合は自分で定義しなければいけないようです。 forums.meteor.com