diff --git a/docs/tutorial/Makefile b/docs/tutorial/Makefile deleted file mode 100644 index 04d8d71..0000000 --- a/docs/tutorial/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -default: - pandoc -f markdown+lhs+yaml_metadata_block --highlight-style=haddock -S -c "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" --section-divs -c tutorial.css --toc --standalone -t html5 -o tutorial.html tutorial.lhs - pandoc -f markdown+lhs+yaml_metadata_block --highlight-style=haddock --toc --standalone -t rst -o tutorial.rst tutorial.lhs - pandoc -f markdown+lhs+yaml_metadata_block --highlight-style=haddock --toc --standalone -t latex -o tutorial.pdf tutorial.lhs diff --git a/docs/tutorial/tutorial.css b/docs/tutorial/tutorial.css deleted file mode 100644 index 831b73d..0000000 --- a/docs/tutorial/tutorial.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - padding: 0 20px; -} diff --git a/docs/tutorial/tutorial.html b/docs/tutorial/tutorial.html deleted file mode 100644 index cbec66d..0000000 --- a/docs/tutorial/tutorial.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - GraphQL Haskell Tutorial - - - - - - - -
-

GraphQL Haskell Tutorial

-
- -
-

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.

-
{-# 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.List.NonEmpty (NonEmpty((:|)))
-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.

-

First we build a GraphQL schema.

-
schema1 :: Alternative f => Schema f
-schema1 = 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.

-
query1 :: Text
-query1 = "{ hello }"
-

To run the query, we call the graphql with the schema and the query.

-
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.

-
schema2 :: Schema IO
-schema2 = 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.

-
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:

-
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
-  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.

-
schema3 :: Schema IO
-schema3 = 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 module. This includes a more complex schema, and more complex queries.

-
- - diff --git a/docs/tutorial/tutorial.lhs b/docs/tutorial/tutorial.lhs index 7c534c4..a4943c6 100644 --- a/docs/tutorial/tutorial.lhs +++ b/docs/tutorial/tutorial.lhs @@ -15,20 +15,20 @@ Since this file is a literate haskell file, we start by importing some dependenc > {-# 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.List.NonEmpty (NonEmpty((:|))) -> import Data.Text hiding (empty) -> import Data.Aeson +> import Control.Monad.IO.Class (liftIO) +> import Control.Monad.Trans.Except (throwE) +> import Data.Aeson (encode) > import Data.ByteString.Lazy.Char8 (putStrLn) +> import Data.List.NonEmpty (NonEmpty(..)) +> import Data.Text (Text) +> import Data.Time (getCurrentTime) > -> import Data.Time +> import Language.GraphQL +> import Language.GraphQL.Schema (Schema) +> import qualified Language.GraphQL.Schema as Schema +> import Language.GraphQL.Trans (ActionT(..)) > -> import Debug.Trace +> import Prelude hiding (putStrLn) === First example === @@ -37,11 +37,11 @@ example from [graphql.js](https://github.com/graphql/graphql-js). First we build a GraphQL schema. -> schema1 :: Alternative f => Schema f +> schema1 :: Schema IO > schema1 = hello :| [] > -> hello :: Alternative f => Resolver f -> hello = Schema.scalar "hello" ("it's me" :: Text) +> hello :: Schema.Resolver IO +> hello = Schema.scalar "hello" (return ("it's me" :: Text)) This defines a simple schema with one type and one field, that resolves to a fixed value. @@ -70,11 +70,11 @@ For this example, we're going to be using time. > schema2 :: Schema IO > schema2 = time :| [] > -> time :: Resolver IO +> time :: Schema.Resolver IO > time = Schema.scalarA "time" $ \case -> [] -> do t <- getCurrentTime +> [] -> do t <- liftIO getCurrentTime > return $ show t -> _ -> empty +> _ -> ActionT $ throwE "Invalid arguments." This defines a simple schema with one type and one field, which resolves to the current time. @@ -108,11 +108,11 @@ and the query will fail, as we can see in the following example. > mainShouldFail :: IO () > mainShouldFail = do -> r <- graphql schema1 query1 -> putStrLn $ encode r +> success <- graphql schema1 query1 +> putStrLn $ encode success > putStrLn "This will fail" -> r <- graphql schema1 queryShouldFail -> putStrLn $ encode r +> failure <- graphql schema1 queryShouldFail +> putStrLn $ encode failure > This outputs: @@ -149,3 +149,6 @@ In GraphQL there can only be one operation per query. 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 diff --git a/docs/tutorial/tutorial.pdf b/docs/tutorial/tutorial.pdf deleted file mode 100644 index cfe4434..0000000 Binary files a/docs/tutorial/tutorial.pdf and /dev/null differ diff --git a/docs/tutorial/tutorial.rst b/docs/tutorial/tutorial.rst deleted file mode 100644 index 48fc29f..0000000 --- a/docs/tutorial/tutorial.rst +++ /dev/null @@ -1,177 +0,0 @@ -======================== -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.List.NonEmpty (NonEmpty((:|))) - 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 `__. - -First we build a GraphQL schema. - -.. code:: haskell - - schema1 :: Alternative f => Schema f - schema1 = 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 = 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 = 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. diff --git a/semaphoreci.sh b/semaphoreci.sh index 09f7aa7..f77ac75 100755 --- a/semaphoreci.sh +++ b/semaphoreci.sh @@ -18,6 +18,10 @@ test() { $STACK --no-terminal test --pedantic } +test_docs() { + $STACK --no-terminal ghc -- -Wall -fno-code docs/tutorial/tutorial.lhs +} + setup_lint() { $STACK --no-terminal install hlint } diff --git a/stack.yaml b/stack.yaml index 7ecba39..8d2eae9 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,4 +1,4 @@ -resolver: lts-13.28 +resolver: lts-13.29 packages: - '.' extra-deps: [] diff --git a/stack.yaml.lock b/stack.yaml.lock index b984045..d2178fe 100644 --- a/stack.yaml.lock +++ b/stack.yaml.lock @@ -7,6 +7,6 @@ packages: [] snapshots: - completed: size: 500539 - url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/13/28.yaml - sha256: cdde1bfb38fdee21c6acb73d506e78f7e12e0a73892adbbbe56374ebef4d3adf - original: lts-13.28 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/13/29.yaml + sha256: 006398c5e92d1d64737b7e98ae4d63987c36808814504d1451f56ebd98093f75 + original: lts-13.29