diff --git a/src/index.d.ts b/src/index.d.ts index ac935945c5..317602293e 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -94,6 +94,7 @@ export { isWrappingType, isNullableType, isNamedType, + isRequiredInput, isRequiredArgument, isRequiredInputField, isSpecifiedScalarType, @@ -148,6 +149,8 @@ export { GraphQLArgument, GraphQLArgumentConfig, GraphQLArgumentExtensions, + GraphQLInputValue, + GraphQLInputValueConfig, GraphQLEnumTypeConfig, GraphQLEnumTypeExtensions, GraphQLEnumValue, @@ -157,14 +160,12 @@ export { GraphQLField, GraphQLFieldConfig, GraphQLFieldExtensions, - GraphQLFieldConfigArgumentMap, GraphQLFieldConfigMap, GraphQLFieldMap, GraphQLFieldResolver, GraphQLInputField, GraphQLInputFieldConfig, GraphQLInputFieldExtensions, - GraphQLInputFieldConfigMap, GraphQLInputFieldMap, GraphQLInputObjectTypeConfig, GraphQLInputObjectTypeExtensions, diff --git a/src/index.js b/src/index.js index 1e6b3f247a..b46f10cd3a 100644 --- a/src/index.js +++ b/src/index.js @@ -93,6 +93,7 @@ export { isWrappingType, isNullableType, isNamedType, + isRequiredInput, isRequiredArgument, isRequiredInputField, isSpecifiedScalarType, @@ -144,19 +145,19 @@ export type { GraphQLDirectiveConfig, GraphQLArgument, GraphQLArgumentConfig, + GraphQLInputValue, + GraphQLInputValueConfig, GraphQLEnumTypeConfig, GraphQLEnumValue, GraphQLEnumValueConfig, GraphQLEnumValueConfigMap, GraphQLField, GraphQLFieldConfig, - GraphQLFieldConfigArgumentMap, GraphQLFieldConfigMap, GraphQLFieldMap, GraphQLFieldResolver, GraphQLInputField, GraphQLInputFieldConfig, - GraphQLInputFieldConfigMap, GraphQLInputFieldMap, GraphQLInputObjectTypeConfig, GraphQLInterfaceTypeConfig, diff --git a/src/type/__tests__/predicate-test.js b/src/type/__tests__/predicate-test.js index f94bed1030..899752864c 100644 --- a/src/type/__tests__/predicate-test.js +++ b/src/type/__tests__/predicate-test.js @@ -49,8 +49,7 @@ import { isWrappingType, isNullableType, isNamedType, - isRequiredArgument, - isRequiredInputField, + isRequiredInput, assertType, assertScalarType, assertObjectType, @@ -562,7 +561,7 @@ describe('Type predicates', () => { }); }); - describe('isRequiredArgument', () => { + describe('isRequiredInput', () => { function buildArg(config: {| type: GraphQLInputType, defaultValue?: mixed, @@ -582,35 +581,33 @@ describe('Type predicates', () => { const requiredArg = buildArg({ type: new GraphQLNonNull(GraphQLString), }); - expect(isRequiredArgument(requiredArg)).to.equal(true); + expect(isRequiredInput(requiredArg)).to.equal(true); }); it('returns false for optional arguments', () => { const optArg1 = buildArg({ type: GraphQLString, }); - expect(isRequiredArgument(optArg1)).to.equal(false); + expect(isRequiredInput(optArg1)).to.equal(false); const optArg2 = buildArg({ type: GraphQLString, defaultValue: null, }); - expect(isRequiredArgument(optArg2)).to.equal(false); + expect(isRequiredInput(optArg2)).to.equal(false); const optArg3 = buildArg({ type: new GraphQLList(new GraphQLNonNull(GraphQLString)), }); - expect(isRequiredArgument(optArg3)).to.equal(false); + expect(isRequiredInput(optArg3)).to.equal(false); const optArg4 = buildArg({ type: new GraphQLNonNull(GraphQLString), defaultValue: 'default', }); - expect(isRequiredArgument(optArg4)).to.equal(false); + expect(isRequiredInput(optArg4)).to.equal(false); }); - }); - describe('isRequiredInputField', () => { function buildInputField(config: {| type: GraphQLInputType, defaultValue?: mixed, @@ -630,31 +627,31 @@ describe('Type predicates', () => { const requiredField = buildInputField({ type: new GraphQLNonNull(GraphQLString), }); - expect(isRequiredInputField(requiredField)).to.equal(true); + expect(isRequiredInput(requiredField)).to.equal(true); }); it('returns false for optional input field', () => { const optField1 = buildInputField({ type: GraphQLString, }); - expect(isRequiredInputField(optField1)).to.equal(false); + expect(isRequiredInput(optField1)).to.equal(false); const optField2 = buildInputField({ type: GraphQLString, defaultValue: null, }); - expect(isRequiredInputField(optField2)).to.equal(false); + expect(isRequiredInput(optField2)).to.equal(false); const optField3 = buildInputField({ type: new GraphQLList(new GraphQLNonNull(GraphQLString)), }); - expect(isRequiredInputField(optField3)).to.equal(false); + expect(isRequiredInput(optField3)).to.equal(false); const optField4 = buildInputField({ type: new GraphQLNonNull(GraphQLString), defaultValue: 'default', }); - expect(isRequiredInputField(optField4)).to.equal(false); + expect(isRequiredInput(optField4)).to.equal(false); }); }); }); diff --git a/src/type/definition.d.ts b/src/type/definition.d.ts index c520340b0e..f07202d91a 100644 --- a/src/type/definition.d.ts +++ b/src/type/definition.d.ts @@ -441,10 +441,6 @@ export class GraphQLObjectType { get [Symbol.toStringTag](): string; } -export function argsToArgsConfig( - args: ReadonlyArray, -): GraphQLFieldConfigArgumentMap; - export interface GraphQLObjectTypeConfig { name: string; description?: Maybe; @@ -520,7 +516,7 @@ export interface GraphQLFieldConfig< > { description?: Maybe; type: GraphQLOutputType; - args?: GraphQLFieldConfigArgumentMap; + args?: ObjMap; resolve?: GraphQLFieldResolver; subscribe?: GraphQLFieldResolver; deprecationReason?: Maybe; @@ -530,8 +526,6 @@ export interface GraphQLFieldConfig< astNode?: Maybe; } -export type GraphQLFieldConfigArgumentMap = ObjMap; - /** * Custom extensions * @@ -545,14 +539,7 @@ export interface GraphQLArgumentExtensions { [attributeName: string]: unknown; } -export interface GraphQLArgumentConfig { - description?: Maybe; - type: GraphQLInputType; - defaultValue?: unknown; - deprecationReason?: Maybe; - extensions?: Maybe>; - astNode?: Maybe; -} +export type GraphQLArgumentConfig = GraphQLInputValueConfig; export type GraphQLFieldConfigMap = ObjMap< GraphQLFieldConfig @@ -574,21 +561,34 @@ export interface GraphQLField< astNode?: Maybe; } -export interface GraphQLArgument { +export type GraphQLArgument = GraphQLInputValue; + +export function isRequiredArgument(arg: GraphQLArgument): boolean; + +export type GraphQLFieldMap = ObjMap< + GraphQLField +>; + +export function isRequiredInput(input: GraphQLInputValue): boolean; + +export interface GraphQLInputValue { name: string; description: Maybe; type: GraphQLInputType; defaultValue: unknown; deprecationReason: Maybe; - extensions: Maybe>; + extensions: Maybe>; astNode: Maybe; } -export function isRequiredArgument(arg: GraphQLArgument): boolean; - -export type GraphQLFieldMap = ObjMap< - GraphQLField ->; +export interface GraphQLInputValueConfig { + description?: Maybe; + type: GraphQLInputType; + defaultValue?: unknown; + deprecationReason?: Maybe; + extensions?: Maybe>; + astNode?: Maybe; +} /** * Custom extensions @@ -883,7 +883,7 @@ export class GraphQLInputObjectType { getFields(): GraphQLInputFieldMap; toConfig(): GraphQLInputObjectTypeConfig & { - fields: GraphQLInputFieldConfigMap; + fields: ObjMap; extensions: Maybe>; extensionASTNodes: ReadonlyArray; }; @@ -913,29 +913,12 @@ export interface GraphQLInputObjectTypeConfig { * an object which can contain all the values you need. */ export interface GraphQLInputFieldExtensions { - [attributeName: string]: any; -} - -export interface GraphQLInputFieldConfig { - description?: Maybe; - type: GraphQLInputType; - defaultValue?: unknown; - deprecationReason?: Maybe; - extensions?: Maybe>; - astNode?: Maybe; + [attributeName: string]: unknown; } -export type GraphQLInputFieldConfigMap = ObjMap; +export type GraphQLInputFieldConfig = GraphQLInputValueConfig; -export interface GraphQLInputField { - name: string; - description?: Maybe; - type: GraphQLInputType; - defaultValue?: unknown; - deprecationReason: Maybe; - extensions: Maybe>; - astNode?: Maybe; -} +export type GraphQLInputField = GraphQLInputValue; export function isRequiredInputField(field: GraphQLInputField): boolean; diff --git a/src/type/definition.js b/src/type/definition.js index 7abdc25b0a..c16433d5b3 100644 --- a/src/type/definition.js +++ b/src/type/definition.js @@ -821,7 +821,9 @@ function defineFieldMap( name: fieldName, description: fieldConfig.description, type: fieldConfig.type, - args: defineArguments(argsConfig), + args: Object.entries(argsConfig).map(([argName, argConfig]) => + defineInputValue(argConfig, argName), + ), resolve: fieldConfig.resolve, subscribe: fieldConfig.subscribe, deprecationReason: fieldConfig.deprecationReason, @@ -831,20 +833,6 @@ function defineFieldMap( }); } -export function defineArguments( - config: GraphQLFieldConfigArgumentMap, -): $ReadOnlyArray { - return Object.entries(config).map(([argName, argConfig]) => ({ - name: argName, - description: argConfig.description, - type: argConfig.type, - defaultValue: argConfig.defaultValue, - deprecationReason: argConfig.deprecationReason, - extensions: argConfig.extensions && toObjMap(argConfig.extensions), - astNode: argConfig.astNode, - })); -} - function isPlainObj(obj: mixed): boolean { return isObjectLike(obj) && !Array.isArray(obj); } @@ -855,7 +843,7 @@ function fieldsToFieldsConfig( return mapValue(fields, (field) => ({ description: field.description, type: field.type, - args: argsToArgsConfig(field.args), + args: keyValMap(field.args, (arg) => arg.name, inputValueToConfig), resolve: field.resolve, subscribe: field.subscribe, deprecationReason: field.deprecationReason, @@ -864,26 +852,6 @@ function fieldsToFieldsConfig( })); } -/** - * @internal - */ -export function argsToArgsConfig( - args: $ReadOnlyArray, -): GraphQLFieldConfigArgumentMap { - return keyValMap( - args, - (arg) => arg.name, - (arg) => ({ - description: arg.description, - type: arg.type, - defaultValue: arg.defaultValue, - deprecationReason: arg.deprecationReason, - extensions: arg.extensions, - astNode: arg.astNode, - }), - ); -} - export type GraphQLObjectTypeConfig = {| name: string, description?: ?string, @@ -950,7 +918,7 @@ export type GraphQLFieldConfig< > = {| description?: ?string, type: GraphQLOutputType, - args?: GraphQLFieldConfigArgumentMap, + args?: ObjMap, resolve?: GraphQLFieldResolver, subscribe?: GraphQLFieldResolver, deprecationReason?: ?string, @@ -958,16 +926,7 @@ export type GraphQLFieldConfig< astNode?: ?FieldDefinitionNode, |}; -export type GraphQLFieldConfigArgumentMap = ObjMap; - -export type GraphQLArgumentConfig = {| - description?: ?string, - type: GraphQLInputType, - defaultValue?: mixed, - extensions?: ?ReadOnlyObjMapLike, - deprecationReason?: ?string, - astNode?: ?InputValueDefinitionNode, -|}; +export type GraphQLArgumentConfig = GraphQLInputValueConfig; export type GraphQLFieldConfigMap = ObjMap< GraphQLFieldConfig, @@ -989,7 +948,57 @@ export type GraphQLField< astNode: ?FieldDefinitionNode, |}; -export type GraphQLArgument = {| +export type GraphQLArgument = GraphQLInputValue; + +export const isRequiredArgument = isRequiredInput; + +export type GraphQLFieldMap = ObjMap< + GraphQLField, +>; + +export function isRequiredInput(input: GraphQLInputValue): boolean %checks { + return isNonNullType(input.type) && input.defaultValue === undefined; +} + +/** + * @internal + */ +export function defineInputValue( + config: GraphQLInputValueConfig, + name: string, +): GraphQLInputValue { + devAssert( + !('resolve' in config), + `${name} has a resolve property, but inputs cannot define resolvers.`, + ); + return { + name, + description: config.description, + type: config.type, + defaultValue: config.defaultValue, + deprecationReason: config.deprecationReason, + extensions: config.extensions && toObjMap(config.extensions), + astNode: config.astNode, + }; +} + +/** + * @internal + */ +export function inputValueToConfig( + inputValue: GraphQLInputValue, +): GraphQLInputValueConfig { + return { + description: inputValue.description, + type: inputValue.type, + defaultValue: inputValue.defaultValue, + deprecationReason: inputValue.deprecationReason, + extensions: inputValue.extensions, + astNode: inputValue.astNode, + }; +} + +export type GraphQLInputValue = {| name: string, description: ?string, type: GraphQLInputType, @@ -999,13 +1008,14 @@ export type GraphQLArgument = {| astNode: ?InputValueDefinitionNode, |}; -export function isRequiredArgument(arg: GraphQLArgument): boolean %checks { - return isNonNullType(arg.type) && arg.defaultValue === undefined; -} - -export type GraphQLFieldMap = ObjMap< - GraphQLField, ->; +export type GraphQLInputValueConfig = {| + description?: ?string, + type: GraphQLInputType, + defaultValue?: mixed, + deprecationReason?: ?string, + extensions?: ?ReadOnlyObjMapLike, + astNode?: ?InputValueDefinitionNode, +|}; /** * Interface Type Definition @@ -1497,18 +1507,10 @@ export class GraphQLInputObjectType { } toConfig(): GraphQLInputObjectTypeNormalizedConfig { - const fields = mapValue(this.getFields(), (field) => ({ - description: field.description, - type: field.type, - defaultValue: field.defaultValue, - extensions: field.extensions, - astNode: field.astNode, - })); - return { name: this.name, description: this.description, - fields, + fields: mapValue(this.getFields(), inputValueToConfig), extensions: this.extensions, astNode: this.astNode, extensionASTNodes: this.extensionASTNodes, @@ -1542,16 +1544,7 @@ function defineInputFieldMap( !('resolve' in fieldConfig), `${config.name}.${fieldName} field has a resolve property, but Input Types cannot define resolvers.`, ); - - return { - name: fieldName, - description: fieldConfig.description, - type: fieldConfig.type, - defaultValue: fieldConfig.defaultValue, - deprecationReason: fieldConfig.deprecationReason, - extensions: fieldConfig.extensions && toObjMap(fieldConfig.extensions), - astNode: fieldConfig.astNode, - }; + return defineInputValue(fieldConfig, fieldName); }); } @@ -1566,36 +1559,15 @@ export type GraphQLInputObjectTypeConfig = {| type GraphQLInputObjectTypeNormalizedConfig = {| ...GraphQLInputObjectTypeConfig, - fields: GraphQLInputFieldConfigMap, + fields: ObjMap, extensions: ?ReadOnlyObjMap, extensionASTNodes: $ReadOnlyArray, |}; -export type GraphQLInputFieldConfig = {| - description?: ?string, - type: GraphQLInputType, - defaultValue?: mixed, - deprecationReason?: ?string, - extensions?: ?ReadOnlyObjMapLike, - astNode?: ?InputValueDefinitionNode, -|}; +export type GraphQLInputFieldConfig = GraphQLInputValueConfig; -export type GraphQLInputFieldConfigMap = ObjMap; +export type GraphQLInputField = GraphQLInputValue; -export type GraphQLInputField = {| - name: string, - description: ?string, - type: GraphQLInputType, - defaultValue: mixed, - deprecationReason: ?string, - extensions: ?ReadOnlyObjMap, - astNode: ?InputValueDefinitionNode, -|}; - -export function isRequiredInputField( - field: GraphQLInputField, -): boolean %checks { - return isNonNullType(field.type) && field.defaultValue === undefined; -} +export const isRequiredInputField = isRequiredInput; export type GraphQLInputFieldMap = ObjMap; diff --git a/src/type/directives.d.ts b/src/type/directives.d.ts index 66415d879a..69f8656335 100644 --- a/src/type/directives.d.ts +++ b/src/type/directives.d.ts @@ -2,11 +2,12 @@ /* eslint-disable import/no-cycle */ import { Maybe } from '../jsutils/Maybe'; +import { ObjMap } from '../jsutils/ObjMap'; import { DirectiveDefinitionNode } from '../language/ast'; import { DirectiveLocationEnum } from '../language/directiveLocation'; -import { GraphQLFieldConfigArgumentMap, GraphQLArgument } from './definition'; +import { GraphQLArgument, GraphQLArgumentConfig } from './definition'; /** * Test if the given value is a GraphQL directive. @@ -43,7 +44,7 @@ export class GraphQLDirective { constructor(config: Readonly); toConfig(): GraphQLDirectiveConfig & { - args: GraphQLFieldConfigArgumentMap; + args: ObjMap; isRepeatable: boolean; extensions: Maybe>; }; @@ -58,7 +59,7 @@ export interface GraphQLDirectiveConfig { name: string; description?: Maybe; locations: Array; - args?: Maybe; + args?: Maybe>; isRepeatable?: Maybe; extensions?: Maybe>; astNode?: Maybe; diff --git a/src/type/directives.js b/src/type/directives.js index a6ca5005c9..702abebb1e 100644 --- a/src/type/directives.js +++ b/src/type/directives.js @@ -1,5 +1,10 @@ -import type { ReadOnlyObjMap, ReadOnlyObjMapLike } from '../jsutils/ObjMap'; +import type { + ObjMap, + ReadOnlyObjMap, + ReadOnlyObjMapLike, +} from '../jsutils/ObjMap'; import { inspect } from '../jsutils/inspect'; +import { keyValMap } from '../jsutils/keyValMap'; import { toObjMap } from '../jsutils/toObjMap'; import { devAssert } from '../jsutils/devAssert'; import { instanceOf } from '../jsutils/instanceOf'; @@ -9,14 +14,11 @@ import type { DirectiveDefinitionNode } from '../language/ast'; import type { DirectiveLocationEnum } from '../language/directiveLocation'; import { DirectiveLocation } from '../language/directiveLocation'; -import type { - GraphQLArgument, - GraphQLFieldConfigArgumentMap, -} from './definition'; +import type { GraphQLArgument, GraphQLArgumentConfig } from './definition'; import { GraphQLString, GraphQLBoolean } from './scalars'; import { - defineArguments, - argsToArgsConfig, + defineInputValue, + inputValueToConfig, GraphQLNonNull, } from './definition'; @@ -73,7 +75,9 @@ export class GraphQLDirective { `@${config.name} args must be an object with argument names as keys.`, ); - this.args = defineArguments(args); + this.args = Object.entries(args).map(([argName, argConfig]) => + defineInputValue(argConfig, argName), + ); } toConfig(): GraphQLDirectiveNormalizedConfig { @@ -81,7 +85,7 @@ export class GraphQLDirective { name: this.name, description: this.description, locations: this.locations, - args: argsToArgsConfig(this.args), + args: keyValMap(this.args, (arg) => arg.name, inputValueToConfig), isRepeatable: this.isRepeatable, extensions: this.extensions, astNode: this.astNode, @@ -106,7 +110,7 @@ export type GraphQLDirectiveConfig = {| name: string, description?: ?string, locations: Array, - args?: ?GraphQLFieldConfigArgumentMap, + args?: ?ObjMap, isRepeatable?: ?boolean, extensions?: ?ReadOnlyObjMapLike, astNode?: ?DirectiveDefinitionNode, @@ -114,7 +118,7 @@ export type GraphQLDirectiveConfig = {| type GraphQLDirectiveNormalizedConfig = {| ...GraphQLDirectiveConfig, - args: GraphQLFieldConfigArgumentMap, + args: ObjMap, isRepeatable: boolean, extensions: ?ReadOnlyObjMap, |}; diff --git a/src/type/index.d.ts b/src/type/index.d.ts index 253fcf2113..365256dfd1 100644 --- a/src/type/index.d.ts +++ b/src/type/index.d.ts @@ -30,6 +30,7 @@ export { isWrappingType, isNullableType, isNamedType, + isRequiredInput, isRequiredArgument, isRequiredInputField, // Assertions @@ -80,6 +81,8 @@ export { GraphQLArgument, GraphQLArgumentConfig, GraphQLArgumentExtensions, + GraphQLInputValue, + GraphQLInputValueConfig, GraphQLEnumTypeConfig, GraphQLEnumTypeExtensions, GraphQLEnumValue, @@ -88,14 +91,12 @@ export { GraphQLEnumValueExtensions, GraphQLField, GraphQLFieldConfig, - GraphQLFieldConfigArgumentMap, GraphQLFieldConfigMap, GraphQLFieldExtensions, GraphQLFieldMap, GraphQLFieldResolver, GraphQLInputField, GraphQLInputFieldConfig, - GraphQLInputFieldConfigMap, GraphQLInputFieldExtensions, GraphQLInputFieldMap, GraphQLInputObjectTypeConfig, diff --git a/src/type/index.js b/src/type/index.js index bf0b17973e..6bf0943f22 100644 --- a/src/type/index.js +++ b/src/type/index.js @@ -29,6 +29,7 @@ export { isWrappingType, isNullableType, isNamedType, + isRequiredInput, isRequiredArgument, isRequiredInputField, // Assertions @@ -134,19 +135,19 @@ export type { ThunkObjMap, GraphQLArgument, GraphQLArgumentConfig, + GraphQLInputValue, + GraphQLInputValueConfig, GraphQLEnumTypeConfig, GraphQLEnumValue, GraphQLEnumValueConfig, GraphQLEnumValueConfigMap, GraphQLField, GraphQLFieldConfig, - GraphQLFieldConfigArgumentMap, GraphQLFieldConfigMap, GraphQLFieldMap, GraphQLFieldResolver, GraphQLInputField, GraphQLInputFieldConfig, - GraphQLInputFieldConfigMap, GraphQLInputFieldMap, GraphQLInputObjectTypeConfig, GraphQLInterfaceTypeConfig, diff --git a/src/type/validate.js b/src/type/validate.js index 919e58248d..ded614c6d6 100644 --- a/src/type/validate.js +++ b/src/type/validate.js @@ -34,8 +34,7 @@ import { isNonNullType, isInputType, isOutputType, - isRequiredArgument, - isRequiredInputField, + isRequiredInput, } from './definition'; /** @@ -180,7 +179,7 @@ function validateDirectives(context: SchemaValidationContext): void { ); } - if (isRequiredArgument(arg) && arg.deprecationReason != null) { + if (isRequiredInput(arg) && arg.deprecationReason != null) { context.reportError( `Required argument @${directive.name}(${arg.name}:) cannot be deprecated.`, [getDeprecatedDirectiveNode(arg.astNode), arg.astNode?.type], @@ -292,7 +291,7 @@ function validateFields( ); } - if (isRequiredArgument(arg) && arg.deprecationReason != null) { + if (isRequiredInput(arg) && arg.deprecationReason != null) { context.reportError( `Required argument ${type.name}.${field.name}(${argName}:) cannot be deprecated.`, [getDeprecatedDirectiveNode(arg.astNode), arg.astNode?.type], @@ -411,7 +410,7 @@ function validateTypeImplementsInterface( for (const typeArg of typeField.args) { const argName = typeArg.name; const ifaceArg = ifaceField.args.find((arg) => arg.name === argName); - if (!ifaceArg && isRequiredArgument(typeArg)) { + if (!ifaceArg && isRequiredInput(typeArg)) { context.reportError( `Object field ${type.name}.${fieldName} includes required argument ${argName} that is missing from the Interface field ${iface.name}.${fieldName}.`, [typeArg.astNode, ifaceField.astNode], @@ -529,7 +528,7 @@ function validateInputFields( ); } - if (isRequiredInputField(field) && field.deprecationReason != null) { + if (isRequiredInput(field) && field.deprecationReason != null) { context.reportError( `Required input field ${inputObj.name}.${field.name} cannot be deprecated.`, [ diff --git a/src/utilities/extendSchema.js b/src/utilities/extendSchema.js index 4aeac58584..9c55417d95 100644 --- a/src/utilities/extendSchema.js +++ b/src/utilities/extendSchema.js @@ -1,3 +1,4 @@ +import type { ObjMap } from '../jsutils/ObjMap'; import { keyMap } from '../jsutils/keyMap'; import { inspect } from '../jsutils/inspect'; import { mapValue } from '../jsutils/mapValue'; @@ -47,10 +48,9 @@ import type { GraphQLNamedType, GraphQLFieldConfig, GraphQLFieldConfigMap, + GraphQLInputValueConfig, GraphQLArgumentConfig, - GraphQLFieldConfigArgumentMap, GraphQLEnumValueConfigMap, - GraphQLInputFieldConfigMap, } from '../type/definition'; import { assertSchema, GraphQLSchema } from '../type/schema'; import { specifiedScalarTypes, isSpecifiedScalarType } from '../type/scalars'; @@ -444,7 +444,7 @@ export function extendSchemaImpl( // $FlowFixMe[incompatible-call] locations: node.locations.map(({ value }) => value), isRepeatable: node.repeatable, - args: buildArgumentMap(node.arguments), + args: buildInputValueMap(node.arguments), astNode: node, }); } @@ -469,7 +469,7 @@ export function extendSchemaImpl( // with validateSchema() will produce more actionable results. type: getWrappedType(field.type), description: field.description?.value, - args: buildArgumentMap(field.arguments), + args: buildInputValueMap(field.arguments), deprecationReason: getDeprecationReason(field), astNode: field, }; @@ -478,54 +478,38 @@ export function extendSchemaImpl( return fieldConfigMap; } - function buildArgumentMap( - args: ?$ReadOnlyArray, - ): GraphQLFieldConfigArgumentMap { + function buildInputValueMap( + nodes: ?$ReadOnlyArray, + configMap: ObjMap = Object.create(null), + ): ObjMap { // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203') - const argsNodes = args ?? []; + const inputNodes = nodes ?? []; - const argConfigMap = Object.create(null); - for (const arg of argsNodes) { + for (const node of inputNodes) { // 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 = getWrappedType(arg.type); + const type: any = getWrappedType(node.type); - argConfigMap[arg.name.value] = { + configMap[node.name.value] = { type, - description: arg.description?.value, - defaultValue: valueFromAST(arg.defaultValue, type), - deprecationReason: getDeprecationReason(arg), - astNode: arg, + description: node.description?.value, + defaultValue: valueFromAST(node.defaultValue, type), + deprecationReason: getDeprecationReason(node), + astNode: node, }; } - return argConfigMap; + return configMap; } function buildInputFieldMap( nodes: $ReadOnlyArray< InputObjectTypeDefinitionNode | InputObjectTypeExtensionNode, >, - ): GraphQLInputFieldConfigMap { - const inputFieldMap = Object.create(null); + ): ObjMap { + let inputFieldMap = Object.create(null); for (const node of nodes) { - // istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2203') - const fieldsNodes = node.fields ?? []; - - for (const field of fieldsNodes) { - // 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 = getWrappedType(field.type); - - inputFieldMap[field.name.value] = { - type, - description: field.description?.value, - defaultValue: valueFromAST(field.defaultValue, type), - deprecationReason: getDeprecationReason(field), - astNode: field, - }; - } + inputFieldMap = buildInputValueMap(node.fields, inputFieldMap); } return inputFieldMap; } diff --git a/src/utilities/findBreakingChanges.js b/src/utilities/findBreakingChanges.js index d259d3b510..cc7ffe7443 100644 --- a/src/utilities/findBreakingChanges.js +++ b/src/utilities/findBreakingChanges.js @@ -29,8 +29,7 @@ import { isNonNullType, isListType, isNamedType, - isRequiredArgument, - isRequiredInputField, + isRequiredInput, } from '../type/definition'; import { astFromValue } from './astFromValue'; @@ -133,7 +132,7 @@ function findDirectiveChanges( const argsDiff = diff(oldDirective.args, newDirective.args); for (const newArg of argsDiff.added) { - if (isRequiredArgument(newArg)) { + if (isRequiredInput(newArg)) { schemaChanges.push({ type: BreakingChangeType.REQUIRED_DIRECTIVE_ARG_ADDED, description: `A required arg ${newArg.name} on directive ${oldDirective.name} was added.`, @@ -229,7 +228,7 @@ function findInputObjectTypeChanges( ); for (const newField of fieldsDiff.added) { - if (isRequiredInputField(newField)) { + if (isRequiredInput(newField)) { schemaChanges.push({ type: BreakingChangeType.REQUIRED_INPUT_FIELD_ADDED, description: `A required field ${newField.name} on input type ${oldType.name} was added.`, @@ -427,7 +426,7 @@ function findArgChanges( } for (const newArg of argsDiff.added) { - if (isRequiredArgument(newArg)) { + if (isRequiredInput(newArg)) { schemaChanges.push({ type: BreakingChangeType.REQUIRED_ARG_ADDED, description: `A required arg ${newArg.name} on ${oldType.name}.${oldField.name} was added.`, diff --git a/src/utilities/lexicographicSortSchema.js b/src/utilities/lexicographicSortSchema.js index 291248ec1a..03918ce344 100644 --- a/src/utilities/lexicographicSortSchema.js +++ b/src/utilities/lexicographicSortSchema.js @@ -8,8 +8,7 @@ import type { GraphQLType, GraphQLNamedType, GraphQLFieldConfigMap, - GraphQLFieldConfigArgumentMap, - GraphQLInputFieldConfigMap, + GraphQLInputValueConfig, } from '../type/definition'; import { GraphQLSchema } from '../type/schema'; import { GraphQLDirective } from '../type/directives'; @@ -79,14 +78,14 @@ export function lexicographicSortSchema(schema: GraphQLSchema): GraphQLSchema { return new GraphQLDirective({ ...config, locations: sortBy(config.locations, (x) => x), - args: sortArgs(config.args), + args: sortInputs(config.args), }); } - function sortArgs(args: GraphQLFieldConfigArgumentMap) { - return sortObjMap(args, (arg) => ({ - ...arg, - type: replaceType(arg.type), + function sortInputs(inputs: ObjMap) { + return sortObjMap(inputs, (input) => ({ + ...input, + type: replaceType(input.type), })); } @@ -94,14 +93,7 @@ export function lexicographicSortSchema(schema: GraphQLSchema): GraphQLSchema { return sortObjMap(fieldsMap, (field) => ({ ...field, type: replaceType(field.type), - args: sortArgs(field.args), - })); - } - - function sortInputFields(fieldsMap: GraphQLInputFieldConfigMap) { - return sortObjMap(fieldsMap, (field) => ({ - ...field, - type: replaceType(field.type), + args: sortInputs(field.args), })); } @@ -148,7 +140,7 @@ export function lexicographicSortSchema(schema: GraphQLSchema): GraphQLSchema { const config = type.toConfig(); return new GraphQLInputObjectType({ ...config, - fields: () => sortInputFields(config.fields), + fields: () => sortInputs(config.fields), }); } diff --git a/src/validation/rules/ProvidedRequiredArgumentsRule.js b/src/validation/rules/ProvidedRequiredArgumentsRule.js index 0ddc8f784d..d67443d104 100644 --- a/src/validation/rules/ProvidedRequiredArgumentsRule.js +++ b/src/validation/rules/ProvidedRequiredArgumentsRule.js @@ -9,7 +9,7 @@ import { Kind } from '../../language/kinds'; import { print } from '../../language/printer'; import { specifiedDirectives } from '../../type/directives'; -import { isType, isRequiredArgument } from '../../type/definition'; +import { isType, isRequiredInput } from '../../type/definition'; import type { ValidationContext, @@ -41,7 +41,7 @@ export function ProvidedRequiredArgumentsRule( fieldNode.arguments?.map((arg) => arg.name.value), ); for (const argDef of fieldDef.args) { - if (!providedArgs.has(argDef.name) && isRequiredArgument(argDef)) { + if (!providedArgs.has(argDef.name) && isRequiredInput(argDef)) { const argTypeStr = inspect(argDef.type); context.reportError( new GraphQLError( @@ -68,7 +68,7 @@ export function ProvidedRequiredArgumentsOnDirectivesRule( const definedDirectives = schema?.getDirectives() ?? specifiedDirectives; for (const directive of definedDirectives) { requiredArgsMap[directive.name] = keyMap( - directive.args.filter(isRequiredArgument), + directive.args.filter(isRequiredInput), (arg) => arg.name, ); } @@ -80,7 +80,7 @@ export function ProvidedRequiredArgumentsOnDirectivesRule( const argNodes = def.arguments ?? []; requiredArgsMap[def.name.value] = keyMap( - argNodes.filter(isRequiredArgumentNode), + argNodes.filter(isRequiredInputNode), (arg) => arg.name.value, ); } @@ -115,6 +115,6 @@ export function ProvidedRequiredArgumentsOnDirectivesRule( }; } -function isRequiredArgumentNode(arg: InputValueDefinitionNode): boolean { +function isRequiredInputNode(arg: InputValueDefinitionNode): boolean { return arg.type.kind === Kind.NON_NULL_TYPE && arg.defaultValue == null; } diff --git a/src/validation/rules/ValuesOfCorrectTypeRule.js b/src/validation/rules/ValuesOfCorrectTypeRule.js index 6d5dc5c1ca..9153b1a5ed 100644 --- a/src/validation/rules/ValuesOfCorrectTypeRule.js +++ b/src/validation/rules/ValuesOfCorrectTypeRule.js @@ -14,7 +14,7 @@ import { isInputObjectType, isListType, isNonNullType, - isRequiredInputField, + isRequiredInput, getNullableType, getNamedType, } from '../../type/definition'; @@ -50,7 +50,7 @@ export function ValuesOfCorrectTypeRule( const fieldNodeMap = keyMap(node.fields, (field) => field.name.value); for (const fieldDef of Object.values(type.getFields())) { const fieldNode = fieldNodeMap[fieldDef.name]; - if (!fieldNode && isRequiredInputField(fieldDef)) { + if (!fieldNode && isRequiredInput(fieldDef)) { const typeStr = inspect(fieldDef.type); context.reportError( new GraphQLError(