Built-in generation plugin for the @include and @skip directives.
A conditionally-selected field may be omitted from the response, so its generated type must be nullable even when the schema says the field is non-null. Runtime decode already tolerates the omission; this plugin only fixes generated-type accuracy.
After the normalize step has propagated ancestor (inline-fragment /
fragment-spread) directives onto each field, this plugin walks the
resolved tree and marks every conditionally-selected field nullable.
Conditionality
A directive's if: argument is a TypedGql.Language.Variable or a literal
TypedGql.Language.BooleanValue:
@include(if: $var)/@skip(if: $var)— conditional (variable).@include(if: true)/@skip(if: false)— no-op, not conditional.@include(if: false)/@skip(if: true)— always omitted, but still generated as nullable to keep the struct shape stable.
So @include is conditional unless if: is literal true, and @skip
is conditional unless if: is literal false.
A [T!]! object list is generated as embeds_many, which is forced to
default: [] downstream and so cannot represent whole-absence as nil; its
nullability is left unchanged (see the type generator docs). Every other list
shape is a plain field and is marked nullable like any other.
Summary
Functions
Whether directives can remove the field from the response.
Whether a single directive is @skip or @include.
Functions
@spec conditional?([TypedGql.Language.Directive.t()]) :: boolean()
Whether directives can remove the field from the response.
TypedGql.TypeGenerator shares this when merging repeated selections: a copy
that cannot be removed makes the merged field unconditional.
@spec skip_include?(TypedGql.Language.Directive.t()) :: boolean()
Whether a single directive is @skip or @include.
The merge in TypedGql.TypeGenerator uses this to strip only the
conditionality of a repeated selection, keeping every other directive
visible to generation plugins.