From 699b99c808309b2e7d7040e316ec2cd6cd24ddf9 Mon Sep 17 00:00:00 2001 From: ewnd9 Date: Thu, 3 Nov 2016 19:23:59 +0800 Subject: [PATCH] feat: bulk method --- README.md | 5 +++++ src/index.js | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test/test.js | 27 ++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/README.md b/README.md index 0c8be85..a92cc68 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,11 @@ Returns the `_id` field in `data` or new id generated by a function provided in Overwrites the previous object if existed with a correct `_rev` or insert a new doc +## `#bulk(data: Object[])` + +Returns an array of the same length containing corresponding doc (has `_id` and `_rev`) +or error (has `error`, `name`, `status` and, in case of validation error - `err`) + ### `#sync(db: PouchDB | String, options: Object?, notify: Function)` ## License diff --git a/src/index.js b/src/index.js index 1f2a1e1..e39e0cb 100644 --- a/src/index.js +++ b/src/index.js @@ -146,6 +146,61 @@ Model.prototype.update = function(data) { ); }; +Model.prototype.bulk = function(docs) { + const errors = []; + const correct = []; + + return Promise + .all( + docs.map((doc, index) => this.validate(doc).then( + doc => correct.push({ doc, index }), + err => errors.push({ + err: { + error: true, + name: 'validation error', + err + }, + index + }) + )) + ) + .then(() => { + const docs = correct.map(item => { + item.doc._id = this.createId(item.doc); + return item.doc; + }); + return this.db.bulkDocs(docs); + }) + .then(dbDocs => { + let correctIndex = 0; + let errorsIndex = 0; + let dbIndex = 0; + + return docs.map((doc, index) => { + let dbDoc; + + if (correct[correctIndex] && correct[correctIndex].index === index) { + dbDoc = dbDocs[dbIndex]; + correctIndex++; + dbIndex++; + } else if (errors[errorsIndex] && errors[errorsIndex].index === index) { + dbDoc = errors[errorsIndex].err; + errorsIndex++; + } + + if (dbDoc.ok === true) { + return { + ...docs[index], + _id: dbDoc.id, + _rev: dbDoc.rev + }; + } + + return dbDoc; + }); + }); +}; + /* * https://pouchdb.com/api.html#sync */ diff --git a/test/test.js b/test/test.js index 77e192f..c5fcc0a 100644 --- a/test/test.js +++ b/test/test.js @@ -142,6 +142,33 @@ test('#update', async t => { await model.update({ name: 'test' }); }); +test('#bulk', async t => { + const db = new PouchDB('bulk', { adapter: 'memory' }); + + const validate = doc => new Promise((resolve, reject) => { + return doc.name !== 'test-4' ? resolve(doc) : reject(new Error('name === test-4')); + }); + + const model = new Model(db, { + createId: ({ name }) => `item:${name}`, + }, validate); + + const result0 = await model.bulk([{ name: 'test-1' }, { name: 'test-2' }]); + const result1 = await model.bulk([{ name: 'test-1' }, { name: 'test-2' }, { name: 'test-3' }]); + + t.truthy(result0.filter(_ => _._rev).length === 2); + t.truthy(result1.filter(_ => _._rev).length === 1); + + const result2 = await model.bulk([{ name: 'test-1' }, { name: 'test-2' }, { name: 'test-3' }, { name: 'test-4' }]); + t.truthy(result2.filter(_ => _.rev).length === 0); + t.deepEqual(result2.filter(_ => _.error).map(_ => _.name), [ + 'conflict', + 'conflict', + 'conflict', + 'validation error' + ]); +}); + test('#ensureIndexes', async t => { const db = new PouchDB('ensureIndexes', { adapter: 'memory' });