diff --git a/src/execution/__tests__/semantic-nullability-test.ts b/src/execution/__tests__/semantic-nullability-test.ts index 20a33c2ffa..6d9098d016 100644 --- a/src/execution/__tests__/semantic-nullability-test.ts +++ b/src/execution/__tests__/semantic-nullability-test.ts @@ -10,7 +10,6 @@ import { GraphQLNonNull, GraphQLObjectType, GraphQLSemanticNonNull, - GraphQLSemanticNullable, } from '../../type/definition'; import { GraphQLString } from '../../type/scalars'; import { GraphQLSchema } from '../../type/schema'; @@ -28,7 +27,7 @@ describe('Execute: Handles Semantic Nullability', () => { const DataType: GraphQLObjectType = new GraphQLObjectType({ name: 'DataType', fields: () => ({ - a: { type: new GraphQLSemanticNullable(GraphQLString) }, + a: { type: GraphQLString }, b: { type: new GraphQLSemanticNonNull(GraphQLString) }, c: { type: new GraphQLNonNull(GraphQLString) }, d: { type: new GraphQLSemanticNonNull(DeepDataType) }, diff --git a/src/execution/execute.ts b/src/execution/execute.ts index 0bfbcf3f3e..055b778983 100644 --- a/src/execution/execute.ts +++ b/src/execution/execute.ts @@ -44,7 +44,6 @@ import { isNonNullType, isObjectType, isSemanticNonNullType, - isSemanticNullableType, } from '../type/definition'; import { SchemaMetaFieldDef, @@ -690,18 +689,6 @@ function completeValue( return completed; } - // If field type is SemanticNullable, complete for inner type - if (isSemanticNullableType(returnType)) { - return completeValue( - exeContext, - returnType.ofType, - fieldNodes, - info, - path, - result, - ); - } - // If result value is null or undefined then return null. if (result == null) { return null; diff --git a/src/language/__tests__/parser-test.ts b/src/language/__tests__/parser-test.ts index 4c134f2be0..f3577ef64d 100644 --- a/src/language/__tests__/parser-test.ts +++ b/src/language/__tests__/parser-test.ts @@ -659,7 +659,7 @@ describe('Parser', () => { }); describe('parseDocumentDirective', () => { - it('doesn\'t throw on document-level directive', () => { + it("doesn't throw on document-level directive", () => { parse(dedent` @SemanticNullability type Query { @@ -690,16 +690,12 @@ describe('Parser', () => { it('parses nullable types', () => { const result = parseType('MyType?', { allowSemanticNullability: true }); expectJSON(result).toDeepEqual({ - kind: Kind.SEMANTIC_NULLABLE_TYPE, - loc: { start: 0, end: 7 }, - type: { - kind: Kind.NAMED_TYPE, + kind: Kind.NAMED_TYPE, + loc: { start: 0, end: 6 }, + name: { + kind: Kind.NAME, loc: { start: 0, end: 6 }, - name: { - kind: Kind.NAME, - loc: { start: 0, end: 6 }, - value: 'MyType', - }, + value: 'MyType', }, }); }); diff --git a/src/language/__tests__/predicates-test.ts b/src/language/__tests__/predicates-test.ts index aa41961177..32ef7d1fe1 100644 --- a/src/language/__tests__/predicates-test.ts +++ b/src/language/__tests__/predicates-test.ts @@ -93,7 +93,6 @@ describe('AST node predicates', () => { 'ListType', 'NonNullType', 'SemanticNonNullType', - 'SemanticNullableType', ]); }); diff --git a/src/language/__tests__/schema-printer-test.ts b/src/language/__tests__/schema-printer-test.ts index a5f803bc1d..a2e3fa070d 100644 --- a/src/language/__tests__/schema-printer-test.ts +++ b/src/language/__tests__/schema-printer-test.ts @@ -183,28 +183,38 @@ describe('Printer: SDL document', () => { it('prints NamedType', () => { expect( - print(parseType('MyType', { allowSemanticNullability: false })), + print(parseType('MyType', { allowSemanticNullability: false }), { + useSemanticNullability: false, + }), ).to.equal(dedent`MyType`); }); it('prints SemanticNullableType', () => { expect( - print(parseType('MyType?', { allowSemanticNullability: true })), + print(parseType('MyType?', { allowSemanticNullability: true }), { + useSemanticNullability: true, + }), ).to.equal(dedent`MyType?`); }); it('prints SemanticNonNullType', () => { expect( - print(parseType('MyType', { allowSemanticNullability: true })), + print(parseType('MyType', { allowSemanticNullability: true }), { + useSemanticNullability: true, + }), ).to.equal(dedent`MyType`); }); it('prints NonNullType', () => { expect( - print(parseType('MyType!', { allowSemanticNullability: true })), + print(parseType('MyType!', { allowSemanticNullability: true }), { + useSemanticNullability: true, + }), ).to.equal(dedent`MyType!`); expect( - print(parseType('MyType!', { allowSemanticNullability: false })), + print(parseType('MyType!', { allowSemanticNullability: false }), { + useSemanticNullability: true, + }), ).to.equal(dedent`MyType!`); }); }); diff --git a/src/language/ast.ts b/src/language/ast.ts index 57beb3c573..21c4160464 100644 --- a/src/language/ast.ts +++ b/src/language/ast.ts @@ -162,7 +162,6 @@ export type ASTNode = | ListTypeNode | NonNullTypeNode | SemanticNonNullTypeNode - | SemanticNullableTypeNode | SchemaDefinitionNode | OperationTypeDefinitionNode | ScalarTypeDefinitionNode @@ -238,7 +237,6 @@ export const QueryDocumentKeys: { ListType: ['type'], NonNullType: ['type'], SemanticNonNullType: ['type'], - SemanticNullableType: ['type'], SchemaDefinition: ['description', 'directives', 'operationTypes'], OperationTypeDefinition: ['type'], @@ -529,20 +527,13 @@ export interface SemanticNonNullTypeNode { readonly type: NamedTypeNode | ListTypeNode; } -export interface SemanticNullableTypeNode { - readonly kind: Kind.SEMANTIC_NULLABLE_TYPE; - readonly loc?: Location; - readonly type: NamedTypeNode | ListTypeNode; -} - /** Type Reference */ export type TypeNode = | NamedTypeNode | ListTypeNode | NonNullTypeNode - | SemanticNonNullTypeNode - | SemanticNullableTypeNode; + | SemanticNonNullTypeNode; export interface NamedTypeNode { readonly kind: Kind.NAMED_TYPE; diff --git a/src/language/kinds.ts b/src/language/kinds.ts index 7111a94834..e91373746c 100644 --- a/src/language/kinds.ts +++ b/src/language/kinds.ts @@ -38,7 +38,6 @@ enum Kind { LIST_TYPE = 'ListType', NON_NULL_TYPE = 'NonNullType', SEMANTIC_NON_NULL_TYPE = 'SemanticNonNullType', - SEMANTIC_NULLABLE_TYPE = 'SemanticNullableType', /** Type System Definitions */ SCHEMA_DEFINITION = 'SchemaDefinition', diff --git a/src/language/parser.ts b/src/language/parser.ts index 5743eef9da..790aee3b4b 100644 --- a/src/language/parser.ts +++ b/src/language/parser.ts @@ -51,7 +51,6 @@ import type { SelectionNode, SelectionSetNode, SemanticNonNullTypeNode, - SemanticNullableTypeNode, StringValueNode, Token, TypeNode, @@ -795,10 +794,7 @@ export class Parser { type, }); } else if (this.expectOptionalToken(TokenKind.QUESTION_MARK)) { - return this.node(start, { - kind: Kind.SEMANTIC_NULLABLE_TYPE, - type, - }); + return type; } return this.node(start, { diff --git a/src/language/predicates.ts b/src/language/predicates.ts index d528e6c3c2..3ddf52b94c 100644 --- a/src/language/predicates.ts +++ b/src/language/predicates.ts @@ -68,8 +68,7 @@ export function isTypeNode(node: ASTNode): node is TypeNode { node.kind === Kind.NAMED_TYPE || node.kind === Kind.LIST_TYPE || node.kind === Kind.NON_NULL_TYPE || - node.kind === Kind.SEMANTIC_NON_NULL_TYPE || - node.kind === Kind.SEMANTIC_NULLABLE_TYPE + node.kind === Kind.SEMANTIC_NON_NULL_TYPE ); } diff --git a/src/language/printer.ts b/src/language/printer.ts index 17b805e624..2b14ec5dfd 100644 --- a/src/language/printer.ts +++ b/src/language/printer.ts @@ -2,6 +2,7 @@ import type { Maybe } from '../jsutils/Maybe'; import type { ASTNode } from './ast'; import { printBlockString } from './blockString'; +import { Kind } from './kinds'; import { printString } from './printString'; import type { ASTReducer } from './visitor'; import { visit } from './visitor'; @@ -17,302 +18,314 @@ export interface PrintOptions { * Converts an AST into a string, using one set of reasonable * formatting rules. */ -export function print(ast: ASTNode): string { - return visit(ast, printDocASTReducer); -} +export function print(ast: ASTNode, options: PrintOptions = {}): string { + return visit(ast, { + Name: { leave: (node) => node.value }, + Variable: { leave: (node) => '$' + node.name }, -const MAX_LINE_LENGTH = 80; + // Document -const printDocASTReducer: ASTReducer = { - Name: { leave: (node) => node.value }, - Variable: { leave: (node) => '$' + node.name }, - - // Document - - Document: { - leave: (node) => join(node.definitions, '\n\n'), - }, - - OperationDefinition: { - leave(node) { - const varDefs = wrap('(', join(node.variableDefinitions, ', '), ')'); - const prefix = join( - [ - node.operation, - join([node.name, varDefs]), - join(node.directives, ' '), - ], - ' ', - ); - - // Anonymous queries with no directives or variable definitions can use - // the query short form. - return (prefix === 'query' ? '' : prefix + ' ') + node.selectionSet; + Document: { + leave: (node) => join(node.definitions, '\n\n'), }, - }, - - VariableDefinition: { - leave: ({ variable, type, defaultValue, directives }) => - variable + - ': ' + - type + - wrap(' = ', defaultValue) + - wrap(' ', join(directives, ' ')), - }, - SelectionSet: { leave: ({ selections }) => block(selections) }, - - Field: { - leave({ alias, name, arguments: args, directives, selectionSet }) { - const prefix = wrap('', alias, ': ') + name; - let argsLine = prefix + wrap('(', join(args, ', '), ')'); - - if (argsLine.length > MAX_LINE_LENGTH) { - argsLine = prefix + wrap('(\n', indent(join(args, '\n')), '\n)'); - } - - return join([argsLine, join(directives, ' '), selectionSet], ' '); + + OperationDefinition: { + leave(node) { + const varDefs = wrap('(', join(node.variableDefinitions, ', '), ')'); + const prefix = join( + [ + node.operation, + join([node.name, varDefs]), + join(node.directives, ' '), + ], + ' ', + ); + + // Anonymous queries with no directives or variable definitions can use + // the query short form. + return (prefix === 'query' ? '' : prefix + ' ') + node.selectionSet; + }, + }, + + VariableDefinition: { + leave: ({ variable, type, defaultValue, directives }) => + variable + + ': ' + + type + + wrap(' = ', defaultValue) + + wrap(' ', join(directives, ' ')), + }, + SelectionSet: { leave: ({ selections }) => block(selections) }, + + Field: { + leave({ alias, name, arguments: args, directives, selectionSet }) { + const prefix = wrap('', alias, ': ') + name; + let argsLine = prefix + wrap('(', join(args, ', '), ')'); + + if (argsLine.length > MAX_LINE_LENGTH) { + argsLine = prefix + wrap('(\n', indent(join(args, '\n')), '\n)'); + } + + return join([argsLine, join(directives, ' '), selectionSet], ' '); + }, + }, + + Argument: { leave: ({ name, value }) => name + ': ' + value }, + + // Fragments + + FragmentSpread: { + leave: ({ name, directives }) => + '...' + name + wrap(' ', join(directives, ' ')), + }, + + InlineFragment: { + leave: ({ typeCondition, directives, selectionSet }) => + join( + [ + '...', + wrap('on ', typeCondition), + join(directives, ' '), + selectionSet, + ], + ' ', + ), + }, + + FragmentDefinition: { + leave: ({ + name, + typeCondition, + variableDefinitions, + directives, + selectionSet, + }) => + // Note: fragment variable definitions are experimental and may be changed + // or removed in the future. + `fragment ${name}${wrap('(', join(variableDefinitions, ', '), ')')} ` + + `on ${typeCondition} ${wrap('', join(directives, ' '), ' ')}` + + selectionSet, }, - }, - - Argument: { leave: ({ name, value }) => name + ': ' + value }, - - // Fragments - - FragmentSpread: { - leave: ({ name, directives }) => - '...' + name + wrap(' ', join(directives, ' ')), - }, - - InlineFragment: { - leave: ({ typeCondition, directives, selectionSet }) => - join( - [ - '...', - wrap('on ', typeCondition), - join(directives, ' '), - selectionSet, - ], - ' ', - ), - }, - - FragmentDefinition: { - leave: ({ - name, - typeCondition, - variableDefinitions, - directives, - selectionSet, - }) => - // Note: fragment variable definitions are experimental and may be changed - // or removed in the future. - `fragment ${name}${wrap('(', join(variableDefinitions, ', '), ')')} ` + - `on ${typeCondition} ${wrap('', join(directives, ' '), ' ')}` + - selectionSet, - }, - - // Value - - IntValue: { leave: ({ value }) => value }, - FloatValue: { leave: ({ value }) => value }, - StringValue: { - leave: ({ value, block: isBlockString }) => - isBlockString ? printBlockString(value) : printString(value), - }, - BooleanValue: { leave: ({ value }) => (value ? 'true' : 'false') }, - NullValue: { leave: () => 'null' }, - EnumValue: { leave: ({ value }) => value }, - ListValue: { leave: ({ values }) => '[' + join(values, ', ') + ']' }, - ObjectValue: { leave: ({ fields }) => '{' + join(fields, ', ') + '}' }, - ObjectField: { leave: ({ name, value }) => name + ': ' + value }, - - // Directive - - Directive: { - leave: ({ name, arguments: args }) => - '@' + name + wrap('(', join(args, ', '), ')'), - }, - - // Type - - NamedType: { leave: ({ name }) => name }, - ListType: { leave: ({ type }) => '[' + type + ']' }, - NonNullType: { leave: ({ type }) => type + '!' }, - SemanticNonNullType: { leave: ({ type }) => type }, - SemanticNullableType: { leave: ({ type }) => type + '?' }, - - // Type System Definitions - - SchemaDefinition: { - leave: ({ description, directives, operationTypes }) => - wrap('', description, '\n') + - join(['schema', join(directives, ' '), block(operationTypes)], ' '), - }, - - OperationTypeDefinition: { - leave: ({ operation, type }) => operation + ': ' + type, - }, - - ScalarTypeDefinition: { - leave: ({ description, name, directives }) => - wrap('', description, '\n') + - join(['scalar', name, join(directives, ' ')], ' '), - }, - - ObjectTypeDefinition: { - leave: ({ description, name, interfaces, directives, fields }) => - wrap('', description, '\n') + - join( - [ - 'type', - name, - wrap('implements ', join(interfaces, ' & ')), - join(directives, ' '), - block(fields), - ], - ' ', - ), - }, - - FieldDefinition: { - leave: ({ description, name, arguments: args, type, directives }) => - wrap('', description, '\n') + - name + - (hasMultilineItems(args) - ? wrap('(\n', indent(join(args, '\n')), '\n)') - : wrap('(', join(args, ', '), ')')) + - ': ' + - type + - wrap(' ', join(directives, ' ')), - }, - - InputValueDefinition: { - leave: ({ description, name, type, defaultValue, directives }) => - wrap('', description, '\n') + - join( - [name + ': ' + type, wrap('= ', defaultValue), join(directives, ' ')], - ' ', - ), - }, - - InterfaceTypeDefinition: { - leave: ({ description, name, interfaces, directives, fields }) => - wrap('', description, '\n') + - join( - [ - 'interface', - name, - wrap('implements ', join(interfaces, ' & ')), - join(directives, ' '), - block(fields), - ], - ' ', - ), - }, - - UnionTypeDefinition: { - leave: ({ description, name, directives, types }) => - wrap('', description, '\n') + - join( - ['union', name, join(directives, ' '), wrap('= ', join(types, ' | '))], - ' ', - ), - }, - - EnumTypeDefinition: { - leave: ({ description, name, directives, values }) => - wrap('', description, '\n') + - join(['enum', name, join(directives, ' '), block(values)], ' '), - }, - - EnumValueDefinition: { - leave: ({ description, name, directives }) => - wrap('', description, '\n') + join([name, join(directives, ' ')], ' '), - }, - - InputObjectTypeDefinition: { - leave: ({ description, name, directives, fields }) => - wrap('', description, '\n') + - join(['input', name, join(directives, ' '), block(fields)], ' '), - }, - - DirectiveDefinition: { - leave: ({ description, name, arguments: args, repeatable, locations }) => - wrap('', description, '\n') + - 'directive @' + - name + - (hasMultilineItems(args) - ? wrap('(\n', indent(join(args, '\n')), '\n)') - : wrap('(', join(args, ', '), ')')) + - (repeatable ? ' repeatable' : '') + - ' on ' + - join(locations, ' | '), - }, - - SchemaExtension: { - leave: ({ directives, operationTypes }) => - join( - ['extend schema', join(directives, ' '), block(operationTypes)], - ' ', - ), - }, - - ScalarTypeExtension: { - leave: ({ name, directives }) => - join(['extend scalar', name, join(directives, ' ')], ' '), - }, - - ObjectTypeExtension: { - leave: ({ name, interfaces, directives, fields }) => - join( - [ - 'extend type', - name, - wrap('implements ', join(interfaces, ' & ')), - join(directives, ' '), - block(fields), - ], - ' ', - ), - }, - - InterfaceTypeExtension: { - leave: ({ name, interfaces, directives, fields }) => - join( - [ - 'extend interface', - name, - wrap('implements ', join(interfaces, ' & ')), - join(directives, ' '), - block(fields), - ], - ' ', - ), - }, - - UnionTypeExtension: { - leave: ({ name, directives, types }) => - join( - [ - 'extend union', - name, - join(directives, ' '), - wrap('= ', join(types, ' | ')), - ], - ' ', - ), - }, - - EnumTypeExtension: { - leave: ({ name, directives, values }) => - join(['extend enum', name, join(directives, ' '), block(values)], ' '), - }, - - InputObjectTypeExtension: { - leave: ({ name, directives, fields }) => - join(['extend input', name, join(directives, ' '), block(fields)], ' '), - }, -}; + + // Value + + IntValue: { leave: ({ value }) => value }, + FloatValue: { leave: ({ value }) => value }, + StringValue: { + leave: ({ value, block: isBlockString }) => + isBlockString ? printBlockString(value) : printString(value), + }, + BooleanValue: { leave: ({ value }) => (value ? 'true' : 'false') }, + NullValue: { leave: () => 'null' }, + EnumValue: { leave: ({ value }) => value }, + ListValue: { leave: ({ values }) => '[' + join(values, ', ') + ']' }, + ObjectValue: { leave: ({ fields }) => '{' + join(fields, ', ') + '}' }, + ObjectField: { leave: ({ name, value }) => name + ': ' + value }, + + // Directive + + Directive: { + leave: ({ name, arguments: args }) => + '@' + name + wrap('(', join(args, ', '), ')'), + }, + + // Type + + NamedType: { + leave: ({ name }, _, parent) => + parent && + !Array.isArray(parent) && + ((parent as ASTNode).kind === Kind.SEMANTIC_NON_NULL_TYPE || + (parent as ASTNode).kind === Kind.NON_NULL_TYPE) + ? name + : options?.useSemanticNullability + ? `${name}?` + : name, + }, + ListType: { leave: ({ type }) => '[' + type + ']' }, + NonNullType: { leave: ({ type }) => type + '!' }, + SemanticNonNullType: { leave: ({ type }) => type }, + + // Type System Definitions + + SchemaDefinition: { + leave: ({ description, directives, operationTypes }) => + wrap('', description, '\n') + + join(['schema', join(directives, ' '), block(operationTypes)], ' '), + }, + + OperationTypeDefinition: { + leave: ({ operation, type }) => operation + ': ' + type, + }, + + ScalarTypeDefinition: { + leave: ({ description, name, directives }) => + wrap('', description, '\n') + + join(['scalar', name, join(directives, ' ')], ' '), + }, + + ObjectTypeDefinition: { + leave: ({ description, name, interfaces, directives, fields }) => + wrap('', description, '\n') + + join( + [ + 'type', + name, + wrap('implements ', join(interfaces, ' & ')), + join(directives, ' '), + block(fields), + ], + ' ', + ), + }, + + FieldDefinition: { + leave: ({ description, name, arguments: args, type, directives }) => + wrap('', description, '\n') + + name + + (hasMultilineItems(args) + ? wrap('(\n', indent(join(args, '\n')), '\n)') + : wrap('(', join(args, ', '), ')')) + + ': ' + + type + + wrap(' ', join(directives, ' ')), + }, + + InputValueDefinition: { + leave: ({ description, name, type, defaultValue, directives }) => + wrap('', description, '\n') + + join( + [name + ': ' + type, wrap('= ', defaultValue), join(directives, ' ')], + ' ', + ), + }, + + InterfaceTypeDefinition: { + leave: ({ description, name, interfaces, directives, fields }) => + wrap('', description, '\n') + + join( + [ + 'interface', + name, + wrap('implements ', join(interfaces, ' & ')), + join(directives, ' '), + block(fields), + ], + ' ', + ), + }, + + UnionTypeDefinition: { + leave: ({ description, name, directives, types }) => + wrap('', description, '\n') + + join( + [ + 'union', + name, + join(directives, ' '), + wrap('= ', join(types, ' | ')), + ], + ' ', + ), + }, + + EnumTypeDefinition: { + leave: ({ description, name, directives, values }) => + wrap('', description, '\n') + + join(['enum', name, join(directives, ' '), block(values)], ' '), + }, + + EnumValueDefinition: { + leave: ({ description, name, directives }) => + wrap('', description, '\n') + join([name, join(directives, ' ')], ' '), + }, + + InputObjectTypeDefinition: { + leave: ({ description, name, directives, fields }) => + wrap('', description, '\n') + + join(['input', name, join(directives, ' '), block(fields)], ' '), + }, + + DirectiveDefinition: { + leave: ({ description, name, arguments: args, repeatable, locations }) => + wrap('', description, '\n') + + 'directive @' + + name + + (hasMultilineItems(args) + ? wrap('(\n', indent(join(args, '\n')), '\n)') + : wrap('(', join(args, ', '), ')')) + + (repeatable ? ' repeatable' : '') + + ' on ' + + join(locations, ' | '), + }, + + SchemaExtension: { + leave: ({ directives, operationTypes }) => + join( + ['extend schema', join(directives, ' '), block(operationTypes)], + ' ', + ), + }, + + ScalarTypeExtension: { + leave: ({ name, directives }) => + join(['extend scalar', name, join(directives, ' ')], ' '), + }, + + ObjectTypeExtension: { + leave: ({ name, interfaces, directives, fields }) => + join( + [ + 'extend type', + name, + wrap('implements ', join(interfaces, ' & ')), + join(directives, ' '), + block(fields), + ], + ' ', + ), + }, + + InterfaceTypeExtension: { + leave: ({ name, interfaces, directives, fields }) => + join( + [ + 'extend interface', + name, + wrap('implements ', join(interfaces, ' & ')), + join(directives, ' '), + block(fields), + ], + ' ', + ), + }, + + UnionTypeExtension: { + leave: ({ name, directives, types }) => + join( + [ + 'extend union', + name, + join(directives, ' '), + wrap('= ', join(types, ' | ')), + ], + ' ', + ), + }, + + EnumTypeExtension: { + leave: ({ name, directives, values }) => + join(['extend enum', name, join(directives, ' '), block(values)], ' '), + }, + + InputObjectTypeExtension: { + leave: ({ name, directives, fields }) => + join(['extend input', name, join(directives, ' '), block(fields)], ' '), + }, + }); +} + +const MAX_LINE_LENGTH = 80; /** * Given maybeArray, print an empty string if it is null or empty, otherwise diff --git a/src/type/definition.ts b/src/type/definition.ts index 80887c852d..bcd3862c89 100644 --- a/src/type/definition.ts +++ b/src/type/definition.ts @@ -75,15 +75,6 @@ export type GraphQLType = | GraphQLEnumType | GraphQLInputObjectType | GraphQLList - > - | GraphQLSemanticNullable< - | GraphQLScalarType - | GraphQLObjectType - | GraphQLInterfaceType - | GraphQLUnionType - | GraphQLEnumType - | GraphQLInputObjectType - | GraphQLList >; export function isType(type: unknown): type is GraphQLType { @@ -249,32 +240,6 @@ export function assertSemanticNonNullType( return type; } -export function isSemanticNullableType( - type: GraphQLInputType, -): type is GraphQLSemanticNullable; -export function isSemanticNullableType( - type: GraphQLOutputType, -): type is GraphQLSemanticNullable; -export function isSemanticNullableType( - type: unknown, -): type is GraphQLSemanticNullable; -export function isSemanticNullableType( - type: unknown, -): type is GraphQLSemanticNullable { - return instanceOf(type, GraphQLSemanticNullable); -} - -export function assertSemanticNullableType( - type: unknown, -): GraphQLSemanticNullable { - if (!isSemanticNullableType(type)) { - throw new Error( - `Expected ${inspect(type)} to be a GraphQL Semantic-Non-Null type.`, - ); - } - return type; -} - /** * These types may be used as input types for arguments and directives. */ @@ -545,52 +510,6 @@ export class GraphQLSemanticNonNull { } } -/** - * Semantic-Nullable Type Wrapper - * - * A semantic-nullable is a wrapping type which points to another type. - * Semantic-nullable types allow their values to be null. - * - * Example: - * - * ```ts - * const RowType = new GraphQLObjectType({ - * name: 'Row', - * fields: () => ({ - * email: { type: new GraphQLSemanticNullable(GraphQLString) }, - * }) - * }) - * ``` - * Note: This is equivalent to the unadorned named type that is - * used by GraphQL when it is not operating in SemanticNullability mode. - * - * @experimental - */ -export class GraphQLSemanticNullable { - readonly ofType: T; - - constructor(ofType: T) { - devAssert( - isNullableType(ofType), - `Expected ${inspect(ofType)} to be a GraphQL nullable type.`, - ); - - this.ofType = ofType; - } - - get [Symbol.toStringTag]() { - return 'GraphQLSemanticNullable'; - } - - toString(): string { - return String(this.ofType) + '?'; - } - - toJSON(): string { - return this.toString(); - } -} - /** * These types wrap and modify other types */ @@ -598,16 +517,10 @@ export class GraphQLSemanticNullable { export type GraphQLWrappingType = | GraphQLList | GraphQLNonNull - | GraphQLSemanticNonNull - | GraphQLSemanticNullable; + | GraphQLSemanticNonNull; export function isWrappingType(type: unknown): type is GraphQLWrappingType { - return ( - isListType(type) || - isNonNullType(type) || - isSemanticNonNullType(type) || - isSemanticNullableType(type) - ); + return isListType(type) || isNonNullType(type) || isSemanticNonNullType(type); } export function assertWrappingType(type: unknown): GraphQLWrappingType { diff --git a/src/utilities/extendSchema.ts b/src/utilities/extendSchema.ts index 40ba62c964..876aae277f 100644 --- a/src/utilities/extendSchema.ts +++ b/src/utilities/extendSchema.ts @@ -54,7 +54,6 @@ import { GraphQLObjectType, GraphQLScalarType, GraphQLSemanticNonNull, - GraphQLSemanticNullable, GraphQLUnionType, isEnumType, isInputObjectType, @@ -442,9 +441,6 @@ export function extendSchemaImpl( if (node.kind === Kind.SEMANTIC_NON_NULL_TYPE) { return new GraphQLSemanticNonNull(getWrappedType(node.type)); } - if (node.kind === Kind.SEMANTIC_NULLABLE_TYPE) { - return new GraphQLSemanticNullable(getWrappedType(node.type)); - } return getNamedType(node); } diff --git a/src/utilities/typeFromAST.ts b/src/utilities/typeFromAST.ts index 9e5bc9b925..c5d5f537a2 100644 --- a/src/utilities/typeFromAST.ts +++ b/src/utilities/typeFromAST.ts @@ -11,7 +11,6 @@ import { GraphQLList, GraphQLNonNull, GraphQLSemanticNonNull, - GraphQLSemanticNullable, } from '../type/definition'; import type { GraphQLSchema } from '../type/schema'; @@ -55,10 +54,6 @@ export function typeFromAST( const innerType = typeFromAST(schema, typeNode.type); return innerType && new GraphQLSemanticNonNull(innerType); } - case Kind.SEMANTIC_NULLABLE_TYPE: { - const innerType = typeFromAST(schema, typeNode.type); - return innerType && new GraphQLSemanticNullable(innerType); - } case Kind.NAMED_TYPE: return schema.getType(typeNode.name.value); }