Skip to content
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

Schema Coordinates #794

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion spec/Appendix B -- Grammar Summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,14 @@ Token ::
- FloatValue
- StringValue

Punctuator :: one of ! $ & ( ) ... : = @ [ ] { | }
Punctuator ::

- DotPunctuator
- OtherPunctuator

DotPunctuator :: `.` [lookahead != {`.`, Digit}]

OtherPunctuator :: one of ! $ & ( ) ... : = @ [ ] { | }

Name ::

Expand Down Expand Up @@ -412,3 +419,11 @@ TypeSystemDirectiveLocation : one of
- `ENUM_VALUE`
- `INPUT_OBJECT`
- `INPUT_FIELD_DEFINITION`

SchemaCoordinate :

- Name
- Name . Name
- Name . Name ( Name : )
- @ Name
- @ Name ( Name : )
15 changes: 14 additions & 1 deletion spec/Section 2 -- Language.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,25 @@ and is {Ignored}.

### Punctuators

Punctuator :: one of ! $ & ( ) ... : = @ [ ] { | }
Punctuator ::

- DotPunctuator
- OtherPunctuator

DotPunctuator :: `.` [lookahead != {`.`, Digit}]

OtherPunctuator :: one of ! $ & ( ) ... : = @ [ ] { | }

GraphQL documents include punctuation in order to describe structure. GraphQL is
a data description language and not a programming language, therefore GraphQL
lacks the punctuation often used to describe mathematical expressions.

The {`.`} punctuator must not be followed by a {`.`} or {Digit}. This ensures
that the source {"..."} can only be interpreted as a single {`...`} and not
three {`.`}. It also avoids any potential ambiguity with {FloatValue}. As an
example the source {".123"} has no valid lexical representation (without this
restriction it would have been interpreted as {`.`} followed by {IntValue}).

### Names

Name ::
Expand Down
125 changes: 125 additions & 0 deletions spec/Section 3 -- Type System.md
Original file line number Diff line number Diff line change
Expand Up @@ -2164,3 +2164,128 @@ to the relevant IETF specification.
```graphql example
scalar UUID @specifiedBy(url: "https://tools.ietf.org/html/rfc4122")
```

## Schema Coordinates

SchemaCoordinate :

- Name
- Name . Name
- Name . Name ( Name : )
- @ Name
- @ Name ( Name : )

:: A _schema coordinate_ is a human readable string that uniquely identifies a
_schema element_ within a GraphQL Schema.

:: A _schema element_ is a specific instance of a named type, field, input
field, enum value, field argument, directive, or directive argument.

A _schema coordinate_ is always unique. Each _schema element_ may be referenced
by exactly one possible schema coordinate.

A _schema coordinate_ may refer to either a defined or built-in _schema
element_. For example, `String` and `@deprecated(reason:)` are both valid schema
coordinates which refer to built-in schema elements. However it must not refer
to a meta-field. For example, `Business.__typename` is _not_ a valid schema
coordinate.

Note: A union member is not a valid _schema coordinate_ as they reference
existing types in the schema. This preserves the uniqueness property of a
_schema coordinate_ as stated above.

Note: A {SchemaCoordinate} is not a definition within a GraphQL {Document}, but
a separate standalone grammar, intended to be used by tools to reference types,
fields, and other *schema element*s. Examples include: as references within
documentation to refer to types and fields in a schema, a lookup key that can be
used in logging tools to track how often particular fields are queried in
production.

**Semantics**

To refer to a _schema element_, a _schema coordinate_ must be interpreted in the
context of a GraphQL {schema}.

SchemaCoordinate : Name

1. Let {typeName} be the value of the first {Name}.
2. Return the type in the {schema} named {typeName}.

SchemaCoordinate : Name . Name

1. Let {typeName} be the value of the first {Name}.
2. Let {type} be the type in the {schema} named {typeName}.
3. If {type} is an Enum type:
4. Let {enumValueName} be the value of the second {Name}.
5. Return the enum value of {type} named {enumValueName}.
6. Otherwise if {type} is an Input Object type:
7. Let {inputFieldName} be the value of the second {Name}.
8. Return the input field of {type} named {inputFieldName}.
9. Otherwise:
10. Assert {type} must be an Object or Interface type.
11. Let {fieldName} be the value of the second {Name}.
12. Return the field of {type} named {fieldName}.

SchemaCoordinate : Name . Name ( Name : )

1. Let {typeName} be the value of the first {Name}.
2. Let {type} be the type in the {schema} named {typeName}.
3. Assert {type} must be an Object or Interface type.
4. Let {fieldName} be the value of the second {Name}.
5. Let {field} be the field of {type} named {fieldName}.
6. Assert {field} must exist.
7. Let {fieldArgumentName} be the value of the third {Name}.
8. Return the argument of {field} named {fieldArgumentName}.

SchemaCoordinate : @ Name

1. Let {directiveName} be the value of the first {Name}.
2. Return the directive in the {schema} named {directiveName}.

SchemaCoordinate : @ Name ( Name : )

1. Let {directiveName} be the value of the first {Name}.
2. Let {directive} be the directive in the {schema} named {directiveName}.
3. Assert {directive} must exist.
4. Let {directiveArgumentName} be the value of the second {Name}.
5. Return the argument of {directive} named {directiveArgumentName}.

**Examples**

| Element Kind | _Schema Coordinate_ | _Schema Element_ |
| ------------------ | --------------------------------- | --------------------------------------------------------------------- |
| Named Type | `Business` | `Business` type |
| Field | `Business.name` | `name` field on the `Business` type |
| Input Field | `SearchCriteria.filter` | `filter` input field on the `SearchCriteria` input object type |
| Enum Value | `SearchFilter.OPEN_NOW` | `OPEN_NOW` value of the `SearchFilter` enum |
| Field Argument | `Query.searchBusiness(criteria:)` | `criteria` argument on the `searchBusiness` field on the `Query` type |
| Directive | `@private` | `@private` directive |
| Directive Argument | `@private(scope:)` | `scope` argument on the `@private` directive |

The table above shows an example of a _schema coordinate_ for every kind of
_schema element_ based on the schema below.

```graphql
type Query {
searchBusiness(criteria: SearchCriteria!): [Business]
}

input SearchCriteria {
name: String
filter: SearchFilter
}

enum SearchFilter {
OPEN_NOW
DELIVERS_TAKEOUT
VEGETARIAN_MENU
}

type Business {
id: ID
name: String
email: String @private(scope: "loggedIn")
}

directive @private(scope: String!) on FIELD_DEFINITION
```
Loading