diff --git a/spec/Section 4 -- Composition.md b/spec/Section 4 -- Composition.md index 191e2b4..edae329 100644 --- a/spec/Section 4 -- Composition.md +++ b/spec/Section 4 -- Composition.md @@ -728,6 +728,148 @@ interface Node { } ``` +### Validate Is Directives + +#### Is Invalid Syntax + +**Error Code** + +`IS_INVALID_SYNTAX` + +**Formal Specification** + +(to be completed) + +**Explanatory Text** + +The `@is` directive’s `field` argument must be syntactically valid GraphQL. If +the selection map string is malformed (e.g., missing closing braces, unbalanced +quotes, invalid tokens), then the schema cannot be composed correctly. In such +cases, the error `IS_INVALID_SYNTAX` is raised. + +**Examples** + +In the following example, the `@is` directive’s `field` argument is a valid +selection map and satisfies the rule. + +```graphql example +type Query { + personById(id: ID! @is(field: "id")): Person @lookup +} + +type Person { + id: ID! + name: String +} +``` + +In the following counter-example, the `@is` directive’s `field` argument has +invalid syntax because it is missing a closing brace. + +```graphql counter-example +type Query { + personById(id: ID! @is(field: "{ id ")): Person @lookup +} + +type Person { + id: ID! + name: String +} +``` + +#### Is Invalid Field Type + +**Error Code** + +`IS_INVALID_FIELD_TYPE` + +**Formal Specification** + +(to be completed) + +**Explanatory Text** + +When using the `@is` directive, the `field` argument must always be a string +that describes how the arguments can be mapped from the entity type that the +lookup field resolves. If the `field` argument is provided as a type other than +a string (such as an integer, boolean, or enum), the directive usage is invalid +and will cause schema composition to fail. + +**Examples** + +In the following example, the `@is` directive’s `field` argument is a valid +string and satisfies the rule. + +```graphql example +type Query { + personById(id: ID! @is(field: "id")): Person @lookup +} + +type Person { + id: ID! + name: String +} +``` + +Since `field` is set to `123` (an integer) instead of a string, this violates +the rule and triggers an `IS_INVALID_FIELD_TYPE` error. + +```graphql counter-example +type Query { + personById(id: ID! @is(field: 123)): Person @lookup +} + +type Person { + id: ID! + name: String +} +``` + +#### Is Invalid Usage + +**Error Code** + +`IS_INVALID_USAGE` + +**Formal Specification** + +(to be completed) + +**Explanatory Text** + +When using the `@is` directive, the field declaring the argument must be a +lookup field (i.e. have the `@lookup` directive applied). + +**Examples** + +In the following example, the `@is` directive is applied to an argument declared +on a field with the `@lookup` directive, satisfying the rule. + +```graphql example +type Query { + personById(id: ID! @is(field: "id")): Person @lookup +} + +type Person { + id: ID! + name: String +} +``` + +In the following counter-example, the `@is` directive is applied to an argument +declared on a field without the `@lookup` directive, violating the rule. + +```graphql counter-example +type Query { + personById(id: ID! @is(field: "id")): Person +} + +type Person { + id: ID! + name: String +} +``` + ### Validate Key Directives #### Key Fields Select Invalid Type @@ -5723,6 +5865,59 @@ type Product @inaccessible { } ``` +### Validate Is Directives + +#### Is Invalid Field + +**Error Code** + +`IS_INVALID_FIELD` + +**Formal Specification** + +(to be completed) + +**Explanatory Text** + +Even if the field selection map for `@is(field: "…")` is syntactically valid, +its contents must also be valid within the composed schema. Fields must exist on +the parent type for them to be referenced by `@is`. In addition, fields +referencing unknown fields break the valid usage of `@is`, leading to an +`IS_INVALID_FIELD` error. + +**Examples** + +In the following example, the `@is` directive’s `field` argument is a valid +field selection map and satisfies the rule. + +```graphql example +# Schema A +type Query { + personById(id: ID! @is(field: "id")): Person @lookup +} + +type Person { + id: ID! + name: String +} +``` + +In this counter-example, the `@is` directive references a field (`unknownField`) +that does not exist on the return type (`Person`), causing an `IS_INVALID_FIELD` +error. + +```graphql counter-example +# Schema A +type Query { + personById(id: ID! @is(field: "unknownField")): Person @lookup +} + +type Person { + id: ID! + name: String +} +``` + ### Validate Provides Directives #### Provides Invalid Fields