<commit_before>'use strict';

const { parse } = require('graphql');

const { EngineError } = require('../../../../error');
const { memoize } = require('../../../../utilities');

// Raw GraphQL parsing
const parseQuery = memoize(({ query, goal, operationName }) => {
  if (!query) {
    const message = 'Missing GraphQL query';
    throw new EngineError(message, { reason: 'GRAPHQL_NO_QUERY' });
  }

  try {
    const queryDocument = parse(query);
    const { graphqlMethod } = validateQuery({
      queryDocument,
      goal,
      operationName,
    });
    return { queryDocument, graphqlMethod };
  } catch (error) {
    const message = 'Could not parse GraphQL query';
    throw new EngineError(message, {
      reason: 'GRAPHQL_SYNTAX_ERROR',
      innererror: error,
    });
  }
});

// Make sure GraphQL query is valid
const validateQuery = function ({ queryDocument, goal, operationName }) {
  // Get all query|mutation definitions
  const operationDefinitions = queryDocument.definitions.filter(({ kind }) =>
    kind === 'OperationDefinition'
  );
  const definitions = operationDefinitions.filter(({
    name: { value: name } = {},
  }) => !operationName || name === operationName);

  if (definitions.length === 0) {
    if (operationName) {
      const message = `Could not find GraphQL operation ${operationName}`;
      throw new EngineError(message, { reason: 'GRAPHQL_SYNTAX_ERROR' });
    } else {
      const message = 'Missing GraphQL query';
      throw new EngineError(message, { reason: 'GRAPHQL_NO_QUERY' });
    }
  }

  const [definition] = definitions;

  // GraphQL-anywhere do not support operationName yet,
  // so we must patch it until they do
  // See https://github.com/apollographql/graphql-anywhere/issues/34
  if (operationDefinitions.length > 1) {
    queryDocument.definitions = queryDocument.definitions.filter(def =>
      !operationDefinitions.includes(def) || def === definition
    );
  }

  if (goal === 'find' && definition.operation !== 'query') {
    const message = 'Can only perform GraphQL queries, not mutations, with the current protocol method';
    throw new EngineError(message, { reason: 'GRAPHQL_SYNTAX_ERROR' });
  }

  return { graphqlMethod: definition.operation };
};

module.exports = {
  parseQuery,
  validateQuery,
};<commit_msg>Small refactoring<commit_after>'use strict';

const { parse } = require('graphql');

const { EngineError } = require('../../../../error');
const { memoize } = require('../../../../utilities');

// Raw GraphQL parsing
const parseQuery = memoize(({ query, goal, operationName }) => {
  if (!query) {
    const message = 'Missing GraphQL query';
    throw new EngineError(message, { reason: 'GRAPHQL_NO_QUERY' });
  }

  try {
    const queryDocument = parse(query);
    const { graphqlMethod } = validateQuery({
      queryDocument,
      goal,
      operationName,
    });
    return { queryDocument, graphqlMethod };
  } catch (error) {
    const message = 'Could not parse GraphQL query';
    throw new EngineError(message, {
      reason: 'GRAPHQL_SYNTAX_ERROR',
      innererror: error,
    });
  }
});

// Make sure GraphQL query is valid
const validateQuery = function ({ queryDocument, goal, operationName }) {
  // Get all query|mutation definitions
  const operationDefinitions = queryDocument.definitions.filter(({ kind }) =>
    kind === 'OperationDefinition'
  );
  const definition = getDefinition({ operationDefinitions, operationName });

  // GraphQL-anywhere do not support operationName yet,
  // so we must patch it until they do
  // See https://github.com/apollographql/graphql-anywhere/issues/34
  if (operationDefinitions.length > 1) {
    queryDocument.definitions = queryDocument.definitions.filter(def =>
      !operationDefinitions.includes(def) || def === definition
    );
  }

  if (goal === 'find' && definition.operation !== 'query') {
    const message = 'Can only perform GraphQL queries, not mutations, with the current protocol method';
    throw new EngineError(message, { reason: 'GRAPHQL_SYNTAX_ERROR' });
  }

  return { graphqlMethod: definition.operation };
};

const getDefinition = function ({ operationDefinitions, operationName }) {
  const definitions = operationDefinitions.filter(({
    name: { value: name } = {},
  }) => !operationName || name === operationName);

  if (definitions.length === 0) {
    if (operationName) {
      const message = `Could not find GraphQL operation ${operationName}`;
      throw new EngineError(message, { reason: 'GRAPHQL_SYNTAX_ERROR' });
    } else {
      const message = 'Missing GraphQL query';
      throw new EngineError(message, { reason: 'GRAPHQL_NO_QUERY' });
    }
  }

  const [definition] = definitions;
  return definition;
};

module.exports = {
  parseQuery,
  validateQuery,
};
{'fraction_non_alphanumeric': 0.13681122983448565, 'fraction_numerical': 0.0016760946993505132, 'mean_word_length': 3.5122873345935726, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2645155', 'n_tokens_mistral': 1390, 'n_tokens_neox': 1345, 'n_words': 369}