1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- import { GraphQLError } from '../../error/GraphQLError.mjs';
- import { Kind } from '../../language/kinds.mjs';
- import { collectFields } from '../../execution/collectFields.mjs';
- /**
- * Subscriptions must only include a non-introspection field.
- *
- * A GraphQL subscription is valid only if it contains a single root field and
- * that root field is not an introspection field.
- *
- * See https://spec.graphql.org/draft/#sec-Single-root-field
- */
- export function SingleFieldSubscriptionsRule(context) {
- return {
- OperationDefinition(node) {
- if (node.operation === 'subscription') {
- const schema = context.getSchema();
- const subscriptionType = schema.getSubscriptionType();
- if (subscriptionType) {
- const operationName = node.name ? node.name.value : null;
- const variableValues = Object.create(null);
- const document = context.getDocument();
- const fragments = Object.create(null);
- for (const definition of document.definitions) {
- if (definition.kind === Kind.FRAGMENT_DEFINITION) {
- fragments[definition.name.value] = definition;
- }
- }
- const fields = collectFields(
- schema,
- fragments,
- variableValues,
- subscriptionType,
- node.selectionSet,
- );
- if (fields.size > 1) {
- const fieldSelectionLists = [...fields.values()];
- const extraFieldSelectionLists = fieldSelectionLists.slice(1);
- const extraFieldSelections = extraFieldSelectionLists.flat();
- context.reportError(
- new GraphQLError(
- operationName != null
- ? `Subscription "${operationName}" must select only one top level field.`
- : 'Anonymous Subscription must select only one top level field.',
- {
- nodes: extraFieldSelections,
- },
- ),
- );
- }
- for (const fieldNodes of fields.values()) {
- const field = fieldNodes[0];
- const fieldName = field.name.value;
- if (fieldName.startsWith('__')) {
- context.reportError(
- new GraphQLError(
- operationName != null
- ? `Subscription "${operationName}" must not select an introspection top level field.`
- : 'Anonymous Subscription must not select an introspection top level field.',
- {
- nodes: fieldNodes,
- },
- ),
- );
- }
- }
- }
- }
- },
- };
- }
|