all files / lib/deps/docs/ parseDoc.js

100% Statements 83/83
97.62% Branches 41/42
100% Functions 7/7
100% Lines 82/82
1 branch Ignored     
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160                  22× 22×                                   26504× 26504× 10× 26494× 26491×   26504× 20×       8257×   8255× 8255× 8255× 8255×           1629×   1629× 1629×   1629× 35039×     1629×                 19323× 19323× 19323× 19323× 19323× 1393×     19323× 15809× 1806×   15809× 15809× 6372× 6372×   6371×       6371×   9437×       9437×     3514× 1629× 1629× 1629×   3514× 1885× 1885×   1884× 1884× 1884×             19321×   19317×   19317× 19317×   85523× 85523× 85523× 85520× 63281×   22239×       19314×    
'use strict';
 
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.parseDoc = exports.invalidIdError = undefined;
 
var _uuid = require('./../uuid');
 
var _uuid2 = _interopRequireDefault(_uuid);
 
var _errors = require('../../deps/errors');
 
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
function toObject(array) {
  return array.reduce(function (obj, item) {
    obj[item] = true;
    return obj;
  }, {});
}
// List of top level reserved words for doc
var reservedWords = toObject(['_id', '_rev', '_attachments', '_deleted', '_revisions', '_revs_info', '_conflicts', '_deleted_conflicts', '_local_seq', '_rev_tree',
//replication documents
'_replication_id', '_replication_state', '_replication_state_time', '_replication_state_reason', '_replication_stats',
// Specific to Couchbase Sync Gateway
'_removed']);
 
// List of reserved words that should end up the document
var dataWords = toObject(['_attachments',
//replication documents
'_replication_id', '_replication_state', '_replication_state_time', '_replication_state_reason', '_replication_stats']);
 
// Determine id an ID is valid
//   - invalid IDs begin with an underescore that does not begin '_design' or
//     '_local'
//   - any other string value is a valid id
// Returns the specific error object for each case
function invalidIdError(id) {
  var err;
  if (!id) {
    err = (0, _errors.createError)(_errors.MISSING_ID);
  } else if (typeof id !== 'string') {
    err = (0, _errors.createError)(_errors.INVALID_ID);
  } else if (/^_/.test(id) && !/^_(design|local)/.test(id)) {
    err = (0, _errors.createError)(_errors.RESERVED_ID);
  }
  if (err) {
    throw err;
  }
}
 
function parseRevisionInfo(rev) {
  if (!/^\d+\-./.test(rev)) {
    return (0, _errors.createError)(_errors.INVALID_REV);
  }
  var idx = rev.indexOf('-');
  var left = rev.substring(0, idx);
  var right = rev.substring(idx + 1);
  return {
    prefix: parseInt(left, 10),
    id: right
  };
}
 
function makeRevTreeFromRevisions(revisions, opts) {
  var pos = revisions.start - revisions.ids.length + 1;
 
  var revisionIds = revisions.ids;
  var ids = [revisionIds[0], opts, []];
 
  for (var i = 1, len = revisionIds.length; i < len; i++) {
    ids = [revisionIds[i], { status: 'missing' }, [ids]];
  }
 
  return [{
    pos: pos,
    ids: ids
  }];
}
 
// Preprocess documents, parse their revisions, assign an id and a
// revision for new writes that are missing them, etc
function parseDoc(doc, newEdits) {
 
  var nRevNum;
  var newRevId;
  var revInfo;
  var opts = { status: 'available' };
  if (doc._deleted) {
    opts.deleted = true;
  }
 
  if (newEdits) {
    if (!doc._id) {
      doc._id = (0, _uuid2.default)();
    }
    newRevId = (0, _uuid2.default)(32, 16).toLowerCase();
    if (doc._rev) {
      revInfo = parseRevisionInfo(doc._rev);
      if (revInfo.error) {
        return revInfo;
      }
      doc._rev_tree = [{
        pos: revInfo.prefix,
        ids: [revInfo.id, { status: 'missing' }, [[newRevId, opts, []]]]
      }];
      nRevNum = revInfo.prefix + 1;
    } else {
      doc._rev_tree = [{
        pos: 1,
        ids: [newRevId, opts, []]
      }];
      nRevNum = 1;
    }
  } else {
    if (doc._revisions) {
      doc._rev_tree = makeRevTreeFromRevisions(doc._revisions, opts);
      nRevNum = doc._revisions.start;
      newRevId = doc._revisions.ids[0];
    }
    if (!doc._rev_tree) {
      revInfo = parseRevisionInfo(doc._rev);
      if (revInfo.error) {
        return revInfo;
      }
      nRevNum = revInfo.prefix;
      newRevId = revInfo.id;
      doc._rev_tree = [{
        pos: nRevNum,
        ids: [newRevId, opts, []]
      }];
    }
  }
 
  invalidIdError(doc._id);
 
  doc._rev = nRevNum + '-' + newRevId;
 
  var result = { metadata: {}, data: {} };
  for (var key in doc) {
    /* istanbul ignore else */
    Eif (Object.prototype.hasOwnProperty.call(doc, key)) {
      var specialKey = key[0] === '_';
      if (specialKey && !reservedWords[key]) {
        var error = (0, _errors.createError)(_errors.DOC_VALIDATION, key);
        error.message = _errors.DOC_VALIDATION.message + ': ' + key;
        throw error;
      } else if (specialKey && !dataWords[key]) {
        result.metadata[key.slice(1)] = doc[key];
      } else {
        result.data[key] = doc[key];
      }
    }
  }
  return result;
}
 
exports.invalidIdError = invalidIdError;
exports.parseDoc = parseDoc;