couchdb-tools
Advanced tools
Comparing version 0.0.3 to 0.0.4
160
index.js
@@ -7,12 +7,2 @@ var uglifyjs = require('uglify-js') | ||
/** | ||
* Build a JSON/CouchDB compatible design document from a native JavaScript | ||
* object. The main utility of this function is to translate any map/reduce | ||
* functions encountered in the design document into tidy JSON-safe strings. | ||
* | ||
* @param {object} ddoc Native JS object representing the design document | ||
* @param {string} name Design document name (optional) | ||
* | ||
* @return {object} A new design document object suitable for adding to a db | ||
*/ | ||
exports.ddoc = function (obj,name) { | ||
@@ -36,16 +26,11 @@ obj = JSON.parse(JSON.stringify(obj,function (key,val) { | ||
/** | ||
* Normalise a CouchDB result object into a flat array of document objects | ||
* containing _id and _rev properties. | ||
* | ||
* @param {object} CouchDB result object | ||
* | ||
* @returns {array} Normalised flat array of documents | ||
*/ | ||
module.exports.normalise = function (collection) { | ||
if ( !_.isArray(collection) ) { | ||
collection = collection.rows; | ||
module.exports.normalise = function (res) { | ||
if ( !_.isArray(res) && _.isNumber(res.offset) ) { | ||
res = res.rows; | ||
} | ||
return collection.map(function (obj) { | ||
if ( typeof obj.doc == 'object' ) { | ||
if ( !_.isArray(res) ) { | ||
return res; | ||
} | ||
return res.map(function (obj) { | ||
if ( _.isObject(obj.doc) && _.isString(obj.doc._id) ) { | ||
return obj.doc; | ||
@@ -61,53 +46,2 @@ } else { | ||
/** | ||
* Algorithm for comparing two collections of documents. One collection is | ||
* deemed to be new, the other old. The returned result object categorises | ||
* the documents into a set of arrays: onlyOld, onlyNew, bothAndEqual and | ||
* bothAndUnEqual. For example, you may decide that the documents in onlyOld | ||
* need deleting and those in onlyNew need inserting. | ||
* | ||
* @param {array} current Array of up-to-date documents | ||
* @param {array} old Arrray of out-of-date documents | ||
*/ | ||
exports.sync = function (newColl,oldColl) { | ||
var onlyOld = []; | ||
var bothAndEqual = []; | ||
var bothAndUnEqual = []; | ||
var onlyNew = []; | ||
oldColl.forEach(function (oldDoc) { | ||
if ( !exports.find(newColl,oldDoc._id) ) { | ||
onlyOld.push(oldDoc); | ||
} | ||
}); | ||
newColl.forEach(function (newDoc) { | ||
var oldDoc = exports.find(oldColl,newDoc._id); | ||
if ( oldDoc ) { | ||
if ( !exports.equal(oldDoc,newDoc) ) { | ||
bothAndUnEqual.push({ | ||
old: oldDoc, | ||
new: newDoc | ||
}); | ||
} else { | ||
bothAndEqual.push({ | ||
old: oldDoc, | ||
new: newDoc | ||
}); | ||
} | ||
} else { | ||
onlyNew.push(newDoc); | ||
} | ||
}); | ||
return { | ||
onlyOld: onlyOld, | ||
bothAndEqual: bothAndEqual, | ||
bothAndUnEqual: bothAndUnEqual, | ||
onlyNew: onlyNew | ||
} | ||
} | ||
/** | ||
* Clone a document. Ensures that any manipulation of complex types (objects and | ||
* arrays) in the clone will not corrupt data in the source document. | ||
*/ | ||
exports.clone = function (obj) { | ||
@@ -117,10 +51,2 @@ return JSON.parse(JSON.stringify(obj)); | ||
/** | ||
* Find a document by _id in a collection. | ||
* | ||
* @param {array} Normalised collection of documents | ||
* @param {string} The _id to search for | ||
* | ||
* @returns {object} The found object or undefined | ||
*/ | ||
exports.find = function (collection,id) { | ||
@@ -132,10 +58,2 @@ return _.find(collection,function (item) { | ||
/** | ||
* Compare two documents for equality while ignoring their _rev properties. | ||
* | ||
* @param {object} a The first object to compare | ||
* @param {object} a The second object to compare | ||
* | ||
* @returns {boolean} The objects' equality | ||
*/ | ||
exports.equal = function (a,b) { | ||
@@ -152,11 +70,2 @@ var aRev = a._rev; | ||
/** | ||
* Create a new document that is the result of merging the properties of an | ||
* arbitrary number of documents. Right-most parameters passed to the function | ||
* gain increasing priority during the merge. | ||
* | ||
* @param {object} Any number of documents | ||
* | ||
* @returns {object} A new merged document | ||
*/ | ||
exports.combine = function () { | ||
@@ -167,11 +76,2 @@ var args = Array.prototype.slice.call(arguments); | ||
/** | ||
* Generate URI-safe, short, non-sequential unqiue ids. Optionally pass in a | ||
* unique-for-your-app random number seed which will make your ids more secure. | ||
* Passing the seed only needs to be done once at the start. | ||
* | ||
* @param {number} seed Random number seed (optional) | ||
* | ||
* @returns {string} A short unique id. | ||
*/ | ||
exports.shortid = function (seed) { | ||
@@ -184,12 +84,40 @@ if ( typeof seed != 'undefined' ) { | ||
/** | ||
* Converts a string into a URI-safe slug. Symbols are removed and foreign | ||
* characters are coerced into to their English equivalent. | ||
* | ||
* @param {string} text The text to slugify. | ||
* | ||
* @returns {string} A URI-safe slug. | ||
*/ | ||
exports.slug = function (text) { | ||
return slug(text); | ||
} | ||
exports.sync = function (newColl,oldColl) { | ||
var onlyOld = []; | ||
var bothAndEqual = []; | ||
var bothAndUnEqual = []; | ||
var onlyNew = []; | ||
oldColl.forEach(function (oldDoc) { | ||
if ( !exports.find(newColl,oldDoc._id) ) { | ||
onlyOld.push(oldDoc); | ||
} | ||
}); | ||
newColl.forEach(function (newDoc) { | ||
var oldDoc = exports.find(oldColl,newDoc._id); | ||
if ( oldDoc ) { | ||
if ( !exports.equal(oldDoc,newDoc) ) { | ||
bothAndUnEqual.push({ | ||
old: oldDoc, | ||
new: newDoc | ||
}); | ||
} else { | ||
bothAndEqual.push({ | ||
old: oldDoc, | ||
new: newDoc | ||
}); | ||
} | ||
} else { | ||
onlyNew.push(newDoc); | ||
} | ||
}); | ||
return { | ||
onlyOld: onlyOld, | ||
bothAndEqual: bothAndEqual, | ||
bothAndUnEqual: bothAndUnEqual, | ||
onlyNew: onlyNew | ||
} | ||
} |
{ | ||
"name": "couchdb-tools", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"description": "A library of handy functions for use when working with CouchDB documents.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
111
README.md
@@ -1,7 +0,6 @@ | ||
couchdb-tools | ||
============= | ||
# couchdb-tools | ||
`npm install coucbdb-tools --save` | ||
A library of handy functions for use when working with CouchDB documents. All functions are database adapter agnostic. | ||
A Node.js library of handy functions for use when working with CouchDB documents. All functions are database adapter agnostic. | ||
@@ -12,3 +11,3 @@ Some functions are unique to this library, others are just wrappers around some of the best packages for the job from the Node.JS community - and in which case thanks for your hard work :) | ||
Build a JSON/CouchDB compatible design document from a native JavaScript object. The main utility of this function is to translate any map/reduce functions encountered in the design document into tidy JSON-safe strings. | ||
Build a JSON/CouchDB compatible design document from a native JavaScript object. The main utility of this function is to translate any functions encountered in the design document into tidy JSON-safe strings. Design documents stored as valid JavaScript objects alongside your app source code rather than as raw JSON can benefit properly from version control and linting. | ||
@@ -21,2 +20,3 @@ The `name` parameter is optional, and only required if you wish to create the design document's id too. | ||
var tools = require('couchdb-tools'); | ||
var projects = { | ||
@@ -35,2 +35,3 @@ views: { | ||
var projectsDesignDoc = tools.ddoc(projects,'projects'); | ||
console.log(projectsDesignDoc); | ||
@@ -53,25 +54,71 @@ ``` | ||
#### `normalise(collection)` | ||
#### `normalise(res)` | ||
Documentation to do. | ||
Normalise a CouchDB result set into a flat array of document objects containing `_id` and `_rev` properties. The function will try to intelligently deal with the presence or lack of actual documents in the result as defined by the `include_docs` parameter. | ||
#### `sync(current,old)` | ||
##### Example | ||
Documentation to do. | ||
Given a raw CouchDB result set object similar to, | ||
#### `clone(obj,obj[,obj...])` | ||
```javascript | ||
{ | ||
total_rows: 10, | ||
offset: 0, | ||
rows: [ | ||
{ | ||
id: '...', | ||
key: '...', | ||
value: {...}, | ||
doc: {...} | ||
}, | ||
{ ... }, | ||
{ ... }, | ||
etc. | ||
] | ||
} | ||
``` | ||
Documentation to do. | ||
and invoking `normalise` on this object, | ||
```javascript | ||
var tools = require('couchdb-tools'); | ||
res = tools.normalise(res); | ||
console.log(res); | ||
``` | ||
will produce the following output: | ||
```javascript | ||
[ | ||
{ | ||
_id: '...', | ||
_rev: '...', | ||
propA: '...', | ||
propB: '...' | ||
}, | ||
{ ... }, | ||
{ ... }, | ||
etc. | ||
] | ||
``` | ||
You can now inspect or manipulate this array of documents freely and save back to CouchDB in a bulk operation. | ||
#### `clone(obj)` | ||
Returns a deep clone of a document. Use it when you need to copy and manipulate a document without fear of corrupting the original data set. | ||
#### `find(collection,id)` | ||
Documentation to do. | ||
Find a document by `_id` in an array. | ||
#### `equal(a,b)` | ||
Documentation to do. | ||
Compares two documents for deep equality. Document `_rev` values are ignored and can differ while their parent documents are still considered equal. | ||
#### `combine(a,b)` | ||
#### `combine(obj,obj[,obj,...])` | ||
Create a new object that is the result of copying the properties of the second parameter into the first. | ||
Create a new document that is the result of copying the properties of an arbitrary number of documents into it. Documents at the right end of the parameter list are given precedent. | ||
@@ -112,3 +159,3 @@ ##### Example | ||
Similar contents to the following will be output to the console: | ||
Output similar to the following will be generated: | ||
@@ -137,1 +184,35 @@ ``` | ||
``` | ||
#### `sync(newColl,oldColl)` | ||
Algorithm for synchronising two collections of documents by `_id`. Useful for synchronising a local data set with the db (for example design documents or static app config data etc.). | ||
The algorithm will compare the two sets of documents and determine which documents, | ||
- only exist in the old set | ||
- only exist in the new set | ||
- exist in both and are identical | ||
- exist in both and are different | ||
It is left to your app code to determine how to handle each set. The results are exposed in the returned object, which has the following structure: | ||
```javascript | ||
{ | ||
onlyOld: [ ... ], | ||
onlyNew: [ ... ], | ||
bothAndEqual: [ | ||
{ | ||
old: {}, | ||
new: {} | ||
}, | ||
{ ... } | ||
], | ||
bothAndUnEqual: [ | ||
{ | ||
old: {}, | ||
new: {} | ||
}, | ||
{ ... } | ||
] | ||
} | ||
``` |
20
test.js
@@ -70,1 +70,21 @@ var tools = require('./index'); | ||
console.log(synced); | ||
var equalityA = { | ||
foo: 'bar', | ||
baz: [1,2,3], | ||
qux: { | ||
quux: 'quuux' | ||
} | ||
} | ||
var equalityB = { | ||
foo: 'bar', | ||
baz: [1,2,3], | ||
qux: { | ||
quux: 'quuux' | ||
} | ||
} | ||
console.log('\n>>> equal\n'); | ||
console.log(tools.equal(equalityA,equalityB)); |
213
11145
176