-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
base: main
Are you sure you want to change the base?
Schema Coordinates #794
Changes from all commits
38616cc
45fb46c
eabdaff
f994f99
17002d4
6456c5f
4905977
8be29ca
568d26f
b8f3f47
8580162
87a38e2
75c48ba
148d073
c43f4aa
bb896cf
e5a2092
b65eb31
c16a28b
93bd2c6
b2e42e8
4ce2d48
2d60b33
d61cdc3
caed065
07b3bbd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -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_ can be a named type, a field, an input | ||||||||||||||||
field, an enum value, a field argument, a directive, or a 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. | ||||||||||||||||
Comment on lines
+2189
to
+2191
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a specific reason to forbid meta fields? I can definitely see myself using it. For an example to log introspection usages of my server. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||
|
||||||||||||||||
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}. | ||||||||||||||||
|
||||||||||||||||
Comment on lines
+2211
to
+2213
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: should we assert that the type exists?
Suggested change
This is mainly for symmetry with the "argument coordinate" case below which asserts field existence and is therefore allowed to "fail". Asserting that the type exists makes it explicit that a coordinate may "fail". |
||||||||||||||||
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 | ||||||||||||||||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, why do we even need that lexical rule? Most of the parsers I've bumped into do not have a
Punctuator
token and just use the underlying character directly.Punctuator
doesn't seem to be used by any grammar rule either?