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

[RFC] Repeatable directives #472

Merged
merged 9 commits into from Jan 10, 2020
2 changes: 1 addition & 1 deletion spec/Appendix B -- Grammar Summary.md
Expand Up @@ -278,7 +278,7 @@ InputObjectTypeExtension :
- extend input Name Directives[Const]? InputFieldsDefinition
- extend input Name Directives[Const]

DirectiveDefinition : Description? directive @ Name ArgumentsDefinition? on DirectiveLocations
DirectiveDefinition : Description? directive @ Name ArgumentsDefinition? `repeatable`? on DirectiveLocations

DirectiveLocations :
- `|`? DirectiveLocation
Expand Down
31 changes: 23 additions & 8 deletions spec/Section 3 -- Type System.md
Expand Up @@ -165,7 +165,7 @@ adds additional operation types, or additional directives to an existing schema.
Schema extensions have the potential to be invalid if incorrectly defined.

1. The Schema must already be defined.
2. Any directives provided must not already apply to the original Schema.
2. Any non-`repeatable` directives provided must not already apply to the original Schema.


## Descriptions
Expand Down Expand Up @@ -544,7 +544,7 @@ GraphQL tool or service which adds directives to an existing scalar.
Scalar type extensions have the potential to be invalid if incorrectly defined.

1. The named type must already be defined and must be a Scalar type.
2. Any directives provided must not already apply to the original Scalar type.
2. Any non-`repeatable` directives provided must not already apply to the original Scalar type.


## Objects
Expand Down Expand Up @@ -934,7 +934,7 @@ Object type extensions have the potential to be invalid if incorrectly defined.
may share the same name.
3. Any fields of an Object type extension must not be already defined on the
original Object type.
4. Any directives provided must not already apply to the original Object type.
4. Any non-`repeatable` directives provided must not already apply to the original Object type.
5. Any interfaces provided must not be already implemented by the original
Object type.
6. The resulting extended object type must be a super-set of all interfaces it
Expand Down Expand Up @@ -1116,7 +1116,7 @@ Interface type extensions have the potential to be invalid if incorrectly define
4. Any Object type which implemented the original Interface type must also be a
super-set of the fields of the Interface type extension (which may be due to
Object type extension).
5. Any directives provided must not already apply to the original Interface type.
5. Any non-`repeatable` directives provided must not already apply to the original Interface type.


## Unions
Expand Down Expand Up @@ -1239,7 +1239,7 @@ Union type extensions have the potential to be invalid if incorrectly defined.
3. All member types of a Union type extension must be unique.
4. All member types of a Union type extension must not already be a member of
the original Union type.
5. Any directives provided must not already apply to the original Union type.
5. Any non-`repeatable` directives provided must not already apply to the original Union type.

## Enums

Expand Down Expand Up @@ -1308,7 +1308,7 @@ Enum type extensions have the potential to be invalid if incorrectly defined.
2. All values of an Enum type extension must be unique.
3. All values of an Enum type extension must not already be a value of
the original Enum.
4. Any directives provided must not already apply to the original Enum type.
4. Any non-`repeatable` directives provided must not already apply to the original Enum type.


## Input Objects
Expand Down Expand Up @@ -1437,7 +1437,7 @@ Input object type extensions have the potential to be invalid if incorrectly def
3. All fields of an Input Object type extension must have unique names.
4. All fields of an Input Object type extension must not already be a field of
the original Input Object.
5. Any directives provided must not already apply to the original Input Object type.
5. Any non-`repeatable` directives provided must not already apply to the original Input Object type.


## List
Expand Down Expand Up @@ -1606,7 +1606,7 @@ Expected Type | Internal Value | Coerced Result

## Directives

DirectiveDefinition : Description? directive @ Name ArgumentsDefinition? on DirectiveLocations
DirectiveDefinition : Description? directive @ Name ArgumentsDefinition? `repeatable`? on DirectiveLocations

DirectiveLocations :
- `|`? DirectiveLocation
Expand Down Expand Up @@ -1660,6 +1660,21 @@ fragment SomeFragment on SomeType {
}
```

A directive may be defined as repeatable at any permitted location with the `repeatable`
keyword. Repeatable directives often useful when the same directive should be used with
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
keyword. Repeatable directives often useful when the same directive should be used with
keyword. Repeatable directives are often useful when the same directive should be used with

different arguments at the one location, especially in cases where additional information
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
different arguments at the one location, especially in cases where additional information
different arguments at a single location, especially in cases where additional information

need to be provided in a form of directive via a type or a schema extension:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
need to be provided in a form of directive via a type or a schema extension:
needs to be provided to a type or schema extension through a directive:


```graphql example
directive @delegateField(name: String!) repeatable on OBJECT | INTERFACE

type Book @delegateField(name: "pageCount") @delegateField(name: "author") {
id: ID!
}

extend type Book @delegateField(name: "index")
```

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be great to include a more complex example that illustrates how repeatable is useful or at least add a note that directive order is significant and you can use it to create chains of directives.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I extended the example 218e0da and the description 477919e.

I struggled with it a bit since I find it hard to strike the right balance between completeness of the example including its description and succinct focused content required from a perspective of the specification. For this reason I also hesitated mentioning the order significance since it has its own dedication section with a separate example.

WDYT?

Directive locations may be defined with an optional leading `|` character to aid
formatting when representing a longer list of possible locations:

Expand Down
2 changes: 2 additions & 0 deletions spec/Section 4 -- Introspection.md
Expand Up @@ -187,6 +187,7 @@ type __Directive {
description: String
locations: [__DirectiveLocation!]!
args: [__InputValue!]!
isRepeatable: Boolean!
}

enum __DirectiveLocation {
Expand Down Expand Up @@ -417,3 +418,4 @@ Fields
locations this directive may be placed.
* `args` returns a List of `__InputValue` representing the arguments this
directive accepts.
* `isRepeatable` must return a Boolean which permits using the directive multiple times at the same location.
Copy link
Member

@spawnia spawnia Jun 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* `isRepeatable` must return a Boolean which permits using the directive multiple times at the same location.
* `isRepeatable` must return a Boolean that indicates if a directive may be used repeatedly at a single location.

2 changes: 1 addition & 1 deletion spec/Section 5 -- Validation.md
Expand Up @@ -1440,7 +1440,7 @@ query @skip(if: $foo) {
**Formal Specification**

* For every {location} in the document for which Directives can apply:
* Let {directives} be the set of Directives which apply to {location}.
* Let {directives} be the set of Directives which apply to {location} and not marked as `repeatable`.
Copy link
Member

@spawnia spawnia Jun 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Let {directives} be the set of Directives which apply to {location} and not marked as `repeatable`.
* Let {directives} be the set of Directives which apply to {location} and are not `repeatable`.

* For each {directive} in {directives}:
* Let {directiveName} be the name of {directive}.
* Let {namedDirectives} be the set of all Directives named {directiveName}
Expand Down