Skip to content

Commit

Permalink
Add Node Predicates
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanGoncharov committed Aug 9, 2018
1 parent bce300f commit 818e878
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 86 deletions.
10 changes: 10 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,16 @@ export {
TokenKind,
DirectiveLocation,
BREAK,
// Predicates
isDefinitionNode,
isExecutableDefinitionNode,
isSelectionNode,
isValueNode,
isTypeNode,
isTypeSystemDefinitionNode,
isTypeDefinitionNode,
isTypeSystemExtensionNode,
isTypeExtensionNode,
} from './language';

export type {
Expand Down
12 changes: 12 additions & 0 deletions src/language/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
34 changes: 13 additions & 21 deletions src/utilities/buildASTSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import type {
StringValueNode,
Location,
} from '../language/ast';
import { isTypeDefinitionNode } from '../language/predicates';

import type { DirectiveLocationEnum } from '../language/directiveLocation';

Expand Down Expand Up @@ -132,27 +133,18 @@ export function buildASTSchema(
const nodeMap: ObjMap<TypeDefinitionNode> = Object.create(null);
const directiveDefs: Array<DirectiveDefinitionNode> = [];
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);
}
}

Expand Down
110 changes: 49 additions & 61 deletions src/utilities/extendSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ import type {
SchemaExtensionNode,
SchemaDefinitionNode,
} from '../language/ast';
import {
isTypeDefinitionNode,
isTypeExtensionNode,
} from '../language/predicates';

type Options = {|
...GraphQLSchemaValidationOptions,
Expand Down Expand Up @@ -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);
}
}

Expand Down
6 changes: 2 additions & 4 deletions src/validation/rules/ExecutableDefinitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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(
Expand Down

0 comments on commit 818e878

Please sign in to comment.