GAP-33: Set Extensions for Type System Documents
Version: Draft
Authors: Matt Mahoney
Discussion: github.com/graphql/gaps/pull/33

Set Extensions for Type System Documents

This document specifics an alternative to the Type System Document for defining a set-compatible version of the type system of a GraphQL Schema.

It is common to need to treat schema documents as sets: we may want to merge two documents to create a “Composite Schema”, or you might want to know the intersection between documents to build products that work against all the provided GraphQL Services.

Any grammar not defined, but used, in this document is a reference to the grammar defined in the GraphQL Specification’s Grammar.

The key change to the grammar: every location in the schema that can have a directive now can also be an Extension.

To put it another way, if a location in the Schema can be defined by a Schema Coordinate, then it can exist in the Set Type System in an extend representation. Additionally, the root schema has an extend representation, because it can apply set operations.

1Set Type System

1.1Schema

SetSchemaDefinition
DescriptionoptschemaDirectivesConstopt{RootOperationTypeDefinitionlist}
RootOperationTypeDefinition
OperationType:NamedType

1.1.1Schema Extension

SetSchemaExtension
extendschemaDirectivesConstopt{RootOperationTypeDefinitionlist}
extendschemaDirectivesConst{

SetSchemaDefinition and SetSchemaExtension are grammatically identical to the Schema in the GraphQL Specification.

1.2Types

1.2.1Type Extensions

1.3Scalars

SetScalarTypeDefinition
DescriptionoptscalarNameDirectivesConstopt

SetScalarTypeDefinition and SetScalarTypeExtension are gramatically identical to the Scalars Specification.

1.3.1Scalar Extensions

SetScalarTypeExtension
extendscalarNameDirectivesConst

1.4Objects

SetObjectTypeDefinition
DescriptionopttypeNameImplementsInterfacesoptDirectivesConstoptSetFieldsDefinitionOrExtension
DescriptionopttypeNameImplementsInterfacesoptDirectivesConstopt{
ImplementsInterfaces
implements&optNamedType

1.4.1Object Extensions

SetObjectTypeExtension
extendtypeNameImplementsInterfacesoptDirectivesConstoptSetFieldsDefinitionOrExtension
extendtypeNameImplementsInterfacesoptDirectivesConst{
extendtypeNameImplementsInterfaces{

1.5Fields

SetFieldDefinition
DescriptionoptNameSetArgumentsDefinitionOrExtensionopt:TypeDirectivesConstopt
DescriptionoptNameSetArgumentsDefinitionOrExtension:DirectivesConstopt
DescriptionoptName:DirectivesConstopt

1.5.1Field Extensions

SetFieldExtension
extendNameSetArgumentsDefinitionOrExtensionopt:TypeDirectivesConstopt
extendNameSetArgumentsDefinitionOrExtension:DirectivesConstopt
extendName:DirectivesConstopt

It is possible for the type definition of a field to only be present in that field’s extension. Likewise, we need to be able to extend a field (like deprecating it) with a guarantee that the field’s type will not change through the extension.

Field extensions are different from fields defined by a type extension. The below is valid syntax:

graphql field-extension extend type Person { extend age @deprecated name } type Business { extend name @deprecated } To become a valid GraphQL Spec document, the above would need to be union‘d with a document like:

graphql field-extension-merge type Person { age: Int extend name: String @deprecated } extend type Business { name: String }

resulting in:

graphql field-extension-union type Person { age: Int @deprecated name: String @deprecated } type Business { name: String @deprecated } which is now a valid GraphQL Type System Document.

The syntax of allowing field definitions without a type definition enables tooling, such as diff tools, to have a valid syntax for how a schema is evolving, even if the semantic meaning of the syntax would not produce a valid GraphQL Schema.

1.5.2Field Arguments

1.5.3Input Values

SetInputValueDefinition
DescriptionoptName:TypeDefaultValueoptDirectivesConstopt
DescriptionoptName:DefaultValueoptDirectivesConstopt

1.5.4Input Value Extensions

SetInputValueExtension
extendName:TypeDirectivesConstopt
extendName:DirectivesConstopt

Similar to Field Definitions and Extensions, Input Value Definitions and Extensions cannot may elide the input value’s type.

Example
graphql argument-extension type Person { name(short): String extend age(minimum: Int) } uniongraphql argument-extension-union type Person { extend name(extend short: Boolean) age(extend minimum @deprecated): Int } resultsin:type Person { name(short: Boolean): String age(minimum @deprecated): Int }
SetInterfaceTypeDefinition
DescriptionoptinterfaceNameImplementsInterfacesoptDirectivesConstoptSetFieldsDefinitionOrExtension
DescriptionoptinterfaceNameImplementsInterfacesoptDirectivesConstopt{
SetInterfaceTypeExtension
extendinterfaceNameImplementsInterfacesoptDirectivesConstoptSetFieldsDefinitionOrExtension
extendinterfaceNameImplementsInterfacesoptDirectivesConst{
extendinterfaceNameImplementsInterfaces{

1.6Unions

SetUnionTypeDefinition
DescriptionoptunionNameDirectivesConstoptUnionMemberTypesopt
UnionMemberTypes
=|optNamedType

1.6.1Union Extensions

SetUnionTypeExtension
extendunionNameDirectivesConstoptUnionMemberTypes
extendunionNameDirectivesConst

SetUntionTypeExtension is gramatically identical to the Unions in the GraphQL Specification.

1.7Enums

SetEnumTypeDefinition
DescriptionoptenumNameDirectivesConstoptSetEnumValuesDefinitionOrExtension
DescriptionoptenumNameDirectivesConstopt{

1.7.1Enum Values

SetEnumValueDefinition
DescriptionoptEnumValueDirectivesConstoptSetEnumValueExtension:extendEnumValueDirectivesConstopt

1.7.2Enum Extensions

SetEnumTypeExtension
extendenumNameDirectivesConstoptSetEnumValuesDefinitionOrExtension
extendenumNameDirectivesConst{

1.8Input Objects

InputObjectTypeDefinition
DescriptionoptinputNameDirectivesConstoptSetInputFieldsDefinitionOrExtension
DescriptionoptinputNameDirectivesConstopt{

1.9Input Object Extensions

InputObjectTypeExtension
extendinputNameDirectivesConstoptSetInputFieldsDefinitionOrExtension
extendinputNameDirectivesConst{

1.10Directives

Note we are assuming that directives on directive definitions, (https://github.com/graphql/graphql-spec/pull/1206) is in the spec at this point.
SetDirectiveDefinition
Descriptionoptdirective@NameSetArgumentsDefinitionOrExtensionoptDirectivesConstoptrepeatableoptonDirectiveLocations
ExecutableDirectiveLocation
QUERY
MUTATION
SUBSCRIPTION
FIELD
FRAGMENT_DEFINITION
FRAGMENT_SPREAD
INLINE_FRAGMENT
VARIABLE_DEFINITION
TypeSystemDirectiveLocation
SCHEMA
SCALAR
OBJECT
FIELD_DEFINITION
ARGUMENT_DEFINITION
INTERFACE
UNION
ENUM
ENUM_VALUE
INPUT_OBJECT
INPUT_FIELD_DEFINITION
DIRECTIVE_DEFINITION

1.10.1Directive Extensions

SetDirectiveExtension
extenddirective@NameSetArgumentsDefinitionOrExtensionoptDirectivesConst

2Set Operations

With the provided syntax, we can create set operations

2.1Union

type A implements X {
  field(arg: Int): String
}

union graphql type A @directive { field(arg: Int!): String! } will result in: type A implements X @directive { field(arg: Int!): String }

If a union could not possibly be commutative, i.e. the order of set union would affect the result, then the union operation should return a UnionError. The type of A.field below cannot be determined. type A { field: Int! } union type A { field: String! }

2.2Exclude

2.3Intersect

A intersect B = A exclude (A exclude B).

intersect is defined by the application of exclude.

3Appendix: Grammar Summary

SetSchemaDefinition
DescriptionoptschemaDirectivesConstopt{RootOperationTypeDefinitionlist}
SetSchemaExtension
extendschemaDirectivesConstopt{RootOperationTypeDefinitionlist}
extendschemaDirectivesConst{
RootOperationTypeDefinition
OperationType:NamedType
SetScalarTypeDefinition
DescriptionoptscalarNameDirectivesConstopt
SetScalarTypeExtension
extendscalarNameDirectivesConst
SetObjectTypeDefinition
DescriptionopttypeNameImplementsInterfacesoptDirectivesConstoptSetFieldsDefinitionOrExtension
DescriptionopttypeNameImplementsInterfacesoptDirectivesConstopt{
SetObjectTypeExtension
extendtypeNameImplementsInterfacesoptDirectivesConstoptSetFieldsDefinitionOrExtension
extendtypeNameImplementsInterfacesoptDirectivesConst{
extendtypeNameImplementsInterfaces{
ImplementsInterfaces
implements&optNamedType
SetFieldDefinition
DescriptionoptNameSetArgumentsDefinitionOrExtensionopt:TypeDirectivesConstopt
DescriptionoptNameSetArgumentsDefinitionOrExtension:DirectivesConstopt
DescriptionoptName:DirectivesConstopt
SetFieldExtension
extendNameSetArgumentsDefinitionOrExtensionopt:TypeDirectivesConstopt
extendNameSetArgumentsDefinitionOrExtension:DirectivesConstopt
extendName:DirectivesConstopt
SetInputValueDefinition
DescriptionoptName:TypeDefaultValueoptDirectivesConstopt
DescriptionoptName:DirectivesConstopt
SetInputValueExtension
extendName:TypeDefaultValueoptDirectivesConstopt
extendName:DirectivesConstopt
SetInterfaceTypeDefinition
DescriptionoptinterfaceNameImplementsInterfacesoptDirectivesConstoptSetFieldsDefinitionOrExtension
DescriptionoptinterfaceNameImplementsInterfacesoptDirectivesConstopt{
SetInterfaceTypeExtension
extendinterfaceNameImplementsInterfacesoptDirectivesConstoptSetFieldsDefinitionOrExtension
extendinterfaceNameImplementsInterfacesoptDirectivesConst{
extendinterfaceNameImplementsInterfaces{
SetUnionTypeDefinition
DescriptionoptunionNameDirectivesConstoptUnionMemberTypesopt
UnionMemberTypes
=|optNamedType
SetUnionTypeExtension
extendunionNameDirectivesConstoptUnionMemberTypes
extendunionNameDirectivesConst
SetEnumTypeDefinition
DescriptionoptenumNameDirectivesConstoptSetEnumValuesDefinitionsOrExtension
DescriptionoptenumNameDirectivesConstopt{
SetEnumValueDefinition
DescriptionoptEnumValueDirectivesConstopt
SetEnumValueExtension
extendEnumValueDirectivesConstopt
SetEnumTypeExtension
extendenumNameDirectivesConstoptSetEnumValuesDefinitionsOrExtension
extendenumNameDirectivesConst{
SetInputObjectTypeDefinition
DescriptionoptinputNameDirectivesConstoptSetInputFieldsDefinition
DescriptionoptinputNameDirectivesConstopt{
SetInputObjectTypeExtension
extendinputNameDirectivesConstoptSetInputFieldsDefinition
extendinputNameDirectivesConst{
ExecutableDirectiveLocation
QUERY
MUTATION
SUBSCRIPTION
FIELD
FRAGMENT_DEFINITION
FRAGMENT_SPREAD
INLINE_FRAGMENT
VARIABLE_DEFINITION
TypeSystemDirectiveLocation
SCHEMA
SCALAR
OBJECT
FIELD_DEFINITION
ARGUMENT_DEFINITION
INTERFACE
UNION
ENUM
ENUM_VALUE
INPUT_OBJECT
INPUT_FIELD_DEFINITION
DIRECTIVE_DEFINITION
SetDirectiveExtension
extenddirective@NameSetArgumentsDefinitionOrExtensionoptDirectivesConst

§Index

  1. DirectiveLocation
  2. DirectiveLocations
  3. Example
  4. ExecutableDirectiveLocation
  5. ImplementsInterfaces
  6. InputObjectTypeDefinition
  7. InputObjectTypeExtension
  8. RootOperationTypeDefinition
  9. SetArgumentsDefinition
  10. SetArgumentsDefinitionOrExtension
  11. SetDirectiveDefinition
  12. SetDirectiveExtension
  13. SetEnumTypeDefinition
  14. SetEnumTypeExtension
  15. SetEnumValueDefinition
  16. SetEnumValueDefinitionOrExtension
  17. SetEnumValueExtension
  18. SetEnumValuesDefinitionOrExtension
  19. SetFieldDefinition
  20. SetFieldDefinitionOrExtension
  21. SetFieldExtension
  22. SetFieldsDefinitionOrExtension
  23. SetInputFieldsDefinition
  24. SetInputFieldsDefinitionOrExtension
  25. SetInputObjectTypeDefinition
  26. SetInputObjectTypeExtension
  27. SetInputValueDefinition
  28. SetInputValueDefinitionOrExtension
  29. SetInputValueExtension
  30. SetInterfaceTypeDefinition
  31. SetInterfaceTypeExtension
  32. SetObjectTypeDefinition
  33. SetObjectTypeExtension
  34. SetScalarTypeDefinition
  35. SetScalarTypeExtension
  36. SetSchemaDefinition
  37. SetSchemaExtension
  38. SetTypeDefinition
  39. SetTypeExtension
  40. SetTypeSystemDefinition
  41. SetTypeSystemDefinitionOrExtension
  42. SetTypeSystemDocument
  43. SetTypeSystemExtension
  44. SetTypeSystemExtensionDocument
  45. SetUnionTypeDefinition
  46. SetUnionTypeExtension
  47. TypeSystemDirectiveLocation
  48. UnionMemberTypes
  1. 1Set Type System
    1. 1.1Schema
      1. 1.1.1Schema Extension
    2. 1.2Types
      1. 1.2.1Type Extensions
    3. 1.3Scalars
      1. 1.3.1Scalar Extensions
    4. 1.4Objects
      1. 1.4.1Object Extensions
    5. 1.5Fields
      1. 1.5.1Field Extensions
      2. 1.5.2Field Arguments
      3. 1.5.3Input Values
      4. 1.5.4Input Value Extensions
    6. 1.6Unions
      1. 1.6.1Union Extensions
    7. 1.7Enums
      1. 1.7.1Enum Values
      2. 1.7.2Enum Extensions
    8. 1.8Input Objects
    9. 1.9Input Object Extensions
    10. 1.10Directives
      1. 1.10.1Directive Extensions
  2. 2Set Operations
    1. 2.1Union
    2. 2.2Exclude
    3. 2.3Intersect
  3. 3Appendix: Grammar Summary
  4. §Index