forked from OSS/graphql
Use sequences of selections
This commit is contained in:
parent
5505739e21
commit
2dafb00a16
@ -34,11 +34,14 @@ import Data.Int (Int32)
|
|||||||
import Data.List.NonEmpty (NonEmpty(..))
|
import Data.List.NonEmpty (NonEmpty(..))
|
||||||
import qualified Data.List.NonEmpty as NonEmpty
|
import qualified Data.List.NonEmpty as NonEmpty
|
||||||
import Data.Maybe (fromMaybe, isJust)
|
import Data.Maybe (fromMaybe, isJust)
|
||||||
|
import Data.Sequence (Seq, (><))
|
||||||
|
import qualified Data.Sequence as Seq
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
import qualified Language.GraphQL.Execute.Coerce as Coerce
|
import qualified Language.GraphQL.Execute.Coerce as Coerce
|
||||||
import Language.GraphQL.Execute.OrderedMap (OrderedMap)
|
import Language.GraphQL.Execute.OrderedMap (OrderedMap)
|
||||||
import qualified Language.GraphQL.Execute.OrderedMap as OrderedMap
|
import qualified Language.GraphQL.Execute.OrderedMap as OrderedMap
|
||||||
|
import qualified Language.GraphQL.Type.In as In
|
||||||
import qualified Language.GraphQL.Type.Out as Out
|
import qualified Language.GraphQL.Type.Out as Out
|
||||||
import qualified Language.GraphQL.Type as Type
|
import qualified Language.GraphQL.Type as Type
|
||||||
import qualified Language.GraphQL.Type.Internal as Type.Internal
|
import qualified Language.GraphQL.Type.Internal as Type.Internal
|
||||||
@ -131,13 +134,13 @@ data Operation = Operation
|
|||||||
Type.Subs
|
Type.Subs
|
||||||
SelectionSet
|
SelectionSet
|
||||||
|
|
||||||
type SelectionSet = [Selection]
|
type SelectionSet = Seq Selection
|
||||||
|
|
||||||
data Selection
|
data Selection
|
||||||
= FieldSelection Field
|
= FieldSelection Field
|
||||||
| FragmentSelection Fragment
|
| FragmentSelection Fragment
|
||||||
|
|
||||||
data Argument = Argument Full.Name (Full.Node Value) Full.Location
|
data Argument = Argument Full.Name (Full.Node Input) Full.Location
|
||||||
|
|
||||||
data Field = Field
|
data Field = Field
|
||||||
(Maybe Full.Name)
|
(Maybe Full.Name)
|
||||||
@ -149,7 +152,7 @@ data Field = Field
|
|||||||
data Fragment = Fragment
|
data Fragment = Fragment
|
||||||
(Type.Internal.CompositeType IO) SelectionSet Full.Location
|
(Type.Internal.CompositeType IO) SelectionSet Full.Location
|
||||||
|
|
||||||
data Value
|
data Input
|
||||||
= Variable Full.Name
|
= Variable Full.Name
|
||||||
| Int Int32
|
| Int Int32
|
||||||
| Float Double
|
| Float Double
|
||||||
@ -157,12 +160,12 @@ data Value
|
|||||||
| Boolean Bool
|
| Boolean Bool
|
||||||
| Null
|
| Null
|
||||||
| Enum Full.Name
|
| Enum Full.Name
|
||||||
| List [Full.Node Value]
|
| List [Full.Node Input]
|
||||||
| Object [ObjectField]
|
| Object [ObjectField]
|
||||||
|
|
||||||
data ObjectField = ObjectField
|
data ObjectField = ObjectField
|
||||||
{ name :: Full.Name
|
{ name :: Full.Name
|
||||||
, value :: Full.Node Value
|
, value :: Full.Node Input
|
||||||
, location :: Full.Location
|
, location :: Full.Location
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,10 +195,10 @@ selectionSet :: Full.SelectionSet -> Transform SelectionSet
|
|||||||
selectionSet = selectionSetOpt . NonEmpty.toList
|
selectionSet = selectionSetOpt . NonEmpty.toList
|
||||||
|
|
||||||
selectionSetOpt :: Full.SelectionSetOpt -> Transform SelectionSet
|
selectionSetOpt :: Full.SelectionSetOpt -> Transform SelectionSet
|
||||||
selectionSetOpt = foldM go []
|
selectionSetOpt = foldM go Seq.empty
|
||||||
where
|
where
|
||||||
go accumulatedSelections currentSelection =
|
go accumulatedSelections currentSelection =
|
||||||
selection currentSelection <&> (accumulatedSelections ++)
|
selection currentSelection <&> (accumulatedSelections ><)
|
||||||
|
|
||||||
selection :: Full.Selection -> Transform SelectionSet
|
selection :: Full.Selection -> Transform SelectionSet
|
||||||
selection (Full.FieldSelection field') =
|
selection (Full.FieldSelection field') =
|
||||||
@ -209,7 +212,7 @@ maybeToSelectionSet :: forall a
|
|||||||
. (a -> Selection)
|
. (a -> Selection)
|
||||||
-> Transform (Maybe a)
|
-> Transform (Maybe a)
|
||||||
-> Transform SelectionSet
|
-> Transform SelectionSet
|
||||||
maybeToSelectionSet selectionType = fmap (maybe [] $ pure . selectionType)
|
maybeToSelectionSet selectionType = fmap (maybe Seq.empty $ pure . selectionType)
|
||||||
|
|
||||||
directives :: [Full.Directive] -> Transform (Maybe [Type.Directive])
|
directives :: [Full.Directive] -> Transform (Maybe [Type.Directive])
|
||||||
directives = fmap Type.selection . traverse directive
|
directives = fmap Type.selection . traverse directive
|
||||||
@ -226,13 +229,13 @@ inlineFragment (Full.InlineFragment maybeCondition directives' selectionSet' loc
|
|||||||
pure $ case transformedDirectives >> maybeFragmentType of
|
pure $ case transformedDirectives >> maybeFragmentType of
|
||||||
Just fragmentType -> Right
|
Just fragmentType -> Right
|
||||||
$ Fragment fragmentType transformedSelections location
|
$ Fragment fragmentType transformedSelections location
|
||||||
Nothing -> Left []
|
Nothing -> Left Seq.empty
|
||||||
| otherwise = do
|
| otherwise = do
|
||||||
transformedSelections <- selectionSet selectionSet'
|
transformedSelections <- selectionSet selectionSet'
|
||||||
transformedDirectives <- directives directives'
|
transformedDirectives <- directives directives'
|
||||||
pure $ if isJust transformedDirectives
|
pure $ if isJust transformedDirectives
|
||||||
then Left transformedSelections
|
then Left transformedSelections
|
||||||
else Left []
|
else Left Seq.empty
|
||||||
|
|
||||||
fragmentSpread :: Full.FragmentSpread -> Transform (Maybe Fragment)
|
fragmentSpread :: Full.FragmentSpread -> Transform (Maybe Fragment)
|
||||||
fragmentSpread (Full.FragmentSpread spreadName directives' location) = do
|
fragmentSpread (Full.FragmentSpread spreadName directives' location) = do
|
||||||
@ -260,7 +263,6 @@ fragmentSpread (Full.FragmentSpread spreadName directives' location) = do
|
|||||||
fragmentInserter replacement@Replacement{ visitedFragments } = replacement
|
fragmentInserter replacement@Replacement{ visitedFragments } = replacement
|
||||||
{ visitedFragments = HashSet.insert spreadName visitedFragments }
|
{ visitedFragments = HashSet.insert spreadName visitedFragments }
|
||||||
|
|
||||||
|
|
||||||
field :: Full.Field -> Transform (Maybe Field)
|
field :: Full.Field -> Transform (Maybe Field)
|
||||||
field (Full.Field alias' name' arguments' directives' selectionSet' location') = do
|
field (Full.Field alias' name' arguments' directives' selectionSet' location') = do
|
||||||
transformedSelections <- selectionSetOpt selectionSet'
|
transformedSelections <- selectionSetOpt selectionSet'
|
||||||
@ -309,7 +311,7 @@ directiveValue = \case
|
|||||||
transformedValue <- directiveNode value
|
transformedValue <- directiveNode value
|
||||||
pure $ HashMap.insert name transformedValue accumulator
|
pure $ HashMap.insert name transformedValue accumulator
|
||||||
|
|
||||||
variableValue :: Full.Value -> Value
|
variableValue :: Full.Value -> Input
|
||||||
variableValue (Full.Variable name') = Variable name'
|
variableValue (Full.Variable name') = Variable name'
|
||||||
variableValue (Full.Int integer) = Int integer
|
variableValue (Full.Int integer) = Int integer
|
||||||
variableValue (Full.Float double) = Float double
|
variableValue (Full.Float double) = Float double
|
||||||
@ -327,7 +329,7 @@ variableValue (Full.Object objectFields) = Object $ objectField <$> objectFields
|
|||||||
, location = location
|
, location = location
|
||||||
}
|
}
|
||||||
|
|
||||||
node :: Full.Node Full.Value -> Full.Node Value
|
node :: Full.Node Full.Value -> Full.Node Input
|
||||||
node Full.Node{node = node', ..} = Full.Node (variableValue node') location
|
node Full.Node{node = node', ..} = Full.Node (variableValue node') location
|
||||||
|
|
||||||
executeRequest :: Schema IO
|
executeRequest :: Schema IO
|
||||||
@ -411,9 +413,39 @@ executeSelectionSet
|
|||||||
-> Aeson.Object
|
-> Aeson.Object
|
||||||
-> Type.Subs
|
-> Type.Subs
|
||||||
-> Aeson.Object
|
-> Aeson.Object
|
||||||
executeSelectionSet selections objectType _objectValue _variableValues =
|
executeSelectionSet selections objectType objectValue variableValues =
|
||||||
let _groupedFieldSet = collectFields objectType selections
|
let groupedFieldSet = collectFields objectType selections
|
||||||
in mempty
|
in OrderedMap.foldlWithKey' go mempty groupedFieldSet
|
||||||
|
where
|
||||||
|
Out.ObjectType _ _ _ resolvers = objectType
|
||||||
|
executeField' fields resolver =
|
||||||
|
executeField objectType objectValue fields resolver variableValues
|
||||||
|
go resultMap responseKey fields@(Field _ fieldName _ _ _ :| _) =
|
||||||
|
case HashMap.lookup fieldName resolvers of
|
||||||
|
Just resolver ->
|
||||||
|
let responseValue = executeField' fields resolver
|
||||||
|
in HashMap.insert responseKey responseValue resultMap
|
||||||
|
Nothing -> resultMap
|
||||||
|
|
||||||
|
executeField :: Out.ObjectType IO
|
||||||
|
-> Aeson.Object
|
||||||
|
-> NonEmpty Field
|
||||||
|
-> Out.Resolver IO
|
||||||
|
-> Type.Subs
|
||||||
|
-> Aeson.Value
|
||||||
|
executeField _objectType _objectValue fields fieldType _variableValues =
|
||||||
|
let _field'@(Field _ _fieldName inputArguments _ _) :| _ = fields
|
||||||
|
Out.Field _ _ argumentTypes = resolverField fieldType
|
||||||
|
_argumentValues = coerceArgumentValues argumentTypes inputArguments
|
||||||
|
in Aeson.Null
|
||||||
|
where
|
||||||
|
resolverField (Out.ValueResolver resolverField' _) = resolverField'
|
||||||
|
resolverField (Out.EventStreamResolver resolverField' _ _) = resolverField'
|
||||||
|
|
||||||
|
coerceArgumentValues :: HashMap Full.Name In.Argument
|
||||||
|
-> [Argument]
|
||||||
|
-> Either [Full.Location] Type.Subs
|
||||||
|
coerceArgumentValues _argumentDefinitions _argumentNodes = pure mempty
|
||||||
|
|
||||||
collectFields :: Out.ObjectType IO
|
collectFields :: Out.ObjectType IO
|
||||||
-> SelectionSet
|
-> SelectionSet
|
||||||
|
Loading…
Reference in New Issue
Block a user