summaryrefslogtreecommitdiff
path: root/docs/tutorial/tutorial.rst
diff options
context:
space:
mode:
authorMatthías Páll Gissurarson <mpg@mpg.is>2016-03-09 01:07:57 +0100
committerMatthías Páll Gissurarson <mpg@mpg.is>2016-03-14 01:01:20 +0100
commitb74278cd19d900d1397e35b85f7b80d70cd574f2 (patch)
tree17b7282544f73c9c2f2cec404f0d3fab1896bbe6 /docs/tutorial/tutorial.rst
parentd8a731fe30ce800ac8347a902f38373d6cf689b2 (diff)
downloadgraphql-b74278cd19d900d1397e35b85f7b80d70cd574f2.tar.gz
Added a tutorial, based on graphql-js and servant documentation.
Diffstat (limited to 'docs/tutorial/tutorial.rst')
-rw-r--r--docs/tutorial/tutorial.rst176
1 files changed, 176 insertions, 0 deletions
diff --git a/docs/tutorial/tutorial.rst b/docs/tutorial/tutorial.rst
new file mode 100644
index 0000000..1c8b5ff
--- /dev/null
+++ b/docs/tutorial/tutorial.rst
@@ -0,0 +1,176 @@
+========================
+GraphQL Haskell Tutorial
+========================
+
+.. contents::
+ :depth: 3
+..
+
+Getting started
+===============
+
+Welcome to graphql-haskell!
+
+We have written a small tutorial to help you (and ourselves) understand
+the graphql package.
+
+Since this file is a literate haskell file, we start by importing some
+dependencies.
+
+.. code:: haskell
+
+ {-# LANGUAGE OverloadedStrings #-}
+ {-# LANGUAGE LambdaCase #-}
+ module Main where
+
+ import Prelude hiding (empty, putStrLn)
+ import Data.GraphQL
+ import Data.GraphQL.Schema
+ import qualified Data.GraphQL.Schema as Schema
+
+ import Control.Applicative
+ import Data.Text hiding (empty)
+ import Data.Aeson
+ import Data.ByteString.Lazy.Char8 (putStrLn)
+
+ import Data.Time
+
+ import Debug.Trace
+
+First example
+-------------
+
+Now, as our first example, we are going to look at the example from
+`graphql.js <https://github.com/graphql/graphql-js>`__.
+
+First we build a GraphQL schema.
+
+.. code:: haskell
+
+ schema1 :: Alternative f => Schema f
+ schema1 = Schema [hello]
+
+ hello :: Alternative f => Resolver f
+ hello = Schema.scalar "hello" ("it's me" :: Text)
+
+This defines a simple schema with one type and one field, that resolves
+to a fixed value.
+
+Next we define our query.
+
+.. code:: haskell
+
+ query1 :: Text
+ query1 = "{ hello }"
+
+To run the query, we call the ``graphql`` with the schema and the query.
+
+.. code:: haskell
+
+ main1 :: IO ()
+ main1 = putStrLn =<< encode <$> graphql schema1 query1
+
+This runs the query by fetching the one field defined, returning
+
+``{"data" : {"hello":"it's me"}}``
+
+Monadic actions
+---------------
+
+For this example, we're going to be using time.
+
+.. code:: haskell
+
+ schema2 :: Schema IO
+ schema2 = Schema [time]
+
+ time :: Resolver IO
+ time = Schema.scalarA "time" $ \case
+ [] -> do t <- getCurrentTime
+ return $ show t
+ _ -> empty
+
+This defines a simple schema with one type and one field, which resolves
+to the current time.
+
+Next we define our query.
+
+.. code:: haskell
+
+ query2 :: Text
+ query2 = "{ time }"
+
+ main2 :: IO ()
+ main2 = putStrLn =<< encode <$> graphql schema2 query2
+
+This runs the query, returning the current time
+
+``{"data": {"time":"2016-03-08 23:28:14.546899 UTC"}}``
+
+Errors
+------
+
+Errors are handled according to the spec, with fields that cause erros
+being resolved to ``null``, and an error being added to the error list.
+
+An example of this is the following query:
+
+.. code:: haskell
+
+ queryShouldFail :: Text
+ queryShouldFail = "{ boyhowdy }"
+
+Since there is no ``boyhowdy`` field in our schema, it will not resolve,
+and the query will fail, as we can see in the following example.
+
+.. code:: haskell
+
+ mainShouldFail :: IO ()
+ mainShouldFail = do
+ r <- graphql schema1 query1
+ putStrLn $ encode r
+ putStrLn "This will fail"
+ r <- graphql schema1 queryShouldFail
+ putStrLn $ encode r
+
+This outputs:
+
+::
+
+ {"data": {"hello": "it's me"}}
+ This will fail
+ {"data": {"boyhowdy": null}, "errors":[{"message": "the field boyhowdy did not resolve."}]}
+
+Combining resolvers
+-------------------
+
+Now that we have two resolvers, we can define a schema which uses them
+both.
+
+.. code:: haskell
+
+ schema3 :: Schema IO
+ schema3 = Schema [hello, time]
+
+ query3 :: Text
+ query3 = "query timeAndHello { time hello }"
+
+ main3 :: IO ()
+ main3 = putStrLn =<< encode <$> graphql schema3 query3
+
+This queries for both time and hello, returning
+
+``{ "data": {"hello":"it's me","time":"2016-03-08 23:29:11.62108 UTC"}}``
+
+Notice that we can name our queries, as we did with ``timeAndHello``.
+Since we have only been using single queries, we can use the shorthand
+``{ time hello}``, as we have been doing in the previous examples.
+
+In GraphQL there can only be one operation per query.
+
+Further examples
+================
+
+More examples on queries and a more complex schema can be found in the
+test directory, in the `Test.StarWars <../../tests/Test/StarWars>`__
+module. This includes a more complex schema, and more complex queries.