@@ -728,6 +728,189 @@ interface Node {
728728}
729729```
730730
731+ ### Validate `@is` Directive
732+
733+ #### Is Invalid Syntax
734+
735+ **Error Code **
736+
737+ `IS_INVALID_SYNTAX `
738+
739+ **Severity **
740+
741+ ERROR
742+
743+ **Formal Specification **
744+
745+ - Let {types } be the set of all {INTERFACE } and {OBJECT } types in the source
746+ schema .
747+ - For each {type} in {types }:
748+ - Let {fields } be the set of all lookup fields on {type }.
749+ - Let {arguments } be the set of all arguments on {fields }.
750+ - For each {argument } in {arguments }:
751+ - If {argument } is annotated with `@is `:
752+ - Let {fieldArg } be the string value of the `field ` argument of the `@is `
753+ directive on {argument }.
754+ - {fieldArg } must be be parsable as a valid {FieldSelectionMap }.
755+
756+ **Explanatory Text **
757+
758+ The `@is ` directive ’s `field ` argument must be syntactically valid GraphQL . If
759+ the {FieldSelectionMap } string is malformed (e.g., missing closing braces,
760+ unbalanced quotes, invalid tokens), then the schema cannot be composed
761+ correctly. In such cases, the error `IS_INVALID_SYNTAX` is raised.
762+
763+ **Examples**
764+
765+ In the following example, the `@is ` directive’s `field` argument is a valid
766+ {FieldSelectionMap} and satisfies the rule .
767+
768+ ```graphql example
769+ type Query {
770+ product (id : ID ! @is (field : " id" )): Product @lookup
771+ }
772+
773+ type Product {
774+ id : ID !
775+ name : String
776+ }
777+ ```
778+
779+ In the following counter -example , the `@is ` directive ’s `field ` argument has
780+ invalid syntax because it is missing a closing brace .
781+
782+ ```graphql counter -example
783+ type Query {
784+ product (id : ID ! @is (field : " { id " )): Product @lookup
785+ }
786+
787+ type Product {
788+ id : ID !
789+ name : String
790+ }
791+ ```
792+
793+ #### Is Invalid Field Type
794+
795+ **Error Code **
796+
797+ `IS_INVALID_FIELD_TYPE `
798+
799+ **Severity **
800+
801+ ERROR
802+
803+ **Formal Specification **
804+
805+ - Let {schema } be the source schema to validate.
806+ - Let {compositeTypes} be the set of all composite types in {schema }.
807+ - For each {composite } in {compositeTypes }:
808+ - Let {fields } be the set of fields on {composite }.
809+ - Let {arguments } be the set of all arguments on {fields }.
810+ - For each {argument } in {arguments }:
811+ - If {argument } is **not ** annotated with `@is `:
812+ - Continue
813+ - Let {fieldArg } be the value of the `field ` argument of the `@is ` directive
814+ on {argument }.
815+ - If {fieldArg } is **not ** a string :
816+ - Produce an `IS_INVALID_FIELD_TYPE ` error .
817+
818+ **Explanatory Text **
819+
820+ When using the `@is ` directive , the `field ` argument must always be a string
821+ that describes how the arguments can be mapped from the entity type that the
822+ lookup field resolves . If the `field ` argument is provided as a type other than
823+ a string (such as an integer, boolean, or enum), the directive usage is invalid
824+ and will cause schema composition to fail.
825+
826+ **Examples**
827+
828+ In the following example, the `@is ` directive’s `field` argument is a valid
829+ string and satisfies the rule.
830+
831+ ```graphql example
832+ type Query {
833+ personById (id : ID ! @is (field : "id" )): Person @lookup
834+ }
835+
836+ type Person {
837+ id : ID !
838+ name : String
839+ }
840+ ```
841+
842+ Since `field ` is set to `123` (an integer) instead of a string , this violates
843+ the rule and triggers an `IS_INVALID_FIELD_TYPE ` error .
844+
845+ ```graphql counter -example
846+ type Query {
847+ personById (id : ID ! @is (field : 123 )): Person @lookup
848+ }
849+
850+ type Person {
851+ id : ID !
852+ name : String
853+ }
854+ ```
855+
856+ #### Is Invalid Usage
857+
858+ **Error Code **
859+
860+ `IS_INVALID_USAGE `
861+
862+ **Severity **
863+
864+ ERROR
865+
866+ **Formal Specification **
867+
868+ - Let {schema } be the source schema to validate.
869+ - Let {compositeTypes} be the set of all composite types in {schema }.
870+ - For each {compositeType } in {compositeTypes }:
871+ - Let {fields } be the set of fields on {compositeType }.
872+ - For each {field } in {fields }:
873+ - Let {arguments } be the set of all arguments on {field }.
874+ - For each {argument } in {arguments }:
875+ - If {argument } is **not ** annotated with `@is `:
876+ - Continue
877+ - {field } must be annotated with `@lookup `
878+
879+ **Explanatory Text **
880+
881+ When using the `@is ` directive , the field declaring the argument must be a
882+ lookup field (i.e. have the `@lookup` directive applied).
883+
884+ **Examples **
885+
886+ In the following example , the `@is ` directive is applied to an argument declared
887+ on a field with the `@lookup ` directive , satisfying the rule .
888+
889+ ```graphql example
890+ type Query {
891+ personById (id : ID ! @is (field : " id" )): Person @lookup
892+ }
893+
894+ type Person {
895+ id : ID !
896+ name : String
897+ }
898+ ```
899+
900+ In the following counter -example , the `@is ` directive is applied to an argument
901+ declared on a field without the `@lookup ` directive , violating the rule .
902+
903+ ```graphql counter -example
904+ type Query {
905+ personById (id : ID ! @is (field : " id" )): Person
906+ }
907+
908+ type Person {
909+ id : ID !
910+ name : String
911+ }
912+ ```
913+
731914### Validate Key Directives
732915
733916#### Key Fields Select Invalid Type
@@ -5863,6 +6046,86 @@ type Product @inaccessible {
58636046}
58646047```
58656048
6049+ ### Validate Is Directives
6050+
6051+ #### Is Invalid Fields
6052+
6053+ **Error Code **
6054+
6055+ `IS_INVALID_FIELDS `
6056+
6057+ **Severity **
6058+
6059+ ERROR
6060+
6061+ **Formal Specification **
6062+
6063+ - Let {schemas } be all source schemas .
6064+ - Let {compositeTypes } be the set of all composite types in {schemas }.
6065+ - For each {composite } in {compositeTypes }:
6066+ - Let {fields } be the set of fields on {composite }.
6067+ - Let {arguments } be the set of all arguments on {fields }.
6068+ - For each {argument } in {arguments }:
6069+ - If {argument } is **not ** annotated with `@is `:
6070+ - Continue
6071+ - Let {schema } be the schema that defines {argument}.
6072+ - Let {declaringField } be the field that defines {argument }.
6073+ - Let {declaringType } be the type that defines {declaringField }.
6074+ - Let {otherSchemas } be the set of all {schemas } excluding {schema }.
6075+ - Let {fieldArg } be the string value of the `field ` argument of the `@is `
6076+ directive on {argument }.
6077+ - Let {parsedFieldArg } be the parsed selection map from {fieldArg }.
6078+ - The parsed selection map {parsedFieldArg } must satisfy the validation
6079+ rules defined in Appendix A , Section 6.3, using :
6080+ - {declaringType } as the initial root type .
6081+ - The combined schema context formed by the union of {otherSchemas} as the
6082+ schema context except all fields marked as `@internal `
6083+ - Validation succeeds if each required field selection path can be
6084+ resolved across this combined schema context. Individual fields in the
6085+ selection may exist in different schemas; it is not required that all
6086+ fields referenced by {parsedFieldArg} reside within a single schema .
6087+
6088+ **Explanatory Text**
6089+
6090+ Even if the field selection map for `@is (field : " …" )` is syntactically valid,
6091+ its contents must also be valid within the composed schema. Fields must exist on
6092+ the parent type for them to be referenced by `@is `. In addition, fields
6093+ referencing unknown fields break the valid usage of `@is `, leading to an
6094+ `IS_INVALID_FIELDS` error.
6095+
6096+ **Examples**
6097+
6098+ In the following example, the `@is ` directive’s `field` argument is a valid
6099+ field selection map and satisfies the rule.
6100+
6101+ ```graphql example
6102+ # Schema A
6103+ type Query {
6104+ personById (id : ID ! @is (field : "id" )): Person @lookup
6105+ }
6106+
6107+ type Person {
6108+ id : ID !
6109+ name : String
6110+ }
6111+ ```
6112+
6113+ In this counter -example , the `@is ` directive references a field (`unknownField`)
6114+ that does not exist on the return type (`Person`), causing an
6115+ `IS_INVALID_FIELDS ` error .
6116+
6117+ ```graphql counter -example
6118+ # Schema A
6119+ type Query {
6120+ personById (id : ID ! @is (field : " unknownField" )): Person @lookup
6121+ }
6122+
6123+ type Person {
6124+ id : ID !
6125+ name : String
6126+ }
6127+ ```
6128+
58666129### Validate Provides Directives
58676130
58686131#### Provides Invalid Fields
0 commit comments