Skip to content

Commit 9dd2ba4

Browse files
committed
Merge branch 'main' into lee/license-md
2 parents 62e5c1f + 1e29b8a commit 9dd2ba4

File tree

5 files changed

+238
-37
lines changed

5 files changed

+238
-37
lines changed

spec/Appendix B -- Grammar Summary.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,3 +413,32 @@ TypeSystemDirectiveLocation : one of
413413
- `ENUM_VALUE`
414414
- `INPUT_OBJECT`
415415
- `INPUT_FIELD_DEFINITION`
416+
417+
## Schema Coordinate Syntax
418+
419+
Note: Schema coordinates must not contain {Ignored}.
420+
421+
SchemaCoordinateToken ::
422+
423+
- SchemaCoordinatePunctuator
424+
- Name
425+
426+
SchemaCoordinatePunctuator :: one of ( ) . : @
427+
428+
SchemaCoordinate ::
429+
430+
- TypeCoordinate
431+
- MemberCoordinate
432+
- ArgumentCoordinate
433+
- DirectiveCoordinate
434+
- DirectiveArgumentCoordinate
435+
436+
TypeCoordinate :: Name
437+
438+
MemberCoordinate :: Name . Name
439+
440+
ArgumentCoordinate :: Name . Name ( Name : )
441+
442+
DirectiveCoordinate :: @ Name
443+
444+
DirectiveArgumentCoordinate :: @ Name ( Name : )

spec/Section 2 -- Language.md

