New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

angular-data

Package Overview
Dependencies
Maintainers
1
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

angular-data - npm Package Compare versions

Comparing version 0.9.0 to 0.10.0-beta.1

src/datastore/async_methods/loadRelations.js

24

CHANGELOG.md

@@ -1,4 +0,26 @@

##### 0.9.0 - xx May 2014
##### 0.10.0-beta.1 - 28 June 2014
###### Breaking API changes
- #76 - Queries and filtering. See [TRANSITION.md](https://github.com/jmdobry/angular-data/blob/master/TRANSITION.md).
- #82 - Simplify error handling. Reduced size of angular-data.min.js by 4kb.
- #42 - Relations/Associations. `DS.inject` now looks for relations and injects them as well.
###### Backwards compatible API changes
- #17 - Where predicates should be able to handle OR, not just AND
- #23 - Computed Properties
- #78 - Added optional callback to `bindOne` and `bindAll`
- #79 - `ejectAll` should clear matching completed queries
- #83 - Implement `DS.loadRelations(resourceName, instance(Id), relations[, options])`
- #84 - idAttribute of a resource can be a computed property
##### 0.9.1 - 30 May 2014
###### Backwards compatible bug fixes
- #68 - Async methods should honor methods on a resource definition.
- #69 - Failed requests should throw an error, not just return it
- #70 - Make `params` and `params.query` optional
##### 0.9.0 - 22 May 2014
###### Breaking API changes
- #61 - Make custom serializers/deserializers more valuable

@@ -5,0 +27,0 @@ - #59, #62 - Make queryTransform() consistent with the rest of the API

6

