New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] GraphQL Schema Definition Language (SDL) #90

Merged
merged 28 commits into from Feb 8, 2018

Conversation

@leebyron
Collaborator

leebyron commented Sep 2, 2015

This adds the type definition syntax to the GraphQL specification.

There are some remaining issues to solve:

  • Include reference in Execution chapter about non-executable GraphQL
  • Description is not yet represented
  • Deprecation is not yet represented
  • Directives are not yet represented
  • Top level Schema is not yet represented
  • Investigate impact on validation rules
  • Decide on any or many rules for type fields / enum values
  • Combine into type system chapter
  • Consider separating into two top level grammars
  • Solve ambiguity for extending interfaces (graphql/graphql-js#1166)
@leebyron

This comment has been minimized.

Show comment
Hide comment
@leebyron

leebyron Sep 2, 2015

Collaborator

Proposal for schema:

schema {
  query: QueryType
  mutation: MutationType
}
SchemaDefinition : schema { OperationTypeDefinition+ }
OperationTypeDefinition : OperationType : NamedType
Collaborator

leebyron commented Sep 2, 2015

Proposal for schema:

schema {
  query: QueryType
  mutation: MutationType
}
SchemaDefinition : schema { OperationTypeDefinition+ }
OperationTypeDefinition : OperationType : NamedType
Show outdated Hide outdated spec/Appendix B -- Grammar Summary.md Outdated
@nuance

This comment has been minimized.

Show comment
Hide comment
@nuance

nuance Nov 2, 2015

Should this also include directives? Something like:

DirectiveDefinition : directive Name ArgumentsDefinition?

This doesn't capture scope / validation rules, so perhaps it should include an 'on' clause?

DirectiveDefinition : directive Name ArgumentsDefinition? DirectiveScopes?
DirectiveScopes : on DirectiveScope+
DirectiveScope : field | fragment | operation

So include would be defined like:

directive include(if: Boolean!) on field, fragment

nuance commented Nov 2, 2015

Should this also include directives? Something like:

DirectiveDefinition : directive Name ArgumentsDefinition?

This doesn't capture scope / validation rules, so perhaps it should include an 'on' clause?

DirectiveDefinition : directive Name ArgumentsDefinition? DirectiveScopes?
DirectiveScopes : on DirectiveScope+
DirectiveScope : field | fragment | operation

So include would be defined like:

directive include(if: Boolean!) on field, fragment
@joshprice

This comment has been minimized.

Show comment
Hide comment
@joshprice

joshprice Jan 21, 2016

Is there any movement on this? This is a pretty compelling piece of the GraphQL puzzle and opens up the possibility of tooling around schema design and also allows the creation of a cross language test suite.

joshprice commented Jan 21, 2016

Is there any movement on this? This is a pretty compelling piece of the GraphQL puzzle and opens up the possibility of tooling around schema design and also allows the creation of a cross language test suite.

@nuance

This comment has been minimized.

Show comment
Hide comment
@nuance

nuance Jan 21, 2016

I ended up implementing most of this grammar in a project I'm working on. Here's the relevant lines from a PEG grammar (just the type parsing stuff):

TypeDefinition <- ObjectTypeDefinition / InterfaceTypeDefinition / UnionTypeDefinition / ScalarTypeDefinition / EnumTypeDefinition / InputObjectTypeDefinition / TypeExtensionDefinition / DirectiveDefinition
ObjectTypeDefinition <- "type" _ Name _ ImplementsInterfaces? _ "{" __ (FieldDefinition __)* "}"
ImplementsInterfaces <- "implements" _ (Name _)+
FieldDefinition <- Name _ ArgumentsDefinition? _ ':' _ InputType
ArgumentsDefinition <- '(' _ ( InputValueDefinition _ )* ')'
InputValueDefinition <- Name _ ':' _ InputType _ DefaultValue?
InterfaceTypeDefinition <- "interface" _ Name _ '{' __ (FieldDefinition __)+ '}'
UnionTypeDefinition <- ("union" / "Union") _ Name _ "=" _ UnionMembers
UnionMembers <- NamedType _ ("|" _ NamedType _)*
ScalarTypeDefinition <- "scalar" _ Name
EnumTypeDefinition <- "enum" _ Name _ "{" __ (EnumValue __)+ __ "}"
InputTypeDefinition <- Name _ ':' _ InputType _ DefaultValue?
InputObjectTypeDefinition <- "input" _ Name _ "{" __ (InputTypeDefinition __)+ "}"
DirectiveDefinition <- "directive" _ Name _ "on" _ (Name _)+ ArgumentsDefinition?
TypeExtensionDefinition <- "extend" _ ObjectTypeDefinition

I think this is basically compatible with the language defined in this PR, with a few additions (directives).

Answering the questions @leebyron asked:

  • description and deprecation are both expressed via directives
  • not sure what top level schema means - we define a query root object like:
type QueryRoot{}

then extend it as needed (I'm assuming that's what you're referencing?)

extend type QueryRoot {
    __schema : __Schema!
    __type(name: String!) : __Type
}
  • It's not clear what validation would be required. We're doing a little to catch compliance with the relay extensions and handle some of our own extensions, but nothing that passes the grammar has brought up anything interesting.

nuance commented Jan 21, 2016

I ended up implementing most of this grammar in a project I'm working on. Here's the relevant lines from a PEG grammar (just the type parsing stuff):

TypeDefinition <- ObjectTypeDefinition / InterfaceTypeDefinition / UnionTypeDefinition / ScalarTypeDefinition / EnumTypeDefinition / InputObjectTypeDefinition / TypeExtensionDefinition / DirectiveDefinition
ObjectTypeDefinition <- "type" _ Name _ ImplementsInterfaces? _ "{" __ (FieldDefinition __)* "}"
ImplementsInterfaces <- "implements" _ (Name _)+
FieldDefinition <- Name _ ArgumentsDefinition? _ ':' _ InputType
ArgumentsDefinition <- '(' _ ( InputValueDefinition _ )* ')'
InputValueDefinition <- Name _ ':' _ InputType _ DefaultValue?
InterfaceTypeDefinition <- "interface" _ Name _ '{' __ (FieldDefinition __)+ '}'
UnionTypeDefinition <- ("union" / "Union") _ Name _ "=" _ UnionMembers
UnionMembers <- NamedType _ ("|" _ NamedType _)*
ScalarTypeDefinition <- "scalar" _ Name
EnumTypeDefinition <- "enum" _ Name _ "{" __ (EnumValue __)+ __ "}"
InputTypeDefinition <- Name _ ':' _ InputType _ DefaultValue?
InputObjectTypeDefinition <- "input" _ Name _ "{" __ (InputTypeDefinition __)+ "}"
DirectiveDefinition <- "directive" _ Name _ "on" _ (Name _)+ ArgumentsDefinition?
TypeExtensionDefinition <- "extend" _ ObjectTypeDefinition

I think this is basically compatible with the language defined in this PR, with a few additions (directives).

Answering the questions @leebyron asked:

  • description and deprecation are both expressed via directives
  • not sure what top level schema means - we define a query root object like:
type QueryRoot{}

then extend it as needed (I'm assuming that's what you're referencing?)

extend type QueryRoot {
    __schema : __Schema!
    __type(name: String!) : __Type
}
  • It's not clear what validation would be required. We're doing a little to catch compliance with the relay extensions and handle some of our own extensions, but nothing that passes the grammar has brought up anything interesting.
@joshprice

This comment has been minimized.

Show comment
Hide comment
@joshprice

joshprice Jan 23, 2016

  • Got a concrete example for implementing metadata (description, isDeprecated, etc) using directives @nuance ?
  • Top level schema I think refers to being able to parse the schema itself which is fairly trivial, just needs to be spec'd fully, but it looks like your example could use existing primitives
schema {
  query: QueryType
  mutation: MutationType
}
  • You can't mix type defs and queries which is described in the spec already, but presumably not in the execution section yet
  • Schema validation would be somewhat different to query validation, but as you point out if it is parsable then it's probably right, not sure what semantics could be validated? Guidance on orphan/unreferenced types, circular references, for a start

joshprice commented Jan 23, 2016

  • Got a concrete example for implementing metadata (description, isDeprecated, etc) using directives @nuance ?
  • Top level schema I think refers to being able to parse the schema itself which is fairly trivial, just needs to be spec'd fully, but it looks like your example could use existing primitives
schema {
  query: QueryType
  mutation: MutationType
}
  • You can't mix type defs and queries which is described in the spec already, but presumably not in the execution section yet
  • Schema validation would be somewhat different to query validation, but as you point out if it is parsable then it's probably right, not sure what semantics could be validated? Guidance on orphan/unreferenced types, circular references, for a start
@joshprice

This comment has been minimized.

Show comment
Hide comment
@joshprice

joshprice Jan 23, 2016

For reference there are some concrete examples here: https://github.com/matthewmueller/graph.ql

Descriptions are assumed to be in comments immediately preceding the thing it's describing, assuming deprecation etc could be handled in a similar fashion with a specially formatted comment.

Another possibility for metadata might be type annotations starting with @:

@description Describes a person
type Person {
  @isDeprecated true
  field: Int
}

joshprice commented Jan 23, 2016

For reference there are some concrete examples here: https://github.com/matthewmueller/graph.ql

Descriptions are assumed to be in comments immediately preceding the thing it's describing, assuming deprecation etc could be handled in a similar fashion with a specially formatted comment.

Another possibility for metadata might be type annotations starting with @:

@description Describes a person
type Person {
  @isDeprecated true
  field: Int
}
@joshprice

This comment has been minimized.

Show comment
Hide comment
@joshprice

joshprice Jan 25, 2016

Thinking more about how this is done with directives, you could make something quite readable:

@metadata(description: "Describes a person")
type Person {
  @metadata(isDeprecated true)
  field: Int
}

joshprice commented Jan 25, 2016

Thinking more about how this is done with directives, you could make something quite readable:

@metadata(description: "Describes a person")
type Person {
  @metadata(isDeprecated true)
  field: Int
}
@joshprice

This comment has been minimized.

Show comment
Hide comment
@joshprice

joshprice Feb 19, 2016

Enums are also an issue, since values are not able to be supplied using the current syntax

joshprice commented Feb 19, 2016

Enums are also an issue, since values are not able to be supplied using the current syntax

@leebyron

This comment has been minimized.

Show comment
Hide comment
@leebyron

leebyron Mar 22, 2016

Collaborator

Updated to rebase atop recent changes and includes syntax for defining directives based on graphql/graphql-js#318

Collaborator

leebyron commented Mar 22, 2016

Updated to rebase atop recent changes and includes syntax for defining directives based on graphql/graphql-js#318

@leebyron

This comment has been minimized.

Show comment
Hide comment
@leebyron

leebyron Mar 22, 2016

Collaborator

Updated to rebase, fixed some outdated language and added SchemaDefinition

Collaborator

leebyron commented Mar 22, 2016

Updated to rebase, fixed some outdated language and added SchemaDefinition

leebyron added a commit to graphql/graphql-js that referenced this pull request Mar 22, 2016

leebyron added a commit to graphql/graphql-js that referenced this pull request Mar 22, 2016

[RFC] Add Schema Definition to IDL.
This implements the schema definition in the spec proposal in facebook/graphql#90

Adjusts AST, parser, printer, visitor, but also changes the API of buildASTSchema to require a schema definition instead of passing the type names into the function.
Show outdated Hide outdated spec/Section 2 -- Language.md Outdated

@OlegIlyenko OlegIlyenko referenced this pull request May 22, 2016

Closed

IDL (schema definition) syntax parsing and rendering #62

3 of 3 tasks complete

sogko added a commit to sogko/graphql that referenced this pull request May 30, 2016

Updating schema parser to more closely match current state of RFC
facebook/graphql#90

Commit:
b0885a038ec0e654962d69fb910ac86659279579 [b0885a0]
Parents:
fdafe32724
Author:
Lee Byron <lee@leebyron.com>
Date:
23 March 2016 at 6:35:37 AM SGT
Commit Date:
23 March 2016 at 6:35:39 AM SGT

sogko added a commit to sogko/graphql that referenced this pull request May 30, 2016

[RFC] Add Schema Definition to IDL.
This implements the schema definition in the spec proposal in facebook/graphql#90

Adjusts AST, parser, printer, visitor, but also changes the API of buildASTSchema to require a schema definition instead of passing the type names into the function.

Commit:
8379e71f7011fe044574f4bdef2a761d18d6cf2c [8379e71]
Parents:
176076c8a6
Author:
Lee Byron <lee@leebyron.com>
Date:
23 March 2016 at 7:38:15 AM SGT
Labels:
HEAD

@sogko sogko referenced this pull request Jun 13, 2016

Closed

Schema Definition #2

@joshprice joshprice referenced this pull request Jun 17, 2016

Closed

Schema DSL #15

@charlieschwabacher

This comment has been minimized.

Show comment
Hide comment
@charlieschwabacher

charlieschwabacher Jul 2, 2016

@leebyron can you share anything about your thinking on a syntax for descriptions? Do you expect it to use directives? comments? Or is it still a ways off?

charlieschwabacher commented Jul 2, 2016

@leebyron can you share anything about your thinking on a syntax for descriptions? Do you expect it to use directives? comments? Or is it still a ways off?

@helfer

This comment has been minimized.

Show comment
Hide comment
@helfer

helfer Jul 2, 2016

Contributor

@charlieschwabacher Lee has said somewhere that he wants it to be in comment format, because that will be the easiest to read and format. I can't find the issue(s) where he said that any more, but I'm 100% sure about it.

Contributor

helfer commented Jul 2, 2016

@charlieschwabacher Lee has said somewhere that he wants it to be in comment format, because that will be the easiest to read and format. I can't find the issue(s) where he said that any more, but I'm 100% sure about it.

@leebyron

This comment has been minimized.

Show comment
Hide comment
@leebyron

leebyron Jul 2, 2016

Collaborator

Yep, I think we should use comments as doc blocks to describe types and fields. It's a little annoying and "un-pure" from the parser's point of view since technically comments are "ignored" tokens, however it's hard to ignore the better developer ergonomics and it's also quite easy to point to prior art like JavaDoc.

Collaborator

leebyron commented Jul 2, 2016

Yep, I think we should use comments as doc blocks to describe types and fields. It's a little annoying and "un-pure" from the parser's point of view since technically comments are "ignored" tokens, however it's hard to ignore the better developer ergonomics and it's also quite easy to point to prior art like JavaDoc.

@leebyron leebyron merged commit 593dd2c into master Feb 8, 2018

2 checks passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
continuous-integration/travis-ci/push The Travis CI build passed
Details

@leebyron leebyron deleted the rfc-idl branch Feb 8, 2018

danez pushed a commit to danez/graphql-php that referenced this pull request Feb 9, 2018

Daniel Tschinder
RFC: Descriptions as strings
As discussed in facebook/graphql#90

This proposes replacing leading comment blocks as descriptions in the schema definition language with leading strings (typically block strings).

While I think there is some reduced ergonomics of using a string literal instead of a comment to write descriptions (unless perhaps you are accustomed to Python or Clojure), there are some compelling advantages:

* Descriptions are first-class in the AST of the schema definition language.
* Comments can remain "ignored" characters.
* No ambiguity between commented out regions and descriptions.

Specific to this reference implementation, since this is a breaking change and comment descriptions in the experimental SDL have fairly wide usage, I've left the comment description implementation intact and allow it to be enabled via an option. This should help with allowing upgrading with minimal impact on existing codebases and aid in automated transforms.

BREAKING CHANGE: This does not parse descriptions from comments by default anymore and the value of description in Nodes changed from string to StringValueNode

danez pushed a commit to danez/graphql-php that referenced this pull request Feb 10, 2018

Daniel Tschinder
RFC: Descriptions as strings
As discussed in facebook/graphql#90

This proposes replacing leading comment blocks as descriptions in the schema definition language with leading strings (typically block strings).

While I think there is some reduced ergonomics of using a string literal instead of a comment to write descriptions (unless perhaps you are accustomed to Python or Clojure), there are some compelling advantages:

* Descriptions are first-class in the AST of the schema definition language.
* Comments can remain "ignored" characters.
* No ambiguity between commented out regions and descriptions.

Specific to this reference implementation, since this is a breaking change and comment descriptions in the experimental SDL have fairly wide usage, I've left the comment description implementation intact and allow it to be enabled via an option. This should help with allowing upgrading with minimal impact on existing codebases and aid in automated transforms.

BREAKING CHANGE: This does not parse descriptions from comments by default anymore and the value of description in Nodes changed from string to StringValueNode

danez pushed a commit to danez/graphql-php that referenced this pull request Feb 11, 2018

Daniel Tschinder
Update to match SDL changes
This changes the parsing grammar and validation rules to more correctly implement the current state of the GraphQL SDL proposal (facebook/graphql#90)

ref: graphql/graphl-js#1102

tonyghita added a commit to graph-gophers/graphql-go that referenced this pull request Mar 7, 2018

Separate multiple inherited interfaces with `&`
This replaces:

```graphql
type Foo implements Bar, Baz { field: Type }
```

With:

```graphql
type Foo implements Bar & Baz { field: Type }
```

This is more consistent with other trailing lists of values which
either have an explicit separator (union members) or are prefixed
with a sigil (directives). This avoids parse ambiguity in the
case of an omitted field set, illustrated by
[github.com/graphql/graphql-js#1166](graphql/graphql-js#1166).

For now, the old method of declaration remains valid.

References:
- graphql/graphql-js#1169
- facebook/graphql#90
- facebook/graphql@32b55ed

@jburghardt jburghardt referenced this pull request Mar 28, 2018

Merged

Update docs on schema #999

@ermik

This comment has been minimized.

Show comment
Hide comment
@ermik

ermik May 11, 2018

@leebyron why is the spec still dated October 2016 at http://facebook.github.io/graphql/?

ermik commented May 11, 2018

@leebyron why is the spec still dated October 2016 at http://facebook.github.io/graphql/?

@IvanGoncharov

This comment has been minimized.

Show comment
Hide comment
@IvanGoncharov

IvanGoncharov May 11, 2018

Collaborator

@ermik Because it's the last official release.
You can find the draft of the next release (including SDL) here:
http://facebook.github.io/graphql/draft/

Collaborator

IvanGoncharov commented May 11, 2018

@ermik Because it's the last official release.
You can find the draft of the next release (including SDL) here:
http://facebook.github.io/graphql/draft/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment