87 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| Object.defineProperty(exports, '__esModule', {
 | |
|   value: true,
 | |
| });
 | |
| exports.SingleFieldSubscriptionsRule = SingleFieldSubscriptionsRule;
 | |
| 
 | |
| var _GraphQLError = require('../../error/GraphQLError.js');
 | |
| 
 | |
| var _kinds = require('../../language/kinds.js');
 | |
| 
 | |
| var _collectFields = require('../../execution/collectFields.js');
 | |
| 
 | |
| /**
 | |
|  * 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
 | |
|  */
 | |
| 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 === _kinds.Kind.FRAGMENT_DEFINITION) {
 | |
|               fragments[definition.name.value] = definition;
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           const fields = (0, _collectFields.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.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.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,
 | |
|                   },
 | |
|                 ),
 | |
|               );
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     },
 | |
|   };
 | |
| }
 |