| 'use strict'; |
| |
| var merge = require('../../merge'); |
| var errors = require('../errors'); |
| var updateDoc = require('./updateDoc'); |
| var isDeleted = require('./isDeleted'); |
| var isLocalId = require('./isLocalId'); |
| |
| var collections = require('pouchdb-collections'); |
| var Map = collections.Map; |
| |
| function processDocs(docInfos, api, fetchedDocs, tx, results, writeDoc, opts, |
| overallCallback) { |
| |
| function insertDoc(docInfo, resultsIdx, callback) { |
| // Cant insert new deleted documents |
| var winningRev = merge.winningRev(docInfo.metadata); |
| var deleted = isDeleted(docInfo.metadata, winningRev); |
| if ('was_delete' in opts && deleted) { |
| results[resultsIdx] = errors.error(errors.MISSING_DOC, 'deleted'); |
| return callback(); |
| } |
| |
| var delta = deleted ? 0 : 1; |
| |
| writeDoc(docInfo, winningRev, deleted, deleted, false, |
| delta, resultsIdx, callback); |
| } |
| |
| var newEdits = opts.new_edits; |
| var idsToDocs = new Map(); |
| |
| var docsDone = 0; |
| var docsToDo = docInfos.length; |
| |
| function checkAllDocsDone() { |
| if (++docsDone === docsToDo && overallCallback) { |
| overallCallback(); |
| } |
| } |
| |
| docInfos.forEach(function (currentDoc, resultsIdx) { |
| |
| if (currentDoc._id && isLocalId(currentDoc._id)) { |
| api[currentDoc._deleted ? '_removeLocal' : '_putLocal']( |
| currentDoc, {ctx: tx}, function (err) { |
| if (err) { |
| results[resultsIdx] = err; |
| } else { |
| results[resultsIdx] = {ok: true}; |
| } |
| checkAllDocsDone(); |
| }); |
| return; |
| } |
| |
| var id = currentDoc.metadata.id; |
| if (idsToDocs.has(id)) { |
| docsToDo--; // duplicate |
| idsToDocs.get(id).push([currentDoc, resultsIdx]); |
| } else { |
| idsToDocs.set(id, [[currentDoc, resultsIdx]]); |
| } |
| }); |
| |
| // in the case of new_edits, the user can provide multiple docs |
| // with the same id. these need to be processed sequentially |
| idsToDocs.forEach(function (docs, id) { |
| var numDone = 0; |
| |
| function docWritten() { |
| if (++numDone < docs.length) { |
| nextDoc(); |
| } else { |
| checkAllDocsDone(); |
| } |
| } |
| function nextDoc() { |
| var value = docs[numDone]; |
| var currentDoc = value[0]; |
| var resultsIdx = value[1]; |
| |
| if (fetchedDocs.has(id)) { |
| updateDoc(fetchedDocs.get(id), currentDoc, results, |
| resultsIdx, docWritten, writeDoc, newEdits); |
| } else { |
| insertDoc(currentDoc, resultsIdx, docWritten); |
| } |
| } |
| nextDoc(); |
| }); |
| } |
| |
| module.exports = processDocs; |