<commit_before>import { get, isEmpty, lowerFirst, pick } from 'lodash';

const allMutations = [];

const addMutation = (mutation = () => '') => {
  allMutations.push(mutation);
  return (newMutation = () => '') => {
    allMutations.push(newMutation);
    return (key) => allMutations.map(mutation => `${mutation(key)} \n` ).join('');
  }
}

const validateSchema = (target, newData) => {
  return !isEmpty(pick(newData, Object.keys(get(target, 'schema', {}))));
}

const addResolver = (target, key, descriptor) => {
  return async function() {
      try {
        const nameClass = lowerFirst(target.nameClass);
        const isAllow = get(target[key], 'allow', function() { return true; });
        if (isAllow.bind(target)(...arguments)) {
          const resolveData = await descriptor.value.bind(target)(...arguments);

          if (validateSchema(target, resolveData)) {
            return { [nameClass]: resolveData, errors: null };
          } else {
            return { [nameClass]: null, errors: resolveData };
          }
        }
        return null;
      } catch (error) {
        throw new Error('Decorators query failed. \n' + error);
      }
    };
}

const createInputType = (typeName, createTypes) => {
  return `
    input create${typeName} {
      ${createTypes}
    }`;
}

const updateInputType = (typeName, createTypes) => {
  const pattern = new RegExp(/!/g);
  const parseTypes = createTypes.replace(pattern, '');
  return `
    input update${typeName} {
      ${parseTypes}
    }`;
}

const responseTypeWithError = (typeName) => {
  return `
    type response${typeName} {
      ${lowerFirst(typeName)}: ${typeName},
      errors: [Errors],
    }
  `;
}

const mutation = function(params) {
  return function(target, key, descriptor) {
    const defaultFields = '';
    let newMutation = '';
    let parseFields = '';
    let fields = '';

    switch (typeof params) {
      // { type: 'create'} // return resposeType with errors
      // { type: 'update'} // return resposeType with errors
      // { type: 'remove'} // return resposeType with errors
      // ({ fields: 'id: ID!', responseType: 'Todo' })
      // ('id: ID!') // default return current name Type
      case 'string':
        parseFields = isEmpty(params) ? '' : `(${params})`;
        newMutation = (nameType) => `${key}${parseFields}: [${nameType}],`;
        break;
      case 'object':
        const type = get(params, 'type', false);

        if (type) {
          if (['create', 'update', 'remove'].includes(type)) {
            target.responseTypeWithError = responseTypeWithError;
          }

          if (type == 'create') {
            target.create = createInputType;
            // key name of function for e.g., createTodo
            // createTodo(todo: createTodo): responseTodo
            newMutation = (nameType) => `${key}(${lowerFirst(nameType)}: create${nameType}): response${nameType},`;
            break;
          }

          if (type == 'update') {
            target.update = updateInputType;
            // key name of function for e.g., updateTodo
            // updateTodo(id: ID!, todo: updateTodo): responseTodo
            newMutation = (nameType) => `${key}(id: ID!, ${lowerFirst(nameType)}: update${nameType}): response${nameType},`;
            break;
          }

          if (type == 'remove') {
            // key name of function for e.g., removeTodo
            // removeTodo(id: ID!): responseTodo
            newMutation = (nameType) => `${key}(id: ID!): response${nameType},`;
            break;
          }
        }

        fields = get(params, 'fields', defaultFields);

        if (fields) {
          parseFields = isEmpty(fields) ? '' : `(${params})`;
          newMutation = (nameType) => `${key}${parseFields}: ${get(params, 'responseType', nameType)},`;
          break;
        }

        newMutation = (nameType) => `${key}: ${nameType},`;
        break;
      default:
        newMutation = (nameType) => `${key}: ${nameType},`;
    }

    target.Mutation = addMutation(newMutation);
    target.Resolvers = Object.assign({}, target.Resolvers);
    target.Resolvers.Mutation = Object.assign({}, target.Resolvers.Mutation);
    target.Resolvers.Mutation[key] = addResolver(target, key, descriptor);
  };
};

export default mutation;
<commit_msg>proposal refactor mutation decorator<commit_after>import { get, isEmpty, lowerFirst, pick } from 'lodash';

const CREATE = 'create';
const UPDATE = 'update';
const REMOVE = 'remove';
const ACTIONS_TYPES = [CREATE, UPDATE, REMOVE];
const MUTATIONS = [];
const DEFAULT_MUTATION = (nameType) => `${key}: ${nameType},`;


const addMutation = (mutation = () => '') => {
  MUTATIONS.push(mutation);
  return (newMutation = () => '') => {
    MUTATIONS.push(newMutation);
    return (key) => MUTATIONS.map(mutation => `${mutation(key)} \n` ).join('');
  }
}

const validateSchema = (target, newData) => {
  // checking if the new data has the all key of the schema
  // if not has the the keys we have to consider is a error
  return !isEmpty(pick(newData, Object.keys(get(target, 'schema', {}))));
}

const addResolver = (target, key, descriptor) => {
  return async function() {
      try {
        const nameClass = lowerFirst(target.nameClass);
        const isAllow = get(target[key], 'allow', function() { return true; });
        if (isAllow.bind(target)(...arguments)) {
          const resolveData = await descriptor.value.bind(target)(...arguments);

          if (validateSchema(target, resolveData)) {
            return { [nameClass]: resolveData, errors: null };
          } else {
            return { [nameClass]: null, errors: resolveData };
          }
        }
        return null;
      } catch (error) {
        throw new Error('Decorators query failed. \n' + error);
      }
    };
}

const TYPE_CREATE = {
  inputType: (typeName, createTypes) => {
    return `
      input create${typeName} {
        ${createTypes}
      }`;
  },
  // key name of function for e.g., createTodo
  // createTodo(todo: createTodo): responseTodo
  mutation: (nameType) => `${key}(${lowerFirst(nameType)}: create${nameType}): response${nameType},`,
}

const TYPE_UPDATE = {
  inputType: (typeName, createTypes) => {
    const pattern = new RegExp(/!/g);
    const parseTypes = createTypes.replace(pattern, '');
    return `
      input update${typeName} {
        ${parseTypes}
      }`;
  },
  // key name of function for e.g., updateTodo
  // updateTodo(id: ID!, todo: updateTodo): responseTodo
  mutation: (nameType) => `${key}(id: ID!, ${lowerFirst(nameType)}: update${nameType}): response${nameType},`,
}

const TYPE_REMOVE = {
  // key name of function for e.g., removeTodo
  // removeTodo(id: ID!): responseTodo
  mutation: (nameType) => `${key}(id: ID!): response${nameType},`,
}

const TYPE_RESPONSE_WITH_ERROR = (typeName) => {
  return `
    type response${typeName} {
      ${lowerFirst(typeName)}: ${typeName},
      errors: [Errors],
    }
  `;
}

const mutation = function(params) {
  return function(target, key, descriptor) {

    let newMutation = '';
    let parseFields = '';

    switch (typeof params) {
      // { type: 'create'} // return resposeType with errors
      // { type: 'update'} // return resposeType with errors
      // { type: 'remove'} // return resposeType with errors
      // ({ fields: 'id: ID!', responseType: 'Todo' })
      // ('id: ID!') // default return current name Type
      case 'string':
        parseFields = isEmpty(params) ? '' : `(${params})`;
        newMutation = (nameType) => `${key}${parseFields}: ${nameType},`;
        break;

      case 'object':
        const type = get(params, 'type', false);

        if (ACTIONS_TYPES.includes(type)) {
          target.responseTypeWithError = TYPE_RESPONSE_WITH_ERROR;

          switch (type) {

            case CREATE:
              target.create = TYPE_CREATE.inputType;
              newMutation = TYPE_CREATE.mutation;
              break;

            case UPDATE:
              target.update = TYPE_UPDATE.inputType;
              newMutation = TYPE_UPDATE.mutation;
              break;

            case REMOVE:
              newMutation = TYPE_REMOVE.mutation;
              break;

            default:
              break;
          }
          break;
        }

        const fields = get(params, 'fields', false);

        if (fields) {
          parseFields = isEmpty(fields) ? '' : `(${params})`;
          newMutation = (nameType) => `${key}${parseFields}: ${get(params, 'responseType', nameType)},`;
          break;
        }

        newMutation = DEFAULT_MUTATION;
        break;
      default:
        newMutation = DEFAULT_MUTATION;
    }

    target.Mutation = addMutation(newMutation);
    target.Resolvers = Object.assign({}, target.Resolvers);
    target.Resolvers.Mutation = Object.assign({}, target.Resolvers.Mutation);
    target.Resolvers.Mutation[key] = addResolver(target, key, descriptor);
  };
};

export default mutation;

{'fraction_non_alphanumeric': 0.1578301149681884, 'fraction_numerical': 0.0, 'mean_word_length': 2.5527359238699443, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 38, 'https://': 0, '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': '5821366', 'n_tokens_mistral': 2730, 'n_tokens_neox': 2694, 'n_words': 632}