diff options
Diffstat (limited to 'Data/GraphQL/Schema.hs')
| -rw-r--r-- | Data/GraphQL/Schema.hs | 68 |
1 files changed, 34 insertions, 34 deletions
diff --git a/Data/GraphQL/Schema.hs b/Data/GraphQL/Schema.hs index 0a30eb9..7966392 100644 --- a/Data/GraphQL/Schema.hs +++ b/Data/GraphQL/Schema.hs @@ -1,9 +1,8 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE LambdaCase #-} --- | This module provides the type Schema, --- representing a GraphQL schema, and functions for defining --- a schema. +-- | This module provides a representation of a @GraphQL@ Schema in addition to +-- functions for defining and manipulating Schemas. module Data.GraphQL.Schema ( Schema(..) , Resolver @@ -25,14 +24,16 @@ module Data.GraphQL.Schema ) where #if !MIN_VERSION_base(4,8,0) -import Control.Applicative (pure, (<|>)) +import Control.Applicative (pure) +import Control.Arrow (first) import Data.Foldable (foldMap) import Data.Traversable (traverse) import Data.Monoid (Monoid(mempty,mappend)) #else +import Data.Bifunctor (first) import Data.Monoid (Alt(Alt,getAlt)) #endif -import Control.Applicative (Alternative(..)) +import Control.Applicative (Alternative((<|>), empty)) import Data.Maybe (catMaybes) import Data.Foldable (fold) @@ -42,30 +43,27 @@ import qualified Data.HashMap.Strict as HashMap import Data.Text (Text) import qualified Data.Text as T (null, unwords) -import Control.Arrow - import Data.GraphQL.AST import Data.GraphQL.Error --- | Schema represents a GraphQL schema. --- f usually has to be an instance of Alternative. +-- | A GraphQL schema. +-- @f@ is usually expected to be an instance of 'Alternative'. data Schema f = Schema [Resolver f] --- | Resolver resolves a field in to a wrapped Aeson.Object with error information --- (or empty). The wrapped f usually has to be an instance of Alternative. +-- | Resolves a 'Field' into an @Aeson.@'Aeson.Object' with error information +-- (or 'empty'). @f@ is usually expected to be an instance of 'Alternative'. type Resolver f = Field -> CollectErrsT f Aeson.Object --- | Subs represents a substitution. +-- | Variable substitution function. type Subs = Text -> Maybe Text --- | Objects represent a list of named fields, each of which --- yield a value of a specific type. +-- | Create a named 'Resolver' from a list of 'Resolver's. object :: Alternative f => Text -> [Resolver f] -> Resolver f object name resolvs = objectA name $ \case [] -> resolvs _ -> empty --- | Fields can accept arguments to further specify the return value. +-- | Like 'object' but also taking 'Argument's. objectA :: Alternative f => Text -> ([Argument] -> [Resolver f]) -> Resolver f @@ -78,39 +76,39 @@ scalar name s = scalarA name $ \case [] -> pure s _ -> empty --- | Arguments can be used to further specify a scalar's return value. +-- | Like 'scalar' but also taking 'Argument's. scalarA :: (Alternative f, Aeson.ToJSON a) => Text -> ([Argument] -> f a) -> Resolver f scalarA name f fld@(Field _ _ args _ []) = withField name (errWrap $ f args) fld scalarA _ _ _ = empty --- | Arrays are like objects but have an array of resolvers instead of a list. +-- | Like 'object' but taking lists of 'Resolver's instead of a single list. array :: Alternative f => Text -> [[Resolver f]] -> Resolver f array name resolvs = arrayA name $ \case [] -> resolvs _ -> empty --- | Arguments can be used to further specify an array's return values. +-- | Like 'array' but also taking 'Argument's. arrayA :: Alternative f => Text -> ([Argument] -> [[Resolver f]]) -> Resolver f arrayA name f fld@(Field _ _ args _ sels) = withField name (joinErrs $ traverse (flip resolvers $ fields sels) $ f args) fld --- | An enum represents one of a finite set of possible values. --- Used in place of a scalar when the possible responses are easily enumerable. +-- | Represents one of a finite set of possible values. +-- Used in place of a 'scalar' when the possible responses are easily enumerable. enum :: Alternative f => Text -> f [Text] -> Resolver f enum name enums = enumA name $ \case [] -> enums _ -> empty --- | Arguments can be used to further specify an enum's return values. +-- | Like 'enum' but also taking 'Argument's. enumA :: Alternative f => Text -> ([Argument] -> f [Text]) -> Resolver f enumA name f fld@(Field _ _ args _ []) = withField name (errWrap $ f args) fld enumA _ _ _ = empty --- | Used to implement a resolver with arguments. +-- | Helper function to facilitate 'Argument' handling. withField :: (Alternative f, Aeson.ToJSON a) => Text -> CollectErrsT f a -> Field -> CollectErrsT f (HashMap Text Aeson.Value) @@ -121,25 +119,27 @@ withField name f (Field alias name' _ _ _) = where aliasOrName = if T.null alias then name' else alias --- | resolvers takes a list of resolvers and a list of fields, --- and applies each resolver to each field. Resolves into a value --- containing the resolved field, or a null value and error information. +-- | Takes a list of 'Resolver's and a list of 'Field's and applies each +-- 'Resolver' to each 'Field'. Resolves into a value containing the +-- resolved 'Field', or a null value and error information. resolvers :: Alternative f => [Resolver f] -> [Field] -> CollectErrsT f Aeson.Value resolvers resolvs = fmap (first Aeson.toJSON . fold) - . traverse (\fld -> (getAlt $ foldMap (Alt . ($ fld)) resolvs) <|> errmsg fld) - where errmsg (Field alias name _ _ _) = addErrMsg msg $ (errWrap . pure) val - where val = HashMap.singleton aliasOrName Aeson.Null - msg = T.unwords ["field", name, "not resolved."] - aliasOrName = if T.null alias then name else alias - --- | Checks whether the given selection contains a field and --- returns the field if so, else returns Nothing. + . traverse (\fld -> getAlt (foldMap (Alt . ($ fld)) resolvs) <|> errmsg fld) + where + errmsg (Field alias name _ _ _) = addErrMsg msg $ (errWrap . pure) val + where + val = HashMap.singleton aliasOrName Aeson.Null + msg = T.unwords ["field", name, "not resolved."] + aliasOrName = if T.null alias then name else alias + +-- | Checks whether the given 'Selection' contains a 'Field' and +-- returns the 'Field' if so, else returns 'Nothing'. field :: Selection -> Maybe Field field (SelectionField x) = Just x field _ = Nothing --- | Returns a list of the fields contained in the given selection set. +-- | Returns a list of the 'Field's contained in the given 'SelectionSet'. fields :: SelectionSet -> [Field] fields = catMaybes . fmap field |