Lines changed: 178 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,11 @@ GraphQL descriptions are provided as Markdown (as specified by
247247
[CommonMark](https://commonmark.org/)). Description strings (often
248248
{BlockString}) occur immediately before the definition they describe.
249249

250+
Descriptions in GraphQL executable documents are purely for documentation
251+
purposes. They MUST NOT affect the execution, validation, or response of a
252+
GraphQL document. It is safe to remove all descriptions and comments from
253+
executable documents without changing their behavior or results.
254+
250255
This is an example of a well-described operation:
251256

252257
```graphql example
@@ -279,11 +284,6 @@ fragment TimeMachineDetails on TimeMachine {
279284
}
280285
```
281286

282-
Descriptions in GraphQL executable documents are purely for documentation
283-
purposes. They MUST NOT affect the execution, validation, or response of a
284-
GraphQL document. It is safe to remove all descriptions and comments from
285-
executable documents without changing their behavior or results.
286-
287287
## Document
288288

289289
Document : Definition+
@@ -1377,3 +1377,176 @@ type Person
13771377
name: String
13781378
}
13791379
```
1380+
1381+
## Schema Coordinates
1382+
1383+
SchemaCoordinate ::
1384+
1385+
- TypeCoordinate
1386+
- MemberCoordinate
1387+
- ArgumentCoordinate
1388+
- DirectiveCoordinate
1389+
- DirectiveArgumentCoordinate
1390+
1391+
TypeCoordinate :: Name
1392+
1393+
MemberCoordinate :: Name . Name
1394+
1395+
ArgumentCoordinate :: Name . Name ( Name : )
1396+
1397+
DirectiveCoordinate :: @ Name
1398+
1399+
DirectiveArgumentCoordinate :: @ Name ( Name : )
1400+
1401+
:: A _schema coordinate_ is a human readable string that uniquely identifies a
1402+
_schema element_ within a GraphQL Schema, intended to be used by tools to
1403+
reference types, fields, and other _schema element_. Examples include:
1404+
references within documentation to refer to types and fields in a schema, a
1405+
lookup key that can be used in logging tools to track how often particular
1406+
fields are queried in production.
1407+
1408+
:: A _schema element_ can be a named type, a field, an input field, an enum
1409+
value, a field argument, a directive, or a directive argument defined within a
1410+
schema (including built-in types and directives).
1411+
1412+
Note: Meta-fields are not defined within a schema, and thus are not _schema
1413+
element_. By extension, an introspection type is not a _schema element_.
1414+
1415+
:: The _containing element_ of a _schema element_ is the schema element with one
1416+
fewer {Name} token that syntactically contains it. Specifically:
1417+
1418+
- The containing element of an {ArgumentCoordinate} is a {MemberCoordinate}.
1419+
- The containing element of a {MemberCoordinate} is a {TypeCoordinate}.
1420+
- The containing element of a {DirectiveArgumentCoordinate} is a
1421+
{DirectiveCoordinate}.
1422+
- {TypeCoordinate} and {DirectiveCoordinate} have no containing element.
1423+
1424+
A _schema coordinate_ is always unique. Each _schema element_ can be referenced
1425+
by exactly one possible schema coordinate.
1426+
1427+
A _schema coordinate_ may refer to either a defined or built-in _schema
1428+
element_. For example, `String` and `@deprecated(reason:)` are both valid schema
1429+
coordinates which refer to built-in schema elements.
1430+
1431+
Note: A union member references a type in the schema. A type in the schema is
1432+
identified by a {TypeCoordinate}. There is no schema coordinate which indicates
1433+
a union member; this preserves the uniqueness property of a _schema coordinate_
1434+
as stated above.
1435+
1436+
**Parsing a Schema Coordinate**
1437+
1438+
SchemaCoordinateToken ::
1439+
1440+
- SchemaCoordinatePunctuator
1441+
- Name
1442+
1443+
SchemaCoordinatePunctuator :: one of ( ) . : @
1444+
1445+
A {SchemaCoordinate} is a self-contained grammar with its own set of lexical
1446+
tokens, it is not contained within a {Document}. The source text of a
1447+
SchemaCoordinate must be a sequence of {SourceCharacter}.
1448+
1449+
Unlike other [GraphQL documents](#sec-Language), {SchemaCoordinate} must not
1450+
contain {Whitespace} or other {Ignored} grammars within the character sequence.
1451+
This ensures that every schema coordinates has a single unambiguous and unique
1452+
lexical form.
1453+
1454+
**Resolving a Schema Coordinate**
1455+
1456+
To refer to a _schema element_, a _schema coordinate_ must be interpreted in the
1457+
context of a GraphQL {schema}.
1458+
1459+
If the _schema element_ cannot be found, the resolve function will not yield a
1460+
value (without raising an error). However, an error will be raised if any
1461+
non-leaf nodes within a _schema coordinate_ cannot be found in the {schema}.
1462+
1463+
Note: Although it is syntactically possible to describe a meta-field or element
1464+
of the introspection schema with a schema coordinate (e.g. `Business.__typename`
1465+
or `__Type.fields(includeDeprecated:)`), they are not _schema element_ and
1466+
therefore resolving such coordinates does not have a defined behavior.
1467+
1468+
TypeCoordinate :: Name
1469+
1470+
1. Let {typeName} be the value of {Name}.
1471+
2. Return the type in {schema} named {typeName} if it exists.
1472+
1473+
MemberCoordinate :: Name . Name
1474+
1475+
1. Let {typeName} be the value of the first {Name}.
1476+
2. Let {type} be the type in {schema} named {typeName}.
1477+
3. Assert: {type} must exist, and must be an Enum, Input Object, Object or
1478+
Interface type.
1479+
4. If {type} is an Enum type:
1480+
1. Let {enumValueName} be the value of the second {Name}.
1481+
2. Return the enum value of {type} named {enumValueName} if it exists.
1482+
5. Otherwise, if {type} is an Input Object type:
1483+
1. Let {inputFieldName} be the value of the second {Name}.
1484+
2. Return the input field of {type} named {inputFieldName} if it exists.
1485+
6. Otherwise:
1486+
1. Let {fieldName} be the value of the second {Name}.
1487+
2. Return the field of {type} named {fieldName} if it exists.
1488+
1489+
ArgumentCoordinate :: Name . Name ( Name : )
1490+
1491+
1. Let {typeName} be the value of the first {Name}.
1492+
2. Let {type} be the type in {schema} named {typeName}.
1493+
3. Assert: {type} must exist, and be an Object or Interface type.
1494+
4. Let {fieldName} be the value of the second {Name}.
1495+
5. Let {field} be the field of {type} named {fieldName}.
1496+
6. Assert: {field} must exist.
1497+
7. Let {fieldArgumentName} be the value of the third {Name}.
1498+
8. Return the argument of {field} named {fieldArgumentName} if it exists.
1499+
1500+
DirectiveCoordinate :: @ Name
1501+
1502+
1. Let {directiveName} be the value of {Name}.
1503+
2. Return the directive in {schema} named {directiveName} if it exists.
1504+
1505+
DirectiveArgumentCoordinate :: @ Name ( Name : )
1506+
1507+
1. Let {directiveName} be the value of the first {Name}.
1508+
2. Let {directive} be the directive in {schema} named {directiveName}.
1509+
3. Assert: {directive} must exist.
1510+
4. Let {directiveArgumentName} be the value of the second {Name}.
1511+
5. Return the argument of {directive} named {directiveArgumentName} if it
1512+
exists.
1513+
1514+
**Examples**
1515+
1516+
| Element Kind | Schema Coordinate | Schema Element |
1517+
| ------------------ | --------------------------------- | --------------------------------------------------------------------- |
1518+
| Named Type | `Business` | `Business` type |
1519+
| Field | `Business.name` | `name` field on the `Business` type |
1520+
| Input Field | `SearchCriteria.filter` | `filter` input field on the `SearchCriteria` input object type |
1521+
| Enum Value | `SearchFilter.OPEN_NOW` | `OPEN_NOW` value of the `SearchFilter` enum |
1522+
| Field Argument | `Query.searchBusiness(criteria:)` | `criteria` argument on the `searchBusiness` field on the `Query` type |
1523+
| Directive | `@private` | `@private` directive |
1524+
| Directive Argument | `@private(scope:)` | `scope` argument on the `@private` directive |
1525+
1526+
The table above shows an example of a _schema coordinate_ for every kind of
1527+
_schema element_ based on the schema below.
1528+
1529+
```graphql
1530+
type Query {
1531+
searchBusiness(criteria: SearchCriteria!): [Business]
1532+
}
1533+
1534+
input SearchCriteria {
1535+
name: String
1536+
filter: SearchFilter
1537+
}
1538+
1539+
enum SearchFilter {
1540+
OPEN_NOW
1541+
DELIVERS_TAKEOUT
1542+
VEGETARIAN_MENU
1543+
}
1544+
1545+
type Business {
1546+
id: ID
1547+
name: String
1548+
email: String @private(scope: "loggedIn")
1549+
}
1550+
1551+
directive @private(scope: String!) on FIELD_DEFINITION
1552+
```

spec/Section 3 -- Type System.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ via introspection.
5858

5959
[Descriptions](#sec-Descriptions) allow GraphQL service designers to easily
6060
provide documentation which remains consistent with the capabilities of a
61-
GraphQL service. Descriptions provided as Markdown (as specified by
61+
GraphQL service. Descriptions should be provided as Markdown (as specified by
6262
[CommonMark](https://commonmark.org/)) for every definition in a type system.
6363

6464
GraphQL schema and all other definitions (e.g. types, fields, arguments, etc.)
@@ -775,8 +775,8 @@ type Person {
775775
}
776776
```
777777

778-
Valid operations must supply a _selection set_ for every field of an object
779-
type, so this operation is not valid:
778+
Valid operations must supply a _selection set_ for every field whose return type
779+
is an object type, so this operation is not valid:
780780

781781
```graphql counter-example
782782
{

spec/Section 5 -- Validation.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -334,11 +334,11 @@ CollectSubscriptionFields(objectType, selectionSet, visitedFragments):
334334
- If {DoesFragmentTypeApply(objectType, fragmentType)} is {false}, continue
335335
with the next {selection} in {selectionSet}.
336336
- Let {fragmentSelectionSet} be the top-level selection set of {fragment}.
337-
- Let {fragmentCollectedFieldMap} be the result of calling
337+
- Let {fragmentCollectedFieldsMap} be the result of calling
338338
{CollectSubscriptionFields(objectType, fragmentSelectionSet,
339339
visitedFragments)}.
340340
- For each {responseName} and {fragmentFields} in
341-
{fragmentCollectedFieldMap}:
341+
{fragmentCollectedFieldsMap}:
342342
- Let {fieldsForResponseKey} be the _field set_ value in
343343
{collectedFieldsMap} for the key {responseName}; otherwise create the
344344
entry with an empty ordered set.
@@ -349,11 +349,11 @@ CollectSubscriptionFields(objectType, selectionSet, visitedFragments):
349349
fragmentType)} is {false}, continue with the next {selection} in
350350
{selectionSet}.
351351
- Let {fragmentSelectionSet} be the top-level selection set of {selection}.
352-
- Let {fragmentCollectedFieldMap} be the result of calling
352+
- Let {fragmentCollectedFieldsMap} be the result of calling
353353
{CollectSubscriptionFields(objectType, fragmentSelectionSet,
354354
visitedFragments)}.
355355
- For each {responseName} and {fragmentFields} in
356-
{fragmentCollectedFieldMap}:
356+
{fragmentCollectedFieldsMap}:
357357
- Let {fieldsForResponseKey} be the _field set_ value in
358358
{collectedFieldsMap} for the key {responseName}; otherwise create the
359359
entry with an empty ordered set.
@@ -584,7 +584,7 @@ should be unambiguous. Therefore any two field selections which might both be
584584
encountered for the same object are only valid if they are equivalent.
585585

586586
During execution, the simultaneous execution of fields with the same response
587-
name is accomplished by {CollectSubfields()} before execution.
587+
name is accomplished by performing {CollectSubfields()} before their execution.
588588

589589
For simple hand-written GraphQL, this rule is obviously a clear developer error,
590590
however nested fragments can make this difficult to detect manually.

0 commit comments

Comments
 (0)