Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

angular-data

Package Overview
Dependencies
Maintainers
1
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

angular-data - npm Package Compare versions

Comparing version 0.4.2 to 0.5.0

lib/observe-js.js

2

bower.json

@@ -5,3 +5,3 @@ {

"description": "Data store for Angular.js.",
"version": "0.4.2",
"version": "0.5.0",
"homepage": "http://jmdobry.github.io/angular-data/",

@@ -8,0 +8,0 @@ "repository": {

@@ -0,1 +1,14 @@

##### 0.5.0 - 16 January 2014
###### Backwards API changes
- #1 - Pluggable adapters
- #6 - Observable objects
- #7 - Model lifecycle hooks
###### Backwards compatible bug fixes
- #19 - Null pointer exception in several places where angular-data tries to use the $q service
##### Other
- #15 - Integration test coverage
##### 0.4.2 - 15 January 2014

@@ -2,0 +15,0 @@

/**
* @author Jason Dobry <jason.dobry@gmail.com>
* @file angular-data.min.js
* @version 0.4.2 - Homepage <http://jmdobry.github.io/angular-data/>
* @version 0.5.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}({1:[function(a,b){function c(a,b){return-1!==d(a,b)}var d=a("./indexOf");b.exports=c},{"./indexOf":3}],2:[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_":9}],3:[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},{}],4:[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":2}],5:[function(a,b){function c(a,b,c){return d.call(a,b,c)}var d=Array.prototype.slice;b.exports=c},{}],6:[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},{}],7:[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":13}],8:[function(a,b){function c(a){return a}b.exports=c},{}],9:[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":18,"./identity":8,"./prop":10}],10:[function(a,b){function c(a){return function(b){return b[a]}}b.exports=c},{}],11:[function(a,b){var c=a("./isKind"),d=Array.isArray||function(a){return c(a,"Array")};b.exports=d},{"./isKind":14}],12:[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":21,"./isArray":11}],13:[function(a,b){function c(a){return d(a,"Function")}var d=a("./isKind");b.exports=c},{"./isKind":14}],14:[function(a,b){function c(a,b){return d(a)===b}var d=a("./kindOf");b.exports=c},{"./kindOf":16}],15:[function(a,b){function c(a){return!!a&&"object"==typeof a&&a.constructor===Object}b.exports=c},{}],16:[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},{}],17:[function(a,b){function c(a){return null==a?"":a.toString()}b.exports=c},{}],18:[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":11,"./forOwn":21}],19:[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":15,"./forOwn":21}],20:[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},{}],21:[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":20,"./hasOwn":22}],22:[function(a,b){function c(a,b){return Object.prototype.hasOwnProperty.call(a,b)}b.exports=c},{}],23:[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":4,"../array/slice":5}],24:[function(a,b){function c(a){return a=d(a),a.toUpperCase()}var d=a("../lang/toString");b.exports=c},{"../lang/toString":17}],observejs:[function(a,b){b.exports=a("q+M0EE")},{}],"q+M0EE":[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===a>>>0}function d(a){return+a}function e(a){return a===Object(a)}function f(a,b){return a===b?0!==a||1/a===1/b:K(a)&&K(b)?!0:a!==a&&b!==b}function g(a){return"string"!=typeof a?!1:(a=a.replace(/\s/g,""),""==a?!0:"."==a[0]?!1:S.test(a))}function h(a){var b=T[a];if(b)return b;if(g(a)){var b=new i(a);return T[a]=b,b}}function i(a){return""==a.trim()?this:c(a)?(this.push(String(a)),this):(a.split(/\./).filter(function(a){return a}).forEach(function(a){this.push(a)},this),H&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn()),void 0)}function j(a){for(var b=0;U>b&&a.check();)a.report(),b++}function k(a){for(var b in a)return!1;return!0}function l(a){return k(a.added)&&k(a.removed)&&k(a.changed)}function m(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 n(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 o(a,b,c,d){if(this.closed=!1,this.object=a,this.callback=b,this.target=c,this.token=d,this.reporting=!0,G){var e=this;this.boundInternalCallback=function(a){e.internalCallback(a)}}p(this),this.connect(),this.sync(!0)}function p(a){W&&(V.push(a),o._allObserversCount++)}function q(a,b,c,d){o.call(this,a,b,c,d)}function r(a,b,c,d){if(!Array.isArray(a))throw Error("Provided object is not an Array");o.call(this,a,b,c,d)}function s(a){this.arr=[],this.callback=a,this.isObserved=!0}function t(a,b,c,d,f){this.value=void 0;var g=h(b);return g?g.length?e(a)?(this.path=g,o.call(this,a,c,d,f),void 0):(this.closed=!0,this.value=void 0,void 0):(this.closed=!0,this.value=a,void 0):(this.closed=!0,this.value=void 0,void 0)}function u(a,b){if("function"==typeof Object.observe){var c=Object.getNotifier(a);return function(d,e){var f={object:a,type:d,name:b};2===arguments.length&&(f.oldValue=e),c.notify(f)}}}function v(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];_[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}}function w(a,b,c,d,e,f){for(var g=f-e+1,h=c-b+1,i=new Array(g),j=0;g>j;j++)i[j]=new Array(h),i[j][0]=j;for(var k=0;h>k;k++)i[0][k]=k;for(var j=1;g>j;j++)for(var k=1;h>k;k++)if(d[e+j-1]===a[b+k-1])i[j][k]=i[j-1][k-1];else{var l=i[j-1][k]+1,m=i[j][k-1]+1;i[j][k]=m>l?l:m}return i}function x(a){for(var b=a.length-1,c=a[0].length-1,d=a[b][c],e=[];b>0||c>0;)if(0!=b)if(0!=c){var f,g=a[b-1][c-1],h=a[b-1][c],i=a[b][c-1];f=i>h?g>h?h:g:g>i?i:g,f==g?(g==d?e.push(ab):(e.push(bb),d=g),b--,c--):f==h?(e.push(db),b--,d=h):(e.push(cb),c--,d=i)}else e.push(db),b--;else e.push(cb),c--;return e.reverse(),e}function y(a,b,c){for(var d=0;c>d;d++)if(a[d]!==b[d])return d;return c}function z(a,b,c){for(var d=a.length,e=b.length,f=0;c>f&&a[--d]===b[--e];)f++;return f}function A(a,b,c){return{index:a,removed:b,addedCount:c}}function B(a,b,c,d,e,f){var g=0,h=0,i=Math.min(c-b,f-e);if(0==b&&0==e&&(g=y(a,d,i)),c==a.length&&f==d.length&&(h=z(a,d,i-g)),b+=g,e+=g,c-=h,f-=h,c-b==0&&f-e==0)return[];if(b==c){for(var j=A(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[A(b,[],c-b)];for(var k=x(w(a,b,c,d,e,f)),j=void 0,l=[],m=b,n=e,o=0;o<k.length;o++)switch(k[o]){case ab:j&&(l.push(j),j=void 0),m++,n++;break;case bb:j||(j=A(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case cb:j||(j=A(m,[],0)),j.addedCount++,m++;break;case db:j||(j=A(m,[],0)),j.removed.push(d[n]),n++}return j&&l.push(j),l}function C(a,b,c,d){return c>b||a>d?-1:b==c||d==a?0:c>a?d>b?b-c:d-c:b>d?d-a:b-a}function D(a,b,c,d){for(var e=A(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=C(e.index,e.index+e.removed.length,i.index,i.index+i.addedCount);if(j>=0){a.splice(h,1),h--,g-=i.addedCount-i.removed.length,e.addedCount+=i.addedCount-j;var k=e.removed.length+i.removed.length-j;if(e.addedCount||k){var c=i.removed;if(e.index<i.index){var l=e.removed.slice(0,i.index-e.index);Array.prototype.push.apply(l,c),c=l}if(e.index+e.removed.length>i.index+i.addedCount){var m=e.removed.slice(i.index+i.addedCount-e.index);Array.prototype.push.apply(c,m)}e.removed=c,i.index<e.index&&(e.index=i.index)}else f=!0}else if(e.index<i.index){f=!0,a.splice(h,0,e),h++;var n=e.addedCount-e.removed.length;i.index+=n,g+=n}}}f||a.push(e)}function E(a,b){for(var e=[],f=0;f<b.length;f++){var g=b[f];switch(g.type){case"splice":D(e,g.index,g.removed.slice(),g.addedCount);break;case"new":case"updated":case"deleted":if(!c(g.name))continue;var h=d(g.name);if(0>h)continue;D(e,h,[g.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(g))}}return e}function F(a,b){var c=[];return E(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?(b.removed[0]!==a[b.index]&&c.push(b),void 0):(c=c.concat(B(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)),void 0)}),c}var G=b(),H=!1;try{var I=new Function("","return true;");H=I()}catch(J){}var K=a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},L="__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},M="[$_a-zA-Z]",N="[$_a-zA-Z0-9]",O=M+"+"+N+"*",P="(?:[0-9]|[1-9]+[0-9]+)",Q="(?:"+O+"|"+P+")",R="(?:"+Q+")(?:\\."+Q+")*",S=new RegExp("^"+R+"$"),T={};i.prototype=L({__proto__:[],toString:function(){return this.join(".")},getValueFrom:function(a){for(var b=0;b<this.length;b++){if(void 0===a||null===a)return;a=a[this[b]]}return a},getValueFromObserved:function(a,b){b.reset();for(var c=0;c<this.length;c++){if(void 0===a||null===a)return b.cleanup(),void 0;b.observe(a),a=a[this[c]]}return a},compiledGetValueFromFn:function(){var a=this.map(function(a){return c(a)?'["'+a+'"]':"."+a}),b="",d="obj";b+="if (obj !== null && obj !== undefined";for(var e=0;e<this.length-1;e++){{this[e]}d+=a[e],b+=" &&\n "+d+" !== null && "+d+" !== undefined"}return b+=")\n",d+=a[e],b+=" return "+d+";\nelse\n return undefined;",new Function("obj",b)},setValueFrom:function(a,b){if(!this.length)return!1;for(var c=0;c<this.length-1;c++){if(void 0===a||null===a)return!1;a=a[this[c]]}return void 0===a||null===a?!1:(a[this[this.length-1]]=b,!0)}});var U=1e3;o.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||(G?(this.testingResults=a,Object.deliverChangeRecords(this.boundInternalCallback),this.testingResults=void 0):j(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){o._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+b)}},reset:function(){this.closed||(G&&(this.reporting=!1,Object.deliverChangeRecords(this.boundInternalCallback),this.reporting=!0),this.sync(!0))}};var V,W=!G||a.forceCollectObservers;o._allObserversCount=0,W&&(V=[]);var X=!1,Y="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!X){if(Y)return Object.deliverAllChangeRecords(),void 0;if(W){X=!0;var a=0,b={};do{a++;var c=V;V=[],b.anyChanged=!1;for(var d=0;d<c.length;d++){var e=c[d];e.closed||(G?e.deliver(b):e.check()&&(b.anyChanged=!0,e.report()),V.push(e))}}while(U>a&&b.anyChanged);o._allObserversCount=V.length,X=!1}}},W&&(a.Platform.clearObservers=function(){V=[]}),q.prototype=L({__proto__:o.prototype,connect:function(){G&&Object.observe(this.object,this.boundInternalCallback)},sync:function(){G||(this.oldObject=n(this.object))},check:function(a){var b,c;if(G){if(!a)return!1;c={},b=v(this.object,a,c)}else c=this.oldObject,b=m(this.object,this.oldObject);return l(b)?!1:(this.reportArgs=[b.added||{},b.removed||{},b.changed||{}],this.reportArgs.push(function(a){return c[a]}),!0)},disconnect:function(){G?this.object&&Object.unobserve(this.object,this.boundInternalCallback):this.oldObject=void 0}}),r.prototype=L({__proto__:q.prototype,connect:function(){G&&Array.observe(this.object,this.boundInternalCallback)},sync:function(){G||(this.oldObject=this.object.slice())},check:function(a){var b;if(G){if(!a)return!1;b=F(this.object,a)}else b=B(this.object,0,this.object.length,this.oldObject,0,this.oldObject.length);return b&&b.length?(this.reportArgs=[b],!0):!1}}),r.applySplices=function(a,b,c){c.forEach(function(c){for(var d=[c.index,c.removed.length],e=c.index;e<c.index+c.addedCount;)d.push(b[e]),e++;Array.prototype.splice.apply(a,d)})};var Z=Object.getPrototypeOf({}),$=Object.getPrototypeOf([]);s.prototype={reset:function(){this.isObserved=!this.isObserved},observe:function(a){if(e(a)&&a!==Z&&a!==$){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}},t.prototype=L({__proto__:o.prototype,connect:function(){G&&(this.observedSet=new s(this.boundInternalCallback))},disconnect:function(){this.value=void 0,G&&(this.observedSet.reset(),this.observedSet.cleanup(),this.observedSet=void 0)},check:function(){return this.value=G?this.path.getValueFromObserved(this.object,this.observedSet):this.path.getValueFrom(this.object),f(this.value,this.oldValue)?!1:(this.reportArgs=[this.value,this.oldValue],!0)},sync:function(a){a&&(this.value=G?this.path.getValueFromObserved(this.object,this.observedSet):this.path.getValueFrom(this.object)),this.oldValue=this.value}}),t.getValueAtPath=function(a,b){var c=h(b);if(c)return c.getValueFrom(a)},t.setValueAtPath=function(a,b,c){var d=h(b);d&&d.setValueFrom(a,c)};var _={"new":!0,updated:!0,deleted:!0};t.defineProperty=function(a,b,c){var d=c.object,e=h(c.path),f=u(a,b),g=new t(d,c.path,function(a,b){f&&f("updated",b)});return Object.defineProperty(a,b,{get:function(){return e.getValueFrom(d)},set:function(a){e.setValueFrom(d,a)},configurable:!0}),{close:function(){var c=e.getValueFrom(d);f&&g.deliver(),g.close(),Object.defineProperty(a,b,{value:c,writable:!0,configurable:!0})}}};var ab=0,bb=1,cb=2,db=3;a.Observer=o,a.Observer.hasObjectObserve=G,a.ArrayObserver=r,a.ArrayObserver.calculateSplices=function(a,b){return B(a,0,a.length,b,0,b.length)},a.ObjectObserver=q,a.PathObserver=t,a.Path=i}((c.Number={isNaN:window.isNaN})?c:c)},{}],27:[function(a,b){function c(a,b){var c=$q.defer();f.store[a]?d.isObject(b)||c.reject(new e.IllegalArgumentError(g+"attrs: Must be an object!",{attrs:{actual:typeof b,expected:"object"}})):c.reject(new e.RuntimeError(g+a+" is not a registered resource!"));try{var h=f.store[a],i=this,j=d.makePath(h.baseUrl||f.config.baseUrl,h.endpoint||h.name);h.validate?h.validate(b,null,function(a){a?c.reject(a):i.POST(j,b,null).then(function(a){try{c.resolve(i.inject(h.name,a))}catch(b){c.reject(b)}},c.reject)}):i.POST(j,b,null).then(function(a){try{c.resolve(i.inject(h.name,a))}catch(b){c.reject(b)}},c.reject)}catch(k){c.reject(new e.UnhandledError(k))}return c.promise}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"}],28:[function(a,b){function c(a,b){var c=$q.defer();f.store[a]?d.isString(b)||d.isNumber(b)||c.reject(new e.IllegalArgumentError(g+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}})):c.reject(new e.RuntimeError(g+a+" is not a registered resource!"));try{var h=f.store[a],i=this,j=d.makePath(h.baseUrl||f.config.baseUrl,h.endpoint||h.name,b);i.DEL(j,null).then(function(){try{i.eject(a,b),c.resolve(b)}catch(d){c.reject(d)}},c.reject)}catch(k){c.reject(new e.UnhandledError(k))}return c.promise}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"}],29:[function(a,b){function c(a,b,c){var i=$q.defer();if(c=c||{},f.store[a])if(d.isString(b)||d.isNumber(b))if(d.isObject(c)){var j=this;try{var k=f.store[a];if(b in k.index&&!c.bypassCache)i.resolve(j.get(a,b));else{var l=d.makePath(k.baseUrl||f.config.baseUrl,k.endpoint||k.name,b),m=null;c.bypassCache&&(m={headers:{"Last-Modified":new Date(k.modified[b])}}),g(l,m).then(function(c){try{j.inject(a,c),i.resolve(j.get(a,b))}catch(d){i.reject(d)}},i.reject)}}catch(n){n instanceof e.UnhandledError?i.reject(n):i.reject(new e.UnhandledError(n))}}else i.reject(new e.IllegalArgumentError(h+"options: Must be an object!",{options:{actual:typeof c,expected:"object"}}));else i.reject(new e.IllegalArgumentError(h+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}}));else i.reject(new e.RuntimeError(h+a+" is not a registered resource!"));return i.promise}var d=a("utils"),e=a("errors"),f=a("services"),g=a("../../http").GET,h="DS.find(resourceName, id[, options]): ";b.exports=c},{"../../http":34,errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],30:[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||h.config.idAttribute||"id"),d.collectionModified=f.updateTimestamp(d.collectionModified),a}function d(a,b,d,e){var j=h.store[b],k=this,l=f.toJson(d);if(e.bypassCache&&delete j.completedQueries[l],l in j.completedQueries)a.resolve(this.filter(b,d,e));else if(!j.pendingQueries[l]){var m=f.makePath(j.baseUrl||h.config.baseUrl,j.endpoint||j.name);j.pendingQueries[l]=i(m,{params:d}).then(function(d){try{a.resolve(c.apply(k,[d,b,l]))}catch(e){a.reject(new g.UnhandledError(e))}},a.reject)}}function e(a,b,c){var e=h.$q.defer();if(c=c||{},h.store[a])if(f.isObject(b))if(f.isObject(c))try{d.apply(this,[e,a,b,c])}catch(i){e.reject(new g.UnhandledError(i))}else e.reject(new g.IllegalArgumentError(j+"options: Must be an object!",{options:{actual:typeof c,expected:"object"}}));else e.reject(new g.IllegalArgumentError(j+"params: Must be an object!",{params:{actual:typeof b,expected:"object"}}));else e.reject(new g.RuntimeError(j+a+" is not a registered resource!"));return e.promise}var f=a("utils"),g=a("errors"),h=a("services"),i=a("../../http").GET,j="DS.findAll(resourceName, params[, options]): ";b.exports=e},{"../../http":34,errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],31:[function(a,b){b.exports={create:a("./create"),destroy:a("./destroy"),find:a("./find"),findAll:a("./findAll"),refresh:a("./refresh"),save:a("./save")}},{"./create":27,"./destroy":28,"./find":29,"./findAll":30,"./refresh":32,"./save":33}],32:[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("DS.refresh(resourceName, id): 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"}});return b in f.store[a].index?this.find(a,b,!0):!1}var d=a("utils"),e=a("errors"),f=a("services"),g=(a("../../http").PUT,"DS.refresh(resourceName, id): ");b.exports=c},{"../../http":34,errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],33:[function(a,b){function c(a,b,c,d){var f=this,i=e.makePath(b.baseUrl||g.config.baseUrl,b.endpoint||b.name,c);h(i,b.index[c],null).then(function(g){var h=f.inject(b.name,g,d);b.saved[c]=e.updateTimestamp(b.saved[c]),a.resolve(h)},a.reject)}function d(a,b,d){var h=$q.defer();if(d=d||{},g.store[a])if(e.isString(b)||e.isNumber(b))if(e.isObject(d)){var j=this;try{var k=g.store[a];k.schema?k.schema.validate(k.index[b],function(a){a?h.reject(a):c.call(j,h,k,b,d)}):c.call(j,h,k,b,d)}catch(l){l instanceof f.UnhandledError?h.reject(l):h.reject(new f.UnhandledError(l))}}else h.reject(new f.IllegalArgumentError(i+"id: Must be an object!",{options:{actual:typeof d,expected:"object"}}));else h.reject(new f.IllegalArgumentError(i+"id: Must be a string or a number!",{id:{actual:typeof b,expected:"string|number"}}));else h.reject(new f.RuntimeError(i+a+" is not a registered resource!"));return h.promise}var e=a("utils"),f=a("errors"),g=a("services"),h=a("../../http").PUT,i="DS.save(resourceName, id[, options]): ";b.exports=d},{"../../http":34,errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],34:[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"}],35:[function(a,b){function c(a){if(a=a||{},!e.isObject(a))throw new g(i+"options: Must be an object!",{actual:typeof a,expected:"object"});if(!e.isString(a.baseUrl))throw new g(i+"options: Must be an object!",{baseUrl:{actual:typeof a,expected:"object"}});e.deepMixIn(h.config,a)}function d(){this.config=c,this.$get=["$rootScope","$log","$http","$q",function(b,c,d,g){h.$rootScope=b,h.$log=c,h.$http=d,h.$q=g,h.store={};var i={};e.deepMixIn(i,a("./http")),e.deepMixIn(i,a("./sync_methods")),e.deepMixIn(i,a("./async_methods")),i.errors=f,e.deepFreeze(i);var j=b.$new();return j.$watch(function(){return(new Date).getTime()/100|0},function(){i.digest()}),i}]}var e=a("utils"),f=a("errors"),g=f.IllegalArgumentError,h=a("services"),i="DSProvider.config(options): ";b.exports=d},{"./async_methods":31,"./http":34,"./sync_methods":45,errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],services:[function(a,b){b.exports=a("cX8q+p")},{}],"cX8q+p":[function(a,b){b.exports={config:{idAttribute:"id"},store:{}}},{}],38:[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 d.deepMixIn({},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"}],39:[function(a,b){function c(a){if(d.isString(a)&&(a={name:a}),!d.isObject(a))throw new e.IllegalArgumentError(g+"definition: Must be an object!",{definition:{actual:typeof a,expected:"object"}});if(!d.isString(a.name))throw new e.IllegalArgumentError(g+"definition.name: Must be a string!",{definition:{name:{actual:typeof a.name,expected:"string"}}});if(a.idAttribute&&!d.isString(a.idAttribute))throw new e.IllegalArgumentError(g+"definition.idAttribute: Must be a string!",{definition:{idAttribute:{actual:typeof a.idAttribute,expected:"string"}}});if(f.store[a.name])throw new e.RuntimeError(g+a.name+" is already registered!");try{f.store[a.name]=a;var b=f.store[a.name];b.collection=[],b.completedQueries={},b.pendingQueries={},b.index={},b.modified={},b.changes={},b.previous_attributes={},b.saved={},b.observers={},b.collectionModified=0,b.idAttribute=b.idAttribute||f.config.idAttribute||"id"}catch(c){throw delete f.store[a.name],new e.UnhandledError(c)}}var d=a("utils"),e=a("errors"),f=a("services"),g="DS.defineResource(definition): ";b.exports=c},{errors:"hIh4e1",services:"cX8q+p",utils:"uE/lJt"}],40:[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:"q+M0EE",services:"cX8q+p",utils:"uE/lJt"}],41:[function(a,b){function c(a,b){if(b){for(var c=0;c<a.collection.length&&a.collection[c][a.idAttribute||"id"]!=b;c++);a.collection.splice(c,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.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"}],42:[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"}],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.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),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"}],44:[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 c(g.store[a].changes[b])}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"}],45:[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":38,"./defineResource":39,"./digest":40,"./eject":41,"./filter":42,"./get":43,"./hasChanges":44,"./inject":46,"./lastModified":47,"./lastSaved":48,"./previous":49}],46:[function(a,b){function c(a,b){var d=this;if(e.isArray(b))for(var i=0;i<b.length;i++)c.call(d,a,b[i]);else{var j=b[a.idAttribute||"id"];j in a.index?(e.deepMixIn(a.index[j],b),a.observers[j].deliver()):(a.index[j]={},a.previous_attributes[j]={},e.deepMixIn(a.index[j],b),e.deepMixIn(a.previous_attributes[j],b),a.collection.push(a.index[j]),a.observers[j]=new h.ObjectObserver(a.index[j],function(b,c,d,h){try{var i=h(a.idAttribute||"id");
a.index[i][a.idAttribute||"id"]!=i&&(a.index[i][a.idAttribute||"id"]=i,g.$log.error("You cannot change the primary key of an object! Reverting change to primary key.")),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)}catch(j){throw new f.UnhandledError(j)}}),a.observers[j].deliver())}}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],j=this,k=h.idAttribute||"id";if(b[k]){try{g.$rootScope.$$phase?c.apply(j,[g.store[a],b]):g.$rootScope.$apply(function(){c.apply(j,[g.store[a],b])})}catch(l){throw new f.UnhandledError(l)}return h.index[b[k]]}throw new f.RuntimeError(i+"attrs: Must contain the property specified by `idAttribute` in the resource definition!")}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:"q+M0EE",services:"cX8q+p",utils:"uE/lJt"}],47:[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 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"}],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 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"}],49:[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}},{}],52:[function(a){!function(b,c){"use strict";c.module("jmdobry.angular-data",["ng"]),c.module("jmdobry.angular-data").provider("DS",a("./datastore"))}(window,window.angular)},{"./datastore":35}],"uE/lJt":[function(a,b){b.exports={isString:angular.isString,isArray:angular.isArray,isObject:angular.isObject,isNumber:angular.isNumber,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":1,"mout/array/filter":2,"mout/array/slice":5,"mout/array/sort":6,"mout/array/toLookup":7,"mout/lang/isEmpty":12,"mout/object/deepMixIn":19,"mout/object/forOwn":21,"mout/string/makePath":23,"mout/string/upperCase":24}],utils:[function(a,b){b.exports=a("uE/lJt")},{}]},{},[52]);
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]);

@@ -76,3 +76,4 @@ /*

alias: [
'node_modules/observe-js/src/observe.js:observejs',
'lib/observe-js.js:observejs',
'src/datastore/adapters/http/index.js:HttpAdapter',
'src/datastore/services/index.js:services',

@@ -79,0 +80,0 @@ 'src/errors/index.js:errors',

@@ -25,3 +25,3 @@ // an example karma.conf.js

'dist/angular-data.js',
'test/**/*.js',
'test/integration/**/*.js',
'karma.start.js'

@@ -28,0 +28,0 @@ ],

// Setup global test variables
var $rootScope, $q, $log, DS, app, $httpBackend, p1, p2, p3, p4;
var $rootScope, $q, $log, DSProvider, DS, app, $httpBackend, p1, p2, p3, p4;
var lifecycle = {};
// Helper globals

@@ -12,2 +14,4 @@ var fail = function (msg) {

}],
TYPES_EXCEPT_STRING_OR_OBJECT = [123, 123.123, null, undefined, [], true, false, function () {
}],
TYPES_EXCEPT_ARRAY = ['string', 123, 123.123, null, undefined, {}, true, false, function () {

@@ -31,4 +35,54 @@ }],

