forked from OSS/graphql
Rewrite selections into a Sequence. Fix #21
This commit is contained in:
parent
115aa02672
commit
7b92e5bcfd
@ -28,6 +28,7 @@ data-files:
|
|||||||
dependencies:
|
dependencies:
|
||||||
- aeson
|
- aeson
|
||||||
- base >= 4.7 && < 5
|
- base >= 4.7 && < 5
|
||||||
|
- containers
|
||||||
- megaparsec
|
- megaparsec
|
||||||
- text
|
- text
|
||||||
- transformers
|
- transformers
|
||||||
|
@ -15,6 +15,7 @@ module Language.GraphQL.AST.Core
|
|||||||
import Data.Int (Int32)
|
import Data.Int (Int32)
|
||||||
import Data.HashMap.Strict (HashMap)
|
import Data.HashMap.Strict (HashMap)
|
||||||
import Data.List.NonEmpty (NonEmpty)
|
import Data.List.NonEmpty (NonEmpty)
|
||||||
|
import Data.Sequence (Seq)
|
||||||
import Data.String (IsString(..))
|
import Data.String (IsString(..))
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Language.GraphQL.AST (Alias, Name, TypeCondition)
|
import Language.GraphQL.AST (Alias, Name, TypeCondition)
|
||||||
@ -26,19 +27,21 @@ type Document = NonEmpty Operation
|
|||||||
--
|
--
|
||||||
-- Currently only queries and mutations are supported.
|
-- Currently only queries and mutations are supported.
|
||||||
data Operation
|
data Operation
|
||||||
= Query (Maybe Text) (NonEmpty Selection)
|
= Query (Maybe Text) (Seq Selection)
|
||||||
| Mutation (Maybe Text) (NonEmpty Selection)
|
| Mutation (Maybe Text) (Seq Selection)
|
||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
-- | Single GraphQL field.
|
-- | Single GraphQL field.
|
||||||
data Field = Field (Maybe Alias) Name [Argument] [Selection] deriving (Eq, Show)
|
data Field
|
||||||
|
= Field (Maybe Alias) Name [Argument] (Seq Selection)
|
||||||
|
deriving (Eq, Show)
|
||||||
|
|
||||||
-- | Single argument.
|
-- | Single argument.
|
||||||
data Argument = Argument Name Value deriving (Eq, Show)
|
data Argument = Argument Name Value deriving (Eq, Show)
|
||||||
|
|
||||||
-- | Represents fragments and inline fragments.
|
-- | Represents fragments and inline fragments.
|
||||||
data Fragment
|
data Fragment
|
||||||
= Fragment TypeCondition (NonEmpty Selection)
|
= Fragment TypeCondition (Seq Selection)
|
||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
-- | Single selection element.
|
-- | Single selection element.
|
||||||
|
@ -13,17 +13,19 @@ import Control.Monad (foldM, unless)
|
|||||||
import Control.Monad.Trans.Class (lift)
|
import Control.Monad.Trans.Class (lift)
|
||||||
import Control.Monad.Trans.Reader (ReaderT, ask, runReaderT)
|
import Control.Monad.Trans.Reader (ReaderT, ask, runReaderT)
|
||||||
import Control.Monad.Trans.State (StateT, evalStateT, gets, modify)
|
import Control.Monad.Trans.State (StateT, evalStateT, gets, modify)
|
||||||
|
import Data.Foldable (toList)
|
||||||
import Data.HashMap.Strict (HashMap)
|
import Data.HashMap.Strict (HashMap)
|
||||||
import qualified Data.HashMap.Strict as HashMap
|
import qualified Data.HashMap.Strict as HashMap
|
||||||
import Data.List.NonEmpty (NonEmpty)
|
|
||||||
import qualified Data.List.NonEmpty as NonEmpty
|
import qualified Data.List.NonEmpty as NonEmpty
|
||||||
|
import Data.Sequence (Seq, (<|), (><))
|
||||||
|
import qualified Data.Sequence as Sequence
|
||||||
import qualified Language.GraphQL.AST as Full
|
import qualified Language.GraphQL.AST as Full
|
||||||
import qualified Language.GraphQL.AST.Core as Core
|
import qualified Language.GraphQL.AST.Core as Core
|
||||||
import qualified Language.GraphQL.Schema as Schema
|
import qualified Language.GraphQL.Schema as Schema
|
||||||
|
|
||||||
-- | Associates a fragment name with a list of 'Core.Field's.
|
-- | Associates a fragment name with a list of 'Core.Field's.
|
||||||
data Replacement = Replacement
|
data Replacement = Replacement
|
||||||
{ fragments :: HashMap Core.Name (NonEmpty Core.Selection)
|
{ fragments :: HashMap Core.Name (Seq Core.Selection)
|
||||||
, fragmentDefinitions :: HashMap Full.Name Full.FragmentDefinition
|
, fragmentDefinitions :: HashMap Full.Name Full.FragmentDefinition
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,13 +65,13 @@ operation (Full.OperationDefinition Full.Mutation name _vars _dirs sels) =
|
|||||||
|
|
||||||
selection ::
|
selection ::
|
||||||
Full.Selection ->
|
Full.Selection ->
|
||||||
TransformT (Either (NonEmpty Core.Selection) Core.Selection)
|
TransformT (Either (Seq Core.Selection) Core.Selection)
|
||||||
selection (Full.SelectionField fld) = Right . Core.SelectionField <$> field fld
|
selection (Full.SelectionField fld) = Right . Core.SelectionField <$> field fld
|
||||||
selection (Full.SelectionFragmentSpread (Full.FragmentSpread name _)) = do
|
selection (Full.SelectionFragmentSpread (Full.FragmentSpread name _)) = do
|
||||||
fragments' <- gets fragments
|
fragments' <- gets fragments
|
||||||
Left <$> maybe lookupDefinition liftJust (HashMap.lookup name fragments')
|
Left <$> maybe lookupDefinition liftJust (HashMap.lookup name fragments')
|
||||||
where
|
where
|
||||||
lookupDefinition :: TransformT (NonEmpty Core.Selection)
|
lookupDefinition :: TransformT (Seq Core.Selection)
|
||||||
lookupDefinition = do
|
lookupDefinition = do
|
||||||
fragmentDefinitions' <- gets fragmentDefinitions
|
fragmentDefinitions' <- gets fragmentDefinitions
|
||||||
found <- lift . lift $ HashMap.lookup name fragmentDefinitions'
|
found <- lift . lift $ HashMap.lookup name fragmentDefinitions'
|
||||||
@ -96,11 +98,11 @@ collectFragments = do
|
|||||||
|
|
||||||
fragmentDefinition ::
|
fragmentDefinition ::
|
||||||
Full.FragmentDefinition ->
|
Full.FragmentDefinition ->
|
||||||
TransformT (NonEmpty Core.Selection)
|
TransformT (Seq Core.Selection)
|
||||||
fragmentDefinition (Full.FragmentDefinition name _tc _dirs sels) = do
|
fragmentDefinition (Full.FragmentDefinition name _tc _dirs sels) = do
|
||||||
modify deleteFragmentDefinition
|
modify deleteFragmentDefinition
|
||||||
selections <- traverse selection sels
|
selections <- traverse selection sels
|
||||||
let newValue = either id pure =<< selections
|
let newValue = either id pure =<< Sequence.fromList (toList selections)
|
||||||
modify $ insertFragment newValue
|
modify $ insertFragment newValue
|
||||||
liftJust newValue
|
liftJust newValue
|
||||||
where
|
where
|
||||||
@ -113,7 +115,7 @@ fragmentDefinition (Full.FragmentDefinition name _tc _dirs sels) = do
|
|||||||
field :: Full.Field -> TransformT Core.Field
|
field :: Full.Field -> TransformT Core.Field
|
||||||
field (Full.Field a n args _dirs sels) = do
|
field (Full.Field a n args _dirs sels) = do
|
||||||
arguments <- traverse argument args
|
arguments <- traverse argument args
|
||||||
selection' <- appendSelectionOpt sels
|
selection' <- appendSelection sels
|
||||||
return $ Core.Field a n arguments selection'
|
return $ Core.Field a n arguments selection'
|
||||||
|
|
||||||
argument :: Full.Argument -> TransformT Core.Argument
|
argument :: Full.Argument -> TransformT Core.Argument
|
||||||
@ -137,22 +139,15 @@ value (Full.Object o) =
|
|||||||
objectField :: Full.ObjectField -> TransformT (Core.Name, Core.Value)
|
objectField :: Full.ObjectField -> TransformT (Core.Name, Core.Value)
|
||||||
objectField (Full.ObjectField n v) = (n,) <$> value v
|
objectField (Full.ObjectField n v) = (n,) <$> value v
|
||||||
|
|
||||||
appendSelectionOpt ::
|
appendSelection ::
|
||||||
Traversable t =>
|
Traversable t =>
|
||||||
t Full.Selection ->
|
t Full.Selection ->
|
||||||
TransformT [Core.Selection]
|
TransformT (Seq Core.Selection)
|
||||||
appendSelectionOpt = foldM go []
|
appendSelection = foldM go mempty
|
||||||
where
|
where
|
||||||
go acc sel = append acc <$> selection sel
|
go acc sel = append acc <$> selection sel
|
||||||
append acc (Left list) = NonEmpty.toList list <> acc
|
append acc (Left list) = list >< acc
|
||||||
append acc (Right one) = one : acc
|
append acc (Right one) = one <| acc
|
||||||
|
|
||||||
appendSelection ::
|
|
||||||
NonEmpty Full.Selection ->
|
|
||||||
TransformT (NonEmpty Core.Selection)
|
|
||||||
appendSelection fullSelection = do
|
|
||||||
coreSelection <-appendSelectionOpt fullSelection
|
|
||||||
lift . lift $ NonEmpty.nonEmpty coreSelection
|
|
||||||
|
|
||||||
liftJust :: forall a. a -> TransformT a
|
liftJust :: forall a. a -> TransformT a
|
||||||
liftJust = lift . lift . Just
|
liftJust = lift . lift . Just
|
||||||
|
@ -8,6 +8,7 @@ module Language.GraphQL.Execute
|
|||||||
|
|
||||||
import Control.Monad.IO.Class (MonadIO)
|
import Control.Monad.IO.Class (MonadIO)
|
||||||
import qualified Data.Aeson as Aeson
|
import qualified Data.Aeson as Aeson
|
||||||
|
import Data.Foldable (toList)
|
||||||
import Data.List.NonEmpty (NonEmpty(..))
|
import Data.List.NonEmpty (NonEmpty(..))
|
||||||
import qualified Data.List.NonEmpty as NE
|
import qualified Data.List.NonEmpty as NE
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
@ -71,6 +72,6 @@ operation :: MonadIO m
|
|||||||
-> AST.Core.Operation
|
-> AST.Core.Operation
|
||||||
-> m Aeson.Value
|
-> m Aeson.Value
|
||||||
operation schema (AST.Core.Query _ flds)
|
operation schema (AST.Core.Query _ flds)
|
||||||
= runCollectErrs (Schema.resolve (NE.toList schema) (NE.toList flds))
|
= runCollectErrs (Schema.resolve (toList schema) flds)
|
||||||
operation schema (AST.Core.Mutation _ flds)
|
operation schema (AST.Core.Mutation _ flds)
|
||||||
= runCollectErrs (Schema.resolve (NE.toList schema) (NE.toList flds))
|
= runCollectErrs (Schema.resolve (toList schema) flds)
|
||||||
|
@ -28,6 +28,7 @@ import Data.Maybe (fromMaybe)
|
|||||||
import qualified Data.Aeson as Aeson
|
import qualified Data.Aeson as Aeson
|
||||||
import Data.HashMap.Strict (HashMap)
|
import Data.HashMap.Strict (HashMap)
|
||||||
import qualified Data.HashMap.Strict as HashMap
|
import qualified Data.HashMap.Strict as HashMap
|
||||||
|
import Data.Sequence (Seq)
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Language.GraphQL.AST.Core
|
import Language.GraphQL.AST.Core
|
||||||
@ -118,7 +119,7 @@ withField v fld
|
|||||||
-- 'Resolver' to each 'Field'. Resolves into a value containing the
|
-- 'Resolver' to each 'Field'. Resolves into a value containing the
|
||||||
-- resolved 'Field', or a null value and error information.
|
-- resolved 'Field', or a null value and error information.
|
||||||
resolve :: MonadIO m
|
resolve :: MonadIO m
|
||||||
=> [Resolver m] -> [Selection] -> CollectErrsT m Aeson.Value
|
=> [Resolver m] -> Seq Selection -> CollectErrsT m Aeson.Value
|
||||||
resolve resolvers = fmap (Aeson.toJSON . fold) . traverse tryResolvers
|
resolve resolvers = fmap (Aeson.toJSON . fold) . traverse tryResolvers
|
||||||
where
|
where
|
||||||
resolveTypeName (Resolver "__typename" f) = do
|
resolveTypeName (Resolver "__typename" f) = do
|
||||||
|
Loading…
Reference in New Issue
Block a user