<commit_before>import log from '../../../logger';
import _   from 'lodash';
var mongodb = require('mongodb');
var Parse = require('parse/node').Parse;

// Transforms a key-value pair from REST API form to Mongo form.
// This is the main entry point for converting anything from REST form
// to Mongo form; no conversion should happen that doesn't pass
// through this function.
// Schema should already be loaded.
//
// There are several options that can help transform:
//
// query: true indicates that query constraints like $lt are allowed in
// the value.
//
// update: true indicates that __op operators like Add and Delete
// in the value are converted to a mongo update form. Otherwise they are
// converted to static data.
//
// validate: true indicates that key names are to be validated.
//
// Returns an object with {key: key, value: value}.
export function transformKeyValue(schema, className, restKey, restValue, {
  inArray,
  inObject,
  query,
  update,
  validate,
} = {}) {
  // Check if the schema is known since it's a built-in field.
  var key = restKey;
  var timeField = false;
  switch(key) {
  case 'objectId':
  case '_id':
    key = '_id';
    break;
  case 'createdAt':
  case '_created_at':
    key = '_created_at';
    timeField = true;
    break;
  case 'updatedAt':
  case '_updated_at':
    key = '_updated_at';
    timeField = true;
    break;
  case '_email_verify_token':
    key = "_email_verify_token";
    break;
  case '_perishable_token':
    key = "_perishable_token";
    break;
  case 'sessionToken':
  case '_session_token':
    key = '_session_token';
    break;
  case 'expiresAt':
  case '_expiresAt':
    key = 'expiresAt';
    timeField = true;
    break;
  case '_rperm':
  case '_wperm':
    return {key: key, value: restValue};
    break;
  case '$or':
    if (!query) {
      throw new Parse.Error(Parse.Error.INVALID_KEY_NAME,
                            'you can only use $or in queries');
    }
    if (!(restValue instanceof Array)) {
      throw new Parse.Error(Parse.Error.INVALID_QUERY,
                            'bad $or format - use an array value');
    }
    var mongoSubqueries = restValue.map((s) => {
      return transformWhere(schema, className, s);
    });
    return {key: '$or', value: mongoSubqueries};
  case '$and':
    if (!query) {
      throw new Parse.Error(Parse.Error.INVALID_KEY_NAME,
                            'you can only use $and in queries');
    }
    if (!(restValue instanceof Array)) {
      throw new Parse.Error(Parse.Error.INVALID_QUERY,
                            'bad $and format - use an array value');
    }
    var mongoSubqueries = restValue.map((s) => {
      return transformWhere(schema, className, s);
    });
    return {key: '$and', value: mongoSubqueries};
  default:
    // Other auth data
    var authDataMatch = key.match(/^authData\.([a-zA-Z0-9_]+)\.id$/);
    if (authDataMatch) {
      if (query) {
        var provider = authDataMatch[1];
        // Special-case auth data.
        return {key: '_auth_data_'+provider+'.id', value: restValue};
      }
      throw new Parse.Error(Parse.Error.INVALID_KEY_NAME,
                            'can only query on ' + key);
      break;
    };
    if (validate && !key.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) {
      throw new Parse.Error(Parse.Error.INVALID_KEY_NAME,
                            'invalid key name: ' + key);
    }
  }

  // Handle special schema key changes
  // TODO: it seems like this is likely to have edge cases where
  // pointer types are missed
  var expected = undefined;
  if (schema && schema.getExpectedType) {
    expected = schema.getExpectedType(className, key);
  }
  if ((expected && expected.type == 'Pointer') ||
      (!expected && restValue && restValue.__type == 'Pointer')) {
    key = '_p_' + key;
  }
  var expectedTypeIsArray = (expected && expected.type === 'Array');

  // Handle query constraints
  if (query) {
    value = transformConstraint(restValue, expectedTypeIsArray);
    if (value !== CannotTransform) {
      return {key: key, value: value};
    }
  }

  if (expectedTypeIsArray && query && !(restValue instanceof Array)) {
    return {
      key: key, value: { '$all' : [restValue] }
    };
  }

  // Handle atomic values
  var value = transformAtom(restValue, false, { inArray, inObject });
  if (value !== CannotTransform) {
    if (timeField && (typeof value === 'string')) {
      value = new Date(value);
    }
    return {key: key, value: value};
  }

  // ACLs are handled before this method is called
  // If an ACL key still exists here, something is wrong.
  if (key === 'ACL') {
    throw 'There was a problem transforming an ACL.';
  }

  // Handle arrays
  if (restValue instanceof Array) {
    if (query) {
      throw new Parse.Error(Parse.Error.INVALID_JSON,
                            'cannot use array as query param');
    }
    value = restValue.map((restObj) => {
      var out = transformKeyValue(schema, className, restKey, restObj, { inArray: true });
      return out.value;
    });
    return {key: key, value: value};
  }

  // Handle update operators
  value = transformUpdateOperator(restValue, !update);
  if (value !== CannotTransform) {
    return {key: key, value: value};
  }

  // Handle normal objects by recursing
  value = {};
  for (var subRestKey in restValue) {
    var subRestValue = restValue[subRestKey];
    var out = transformKeyValue(schema, className, subRestKey, subRestValue, { inObject: true });
    // For recursed objects, keep the keys in rest format
    value[subRestKey] = out.value;
  }
  return {key: key, value: value};
}


