forked from STI/Astroport.ONE
70 lines
2.3 KiB
Python
70 lines
2.3 KiB
Python
|
from typing import Any, Dict, Optional, Union
|
||
|
|
||
|
from ...error import GraphQLError
|
||
|
from ...language import (
|
||
|
OperationTypeDefinitionNode,
|
||
|
OperationType,
|
||
|
SchemaDefinitionNode,
|
||
|
SchemaExtensionNode,
|
||
|
VisitorAction,
|
||
|
SKIP,
|
||
|
)
|
||
|
from ...type import GraphQLObjectType
|
||
|
from . import SDLValidationContext, SDLValidationRule
|
||
|
|
||
|
__all__ = ["UniqueOperationTypesRule"]
|
||
|
|
||
|
|
||
|
class UniqueOperationTypesRule(SDLValidationRule):
|
||
|
"""Unique operation types
|
||
|
|
||
|
A GraphQL document is only valid if it has only one type per operation.
|
||
|
"""
|
||
|
|
||
|
def __init__(self, context: SDLValidationContext):
|
||
|
super().__init__(context)
|
||
|
schema = context.schema
|
||
|
self.defined_operation_types: Dict[
|
||
|
OperationType, OperationTypeDefinitionNode
|
||
|
] = {}
|
||
|
self.existing_operation_types: Dict[
|
||
|
OperationType, Optional[GraphQLObjectType]
|
||
|
] = (
|
||
|
{
|
||
|
OperationType.QUERY: schema.query_type,
|
||
|
OperationType.MUTATION: schema.mutation_type,
|
||
|
OperationType.SUBSCRIPTION: schema.subscription_type,
|
||
|
}
|
||
|
if schema
|
||
|
else {}
|
||
|
)
|
||
|
self.schema = schema
|
||
|
|
||
|
def check_operation_types(
|
||
|
self, node: Union[SchemaDefinitionNode, SchemaExtensionNode], *_args: Any
|
||
|
) -> VisitorAction:
|
||
|
for operation_type in node.operation_types or []:
|
||
|
operation = operation_type.operation
|
||
|
already_defined_operation_type = self.defined_operation_types.get(operation)
|
||
|
|
||
|
if self.existing_operation_types.get(operation):
|
||
|
self.report_error(
|
||
|
GraphQLError(
|
||
|
f"Type for {operation.value} already defined in the schema."
|
||
|
" It cannot be redefined.",
|
||
|
operation_type,
|
||
|
)
|
||
|
)
|
||
|
elif already_defined_operation_type:
|
||
|
self.report_error(
|
||
|
GraphQLError(
|
||
|
f"There can be only one {operation.value} type in schema.",
|
||
|
[already_defined_operation_type, operation_type],
|
||
|
)
|
||
|
)
|
||
|
else:
|
||
|
self.defined_operation_types[operation] = operation_type
|
||
|
return SKIP
|
||
|
|
||
|
enter_schema_definition = enter_schema_extension = check_operation_types
|