bengl/mongosmash

View on GitHub
src/queryGenerator.js

Summary

Maintainability
A
2 hrs
Test Coverage
export function queryGenerator(list, smash){
  if (list.indexOf('insert') >= 0) return {insert: true};

  var query = {$set:{}, $unset:{}, _$incoriginal:{}};
  list.forEach(function(change){

    if (change.type == 'add') {
      if (isPush(change, smash)) {
        var path = change.path.split('.');
        path.pop();
        path = path.join('.');
        if (!query.$pushAll) query.$pushAll = {};
        if (!query.$pushAll[path]) query.$pushAll[path] = [];
        query.$pushAll[path].push(change.value);
        return;
      }
      query.$set[change.path] = change.value;
      if (typeof query.$unset[change.path] !== undefined) {
        delete query.$unset[change.path];
      }
    }
    if (change.type === 'update') {

      // dupe of deleting. also happens in change then delete.
      if (change.value === undefined) return;

      if (Array.isArray(change.object) && change.name === 'length') return;
      if (isInc(change, smash)) {
        if (!query.$inc) query.$inc = {};
        var orig = query._$incoriginal[change.path], newValue = change.value;
        if (!orig) {
          // need to store original values for $inc, since change.value lies.
          orig = change.oldValue;
          query._$incoriginal[change.path] = orig;
          query.$inc[change.path] = newValue - change.oldValue;
        }
        query.$inc[change.path] = newValue - orig;
        return;
      }
      query.$set[change.path] = change.value;
    }
    if (change.type === 'delete') {
      query.$unset[change.path] = "";
      // sets then deletions don't happen; value in update change is undefined.
    }
  });
  delete query._$incoriginal;
  if (!Object.keys(query.$set).length) delete query.$set;
  if (!Object.keys(query.$unset).length) delete query.$unset;
  if (!Object.keys(query).length) return {};
  return {update: query};
}

function isPush(change, smash){
  if (smash.isNeDB) return false;
  if (!Array.isArray(change.object)) return false;
  var index = parseInt(change.name);
  if (isNaN(index)) return false;
  if (typeof change.oldValue !== 'undefined') return false;
  return true;
}

function isInc(change, smash) {
  if (smash.isNeDB) return false;
  if (change.oldValue !== parseInt(change.oldValue)) return false;
  if (change.value !== parseInt(change.value)) return false;
  return true;
}