dist/angular-data.min.js
/**
* @author Jason Dobry <jason.dobry@gmail.com>
* @file angular-data.min.js
* @version 0.9.0 - Homepage <http://angular-data.codetrain.io/>
* @version 0.10.0-beta.1 - Homepage <http://angular-data.pseudobry.com/>
* @copyright (c) 2014 Jason Dobry <https://github.com/jmdobry/>

@@ -10,3 +10,3 @@ * @license MIT <https://github.com/jmdobry/angular-data/blob/master/LICENSE>

*/
require=function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({QYwGEY:[function(a,b,c){(function(){!function(a){"use strict";function b(){function a(a){"splice"===a[0].type&&"splice"===a[1].type&&(b=!0)}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=!1,c=[0];return Array.observe(c,a),c[1]=1,c.length=0,Object.deliverChangeRecords(a),b}function c(a){return a===Object(a)}function d(a){for(var b=0;s>b&&a.check();)a.report(),b++}function e(a){for(var b in a)return!1;return!0}function f(a){return e(a.added)&&e(a.removed)&&e(a.changed)}function g(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function h(a,b){var c=b||(Array.isArray(a)?[]:{});for(var d in a)c[d]=a[d];return Array.isArray(a)&&(c.length=a.length),c}function i(a,b,c,d){if(this.closed=!1,this.object=a,this.callback=b,this.target=c,this.token=d,this.reporting=!0,n){var e=this;this.boundInternalCallback=function(a){e.internalCallback(a)}}j(this),this.connect(),this.sync(!0)}function j(a){u&&(t.push(a),i._allObserversCount++)}function k(a,b,c,d){i.call(this,a,b,c,d)}function l(a){this.arr=[],this.callback=a,this.isObserved=!0}function m(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];z[g.type]?(g.name in c||(c[g.name]=g.oldValue),"updated"!=g.type&&("new"!=g.type?g.name in d?(delete d[g.name],delete c[g.name]):e[g.name]=!0:g.name in e?delete e[g.name]:d[g.name]=!0)):(console.error("Unknown changeRecord type: "+g.type),console.error(g))}for(var h in d)d[h]=a[h];for(var h in e)e[h]=void 0;var i={};for(var h in c)if(!(h in d||h in e)){var j=a[h];c[h]!==j&&(i[h]=j)}return{added:d,removed:e,changed:i}}var n=b(),o=!1;try{var p=new Function("","return true;");o=p()}catch(q){}var r=(a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},"__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c}),s=1e3;i.prototype={internalCallback:function(a){this.closed||this.reporting&&this.check(a)&&(this.report(),this.testingResults&&(this.testingResults.anyChanged=!0))},close:function(){this.closed||(this.object&&"function"==typeof this.object.unobserved&&this.object.unobserved(),this.disconnect(),this.object=void 0,this.closed=!0)},deliver:function(a){this.closed||(n?(this.testingResults=a,Object.deliverChangeRecords(this.boundInternalCallback),this.testingResults=void 0):d(this))},report:function(){this.reporting&&(this.sync(!1),this.reportArgs.push(this.token),this.invokeCallback(this.reportArgs),this.reportArgs=void 0)},invokeCallback:function(a){try{this.callback.apply(this.target,a)}catch(b){i._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+b)}},reset:function(){this.closed||(n&&(this.reporting=!1,Object.deliverChangeRecords(this.boundInternalCallback),this.reporting=!0),this.sync(!0))}};var t,u=!n||a.forceCollectObservers;i._allObserversCount=0,u&&(t=[]);var v=!1,w="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!v){if(w)return void Object.deliverAllChangeRecords();if(u){v=!0;var a=0,b={};do{a++;var c=t;t=[],b.anyChanged=!1;for(var d=0;d<c.length;d++){var e=c[d];e.closed||(n?e.deliver(b):e.check()&&(b.anyChanged=!0,e.report()),t.push(e))}}while(s>a&&b.anyChanged);i._allObserversCount=t.length,v=!1}}},u&&(a.Platform.clearObservers=function(){t=[]}),k.prototype=r({__proto__:i.prototype,connect:function(){n&&Object.observe(this.object,this.boundInternalCallback)},sync:function(){n||(this.oldObject=h(this.object))},check:function(a){var b,c;if(n){if(!a)return!1;c={},b=m(this.object,a,c)}else c=this.oldObject,b=g(this.object,this.oldObject);return f(b)?!1:(this.reportArgs=[b.added||{},b.removed||{},b.changed||{}],this.reportArgs.push(function(a){return c[a]}),!0)},disconnect:function(){n?this.object&&Object.unobserve(this.object,this.boundInternalCallback):this.oldObject=void 0}});var x=Object.getPrototypeOf({}),y=Object.getPrototypeOf([]);l.prototype={reset:function(){this.isObserved=!this.isObserved},observe:function(a){if(c(a)&&a!==x&&a!==y){var b=this.arr.indexOf(a);b>=0&&this.arr[b+1]===this.isObserved||(0>b&&(b=this.arr.length,this.arr[b]=a,Object.observe(a,this.callback)),this.arr[b+1]=this.isObserved,this.observe(Object.getPrototypeOf(a)))}},cleanup:function(){for(var a=0,b=0,c=this.isObserved;b<this.arr.length;){var d=this.arr[b];this.arr[b+1]==c?(b>a&&(this.arr[a]=d,this.arr[a+1]=c),a+=2):Object.unobserve(d,this.callback),b+=2}this.arr.length=a}};var z={"new":!0,updated:!0,deleted:!0};a.Observer=i,a.Observer.hasObjectObserve=n,a.ObjectObserver=k}((c.Number={isNaN:window.isNaN})?c:c)}).call(this,"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],observejs:[function(a,b){b.exports=a("QYwGEY")},{}],3:[function(a,b){function c(a,b){return-1!==d(a,b)}var d=a("./indexOf");b.exports=c},{"./indexOf":6}],4:[function(a,b){function c(a,b,c){b=d(b,c);var e=[];if(null==a)return e;for(var f,g=-1,h=a.length;++g<h;)f=a[g],b(f,g,a)&&e.push(f);return e}var d=a("../function/makeIterator_");b.exports=c},{"../function/makeIterator_":12}],5:[function(a,b){function c(a,b,c){if(null!=a)for(var d=-1,e=a.length;++d<e&&b.call(c,a[d],d,a)!==!1;);}b.exports=c},{}],6:[function(a,b){function c(a,b,c){if(c=c||0,null==a)return-1;for(var d=a.length,e=0>c?d+c:c;d>e;){if(a[e]===b)return e;e++}return-1}b.exports=c},{}],7:[function(a,b){function c(a){return null!=a&&""!==a}function d(a,b){return b=b||"",e(a,c).join(b)}var e=a("./filter");b.exports=d},{"./filter":4}],8:[function(a,b){function c(a,b,c){var d=a.length;b=null==b?0:0>b?Math.max(d+b,0):Math.min(b,d),c=null==c?d:0>c?Math.max(d+c,0):Math.min(c,d);for(var e=[];c>b;)e.push(a[b++]);return e}b.exports=c},{}],9:[function(a,b){function c(a,b){if(null==a)return[];if(a.length<2)return a;null==b&&(b=d);var f,g,h;return f=~~(a.length/2),g=c(a.slice(0,f),b),h=c(a.slice(f,a.length),b),e(g,h,b)}function d(a,b){return b>a?-1:a>b?1:0}function e(a,b,c){for(var d=[];a.length&&b.length;)d.push(c(a[0],b[0])<=0?a.shift():b.shift());return a.length&&d.push.apply(d,a),b.length&&d.push.apply(d,b),d}b.exports=c},{}],10:[function(a,b){function c(a,b){var c={};if(null==a)return c;var e,f=-1,g=a.length;if(d(b))for(;++f<g;)e=a[f],c[b(e)]=e;else for(;++f<g;)e=a[f],c[e[b]]=e;return c}var d=a("../lang/isFunction");b.exports=c},{"../lang/isFunction":16}],11:[function(a,b){function c(a){return a}b.exports=c},{}],12:[function(a,b){function c(a,b){if(null==a)return d;switch(typeof a){case"function":return"undefined"!=typeof b?function(c,d,e){return a.call(b,c,d,e)}:a;case"object":return function(b){return f(b,a)};case"string":case"number":return e(a)}}var d=a("./identity"),e=a("./prop"),f=a("../object/deepMatches");b.exports=c},{"../object/deepMatches":21,"./identity":11,"./prop":13}],13:[function(a,b){function c(a){return function(b){return b[a]}}b.exports=c},{}],14:[function(a,b){var c=a("./isKind"),d=Array.isArray||function(a){return c(a,"Array")};b.exports=d},{"./isKind":17}],15:[function(a,b){function c(a){if(null==a)return!1;if("string"==typeof a||e(a))return!a.length;if("object"==typeof a||"function"==typeof a){var b=!0;return d(a,function(){return b=!1,!1}),b}return!1}var d=a("../object/forOwn"),e=a("./isArray");b.exports=c},{"../object/forOwn":24,"./isArray":14}],16:[function(a,b){function c(a){return d(a,"Function")}var d=a("./isKind");b.exports=c},{"./isKind":17}],17:[function(a,b){function c(a,b){return d(a)===b}var d=a("./kindOf");b.exports=c},{"./kindOf":19}],18:[function(a,b){function c(a){return!!a&&"object"==typeof a&&a.constructor===Object}b.exports=c},{}],19:[function(a,b){function c(a){return null===a?"Null":a===d?"Undefined":e.exec(f.call(a))[1]}var d,e=/^\[object (.*)\]$/,f=Object.prototype.toString;b.exports=c},{}],20:[function(a,b){function c(a){return null==a?"":a.toString()}b.exports=c},{}],21:[function(a,b){function c(a,b){for(var c=-1,d=a.length;++c<d;)if(f(a[c],b))return!0;return!1}function d(a,b){for(var d=-1,e=b.length;++d<e;)if(!c(a,b[d]))return!1;return!0}function e(a,b){var c=!0;return g(b,function(b,d){return f(a[d],b)?void 0:c=!1}),c}function f(a,b){return a&&"object"==typeof a?h(a)&&h(b)?d(a,b):e(a,b):a===b}var g=a("./forOwn"),h=a("../lang/isArray");b.exports=f},{"../lang/isArray":14,"./forOwn":24}],22:[function(a,b){function c(a){for(var b,c=0,f=arguments.length;++c<f;)b=arguments[c],b&&e(b,d,a);return a}function d(a,b){var d=this[b];f(a)&&f(d)?c(d,a):this[b]=a}var e=a("./forOwn"),f=a("../lang/isPlainObject");b.exports=c},{"../lang/isPlainObject":18,"./forOwn":24}],23:[function(a,b){function c(){g=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],f=!0;for(var a in{toString:null})f=!1}function d(a,b,d){var i,j=0;null==f&&c();for(i in a)if(e(b,a,i,d)===!1)break;if(f)for(var k=a.constructor,l=!!k&&a===k.prototype;(i=g[j++])&&("constructor"===i&&(l||!h(a,i))||a[i]===Object.prototype[i]||e(b,a,i,d)!==!1););}function e(a,b,c,d){return a.call(d,b[c],c,b)}var f,g,h=a("./hasOwn");b.exports=d},{"./hasOwn":25}],24:[function(a,b){function c(a,b,c){e(a,function(e,f){return d(a,f)?b.call(c,a[f],f,a):void 0})}var d=a("./hasOwn"),e=a("./forIn");b.exports=c},{"./forIn":23,"./hasOwn":25}],25:[function(a,b){function c(a,b){return Object.prototype.hasOwnProperty.call(a,b)}b.exports=c},{}],26:[function(a,b){function c(a,b){return b?(d(b.split("."),function(b){a[b]||(a[b]={}),a=a[b]}),a):a}var d=a("../array/forEach");b.exports=c},{"../array/forEach":5}],27:[function(a,b){function c(a){for(var b,c="string"!=typeof arguments[1]?arguments[1]:d(arguments,1),e={},f=0;b=c[f++];)e[b]=a[b];return e}var d=a("../array/slice");b.exports=c},{"../array/slice":8}],28:[function(a,b){function c(a,b,c){var e=/^(.+)\.(.+)$/.exec(b);e?d(a,e[1])[e[2]]=c:a[b]=c}var d=a("./namespace");b.exports=c},{"./namespace":26}],29:[function(a,b){function c(){var a=d(e(arguments),"/");return a.replace(/([^:\/]|^)\/{2,}/g,"$1/")}var d=a("../array/join"),e=a("../array/slice");b.exports=c},{"../array/join":7,"../array/slice":8}],30:[function(a,b){function c(a){return a=d(a),a.toUpperCase()}var d=a("../lang/toString");b.exports=c},{"../lang/toString":20}],31:[function(a,b){function c(){var a=this.defaults={queryTransform:function(a,b){return b}};this.$get=["$http","$log","DSUtils",function(b,c,d){function e(a){var d=(new Date).getTime();return b(a).then(function(a){return c.debug(a.config.method+" request:"+a.config.url+" Time taken: "+((new Date).getTime()-d)+"ms",arguments),a})}function f(a,b){return b=b||{},e(d.deepMixIn(b,{url:a,method:"GET"}))}function g(a,b,c){return c=c||{},e(d.deepMixIn(c,{url:a,data:b,method:"POST"}))}function h(a,b,c){return c=c||{},e(d.deepMixIn(c,{url:a,data:b,method:"PUT"}))}function i(a,b){return b=b||{},this.HTTP(d.deepMixIn(b,{url:a,method:"DELETE"}))}function j(a,b,c){return c=c||{},this.POST(d.makePath(c.baseUrl||a.baseUrl,a.endpoint),b,c)}function k(a,b,c){return c=c||{},this.DEL(d.makePath(c.baseUrl||a.baseUrl,a.endpoint,b),c)}function l(b,c,e){return e=e||{},e.params=e.params||{},c&&(c.query=c.query?a.queryTransform(b.name,c.query):c.query,d.deepMixIn(e.params,c)),this.DEL(d.makePath(e.baseUrl||b.baseUrl,b.endpoint),e)}function m(a,b,c){return c=c||{},this.GET(d.makePath(c.baseUrl||a.baseUrl,a.endpoint,b),c)}function n(b,c,e){return e=e||{},e.params=e.params||{},c&&(c.query=c.query?a.queryTransform(b.name,c.query):c.query,d.deepMixIn(e.params,c)),this.GET(d.makePath(e.baseUrl||b.baseUrl,b.endpoint),e)}function o(a,b,c,e){return e=e||{},this.PUT(d.makePath(e.baseUrl||a.baseUrl,a.endpoint,b),c,e)}function p(b,c,e,f){return f=f||{},f.params=f.params||{},e&&(e.query=e.query?a.queryTransform(b.name,e.query):e.query,d.deepMixIn(f.params,e)),this.PUT(d.makePath(f.baseUrl||b.baseUrl,b.endpoint),c,f)}return{defaults:a,HTTP:e,GET:f,POST:g,PUT:h,DEL:i,find:m,findAll:n,create:j,update:o,updateAll:p,destroy:k,destroyAll:l}}]}b.exports=c},{}],32:[function(a,b){function c(){this.$get=["$q","DSUtils",function(a,b){function c(b){var c=a.defer();try{var d=localStorage.getItem(b);c.resolve(d?angular.fromJson(d):void 0)}catch(e){c.reject(e)}return c.promise}function d(c,d){var e=a.defer();try{var f=localStorage.getItem(c);f?(f=angular.fromJson(f),b.deepMixIn(f,d),e.resolve(localStorage.setItem(c,angular.toJson(f)))):e.resolve(localStorage.setItem(c,angular.toJson(d)))}catch(g){e.reject(g)}return e.promise}function e(b){var c=a.defer();try{c.resolve(localStorage.removeItem(b))}catch(d){c.reject(d)}return c.promise}function f(a,c,d){return d=d||{},e(b.makePath(d.baseUrl||a.baseUrl,a.endpoint,c),d)}function g(a,d,e){return e=e||{},c(b.makePath(e.baseUrl||a.baseUrl,a.endpoint,d),e)}function h(a,e,f,g){return g=g||{},d(b.makePath(g.baseUrl||a.baseUrl,a.endpoint,e),f,g).then(function(){return c(b.makePath(g.baseUrl||a.baseUrl,a.endpoint,e))})}return{find:g,findAll:function(){throw new Error("Not supported!")},create:function(){throw new Error("Not supported!")},update:h,updateAll:function(){throw new Error("Not supported!")},destroy:f,destroyAll:function(){throw new Error("Not supported!")}}}]}b.exports=c},{}],33:[function(a,b){function c(a,b,c){var e=this.$q.defer(),f=e.promise;if(c=c||{},this.definitions[a])if(this.utils.isObject(b))try{var g=this.definitions[a],h=this.store[a],i=this;f=f.then(function(b){return i.$q.promisify(g.beforeValidate)(a,b)}).then(function(b){return i.$q.promisify(g.validate)(a,b)}).then(function(b){return i.$q.promisify(g.afterValidate)(a,b)}).then(function(b){return i.$q.promisify(g.beforeCreate)(a,b)}).then(function(b){return i.adapters[c.adapter||g.defaultAdapter].create(g,g.serialize(a,b),c)}).then(function(b){return i.$q.promisify(g.afterCreate)(a,g.deserialize(a,b))}).then(function(a){var b=i.inject(g.name,a),c=b[g.idAttribute];return h.previousAttributes[c]=i.utils.deepMixIn({},b),h.saved[c]=i.utils.updateTimestamp(h.saved[c]),i.get(g.name,c)}),e.resolve(b)}catch(j){e.reject(new this.errors.UnhandledError(j))}else e.reject(new this.errors.IllegalArgumentError(d+"attrs: Must be an object!",{attrs:{actual:typeof b,expected:"object"}}));else e.reject(new this.errors.RuntimeError(d+a+" is not a registered resource!"));return f}var d="DS.create(resourceName, attrs[, options]): ";b.exports=c},{}],34:[function(a,b){function c(a,b,c){var e=this.$q.defer(),f=e.promise;if(c=c||{},this.definitions[a])if(this.utils.isString(b)||this.utils.isNumber(b)){var g=this.get(a,b);if(g){var h=this.definitions[a],i=(this.store[a],this);f=f.then(function(b){return i.$q.promisify(h.beforeDestroy)(a,b)}).then(function(){return i.adapters[c.adapter||h.defaultAdapter].destroy(h,b,c)}).then(function(){return i.$q.promisify(h.afterDestroy)(a,g)}).then(function(){return i.eject(a,b),b}),e.resolve(g)}else e.reject(new this.errors.RuntimeError(d+'id: "'+b+'" not found!'))}else e.reject(new this.errors.IllegalArgumentError(d+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}}));else e.reject(new this.errors.RuntimeError(d+a+" is not a registered resource!"));return f}var d="DS.destroy(resourceName, id): ";b.exports=c},{}],35:[function(a,b){function c(a,b,c){var e=this.$q.defer(),f=e.promise,g=this;if(c=c||{},this.definitions[a])if(this.utils.isObject(b))if(this.utils.isObject(c))try{var h=this.definitions[a];f=f.then(function(){return g.adapters[c.adapter||h.defaultAdapter].destroyAll(h,b,c)}).then(function(){return g.ejectAll(a,b)}),e.resolve()}catch(i){e.reject(new this.errors.UnhandledError(i))}else e.reject(new this.errors.IllegalArgumentError(d+"options: Must be an object!"));else e.reject(new this.errors.IllegalArgumentError(d+"params: Must be an object!"));else e.reject(new this.errors.RuntimeError(d+a+" is not a registered resource!"));return f}var d="DS.destroyAll(resourceName, params[, options]): ";b.exports=c},{}],36:[function(a,b){function c(a,b,c){var e=this.$q.defer(),f=e.promise;if(c=c||{},this.definitions[a])if(this.utils.isString(b)||this.utils.isNumber(b))if(this.utils.isObject(c)){c.cacheResponse="cacheResponse"in c?!!c.cacheResponse:!0;try{var g=this.definitions[a],h=this.store[a],i=this;if(c.bypassCache&&delete h.completedQueries[b],!(b in h.completedQueries))return b in h.pendingQueries||(f=h.pendingQueries[b]=i.adapters[c.adapter||g.defaultAdapter].find(g,b,c).then(function(d){var e=g.deserialize(a,d);return c.cacheResponse?(delete h.pendingQueries[b],h.completedQueries[b]=(new Date).getTime(),i.inject(a,e)):e},function(a){return delete h.pendingQueries[b],a})),h.pendingQueries[b];e.resolve(i.get(a,b))}catch(j){e.reject(j)}}else e.reject(new this.errors.IllegalArgumentError(d+"options: Must be an object!",{options:{actual:typeof c,expected:"object"}}));else e.reject(new this.errors.IllegalArgumentError(d+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}}));else e.reject(new this.errors.RuntimeError(d+a+" is not a registered resource!"));return f}var d="DS.find(resourceName, id[, options]): ";b.exports=c},{}],37:[function(a,b){function c(a,b,c,d){var e=this.store[c];return b=b||[],delete e.pendingQueries[d],e.completedQueries[d]=(new Date).getTime(),this.inject(c,b),e.collectionModified=a.updateTimestamp(e.collectionModified),b}function d(a,b,d,e){var f=this.definitions[b],g=this.store[b],h=this,i=a.toJson(d);return e.bypassCache&&delete g.completedQueries[i],i in g.completedQueries?this.filter(b,d,e):(i in g.pendingQueries||(g.pendingQueries[i]=h.adapters[e.adapter||f.defaultAdapter].findAll(f,d,e).then(function(d){var g=f.deserialize(b,d);if(!e.cacheResponse)return g;try{return c.apply(h,[a,g,b,i])}catch(j){throw new h.errors.UnhandledError(j)}},function(a){return delete g.pendingQueries[i],a})),g.pendingQueries[i])}function e(a,b,c){var e=this.$q.defer(),g=e.promise,h=this;if(c=c||{},this.definitions[a])if(this.utils.isObject(b))if(this.utils.isObject(c)){c.cacheResponse="cacheResponse"in c?!!c.cacheResponse:!0;try{g=g.then(function(){return d.apply(h,[h.utils,a,b,c])}),e.resolve()}catch(i){e.reject(new this.errors.UnhandledError(i))}}else e.reject(new this.errors.IllegalArgumentError(f+"options: Must be an object!"));else e.reject(new this.errors.IllegalArgumentError(f+"params: Must be an object!"));else e.reject(new this.errors.RuntimeError(f+a+" is not a registered resource!"));return g}var f="DS.findAll(resourceName, params[, options]): ";b.exports=e},{}],38:[function(a,b){b.exports={create:a("./create"),destroy:a("./destroy"),destroyAll:a("./destroyAll"),find:a("./find"),findAll:a("./findAll"),refresh:a("./refresh"),save:a("./save"),update:a("./update"),updateAll:a("./updateAll")}},{"./create":33,"./destroy":34,"./destroyAll":35,"./find":36,"./findAll":37,"./refresh":39,"./save":40,"./update":41,"./updateAll":42}],39:[function(a,b){function c(a,b,c){if(c=c||{},this.definitions[a]){if(this.utils.isString(b)||this.utils.isNumber(b)){if(this.utils.isObject(c))return c.bypassCache=!0,this.get(a,b)?this.find(a,b,c):!1;throw new this.errors.IllegalArgumentError(d+"options: Must be an object!",{options:{actual:typeof c,expected:"object"}})}throw new this.errors.IllegalArgumentError(d+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}})}throw new this.errors.RuntimeError(d+a+" is not a registered resource!")}var d="DS.refresh(resourceName, id[, options]): ";b.exports=c},{}],40:[function(a,b){function c(a,b,c){var e=this.$q.defer(),f=e.promise;if(c=c||{},this.definitions[a])if(this.utils.isString(b)||this.utils.isNumber(b))if(this.utils.isObject(c)){var g=this.get(a,b);if(g){var h=this.definitions[a],i=this.store[a],j=this;f=f.then(function(b){return j.$q.promisify(h.beforeValidate)(a,b)}).then(function(b){return j.$q.promisify(h.validate)(a,b)}).then(function(b){return j.$q.promisify(h.afterValidate)(a,b)}).then(function(b){return j.$q.promisify(h.beforeUpdate)(a,b)}).then(function(d){if(c.changesOnly){i.observers[b].deliver();var e=[],f=j.changes(a,b);for(var g in f.added)e.push(g);for(g in f.changed)e.push(g);if(f=j.utils.pick(d,e),j.utils.isEmpty(f))return d;d=f}return j.adapters[c.adapter||h.defaultAdapter].update(h,b,h.serialize(a,d),c)}).then(function(b){return j.$q.promisify(h.afterUpdate)(a,h.deserialize(a,b))}).then(function(d){return j.inject(h.name,d,c),i.previousAttributes[b]=j.utils.deepMixIn({},d),i.saved[b]=j.utils.updateTimestamp(i.saved[b]),j.get(a,b)}),e.resolve(g)}else e.reject(new this.errors.RuntimeError(d+'id: "'+b+'" not found!'))}else e.reject(new this.errors.IllegalArgumentError(d+"options: Must be an object!",{options:{actual:typeof c,expected:"object"}}));else e.reject(new this.errors.IllegalArgumentError(d+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}}));else e.reject(new this.errors.RuntimeError(d+a+" is not a registered resource!"));return f}var d="DS.save(resourceName, id[, options]): ";b.exports=c},{}],41:[function(a,b){function c(a,b,c,e){var f=this.$q.defer(),g=f.promise;if(e=e||{},this.definitions[a])if(this.utils.isString(b)||this.utils.isNumber(b))if(this.utils.isObject(c))if(this.utils.isObject(e)){var h=this.definitions[a],i=this.store[a],j=this;e.cacheResponse="cacheResponse"in e?!!e.cacheResponse:!0,g=g.then(function(b){return j.$q.promisify(h.beforeValidate)(a,b)}).then(function(b){return j.$q.promisify(h.validate)(a,b)}).then(function(b){return j.$q.promisify(h.afterValidate)(a,b)}).then(function(b){return j.$q.promisify(h.beforeUpdate)(a,b)}).then(function(c){return j.adapters[e.adapter||h.defaultAdapter].update(h,b,h.serialize(a,c),e)}).then(function(b){return j.$q.promisify(h.afterUpdate)(a,h.deserialize(a,b))}).then(function(a){if(e.cacheResponse){var b=j.inject(h.name,a,e),c=b[h.idAttribute];return i.previousAttributes[c]=j.utils.deepMixIn({},b),i.saved[c]=j.utils.updateTimestamp(i.saved[c]),j.get(h.name,c)}return a}),f.resolve(c)}else f.reject(new this.errors.IllegalArgumentError(d+"options: Must be an object!"));else f.reject(new this.errors.IllegalArgumentError(d+"attrs: Must be an object!"));else f.reject(new this.errors.IllegalArgumentError(d+"id: Must be a string or a number!"));else f.reject(new this.errors.RuntimeError(d+a+" is not a registered resource!"));return g}var d="DS.update(resourceName, id, attrs[, options]): ";b.exports=c},{}],42:[function(a,b){function c(a,b,c,e){var f=this.$q.defer(),g=f.promise;if(e=e||{},this.definitions[a])if(this.utils.isObject(b))if(this.utils.isObject(c))if(this.utils.isObject(e)){var h=this.definitions[a],i=(this.store[a],this);e.cacheResponse="cacheResponse"in e?!!e.cacheResponse:!0,g=g.then(function(b){return i.$q.promisify(h.beforeValidate)(a,b)}).then(function(b){return i.$q.promisify(h.validate)(a,b)}).then(function(b){return i.$q.promisify(h.afterValidate)(a,b)}).then(function(b){return i.$q.promisify(h.beforeUpdate)(a,b)}).then(function(b){return i.adapters[e.adapter||h.defaultAdapter].updateAll(h,h.serialize(a,b),c,e)}).then(function(b){return i.$q.promisify(h.afterUpdate)(a,h.deserialize(a,b))}).then(function(a){return e.cacheResponse?i.inject(h.name,a,e):a}),f.resolve(b)}else f.reject(new this.errors.IllegalArgumentError(d+"options: Must be an object!"));else f.reject(new this.errors.IllegalArgumentError(d+"params: Must be an object!"));else f.reject(new this.errors.IllegalArgumentError(d+"attrs: Must be an object!"));else f.reject(new this.errors.RuntimeError(d+a+" is not a registered resource!"));return g}var d="DS.updateAll(resourceName, attrs, params[, options]): ";b.exports=c},{}],43:[function(a,b){function c(a,b,c){c(null,b)}function d(){}function e(){var b=this.defaults=new d;this.$get=["$rootScope","$log","$q","DSHttpAdapter","DSLocalStorageAdapter","DSUtils","DSErrors",function(c,d,e,f,g,h,i){var j,k=a("./sync_methods"),l=a("./async_methods");try{j=angular.injector(["angular-data.DSCacheFactory"]).get("DSCacheFactory")}catch(m){d.warn(m),d.warn("DSCacheFactory is unavailable. Resorting to the lesser capabilities of $cacheFactory."),j=angular.injector(["ng"]).get("$cacheFactory")}var n={$rootScope:c,$log:d,$q:e,cacheFactory:j,defaults:b,store:{},definitions:{},adapters:{DSHttpAdapter:f,DSLocalStorageAdapter:g},errors:i,utils:h};h.deepFreeze(k),h.deepFreeze(l),h.deepMixIn(n,k),h.deepMixIn(n,l),h.deepFreeze(n.errors),h.deepFreeze(n.utils);var o=c.$new();return o.$watch(function(){return(new Date).getTime()/100|0},function(){n.digest()}),n}]}var f=a("../utils")[0]();d.prototype.idAttribute="id",d.prototype.defaultAdapter="DSHttpAdapter",d.prototype.filter=function(a,b,c){var d=!0;return f.forOwn(b,function(a,b){f.isString(a)?a={"===":a}:f.isNumber(a)&&(a={"==":a}),"=="in a?d=d&&c[b]==a["=="]:"==="in a?d=d&&c[b]===a["==="]:"!="in a?d=d&&c[b]!=a["!="]:">"in a?d=d&&c[b]>a[">"]:">="in a?d=d&&c[b]>=a[">="]:"<"in a?d=d&&c[b]<a["<"]:"<="in a?d=d&&c[b]<=a["<="]:"in"in a&&(d=d&&f.contains(a["in"],c[b]))}),d},d.prototype.baseUrl="",d.prototype.endpoint="",d.prototype.beforeValidate=c,d.prototype.validate=c,d.prototype.afterValidate=c,d.prototype.beforeCreate=c,d.prototype.afterCreate=c,d.prototype.beforeUpdate=c,d.prototype.afterUpdate=c,d.prototype.beforeDestroy=c,d.prototype.afterDestroy=c,d.prototype.beforeInject=function(a,b){return b},d.prototype.afterInject=function(a,b){return b},d.prototype.serialize=function(a,b){return b},d.prototype.deserialize=function(a,b){return b.data},b.exports=e},{"../utils":"K0yknU","./async_methods":38,"./sync_methods":54}],44:[function(a,b){function c(a,b,c,e){if(!this.utils.isObject(a))throw new this.errors.IllegalArgumentError(d+"scope: Must be an object!");if(!this.utils.isString(b))throw new this.errors.IllegalArgumentError(d+"expr: Must be a string!");if(!this.definitions[c])throw new this.errors.RuntimeError(d+c+" is not a registered resource!");if(!this.utils.isObject(e))throw new this.errors.IllegalArgumentError(d+"params: Must be an object!");var f=this;try{return a.$watch(function(){return f.lastModified(c)},function(){f.utils.set(a,b,f.filter(c,e))})}catch(g){throw new this.errors.UnhandledError(g)}}var d="DS.bindAll(scope, expr, resourceName, params): ";b.exports=c},{}],45:[function(a,b){function c(a,b,c,e){if(!this.utils.isObject(a))throw new this.errors.IllegalArgumentError(d+"scope: Must be an object!");if(!this.utils.isString(b))throw new this.errors.IllegalArgumentError(d+"expr: Must be a string!");if(!this.definitions[c])throw new this.errors.RuntimeError(d+c+" is not a registered resource!");if(!this.utils.isString(e)&&!this.utils.isNumber(e))throw new this.errors.IllegalArgumentError(d+"id: Must be a string or a number!");var f=this;try{return a.$watch(function(){return f.lastModified(c,e)},function(){f.utils.set(a,b,f.get(c,e))})}catch(g){throw new this.errors.UnhandledError(g)}}var d="DS.bindOne(scope, expr, resourceName, id): ";b.exports=c},{}],46:[function(a,b){function c(a,b){if(!this.definitions[a])throw new this.errors.RuntimeError(d+a+" is not a registered resource!");if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new this.errors.IllegalArgumentError(d+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}});try{var c=this.get(a,b);if(c)return this.store[a].observers[b].deliver(),this.utils.diffObjectFromOldObject(c,this.store[a].previousAttributes[b])}catch(e){throw new this.errors.UnhandledError(e)}}var d="DS.changes(resourceName, id): ";b.exports=c},{}],47:[function(require,module,exports){function Resource(a,b){a.deepMixIn(this,b),this.endpoint="endpoint"in b?b.endpoint:this.name}function defineResource(definition){if(this.utils.isString(definition)&&(definition={name:definition}),!this.utils.isObject(definition))throw new this.errors.IllegalArgumentError(errorPrefix+"definition: Must be an object!",{definition:{actual:typeof definition,expected:"object"}});if(!this.utils.isString(definition.name))throw new this.errors.IllegalArgumentError(errorPrefix+"definition.name: Must be a string!",{definition:{name:{actual:typeof definition.name,expected:"string"}}});if(definition.idAttribute&&!this.utils.isString(definition.idAttribute))throw new this.errors.IllegalArgumentError(errorPrefix+"definition.idAttribute: Must be a string!",{definition:{idAttribute:{actual:typeof definition.idAttribute,expected:"string"}}});if(definition.endpoint&&!this.utils.isString(definition.endpoint))throw new this.errors.IllegalArgumentError(errorPrefix+"definition.endpoint: Must be a string!",{definition:{endpoint:{actual:typeof definition.endpoint,expected:"string"}}});if(this.store[definition.name])throw new this.errors.RuntimeError(errorPrefix+definition.name+" is already registered!");try{Resource.prototype=this.defaults,this.definitions[definition.name]=new Resource(this.utils,definition);var _this=this,def=this.definitions[definition.name],cache=this.cacheFactory("DS."+def.name,{maxAge:def.maxAge||null,recycleFreq:def.recycleFreq||1e3,cacheFlushInterval:def.cacheFlushInterval||null,deleteOnExpire:def.deleteOnExpire||"none",onExpire:function(a){_this.eject(def.name,a)},capacity:Number.MAX_VALUE,storageMode:"memory",storageImpl:null,disabled:!1,storagePrefix:"DS."+def.name});def.methods&&(def.class=definition.name[0].toUpperCase()+definition.name.substring(1),eval("function "+def.class+"() {}"),def[def.class]=eval(def.class),this.utils.deepMixIn(def[def.class].prototype,def.methods)),this.store[def.name]={collection:[],completedQueries:{},pendingQueries:{},index:cache,modified:{},saved:{},previousAttributes:{},observers:{},collectionModified:0}}catch(err){throw delete this.definitions[definition.name],delete this.store[definition.name],new this.errors.UnhandledError(err)}}var errorPrefix="DS.defineResource(definition): ";module.exports=defineResource},{}],48:[function(a,b){function c(){try{this.$rootScope.$$phase?d.Platform.performMicrotaskCheckpoint():this.$rootScope.$apply(function(){d.Platform.performMicrotaskCheckpoint()})}catch(a){throw new this.errors.UnhandledError(a)}}var d=a("observejs");b.exports=c},{observejs:"QYwGEY"}],49:[function(a,b){function c(a,b,c){for(var d=!1,e=0;e<b.collection.length;e++)if(b.collection[e][a.idAttribute]==c){d=!0;break}d&&(b.collection.splice(e,1),b.observers[c].close(),delete b.observers[c],b.index.remove(c),delete b.previousAttributes[c],delete b.modified[c],delete b.saved[c])}function d(a,b){if(!this.definitions[a])throw new this.errors.RuntimeError(e+a+" is not a registered resource!");if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new this.errors.IllegalArgumentError(e+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}});var d=this.store[a],f=this;try{this.$rootScope.$$phase?(c(f.definitions[a],d,b),d.collectionModified=f.utils.updateTimestamp(d.collectionModified)):this.$rootScope.$apply(function(){c(f.definitions[a],d,b),d.collectionModified=f.utils.updateTimestamp(d.collectionModified)}),delete this.store[a].completedQueries[b]}catch(g){throw new this.errors.UnhandledError(g)}}var e="DS.eject(resourceName, id): ";b.exports=d},{}],50:[function(a,b){function c(a,b,c){for(var d=this.utils.toJson(c),e=this.filter(a.name,c),f=0;f<e.length;f++)this.eject(a.name,e[f][a.idAttribute]);delete b.completedQueries[d]}function d(a,b){if(b=b||{},!this.definitions[a])throw new this.errors.RuntimeError(e+a+" is not a registered resource!");if(!this.utils.isObject(b))throw new this.errors.IllegalArgumentError(e+"params: Must be an object!",{params:{actual:typeof b,expected:"object"}});var d=this.store[a],f=this;
try{this.$rootScope.$$phase?(c.apply(f,[f.definitions[a],d,b]),d.collectionModified=this.utils.updateTimestamp(d.collectionModified)):this.$rootScope.$apply(function(){c.apply(f,[f.definitions[a],d,b]),d.collectionModified=f.utils.updateTimestamp(d.collectionModified)})}catch(g){throw new this.errors.UnhandledError(g)}}var e="DS.ejectAll(resourceName[, params]): ";b.exports=d},{}],51:[function(a,b){function c(a,b,c){if(c=c||{},!this.definitions[a])throw new this.errors.RuntimeError(d+a+" is not a registered resource!");if(!this.utils.isObject(b))throw new this.errors.IllegalArgumentError(d+"params: Must be an object!",{params:{actual:typeof b,expected:"object"}});if(!this.utils.isObject(c))throw new this.errors.IllegalArgumentError(d+"options: Must be an object!",{options:{actual:typeof c,expected:"object"}});try{var e=this.definitions[a],f=this.store[a],g=this;b.query=b.query||{};var h=this.utils.toJson(b);h in f.completedQueries||!c.loadFromServer||f.pendingQueries[h]||this.findAll(a,b,c);var i=this.utils.filter(f.collection,function(c){var f=!0,h=b.query.where;if(h){if(!g.utils.isObject(h))throw new g.errors.IllegalArgumentError(d+"params.query.where: Must be an object!",{params:{query:{where:{actual:typeof b.query.where,expected:"object"}}}});f=e.filter(a,h,c)}return f});if(b.query.orderBy){if(this.utils.isString(b.query.orderBy)&&(b.query.orderBy=[[b.query.orderBy,"ASC"]]),!this.utils.isArray(b.query.orderBy))throw new this.errors.IllegalArgumentError(d+"params.query.orderBy: Must be a string or an array!",{params:{query:{orderBy:{actual:typeof b.query.orderBy,expected:"string|array"}}}});for(var j=0;j<b.query.orderBy.length;j++){if(this.utils.isString(b.query.orderBy[j]))b.query.orderBy[j]=[b.query.orderBy[j],"ASC"];else if(!this.utils.isArray(b.query.orderBy[j]))throw new this.errors.IllegalArgumentError(d+"params.query.orderBy["+j+"]: Must be a string or an array!",{params:{query:{"orderBy[i]":{actual:typeof b.query.orderBy[j],expected:"string|array"}}}});i=this.utils.sort(i,function(a,c){var d=a[b.query.orderBy[j][0]],e=c[b.query.orderBy[j][0]];return g.utils.isString(d)&&(d=g.utils.upperCase(d)),g.utils.isString(e)&&(e=g.utils.upperCase(e)),"DESC"===b.query.orderBy[j][1]?d>e?-1:e>d?1:0:e>d?-1:d>e?1:0})}}return this.utils.isNumber(b.query.limit)&&this.utils.isNumber(b.query.skip)?i=this.utils.slice(i,b.query.skip,Math.min(i.length,b.query.skip+b.query.limit)):this.utils.isNumber(b.query.limit)?i=this.utils.slice(i,0,Math.min(i.length,b.query.limit)):this.utils.isNumber(b.query.skip)&&(i=b.query.skip<i.length?this.utils.slice(i,b.query.skip):[]),i}catch(k){throw k instanceof this.errors.IllegalArgumentError?k:new this.errors.UnhandledError(k)}}var d="DS.filter(resourceName, params[, options]): ";b.exports=c},{}],52:[function(a,b){function c(a,b,c){if(c=c||{},!this.definitions[a])throw new this.errors.RuntimeError(d+a+" is not a registered resource!");if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new this.errors.IllegalArgumentError(d+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}});if(!this.utils.isObject(c))throw new this.errors.IllegalArgumentError(d+"options: Must be an object!",{options:{actual:typeof c,expected:"object"}});try{var e=this.store[a].index.get(b);return!e&&c.loadFromServer&&this.find(a,b).then(null,function(a){throw a}),e}catch(f){throw new this.errors.UnhandledError(f)}}var d="DS.get(resourceName, id[, options]): ";b.exports=c},{}],53:[function(a,b){function c(a,b){return!(a.isEmpty(b.added)&&a.isEmpty(b.removed)&&a.isEmpty(b.changed))}function d(a,b){if(!this.definitions[a])throw new this.errors.RuntimeError(e+a+" is not a registered resource!");if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new this.errors.IllegalArgumentError(e+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}});try{return this.get(a,b)?c(this.utils,this.changes(a,b)):!1}catch(d){throw new this.errors.UnhandledError(d)}}var e="DS.hasChanges(resourceName, id): ";b.exports=d},{}],54:[function(a,b){b.exports={defineResource:a("./defineResource"),bindOne:a("./bindOne"),bindAll:a("./bindAll"),eject:a("./eject"),ejectAll:a("./ejectAll"),filter:a("./filter"),get:a("./get"),inject:a("./inject"),lastModified:a("./lastModified"),lastSaved:a("./lastSaved"),digest:a("./digest"),changes:a("./changes"),previous:a("./previous"),hasChanges:a("./hasChanges")}},{"./bindAll":44,"./bindOne":45,"./changes":46,"./defineResource":47,"./digest":48,"./eject":49,"./ejectAll":50,"./filter":51,"./get":52,"./hasChanges":53,"./inject":55,"./lastModified":56,"./lastSaved":57,"./previous":58}],55:[function(a,b){function c(a,b,d){function g(c,d,e,f){try{var g=f(a.idAttribute);b.modified[g]=h.utils.updateTimestamp(b.modified[g]),b.collectionModified=h.utils.updateTimestamp(b.collectionModified),a.idAttribute in e&&i.error("Doh! You just changed the primary key of an object! I don't know how to handle this yet, so your data for the \""+a.name+'" resource is now in an undefined (probably broken) state.')}catch(j){throw new h.errors.UnhandledError(j)}}var h=this,i=h.$log;if(h.utils.isArray(d))for(var j=0;j<d.length;j++)c.call(h,a,b,d[j]);else{if(!(a.idAttribute in d))throw new h.errors.RuntimeError(f+"attrs: Must contain the property specified by `idAttribute`!");try{a.beforeInject(a.name,d);var k=d[a.idAttribute],l=this.get(a.name,k);l?(h.utils.deepMixIn(l,d),"function"==typeof b.index.touch?b.index.touch(k):b.index.put(k,b.index.get(k)),b.observers[k].deliver()):(l=a.class?d instanceof a[a.class]?d:new a[a.class]:{},b.previousAttributes[k]={},h.utils.deepMixIn(l,d),h.utils.deepMixIn(b.previousAttributes[k],d),b.collection.push(l),b.observers[k]=new e.ObjectObserver(l,g),b.index.put(k,l),g({},{},{},function(){return k})),b.saved[k]=h.utils.updateTimestamp(b.saved[k]),a.afterInject(a.name,l)}catch(m){i.error(m),i.error("inject failed!",a.name,d)}}}function d(a,b,d){if(d=d||{},!this.definitions[a])throw new this.errors.RuntimeError(f+a+" is not a registered resource!");if(!this.utils.isObject(b)&&!this.utils.isArray(b))throw new this.errors.IllegalArgumentError(f+"attrs: Must be an object or an array!",{attrs:{actual:typeof b,expected:"object|array"}});if(!this.utils.isObject(d))throw new this.errors.IllegalArgumentError(f+"options: Must be an object!",{options:{actual:typeof d,expected:"object"}});var e=this.definitions[a],g=this.store[a],h=this;try{return this.$rootScope.$$phase?c.apply(h,[e,g,b]):this.$rootScope.$apply(function(){c.apply(h,[e,g,b])}),h.utils.isArray(b)?b:this.get(a,b[e.idAttribute])}catch(i){throw i instanceof this.errors.RuntimeError?i:new this.errors.UnhandledError(i)}}var e=a("observejs"),f="DS.inject(resourceName, attrs[, options]): ";b.exports=d},{observejs:"QYwGEY"}],56:[function(a,b){function c(a,b){if(!this.definitions[a])throw new this.errors.RuntimeError(d+a+" is not a registered resource!");if(b&&!this.utils.isString(b)&&!this.utils.isNumber(b))throw new this.errors.IllegalArgumentError(d+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}});try{return b?(b in this.store[a].modified||(this.store[a].modified[b]=0),this.store[a].modified[b]):this.store[a].collectionModified}catch(c){throw new this.errors.UnhandledError(c)}}var d="DS.lastModified(resourceName[, id]): ";b.exports=c},{}],57:[function(a,b){function c(a,b){if(!this.definitions[a])throw new this.errors.RuntimeError(d+a+" is not a registered resource!");if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new this.errors.IllegalArgumentError(d+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}});try{return b in this.store[a].saved||(this.store[a].saved[b]=0),this.store[a].saved[b]}catch(c){throw new this.errors.UnhandledError(c)}}var d="DS.lastSaved(resourceName[, id]): ";b.exports=c},{}],58:[function(a,b){function c(a,b){if(!this.definitions[a])throw new this.errors.RuntimeError(d+a+" is not a registered resource!");if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new this.errors.IllegalArgumentError(d+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}});try{return angular.copy(this.store[a].previousAttributes[b])}catch(c){throw new this.errors.UnhandledError(c)}}var d="DS.previous(resourceName, id): ";b.exports=c},{}],errors:[function(a,b){b.exports=a("XIsZmp")},{}],XIsZmp:[function(a,b){function c(a){Error.call(this),"function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),a=a||{},this.type=this.constructor.name,this.originalError=a,this.message="UnhandledError: This is an uncaught exception. Please consider submitting an issue at https://github.com/jmdobry/angular-data/issues.\n\nOriginal Uncaught Exception:\n"+(a.stack?a.stack.toString():a.stack),this.stack=this.message}function d(a,b){Error.call(this),"function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.type=this.constructor.name,this.errors=b||{},this.message=a||"Illegal Argument!"}function e(a,b){Error.call(this),"function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.type=this.constructor.name,this.errors=b||{},this.message=a||"RuntimeError Error!"}c.prototype=Object.create(Error.prototype),c.prototype.constructor=c,d.prototype=Object.create(Error.prototype),d.prototype.constructor=d,e.prototype=Object.create(Error.prototype),e.prototype.constructor=e,b.exports=[function(){return{UnhandledError:c,IllegalArgumentError:d,RuntimeError:e}}]},{}],61:[function(a){!function(b,c){"use strict";c.module("angular-data.DS",["ng"]).factory("DSUtils",a("./utils")).factory("DSErrors",a("./errors")).provider("DSHttpAdapter",a("./adapters/http")).provider("DSLocalStorageAdapter",a("./adapters/localStorage")).provider("DS",a("./datastore")).config(["$provide",function(a){a.decorator("$q",["$delegate",function(a){return a.promisify=function(a,b){var c=this;return function(){var d=c.defer(),e=Array.prototype.slice.apply(arguments);e.push(function(a,b){a?d.reject(a):d.resolve(b)});try{a.apply(b||this,e)}catch(f){d.reject(f)}return d.promise}},a}])}])}(window,window.angular)},{"./adapters/http":31,"./adapters/localStorage":32,"./datastore":43,"./errors":"XIsZmp","./utils":"K0yknU"}],K0yknU:[function(a,b){b.exports=[function(){return{isString:angular.isString,isArray:angular.isArray,isObject:angular.isObject,isNumber:angular.isNumber,isFunction:angular.isFunction,isEmpty:a("mout/lang/isEmpty"),toJson:angular.toJson,makePath:a("mout/string/makePath"),upperCase:a("mout/string/upperCase"),deepMixIn:a("mout/object/deepMixIn"),forOwn:a("mout/object/forOwn"),pick:a("mout/object/pick"),set:a("mout/object/set"),contains:a("mout/array/contains"),filter:a("mout/array/filter"),toLookup:a("mout/array/toLookup"),slice:a("mout/array/slice"),sort:a("mout/array/sort"),updateTimestamp:function(a){var b="function"==typeof Date.now?Date.now():(new Date).getTime();return a&&a>=b?a+1:b},deepFreeze:function b(a){if("function"==typeof Object.freeze){var c,d;Object.freeze(a);for(d in a)c=a[d],a.hasOwnProperty(d)&&"object"==typeof c&&!Object.isFrozen(c)&&b(c)}},diffObjectFromOldObject:function(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var h in a)h in b||(c[h]=a[h]);return{added:c,removed:d,changed:e}}}}]},{"mout/array/contains":3,"mout/array/filter":4,"mout/array/slice":8,"mout/array/sort":9,"mout/array/toLookup":10,"mout/lang/isEmpty":15,"mout/object/deepMixIn":22,"mout/object/forOwn":24,"mout/object/pick":27,"mout/object/set":28,"mout/string/makePath":29,"mout/string/upperCase":30}],utils:[function(a,b){b.exports=a("K0yknU")},{}]},{},[61]);
!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){(function(){!function(a){"use strict";function b(){function a(a){"splice"===a[0].type&&"splice"===a[1].type&&(b=!0)}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=!1,c=[0];return Array.observe(c,a),c[1]=1,c.length=0,Object.deliverChangeRecords(a),b}function c(a){return a===Object(a)}function d(a){for(var b=0;s>b&&a.check();)a.report(),b++}function e(a){for(var b in a)return!1;return!0}function f(a){return e(a.added)&&e(a.removed)&&e(a.changed)}function g(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function h(a,b){var c=b||(Array.isArray(a)?[]:{});for(var d in a)c[d]=a[d];return Array.isArray(a)&&(c.length=a.length),c}function i(a,b,c,d){if(this.closed=!1,this.object=a,this.callback=b,this.target=c,this.token=d,this.reporting=!0,n){var e=this;this.boundInternalCallback=function(a){e.internalCallback(a)}}j(this),this.connect(),this.sync(!0)}function j(a){u&&(t.push(a),i._allObserversCount++)}function k(a,b,c,d){i.call(this,a,b,c,d)}function l(a){this.arr=[],this.callback=a,this.isObserved=!0}function m(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];z[g.type]?(g.name in c||(c[g.name]=g.oldValue),"updated"!=g.type&&("new"!=g.type?g.name in d?(delete d[g.name],delete c[g.name]):e[g.name]=!0:g.name in e?delete e[g.name]:d[g.name]=!0)):(console.error("Unknown changeRecord type: "+g.type),console.error(g))}for(var h in d)d[h]=a[h];for(var h in e)e[h]=void 0;var i={};for(var h in c)if(!(h in d||h in e)){var j=a[h];c[h]!==j&&(i[h]=j)}return{added:d,removed:e,changed:i}}var n=b(),o=!1;try{var p=new Function("","return true;");o=p()}catch(q){}var r=(a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},"__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c}),s=1e3;i.prototype={internalCallback:function(a){this.closed||this.reporting&&this.check(a)&&(this.report(),this.testingResults&&(this.testingResults.anyChanged=!0))},close:function(){this.closed||(this.object&&"function"==typeof this.object.unobserved&&this.object.unobserved(),this.disconnect(),this.object=void 0,this.closed=!0)},deliver:function(a){this.closed||(n?(this.testingResults=a,Object.deliverChangeRecords(this.boundInternalCallback),this.testingResults=void 0):d(this))},report:function(){this.reporting&&(this.sync(!1),this.reportArgs.push(this.token),this.invokeCallback(this.reportArgs),this.reportArgs=void 0)},invokeCallback:function(a){try{this.callback.apply(this.target,a)}catch(b){i._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+b)}},reset:function(){this.closed||(n&&(this.reporting=!1,Object.deliverChangeRecords(this.boundInternalCallback),this.reporting=!0),this.sync(!0))}};var t,u=!n||a.forceCollectObservers;i._allObserversCount=0,u&&(t=[]);var v=!1,w="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!v){if(w)return void Object.deliverAllChangeRecords();if(u){v=!0;var a=0,b={};do{a++;var c=t;t=[],b.anyChanged=!1;for(var d=0;d<c.length;d++){var e=c[d];e.closed||(n?e.deliver(b):e.check()&&(b.anyChanged=!0,e.report()),t.push(e))}}while(s>a&&b.anyChanged);i._allObserversCount=t.length,v=!1}}},u&&(a.Platform.clearObservers=function(){t=[]}),k.prototype=r({__proto__:i.prototype,connect:function(){n&&Object.observe(this.object,this.boundInternalCallback)},sync:function(){n||(this.oldObject=h(this.object))},check:function(a){var b,c;if(n){if(!a)return!1;c={},b=m(this.object,a,c)}else c=this.oldObject,b=g(this.object,this.oldObject);return f(b)?!1:(this.reportArgs=[b.added||{},b.removed||{},b.changed||{}],this.reportArgs.push(function(a){return c[a]}),!0)},disconnect:function(){n?this.object&&Object.unobserve(this.object,this.boundInternalCallback):this.oldObject=void 0}});var x=Object.getPrototypeOf({}),y=Object.getPrototypeOf([]);l.prototype={reset:function(){this.isObserved=!this.isObserved},observe:function(a){if(c(a)&&a!==x&&a!==y){var b=this.arr.indexOf(a);b>=0&&this.arr[b+1]===this.isObserved||(0>b&&(b=this.arr.length,this.arr[b]=a,Object.observe(a,this.callback)),this.arr[b+1]=this.isObserved,this.observe(Object.getPrototypeOf(a)))}},cleanup:function(){for(var a=0,b=0,c=this.isObserved;b<this.arr.length;){var d=this.arr[b];this.arr[b+1]==c?(b>a&&(this.arr[a]=d,this.arr[a+1]=c),a+=2):Object.unobserve(d,this.callback),b+=2}this.arr.length=a}};var z={"new":!0,updated:!0,deleted:!0};a.Observer=i,a.Observer.hasObjectObserve=n,a.ObjectObserver=k}((c.Number={isNaN:window.isNaN})?c:c)}).call(this,"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],2:[function(a,b){function c(a,b){return-1!==d(a,b)}var d=a("./indexOf");b.exports=c},{"./indexOf":5}],3:[function(a,b){function c(a,b,c){b=d(b,c);var e=[];if(null==a)return e;for(var f,g=-1,h=a.length;++g<h;)f=a[g],b(f,g,a)&&e.push(f);return e}var d=a("../function/makeIterator_");b.exports=c},{"../function/makeIterator_":11}],4:[function(a,b){function c(a,b,c){if(null!=a)for(var d=-1,e=a.length;++d<e&&b.call(c,a[d],d,a)!==!1;);}b.exports=c},{}],5:[function(a,b){function c(a,b,c){if(c=c||0,null==a)return-1;for(var d=a.length,e=0>c?d+c:c;d>e;){if(a[e]===b)return e;e++}return-1}b.exports=c},{}],6:[function(a,b){function c(a){return null!=a&&""!==a}function d(a,b){return b=b||"",e(a,c).join(b)}var e=a("./filter");b.exports=d},{"./filter":3}],7:[function(a,b){function c(a,b,c){var d=a.length;b=null==b?0:0>b?Math.max(d+b,0):Math.min(b,d),c=null==c?d:0>c?Math.max(d+c,0):Math.min(c,d);for(var e=[];c>b;)e.push(a[b++]);return e}b.exports=c},{}],8:[function(a,b){function c(a,b){if(null==a)return[];if(a.length<2)return a;null==b&&(b=d);var f,g,h;return f=~~(a.length/2),g=c(a.slice(0,f),b),h=c(a.slice(f,a.length),b),e(g,h,b)}function d(a,b){return b>a?-1:a>b?1:0}function e(a,b,c){for(var d=[];a.length&&b.length;)d.push(c(a[0],b[0])<=0?a.shift():b.shift());return a.length&&d.push.apply(d,a),b.length&&d.push.apply(d,b),d}b.exports=c},{}],9:[function(a,b){function c(a,b){var c={};if(null==a)return c;var e,f=-1,g=a.length;if(d(b))for(;++f<g;)e=a[f],c[b(e)]=e;else for(;++f<g;)e=a[f],c[e[b]]=e;return c}var d=a("../lang/isFunction");b.exports=c},{"../lang/isFunction":15}],10:[function(a,b){function c(a){return a}b.exports=c},{}],11:[function(a,b){function c(a,b){if(null==a)return d;switch(typeof a){case"function":return"undefined"!=typeof b?function(c,d,e){return a.call(b,c,d,e)}:a;case"object":return function(b){return f(b,a)};case"string":case"number":return e(a)}}var d=a("./identity"),e=a("./prop"),f=a("../object/deepMatches");b.exports=c},{"../object/deepMatches":20,"./identity":10,"./prop":12}],12:[function(a,b){function c(a){return function(b){return b[a]}}b.exports=c},{}],13:[function(a,b){var c=a("./isKind"),d=Array.isArray||function(a){return c(a,"Array")};b.exports=d},{"./isKind":16}],14:[function(a,b){function c(a){if(null==a)return!1;if("string"==typeof a||e(a))return!a.length;if("object"==typeof a||"function"==typeof a){var b=!0;return d(a,function(){return b=!1,!1}),b}return!1}var d=a("../object/forOwn"),e=a("./isArray");b.exports=c},{"../object/forOwn":23,"./isArray":13}],15:[function(a,b){function c(a){return d(a,"Function")}var d=a("./isKind");b.exports=c},{"./isKind":16}],16:[function(a,b){function c(a,b){return d(a)===b}var d=a("./kindOf");b.exports=c},{"./kindOf":18}],17:[function(a,b){function c(a){return!!a&&"object"==typeof a&&a.constructor===Object}b.exports=c},{}],18:[function(a,b){function c(a){return null===a?"Null":a===d?"Undefined":e.exec(f.call(a))[1]}var d,e=/^\[object (.*)\]$/,f=Object.prototype.toString;b.exports=c},{}],19:[function(a,b){function c(a){return null==a?"":a.toString()}b.exports=c},{}],20:[function(a,b){function c(a,b){for(var c=-1,d=a.length;++c<d;)if(f(a[c],b))return!0;return!1}function d(a,b){for(var d=-1,e=b.length;++d<e;)if(!c(a,b[d]))return!1;return!0}function e(a,b){var c=!0;return g(b,function(b,d){return f(a[d],b)?void 0:c=!1}),c}function f(a,b){return a&&"object"==typeof a?h(a)&&h(b)?d(a,b):e(a,b):a===b}var g=a("./forOwn"),h=a("../lang/isArray");b.exports=f},{"../lang/isArray":13,"./forOwn":23}],21:[function(a,b){function c(a){for(var b,c=0,f=arguments.length;++c<f;)b=arguments[c],b&&e(b,d,a);return a}function d(a,b){var d=this[b];f(a)&&f(d)?c(d,a):this[b]=a}var e=a("./forOwn"),f=a("../lang/isPlainObject");b.exports=c},{"../lang/isPlainObject":17,"./forOwn":23}],22:[function(a,b){function c(){g=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],f=!0;for(var a in{toString:null})f=!1}function d(a,b,d){var i,j=0;null==f&&c();for(i in a)if(e(b,a,i,d)===!1)break;if(f)for(var k=a.constructor,l=!!k&&a===k.prototype;(i=g[j++])&&("constructor"===i&&(l||!h(a,i))||a[i]===Object.prototype[i]||e(b,a,i,d)!==!1););}function e(a,b,c,d){return a.call(d,b[c],c,b)}var f,g,h=a("./hasOwn");b.exports=d},{"./hasOwn":24}],23:[function(a,b){function c(a,b,c){e(a,function(e,f){return d(a,f)?b.call(c,a[f],f,a):void 0})}var d=a("./hasOwn"),e=a("./forIn");b.exports=c},{"./forIn":22,"./hasOwn":24}],24:[function(a,b){function c(a,b){return Object.prototype.hasOwnProperty.call(a,b)}b.exports=c},{}],25:[function(a,b){function c(a,b){return b?(d(b.split("."),function(b){a[b]||(a[b]={}),a=a[b]}),a):a}var d=a("../array/forEach");b.exports=c},{"../array/forEach":4}],26:[function(a,b){function c(a){for(var b,c="string"!=typeof arguments[1]?arguments[1]:d(arguments,1),e={},f=0;b=c[f++];)e[b]=a[b];return e}var d=a("../array/slice");b.exports=c},{"../array/slice":7}],27:[function(a,b){function c(a,b,c){var e=/^(.+)\.(.+)$/.exec(b);e?d(a,e[1])[e[2]]=c:a[b]=c}var d=a("./namespace");b.exports=c},{"./namespace":25}],28:[function(a,b){function c(){var a=d(e(arguments),"/");return a.replace(/([^:\/]|^)\/{2,}/g,"$1/")}var d=a("../array/join"),e=a("../array/slice");b.exports=c},{"../array/join":6,"../array/slice":7}],29:[function(a,b){function c(a){return a=d(a),a.toUpperCase()}var d=a("../lang/toString");b.exports=c},{"../lang/toString":19}],30:[function(a,b){function c(){var a=this.defaults={queryTransform:function(a,b){return b}};this.$get=["$http","$log","DSUtils",function(b,c,d){function e(a){var d=(new Date).getTime();return b(a).then(function(a){return c.debug(a.config.method+" request:"+a.config.url+" Time taken: "+((new Date).getTime()-d)+"ms",arguments),a})}function f(a,b){return b=b||{},e(d.deepMixIn(b,{url:a,method:"GET"}))}function g(a,b,c){return c=c||{},e(d.deepMixIn(c,{url:a,data:b,method:"POST"}))}function h(a,b,c){return c=c||{},e(d.deepMixIn(c,{url:a,data:b,method:"PUT"}))}function i(a,b){return b=b||{},this.HTTP(d.deepMixIn(b,{url:a,method:"DELETE"}))}function j(a,b,c){return c=c||{},this.POST(d.makePath(c.baseUrl||a.baseUrl,a.endpoint),b,c)}function k(a,b,c){return c=c||{},this.DEL(d.makePath(c.baseUrl||a.baseUrl,a.endpoint,b),c)}function l(b,c,e){return e=e||{},e.params=e.params||{},c&&(c=a.queryTransform(b.name,c),d.deepMixIn(e.params,c)),this.DEL(d.makePath(e.baseUrl||b.baseUrl,b.endpoint),e)}function m(a,b,c){return c=c||{},this.GET(d.makePath(c.baseUrl||a.baseUrl,a.endpoint,b),c)}function n(b,c,e){return e=e||{},e.params=e.params||{},c&&(c=a.queryTransform(b.name,c),d.deepMixIn(e.params,c)),this.GET(d.makePath(e.baseUrl||b.baseUrl,b.endpoint),e)}function o(a,b,c,e){return e=e||{},this.PUT(d.makePath(e.baseUrl||a.baseUrl,a.endpoint,b),c,e)}function p(b,c,e,f){return f=f||{},f.params=f.params||{},e&&(e=a.queryTransform(b.name,e),d.deepMixIn(f.params,e)),this.PUT(d.makePath(f.baseUrl||b.baseUrl,b.endpoint),c,f)}return{defaults:a,HTTP:e,GET:f,POST:g,PUT:h,DEL:i,find:m,findAll:n,create:j,update:o,updateAll:p,destroy:k,destroyAll:l}}]}b.exports=c},{}],31:[function(a,b){function c(){this.$get=["$q","DSUtils",function(a,b){function c(b){var c=a.defer();try{var d=localStorage.getItem(b);c.resolve(d?angular.fromJson(d):void 0)}catch(e){c.reject(e)}return c.promise}function d(c,d){var e=a.defer();try{var f=localStorage.getItem(c);f?(f=angular.fromJson(f),b.deepMixIn(f,d),e.resolve(localStorage.setItem(c,angular.toJson(f)))):e.resolve(localStorage.setItem(c,angular.toJson(d)))}catch(g){e.reject(g)}return e.promise}function e(b){var c=a.defer();try{c.resolve(localStorage.removeItem(b))}catch(d){c.reject(d)}return c.promise}function f(a,c,d){return d=d||{},e(b.makePath(d.baseUrl||a.baseUrl,a.endpoint,c),d)}function g(a,d,e){return e=e||{},c(b.makePath(e.baseUrl||a.baseUrl,a.endpoint,d),e)}function h(a,e,f,g){return g=g||{},d(b.makePath(g.baseUrl||a.baseUrl,a.endpoint,e),f,g).then(function(){return c(b.makePath(g.baseUrl||a.baseUrl,a.endpoint,e))})}return{find:g,findAll:function(){throw new Error("Not supported!")},create:function(){throw new Error("Not supported!")},update:h,updateAll:function(){throw new Error("Not supported!")},destroy:f,destroyAll:function(){throw new Error("Not supported!")}}}]}b.exports=c},{}],32:[function(a,b){function c(a,b,c){var e=this.$q.defer(),f=e.promise;try{if(c=c||{},!this.definitions[a])throw new this.errors.NER(d+a);if(!this.utils.isObject(b))throw new this.errors.IA(d+"attrs: Must be an object!");var g=this.definitions[a],h=this.store[a],i=this;f=f.then(function(b){return i.$q.promisify(g.beforeValidate)(a,b)}).then(function(b){return i.$q.promisify(g.validate)(a,b)}).then(function(b){return i.$q.promisify(g.afterValidate)(a,b)}).then(function(b){return i.$q.promisify(g.beforeCreate)(a,b)}).then(function(b){return i.adapters[c.adapter||g.defaultAdapter].create(g,g.serialize(a,b),c)}).then(function(b){return i.$q.promisify(g.afterCreate)(a,g.deserialize(a,b))}).then(function(a){var b=i.inject(g.name,a),c=b[g.idAttribute];return h.previousAttributes[c]=i.utils.deepMixIn({},b),h.saved[c]=i.utils.updateTimestamp(h.saved[c]),i.get(g.name,c)}),e.resolve(b)}catch(j){e.reject(j)}return f}var d="DS.create(resourceName, attrs[, options]): ";b.exports=c},{}],33:[function(a,b){function c(a,b,c){var e=this.$q.defer(),f=e.promise;try{if(c=c||{},!this.definitions[a])throw new this.errors.NER(d+a);if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new this.errors.IA(d+"id: Must be a string or a number!");var g=this.get(a,b);if(!g)throw new this.errors.R(d+'id: "'+b+'" not found!');var h=this.definitions[a],i=this;f=f.then(function(b){return i.$q.promisify(h.beforeDestroy)(a,b)}).then(function(){return i.adapters[c.adapter||h.defaultAdapter].destroy(h,b,c)}).then(function(){return i.$q.promisify(h.afterDestroy)(a,g)}).then(function(){return i.eject(a,b),b}),e.resolve(g)}catch(j){e.reject(j)}return f}var d="DS.destroy(resourceName, id): ";b.exports=c},{}],34:[function(a,b){function c(a,b,c){var e=this.$q.defer(),f=e.promise;try{var g=this,h=this.errors.IA;if(c=c||{},!this.definitions[a])throw new this.errors.NER(d+a);if(!this.utils.isObject(b))throw new h(d+"params: Must be an object!");if(!this.utils.isObject(c))throw new h(d+"options: Must be an object!");var i=this.definitions[a];f=f.then(function(){return g.adapters[c.adapter||i.defaultAdapter].destroyAll(i,b,c)}).then(function(){return g.ejectAll(a,b)}),e.resolve()}catch(j){e.reject(j)}return f}var d="DS.destroyAll(resourceName, params[, options]): ";b.exports=c},{}],35:[function(a,b){function c(a,b,c){var e=this.$q.defer(),f=e.promise;try{var g=this.errors.IA;if(c=c||{},!this.definitions[a])throw new this.errors.NER(d+a);if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new g(d+"id: Must be a string or a number!");if(!this.utils.isObject(c))throw new g(d+"options: Must be an object!");c.cacheResponse="cacheResponse"in c?!!c.cacheResponse:!0;var h=this.definitions[a],i=this.store[a],j=this;if(c.bypassCache&&delete i.completedQueries[b],!(b in i.completedQueries))return b in i.pendingQueries||(f=i.pendingQueries[b]=j.adapters[c.adapter||h.defaultAdapter].find(h,b,c).then(function(d){var e=h.deserialize(a,d);return c.cacheResponse?(delete i.pendingQueries[b],i.completedQueries[b]=(new Date).getTime(),j.inject(a,e)):e},function(a){return delete i.pendingQueries[b],j.$q.reject(a)})),i.pendingQueries[b];e.resolve(j.get(a,b))}catch(k){e.reject(k)}return f}var d="DS.find(resourceName, id[, options]): ";b.exports=c},{}],36:[function(a,b){function c(a,b,c,d){var e=this.store[c];return b=b||[],delete e.pendingQueries[d],e.completedQueries[d]=(new Date).getTime(),e.collectionModified=a.updateTimestamp(e.collectionModified),this.inject(c,b)}function d(a,b,d,e){var f=this.definitions[b],g=this.store[b],h=this,i=a.toJson(d);return e.bypassCache&&delete g.completedQueries[i],i in g.completedQueries?this.filter(b,d,e):(i in g.pendingQueries||(g.pendingQueries[i]=h.adapters[e.adapter||f.defaultAdapter].findAll(f,d,e).then(function(d){var g=f.deserialize(b,d);if(!e.cacheResponse)return g;try{return c.apply(h,[a,g,b,i])}catch(j){return h.$q.reject(j)}},function(a){return delete g.pendingQueries[i],h.$q.reject(a)})),g.pendingQueries[i])}function e(a,b,c){var e=this.$q.defer(),g=e.promise;try{var h=this.errors.IA,i=this;if(c=c||{},b=b||{},!this.definitions[a])throw new this.errors.NER(f+a);if(!this.utils.isObject(b))throw new h(f+"params: Must be an object!");if(!this.utils.isObject(c))throw new h(f+"options: Must be an object!");c.cacheResponse="cacheResponse"in c?!!c.cacheResponse:!0,g=g.then(function(){return d.apply(i,[i.utils,a,b,c])}),e.resolve()}catch(j){e.reject(j)}return g}var f="DS.findAll(resourceName, params[, options]): ";b.exports=e},{}],37:[function(a,b){b.exports={create:a("./create"),destroy:a("./destroy"),destroyAll:a("./destroyAll"),find:a("./find"),findAll:a("./findAll"),loadRelations:a("./loadRelations"),refresh:a("./refresh"),save:a("./save"),update:a("./update"),updateAll:a("./updateAll")}},{"./create":32,"./destroy":33,"./destroyAll":34,"./find":35,"./findAll":36,"./loadRelations":38,"./refresh":39,"./save":40,"./update":41,"./updateAll":42}],38:[function(a,b){function c(a,b,c,e){var f=this.$q.defer(),g=f.promise;try{var h=this.errors.IA;if(e=e||{},(angular.isString(b)||angular.isNumber(b))&&(b=this.get(a,b)),angular.isString(c)&&(c=[c]),!this.definitions[a])throw new this.errors.NER(d+a);if(!this.utils.isObject(b))throw new h(d+"instance(Id): Must be a string, number or object!");if(!this.utils.isArray(c))throw new h(d+"relations: Must be a string or an array!");if(!this.utils.isObject(e))throw new h(d+"options: Must be an object!");var i=this.definitions[a],j=this,k=[],l=[];j.utils.forOwn(i.relations,function(a,d){j.utils.forOwn(a,function(a,f){if(j.utils.contains(c,f)){var g,h={};h[a.foreignKey]=b[i.idAttribute],"hasMany"===d?g=j.findAll(f,h,e):"hasOne"===d?a.localKey&&b[a.localKey]?g=j.find(f,b[a.localKey],e):a.foreignKey&&(g=j.findAll(f,h,e)):g=j.find(f,b[a.localKey],e),g&&(k.push(g),l.push(a.localField))}})}),g=g.then(function(){return j.$q.all(k)}).then(function(a){return angular.forEach(l,function(c,d){b[c]=a[d]}),b}),f.resolve()}catch(m){f.reject(m)}return g}var d="DS.loadRelations(resourceName, instance(Id), relations[, options]): ";b.exports=c},{}],39:[function(a,b){function c(a,b,c){var e=this.errors.IA;if(c=c||{},this.definitions[a]){if(this.utils.isString(b)||this.utils.isNumber(b)){if(this.utils.isObject(c))return c.bypassCache=!0,this.get(a,b)?this.find(a,b,c):!1;throw new e(d+"options: Must be an object!")}throw new e(d+"id: Must be a string or a number!")}throw new this.errors.NER(d+a)}var d="DS.refresh(resourceName, id[, options]): ";b.exports=c},{}],40:[function(a,b){function c(a,b,c){var e=this.$q.defer(),f=e.promise;try{var g=this.errors.IA;if(c=c||{},!this.definitions[a])throw new this.errors.NER(d+a);if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new g(d+"id: Must be a string or a number!");if(!this.utils.isObject(c))throw new g(d+"options: Must be an object!");var h=this.get(a,b);if(!h)throw new this.errors.R(d+'id: "'+b+'" not found!');var i=this.definitions[a],j=this.store[a],k=this;f=f.then(function(b){return k.$q.promisify(i.beforeValidate)(a,b)}).then(function(b){return k.$q.promisify(i.validate)(a,b)}).then(function(b){return k.$q.promisify(i.afterValidate)(a,b)}).then(function(b){return k.$q.promisify(i.beforeUpdate)(a,b)}).then(function(d){if(c.changesOnly){j.observers[b].deliver();var e=[],f=k.changes(a,b);for(var g in f.added)e.push(g);for(g in f.changed)e.push(g);if(f=k.utils.pick(d,e),k.utils.isEmpty(f))return d;d=f}return k.adapters[c.adapter||i.defaultAdapter].update(i,b,i.serialize(a,d),c)}).then(function(b){return k.$q.promisify(i.afterUpdate)(a,i.deserialize(a,b))}).then(function(d){return k.inject(i.name,d,c),j.previousAttributes[b]=k.utils.deepMixIn({},d),j.saved[b]=k.utils.updateTimestamp(j.saved[b]),k.get(a,b)}),e.resolve(h)}catch(l){e.reject(l)}return f}var d="DS.save(resourceName, id[, options]): ";b.exports=c},{}],41:[function(a,b){function c(a,b,c,e){var f=this.$q.defer(),g=f.promise;try{var h=this.errors.IA;if(e=e||{},!this.definitions[a])throw new this.errors.NER(d+a);if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new h(d+"id: Must be a string or a number!");if(!this.utils.isObject(c))throw new h(d+"attrs: Must be an object!");if(!this.utils.isObject(e))throw new h(d+"options: Must be an object!");var i=this.definitions[a],j=this.store[a],k=this;e.cacheResponse="cacheResponse"in e?!!e.cacheResponse:!0,g=g.then(function(b){return k.$q.promisify(i.beforeValidate)(a,b)}).then(function(b){return k.$q.promisify(i.validate)(a,b)}).then(function(b){return k.$q.promisify(i.afterValidate)(a,b)}).then(function(b){return k.$q.promisify(i.beforeUpdate)(a,b)}).then(function(c){return k.adapters[e.adapter||i.defaultAdapter].update(i,b,i.serialize(a,c),e)}).then(function(b){return k.$q.promisify(i.afterUpdate)(a,i.deserialize(a,b))}).then(function(a){if(e.cacheResponse){var b=k.inject(i.name,a,e),c=b[i.idAttribute];return j.previousAttributes[c]=k.utils.deepMixIn({},b),j.saved[c]=k.utils.updateTimestamp(j.saved[c]),k.get(i.name,c)}return a}),f.resolve(c)}catch(l){f.reject(l)}return g}var d="DS.update(resourceName, id, attrs[, options]): ";b.exports=c},{}],42:[function(a,b){function c(a,b,c,e){var f=this.$q.defer(),g=f.promise;try{var h=this.errors.IA;if(e=e||{},!this.definitions[a])throw new this.errors.NER(d+a);if(!this.utils.isObject(b))throw new h(d+"attrs: Must be an object!");if(!this.utils.isObject(c))throw new h(d+"params: Must be an object!");if(!this.utils.isObject(e))throw new h(d+"options: Must be an object!");var i=this.definitions[a],j=this;e.cacheResponse="cacheResponse"in e?!!e.cacheResponse:!0,g=g.then(function(b){return j.$q.promisify(i.beforeValidate)(a,b)}).then(function(b){return j.$q.promisify(i.validate)(a,b)}).then(function(b){return j.$q.promisify(i.afterValidate)(a,b)}).then(function(b){return j.$q.promisify(i.beforeUpdate)(a,b)}).then(function(b){return j.adapters[e.adapter||i.defaultAdapter].updateAll(i,i.serialize(a,b),c,e)}).then(function(b){return j.$q.promisify(i.afterUpdate)(a,i.deserialize(a,b))}).then(function(a){return e.cacheResponse?j.inject(i.name,a,e):a}),f.resolve(b)}catch(k){f.reject(k)}return g}var d="DS.updateAll(resourceName, attrs, params[, options]): ";b.exports=c},{}],43:[function(a,b){function c(a,b,c){c(null,b)}function d(){}function e(){var b=this.defaults=new d;this.$get=["$rootScope","$log","$q","DSHttpAdapter","DSLocalStorageAdapter","DSUtils","DSErrors",function(c,d,e,f,g,h,i){var j,k=a("./sync_methods"),l=a("./async_methods");try{j=angular.injector(["angular-data.DSCacheFactory"]).get("DSCacheFactory")}catch(m){d.warn(m),d.warn("DSCacheFactory is unavailable. Resorting to the lesser capabilities of $cacheFactory."),j=angular.injector(["ng"]).get("$cacheFactory")}var n={$rootScope:c,$log:d,$q:e,cacheFactory:j,defaults:b,store:{},definitions:{},adapters:{DSHttpAdapter:f,DSLocalStorageAdapter:g},errors:i,utils:h};h.deepFreeze(k),h.deepFreeze(l),h.deepMixIn(n,k),h.deepMixIn(n,l),h.deepFreeze(n.errors),h.deepFreeze(n.utils);var o=c.$new();return o.$watch(function(){return(new Date).getTime()/100|0},function(){n.digest()}),n}]}a("../utils")[0]();d.prototype.idAttribute="id",d.prototype.defaultAdapter="DSHttpAdapter",d.prototype.filter=function(a,b,c,d){var e=this,f=a,g=null,h={skip:"",offset:"",where:"",limit:"",orderBy:"",sort:""};g=this.utils.isObject(c.where)?c.where:{},d.allowSimpleWhere&&this.utils.forOwn(c,function(a,b){b in h||b in g||(g[b]={"==":a})}),this.utils.isEmpty(g)&&(g=null),g&&(f=this.utils.filter(f,function(a){var b=!0,c=!0;return e.utils.forOwn(g,function(d,f){e.utils.isString(d)?d={"===":d}:e.utils.isNumber(d)&&(d={"==":d}),e.utils.isObject(d)&&e.utils.forOwn(d,function(d,g){"=="===g?c=b?a[f]==d:c&&a[f]==d:"==="===g?c=b?a[f]===d:c&&a[f]===d:"!="===g?c=b?a[f]!=d:c&&a[f]!=d:"!=="===g?c=b?a[f]!==d:c&&a[f]!==d:">"===g?c=b?a[f]>d:c&&a[f]>d:">="===g?c=b?a[f]>=d:c&&a[f]>=d:"<"===g?c=b?a[f]<d:c&&a[f]<d:"<="===g?c=b?a[f]<=d:c&&a[f]<=d:"in"===g?c=b?e.utils.contains(d,a[f]):c&&e.utils.contains(d,a[f]):"|=="===g?c=b?a[f]==d:c||a[f]==d:"|==="===g?c=b?a[f]===d:c||a[f]===d:"|!="===g?c=b?a[f]!=d:c||a[f]!=d:"|!=="===g?c=b?a[f]!==d:c||a[f]!==d:"|>"===g?c=b?a[f]>d:c||a[f]>d:"|>="===g?c=b?a[f]>=d:c||a[f]>=d:"|<"===g?c=b?a[f]<d:c||a[f]<d:"|<="===g?c=b?a[f]<=d:c||a[f]<=d:"|in"===g&&(c=b?e.utils.contains(d,a[f]):c||e.utils.contains(d,a[f])),b=!1})}),c}));var i=null;this.utils.isString(c.orderBy)?i=[[c.orderBy,"ASC"]]:this.utils.isArray(c.orderBy)&&(i=c.orderBy),!i&&this.utils.isString(c.sort)?i=[[c.sort,"ASC"]]:!i&&this.utils.isArray(c.sort)&&(i=c.sort),i&&angular.forEach(i,function(a){if(e.utils.isString(a))a=[a,"ASC"];else if(!e.utils.isArray(a))throw new e.errors.IllegalArgumentError("DS.filter(resourceName[, params][, options]): "+angular.toJson(a)+": Must be a string or an array!",{params:{"orderBy[i]":{actual:typeof a,expected:"string|array"}}});f=e.utils.sort(f,function(b,c){var d=b[a[0]],f=c[a[0]];return e.utils.isString(d)&&(d=e.utils.upperCase(d)),e.utils.isString(f)&&(f=e.utils.upperCase(f)),"DESC"===a[1]?d>f?-1:f>d?1:0:f>d?-1:d>f?1:0})});var j=angular.isNumber(c.limit)?c.limit:null,k=null;return angular.isNumber(c.skip)?k=c.skip:angular.isNumber(c.offset)&&(k=c.offset),j&&k?f=this.utils.slice(f,k,Math.min(f.length,k+j)):this.utils.isNumber(j)?f=this.utils.slice(f,0,Math.min(f.length,j)):this.utils.isNumber(k)&&(f=k<f.length?this.utils.slice(f,k):[]),f},d.prototype.baseUrl="",d.prototype.endpoint="",d.prototype.beforeValidate=c,d.prototype.validate=c,d.prototype.afterValidate=c,d.prototype.beforeCreate=c,d.prototype.afterCreate=c,d.prototype.beforeUpdate=c,d.prototype.afterUpdate=c,d.prototype.beforeDestroy=c,d.prototype.afterDestroy=c,d.prototype.beforeInject=function(a,b){return b},d.prototype.afterInject=function(a,b){return b},d.prototype.serialize=function(a,b){return b},d.prototype.deserialize=function(a,b){return b.data},b.exports=e},{"../utils":61,"./async_methods":37,"./sync_methods":54}],44:[function(a,b){function c(a,b,c,e,f){var g=this.errors.IA;if(!this.utils.isObject(a))throw new g(d+"scope: Must be an object!");if(!this.utils.isString(b))throw new g(d+"expr: Must be a string!");if(!this.definitions[c])throw new this.errors.NER(d+c);if(!this.utils.isObject(e))throw new g(d+"params: Must be an object!");var h=this;try{return a.$watch(function(){return h.lastModified(c)},function(){var d=h.filter(c,e);h.utils.set(a,b,d),f&&f(null,d)})}catch(i){if(!f)throw i;f(i)}}var d="DS.bindAll(scope, expr, resourceName, params[, cb]): ";b.exports=c},{}],45:[function(a,b){function c(a,b,c,e,f){var g=this.errors.IA;if(!this.utils.isObject(a))throw new g(d+"scope: Must be an object!");if(!this.utils.isString(b))throw new g(d+"expr: Must be a string!");if(!this.definitions[c])throw new this.errors.NER(d+c);if(!this.utils.isString(e)&&!this.utils.isNumber(e))throw new g(d+"id: Must be a string or a number!");var h=this;try{return a.$watch(function(){return h.lastModified(c,e)},function(){var d=h.get(c,e);h.utils.set(a,b,d),f&&f(null,d)})}catch(i){if(!f)throw i;f(i)}}var d="DS.bindOne(scope, expr, resourceName, id[, cb]): ";b.exports=c},{}],46:[function(a,b){function c(a,b){if(!this.definitions[a])throw new this.errors.NER(d+a);if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new this.errors.IA(d+"id: Must be a string or a number!");var c=this.get(a,b);return c?(this.store[a].observers[b].deliver(),this.utils.diffObjectFromOldObject(c,this.store[a].previousAttributes[b])):void 0}var d="DS.changes(resourceName, id): ";b.exports=c},{}],47:[function(require,module,exports){function Resource(a,b){a.deepMixIn(this,b),this.endpoint="endpoint"in b?b.endpoint:this.name}function defineResource(definition){var IA=this.errors.IA;if(this.utils.isString(definition)&&(definition={name:definition}),!this.utils.isObject(definition))throw new IA(errorPrefix+"definition: Must be an object!");if(!this.utils.isString(definition.name))throw new IA(errorPrefix+"definition.name: Must be a string!");if(definition.idAttribute&&!this.utils.isString(definition.idAttribute))throw new IA(errorPrefix+"definition.idAttribute: Must be a string!");if(definition.endpoint&&!this.utils.isString(definition.endpoint))throw new IA(errorPrefix+"definition.endpoint: Must be a string!");if(this.store[definition.name])throw new this.errors.R(errorPrefix+definition.name+" is already registered!");try{Resource.prototype=this.defaults,this.definitions[definition.name]=new Resource(this.utils,definition);var _this=this,def=this.definitions[definition.name],cache=this.cacheFactory("DS."+def.name,{maxAge:def.maxAge||null,recycleFreq:def.recycleFreq||1e3,cacheFlushInterval:def.cacheFlushInterval||null,deleteOnExpire:def.deleteOnExpire||"none",onExpire:function(a){_this.eject(def.name,a)},capacity:Number.MAX_VALUE,storageMode:"memory",storageImpl:null,disabled:!1,storagePrefix:"DS."+def.name});def.methods&&(def.class=definition.name[0].toUpperCase()+definition.name.substring(1),eval("function "+def.class+"() {}"),def[def.class]=eval(def.class),this.utils.deepMixIn(def[def.class].prototype,def.methods)),def.computed&&this.utils.forOwn(def.computed,function(a,b){def.methods&&b in def.methods&&_this.$log.warn(errorPrefix+'Computed property "'+b+'" conflicts with previously defined prototype method!');var c=a.toString().match(/function.*?\(([\s\S]*?)\)/),d=c[1].split(",");a.deps=_this.utils.filter(d,function(a){return!!a}),angular.forEach(a.deps,function(b,c){a.deps[c]=b.trim()})}),this.store[def.name]={collection:[],completedQueries:{},pendingQueries:{},index:cache,modified:{},saved:{},previousAttributes:{},observers:{},collectionModified:0}}catch(err){throw delete this.definitions[definition.name],delete this.store[definition.name],err}}var errorPrefix="DS.defineResource(definition): ";module.exports=defineResource},{}],48:[function(a,b){function c(){this.$rootScope.$$phase?d.Platform.performMicrotaskCheckpoint():this.$rootScope.$apply(function(){d.Platform.performMicrotaskCheckpoint()})}var d=a("../../../lib/observe-js/observe-js");b.exports=c},{"../../../lib/observe-js/observe-js":1}],49:[function(a,b){function c(a,b,c){for(var d=!1,e=0;e<b.collection.length;e++)if(b.collection[e][a.idAttribute]==c){d=!0;break}d&&(b.collection.splice(e,1),b.observers[c].close(),delete b.observers[c],b.index.remove(c),delete b.previousAttributes[c],delete b.modified[c],delete b.saved[c])}function d(a,b){if(!this.definitions[a])throw new this.errors.NER(e+a);if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new this.errors.IA(e+"id: Must be a string or a number!");
var d=this.store[a],f=this;this.$rootScope.$$phase?(c(f.definitions[a],d,b),d.collectionModified=f.utils.updateTimestamp(d.collectionModified)):this.$rootScope.$apply(function(){c(f.definitions[a],d,b),d.collectionModified=f.utils.updateTimestamp(d.collectionModified)}),delete this.store[a].completedQueries[b]}var e="DS.eject(resourceName, id): ";b.exports=d},{}],50:[function(a,b){function c(a,b,c){var d=this.utils.toJson(c),e=this.filter(a.name,c),f=this.utils.toLookup(e,a.idAttribute),g=this;angular.forEach(f,function(b,c){g.eject(a.name,c)}),delete b.completedQueries[d]}function d(a,b){if(b=b||{},!this.definitions[a])throw new this.errors.NER(e+a);if(!this.utils.isObject(b))throw new this.errors.IA(e+"params: Must be an object!");var d=this,f=this.store[a],g=this.utils.toJson(b);delete f.completedQueries[g],this.utils.isEmpty(b)&&(f.completedQueries={}),this.$rootScope.$$phase?(c.apply(d,[d.definitions[a],f,b]),f.collectionModified=this.utils.updateTimestamp(f.collectionModified)):this.$rootScope.$apply(function(){c.apply(d,[d.definitions[a],f,b]),f.collectionModified=d.utils.updateTimestamp(f.collectionModified)})}var e="DS.ejectAll(resourceName[, params]): ";b.exports=d},{}],51:[function(a,b){function c(a,b,c){var e=this.errors.IA;if(c=c||{},!this.definitions[a])throw new this.errors.NER(d+a);if(b&&!this.utils.isObject(b))throw new e(d+"params: Must be an object!");if(!this.utils.isObject(c))throw new e(d+"options: Must be an object!");var f=this.definitions[a],g=this.store[a];b=b||{},c.allowSimpleWhere="allowSimpleWhere"in c?!!c.allowSimpleWhere:!0;var h=this.utils.toJson(b);return h in g.completedQueries||!c.loadFromServer||g.pendingQueries[h]||this.findAll(a,b,c),f.filter.call(this,g.collection,a,b,c)}var d="DS.filter(resourceName[, params][, options]): ";b.exports=c},{}],52:[function(a,b){function c(a,b,c){var e=this.errors.IA;if(c=c||{},!this.definitions[a])throw new this.errors.NER(d+a);if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new e(d+"id: Must be a string or a number!");if(!this.utils.isObject(c))throw new e(d+"options: Must be an object!");var f=this,g=this.store[a].index.get(b);return!g&&c.loadFromServer&&this.find(a,b).then(null,function(a){return f.$q.reject(a)}),g}var d="DS.get(resourceName, id[, options]): ";b.exports=c},{}],53:[function(a,b){function c(a,b){return!(a.isEmpty(b.added)&&a.isEmpty(b.removed)&&a.isEmpty(b.changed))}function d(a,b){if(!this.definitions[a])throw new this.errors.NER(e+a);if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new this.errors.IA(e+"id: Must be a string or a number!");return this.get(a,b)?c(this.utils,this.changes(a,b)):!1}var e="DS.hasChanges(resourceName, id): ";b.exports=d},{}],54:[function(a,b){b.exports={defineResource:a("./defineResource"),bindOne:a("./bindOne"),bindAll:a("./bindAll"),eject:a("./eject"),ejectAll:a("./ejectAll"),filter:a("./filter"),get:a("./get"),inject:a("./inject"),lastModified:a("./lastModified"),lastSaved:a("./lastSaved"),digest:a("./digest"),changes:a("./changes"),previous:a("./previous"),hasChanges:a("./hasChanges")}},{"./bindAll":44,"./bindOne":45,"./changes":46,"./defineResource":47,"./digest":48,"./eject":49,"./ejectAll":50,"./filter":51,"./get":52,"./hasChanges":53,"./inject":55,"./lastModified":56,"./lastSaved":57,"./previous":58}],55:[function(a,b){function c(a,b,d){function e(c,d,e,f){var g=f(a.idAttribute);if(b.modified[g]=i.utils.updateTimestamp(b.modified[g]),b.collectionModified=i.utils.updateTimestamp(b.collectionModified),a.computed){var h=i.get(a.name,g);i.utils.forOwn(a.computed,function(a,b){var c=!1;if(angular.forEach(a.deps,function(a){(a in e||a in d||a in e||!(b in h))&&(c=!0)}),c){var f=[];angular.forEach(a.deps,function(a){f.push(h[a])}),h[b]=a.apply(h,f)}})}a.idAttribute in e&&j.error("Doh! You just changed the primary key of an object! I don't know how to handle this yet, so your data for the \""+a.name+'" resource is now in an undefined (probably broken) state.')}var h,i=this,j=i.$log;if(i.utils.isArray(d)){h=[];for(var k=0;k<d.length;k++)h.push(c.call(i,a,b,d[k]))}else{if(a.computed&&a.computed[a.idAttribute]){var l=[];angular.forEach(a.computed[a.idAttribute].deps,function(a){l.push(d[a])}),d[a.idAttribute]=a.computed[a.idAttribute].apply(d,l)}if(!(a.idAttribute in d))throw new i.errors.R(g+"attrs: Must contain the property specified by `idAttribute`!");try{a.beforeInject(a.name,d);var m=d[a.idAttribute],n=this.get(a.name,m);n?(i.utils.deepMixIn(n,d),"function"==typeof b.index.touch?b.index.touch(m):b.index.put(m,b.index.get(m)),b.observers[m].deliver()):(n=a.class?d instanceof a[a.class]?d:new a[a.class]:{},b.previousAttributes[m]={},i.utils.deepMixIn(n,d),i.utils.deepMixIn(b.previousAttributes[m],d),b.collection.push(n),b.observers[m]=new f.ObjectObserver(n,e),b.index.put(m,n),e({},{},{},function(){return m})),b.saved[m]=i.utils.updateTimestamp(b.saved[m]),a.afterInject(a.name,n),h=n}catch(o){j.error(o),j.error("inject failed!",a.name,d)}}return h}function d(a,b){var c=this;c.utils.forOwn(a.relations,function(a,d){c.utils.forOwn(a,function(a,e){if(c.definitions[e]&&b[a.localField])try{b[a.localField]=c.inject(e,b[a.localField])}catch(f){c.$log.error(g+"Failed to inject "+d+' relation: "'+e+'"!',f)}})})}function e(a,b,e){var f=this.errors.IA;if(e=e||{},!this.definitions[a])throw new this.errors.NER(g+a);if(!this.utils.isObject(b)&&!this.utils.isArray(b))throw new f(g+"attrs: Must be an object or an array!");if(!this.utils.isObject(e))throw new f(g+"options: Must be an object!");var h,i=this.definitions[a],j=this.store[a],k=this;return this.$rootScope.$$phase?h=c.call(k,i,j,b):this.$rootScope.$apply(function(){h=c.call(k,i,j,b)}),i.relations&&d.call(k,i,h),h}var f=a("../../../lib/observe-js/observe-js"),g="DS.inject(resourceName, attrs[, options]): ";b.exports=e},{"../../../lib/observe-js/observe-js":1}],56:[function(a,b){function c(a,b){if(!this.definitions[a])throw new this.errors.NER(d+a);if(b&&!this.utils.isString(b)&&!this.utils.isNumber(b))throw new this.errors.IA(d+"id: Must be a string or a number!");return b?(b in this.store[a].modified||(this.store[a].modified[b]=0),this.store[a].modified[b]):this.store[a].collectionModified}var d="DS.lastModified(resourceName[, id]): ";b.exports=c},{}],57:[function(a,b){function c(a,b){if(!this.definitions[a])throw new this.errors.NER(d+a);if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new this.errors.IA(d+"id: Must be a string or a number!");return b in this.store[a].saved||(this.store[a].saved[b]=0),this.store[a].saved[b]}var d="DS.lastSaved(resourceName[, id]): ";b.exports=c},{}],58:[function(a,b){function c(a,b){if(!this.definitions[a])throw new this.errors.NER(d+a);if(!this.utils.isString(b)&&!this.utils.isNumber(b))throw new this.errors.IA(d+"id: Must be a string or a number!");return angular.copy(this.store[a].previousAttributes[b])}var d="DS.previous(resourceName, id): ";b.exports=c},{}],59:[function(a,b){function c(a){Error.call(this),"function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.type=this.constructor.name,this.message=a||"Illegal Argument!"}function d(a){Error.call(this),"function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.type=this.constructor.name,this.message=a||"RuntimeError Error!"}function e(a){Error.call(this),"function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.type=this.constructor.name,this.message=(a||"")+" is not a registered resource!"}c.prototype=Object.create(Error.prototype),c.prototype.constructor=c,d.prototype=Object.create(Error.prototype),d.prototype.constructor=d,e.prototype=Object.create(Error.prototype),e.prototype.constructor=e,b.exports=[function(){return{IllegalArgumentError:c,IA:c,RuntimeError:d,R:d,NonexistentResourceError:e,NER:e}}]},{}],60:[function(a){!function(b,c){"use strict";c.module("angular-data.DS",["ng"]).factory("DSUtils",a("./utils")).factory("DSErrors",a("./errors")).provider("DSHttpAdapter",a("./adapters/http")).provider("DSLocalStorageAdapter",a("./adapters/localStorage")).provider("DS",a("./datastore")).config(["$provide",function(a){a.decorator("$q",["$delegate",function(a){return a.promisify=function(a,b){var c=this;return function(){var d=c.defer(),e=Array.prototype.slice.apply(arguments);e.push(function(a,b){a?d.reject(a):d.resolve(b)});try{a.apply(b||this,e)}catch(f){d.reject(f)}return d.promise}},a}])}])}(window,window.angular)},{"./adapters/http":30,"./adapters/localStorage":31,"./datastore":43,"./errors":59,"./utils":61}],61:[function(a,b){b.exports=[function(){return{isString:angular.isString,isArray:angular.isArray,isObject:angular.isObject,isNumber:angular.isNumber,isFunction:angular.isFunction,isEmpty:a("mout/lang/isEmpty"),toJson:angular.toJson,makePath:a("mout/string/makePath"),upperCase:a("mout/string/upperCase"),deepMixIn:a("mout/object/deepMixIn"),forOwn:a("mout/object/forOwn"),pick:a("mout/object/pick"),set:a("mout/object/set"),contains:a("mout/array/contains"),filter:a("mout/array/filter"),toLookup:a("mout/array/toLookup"),slice:a("mout/array/slice"),sort:a("mout/array/sort"),updateTimestamp:function(a){var b="function"==typeof Date.now?Date.now():(new Date).getTime();return a&&a>=b?a+1:b},deepFreeze:function b(a){if("function"==typeof Object.freeze){var c,d;Object.freeze(a);for(d in a)c=a[d],a.hasOwnProperty(d)&&"object"==typeof c&&!Object.isFrozen(c)&&b(c)}},diffObjectFromOldObject:function(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var h in a)h in b||(c[h]=a[h]);return{added:c,removed:d,changed:e}}}}]},{"mout/array/contains":2,"mout/array/filter":3,"mout/array/slice":7,"mout/array/sort":8,"mout/array/toLookup":9,"mout/lang/isEmpty":14,"mout/object/deepMixIn":21,"mout/object/forOwn":23,"mout/object/pick":26,"mout/object/set":27,"mout/string/makePath":28,"mout/string/upperCase":29}]},{},[60]);

@@ -9,375 +9,373 @@ /*

module.exports = function (grunt) {
'use strict';
'use strict';
require('load-grunt-tasks')(grunt);
require('time-grunt')(grunt);
require('load-grunt-tasks')(grunt);
require('time-grunt')(grunt);
var dev = process.cwd().indexOf('/home/codetrain/angular-data') === -1,
pkg = grunt.file.readJSON('package.json');
var dev = process.cwd().indexOf('/home/jdobry/angular-data') === -1,
pkg = grunt.file.readJSON('package.json');
// Project configuration.
grunt.initConfig({
pkg: pkg,
clean: {
coverage: ['coverage/'],
dist: ['dist/'],
doc: ['doc/'],
afterDoc: [
'doc/resources/img/angular.png',
'doc/resources/img/angular_grey.png',
'doc/resources/img/AngularJS-small.png',
'doc/resources/img/docular-small.png',
'doc/resources/img/favicon.ico',
'doc/resources/img/grunt.png',
'doc/resources/img/grunt_grey.png',
'doc/resources/img/node.png',
'doc/resources/img/node_grey.png',
'doc/resources/angular/',
'doc/resources/doc_api_resources/doc_api.js',
'doc/resources/js/docs*.js',
'doc/resources/js/jquery*.js'
]
},
jshint: {
all: ['Gruntfile.js', 'src/**/*.js', 'test/*.js'],
jshintrc: '.jshintrc'
},
watch: {
files: ['src/**/*.js'],
tasks: ['build']
},
uglify: {
main: {
options: {
banner: '/**\n' +
'* @author Jason Dobry <jason.dobry@gmail.com>\n' +
'* @file angular-data.min.js\n' +
'* @version <%= pkg.version %> - Homepage <http://angular-data.codetrain.io/>\n' +
'* @copyright (c) 2014 Jason Dobry <https://github.com/jmdobry/>\n' +
'* @license MIT <https://github.com/jmdobry/angular-data/blob/master/LICENSE>\n' +
'*\n' +
'* @overview Data store for Angular.js.\n' +
'*/\n'
},
files: {
'dist/angular-data.min.js': ['dist/angular-data.js']
}
},
scripts: {
files: {
'doc/resources/js/libs.min.js': ['doc/resources/js/libs.js']
}
}
},
browserify: {
dist: {
files: {
'dist/angular-data.js': ['src/index.js']
},
options: {
alias: [
'lib/observe-js/observe-js.js:observejs',
'src/errors.js:errors',
'src/utils.js:utils'
],
// TODO: There's got to be a better way to consume observe-js without it polluting the global space
postBundleCB: function (err, src, next) {
if (err) {
next(err);
}
src = src.replace('(typeof global !== \'undefined\' && global ? global : window)', '((exports.Number = { isNaN: window.isNaN }) ? exports : exports)');
next(err, src);
}
}
}
},
karma: {
options: {
configFile: './karma.conf.js'
},
dev: {
browsers: ['Chrome'],
autoWatch: true,
singleRun: false,
exclude: [
'test/integration/datastore/cacheFactory.test.js'
]
},
min: {
browsers: ['Firefox', 'PhantomJS'],
options: {
files: [
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'bower_components/angular-cache/dist/angular-cache.js',
'dist/angular-data.min.js',
'karma.start.js',
'test/integration/**/*.js'
]
},
exclude: [
'test/integration/datastore/cacheFactory.test.js'
]
},
cacheFactory: {
browsers: ['Firefox', 'PhantomJS'],
options: {
files: [
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'dist/angular-data.js',
'karma.start.js',
'test/integration/datastore/cacheFactory.test.js'
]
}
},
ci: {
browsers: ['Firefox', 'PhantomJS'],
exclude: [
'test/integration/datastore/cacheFactory.test.js'
]
}
},
coveralls: {
options: {
coverage_dir: 'coverage'
}
},
// Project configuration.
grunt.initConfig({
pkg: pkg,
clean: {
coverage: ['coverage/'],
dist: ['dist/'],
doc: ['doc/'],
afterDoc: [
'doc/resources/img/angular.png',
'doc/resources/img/angular_grey.png',
'doc/resources/img/AngularJS-small.png',
'doc/resources/img/docular-small.png',
'doc/resources/img/favicon.ico',
'doc/resources/img/grunt.png',
'doc/resources/img/grunt_grey.png',
'doc/resources/img/node.png',
'doc/resources/img/node_grey.png',
'doc/resources/angular/',
'doc/resources/doc_api_resources/doc_api.js',
'doc/resources/js/docs*.js',
'doc/resources/js/jquery*.js'
]
},
jshint: {
all: ['Gruntfile.js', 'src/**/*.js', 'test/*.js'],
jshintrc: '.jshintrc'
},
watch: {
files: ['src/**/*.js'],
tasks: ['build']
},
uglify: {
main: {
options: {
banner: '/**\n' +
'* @author Jason Dobry <jason.dobry@gmail.com>\n' +
'* @file angular-data.min.js\n' +
'* @version <%= pkg.version %> - Homepage <http://angular-data.pseudobry.com/>\n' +
'* @copyright (c) 2014 Jason Dobry <https://github.com/jmdobry/>\n' +
'* @license MIT <https://github.com/jmdobry/angular-data/blob/master/LICENSE>\n' +
'*\n' +
'* @overview Data store for Angular.js.\n' +
'*/\n'
},
files: {
'dist/angular-data.min.js': ['dist/angular-data.js']
}
},
scripts: {
files: {
'doc/resources/js/libs.min.js': ['doc/resources/js/libs.js']
}
}
},
browserify: {
dist: {
files: {
'dist/angular-data.js': ['src/index.js']
},
options: {
// TODO: There's got to be a better way to consume observe-js without it polluting the global space
postBundleCB: function (err, src, next) {
if (err) {
next(err);
}
src = src.replace('(typeof global !== \'undefined\' && global ? global : window)', '((exports.Number = { isNaN: window.isNaN }) ? exports : exports)');
next(err, src);
}
}
}
},
karma: {
options: {
configFile: './karma.conf.js'
},
dev: {
browsers: ['Chrome'],
autoWatch: true,
singleRun: false,
reporters: ['spec'],
preprocessors: {},
exclude: [
'test/integration/datastore/cacheFactory.test.js'
]
},
min: {
browsers: ['Firefox', 'PhantomJS'],
options: {
files: [
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'bower_components/angular-cache/dist/angular-cache.js',
'dist/angular-data.min.js',
'karma.start.js',
'test/integration/**/*.js'
]
},
exclude: [
'test/integration/datastore/cacheFactory.test.js'
]
},
cacheFactory: {
browsers: ['Firefox', 'PhantomJS'],
options: {
files: [
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'dist/angular-data.js',
'karma.start.js',
'test/integration/datastore/cacheFactory.test.js'
]
}
},
ci: {
browsers: ['Firefox', 'PhantomJS'],
exclude: [
'test/integration/datastore/cacheFactory.test.js'
]
}
},
coveralls: {
options: {
coverage_dir: 'coverage'
}
},
concat: {
libs: {
src: [
'doc/resources/js/jquery.js',
'doc/resources/js/jquery.goto.js',
'doc/resources/js/jquery.cookie.js',
'doc/resources/angular/angular.js',
'doc/resources/angular/angular-bootstrap.js',
'doc/resources/angular/angular-bootstrap-prettify.js',
'doc/resources/angular/angular-cookies.js',
'doc/resources/angular/angular-resource.js',
'doc/resources/angular/angular-sanitize.js'
concat: {
libs: {
src: [
'doc/resources/js/jquery.js',
'doc/resources/js/jquery.goto.js',
'doc/resources/js/jquery.cookie.js',
'doc/resources/angular/angular.js',
'doc/resources/angular/angular-bootstrap.js',
'doc/resources/angular/angular-bootstrap-prettify.js',
'doc/resources/angular/angular-cookies.js',
'doc/resources/angular/angular-resource.js',
'doc/resources/angular/angular-sanitize.js'
],
dest: 'doc/resources/js/libs.js'
},
scripts: {
src: [
'doc/resources/js/docs_module_begin.js',
'guide/angular-data.js',
'doc/resources/doc_api_resources/doc_api.js',
'doc/resources/js/docs_module_end.js',
'doc/documentation/docs-metadata.js',
'doc/documentation/groups-metadata.js',
'doc/documentation/layout-metadata.js'
],
dest: 'doc/resources/js/libs.js'
},
scripts: {
src: [
'doc/resources/js/docs_module_begin.js',
'guide/angular-data.js',
'doc/resources/doc_api_resources/doc_api.js',
'doc/resources/js/docs_module_end.js',
'doc/documentation/docs-metadata.js',
'doc/documentation/groups-metadata.js',
'doc/documentation/layout-metadata.js'
],
dest: 'doc/resources/js/scripts.js'
},
css: {
src: [
'doc/resources/css/bootstrap.min.css',
'doc/resources/css/font-awesome.css',
'doc/resources/css/docular.css',
'doc/resources/css/custom.css',
'doc/resources/doc_api_resources/doc_api.css',
'guide/angular-data.css'
],
dest: 'doc/resources/css/styles.css'
}
},
],
dest: 'doc/resources/js/scripts.js'
},
css: {
src: [
'doc/resources/css/bootstrap.min.css',
'doc/resources/css/font-awesome.css',
'doc/resources/css/docular.css',
'doc/resources/css/custom.css',
'doc/resources/doc_api_resources/doc_api.css',
'guide/angular-data.css'
],
dest: 'doc/resources/css/styles.css'
}
},
copy: {
favicon: {
expand: true,
cwd: 'guide/',
src: 'favicon.ico',
dest: 'doc/',
flatten: true
},
index: {
expand: true,
cwd: 'guide/',
src: 'index.html',
dest: 'doc/',
flatten: true
},
data_white: {
expand: true,
cwd: 'guide/',
src: 'data_white.png',
dest: 'doc/resources/img/',
flatten: true
},
chart: {
expand: true,
cwd: 'guide/',
src: 'chart.png',
dest: 'doc/resources/img/',
flatten: true
},
cream_dust: {
expand: true,
cwd: 'guide/',
src: 'cream_dust.png',
dest: 'doc/resources/img/',
flatten: true
}
},
docular: {
groups: [
{
groupTitle: 'Guide',
groupId: 'guide',
groupIcon: 'icon-book',
sections: [
{
id: 'angular-data',
title: 'angular-data',
docs: [
'guide/angular-data/index.doc',
'guide/angular-data/overview.doc',
'guide/angular-data/resources.doc',
'guide/angular-data/asynchronous.doc',
'guide/angular-data/synchronous.doc',
'guide/angular-data/queries.doc',
'guide/angular-data/adapters.doc',
'guide/angular-data/how.doc'
],
rank: {
index: 1,
overview: 2,
resources: 3,
asynchronous: 4,
synchronous: 5,
queries: 6,
adapters: 7,
how: 8
}
},
{
id: 'angular-cache',
title: 'angular-cache',
docs: ['guide/angular-cache/'],
rank: {
index: 1,
basics: 2,
configure: 3,
http: 4,
storage: 5
}
},
{
id: 'angular-data-mocks',
title: 'angular-data-mocks',
docs: ['guide/angular-data-mocks/'],
rank: {
index: 1,
overview: 2,
setup: 3,
testing: 4
}
},
{
id: 'angular-data-resource',
title: 'Defining Resources',
docs: ['guide/angular-data/resource/'],
rank: {
index: 1,
overview: 2,
basic: 3,
advanced: 4,
lifecycle: 5,
custom: 6
}
}
]
},
{
groupTitle: 'API',
groupId: 'api',
groupIcon: 'icon-wrench',
showSource: true,
sections: [
{
id: 'angular-data',
title: 'angular-data',
scripts: [
'src/'
],
docs: ['guide/api']
},
{
id: 'angular-cache',
title: 'angular-cache',
scripts: [
'bower_components/angular-cache/dist/angular-cache.js'
],
docs: ['guide/api']
},
{
id: 'angular-data-mocks',
title: 'angular-data-mocks',
scripts: [
'bower_components/angular-data-mocks/dist/angular-data-mocks.js'
],
docs: ['guide/api']
}
]
}
],
docular_webapp_target: 'doc',
showDocularDocs: false,
showAngularDocs: false,
docular_partial_home: 'guide/home.html',
docular_partial_navigation: 'guide/nav.html',
docular_partial_footer: 'guide/footer.html',
analytics: {
account: 'UA-46792694-5',
domainName: 'angular-data.codetrain.io'
},
discussions: {
shortName: 'angular-data',
url: 'http://angular-data.codetrain.io',
dev: dev
}
}
});
copy: {
favicon: {
expand: true,
cwd: 'guide/',
src: 'favicon.ico',
dest: 'doc/',
flatten: true
},
index: {
expand: true,
cwd: 'guide/',
src: 'index.html',
dest: 'doc/',
flatten: true
},
data_white: {
expand: true,
cwd: 'guide/',
src: 'data_white.png',
dest: 'doc/resources/img/',
flatten: true
},
chart: {
expand: true,
cwd: 'guide/',
src: 'chart.png',
dest: 'doc/resources/img/',
flatten: true
},
cream_dust: {
expand: true,
cwd: 'guide/',
src: 'cream_dust.png',
dest: 'doc/resources/img/',
flatten: true
}
},
docular: {
groups: [
{
groupTitle: 'Guide',
groupId: 'guide',
groupIcon: 'icon-book',
sections: [
{
id: 'angular-data',
title: 'angular-data',
docs: [
'guide/angular-data/index.md',
'guide/angular-data/overview.md',
'guide/angular-data/resources.md',
'guide/angular-data/asynchronous.md',
'guide/angular-data/synchronous.md',
'guide/angular-data/queries.md',
'guide/angular-data/adapters.md',
'guide/angular-data/how.md'
],
rank: {
index: 1,
overview: 2,
resources: 3,
asynchronous: 4,
synchronous: 5,
queries: 6,
adapters: 7,
how: 8
}
},
{
id: 'angular-cache',
title: 'angular-cache',
docs: ['guide/angular-cache/'],
rank: {
index: 1,
basics: 2,
configure: 3,
http: 4,
storage: 5
}
},
{
id: 'angular-data-mocks',
title: 'angular-data-mocks',
docs: ['guide/angular-data-mocks/'],
rank: {
index: 1,
overview: 2,
setup: 3,
testing: 4
}
},
{
id: 'angular-data-resource',
title: 'Defining Resources',
docs: ['guide/angular-data/resource/'],
rank: {
index: 1,
overview: 2,
basic: 3,
advanced: 4,
lifecycle: 5,
custom: 6,
relations: 7
}
}
]
},
{
groupTitle: 'API',
groupId: 'api',
groupIcon: 'icon-wrench',
showSource: true,
sections: [
{
id: 'angular-data',
title: 'angular-data',
scripts: [
'src/'
],
docs: ['guide/api']
},
{
id: 'angular-cache',
title: 'angular-cache',
scripts: [
'bower_components/angular-cache/dist/angular-cache.js'
],
docs: ['guide/api']
},
{
id: 'angular-data-mocks',
title: 'angular-data-mocks',
scripts: [
'bower_components/angular-data-mocks/dist/angular-data-mocks.js'
],
docs: ['guide/api']
}
]
}
],
docular_webapp_target: 'doc',
showDocularDocs: false,
showAngularDocs: false,
docular_partial_home: 'guide/home.html',
docular_partial_navigation: 'guide/nav.html',
docular_partial_footer: 'guide/footer.html',
analytics: {
account: 'UA-34445126-2',
domainName: 'angular-data.pseudobry.com'
},
discussions: {
shortName: 'angular-data',
url: 'http://angular-data.pseudobry.com',
dev: dev
}
}
});
grunt.registerTask('version', function (filePath) {
var file = grunt.file.read(filePath);
grunt.registerTask('version', function (filePath) {
var file = grunt.file.read(filePath);
file = file.replace(/<%= pkg\.version %>/gi, pkg.version);
file = file.replace(/<%= pkg\.version %>/gi, pkg.version);
grunt.file.write(filePath, file);
});
grunt.file.write(filePath, file);
});
grunt.registerTask('banner', function () {
var file = grunt.file.read('dist/angular-data.js');
grunt.registerTask('banner', function () {
var file = grunt.file.read('dist/angular-data.js');
var banner = '/**\n' +
'* @author Jason Dobry <jason.dobry@gmail.com>\n' +
'* @file angular-data.js\n' +
'* @version ' + pkg.version + ' - Homepage <http://angular-data.codetrain.io/>\n' +
'* @copyright (c) 2014 Jason Dobry <https://github.com/jmdobry/>\n' +
'* @license MIT <https://github.com/jmdobry/angular-data/blob/master/LICENSE>\n' +
'*\n' +
'* @overview Data store for Angular.js.\n' +
'*/\n';
var banner = '/**\n' +
'* @author Jason Dobry <jason.dobry@gmail.com>\n' +
'* @file angular-data.js\n' +
'* @version ' + pkg.version + ' - Homepage <http://angular-data.pseudobry.com/>\n' +
'* @copyright (c) 2014 Jason Dobry <https://github.com/jmdobry/>\n' +
'* @license MIT <https://github.com/jmdobry/angular-data/blob/master/LICENSE>\n' +
'*\n' +
'* @overview Data store for Angular.js.\n' +
'*/\n';
file = banner + file;
file = banner + file;
grunt.file.write('dist/angular-data.js', file);
});
grunt.file.write('dist/angular-data.js', file);
});
grunt.registerTask('test', ['build', 'karma:ci', 'karma:cacheFactory', 'karma:min']);
grunt.registerTask('doc', ['clean:doc', 'docular', 'concat', 'copy', 'clean:afterDoc', 'uglify:scripts']);
grunt.registerTask('build', [
'clean',
'jshint',
'browserify',
'banner',
'uglify:main'
]);
grunt.registerTask('go', ['build', 'watch']);
grunt.registerTask('default', ['build']);
grunt.registerTask('test', ['build', 'karma:ci', 'karma:cacheFactory', 'karma:min']);
grunt.registerTask('doc', ['clean:doc', 'docular', 'concat', 'copy', 'clean:afterDoc', 'uglify:scripts']);
grunt.registerTask('build', [
'clean',
'jshint',
'browserify',
'banner',
'uglify:main'
]);
grunt.registerTask('go', ['build', 'watch']);
grunt.registerTask('default', ['build']);
};
{
"name": "angular-data",
"description": "Data store for Angular.js.",
"version": "0.9.0",
"homepage": "http://angular-data.codetrain.io",
"version": "0.10.0-beta.1",
"homepage": "http://angular-data.pseudobry.com",
"repository": {

@@ -7,0 +7,0 @@ "type": "git",

@@ -5,4 +5,4 @@ ## angular-data

__Latest Release:__ [0.8.1](http://angular-data.codetrain.io/)
__master:__ [0.9.0](http://angular-data-next.codetrain.io/)
__Latest Release:__ [0.9.1](http://angular-data.pseudobry.com/)
__master:__ [0.9.1](http://angular-data-next.pseudobry.com/)

@@ -9,0 +9,0 @@ Angular-data is in a pre-1.0.0 development stage; the API is fluctuating, not a lot of tests yet, etc.

@@ -8,421 +8,421 @@ /**

/**
* @doc property
* @id DSHttpAdapterProvider.properties:defaults
* @name defaults
* @description
* Default configuration for this adapter.
*
* Properties:
*
* - `{function}` - `queryTransform` - See [the guide](/documentation/guide/adapters/index). Default: No-op.
*/
var defaults = this.defaults = {
/**
* @doc property
* @id DSHttpAdapterProvider.properties:defaults.queryTransform
* @name defaults.queryTransform
* @description
* Transform the angular-data query to something your server understands. You might just do this on the server instead.
*
* @param {string} resourceName The name of the resource.
* @param {object} query Response object from `$http()`.
* @returns {*} Returns `query` as-is.
*/
queryTransform: function (resourceName, query) {
return query;
}
};
/**
* @doc property
* @id DSHttpAdapterProvider.properties:defaults
* @name defaults
* @description
* Default configuration for this adapter.
*
* Properties:
*
* - `{function}` - `queryTransform` - See [the guide](/documentation/guide/adapters/index). Default: No-op.
*/
var defaults = this.defaults = {
/**
* @doc property
* @id DSHttpAdapterProvider.properties:defaults.queryTransform
* @name defaults.queryTransform
* @description
* Transform the angular-data query to something your server understands. You might just do this on the server instead.
*
* @param {string} resourceName The name of the resource.
* @param {object} params Params sent through from `$http()`.
* @returns {*} Returns `params` as-is.
*/
queryTransform: function (resourceName, params) {
return params;
}
};
this.$get = ['$http', '$log', 'DSUtils', function ($http, $log, DSUtils) {
this.$get = ['$http', '$log', 'DSUtils', function ($http, $log, DSUtils) {
/**
* @doc interface
* @id DSHttpAdapter
* @name DSHttpAdapter
* @description
* Default adapter used by angular-data. This adapter uses AJAX and JSON to send/retrieve data to/from a server.
* Developers may provide custom adapters that implement the adapter interface.
*/
return {
/**
* @doc property
* @id DSHttpAdapter.properties:defaults
* @name defaults
* @description
* Reference to [DSHttpAdapterProvider.defaults](/documentation/api/api/DSHttpAdapterProvider.properties:defaults).
*/
defaults: defaults,
/**
* @doc interface
* @id DSHttpAdapter
* @name DSHttpAdapter
* @description
* Default adapter used by angular-data. This adapter uses AJAX and JSON to send/retrieve data to/from a server.
* Developers may provide custom adapters that implement the adapter interface.
*/
return {
/**
* @doc property
* @id DSHttpAdapter.properties:defaults
* @name defaults
* @description
* Reference to [DSHttpAdapterProvider.defaults](/documentation/api/api/DSHttpAdapterProvider.properties:defaults).
*/
defaults: defaults,
/**
* @doc method
* @id DSHttpAdapter.methods:HTTP
* @name HTTP
* @description
* Wrapper for `$http()`.
*
* ## Signature:
* ```js
* DS.HTTP(config)
* ```
*
* ## Example:
*
* ```js
* works the same as $http()
* ```
*
* @param {object} config Configuration for the request.
* @returns {Promise} Promise produced by the `$q` service.
*/
HTTP: HTTP,
/**
* @doc method
* @id DSHttpAdapter.methods:HTTP
* @name HTTP
* @description
* Wrapper for `$http()`.
*
* ## Signature:
* ```js
* DS.HTTP(config)
* ```
*
* ## Example:
*
* ```js
* works the same as $http()
* ```
*
* @param {object} config Configuration for the request.
* @returns {Promise} Promise produced by the `$q` service.
*/
HTTP: HTTP,
/**
* @doc method
* @id DSHttpAdapter.methods:GET
* @name GET
* @description
* Wrapper for `$http.get()`.
*
* ## Signature:
* ```js
* DS.GET(url[, config])
* ```
*
* ## Example:
*
* ```js
* Works the same as $http.get()
* ```
*
* @param {string} url The url of the request.
* @param {object=} config Configuration for the request.
* @returns {Promise} Promise produced by the `$q` service.
*/
GET: GET,
/**
* @doc method
* @id DSHttpAdapter.methods:GET
* @name GET
* @description
* Wrapper for `$http.get()`.
*
* ## Signature:
* ```js
* DS.GET(url[, config])
* ```
*
* ## Example:
*
* ```js
* Works the same as $http.get()
* ```
*
* @param {string} url The url of the request.
* @param {object=} config Configuration for the request.
* @returns {Promise} Promise produced by the `$q` service.
*/
GET: GET,
/**
* @doc method
* @id DSHttpAdapter.methods:POST
* @name POST
* @description
* Wrapper for `$http.post()`.
*
* ## Signature:
* ```js
* DS.POST(url[, attrs][, config])
* ```
*
* ## Example:
*
* ```js
* Works the same as $http.post()
* ```
*
* @param {string} url The url of the request.
* @param {object=} attrs Request payload.
* @param {object=} config Configuration for the request.
* @returns {Promise} Promise produced by the `$q` service.
*/
POST: POST,
/**
* @doc method
* @id DSHttpAdapter.methods:POST
* @name POST
* @description
* Wrapper for `$http.post()`.
*
* ## Signature:
* ```js
* DS.POST(url[, attrs][, config])
* ```
*
* ## Example:
*
* ```js
* Works the same as $http.post()
* ```
*
* @param {string} url The url of the request.
* @param {object=} attrs Request payload.
* @param {object=} config Configuration for the request.
* @returns {Promise} Promise produced by the `$q` service.
*/
POST: POST,
/**
* @doc method
* @id DSHttpAdapter.methods:PUT
* @name PUT
* @description
* Wrapper for `$http.put()`.
*
* ## Signature:
* ```js
* DS.PUT(url[, attrs][, config])
* ```
*
* ## Example:
*
* ```js
* Works the same as $http.put()
* ```
*
* @param {string} url The url of the request.
* @param {object=} attrs Request payload.
* @param {object=} config Configuration for the request.
* @returns {Promise} Promise produced by the `$q` service.
*/
PUT: PUT,
/**
* @doc method
* @id DSHttpAdapter.methods:PUT
* @name PUT
* @description
* Wrapper for `$http.put()`.
*
* ## Signature:
* ```js
* DS.PUT(url[, attrs][, config])
* ```
*
* ## Example:
*
* ```js
* Works the same as $http.put()
* ```
*
* @param {string} url The url of the request.
* @param {object=} attrs Request payload.
* @param {object=} config Configuration for the request.
* @returns {Promise} Promise produced by the `$q` service.
*/
PUT: PUT,
/**
* @doc method
* @id DSHttpAdapter.methods:DEL
* @name DEL
* @description
* Wrapper for `$http.delete()`.
*
* ## Signature:
* ```js
* DS.DEL(url[, config])
* ```
*
* ## Example:
*
* ```js
* Works the same as $http.delete
* ```
*
* @param {string} url The url of the request.
* @param {object} config Configuration for the request.
* @returns {Promise} Promise produced by the `$q` service.
*/
DEL: DEL,
/**
* @doc method
* @id DSHttpAdapter.methods:DEL
* @name DEL
* @description
* Wrapper for `$http.delete()`.
*
* ## Signature:
* ```js
* DS.DEL(url[, config])
* ```
*
* ## Example:
*
* ```js
* Works the same as $http.delete
* ```
*
* @param {string} url The url of the request.
* @param {object} config Configuration for the request.
* @returns {Promise} Promise produced by the `$q` service.
*/
DEL: DEL,
/**
* @doc method
* @id DSHttpAdapter.methods:find
* @name find
* @description
* Retrieve a single entity from the server.
*
* Sends a `GET` request to `:baseUrl/:endpoint/:id`.
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {string|number} id The primary key of the entity to retrieve.
* @param {object=} options Optional configuration. Refer to the documentation for `$http.get`.
* @returns {Promise} Promise.
*/
find: find,
/**
* @doc method
* @id DSHttpAdapter.methods:find
* @name find
* @description
* Retrieve a single entity from the server.
*
* Sends a `GET` request to `:baseUrl/:endpoint/:id`.
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {string|number} id The primary key of the entity to retrieve.
* @param {object=} options Optional configuration. Refer to the documentation for `$http.get`.
* @returns {Promise} Promise.
*/
find: find,
/**
* @doc method
* @id DSHttpAdapter.methods:findAll
* @name findAll
* @description
* Retrieve a collection of entities from the server.
*
* Sends a `GET` request to `:baseUrl/:endpoint`.
*
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {object=} params Search query parameters. See the [query guide](/documentation/guide/queries/index).
* @param {object=} options Optional configuration. Refer to the documentation for `$http.get`.
* @returns {Promise} Promise.
*/
findAll: findAll,
/**
* @doc method
* @id DSHttpAdapter.methods:findAll
* @name findAll
* @description
* Retrieve a collection of entities from the server.
*
* Sends a `GET` request to `:baseUrl/:endpoint`.
*
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {object=} params Search query parameters. See the [query guide](/documentation/guide/queries/index).
* @param {object=} options Optional configuration. Refer to the documentation for `$http.get`.
* @returns {Promise} Promise.
*/
findAll: findAll,
/**
* @doc method
* @id DSHttpAdapter.methods:findAll
* @name find
* @description
* Create a new entity on the server.
*
* Sends a `POST` request to `:baseUrl/:endpoint`.
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {object=} params Search query parameters. See the [query guide](/documentation/guide/queries/index).
* @param {object=} options Optional configuration. Refer to the documentation for `$http.post`.
* @returns {Promise} Promise.
*/
create: create,
/**
* @doc method
* @id DSHttpAdapter.methods:findAll
* @name find
* @description
* Create a new entity on the server.
*
* Sends a `POST` request to `:baseUrl/:endpoint`.
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {object=} params Search query parameters. See the [query guide](/documentation/guide/queries/index).
* @param {object=} options Optional configuration. Refer to the documentation for `$http.post`.
* @returns {Promise} Promise.
*/
create: create,
/**
* @doc method
* @id DSHttpAdapter.methods:update
* @name update
* @description
* Update an entity on the server.
*
* Sends a `PUT` request to `:baseUrl/:endpoint/:id`.
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {string|number} id The primary key of the entity to update.
* @param {object} attrs The attributes with which to update the entity. See the [query guide](/documentation/guide/queries/index).
* @param {object=} options Optional configuration. Refer to the documentation for `$http.put`.
* @returns {Promise} Promise.
*/
update: update,
/**
* @doc method
* @id DSHttpAdapter.methods:update
* @name update
* @description
* Update an entity on the server.
*
* Sends a `PUT` request to `:baseUrl/:endpoint/:id`.
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {string|number} id The primary key of the entity to update.
* @param {object} attrs The attributes with which to update the entity. See the [query guide](/documentation/guide/queries/index).
* @param {object=} options Optional configuration. Refer to the documentation for `$http.put`.
* @returns {Promise} Promise.
*/
update: update,
/**
* @doc method
* @id DSHttpAdapter.methods:updateAll
* @name updateAll
* @description
* Update a collection of entities on the server.
*
* Sends a `PUT` request to `:baseUrl/:endpoint`.
*
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {object=} params Search query parameters. See the [query guide](/documentation/guide/queries/index).
* @param {object=} options Optional configuration. Refer to the documentation for `$http.put`.
* @returns {Promise} Promise.
*/
updateAll: updateAll,
/**
* @doc method
* @id DSHttpAdapter.methods:updateAll
* @name updateAll
* @description
* Update a collection of entities on the server.
*
* Sends a `PUT` request to `:baseUrl/:endpoint`.
*
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {object=} params Search query parameters. See the [query guide](/documentation/guide/queries/index).
* @param {object=} options Optional configuration. Refer to the documentation for `$http.put`.
* @returns {Promise} Promise.
*/
updateAll: updateAll,
/**
* @doc method
* @id DSHttpAdapter.methods:destroy
* @name destroy
* @description
* destroy an entity on the server.
*
* Sends a `PUT` request to `:baseUrl/:endpoint/:id`.
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {string|number} id The primary key of the entity to destroy.
* @param {object=} options Optional configuration. Refer to the documentation for `$http.delete`.
* @returns {Promise} Promise.
*/
destroy: destroy,
/**
* @doc method
* @id DSHttpAdapter.methods:destroy
* @name destroy
* @description
* destroy an entity on the server.
*
* Sends a `PUT` request to `:baseUrl/:endpoint/:id`.
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {string|number} id The primary key of the entity to destroy.
* @param {object=} options Optional configuration. Refer to the documentation for `$http.delete`.
* @returns {Promise} Promise.
*/
destroy: destroy,
/**
* @doc method
* @id DSHttpAdapter.methods:destroyAll
* @name destroyAll
* @description
* Retrieve a collection of entities from the server.
*
* Sends a `DELETE` request to `:baseUrl/:endpoint`.
*
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {object=} params Search query parameters. See the [query guide](/documentation/guide/queries/index).
* @param {object=} options Optional configuration. Refer to the documentation for `$http.delete`.
* @returns {Promise} Promise.
*/
destroyAll: destroyAll
};
/**
* @doc method
* @id DSHttpAdapter.methods:destroyAll
* @name destroyAll
* @description
* Retrieve a collection of entities from the server.
*
* Sends a `DELETE` request to `:baseUrl/:endpoint`.
*
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {object=} params Search query parameters. See the [query guide](/documentation/guide/queries/index).
* @param {object=} options Optional configuration. Refer to the documentation for `$http.delete`.
* @returns {Promise} Promise.
*/
destroyAll: destroyAll
};
function HTTP(config) {
var start = new Date().getTime();
function HTTP(config) {
var start = new Date().getTime();
return $http(config).then(function (data) {
$log.debug(data.config.method + ' request:' + data.config.url + ' Time taken: ' + (new Date().getTime() - start) + 'ms', arguments);
return data;
});
}
return $http(config).then(function (data) {
$log.debug(data.config.method + ' request:' + data.config.url + ' Time taken: ' + (new Date().getTime() - start) + 'ms', arguments);
return data;
});
}
function GET(url, config) {
config = config || {};
return HTTP(DSUtils.deepMixIn(config, {
url: url,
method: 'GET'
}));
}
function GET(url, config) {
config = config || {};
return HTTP(DSUtils.deepMixIn(config, {
url: url,
method: 'GET'
}));
}
function POST(url, attrs, config) {
config = config || {};
return HTTP(DSUtils.deepMixIn(config, {
url: url,
data: attrs,
method: 'POST'
}));
}
function POST(url, attrs, config) {
config = config || {};
return HTTP(DSUtils.deepMixIn(config, {
url: url,
data: attrs,
method: 'POST'
}));
}
function PUT(url, attrs, config) {
config = config || {};
return HTTP(DSUtils.deepMixIn(config, {
url: url,
data: attrs,
method: 'PUT'
}));
}
function PUT(url, attrs, config) {
config = config || {};
return HTTP(DSUtils.deepMixIn(config, {
url: url,
data: attrs,
method: 'PUT'
}));
}
function DEL(url, config) {
config = config || {};
return this.HTTP(DSUtils.deepMixIn(config, {
url: url,
method: 'DELETE'
}));
}
function DEL(url, config) {
config = config || {};
return this.HTTP(DSUtils.deepMixIn(config, {
url: url,
method: 'DELETE'
}));
}
function create(resourceConfig, attrs, options) {
options = options || {};
return this.POST(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint),
attrs,
options
);
}
function create(resourceConfig, attrs, options) {
options = options || {};
return this.POST(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint),
attrs,
options
);
}
function destroy(resourceConfig, id, options) {
options = options || {};
return this.DEL(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint, id),
options
);
}
function destroy(resourceConfig, id, options) {
options = options || {};
return this.DEL(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint, id),
options
);
}
function destroyAll(resourceConfig, params, options) {
options = options || {};
options.params = options.params || {};
if (params) {
params.query = params.query ? defaults.queryTransform(resourceConfig.name, params.query) : params.query;
DSUtils.deepMixIn(options.params, params);
}
return this.DEL(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint),
options
);
}
function destroyAll(resourceConfig, params, options) {
options = options || {};
options.params = options.params || {};
if (params) {
params = defaults.queryTransform(resourceConfig.name, params);
DSUtils.deepMixIn(options.params, params);
}
return this.DEL(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint),
options
);
}
function find(resourceConfig, id, options) {
options = options || {};
return this.GET(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint, id),
options
);
}
function find(resourceConfig, id, options) {
options = options || {};
return this.GET(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint, id),
options
);
}
function findAll(resourceConfig, params, options) {
options = options || {};
options.params = options.params || {};
if (params) {
params.query = params.query ? defaults.queryTransform(resourceConfig.name, params.query) : params.query;
DSUtils.deepMixIn(options.params, params);
}
return this.GET(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint),
options
);
}
function findAll(resourceConfig, params, options) {
options = options || {};
options.params = options.params || {};
if (params) {
params = defaults.queryTransform(resourceConfig.name, params);
DSUtils.deepMixIn(options.params, params);
}
return this.GET(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint),
options
);
}
function update(resourceConfig, id, attrs, options) {
options = options || {};
return this.PUT(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint, id),
attrs,
options
);
}
function update(resourceConfig, id, attrs, options) {
options = options || {};
return this.PUT(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint, id),
attrs,
options
);
}
function updateAll(resourceConfig, attrs, params, options) {
options = options || {};
options.params = options.params || {};
if (params) {
params.query = params.query ? defaults.queryTransform(resourceConfig.name, params.query) : params.query;
DSUtils.deepMixIn(options.params, params);
}
return this.PUT(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint),
attrs,
options
);
}
}];
function updateAll(resourceConfig, attrs, params, options) {
options = options || {};
options.params = options.params || {};
if (params) {
params = defaults.queryTransform(resourceConfig.name, params);
DSUtils.deepMixIn(options.params, params);
}
return this.PUT(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint),
attrs,
options
);
}
}];
}
module.exports = DSHttpAdapterProvider;

@@ -8,177 +8,177 @@ /**

this.$get = ['$q', 'DSUtils', function ($q, DSUtils) {
this.$get = ['$q', 'DSUtils', function ($q, DSUtils) {
/**
* @doc interface
* @id DSLocalStorage
* @name DSLocalStorage
* @description
* Default adapter used by angular-data. This adapter uses AJAX and JSON to send/retrieve data to/from a server.
* Developers may provide custom adapters that implement the adapter interface.
*/
return {
/**
* @doc method
* @id DSLocalStorage.methods:find
* @name find
* @description
* Retrieve a single entity from localStorage.
*
* Calls `localStorage.getItem(key)`.
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `namespace` - Namespace path for the resource.
* @param {string|number} id The primary key of the entity to retrieve.
* @returns {Promise} Promise.
*/
find: find,
/**
* @doc interface
* @id DSLocalStorage
* @name DSLocalStorage
* @description
* Default adapter used by angular-data. This adapter uses AJAX and JSON to send/retrieve data to/from a server.
* Developers may provide custom adapters that implement the adapter interface.
*/
return {
/**
* @doc method
* @id DSLocalStorage.methods:find
* @name find
* @description
* Retrieve a single entity from localStorage.
*
* Calls `localStorage.getItem(key)`.
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `namespace` - Namespace path for the resource.
* @param {string|number} id The primary key of the entity to retrieve.
* @returns {Promise} Promise.
*/
find: find,
/**
* @doc method
* @id DSLocalStorage.methods:findAll
* @name findAll
* @description
* Not supported.
*/
findAll: function () {
throw new Error('Not supported!');
},
/**
* @doc method
* @id DSLocalStorage.methods:findAll
* @name findAll
* @description
* Not supported.
*/
findAll: function () {
throw new Error('Not supported!');
},
/**
* @doc method
* @id DSLocalStorage.methods:findAll
* @name find
* @description
* Not supported.
*/
create: function () {
throw new Error('Not supported!');
},
/**
* @doc method
* @id DSLocalStorage.methods:findAll
* @name find
* @description
* Not supported.
*/
create: function () {
throw new Error('Not supported!');
},
/**
* @doc method
* @id DSLocalStorage.methods:update
* @name update
* @description
* Update an entity in localStorage.
*
* Calls `localStorage.setItem(key, value)`.
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `namespace` - Namespace path for the resource.
* @param {string|number} id The primary key of the entity to update.
* @param {object} attrs The attributes with which to update the entity.
* @returns {Promise} Promise.
*/
update: update,
/**
* @doc method
* @id DSLocalStorage.methods:update
* @name update
* @description
* Update an entity in localStorage.
*
* Calls `localStorage.setItem(key, value)`.
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `namespace` - Namespace path for the resource.
* @param {string|number} id The primary key of the entity to update.
* @param {object} attrs The attributes with which to update the entity.
* @returns {Promise} Promise.
*/
update: update,
/**
* @doc method
* @id DSLocalStorage.methods:updateAll
* @name updateAll
* @description
* Not supported.
*/
updateAll: function () {
throw new Error('Not supported!');
},
/**
* @doc method
* @id DSLocalStorage.methods:updateAll
* @name updateAll
* @description
* Not supported.
*/
updateAll: function () {
throw new Error('Not supported!');
},
/**
* @doc method
* @id DSLocalStorage.methods:destroy
* @name destroy
* @description
* Destroy an entity from localStorage.
*
* Calls `localStorage.removeItem(key)`.
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {string|number} id The primary key of the entity to destroy.
* @returns {Promise} Promise.
*/
destroy: destroy,
/**
* @doc method
* @id DSLocalStorage.methods:destroy
* @name destroy
* @description
* Destroy an entity from localStorage.
*
* Calls `localStorage.removeItem(key)`.
*
* @param {object} resourceConfig Properties:
* - `{string}` - `baseUrl` - Base url.
* - `{string=}` - `endpoint` - Endpoint path for the resource.
* @param {string|number} id The primary key of the entity to destroy.
* @returns {Promise} Promise.
*/
destroy: destroy,
/**
* @doc method
* @id DSLocalStorage.methods:destroyAll
* @name destroyAll
* @description
* Not supported.
*/
destroyAll: function () {
throw new Error('Not supported!');
}
};
/**
* @doc method
* @id DSLocalStorage.methods:destroyAll
* @name destroyAll
* @description
* Not supported.
*/
destroyAll: function () {
throw new Error('Not supported!');
}
};
function GET(key) {
var deferred = $q.defer();
try {
var item = localStorage.getItem(key);
deferred.resolve(item ? angular.fromJson(item) : undefined);
} catch (err) {
deferred.reject(err);
}
return deferred.promise;
}
function GET(key) {
var deferred = $q.defer();
try {
var item = localStorage.getItem(key);
deferred.resolve(item ? angular.fromJson(item) : undefined);
} catch (err) {
deferred.reject(err);
}
return deferred.promise;
}
function PUT(key, value) {
var deferred = $q.defer();
try {
var item = localStorage.getItem(key);
if (item) {
item = angular.fromJson(item);
DSUtils.deepMixIn(item, value);
deferred.resolve(localStorage.setItem(key, angular.toJson(item)));
} else {
deferred.resolve(localStorage.setItem(key, angular.toJson(value)));
}
} catch (err) {
deferred.reject(err);
}
return deferred.promise;
}
function PUT(key, value) {
var deferred = $q.defer();
try {
var item = localStorage.getItem(key);
if (item) {
item = angular.fromJson(item);
DSUtils.deepMixIn(item, value);
deferred.resolve(localStorage.setItem(key, angular.toJson(item)));
} else {
deferred.resolve(localStorage.setItem(key, angular.toJson(value)));
}
} catch (err) {
deferred.reject(err);
}
return deferred.promise;
}
function DEL(key) {
var deferred = $q.defer();
try {
deferred.resolve(localStorage.removeItem(key));
} catch (err) {
deferred.reject(err);
}
return deferred.promise;
}
function DEL(key) {
var deferred = $q.defer();
try {
deferred.resolve(localStorage.removeItem(key));
} catch (err) {
deferred.reject(err);
}
return deferred.promise;
}
function destroy(resourceConfig, id, options) {
options = options || {};
return DEL(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint, id),
options
);
}
function destroy(resourceConfig, id, options) {
options = options || {};
return DEL(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint, id),
options
);
}
function find(resourceConfig, id, options) {
options = options || {};
return GET(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint, id),
options
);
}
function find(resourceConfig, id, options) {
options = options || {};
return GET(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint, id),
options
);
}
function update(resourceConfig, id, attrs, options) {
options = options || {};
return PUT(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint, id),
attrs,
options
).then(function () {
return GET(DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint, id));
});
}
}];
function update(resourceConfig, id, attrs, options) {
options = options || {};
return PUT(
DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint, id),
attrs,
options
).then(function () {
return GET(DSUtils.makePath(options.baseUrl || resourceConfig.baseUrl, resourceConfig.endpoint, id));
});
}
}];
}
module.exports = DSLocalStorageProvider;

@@ -42,57 +42,55 @@ var errorPrefix = 'DS.create(resourceName, attrs[, options]): ';

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*/
function create(resourceName, attrs, options) {
var deferred = this.$q.defer(),
promise = deferred.promise;
var deferred = this.$q.defer();
var promise = deferred.promise;
options = options || {};
try {
options = options || {};
if (!this.definitions[resourceName]) {
deferred.reject(new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'));
} else if (!this.utils.isObject(attrs)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'attrs: Must be an object!', { attrs: { actual: typeof attrs, expected: 'object' } }));
} else {
try {
var definition = this.definitions[resourceName],
resource = this.store[resourceName],
_this = this;
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isObject(attrs)) {
throw new this.errors.IA(errorPrefix + 'attrs: Must be an object!');
}
var definition = this.definitions[resourceName];
var resource = this.store[resourceName];
var _this = this;
promise = promise
.then(function (attrs) {
return _this.$q.promisify(definition.beforeValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.validate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.afterValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.beforeCreate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.adapters[options.adapter || definition.defaultAdapter].create(definition, definition.serialize(resourceName, attrs), options);
})
.then(function (res) {
return _this.$q.promisify(definition.afterCreate)(resourceName, definition.deserialize(resourceName, res));
})
.then(function (data) {
var created = _this.inject(definition.name, data);
var id = created[definition.idAttribute];
resource.previousAttributes[id] = _this.utils.deepMixIn({}, created);
resource.saved[id] = _this.utils.updateTimestamp(resource.saved[id]);
return _this.get(definition.name, id);
});
promise = promise
.then(function (attrs) {
return _this.$q.promisify(definition.beforeValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.validate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.afterValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.beforeCreate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.adapters[options.adapter || definition.defaultAdapter].create(definition, definition.serialize(resourceName, attrs), options);
})
.then(function (res) {
return _this.$q.promisify(definition.afterCreate)(resourceName, definition.deserialize(resourceName, res));
})
.then(function (data) {
var created = _this.inject(definition.name, data);
var id = created[definition.idAttribute];
resource.previousAttributes[id] = _this.utils.deepMixIn({}, created);
resource.saved[id] = _this.utils.updateTimestamp(resource.saved[id]);
return _this.get(definition.name, id);
});
deferred.resolve(attrs);
} catch (err) {
deferred.reject(new this.errors.UnhandledError(err));
}
}
deferred.resolve(attrs);
} catch (err) {
deferred.reject(err);
}
return promise;
return promise;
}
module.exports = create;

@@ -43,44 +43,47 @@ var errorPrefix = 'DS.destroy(resourceName, id): ';

* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*/
function destroy(resourceName, id, options) {
var deferred = this.$q.defer(),
promise = deferred.promise;
var deferred = this.$q.defer();
var promise = deferred.promise;
options = options || {};
try {
options = options || {};
if (!this.definitions[resourceName]) {
deferred.reject(new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'));
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } }));
} else {
var item = this.get(resourceName, id);
if (!item) {
deferred.reject(new this.errors.RuntimeError(errorPrefix + 'id: "' + id + '" not found!'));
} else {
var definition = this.definitions[resourceName],
resource = this.store[resourceName],
_this = this;
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IA(errorPrefix + 'id: Must be a string or a number!');
}
promise = promise
.then(function (attrs) {
return _this.$q.promisify(definition.beforeDestroy)(resourceName, attrs);
})
.then(function () {
return _this.adapters[options.adapter || definition.defaultAdapter].destroy(definition, id, options);
})
.then(function () {
return _this.$q.promisify(definition.afterDestroy)(resourceName, item);
})
.then(function () {
_this.eject(resourceName, id);
return id;
});
deferred.resolve(item);
}
}
var item = this.get(resourceName, id);
if (!item) {
throw new this.errors.R(errorPrefix + 'id: "' + id + '" not found!');
}
return promise;
var definition = this.definitions[resourceName];
var _this = this;
promise = promise
.then(function (attrs) {
return _this.$q.promisify(definition.beforeDestroy)(resourceName, attrs);
})
.then(function () {
return _this.adapters[options.adapter || definition.defaultAdapter].destroy(definition, id, options);
})
.then(function () {
return _this.$q.promisify(definition.afterDestroy)(resourceName, item);
})
.then(function () {
_this.eject(resourceName, id);
return id;
});
deferred.resolve(item);
} catch (err) {
deferred.reject(err);
}
return promise;
}
module.exports = destroy;

@@ -19,3 +19,3 @@ var errorPrefix = 'DS.destroyAll(resourceName, params[, options]): ';

* ```js
* var query = {
* var params = {
* where: {

@@ -28,9 +28,5 @@ * author: {

*
* DS.destroyAll('document', {
* query: query
* }).then(function (documents) {
* DS.destroyAll('document', params).then(function (documents) {
* // The documents are gone from the data store
* DS.filter('document', {
* query: query
* }); // []
* DS.filter('document', params); // []
*

@@ -45,7 +41,7 @@ * }, function (err) {

*
* - `{object=}` - `query` - The query object by which to filter items of the type specified by `resourceName`. Properties:
* - `{object=}` - `where` - Where clause.
* - `{number=}` - `limit` - Limit clause.
* - `{skip=}` - `skip` - Skip clause.
* - `{orderBy=}` - `orderBy` - OrderBy clause.
* - `{object=}` - `where` - Where clause.
* - `{number=}` - `limit` - Limit clause.
* - `{number=}` - `skip` - Skip clause.
* - `{number=}` - `offset` - Same as skip.
* - `{string|array=}` - `orderBy` - OrderBy clause.
*

@@ -60,38 +56,39 @@ * @param {object=} options Optional configuration. Properties:

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*/
function destroyAll(resourceName, params, options) {
var deferred = this.$q.defer(),
promise = deferred.promise,
_this = this;
var deferred = this.$q.defer();
var promise = deferred.promise;
options = options || {};
try {
var _this = this;
var IA = this.errors.IA;
if (!this.definitions[resourceName]) {
deferred.reject(new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'));
} else if (!this.utils.isObject(params)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'params: Must be an object!'));
} else if (!this.utils.isObject(options)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!'));
} else {
try {
var definition = this.definitions[resourceName];
options = options || {};
promise = promise
.then(function () {
return _this.adapters[options.adapter || definition.defaultAdapter].destroyAll(definition, params, options);
})
.then(function () {
return _this.ejectAll(resourceName, params);
});
deferred.resolve();
} catch (err) {
deferred.reject(new this.errors.UnhandledError(err));
}
}
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isObject(params)) {
throw new IA(errorPrefix + 'params: Must be an object!');
} else if (!this.utils.isObject(options)) {
throw new IA(errorPrefix + 'options: Must be an object!');
}
return promise;
var definition = this.definitions[resourceName];
promise = promise
.then(function () {
return _this.adapters[options.adapter || definition.defaultAdapter].destroyAll(definition, params, options);
})
.then(function () {
return _this.ejectAll(resourceName, params);
});
deferred.resolve();
} catch (err) {
deferred.reject(err);
}
return promise;
}
module.exports = destroyAll;

@@ -44,63 +44,65 @@ var errorPrefix = 'DS.find(resourceName, id[, options]): ';

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*/
function find(resourceName, id, options) {
var deferred = this.$q.defer(),
promise = deferred.promise;
var deferred = this.$q.defer();
var promise = deferred.promise;
options = options || {};
try {
var IA = this.errors.IA;
if (!this.definitions[resourceName]) {
deferred.reject(new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'));
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } }));
} else if (!this.utils.isObject(options)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } }));
} else {
if (!('cacheResponse' in options)) {
options.cacheResponse = true;
} else {
options.cacheResponse = !!options.cacheResponse;
}
try {
var definition = this.definitions[resourceName],
resource = this.store[resourceName],
_this = this;
options = options || {};
if (options.bypassCache) {
delete resource.completedQueries[id];
}
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new IA(errorPrefix + 'id: Must be a string or a number!');
} else if (!this.utils.isObject(options)) {
throw new IA(errorPrefix + 'options: Must be an object!');
}
if (!(id in resource.completedQueries)) {
if (!(id in resource.pendingQueries)) {
promise = resource.pendingQueries[id] = _this.adapters[options.adapter || definition.defaultAdapter].find(definition, id, options)
.then(function (res) {
var data = definition.deserialize(resourceName, res);
if (options.cacheResponse) {
// Query is no longer pending
delete resource.pendingQueries[id];
resource.completedQueries[id] = new Date().getTime();
return _this.inject(resourceName, data);
} else {
return data;
}
}, function (err) {
delete resource.pendingQueries[id];
return err;
});
}
if (!('cacheResponse' in options)) {
options.cacheResponse = true;
} else {
options.cacheResponse = !!options.cacheResponse;
}
return resource.pendingQueries[id];
} else {
deferred.resolve(_this.get(resourceName, id));
}
} catch (err) {
deferred.reject(err);
}
}
var definition = this.definitions[resourceName];
var resource = this.store[resourceName];
var _this = this;
return promise;
if (options.bypassCache) {
delete resource.completedQueries[id];
}
if (!(id in resource.completedQueries)) {
if (!(id in resource.pendingQueries)) {
promise = resource.pendingQueries[id] = _this.adapters[options.adapter || definition.defaultAdapter].find(definition, id, options)
.then(function (res) {
var data = definition.deserialize(resourceName, res);
if (options.cacheResponse) {
// Query is no longer pending
delete resource.pendingQueries[id];
resource.completedQueries[id] = new Date().getTime();
return _this.inject(resourceName, data);
} else {
return data;
}
}, function (err) {
delete resource.pendingQueries[id];
return _this.$q.reject(err);
});
}
return resource.pendingQueries[id];
} else {
deferred.resolve(_this.get(resourceName, id));
}
} catch (err) {
deferred.reject(err);
}
return promise;
}
module.exports = find;
var errorPrefix = 'DS.findAll(resourceName, params[, options]): ';
function processResults(utils, data, resourceName, queryHash) {
var resource = this.store[resourceName];
var resource = this.store[resourceName];
data = data || [];
data = data || [];
// Query is no longer pending
delete resource.pendingQueries[queryHash];
resource.completedQueries[queryHash] = new Date().getTime();
// Query is no longer pending
delete resource.pendingQueries[queryHash];
resource.completedQueries[queryHash] = new Date().getTime();
// Merge the new values into the cache
this.inject(resourceName, data);
// Update modified timestamp of collection
resource.collectionModified = utils.updateTimestamp(resource.collectionModified);
// Update modified timestamp of collection
resource.collectionModified = utils.updateTimestamp(resource.collectionModified);
return data;
// Merge the new values into the cache
return this.inject(resourceName, data);
}
function _findAll(utils, resourceName, params, options) {
var definition = this.definitions[resourceName],
resource = this.store[resourceName],
_this = this,
queryHash = utils.toJson(params);
var definition = this.definitions[resourceName],
resource = this.store[resourceName],
_this = this,
queryHash = utils.toJson(params);
if (options.bypassCache) {
delete resource.completedQueries[queryHash];
}
if (options.bypassCache) {
delete resource.completedQueries[queryHash];
}
if (!(queryHash in resource.completedQueries)) {
// This particular query has never been completed
if (!(queryHash in resource.completedQueries)) {
// This particular query has never been completed
if (!(queryHash in resource.pendingQueries)) {
if (!(queryHash in resource.pendingQueries)) {
// This particular query has never even been made
resource.pendingQueries[queryHash] = _this.adapters[options.adapter || definition.defaultAdapter].findAll(definition, params, options)
.then(function (res) {
var data = definition.deserialize(resourceName, res);
if (options.cacheResponse) {
try {
return processResults.apply(_this, [utils, data, resourceName, queryHash]);
} catch (err) {
throw new _this.errors.UnhandledError(err);
}
} else {
return data;
}
}, function (err) {
delete resource.pendingQueries[queryHash];
return err;
});
}
// This particular query has never even been made
resource.pendingQueries[queryHash] = _this.adapters[options.adapter || definition.defaultAdapter].findAll(definition, params, options)
.then(function (res) {
var data = definition.deserialize(resourceName, res);
if (options.cacheResponse) {
try {
return processResults.apply(_this, [utils, data, resourceName, queryHash]);
} catch (err) {
return _this.$q.reject(err);
}
} else {
return data;
}
}, function (err) {
delete resource.pendingQueries[queryHash];
return _this.$q.reject(err);
});
}
return resource.pendingQueries[queryHash];
} else {
return this.filter(resourceName, params, options);
}
return resource.pendingQueries[queryHash];
} else {
return this.filter(resourceName, params, options);
}
}

@@ -76,3 +75,3 @@

* ```js
* var query = {
* var params = {
* where: {

@@ -85,13 +84,9 @@ * author: {

*
* DS.findAll('document', {
* query: query
* }).then(function (documents) {
* documents; // [{ id: 'aab7ff66-e21e-46e2-8be8-264d82aee535', author: 'John Anderson', title: 'How to cook' },
* // { id: 'ee7f3f4d-98d5-4934-9e5a-6a559b08479f', author: 'John Anderson', title: 'How NOT to cook' }]
* DS.findAll('document', params).then(function (documents) {
* documents; // [{ id: '1', author: 'John Anderson', title: 'How to cook' },
* // { id: '2', author: 'John Anderson', title: 'How NOT to cook' }]
*
* // The documents are now in the data store
* DS.filter('document', {
* query: query
* }); // [{ id: 'aab7ff66-e21e-46e2-8be8-264d82aee535', author: 'John Anderson', title: 'How to cook' },
* // { id: 'ee7f3f4d-98d5-4934-9e5a-6a559b08479f', author: 'John Anderson', title: 'How NOT to cook' }]
* DS.filter('document', params); // [{ id: '1', author: 'John Anderson', title: 'How to cook' },
* // { id: '2', author: 'John Anderson', title: 'How NOT to cook' }]
*

@@ -104,9 +99,9 @@ * }, function (err) {

* @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.
* @param {object} params Parameter object that is serialized into the query string. Properties:
* @param {object=} params Parameter object that is serialized into the query string. Properties:
*
* - `{object=}` - `query` - The query object by which to filter items of the type specified by `resourceName`. Properties:
* - `{object=}` - `where` - Where clause.
* - `{number=}` - `limit` - Limit clause.
* - `{skip=}` - `skip` - Skip clause.
* - `{orderBy=}` - `orderBy` - OrderBy clause.
* - `{object=}` - `where` - Where clause.
* - `{number=}` - `limit` - Limit clause.
* - `{number=}` - `skip` - Skip clause.
* - `{number=}` - `offset` - Same as skip.
* - `{string|array=}` - `orderBy` - OrderBy clause.
*

@@ -126,37 +121,40 @@ * @param {object=} options Optional configuration. Properties:

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*/
function findAll(resourceName, params, options) {
var deferred = this.$q.defer(),
promise = deferred.promise,
_this = this;
var deferred = this.$q.defer();
var promise = deferred.promise;
options = options || {};
try {
var IA = this.errors.IA;
var _this = this;
if (!this.definitions[resourceName]) {
deferred.reject(new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'));
} else if (!this.utils.isObject(params)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'params: Must be an object!'));
} else if (!this.utils.isObject(options)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!'));
} else {
if (!('cacheResponse' in options)) {
options.cacheResponse = true;
} else {
options.cacheResponse = !!options.cacheResponse;
}
try {
promise = promise.then(function () {
return _findAll.apply(_this, [_this.utils, resourceName, params, options]);
});
deferred.resolve();
} catch (err) {
deferred.reject(new this.errors.UnhandledError(err));
}
}
options = options || {};
params = params || {};
return promise;
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isObject(params)) {
throw new IA(errorPrefix + 'params: Must be an object!');
} else if (!this.utils.isObject(options)) {
throw new IA(errorPrefix + 'options: Must be an object!');
}
if (!('cacheResponse' in options)) {
options.cacheResponse = true;
} else {
options.cacheResponse = !!options.cacheResponse;
}
promise = promise.then(function () {
return _findAll.apply(_this, [_this.utils, resourceName, params, options]);
});
deferred.resolve();
} catch (err) {
deferred.reject(err);
}
return promise;
}
module.exports = findAll;
module.exports = {
/**
* @doc method
* @id DS.async_methods:create
* @name create
* @methodOf DS
* @description
* See [DS.create](/documentation/api/api/DS.async_methods:create).
*/
create: require('./create'),
/**
* @doc method
* @id DS.async_methods:create
* @name create
* @methodOf DS
* @description
* See [DS.create](/documentation/api/api/DS.async_methods:create).
*/
create: require('./create'),
/**
* @doc method
* @id DS.async_methods:destroy
* @name destroy
* @methodOf DS
* @description
* See [DS.destroy](/documentation/api/api/DS.async_methods:destroy).
*/
destroy: require('./destroy'),
/**
* @doc method
* @id DS.async_methods:destroy
* @name destroy
* @methodOf DS
* @description
* See [DS.destroy](/documentation/api/api/DS.async_methods:destroy).
*/
destroy: require('./destroy'),
/**
* @doc method
* @id DS.async_methods:destroyAll
* @name destroyAll
* @methodOf DS
* @description
* See [DS.destroyAll](/documentation/api/api/DS.async_methods:destroyAll).
*/
destroyAll: require('./destroyAll'),
/**
* @doc method
* @id DS.async_methods:destroyAll
* @name destroyAll
* @methodOf DS
* @description
* See [DS.destroyAll](/documentation/api/api/DS.async_methods:destroyAll).
*/
destroyAll: require('./destroyAll'),
/**
* @doc method
* @id DS.async_methods:find
* @name find
* @methodOf DS
* @description
* See [DS.find](/documentation/api/api/DS.async_methods:find).
*/
find: require('./find'),
/**
* @doc method
* @id DS.async_methods:find
* @name find
* @methodOf DS
* @description
* See [DS.find](/documentation/api/api/DS.async_methods:find).
*/
find: require('./find'),
/**
* @doc method
* @id DS.async_methods:findAll
* @name findAll
* @methodOf DS
* @description
* See [DS.findAll](/documentation/api/api/DS.async_methods:findAll).
*/
findAll: require('./findAll'),
/**
* @doc method
* @id DS.async_methods:findAll
* @name findAll
* @methodOf DS
* @description
* See [DS.findAll](/documentation/api/api/DS.async_methods:findAll).
*/
findAll: require('./findAll'),
/**
* @doc method
* @id DS.async_methods:refresh
* @name refresh
* @methodOf DS
* @description
* See [DS.refresh](/documentation/api/api/DS.async_methods:refresh).
*/
refresh: require('./refresh'),
/**
* @doc method
* @id DS.async_methods:loadRelations
* @name loadRelations
* @methodOf DS
* @description
* See [DS.loadRelations](/documentation/api/api/DS.async_methods:loadRelations).
*/
loadRelations: require('./loadRelations'),
/**
* @doc method
* @id DS.async_methods:save
* @name save
* @methodOf DS
* @description
* See [DS.save](/documentation/api/api/DS.async_methods:save).
*/
save: require('./save'),
/**
* @doc method
* @id DS.async_methods:refresh
* @name refresh
* @methodOf DS
* @description
* See [DS.refresh](/documentation/api/api/DS.async_methods:refresh).
*/
refresh: require('./refresh'),
/**
* @doc method
* @id DS.async_methods:update
* @name update
* @methodOf DS
* @description
* See [DS.update](/documentation/api/api/DS.async_methods:update).
*/
update: require('./update'),
/**
* @doc method
* @id DS.async_methods:save
* @name save
* @methodOf DS
* @description
* See [DS.save](/documentation/api/api/DS.async_methods:save).
*/
save: require('./save'),
/**
* @doc method
* @id DS.async_methods:updateAll
* @name updateAll
* @methodOf DS
* @description
* See [DS.updateAll](/documentation/api/api/DS.async_methods:updateAll).
*/
updateAll: require('./updateAll')
/**
* @doc method
* @id DS.async_methods:update
* @name update
* @methodOf DS
* @description
* See [DS.update](/documentation/api/api/DS.async_methods:update).
*/
update: require('./update'),
/**
* @doc method
* @id DS.async_methods:updateAll
* @name updateAll
* @methodOf DS
* @description
* See [DS.updateAll](/documentation/api/api/DS.async_methods:updateAll).
*/
updateAll: require('./updateAll')
};

@@ -34,3 +34,3 @@ var errorPrefix = 'DS.refresh(resourceName, id[, options]): ';

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{NonexistentResourceError}`
*

@@ -50,25 +50,26 @@ * @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*/
function refresh(resourceName, id, options) {
options = options || {};
var IA = this.errors.IA;
if (!this.definitions[resourceName]) {
throw new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!');
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } });
} else if (!this.utils.isObject(options)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } });
} else {
options.bypassCache = true;
options = options || {};
if (this.get(resourceName, id)) {
return this.find(resourceName, id, options);
} else {
return false;
}
}
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new IA(errorPrefix + 'id: Must be a string or a number!');
} else if (!this.utils.isObject(options)) {
throw new IA(errorPrefix + 'options: Must be an object!');
} else {
options.bypassCache = true;
if (this.get(resourceName, id)) {
return this.find(resourceName, id, options);
} else {
return false;
}
}
}
module.exports = refresh;

@@ -43,76 +43,83 @@ var errorPrefix = 'DS.save(resourceName, id[, options]): ';

* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*/
function save(resourceName, id, options) {
var deferred = this.$q.defer(),
promise = deferred.promise;
var deferred = this.$q.defer();
var promise = deferred.promise;
options = options || {};
try {
var IA = this.errors.IA;
if (!this.definitions[resourceName]) {
deferred.reject(new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'));
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } }));
} else if (!this.utils.isObject(options)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } }));
} else {
var item = this.get(resourceName, id);
if (!item) {
deferred.reject(new this.errors.RuntimeError(errorPrefix + 'id: "' + id + '" not found!'));
} else {
var definition = this.definitions[resourceName],
resource = this.store[resourceName],
_this = this;
options = options || {};
promise = promise
.then(function (attrs) {
return _this.$q.promisify(definition.beforeValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.validate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.afterValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.beforeUpdate)(resourceName, attrs);
})
.then(function (attrs) {
if (options.changesOnly) {
resource.observers[id].deliver();
var toKeep = [],
changes = _this.changes(resourceName, id);
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new IA(errorPrefix + 'id: Must be a string or a number!');
} else if (!this.utils.isObject(options)) {
throw new IA(errorPrefix + 'options: Must be an object!');
}
for (var key in changes.added) {
toKeep.push(key);
}
for (key in changes.changed) {
toKeep.push(key);
}
changes = _this.utils.pick(attrs, toKeep);
if (_this.utils.isEmpty(changes)) {
// no changes, return
return attrs;
} else {
attrs = changes;
}
}
return _this.adapters[options.adapter || definition.defaultAdapter].update(definition, id, definition.serialize(resourceName, attrs), options);
})
.then(function (res) {
return _this.$q.promisify(definition.afterUpdate)(resourceName, definition.deserialize(resourceName, res));
})
.then(function (data) {
_this.inject(definition.name, data, options);
resource.previousAttributes[id] = _this.utils.deepMixIn({}, data);
resource.saved[id] = _this.utils.updateTimestamp(resource.saved[id]);
return _this.get(resourceName, id);
});
var item = this.get(resourceName, id);
if (!item) {
throw new this.errors.R(errorPrefix + 'id: "' + id + '" not found!');
}
deferred.resolve(item);
}
}
return promise;
var definition = this.definitions[resourceName];
var resource = this.store[resourceName];
var _this = this;
promise = promise
.then(function (attrs) {
return _this.$q.promisify(definition.beforeValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.validate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.afterValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.beforeUpdate)(resourceName, attrs);
})
.then(function (attrs) {
if (options.changesOnly) {
resource.observers[id].deliver();
var toKeep = [],
changes = _this.changes(resourceName, id);
for (var key in changes.added) {
toKeep.push(key);
}
for (key in changes.changed) {
toKeep.push(key);
}
changes = _this.utils.pick(attrs, toKeep);
if (_this.utils.isEmpty(changes)) {
// no changes, return
return attrs;
} else {
attrs = changes;
}
}
return _this.adapters[options.adapter || definition.defaultAdapter].update(definition, id, definition.serialize(resourceName, attrs), options);
})
.then(function (res) {
return _this.$q.promisify(definition.afterUpdate)(resourceName, definition.deserialize(resourceName, res));
})
.then(function (data) {
_this.inject(definition.name, data, options);
resource.previousAttributes[id] = _this.utils.deepMixIn({}, data);
resource.saved[id] = _this.utils.updateTimestamp(resource.saved[id]);
return _this.get(resourceName, id);
});
deferred.resolve(item);
} catch (err) {
deferred.reject(err);
}
return promise;
}
module.exports = save;

@@ -45,66 +45,72 @@ var errorPrefix = 'DS.update(resourceName, id, attrs[, options]): ';

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*/
function update(resourceName, id, attrs, options) {
var deferred = this.$q.defer(),
promise = deferred.promise;
var deferred = this.$q.defer();
var promise = deferred.promise;
options = options || {};
try {
var IA = this.errors.IA;
if (!this.definitions[resourceName]) {
deferred.reject(new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'));
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!'));
} else if (!this.utils.isObject(attrs)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'attrs: Must be an object!'));
} else if (!this.utils.isObject(options)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!'));
} else {
var definition = this.definitions[resourceName],
resource = this.store[resourceName],
_this = this;
options = options || {};
if (!('cacheResponse' in options)) {
options.cacheResponse = true;
} else {
options.cacheResponse = !!options.cacheResponse;
}
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new IA(errorPrefix + 'id: Must be a string or a number!');
} else if (!this.utils.isObject(attrs)) {
throw new IA(errorPrefix + 'attrs: Must be an object!');
} else if (!this.utils.isObject(options)) {
throw new IA(errorPrefix + 'options: Must be an object!');
}
promise = promise
.then(function (attrs) {
return _this.$q.promisify(definition.beforeValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.validate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.afterValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.beforeUpdate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.adapters[options.adapter || definition.defaultAdapter].update(definition, id, definition.serialize(resourceName, attrs), options);
})
.then(function (res) {
return _this.$q.promisify(definition.afterUpdate)(resourceName, definition.deserialize(resourceName, res));
})
.then(function (data) {
if (options.cacheResponse) {
var updated = _this.inject(definition.name, data, options);
var id = updated[definition.idAttribute];
resource.previousAttributes[id] = _this.utils.deepMixIn({}, updated);
resource.saved[id] = _this.utils.updateTimestamp(resource.saved[id]);
return _this.get(definition.name, id);
} else {
return data;
}
});
var definition = this.definitions[resourceName];
var resource = this.store[resourceName];
var _this = this;
deferred.resolve(attrs);
}
return promise;
if (!('cacheResponse' in options)) {
options.cacheResponse = true;
} else {
options.cacheResponse = !!options.cacheResponse;
}
promise = promise
.then(function (attrs) {
return _this.$q.promisify(definition.beforeValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.validate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.afterValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.beforeUpdate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.adapters[options.adapter || definition.defaultAdapter].update(definition, id, definition.serialize(resourceName, attrs), options);
})
.then(function (res) {
return _this.$q.promisify(definition.afterUpdate)(resourceName, definition.deserialize(resourceName, res));
})
.then(function (data) {
if (options.cacheResponse) {
var updated = _this.inject(definition.name, data, options);
var id = updated[definition.idAttribute];
resource.previousAttributes[id] = _this.utils.deepMixIn({}, updated);
resource.saved[id] = _this.utils.updateTimestamp(resource.saved[id]);
return _this.get(definition.name, id);
} else {
return data;
}
});
deferred.resolve(attrs);
} catch (err) {
deferred.reject(err);
}
return promise;
}
module.exports = update;

@@ -23,7 +23,5 @@ var errorPrefix = 'DS.updateAll(resourceName, attrs, params[, options]): ';

* DS.updateAll('document', 5, { author: 'Sally' }, {
* query: {
* where: {
* author: {
* '==': 'John Anderson'
* }
* where: {
* author: {
* '==': 'John Anderson'
* }

@@ -44,7 +42,7 @@ * }

*
* - `{object=}` - `query` - The query object by which to filter items of the type specified by `resourceName`. Properties:
* - `{object=}` - `where` - Where clause.
* - `{number=}` - `limit` - Limit clause.
* - `{skip=}` - `skip` - Skip clause.
* - `{orderBy=}` - `orderBy` - OrderBy clause.
* - `{object=}` - `where` - Where clause.
* - `{number=}` - `limit` - Limit clause.
* - `{number=}` - `skip` - Skip clause.
* - `{number=}` - `offset` - Same as skip.
* - `{string|array=}` - `orderBy` - OrderBy clause.
*

@@ -63,62 +61,67 @@ * @param {object=} options Optional configuration. Properties:

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*/
function updateAll(resourceName, attrs, params, options) {
var deferred = this.$q.defer(),
promise = deferred.promise;
var deferred = this.$q.defer();
var promise = deferred.promise;
options = options || {};
try {
var IA = this.errors.IA;
if (!this.definitions[resourceName]) {
deferred.reject(new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'));
} else if (!this.utils.isObject(attrs)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'attrs: Must be an object!'));
} else if (!this.utils.isObject(params)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'params: Must be an object!'));
} else if (!this.utils.isObject(options)) {
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!'));
} else {
var definition = this.definitions[resourceName],
resource = this.store[resourceName],
_this = this;
options = options || {};
if (!('cacheResponse' in options)) {
options.cacheResponse = true;
} else {
options.cacheResponse = !!options.cacheResponse;
}
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isObject(attrs)) {
throw new IA(errorPrefix + 'attrs: Must be an object!');
} else if (!this.utils.isObject(params)) {
throw new IA(errorPrefix + 'params: Must be an object!');
} else if (!this.utils.isObject(options)) {
throw new IA(errorPrefix + 'options: Must be an object!');
}
promise = promise
.then(function (attrs) {
return _this.$q.promisify(definition.beforeValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.validate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.afterValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.beforeUpdate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.adapters[options.adapter || definition.defaultAdapter].updateAll(definition, definition.serialize(resourceName, attrs), params, options);
})
.then(function (res) {
return _this.$q.promisify(definition.afterUpdate)(resourceName, definition.deserialize(resourceName, res));
})
.then(function (data) {
if (options.cacheResponse) {
return _this.inject(definition.name, data, options);
} else {
return data;
}
});
var definition = this.definitions[resourceName];
var _this = this;
deferred.resolve(attrs);
}
return promise;
if (!('cacheResponse' in options)) {
options.cacheResponse = true;
} else {
options.cacheResponse = !!options.cacheResponse;
}
promise = promise
.then(function (attrs) {
return _this.$q.promisify(definition.beforeValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.validate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.afterValidate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.$q.promisify(definition.beforeUpdate)(resourceName, attrs);
})
.then(function (attrs) {
return _this.adapters[options.adapter || definition.defaultAdapter].updateAll(definition, definition.serialize(resourceName, attrs), params, options);
})
.then(function (res) {
return _this.$q.promisify(definition.afterUpdate)(resourceName, definition.deserialize(resourceName, res));
})
.then(function (data) {
if (options.cacheResponse) {
return _this.inject(definition.name, data, options);
} else {
return data;
}
});
deferred.resolve(attrs);
} catch (err) {
deferred.reject(err);
}
return promise;
}
module.exports = updateAll;
var utils = require('../utils')[0]();
function lifecycleNoop(resourceName, attrs, cb) {
cb(null, attrs);
cb(null, attrs);
}
function BaseConfig() {
function Defaults() {
}
BaseConfig.prototype.idAttribute = 'id';
BaseConfig.prototype.defaultAdapter = 'DSHttpAdapter';
BaseConfig.prototype.filter = function (resourceName, where, attrs) {
var keep = true;
utils.forOwn(where, function (clause, field) {
if (utils.isString(clause)) {
clause = {
'===': clause
};
} else if (utils.isNumber(clause)) {
clause = {
'==': clause
};
}
if ('==' in clause) {
keep = keep && (attrs[field] == clause['==']);
} else if ('===' in clause) {
keep = keep && (attrs[field] === clause['===']);
} else if ('!=' in clause) {
keep = keep && (attrs[field] != clause['!=']);
} else if ('>' in clause) {
keep = keep && (attrs[field] > clause['>']);
} else if ('>=' in clause) {
keep = keep && (attrs[field] >= clause['>=']);
} else if ('<' in clause) {
keep = keep && (attrs[field] < clause['<']);
} else if ('<=' in clause) {
keep = keep && (attrs[field] <= clause['<=']);
} else if ('in' in clause) {
keep = keep && utils.contains(clause['in'], attrs[field]);
}
});
return keep;
Defaults.prototype.idAttribute = 'id';
Defaults.prototype.defaultAdapter = 'DSHttpAdapter';
Defaults.prototype.filter = function (collection, resourceName, params, options) {
var _this = this;
var filtered = collection;
var where = null;
var reserved = {
skip: '',
offset: '',
where: '',
limit: '',
orderBy: '',
sort: ''
};
if (this.utils.isObject(params.where)) {
where = params.where;
} else {
where = {};
}
if (options.allowSimpleWhere) {
this.utils.forOwn(params, function (value, key) {
if (!(key in reserved) && !(key in where)) {
where[key] = {
'==': value
};
}
});
}
if (this.utils.isEmpty(where)) {
where = null;
}
if (where) {
filtered = this.utils.filter(filtered, function (attrs) {
// console.log(attrs);
var first = true;
var keep = true;
_this.utils.forOwn(where, function (clause, field) {
// console.log(clause, field);
if (_this.utils.isString(clause)) {
clause = {
'===': clause
};
} else if (_this.utils.isNumber(clause)) {
clause = {
'==': clause
};
}
if (_this.utils.isObject(clause)) {
_this.utils.forOwn(clause, function (val, op) {
// console.log(op, val);
if (op === '==') {
keep = first ? (attrs[field] == val) : keep && (attrs[field] == val);
} else if (op === '===') {
keep = first ? (attrs[field] === val) : keep && (attrs[field] === val);
} else if (op === '!=') {
keep = first ? (attrs[field] != val) : keep && (attrs[field] != val);
} else if (op === '!==') {
keep = first ? (attrs[field] !== val) : keep && (attrs[field] !== val);
} else if (op === '>') {
keep = first ? (attrs[field] > val) : keep && (attrs[field] > val);
} else if (op === '>=') {
keep = first ? (attrs[field] >= val) : keep && (attrs[field] >= val);
} else if (op === '<') {
keep = first ? (attrs[field] < val) : keep && (attrs[field] < val);
} else if (op === '<=') {
keep = first ? (attrs[field] <= val) : keep && (attrs[field] <= val);
} else if (op === 'in') {
keep = first ? _this.utils.contains(val, attrs[field]) : keep && _this.utils.contains(val, attrs[field]);
} else if (op === '|==') {
keep = first ? (attrs[field] == val) : keep || (attrs[field] == val);
} else if (op === '|===') {
keep = first ? (attrs[field] === val) : keep || (attrs[field] === val);
} else if (op === '|!=') {
keep = first ? (attrs[field] != val) : keep || (attrs[field] != val);
} else if (op === '|!==') {
keep = first ? (attrs[field] !== val) : keep || (attrs[field] !== val);
} else if (op === '|>') {
keep = first ? (attrs[field] > val) : keep || (attrs[field] > val);
} else if (op === '|>=') {
keep = first ? (attrs[field] >= val) : keep || (attrs[field] >= val);
} else if (op === '|<') {
keep = first ? (attrs[field] < val) : keep || (attrs[field] < val);
} else if (op === '|<=') {
keep = first ? (attrs[field] <= val) : keep || (attrs[field] <= val);
} else if (op === '|in') {
keep = first ? _this.utils.contains(val, attrs[field]) : keep || _this.utils.contains(val, attrs[field]);
}
first = false;
// console.log(keep, first);
});
}
});
return keep;
});
}
var orderBy = null;
if (this.utils.isString(params.orderBy)) {
orderBy = [
[params.orderBy, 'ASC']
];
} else if (this.utils.isArray(params.orderBy)) {
orderBy = params.orderBy;
}
if (!orderBy && this.utils.isString(params.sort)) {
orderBy = [
[params.sort, 'ASC']
];
} else if (!orderBy && this.utils.isArray(params.sort)) {
orderBy = params.sort;
}
// Apply 'orderBy'
if (orderBy) {
angular.forEach(orderBy, function (def) {
if (_this.utils.isString(def)) {
def = [def, 'ASC'];
} else if (!_this.utils.isArray(def)) {
throw new _this.errors.IllegalArgumentError('DS.filter(resourceName[, params][, options]): ' + angular.toJson(def) + ': Must be a string or an array!', { params: { 'orderBy[i]': { actual: typeof def, expected: 'string|array' } } });
}
filtered = _this.utils.sort(filtered, function (a, b) {
var cA = a[def[0]], cB = b[def[0]];
if (_this.utils.isString(cA)) {
cA = _this.utils.upperCase(cA);
}
if (_this.utils.isString(cB)) {
cB = _this.utils.upperCase(cB);
}
if (def[1] === 'DESC') {
if (cB < cA) {
return -1;
} else if (cB > cA) {
return 1;
} else {
return 0;
}
} else {
if (cA < cB) {
return -1;
} else if (cA > cB) {
return 1;
} else {
return 0;
}
}
});
});
}
var limit = angular.isNumber(params.limit) ? params.limit : null;
var skip = null;
if (angular.isNumber(params.skip)) {
skip = params.skip;
} else if (angular.isNumber(params.offset)) {
skip = params.offset;
}
// Apply 'limit' and 'skip'
if (limit && skip) {
filtered = this.utils.slice(filtered, skip, Math.min(filtered.length, skip + limit));
} else if (this.utils.isNumber(limit)) {
filtered = this.utils.slice(filtered, 0, Math.min(filtered.length, limit));
} else if (this.utils.isNumber(skip)) {
if (skip < filtered.length) {
filtered = this.utils.slice(filtered, skip);
} else {
filtered = [];
}
}
return filtered;
};
BaseConfig.prototype.baseUrl = '';
BaseConfig.prototype.endpoint = '';
Defaults.prototype.baseUrl = '';
Defaults.prototype.endpoint = '';
/**

@@ -76,3 +221,3 @@ * @doc property

*/
BaseConfig.prototype.beforeValidate = lifecycleNoop;
Defaults.prototype.beforeValidate = lifecycleNoop;
/**

@@ -108,3 +253,3 @@ * @doc property

*/
BaseConfig.prototype.validate = lifecycleNoop;
Defaults.prototype.validate = lifecycleNoop;
/**

@@ -140,3 +285,3 @@ * @doc property

*/
BaseConfig.prototype.afterValidate = lifecycleNoop;
Defaults.prototype.afterValidate = lifecycleNoop;
/**

@@ -172,3 +317,3 @@ * @doc property

*/
BaseConfig.prototype.beforeCreate = lifecycleNoop;
Defaults.prototype.beforeCreate = lifecycleNoop;
/**

@@ -204,3 +349,3 @@ * @doc property

*/
BaseConfig.prototype.afterCreate = lifecycleNoop;
Defaults.prototype.afterCreate = lifecycleNoop;
/**

@@ -236,3 +381,3 @@ * @doc property

*/
BaseConfig.prototype.beforeUpdate = lifecycleNoop;
Defaults.prototype.beforeUpdate = lifecycleNoop;
/**

@@ -268,3 +413,3 @@ * @doc property

*/
BaseConfig.prototype.afterUpdate = lifecycleNoop;
Defaults.prototype.afterUpdate = lifecycleNoop;
/**

@@ -300,3 +445,3 @@ * @doc property

*/
BaseConfig.prototype.beforeDestroy = lifecycleNoop;
Defaults.prototype.beforeDestroy = lifecycleNoop;
/**

@@ -332,3 +477,3 @@ * @doc property

*/
BaseConfig.prototype.afterDestroy = lifecycleNoop;
Defaults.prototype.afterDestroy = lifecycleNoop;
/**

@@ -358,4 +503,4 @@ * @doc property

*/
BaseConfig.prototype.beforeInject = function (resourceName, attrs) {
return attrs;
Defaults.prototype.beforeInject = function (resourceName, attrs) {
return attrs;
};

@@ -386,4 +531,4 @@ /**

*/
BaseConfig.prototype.afterInject = function (resourceName, attrs) {
return attrs;
Defaults.prototype.afterInject = function (resourceName, attrs) {
return attrs;
};

@@ -411,4 +556,4 @@ /**

*/
BaseConfig.prototype.serialize = function (resourceName, data) {
return data;
Defaults.prototype.serialize = function (resourceName, data) {
return data;
};

@@ -435,4 +580,4 @@

*/
BaseConfig.prototype.deserialize = function (resourceName, data) {
return data.data;
Defaults.prototype.deserialize = function (resourceName, data) {
return data.data;
};

@@ -447,145 +592,146 @@

/**
* @doc property
* @id DSProvider.properties:defaults
* @name defaults
* @description
* See the [configuration guide](/documentation/guide/configure/global).
*
* Properties:
*
* - `{string}` - `baseUrl` - The url relative to which all AJAX requests will be made.
* - `{string}` - `idAttribute` - Default: `"id"` - The attribute that specifies the primary key for resources.
* - `{string}` - `defaultAdapter` - Default: `"DSHttpAdapter"`
* - `{function}` - `filter` - Default: See [angular-data query language](/documentation/guide/queries/custom).
* - `{function}` - `beforeValidate` - See [DSProvider.defaults.beforeValidate](/documentation/api/angular-data/DSProvider.properties:defaults.beforeValidate). Default: No-op
* - `{function}` - `validate` - See [DSProvider.defaults.validate](/documentation/api/angular-data/DSProvider.properties:defaults.validate). Default: No-op
* - `{function}` - `afterValidate` - See [DSProvider.defaults.afterValidate](/documentation/api/angular-data/DSProvider.properties:defaults.afterValidate). Default: No-op
* - `{function}` - `beforeCreate` - See [DSProvider.defaults.beforeCreate](/documentation/api/angular-data/DSProvider.properties:defaults.beforeCreate). Default: No-op
* - `{function}` - `afterCreate` - See [DSProvider.defaults.afterCreate](/documentation/api/angular-data/DSProvider.properties:defaults.afterCreate). Default: No-op
* - `{function}` - `beforeUpdate` - See [DSProvider.defaults.beforeUpdate](/documentation/api/angular-data/DSProvider.properties:defaults.beforeUpdate). Default: No-op
* - `{function}` - `afterUpdate` - See [DSProvider.defaults.afterUpdate](/documentation/api/angular-data/DSProvider.properties:defaults.afterUpdate). Default: No-op
* - `{function}` - `beforeDestroy` - See [DSProvider.defaults.beforeDestroy](/documentation/api/angular-data/DSProvider.properties:defaults.beforeDestroy). Default: No-op
* - `{function}` - `afterDestroy` - See [DSProvider.defaults.afterDestroy](/documentation/api/angular-data/DSProvider.properties:defaults.afterDestroy). Default: No-op
* - `{function}` - `afterInject` - See [DSProvider.defaults.afterInject](/documentation/api/angular-data/DSProvider.properties:defaults.afterInject). Default: No-op
* - `{function}` - `beforeInject` - See [DSProvider.defaults.beforeInject](/documentation/api/angular-data/DSProvider.properties:defaults.beforeInject). Default: No-op
* - `{function}` - `serialize` - See [DSProvider.defaults.serialize](/documentation/api/angular-data/DSProvider.properties:defaults.serialize). Default: No-op
* - `{function}` - `deserialize` - See [DSProvider.defaults.deserialize](/documentation/api/angular-data/DSProvider.properties:defaults.deserialize). Default: No-op
*/
var defaults = this.defaults = new BaseConfig();
/**
* @doc property
* @id DSProvider.properties:defaults
* @name defaults
* @description
* See the [configuration guide](/documentation/guide/configure/global).
*
* Properties:
*
* - `{string}` - `baseUrl` - The url relative to which all AJAX requests will be made.
* - `{string}` - `idAttribute` - Default: `"id"` - The attribute that specifies the primary key for resources.
* - `{string}` - `defaultAdapter` - Default: `"DSHttpAdapter"`
* - `{function}` - `filter` - Default: See [angular-data query language](/documentation/guide/queries/custom).
* - `{function}` - `beforeValidate` - See [DSProvider.defaults.beforeValidate](/documentation/api/angular-data/DSProvider.properties:defaults.beforeValidate). Default: No-op
* - `{function}` - `validate` - See [DSProvider.defaults.validate](/documentation/api/angular-data/DSProvider.properties:defaults.validate). Default: No-op
* - `{function}` - `afterValidate` - See [DSProvider.defaults.afterValidate](/documentation/api/angular-data/DSProvider.properties:defaults.afterValidate). Default: No-op
* - `{function}` - `beforeCreate` - See [DSProvider.defaults.beforeCreate](/documentation/api/angular-data/DSProvider.properties:defaults.beforeCreate). Default: No-op
* - `{function}` - `afterCreate` - See [DSProvider.defaults.afterCreate](/documentation/api/angular-data/DSProvider.properties:defaults.afterCreate). Default: No-op
* - `{function}` - `beforeUpdate` - See [DSProvider.defaults.beforeUpdate](/documentation/api/angular-data/DSProvider.properties:defaults.beforeUpdate). Default: No-op
* - `{function}` - `afterUpdate` - See [DSProvider.defaults.afterUpdate](/documentation/api/angular-data/DSProvider.properties:defaults.afterUpdate). Default: No-op
* - `{function}` - `beforeDestroy` - See [DSProvider.defaults.beforeDestroy](/documentation/api/angular-data/DSProvider.properties:defaults.beforeDestroy). Default: No-op
* - `{function}` - `afterDestroy` - See [DSProvider.defaults.afterDestroy](/documentation/api/angular-data/DSProvider.properties:defaults.afterDestroy). Default: No-op
* - `{function}` - `afterInject` - See [DSProvider.defaults.afterInject](/documentation/api/angular-data/DSProvider.properties:defaults.afterInject). Default: No-op
* - `{function}` - `beforeInject` - See [DSProvider.defaults.beforeInject](/documentation/api/angular-data/DSProvider.properties:defaults.beforeInject). Default: No-op
* - `{function}` - `serialize` - See [DSProvider.defaults.serialize](/documentation/api/angular-data/DSProvider.properties:defaults.serialize). Default: No-op
* - `{function}` - `deserialize` - See [DSProvider.defaults.deserialize](/documentation/api/angular-data/DSProvider.properties:defaults.deserialize). Default: No-op
*/
var defaults = this.defaults = new Defaults();
this.$get = [
'$rootScope', '$log', '$q', 'DSHttpAdapter', 'DSLocalStorageAdapter', 'DSUtils', 'DSErrors',
function ($rootScope, $log, $q, DSHttpAdapter, DSLocalStorageAdapter, DSUtils, DSErrors) {
this.$get = [
'$rootScope', '$log', '$q', 'DSHttpAdapter', 'DSLocalStorageAdapter', 'DSUtils', 'DSErrors',
function ($rootScope, $log, $q, DSHttpAdapter, DSLocalStorageAdapter, DSUtils, DSErrors) {
var syncMethods = require('./sync_methods'),
asyncMethods = require('./async_methods'),
cache;
var syncMethods = require('./sync_methods'),
asyncMethods = require('./async_methods'),
cache;
try {
cache = angular.injector(['angular-data.DSCacheFactory']).get('DSCacheFactory');
} catch (err) {
$log.warn(err);
$log.warn('DSCacheFactory is unavailable. Resorting to the lesser capabilities of $cacheFactory.');
cache = angular.injector(['ng']).get('$cacheFactory');
}
try {
cache = angular.injector(['angular-data.DSCacheFactory']).get('DSCacheFactory');
} catch (err) {
$log.warn(err);
$log.warn('DSCacheFactory is unavailable. Resorting to the lesser capabilities of $cacheFactory.');
cache = angular.injector(['ng']).get('$cacheFactory');
}
/**
* @doc interface
* @id DS
* @name DS
* @description
* Public data store interface. Consists of several properties and a number of methods. Injectable as `DS`.
*
* See the [guide](/documentation/guide/overview/index).
*/
var DS = {
$rootScope: $rootScope,
$log: $log,
$q: $q,
/**
* @doc interface
* @id DS
* @name DS
* @description
* Public data store interface. Consists of several properties and a number of methods. Injectable as `DS`.
*
* See the [guide](/documentation/guide/overview/index).
*/
var DS = {
$rootScope: $rootScope,
$log: $log,
$q: $q,
cacheFactory: cache,
cacheFactory: cache,
/**
* @doc property
* @id DS.properties:defaults
* @name defaults
* @description
* Reference to [DSProvider.defaults](/documentation/api/api/DSProvider.properties:defaults).
*/
defaults: defaults,
/**
* @doc property
* @id DS.properties:defaults
* @name defaults
* @description
* Reference to [DSProvider.defaults](/documentation/api/api/DSProvider.properties:defaults).
*/
defaults: defaults,
/*!
* @doc property
* @id DS.properties:store
* @name store
* @description
* Meta data for each registered resource.
*/
store: {},
/*!
* @doc property
* @id DS.properties:store
* @name store
* @description
* Meta data for each registered resource.
*/
store: {},
/*!
* @doc property
* @id DS.properties:definitions
* @name definitions
* @description
* Registered resource definitions available to the data store.
*/
definitions: {},
/*!
* @doc property
* @id DS.properties:definitions
* @name definitions
* @description
* Registered resource definitions available to the data store.
*/
definitions: {},
/**
* @doc property
* @id DS.properties:adapters
* @name adapters
* @description
* Registered adapters available to the data store. Object consists of key-values pairs where the key is
* the name of the adapter and the value is the adapter itself.
*/
adapters: {
DSHttpAdapter: DSHttpAdapter,
DSLocalStorageAdapter: DSLocalStorageAdapter
},
/**
* @doc property
* @id DS.properties:adapters
* @name adapters
* @description
* Registered adapters available to the data store. Object consists of key-values pairs where the key is
* the name of the adapter and the value is the adapter itself.
*/
adapters: {
DSHttpAdapter: DSHttpAdapter,
DSLocalStorageAdapter: DSLocalStorageAdapter
},
/**
* @doc property
* @id DS.properties:errors
* @name errors
* @description
* References to the various [error types](/documentation/api/api/errors) used by angular-data.
*/
errors: DSErrors,
/**
* @doc property
* @id DS.properties:errors
* @name errors
* @description
* References to the various [error types](/documentation/api/api/errors) used by angular-data.
*/
errors: DSErrors,
/*!
* @doc property
* @id DS.properties:utils
* @name utils
* @description
* Utility functions used internally by angular-data.
*/
utils: DSUtils
};
/*!
* @doc property
* @id DS.properties:utils
* @name utils
* @description
* Utility functions used internally by angular-data.
*/
utils: DSUtils
};
DSUtils.deepFreeze(syncMethods);
DSUtils.deepFreeze(asyncMethods);
DSUtils.deepFreeze(syncMethods);
DSUtils.deepFreeze(asyncMethods);
DSUtils.deepMixIn(DS, syncMethods);
DSUtils.deepMixIn(DS, asyncMethods);
DSUtils.deepMixIn(DS, syncMethods);
DSUtils.deepMixIn(DS, asyncMethods);
DSUtils.deepFreeze(DS.errors);
DSUtils.deepFreeze(DS.utils);
DSUtils.deepFreeze(DS.errors);
DSUtils.deepFreeze(DS.utils);
var $dirtyCheckScope = $rootScope.$new();
var $dirtyCheckScope = $rootScope.$new();
$dirtyCheckScope.$watch(function () {
// Throttle angular-data's digest loop to tenths of a second
// TODO: Is this okay?
return new Date().getTime() / 100 | 0;
}, function () {
DS.digest();
});
$dirtyCheckScope.$watch(function () {
// Throttle angular-data's digest loop to tenths of a second
// TODO: Is this okay?
return new Date().getTime() / 100 | 0;
}, function () {
DS.digest();
});
return DS;
}];
return DS;
}
];
}
module.exports = DSProvider;

@@ -1,2 +0,2 @@

var errorPrefix = 'DS.bindAll(scope, expr, resourceName, params): ';
var errorPrefix = 'DS.bindAll(scope, expr, resourceName, params[, cb]): ';

@@ -12,3 +12,3 @@ /**

* ```js
* DS.bindAll(scope, expr, resourceName, params)
* DS.bindAll(scope, expr, resourceName, params[, cb])
* ```

@@ -21,6 +21,4 @@ *

* var deregisterFunc = DS.bindAll($scope, 'docs', 'document', {
* query: {
* criteria: {
* ownerId: 5
* }
* where: {
* ownerId: 5
* }

@@ -33,4 +31,3 @@ * });

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*

@@ -42,33 +39,46 @@ * @param {object} scope The scope to bind to.

*
* - `{object=}` - `query` - The query object by which to filter items of the type specified by `resourceName`. Properties:
* - `{object=}` - `where` - Where clause.
* - `{number=}` - `limit` - Limit clause.
* - `{skip=}` - `skip` - Skip clause.
* - `{orderBy=}` - `orderBy` - OrderBy clause.
* - `{object=}` - `where` - Where clause.
* - `{number=}` - `limit` - Limit clause.
* - `{number=}` - `skip` - Skip clause.
* - `{number=}` - `offset` - Same as skip.
* - `{string|array=}` - `orderBy` - OrderBy clause.
*
* @param {function=} cb Optional callback executed on change. Signature: `cb(err, items)`.
*
* @returns {function} Scope $watch deregistration function.
*/
function bindOne(scope, expr, resourceName, params) {
if (!this.utils.isObject(scope)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'scope: Must be an object!');
} else if (!this.utils.isString(expr)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'expr: Must be a string!');
} else if (!this.definitions[resourceName]) {
throw new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!');
} else if (!this.utils.isObject(params)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'params: Must be an object!');
}
function bindOne(scope, expr, resourceName, params, cb) {
var IA = this.errors.IA;
var _this = this;
if (!this.utils.isObject(scope)) {
throw new IA(errorPrefix + 'scope: Must be an object!');
} else if (!this.utils.isString(expr)) {
throw new IA(errorPrefix + 'expr: Must be a string!');
} else if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isObject(params)) {
throw new IA(errorPrefix + 'params: Must be an object!');
}
try {
return scope.$watch(function () {
return _this.lastModified(resourceName);
}, function () {
_this.utils.set(scope, expr, _this.filter(resourceName, params));
});
} catch (err) {
throw new this.errors.UnhandledError(err);
}
var _this = this;
try {
return scope.$watch(function () {
return _this.lastModified(resourceName);
}, function () {
var items = _this.filter(resourceName, params);
_this.utils.set(scope, expr, items);
if (cb) {
cb(null, items);
}
});
} catch (err) {
if (cb) {
cb(err);
} else {
throw err;
}
}
}
module.exports = bindOne;

@@ -1,2 +0,2 @@

var errorPrefix = 'DS.bindOne(scope, expr, resourceName, id): ';
var errorPrefix = 'DS.bindOne(scope, expr, resourceName, id[, cb]): ';

@@ -12,3 +12,3 @@ /**

* ```js
* DS.bindOne(scope, expr, resourceName, id)
* DS.bindOne(scope, expr, resourceName, id[, cb])
* ```

@@ -26,4 +26,3 @@ *

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*

@@ -34,28 +33,39 @@ * @param {object} scope The scope to bind to.

* @param {string|number} id The primary key of the item to bind.
* @param {function=} cb Optional callback executed on change. Signature: `cb(err, item)`.
* @returns {function} Scope $watch deregistration function.
*/
function bindOne(scope, expr, resourceName, id) {
if (!this.utils.isObject(scope)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'scope: Must be an object!');
} else if (!this.utils.isString(expr)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'expr: Must be a string!');
} else if (!this.definitions[resourceName]) {
throw new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!');
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!');
}
function bindOne(scope, expr, resourceName, id, cb) {
var IA = this.errors.IA;
var _this = this;
if (!this.utils.isObject(scope)) {
throw new IA(errorPrefix + 'scope: Must be an object!');
} else if (!this.utils.isString(expr)) {
throw new IA(errorPrefix + 'expr: Must be a string!');
} else if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new IA(errorPrefix + 'id: Must be a string or a number!');
}
try {
return scope.$watch(function () {
return _this.lastModified(resourceName, id);
}, function () {
_this.utils.set(scope, expr, _this.get(resourceName, id));
});
} catch (err) {
throw new this.errors.UnhandledError(err);
}
var _this = this;
try {
return scope.$watch(function () {
return _this.lastModified(resourceName, id);
}, function () {
var item = _this.get(resourceName, id);
_this.utils.set(scope, expr, item);
if (cb) {
cb(null, item);
}
});
} catch (err) {
if (cb) {
cb(err);
} else {
throw err;
}
}
}
module.exports = bindOne;

@@ -30,4 +30,3 @@ var errorPrefix = 'DS.changes(resourceName, id): ';

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*

@@ -39,19 +38,15 @@ * @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.

function changes(resourceName, id) {
if (!this.definitions[resourceName]) {
throw new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!');
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } });
}
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IA(errorPrefix + 'id: Must be a string or a number!');
}
try {
var item = this.get(resourceName, id);
if (item) {
this.store[resourceName].observers[id].deliver();
return this.utils.diffObjectFromOldObject(item, this.store[resourceName].previousAttributes[id]);
}
} catch (err) {
throw new this.errors.UnhandledError(err);
}
var item = this.get(resourceName, id);
if (item) {
this.store[resourceName].observers[id].deliver();
return this.utils.diffObjectFromOldObject(item, this.store[resourceName].previousAttributes[id]);
}
}
module.exports = changes;

@@ -6,9 +6,9 @@ /*jshint evil:true*/

utils.deepMixIn(this, options);
utils.deepMixIn(this, options);
if ('endpoint' in options) {
this.endpoint = options.endpoint;
} else {
this.endpoint = this.name;
}
if ('endpoint' in options) {
this.endpoint = options.endpoint;
} else {
this.endpoint = this.name;
}
}

@@ -47,3 +47,2 @@

* - `{RuntimeError}`
* - `{UnhandledError}`
*

@@ -78,66 +77,86 @@ * @param {string|object} definition Name of resource or resource definition object: Properties:

function defineResource(definition) {
if (this.utils.isString(definition)) {
definition = {
name: definition
};
}
if (!this.utils.isObject(definition)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'definition: Must be an object!', { definition: { actual: typeof definition, expected: 'object' } });
} else if (!this.utils.isString(definition.name)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'definition.name: Must be a string!', { definition: { name: { actual: typeof definition.name, expected: 'string' } } });
} else if (definition.idAttribute && !this.utils.isString(definition.idAttribute)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'definition.idAttribute: Must be a string!', { definition: { idAttribute: { actual: typeof definition.idAttribute, expected: 'string' } } });
} else if (definition.endpoint && !this.utils.isString(definition.endpoint)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'definition.endpoint: Must be a string!', { definition: { endpoint: { actual: typeof definition.endpoint, expected: 'string' } } });
} else if (this.store[definition.name]) {
throw new this.errors.RuntimeError(errorPrefix + definition.name + ' is already registered!');
}
var IA = this.errors.IA;
try {
Resource.prototype = this.defaults;
this.definitions[definition.name] = new Resource(this.utils, definition);
if (this.utils.isString(definition)) {
definition = {
name: definition
};
}
if (!this.utils.isObject(definition)) {
throw new IA(errorPrefix + 'definition: Must be an object!');
} else if (!this.utils.isString(definition.name)) {
throw new IA(errorPrefix + 'definition.name: Must be a string!');
} else if (definition.idAttribute && !this.utils.isString(definition.idAttribute)) {
throw new IA(errorPrefix + 'definition.idAttribute: Must be a string!');
} else if (definition.endpoint && !this.utils.isString(definition.endpoint)) {
throw new IA(errorPrefix + 'definition.endpoint: Must be a string!');
} else if (this.store[definition.name]) {
throw new this.errors.R(errorPrefix + definition.name + ' is already registered!');
}
var _this = this,
def = this.definitions[definition.name];
try {
Resource.prototype = this.defaults;
this.definitions[definition.name] = new Resource(this.utils, definition);
var cache = this.cacheFactory('DS.' + def.name, {
maxAge: def.maxAge || null,
recycleFreq: def.recycleFreq || 1000,
cacheFlushInterval: def.cacheFlushInterval || null,
deleteOnExpire: def.deleteOnExpire || 'none',
onExpire: function (id) {
_this.eject(def.name, id);
},
capacity: Number.MAX_VALUE,
storageMode: 'memory',
storageImpl: null,
disabled: false,
storagePrefix: 'DS.' + def.name
});
var _this = this;
var def = this.definitions[definition.name];
if (def.methods) {
def.class = definition.name[0].toUpperCase() + definition.name.substring(1);
eval('function ' + def.class + '() {}');
def[def.class] = eval(def.class);
this.utils.deepMixIn(def[def.class].prototype, def.methods);
}
var cache = this.cacheFactory('DS.' + def.name, {
maxAge: def.maxAge || null,
recycleFreq: def.recycleFreq || 1000,
cacheFlushInterval: def.cacheFlushInterval || null,
deleteOnExpire: def.deleteOnExpire || 'none',
onExpire: function (id) {
_this.eject(def.name, id);
},
capacity: Number.MAX_VALUE,
storageMode: 'memory',
storageImpl: null,
disabled: false,
storagePrefix: 'DS.' + def.name
});
this.store[def.name] = {
collection: [],
completedQueries: {},
pendingQueries: {},
index: cache,
modified: {},
saved: {},
previousAttributes: {},
observers: {},
collectionModified: 0
};
} catch (err) {
delete this.definitions[definition.name];
delete this.store[definition.name];
throw new this.errors.UnhandledError(err);
}
if (def.methods) {
def.class = definition.name[0].toUpperCase() + definition.name.substring(1);
eval('function ' + def.class + '() {}');
def[def.class] = eval(def.class);
this.utils.deepMixIn(def[def.class].prototype, def.methods);
}
if (def.computed) {
this.utils.forOwn(def.computed, function (fn, field) {
if (def.methods && field in def.methods) {
_this.$log.warn(errorPrefix + 'Computed property "' + field + '" conflicts with previously defined prototype method!');
}
var match = fn.toString().match(/function.*?\(([\s\S]*?)\)/);
var deps = match[1].split(',');
fn.deps = _this.utils.filter(deps, function (dep) {
return !!dep;
});
angular.forEach(fn.deps, function (val, index) {
fn.deps[index] = val.trim();
});
});
}
this.store[def.name] = {
collection: [],
completedQueries: {},
pendingQueries: {},
index: cache,
modified: {},
saved: {},
previousAttributes: {},
observers: {},
collectionModified: 0
};
}
catch
(err) {
delete this.definitions[definition.name];
delete this.store[definition.name];
throw err;
}
}
module.exports = defineResource;

@@ -1,2 +0,2 @@

var observe = require('observejs');
var observe = require('../../../lib/observe-js/observe-js');

@@ -22,20 +22,13 @@ /**

*
* ## Throws
*
* - `{UnhandledError}`
*/
function digest() {
try {
if (!this.$rootScope.$$phase) {
this.$rootScope.$apply(function () {
observe.Platform.performMicrotaskCheckpoint();
});
} else {
observe.Platform.performMicrotaskCheckpoint();
}
} catch (err) {
throw new this.errors.UnhandledError(err);
}
if (!this.$rootScope.$$phase) {
this.$rootScope.$apply(function () {
observe.Platform.performMicrotaskCheckpoint();
});
} else {
observe.Platform.performMicrotaskCheckpoint();
}
}
module.exports = digest;
var errorPrefix = 'DS.eject(resourceName, id): ';
function _eject(definition, resource, id) {
var found = false;
for (var i = 0; i < resource.collection.length; i++) {
if (resource.collection[i][definition.idAttribute] == id) {
found = true;
break;
}
}
if (found) {
resource.collection.splice(i, 1);
resource.observers[id].close();
delete resource.observers[id];
var found = false;
for (var i = 0; i < resource.collection.length; i++) {
if (resource.collection[i][definition.idAttribute] == id) {
found = true;
break;
}
}
if (found) {
resource.collection.splice(i, 1);
resource.observers[id].close();
delete resource.observers[id];
resource.index.remove(id);
delete resource.previousAttributes[id];
delete resource.modified[id];
delete resource.saved[id];
}
resource.index.remove(id);
delete resource.previousAttributes[id];
delete resource.modified[id];
delete resource.saved[id];
}
}

@@ -49,4 +49,3 @@

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*

@@ -57,27 +56,23 @@ * @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.

function eject(resourceName, id) {
if (!this.definitions[resourceName]) {
throw new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!');
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } });
}
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IA(errorPrefix + 'id: Must be a string or a number!');
}
var resource = this.store[resourceName],
_this = this;
var resource = this.store[resourceName];
var _this = this;
try {
if (!this.$rootScope.$$phase) {
this.$rootScope.$apply(function () {
_eject(_this.definitions[resourceName], resource, id);
resource.collectionModified = _this.utils.updateTimestamp(resource.collectionModified);
});
} else {
_eject(_this.definitions[resourceName], resource, id);
resource.collectionModified = _this.utils.updateTimestamp(resource.collectionModified);
}
delete this.store[resourceName].completedQueries[id];
} catch (err) {
throw new this.errors.UnhandledError(err);
}
if (!this.$rootScope.$$phase) {
this.$rootScope.$apply(function () {
_eject(_this.definitions[resourceName], resource, id);
resource.collectionModified = _this.utils.updateTimestamp(resource.collectionModified);
});
} else {
_eject(_this.definitions[resourceName], resource, id);
resource.collectionModified = _this.utils.updateTimestamp(resource.collectionModified);
}
delete this.store[resourceName].completedQueries[id];
}
module.exports = eject;
var errorPrefix = 'DS.ejectAll(resourceName[, params]): ';
function _ejectAll(definition, resource, params) {
var queryHash = this.utils.toJson(params),
items = this.filter(definition.name, params);
var queryHash = this.utils.toJson(params);
var items = this.filter(definition.name, params);
var ids = this.utils.toLookup(items, definition.idAttribute);
var _this = this;
for (var i = 0; i < items.length; i++) {
this.eject(definition.name, items[i][definition.idAttribute]);
}
angular.forEach(ids, function (item, id) {
_this.eject(definition.name, id);
});
delete resource.completedQueries[queryHash];
delete resource.completedQueries[queryHash];
}

@@ -44,3 +46,3 @@

*
* DS.ejectAll('document', { query: { where: { author: 'Sally Jane' } } });
* DS.ejectAll('document', { where: { author: 'Sally Jane' } });
*

@@ -64,4 +66,3 @@ * DS.filter('document'); // [ { title: 'How to Cook', id: 45, author: 'John Anderson' } ]

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*

@@ -71,35 +72,38 @@ * @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.

*
* - `{object=}` - `query` - The query object by which to filter items of the type specified by `resourceName`. Properties:
* - `{object=}` - `where` - Where clause.
* - `{number=}` - `limit` - Limit clause.
* - `{skip=}` - `skip` - Skip clause.
* - `{orderBy=}` - `orderBy` - OrderBy clause.
* - `{object=}` - `where` - Where clause.
* - `{number=}` - `limit` - Limit clause.
* - `{number=}` - `skip` - Skip clause.
* - `{number=}` - `offset` - Same as skip.
* - `{string|array=}` - `orderBy` - OrderBy clause.
*/
function ejectAll(resourceName, params) {
params = params || {};
params = params || {};
if (!this.definitions[resourceName]) {
throw new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!');
} else if (!this.utils.isObject(params)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'params: Must be an object!', { params: { actual: typeof params, expected: 'object' } });
}
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isObject(params)) {
throw new this.errors.IA(errorPrefix + 'params: Must be an object!');
}
var resource = this.store[resourceName],
_this = this;
var _this = this;
var resource = this.store[resourceName];
var queryHash = this.utils.toJson(params);
try {
if (!this.$rootScope.$$phase) {
this.$rootScope.$apply(function () {
_ejectAll.apply(_this, [_this.definitions[resourceName], resource, params]);
resource.collectionModified = _this.utils.updateTimestamp(resource.collectionModified);
});
} else {
_ejectAll.apply(_this, [_this.definitions[resourceName], resource, params]);
resource.collectionModified = this.utils.updateTimestamp(resource.collectionModified);
}
} catch (err) {
throw new this.errors.UnhandledError(err);
}
delete resource.completedQueries[queryHash];
if (this.utils.isEmpty(params)) {
resource.completedQueries = {};
}
if (!this.$rootScope.$$phase) {
this.$rootScope.$apply(function () {
_ejectAll.apply(_this, [_this.definitions[resourceName], resource, params]);
resource.collectionModified = _this.utils.updateTimestamp(resource.collectionModified);
});
} else {
_ejectAll.apply(_this, [_this.definitions[resourceName], resource, params]);
resource.collectionModified = this.utils.updateTimestamp(resource.collectionModified);
}
}
module.exports = ejectAll;

@@ -1,3 +0,2 @@

/* jshint loopfunc: true */
var errorPrefix = 'DS.filter(resourceName, params[, options]): ';
var errorPrefix = 'DS.filter(resourceName[, params][, options]): ';

@@ -13,3 +12,3 @@ /**

* ```js
* DS.filter(resourceName, params[, options])
* DS.filter(resourceName[, params][, options])
* ```

@@ -26,132 +25,57 @@ *

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*
* @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.
* @param {object} params Parameter object that is serialized into the query string. Properties:
* @param {object=} params Parameter object that is serialized into the query string. Properties:
*
* - `{object=}` - `query` - The query object by which to filter items of the type specified by `resourceName`. Properties:
* - `{object=}` - `where` - Where clause.
* - `{number=}` - `limit` - Limit clause.
* - `{skip=}` - `skip` - Skip clause.
* - `{orderBy=}` - `orderBy` - OrderBy clause.
* - `{object=}` - `where` - Where clause.
* - `{number=}` - `limit` - Limit clause.
* - `{number=}` - `skip` - Skip clause.
* - `{number=}` - `offset` - Same as skip.
* - `{string|array=}` - `orderBy` - OrderBy clause.
*
* @param {object=} options Optional configuration. Properties:
* - `{boolean=}` - `loadFromServer` - Send the query to server if it has not been sent yet. Default: `false`.
* - `{boolean=}` - `allowSimpleWhere` - Treat top-level fields on the `params` argument as simple "where" equality clauses. Default: `true`.
* @returns {array} The filtered collection of items of the type specified by `resourceName`.
*/
function filter(resourceName, params, options) {
options = options || {};
var IA = this.errors.IA;
if (!this.definitions[resourceName]) {
throw new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!');
} else if (!this.utils.isObject(params)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'params: Must be an object!', { params: { actual: typeof params, expected: 'object' } });
} else if (!this.utils.isObject(options)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } });
}
options = options || {};
try {
var definition = this.definitions[resourceName],
resource = this.store[resourceName],
_this = this;
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (params && !this.utils.isObject(params)) {
throw new IA(errorPrefix + 'params: Must be an object!');
} else if (!this.utils.isObject(options)) {
throw new IA(errorPrefix + 'options: Must be an object!');
}
// Protect against null
params.query = params.query || {};
var definition = this.definitions[resourceName];
var resource = this.store[resourceName];
var queryHash = this.utils.toJson(params);
// Protect against null
params = params || {};
if (!(queryHash in resource.completedQueries) && options.loadFromServer) {
// This particular query has never been completed
if ('allowSimpleWhere' in options) {
options.allowSimpleWhere = !!options.allowSimpleWhere;
} else {
options.allowSimpleWhere = true;
}
if (!resource.pendingQueries[queryHash]) {
// This particular query has never even been started
this.findAll(resourceName, params, options);
}
}
var queryHash = this.utils.toJson(params);
// The query has been completed, so hit the cache with the query
var filtered = this.utils.filter(resource.collection, function (attrs) {
var keep = true,
where = params.query.where;
if (!(queryHash in resource.completedQueries) && options.loadFromServer) {
// This particular query has never been completed
// Apply 'where' clauses
if (where) {
if (!_this.utils.isObject(where)) {
throw new _this.errors.IllegalArgumentError(errorPrefix + 'params.query.where: Must be an object!', { params: { query: { where: { actual: typeof params.query.where, expected: 'object' } } } });
}
keep = definition.filter(resourceName, where, attrs);
}
return keep;
});
if (!resource.pendingQueries[queryHash]) {
// This particular query has never even been started
this.findAll(resourceName, params, options);
}
}
// Apply 'orderBy'
if (params.query.orderBy) {
if (this.utils.isString(params.query.orderBy)) {
params.query.orderBy = [
[params.query.orderBy, 'ASC']
];
}
if (this.utils.isArray(params.query.orderBy)) {
for (var i = 0; i < params.query.orderBy.length; i++) {
if (this.utils.isString(params.query.orderBy[i])) {
params.query.orderBy[i] = [params.query.orderBy[i], 'ASC'];
} else if (!this.utils.isArray(params.query.orderBy[i])) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'params.query.orderBy[' + i + ']: Must be a string or an array!', { params: { query: { 'orderBy[i]': { actual: typeof params.query.orderBy[i], expected: 'string|array' } } } });
}
filtered = this.utils.sort(filtered, function (a, b) {
var cA = a[params.query.orderBy[i][0]], cB = b[params.query.orderBy[i][0]];
if (_this.utils.isString(cA)) {
cA = _this.utils.upperCase(cA);
}
if (_this.utils.isString(cB)) {
cB = _this.utils.upperCase(cB);
}
if (params.query.orderBy[i][1] === 'DESC') {
if (cB < cA) {
return -1;
} else if (cB > cA) {
return 1;
} else {
return 0;
}
} else {
if (cA < cB) {
return -1;
} else if (cA > cB) {
return 1;
} else {
return 0;
}
}
});
}
} else {
throw new this.errors.IllegalArgumentError(errorPrefix + 'params.query.orderBy: Must be a string or an array!', { params: { query: { orderBy: { actual: typeof params.query.orderBy, expected: 'string|array' } } } });
}
}
// Apply 'limit' and 'skip'
if (this.utils.isNumber(params.query.limit) && this.utils.isNumber(params.query.skip)) {
filtered = this.utils.slice(filtered, params.query.skip, Math.min(filtered.length, params.query.skip + params.query.limit));
} else if (this.utils.isNumber(params.query.limit)) {
filtered = this.utils.slice(filtered, 0, Math.min(filtered.length, params.query.limit));
} else if (this.utils.isNumber(params.query.skip)) {
if (params.query.skip < filtered.length) {
filtered = this.utils.slice(filtered, params.query.skip);
} else {
filtered = [];
}
}
return filtered;
} catch (err) {
if (err instanceof this.errors.IllegalArgumentError) {
throw err;
} else {
throw new this.errors.UnhandledError(err);
}
}
return definition.filter.call(this, resource.collection, resourceName, params, options);
}
module.exports = filter;

@@ -25,4 +25,3 @@ var errorPrefix = 'DS.get(resourceName, id[, options]): ';

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*

@@ -36,28 +35,27 @@ * @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.

function get(resourceName, id, options) {
options = options || {};
var IA = this.errors.IA;
if (!this.definitions[resourceName]) {
throw new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!');
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } });
} else if (!this.utils.isObject(options)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } });
}
options = options || {};
try {
// cache miss, request resource from server
var item = this.store[resourceName].index.get(id);
if (!item && options.loadFromServer) {
this.find(resourceName, id).then(null, function (err) {
throw err;
});
}
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new IA(errorPrefix + 'id: Must be a string or a number!');
} else if (!this.utils.isObject(options)) {
throw new IA(errorPrefix + 'options: Must be an object!');
}
var _this = this;
// return resource from cache
return item;
} catch (err) {
throw new this.errors.UnhandledError(err);
}
// cache miss, request resource from server
var item = this.store[resourceName].index.get(id);
if (!item && options.loadFromServer) {
this.find(resourceName, id).then(null, function (err) {
return _this.$q.reject(err);
});
}
// return resource from cache
return item;
}
module.exports = get;
var errorPrefix = 'DS.hasChanges(resourceName, id): ';
function diffIsEmpty(utils, diff) {
return !(utils.isEmpty(diff.added) &&
utils.isEmpty(diff.removed) &&
utils.isEmpty(diff.changed));
return !(utils.isEmpty(diff.added) &&
utils.isEmpty(diff.removed) &&
utils.isEmpty(diff.changed));
}

@@ -35,4 +35,3 @@

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*

@@ -44,20 +43,16 @@ * @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.

function hasChanges(resourceName, id) {
if (!this.definitions[resourceName]) {
throw new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!');
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } });
}
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IA(errorPrefix + 'id: Must be a string or a number!');
}
try {
// return resource from cache
if (this.get(resourceName, id)) {
return diffIsEmpty(this.utils, this.changes(resourceName, id));
} else {
return false;
}
} catch (err) {
throw new this.errors.UnhandledError(err);
}
// return resource from cache
if (this.get(resourceName, id)) {
return diffIsEmpty(this.utils, this.changes(resourceName, id));
} else {
return false;
}
}
module.exports = hasChanges;
module.exports = {
/**
* @doc method
* @id DS.sync_methods:defineResource
* @name defineResource
* @methodOf DS
* @description
* See [DS.defineResource](/documentation/api/api/DS.sync_methods:defineResource).
*/
defineResource: require('./defineResource'),
/**
* @doc method
* @id DS.sync_methods:defineResource
* @name defineResource
* @methodOf DS
* @description
* See [DS.defineResource](/documentation/api/api/DS.sync_methods:defineResource).
*/
defineResource: require('./defineResource'),
/**
* @doc method
* @id DS.sync_methods:bindOne
* @name bindOne
* @methodOf DS
* @description
* See [DS.bindOne](/documentation/api/api/DS.sync_methods:bindOne).
*/
bindOne: require('./bindOne'),
/**
* @doc method
* @id DS.sync_methods:bindOne
* @name bindOne
* @methodOf DS
* @description
* See [DS.bindOne](/documentation/api/api/DS.sync_methods:bindOne).
*/
bindOne: require('./bindOne'),
/**
* @doc method
* @id DS.sync_methods:bindAll
* @name bindAll
* @methodOf DS
* @description
* See [DS.bindAll](/documentation/api/api/DS.sync_methods:bindAll).
*/
bindAll: require('./bindAll'),
/**
* @doc method
* @id DS.sync_methods:bindAll
* @name bindAll
* @methodOf DS
* @description
* See [DS.bindAll](/documentation/api/api/DS.sync_methods:bindAll).
*/
bindAll: require('./bindAll'),
/**
* @doc method
* @id DS.sync_methods:eject
* @name eject
* @methodOf DS
* @description
* See [DS.eject](/documentation/api/api/DS.sync_methods:eject).
*/
eject: require('./eject'),
/**
* @doc method
* @id DS.sync_methods:eject
* @name eject
* @methodOf DS
* @description
* See [DS.eject](/documentation/api/api/DS.sync_methods:eject).
*/
eject: require('./eject'),
/**
* @doc method
* @id DS.sync_methods:ejectAll
* @name ejectAll
* @methodOf DS
* @description
* See [DS.ejectAll](/documentation/api/api/DS.sync_methods:ejectAll).
*/
ejectAll: require('./ejectAll'),
/**
* @doc method
* @id DS.sync_methods:ejectAll
* @name ejectAll
* @methodOf DS
* @description
* See [DS.ejectAll](/documentation/api/api/DS.sync_methods:ejectAll).
*/
ejectAll: require('./ejectAll'),
/**
* @doc method
* @id DS.sync_methods:filter
* @name filter
* @methodOf DS
* @description
* See [DS.filter](/documentation/api/api/DS.sync_methods:filter).
*/
filter: require('./filter'),
/**
* @doc method
* @id DS.sync_methods:filter
* @name filter
* @methodOf DS
* @description
* See [DS.filter](/documentation/api/api/DS.sync_methods:filter).
*/
filter: require('./filter'),
/**
* @doc method
* @id DS.sync_methods:get
* @name get
* @methodOf DS
* @description
* See [DS.get](/documentation/api/api/DS.sync_methods:get).
*/
get: require('./get'),
/**
* @doc method
* @id DS.sync_methods:get
* @name get
* @methodOf DS
* @description
* See [DS.get](/documentation/api/api/DS.sync_methods:get).
*/
get: require('./get'),
/**
* @doc method
* @id DS.sync_methods:inject
* @name inject
* @methodOf DS
* @description
* See [DS.inject](/documentation/api/api/DS.sync_methods:inject).
*/
inject: require('./inject'),
/**
* @doc method
* @id DS.sync_methods:inject
* @name inject
* @methodOf DS
* @description
* See [DS.inject](/documentation/api/api/DS.sync_methods:inject).
*/
inject: require('./inject'),
/**
* @doc method
* @id DS.sync_methods:lastModified
* @name lastModified
* @methodOf DS
* @description
* See [DS.lastModified](/documentation/api/api/DS.sync_methods:lastModified).
*/
lastModified: require('./lastModified'),
/**
* @doc method
* @id DS.sync_methods:lastModified
* @name lastModified
* @methodOf DS
* @description
* See [DS.lastModified](/documentation/api/api/DS.sync_methods:lastModified).
*/
lastModified: require('./lastModified'),
/**
* @doc method
* @id DS.sync_methods:lastSaved
* @name lastSaved
* @methodOf DS
* @description
* See [DS.lastSaved](/documentation/api/api/DS.sync_methods:lastSaved).
*/
lastSaved: require('./lastSaved'),
/**
* @doc method
* @id DS.sync_methods:lastSaved
* @name lastSaved
* @methodOf DS
* @description
* See [DS.lastSaved](/documentation/api/api/DS.sync_methods:lastSaved).
*/
lastSaved: require('./lastSaved'),
/**
* @doc method
* @id DS.sync_methods:digest
* @name digest
* @methodOf DS
* @description
* See [DS.digest](/documentation/api/api/DS.sync_methods:digest).
*/
digest: require('./digest'),
/**
* @doc method
* @id DS.sync_methods:digest
* @name digest
* @methodOf DS
* @description
* See [DS.digest](/documentation/api/api/DS.sync_methods:digest).
*/
digest: require('./digest'),
/**
* @doc method
* @id DS.sync_methods:changes
* @name changes
* @methodOf DS
* @description
* See [DS.changes](/documentation/api/api/DS.sync_methods:changes).
*/
changes: require('./changes'),
/**
* @doc method
* @id DS.sync_methods:changes
* @name changes
* @methodOf DS
* @description
* See [DS.changes](/documentation/api/api/DS.sync_methods:changes).
*/
changes: require('./changes'),
/**
* @doc method
* @id DS.sync_methods:previous
* @name previous
* @methodOf DS
* @description
* See [DS.previous](/documentation/api/api/DS.sync_methods:previous).
*/
previous: require('./previous'),
/**
* @doc method
* @id DS.sync_methods:previous
* @name previous
* @methodOf DS
* @description
* See [DS.previous](/documentation/api/api/DS.sync_methods:previous).
*/
previous: require('./previous'),
/**
* @doc method
* @id DS.sync_methods:hasChanges
* @name hasChanges
* @methodOf DS
* @description
* See [DS.hasChanges](/documentation/api/api/DS.sync_methods:hasChanges).
*/
hasChanges: require('./hasChanges')
/**
* @doc method
* @id DS.sync_methods:hasChanges
* @name hasChanges
* @methodOf DS
* @description
* See [DS.hasChanges](/documentation/api/api/DS.sync_methods:hasChanges).
*/
hasChanges: require('./hasChanges')
};

@@ -1,80 +0,124 @@

var observe = require('observejs'),
errorPrefix = 'DS.inject(resourceName, attrs[, options]): ';
var observe = require('../../../lib/observe-js/observe-js');
var errorPrefix = 'DS.inject(resourceName, attrs[, options]): ';
function _inject(definition, resource, attrs) {
var _this = this,
$log = _this.$log;
var _this = this;
var $log = _this.$log;
function _react(added, removed, changed, getOldValueFn) {
try {
var innerId = getOldValueFn(definition.idAttribute);
function _react(added, removed, changed, getOldValueFn) {
var innerId = getOldValueFn(definition.idAttribute);
resource.modified[innerId] = _this.utils.updateTimestamp(resource.modified[innerId]);
resource.collectionModified = _this.utils.updateTimestamp(resource.collectionModified);
resource.modified[innerId] = _this.utils.updateTimestamp(resource.modified[innerId]);
resource.collectionModified = _this.utils.updateTimestamp(resource.collectionModified);
if (definition.idAttribute in changed) {
$log.error('Doh! You just changed the primary key of an object! ' +
'I don\'t know how to handle this yet, so your data for the "' + definition.name +
'" resource is now in an undefined (probably broken) state.');
}
} catch (err) {
throw new _this.errors.UnhandledError(err);
}
}
if (definition.computed) {
var item = _this.get(definition.name, innerId);
_this.utils.forOwn(definition.computed, function (fn, field) {
var compute = false;
// check if required fields changed
angular.forEach(fn.deps, function (dep) {
if (dep in changed || dep in removed || dep in changed || !(field in item)) {
compute = true;
}
});
if (compute) {
var args = [];
angular.forEach(fn.deps, function (dep) {
args.push(item[dep]);
});
// recompute property
item[field] = fn.apply(item, args);
}
});
}
if (_this.utils.isArray(attrs)) {
for (var i = 0; i < attrs.length; i++) {
_inject.call(_this, definition, resource, attrs[i]);
}
} else {
if (!(definition.idAttribute in attrs)) {
throw new _this.errors.RuntimeError(errorPrefix + 'attrs: Must contain the property specified by `idAttribute`!');
} else {
try {
definition.beforeInject(definition.name, attrs);
var id = attrs[definition.idAttribute],
item = this.get(definition.name, id);
if (definition.idAttribute in changed) {
$log.error('Doh! You just changed the primary key of an object! ' +
'I don\'t know how to handle this yet, so your data for the "' + definition.name +
'" resource is now in an undefined (probably broken) state.');
}
}
if (!item) {
if (definition.class) {
if (attrs instanceof definition[definition.class]) {
item = attrs;
} else {
item = new definition[definition.class]();
}
} else {
item = {};
}
resource.previousAttributes[id] = {};
var injected;
if (_this.utils.isArray(attrs)) {
injected = [];
for (var i = 0; i < attrs.length; i++) {
injected.push(_inject.call(_this, definition, resource, attrs[i]));
}
} else {
// check if "idAttribute" is a computed property
if (definition.computed && definition.computed[definition.idAttribute]) {
var args = [];
angular.forEach(definition.computed[definition.idAttribute].deps, function (dep) {
args.push(attrs[dep]);
});
attrs[definition.idAttribute] = definition.computed[definition.idAttribute].apply(attrs, args);
}
if (!(definition.idAttribute in attrs)) {
throw new _this.errors.R(errorPrefix + 'attrs: Must contain the property specified by `idAttribute`!');
} else {
try {
definition.beforeInject(definition.name, attrs);
var id = attrs[definition.idAttribute],
item = this.get(definition.name, id);
_this.utils.deepMixIn(item, attrs);
_this.utils.deepMixIn(resource.previousAttributes[id], attrs);
if (!item) {
if (definition.class) {
if (attrs instanceof definition[definition.class]) {
item = attrs;
} else {
item = new definition[definition.class]();
}
} else {
item = {};
}
resource.previousAttributes[id] = {};
resource.collection.push(item);
_this.utils.deepMixIn(item, attrs);
_this.utils.deepMixIn(resource.previousAttributes[id], attrs);
resource.observers[id] = new observe.ObjectObserver(item, _react);
resource.index.put(id, item);
resource.collection.push(item);
_react({}, {}, {}, function () {
return id;
});
} else {
_this.utils.deepMixIn(item, attrs);
if (typeof resource.index.touch === 'function') {
resource.index.touch(id);
} else {
resource.index.put(id, resource.index.get(id));
}
resource.observers[id].deliver();
}
resource.saved[id] = _this.utils.updateTimestamp(resource.saved[id]);
definition.afterInject(definition.name, item);
} catch (err) {
$log.error(err);
$log.error('inject failed!', definition.name, attrs);
}
}
}
resource.observers[id] = new observe.ObjectObserver(item, _react);
resource.index.put(id, item);
_react({}, {}, {}, function () {
return id;
});
} else {
_this.utils.deepMixIn(item, attrs);
if (typeof resource.index.touch === 'function') {
resource.index.touch(id);
} else {
resource.index.put(id, resource.index.get(id));
}
resource.observers[id].deliver();
}
resource.saved[id] = _this.utils.updateTimestamp(resource.saved[id]);
definition.afterInject(definition.name, item);
injected = item;
} catch (err) {
$log.error(err);
$log.error('inject failed!', definition.name, attrs);
}
}
}
return injected;
}
function _injectRelations(definition, injected) {
var _this = this;
_this.utils.forOwn(definition.relations, function (relation, type) {
_this.utils.forOwn(relation, function (def, relationName) {
if (_this.definitions[relationName] && injected[def.localField]) {
try {
injected[def.localField] = _this.inject(relationName, injected[def.localField]);
} catch (err) {
_this.$log.error(errorPrefix + 'Failed to inject ' + type + ' relation: "' + relationName + '"!', err);
}
}
});
});
}
/**

@@ -117,3 +161,3 @@ * @doc method

* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*

@@ -127,38 +171,33 @@ * @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.

function inject(resourceName, attrs, options) {
options = options || {};
var IA = this.errors.IA;
if (!this.definitions[resourceName]) {
throw new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!');
} else if (!this.utils.isObject(attrs) && !this.utils.isArray(attrs)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'attrs: Must be an object or an array!', { attrs: { actual: typeof attrs, expected: 'object|array' } });
} else if (!this.utils.isObject(options)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } });
}
options = options || {};
var definition = this.definitions[resourceName],
resource = this.store[resourceName],
_this = this;
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isObject(attrs) && !this.utils.isArray(attrs)) {
throw new IA(errorPrefix + 'attrs: Must be an object or an array!');
} else if (!this.utils.isObject(options)) {
throw new IA(errorPrefix + 'options: Must be an object!');
}
try {
if (!this.$rootScope.$$phase) {
this.$rootScope.$apply(function () {
_inject.apply(_this, [definition, resource, attrs]);
});
} else {
_inject.apply(_this, [definition, resource, attrs]);
}
if (_this.utils.isArray(attrs)) {
return attrs;
} else {
return this.get(resourceName, attrs[definition.idAttribute]);
}
} catch (err) {
if (!(err instanceof this.errors.RuntimeError)) {
throw new this.errors.UnhandledError(err);
} else {
throw err;
}
}
var definition = this.definitions[resourceName];
var resource = this.store[resourceName];
var _this = this;
var injected;
if (!this.$rootScope.$$phase) {
this.$rootScope.$apply(function () {
injected = _inject.call(_this, definition, resource, attrs);
});
} else {
injected = _inject.call(_this, definition, resource, attrs);
}
if (definition.relations) {
_injectRelations.call(_this, definition, injected);
}
return injected;
}
module.exports = inject;

@@ -29,4 +29,3 @@ var errorPrefix = 'DS.lastModified(resourceName[, id]): ';

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*

@@ -39,20 +38,16 @@ * @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.

function lastModified(resourceName, id) {
if (!this.definitions[resourceName]) {
throw new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!');
} else if (id && !this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } });
}
try {
if (id) {
if (!(id in this.store[resourceName].modified)) {
this.store[resourceName].modified[id] = 0;
}
return this.store[resourceName].modified[id];
}
return this.store[resourceName].collectionModified;
} catch (err) {
throw new this.errors.UnhandledError(err);
}
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (id && !this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IA(errorPrefix + 'id: Must be a string or a number!');
}
if (id) {
if (!(id in this.store[resourceName].modified)) {
this.store[resourceName].modified[id] = 0;
}
return this.store[resourceName].modified[id];
}
return this.store[resourceName].collectionModified;
}
module.exports = lastModified;

@@ -36,4 +36,3 @@ var errorPrefix = 'DS.lastSaved(resourceName[, id]): ';

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*

@@ -45,17 +44,13 @@ * @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.

function lastSaved(resourceName, id) {
if (!this.definitions[resourceName]) {
throw new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!');
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } });
}
try {
if (!(id in this.store[resourceName].saved)) {
this.store[resourceName].saved[id] = 0;
}
return this.store[resourceName].saved[id];
} catch (err) {
throw new this.errors.UnhandledError(err);
}
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IA(errorPrefix + 'id: Must be a string or a number!');
}
if (!(id in this.store[resourceName].saved)) {
this.store[resourceName].saved[id] = 0;
}
return this.store[resourceName].saved[id];
}
module.exports = lastSaved;

@@ -31,4 +31,3 @@ var errorPrefix = 'DS.previous(resourceName, id): ';

* - `{IllegalArgumentError}`
* - `{RuntimeError}`
* - `{UnhandledError}`
* - `{NonexistentResourceError}`
*

@@ -40,16 +39,12 @@ * @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.

function previous(resourceName, id) {
if (!this.definitions[resourceName]) {
throw new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!');
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } });
}
if (!this.definitions[resourceName]) {
throw new this.errors.NER(errorPrefix + resourceName);
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
throw new this.errors.IA(errorPrefix + 'id: Must be a string or a number!');
}
try {
// return resource from cache
return angular.copy(this.store[resourceName].previousAttributes[id]);
} catch (err) {
throw new this.errors.UnhandledError(err);
}
// return resource from cache
return angular.copy(this.store[resourceName].previousAttributes[id]);
}
module.exports = previous;
/**
* @doc function
* @id errors.types:UnhandledError
* @name UnhandledError
* @description Error that is thrown/returned when Reheat encounters an uncaught/unknown exception.
* @param {Error} error The originally thrown error.
* @returns {UnhandledError} A new instance of `UnhandledError`.
*/
function UnhandledError(error) {
Error.call(this);
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
}
error = error || {};
/**
* @doc property
* @id errors.types:UnhandledError.type
* @name type
* @propertyOf errors.types:UnhandledError
* @description Name of error type. Default: `"UnhandledError"`.
*/
this.type = this.constructor.name;
/**
* @doc property
* @id errors.types:UnhandledError.originalError
* @name originalError
* @propertyOf errors.types:UnhandledError
* @description A reference to the original error that was thrown.
*/
this.originalError = error;
/**
* @doc property
* @id errors.types:UnhandledError.message
* @name message
* @propertyOf errors.types:UnhandledError
* @description Message and stack trace. Same as `UnhandledError#stack`.
*/
this.message = 'UnhandledError: This is an uncaught exception. Please consider submitting an issue at https://github.com/jmdobry/angular-data/issues.\n\n' +
'Original Uncaught Exception:\n' + (error.stack ? error.stack.toString() : error.stack);
/**
* @doc property
* @id errors.types:UnhandledError.stack
* @name stack
* @propertyOf errors.types:UnhandledError
* @description Message and stack trace. Same as `UnhandledError#message`.
*/
this.stack = this.message;
}
UnhandledError.prototype = Object.create(Error.prototype);
UnhandledError.prototype.constructor = UnhandledError;
/**
* @doc function
* @id errors.types:IllegalArgumentError

@@ -64,37 +7,27 @@ * @name IllegalArgumentError

* @param {string=} message Error message. Default: `"Illegal Argument!"`.
* @param {object=} errors Object containing information about the error.
* @returns {IllegalArgumentError} A new instance of `IllegalArgumentError`.
*/
function IllegalArgumentError(message, errors) {
Error.call(this);
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
}
function IllegalArgumentError(message) {
Error.call(this);
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
}
/**
* @doc property
* @id errors.types:IllegalArgumentError.type
* @name type
* @propertyOf errors.types:IllegalArgumentError
* @description Name of error type. Default: `"IllegalArgumentError"`.
*/
this.type = this.constructor.name;
/**
* @doc property
* @id errors.types:IllegalArgumentError.type
* @name type
* @propertyOf errors.types:IllegalArgumentError
* @description Name of error type. Default: `"IllegalArgumentError"`.
*/
this.type = this.constructor.name;
/**
* @doc property
* @id errors.types:IllegalArgumentError.errors
* @name errors
* @propertyOf errors.types:IllegalArgumentError
* @description Object containing information about the error.
*/
this.errors = errors || {};
/**
* @doc property
* @id errors.types:IllegalArgumentError.message
* @name message
* @propertyOf errors.types:IllegalArgumentError
* @description Error message. Default: `"Illegal Argument!"`.
*/
this.message = message || 'Illegal Argument!';
/**
* @doc property
* @id errors.types:IllegalArgumentError.message
* @name message
* @propertyOf errors.types:IllegalArgumentError
* @description Error message. Default: `"Illegal Argument!"`.
*/
this.message = message || 'Illegal Argument!';
}

@@ -111,37 +44,27 @@

* @param {string=} message Error message. Default: `"Runtime Error!"`.
* @param {object=} errors Object containing information about the error.
* @returns {RuntimeError} A new instance of `RuntimeError`.
*/
function RuntimeError(message, errors) {
Error.call(this);
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
}
function RuntimeError(message) {
Error.call(this);
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
}
/**
* @doc property
* @id errors.types:RuntimeError.type
* @name type
* @propertyOf errors.types:RuntimeError
* @description Name of error type. Default: `"RuntimeError"`.
*/
this.type = this.constructor.name;
/**
* @doc property
* @id errors.types:RuntimeError.type
* @name type
* @propertyOf errors.types:RuntimeError
* @description Name of error type. Default: `"RuntimeError"`.
*/
this.type = this.constructor.name;
/**
* @doc property
* @id errors.types:RuntimeError.errors
* @name errors
* @propertyOf errors.types:RuntimeError
* @description Object containing information about the error.
*/
this.errors = errors || {};
/**
* @doc property
* @id errors.types:RuntimeError.message
* @name message
* @propertyOf errors.types:RuntimeError
* @description Error message. Default: `"Runtime Error!"`.
*/
this.message = message || 'RuntimeError Error!';
/**
* @doc property
* @id errors.types:RuntimeError.message
* @name message
* @propertyOf errors.types:RuntimeError
* @description Error message. Default: `"Runtime Error!"`.
*/
this.message = message || 'RuntimeError Error!';
}

@@ -153,2 +76,38 @@

/**
* @doc function
* @id errors.types:NonexistentResourceError
* @name NonexistentResourceError
* @description Error that is thrown/returned when trying to access a resource that does not exist.
* @param {string=} resourceName Name of non-existent resource.
* @returns {NonexistentResourceError} A new instance of `NonexistentResourceError`.
*/
function NonexistentResourceError(resourceName) {
Error.call(this);
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
}
/**
* @doc property
* @id errors.types:NonexistentResourceError.type
* @name type
* @propertyOf errors.types:NonexistentResourceError
* @description Name of error type. Default: `"NonexistentResourceError"`.
*/
this.type = this.constructor.name;
/**
* @doc property
* @id errors.types:NonexistentResourceError.message
* @name message
* @propertyOf errors.types:NonexistentResourceError
* @description Error message. Default: `"Runtime Error!"`.
*/
this.message = (resourceName || '') + ' is not a registered resource!';
}
NonexistentResourceError.prototype = Object.create(Error.prototype);
NonexistentResourceError.prototype.constructor = NonexistentResourceError;
/**
* @doc interface

@@ -160,5 +119,5 @@ * @id errors

*
* - [UnhandledError](/documentation/api/api/errors.types:UnhandledError)
* - [IllegalArgumentError](/documentation/api/api/errors.types:IllegalArgumentError)
* - [RuntimeError](/documentation/api/api/errors.types:RuntimeError)
* - [NonexistentResourceError](/documentation/api/api/errors.types:NonexistentResourceError)
*

@@ -168,7 +127,10 @@ * References to the constructor functions of these errors can be found in `DS.errors`.

module.exports = [function () {
return {
UnhandledError: UnhandledError,
IllegalArgumentError: IllegalArgumentError,
RuntimeError: RuntimeError
};
return {
IllegalArgumentError: IllegalArgumentError,
IA: IllegalArgumentError,
RuntimeError: RuntimeError,
R: RuntimeError,
NonexistentResourceError: NonexistentResourceError,
NER: NonexistentResourceError
};
}];
(function (window, angular, undefined) {
'use strict';
'use strict';
/**
* @doc overview
* @id angular-data
* @name angular-data
* @description
* __Version:__ 0.9.0
*
* ## Install
*
* #### Bower
* ```text
* bower install angular-data
* ```
*
* Load `dist/angular-data.js` or `dist/angular-data.min.js` onto your web page after Angular.js.
*
* #### Npm
* ```text
* npm install angular-data
* ```
*
* Load `dist/angular-data.js` or `dist/angular-data.min.js` onto your web page after Angular.js.
*
* #### Manual download
* Download angular-data-<%= pkg.version %>.js from the [Releases](https://github.com/jmdobry/angular-data/releases)
* section of the angular-data GitHub project.
*
* ## Load into Angular
* Your Angular app must depend on the module `"angular-data.DS"` in order to use angular-data. Loading
* angular-data into your app allows you to inject the following:
*
* - `DS`
* - `DSHttpAdapter`
* - `DSUtils`
* - `DSErrors`
*
* [DS](/documentation/api/api/DS) is the Data Store itself, which you will inject often.
* [DSHttpAdapter](/documentation/api/api/DSHttpAdapter) is useful as a wrapper for `$http` and is configurable.
* [DSUtils](/documentation/api/api/DSUtils) has some useful utility methods.
* [DSErrors](/documentation/api/api/DSErrors) provides references to the various errors thrown by the data store.
*/
angular.module('angular-data.DS', ['ng'])
.factory('DSUtils', require('./utils'))
.factory('DSErrors', require('./errors'))
.provider('DSHttpAdapter', require('./adapters/http'))
.provider('DSLocalStorageAdapter', require('./adapters/localStorage'))
.provider('DS', require('./datastore'))
.config(['$provide', function ($provide) {
$provide.decorator('$q', ['$delegate', function ($delegate) {
// do whatever you you want
$delegate.promisify = function (fn, target) {
var _this = this;
return function () {
var deferred = _this.defer(),
args = Array.prototype.slice.apply(arguments);
/**
* @doc overview
* @id angular-data
* @name angular-data
* @description
* __Version:__ 0.10.0
*
* ## Install
*
* #### Bower
* ```text
* bower install angular-data
* ```
*
* Load `dist/angular-data.js` or `dist/angular-data.min.js` onto your web page after Angular.js.
*
* #### Npm
* ```text
* npm install angular-data
* ```
*
* Load `dist/angular-data.js` or `dist/angular-data.min.js` onto your web page after Angular.js.
*
* #### Manual download
* Download angular-data-<%= pkg.version %>.js from the [Releases](https://github.com/jmdobry/angular-data/releases)
* section of the angular-data GitHub project.
*
* ## Load into Angular
* Your Angular app must depend on the module `"angular-data.DS"` in order to use angular-data. Loading
* angular-data into your app allows you to inject the following:
*
* - `DS`
* - `DSHttpAdapter`
* - `DSUtils`
* - `DSErrors`
*
* [DS](/documentation/api/api/DS) is the Data Store itself, which you will inject often.
* [DSHttpAdapter](/documentation/api/api/DSHttpAdapter) is useful as a wrapper for `$http` and is configurable.
* [DSUtils](/documentation/api/api/DSUtils) has some useful utility methods.
* [DSErrors](/documentation/api/api/DSErrors) provides references to the various errors thrown by the data store.
*/
angular.module('angular-data.DS', ['ng'])
.factory('DSUtils', require('./utils'))
.factory('DSErrors', require('./errors'))
.provider('DSHttpAdapter', require('./adapters/http'))
.provider('DSLocalStorageAdapter', require('./adapters/localStorage'))
.provider('DS', require('./datastore'))
.config(['$provide', function ($provide) {
$provide.decorator('$q', ['$delegate', function ($delegate) {
// do whatever you you want
$delegate.promisify = function (fn, target) {
var _this = this;
return function () {
var deferred = _this.defer(),
args = Array.prototype.slice.apply(arguments);
args.push(function (err, result) {
if (err) {
deferred.reject(err);
} else {
deferred.resolve(result);
}
});
args.push(function (err, result) {
if (err) {
deferred.reject(err);
} else {
deferred.resolve(result);
}
});
try {
fn.apply(target || this, args);
} catch (err) {
deferred.reject(err);
}
try {
fn.apply(target || this, args);
} catch (err) {
deferred.reject(err);
}
return deferred.promise;
};
};
return $delegate;
}]);
}]);
return deferred.promise;
};
};
return $delegate;
}]);
}]);
})(window, window.angular);
module.exports = [function () {
return {
isString: angular.isString,
isArray: angular.isArray,
isObject: angular.isObject,
isNumber: angular.isNumber,
isFunction: angular.isFunction,
isEmpty: require('mout/lang/isEmpty'),
toJson: angular.toJson,
makePath: require('mout/string/makePath'),
upperCase: require('mout/string/upperCase'),
deepMixIn: require('mout/object/deepMixIn'),
forOwn: require('mout/object/forOwn'),
pick: require('mout/object/pick'),
set: require('mout/object/set'),
contains: require('mout/array/contains'),
filter: require('mout/array/filter'),
toLookup: require('mout/array/toLookup'),
slice: require('mout/array/slice'),
sort: require('mout/array/sort'),
updateTimestamp: function (timestamp) {
var newTimestamp = typeof Date.now === 'function' ? Date.now() : new Date().getTime();
if (timestamp && newTimestamp <= timestamp) {
return timestamp + 1;
} else {
return newTimestamp;
}
},
deepFreeze: function deepFreeze(o) {
if (typeof Object.freeze === 'function') {
var prop, propKey;
Object.freeze(o); // First freeze the object.
for (propKey in o) {
prop = o[propKey];
if (!o.hasOwnProperty(propKey) || typeof prop !== 'object' || Object.isFrozen(prop)) {
// If the object is on the prototype, not an object, or is already frozen,
// skip it. Note that this might leave an unfrozen reference somewhere in the
// object if there is an already frozen object containing an unfrozen object.
continue;
}
return {
isString: angular.isString,
isArray: angular.isArray,
isObject: angular.isObject,
isNumber: angular.isNumber,
isFunction: angular.isFunction,
isEmpty: require('mout/lang/isEmpty'),
toJson: angular.toJson,
makePath: require('mout/string/makePath'),
upperCase: require('mout/string/upperCase'),
deepMixIn: require('mout/object/deepMixIn'),
forOwn: require('mout/object/forOwn'),
pick: require('mout/object/pick'),
set: require('mout/object/set'),
contains: require('mout/array/contains'),
filter: require('mout/array/filter'),
toLookup: require('mout/array/toLookup'),
slice: require('mout/array/slice'),
sort: require('mout/array/sort'),
updateTimestamp: function (timestamp) {
var newTimestamp = typeof Date.now === 'function' ? Date.now() : new Date().getTime();
if (timestamp && newTimestamp <= timestamp) {
return timestamp + 1;
} else {
return newTimestamp;
}
},
deepFreeze: function deepFreeze(o) {
if (typeof Object.freeze === 'function') {
var prop, propKey;
Object.freeze(o); // First freeze the object.
for (propKey in o) {
prop = o[propKey];
if (!o.hasOwnProperty(propKey) || typeof prop !== 'object' || Object.isFrozen(prop)) {
// If the object is on the prototype, not an object, or is already frozen,
// skip it. Note that this might leave an unfrozen reference somewhere in the
// object if there is an already frozen object containing an unfrozen object.
continue;
}
deepFreeze(prop); // Recursively call deepFreeze.
}
}
},
diffObjectFromOldObject: function (object, oldObject) {
var added = {};
var removed = {};
var changed = {};
deepFreeze(prop); // Recursively call deepFreeze.
}
}
},
diffObjectFromOldObject: function (object, oldObject) {
var added = {};
var removed = {};
var changed = {};
for (var prop in oldObject) {
var newValue = object[prop];
for (var prop in oldObject) {
var newValue = object[prop];
if (newValue !== undefined && newValue === oldObject[prop])
continue;
if (newValue !== undefined && newValue === oldObject[prop])
continue;
if (!(prop in object)) {
removed[prop] = undefined;
continue;
}
if (!(prop in object)) {
removed[prop] = undefined;
continue;
}
if (newValue !== oldObject[prop])
changed[prop] = newValue;
}
if (newValue !== oldObject[prop])
changed[prop] = newValue;
}
for (var prop2 in object) {
if (prop2 in oldObject)
continue;
for (var prop2 in object) {
if (prop2 in oldObject)
continue;
added[prop2] = object[prop2];
}
added[prop2] = object[prop2];
}
return {
added: added,
removed: removed,
changed: changed
};
}
};
return {
added: added,
removed: removed,
changed: changed
};
}
};
}];

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc