Skip to content

Commit

Permalink
Directives improvements
Browse files Browse the repository at this point in the history
Here is spec language mirroring the changes in graphql/graphql-js#31.

Changed:

* Directive grammar changed to `@ Name Arguments?`
* "Field Arguments" changed to "Arguments" almost everywhere to be more generic.
* Argument validation rules made more generic to handle directives cases.
* Directive validation simplified.
* Directive explaination in Language now matches current state.
* @include and @Skip documented in Type System
  • Loading branch information
leebyron committed Jul 7, 2015
1 parent fd7410b commit 9e68777
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 123 deletions.
89 changes: 63 additions & 26 deletions Section 2 -- Language.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,12 @@ query getZuck {
}
```

## Field Arguments
## Arguments

Fields may take arguments. These often map directly to function arguments
within the GraphQL server implementation. We already saw arguments used
in the global field above.
Fields and directives may take arguments.

These often map directly to function arguments within the GraphQL server
implementation. We already saw arguments used in the global field above.

In this example, we want to query a user's profile picture of a
specific size:
Expand Down Expand Up @@ -119,7 +120,7 @@ Many arguments can exist for a given field:

**Arguments are unordered**

Field arguments may be provided in any syntactic order and maintain identical
Arguments may be provided in any syntactic order and maintain identical
semantic meaning.

These two queries are semantically identical:
Expand Down Expand Up @@ -195,7 +196,7 @@ the field's name otherwise.

## Input Values

Both field arguments and directives accept input values. Input values can be
Field and directive arguments accept input values. Input values can be
specified as a variable or represented inline as literals. Input values can
be scalars, enumerations, or input objects. List and inputs objects may also
contain variables.
Expand Down Expand Up @@ -270,26 +271,6 @@ could run this query and request profilePic of size 60 with:
}
```

## Directives

In some cases, you need to provide options to alter GraphQL's execution
behavior in ways field arguments will not suffice, such as conditionally
skipping a field. Directives provide this with a `@name` and can be
specified to be used without an argument or with a value argument.

Directives can be used to conditionally include fields in a query based
on a provided boolean value. In this contrived example experimentalField
will be queried and controlField will not.

```graphql
query myQuery($someTest: Boolean) {
experimentalField @if: $someTest,
controlField @unless: $someTest
}
```

As future versions of GraphQL adopts new configurable execution capabilities,
they may be exposed via directives.

## Fragments

Expand Down Expand Up @@ -446,3 +427,59 @@ query InlineFragmentTyping {
}
```


## Directives

In some cases, you need to provide options to alter GraphQL's execution
behavior in ways field arguments will not suffice, such as conditionally
including or skipping a field. Directives provide this by describing additional information to the executor.

Directives have a name along with a list of arguments which may accept values
of any input type.

Directives can be used to describe additional information for fields, fragments,
and operations.

As future versions of GraphQL adopts new configurable execution capabilities,
they may be exposed via directives.

### Fragment Directives

Fragments may include directives to alter their behavior. At runtime, the directives provided on a fragment spread override those described on the
definition.

For example, the following query:

```graphql
query HasConditionalFragment($condition: Boolean) {
...MaybeFragment @include(if: $condition)
}

fragment MaybeFragment on Query {
me {
name
}
}
```

Will have identical runtime behavior as

```graphql
query HasConditionalFragment($condition: Boolean) {
...MaybeFragment
}

fragment MaybeFragment on Query @include(if: $condition) {
me {
name
}
}
```

FragmentSpreadDirectives(fragmentSpread) :
* Let {directives} be the set of directives on {fragmentSpread}
* Let {fragmentDefinition} be the FragmentDefinition in the document named {fragmentSpread} refers to.
* For each {directive} in directives on {fragmentDefinition}
* If {directives} does not contain a directive named {directive}.
* Add {directive} into {directives}
* Return {directives}
54 changes: 40 additions & 14 deletions Section 3 -- Type System.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Scalar type.

**Input Coercion**

If a GraphQL server expects a scalar type as input to a field argument, coercion
If a GraphQL server expects a scalar type as input to an argument, coercion
is observable and the rules must be well defined. If an input value does not
match a coercion rule, a query error must be raised.

Expand Down Expand Up @@ -354,9 +354,9 @@ Objects are never valid inputs.
#### Object Field Arguments

Object fields are conceptually functions which yield values. Occasionally object
fields can accept arguments to further specify the return value. Field arguments
are defined as a list of all possible argument names and their expected input
types.
fields can accept arguments to further specify the return value. Object field
arguments are defined as a list of all possible argument names and their
expected input types.

For example, a `Person` type with a `picture` field could accept an argument to
determine what size of an image to return.
Expand Down Expand Up @@ -389,9 +389,7 @@ May yield the result:
}
```

The type of a field argument can be a Scalar, as it was in this example, or an
Enum. It can also be an Input Object, covered later in this document, or it can
be any wrapping type whose underlying base type is one of those three.
The type of an object field argument can be any Input type.

#### Object Field deprecation

Expand Down Expand Up @@ -723,14 +721,42 @@ case), the client can just pass that value rather than constructing the list.

## Directives

A GraphQL schema includes a list of supported directives, each of which has
a name. Directives can apply to operations, fragments, or fields; each directive
indicates which of those it applies to.
A GraphQL schema includes a list of the directives the execution
engine supports.

GraphQL implementations should provide the `@skip` and `@include` directives.

### @skip

The `@skip` directive may be provided for fields or fragments, and allows
for conditional exclusion during execution as described by the if argument.

In this example `experimentalField` will be queried only if the `$someTest` is
provided a `false` value.

```graphql
query myQuery($someTest: Boolean) {
experimentalField @skip(if: $someTest)
}
```

### @include

The `@include` directive may be provided for fields or fragments, and allows
for conditional inclusion during execution as described by the if argument.

In this example `experimentalField` will be queried only if the `$someTest` is
provided a `true` value.

```graphql
query myQuery($someTest: Boolean) {
experimentalField @include(if: $someTest)
}
```

The `@skip` directive has precidence over the `@include` directive should both
be provided in the same context.

Directives can optionally take an argument. The type of the argument to
a directive has the same restrictions as the type of an argument to a field. It
can be a Scalar, an Enum, an Input Object, or any wrapping type whose underlying
base type is one of those three.

## Starting types

Expand Down
2 changes: 1 addition & 1 deletion Section 4 -- Introspection.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ enum __TypeKind {
type __Directive {
name: String!
description: String
type: __Type
args: [__InputValue!]!
onOperation: Boolean!
onFragment: Boolean!
onField: Boolean!
Expand Down
Loading

0 comments on commit 9e68777

Please sign in to comment.