All Downloads are FREE. Search and download functionalities are using the official Maven repository.

node_modules.graphql.utilities.isValidLiteralValue.js.flow Maven / Gradle / Ivy

There is a newer version: 1.1.2
Show newest version
/* @flow */
/**
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */

import { print } from '../language/printer';
import type {
  ValueNode,
  ListValueNode,
  ObjectValueNode
} from '../language/ast';
import * as Kind from '../language/kinds';
import {
  GraphQLScalarType,
  GraphQLEnumType,
  GraphQLInputObjectType,
  GraphQLList,
  GraphQLNonNull
} from '../type/definition';
import type { GraphQLInputType } from '../type/definition';
import invariant from '../jsutils/invariant';
import keyMap from '../jsutils/keyMap';


/**
 * Utility for validators which determines if a value literal node is valid
 * given an input type.
 *
 * Note that this only validates literal values, variables are assumed to
 * provide values of the correct type.
 */
export function isValidLiteralValue(
  type: GraphQLInputType,
  valueNode: ValueNode
): Array {
  // A value must be provided if the type is non-null.
  if (type instanceof GraphQLNonNull) {
    if (!valueNode || (valueNode.kind === Kind.NULL)) {
      return [ `Expected "${String(type)}", found null.` ];
    }
    return isValidLiteralValue(type.ofType, valueNode);
  }

  if (!valueNode || (valueNode.kind === Kind.NULL)) {
    return [];
  }

  // This function only tests literals, and assumes variables will provide
  // values of the correct type.
  if (valueNode.kind === Kind.VARIABLE) {
    return [];
  }

  // Lists accept a non-list value as a list of one.
  if (type instanceof GraphQLList) {
    const itemType = type.ofType;
    if (valueNode.kind === Kind.LIST) {
      return (valueNode: ListValueNode).values.reduce((acc, item, index) => {
        const errors = isValidLiteralValue(itemType, item);
        return acc.concat(errors.map(error =>
          `In element #${index}: ${error}`
        ));
      }, []);
    }
    return isValidLiteralValue(itemType, valueNode);
  }

  // Input objects check each defined field and look for undefined fields.
  if (type instanceof GraphQLInputObjectType) {
    if (valueNode.kind !== Kind.OBJECT) {
      return [ `Expected "${type.name}", found not an object.` ];
    }
    const fields = type.getFields();

    const errors = [];

    // Ensure every provided field is defined.
    const fieldNodes = (valueNode: ObjectValueNode).fields;
    fieldNodes.forEach(providedFieldNode => {
      if (!fields[providedFieldNode.name.value]) {
        errors.push(
          `In field "${providedFieldNode.name.value}": Unknown field.`
        );
      }
    });

    // Ensure every defined field is valid.
    const fieldNodeMap = keyMap(fieldNodes, fieldNode => fieldNode.name.value);
    Object.keys(fields).forEach(fieldName => {
      const result = isValidLiteralValue(
        fields[fieldName].type,
        fieldNodeMap[fieldName] && fieldNodeMap[fieldName].value
      );
      errors.push(...(result.map(error =>
        `In field "${fieldName}": ${error}`
      )));
    });

    return errors;
  }

  invariant(
    type instanceof GraphQLScalarType || type instanceof GraphQLEnumType,
    'Must be input type'
  );

  // Scalars determine if a literal values is valid.
  if (!type.isValidLiteral(valueNode)) {
    return [ `Expected type "${type.name}", found ${print(valueNode)}.` ];
  }

  return [];
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy