obj_diff is for examining changes between Javascript and JSON objects. Use it to see how data has changed and to decide whether that change is good or bad. Thus obj_diff is useful for security and validation.

obj_diff comes from an internal Iris Couch application used in production for two years. It works in the browser, in CouchDB, and as an NPM module.

Declarative. Data validation is crucial. It must be correct. Validation rules must be easy to express clearly and easy to reason about.

JSON compatible. Diffs and validation rules (containing regexes, functions, etc.) can be encoded and decoded as JSON, without losing functionality. You can store changes and validation policies as plain JSON.

obj_diff excels (and was designed for) Apache CouchDBvalidate_doc_update() functions. Combine atleast() and atmost() to make a sieve and sift out good and bad changes. obj_diff cannot replace all validation code, but it augments it well.

atleast() confirms required changes.

atmost() confirms allowed changes.

First of all, CouchDB changes document metadata under the hood, and you don't want that triggering false alarms. So the first thing is to set obj_diff's defaults for CouchDB mode, which modifies atmost() to allow normal document changes:

null is treated as an empty object, {}. This always works: doc_diff(oldDoc, newDoc)

obj_diff validates changes, not data. What happens if you GET a document and PUT it back unmodified? There will be zero changes in the diff. Any atleast() checks will necessarily fail. Therefore, the best practice is to check the data and then apply certain policies based on that.

Of course, sometimes you want changes in every update, such as timestamp validation:

obj_diff supports regular expressions and function callbacks in its rules. Yet it can be nice to store them as JSON, and to load them later. For example, you could store a few rules in a CouchDB _security object, and do database-specific data validation with an identical validate_doc_update() function.

Both Diff and Rule obejcts behave the same after a JSON round-trip. They have a .toJSON function to handle things, so just JSON.stringify() them and store them in a file or database. Later, JSON.parse() them and pass the object to the constructors.

var obj_diff =require("obj_diff");

functiongood_guy(guy){return guy.good || guy.awesome }

var diffs =

[ obj_diff({some_key:"old_value"},{some_key:"new_value"})

, obj_diff({log:{level:"Anything!"}},{log:{level:"info"}})

, obj_diff({guy:{"good":true}},{guy:"Fawkes"})

];

var rules =

[newobj_diff.Rule("some_key","old_value","new_value")

,newobj_diff.Rule("log.level", obj_diff.ANY,/^(debug|info|error)$/)

,newobj_diff.Rule("guy", good_guy, obj_diff.ANY)

];

console.log("Diffs: "+ JSON.stringify(diffs));

console.log("Rules: "+ JSON.stringify(rules));

Note, functions are stored using their source code, so be careful about global or closed variables they depend on.