diff options
Diffstat (limited to 'docs/tutorial')
| -rw-r--r-- | docs/tutorial/tutorial.lhs | 98 |
1 files changed, 38 insertions, 60 deletions
diff --git a/docs/tutorial/tutorial.lhs b/docs/tutorial/tutorial.lhs index 13afb81..dc44c1e 100644 --- a/docs/tutorial/tutorial.lhs +++ b/docs/tutorial/tutorial.lhs @@ -5,11 +5,13 @@ title: GraphQL Haskell Tutorial == Getting started == -Welcome to graphql-haskell! +Welcome to GraphQL! -We have written a small tutorial to help you (and ourselves) understand the graphql package. +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. +Since this file is a literate haskell file, we start by importing some +dependencies. > {-# LANGUAGE OverloadedStrings #-} > module Main where @@ -23,75 +25,76 @@ Since this file is a literate haskell file, we start by importing some dependenc > import Data.Time (getCurrentTime) > > import Language.GraphQL -> import Language.GraphQL.Trans > import Language.GraphQL.Type > import qualified Language.GraphQL.Type.Out as Out > > import Prelude hiding (putStrLn) + === First example === -Now, as our first example, we are going to look at the -example from [graphql.js](https://github.com/graphql/graphql-js). +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. > schema1 :: Schema IO -> schema1 = Schema queryType Nothing +> schema1 = Schema +> { query = queryType , mutation = Nothing , subscription = Nothing } > > queryType :: ObjectType IO > queryType = ObjectType "Query" Nothing [] > $ HashMap.singleton "hello" -> $ Out.Resolver helloField hello +> $ ValueResolver helloField hello > > helloField :: Field IO > helloField = Field Nothing (Out.NamedScalarType string) mempty > -> hello :: ActionT IO Value +> hello :: Resolve IO > hello = pure $ String "it's me" -This defines a simple schema with one type and one field, that resolves to a fixed value. +This defines a simple schema with one type and one field, that resolves to a +fixed value. Next we define our query. > query1 :: Text > query1 = "{ hello }" - To run the query, we call the `graphql` with the schema and the query. > main1 :: IO () -> main1 = graphql schema1 query1 >>= putStrLn . encode +> main1 = graphql schema1 query1 +> >>= either (const $ pure ()) (putStrLn . encode) -This runs the query by fetching the one field defined, -returning +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. > schema2 :: Schema IO -> schema2 = Schema queryType2 Nothing +> schema2 = Schema +> { query = queryType2, mutation = Nothing, subscription = Nothing } > > queryType2 :: ObjectType IO > queryType2 = ObjectType "Query" Nothing [] > $ HashMap.singleton "time" -> $ Out.Resolver timeField time +> $ ValueResolver timeField time > > timeField :: Field IO > timeField = Field Nothing (Out.NamedScalarType string) mempty > -> time :: ActionT IO Value +> time :: Resolve IO > time = do > t <- liftIO getCurrentTime > pure $ String $ Text.pack $ show t -This defines a simple schema with one type and one field, -which resolves to the current time. +This defines a simple schema with one type and one field, which resolves to the +current time. Next we define our query. @@ -99,76 +102,51 @@ Next we define our query. > query2 = "{ time }" > > main2 :: IO () -> main2 = graphql schema2 query2 >>= putStrLn . encode +> main2 = graphql schema2 query2 +> >>= either (const $ pure ()) (putStrLn . encode) 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: - -> 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. - -> mainShouldFail :: IO () -> mainShouldFail = do -> success <- graphql schema1 query1 -> putStrLn $ encode success -> putStrLn "This will fail" -> failure <- graphql schema1 queryShouldFail -> putStrLn $ encode failure -> - -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. > schema3 :: Schema IO -> schema3 = Schema queryType3 Nothing +> schema3 = Schema +> { query = queryType3, mutation = Nothing, subscription = Nothing } > > queryType3 :: ObjectType IO > queryType3 = ObjectType "Query" Nothing [] $ HashMap.fromList -> [ ("hello", Out.Resolver helloField hello) -> , ("time", Out.Resolver timeField time) +> [ ("hello", ValueResolver helloField hello) +> , ("time", ValueResolver timeField time) > ] > > query3 :: Text > query3 = "query timeAndHello { time hello }" > > main3 :: IO () -> main3 = graphql schema3 query3 >>= putStrLn . encode +> main3 = graphql schema3 query3 +> >>= either (const $ pure ()) (putStrLn . encode) 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. +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. +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. > main :: IO () -> main = main1 >> main2 >> mainShouldFail >> main3 +> main = main1 >> main2 >> main3 |