beforeEach(function (done) {
module('app');
inject(function (_$rootScope_, _$q_, _$httpBackend_, _DS_) {
lifecycle.beforeValidate = function (resourceName, attrs, cb) {
lifecycle.beforeValidate.callCount += 1;
cb(null, attrs);
};
lifecycle.validate = function (resourceName, attrs, cb) {
lifecycle.validate.callCount += 1;
cb(null, attrs);
};
lifecycle.afterValidate = function (resourceName, attrs, cb) {
lifecycle.afterValidate.callCount += 1;
cb(null, attrs);
};
lifecycle.beforeCreate = function (resourceName, attrs, cb) {
lifecycle.beforeCreate.callCount += 1;
cb(null, attrs);
};
lifecycle.afterCreate = function (resourceName, attrs, cb) {
lifecycle.afterCreate.callCount += 1;
cb(null, attrs);
};
lifecycle.beforeUpdate = function (resourceName, attrs, cb) {
lifecycle.beforeUpdate.callCount += 1;
cb(null, attrs);
};
lifecycle.afterUpdate = function (resourceName, attrs, cb) {
lifecycle.afterUpdate.callCount += 1;
cb(null, attrs);
};
lifecycle.beforeDestroy = function (resourceName, attrs, cb) {
lifecycle.beforeDestroy.callCount += 1;
cb(null, attrs);
};
lifecycle.afterDestroy = function (resourceName, attrs, cb) {
lifecycle.afterDestroy.callCount += 1;
cb(null, attrs);
};
module('app', function (_DSProvider_) {
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
});
});
inject(function (_$rootScope_, _$q_, _$httpBackend_, _DS_, _$log_) {
// Setup global mocks

@@ -39,29 +93,17 @@ $q = _$q_;

$httpBackend = _$httpBackend_;
app = {
baseUrl: 'http://test.angular-cache.com'
};
DS.defineResource({
name: 'post',
endpoint: '/posts',
baseUrl: app.baseUrl
endpoint: '/posts'
});
$log = {
warn: function () {
},
log: function () {
},
info: function () {
},
error: function () {
},
debug: function () {
}
};
$log = _$log_;
// Setup global spies
sinon.spy($log, 'warn');
sinon.spy($log, 'log');
sinon.spy($log, 'info');
sinon.spy($log, 'error');
sinon.spy($log, 'debug');
lifecycle.beforeValidate.callCount = 0;
lifecycle.validate.callCount = 0;
lifecycle.afterValidate.callCount = 0;
lifecycle.beforeCreate.callCount = 0;
lifecycle.afterCreate.callCount = 0;
lifecycle.beforeUpdate.callCount = 0;
lifecycle.afterUpdate.callCount = 0;
lifecycle.beforeDestroy.callCount = 0;
lifecycle.afterDestroy.callCount = 0;
});

@@ -79,10 +121,5 @@

afterEach(function () {
// Tear down global spies
$log.warn.restore();
$log.log.restore();
$log.info.restore();
$log.error.restore();
$log.debug.restore();
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
$log.reset();
});
{
"name": "angular-data",
"description": "Data store for Angular.js.",
"version": "0.4.2",
"version": "0.5.0",
"homepage": "http://github.com/jmdobry/angular-data",

@@ -6,0 +6,0 @@ "repository": {

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

__Current version:__ 0.4.2
__Current version:__ 0.5.0

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

- 100% tested (whatever _that_ means)
- See [issues](https://github.com/jmdobry/angular-data/issues?milestone=8&page=1&state=open) for what's in development
- See [issues](https://github.com/jmdobry/angular-data/issues?milestone=7&page=1&state=open) for what's in development

@@ -19,0 +19,0 @@ ## Changelog

@@ -48,3 +48,5 @@ var utils = require('utils'),

function create(resourceName, attrs) {
var deferred = $q.defer();
var deferred = services.$q.defer(),
promise = deferred.promise;
if (!services.store[resourceName]) {

@@ -54,40 +56,39 @@ deferred.reject(new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'));

deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'attrs: Must be an object!', { attrs: { actual: typeof attrs, expected: 'object' } }));
}
} else {
try {
var resource = services.store[resourceName],
_this = this;
try {
var resource = services.store[resourceName],
_this = this,
url = utils.makePath(resource.baseUrl || services.config.baseUrl, resource.endpoint || resource.name);
promise = promise
.then(function (attrs) {
return services.$q.promisify(resource.beforeValidate)(resourceName, attrs);
})
.then(function (attrs) {
return services.$q.promisify(resource.validate)(resourceName, attrs);
})
.then(function (attrs) {
return services.$q.promisify(resource.afterValidate)(resourceName, attrs);
})
.then(function (attrs) {
return services.$q.promisify(resource.beforeCreate)(resourceName, attrs);
})
.then(function (attrs) {
return services.adapters[resource.defaultAdapter].POST.apply(_this, [utils.makePath(resource.baseUrl, resource.endpoint), attrs, null]);
})
.then(function (data) {
return services.$q.promisify(resource.afterCreate)(resourceName, data);
})
.then(function (data) {
return _this.inject(resource.name, data);
});
if (resource.validate) {
resource.validate(attrs, null, function (err) {
if (err) {
deferred.reject(err);
} else {
_this.POST(url, attrs, null).then(function (data) {
try {
deferred.resolve(_this.inject(resource.name, data));
} catch (err) {
deferred.reject(err);
}
}, deferred.reject);
}
});
} else {
_this.POST(url, attrs, null).then(function (data) {
try {
deferred.resolve(_this.inject(resource.name, data));
} catch (err) {
deferred.reject(err);
}
}, deferred.reject);
deferred.resolve(attrs);
} catch (err) {
deferred.reject(new errors.UnhandledError(err));
}
} catch (err) {
deferred.reject(new errors.UnhandledError(err));
}
return deferred.promise;
return promise;
}
module.exports = create;

@@ -48,3 +48,5 @@ var utils = require('utils'),

function destroy(resourceName, id) {
var deferred = $q.defer();
var deferred = services.$q.defer(),
promise = deferred.promise;
if (!services.store[resourceName]) {

@@ -54,24 +56,27 @@ deferred.reject(new errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'));

deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } }));
}
try {
} else {
var resource = services.store[resourceName],
_this = this,
url = utils.makePath(resource.baseUrl || services.config.baseUrl, resource.endpoint || resource.name, id);
_this = this;
_this.DEL(url, null).then(function () {
try {
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);
deferred.resolve(id);
} catch (err) {
deferred.reject(err);
}
}, deferred.reject);
} catch (err) {
deferred.reject(new errors.UnhandledError(err));
return id;
});
deferred.resolve(resource.index[id]);
}
return deferred.promise;
return promise;
}
module.exports = destroy;
var utils = require('utils'),
errors = require('errors'),
services = require('services'),
GET = require('../../http').GET,
errorPrefix = 'DS.find(resourceName, id[, options]): ';

