Skip to content

Commit 8426c7b

Browse files
authored
always include nullable outer most input type (#176)
see: #174
1 parent b4a3a2b commit 8426c7b

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

.changeset/quick-pans-tan.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'graphql-executor': patch
3+
---
4+
5+
Always include nullable outermost input type within schema
6+
7+
Because variables could include a default value.
8+
9+
See https://github.com/yaacovCR/graphql-executor/issues/174 for more details.

src/executorSchema/__tests__/toExecutorSchema-test.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ import { expect } from 'chai';
22
import { describe, it } from 'mocha';
33

44
import type {
5-
GraphQLNonNull,
65
ListTypeNode,
76
NamedTypeNode,
87
NonNullTypeNode,
8+
TypeNode,
99
} from 'graphql';
1010
import {
1111
GraphQLList,
1212
GraphQLInputObjectType,
13+
GraphQLNonNull,
1314
GraphQLObjectType,
1415
GraphQLSchema,
1516
GraphQLString,
@@ -27,6 +28,16 @@ describe('ExecutorSchema:', () => {
2728
},
2829
},
2930
});
31+
const nonNullableInput = new GraphQLNonNull(
32+
new GraphQLInputObjectType({
33+
name: 'AnotherInput',
34+
fields: {
35+
inputField: {
36+
type: GraphQLString,
37+
},
38+
},
39+
}),
40+
);
3041
const query = new GraphQLObjectType({
3142
name: 'Query',
3243
fields: {
@@ -38,6 +49,14 @@ describe('ExecutorSchema:', () => {
3849
},
3950
},
4051
},
52+
fieldWithNonNullInputArg: {
53+
type: GraphQLString,
54+
args: {
55+
arg: {
56+
type: nonNullableInput,
57+
},
58+
},
59+
},
4160
fieldWithListInputArg: {
4261
type: GraphQLString,
4362
args: {
@@ -102,6 +121,21 @@ describe('ExecutorSchema:', () => {
102121
expect((type as GraphQLNonNull<any>).ofType).to.equal(input);
103122
});
104123

124+
it('allows retrieving non-nullable input types defined in schema when unwrapped', () => {
125+
const executorSchema = toExecutorSchema(schema);
126+
const nullableTypeNode: TypeNode = {
127+
kind: Kind.NAMED_TYPE,
128+
name: {
129+
kind: Kind.NAME,
130+
value: 'AnotherInput',
131+
},
132+
};
133+
const type = executorSchema.getType(nullableTypeNode);
134+
expect(type).to.equal(nonNullableInput.ofType);
135+
expect(executorSchema.isNonNullType(type)).to.equal(false);
136+
expect(executorSchema.isInputType(type)).to.equal(true);
137+
});
138+
105139
it('allows retrieving list input types defined in schema', () => {
106140
const executorSchema = toExecutorSchema(schema);
107141
const listTypeNode: ListTypeNode = {

src/executorSchema/getPossibleInputTypes.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,17 @@ export function getPossibleInputTypes(
8787
isNonNullType: (type: unknown) => type is GraphQLNonNull<any>,
8888
type: GraphQLInputType,
8989
): Array<GraphQLInputType> {
90+
// See: https://github.com/yaacovCR/graphql-executor/issues/174
91+
// Unwrap any non-null modifier to the outermost type because a variable
92+
// on the outermost type can be nullable if a default value is supplied.
93+
// Non-null versions will then be allowed by the algorithm below as at all
94+
// levels.
95+
const nullableOuterType = isNonNullType(type) ? type.ofType : type;
96+
9097
const { nonNullListWrappers, nonNull, namedType } = getInputTypeInfo(
9198
isListType,
9299
isNonNullType,
93-
type,
100+
nullableOuterType,
94101
);
95102
const sequences = getPossibleSequences(nonNullListWrappers);
96103

0 commit comments

Comments
 (0)