From 818e878f5d1b38d5e086d7b525c066ffa96be950 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Thu, 9 Aug 2018 17:38:40 +0300 Subject: [PATCH] Add Node Predicates --- src/index.js | 10 ++ src/language/index.js | 12 ++ src/utilities/buildASTSchema.js | 34 +++--- src/utilities/extendSchema.js | 110 ++++++++---------- src/validation/rules/ExecutableDefinitions.js | 6 +- 5 files changed, 86 insertions(+), 86 deletions(-) diff --git a/src/index.js b/src/index.js index 2dd2bbb133c..7a8a2f69812 100644 --- a/src/index.js +++ b/src/index.js @@ -189,6 +189,16 @@ export { TokenKind, DirectiveLocation, BREAK, + // Predicates + isDefinitionNode, + isExecutableDefinitionNode, + isSelectionNode, + isValueNode, + isTypeNode, + isTypeSystemDefinitionNode, + isTypeDefinitionNode, + isTypeSystemExtensionNode, + isTypeExtensionNode, } from './language'; export type { diff --git a/src/language/index.js b/src/language/index.js index e49e8917d15..8054718aa91 100644 --- a/src/language/index.js +++ b/src/language/index.js @@ -88,5 +88,17 @@ export type { InputObjectTypeExtensionNode, } from './ast'; +export { + isDefinitionNode, + isExecutableDefinitionNode, + isSelectionNode, + isValueNode, + isTypeNode, + isTypeSystemDefinitionNode, + isTypeDefinitionNode, + isTypeSystemExtensionNode, + isTypeExtensionNode, +} from './predicates'; + export { DirectiveLocation } from './directiveLocation'; export type { DirectiveLocationEnum } from './directiveLocation'; diff --git a/src/utilities/buildASTSchema.js b/src/utilities/buildASTSchema.js index 8b79af1c318..2319e740b37 100644 --- a/src/utilities/buildASTSchema.js +++ b/src/utilities/buildASTSchema.js @@ -40,6 +40,7 @@ import type { StringValueNode, Location, } from '../language/ast'; +import { isTypeDefinitionNode } from '../language/predicates'; import type { DirectiveLocationEnum } from '../language/directiveLocation'; @@ -132,27 +133,18 @@ export function buildASTSchema( const nodeMap: ObjMap = Object.create(null); const directiveDefs: Array = []; for (let i = 0; i < documentAST.definitions.length; i++) { - const d = documentAST.definitions[i]; - switch (d.kind) { - case Kind.SCHEMA_DEFINITION: - schemaDef = d; - break; - case Kind.SCALAR_TYPE_DEFINITION: - case Kind.OBJECT_TYPE_DEFINITION: - case Kind.INTERFACE_TYPE_DEFINITION: - case Kind.ENUM_TYPE_DEFINITION: - case Kind.UNION_TYPE_DEFINITION: - case Kind.INPUT_OBJECT_TYPE_DEFINITION: - const typeName = d.name.value; - if (nodeMap[typeName]) { - throw new Error(`Type "${typeName}" was defined more than once.`); - } - typeDefs.push(d); - nodeMap[typeName] = d; - break; - case Kind.DIRECTIVE_DEFINITION: - directiveDefs.push(d); - break; + const def = documentAST.definitions[i]; + if (def.kind === Kind.SCHEMA_DEFINITION) { + schemaDef = def; + } else if (isTypeDefinitionNode(def)) { + const typeName = def.name.value; + if (nodeMap[typeName]) { + throw new Error(`Type "${typeName}" was defined more than once.`); + } + typeDefs.push(def); + nodeMap[typeName] = def; + } else if (def.kind === Kind.DIRECTIVE_DEFINITION) { + directiveDefs.push(def); } } diff --git a/src/utilities/extendSchema.js b/src/utilities/extendSchema.js index 7be0a0d2c02..ffe0f9ed401 100644 --- a/src/utilities/extendSchema.js +++ b/src/utilities/extendSchema.js @@ -56,6 +56,10 @@ import type { SchemaExtensionNode, SchemaDefinitionNode, } from '../language/ast'; +import { + isTypeDefinitionNode, + isTypeExtensionNode, +} from '../language/predicates'; type Options = {| ...GraphQLSchemaValidationOptions, @@ -125,67 +129,51 @@ export function extendSchema( for (let i = 0; i < documentAST.definitions.length; i++) { const def = documentAST.definitions[i]; - switch (def.kind) { - case Kind.SCHEMA_DEFINITION: - schemaDef = def; - break; - case Kind.SCHEMA_EXTENSION: - schemaExtensions.push(def); - break; - case Kind.OBJECT_TYPE_DEFINITION: - case Kind.INTERFACE_TYPE_DEFINITION: - case Kind.ENUM_TYPE_DEFINITION: - case Kind.UNION_TYPE_DEFINITION: - case Kind.SCALAR_TYPE_DEFINITION: - case Kind.INPUT_OBJECT_TYPE_DEFINITION: - // Sanity check that none of the defined types conflict with the - // schema's existing types. - const typeName = def.name.value; - if (schema.getType(typeName)) { - throw new GraphQLError( - `Type "${typeName}" already exists in the schema. It cannot also ` + - 'be defined in this type definition.', - [def], - ); - } - typeDefinitionMap[typeName] = def; - break; - case Kind.SCALAR_TYPE_EXTENSION: - case Kind.OBJECT_TYPE_EXTENSION: - case Kind.INTERFACE_TYPE_EXTENSION: - case Kind.ENUM_TYPE_EXTENSION: - case Kind.INPUT_OBJECT_TYPE_EXTENSION: - case Kind.UNION_TYPE_EXTENSION: - // Sanity check that this type extension exists within the - // schema's existing types. - const extendedTypeName = def.name.value; - const existingType = schema.getType(extendedTypeName); - if (!existingType) { - throw new GraphQLError( - `Cannot extend type "${extendedTypeName}" because it does not ` + - 'exist in the existing schema.', - [def], - ); - } - checkExtensionNode(existingType, def); - - const existingTypeExtensions = typeExtensionsMap[extendedTypeName]; - typeExtensionsMap[extendedTypeName] = existingTypeExtensions - ? existingTypeExtensions.concat([def]) - : [def]; - break; - case Kind.DIRECTIVE_DEFINITION: - const directiveName = def.name.value; - const existingDirective = schema.getDirective(directiveName); - if (existingDirective) { - throw new GraphQLError( - `Directive "${directiveName}" already exists in the schema. It ` + - 'cannot be redefined.', - [def], - ); - } - directiveDefinitions.push(def); - break; + if (def.kind === Kind.SCHEMA_DEFINITION) { + schemaDef = def; + } else if (def.kind === Kind.SCHEMA_EXTENSION) { + schemaExtensions.push(def); + } else if (isTypeDefinitionNode(def)) { + // Sanity check that none of the defined types conflict with the + // schema's existing types. + const typeName = def.name.value; + if (schema.getType(typeName)) { + throw new GraphQLError( + `Type "${typeName}" already exists in the schema. It cannot also ` + + 'be defined in this type definition.', + [def], + ); + } + typeDefinitionMap[typeName] = def; + } else if (isTypeExtensionNode(def)) { + // Sanity check that this type extension exists within the + // schema's existing types. + const extendedTypeName = def.name.value; + const existingType = schema.getType(extendedTypeName); + if (!existingType) { + throw new GraphQLError( + `Cannot extend type "${extendedTypeName}" because it does not ` + + 'exist in the existing schema.', + [def], + ); + } + checkExtensionNode(existingType, def); + + const existingTypeExtensions = typeExtensionsMap[extendedTypeName]; + typeExtensionsMap[extendedTypeName] = existingTypeExtensions + ? existingTypeExtensions.concat([def]) + : [def]; + } else if (def.kind === Kind.DIRECTIVE_DEFINITION) { + const directiveName = def.name.value; + const existingDirective = schema.getDirective(directiveName); + if (existingDirective) { + throw new GraphQLError( + `Directive "${directiveName}" already exists in the schema. It ` + + 'cannot be redefined.', + [def], + ); + } + directiveDefinitions.push(def); } } diff --git a/src/validation/rules/ExecutableDefinitions.js b/src/validation/rules/ExecutableDefinitions.js index 188bbbcb291..4c5cca6de2a 100644 --- a/src/validation/rules/ExecutableDefinitions.js +++ b/src/validation/rules/ExecutableDefinitions.js @@ -10,6 +10,7 @@ import type { ASTValidationContext } from '../ValidationContext'; import { GraphQLError } from '../../error'; import { Kind } from '../../language/kinds'; +import { isExecutableDefinitionNode } from '../../language/predicates'; import type { ASTVisitor } from '../../language/visitor'; export function nonExecutableDefinitionMessage(defName: string): string { @@ -28,10 +29,7 @@ export function ExecutableDefinitions( return { Document(node) { for (const definition of node.definitions) { - if ( - definition.kind !== Kind.OPERATION_DEFINITION && - definition.kind !== Kind.FRAGMENT_DEFINITION - ) { + if (!isExecutableDefinitionNode(node)) { context.reportError( new GraphQLError( nonExecutableDefinitionMessage(