From 92042711e4dc4cdfafd4dda66869b5f08b4b5660 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Wed, 21 Jun 2017 15:37:53 +0300 Subject: [PATCH] Add predicates to for built-in types. --- src/index.js | 5 +++ src/type/builtins.js | 23 ++++++++++++++ src/type/directives.js | 5 +++ src/type/index.js | 9 ++++++ src/type/introspection.js | 18 ++++++++++- src/type/scalars.js | 13 ++++++++ src/utilities/buildASTSchema.js | 38 +++-------------------- src/utilities/buildClientSchema.js | 36 ++------------------- src/utilities/schemaPrinter.js | 50 +++++++++--------------------- 9 files changed, 93 insertions(+), 104 deletions(-) create mode 100644 src/type/builtins.js diff --git a/src/index.js b/src/index.js index fa04a8f393..3d1767f81d 100644 --- a/src/index.js +++ b/src/index.js @@ -59,6 +59,7 @@ export { DirectiveLocation, // Scalars + builtInScalars, GraphQLInt, GraphQLFloat, GraphQLString, @@ -80,6 +81,7 @@ export { TypeNameMetaFieldDef, // GraphQL Types for introspection. + introspectionTypes, __Schema, __Directive, __DirectiveLocation, @@ -97,6 +99,9 @@ export { isCompositeType, isAbstractType, isNamedType, + isBuiltInScalar, + isIntrospectionType, + isSpecDirective, // Assertions assertType, diff --git a/src/type/builtins.js b/src/type/builtins.js new file mode 100644 index 0000000000..ccee71cd82 --- /dev/null +++ b/src/type/builtins.js @@ -0,0 +1,23 @@ +/* @flow */ +/** + * Copyright (c) 2017, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +import type { GraphQLNamedType } from './definition'; +import { introspectionTypes } from './introspection'; +import { builtInScalars } from './scalars'; + +export const builtInTypes: Array = [ + ...introspectionTypes, + ...builtInScalars, +]; + +const builtInTypeNames = builtInTypes.map(x => x.name); +export function isBuiltInType(type: GraphQLNamedType): boolean %checks { + return builtInTypeNames.includes(type.name); +} diff --git a/src/type/directives.js b/src/type/directives.js index 88d52b184d..a941a8c800 100644 --- a/src/type/directives.js +++ b/src/type/directives.js @@ -181,3 +181,8 @@ export const specifiedDirectives: Array = [ GraphQLSkipDirective, GraphQLDeprecatedDirective, ]; + +const specifiedDirectivesNames = specifiedDirectives.map(x => x.name); +export function isSpecDirective(directive: GraphQLDirective): boolean %checks { + return specifiedDirectivesNames.includes(directive.name); +} diff --git a/src/type/index.js b/src/type/index.js index 8434530383..f35fcaaffc 100644 --- a/src/type/index.js +++ b/src/type/index.js @@ -45,6 +45,8 @@ export { } from './definition'; export { + isSpecDirective, + // "Enum" of Directive Locations DirectiveLocation, @@ -68,13 +70,18 @@ export { GraphQLString, GraphQLBoolean, GraphQLID, + builtInScalars, + isBuiltInScalar, } from './scalars'; export { + isIntrospectionType, + // "Enum" of Type Kinds TypeKind, // GraphQL Types for introspection. + introspectionTypes, __Schema, __Directive, __DirectiveLocation, @@ -128,3 +135,5 @@ export type { GraphQLTypeResolver, GraphQLUnionTypeConfig, } from './definition'; + +export { builtInTypes, isBuiltInType } from './builtins'; diff --git a/src/type/introspection.js b/src/type/introspection.js index 274875004f..6cb97eddbc 100644 --- a/src/type/introspection.js +++ b/src/type/introspection.js @@ -23,7 +23,7 @@ import { } from './definition'; import { GraphQLString, GraphQLBoolean } from './scalars'; import { DirectiveLocation } from './directives'; -import type { GraphQLField } from './definition'; +import type { GraphQLField, GraphQLNamedType } from './definition'; export const __Schema = new GraphQLObjectType({ @@ -451,3 +451,19 @@ export const TypeNameMetaFieldDef: GraphQLField<*, *> = { args: [], resolve: (source, args, context, { parentType }) => parentType.name }; + +export const introspectionTypes: Array = [ + __Schema, + __Directive, + __DirectiveLocation, + __Type, + __Field, + __InputValue, + __EnumValue, + __TypeKind, +]; + +const introspectionTypeNames = introspectionTypes.map(x => x.name); +export function isIntrospectionType(type: GraphQLNamedType): boolean %checks { + return introspectionTypeNames.includes(type.name); +} diff --git a/src/type/scalars.js b/src/type/scalars.js index 46d636b771..aff4618356 100644 --- a/src/type/scalars.js +++ b/src/type/scalars.js @@ -135,3 +135,16 @@ export const GraphQLID = new GraphQLScalarType({ undefined; } }); + +export const builtInScalars: Array = [ + GraphQLString, + GraphQLInt, + GraphQLFloat, + GraphQLBoolean, + GraphQLID, +]; + +const builtInScalarNames = builtInScalars.map(x => x.name); +export function isBuiltInScalar(type: GraphQLScalarType): boolean %checks { + return builtInScalarNames.includes(type.name); +} diff --git a/src/utilities/buildASTSchema.js b/src/utilities/buildASTSchema.js index 00259d1ea2..7dd0ff92cd 100644 --- a/src/utilities/buildASTSchema.js +++ b/src/utilities/buildASTSchema.js @@ -8,6 +8,7 @@ */ import invariant from '../jsutils/invariant'; +import keyMap from '../jsutils/keyMap'; import keyValMap from '../jsutils/keyValMap'; import type {ObjMap} from '../jsutils/ObjMap'; import { valueFromAST } from './valueFromAST'; @@ -41,14 +42,6 @@ import type { import { GraphQLSchema } from '../type/schema'; -import { - GraphQLString, - GraphQLInt, - GraphQLFloat, - GraphQLBoolean, - GraphQLID, -} from '../type/scalars'; - import { GraphQLScalarType, GraphQLObjectType, @@ -81,16 +74,7 @@ import type { DirectiveLocationEnum } from '../type/directives'; -import { - __Schema, - __Directive, - __DirectiveLocation, - __Type, - __Field, - __InputValue, - __EnumValue, - __TypeKind, -} from '../type/introspection'; +import { builtInTypes } from '../type/builtins'; type Options = {| commentDescriptions?: boolean |}; @@ -260,7 +244,7 @@ export class ASTDefinitionBuilder { _typeDefinitionsMap: TypeDefinitionsMap; _options: ?Options; _resolveType: TypeResolver; - _cache: { [typeName: string]: GraphQLNamedType }; + _cache: ObjMap; constructor( typeDefinitionsMap: TypeDefinitionsMap, @@ -271,21 +255,7 @@ export class ASTDefinitionBuilder { this._options = options; this._resolveType = resolveType; // Initialize to the GraphQL built in scalars and introspection types. - this._cache = { - String: GraphQLString, - Int: GraphQLInt, - Float: GraphQLFloat, - Boolean: GraphQLBoolean, - ID: GraphQLID, - __Schema, - __Directive, - __DirectiveLocation, - __Type, - __Field, - __InputValue, - __EnumValue, - __TypeKind, - }; + this._cache = keyMap(builtInTypes, type => type.name); } _buildType(typeName: string, typeNode?: ?NamedTypeNode): GraphQLNamedType { diff --git a/src/utilities/buildClientSchema.js b/src/utilities/buildClientSchema.js index 2ebddc0d50..4618806030 100644 --- a/src/utilities/buildClientSchema.js +++ b/src/utilities/buildClientSchema.js @@ -27,25 +27,6 @@ import { GraphQLNonNull, } from '../type/definition'; -import { - __Schema, - __Directive, - __DirectiveLocation, - __Type, - __Field, - __InputValue, - __EnumValue, - __TypeKind, -} from '../type/introspection'; - -import { - GraphQLInt, - GraphQLFloat, - GraphQLString, - GraphQLBoolean, - GraphQLID -} from '../type/scalars'; - import { DirectiveLocation, GraphQLDirective } from '../type/directives'; import { TypeKind } from '../type/introspection'; @@ -72,6 +53,7 @@ import type { IntrospectionNamedTypeRef, } from './introspectionQuery'; +import { builtInTypes } from '../type/builtins'; /** * Build a GraphQLSchema for use by client tools. @@ -101,21 +83,7 @@ export function buildClientSchema( // A cache to use to store the actual GraphQLType definition objects by name. // Initialize to the GraphQL built in scalars. All functions below are inline // so that this type def cache is within the scope of the closure. - const typeDefCache = { - String: GraphQLString, - Int: GraphQLInt, - Float: GraphQLFloat, - Boolean: GraphQLBoolean, - ID: GraphQLID, - __Schema, - __Directive, - __DirectiveLocation, - __Type, - __Field, - __InputValue, - __EnumValue, - __TypeKind, - }; + const typeDefCache = keyMap(builtInTypes, type => type.name); // Given a type reference in introspection, return the GraphQLType instance. // preferring cached instances before building new instances. diff --git a/src/utilities/schemaPrinter.js b/src/utilities/schemaPrinter.js index bf8cc1d434..20d9311e4c 100644 --- a/src/utilities/schemaPrinter.js +++ b/src/utilities/schemaPrinter.js @@ -13,7 +13,7 @@ import isInvalid from '../jsutils/isInvalid'; import { astFromValue } from '../utilities/astFromValue'; import { print } from '../language/printer'; import type { GraphQLSchema } from '../type/schema'; -import type { GraphQLType } from '../type/definition'; +import type { GraphQLType, GraphQLNamedType } from '../type/definition'; import { GraphQLScalarType, GraphQLObjectType, @@ -23,7 +23,14 @@ import { GraphQLInputObjectType, } from '../type/definition'; import { GraphQLString } from '../type/scalars'; -import { DEFAULT_DEPRECATION_REASON } from '../type/directives'; +import { + GraphQLDirective, + DEFAULT_DEPRECATION_REASON, + isSpecDirective, +} from '../type/directives'; + +import { isIntrospectionType } from '../type/introspection'; +import { isBuiltInType } from '../type/builtins'; type Options = {| commentDescriptions?: boolean |}; @@ -38,7 +45,7 @@ export function printSchema(schema: GraphQLSchema, options?: Options): string { return printFilteredSchema( schema, n => !isSpecDirective(n), - isDefinedType, + type => !isBuiltInType(type), options ); } @@ -55,45 +62,18 @@ export function printIntrospectionSchema( ); } -function isSpecDirective(directiveName: string): boolean { - return ( - directiveName === 'skip' || - directiveName === 'include' || - directiveName === 'deprecated' - ); -} - -function isDefinedType(typename: string): boolean { - return !isIntrospectionType(typename) && !isBuiltInScalar(typename); -} - -function isIntrospectionType(typename: string): boolean { - return typename.indexOf('__') === 0; -} - -function isBuiltInScalar(typename: string): boolean { - return ( - typename === 'String' || - typename === 'Boolean' || - typename === 'Int' || - typename === 'Float' || - typename === 'ID' - ); -} - function printFilteredSchema( schema: GraphQLSchema, - directiveFilter: (type: string) => boolean, - typeFilter: (type: string) => boolean, + directiveFilter: (type: GraphQLDirective) => boolean, + typeFilter: (type: GraphQLNamedType) => boolean, options ): string { - const directives = schema.getDirectives() - .filter(directive => directiveFilter(directive.name)); + const directives = schema.getDirectives().filter(directiveFilter); const typeMap = schema.getTypeMap(); const types = Object.keys(typeMap) - .filter(typeFilter) .sort((name1, name2) => name1.localeCompare(name2)) - .map(typeName => typeMap[typeName]); + .map(typeName => typeMap[typeName]) + .filter(typeFilter); return [ printSchemaDefinition(schema) ].concat( directives.map(directive => printDirective(directive, options)),