Safe Haskell | None |
---|---|
Language | Haskell2010 |
Synopsis
- buildRemoteParser :: forall r m n. MonadBuildRemoteSchema r m n => IntrospectionResult -> RemoteSchemaRelationships -> RemoteSchemaInfo -> m (RemoteSchemaParser n)
- makeResultCustomizer :: RemoteSchemaCustomizer -> GraphQLField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable -> ResultCustomizer
- buildRawRemoteParser :: forall r m n. MonadBuildRemoteSchema r m n => IntrospectionResult -> RemoteSchemaRelationships -> RemoteSchemaInfo -> m ([FieldParser n (RemoteSchemaRootField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)], Maybe [FieldParser n (RemoteSchemaRootField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)], Maybe [FieldParser n (RemoteSchemaRootField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)])
- newtype Altered = Altered {
- getAltered :: Bool
- inputValueDefinitionParser :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> InputValueDefinition -> m (InputFieldsParser n (Maybe (Altered, Value RemoteSchemaVariable)))
- remoteFieldScalarParser :: MonadParse n => MkTypename -> ScalarTypeDefinition -> Parser 'Both n (Altered, Value RemoteSchemaVariable)
- remoteFieldEnumParser :: MonadParse n => MkTypename -> EnumTypeDefinition -> Parser 'Both n (Altered, Value RemoteSchemaVariable)
- remoteInputObjectParser :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> InputObjectTypeDefinition RemoteSchemaInputValueDefinition -> m (Either (InputFieldsParser n (Altered, Value RemoteSchemaVariable)) (Parser 'Input n (Altered, Value RemoteSchemaVariable)))
- shortCircuitIfUnaltered :: forall k n. ('Input <: k, MonadParse n) => Parser k n (Maybe (Altered, Value RemoteSchemaVariable)) -> Parser k n (Maybe (Altered, Value RemoteSchemaVariable))
- argumentsParser :: forall r m n. MonadBuildRemoteSchema r m n => ArgumentsDefinition RemoteSchemaInputValueDefinition -> RemoteSchemaIntrospection -> m (InputFieldsParser n (Altered, HashMap Name (Value RemoteSchemaVariable)))
- aggregateListAndAlteration :: [Maybe (Altered, a)] -> (Altered, [a])
- remoteSchemaRelationships :: forall r n m. MonadBuildRemoteSchema r m n => RemoteSchemaRelationships -> Name -> m [FieldParser n (SchemaRemoteRelationshipSelect (RemoteRelationshipField UnpreparedValue))]
- remoteSchemaObject :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> RemoteSchemaRelationships -> ObjectTypeDefinition RemoteSchemaInputValueDefinition -> m (Parser 'Output n (ObjectSelectionSet (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable))
- remoteSchemaInterface :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> RemoteSchemaRelationships -> InterfaceTypeDefinition [Name] RemoteSchemaInputValueDefinition -> m (Parser 'Output n (DeduplicatedSelectionSet (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable))
- remoteSchemaUnion :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> RemoteSchemaRelationships -> UnionTypeDefinition -> m (Parser 'Output n (DeduplicatedSelectionSet (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable))
- remoteFieldFromDefinition :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> Name -> RemoteSchemaRelationships -> FieldDefinition RemoteSchemaInputValueDefinition -> m (FieldParser n (GraphQLField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable))
- remoteFieldFromName :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> RemoteSchemaRelationships -> Name -> Name -> Maybe Description -> Name -> ArgumentsDefinition RemoteSchemaInputValueDefinition -> m (FieldParser n (GraphQLField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable))
- remoteField :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> RemoteSchemaRelationships -> Name -> Name -> Maybe Description -> ArgumentsDefinition RemoteSchemaInputValueDefinition -> TypeDefinition [Name] RemoteSchemaInputValueDefinition -> m (FieldParser n (GraphQLField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable))
- getObjectParser :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> RemoteSchemaRelationships -> (Name -> m (ObjectTypeDefinition RemoteSchemaInputValueDefinition)) -> Name -> m (Parser 'Output n (Name, ObjectSelectionSet (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable))
- customizeRemoteNamespace :: forall n. MonadParse n => RemoteSchemaInfo -> Name -> [FieldParser n (RemoteSchemaRootField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)] -> [FieldParser n (NamespacedField (RemoteSchemaRootField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable))]
- withRemoteSchemaCustomization :: forall m r a. (MonadReader r m, Has MkTypename r, Has CustomizeRemoteFieldName r) => RemoteSchemaCustomizer -> m a -> m a
Documentation
buildRemoteParser :: forall r m n. MonadBuildRemoteSchema r m n => IntrospectionResult -> RemoteSchemaRelationships -> RemoteSchemaInfo -> m (RemoteSchemaParser n) Source #
makeResultCustomizer :: RemoteSchemaCustomizer -> GraphQLField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable -> ResultCustomizer Source #
:: forall r m n. MonadBuildRemoteSchema r m n | |
=> IntrospectionResult | |
-> RemoteSchemaRelationships | |
-> RemoteSchemaInfo | |
-> m ([FieldParser n (RemoteSchemaRootField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)], Maybe [FieldParser n (RemoteSchemaRootField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)], Maybe [FieldParser n (RemoteSchemaRootField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)]) | parsers for, respectively: queries, mutations, and subscriptions |
Helper, used to track whether an input value was altered during its parsing. There are two possible sources of alteration: - preset values, and - type name customizations. They might force evaluation of variables, and encapsulation of sub-JSON expressions as new variables. Each parser indicates whether such alteration took place within its part of the tree. See Note [Variable expansion in remote schema input parsers] for more information.
inputValueDefinitionParser :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> InputValueDefinition -> m (InputFieldsParser n (Maybe (Altered, Value RemoteSchemaVariable))) Source #
inputValueDefinitionParser
accepts a InputValueDefinition
and will return an
InputFieldsParser
for it. If a non Input
GraphQL type is found in the 'type' of the
InputValueDefinition
then an error will be thrown.
Each parser also returns a boolean that indicates whether the parsed value was altered by presets. Presets might force the evaluation of variables that would otherwise be transmitted unmodified.
remoteFieldScalarParser :: MonadParse n => MkTypename -> ScalarTypeDefinition -> Parser 'Both n (Altered, Value RemoteSchemaVariable) Source #
remoteFieldScalarParser attempts to parse a scalar value for a given remote field
We do not attempt to verify that the literal is correct! Some GraphQL implementations, including
ours, are a bit flexible with the intepretations of literals; for instance, there are several
places in our schema where we declare something to be an Int
, but actually accept String
literals. We do however peform variable type-checking.
If we encounter a JSON value, it means that we were introspecting a query variable. To call the remote schema, we need a graphql value; we therefore need to treat that JSON expression as if it were a query variable of its own. To avoid ending up with one such variable per scalar in the query, we also track alterations, to apply optimizations. See Note [Variable expansion in remote schema input parsers] for more information.
If the value contains a variable with a customized type name then we need to consider it to be altered to ensure that the original type name is passed to the remote server.
remoteFieldEnumParser :: MonadParse n => MkTypename -> EnumTypeDefinition -> Parser 'Both n (Altered, Value RemoteSchemaVariable) Source #
remoteInputObjectParser :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> InputObjectTypeDefinition RemoteSchemaInputValueDefinition -> m (Either (InputFieldsParser n (Altered, Value RemoteSchemaVariable)) (Parser 'Input n (Altered, Value RemoteSchemaVariable))) Source #
remoteInputObjectParser returns an input parser for a given InputObjectTypeDefinition
Now, this is tricky! We are faced with two contradicting constraints here. On one hand, the
GraphQL spec forbids us from creating empty input objects. This means that if all the arguments
have presets, we CANNOT use the parser this function creates, and the caller cannot create a
field for this object (and instead should use pure
to include the preset values in the result
of parsing the fields).
One way we could fix this would be to change the type of this function to return a `Maybe
Parser`, inspect the result of argumentsParser
, and return Nothing
when we realize that there
aren't any actual field in it (or at least return a value that propagates the preset values). But
this would contradict our second constraint: this function needs to be memoized!
At time of writing, we can't memoize functions that return arbitrary functors of Parsers; so no
memoizing Maybe Parser or Either Presets Parser. Which means that we would need to first call
argumentsParser
, then memoize the Just branch that builds the actual Parser. The problem is
that the recursive call ro remoteSchemaInputObject is within argumentsParser
, meaning the call
to it MUST be in the memoized branch!
This is why, in the end, we do the following: we first test whether there is any non-preset field: if yes, we memoize that branch and proceed as normal. Otherwise we can omit the memoization: we know for sure that the preset fields won't generate a recursive call!
shortCircuitIfUnaltered :: forall k n. ('Input <: k, MonadParse n) => Parser k n (Maybe (Altered, Value RemoteSchemaVariable)) -> Parser k n (Maybe (Altered, Value RemoteSchemaVariable)) Source #
Variable expansion optimization. Since each parser returns a value that indicates whether it was altered, we can detect when no alteration took place, and replace the parsed and expanded value by its original. See Note [Variable expansion in remote schema input parsers] for more information.
argumentsParser :: forall r m n. MonadBuildRemoteSchema r m n => ArgumentsDefinition RemoteSchemaInputValueDefinition -> RemoteSchemaIntrospection -> m (InputFieldsParser n (Altered, HashMap Name (Value RemoteSchemaVariable))) Source #
argumentsParser is used for creating an argument parser for remote fields, This function is called for field arguments and input object fields. This function works in the following way:
- if a field is not preset, we recursively call
inputValueDefinitionParser
on it - otherwise, we use the preset
For example, consider the following input objects:
input MessageWhereInpObj { id: IntCompareObj name: StringCompareObj }
input IntCompareObj { eq : Int @preset(value: 2) gt : Int lt : Int }
parsing a MessageWhereInpObj will result in the following call tree:
- > argumentsParser MessageWhereInpObj
- > id => inputValueDefinitionParser IntCompareObj
- > remoteInputObjectParser IntCompareObj
- > argumentsParser IntCompareObj
- > eq => using preset, no recursion
- > gt => inputValueDefinitionParser Int
- > remoteFieldScalarParser Int
- > lt => inputValueDefinitionParser Int
- > remoteFieldScalarParser Int
- > name => inputValueDefinitionParser StringCompareObj
- > ...
Furthermore, like all other input parsers in this file, argumentsParser
indicates whether this
part of the tree was altered during parsing; if any of the fields is preset, or recursively
contains values that contain presets further down, then this result is labelled as altered.
remoteSchemaRelationships :: forall r n m. MonadBuildRemoteSchema r m n => RemoteSchemaRelationships -> Name -> m [FieldParser n (SchemaRemoteRelationshipSelect (RemoteRelationshipField UnpreparedValue))] Source #
remoteSchemaObject :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> RemoteSchemaRelationships -> ObjectTypeDefinition RemoteSchemaInputValueDefinition -> m (Parser 'Output n (ObjectSelectionSet (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)) Source #
remoteSchemaObject
returns a output parser for a given ObjectTypeDefinition
.
remoteSchemaInterface :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> RemoteSchemaRelationships -> InterfaceTypeDefinition [Name] RemoteSchemaInputValueDefinition -> m (Parser 'Output n (DeduplicatedSelectionSet (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)) Source #
remoteSchemaInterface
returns a output parser for a given InterfaceTypeDefinition
.
Also check Note [Querying remote schema interfaces]
remoteSchemaUnion :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> RemoteSchemaRelationships -> UnionTypeDefinition -> m (Parser 'Output n (DeduplicatedSelectionSet (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)) Source #
remoteSchemaUnion
returns a output parser for a given UnionTypeDefinition
.
remoteFieldFromDefinition :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> Name -> RemoteSchemaRelationships -> FieldDefinition RemoteSchemaInputValueDefinition -> m (FieldParser n (GraphQLField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)) Source #
remoteFieldFromName :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> RemoteSchemaRelationships -> Name -> Name -> Maybe Description -> Name -> ArgumentsDefinition RemoteSchemaInputValueDefinition -> m (FieldParser n (GraphQLField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)) Source #
remoteFieldFromName
accepts a GraphQL name and searches for its definition
in the RemoteSchemaIntrospection
.
remoteField :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> RemoteSchemaRelationships -> Name -> Name -> Maybe Description -> ArgumentsDefinition RemoteSchemaInputValueDefinition -> TypeDefinition [Name] RemoteSchemaInputValueDefinition -> m (FieldParser n (GraphQLField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)) Source #
remoteField
accepts a TypeDefinition
and will returns a FieldParser
for it.
Note that the TypeDefinition
should be of the GraphQL Output
kind, when an
GraphQL Input
kind is provided, then error will be thrown.
getObjectParser :: forall r m n. MonadBuildRemoteSchema r m n => RemoteSchemaIntrospection -> RemoteSchemaRelationships -> (Name -> m (ObjectTypeDefinition RemoteSchemaInputValueDefinition)) -> Name -> m (Parser 'Output n (Name, ObjectSelectionSet (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)) Source #
helper function to get a parser of an object with it's name
This function is called from remoteSchemaInterface
and
remoteSchemaObject
functions. Both of these have a slightly
different implementation of getObject
, which is the
reason getObject
is an argument to this function
customizeRemoteNamespace :: forall n. MonadParse n => RemoteSchemaInfo -> Name -> [FieldParser n (RemoteSchemaRootField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable)] -> [FieldParser n (NamespacedField (RemoteSchemaRootField (RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable))] Source #
withRemoteSchemaCustomization :: forall m r a. (MonadReader r m, Has MkTypename r, Has CustomizeRemoteFieldName r) => RemoteSchemaCustomizer -> m a -> m a Source #