@@ -52,3 +51,5 @@

function find(resourceName, id, options) {
var deferred = $q.defer();
var deferred = services.$q.defer(),
promise = deferred.promise;
options = options || {};

@@ -63,41 +64,33 @@

} else {
var _this = this;
try {
var resource = services.store[resourceName];
var resource = services.store[resourceName],
_this = this;
if (id in resource.index && !options.bypassCache) {
deferred.resolve(_this.get(resourceName, id));
} else {
var url = utils.makePath(resource.baseUrl || services.config.baseUrl, resource.endpoint || resource.name, id),
config = null;
if (options.bypassCache) {
delete resource.completedQueries[id];
}
if (options.bypassCache) {
config = {
headers: {
'Last-Modified': new Date(resource.modified[id])
}
};
if (!(id in resource.completedQueries)) {
if (!(id in resource.pendingQueries)) {
promise = resource.pendingQueries[id] = services.adapters[resource.defaultAdapter].GET(utils.makePath(resource.baseUrl, resource.endpoint, id), null)
.then(function (data) {
// Query is no longer pending
delete resource.pendingQueries[id];
resource.completedQueries[id] = new Date().getTime();
return _this.inject(resourceName, data);
});
}
GET(url, config).then(function (data) {
try {
_this.inject(resourceName, data);
deferred.resolve(_this.get(resourceName, id));
} catch (err) {
deferred.reject(err);
}
}, deferred.reject);
return resource.pendingQueries[id];
} else {
deferred.resolve(_this.get(resourceName, id));
}
} catch (err) {
if (!(err instanceof errors.UnhandledError)) {
deferred.reject(new errors.UnhandledError(err));
} else {
deferred.reject(err);
}
deferred.reject(err);
}
}
return deferred.promise;
return promise;
}
module.exports = find;
var utils = require('utils'),
errors = require('errors'),
services = require('services'),
GET = require('../../http').GET,
errorPrefix = 'DS.findAll(resourceName, params[, options]): ';

@@ -22,3 +21,3 @@

// Update the data store's index for this resource
resource.index = utils.toLookup(resource.collection, resource.idAttribute || services.config.idAttribute || 'id');
resource.index = utils.toLookup(resource.collection, resource.idAttribute);

@@ -30,8 +29,7 @@ // Update modified timestamp of collection

function _findAll(deferred, resourceName, params, options) {
function _findAll(resourceName, params, options) {
var resource = services.store[resourceName],
_this = this;
_this = this,
queryHash = utils.toJson(params);
var queryHash = utils.toJson(params);
if (options.bypassCache) {

@@ -44,16 +42,18 @@ delete resource.completedQueries[queryHash];

if (!resource.pendingQueries[queryHash]) {
if (!(queryHash in resource.pendingQueries)) {
// This particular query has never even been started
var url = utils.makePath(resource.baseUrl || services.config.baseUrl, resource.endpoint || resource.name);
resource.pendingQueries[queryHash] = GET(url, { params: params }).then(function (data) {
try {
deferred.resolve(processResults.apply(_this, [data, resourceName, queryHash]));
} catch (err) {
deferred.reject(new errors.UnhandledError(err));
}
}, deferred.reject);
// This particular query has never even been made
resource.pendingQueries[queryHash] = services.adapters[resource.defaultAdapter].GET(utils.makePath(resource.baseUrl, resource.endpoint), { params: params })
.then(function (data) {
try {
return processResults.apply(_this, [data, resourceName, queryHash]);
} catch (err) {
throw new errors.UnhandledError(err);
}
});
}
return resource.pendingQueries[queryHash];
} else {
deferred.resolve(this.filter(resourceName, params, options));
return this.filter(resourceName, params, options);
}

@@ -130,3 +130,5 @@ }

function findAll(resourceName, params, options) {
var deferred = services.$q.defer();
var deferred = services.$q.defer(),
promise = deferred.promise,
_this = this;

@@ -143,3 +145,6 @@ options = options || {};

try {
_findAll.apply(this, [deferred, resourceName, params, options]);
promise = promise.then(function () {
return _findAll.apply(_this, [resourceName, params, options]);
});
deferred.resolve();
} catch (err) {

@@ -150,5 +155,5 @@ deferred.reject(new errors.UnhandledError(err));

return deferred.promise;
return promise;
}
module.exports = findAll;
var utils = require('utils'),
errors = require('errors'),
services = require('services'),
PUT = require('../../http').PUT,
errorPrefix = 'DS.refresh(resourceName, id): ';
errorPrefix = 'DS.refresh(resourceName, id[, options]): ';

@@ -64,11 +63,13 @@ /**

} else if (!utils.isString(id) && !utils.isNumber(id)) {
throw new errors.IllegalArgumentError('DS.refresh(resourceName, id): id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } });
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' } });
}
} else {
options.bypassCache = true;
if (id in services.store[resourceName].index) {
return this.find(resourceName, id, true);
} else {
return false;
if (id in services.store[resourceName].index) {
return this.find(resourceName, id, options);
} else {
return false;
}
}

@@ -75,0 +76,0 @@ }

var utils = require('utils'),
errors = require('errors'),
services = require('services'),
PUT = require('../../http').PUT,
errorPrefix = 'DS.save(resourceName, id[, options]): ';
function _save(deferred, resource, id, options) {
var _this = this;
var url = utils.makePath(resource.baseUrl || services.config.baseUrl, resource.endpoint || resource.name, id);
PUT(url, resource.index[id], null).then(function (data) {
var saved = _this.inject(resource.name, data, options);
resource.saved[id] = utils.updateTimestamp(resource.saved[id]);
deferred.resolve(saved);
}, deferred.reject);
}
/**

@@ -61,3 +50,4 @@ * @doc method

function save(resourceName, id, options) {
var deferred = $q.defer();
var deferred = services.$q.defer(),
promise = deferred.promise;

@@ -71,32 +61,41 @@ options = options || {};

} else if (!utils.isObject(options)) {
deferred.reject(new errors.IllegalArgumentError(errorPrefix + 'id: Must be an object!', { options: { actual: typeof options, expected: 'object' } }));
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!'));
} else {
var _this = this;
var resource = services.store[resourceName],
_this = this;
try {
var resource = services.store[resourceName];
promise = promise
.then(function (attrs) {
return services.$q.promisify(resource.beforeValidate)(resourceName, attrs);
})
.then(function (attrs) {
return services.$q.promisify(resource.validate)(resourceName, attrs);
})
.then(function (attrs) {
return services.$q.promisify(resource.afterValidate)(resourceName, attrs);
})
.then(function (attrs) {
return services.$q.promisify(resource.beforeUpdate)(resourceName, attrs);
})
.then(function (attrs) {
return services.adapters[resource.defaultAdapter].PUT(utils.makePath(resource.baseUrl, resource.endpoint, id), attrs, null);
})
.then(function (data) {
return services.$q.promisify(resource.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]);
return saved;
});
if (resource.schema) {
resource.schema.validate(resource.index[id], function (err) {
if (err) {
deferred.reject(err);
} else {
_save.call(_this, deferred, resource, id, options);
}
});
} else {
_save.call(_this, deferred, resource, id, options);
}
} catch (err) {
if (!(err instanceof errors.UnhandledError)) {
deferred.reject(new errors.UnhandledError(err));
} else {
deferred.reject(err);
}
}
deferred.resolve(resource.index[id]);
}
return deferred.promise;
return promise;
}
module.exports = save;
var utils = require('utils'),
errors = require('errors'),
IllegalArgumentError = errors.IllegalArgumentError,
services = require('services'),
errorPrefix = 'DSProvider.config(options): ';
HttpAdapter = require('HttpAdapter'),
configErrorPrefix = 'DSProvider.config(options): ',
registerAdapterErrorPrefix = 'DSProvider.registerAdapter(name, adapter): ';

@@ -22,3 +23,8 @@ /**

* DSProvider.config({
* baseUrl: 'http://myapp.com/api'
* baseUrl: 'http://myapp.com/api',
* idAttribute: '_id',
* validate: function (resourceName, attrs, cb) {
* console.log('looks good to me');
* cb(null, attrs);
* }
* });

@@ -31,3 +37,14 @@ * ```

*
* @param {object} options Configuration for the data store.
* @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)`.
*/

@@ -38,11 +55,73 @@ function config(options) {

if (!utils.isObject(options)) {
throw new IllegalArgumentError(errorPrefix + 'options: Must be an object!', { actual: typeof options, expected: 'object' });
} else if (!utils.isString(options.baseUrl)) {
throw new IllegalArgumentError(errorPrefix + 'options: Must be an object!', { baseUrl: { actual: typeof options, expected: 'object' } });
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' } });
}
utils.deepMixIn(services.config, options);
services.config = new services.BaseConfig(options);
}
/**
* @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) {
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;
}
/**
* @doc interface

@@ -64,2 +143,14 @@ * @id DSProvider

config({});
/**
* @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', '$http', '$q', function ($rootScope, $log, $http, $q) {

@@ -72,3 +163,6 @@

services.store = {};
services.adapters = {};
registerAdapter('HttpAdapter', HttpAdapter);
/**

@@ -81,10 +175,10 @@ * @doc interface

*/
var DS = {};
var DS = {
HttpAdapter: HttpAdapter,
errors: errors
};
utils.deepMixIn(DS, require('./http'));
utils.deepMixIn(DS, require('./sync_methods'));
utils.deepMixIn(DS, require('./async_methods'));
DS.errors = errors;
utils.deepFreeze(DS);

@@ -91,0 +185,0 @@

@@ -1,6 +0,70 @@

module.exports = {
config: {
idAttribute: 'id'
},
store: {}
function lifecycleNoop(resourceName, attrs, cb) {
cb(null, attrs);
}
var services = module.exports = {
store: {},
BaseConfig: function (options) {
if ('idAttribute' in options) {
this.idAttribute = options.idAttribute;
}
if ('baseUrl' in options) {
this.baseUrl = options.baseUrl;
}
if ('beforeValidate' in options) {
this.beforeValidate = options.beforeValidate;
}
if ('validate' in options) {
this.validate = options.validate;
}
if ('afterValidate' in options) {
this.afterValidate = options.afterValidate;
}
if ('beforeCreate' in options) {
this.beforeCreate = options.beforeCreate;
}
if ('afterCreate' in options) {
this.afterCreate = options.afterCreate;
}
if ('beforeUpdate' in options) {
this.beforeUpdate = options.beforeUpdate;
}
if ('afterUpdate' in options) {
this.afterUpdate = options.afterUpdate;
}
if ('beforeDestroy' in options) {
this.beforeDestroy = options.beforeDestroy;
}
if ('afterDestroy' in options) {
this.afterDestroy = options.afterDestroy;
}
if ('defaultAdapter' in options) {
this.defaultAdapter = options.defaultAdapter;
}
}
};
services.BaseConfig.prototype.idAttribute = 'id';
services.BaseConfig.prototype.defaultAdapter = 'HttpAdapter';
services.BaseConfig.prototype.baseUrl = '';
services.BaseConfig.prototype.endpoint = '';
services.BaseConfig.prototype.beforeValidate = lifecycleNoop;
services.BaseConfig.prototype.validate = lifecycleNoop;
services.BaseConfig.prototype.afterValidate = lifecycleNoop;
services.BaseConfig.prototype.beforeCreate = lifecycleNoop;
services.BaseConfig.prototype.afterCreate = lifecycleNoop;
services.BaseConfig.prototype.beforeUpdate = lifecycleNoop;
services.BaseConfig.prototype.afterUpdate = lifecycleNoop;
services.BaseConfig.prototype.beforeDestroy = lifecycleNoop;
services.BaseConfig.prototype.afterDestroy = lifecycleNoop;

@@ -48,3 +48,3 @@ var utils = require('utils'),

try {
return utils.deepMixIn({}, services.store[resourceName].changes[id]);
return angular.copy(services.store[resourceName].changes[id]);
} catch (err) {

@@ -51,0 +51,0 @@ throw new errors.UnhandledError(err);

@@ -6,2 +6,29 @@ var utils = require('utils'),

function Resource(options) {
services.BaseConfig.apply(this, [options]);
if ('name' in options) {
this.name = options.name;
}
if ('endpoint' in options) {
this.endpoint = options.endpoint;
} else {
this.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;
}
Resource.prototype = services.config;
/**

@@ -27,5 +54,5 @@ * @doc method

* baseUrl: 'http://myapp.com/api',
* validate: function (attrs, options, cb) {
* beforeDestroy: function (resourceName attrs, cb) {
* console.log('looks good to me');
* cb(null);
* cb(null, attrs);
* }

@@ -46,4 +73,12 @@ * });

* - `{string=}` - `endpoint` - The attribute that specifies the primary key for this resource. Default is the value of `name`.
* - `{string="/"}` - `baseUrl` - The url relative to which all AJAX requests will be made.
* - `{function=}` - `validate` - The validation function to be executed before create operations.
* - `{string=}` - `baseUrl` - The url relative to which all AJAX requests will be made.
* - `{function=}` - `beforeValidate` - Lifecycle hook. Overrides global. Signature: `beforeValidate(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`.
* - `{function=}` - `validate` - Lifecycle hook. Overrides global. Signature: `validate(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`.
* - `{function=}` - `afterValidate` - Lifecycle hook. Overrides global. Signature: `afterValidate(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`.
* - `{function=}` - `beforeCreate` - Lifecycle hook. Overrides global. Signature: `beforeCreate(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`.
* - `{function=}` - `afterCreate` - Lifecycle hook. Overrides global. Signature: `afterCreate(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`.
* - `{function=}` - `beforeUpdate` - Lifecycle hook. Overrides global. Signature: `beforeUpdate(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`.
* - `{function=}` - `afterUpdate` - Lifecycle hook. Overrides global. Signature: `afterUpdate(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`.
* - `{function=}` - `beforeDestroy` - Lifecycle hook. Overrides global. Signature: `beforeDestroy(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`.
* - `{function=}` - `afterDestroy` - Lifecycle hook. Overrides global. Signature: `afterDestroy(resourceName, attrs, cb)`. Callback signature: `cb(err, attrs)`.
*/

@@ -62,2 +97,4 @@ function defineResource(definition) {

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]) {

@@ -68,16 +105,3 @@ throw new errors.RuntimeError(errorPrefix + definition.name + ' is already registered!');

try {
services.store[definition.name] = definition;
var resource = services.store[definition.name];
resource.collection = [];
resource.completedQueries = {};
resource.pendingQueries = {};
resource.index = {};
resource.modified = {};
resource.changes = {};
resource.previous_attributes = {};
resource.saved = {};
resource.observers = {};
resource.collectionModified = 0;
resource.idAttribute = resource.idAttribute || services.config.idAttribute || 'id';
services.store[definition.name] = new Resource(definition);
} catch (err) {

@@ -84,0 +108,0 @@ delete services.store[definition.name];

@@ -8,15 +8,19 @@ var utils = require('utils'),

if (id) {
var found = false;
for (var i = 0; i < resource.collection.length; i++) {
if (resource.collection[i][resource.idAttribute || 'id'] == id) {
if (resource.collection[i][resource.idAttribute] == id) {
found = true;
break;
}
}
resource.collection.splice(i, 1);
resource.observers[id].close();
delete resource.observers[id];
delete resource.index[id];
delete resource.changes[id];
delete resource.previous_attributes[id];
delete resource.modified[id];
delete resource.saved[id];
if (found) {
resource.collection.splice(i, 1);
resource.observers[id].close();
delete resource.observers[id];
delete resource.index[id];
delete resource.changes[id];
delete resource.previous_attributes[id];
delete resource.modified[id];
delete resource.saved[id];
}
} else {

@@ -26,2 +30,5 @@ resource.collection = [];

resource.modified = {};
resource.saved = {};
resource.changes = {};
resource.previous_attributes = {};
}

@@ -72,3 +79,3 @@ resource.collectionModified = utils.updateTimestamp(resource.collectionModified);

* @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.
* @param {string|number} id The primary key of the item to eject.
* @param {string|number=} id The primary key of the item to eject.
*/

@@ -75,0 +82,0 @@ function eject(resourceName, id) {

@@ -51,3 +51,5 @@ var utils = require('utils'),

if (!(id in services.store[resourceName].index) && options.loadFromServer) {
this.find(resourceName, id);
this.find(resourceName, id).then(null, function (err) {
throw err;
});
}

@@ -54,0 +56,0 @@

@@ -7,5 +7,5 @@ var utils = require('utils'),

function diffIsEmpty(diff) {
return utils.isEmpty(diff.added) &&
return !(utils.isEmpty(diff.added) &&
utils.isEmpty(diff.removed) &&
utils.isEmpty(diff.changed);
utils.isEmpty(diff.changed));
}

@@ -55,3 +55,7 @@

// return resource from cache
return diffIsEmpty(services.store[resourceName].changes[id]);
if (id in services.store[resourceName].changes) {
return diffIsEmpty(services.store[resourceName].changes[id]);
} else {
return false;
}
} catch (err) {

@@ -58,0 +62,0 @@ throw new errors.UnhandledError(err);

@@ -10,2 +10,20 @@ var utils = require('utils'),

function _react(added, removed, changed, getOldValueFn) {
try {
var innerId = getOldValueFn(resource.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);
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 +
'" resource is now in an undefined (probably broken) state.');
}
} catch (err) {
throw new errors.UnhandledError(err);
}
}
if (utils.isArray(attrs)) {

@@ -16,34 +34,25 @@ for (var i = 0; i < attrs.length; i++) {

} else {
var id = attrs[resource.idAttribute || 'id'];
if (!(resource.idAttribute in attrs)) {
throw new errors.RuntimeError(errorPrefix + 'attrs: Must contain the property specified by `idAttribute`!');
} else {
var id = attrs[resource.idAttribute];
if (!(id in resource.index)) {
resource.index[id] = {};
resource.previous_attributes[id] = {};
if (!(id in resource.index)) {
resource.index[id] = {};
resource.previous_attributes[id] = {};
utils.deepMixIn(resource.index[id], attrs);
utils.deepMixIn(resource.previous_attributes[id], attrs);
utils.deepMixIn(resource.index[id], attrs);
utils.deepMixIn(resource.previous_attributes[id], attrs);
resource.collection.push(resource.index[id]);
resource.collection.push(resource.index[id]);
resource.observers[id] = new observe.ObjectObserver(resource.index[id], function (added, removed, changed, getOldValueFn) {
try {
var innerId = getOldValueFn(resource.idAttribute || 'id');
resource.observers[id] = new observe.ObjectObserver(resource.index[id], _react);
if (resource.index[innerId][resource.idAttribute || 'id'] != innerId) {
resource.index[innerId][resource.idAttribute || 'id'] = innerId;
services.$log.error('You cannot change the primary key of an object! Reverting change to primary key.');
}
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);
} catch (err) {
throw new errors.UnhandledError(err);
}
});
resource.observers[id].deliver();
} else {
utils.deepMixIn(resource.index[id], attrs);
resource.observers[id].deliver();
_react({}, {}, {}, function () {
return id;
});
} else {
utils.deepMixIn(resource.index[id], attrs);
resource.observers[id].deliver();
}
}

@@ -113,18 +122,17 @@ }

var idAttribute = resource.idAttribute || 'id';
if (!attrs[idAttribute]) {
throw new errors.RuntimeError(errorPrefix + 'attrs: Must contain the property specified by `idAttribute` in the resource definition!');
} else {
try {
if (!services.$rootScope.$$phase) {
services.$rootScope.$apply(function () {
_inject.apply(_this, [services.store[resourceName], attrs]);
});
} else {
try {
if (!services.$rootScope.$$phase) {
services.$rootScope.$apply(function () {
_inject.apply(_this, [services.store[resourceName], attrs]);
}
} catch (err) {
});
} else {
_inject.apply(_this, [services.store[resourceName], attrs]);
}
return attrs;
} catch (err) {
if (!(err instanceof errors.RuntimeError)) {
throw new errors.UnhandledError(err);
} else {
throw err;
}
return resource.index[attrs[idAttribute]];
}

@@ -131,0 +139,0 @@ }

@@ -44,3 +44,3 @@ var utils = require('utils'),

} else if (id && !utils.isString(id) && !utils.isNumber(id)) {
throw new errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or number!', { id: { actual: typeof id, expected: 'string|number' } });
throw new errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } });
}

@@ -47,0 +47,0 @@ try {

@@ -51,3 +51,3 @@ var utils = require('utils'),

} else if (id && !utils.isString(id) && !utils.isNumber(id)) {
throw new errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or number!', { id: { actual: typeof id, expected: 'string|number' } });
throw new errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } });
}

@@ -54,0 +54,0 @@ try {

@@ -43,5 +43,33 @@ (function (window, angular, undefined) {

angular.module('jmdobry.angular-data', ['ng'/*, 'jmdobry.binary-heap'*/]);
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);
}
});
try {
fn.apply(target || this, args);
} catch (err) {
deferred.reject(err);
}
return deferred.promise;
};
};
return $delegate;
});
}]);
angular.module('jmdobry.angular-data').provider('DS', require('./datastore'));
})(window, window.angular);

@@ -6,2 +6,3 @@ module.exports = {

isNumber: angular.isNumber,
isFunction: angular.isFunction,
isEmpty: require('mout/lang/isEmpty'),

@@ -8,0 +9,0 @@ toJson: angular.toJson,

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

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc