angular-data
Advanced tools
Comparing version 0.5.0 to 0.6.0
@@ -5,3 +5,3 @@ { | ||
"description": "Data store for Angular.js.", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"homepage": "http://jmdobry.github.io/angular-data/", | ||
@@ -8,0 +8,0 @@ "repository": { |
@@ -0,1 +1,15 @@ | ||
##### 0.6.0 - 17 January 2014 | ||
Added pluggable filters for the "where" clause of a query. Angular-data's "query language" will remain small and simple. | ||
Developers can provide their own more robust filters for more powerful queries. | ||
###### Breaking API changes | ||
- #3 - Pluggable async adapters | ||
###### Backwards API changes | ||
- #2 - angular-data query language | ||
- #4 - Query caching | ||
- #17 - Where predicates should be able to handle OR, not just AND | ||
- #22 - Reorganize infrastructure to utilize angular's DI | ||
##### 0.5.0 - 16 January 2014 | ||
@@ -2,0 +16,0 @@ |
/** | ||
* @author Jason Dobry <jason.dobry@gmail.com> | ||
* @file angular-data.min.js | ||
* @version 0.5.0 - Homepage <http://jmdobry.github.io/angular-data/> | ||
* @version 0.6.0 - Homepage <http://jmdobry.github.io/angular-data/> | ||
* @copyright (c) 2014 Jason Dobry <https://github.com/jmdobry/angular-data> | ||
@@ -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}({"u+GZEJ":[function(a,b,c){!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 Object.deliverAllChangeRecords(),void 0;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)},{}],observejs:[function(a,b){b.exports=a("u+GZEJ")},{}],3:[function(a,b){function c(a,b){return-1!==d(a,b)}var d=a("./indexOf");b.exports=c},{"./indexOf":5}],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_":11}],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":4}],7:[function(a,b){function c(a,b,c){return d.call(a,b,c)}var d=Array.prototype.slice;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;)c(a[0],b[0])<=0?d.push(a.shift()):d.push(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 h,i=0;null==f&&c();for(h in a)if(e(b,a,h,d)===!1)break;if(f)for(;(h=g[i++])&&(a[h]===Object.prototype[h]||e(b,a,h,d)!==!1););}function e(a,b,c,d){return a.call(d,b[c],c,b)}var f,g;b.exports=d},{}],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(){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}],26:[function(a,b){function c(a){return a=d(a),a.toUpperCase()}var d=a("../lang/toString");b.exports=c},{"../lang/toString":19}],"clHM+W":[function(a,b){function c(a,b){var c=(new Date).getTime();k.$http(b).success(function(b,d,e,f){k.$log.debug(f.method+" request:"+f.url+" Time taken: "+((new Date).getTime()-c)+"ms",arguments),a.resolve(b)}).error(function(b){k.$log.error(arguments),a.reject(b)})}function d(a){var b=k.$q.defer();try{k.$rootScope.$$phase?c(b,a):k.$rootScope.$apply(function(){c(b,a)})}catch(d){b.reject(new j.UnhandledError(d))}return b.promise}function e(a,b){return b=b||{},d(i.deepMixIn(b,{url:a,method:"GET"}))}function f(a,b,c){return c=c||{},d(i.deepMixIn(c,{url:a,data:b,method:"PUT"}))}function g(a,b,c){return c=c||{},d(i.deepMixIn(c,{url:a,data:b,method:"POST"}))}function h(a,b){return b=b||{},d(i.deepMixIn(b,{url:a,method:"DELETE"}))}var i=a("utils"),j=a("errors"),k=a("services");b.exports={HTTP:d,GET:e,POST:g,PUT:f,DEL:h}},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],HttpAdapter:[function(a,b){b.exports=a("clHM+W")},{}],29:[function(a,b){function c(a,b){var c=f.$q.defer(),h=c.promise;if(f.store[a])if(d.isObject(b))try{var i=f.store[a],j=this;h=h.then(function(b){return f.$q.promisify(i.beforeValidate)(a,b)}).then(function(b){return f.$q.promisify(i.validate)(a,b)}).then(function(b){return f.$q.promisify(i.afterValidate)(a,b)}).then(function(b){return f.$q.promisify(i.beforeCreate)(a,b)}).then(function(a){return f.adapters[i.defaultAdapter].POST.apply(j,[d.makePath(i.baseUrl,i.endpoint),a,null])}).then(function(b){return f.$q.promisify(i.afterCreate)(a,b)}).then(function(a){return j.inject(i.name,a)}),c.resolve(b)}catch(k){c.reject(new e.UnhandledError(k))}else c.reject(new e.IllegalArgumentError(g+"attrs: Must be an object!",{attrs:{actual:typeof b,expected:"object"}}));else c.reject(new e.RuntimeError(g+a+" is not a registered resource!"));return h}var d=a("utils"),e=a("errors"),f=a("services"),g="DS.create(resourceName, attrs): ";b.exports=c},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],30:[function(a,b){function c(a,b){var c=f.$q.defer(),h=c.promise;if(f.store[a])if(d.isString(b)||d.isNumber(b)){var i=f.store[a],j=this;h=h.then(function(b){return f.$q.promisify(i.beforeDestroy)(a,b)}).then(function(){return f.adapters[i.defaultAdapter].DEL(d.makePath(i.baseUrl,i.endpoint,b),null)}).then(function(){return f.$q.promisify(i.afterDestroy)(a,i.index[b])}).then(function(){return j.eject(a,b),b}),c.resolve(i.index[b])}else c.reject(new e.IllegalArgumentError(g+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}}));else c.reject(new e.RuntimeError(g+a+" is not a registered resource!"));return h}var d=a("utils"),e=a("errors"),f=a("services"),g="DS.destroy(resourceName, id): ";b.exports=c},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],31:[function(a,b){function c(a,b,c){var h=f.$q.defer(),i=h.promise;if(c=c||{},f.store[a])if(d.isString(b)||d.isNumber(b))if(d.isObject(c))try{var j=f.store[a],k=this;if(c.bypassCache&&delete j.completedQueries[b],!(b in j.completedQueries))return b in j.pendingQueries||(i=j.pendingQueries[b]=f.adapters[j.defaultAdapter].GET(d.makePath(j.baseUrl,j.endpoint,b),null).then(function(c){return delete j.pendingQueries[b],j.completedQueries[b]=(new Date).getTime(),k.inject(a,c)})),j.pendingQueries[b];h.resolve(k.get(a,b))}catch(l){h.reject(l)}else h.reject(new e.IllegalArgumentError(g+"options: Must be an object!",{options:{actual:typeof c,expected:"object"}}));else h.reject(new e.IllegalArgumentError(g+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}}));else h.reject(new e.RuntimeError(g+a+" is not a registered resource!"));return i}var d=a("utils"),e=a("errors"),f=a("services"),g="DS.find(resourceName, id[, options]): ";b.exports=c},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],32:[function(a,b){function c(a,b,c){var d=h.store[b];a=a||[],delete d.pendingQueries[c],d.completedQueries[c]=(new Date).getTime();for(var e=0;e<a.length;e++)this.inject(b,a[e]);return d.index=f.toLookup(d.collection,d.idAttribute),d.collectionModified=f.updateTimestamp(d.collectionModified),a}function d(a,b,d){var e=h.store[a],i=this,j=f.toJson(b);return d.bypassCache&&delete e.completedQueries[j],j in e.completedQueries?this.filter(a,b,d):(j in e.pendingQueries||(e.pendingQueries[j]=h.adapters[e.defaultAdapter].GET(f.makePath(e.baseUrl,e.endpoint),{params:b}).then(function(b){try{return c.apply(i,[b,a,j])}catch(d){throw new g.UnhandledError(d)}})),e.pendingQueries[j])}function e(a,b,c){var e=h.$q.defer(),j=e.promise,k=this;if(c=c||{},h.store[a])if(f.isObject(b))if(f.isObject(c))try{j=j.then(function(){return d.apply(k,[a,b,c])}),e.resolve()}catch(l){e.reject(new g.UnhandledError(l))}else e.reject(new g.IllegalArgumentError(i+"options: Must be an object!",{options:{actual:typeof c,expected:"object"}}));else e.reject(new g.IllegalArgumentError(i+"params: Must be an object!",{params:{actual:typeof b,expected:"object"}}));else e.reject(new g.RuntimeError(i+a+" is not a registered resource!"));return j}var f=a("utils"),g=a("errors"),h=a("services"),i="DS.findAll(resourceName, params[, options]): ";b.exports=e},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],33:[function(a,b){b.exports={create:a("./create"),destroy:a("./destroy"),find:a("./find"),findAll:a("./findAll"),refresh:a("./refresh"),save:a("./save")}},{"./create":29,"./destroy":30,"./find":31,"./findAll":32,"./refresh":34,"./save":35}],34:[function(a,b){function c(a,b,c){if(c=c||{},f.store[a]){if(d.isString(b)||d.isNumber(b)){if(d.isObject(c))return c.bypassCache=!0,b in f.store[a].index?this.find(a,b,c):!1;throw new e.IllegalArgumentError(g+"options: Must be an object!",{options:{actual:typeof c,expected:"object"}})}throw new e.IllegalArgumentError(g+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}})}throw new e.RuntimeError(g+a+" is not a registered resource!")}var d=a("utils"),e=a("errors"),f=a("services"),g="DS.refresh(resourceName, id[, options]): ";b.exports=c},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],35:[function(a,b){function c(a,b,c){var h=f.$q.defer(),i=h.promise;if(c=c||{},f.store[a])if(d.isString(b)||d.isNumber(b))if(d.isObject(c))if(b in f.store[a].index){var j=f.store[a],k=this;i=i.then(function(b){return f.$q.promisify(j.beforeValidate)(a,b)}).then(function(b){return f.$q.promisify(j.validate)(a,b)}).then(function(b){return f.$q.promisify(j.afterValidate)(a,b)}).then(function(b){return f.$q.promisify(j.beforeUpdate)(a,b)}).then(function(a){return f.adapters[j.defaultAdapter].PUT(d.makePath(j.baseUrl,j.endpoint,b),a,null)}).then(function(b){return f.$q.promisify(j.afterUpdate)(a,b)}).then(function(a){var e=k.inject(j.name,a,c);return j.previous_attributes[b]=d.deepMixIn({},a),j.saved[b]=d.updateTimestamp(j.saved[b]),e}),h.resolve(j.index[b])}else h.reject(new e.RuntimeError(g+'id: "'+b+'" not found!'));else h.reject(new e.IllegalArgumentError(g+"options: Must be an object!",{options:{actual:typeof c,expected:"object"}}));else h.reject(new e.IllegalArgumentError(g+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}}));else h.reject(new e.RuntimeError(g+a+" is not a registered resource!"));return i}var d=a("utils"),e=a("errors"),f=a("services"),g="DS.save(resourceName, id[, options]): ";b.exports=c},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],36:[function(a,b){function c(a){if(a=a||{},!f.isObject(a))throw new g.IllegalArgumentError(j+"options: Must be an object!",{actual:typeof a,expected:"object"});if("baseUrl"in a&&!f.isString(a.baseUrl))throw new g.IllegalArgumentError(j+"options.baseUrl: Must be a string!",{baseUrl:{actual:typeof a.baseUrl,expected:"string"}});if("idAttribute"in a&&!f.isString(a.idAttribute))throw new g.IllegalArgumentError(j+"options.idAttribute: Must be a string!",{idAttribute:{actual:typeof a.idAttribute,expected:"string"}});if("mergeStrategy"in a&&!f.isString(a.mergeStrategy))throw new g.IllegalArgumentError(j+"options.mergeStrategy: Must be a string!",{mergeStrategy:{actual:typeof a.mergeStrategy,expected:"string"}});if("beforeValidate"in a&&!f.isFunction(a.beforeValidate))throw new g.IllegalArgumentError(j+"options.beforeValidate: Must be a function!",{beforeValidate:{actual:typeof a.beforeValidate,expected:"function"}});if("validate"in a&&!f.isFunction(a.validate))throw new g.IllegalArgumentError(j+"options.validate: Must be a function!",{validate:{actual:typeof a.validate,expected:"function"}});if("afterValidate"in a&&!f.isFunction(a.afterValidate))throw new g.IllegalArgumentError(j+"options.afterValidate: Must be a function!",{afterValidate:{actual:typeof a.afterValidate,expected:"function"}});if("beforeCreate"in a&&!f.isFunction(a.beforeCreate))throw new g.IllegalArgumentError(j+"options.beforeCreate: Must be a function!",{beforeCreate:{actual:typeof a.beforeCreate,expected:"function"}});if("afterCreate"in a&&!f.isFunction(a.afterCreate))throw new g.IllegalArgumentError(j+"options.afterCreate: Must be a function!",{afterCreate:{actual:typeof a.afterCreate,expected:"function"}});if("beforeUpdate"in a&&!f.isFunction(a.beforeUpdate))throw new g.IllegalArgumentError(j+"options.beforeUpdate: Must be a function!",{beforeUpdate:{actual:typeof a.beforeUpdate,expected:"function"}});if("afterUpdate"in a&&!f.isFunction(a.afterUpdate))throw new g.IllegalArgumentError(j+"options.afterUpdate: Must be a function!",{afterUpdate:{actual:typeof a.afterUpdate,expected:"function"}});if("beforeDestroy"in a&&!f.isFunction(a.beforeDestroy))throw new g.IllegalArgumentError(j+"options.beforeDestroy: Must be a function!",{beforeDestroy:{actual:typeof a.beforeDestroy,expected:"function"}});if("afterDestroy"in a&&!f.isFunction(a.afterDestroy))throw new g.IllegalArgumentError(j+"options.afterDestroy: Must be a function!",{afterDestroy:{actual:typeof a.afterDestroy,expected:"function"}});if("defaultAdapter"in a&&!f.isString(a.defaultAdapter))throw new g.IllegalArgumentError(j+"options.defaultAdapter: Must be a function!",{defaultAdapter:{actual:typeof a.defaultAdapter,expected:"string"}});h.config=new h.BaseConfig(a)}function d(a,b){if(!f.isString(a))throw new g.IllegalArgumentError(k+"name: Must be a string!",{actual:typeof a,expected:"string"});if(!f.isObject(b))throw new g.IllegalArgumentError(k+"adapter: Must be an object!",{actual:typeof b,expected:"object"});if(h.adapters[a])throw new g.RuntimeError(k+a+" is already registered!");h.adapters[a]=b}function e(){this.config=c,c({}),this.registerAdapter=d,this.$get=["$rootScope","$log","$http","$q",function(b,c,e,j){h.$rootScope=b,h.$log=c,h.$http=e,h.$q=j,h.store={},h.adapters={},d("HttpAdapter",i);var k={HttpAdapter:i,errors:g};f.deepMixIn(k,a("./sync_methods")),f.deepMixIn(k,a("./async_methods")),f.deepFreeze(k);var l=b.$new();return l.$watch(function(){return(new Date).getTime()/100|0},function(){k.digest()}),k}]}var f=a("utils"),g=a("errors"),h=a("services"),i=a("HttpAdapter"),j="DSProvider.config(options): ",k="DSProvider.registerAdapter(name, adapter): ";b.exports=e},{"./async_methods":33,"./sync_methods":46,HttpAdapter:"clHM+W",errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],"cX8q+p":[function(a,b){function c(a,b,c){c(null,b)}var d=b.exports={store:{},BaseConfig:function(a){"idAttribute"in a&&(this.idAttribute=a.idAttribute),"baseUrl"in a&&(this.baseUrl=a.baseUrl),"beforeValidate"in a&&(this.beforeValidate=a.beforeValidate),"validate"in a&&(this.validate=a.validate),"afterValidate"in a&&(this.afterValidate=a.afterValidate),"beforeCreate"in a&&(this.beforeCreate=a.beforeCreate),"afterCreate"in a&&(this.afterCreate=a.afterCreate),"beforeUpdate"in a&&(this.beforeUpdate=a.beforeUpdate),"afterUpdate"in a&&(this.afterUpdate=a.afterUpdate),"beforeDestroy"in a&&(this.beforeDestroy=a.beforeDestroy),"afterDestroy"in a&&(this.afterDestroy=a.afterDestroy),"defaultAdapter"in a&&(this.defaultAdapter=a.defaultAdapter)}};d.BaseConfig.prototype.idAttribute="id",d.BaseConfig.prototype.defaultAdapter="HttpAdapter",d.BaseConfig.prototype.baseUrl="",d.BaseConfig.prototype.endpoint="",d.BaseConfig.prototype.beforeValidate=c,d.BaseConfig.prototype.validate=c,d.BaseConfig.prototype.afterValidate=c,d.BaseConfig.prototype.beforeCreate=c,d.BaseConfig.prototype.afterCreate=c,d.BaseConfig.prototype.beforeUpdate=c,d.BaseConfig.prototype.afterUpdate=c,d.BaseConfig.prototype.beforeDestroy=c,d.BaseConfig.prototype.afterDestroy=c},{}],services:[function(a,b){b.exports=a("cX8q+p")},{}],39:[function(a,b){function c(a,b){if(!f.store[a])throw new e.RuntimeError(g+a+" is not a registered resource!");if(!d.isString(b)&&!d.isNumber(b))throw new e.IllegalArgumentError(g+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}});try{return angular.copy(f.store[a].changes[b])}catch(c){throw new e.UnhandledError(c)}}var d=a("utils"),e=a("errors"),f=a("services"),g="DS.changes(resourceName, id): ";b.exports=c},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],40:[function(a,b){function c(a){g.BaseConfig.apply(this,[a]),"name"in a&&(this.name=a.name),this.endpoint="endpoint"in a?a.endpoint:this.name,this.collection=[],this.completedQueries={},this.pendingQueries={},this.index={},this.modified={},this.changes={},this.previous_attributes={},this.saved={},this.observers={},this.collectionModified=0}function d(a){if(e.isString(a)&&(a={name:a}),!e.isObject(a))throw new f.IllegalArgumentError(h+"definition: Must be an object!",{definition:{actual:typeof a,expected:"object"}});if(!e.isString(a.name))throw new f.IllegalArgumentError(h+"definition.name: Must be a string!",{definition:{name:{actual:typeof a.name,expected:"string"}}});if(a.idAttribute&&!e.isString(a.idAttribute))throw new f.IllegalArgumentError(h+"definition.idAttribute: Must be a string!",{definition:{idAttribute:{actual:typeof a.idAttribute,expected:"string"}}});if(a.endpoint&&!e.isString(a.endpoint))throw new f.IllegalArgumentError(h+"definition.endpoint: Must be a string!",{definition:{endpoint:{actual:typeof a.endpoint,expected:"string"}}});if(g.store[a.name])throw new f.RuntimeError(h+a.name+" is already registered!");try{g.store[a.name]=new c(a)}catch(b){throw delete g.store[a.name],new f.UnhandledError(b)}}var e=a("utils"),f=a("errors"),g=a("services"),h="DS.defineResource(definition): ";c.prototype=g.config,b.exports=d},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],41:[function(a,b){function c(){try{e.$rootScope.$$phase?f.Platform.performMicrotaskCheckpoint():e.$rootScope.$apply(function(){f.Platform.performMicrotaskCheckpoint()})}catch(a){throw new d.UnhandledError(a)}}var d=(a("utils"),a("errors")),e=a("services"),f=a("observejs");b.exports=c},{errors:"hIh4e1",observejs:"u+GZEJ",services:"cX8q+p",utils:"uE/lJt"}],42:[function(a,b){function c(a,b){if(b){for(var c=!1,d=0;d<a.collection.length;d++)if(a.collection[d][a.idAttribute]==b){c=!0;break}c&&(a.collection.splice(d,1),a.observers[b].close(),delete a.observers[b],delete a.index[b],delete a.changes[b],delete a.previous_attributes[b],delete a.modified[b],delete a.saved[b])}else a.collection=[],a.index={},a.modified={},a.saved={},a.changes={},a.previous_attributes={};a.collectionModified=e.updateTimestamp(a.collectionModified)}function d(a,b){if(!g.store[a])throw new f.RuntimeError(h+a+" is not a registered resource!");if(b&&!e.isString(b)&&!e.isNumber(b))throw new f.IllegalArgumentError(h+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}});try{g.$rootScope.$$phase?c(g.store[a],b):g.$rootScope.$apply(function(){c(g.store[a],b)})}catch(d){throw new f.UnhandledError(d)}}var e=a("utils"),f=a("errors"),g=a("services"),h="DS.eject(resourceName, id): ";b.exports=d},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],43:[function(a,b){function c(a,b,c){if(c=c||{},!f.store[a])throw new e.RuntimeError(g+a+" is not a registered resource!");if(!d.isObject(b))throw new e.IllegalArgumentError(g+"params: Must be an object!",{params:{actual:typeof b,expected:"object"}});if(!d.isObject(c))throw new e.IllegalArgumentError(g+"options: Must be an object!",{options:{actual:typeof c,expected:"object"}});try{var h=f.store[a];b.query=b.query||{};var i=d.toJson(b);i in h.completedQueries||!c.loadFromServer||h.pendingQueries[i]||this.findAll(a,b,c);var j=d.filter(h.collection,function(a){var c=!0;if(b.query.where){if(!d.isObject(b.query.where))throw new e.IllegalArgumentError(g+"params.query.where: Must be an object!",{params:{query:{where:{actual:typeof b.query.where,expected:"object"}}}});d.forOwn(b.query.where,function(b,e){d.isString(b)&&(b={"===":b}),"=="in b?c=c&&a[e]==b["=="]:"==="in b?c=c&&a[e]===b["==="]:"!="in b?c=c&&a[e]!=b["!="]:">"in b?c=c&&a[e]>b[">"]:">="in b?c=c&&a[e]>=b[">="]:"<"in b?c=c&&a[e]<b["<"]:"<="in b?c=c&&a[e]<=b["<="]:"in"in b&&(c=c&&d.contains(b["in"],a[e]))})}return c});if(b.query.orderBy){if(d.isString(b.query.orderBy)&&(b.query.orderBy=[[b.query.orderBy,"ASC"]]),!d.isArray(b.query.orderBy))throw new e.IllegalArgumentError(g+"params.query.orderBy: Must be a string or an array!",{params:{query:{orderBy:{actual:typeof b.query.orderBy,expected:"string|array"}}}});for(var k=0;k<b.query.orderBy.length;k++){if(d.isString(b.query.orderBy[k]))b.query.orderBy[k]=[b.query.orderBy[k],"ASC"];else if(!d.isArray(b.query.orderBy[k]))throw new e.IllegalArgumentError(g+"params.query.orderBy["+k+"]: Must be a string or an array!",{params:{query:{"orderBy[i]":{actual:typeof b.query.orderBy[k],expected:"string|array"}}}});j=d.sort(j,function(a,c){var e=a[b.query.orderBy[k][0]],f=c[b.query.orderBy[k][0]];return d.isString(e)&&(e=d.upperCase(e)),d.isString(f)&&(f=d.upperCase(f)),"DESC"===b.query.orderBy[k][1]?e>f?-1:f>e?1:0:f>e?-1:e>f?1:0})}}return d.isNumber(b.query.limit)&&d.isNumber(b.query.skip)?j=d.slice(j,b.query.skip,b.query.skip+b.query.limit):d.isNumber(b.query.limit)?j=d.slice(j,0,b.query.limit):d.isNumber(b.query.skip)&&(j=d.slice(j,b.query.skip)),j}catch(l){throw l instanceof e.IllegalArgumentError?l:new e.UnhandledError(l)}}var d=a("utils"),e=a("errors"),f=a("services"),g="DS.filter(resourceName, params[, options]): ";b.exports=c},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],44:[function(a,b){function c(a,b,c){if(c=c||{},!f.store[a])throw new e.RuntimeError(g+a+" is not a registered resource!");if(!d.isString(b)&&!d.isNumber(b))throw new e.IllegalArgumentError(g+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}});if(!d.isObject(c))throw new e.IllegalArgumentError(g+"options: Must be an object!",{options:{actual:typeof c,expected:"object"}});try{return b in f.store[a].index||!c.loadFromServer||this.find(a,b).then(null,function(a){throw a}),f.store[a].index[b]}catch(h){throw new e.UnhandledError(h)}}var d=a("utils"),e=a("errors"),f=a("services"),g="DS.get(resourceName, id[, options]): ";b.exports=c},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],45:[function(a,b){function c(a){return!(e.isEmpty(a.added)&&e.isEmpty(a.removed)&&e.isEmpty(a.changed))}function d(a,b){if(!g.store[a])throw new f.RuntimeError(h+a+" is not a registered resource!");if(!e.isString(b)&&!e.isNumber(b))throw new f.IllegalArgumentError(h+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}});try{return b in g.store[a].changes?c(g.store[a].changes[b]):!1}catch(d){throw new f.UnhandledError(d)}}var e=a("utils"),f=a("errors"),g=a("services"),h="DS.hasChanges(resourceName, id): ";b.exports=d},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],46:[function(a,b){b.exports={defineResource:a("./defineResource"),eject:a("./eject"),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")}},{"./changes":39,"./defineResource":40,"./digest":41,"./eject":42,"./filter":43,"./get":44,"./hasChanges":45,"./inject":47,"./lastModified":48,"./lastSaved":49,"./previous":50}],47:[function(a,b){function c(a,b){function d(b,c,d,h){try{var i=h(a.idAttribute);a.changes[i]=e.diffObjectFromOldObject(a.index[i],a.previous_attributes[i]),a.modified[i]=e.updateTimestamp(a.modified[i]),a.collectionModified=e.updateTimestamp(a.collectionModified),a.idAttribute in d&&g.$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 \""+a.name+'" resource is now in an undefined (probably broken) state.')}catch(j){throw new f.UnhandledError(j)}}var j=this;if(e.isArray(b))for(var k=0;k<b.length;k++)c.call(j,a,b[k]);else{if(!(a.idAttribute in b))throw new f.RuntimeError(i+"attrs: Must contain the property specified by `idAttribute`!");var l=b[a.idAttribute];l in a.index?(e.deepMixIn(a.index[l],b),a.observers[l].deliver()):(a.index[l]={},a.previous_attributes[l]={},e.deepMixIn(a.index[l],b),e.deepMixIn(a.previous_attributes[l],b),a.collection.push(a.index[l]),a.observers[l]=new h.ObjectObserver(a.index[l],d),d({},{},{},function(){return l}))}}function d(a,b,d){if(d=d||{},!g.store[a])throw new f.RuntimeError(i+a+" is not a registered resource!");if(!e.isObject(b)&&!e.isArray(b))throw new f.IllegalArgumentError(i+"attrs: Must be an object or an array!",{attrs:{actual:typeof b,expected:"object|array"}});if(!e.isObject(d))throw new f.IllegalArgumentError(i+"options: Must be an object!",{options:{actual:typeof d,expected:"object"}});var h=(g.store[a],this);try{return g.$rootScope.$$phase?c.apply(h,[g.store[a],b]):g.$rootScope.$apply(function(){c.apply(h,[g.store[a],b])}),b}catch(j){throw j instanceof f.RuntimeError?j:new f.UnhandledError(j)}}var e=a("utils"),f=a("errors"),g=a("services"),h=a("observejs"),i="DS.inject(resourceName, attrs[, options]): ";b.exports=d},{errors:"hIh4e1",observejs:"u+GZEJ",services:"cX8q+p",utils:"uE/lJt"}],48:[function(a,b){function c(a,b){if(!f.store[a])throw new e.RuntimeError(g+a+" is not a registered resource!");if(b&&!d.isString(b)&&!d.isNumber(b))throw new e.IllegalArgumentError(g+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}});try{return b?(b in f.store[a].modified||(f.store[a].modified[b]=0),f.store[a].modified[b]):f.store[a].collectionModified}catch(c){throw new e.UnhandledError(c) | ||
}}var d=a("utils"),e=a("errors"),f=a("services"),g="DS.lastModified(resourceName[, id]): ";b.exports=c},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],49:[function(a,b){function c(a,b){if(!f.store[a])throw new e.RuntimeError(g+a+" is not a registered resource!");if(b&&!d.isString(b)&&!d.isNumber(b))throw new e.IllegalArgumentError(g+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}});try{return b?(b in f.store[a].saved||(f.store[a].saved[b]=0),f.store[a].saved[b]):f.store[a].collectionModified}catch(c){throw new e.UnhandledError(c)}}var d=a("utils"),e=a("errors"),f=a("services"),g="DS.lastSaved(resourceName[, id]): ";b.exports=c},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],50:[function(a,b){function c(a,b){if(!f.store[a])throw new e.RuntimeError(g+a+" is not a registered resource!");if(!d.isString(b)&&!d.isNumber(b))throw new e.IllegalArgumentError(g+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}});try{return angular.copy(f.store[a].previous_attributes[b])}catch(c){throw new e.UnhandledError(c)}}var d=a("utils"),e=a("errors"),f=a("services"),g="DS.previous(resourceName, id): ";b.exports=c},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],errors:[function(a,b){b.exports=a("hIh4e1")},{}],hIh4e1:[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||"Validation Error!"}function f(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,f.prototype=Object.create(Error.prototype),f.prototype.constructor=f,b.exports={UnhandledError:c,IllegalArgumentError:d,ValidationError:e,RuntimeError:f}},{}],53:[function(a){!function(b,c){"use strict";c.module("jmdobry.angular-data",["ng"]).config(["$provide",function(a){a.decorator("$q",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})}]),c.module("jmdobry.angular-data").provider("DS",a("./datastore"))}(window,window.angular)},{"./datastore":36}],"uE/lJt":[function(a,b){b.exports={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"),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 c(a){if("function"==typeof Object.freeze){var b,d;Object.freeze(a);for(d in a)b=a[d],a.hasOwnProperty(d)&&"object"==typeof b&&!Object.isFrozen(b)&&c(b)}},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":7,"mout/array/sort":8,"mout/array/toLookup":9,"mout/lang/isEmpty":14,"mout/object/deepMixIn":21,"mout/object/forOwn":23,"mout/string/makePath":25,"mout/string/upperCase":26}],utils:[function(a,b){b.exports=a("uE/lJt")},{}]},{},[53]); | ||
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}({"u+GZEJ":[function(a,b,c){!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 Object.deliverAllChangeRecords(),void 0;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)},{}],observejs:[function(a,b){b.exports=a("u+GZEJ")},{}],3:[function(a,b){function c(a,b){return-1!==d(a,b)}var d=a("./indexOf");b.exports=c},{"./indexOf":5}],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_":11}],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":4}],7:[function(a,b){function c(a,b,c){return d.call(a,b,c)}var d=Array.prototype.slice;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;)c(a[0],b[0])<=0?d.push(a.shift()):d.push(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 h,i=0;null==f&&c();for(h in a)if(e(b,a,h,d)===!1)break;if(f)for(;(h=g[i++])&&(a[h]===Object.prototype[h]||e(b,a,h,d)!==!1););}function e(a,b,c,d){return a.call(d,b[c],c,b)}var f,g;b.exports=d},{}],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(){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}],26:[function(a,b){function c(a){return a=d(a),a.toUpperCase()}var d=a("../lang/toString");b.exports=c},{"../lang/toString":19}],27:[function(a,b){function c(){this.$get=["$http","$log","DSUtils",function(a,b,c){function d(c){var d=(new Date).getTime();return a(c).then(function(a){return b.debug(a.config.method+" request:"+a.config.url+" Time taken: "+((new Date).getTime()-d)+"ms",arguments),n.deserialize(a)})}function e(a,b){return b=b||{},d(c.deepMixIn(b,{url:a,method:"GET"}))}function f(a,b,e){return e=e||{},d(c.deepMixIn(e,{url:a,data:b,method:"POST"}))}function g(a,b,e){return e=e||{},d(c.deepMixIn(e,{url:a,data:b,method:"PUT"}))}function h(a,b){return b=b||{},this.HTTP(c.deepMixIn(b,{url:a,method:"DELETE"}))}function i(a,b,d){return this.GET(c.makePath(a.baseUrl,a.endpoint,b),d)}function j(a,b,d){return d=d||{},d.params=d.params||{},d.params.query&&(d.params.query=n.queryTransform(d.params.query)),c.deepMixIn(d,b),this.GET(c.makePath(a.baseUrl,a.endpoint),d)}function k(a,b,d){return this.POST(c.makePath(a.baseUrl,a.endpoint),n.serialize(b),d)}function l(a,b,d){return this.PUT(c.makePath(a.baseUrl,a.endpoint,b[a.idAttribute]),n.serialize(b),d)}function m(a,b,d){return this.DEL(c.makePath(a.baseUrl,a.endpoint,b),d)}var n=this.defaults={serialize:function(a){return a},deserialize:function(a){return a.data},queryTransform:function(a){return a}};return{defaults:n,HTTP:d,GET:e,POST:f,PUT:g,DEL:h,find:i,findAll:j,create:k,createMany:function(){throw new Error("Not yet implemented!")},update:l,updateMany:function(){throw new Error("Not yet implemented!")},destroy:m,destroyMany:function(){throw new Error("Not yet implemented!")}}}]}b.exports=c},{}],28:[function(a,b){function c(a,b,c){for(var d=a[c],e=b(d);c>0;){var f=Math.floor((c+1)/2)-1,g=a[f];if(e>=b(g))break;a[f]=d,a[c]=g,c=f}}function d(a,b,c){for(var d=a.length,e=a[c],f=b(e);;){var g=2*(c+1),h=g-1,i=null;if(d>h){var j=a[h],k=b(j);f>k&&(i=h)}if(d>g){var l=a[g],m=b(l);m<(null===i?f:b(a[h]))&&(i=g)}if(null===i)break;a[c]=a[i],a[i]=e,c=i}}function e(a){if(a&&"function"!=typeof a)throw new Error("BinaryHeap(weightFunc): weightFunc: must be a function!");a=defaults.userProvidedDefaultWeightFunc||defaults.defaultWeightFunc,this.weightFunc=a,this.heap=[]}function f(){function a(a){if(!angular.isFunction(a))throw new Error("BinaryHeapProvider.setDefaultWeightFunction(weightFunc): weightFunc: Must be a function!");b.userProvidedDefaultWeightFunc=a}var b={defaultWeightFunc:function(a){return a},userProvidedDefaultWeightFunc:null};this.setDefaultWeightFunction=a,this.$get=function(){return e}}e.prototype.push=function(a){this.heap.push(a),c(this.heap,this.weightFunc,this.heap.length-1)},e.prototype.peek=function(){return this.heap[0]},e.prototype.pop=function(){var a=this.heap[0],b=this.heap.pop();return this.heap.length>0&&(this.heap[0]=b,d(this.heap,this.weightFunc,0)),a},e.prototype.remove=function(a){for(var b=this.heap.length,e=0;b>e;e++)if(angular.equals(this.heap[e],a)){var f=this.heap[e],g=this.heap.pop();return e!==b-1&&(this.heap[e]=g,c(this.heap,this.weightFunc,e),d(this.heap,this.weightFunc,e)),f}return null},e.prototype.removeAll=function(){this.heap=[]},e.prototype.size=function(){return this.heap.length},b.exports=f},{}],29:[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;f=f.then(function(b){return h.$q.promisify(g.beforeValidate)(a,b)}).then(function(b){return h.$q.promisify(g.validate)(a,b)}).then(function(b){return h.$q.promisify(g.afterValidate)(a,b)}).then(function(b){return h.$q.promisify(g.beforeCreate)(a,b)}).then(function(a){return h.adapters[c.adapter||g.defaultAdapter].create(g,a,c)}).then(function(b){return h.$q.promisify(g.afterCreate)(a,b)}).then(function(a){return h.inject(g.name,a)}),e.resolve(b)}catch(i){e.reject(new this.errors.UnhandledError(i))}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): ";b.exports=c},{}],30:[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.definitions[a],h=this.store[a],i=this;b in h.index?(f=f.then(function(b){return i.$q.promisify(g.beforeDestroy)(a,b)}).then(function(){return i.adapters[c.adapter||g.defaultAdapter].destroy(g,b,c)}).then(function(){return i.$q.promisify(g.afterDestroy)(a,h.index[b])}).then(function(){return i.eject(a,b),b}),e.resolve(h.index[b])):e.resolve()}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},{}],31:[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))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(c){return delete h.pendingQueries[b],h.completedQueries[b]=(new Date).getTime(),i.inject(a,c)})),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},{}],32:[function(a,b){function c(a,b,c,d){var e=this.store[c];b=b||[],delete e.pendingQueries[d],e.completedQueries[d]=(new Date).getTime();for(var f=0;f<b.length;f++)this.inject(c,b[f]);return e.index=a.toLookup(e.collection,this.definitions[c].idAttribute),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,{params:d},e).then(function(d){try{return c.apply(h,[a,d,b,i])}catch(e){throw new h.errors.UnhandledError(e)}})),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))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!",{options:{actual:typeof c,expected:"object"}}));else e.reject(new this.errors.IllegalArgumentError(f+"params: Must be an object!",{params:{actual:typeof b,expected:"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},{}],33:[function(a,b){b.exports={create:a("./create"),destroy:a("./destroy"),find:a("./find"),findAll:a("./findAll"),refresh:a("./refresh"),save:a("./save")}},{"./create":29,"./destroy":30,"./find":31,"./findAll":32,"./refresh":34,"./save":35}],34:[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,b in this.store[a].index?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},{}],35:[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))if(b in this.store[a].index){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.beforeUpdate)(a,b)}).then(function(a){return i.adapters[c.adapter||g.defaultAdapter].update(g,a,c)}).then(function(b){return i.$q.promisify(g.afterUpdate)(a,b)}).then(function(a){var d=i.inject(g.name,a,c);return h.previousAttributes[b]=i.utils.deepMixIn({},a),h.saved[b]=i.utils.updateTimestamp(h.saved[b]),d}),e.resolve(h.index[b])}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},{}],36:[function(a,b){function c(a,b,c){c(null,b)}function d(){}function e(){var b=this.defaults=new d,c=this.adapters={};this.$get=["$rootScope","$log","$q","DSHttpAdapter","DSUtils","DSErrors",function(d,e,f,g,h,i){var j=a("./sync_methods"),k=a("./async_methods");c.DSHttpAdapter=g;var l={$rootScope:d,$log:e,$q:f,defaults:b,store:{},definitions:{},adapters:c,errors:i,utils:h};h.deepFreeze(j),h.deepFreeze(k),h.deepMixIn(l,j),h.deepMixIn(l,k),h.deepFreeze(l.errors),h.deepFreeze(l.utils);var m=d.$new();return m.$watch(function(){return(new Date).getTime()/100|0},function(){l.digest()}),l}]}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}),"=="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,b.exports=e},{"../utils":"uE/lJt","./async_methods":33,"./sync_methods":44}],37:[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].changes[b])}catch(c){throw new this.errors.UnhandledError(c)}}var d="DS.changes(resourceName, id): ";b.exports=c},{}],38:[function(a,b){function c(a,b){a.deepMixIn(this,b),this.endpoint="endpoint"in b?b.endpoint:this.name}function d(a){if(this.utils.isString(a)&&(a={name:a}),!this.utils.isObject(a))throw new this.errors.IllegalArgumentError(e+"definition: Must be an object!",{definition:{actual:typeof a,expected:"object"}});if(!this.utils.isString(a.name))throw new this.errors.IllegalArgumentError(e+"definition.name: Must be a string!",{definition:{name:{actual:typeof a.name,expected:"string"}}});if(a.idAttribute&&!this.utils.isString(a.idAttribute))throw new this.errors.IllegalArgumentError(e+"definition.idAttribute: Must be a string!",{definition:{idAttribute:{actual:typeof a.idAttribute,expected:"string"}}});if(a.endpoint&&!this.utils.isString(a.endpoint))throw new this.errors.IllegalArgumentError(e+"definition.endpoint: Must be a string!",{definition:{endpoint:{actual:typeof a.endpoint,expected:"string"}}});if(this.store[a.name])throw new this.errors.RuntimeError(e+a.name+" is already registered!");try{c.prototype=this.defaults,this.definitions[a.name]=new c(this.utils,a),this.store[a.name]={collection:[],completedQueries:{},pendingQueries:{},index:{},changes:{},modified:{},saved:{},previousAttributes:{},observers:{},collectionModified:0}}catch(b){throw delete this.definitions[a.name],delete this.store[a.name],new this.errors.UnhandledError(b)}}var e="DS.defineResource(definition): ";b.exports=d},{}],39:[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:"u+GZEJ"}],40:[function(a,b){function c(a,b,c){if(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],delete b.index[c],delete b.changes[c],delete b.previousAttributes[c],delete b.modified[c],delete b.saved[c])}else b.collection=[],b.index={},b.modified={},b.saved={},b.changes={},b.previousAttributes={}}function d(a,b){if(!this.definitions[a])throw new this.errors.RuntimeError(e+a+" is not a registered resource!");if(b&&!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)})}catch(g){throw new this.errors.UnhandledError(g)}}var e="DS.eject(resourceName, id): ";b.exports=d},{}],41:[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,b.query.skip+b.query.limit):this.utils.isNumber(b.query.limit)?i=this.utils.slice(i,0,b.query.limit):this.utils.isNumber(b.query.skip)&&(i=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},{}],42:[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{return b in this.store[a].index||!c.loadFromServer||this.find(a,b).then(null,function(a){throw a}),this.store[a].index[b]}catch(e){throw new this.errors.UnhandledError(e)}}var d="DS.get(resourceName, id[, options]): ";b.exports=c},{}],43:[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 b in this.store[a].changes?c(this.utils,this.store[a].changes[b]):!1}catch(d){throw new this.errors.UnhandledError(d)}}var e="DS.hasChanges(resourceName, id): ";b.exports=d},{}],44:[function(a,b){b.exports={defineResource:a("./defineResource"),eject:a("./eject"),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")}},{"./changes":37,"./defineResource":38,"./digest":39,"./eject":40,"./filter":41,"./get":42,"./hasChanges":43,"./inject":45,"./lastModified":46,"./lastSaved":47,"./previous":48}],45:[function(a,b){function c(a,b,d){function g(c,d,e,f){try{var g=f(a.idAttribute);b.changes[g]=h.utils.diffObjectFromOldObject(b.index[g],b.previousAttributes[g]),b.modified[g]=h.utils.updateTimestamp(b.modified[g]),b.collectionModified=h.utils.updateTimestamp(b.collectionModified),a.idAttribute in e&&$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 \""+a.name+'" resource is now in an undefined (probably broken) state.')}catch(i){throw new h.errors.UnhandledError(i)}}var h=this;if(h.utils.isArray(d))for(var i=0;i<d.length;i++)c.call(h,a,b,d[i]);else{if(!(a.idAttribute in d))throw new h.errors.RuntimeError(f+"attrs: Must contain the property specified by `idAttribute`!");var j=d[a.idAttribute];j in b.index?(h.utils.deepMixIn(b.index[j],d),b.observers[j].deliver()):(b.index[j]={},b.previousAttributes[j]={},h.utils.deepMixIn(b.index[j],d),h.utils.deepMixIn(b.previousAttributes[j],d),b.collection.push(b.index[j]),b.observers[j]=new e.ObjectObserver(b.index[j],g),g({},{},{},function(){return j}))}}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])}),b}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:"u+GZEJ"}],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(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},{}],47:[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].saved||(this.store[a].saved[b]=0),this.store[a].saved[b]):this.store[a].collectionModified}catch(c){throw new this.errors.UnhandledError(c)}}var d="DS.lastSaved(resourceName[, id]): ";b.exports=c},{}],48:[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("hIh4e1")},{}],hIh4e1:[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}}]},{}],51:[function(a){!function(b,c){"use strict";c.module("angular-data.BinaryHeap",[]).provider("BinaryHeap",a("./binaryHeap")),c.module("angular-data.DS",["ng","angular-data.BinaryHeap"]).service("DSUtils",a("./utils")).service("DSErrors",a("./errors")).provider("DSHttpAdapter",a("./adapters/http")).provider("DS",a("./datastore")).config(["$provide",function(a){a.decorator("$q",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":27,"./binaryHeap":28,"./datastore":36,"./errors":"hIh4e1","./utils":"uE/lJt"}],"uE/lJt":[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"),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":7,"mout/array/sort":8,"mout/array/toLookup":9,"mout/lang/isEmpty":14,"mout/object/deepMixIn":21,"mout/object/forOwn":23,"mout/string/makePath":25,"mout/string/upperCase":26}],utils:[function(a,b){b.exports=a("uE/lJt")},{}]},{},[51]); |
@@ -77,4 +77,2 @@ /* | ||
'lib/observe-js.js:observejs', | ||
'src/datastore/adapters/http/index.js:HttpAdapter', | ||
'src/datastore/services/index.js:services', | ||
'src/errors/index.js:errors', | ||
@@ -81,0 +79,0 @@ 'src/utils/index.js:utils' |
@@ -30,3 +30,3 @@ // Setup global test variables | ||
angular.module('app', ['ng', 'jmdobry.angular-data']); | ||
angular.module('app', ['ng', 'angular-data.DS']); | ||
@@ -73,14 +73,12 @@ // Setup before each test | ||
DSProvider = _DSProvider_; | ||
DSProvider.config({ | ||
baseUrl: 'http://test.angular-cache.com', | ||
beforeValidate: lifecycle.beforeValidate, | ||
validate: lifecycle.validate, | ||
afterValidate: lifecycle.afterValidate, | ||
beforeCreate: lifecycle.beforeCreate, | ||
afterCreate: lifecycle.afterCreate, | ||
beforeUpdate: lifecycle.beforeUpdate, | ||
afterUpdate: lifecycle.afterUpdate, | ||
beforeDestroy: lifecycle.beforeDestroy, | ||
afterDestroy: lifecycle.afterDestroy | ||
}); | ||
DSProvider.defaults.baseUrl = 'http://test.angular-cache.com'; | ||
DSProvider.defaults.beforeValidate = lifecycle.beforeValidate; | ||
DSProvider.defaults.validate = lifecycle.validate; | ||
DSProvider.defaults.afterValidate = lifecycle.afterValidate; | ||
DSProvider.defaults.beforeCreate = lifecycle.beforeCreate; | ||
DSProvider.defaults.afterCreate = lifecycle.afterCreate; | ||
DSProvider.defaults.beforeUpdate = lifecycle.beforeUpdate; | ||
DSProvider.defaults.afterUpdate = lifecycle.afterUpdate; | ||
DSProvider.defaults.beforeDestroy = lifecycle.beforeDestroy; | ||
DSProvider.defaults.afterDestroy = lifecycle.afterDestroy; | ||
}); | ||
@@ -87,0 +85,0 @@ inject(function (_$rootScope_, _$q_, _$httpBackend_, _DS_, _$log_) { |
{ | ||
"name": "angular-data", | ||
"description": "Data store for Angular.js.", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"homepage": "http://github.com/jmdobry/angular-data", | ||
@@ -6,0 +6,0 @@ "repository": { |
@@ -5,3 +5,3 @@ ## angular-data | ||
__Current version:__ 0.5.0 | ||
__Current version:__ 0.6.0 | ||
@@ -8,0 +8,0 @@ Angular-data is in a pre-1.0.0 development stage; the API is fluctuating, not a lot of tests yet, etc. |
@@ -1,3 +0,1 @@ | ||
var defaults = require('./defaults'); | ||
/*! | ||
@@ -196,7 +194,41 @@ * @doc method | ||
* @doc interface | ||
* @id BinaryHeap | ||
* @name BinaryHeap | ||
* @description | ||
* Binary heap implementation of a priority queue. | ||
* @id BinaryHeapProvider | ||
* @name BinaryHeapProvider | ||
*/ | ||
module.exports = BinaryHeap; | ||
function BinaryHeapProvider() { | ||
var defaults = { | ||
defaultWeightFunc: function (x) { | ||
return x; | ||
}, | ||
userProvidedDefaultWeightFunc: null | ||
}; | ||
/** | ||
* @doc method | ||
* @id BinaryHeapProvider.methods:setDefaultWeightFunction | ||
* @name setDefaultWeightFunction | ||
* @param {function} weightFunc New default weight function. | ||
*/ | ||
function setDefaultWeightFunction(weightFunc) { | ||
if (!angular.isFunction(weightFunc)) { | ||
throw new Error('BinaryHeapProvider.setDefaultWeightFunction(weightFunc): weightFunc: Must be a function!'); | ||
} | ||
defaults.userProvidedDefaultWeightFunc = weightFunc; | ||
} | ||
/** | ||
* @doc method | ||
* @id BinaryHeapProvider.methods:setDefaultWeightFunction | ||
* @name setDefaultWeightFunction | ||
* @methodOf BinaryHeapProvider | ||
* @param {function} weightFunc New default weight function. | ||
*/ | ||
this.setDefaultWeightFunction = setDefaultWeightFunction; | ||
this.$get = function () { | ||
return BinaryHeap; | ||
}; | ||
} | ||
module.exports = BinaryHeapProvider; |
@@ -1,5 +0,2 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.create(resourceName, attrs): '; | ||
var errorPrefix = 'DS.create(resourceName, attrs): '; | ||
@@ -35,2 +32,3 @@ /** | ||
* the primary key specified by `id`. | ||
* @param {object=} options Configuration options. | ||
* @returns {Promise} Promise produced by the `$q` service. | ||
@@ -48,13 +46,15 @@ * | ||
*/ | ||
function create(resourceName, attrs) { | ||
var deferred = services.$q.defer(), | ||
function create(resourceName, attrs, options) { | ||
var deferred = this.$q.defer(), | ||
promise = deferred.promise; | ||
if (!services.store[resourceName]) { | ||
deferred.reject(new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!')); | ||
} else if (!utils.isObject(attrs)) { | ||
deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'attrs: Must be an object!', { attrs: { actual: typeof attrs, expected: 'object' } })); | ||
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 resource = services.store[resourceName], | ||
var definition = this.definitions[resourceName], | ||
_this = this; | ||
@@ -64,21 +64,21 @@ | ||
.then(function (attrs) { | ||
return services.$q.promisify(resource.beforeValidate)(resourceName, attrs); | ||
return _this.$q.promisify(definition.beforeValidate)(resourceName, attrs); | ||
}) | ||
.then(function (attrs) { | ||
return services.$q.promisify(resource.validate)(resourceName, attrs); | ||
return _this.$q.promisify(definition.validate)(resourceName, attrs); | ||
}) | ||
.then(function (attrs) { | ||
return services.$q.promisify(resource.afterValidate)(resourceName, attrs); | ||
return _this.$q.promisify(definition.afterValidate)(resourceName, attrs); | ||
}) | ||
.then(function (attrs) { | ||
return services.$q.promisify(resource.beforeCreate)(resourceName, attrs); | ||
return _this.$q.promisify(definition.beforeCreate)(resourceName, attrs); | ||
}) | ||
.then(function (attrs) { | ||
return services.adapters[resource.defaultAdapter].POST.apply(_this, [utils.makePath(resource.baseUrl, resource.endpoint), attrs, null]); | ||
return _this.adapters[options.adapter || definition.defaultAdapter].create(definition, attrs, options); | ||
}) | ||
.then(function (data) { | ||
return services.$q.promisify(resource.afterCreate)(resourceName, data); | ||
return _this.$q.promisify(definition.afterCreate)(resourceName, data); | ||
}) | ||
.then(function (data) { | ||
return _this.inject(resource.name, data); | ||
return _this.inject(definition.name, data); | ||
}); | ||
@@ -88,3 +88,3 @@ | ||
} catch (err) { | ||
deferred.reject(new errors.UnhandledError(err)); | ||
deferred.reject(new this.errors.UnhandledError(err)); | ||
} | ||
@@ -91,0 +91,0 @@ } |
@@ -1,5 +0,2 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.destroy(resourceName, id): '; | ||
var errorPrefix = 'DS.destroy(resourceName, id): '; | ||
@@ -35,2 +32,3 @@ /** | ||
* @param {string|number} id The primary key of the item to remove. | ||
* @param {object=} options Configuration options. | ||
* @returns {Promise} Promise produced by the `$q` service. | ||
@@ -48,30 +46,36 @@ * | ||
*/ | ||
function destroy(resourceName, id) { | ||
var deferred = services.$q.defer(), | ||
function destroy(resourceName, id, options) { | ||
var deferred = this.$q.defer(), | ||
promise = deferred.promise; | ||
if (!services.store[resourceName]) { | ||
deferred.reject(new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!')); | ||
} else if (!utils.isString(id) && !utils.isNumber(id)) { | ||
deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } })); | ||
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 resource = services.store[resourceName], | ||
var definition = this.definitions[resourceName], | ||
resource = this.store[resourceName], | ||
_this = this; | ||
promise = promise | ||
.then(function (attrs) { | ||
return services.$q.promisify(resource.beforeDestroy)(resourceName, attrs); | ||
}) | ||
.then(function () { | ||
return services.adapters[resource.defaultAdapter].DEL(utils.makePath(resource.baseUrl, resource.endpoint, id), null); | ||
}) | ||
.then(function () { | ||
return services.$q.promisify(resource.afterDestroy)(resourceName, resource.index[id]); | ||
}) | ||
.then(function () { | ||
_this.eject(resourceName, id); | ||
return id; | ||
}); | ||
deferred.resolve(resource.index[id]); | ||
if (id in resource.index) { | ||
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, resource.index[id]); | ||
}) | ||
.then(function () { | ||
_this.eject(resourceName, id); | ||
return id; | ||
}); | ||
deferred.resolve(resource.index[id]); | ||
} else { | ||
deferred.resolve(); | ||
} | ||
} | ||
@@ -78,0 +82,0 @@ |
@@ -1,5 +0,2 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.find(resourceName, id[, options]): '; | ||
var errorPrefix = 'DS.find(resourceName, id[, options]): '; | ||
@@ -51,3 +48,3 @@ /** | ||
function find(resourceName, id, options) { | ||
var deferred = services.$q.defer(), | ||
var deferred = this.$q.defer(), | ||
promise = deferred.promise; | ||
@@ -57,11 +54,12 @@ | ||
if (!services.store[resourceName]) { | ||
deferred.reject(new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!')); | ||
} else if (!utils.isString(id) && !utils.isNumber(id)) { | ||
deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } })); | ||
} else if (!utils.isObject(options)) { | ||
deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } })); | ||
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 { | ||
try { | ||
var resource = services.store[resourceName], | ||
var definition = this.definitions[resourceName], | ||
resource = this.store[resourceName], | ||
_this = this; | ||
@@ -75,3 +73,3 @@ | ||
if (!(id in resource.pendingQueries)) { | ||
promise = resource.pendingQueries[id] = services.adapters[resource.defaultAdapter].GET(utils.makePath(resource.baseUrl, resource.endpoint, id), null) | ||
promise = resource.pendingQueries[id] = _this.adapters[options.adapter || definition.defaultAdapter].find(definition, id, options) | ||
.then(function (data) { | ||
@@ -78,0 +76,0 @@ // Query is no longer pending |
@@ -1,8 +0,5 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.findAll(resourceName, params[, options]): '; | ||
var errorPrefix = 'DS.findAll(resourceName, params[, options]): '; | ||
function processResults(data, resourceName, queryHash) { | ||
var resource = services.store[resourceName]; | ||
function processResults(utils, data, resourceName, queryHash) { | ||
var resource = this.store[resourceName]; | ||
@@ -21,3 +18,3 @@ data = data || []; | ||
// Update the data store's index for this resource | ||
resource.index = utils.toLookup(resource.collection, resource.idAttribute); | ||
resource.index = utils.toLookup(resource.collection, this.definitions[resourceName].idAttribute); | ||
@@ -29,4 +26,5 @@ // Update modified timestamp of collection | ||
function _findAll(resourceName, params, options) { | ||
var resource = services.store[resourceName], | ||
function _findAll(utils, resourceName, params, options) { | ||
var definition = this.definitions[resourceName], | ||
resource = this.store[resourceName], | ||
_this = this, | ||
@@ -45,8 +43,8 @@ queryHash = utils.toJson(params); | ||
// This particular query has never even been made | ||
resource.pendingQueries[queryHash] = services.adapters[resource.defaultAdapter].GET(utils.makePath(resource.baseUrl, resource.endpoint), { params: params }) | ||
resource.pendingQueries[queryHash] = _this.adapters[options.adapter || definition.defaultAdapter].findAll(definition, { params: params }, options) | ||
.then(function (data) { | ||
try { | ||
return processResults.apply(_this, [data, resourceName, queryHash]); | ||
return processResults.apply(_this, [utils, data, resourceName, queryHash]); | ||
} catch (err) { | ||
throw new errors.UnhandledError(err); | ||
throw new _this.errors.UnhandledError(err); | ||
} | ||
@@ -130,3 +128,3 @@ }); | ||
function findAll(resourceName, params, options) { | ||
var deferred = services.$q.defer(), | ||
var deferred = this.$q.defer(), | ||
promise = deferred.promise, | ||
@@ -137,16 +135,16 @@ _this = this; | ||
if (!services.store[resourceName]) { | ||
deferred.reject(new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!')); | ||
} else if (!utils.isObject(params)) { | ||
deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'params: Must be an object!', { params: { actual: typeof params, expected: 'object' } })); | ||
} else if (!utils.isObject(options)) { | ||
deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } })); | ||
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!', { params: { actual: typeof params, expected: 'object' } })); | ||
} 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 { | ||
try { | ||
promise = promise.then(function () { | ||
return _findAll.apply(_this, [resourceName, params, options]); | ||
return _findAll.apply(_this, [_this.utils, resourceName, params, options]); | ||
}); | ||
deferred.resolve(); | ||
} catch (err) { | ||
deferred.reject(new errors.UnhandledError(err)); | ||
deferred.reject(new this.errors.UnhandledError(err)); | ||
} | ||
@@ -153,0 +151,0 @@ } |
@@ -1,5 +0,2 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.refresh(resourceName, id[, options]): '; | ||
var errorPrefix = 'DS.refresh(resourceName, id[, options]): '; | ||
@@ -60,12 +57,12 @@ /** | ||
if (!services.store[resourceName]) { | ||
throw new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'); | ||
} else if (!utils.isString(id) && !utils.isNumber(id)) { | ||
throw new errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } }); | ||
} else if (!utils.isObject(options)) { | ||
throw new errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } }); | ||
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; | ||
if (id in services.store[resourceName].index) { | ||
if (id in this.store[resourceName].index) { | ||
return this.find(resourceName, id, options); | ||
@@ -72,0 +69,0 @@ } else { |
@@ -1,5 +0,2 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.save(resourceName, id[, options]): '; | ||
var errorPrefix = 'DS.save(resourceName, id[, options]): '; | ||
@@ -50,3 +47,3 @@ /** | ||
function save(resourceName, id, options) { | ||
var deferred = services.$q.defer(), | ||
var deferred = this.$q.defer(), | ||
promise = deferred.promise; | ||
@@ -56,12 +53,13 @@ | ||
if (!services.store[resourceName]) { | ||
deferred.reject(new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!')); | ||
} else if (!utils.isString(id) && !utils.isNumber(id)) { | ||
deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } })); | ||
} else if (!utils.isObject(options)) { | ||
deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } })); | ||
} else if (!(id in services.store[resourceName].index)) { | ||
deferred.reject(new errors.RuntimeError(errorPrefix + 'id: "' + id + '" not found!')); | ||
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 (!(id in this.store[resourceName].index)) { | ||
deferred.reject(new this.errors.RuntimeError(errorPrefix + 'id: "' + id + '" not found!')); | ||
} else { | ||
var resource = services.store[resourceName], | ||
var definition = this.definitions[resourceName], | ||
resource = this.store[resourceName], | ||
_this = this; | ||
@@ -71,23 +69,23 @@ | ||
.then(function (attrs) { | ||
return services.$q.promisify(resource.beforeValidate)(resourceName, attrs); | ||
return _this.$q.promisify(definition.beforeValidate)(resourceName, attrs); | ||
}) | ||
.then(function (attrs) { | ||
return services.$q.promisify(resource.validate)(resourceName, attrs); | ||
return _this.$q.promisify(definition.validate)(resourceName, attrs); | ||
}) | ||
.then(function (attrs) { | ||
return services.$q.promisify(resource.afterValidate)(resourceName, attrs); | ||
return _this.$q.promisify(definition.afterValidate)(resourceName, attrs); | ||
}) | ||
.then(function (attrs) { | ||
return services.$q.promisify(resource.beforeUpdate)(resourceName, attrs); | ||
return _this.$q.promisify(definition.beforeUpdate)(resourceName, attrs); | ||
}) | ||
.then(function (attrs) { | ||
return services.adapters[resource.defaultAdapter].PUT(utils.makePath(resource.baseUrl, resource.endpoint, id), attrs, null); | ||
return _this.adapters[options.adapter || definition.defaultAdapter].update(definition, attrs, options); | ||
}) | ||
.then(function (data) { | ||
return services.$q.promisify(resource.afterUpdate)(resourceName, data); | ||
return _this.$q.promisify(definition.afterUpdate)(resourceName, data); | ||
}) | ||
.then(function (data) { | ||
var saved = _this.inject(resource.name, data, options); | ||
resource.previous_attributes[id] = utils.deepMixIn({}, data); | ||
resource.saved[id] = utils.updateTimestamp(resource.saved[id]); | ||
var saved = _this.inject(definition.name, data, options); | ||
resource.previousAttributes[id] = _this.utils.deepMixIn({}, data); | ||
resource.saved[id] = _this.utils.updateTimestamp(resource.saved[id]); | ||
return saved; | ||
@@ -94,0 +92,0 @@ }); |
@@ -1,123 +0,53 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
HttpAdapter = require('HttpAdapter'), | ||
configErrorPrefix = 'DSProvider.config(options): ', | ||
registerAdapterErrorPrefix = 'DSProvider.registerAdapter(name, adapter): '; | ||
var errorPrefix = 'DSProvider.registerAdapter(name, adapter): ', | ||
utils = require('../utils')[0](); | ||
/** | ||
* @doc method | ||
* @id DSProvider.methods:config | ||
* @name config | ||
* @description | ||
* Configure the DS service. | ||
* | ||
* ## Signature: | ||
* ```js | ||
* DSProvider.config(options) | ||
* ``` | ||
* | ||
* ## Example: | ||
* ```js | ||
* DSProvider.config({ | ||
* baseUrl: 'http://myapp.com/api', | ||
* idAttribute: '_id', | ||
* validate: function (resourceName, attrs, cb) { | ||
* console.log('looks good to me'); | ||
* cb(null, attrs); | ||
* } | ||
* }); | ||
* ``` | ||
* | ||
* ## Throws: | ||
* | ||
* - `{IllegalArgumentError}` | ||
* | ||
* @param {object} options Global configuration for the data store. Properties: | ||
* - `{string=}` - `baseUrl` - The default base url to be used by the data store. Can be overridden via `DS.defineResource`. | ||
* - `{string=}` - `idAttribute` - The default property that specifies the primary key of an object. Default: `"id"`. | ||
* - `{function=}` - `beforeValidate` - Global lifecycle hook. Signature: `beforeValidate(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`. | ||
* - `{function=}` - `validate` - Global lifecycle hook. Signature: `validate(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`. | ||
* - `{function=}` - `afterValidate` - Global lifecycle hook. Signature: `afterValidate(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`. | ||
* - `{function=}` - `beforeCreate` - Global lifecycle hook. Signature: `beforeCreate(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`. | ||
* - `{function=}` - `afterCreate` - Global lifecycle hook. Signature: `afterCreate(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`. | ||
* - `{function=}` - `beforeUpdate` - Global lifecycle hook. Signature: `beforeUpdate(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`. | ||
* - `{function=}` - `afterUpdate` - Global lifecycle hook. Signature: `afterUpdate(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`. | ||
* - `{function=}` - `beforeDestroy` - Global lifecycle hook. Signature: `beforeDestroy(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`. | ||
* - `{function=}` - `afterDestroy` - Global lifecycle hook. Signature: `afterDestroy(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`. | ||
*/ | ||
function config(options) { | ||
options = options || {}; | ||
function lifecycleNoop(resourceName, attrs, cb) { | ||
cb(null, attrs); | ||
} | ||
if (!utils.isObject(options)) { | ||
throw new errors.IllegalArgumentError(configErrorPrefix + 'options: Must be an object!', { actual: typeof options, expected: 'object' }); | ||
} else if ('baseUrl' in options && !utils.isString(options.baseUrl)) { | ||
throw new errors.IllegalArgumentError(configErrorPrefix + 'options.baseUrl: Must be a string!', { baseUrl: { actual: typeof options.baseUrl, expected: 'string' } }); | ||
} else if ('idAttribute' in options && !utils.isString(options.idAttribute)) { | ||
throw new errors.IllegalArgumentError(configErrorPrefix + 'options.idAttribute: Must be a string!', { idAttribute: { actual: typeof options.idAttribute, expected: 'string' } }); | ||
} else if ('mergeStrategy' in options && !utils.isString(options.mergeStrategy)) { | ||
throw new errors.IllegalArgumentError(configErrorPrefix + 'options.mergeStrategy: Must be a string!', { mergeStrategy: { actual: typeof options.mergeStrategy, expected: 'string' } }); | ||
} else if ('beforeValidate' in options && !utils.isFunction(options.beforeValidate)) { | ||
throw new errors.IllegalArgumentError(configErrorPrefix + 'options.beforeValidate: Must be a function!', { beforeValidate: { actual: typeof options.beforeValidate, expected: 'function' } }); | ||
} else if ('validate' in options && !utils.isFunction(options.validate)) { | ||
throw new errors.IllegalArgumentError(configErrorPrefix + 'options.validate: Must be a function!', { validate: { actual: typeof options.validate, expected: 'function' } }); | ||
} else if ('afterValidate' in options && !utils.isFunction(options.afterValidate)) { | ||
throw new errors.IllegalArgumentError(configErrorPrefix + 'options.afterValidate: Must be a function!', { afterValidate: { actual: typeof options.afterValidate, expected: 'function' } }); | ||
} else if ('beforeCreate' in options && !utils.isFunction(options.beforeCreate)) { | ||
throw new errors.IllegalArgumentError(configErrorPrefix + 'options.beforeCreate: Must be a function!', { beforeCreate: { actual: typeof options.beforeCreate, expected: 'function' } }); | ||
} else if ('afterCreate' in options && !utils.isFunction(options.afterCreate)) { | ||
throw new errors.IllegalArgumentError(configErrorPrefix + 'options.afterCreate: Must be a function!', { afterCreate: { actual: typeof options.afterCreate, expected: 'function' } }); | ||
} else if ('beforeUpdate' in options && !utils.isFunction(options.beforeUpdate)) { | ||
throw new errors.IllegalArgumentError(configErrorPrefix + 'options.beforeUpdate: Must be a function!', { beforeUpdate: { actual: typeof options.beforeUpdate, expected: 'function' } }); | ||
} else if ('afterUpdate' in options && !utils.isFunction(options.afterUpdate)) { | ||
throw new errors.IllegalArgumentError(configErrorPrefix + 'options.afterUpdate: Must be a function!', { afterUpdate: { actual: typeof options.afterUpdate, expected: 'function' } }); | ||
} else if ('beforeDestroy' in options && !utils.isFunction(options.beforeDestroy)) { | ||
throw new errors.IllegalArgumentError(configErrorPrefix + 'options.beforeDestroy: Must be a function!', { beforeDestroy: { actual: typeof options.beforeDestroy, expected: 'function' } }); | ||
} else if ('afterDestroy' in options && !utils.isFunction(options.afterDestroy)) { | ||
throw new errors.IllegalArgumentError(configErrorPrefix + 'options.afterDestroy: Must be a function!', { afterDestroy: { actual: typeof options.afterDestroy, expected: 'function' } }); | ||
} else if ('defaultAdapter' in options && !utils.isString(options.defaultAdapter)) { | ||
throw new errors.IllegalArgumentError(configErrorPrefix + 'options.defaultAdapter: Must be a function!', { defaultAdapter: { actual: typeof options.defaultAdapter, expected: 'string' } }); | ||
} | ||
services.config = new services.BaseConfig(options); | ||
function BaseConfig() { | ||
} | ||
/** | ||
* @doc method | ||
* @id DSProvider.methods:registerAdapter | ||
* @name registerAdapter | ||
* @description | ||
* Register a new adapter. | ||
* | ||
* ## Signature: | ||
* ```js | ||
* DSProvider.registerAdapter(name, adapter); | ||
* ``` | ||
* | ||
* ## Example: | ||
* ```js | ||
* DSProvider.registerAdapter('IndexedDBAdapter', {...}); | ||
* ``` | ||
* | ||
* ## Throws: | ||
* | ||
* - `{IllegalArgumentError}` | ||
* - `{RuntimeError}` | ||
* | ||
* @param {string} name The name of the new adapter. | ||
* @param {object} adapter New adapter. | ||
*/ | ||
function registerAdapter(name, adapter) { | ||
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 | ||
}; | ||
} | ||
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; | ||
}; | ||
BaseConfig.prototype.baseUrl = ''; | ||
BaseConfig.prototype.endpoint = ''; | ||
BaseConfig.prototype.beforeValidate = lifecycleNoop; | ||
BaseConfig.prototype.validate = lifecycleNoop; | ||
BaseConfig.prototype.afterValidate = lifecycleNoop; | ||
BaseConfig.prototype.beforeCreate = lifecycleNoop; | ||
BaseConfig.prototype.afterCreate = lifecycleNoop; | ||
BaseConfig.prototype.beforeUpdate = lifecycleNoop; | ||
BaseConfig.prototype.afterUpdate = lifecycleNoop; | ||
BaseConfig.prototype.beforeDestroy = lifecycleNoop; | ||
BaseConfig.prototype.afterDestroy = lifecycleNoop; | ||
if (!utils.isString(name)) { | ||
throw new errors.IllegalArgumentError(registerAdapterErrorPrefix + 'name: Must be a string!', { actual: typeof name, expected: 'string' }); | ||
} else if (!utils.isObject(adapter)) { | ||
throw new errors.IllegalArgumentError(registerAdapterErrorPrefix + 'adapter: Must be an object!', { actual: typeof adapter, expected: 'object' }); | ||
} else if (services.adapters[name]) { | ||
throw new errors.RuntimeError(registerAdapterErrorPrefix + name + ' is already registered!'); | ||
} | ||
services.adapters[name] = adapter; | ||
} | ||
/** | ||
@@ -130,65 +60,57 @@ * @doc interface | ||
/** | ||
* @doc method | ||
* @id DSProvider.methods:config | ||
* @name config | ||
* @methodOf DSProvider | ||
* @description | ||
* See [DSProvider.config](/documentation/api/api/DSProvider.methods:config). | ||
*/ | ||
this.config = config; | ||
config({}); | ||
var defaults = this.defaults = new BaseConfig(), | ||
adapters = this.adapters = {}; | ||
/** | ||
* @doc method | ||
* @id DSProvider.methods:registerAdapter | ||
* @name config | ||
* @methodOf DSProvider | ||
* @description | ||
* See [DSProvider.registerAdapter](/documentation/api/api/DSProvider.methods:registerAdapter). | ||
*/ | ||
this.registerAdapter = registerAdapter; | ||
this.$get = [ | ||
'$rootScope', '$log', '$q', 'DSHttpAdapter', 'DSUtils', 'DSErrors', | ||
function ($rootScope, $log, $q, DSHttpAdapter, DSUtils, DSErrors) { | ||
this.$get = ['$rootScope', '$log', '$http', '$q', function ($rootScope, $log, $http, $q) { | ||
var syncMethods = require('./sync_methods'), | ||
asyncMethods = require('./async_methods'); | ||
services.$rootScope = $rootScope; | ||
services.$log = $log; | ||
services.$http = $http; | ||
services.$q = $q; | ||
services.store = {}; | ||
services.adapters = {}; | ||
adapters.DSHttpAdapter = DSHttpAdapter; | ||
registerAdapter('HttpAdapter', HttpAdapter); | ||
/** | ||
* @doc interface | ||
* @id DS | ||
* @name DS | ||
* @description | ||
* Data store | ||
*/ | ||
var DS = { | ||
$rootScope: $rootScope, | ||
$log: $log, | ||
$q: $q, | ||
defaults: defaults, | ||
store: {}, | ||
definitions: {}, | ||
adapters: adapters, | ||
errors: DSErrors, | ||
utils: DSUtils | ||
}; | ||
/** | ||
* @doc interface | ||
* @id DS | ||
* @name DS | ||
* @description | ||
* Data store | ||
*/ | ||
var DS = { | ||
HttpAdapter: HttpAdapter, | ||
errors: errors | ||
}; | ||
utils.deepMixIn(DS, require('./sync_methods')); | ||
utils.deepMixIn(DS, require('./async_methods')); | ||
DSUtils.deepFreeze(syncMethods); | ||
DSUtils.deepFreeze(asyncMethods); | ||
utils.deepFreeze(DS); | ||
DSUtils.deepMixIn(DS, syncMethods); | ||
DSUtils.deepMixIn(DS, asyncMethods); | ||
var $dirtyCheckScope = $rootScope.$new(); | ||
DSUtils.deepFreeze(DS.errors); | ||
DSUtils.deepFreeze(DS.utils); | ||
$dirtyCheckScope.$watch(function () { | ||
// Throttle angular-data's digest loop to tenths of a second | ||
return new Date().getTime() / 100 | 0; | ||
}, function () { | ||
DS.digest(); | ||
}); | ||
var $dirtyCheckScope = $rootScope.$new(); | ||
return DS; | ||
}]; | ||
$dirtyCheckScope.$watch(function () { | ||
// Throttle angular-data's digest loop to tenths of a second | ||
return new Date().getTime() / 100 | 0; | ||
}, function () { | ||
DS.digest(); | ||
}); | ||
return DS; | ||
}]; | ||
} | ||
module.exports = DSProvider; |
@@ -1,5 +0,2 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.changes(resourceName, id): '; | ||
var errorPrefix = 'DS.changes(resourceName, id): '; | ||
@@ -41,12 +38,12 @@ /** | ||
function changes(resourceName, id) { | ||
if (!services.store[resourceName]) { | ||
throw new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'); | ||
} else if (!utils.isString(id) && !utils.isNumber(id)) { | ||
throw new 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.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 { | ||
return angular.copy(services.store[resourceName].changes[id]); | ||
return angular.copy(this.store[resourceName].changes[id]); | ||
} catch (err) { | ||
throw new errors.UnhandledError(err); | ||
throw new this.errors.UnhandledError(err); | ||
} | ||
@@ -53,0 +50,0 @@ } |
@@ -1,12 +0,6 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.defineResource(definition): '; | ||
var errorPrefix = 'DS.defineResource(definition): '; | ||
function Resource(options) { | ||
services.BaseConfig.apply(this, [options]); | ||
function Resource(utils, options) { | ||
if ('name' in options) { | ||
this.name = options.name; | ||
} | ||
utils.deepMixIn(this, options); | ||
@@ -18,17 +12,4 @@ if ('endpoint' in options) { | ||
} | ||
this.collection = []; | ||
this.completedQueries = {}; | ||
this.pendingQueries = {}; | ||
this.index = {}; | ||
this.modified = {}; | ||
this.changes = {}; | ||
this.previous_attributes = {}; | ||
this.saved = {}; | ||
this.observers = {}; | ||
this.collectionModified = 0; | ||
} | ||
Resource.prototype = services.config; | ||
/** | ||
@@ -84,3 +65,3 @@ * @doc method | ||
function defineResource(definition) { | ||
if (utils.isString(definition)) { | ||
if (this.utils.isString(definition)) { | ||
definition = { | ||
@@ -90,19 +71,34 @@ name: definition | ||
} | ||
if (!utils.isObject(definition)) { | ||
throw new errors.IllegalArgumentError(errorPrefix + 'definition: Must be an object!', { definition: { actual: typeof definition, expected: 'object' } }); | ||
} else if (!utils.isString(definition.name)) { | ||
throw new errors.IllegalArgumentError(errorPrefix + 'definition.name: Must be a string!', { definition: { name: { actual: typeof definition.name, expected: 'string' } } }); | ||
} else if (definition.idAttribute && !utils.isString(definition.idAttribute)) { | ||
throw new errors.IllegalArgumentError(errorPrefix + 'definition.idAttribute: Must be a string!', { definition: { idAttribute: { actual: typeof definition.idAttribute, expected: 'string' } } }); | ||
} else if (definition.endpoint && !utils.isString(definition.endpoint)) { | ||
throw new errors.IllegalArgumentError(errorPrefix + 'definition.endpoint: Must be a string!', { definition: { endpoint: { actual: typeof definition.endpoint, expected: 'string' } } }); | ||
} else if (services.store[definition.name]) { | ||
throw new errors.RuntimeError(errorPrefix + definition.name + ' is already registered!'); | ||
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!'); | ||
} | ||
try { | ||
services.store[definition.name] = new Resource(definition); | ||
Resource.prototype = this.defaults; | ||
this.definitions[definition.name] = new Resource(this.utils, definition); | ||
this.store[definition.name] = { | ||
collection: [], | ||
completedQueries: {}, | ||
pendingQueries: {}, | ||
index: {}, | ||
changes: {}, | ||
modified: {}, | ||
saved: {}, | ||
previousAttributes: {}, | ||
observers: {}, | ||
collectionModified: 0 | ||
}; | ||
} catch (err) { | ||
delete services.store[definition.name]; | ||
throw new errors.UnhandledError(err); | ||
delete this.definitions[definition.name]; | ||
delete this.store[definition.name]; | ||
throw new this.errors.UnhandledError(err); | ||
} | ||
@@ -109,0 +105,0 @@ } |
@@ -1,5 +0,2 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
observe = require('observejs'); | ||
var observe = require('observejs'); | ||
@@ -31,4 +28,4 @@ /** | ||
try { | ||
if (!services.$rootScope.$$phase) { | ||
services.$rootScope.$apply(function () { | ||
if (!this.$rootScope.$$phase) { | ||
this.$rootScope.$apply(function () { | ||
observe.Platform.performMicrotaskCheckpoint(); | ||
@@ -40,3 +37,3 @@ }); | ||
} catch (err) { | ||
throw new errors.UnhandledError(err); | ||
throw new this.errors.UnhandledError(err); | ||
} | ||
@@ -43,0 +40,0 @@ } |
@@ -1,11 +0,8 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.eject(resourceName, id): '; | ||
var errorPrefix = 'DS.eject(resourceName, id): '; | ||
function _eject(resource, id) { | ||
function _eject(definition, resource, id) { | ||
if (id) { | ||
var found = false; | ||
for (var i = 0; i < resource.collection.length; i++) { | ||
if (resource.collection[i][resource.idAttribute] == id) { | ||
if (resource.collection[i][definition.idAttribute] == id) { | ||
found = true; | ||
@@ -21,3 +18,3 @@ break; | ||
delete resource.changes[id]; | ||
delete resource.previous_attributes[id]; | ||
delete resource.previousAttributes[id]; | ||
delete resource.modified[id]; | ||
@@ -32,5 +29,4 @@ delete resource.saved[id]; | ||
resource.changes = {}; | ||
resource.previous_attributes = {}; | ||
resource.previousAttributes = {}; | ||
} | ||
resource.collectionModified = utils.updateTimestamp(resource.collectionModified); | ||
} | ||
@@ -82,18 +78,23 @@ | ||
function eject(resourceName, id) { | ||
if (!services.store[resourceName]) { | ||
throw new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'); | ||
} else if (id && !utils.isString(id) && !utils.isNumber(id)) { | ||
throw new 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.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' } }); | ||
} | ||
var resource = this.store[resourceName], | ||
_this = this; | ||
try { | ||
if (!services.$rootScope.$$phase) { | ||
services.$rootScope.$apply(function () { | ||
_eject(services.store[resourceName], id); | ||
if (!this.$rootScope.$$phase) { | ||
this.$rootScope.$apply(function () { | ||
_eject(_this.definitions[resourceName], resource, id); | ||
resource.collectionModified = _this.utils.updateTimestamp(resource.collectionModified); | ||
}); | ||
} else { | ||
_eject(services.store[resourceName], id); | ||
_eject(_this.definitions[resourceName], resource, id); | ||
resource.collectionModified = _this.utils.updateTimestamp(resource.collectionModified); | ||
} | ||
} catch (err) { | ||
throw new errors.UnhandledError(err); | ||
throw new this.errors.UnhandledError(err); | ||
} | ||
@@ -100,0 +101,0 @@ } |
/* jshint loopfunc: true */ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.filter(resourceName, params[, options]): '; | ||
var errorPrefix = 'DS.filter(resourceName, params[, options]): '; | ||
@@ -50,12 +47,14 @@ /** | ||
if (!services.store[resourceName]) { | ||
throw new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'); | ||
} else if (!utils.isObject(params)) { | ||
throw new errors.IllegalArgumentError(errorPrefix + 'params: Must be an object!', { params: { actual: typeof params, expected: 'object' } }); | ||
} else if (!utils.isObject(options)) { | ||
throw new errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } }); | ||
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' } }); | ||
} | ||
try { | ||
var resource = services.store[resourceName]; | ||
var definition = this.definitions[resourceName], | ||
resource = this.store[resourceName], | ||
_this = this; | ||
@@ -65,3 +64,3 @@ // Protect against null | ||
var queryHash = utils.toJson(params); | ||
var queryHash = this.utils.toJson(params); | ||
@@ -78,34 +77,12 @@ if (!(queryHash in resource.completedQueries) && options.loadFromServer) { | ||
// The query has been completed, so hit the cache with the query | ||
var filtered = utils.filter(resource.collection, function (value) { | ||
var keep = true; | ||
var filtered = this.utils.filter(resource.collection, function (attrs) { | ||
var keep = true, | ||
where = params.query.where; | ||
// Apply 'where' clauses | ||
if (params.query.where) { | ||
if (!utils.isObject(params.query.where)) { | ||
throw new errors.IllegalArgumentError(errorPrefix + 'params.query.where: Must be an object!', { params: { query: { where: { actual: typeof params.query.where, expected: 'object' } } } }); | ||
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' } } } }); | ||
} | ||
utils.forOwn(params.query.where, function (value2, key2) { | ||
if (utils.isString(value2)) { | ||
value2 = { | ||
'===': value2 | ||
}; | ||
} | ||
if ('==' in value2) { | ||
keep = keep && (value[key2] == value2['==']); | ||
} else if ('===' in value2) { | ||
keep = keep && (value[key2] === value2['===']); | ||
} else if ('!=' in value2) { | ||
keep = keep && (value[key2] != value2['!=']); | ||
} else if ('>' in value2) { | ||
keep = keep && (value[key2] > value2['>']); | ||
} else if ('>=' in value2) { | ||
keep = keep && (value[key2] >= value2['>=']); | ||
} else if ('<' in value2) { | ||
keep = keep && (value[key2] < value2['<']); | ||
} else if ('<=' in value2) { | ||
keep = keep && (value[key2] <= value2['<=']); | ||
} else if ('in' in value2) { | ||
keep = keep && utils.contains(value2['in'], value[key2]); | ||
} | ||
}); | ||
keep = definition.filter(resourceName, where, attrs); | ||
} | ||
@@ -117,3 +94,3 @@ return keep; | ||
if (params.query.orderBy) { | ||
if (utils.isString(params.query.orderBy)) { | ||
if (this.utils.isString(params.query.orderBy)) { | ||
params.query.orderBy = [ | ||
@@ -123,16 +100,16 @@ [params.query.orderBy, 'ASC'] | ||
} | ||
if (utils.isArray(params.query.orderBy)) { | ||
if (this.utils.isArray(params.query.orderBy)) { | ||
for (var i = 0; i < params.query.orderBy.length; i++) { | ||
if (utils.isString(params.query.orderBy[i])) { | ||
if (this.utils.isString(params.query.orderBy[i])) { | ||
params.query.orderBy[i] = [params.query.orderBy[i], 'ASC']; | ||
} else if (!utils.isArray(params.query.orderBy[i])) { | ||
throw new 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' } } } }); | ||
} 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 = utils.sort(filtered, function (a, b) { | ||
filtered = this.utils.sort(filtered, function (a, b) { | ||
var cA = a[params.query.orderBy[i][0]], cB = b[params.query.orderBy[i][0]]; | ||
if (utils.isString(cA)) { | ||
cA = utils.upperCase(cA); | ||
if (_this.utils.isString(cA)) { | ||
cA = _this.utils.upperCase(cA); | ||
} | ||
if (utils.isString(cB)) { | ||
cB = utils.upperCase(cB); | ||
if (_this.utils.isString(cB)) { | ||
cB = _this.utils.upperCase(cB); | ||
} | ||
@@ -159,3 +136,3 @@ if (params.query.orderBy[i][1] === 'DESC') { | ||
} else { | ||
throw new errors.IllegalArgumentError(errorPrefix + 'params.query.orderBy: Must be a string or an array!', { params: { query: { orderBy: { actual: typeof params.query.orderBy, expected: 'string|array' } } } }); | ||
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' } } } }); | ||
} | ||
@@ -165,8 +142,8 @@ } | ||
// Apply 'limit' and 'skip' | ||
if (utils.isNumber(params.query.limit) && utils.isNumber(params.query.skip)) { | ||
filtered = utils.slice(filtered, params.query.skip, params.query.skip + params.query.limit); | ||
} else if (utils.isNumber(params.query.limit)) { | ||
filtered = utils.slice(filtered, 0, params.query.limit); | ||
} else if (utils.isNumber(params.query.skip)) { | ||
filtered = utils.slice(filtered, params.query.skip); | ||
if (this.utils.isNumber(params.query.limit) && this.utils.isNumber(params.query.skip)) { | ||
filtered = this.utils.slice(filtered, params.query.skip, params.query.skip + params.query.limit); | ||
} else if (this.utils.isNumber(params.query.limit)) { | ||
filtered = this.utils.slice(filtered, 0, params.query.limit); | ||
} else if (this.utils.isNumber(params.query.skip)) { | ||
filtered = this.utils.slice(filtered, params.query.skip); | ||
} | ||
@@ -176,6 +153,6 @@ | ||
} catch (err) { | ||
if (err instanceof errors.IllegalArgumentError) { | ||
if (err instanceof this.errors.IllegalArgumentError) { | ||
throw err; | ||
} else { | ||
throw new errors.UnhandledError(err); | ||
throw new this.errors.UnhandledError(err); | ||
} | ||
@@ -182,0 +159,0 @@ } |
@@ -1,5 +0,2 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.get(resourceName, id[, options]): '; | ||
var errorPrefix = 'DS.get(resourceName, id[, options]): '; | ||
@@ -40,8 +37,8 @@ /** | ||
if (!services.store[resourceName]) { | ||
throw new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'); | ||
} else if (!utils.isString(id) && !utils.isNumber(id)) { | ||
throw new errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } }); | ||
} else if (!utils.isObject(options)) { | ||
throw new errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } }); | ||
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' } }); | ||
} | ||
@@ -51,3 +48,3 @@ | ||
// cache miss, request resource from server | ||
if (!(id in services.store[resourceName].index) && options.loadFromServer) { | ||
if (!(id in this.store[resourceName].index) && options.loadFromServer) { | ||
this.find(resourceName, id).then(null, function (err) { | ||
@@ -59,5 +56,5 @@ throw err; | ||
// return resource from cache | ||
return services.store[resourceName].index[id]; | ||
return this.store[resourceName].index[id]; | ||
} catch (err) { | ||
throw new errors.UnhandledError(err); | ||
throw new this.errors.UnhandledError(err); | ||
} | ||
@@ -64,0 +61,0 @@ } |
@@ -1,7 +0,4 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.hasChanges(resourceName, id): '; | ||
var errorPrefix = 'DS.hasChanges(resourceName, id): '; | ||
function diffIsEmpty(diff) { | ||
function diffIsEmpty(utils, diff) { | ||
return !(utils.isEmpty(diff.added) && | ||
@@ -46,6 +43,6 @@ utils.isEmpty(diff.removed) && | ||
function hasChanges(resourceName, id) { | ||
if (!services.store[resourceName]) { | ||
throw new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'); | ||
} else if (!utils.isString(id) && !utils.isNumber(id)) { | ||
throw new 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.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' } }); | ||
} | ||
@@ -55,4 +52,4 @@ | ||
// return resource from cache | ||
if (id in services.store[resourceName].changes) { | ||
return diffIsEmpty(services.store[resourceName].changes[id]); | ||
if (id in this.store[resourceName].changes) { | ||
return diffIsEmpty(this.utils, this.store[resourceName].changes[id]); | ||
} else { | ||
@@ -62,3 +59,3 @@ return false; | ||
} catch (err) { | ||
throw new errors.UnhandledError(err); | ||
throw new this.errors.UnhandledError(err); | ||
} | ||
@@ -65,0 +62,0 @@ } |
@@ -1,8 +0,5 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
observe = require('observejs'), | ||
var observe = require('observejs'), | ||
errorPrefix = 'DS.inject(resourceName, attrs[, options]): '; | ||
function _inject(resource, attrs) { | ||
function _inject(definition, resource, attrs) { | ||
var _this = this; | ||
@@ -12,34 +9,34 @@ | ||
try { | ||
var innerId = getOldValueFn(resource.idAttribute); | ||
var innerId = getOldValueFn(definition.idAttribute); | ||
resource.changes[innerId] = utils.diffObjectFromOldObject(resource.index[innerId], resource.previous_attributes[innerId]); | ||
resource.modified[innerId] = utils.updateTimestamp(resource.modified[innerId]); | ||
resource.collectionModified = utils.updateTimestamp(resource.collectionModified); | ||
resource.changes[innerId] = _this.utils.diffObjectFromOldObject(resource.index[innerId], resource.previousAttributes[innerId]); | ||
resource.modified[innerId] = _this.utils.updateTimestamp(resource.modified[innerId]); | ||
resource.collectionModified = _this.utils.updateTimestamp(resource.collectionModified); | ||
if (resource.idAttribute in changed) { | ||
services.$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 "' + resource.name + | ||
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 errors.UnhandledError(err); | ||
throw new _this.errors.UnhandledError(err); | ||
} | ||
} | ||
if (utils.isArray(attrs)) { | ||
if (_this.utils.isArray(attrs)) { | ||
for (var i = 0; i < attrs.length; i++) { | ||
_inject.call(_this, resource, attrs[i]); | ||
_inject.call(_this, definition, resource, attrs[i]); | ||
} | ||
} else { | ||
if (!(resource.idAttribute in attrs)) { | ||
throw new errors.RuntimeError(errorPrefix + 'attrs: Must contain the property specified by `idAttribute`!'); | ||
if (!(definition.idAttribute in attrs)) { | ||
throw new _this.errors.RuntimeError(errorPrefix + 'attrs: Must contain the property specified by `idAttribute`!'); | ||
} else { | ||
var id = attrs[resource.idAttribute]; | ||
var id = attrs[definition.idAttribute]; | ||
if (!(id in resource.index)) { | ||
resource.index[id] = {}; | ||
resource.previous_attributes[id] = {}; | ||
resource.previousAttributes[id] = {}; | ||
utils.deepMixIn(resource.index[id], attrs); | ||
utils.deepMixIn(resource.previous_attributes[id], attrs); | ||
_this.utils.deepMixIn(resource.index[id], attrs); | ||
_this.utils.deepMixIn(resource.previousAttributes[id], attrs); | ||
@@ -54,3 +51,3 @@ resource.collection.push(resource.index[id]); | ||
} else { | ||
utils.deepMixIn(resource.index[id], attrs); | ||
_this.utils.deepMixIn(resource.index[id], attrs); | ||
resource.observers[id].deliver(); | ||
@@ -111,25 +108,26 @@ } | ||
if (!services.store[resourceName]) { | ||
throw new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'); | ||
} else if (!utils.isObject(attrs) && !utils.isArray(attrs)) { | ||
throw new errors.IllegalArgumentError(errorPrefix + 'attrs: Must be an object or an array!', { attrs: { actual: typeof attrs, expected: 'object|array' } }); | ||
} else if (!utils.isObject(options)) { | ||
throw new errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } }); | ||
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' } }); | ||
} | ||
var resource = services.store[resourceName], | ||
var definition = this.definitions[resourceName], | ||
resource = this.store[resourceName], | ||
_this = this; | ||
try { | ||
if (!services.$rootScope.$$phase) { | ||
services.$rootScope.$apply(function () { | ||
_inject.apply(_this, [services.store[resourceName], attrs]); | ||
if (!this.$rootScope.$$phase) { | ||
this.$rootScope.$apply(function () { | ||
_inject.apply(_this, [definition, resource, attrs]); | ||
}); | ||
} else { | ||
_inject.apply(_this, [services.store[resourceName], attrs]); | ||
_inject.apply(_this, [definition, resource, attrs]); | ||
} | ||
return attrs; | ||
} catch (err) { | ||
if (!(err instanceof errors.RuntimeError)) { | ||
throw new errors.UnhandledError(err); | ||
if (!(err instanceof this.errors.RuntimeError)) { | ||
throw new this.errors.UnhandledError(err); | ||
} else { | ||
@@ -136,0 +134,0 @@ throw err; |
@@ -1,5 +0,2 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.lastModified(resourceName[, id]): '; | ||
var errorPrefix = 'DS.lastModified(resourceName[, id]): '; | ||
@@ -41,17 +38,17 @@ /** | ||
function lastModified(resourceName, id) { | ||
if (!services.store[resourceName]) { | ||
throw new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'); | ||
} else if (id && !utils.isString(id) && !utils.isNumber(id)) { | ||
throw new 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.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 services.store[resourceName].modified)) { | ||
services.store[resourceName].modified[id] = 0; | ||
if (!(id in this.store[resourceName].modified)) { | ||
this.store[resourceName].modified[id] = 0; | ||
} | ||
return services.store[resourceName].modified[id]; | ||
return this.store[resourceName].modified[id]; | ||
} | ||
return services.store[resourceName].collectionModified; | ||
return this.store[resourceName].collectionModified; | ||
} catch (err) { | ||
throw new errors.UnhandledError(err); | ||
throw new this.errors.UnhandledError(err); | ||
} | ||
@@ -58,0 +55,0 @@ } |
@@ -1,5 +0,2 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.lastSaved(resourceName[, id]): '; | ||
var errorPrefix = 'DS.lastSaved(resourceName[, id]): '; | ||
@@ -48,17 +45,17 @@ /** | ||
function lastSaved(resourceName, id) { | ||
if (!services.store[resourceName]) { | ||
throw new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'); | ||
} else if (id && !utils.isString(id) && !utils.isNumber(id)) { | ||
throw new 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.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 services.store[resourceName].saved)) { | ||
services.store[resourceName].saved[id] = 0; | ||
if (!(id in this.store[resourceName].saved)) { | ||
this.store[resourceName].saved[id] = 0; | ||
} | ||
return services.store[resourceName].saved[id]; | ||
return this.store[resourceName].saved[id]; | ||
} | ||
return services.store[resourceName].collectionModified; | ||
return this.store[resourceName].collectionModified; | ||
} catch (err) { | ||
throw new errors.UnhandledError(err); | ||
throw new this.errors.UnhandledError(err); | ||
} | ||
@@ -65,0 +62,0 @@ } |
@@ -1,5 +0,2 @@ | ||
var utils = require('utils'), | ||
errors = require('errors'), | ||
services = require('services'), | ||
errorPrefix = 'DS.previous(resourceName, id): '; | ||
var errorPrefix = 'DS.previous(resourceName, id): '; | ||
@@ -42,6 +39,6 @@ /** | ||
function previous(resourceName, id) { | ||
if (!services.store[resourceName]) { | ||
throw new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'); | ||
} else if (!utils.isString(id) && !utils.isNumber(id)) { | ||
throw new 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.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' } }); | ||
} | ||
@@ -51,5 +48,5 @@ | ||
// return resource from cache | ||
return angular.copy(services.store[resourceName].previous_attributes[id]); | ||
return angular.copy(this.store[resourceName].previousAttributes[id]); | ||
} catch (err) { | ||
throw new errors.UnhandledError(err); | ||
throw new this.errors.UnhandledError(err); | ||
} | ||
@@ -56,0 +53,0 @@ } |
@@ -106,48 +106,2 @@ /** | ||
* @doc function | ||
* @id errors.types:ValidationError | ||
* @name ValidationError | ||
* @description Error that is thrown/returned when validation of a schema fails. | ||
* @param {string=} message Error message. Default: `"Validation Error!"`. | ||
* @param {object=} errors Object containing information about the error. | ||
* @returns {ValidationError} A new instance of `ValidationError`. | ||
*/ | ||
function ValidationError(message, errors) { | ||
Error.call(this); | ||
if (typeof Error.captureStackTrace === 'function') { | ||
Error.captureStackTrace(this, this.constructor); | ||
} | ||
/** | ||
* @doc property | ||
* @id errors.types:ValidationError.type | ||
* @name type | ||
* @propertyOf errors.types:ValidationError | ||
* @description Name of error type. Default: `"ValidationError"`. | ||
*/ | ||
this.type = this.constructor.name; | ||
/** | ||
* @doc property | ||
* @id errors.types:ValidationError.errors | ||
* @name errors | ||
* @propertyOf errors.types:ValidationError | ||
* @description Object containing information about the error. | ||
*/ | ||
this.errors = errors || {}; | ||
/** | ||
* @doc property | ||
* @id errors.types:ValidationError.message | ||
* @name message | ||
* @propertyOf errors.types:ValidationError | ||
* @description Error message. Default: `"Validation Error!"`. | ||
*/ | ||
this.message = message || 'Validation Error!'; | ||
} | ||
ValidationError.prototype = Object.create(Error.prototype); | ||
ValidationError.prototype.constructor = ValidationError; | ||
/** | ||
* @doc function | ||
* @id errors.types:RuntimeError | ||
@@ -202,11 +156,12 @@ * @name RuntimeError | ||
* @description | ||
* `UnhandledError`, `IllegalArgumentError`, `RuntimeError` and `ValidationError`. | ||
* `UnhandledError`, `IllegalArgumentError` and `RuntimeError`. | ||
* | ||
* References to the constructor functions of these errors can be found at `DS.errors`. | ||
*/ | ||
module.exports = { | ||
UnhandledError: UnhandledError, | ||
IllegalArgumentError: IllegalArgumentError, | ||
ValidationError: ValidationError, | ||
RuntimeError: RuntimeError | ||
}; | ||
module.exports = [function () { | ||
return { | ||
UnhandledError: UnhandledError, | ||
IllegalArgumentError: IllegalArgumentError, | ||
RuntimeError: RuntimeError | ||
}; | ||
}]; |
(function (window, angular, undefined) { | ||
'use strict'; | ||
// angular.module('jmdobry.binary-heap', []); | ||
// | ||
// /** | ||
// * @doc interface | ||
// * @id BinaryHeapProvider | ||
// * @name BinaryHeapProvider | ||
// */ | ||
// function BinaryHeapProvider() { | ||
// | ||
// var defaults = require('./binaryHeap/defaults'); | ||
// | ||
// /** | ||
// * @doc method | ||
// * @id BinaryHeapProvider.methods:setDefaultWeightFunction | ||
// * @name setDefaultWeightFunction | ||
// * @param {function} weightFunc New default weight function. | ||
// */ | ||
// function setDefaultWeightFunction(weightFunc) { | ||
// if (!angular.isFunction(weightFunc)) { | ||
// throw new Error('BinaryHeapProvider.setDefaultWeightFunction(weightFunc): weightFunc: Must be a function!'); | ||
// } | ||
// defaults.userProvidedDefaultWeightFunc = weightFunc; | ||
// } | ||
// | ||
// /** | ||
// * @doc method | ||
// * @id BinaryHeapProvider.methods:setDefaultWeightFunction | ||
// * @name setDefaultWeightFunction | ||
// * @methodOf BinaryHeapProvider | ||
// * @param {function} weightFunc New default weight function. | ||
// */ | ||
// this.setDefaultWeightFunction = setDefaultWeightFunction; | ||
// | ||
// this.$get = function () { | ||
// return require('./binaryHeap'); | ||
// }; | ||
// } | ||
// angular.module('jmdobry.binary-heap').provider('BinaryHeap', BinaryHeapProvider); | ||
angular.module('angular-data.BinaryHeap', []) | ||
.provider('BinaryHeap', require('./binaryHeap')); | ||
angular.module('angular-data.DS', ['ng', 'angular-data.BinaryHeap']) | ||
.service('DSUtils', require('./utils')) | ||
.service('DSErrors', require('./errors')) | ||
.provider('DSHttpAdapter', require('./adapters/http')) | ||
.provider('DS', require('./datastore')) | ||
.config(['$provide', function ($provide) { | ||
$provide.decorator('$q', 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); | ||
angular.module('jmdobry.angular-data', ['ng'/*, 'jmdobry.binary-heap'*/]).config(['$provide', function ($provide) { | ||
$provide.decorator('$q', 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) { | ||
try { | ||
fn.apply(target || this, args); | ||
} catch (err) { | ||
deferred.reject(err); | ||
} else { | ||
deferred.resolve(result); | ||
} | ||
}); | ||
try { | ||
fn.apply(target || this, args); | ||
} catch (err) { | ||
deferred.reject(err); | ||
} | ||
return deferred.promise; | ||
return deferred.promise; | ||
}; | ||
}; | ||
}; | ||
return $delegate; | ||
}); | ||
}]); | ||
angular.module('jmdobry.angular-data').provider('DS', require('./datastore')); | ||
return $delegate; | ||
}); | ||
}]); | ||
})(window, window.angular); |
@@ -1,76 +0,78 @@ | ||
module.exports = { | ||
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'), | ||
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; | ||
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'), | ||
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. | ||
} | ||
deepFreeze(prop); // Recursively call deepFreeze. | ||
} | ||
} | ||
}, | ||
diffObjectFromOldObject: function (object, oldObject) { | ||
var added = {}; | ||
var removed = {}; | ||
var changed = {}; | ||
}, | ||
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 | ||
}; | ||
} | ||
}; | ||
}; | ||
}]; |
@@ -214,7 +214,11 @@ describe('DS.filter(resourceName, params[, options])', function () { | ||
params.query.orderBy = [['age', 'DESC']]; | ||
params.query.orderBy = [ | ||
['age', 'DESC'] | ||
]; | ||
assert.deepEqual(DS.filter('post', params), [p4, p3, p2, p1], 'should accept an array of an array and sort in descending for numbers'); | ||
params.query.orderBy = [['author', 'DESC']]; | ||
params.query.orderBy = [ | ||
['author', 'DESC'] | ||
]; | ||
@@ -316,2 +320,33 @@ assert.deepEqual(DS.filter('post', params), [p2, p3, p1, p4], 'should accept an array of an array and sort in descending for strings'); | ||
}); | ||
it('should allow custom "where" filter function', function (done) { | ||
DS.defineResource({ | ||
name: 'comment', | ||
filter: function (resourceName, where, attrs) { | ||
return attrs.author === where.author.EQUALS || attrs.age % where.age.MOD === 1; | ||
} | ||
}); | ||
assert.doesNotThrow(function () { | ||
DS.inject('comment', p1); | ||
DS.inject('comment', p2); | ||
DS.inject('comment', p3); | ||
DS.inject('comment', p4); | ||
}, Error, 'should not throw an error'); | ||
var params = { | ||
query: { | ||
where: { | ||
author: { | ||
'EQUALS': 'John' | ||
}, | ||
age: { | ||
'MOD': 30 | ||
} | ||
} | ||
} | ||
}; | ||
assert.deepEqual(DS.filter('comment', params), [p1, p2], 'should keep p1 and p2'); | ||
done(); | ||
}); | ||
}); |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
327339
70
7548