Skip to content

Commit

Permalink
introduce GraphQLField, GraphQLInputField, GraphQLArgument, and Graph…
Browse files Browse the repository at this point in the history
…QLEnumValue (#4288)

this extracts logic from #3044 and #3145 (later rebased as #3807 and
#3808) to implement more informative error messages without implementing
[the full schema coordinate
RFC](graphql/graphql-spec#794)

This is a BREAKING CHANGE because these schema elements are now longer
plain objects and function differently in various scenarios, for example
with `String(<schemaElement>` `JSON.stringifu(<schemaElement>` and
`.toString()` and `.toJSON()`

---------

Co-authored-by: Jovi De Croock <[email protected]>
  • Loading branch information
yaacovCR and JoviDeCroock authored Dec 1, 2024
1 parent 57ba3a3 commit 79ad146
Show file tree
Hide file tree
Showing 22 changed files with 767 additions and 540 deletions.
8 changes: 4 additions & 4 deletions src/execution/__tests__/nonnull-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ describe('Execute: handles non-nullable types', () => {
errors: [
{
message:
'Argument "cannotBeNull" of required type "String!" was not provided.',
'Argument "Query.withNonNullArg(cannotBeNull:)" of required type "String!" was not provided.',
locations: [{ line: 3, column: 13 }],
path: ['withNonNullArg'],
},
Expand All @@ -710,7 +710,7 @@ describe('Execute: handles non-nullable types', () => {
errors: [
{
message:
'Argument "cannotBeNull" has invalid value: Expected value of non-null type "String!" not to be null.',
'Argument "Query.withNonNullArg(cannotBeNull:)" has invalid value: Expected value of non-null type "String!" not to be null.',
locations: [{ line: 3, column: 42 }],
path: ['withNonNullArg'],
},
Expand Down Expand Up @@ -740,7 +740,7 @@ describe('Execute: handles non-nullable types', () => {
errors: [
{
message:
'Argument "cannotBeNull" has invalid value: Expected variable "$testVar" provided to type "String!" to provide a runtime value.',
'Argument "Query.withNonNullArg(cannotBeNull:)" has invalid value: Expected variable "$testVar" provided to type "String!" to provide a runtime value.',
locations: [{ line: 3, column: 42 }],
path: ['withNonNullArg'],
},
Expand Down Expand Up @@ -768,7 +768,7 @@ describe('Execute: handles non-nullable types', () => {
errors: [
{
message:
'Argument "cannotBeNull" has invalid value: Expected variable "$testVar" provided to non-null type "String!" not to be null.',
'Argument "Query.withNonNullArg(cannotBeNull:)" has invalid value: Expected variable "$testVar" provided to non-null type "String!" not to be null.',
locations: [{ line: 3, column: 43 }],
path: ['withNonNullArg'],
},
Expand Down
10 changes: 5 additions & 5 deletions src/execution/__tests__/oneof-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ describe('Execute: Handles OneOf Input Objects', () => {
message:
// This type of error would be caught at validation-time
// hence the vague error message here.
'Argument "input" has invalid value: Expected variable "$input" provided to type "TestInputObject!" to provide a runtime value.',
'Argument "Query.test(input:)" has invalid value: Expected variable "$input" provided to type "TestInputObject!" to provide a runtime value.',
path: ['test'],
},
],
Expand Down Expand Up @@ -229,7 +229,7 @@ describe('Execute: Handles OneOf Input Objects', () => {
// A nullable variable in a oneOf field position would be caught at validation-time
// hence the vague error message here.
message:
'Argument "input" has invalid value: Expected variable "$a" provided to field "a" for OneOf Input Object type "TestInputObject" not to be null.',
'Argument "Query.test(input:)" has invalid value: Expected variable "$a" provided to field "a" for OneOf Input Object type "TestInputObject" not to be null.',
locations: [{ line: 3, column: 23 }],
path: ['test'],
},
Expand Down Expand Up @@ -257,7 +257,7 @@ describe('Execute: Handles OneOf Input Objects', () => {
// A nullable variable in a oneOf field position would be caught at validation-time
// hence the vague error message here.
message:
'Argument "input" has invalid value: Expected variable "$a" provided to field "a" for OneOf Input Object type "TestInputObject" to provide a runtime value.',
'Argument "Query.test(input:)" has invalid value: Expected variable "$a" provided to field "a" for OneOf Input Object type "TestInputObject" to provide a runtime value.',
locations: [{ line: 3, column: 23 }],
path: ['test'],
},
Expand Down Expand Up @@ -288,7 +288,7 @@ describe('Execute: Handles OneOf Input Objects', () => {
// A nullable variable in a oneOf field position would be caught at validation-time
// hence the vague error message here.
message:
'Argument "input" has invalid value: Expected variable "$a" provided to field "a" for OneOf Input Object type "TestInputObject" not to be null.',
'Argument "Query.test(input:)" has invalid value: Expected variable "$a" provided to field "a" for OneOf Input Object type "TestInputObject" not to be null.',
locations: [{ line: 6, column: 23 }],
path: ['test'],
},
Expand Down Expand Up @@ -319,7 +319,7 @@ describe('Execute: Handles OneOf Input Objects', () => {
// A nullable variable in a oneOf field position would be caught at validation-time
// hence the vague error message here.
message:
'Argument "input" has invalid value: Expected variable "$a" provided to field "a" for OneOf Input Object type "TestInputObject" to provide a runtime value.',
'Argument "Query.test(input:)" has invalid value: Expected variable "$a" provided to field "a" for OneOf Input Object type "TestInputObject" to provide a runtime value.',
locations: [{ line: 6, column: 23 }],
path: ['test'],
},
Expand Down
12 changes: 6 additions & 6 deletions src/execution/__tests__/variables-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ describe('Execute: Handles inputs', () => {
errors: [
{
message:
'Argument "input" has invalid value: Expected value of type "TestInputObject" to be an object, found: ["foo", "bar", "baz"].',
'Argument "TestType.fieldWithObjectInput(input:)" has invalid value: Expected value of type "TestInputObject" to be an object, found: ["foo", "bar", "baz"].',
path: ['fieldWithObjectInput'],
locations: [{ line: 3, column: 41 }],
},
Expand Down Expand Up @@ -320,7 +320,7 @@ describe('Execute: Handles inputs', () => {
errors: [
{
message:
'Argument "input" has invalid value at .e: FaultyScalarErrorMessage',
'Argument "TestType.fieldWithObjectInput(input:)" has invalid value at .e: FaultyScalarErrorMessage',
path: ['fieldWithObjectInput'],
locations: [{ line: 3, column: 13 }],
extensions: { code: 'FaultyScalarErrorExtensionCode' },
Expand Down Expand Up @@ -477,7 +477,7 @@ describe('Execute: Handles inputs', () => {
errors: [
{
message:
'Variable "$input" has invalid value at .e: Argument "input" has invalid value at .e: FaultyScalarErrorMessage',
'Variable "$input" has invalid value at .e: Argument "TestType.fieldWithObjectInput(input:)" has invalid value at .e: FaultyScalarErrorMessage',
locations: [{ line: 2, column: 16 }],
extensions: { code: 'FaultyScalarErrorExtensionCode' },
},
Expand Down Expand Up @@ -802,7 +802,7 @@ describe('Execute: Handles inputs', () => {
errors: [
{
message:
'Argument "input" of required type "String!" was not provided.',
'Argument "TestType.fieldWithNonNullableStringInput(input:)" of required type "String!" was not provided.',
locations: [{ line: 1, column: 3 }],
path: ['fieldWithNonNullableStringInput'],
},
Expand Down Expand Up @@ -850,7 +850,7 @@ describe('Execute: Handles inputs', () => {
errors: [
{
message:
'Argument "input" has invalid value: Expected variable "$foo" provided to type "String!" to provide a runtime value.',
'Argument "TestType.fieldWithNonNullableStringInput(input:)" has invalid value: Expected variable "$foo" provided to type "String!" to provide a runtime value.',
locations: [{ line: 3, column: 50 }],
path: ['fieldWithNonNullableStringInput'],
},
Expand Down Expand Up @@ -1102,7 +1102,7 @@ describe('Execute: Handles inputs', () => {
errors: [
{
message:
'Argument "input" has invalid value: String cannot represent a non string value: WRONG_TYPE',
'Argument "TestType.fieldWithDefaultArgumentValue(input:)" has invalid value: String cannot represent a non string value: WRONG_TYPE',
locations: [{ line: 3, column: 48 }],
path: ['fieldWithDefaultArgumentValue'],
},
Expand Down
12 changes: 9 additions & 3 deletions src/execution/values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ import type {
import { Kind } from '../language/kinds.js';

import type { GraphQLArgument, GraphQLField } from '../type/definition.js';
import { isNonNullType, isRequiredArgument } from '../type/definition.js';
import {
isArgument,
isNonNullType,
isRequiredArgument,
} from '../type/definition.js';
import type { GraphQLDirective } from '../type/directives.js';
import type { GraphQLSchema } from '../type/schema.js';

Expand Down Expand Up @@ -222,7 +226,8 @@ export function experimentalGetArgumentValues(
// execution. This is a runtime check to ensure execution does not
// continue with an invalid argument value.
throw new GraphQLError(
`Argument "${argDef.name}" of required type "${argType}" was not provided.`,
// TODO: clean up the naming of isRequiredArgument(), isArgument(), and argDef if/when experimental fragment variables are merged
`Argument "${isArgument(argDef) ? argDef : argDef.name}" of required type "${argType}" was not provided.`,
{ nodes: node },
);
}
Expand Down Expand Up @@ -272,7 +277,8 @@ export function experimentalGetArgumentValues(
valueNode,
argType,
(error, path) => {
error.message = `Argument "${argDef.name}" has invalid value${printPathArray(
// TODO: clean up the naming of isRequiredArgument(), isArgument(), and argDef if/when experimental fragment variables are merged
error.message = `Argument "${isArgument(argDef) ? argDef : argDef.name}" has invalid value${printPathArray(
path,
)}: ${error.message}`;
throw error;
Expand Down
18 changes: 14 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ export type { GraphQLArgs } from './graphql.js';
export { graphql, graphqlSync } from './graphql.js';

// Create and operate on GraphQL type definitions and schema.
export type {
GraphQLField,
GraphQLArgument,
GraphQLEnumValue,
GraphQLInputField,
} from './type/index.js';
export {
resolveObjMapThunk,
resolveReadonlyArrayThunk,
Expand Down Expand Up @@ -91,10 +97,14 @@ export {
isType,
isScalarType,
isObjectType,
isField,
isArgument,
isInterfaceType,
isUnionType,
isEnumType,
isEnumValue,
isInputObjectType,
isInputField,
isListType,
isNonNullType,
isInputType,
Expand All @@ -116,10 +126,14 @@ export {
assertType,
assertScalarType,
assertObjectType,
assertField,
assertArgument,
assertInterfaceType,
assertUnionType,
assertEnumType,
assertEnumValue,
assertInputObjectType,
assertInputField,
assertListType,
assertNonNullType,
assertInputType,
Expand Down Expand Up @@ -161,23 +175,19 @@ export type {
GraphQLSchemaExtensions,
GraphQLDirectiveConfig,
GraphQLDirectiveExtensions,
GraphQLArgument,
GraphQLArgumentConfig,
GraphQLArgumentExtensions,
GraphQLEnumTypeConfig,
GraphQLEnumTypeExtensions,
GraphQLEnumValue,
GraphQLEnumValueConfig,
GraphQLEnumValueConfigMap,
GraphQLEnumValueExtensions,
GraphQLField,
GraphQLFieldConfig,
GraphQLFieldConfigArgumentMap,
GraphQLFieldConfigMap,
GraphQLFieldExtensions,
GraphQLFieldMap,
GraphQLFieldResolver,
GraphQLInputField,
GraphQLInputFieldConfig,
GraphQLInputFieldConfigMap,
GraphQLInputFieldExtensions,
Expand Down
Loading

0 comments on commit 79ad146

Please sign in to comment.