From 7fe9985eeb2237b7d47f560bf8f3a3f06a3c3ae2 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Wed, 16 Jan 2019 18:57:11 +0200 Subject: [PATCH] Remove usage of Flow placeholder argument + cleanup (#1669) --- src/utilities/buildASTSchema.js | 192 ++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 86 deletions(-) diff --git a/src/utilities/buildASTSchema.js b/src/utilities/buildASTSchema.js index f1a8f3b459..076845c6d6 100644 --- a/src/utilities/buildASTSchema.js +++ b/src/utilities/buildASTSchema.js @@ -24,6 +24,7 @@ import { Kind } from '../language/kinds'; import type { DocumentNode, + NameNode, TypeNode, NamedTypeNode, SchemaDefinitionNode, @@ -49,8 +50,9 @@ import type { GraphQLType, GraphQLNamedType, GraphQLFieldConfig, + GraphQLArgumentConfig, GraphQLEnumValueConfig, - GraphQLInputField, + GraphQLInputFieldConfig, } from '../type/definition'; import { @@ -256,17 +258,17 @@ export class ASTDefinitionBuilder { return this.buildType(typeNode); } - buildDirective(directiveNode: DirectiveDefinitionNode): GraphQLDirective { + buildDirective(directive: DirectiveDefinitionNode): GraphQLDirective { + const locations = directive.locations.map( + ({ value }) => ((value: any): DirectiveLocationEnum), + ); + return new GraphQLDirective({ - name: directiveNode.name.value, - description: getDescription(directiveNode, this._options), - locations: directiveNode.locations.map( - node => ((node.value: any): DirectiveLocationEnum), - ), - args: - directiveNode.arguments && - this._makeInputValues(directiveNode.arguments), - astNode: directiveNode, + name: directive.name.value, + description: getDescription(directive, this._options), + locations, + args: keyByNameNode(directive.arguments || [], arg => this.buildArg(arg)), + astNode: directive, }); } @@ -277,19 +279,31 @@ export class ASTDefinitionBuilder { // with validateSchema() will produce more actionable results. type: (this._buildWrappedType(field.type): any), description: getDescription(field, this._options), - args: field.arguments && this._makeInputValues(field.arguments), + args: keyByNameNode(field.arguments || [], arg => this.buildArg(arg)), deprecationReason: getDeprecationReason(field), astNode: field, }; } - buildInputField(value: InputValueDefinitionNode): GraphQLInputField { + buildArg(value: InputValueDefinitionNode): GraphQLArgumentConfig { + // Note: While this could make assertions to get the correctly typed + // value, that would throw immediately while type system validation + // with validateSchema() will produce more actionable results. + const type: any = this._buildWrappedType(value.type); + return { + type, + description: getDescription(value, this._options), + defaultValue: valueFromAST(value.defaultValue, type), + astNode: value, + }; + } + + buildInputField(value: InputValueDefinitionNode): GraphQLInputFieldConfig { // Note: While this could make assertions to get the correctly typed // value, that would throw immediately while type system validation // with validateSchema() will produce more actionable results. const type: any = this._buildWrappedType(value.type); return { - name: value.name.value, type, description: getDescription(value, this._options), defaultValue: valueFromAST(value.defaultValue, type), @@ -305,121 +319,127 @@ export class ASTDefinitionBuilder { }; } - _makeSchemaDef(def: TypeDefinitionNode): GraphQLNamedType { - switch (def.kind) { + _makeSchemaDef(astNode: TypeDefinitionNode): GraphQLNamedType { + switch (astNode.kind) { case Kind.OBJECT_TYPE_DEFINITION: - return this._makeTypeDef(def); + return this._makeTypeDef(astNode); case Kind.INTERFACE_TYPE_DEFINITION: - return this._makeInterfaceDef(def); + return this._makeInterfaceDef(astNode); case Kind.ENUM_TYPE_DEFINITION: - return this._makeEnumDef(def); + return this._makeEnumDef(astNode); case Kind.UNION_TYPE_DEFINITION: - return this._makeUnionDef(def); + return this._makeUnionDef(astNode); case Kind.SCALAR_TYPE_DEFINITION: - return this._makeScalarDef(def); + return this._makeScalarDef(astNode); case Kind.INPUT_OBJECT_TYPE_DEFINITION: - return this._makeInputObjectDef(def); + return this._makeInputObjectDef(astNode); default: - throw new Error(`Type kind "${def.kind}" not supported.`); + throw new Error(`Type kind "${astNode.kind}" not supported.`); } } - _makeTypeDef(def: ObjectTypeDefinitionNode) { - const interfaces: ?$ReadOnlyArray = def.interfaces; + _makeTypeDef(astNode: ObjectTypeDefinitionNode) { + const interfaceNodes = astNode.interfaces; + const fieldNodes = astNode.fields; + + // Note: While this could make assertions to get the correctly typed + // values below, that would throw immediately while type system + // validation with validateSchema() will produce more actionable results. + const interfaces = + interfaceNodes && interfaceNodes.length > 0 + ? () => interfaceNodes.map(ref => (this.buildType(ref): any)) + : []; + + const fields = + fieldNodes && fieldNodes.length > 0 + ? () => keyByNameNode(fieldNodes, field => this.buildField(field)) + : Object.create(null); + return new GraphQLObjectType({ - name: def.name.value, - description: getDescription(def, this._options), - fields: () => this._makeFieldDefMap(def), - // Note: While this could make early assertions to get the correctly - // typed values, that would throw immediately while type system - // validation with validateSchema() will produce more actionable results. - interfaces: interfaces - ? () => interfaces.map(ref => (this.buildType(ref): any)) - : [], - astNode: def, + name: astNode.name.value, + description: getDescription(astNode, this._options), + interfaces, + fields, + astNode, }); } - _makeFieldDefMap( - def: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, - ) { - return def.fields - ? keyValMap<_, GraphQLFieldConfig>( - def.fields, - field => field.name.value, - field => this.buildField(field), - ) - : {}; - } + _makeInterfaceDef(astNode: InterfaceTypeDefinitionNode) { + const fieldNodes = astNode.fields; - _makeInputValues(values: $ReadOnlyArray) { - return keyValMap<_, GraphQLInputField>( - values, - value => value.name.value, - value => this.buildInputField(value), - ); - } + const fields = + fieldNodes && fieldNodes.length > 0 + ? () => keyByNameNode(fieldNodes, field => this.buildField(field)) + : Object.create(null); - _makeInterfaceDef(def: InterfaceTypeDefinitionNode) { return new GraphQLInterfaceType({ - name: def.name.value, - description: getDescription(def, this._options), - fields: () => this._makeFieldDefMap(def), - astNode: def, + name: astNode.name.value, + description: getDescription(astNode, this._options), + fields, + astNode, }); } - _makeEnumDef(def: EnumTypeDefinitionNode) { + _makeEnumDef(astNode: EnumTypeDefinitionNode) { + const valueNodes = astNode.values || []; + return new GraphQLEnumType({ - name: def.name.value, - description: getDescription(def, this._options), - values: this._makeValueDefMap(def), - astNode: def, + name: astNode.name.value, + description: getDescription(astNode, this._options), + values: keyByNameNode(valueNodes, value => this.buildEnumValue(value)), + astNode, }); } - _makeValueDefMap(def: EnumTypeDefinitionNode) { - return def.values - ? keyValMap<_, GraphQLEnumValueConfig>( - def.values, - enumValue => enumValue.name.value, - enumValue => this.buildEnumValue(enumValue), - ) - : {}; - } + _makeUnionDef(astNode: UnionTypeDefinitionNode) { + const typeNodes = astNode.types; + + // Note: While this could make assertions to get the correctly typed + // values below, that would throw immediately while type system + // validation with validateSchema() will produce more actionable results. + const types = + typeNodes && typeNodes.length > 0 + ? () => typeNodes.map(ref => (this.buildType(ref): any)) + : []; - _makeUnionDef(def: UnionTypeDefinitionNode) { - const types: ?$ReadOnlyArray = def.types; return new GraphQLUnionType({ - name: def.name.value, - description: getDescription(def, this._options), - // Note: While this could make assertions to get the correctly typed - // values below, that would throw immediately while type system - // validation with validateSchema() will produce more actionable results. - types: types ? () => types.map(ref => (this.buildType(ref): any)) : [], - astNode: def, + name: astNode.name.value, + description: getDescription(astNode, this._options), + types, + astNode, }); } - _makeScalarDef(def: ScalarTypeDefinitionNode) { + _makeScalarDef(astNode: ScalarTypeDefinitionNode) { return new GraphQLScalarType({ - name: def.name.value, - description: getDescription(def, this._options), - astNode: def, + name: astNode.name.value, + description: getDescription(astNode, this._options), + astNode, serialize: value => value, }); } _makeInputObjectDef(def: InputObjectTypeDefinitionNode) { + const { fields } = def; + return new GraphQLInputObjectType({ name: def.name.value, description: getDescription(def, this._options), - fields: () => (def.fields ? this._makeInputValues(def.fields) : {}), + fields: fields + ? () => keyByNameNode(fields, field => this.buildInputField(field)) + : Object.create(null), astNode: def, }); } } +function keyByNameNode( + list: $ReadOnlyArray, + valFn: (item: T) => V, +): ObjMap { + return keyValMap(list, ({ name }) => name.value, valFn); +} + /** * Given a field or enum value node, returns the string value for the * deprecation reason.