backbone-pouch
Advanced tools
Comparing version 1.0.1 to 1.3.0
@@ -1,2 +0,2 @@ | ||
/*! backbone-pouch - v1.0.0 - 2013-05-02 | ||
/*! backbone-pouch - v1.3.0 - 2013-10-18 | ||
* http://jo.github.io/backbone-pouch/ | ||
@@ -29,3 +29,3 @@ * Copyright (c) 2013 Johannes J. Schmidt; Licensed MIT */ | ||
fetch: 'allDocs', | ||
listen: true, | ||
listen: false, | ||
options: { | ||
@@ -36,14 +36,7 @@ post: {}, | ||
remove: {}, | ||
allDocs: { | ||
include_docs: true | ||
}, | ||
query: { | ||
include_docs: true | ||
}, | ||
spatial: { | ||
include_docs: true | ||
}, | ||
allDocs: {}, | ||
query: {}, | ||
spatial: {}, | ||
changes: { | ||
continuous: true, | ||
include_docs: true | ||
continuous: true | ||
} | ||
@@ -53,22 +46,23 @@ } | ||
function applyDefaults(options, defaults) { | ||
options.options = options.options || {}; | ||
defaults.options = defaults.options || {}; | ||
// inspired from https://github.com/Raynos/xtend | ||
function extend() { | ||
var target = {}; | ||
// merge toplevel options | ||
if (typeof options.fetch === 'undefined') { | ||
options.fetch = defaults.fetch; | ||
for (var i = 0; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
if (typeof source !== 'object') { | ||
continue; | ||
} | ||
for (var name in source) { | ||
if (typeof source[name] === 'object' && typeof target[name] === 'object') { | ||
target[name] = extend(target[name] || {}, source[name]); | ||
} else { | ||
target[name] = source[name]; | ||
} | ||
} | ||
} | ||
if (typeof options.listen === 'undefined') { | ||
options.listen = defaults.listen; | ||
} | ||
if (typeof options.db === 'undefined') { | ||
options.db = defaults.db; | ||
} | ||
// merge PouchDB options | ||
_.each(defaults.options, function(value, key) { | ||
options.options[key] = options.options[key] || {}; | ||
_.extend(options.options[key], value); | ||
}); | ||
return target; | ||
} | ||
@@ -79,9 +73,14 @@ | ||
defaults = defaults || {}; | ||
applyDefaults(defaults, BackbonePouch.defaults); | ||
defaults = extend(BackbonePouch.defaults, defaults); | ||
var adapter = function(method, model, options) { | ||
options = options || {}; | ||
applyDefaults(options, model.pouch || {}); | ||
applyDefaults(options, defaults); | ||
options = extend(defaults, model && model.pouch || {}, options); | ||
// This is to get the options (especially options.db) | ||
// by calling model.sync() without arguments. | ||
if (typeof method !== 'string') { | ||
return options; | ||
} | ||
// ensure we have a pouch db adapter | ||
@@ -106,13 +105,2 @@ if (!options.db) { | ||
if (method === 'read') { | ||
if (response.rows) { | ||
response = _.map(response.rows, function(row) { | ||
// use `doc` value if present | ||
return row.doc || | ||
// or use `value` property otherwise | ||
// and inject id | ||
_.extend({ | ||
_id: row.id | ||
}, row.value); | ||
}); | ||
} | ||
if (options.listen) { | ||
@@ -180,2 +168,82 @@ // TODO: | ||
}; | ||
BackbonePouch.attachments = function(defaults) { | ||
defaults = defaults || {}; | ||
function getPouch(model) { | ||
if (model.pouch && model.pouch.db) { | ||
return model.pouch.db; | ||
} | ||
if (model.collection && model.collection.pouch && model.collection.pouch.db) { | ||
return model.collection.pouch.db; | ||
} | ||
if (defaults.db) { | ||
return defaults.db; | ||
} | ||
var options = model.sync(); | ||
if (options.db) { | ||
return options.db; | ||
} | ||
// TODO: ask sync adapter | ||
throw new Error('A "db" property must be specified'); | ||
} | ||
return { | ||
attachments: function(filter) { | ||
var atts = this.get('_attachments') || {}; | ||
if (filter) { | ||
return _.filter(_.keys(atts), function(key) { | ||
if (typeof filter === 'function') { | ||
return filter(key, atts[key]); | ||
} | ||
return atts[key].content_type.match(filter); | ||
}); | ||
} | ||
return _.keys(atts); | ||
}, | ||
attachment: function(name, done) { | ||
// TODO: first look at the _attachments stub, | ||
// maybe there the data is already there | ||
var db = getPouch(this); | ||
return db.getAttachment(this.id, name, done); | ||
}, | ||
attach: function(blob, name, type, done) { | ||
if (typeof name === 'function') { | ||
done = name; | ||
name = undefined; | ||
type = undefined; | ||
} | ||
if (typeof type === 'function') { | ||
done = type; | ||
type = undefined; | ||
} | ||
name = name || blob.filename; | ||
type = type || blob.type; | ||
// If I do not already have an id, give me one | ||
if (!this.id) { | ||
this.set({ _id: Math.uuid() }, { silent: true }); | ||
} | ||
var db = getPouch(this); | ||
var that = this; | ||
return db.putAttachment(this.id, name, this.get('_rev'), blob, type, function(err, response) { | ||
if (!err && response.rev) { | ||
var atts = that.get('_attachments') || {}; | ||
atts[name] = { | ||
content_type: type, | ||
stub: true | ||
}; | ||
that.set({ _rev: response.rev, _attachments: atts }, { silent: true }); | ||
} | ||
done(err, response); | ||
}); | ||
} | ||
}; | ||
}; | ||
}(this)); |
@@ -1,4 +0,4 @@ | ||
/*! backbone-pouch - v1.0.0 - 2013-05-02 | ||
/*! backbone-pouch - v1.3.0 - 2013-10-18 | ||
* http://jo.github.io/backbone-pouch/ | ||
* Copyright (c) 2013 Johannes J. Schmidt; Licensed MIT */ | ||
(function(e){"use strict";function t(e,t){e.options=e.options||{},t.options=t.options||{},typeof e.fetch=="undefined"&&(e.fetch=t.fetch),typeof e.listen=="undefined"&&(e.listen=t.listen),typeof e.db=="undefined"&&(e.db=t.db),n.each(t.options,function(t,o){e.options[o]=e.options[o]||{},n.extend(e.options[o],t)})}var o;o="object"==typeof exports?exports:e.BackbonePouch={};var n=e._;n||"function"!=typeof require||(n=require("underscore"));var i={create:"post",update:"put",patch:"put","delete":"remove"};o.defaults={fetch:"allDocs",listen:!0,options:{post:{},put:{},get:{},remove:{},allDocs:{include_docs:!0},query:{include_docs:!0},spatial:{include_docs:!0},changes:{continuous:!0,include_docs:!0}}},o.sync=function(e){e=e||{},t(e,o.defaults);var s=function(o,s,c){function r(e,t){return e?c.error&&c.error(e):(("create"===o||"update"===o||"patch"===o)&&(t={_id:t.id,_rev:t.rev}),"delete"===o&&(t={}),"read"===o&&(t.rows&&(t=n.map(t.rows,function(e){return e.doc||n.extend({_id:e.id},e.value)})),c.listen&&c.db.info(function(e,t){c.db.changes(n.extend({},c.options.changes,{since:t.update_seq,onChange:function(e){var t=s.get(e.id);e.deleted?t&&t.destroy():t?t.set(e.doc):s.add(e.doc),typeof c.options.changes.onChange=="function"&&c.options.changes.onChange(e)}}))})),c.success&&c.success(t))}if(c=c||{},t(c,s.pouch||{}),t(c,e),!c.db)throw Error('A "db" property must be specified');if(s.trigger("request",s,c.db,c),"read"===o){if(s.id)return c.db.get(s.id,c.options.get,r);if(c.fetch==="query"||c.fetch==="spatial"){if(!c.options[c.fetch].fun)throw Error('A "'+c.fetch+'.fun" object must be specified');return c.db[c.fetch](c.options[c.fetch].fun,c.options[c.fetch],r)}c.db[c.fetch](c.options[c.fetch],r)}else c.db[i[o]](s.toJSON(),c.options[i[o]],r);return c};return s.defaults=e,s}})(this); | ||
(function(t){"use strict";function e(){for(var t={},n=0;arguments.length>n;n++){var o=arguments[n];if("object"==typeof o)for(var r in o)t[r]="object"==typeof o[r]&&"object"==typeof t[r]?e(t[r]||{},o[r]):o[r]}return t}var n;n="object"==typeof exports?exports:t.BackbonePouch={};var o=t._;o||"function"!=typeof require||(o=require("underscore"));var r={create:"post",update:"put",patch:"put","delete":"remove"};n.defaults={fetch:"allDocs",listen:!1,options:{post:{},put:{},get:{},remove:{},allDocs:{},query:{},spatial:{},changes:{continuous:!0}}},n.sync=function(t){t=t||{},t=e(n.defaults,t);var i=function(n,i,c){function s(t,e){return t?c.error&&c.error(t):(("create"===n||"update"===n||"patch"===n)&&(e={_id:e.id,_rev:e.rev}),"delete"===n&&(e={}),"read"===n&&c.listen&&c.db.info(function(t,e){c.db.changes(o.extend({},c.options.changes,{since:e.update_seq,onChange:function(t){var e=i.get(t.id);t.deleted?e&&e.destroy():e?e.set(t.doc):i.add(t.doc),"function"==typeof c.options.changes.onChange&&c.options.changes.onChange(t)}}))}),c.success&&c.success(e))}if(c=c||{},c=e(t,i&&i.pouch||{},c),"string"!=typeof n)return c;if(!c.db)throw Error('A "db" property must be specified');if(i.trigger("request",i,c.db,c),"read"===n){if(i.id)return c.db.get(i.id,c.options.get,s);if("query"===c.fetch||"spatial"===c.fetch){if(!c.options[c.fetch].fun)throw Error('A "'+c.fetch+'.fun" object must be specified');return c.db[c.fetch](c.options[c.fetch].fun,c.options[c.fetch],s)}c.db[c.fetch](c.options[c.fetch],s)}else c.db[r[n]](i.toJSON(),c.options[r[n]],s);return c};return i.defaults=t,i},n.attachments=function(t){function e(e){if(e.pouch&&e.pouch.db)return e.pouch.db;if(e.collection&&e.collection.pouch&&e.collection.pouch.db)return e.collection.pouch.db;if(t.db)return t.db;var n=e.sync();if(n.db)return n.db;throw Error('A "db" property must be specified')}return t=t||{},{attachments:function(t){var e=this.get("_attachments")||{};return t?o.filter(o.keys(e),function(n){return"function"==typeof t?t(n,e[n]):e[n].content_type.match(t)}):o.keys(e)},attachment:function(t,n){var o=e(this);return o.getAttachment(this.id,t,n)},attach:function(t,n,o,r){"function"==typeof n&&(r=n,n=void 0,o=void 0),"function"==typeof o&&(r=o,o=void 0),n=n||t.filename,o=o||t.type,this.id||this.set({_id:Math.uuid()},{silent:!0});var i=e(this),c=this;return i.putAttachment(this.id,n,this.get("_rev"),t,o,function(t,e){if(!t&&e.rev){var i=c.get("_attachments")||{};i[n]={content_type:o,stub:!0},c.set({_rev:e.rev,_attachments:i},{silent:!0})}r(t,e)})}}}})(this); |
@@ -1,4 +0,4 @@ | ||
/*! backbone-pouch - v1.0.0 - 2013-05-02 | ||
/*! backbone-pouch - v1.3.0 - 2013-10-18 | ||
* http://jo.github.io/backbone-pouch/ | ||
* Copyright (c) 2013 Johannes J. Schmidt; Licensed MIT */ | ||
(function(e){"use strict";function t(e,t){e.options=e.options||{},t.options=t.options||{},typeof e.fetch=="undefined"&&(e.fetch=t.fetch),typeof e.listen=="undefined"&&(e.listen=t.listen),typeof e.db=="undefined"&&(e.db=t.db),n.each(t.options,function(t,o){e.options[o]=e.options[o]||{},n.extend(e.options[o],t)})}var o;o="object"==typeof exports?exports:e.BackbonePouch={};var n=e._;n||"function"!=typeof require||(n=require("underscore"));var i={create:"post",update:"put",patch:"put","delete":"remove"};o.defaults={fetch:"allDocs",listen:!0,options:{post:{},put:{},get:{},remove:{},allDocs:{include_docs:!0},query:{include_docs:!0},spatial:{include_docs:!0},changes:{continuous:!0,include_docs:!0}}},o.sync=function(e){e=e||{},t(e,o.defaults);var s=function(o,s,c){function r(e,t){return e?c.error&&c.error(e):(("create"===o||"update"===o||"patch"===o)&&(t={_id:t.id,_rev:t.rev}),"delete"===o&&(t={}),"read"===o&&(t.rows&&(t=n.map(t.rows,function(e){return e.doc||n.extend({_id:e.id},e.value)})),c.listen&&c.db.info(function(e,t){c.db.changes(n.extend({},c.options.changes,{since:t.update_seq,onChange:function(e){var t=s.get(e.id);e.deleted?t&&t.destroy():t?t.set(e.doc):s.add(e.doc),typeof c.options.changes.onChange=="function"&&c.options.changes.onChange(e)}}))})),c.success&&c.success(t))}if(c=c||{},t(c,s.pouch||{}),t(c,e),!c.db)throw Error('A "db" property must be specified');if(s.trigger("request",s,c.db,c),"read"===o){if(s.id)return c.db.get(s.id,c.options.get,r);if(c.fetch==="query"||c.fetch==="spatial"){if(!c.options[c.fetch].fun)throw Error('A "'+c.fetch+'.fun" object must be specified');return c.db[c.fetch](c.options[c.fetch].fun,c.options[c.fetch],r)}c.db[c.fetch](c.options[c.fetch],r)}else c.db[i[o]](s.toJSON(),c.options[i[o]],r);return c};return s.defaults=e,s}})(this); | ||
(function(t){"use strict";function e(){for(var t={},n=0;arguments.length>n;n++){var o=arguments[n];if("object"==typeof o)for(var r in o)t[r]="object"==typeof o[r]&&"object"==typeof t[r]?e(t[r]||{},o[r]):o[r]}return t}var n;n="object"==typeof exports?exports:t.BackbonePouch={};var o=t._;o||"function"!=typeof require||(o=require("underscore"));var r={create:"post",update:"put",patch:"put","delete":"remove"};n.defaults={fetch:"allDocs",listen:!1,options:{post:{},put:{},get:{},remove:{},allDocs:{},query:{},spatial:{},changes:{continuous:!0}}},n.sync=function(t){t=t||{},t=e(n.defaults,t);var i=function(n,i,c){function s(t,e){return t?c.error&&c.error(t):(("create"===n||"update"===n||"patch"===n)&&(e={_id:e.id,_rev:e.rev}),"delete"===n&&(e={}),"read"===n&&c.listen&&c.db.info(function(t,e){c.db.changes(o.extend({},c.options.changes,{since:e.update_seq,onChange:function(t){var e=i.get(t.id);t.deleted?e&&e.destroy():e?e.set(t.doc):i.add(t.doc),"function"==typeof c.options.changes.onChange&&c.options.changes.onChange(t)}}))}),c.success&&c.success(e))}if(c=c||{},c=e(t,i&&i.pouch||{},c),"string"!=typeof n)return c;if(!c.db)throw Error('A "db" property must be specified');if(i.trigger("request",i,c.db,c),"read"===n){if(i.id)return c.db.get(i.id,c.options.get,s);if("query"===c.fetch||"spatial"===c.fetch){if(!c.options[c.fetch].fun)throw Error('A "'+c.fetch+'.fun" object must be specified');return c.db[c.fetch](c.options[c.fetch].fun,c.options[c.fetch],s)}c.db[c.fetch](c.options[c.fetch],s)}else c.db[r[n]](i.toJSON(),c.options[r[n]],s);return c};return i.defaults=t,i},n.attachments=function(t){function e(e){if(e.pouch&&e.pouch.db)return e.pouch.db;if(e.collection&&e.collection.pouch&&e.collection.pouch.db)return e.collection.pouch.db;if(t.db)return t.db;var n=e.sync();if(n.db)return n.db;throw Error('A "db" property must be specified')}return t=t||{},{attachments:function(t){var e=this.get("_attachments")||{};return t?o.filter(o.keys(e),function(n){return"function"==typeof t?t(n,e[n]):e[n].content_type.match(t)}):o.keys(e)},attachment:function(t,n){var o=e(this);return o.getAttachment(this.id,t,n)},attach:function(t,n,o,r){"function"==typeof n&&(r=n,n=void 0,o=void 0),"function"==typeof o&&(r=o,o=void 0),n=n||t.filename,o=o||t.type,this.id||this.set({_id:Math.uuid()},{silent:!0});var i=e(this),c=this;return i.putAttachment(this.id,n,this.get("_rev"),t,o,function(t,e){if(!t&&e.rev){var i=c.get("_attachments")||{};i[n]={content_type:o,stub:!0},c.set({_rev:e.rev,_attachments:i},{silent:!0})}r(t,e)})}}}})(this); |
@@ -17,2 +17,3 @@ // An example Backbone application contributed by | ||
db: Pouch(dbname), | ||
listen: true, | ||
fetch: 'query' | ||
@@ -72,2 +73,3 @@ }); | ||
query: { | ||
include_docs: true, | ||
fun: { | ||
@@ -82,2 +84,3 @@ map: function(doc) { | ||
changes: { | ||
include_docs: true, | ||
filter: function(doc) { | ||
@@ -90,2 +93,7 @@ return doc._deleted || doc.type === 'todo'; | ||
// parse view result, use doc property injected via `include_docs` | ||
parse: function(result) { | ||
return _.pluck(result.rows, 'doc'); | ||
}, | ||
// Filter down the list of all todo items that are finished. | ||
@@ -303,2 +311,3 @@ done: function() { | ||
query: { | ||
include_docs: true, | ||
fun: { | ||
@@ -313,2 +322,3 @@ map: function(doc) { | ||
changes: { | ||
include_docs: true, | ||
filter: function(doc) { | ||
@@ -321,2 +331,7 @@ return doc._deleted || doc.type === 'replication'; | ||
// parse view result, use doc property injected via `include_docs` | ||
parse: function(result) { | ||
return _.pluck(result.rows, 'doc'); | ||
}, | ||
// Replications are sorted by url. | ||
@@ -323,0 +338,0 @@ comparator: function(replication) { |
@@ -1,4 +0,4 @@ | ||
/*! backbone-pouch - v1.0.0 - 2013-05-02 | ||
/*! backbone-pouch - v1.3.0 - 2013-10-18 | ||
* http://jo.github.io/backbone-pouch/ | ||
* Copyright (c) 2013 Johannes J. Schmidt; Licensed MIT */ | ||
(function(e){"use strict";function t(e,t){e.options=e.options||{},t.options=t.options||{},typeof e.fetch=="undefined"&&(e.fetch=t.fetch),typeof e.listen=="undefined"&&(e.listen=t.listen),typeof e.db=="undefined"&&(e.db=t.db),n.each(t.options,function(t,o){e.options[o]=e.options[o]||{},n.extend(e.options[o],t)})}var o;o="object"==typeof exports?exports:e.BackbonePouch={};var n=e._;n||"function"!=typeof require||(n=require("underscore"));var i={create:"post",update:"put",patch:"put","delete":"remove"};o.defaults={fetch:"allDocs",listen:!0,options:{post:{},put:{},get:{},remove:{},allDocs:{include_docs:!0},query:{include_docs:!0},spatial:{include_docs:!0},changes:{continuous:!0,include_docs:!0}}},o.sync=function(e){e=e||{},t(e,o.defaults);var s=function(o,s,c){function r(e,t){return e?c.error&&c.error(e):(("create"===o||"update"===o||"patch"===o)&&(t={_id:t.id,_rev:t.rev}),"delete"===o&&(t={}),"read"===o&&(t.rows&&(t=n.map(t.rows,function(e){return e.doc||n.extend({_id:e.id},e.value)})),c.listen&&c.db.info(function(e,t){c.db.changes(n.extend({},c.options.changes,{since:t.update_seq,onChange:function(e){var t=s.get(e.id);e.deleted?t&&t.destroy():t?t.set(e.doc):s.add(e.doc),typeof c.options.changes.onChange=="function"&&c.options.changes.onChange(e)}}))})),c.success&&c.success(t))}if(c=c||{},t(c,s.pouch||{}),t(c,e),!c.db)throw Error('A "db" property must be specified');if(s.trigger("request",s,c.db,c),"read"===o){if(s.id)return c.db.get(s.id,c.options.get,r);if(c.fetch==="query"||c.fetch==="spatial"){if(!c.options[c.fetch].fun)throw Error('A "'+c.fetch+'.fun" object must be specified');return c.db[c.fetch](c.options[c.fetch].fun,c.options[c.fetch],r)}c.db[c.fetch](c.options[c.fetch],r)}else c.db[i[o]](s.toJSON(),c.options[i[o]],r);return c};return s.defaults=e,s}})(this); | ||
(function(t){"use strict";function e(){for(var t={},n=0;arguments.length>n;n++){var o=arguments[n];if("object"==typeof o)for(var r in o)t[r]="object"==typeof o[r]&&"object"==typeof t[r]?e(t[r]||{},o[r]):o[r]}return t}var n;n="object"==typeof exports?exports:t.BackbonePouch={};var o=t._;o||"function"!=typeof require||(o=require("underscore"));var r={create:"post",update:"put",patch:"put","delete":"remove"};n.defaults={fetch:"allDocs",listen:!1,options:{post:{},put:{},get:{},remove:{},allDocs:{},query:{},spatial:{},changes:{continuous:!0}}},n.sync=function(t){t=t||{},t=e(n.defaults,t);var i=function(n,i,c){function s(t,e){return t?c.error&&c.error(t):(("create"===n||"update"===n||"patch"===n)&&(e={_id:e.id,_rev:e.rev}),"delete"===n&&(e={}),"read"===n&&c.listen&&c.db.info(function(t,e){c.db.changes(o.extend({},c.options.changes,{since:e.update_seq,onChange:function(t){var e=i.get(t.id);t.deleted?e&&e.destroy():e?e.set(t.doc):i.add(t.doc),"function"==typeof c.options.changes.onChange&&c.options.changes.onChange(t)}}))}),c.success&&c.success(e))}if(c=c||{},c=e(t,i&&i.pouch||{},c),"string"!=typeof n)return c;if(!c.db)throw Error('A "db" property must be specified');if(i.trigger("request",i,c.db,c),"read"===n){if(i.id)return c.db.get(i.id,c.options.get,s);if("query"===c.fetch||"spatial"===c.fetch){if(!c.options[c.fetch].fun)throw Error('A "'+c.fetch+'.fun" object must be specified');return c.db[c.fetch](c.options[c.fetch].fun,c.options[c.fetch],s)}c.db[c.fetch](c.options[c.fetch],s)}else c.db[r[n]](i.toJSON(),c.options[r[n]],s);return c};return i.defaults=t,i},n.attachments=function(t){function e(e){if(e.pouch&&e.pouch.db)return e.pouch.db;if(e.collection&&e.collection.pouch&&e.collection.pouch.db)return e.collection.pouch.db;if(t.db)return t.db;var n=e.sync();if(n.db)return n.db;throw Error('A "db" property must be specified')}return t=t||{},{attachments:function(t){var e=this.get("_attachments")||{};return t?o.filter(o.keys(e),function(n){return"function"==typeof t?t(n,e[n]):e[n].content_type.match(t)}):o.keys(e)},attachment:function(t,n){var o=e(this);return o.getAttachment(this.id,t,n)},attach:function(t,n,o,r){"function"==typeof n&&(r=n,n=void 0,o=void 0),"function"==typeof o&&(r=o,o=void 0),n=n||t.filename,o=o||t.type,this.id||this.set({_id:Math.uuid()},{silent:!0});var i=e(this),c=this;return i.putAttachment(this.id,n,this.get("_rev"),t,o,function(t,e){if(!t&&e.rev){var i=c.get("_attachments")||{};i[n]={content_type:o,stub:!0},c.set({_rev:e.rev,_attachments:i},{silent:!0})}r(t,e)})}}}})(this); |
@@ -70,5 +70,7 @@ // An example Backbone application contributed by | ||
pouch: { | ||
listen: true, | ||
fetch: 'query', | ||
options: { | ||
query: { | ||
include_docs: true, | ||
fun: { | ||
@@ -79,2 +81,5 @@ map: function(doc) { | ||
} | ||
}, | ||
changes: { | ||
include_docs: true | ||
} | ||
@@ -84,2 +89,7 @@ } | ||
// parse view result, use doc property injected via `include_docs` | ||
parse: function(result) { | ||
return _.pluck(result.rows, 'doc'); | ||
}, | ||
// Filter down the list of all todo items that are finished. | ||
@@ -86,0 +96,0 @@ done: function() { |
@@ -34,3 +34,3 @@ /* | ||
fetch: 'allDocs', | ||
listen: true, | ||
listen: false, | ||
options: { | ||
@@ -41,14 +41,7 @@ post: {}, | ||
remove: {}, | ||
allDocs: { | ||
include_docs: true | ||
}, | ||
query: { | ||
include_docs: true | ||
}, | ||
spatial: { | ||
include_docs: true | ||
}, | ||
allDocs: {}, | ||
query: {}, | ||
spatial: {}, | ||
changes: { | ||
continuous: true, | ||
include_docs: true | ||
continuous: true | ||
} | ||
@@ -58,22 +51,23 @@ } | ||
function applyDefaults(options, defaults) { | ||
options.options = options.options || {}; | ||
defaults.options = defaults.options || {}; | ||
// inspired from https://github.com/Raynos/xtend | ||
function extend() { | ||
var target = {}; | ||
// merge toplevel options | ||
if (typeof options.fetch === 'undefined') { | ||
options.fetch = defaults.fetch; | ||
for (var i = 0; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
if (typeof source !== 'object') { | ||
continue; | ||
} | ||
for (var name in source) { | ||
if (typeof source[name] === 'object' && typeof target[name] === 'object') { | ||
target[name] = extend(target[name] || {}, source[name]); | ||
} else { | ||
target[name] = source[name]; | ||
} | ||
} | ||
} | ||
if (typeof options.listen === 'undefined') { | ||
options.listen = defaults.listen; | ||
} | ||
if (typeof options.db === 'undefined') { | ||
options.db = defaults.db; | ||
} | ||
// merge PouchDB options | ||
_.each(defaults.options, function(value, key) { | ||
options.options[key] = options.options[key] || {}; | ||
_.extend(options.options[key], value); | ||
}); | ||
return target; | ||
} | ||
@@ -84,9 +78,14 @@ | ||
defaults = defaults || {}; | ||
applyDefaults(defaults, BackbonePouch.defaults); | ||
defaults = extend(BackbonePouch.defaults, defaults); | ||
var adapter = function(method, model, options) { | ||
options = options || {}; | ||
applyDefaults(options, model.pouch || {}); | ||
applyDefaults(options, defaults); | ||
options = extend(defaults, model && model.pouch || {}, options); | ||
// This is to get the options (especially options.db) | ||
// by calling model.sync() without arguments. | ||
if (typeof method !== 'string') { | ||
return options; | ||
} | ||
// ensure we have a pouch db adapter | ||
@@ -111,13 +110,2 @@ if (!options.db) { | ||
if (method === 'read') { | ||
if (response.rows) { | ||
response = _.map(response.rows, function(row) { | ||
// use `doc` value if present | ||
return row.doc || | ||
// or use `value` property otherwise | ||
// and inject id | ||
_.extend({ | ||
_id: row.id | ||
}, row.value); | ||
}); | ||
} | ||
if (options.listen) { | ||
@@ -185,2 +173,82 @@ // TODO: | ||
}; | ||
BackbonePouch.attachments = function(defaults) { | ||
defaults = defaults || {}; | ||
function getPouch(model) { | ||
if (model.pouch && model.pouch.db) { | ||
return model.pouch.db; | ||
} | ||
if (model.collection && model.collection.pouch && model.collection.pouch.db) { | ||
return model.collection.pouch.db; | ||
} | ||
if (defaults.db) { | ||
return defaults.db; | ||
} | ||
var options = model.sync(); | ||
if (options.db) { | ||
return options.db; | ||
} | ||
// TODO: ask sync adapter | ||
throw new Error('A "db" property must be specified'); | ||
} | ||
return { | ||
attachments: function(filter) { | ||
var atts = this.get('_attachments') || {}; | ||
if (filter) { | ||
return _.filter(_.keys(atts), function(key) { | ||
if (typeof filter === 'function') { | ||
return filter(key, atts[key]); | ||
} | ||
return atts[key].content_type.match(filter); | ||
}); | ||
} | ||
return _.keys(atts); | ||
}, | ||
attachment: function(name, done) { | ||
// TODO: first look at the _attachments stub, | ||
// maybe there the data is already there | ||
var db = getPouch(this); | ||
return db.getAttachment(this.id, name, done); | ||
}, | ||
attach: function(blob, name, type, done) { | ||
if (typeof name === 'function') { | ||
done = name; | ||
name = undefined; | ||
type = undefined; | ||
} | ||
if (typeof type === 'function') { | ||
done = type; | ||
type = undefined; | ||
} | ||
name = name || blob.filename; | ||
type = type || blob.type; | ||
// If I do not already have an id, give me one | ||
if (!this.id) { | ||
this.set({ _id: Math.uuid() }, { silent: true }); | ||
} | ||
var db = getPouch(this); | ||
var that = this; | ||
return db.putAttachment(this.id, name, this.get('_rev'), blob, type, function(err, response) { | ||
if (!err && response.rev) { | ||
var atts = that.get('_attachments') || {}; | ||
atts[name] = { | ||
content_type: type, | ||
stub: true | ||
}; | ||
that.set({ _rev: response.rev, _attachments: atts }, { silent: true }); | ||
} | ||
done(err, response); | ||
}); | ||
} | ||
}; | ||
}; | ||
}(this)); |
{ | ||
"name": "backbone-pouch", | ||
"description": "Backbone PouchDB Sync Adapter", | ||
"version": "1.0.1", | ||
"version": "1.3.0", | ||
"homepage": "http://jo.github.io/backbone-pouch/", | ||
@@ -6,0 +6,0 @@ "author": { |
187
README.md
@@ -60,2 +60,25 @@ # backbone-pouch [![Build Status](https://secure.travis-ci.org/jo/backbone-pouch.png?branch=master)](http://travis-ci.org/jo/backbone-pouch) | ||
### `BackbonePouch.attachments()` | ||
You can mixin attachment support into a single model: | ||
```javascript | ||
var MyModel = Backbone.Model.extend(BackbonePouch.attachments()); | ||
``` | ||
Or you may want to mixin attachment support globally: | ||
```javascript | ||
_.extend(Backbone.Model.prototype, BackbonePouch.attachments()); | ||
``` | ||
Note that you have to call the attachments function - don't forget the braces. | ||
You can also pass the PouchDB adapter to `BackbonePouch.attachments`: | ||
```javascript | ||
_.extend(Backbone.Model.prototype, BackbonePouch.attachments({ | ||
db: PouchDB('mydb') | ||
})); | ||
``` | ||
### `idAttribute` | ||
@@ -76,3 +99,3 @@ You should adjust the `idAttribute`, because CouchDB (and therefore PouchDB) | ||
sync: BackbonePouch.sync({ | ||
db: Pouch('mydb') | ||
db: PouchDB('mydb') | ||
}) | ||
@@ -91,3 +114,3 @@ }); | ||
sync: BackbonePouch.sync({ | ||
db: Pouch('mydb') | ||
db: PouchDB('mydb') | ||
}) | ||
@@ -98,6 +121,7 @@ }); | ||
sync: BackbonePouch.sync({ | ||
db: Pouch('mydb'), | ||
fetchMethod: 'query', | ||
db: PouchDB('mydb'), | ||
fetch: 'query', | ||
options: { | ||
query: { | ||
include_docs: true, | ||
fun: { | ||
@@ -113,2 +137,3 @@ map: function(doc) { | ||
changes: { | ||
include_docs: true, | ||
filter: function(doc) { | ||
@@ -119,3 +144,6 @@ return doc._deleted || doc.type === 'post'; | ||
} | ||
}) | ||
}), | ||
parse: function(result) { | ||
return _.pluck(result.rows, 'doc'); | ||
} | ||
}); | ||
@@ -132,6 +160,9 @@ ``` | ||
Backbone.sync = BackbonePouch.sync({ | ||
db: Pouch('mydb'), | ||
fetchMethod: 'query', | ||
query: { | ||
limit: 10 | ||
db: PouchDB('mydb'), | ||
fetch: 'query', | ||
options: { | ||
query: { | ||
include_docs: true, | ||
limit: 10 | ||
} | ||
} | ||
@@ -150,16 +181,23 @@ }); | ||
pouch: { | ||
query: { | ||
fun: { | ||
map: function(doc) { | ||
if (doc.type === 'author') { | ||
emit(doc.name, null) | ||
options: { | ||
query: { | ||
include_docs: true, | ||
fun: { | ||
map: function(doc) { | ||
if (doc.type === 'author') { | ||
emit(doc.name, null) | ||
} | ||
} | ||
} | ||
}, | ||
changes: { | ||
include_docs: true, | ||
filter: function(doc) { | ||
return doc._deleted || doc.type === 'author'; | ||
} | ||
} | ||
}, | ||
changes: { | ||
filter: function(doc) { | ||
return doc._deleted || doc.type === 'author'; | ||
} | ||
} | ||
}, | ||
parse: function(result) { | ||
return _.pluck(result.rows, 'doc'); | ||
} | ||
@@ -171,16 +209,23 @@ }); | ||
pouch: { | ||
query: { | ||
fun: { | ||
map: function(doc) { | ||
if (doc.type === 'post') { | ||
emit(doc.date, null) | ||
options: { | ||
query: { | ||
include_docs: true, | ||
fun: { | ||
map: function(doc) { | ||
if (doc.type === 'post') { | ||
emit(doc.date, null) | ||
} | ||
} | ||
} | ||
}, | ||
changes: { | ||
include_docs: true, | ||
filter: function(doc) { | ||
return doc._deleted || doc.type === 'post'; | ||
} | ||
} | ||
}, | ||
changes: { | ||
filter: function(doc) { | ||
return doc._deleted || doc.type === 'post'; | ||
} | ||
} | ||
}, | ||
parse: function(result) { | ||
return _.pluck(result.rows, 'doc'); | ||
} | ||
@@ -190,3 +235,47 @@ }); | ||
### Attachments | ||
```javascript | ||
Backbone.sync = BackbonePouch.sync({ | ||
db: PouchDB('mydb') | ||
}); | ||
Backbone.Model.prototype.idAttribute = '_id'; | ||
var MyModel = Backbone.Model.extend(BackbonePouch.attachments()); | ||
var model = new MyModel(); | ||
model.attach(blob); // store file | ||
model.attachments(); // list files | ||
model.attachment(name); // retrieve file | ||
``` | ||
backbone-pouch helps you with binary attachments by providing convenient methods | ||
for retrieving, storing and listing files. | ||
#### `attach(blob, name, type, callback)` | ||
Store an attachment. | ||
`blob` must be a `Blob` in the browser or a `Buffer` in node. | ||
You can omit `name` if the blob has a `filename` property. | ||
You can omit `type` if the blob has a `type` property. | ||
The callback is invoked with `err` and `result` callbacks. | ||
After the file is stored, the models `_rev` property is updated. | ||
If the model wasn't saved before, an `id` will be assigned and it will be created. | ||
#### `attachments(filter)` | ||
List attachment names. | ||
The optional `filter` argument can be used to list only attachments of a certain type. | ||
If the `filter` argument is a string or a RegExp, | ||
it will be matched against the `content_type` of each attachment | ||
and only the matching attachment names will be returned. | ||
If `filter` is a function, it will be called with the attachments name and its stub. | ||
#### `attachment(name, callback)` | ||
Retrieve an attachment blob by name. | ||
`callback` is called with `error` and `blob` arguments. | ||
In the browser a `Blob` object is returned, a `Buffer` in node. | ||
<p id=configuration></p> | ||
@@ -207,7 +296,7 @@ ## Configuration | ||
#### `db`: Pouch Adapter | ||
Setup a database. This option is mendatory. Must be a Pouch adapter: | ||
#### `db`: PouchDB Adapter | ||
Setup a database. This option is mendatory. Must be a PouchDB adapter: | ||
```javascript | ||
Pouch('dbname') | ||
PouchDB('dbname') | ||
``` | ||
@@ -267,5 +356,14 @@ | ||
##### `allDocs`: Retrieve Collection | ||
Options for fetching all documents. | ||
##### Fetch Collections | ||
When fetching collections from views, one might want to parse the result, eg: | ||
```javascript | ||
parse: function(result) { | ||
return _.pluck(result.rows, 'doc'); | ||
} | ||
``` | ||
###### `allDocs`: Retrieve Collection | ||
Options for fetching all documents. This is a built in view which outputs all documents by id. | ||
* `attachments`: Include attachment data. | ||
@@ -283,3 +381,3 @@ * `conflicts`: If specified conflicting leaf revisions will be attached in _conflicts array. | ||
##### `query`: Retrieve Collection via Map Reduce | ||
###### `query`: Retrieve Collection via Map Reduce | ||
Query options for Map Reduce queries. | ||
@@ -301,3 +399,3 @@ | ||
##### `spatial`: Retrieve Collection via Spatial Index | ||
###### `spatial`: Retrieve Collection via Spatial Index | ||
Options for Spatial query. The spatial query has not been tested. | ||
@@ -347,6 +445,13 @@ You have to use a PouchDB build with included [Spatial](https://github.com/daleharvey/pouchdb/blob/master/src/plugins/pouchdb.spatial.js) plugin. | ||
## Generating the Documentation | ||
_The files in the "doc" subdirectory are generated via Grunt, too. | ||
Edit this README.md and template.jst and run `grunt doc` to generate the documentation._ | ||
To update the Github page, change to the `gh-pages` branch and merge the `doc` subtree: | ||
git pull -s subtree origin master | ||
You will need `git-subtree`, of course. | ||
## Versioning | ||
@@ -359,8 +464,12 @@ backbone-pouch follows [semver-ftw](http://semver-ftw.org/). | ||
## Release History | ||
* `1.3.0`: Do not parse view results, leave that up to the user | ||
* `1.2.1`: Improve option inheritance | ||
* `1.2.0`: Change defaults: do not listen and include_docs | ||
* `1.1.1`: Adapt PouchDB attachment API change with seperate docId and attachment name | ||
* `1.1`: Attachment support | ||
* `1.0`: New chained api, Node support, tests. Support listen to changes feed. Use Grunt. | ||
* `prior 1.0`: Experimental version with example TODO apps | ||
* `1.0.0`: New chained api, Node support, tests. Support listen to changes feed. Use Grunt. | ||
* `before 1.0`: Experimental version with example TODO apps | ||
## License | ||
Copyright (c) 2013 Johannes J. Schmidt | ||
Licensed under the MIT license. |
@@ -40,3 +40,21 @@ 'use strict'; | ||
test.done(); | ||
}, | ||
'deep nested falsy defaults': function(test) { | ||
test.expect(1); | ||
backbone_pouch.defaults.options.query.include_docs = true; | ||
test.equal(backbone_pouch.sync({ options: { query: { include_docs: false } } }).defaults.options.query.include_docs, false, 'should have overwritten falsy value.'); | ||
test.done(); | ||
} | ||
}; | ||
exports.attachments = { | ||
api: function(test) { | ||
test.expect(5); | ||
test.equal(typeof backbone_pouch.attachments, 'function', 'should be a function.'); | ||
test.equal(typeof backbone_pouch.attachments(), 'object', 'should return an object.'); | ||
test.equal(typeof backbone_pouch.attachments().attachments, 'function', 'should be a function.'); | ||
test.equal(typeof backbone_pouch.attachments().attachment, 'function', 'should be a function.'); | ||
test.equal(typeof backbone_pouch.attachments().attach, 'function', 'should be a function.'); | ||
test.done(); | ||
} | ||
}; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
565126
38
3200
460
0