diff options
| author | Danny Navarro <j@dannynavarro.net> | 2016-02-11 14:24:31 +0100 |
|---|---|---|
| committer | Danny Navarro <j@dannynavarro.net> | 2016-02-12 12:51:18 +0100 |
| commit | a088c819442800cf9cf4a2e95d5cb4bc16584029 (patch) | |
| tree | cb1eda5b7a81e9fd146dc067c2d7b62ed55e8aa2 /Data | |
| parent | 70fbaf359ec5b3a88573fdbc5bd90c402a3ebce0 (diff) | |
| download | graphql-a088c819442800cf9cf4a2e95d5cb4bc16584029.tar.gz | |
Handle Field arguments in Schema definition
The `Schema` has been overhauled to make `Output` monomorphic.
Traversing the `GraphQL` document is handled implicitly while defining
the `Schema`.
The 4th end-to-end test from `graphql-js` has been ported.
Diffstat (limited to 'Data')
| -rw-r--r-- | Data/GraphQL/Execute.hs | 55 | ||||
| -rw-r--r-- | Data/GraphQL/Schema.hs | 40 |
2 files changed, 52 insertions, 43 deletions
diff --git a/Data/GraphQL/Execute.hs b/Data/GraphQL/Execute.hs index 0586a2e..01fc118 100644 --- a/Data/GraphQL/Execute.hs +++ b/Data/GraphQL/Execute.hs @@ -3,7 +3,7 @@ module Data.GraphQL.Execute where #if !MIN_VERSION_base(4,8,0) -import Control.Applicative (Applicative, (<$>), pure) +import Control.Applicative ((<$>), pure) import Data.Traversable (traverse) #endif import Control.Applicative (Alternative, empty) @@ -13,32 +13,35 @@ import qualified Data.Aeson as Aeson import qualified Data.HashMap.Strict as HashMap import Data.GraphQL.AST -import Data.GraphQL.Schema +import Data.GraphQL.Schema (Resolver, Schema(..)) +import qualified Data.GraphQL.Schema as Schema -execute :: (Alternative f, Monad f) => Schema f -> Document -> f Aeson.Value +execute :: (Alternative m, Monad m) => Schema m -> Document -> m Aeson.Value execute (Schema resolv) doc = selectionSet resolv =<< query doc -query :: Applicative f => Document -> f SelectionSet +query :: Alternative f => Document -> f SelectionSet query (Document [DefinitionOperation (Query (Node _ _ _ sels))]) = pure sels -query _ = error "query: Not implemented yet" - -selectionSet :: (Alternative f, Monad f) => Resolver f -> SelectionSet -> f Aeson.Value -selectionSet resolv sels = Aeson.Object . fold <$> traverse (selection resolv) sels - -selection :: (Alternative f, Monad f) => Resolver f -> Selection -> f Aeson.Object -selection resolv (SelectionField (Field _ n _ _ sfs)) = - fmap (HashMap.singleton n) $ output sfs =<< resolv (InputField n) -selection _ _ = error "selection: Not implemented yet" - -output :: (Alternative f, Monad f) => SelectionSet -> Output f -> f Aeson.Value -output sels (OutputResolver resolv) = selectionSet resolv sels -output sels (OutputList os) = fmap array . traverse (output sels) =<< os -output sels (OutputEnum e) - | null sels = Aeson.toJSON <$> e - | otherwise = empty -output sels (OutputScalar s) - | null sels = Aeson.toJSON <$> s - | otherwise = empty - -array :: [Aeson.Value] -> Aeson.Value -array = Aeson.toJSON +query _ = empty + +selectionSet :: Alternative f => Resolver f -> SelectionSet -> f Aeson.Value +selectionSet resolv = fmap (Aeson.Object . fold) . traverse (selection resolv) + +selection :: Alternative f => Resolver f -> Selection -> f Aeson.Object +selection resolv (SelectionField field@(Field _ name _ _ _)) = + fmap (HashMap.singleton name) $ Aeson.toJSON <$> resolv (fieldToInput field) +selection _ _ = empty + +-- * AST/Schema conversions + +argument :: Argument -> Schema.Argument +argument (Argument n (ValueInt v)) = (n, Schema.ScalarInt $ fromIntegral v) +argument (Argument n (ValueString (StringValue v))) = (n, Schema.ScalarString v) +argument _ = error "argument: not implemented yet" + +fieldToInput :: Field -> Schema.Input +fieldToInput (Field _ n as _ sels) = + Schema.InputField n (argument <$> as) (fieldToInput . selectionToField <$> sels) + +selectionToField :: Selection -> Field +selectionToField (SelectionField x) = x +selectionToField _ = error "selectionField: not implemented yet" diff --git a/Data/GraphQL/Schema.hs b/Data/GraphQL/Schema.hs index 8a6e625..8ceb11f 100644 --- a/Data/GraphQL/Schema.hs +++ b/Data/GraphQL/Schema.hs @@ -1,35 +1,34 @@ +{-# LANGUAGE CPP #-} module Data.GraphQL.Schema where -import Data.Maybe (catMaybes) +#if !MIN_VERSION_base(4,8,0) +import Control.Applicative ((<$>)) +#endif -import Data.Text (Text) import Data.Aeson (ToJSON(toJSON)) +import Data.HashMap.Strict (HashMap) +import Data.Text (Text) data Schema f = Schema (QueryRoot f) -- (Maybe MutationRoot) type QueryRoot f = Resolver f -type Resolver f = Input -> f (Output f) +type Resolver f = Input -> f Output -data Output f = OutputResolver (Resolver f) - | OutputList (f [Output f]) - | OutputScalar (f Scalar) - | OutputEnum (f Text) +data Output = OutputObject (HashMap Text Output) + | OutputList [Output] + | OutputScalar Scalar + | OutputEnum Text + deriving (Show) -- | OutputUnion [Output] -- | OutputNonNull (Output) -data Input = InputScalar Scalar - | InputField Text - | InputList [Input] - deriving (Show) - -field :: Input -> Maybe Text -field (InputField x) = Just x -field _ = Nothing +type Argument = (Text, Scalar) -fields :: [Input] -> [Text] -fields = catMaybes . fmap field +data Input = InputField Text [Argument] [Input] + deriving (Show) +-- TODO: Make ScalarInt Int32 data Scalar = ScalarInt Int | ScalarFloat Double | ScalarString Text @@ -43,3 +42,10 @@ instance ToJSON Scalar where toJSON (ScalarString x) = toJSON x toJSON (ScalarBoolean x) = toJSON x toJSON (ScalarID x) = toJSON x + +instance ToJSON Output where + toJSON (OutputObject x) = toJSON $ toJSON <$> x + toJSON (OutputList x) = toJSON $ toJSON <$> x + toJSON (OutputScalar x) = toJSON x + toJSON (OutputEnum x) = toJSON x + |
