Skip to content

Commit 3726e57

Browse files
committed
Convert @semanticNonNull to GraphQLSemanticNonNull before going through conversion
1 parent ecfdebf commit 3726e57

File tree

1 file changed

+53
-32
lines changed

1 file changed

+53
-32
lines changed

src/cli.ts

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
GraphQLNamedType,
88
GraphQLNonNull,
99
GraphQLObjectType,
10+
GraphQLOutputType,
1011
GraphQLSchema,
1112
GraphQLSemanticNonNull,
1213
GraphQLType,
@@ -87,11 +88,14 @@ function makeConvertType(toStrict: boolean) {
8788
.filter((v) => v.kind === Kind.INT)
8889
.map((v) => Number(v.value))
8990
: [0];
91+
const type = directive
92+
? applySemanticNonNull(spec.type, levels)
93+
: spec.type;
9094
return [
9195
fieldName,
9296
{
9397
...spec,
94-
type: convertType(spec.type, directive ? levels : undefined),
98+
type: convertType(type),
9599
astNode: spec.astNode && {
96100
...spec.astNode,
97101
directives: spec.astNode?.directives?.filter(
@@ -105,6 +109,48 @@ function makeConvertType(toStrict: boolean) {
105109
};
106110
}
107111

112+
/**
113+
* Takes a GraphQL type along with levels at which to apply
114+
* semantic-non-null, and returns a converted type with these levels applied.
115+
*/
116+
function applySemanticNonNull(type: GraphQLOutputType, levels: number[]) {
117+
function recurse(
118+
type: GraphQLOutputType,
119+
level: number,
120+
): GraphQLOutputType {
121+
if (type instanceof GraphQLSemanticNonNull) {
122+
// Strip semantic-non-null types; this should never happen but if someone
123+
// uses both semantic-non-null and the `@semanticNonNull` directive, we
124+
// want the directive to win (I guess?)
125+
return recurse(type.ofType, level);
126+
} else if (type instanceof GraphQLNonNull) {
127+
const inner = recurse(type.ofType, level);
128+
if (levels.includes(level)) {
129+
// Semantic non-null from `inner` replaces our GrpahQLNonNull wrapper
130+
return inner;
131+
} else {
132+
// Keep non-null wrapper; no semantic-non-null was added to `inner`
133+
return new GraphQLNonNull(inner);
134+
}
135+
} else if (type instanceof GraphQLList) {
136+
const inner = new GraphQLList(recurse(type.ofType, level + 1));
137+
if (levels.includes(level)) {
138+
return new GraphQLSemanticNonNull(inner);
139+
} else {
140+
return inner;
141+
}
142+
} else {
143+
if (levels.includes(level)) {
144+
return new GraphQLSemanticNonNull(type);
145+
} else {
146+
return type;
147+
}
148+
}
149+
}
150+
151+
return recurse(type, 0);
152+
}
153+
108154
function convertTypes(
109155
types: readonly GraphQLInterfaceType[] | null | undefined,
110156
): undefined | (() => readonly GraphQLInterfaceType[]);
@@ -124,30 +170,14 @@ function makeConvertType(toStrict: boolean) {
124170
return () => types.map((t) => convertType(t));
125171
}
126172

127-
function convertType(
128-
type: null | undefined,
129-
semanticNonNullLevels?: number[],
130-
): null | undefined;
131-
function convertType(
132-
type: GraphQLObjectType,
133-
semanticNonNullLevels?: number[],
134-
): GraphQLObjectType;
173+
function convertType(type: null | undefined): null | undefined;
174+
function convertType(type: GraphQLObjectType): GraphQLObjectType;
135175
function convertType(
136176
type: Maybe<GraphQLObjectType>,
137-
semanticNonNullLevels?: number[],
138177
): Maybe<GraphQLObjectType>;
139-
function convertType(
140-
type: GraphQLNamedType,
141-
semanticNonNullLevels?: number[],
142-
): GraphQLNamedType;
143-
function convertType(
144-
type: GraphQLType,
145-
semanticNonNullLevels?: number[],
146-
): GraphQLType;
147-
function convertType(
148-
type: GraphQLType | null | undefined,
149-
semanticNonNullLevels?: number[],
150-
) {
178+
function convertType(type: GraphQLNamedType): GraphQLNamedType;
179+
function convertType(type: GraphQLType): GraphQLType;
180+
function convertType(type: GraphQLType | null | undefined) {
151181
if (!type) return type;
152182
if (type instanceof GraphQLSemanticNonNull) {
153183
const unwrapped = convertType(type.ofType);
@@ -160,16 +190,7 @@ function makeConvertType(toStrict: boolean) {
160190
} else if (type instanceof GraphQLNonNull) {
161191
return new GraphQLNonNull(convertType(type.ofType));
162192
} else if (type instanceof GraphQLList) {
163-
const innerLevels = semanticNonNullLevels?.includes(1) ? [0] : undefined;
164-
if (semanticNonNullLevels?.includes(0) && toStrict) {
165-
return new GraphQLNonNull(
166-
new GraphQLList(convertType(type.ofType, innerLevels)),
167-
);
168-
} else {
169-
return new GraphQLList(convertType(type.ofType, innerLevels));
170-
}
171-
} else if (semanticNonNullLevels?.includes(0) && toStrict) {
172-
return new GraphQLNonNull(convertType(type));
193+
return new GraphQLList(convertType(type.ofType));
173194
}
174195
if (type.name.startsWith("__")) {
175196
return null;

0 commit comments

Comments
 (0)