// Main exposed method to help run queries.
// restWhere is the "where" clause in REST API form.
// Returns the mongo form of the query.
// Throws a Parse.Error if the input query is invalid.
function transformWhere(schema, className, restWhere, options = {validate: true}) {
  let mongoWhere = {};
  if (restWhere['ACL']) {
    throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.');
  }
  let transformKeyOptions = {query: true};
  transformKeyOptions.validate = options.validate;
  for (let restKey in restWhere) {
    let out = transformKeyValue(schema, className, restKey, restWhere[restKey], transformKeyOptions);
    mongoWhere[out.key] = out.value;
  }
  return mongoWhere;
}

const parseObjectKeyValueToMongoObjectKeyValue = (
  schema,
  className,
  restKey,
  restValue,
  parseFormatSchema
) => {
  // Check if the schema is known since it's a built-in field.
  let transformedValue;
  let coercedToDate;
  switch(restKey) {
  case 'objectId': return {key: '_id', value: restValue};
  case 'createdAt':
    transformedValue = transformAtom(restValue, false);
    coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue
    return {key: '_created_at', value: coercedToDate};
  case 'updatedAt':
    transformedValue = transformAtom(restValue, false);<commit_msg>Destructuring<commit_after>import log from '../../../logger';
import _   from 'lodash';
var mongodb = require('mongodb');
var Parse = require('parse/node').Parse;

// Transforms a key-value pair from REST API form to Mongo form.
// This is the main entry point for converting anything from REST form
// to Mongo form; no conversion should happen that doesn't pass
// through this function.
// Schema should already be loaded.
//
// There are several options that can help transform:
//
// query: true indicates that query constraints like $lt are allowed in
// the value.
//
// update: true indicates that __op operators like Add and Delete
// in the value are converted to a mongo update form. Otherwise they are
// converted to static data.
//
// validate: true indicates that key names are to be validated.
//
// Returns an object with {key: key, value: value}.
export function transformKeyValue(schema, className, restKey, restValue, {
  inArray,
  inObject,
  query,
  update,
  validate,
} = {}) {
  // Check if the schema is known since it's a built-in field.
  var key = restKey;
  var timeField = false;
  switch(key) {
  case 'objectId':
  case '_id':
    key = '_id';
    break;
  case 'createdAt':
  case '_created_at':
    key = '_created_at';
    timeField = true;
    break;
  case 'updatedAt':
  case '_updated_at':
    key = '_updated_at';
    timeField = true;
    break;
  case '_email_verify_token':
    key = "_email_verify_token";
    break;
  case '_perishable_token':
    key = "_perishable_token";
    break;
  case 'sessionToken':
  case '_session_token':
    key = '_session_token';
    break;
  case 'expiresAt':
  case '_expiresAt':
    key = 'expiresAt';
    timeField = true;
    break;
  case '_rperm':
  case '_wperm':
    return {key: key, value: restValue};
    break;
  case '$or':
    if (!query) {
      throw new Parse.Error(Parse.Error.INVALID_KEY_NAME,
                            'you can only use $or in queries');
    }
    if (!(restValue instanceof Array)) {
      throw new Parse.Error(Parse.Error.INVALID_QUERY,
                            'bad $or format - use an array value');
    }
    var mongoSubqueries = restValue.map((s) => {
      return transformWhere(schema, className, s);
    });
    return {key: '$or', value: mongoSubqueries};
  case '$and':
    if (!query) {
      throw new Parse.Error(Parse.Error.INVALID_KEY_NAME,
                            'you can only use $and in queries');
    }
    if (!(restValue instanceof Array)) {
      throw new Parse.Error(Parse.Error.INVALID_QUERY,
                            'bad $and format - use an array value');
    }
    var mongoSubqueries = restValue.map((s) => {
      return transformWhere(schema, className, s);
    });
    return {key: '$and', value: mongoSubqueries};
  default:
    // Other auth data
    var authDataMatch = key.match(/^authData\.([a-zA-Z0-9_]+)\.id$/);
    if (authDataMatch) {
      if (query) {
        var provider = authDataMatch[1];
        // Special-case auth data.
        return {key: '_auth_data_'+provider+'.id', value: restValue};
      }
      throw new Parse.Error(Parse.Error.INVALID_KEY_NAME,
                            'can only query on ' + key);
      break;
    };
    if (validate && !key.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) {
      throw new Parse.Error(Parse.Error.INVALID_KEY_NAME,
                            'invalid key name: ' + key);
    }
  }

  // Handle special schema key changes
  // TODO: it seems like this is likely to have edge cases where
  // pointer types are missed
  var expected = undefined;
  if (schema && schema.getExpectedType) {
    expected = schema.getExpectedType(className, key);
  }
  if ((expected && expected.type == 'Pointer') ||
      (!expected && restValue && restValue.__type == 'Pointer')) {
    key = '_p_' + key;
  }
  var expectedTypeIsArray = (expected && expected.type === 'Array');

  // Handle query constraints
  if (query) {
    value = transformConstraint(restValue, expectedTypeIsArray);
    if (value !== CannotTransform) {
      return {key: key, value: value};
    }
  }

  if (expectedTypeIsArray && query && !(restValue instanceof Array)) {
    return {
      key: key, value: { '$all' : [restValue] }
    };
  }

  // Handle atomic values
  var value = transformAtom(restValue, false, { inArray, inObject });
  if (value !== CannotTransform) {
    if (timeField && (typeof value === 'string')) {
      value = new Date(value);
    }
    return {key: key, value: value};
  }

  // ACLs are handled before this method is called
  // If an ACL key still exists here, something is wrong.
  if (key === 'ACL') {
    throw 'There was a problem transforming an ACL.';
  }

  // Handle arrays
  if (restValue instanceof Array) {
    if (query) {
      throw new Parse.Error(Parse.Error.INVALID_JSON,
                            'cannot use array as query param');
    }
    value = restValue.map((restObj) => {
      var out = transformKeyValue(schema, className, restKey, restObj, { inArray: true });
      return out.value;
    });
    return {key: key, value: value};
  }

  // Handle update operators
  value = transformUpdateOperator(restValue, !update);
  if (value !== CannotTransform) {
    return {key: key, value: value};
  }

  // Handle normal objects by recursing
  value = {};
  for (var subRestKey in restValue) {
    var subRestValue = restValue[subRestKey];
    var out = transformKeyValue(schema, className, subRestKey, subRestValue, { inObject: true });
    // For recursed objects, keep the keys in rest format
    value[subRestKey] = out.value;
  }
  return {key: key, value: value};
}


// Main exposed method to help run queries.
// restWhere is the "where" clause in REST API form.
// Returns the mongo form of the query.
// Throws a Parse.Error if the input query is invalid.
function transformWhere(schema, className, restWhere, { validate = true } = {}) {
  let mongoWhere = {};
  if (restWhere['ACL']) {
    throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.');
  }
  for (let restKey in restWhere) {
    let out = transformKeyValue(schema, className, restKey, restWhere[restKey], { query: true, validate });
    mongoWhere[out.key] = out.value;
  }
  return mongoWhere;
}

const parseObjectKeyValueToMongoObjectKeyValue = (
  schema,
  className,
  restKey,
  restValue,
  parseFormatSchema
) => {
  // Check if the schema is known since it's a built-in field.
  let transformedValue;
  let coercedToDate;
  switch(restKey) {
  case 'objectId': return {key: '_id', value: restValue};
  case 'createdAt':
    transformedValue = transformAtom(restValue, false);
    coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue
    return {key: '_created_at', value: coercedToDate};
  case 'updatedAt':
    transformedValue = transformAtom(restValue, false);
{'fraction_non_alphanumeric': 0.12496373658253554, 'fraction_numerical': 0.000725268349289237, 'mean_word_length': 2.8452314556609033, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, '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': '243388', 'n_tokens_mistral': 4182, 'n_tokens_neox': 4112, 'n_words': 1336}