text: import base64
  from datetime import timedelta, datetime, timezone
  from moto.core import ACCOUNT_ID, BaseBackend, BaseModel
  from moto.core.utils import BackendDict, unix_time
  from moto.utilities.tagging_service import TaggingService
  
  from uuid import uuid4
  
  from .exceptions import GraphqlAPINotFound
  
  
  class GraphqlSchema(BaseModel):
      def __init__(self, definition):
          self.definition = definition
          # [graphql.language.ast.ObjectTypeDefinitionNode, ..]
          self.types = []
  
          self.status = "PROCESSING"
          self.parse_error = None
          self._parse_graphql_definition()
  
      def get_type(self, name):
          for graphql_type in self.types:
              if graphql_type.name.value == name:
                  return {
                      "name": name,
                      "description": graphql_type.description.value
                      if graphql_type.description
                      else None,
                      "arn": f"arn:aws:appsync:graphql_type/{name}",
                      "definition": "NotYetImplemented",
                  }
  
      def get_status(self):
          return self.status, self.parse_error
  
      def _parse_graphql_definition(self):
          try:
              from graphql import parse
              from graphql.language.ast import ObjectTypeDefinitionNode
              from graphql.error.graphql_error import GraphQLError
  
              res = parse(self.definition)
              for definition in res.definitions:
                  if isinstance(definition, ObjectTypeDefinitionNode):
                      self.types.append(definition)
              self.status = "SUCCESS"
          except GraphQLError as e:
              self.status = "FAILED"
              self.parse_error = str(e)
  
  
  class GraphqlAPI(BaseModel):
      def __init__(
          self,
          region,
          name,
          authentication_type,
          additional_authentication_providers,
          log_config,
          xray_enabled,
          user_pool_config,
          open_id_connect_config,
          lambda_authorizer_config,
      ):
          self.region = region
          self.name = name
          self.api_id = str(uuid4())
          self.authentication_type = authentication_type
          self.additional_authentication_providers = additional_authentication_providers
          self.lambda_authorizer_config = lambda_authorizer_config
          self.log_config = log_config
          self.open_id_connect_config = open_id_connect_config
          self.user_pool_config = user_pool_config
          self.xray_enabled = xray_enabled
  
          self.arn = f"arn:aws:appsync:{self.region}:{ACCOUNT_ID}:apis/{self.api_id}"
          self.graphql_schema = None
  
          self.api_keys = dict()
  
      def update(
          self,
          name,
          additional_authentication_providers,
          authentication_type,
          lambda_authorizer_config,
          log_config,
          open_id_connect_config,
          user_pool_config,
          xray_enabled,
      ):
          if name:
              self.name = name
          if additional_authentication_providers:
              self.additional_authentication_providers = (
                  additional_authentication_providers
              )
          if authentication_type:
              self.authentication_type = authentication_type
          if lambda_authorizer_config:
              self.lambda_authorizer_config = lambda_authorizer_config
          if log_config:
              self.log_config = log_config
          if open_id_connect_config:
              self.open_id_connect_config = open_id_connect_config
          if user_pool_config:
              self.user_pool_config = user_pool_config
          if xray_enabled is not None:
              self.xray_enabled = xray_enabled
  
      def create_api_key(self, description, expires):
          api_key = GraphqlAPIKey(description, expires)
          self.api_keys[api_key.key_id] = api_key
          return api_key
  
      def list_api_keys(self):
          return self.api_keys.values()
  
      def delete_api_key(self, api_key_id):
          self.api_keys.pop(api_key_id)
  
      def update_api_key(self, api_key_id, description, expires):
          api_key = self.api_keys[api_key_id]
          api_key.update(description, expires)
          return api_key
  
      def start_schema_creation(self, definition):
          graphql_definition = base64.b64decode(definition).decode("utf-8")
  
          self.graphql_schema = GraphqlSchema(graphql_definition)
  
      def get_schema_status(self):
          return self.graphql_schema.get_status()
  
      def get_type(self, type_name, type_format):
          graphql_type = self.graphql_schema.get_type(type_name)
          graphql_type["format"] = type_format
          return graphql_type
  
      def to_json(self):
          return {
              "name": self.name,
              "apiId": self.api_id,
              "authenticationType": self.authentication_type,
              "arn": self.arn,
              "uris": {"GRAPHQL": "http://graphql.uri"},
              "additionalAuthenticationProviders": self.additional_authentication_providers,
              "lambdaAuthorizerConfig": self.lambda_authorizer_config,
              "logConfig": self.log_config,
              "openIDConnectConfig": self.open_id_connect_config,
              "userPoolConfig": self.user_pool_config,
              "xrayEnabled": self.xray_enabled,
          }
  
  
  class GraphqlAPIKey(BaseModel):
      def __init__(self, description, expires):
          self.key_id = str(uuid4())[0:6]
          self.description = description
          self.expires = expires
          if not self.expires:
              default_expiry = datetime.now(timezone.utc)
              default_expiry = default_expiry.replace(
                  minute=0, second=0, microsecond=0, tzinfo=None
              )
              default_expiry = default_expiry + timedelta(days=7)
              self.expires = unix_time(default_expiry)
  
      def update(self, description, expires):
          if description:
              self.description = description
          if expires:
              self.expires = expires
  
      def to_json(self):
          return {
              "id": self.key_id,
              "description": self.description,
              "expires": self.expires,
              "deletes": self.expires,
          }
  
  
  class AppSyncBackend(BaseBackend):
      """Implementation of AppSync APIs."""
  
      def __init__(self, region_name=None):
          self.region_name = region_name
          self.graphql_apis = dict()
          self.tagger = TaggingService()
  
      def reset(self):
          """Re-initialize all attributes for this instance."""
          region_name = self.region_name
          self.__dict__ = {}
          self.__init__(region_name)
  
      def create_graphql_api(
          self,
          name,
          log_config,
          authentication_type,
          user_pool_config,
          open_id_connect_config,
          additional_authentication_providers,
          xray_enabled,
          lambda_authorizer_config,
          tags,
      ):
          graphql_api = GraphqlAPI(
              region=self.region_name,
              name=name,
              authentication_type=authentication_type,
              additional_authentication_providers=additional_authentication_providers,
              log_config=log_config,
              xray_enabled=xray_enabled,
              user_pool_config=user_pool_config,
              open_id_connect_config=open_id_connect_config,
              lambda_authorizer_config=lambda_authorizer_config,
          )
          self.graphql_apis[graphql_api.api_id] = graphql_api
          self.tagger.tag_resource(
              graphql_api.arn, TaggingService.convert_dict_to_tags_input(tags)
          )
          return graphql_api
  
      def update_graphql_api(
          self,
          api_id,
          name,
          log_config,
          authentication_type,
          user_pool_config,
          open_id_connect_config,
          additional_authentication_providers,
          xray_enabled,
          lambda_authorizer_config,
      ):
          graphql_api = self.graphql_apis[api_id]
          graphql_api.update(
              name,
              additional_authentication_providers,
              authentication_type,
              lambda_authorizer_config,
              log_config,
              open_id_connect_config,
              user_pool_config,
              xray_enabled,
          )
          return graphql_api
  
      def get_graphql_api(self, api_id):
          if api_id not in self.graphql_apis:
              raise GraphqlAPINotFound(api_id)
          return self.graphql_apis[api_id]
  
      def delete_graphql_api(self, api_id):
          self.graphql_apis.pop(api_id)
  
      def list_graphql_apis(self):
          """
          Pagination or the maxResults-parameter have not yet been implemented.
          """
          return self.graphql_apis.values()
  
      def create_api_key(self, api_id, description, expires):
          return self.graphql_apis[api_id].create_api_key(description, expires)
  
      def delete_api_key(self, api_id, api_key_id):
          self.graphql_apis[api_id].delete_api_key(api_key_id)
  
      def list_api_keys(self, api_id):
          """
          Pagination or the maxResults-parameter have not yet been implemented.
          """
          if api_id in self.graphql_apis:
              return self.graphql_apis[api_id].list_api_keys()
          else:
              return []
  
      def update_api_key(self, api_id, api_key_id, description, expires):
          return self.graphql_apis[api_id].update_api_key(
              api_key_id, description, expires
          )
  
      def start_schema_creation(self, api_id, definition):
          self.graphql_apis[api_id].start_schema_creation(definition)
          return "PROCESSING"
  
      def get_schema_creation_status(self, api_id):
          return self.graphql_apis[api_id].get_schema_status()
  
      def tag_resource(self, resource_arn, tags):
          self.tagger.tag_resource(
              resource_arn, TaggingService.convert_dict_to_tags_input(tags)
          )
  
      def untag_resource(self, resource_arn, tag_keys):
          self.tagger.untag_resource_using_names(resource_arn, tag_keys)
  
      def list_tags_for_resource(self, resource_arn):
          return self.tagger.get_tag_dict_for_resource(resource_arn)
  
      def get_type(self, api_id, type_name, type_format):
          return self.graphql_apis[api_id].get_type(type_name, type_format)
  
  
  appsync_backends = BackendDict(AppSyncBackend, "appsync")
  