Mirror: The small sibling of the graphql package, slimmed down for client-side libraries.

Implement nullability operators in query language

The ["Nullability RFC" for GraphQL](https://github.com/graphql/graphql-wg/issues/694)
allows fields to individually be marked as optional or required in a query by the
client-side. ([See Strawman Proposal](https://github.com/graphql/graphql-spec/issues/867))

If a field is marked as optional then it's allowed to be missing and `null`, which
can control where missing values cascade to:

```graphql
query {
me {
name?
}
}
```

If a field is marked as required it may never be allowed to become `null` and must
cascade if it otherwise would have been set to `null`:

```graphql
query {
me {
name!
}
}
```

Changed files
+24 -3
alias
+8
alias/language/__tests__/printer.test.js
···
name
}
`);
+
+
const queryWithNullabilityFields = parse('query { id?, name! }');
+
expect(print(queryWithNullabilityFields)).toBe(dedent`
+
{
+
id?
+
name!
+
}
+
`);
});
it('prints query with variable directives', () => {
+9
alias/language/parser.mjs
···
${directive}*
`;
+
const nullability = match(null, (x) => {
+
return x[0] === '?' ? 'optional' : 'required';
+
})`
+
:${ignored}?
+
${/[?!]/}
+
`;
+
const field = match(Kind.FIELD, (x) => {
let i = 0;
return {
kind: x.tag,
alias: x[1].kind === Kind.NAME ? x[i++] : undefined,
name: x[i++],
+
required: typeof x[i] === 'string' ? x[i++] : 'unset',
arguments: x[i++],
directives: x[i++],
selectionSet: x[i++],
···
(?: ${ignored}? ${':'} ${ignored}?)
${name}
)?
+
${nullability}?
${args}
${directives}
${() => selectionSet}?
+7 -3
alias/language/printer.mjs
···
);
case 'Field':
+
let prefix = wrap('', print(node.alias), ': ') + print(node.name);
+
if (node.required === 'optional') {
+
prefix += '?';
+
} else if (node.required === 'required') {
+
prefix += '!';
+
}
return join(
[
-
wrap('', print(node.alias), ': ') +
-
print(node.name) +
-
wrap('(', join(print(node.arguments), ', '), ')'),
+
prefix + wrap('(', join(print(node.arguments), ', '), ')'),
join(print(node.directives), ' '),
print(node.selectionSet),
],