You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by sn...@apache.org on 2014/04/02 17:21:15 UTC

[10/41] git commit: Refactored individual modules for standard callback signature and updated tests

Refactored individual modules for standard callback signature and updated tests


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/da8ecfff
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/da8ecfff
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/da8ecfff

Branch: refs/pull/96/merge
Commit: da8ecfff19c930d5845a0d21a56f6529f81e9c05
Parents: 39fac0d
Author: ryan bridges <rb...@apigee.com>
Authored: Tue Apr 1 12:09:45 2014 -0400
Committer: ryan bridges <rb...@apigee.com>
Committed: Tue Apr 1 12:09:45 2014 -0400

----------------------------------------------------------------------
 sdks/html5-javascript/lib/Usergrid.js           | 171 ++--
 sdks/html5-javascript/lib/modules/Asset.js      |  71 +-
 sdks/html5-javascript/lib/modules/Client.js     | 462 +++++-----
 sdks/html5-javascript/lib/modules/Collection.js | 236 ++---
 sdks/html5-javascript/lib/modules/Counter.js    | 164 ++--
 sdks/html5-javascript/lib/modules/Entity.js     | 452 +++++-----
 sdks/html5-javascript/lib/modules/Error.js      | 112 +--
 sdks/html5-javascript/lib/modules/Folder.js     |  46 +-
 sdks/html5-javascript/lib/modules/Group.js      | 104 ++-
 sdks/html5-javascript/lib/modules/util/Ajax.js  |  16 +-
 sdks/html5-javascript/lib/modules/util/Event.js |   8 +-
 .../html5-javascript/lib/modules/util/Logger.js |  18 +-
 .../lib/modules/util/Promise.js                 |   5 +-
 sdks/html5-javascript/tests/mocha/test.js       |  77 +-
 sdks/html5-javascript/usergrid.js               | 884 +++++++++----------
 sdks/html5-javascript/usergrid.min.js           |   6 +-
 16 files changed, 1431 insertions(+), 1401 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/Usergrid.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/Usergrid.js b/sdks/html5-javascript/lib/Usergrid.js
index 5fb046a..5fed303 100644
--- a/sdks/html5-javascript/lib/Usergrid.js
+++ b/sdks/html5-javascript/lib/Usergrid.js
@@ -35,29 +35,31 @@ function extend(subClass, superClass) {
     subClass.prototype.constructor = subClass;
 
     subClass.superclass = superClass.prototype;
-    if(superClass.prototype.constructor == Object.prototype.constructor) {
+    if (superClass.prototype.constructor == Object.prototype.constructor) {
         superClass.prototype.constructor = superClass;
     }
     return subClass;
 }
-function propCopy(from, to){
-    for(var prop in from){
-        if(from.hasOwnProperty(prop)){
-            if("object"===typeof from[prop] && "object"===typeof to[prop]){
-                to[prop]=propCopy(from[prop], to[prop]);
-            }else{
-                to[prop]=from[prop];
+
+function propCopy(from, to) {
+    for (var prop in from) {
+        if (from.hasOwnProperty(prop)) {
+            if ("object" === typeof from[prop] && "object" === typeof to[prop]) {
+                to[prop] = propCopy(from[prop], to[prop]);
+            } else {
+                to[prop] = from[prop];
             }
         }
     }
     return to;
 }
-function NOOP(){}
+
+function NOOP() {}
 
 function isValidUrl(url) {
     if (!url) return false;
-    var doc, base, anchor, isValid=false;
-    try{
+    var doc, base, anchor, isValid = false;
+    try {
         doc = document.implementation.createHTMLDocument('');
         base = doc.createElement('base');
         base.href = base || window.lo;
@@ -65,15 +67,15 @@ function isValidUrl(url) {
         anchor = doc.createElement('a');
         anchor.href = url;
         doc.body.appendChild(anchor);
-        isValid=!(anchor.href === '')
-    }catch(e){
+        isValid = !(anchor.href === '')
+    } catch (e) {
         console.error(e);
-    }finally{
+    } finally {
         doc.head.removeChild(base);
         doc.body.removeChild(anchor);
-        base=null;
-        anchor=null;
-        doc=null;
+        base = null;
+        anchor = null;
+        doc = null;
         return isValid;
     }
 }
@@ -87,8 +89,9 @@ function isValidUrl(url) {
  * @returns {Boolean} true if string is uuid
  */
 var uuidValueRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
+
 function isUUID(uuid) {
-	return (!uuid)?false:uuidValueRegex.test(uuid);
+    return (!uuid) ? false : uuidValueRegex.test(uuid);
 }
 
 /*
@@ -101,14 +104,34 @@ function isUUID(uuid) {
  */
 function encodeParams(params) {
     var queryString;
-    if(params && Object.keys(params)){
+    if (params && Object.keys(params)) {
         queryString = [].slice.call(arguments)
-            .reduce(function(a, b) {return a.concat((b instanceof Array)?b:[b]);},[])
-            .filter(function(c){return "object"===typeof c})
-            .reduce(function(p,c){(!(c instanceof Array)) ? p= p.concat(Object.keys(c).map(function(key){return [key,c[key]]})): p.push(c); return p;},[])
-            .reduce(function(p,c){((c.length===2) ? p.push(c) : p= p.concat(c)); return p;},[])
-            .reduce(function(p,c){(c[1] instanceof Array) ? c[1].forEach(function(v){p.push([c[0],v])}): p.push(c); return p;},[])
-            .map(function(c){c[1]=encodeURIComponent(c[1]); return c.join('=')})
+            .reduce(function(a, b) {
+                return a.concat((b instanceof Array) ? b : [b]);
+            }, [])
+            .filter(function(c) {
+                return "object" === typeof c
+            })
+            .reduce(function(p, c) {
+                (!(c instanceof Array)) ? p = p.concat(Object.keys(c).map(function(key) {
+                    return [key, c[key]]
+                })) : p.push(c);
+                return p;
+            }, [])
+            .reduce(function(p, c) {
+                ((c.length === 2) ? p.push(c) : p = p.concat(c));
+                return p;
+            }, [])
+            .reduce(function(p, c) {
+                (c[1] instanceof Array) ? c[1].forEach(function(v) {
+                    p.push([c[0], v])
+                }) : p.push(c);
+                return p;
+            }, [])
+            .map(function(c) {
+                c[1] = encodeURIComponent(c[1]);
+                return c.join('=')
+            })
             .join('&');
     }
     return queryString;
@@ -124,7 +147,7 @@ function encodeParams(params) {
  *  @return {boolean} Returns true or false
  */
 function isFunction(f) {
-	return (f && f !== null && typeof(f) === 'function');
+    return (f && f !== null && typeof(f) === 'function');
 }
 
 /*
@@ -138,36 +161,38 @@ function isFunction(f) {
  *  @return Returns whatever would be returned by the callback. or false.
  */
 function doCallback(callback, params, context) {
-	var returnValue;
-	if (isFunction(callback)) {
-		if (!params) params = [];
-		if (!context) context = this;
-		params.push(context);
-		//try {
-			returnValue = callback.apply(context, params);
-		/*} catch (ex) {
+    var returnValue;
+    if (isFunction(callback)) {
+        if (!params) params = [];
+        if (!context) context = this;
+        params.push(context);
+        //try {
+        returnValue = callback.apply(context, params);
+        /*} catch (ex) {
 			if (console && console.error) {
 				console.error("Callback error:", ex);
 			}
 		}*/
-	}
-	return returnValue;
+    }
+    return returnValue;
 }
 
 //noinspection ThisExpressionReferencesGlobalObjectJS
 (function(global) {
-	var name = 'Usergrid', overwrittenName = global[name];
+    var name = 'Usergrid',
+        overwrittenName = global[name];
+    var VALID_REQUEST_METHODS = ['GET', 'POST', 'PUT', 'DELETE'];
 
     function Usergrid() {
         this.logger = new Logger(name);
     }
 
-    Usergrid.isValidEndpoint = function (endpoint) {
+    Usergrid.isValidEndpoint = function(endpoint) {
         //TODO actually implement this
         return true;
     };
-    var VALID_REQUEST_METHODS = ['GET', 'POST', 'PUT', 'DELETE'];
-    Usergrid.Request = function (method, endpoint, query_params, data, callback) {
+
+    Usergrid.Request = function(method, endpoint, query_params, data, callback) {
         var p = new Promise();
         /*
          Create a logger
@@ -177,7 +202,7 @@ function doCallback(callback, params, context) {
         /*
          Validate our input
          */
-        this.endpoint=endpoint+'?'+encodeParams(query_params);
+        this.endpoint = endpoint + '?' + encodeParams(query_params);
         this.method = method.toUpperCase();
         //this.query_params = query_params;
         this.data = ("object" === typeof data) ? JSON.stringify(data) : data;
@@ -194,25 +219,29 @@ function doCallback(callback, params, context) {
             throw new UsergridInvalidURIError("The provided endpoint is not valid: " + this.endpoint);
         }
         /* a callback to make the request */
-        var request=function () {return Ajax.request(this.method, this.endpoint, this.data)}.bind(this);
+        var request = function() {
+            return Ajax.request(this.method, this.endpoint, this.data)
+        }.bind(this);
         /* a callback to process the response */
-        var response=function (err, request) {return new Usergrid.Response(err, request)}.bind(this);
+        var response = function(err, request) {
+            return new Usergrid.Response(err, request)
+        }.bind(this);
         /* a callback to clean up and return data to the client */
-        var oncomplete=function (err, response) {
+        var oncomplete = function(err, response) {
             p.done(err, response);
             this.logger.info("REQUEST", err, response);
             doCallback(callback, [err, response]);
             this.logger.timeEnd("process request " + method + " " + endpoint);
         }.bind(this);
         /* and a promise to chain them all together */
-        Promise.chain([request,response]).then(oncomplete);
+        Promise.chain([request, response]).then(oncomplete);
 
         return p;
     };
     //TODO more granular handling of statusCodes
-    Usergrid.Response = function (err, response) {
+    Usergrid.Response = function(err, response) {
         var p = new Promise();
-        var data=null;
+        var data = null;
         try {
             data = JSON.parse(response.responseText);
         } catch (e) {
@@ -220,8 +249,11 @@ function doCallback(callback, params, context) {
             //this.logger.error("Caught error ", e.message);
             data = {}
         }
-        Object.keys(data).forEach(function(key){
-            Object.defineProperty(this, key, { value : data[key], enumerable:true });
+        Object.keys(data).forEach(function(key) {
+            Object.defineProperty(this, key, {
+                value: data[key],
+                enumerable: true
+            });
         }.bind(this));
         Object.defineProperty(this, "logger", {
             enumerable: false,
@@ -254,13 +286,13 @@ function doCallback(callback, params, context) {
             value: (this.status - this.status % 100)
         });
         switch (this.statusGroup) {
-            case 200:
+            case 200: //success
                 this.success = true;
                 break;
-            case 400:
-            case 500:
-            case 300:
-            case 100:
+            case 400: //user error
+            case 500: //server error
+            case 300: //cache and redirects
+            case 100: //upgrade
             default:
                 //server error
                 this.success = false;
@@ -273,28 +305,25 @@ function doCallback(callback, params, context) {
         }
         return p;
     };
-    Usergrid.Response.prototype.getEntities = function () {
-        var entities=[]
+    Usergrid.Response.prototype.getEntities = function() {
+        var entities;
         if (this.success) {
-            entities=(this.data)?this.data.entities:this.entities;
+            entities = (this.data) ? this.data.entities : this.entities;
         }
-        return entities;
+        return entities || [];
     }
-    Usergrid.Response.prototype.getEntity = function () {
-        var entities=this.getEntities();
+    Usergrid.Response.prototype.getEntity = function() {
+        var entities = this.getEntities();
         return entities[0];
     }
     Usergrid.VERSION = Usergrid.USERGRID_SDK_VERSION = '0.11.0';
 
-	global[name] =  Usergrid;
-	global[name].noConflict = function() {
-		if(overwrittenName){
-			global[name] = overwrittenName;
-		}
-		return Usergrid;
-	};
-	return global[name];
+    global[name] = Usergrid;
+    global[name].noConflict = function() {
+        if (overwrittenName) {
+            global[name] = overwrittenName;
+        }
+        return Usergrid;
+    };
+    return global[name];
 }(this));
-
-
-

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/Asset.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Asset.js b/sdks/html5-javascript/lib/modules/Asset.js
index c368427..b5bc68a 100644
--- a/sdks/html5-javascript/lib/modules/Asset.js
+++ b/sdks/html5-javascript/lib/modules/Asset.js
@@ -30,20 +30,23 @@ Usergrid.Asset = function(options, callback) {
 	self._client = options.client;
 	self._data = options.data || {};
 	self._data.type = "assets";
-	var missingData = ["name", "owner", "path"].some(function(required) { return !(required in self._data)});
-	if(missingData){
-		return doCallback(callback, [true, new UsergridError("Invalid asset data: 'name', 'owner', and 'path' are required properties.")], self);
-	}
-	self.save(function(err, data) {
-		if (err) {
-			doCallback(callback, [true, new UsergridError(data)], self);
-		} else {
-			if (data && data.entities && data.entities.length){
-				self.set(data.entities[0]);
-			}
-			doCallback(callback, [false, self], self);
-		}
+	var missingData = ["name", "owner", "path"].some(function(required) {
+		return !(required in self._data);
 	});
+	if (missingData) {
+		doCallback(callback, [new UsergridError("Invalid asset data: 'name', 'owner', and 'path' are required properties."), null, self], self);
+	} else {
+		self.save(function(err, data) {
+			if (err) {
+				doCallback(callback, [new UsergridError(data), data, self], self);
+			} else {
+				if (data && data.entities && data.entities.length) {
+					self.set(data.entities[0]);
+				}
+				doCallback(callback, [null, data, self], self);
+			}
+		});
+	}
 };
 
 /*
@@ -69,17 +72,26 @@ Usergrid.Asset.prototype.addToFolder = function(options, callback) {
 			uuid: options.folder
 		}, function(err, folder) {
 			if (err) {
-				return callback.call(self, err, folder);
+				doCallback(callback, [UsergridError.fromResponse(folder), folder, self], self);
+			} else {
+				var endpoint = ["folders", folder.get("uuid"), "assets", self.get("uuid")].join('/');
+				var options = {
+					method: 'POST',
+					endpoint: endpoint
+				};
+				this._client.request(options, function(err, response) {
+					if (err) {
+						doCallback(callback, [UsergridError.fromResponse(folder), response, self], self);
+					} else {
+						doCallback(callback, [null, folder, self], self);
+					}
+
+
+				});
 			}
-			var endpoint = ["folders", folder.get("uuid"), "assets", self.get("uuid")].join('/');
-			var options = {
-				method: 'POST',
-				endpoint: endpoint
-			};
-			this._client.request(options, callback);
 		});
 	} else {
-		doCallback(callback, [true, new UsergridError('folder not specified')], self);
+		doCallback(callback, [new UsergridError('folder not specified'), null, self], self);
 	}
 };
 
@@ -93,7 +105,8 @@ Usergrid.Asset.prototype.addToFolder = function(options, callback) {
  */
 Usergrid.Asset.prototype.upload = function(data, callback) {
 	if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
-		return doCallback(callback, [true, new UsergridError('The File APIs are not fully supported by your browser.')], self);
+		doCallback(callback, [new UsergridError('The File APIs are not fully supported by your browser.'), null, this], this);
+		return;
 	}
 	var self = this;
 	var endpoint = [this._client.URI, this._client.orgName, this._client.appName, "assets", self.get("uuid"), 'data'].join('/'); //self._client.buildAssetURL(self.get("uuid"));
@@ -102,13 +115,13 @@ Usergrid.Asset.prototype.upload = function(data, callback) {
 	xhr.open("POST", endpoint, true);
 	xhr.onerror = function(err) {
 		//callback(true, err);
-		doCallback(callback, [true, new UsergridError('The File APIs are not fully supported by your browser.')], self)
+		doCallback(callback, [true, new UsergridError('The File APIs are not fully supported by your browser.')], self);
 	};
 	xhr.onload = function(ev) {
 		if (xhr.status >= 300) {
-			doCallback(callback, [true, new UsergridError(JSON.parse(xhr.responseText))], self)
+			doCallback(callback, [new UsergridError(JSON.parse(xhr.responseText)), null, self], self);
 		} else {
-			doCallback(callback, [null, self], self)
+			doCallback(callback, [null, xhr, self], self);
 		}
 	};
 	var fr = new FileReader();
@@ -120,7 +133,7 @@ Usergrid.Asset.prototype.upload = function(data, callback) {
 		}, 1000);
 	};
 	fr.readAsBinaryString(data);
-}
+};
 
 /*
  *  Download Asset data
@@ -138,12 +151,12 @@ Usergrid.Asset.prototype.download = function(callback) {
 	xhr.onload = function(ev) {
 		var blob = xhr.response;
 		//callback(null, blob);
-		doCallback(callback, [false, blob], self)
+		doCallback(callback, [null, blob, self], self);
 	};
 	xhr.onerror = function(err) {
 		callback(true, err);
-		doCallback(callback, [true, new UsergridError(err)], self)
+		doCallback(callback, [new UsergridError(err), err, self], self);
 	};
 
 	xhr.send();
-}
+};

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/Client.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Client.js b/sdks/html5-javascript/lib/modules/Client.js
index 655b025..d9ab1b2 100644
--- a/sdks/html5-javascript/lib/modules/Client.js
+++ b/sdks/html5-javascript/lib/modules/Client.js
@@ -1,6 +1,16 @@
 (function() {
-  var name = 'Client', global = this, overwrittenName = global[name], exports;
-
+  var name = 'Client',
+    global = this,
+    overwrittenName = global[name],
+    exports;
+  var AUTH_ERRORS = [
+    "auth_expired_session_token",
+    "auth_missing_credentials",
+    "auth_unverified_oath",
+    "expired_token",
+    "unauthorized",
+    "auth_invalid"
+  ];
   Usergrid.Client = function(options) {
     //usergrid endpoint
     this.URI = options.URI || 'https://api.usergrid.com';
@@ -12,7 +22,7 @@
     if (options.appName) {
       this.set('appName', options.appName);
     }
-    if(options.qs){
+    if (options.qs) {
       this.setObject('default_qs', options.qs);
     }
     //other options
@@ -20,9 +30,7 @@
     this.logging = options.logging || false;
 
     //timeout and callbacks
-    this._callTimeout =  options.callTimeout || 30000; //default to 30 seconds
-    this._callTimeoutCallback =  options.callTimeoutCallback || null;
-    this.logoutCallback =  options.logoutCallback || null;
+    // this.logoutCallback =  options.logoutCallback || null;
   };
 
   /*
@@ -41,8 +49,7 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-  Usergrid.Client.prototype.request = function (options, callback) {
-    var self = this;
+  Usergrid.Client.prototype.request = function(options, callback) {
     var method = options.method || 'GET';
     var endpoint = options.endpoint;
     var body = options.body || {};
@@ -50,15 +57,15 @@
     var mQuery = options.mQuery || false; //is this a query to the management endpoint?
     var orgName = this.get('orgName');
     var appName = this.get('appName');
-    var default_qs=this.getObject('default_qs');
+    var default_qs = this.getObject('default_qs');
     var uri;
-      var logoutCallback=function(){
-          if (typeof(this.logoutCallback) === 'function') {
-              return this.logoutCallback(true, 'no_org_or_app_name_specified');
-          }
-      }.bind(this);
-    if(!mQuery && !orgName && !appName){
-        return logoutCallback();
+    /*var logoutCallback=function(){
+        if (typeof(this.logoutCallback) === 'function') {
+            return this.logoutCallback(true, 'no_org_or_app_name_specified');
+        }
+    }.bind(this);*/
+    if (!mQuery && !orgName && !appName) {
+      return logoutCallback();
     }
     if (mQuery) {
       uri = this.URI + '/' + endpoint;
@@ -67,29 +74,29 @@
     }
     if (this.getToken()) {
       qs.access_token = this.getToken();
-      /* //could also use headers for the token
+      /*
+       **NOTE** The token can also be passed as a header on the request
+
        xhr.setRequestHeader("Authorization", "Bearer " + self.getToken());
        xhr.withCredentials = true;
        */
     }
-    if(default_qs){
-      qs=propCopy(qs, default_qs);
+    if (default_qs) {
+      qs = propCopy(qs, default_qs);
     }
-      var req = new Usergrid.Request(method, uri, qs, body, function (err, response) {
-          if ([
-              "auth_expired_session_token",
-              "auth_missing_credentials",
-              "auth_unverified_oath",
-              "expired_token",
-              "unauthorized",
-              "auth_invalid"
-          ].indexOf(response.error) !== -1) {
-              return logoutCallback();
-          }
-          doCallback(callback, [err, response]);
-          //p.done(err, response);
-      });
-  }
+    var self=this;
+    var req = new Usergrid.Request(method, uri, qs, body, function(err, response) {
+      /*if (AUTH_ERRORS.indexOf(response.error) !== -1) {
+            return logoutCallback();
+        }*/
+      if(err){
+        doCallback(callback, [err, response, self], self);
+      }else{
+        doCallback(callback, [null, response, self], self);
+      }
+      //p.done(err, response);
+    });
+  };
 
   /*
    *  function for building asset urls
@@ -127,15 +134,13 @@
    *  @return {callback} callback(err, data)
    */
   Usergrid.Client.prototype.createGroup = function(options, callback) {
-    options = {
+    var group = new Usergrid.Group({
       path: options.path,
       client: this,
       data: options
-    };
-
-    var group = new Usergrid.Group(options);
-    group.save(function(err, data){
-        doCallback(callback, [err, group, data]);
+    });
+    group.save(function(err, response) {
+      doCallback(callback, [err, response, group], group);
     });
   };
 
@@ -150,17 +155,15 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-    Usergrid.Client.prototype.createEntity = function (options, callback) {
-        var entity_data = {
-            client: this,
-            data: options
-        };
-        var entity = new Usergrid.Entity(entity_data);
-        var self = this;
-        entity.save(function (err, data) {
-            doCallback(callback, [err, entity, data]);
-        });
-    };
+  Usergrid.Client.prototype.createEntity = function(options, callback) {
+    var entity = new Usergrid.Entity({
+      client: this,
+      data: options
+    });
+    entity.save(function(err, response) {
+      doCallback(callback, [err, response, entity], entity);
+    });
+  };
   /*
    *  Main function for getting existing entities - should be called directly.
    *
@@ -175,14 +178,13 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-  Usergrid.Client.prototype.getEntity = function (options, callback) {
-    var options = {
-      client:this,
-      data:options
-    }
-    var entity = new Usergrid.Entity(options);
-    entity.fetch(function(err, data) {
-        doCallback(callback, [err, entity, data]);
+  Usergrid.Client.prototype.getEntity = function(options, callback) {
+    var entity = new Usergrid.Entity({
+      client: this,
+      data: options
+    });
+    entity.fetch(function(err, response) {
+      doCallback(callback, [err, response, entity], entity);
     });
   };
 
@@ -196,12 +198,12 @@
    *  @param {string} serializedObject
    *  @return {object} Entity Object
    */
-  Usergrid.Client.prototype.restoreEntity = function (serializedObject) {
+  Usergrid.Client.prototype.restoreEntity = function(serializedObject) {
     var data = JSON.parse(serializedObject);
     var options = {
-      client:this,
-      data:data
-    }
+      client: this,
+      data: data
+    };
     var entity = new Usergrid.Entity(options);
     return entity;
   };
@@ -217,10 +219,11 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-  Usergrid.Client.prototype.createCollection = function (options, callback) {
+  Usergrid.Client.prototype.createCollection = function(options, callback) {
     options.client = this;
-    new Usergrid.Collection(options, function(err, data, collection) {
-        doCallback(callback, [err, collection, data]);
+    var collection = new Usergrid.Collection(options);
+    collection.fetch(function(err, response, collection) {
+      doCallback(callback, [err, response, collection], this);
     });
   };
 
@@ -234,7 +237,7 @@
    *  @param {string} serializedObject
    *  @return {object} Collection Object
    */
-  Usergrid.Client.prototype.restoreCollection = function (serializedObject) {
+  Usergrid.Client.prototype.restoreCollection = function(serializedObject) {
     var data = JSON.parse(serializedObject);
     data.client = this;
     var collection = new Usergrid.Collection(data);
@@ -253,15 +256,15 @@
   Usergrid.Client.prototype.getFeedForUser = function(username, callback) {
     var options = {
       method: "GET",
-      endpoint: "users/"+username+"/feed"
+      endpoint: "users/" + username + "/feed"
     };
 
-    this.request(options, function(err, data){
-        if(err) {
-            doCallback(callback, [err]);
-        } else {
-            doCallback(callback, [err, data, data.getEntities()]);
-        }
+    this.request(options, function(err, data) {
+      if (err) {
+        doCallback(callback, [err]);
+      } else {
+        doCallback(callback, [err, data, data.getEntities()]);
+      }
     });
   };
 
@@ -300,15 +303,15 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-  Usergrid.Client.prototype.createUserActivity = function (user, options, callback) {
-    options.type = 'users/'+user+'/activities';
-    var options = {
-      client:this,
-      data:options
-    }
+  Usergrid.Client.prototype.createUserActivity = function(user, options, callback) {
+    options.type = 'users/' + user + '/activities';
+    options = {
+      client: this,
+      data: options
+    };
     var entity = new Usergrid.Entity(options);
     entity.save(function(err, data) {
-        doCallback(callback, [err, entity]);
+      doCallback(callback, [err, data, entity]);
     });
   };
 
@@ -329,20 +332,20 @@
     var username = user.get("username");
     var options = {
       actor: {
-        "displayName":username,
-        "uuid":user.get("uuid"),
-        "username":username,
-        "email":user.get("email"),
-        "picture":user.get("picture"),
+        "displayName": username,
+        "uuid": user.get("uuid"),
+        "username": username,
+        "email": user.get("email"),
+        "picture": user.get("picture"),
         "image": {
-          "duration":0,
-          "height":80,
-          "url":user.get("picture"),
-          "width":80
+          "duration": 0,
+          "height": 80,
+          "url": user.get("picture"),
+          "width": 80
         }
       },
-      "verb":"post",
-      "content":content
+      "verb": "post",
+      "content": content
     };
 
     this.createUserActivity(username, options, callback);
@@ -352,12 +355,12 @@
   /*
    *  A private method to get call timing of last call
    */
-  Usergrid.Client.prototype.calcTimeDiff = function () {
+  Usergrid.Client.prototype.calcTimeDiff = function() {
     var seconds = 0;
     var time = this._end - this._start;
     try {
-      seconds = ((time/10) / 60).toFixed(2);
-    } catch(e) {
+      seconds = ((time / 10) / 60).toFixed(2);
+    } catch (e) {
       return 0;
     }
     return seconds;
@@ -371,7 +374,7 @@
    *  @params {string} token
    *  @return none
    */
-  Usergrid.Client.prototype.setToken = function (token) {
+  Usergrid.Client.prototype.setToken = function(token) {
     this.set('token', token);
   };
 
@@ -382,7 +385,7 @@
    *  @public
    *  @return {string} token
    */
-  Usergrid.Client.prototype.getToken = function () {
+  Usergrid.Client.prototype.getToken = function() {
     return this.get('token');
   };
 
@@ -393,10 +396,10 @@
     this.set(key, value);
   };
 
-  Usergrid.Client.prototype.set = function (key, value) {
-    var keyStore =  'apigee_' + key;
+  Usergrid.Client.prototype.set = function(key, value) {
+    var keyStore = 'apigee_' + key;
     this[key] = value;
-    if(typeof(Storage)!=="undefined"){
+    if (typeof(Storage) !== "undefined") {
       if (value) {
         localStorage.setItem(keyStore, value);
       } else {
@@ -409,15 +412,15 @@
     return JSON.parse(this.get(key));
   };
 
-  Usergrid.Client.prototype.get = function (key) {
+  Usergrid.Client.prototype.get = function(key) {
     var keyStore = 'apigee_' + key;
-    var value=null;
+    var value = null;
     if (this[key]) {
-      value= this[key];
-    } else if(typeof(Storage)!=="undefined") {
-      value= localStorage.getItem(keyStore);
+      value = this[key];
+    } else if (typeof(Storage) !== "undefined") {
+      value = localStorage.getItem(keyStore);
     }
-    return value  ;
+    return value;
   };
 
   /*
@@ -435,11 +438,11 @@
   Usergrid.Client.prototype.signup = function(username, password, email, name, callback) {
     var self = this;
     var options = {
-      type:"users",
-      username:username,
-      password:password,
-      email:email,
-      name:name
+      type: "users",
+      username: username,
+      password: password,
+      email: email,
+      name: name
     };
 
     this.createEntity(options, callback);
@@ -456,12 +459,12 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-  Usergrid.Client.prototype.login = function (username, password, callback) {
+  Usergrid.Client.prototype.login = function(username, password, callback) {
     var self = this;
     var options = {
-      method:'POST',
-      endpoint:'token',
-      body:{
+      method: 'POST',
+      endpoint: 'token',
+      body: {
         username: username,
         password: password,
         grant_type: 'password'
@@ -470,11 +473,11 @@
     self.request(options, function(err, data) {
       var user = {};
       if (err) {
-        if(self.logging)console.log('error trying to log user in');
+        if (self.logging) console.log('error trying to log user in');
       } else {
         var options = {
-          client:self,
-          data:data.user
+          client: self,
+          data: data.user
         };
         user = new Usergrid.Entity(options);
         self.setToken(data.access_token);
@@ -484,12 +487,12 @@
   };
 
 
-  Usergrid.Client.prototype.reAuthenticateLite = function (callback) {
+  Usergrid.Client.prototype.reAuthenticateLite = function(callback) {
     var self = this;
     var options = {
-      method:'GET',
-      endpoint:'management/me',
-      mQuery:true
+      method: 'GET',
+      endpoint: 'management/me',
+      mQuery: true
     };
     this.request(options, function(err, response) {
       if (err && self.logging) {
@@ -497,21 +500,21 @@
       } else {
 
         //save the re-authed token and current email/username
-          self.setToken(response.data.access_token);
+        self.setToken(response.data.access_token);
 
       }
-        doCallback(callback, [err]);
+      doCallback(callback, [err]);
 
     });
   };
 
 
-  Usergrid.Client.prototype.reAuthenticate = function (email, callback) {
+  Usergrid.Client.prototype.reAuthenticate = function(email, callback) {
     var self = this;
     var options = {
-      method:'GET',
-      endpoint:'management/users/'+email,
-      mQuery:true
+      method: 'GET',
+      endpoint: 'management/users/' + email,
+      mQuery: true
     };
     this.request(options, function(err, response) {
       var organizations = {};
@@ -533,14 +536,14 @@
 
 
         var userData = {
-          "username" : data.username,
-          "email" : data.email,
-          "name" : data.name,
-          "uuid" : data.uuid
+          "username": data.username,
+          "email": data.email,
+          "name": data.name,
+          "uuid": data.uuid
         };
         var options = {
-          client:self,
-          data:userData
+          client: self,
+          data: userData
         };
         user = new Usergrid.Entity(options);
 
@@ -549,9 +552,9 @@
         try {
           //if we have an org stored, then use that one. Otherwise, use the first one.
           var existingOrg = self.get('orgName');
-          org = (organizations[existingOrg])?organizations[existingOrg]:organizations[Object.keys(organizations)[0]];
+          org = (organizations[existingOrg]) ? organizations[existingOrg] : organizations[Object.keys(organizations)[0]];
           self.set('orgName', org.name);
-        } catch(e) {
+        } catch (e) {
           err = true;
           if (self.logging) {
             console.log('error selecting org');
@@ -579,12 +582,12 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-  Usergrid.Client.prototype.loginFacebook = function (facebookToken, callback) {
+  Usergrid.Client.prototype.loginFacebook = function(facebookToken, callback) {
     var self = this;
     var options = {
-      method:'GET',
-      endpoint:'auth/facebook',
-      qs:{
+      method: 'GET',
+      endpoint: 'auth/facebook',
+      qs: {
         fb_access_token: facebookToken
       }
     };
@@ -596,7 +599,7 @@
         var options = {
           client: self,
           data: data.user
-        }
+        };
         user = new Usergrid.Entity(options);
         self.setToken(data.access_token);
       }
@@ -612,14 +615,14 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-  Usergrid.Client.prototype.getLoggedInUser = function (callback) {
+  Usergrid.Client.prototype.getLoggedInUser = function(callback) {
     if (!this.getToken()) {
       callback(true, null, null);
     } else {
       var self = this;
       var options = {
-        method:'GET',
-        endpoint:'users/me'
+        method: 'GET',
+        endpoint: 'users/me'
       };
       this.request(options, function(err, data) {
         if (err) {
@@ -629,8 +632,8 @@
           doCallback(callback, [err, data, null], self);
         } else {
           var options = {
-            client:self,
-            data:data.entities[0]
+            client: self,
+            data: data.entities[0]
           };
           var user = new Usergrid.Entity(options);
           doCallback(callback, [null, data, user], self);
@@ -647,9 +650,9 @@
    *  @public
    *  @return {boolean} Returns true the user is logged in (has token and uuid), false if not
    */
-  Usergrid.Client.prototype.isLoggedIn = function () {
-      var token=this.getToken();
-    return "undefined" !== typeof token && token!==null;
+  Usergrid.Client.prototype.isLoggedIn = function() {
+    var token = this.getToken();
+    return "undefined" !== typeof token && token !== null;
   };
 
   /*
@@ -659,74 +662,74 @@
    *  @public
    *  @return none
    */
-  Usergrid.Client.prototype.logout = function () {
+  Usergrid.Client.prototype.logout = function() {
     this.setToken();
   };
 
-    /*
-    *  A public method to destroy access tokens on the server
-    *
-    *  @method logout
-    *  @public    
-    *	 @param {string} username	the user associated with the token to revoke
-    *	 @param {string} token set to 'null' to revoke the token of the currently logged in user 
-    *  	 or set to token value to revoke a specific token
-    *	 @param {string} revokeAll set to 'true' to revoke all tokens for the user            
-    *  @return none
-    */
-		Usergrid.Client.prototype.destroyToken = function (username, token, revokeAll, callback) {
-      var options = {
-	        client:self,
-	        method:'PUT',	        
-				}
-				
-      if (revokeAll == true) {
-				options.endpoint = 'users/'+username+'/revoketokens';
-			} else if (token == null) {
-				options.endpoint = 'users/'+username+'/revoketoken?token='+this.getToken();
-			} else {
-				options.endpoint = 'users/'+username+'/revoketoken?token='+token;
-			}
-      this.request(options, function(err,data) {
-		    if (err) {
-	          if (self.logging) {
-	            console.log('error destroying access token');
-	          }
-	          doCallback(callback, [err, data, null], self);
-	        } else {
-	          if (revokeAll == true) {
-	            console.log('all user tokens invalidated');
-	          } else {
-							console.log('token invalidated');
-	          }
-	          doCallback(callback, [err, data, null], self);
-	        }
-      });
-	  };
-  
-    /*
-    *  A public method to log out an app user - clears all user fields from client
-    *  and destroys the access token on the server.
-    *
-    *  @method logout
-    *  @public
-    *	 @param {string} username the user associated with the token to revoke
-    *	 @param {string} token set to 'null' to revoke the token of the currently logged in user 
-    *  	 or set to token value to revoke a specific token
-    *	 @param {string} revokeAll set to 'true' to revoke all tokens for the user        
-    *  @return none
-    */
-    Usergrid.Client.prototype.logoutAndDestroyToken = function(username, token, revokeAll, callback) {
-			if (username == null) {
-				console.log('username required to revoke tokens');
-			} else {
-				this.destroyToken(username, token, revokeAll, callback);
-				if (revokeAll == true || token == this.getToken() || token == null) {
-		    	this.setToken(null);
-		    }
-		  }
+  /*
+   *  A public method to destroy access tokens on the server
+   *
+   *  @method logout
+   *  @public
+   *  @param {string} username	the user associated with the token to revoke
+   *  @param {string} token set to 'null' to revoke the token of the currently logged in user
+   *    or set to token value to revoke a specific token
+   *  @param {string} revokeAll set to 'true' to revoke all tokens for the user
+   *  @return none
+   */
+  Usergrid.Client.prototype.destroyToken = function(username, token, revokeAll, callback) {
+    var options = {
+      client: self,
+      method: 'PUT',
     };
 
+    if (revokeAll === true) {
+      options.endpoint = 'users/' + username + '/revoketokens';
+    } else if (token === null) {
+      options.endpoint = 'users/' + username + '/revoketoken?token=' + this.getToken();
+    } else {
+      options.endpoint = 'users/' + username + '/revoketoken?token=' + token;
+    }
+    this.request(options, function(err, data) {
+      if (err) {
+        if (self.logging) {
+          console.log('error destroying access token');
+        }
+        doCallback(callback, [err, data, null], self);
+      } else {
+        if (revokeAll === true) {
+          console.log('all user tokens invalidated');
+        } else {
+          console.log('token invalidated');
+        }
+        doCallback(callback, [err, data, null], self);
+      }
+    });
+  };
+
+  /*
+   *  A public method to log out an app user - clears all user fields from client
+   *  and destroys the access token on the server.
+   *
+   *  @method logout
+   *  @public
+   *  @param {string} username the user associated with the token to revoke
+   *  @param {string} token set to 'null' to revoke the token of the currently logged in user
+   *   or set to token value to revoke a specific token
+   *  @param {string} revokeAll set to 'true' to revoke all tokens for the user
+   *  @return none
+   */
+  Usergrid.Client.prototype.logoutAndDestroyToken = function(username, token, revokeAll, callback) {
+    if (username === null) {
+      console.log('username required to revoke tokens');
+    } else {
+      this.destroyToken(username, token, revokeAll, callback);
+      if (revokeAll === true || token === this.getToken() || token === null) {
+        this.setToken(null);
+      }
+    }
+  };
+
   /*
    *  A private method to build the curl call to display on the command line
    *
@@ -735,7 +738,7 @@
    *  @param {object} options
    *  @return {string} curl
    */
-  Usergrid.Client.prototype.buildCurlCall = function (options) {
+  Usergrid.Client.prototype.buildCurlCall = function(options) {
     var curl = ['curl'];
     var method = (options.method || 'GET').toUpperCase();
     var body = options.body;
@@ -743,44 +746,43 @@
 
     //curl - add the method to the command (no need to add anything for GET)
     curl.push('-X');
-    curl.push((['POST','PUT','DELETE'].indexOf(method)>=0)?method:'GET');
+    curl.push((['POST', 'PUT', 'DELETE'].indexOf(method) >= 0) ? method : 'GET');
 
     //curl - append the path
     curl.push(uri);
 
-    if("object"===typeof body && Object.keys(body).length>0 && ['POST','PUT'].indexOf(method)!==-1){
+    if ("object" === typeof body && Object.keys(body).length > 0 && ['POST', 'PUT'].indexOf(method) !== -1) {
       curl.push('-d');
-      curl.push("'"+JSON.stringify(body)+"'");
+      curl.push("'" + JSON.stringify(body) + "'");
     }
-    curl=curl.join(' ');
+    curl = curl.join(' ');
     //log the curl command to the console
     console.log(curl);
 
     return curl;
-  }
+  };
 
-  Usergrid.Client.prototype.getDisplayImage = function (email, picture, size) {
-      size = size || 50;
-      var image='https://apigee.com/usergrid/images/user_profile.png';
+  Usergrid.Client.prototype.getDisplayImage = function(email, picture, size) {
+    size = size || 50;
+    var image = 'https://apigee.com/usergrid/images/user_profile.png';
     try {
       if (picture) {
-        image= picture;
-      }else if (email.length) {
-        image= 'https://secure.gravatar.com/avatar/' + MD5(email) + '?s=' + size + encodeURI("&d=https://apigee.com/usergrid/images/user_profile.png");
+        image = picture;
+      } else if (email.length) {
+        image = 'https://secure.gravatar.com/avatar/' + MD5(email) + '?s=' + size + encodeURI("&d=https://apigee.com/usergrid/images/user_profile.png");
       }
-    } catch(e) {
+    } catch (e) {
       //TODO do something with this error?
-    }finally{
+    } finally {
       return image;
     }
-  }
-  global[name] =  Usergrid.Client;
+  };
+  global[name] = Usergrid.Client;
   global[name].noConflict = function() {
-    if(overwrittenName){
+    if (overwrittenName) {
       global[name] = overwrittenName;
     }
     return exports;
   };
   return global[name];
 }());
-

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/Collection.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Collection.js b/sdks/html5-javascript/lib/modules/Collection.js
index 75affaa..8233863 100644
--- a/sdks/html5-javascript/lib/modules/Collection.js
+++ b/sdks/html5-javascript/lib/modules/Collection.js
@@ -1,4 +1,3 @@
-
 /*
  *  The Collection class models Usergrid Collections.  It essentially
  *  acts as a container for holding Entity objects, while providing
@@ -6,10 +5,9 @@
  *
  *  @constructor
  *  @param {string} options - configuration object
- *  @param {function} callback
- *  @return {callback} callback(err, data)
+ *  @return {Collection} collection
  */
-Usergrid.Collection = function(options, callback) {
+Usergrid.Collection = function(options) {
 
   if (options) {
     this._client = options.client;
@@ -28,17 +26,17 @@ Usergrid.Collection = function(options, callback) {
     //restore entities if available
     if (options.list) {
       var count = options.list.length;
-      for(var i=0;i<count;i++){
+      for (var i = 0; i < count; i++) {
         //make new entity with
         var entity = this._client.restoreEntity(options.list[i]);
         this._list[i] = entity;
       }
     }
   }
-  if (callback) {
+  /*if (callback) {
     //populate the collection
     this.fetch(callback);
-  }
+  }*/
 
 };
 
@@ -51,9 +49,9 @@ Usergrid.Collection = function(options, callback) {
  *  @params {any} obj - any variable
  *  @return {boolean} Returns true or false
  */
-Usergrid.isCollection = function(obj){
+Usergrid.isCollection = function(obj) {
   return (obj && obj instanceof Usergrid.Collection);
-}
+};
 
 
 /*
@@ -62,10 +60,10 @@ Usergrid.isCollection = function(obj){
  *  @method serialize
  *  @return {object} data
  */
-Usergrid.Collection.prototype.serialize = function () {
+Usergrid.Collection.prototype.serialize = function() {
 
   //pull out the state from this object and return it
-  var data = {}
+  var data = {};
   data.type = this._type;
   data.qs = this.qs;
   data.iterator = this._iterator;
@@ -74,9 +72,9 @@ Usergrid.Collection.prototype.serialize = function () {
   data.cursor = this._cursor;
 
   this.resetEntityPointer();
-  var i=0;
+  var i = 0;
   data.list = [];
-  while(this.hasNextEntity()) {
+  while (this.hasNextEntity()) {
     var entity = this.getNextEntity();
     data.list[i] = entity.serialize();
     i++;
@@ -85,8 +83,8 @@ Usergrid.Collection.prototype.serialize = function () {
   data = JSON.stringify(data);
   return data;
 };
-
-Usergrid.Collection.prototype.addCollection = function (collectionName, options, callback) {
+//addCollection is deprecated?
+/*Usergrid.Collection.prototype.addCollection = function (collectionName, options, callback) {
   self = this;
   options.client = this._client;
   var collection = new Usergrid.Collection(options, function(err, data) {
@@ -104,7 +102,7 @@ Usergrid.Collection.prototype.addCollection = function (collectionName, options,
       doCallback(callback, [err, collection], self);
     }
   });
-};
+};*/
 
 /*
  *  Populates the collection from the server
@@ -113,7 +111,7 @@ Usergrid.Collection.prototype.addCollection = function (collectionName, options,
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
-Usergrid.Collection.prototype.fetch = function (callback) {
+Usergrid.Collection.prototype.fetch = function(callback) {
   var self = this;
   var qs = this.qs;
 
@@ -124,44 +122,33 @@ Usergrid.Collection.prototype.fetch = function (callback) {
     delete qs.cursor;
   }
   var options = {
-    method:'GET',
-    endpoint:this._type,
-    qs:this.qs
+    method: 'GET',
+    endpoint: this._type,
+    qs: this.qs
   };
-  this._client.request(options, function (err, data) {
-    if(err && self._client.logging) {
+  this._client.request(options, function(err, response) {
+    if (err && self._client.logging) {
       console.log('error getting collection');
     } else {
       //save the cursor if there is one
-      var cursor = data.cursor || null;
-      self.saveCursor(cursor);
-      if (data.entities) {
-        self.resetEntityPointer();
-        var count = data.entities.length;
-        //save entities locally
-        self._list = []; //clear the local list first
-        for (var i=0;i<count;i++) {
-          var uuid = data.entities[i].uuid;
-          if (uuid) {
-            var entityData = data.entities[i] || {};
-            self._baseType = data.entities[i].type; //store the base type in the collection
-            entityData.type = self._type;//make sure entities are same type (have same path) as parent collection.
-            var entityOptions = {
-              type:self._type,
-              client:self._client,
-              uuid:uuid,
-              data:entityData
-            };
-
-            var ent = new Usergrid.Entity(entityOptions);
-            ent._json = JSON.stringify(entityData, null, 2);
-            var ct = self._list.length;
-            self._list[ct] = ent;
-          }
-        }
-      }
+      self.saveCursor(response.cursor || null);
+      self.resetEntityPointer();
+      //save entities locally
+      self._list = response.getEntities()
+        .filter(function(entity) {
+          return isUUID(entity.uuid);
+        })
+        .map(function(entity) {
+          var ent = new Usergrid.Entity({
+            client: self._client
+          });
+          ent.set(entity);
+          ent.type = self._type;
+          //ent._json = JSON.stringify(entity, null, 2);
+          return ent;
+        });
     }
-    doCallback(callback, [err, data], self);
+    doCallback(callback, [err, response, self], self);
   });
 };
 
@@ -173,22 +160,21 @@ Usergrid.Collection.prototype.fetch = function (callback) {
  *  @param {function} callback
  *  @return {callback} callback(err, data, entity)
  */
-Usergrid.Collection.prototype.addEntity = function (options, callback) {
+Usergrid.Collection.prototype.addEntity = function(entityObject, callback) {
   var self = this;
-  options.type = this._type;
+  entityObject.type = this._type;
 
   //create the new entity
-  this._client.createEntity(options, function (err, entity) {
+  this._client.createEntity(entityObject, function(err, response, entity) {
     if (!err) {
       //then add the entity to the list
-      var count = self._list.length;
-      self._list[count] = entity;
+      self.addExistingEntity(entity);
     }
-    doCallback(callback, [err, entity], self);    
+    doCallback(callback, [err, response, self], self);
   });
 };
 
-Usergrid.Collection.prototype.addExistingEntity = function (entity) {
+Usergrid.Collection.prototype.addExistingEntity = function(entity) {
   //entity should already exist in the db, so just add it to the list
   var count = this._list.length;
   this._list[count] = entity;
@@ -202,33 +188,58 @@ Usergrid.Collection.prototype.addExistingEntity = function (entity) {
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
-Usergrid.Collection.prototype.destroyEntity = function (entity, callback) {
+Usergrid.Collection.prototype.destroyEntity = function(entity, callback) {
   var self = this;
-  entity.destroy(function(err, data) {
+  entity.destroy(function(err, response) {
     if (err) {
       if (self._client.logging) {
         console.log('could not destroy entity');
       }
-      doCallback(callback, [err, data], self);
+      doCallback(callback, [err, response, self], self);
     } else {
-        //destroy was good, so repopulate the collection
-        self.fetch(callback);
+      //destroy was good, so repopulate the collection
+      self.fetch(callback);
     }
-  });
     //remove entity from the local store
-    this.removeEntity(entity);
+    self.removeEntity(entity);
+  });
 };
 
-
-Usergrid.Collection.prototype.removeEntity = function (entity) {
-  var uuid = entity.get('uuid');
-  for (var key in this._list) {
-    var listItem = this._list[key];
-    if (listItem.get('uuid') === uuid) {
-      return this._list.splice(key, 1);
-    }
-  }
-  return false;
+/*
+ * Filters the list of entities based on the supplied criteria function
+ * works like Array.prototype.filter
+ *
+ *  @method getEntitiesByCriteria
+ *  @param {function} criteria  A function that takes each entity as an argument and returns true or false
+ *  @return {Entity[]} returns a list of entities that caused the criteria function to return true
+ */
+Usergrid.Collection.prototype.getEntitiesByCriteria = function(criteria) {
+  return this._list.filter(criteria);
+};
+/*
+ * Returns the first entity from the list of entities based on the supplied criteria function
+ * works like Array.prototype.filter
+ *
+ *  @method getEntitiesByCriteria
+ *  @param {function} criteria  A function that takes each entity as an argument and returns true or false
+ *  @return {Entity[]} returns a list of entities that caused the criteria function to return true
+ */
+Usergrid.Collection.prototype.getEntityByCriteria = function(criteria) {
+  return this.getEntitiesByCriteria(criteria).shift();
+};
+/*
+ * Removed an entity from the collection without destroying it on the server
+ *
+ *  @method removeEntity
+ *  @param {object} entity
+ *  @return {Entity} returns the removed entity or undefined if it was not found
+ */
+Usergrid.Collection.prototype.removeEntity = function(entity) {
+  var removedEntity = this.getEntityByCriteria(function(item) {
+    return entity.uuid === item.get('uuid');
+  });
+  delete this._list[this._list.indexOf(removedEntity)];
+  return removedEntity;
 };
 
 /*
@@ -239,25 +250,24 @@ Usergrid.Collection.prototype.removeEntity = function (entity) {
  *  @param {function} callback
  *  @return {callback} callback(err, data, entity)
  */
-Usergrid.Collection.prototype.getEntityByUUID = function (uuid, callback) {
-
-  for (var key in this._list) {
-    var listItem = this._list[key];
-    if (listItem.get('uuid') === uuid) {
-        return callback(null, listItem);
-    }
-  }
-
-  //get the entity from the database
-  var options = {
-    data: {
-      type: this._type,
-      uuid:uuid
-    },
-    client: this._client
+Usergrid.Collection.prototype.getEntityByUUID = function(uuid, callback) {
+  var entity = this.getEntityByCriteria(function(item) {
+    return item.get('uuid') === uuid;
+  });
+  if (entity) {
+    doCallback(callback, [null, entity, entity], this);
+  } else {
+    //get the entity from the database
+    var options = {
+      data: {
+        type: this._type,
+        uuid: uuid
+      },
+      client: this._client
+    };
+    entity = new Usergrid.Entity(options);
+    entity.fetch(callback);
   }
-  var entity = new Usergrid.Entity(options);
-  entity.fetch(callback);
 };
 
 /*
@@ -266,7 +276,7 @@ Usergrid.Collection.prototype.getEntityByUUID = function (uuid, callback) {
  *  @method getFirstEntity
  *  @return {object} returns an entity object
  */
-Usergrid.Collection.prototype.getFirstEntity = function () {
+Usergrid.Collection.prototype.getFirstEntity = function() {
   var count = this._list.length;
   if (count > 0) {
     return this._list[0];
@@ -280,10 +290,10 @@ Usergrid.Collection.prototype.getFirstEntity = function () {
  *  @method getLastEntity
  *  @return {object} returns an entity object
  */
-Usergrid.Collection.prototype.getLastEntity = function () {
+Usergrid.Collection.prototype.getLastEntity = function() {
   var count = this._list.length;
   if (count > 0) {
-    return this._list[count-1];
+    return this._list[count - 1];
   }
   return null;
 };
@@ -297,10 +307,10 @@ Usergrid.Collection.prototype.getLastEntity = function () {
  *  @method hasNextEntity
  *  @return {boolean} true if there is a next entity, false if not
  */
-Usergrid.Collection.prototype.hasNextEntity = function () {
+Usergrid.Collection.prototype.hasNextEntity = function() {
   var next = this._iterator + 1;
-  var hasNextElement = (next >=0 && next < this._list.length);
-  if(hasNextElement) {
+  var hasNextElement = (next >= 0 && next < this._list.length);
+  if (hasNextElement) {
     return true;
   }
   return false;
@@ -315,10 +325,10 @@ Usergrid.Collection.prototype.hasNextEntity = function () {
  *  @method hasNextEntity
  *  @return {object} entity
  */
-Usergrid.Collection.prototype.getNextEntity = function () {
+Usergrid.Collection.prototype.getNextEntity = function() {
   this._iterator++;
   var hasNextElement = (this._iterator >= 0 && this._iterator <= this._list.length);
-  if(hasNextElement) {
+  if (hasNextElement) {
     return this._list[this._iterator];
   }
   return false;
@@ -331,10 +341,10 @@ Usergrid.Collection.prototype.getNextEntity = function () {
  *  @method hasPrevEntity
  *  @return {boolean} true if there is a previous entity, false if not
  */
-Usergrid.Collection.prototype.hasPrevEntity = function () {
+Usergrid.Collection.prototype.hasPrevEntity = function() {
   var previous = this._iterator - 1;
-  var hasPreviousElement = (previous >=0 && previous < this._list.length);
-  if(hasPreviousElement) {
+  var hasPreviousElement = (previous >= 0 && previous < this._list.length);
+  if (hasPreviousElement) {
     return true;
   }
   return false;
@@ -346,10 +356,10 @@ Usergrid.Collection.prototype.hasPrevEntity = function () {
  *  @method getPrevEntity
  *  @return {object} entity
  */
-Usergrid.Collection.prototype.getPrevEntity = function () {
+Usergrid.Collection.prototype.getPrevEntity = function() {
   this._iterator--;
   var hasPreviousElement = (this._iterator >= 0 && this._iterator <= this._list.length);
-  if(hasPreviousElement) {
+  if (hasPreviousElement) {
     return this._list[this._iterator];
   }
   return false;
@@ -362,8 +372,8 @@ Usergrid.Collection.prototype.getPrevEntity = function () {
  *  @method resetEntityPointer
  *  @return none
  */
-Usergrid.Collection.prototype.resetEntityPointer = function () {
-  this._iterator  = -1;
+Usergrid.Collection.prototype.resetEntityPointer = function() {
+  this._iterator = -1;
 };
 
 /*
@@ -399,7 +409,7 @@ Usergrid.Collection.prototype.resetPaging = function() {
  *  @method hasNextPage
  *  @return {boolean} returns true if there is a next page of data, false otherwise
  */
-Usergrid.Collection.prototype.hasNextPage = function () {
+Usergrid.Collection.prototype.hasNextPage = function() {
   return (this._next);
 };
 
@@ -412,7 +422,7 @@ Usergrid.Collection.prototype.hasNextPage = function () {
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
-Usergrid.Collection.prototype.getNextPage = function (callback) {
+Usergrid.Collection.prototype.getNextPage = function(callback) {
   if (this.hasNextPage()) {
     //set the cursor to the next page of data
     this._previous.push(this._cursor);
@@ -421,7 +431,7 @@ Usergrid.Collection.prototype.getNextPage = function (callback) {
     this._list = [];
     this.fetch(callback);
   }
-}
+};
 
 /*
  *  Paging -  checks to see if there is a previous page od data
@@ -429,7 +439,7 @@ Usergrid.Collection.prototype.getNextPage = function (callback) {
  *  @method hasPreviousPage
  *  @return {boolean} returns true if there is a previous page of data, false otherwise
  */
-Usergrid.Collection.prototype.hasPreviousPage = function () {
+Usergrid.Collection.prototype.hasPreviousPage = function() {
   return (this._previous.length > 0);
 };
 
@@ -442,9 +452,9 @@ Usergrid.Collection.prototype.hasPreviousPage = function () {
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
-Usergrid.Collection.prototype.getPreviousPage = function (callback) {
+Usergrid.Collection.prototype.getPreviousPage = function(callback) {
   if (this.hasPreviousPage()) {
-    this._next=null; //clear out next so the comparison will find the next item
+    this._next = null; //clear out next so the comparison will find the next item
     this._cursor = this._previous.pop();
     //empty the list
     this._list = [];

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/Counter.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Counter.js b/sdks/html5-javascript/lib/modules/Counter.js
index b6d211f..5de76c8 100644
--- a/sdks/html5-javascript/lib/modules/Counter.js
+++ b/sdks/html5-javascript/lib/modules/Counter.js
@@ -6,17 +6,17 @@
  *  @returns {callback} callback(err, event)
  */
 Usergrid.Counter = function(options, callback) {
-  var self=this;
+  // var self=this;
   this._client = options.client;
   this._data = options.data || {};
-  this._data.category = options.category||"UNKNOWN";
-  this._data.timestamp = options.timestamp||0;
+  this._data.category = options.category || "UNKNOWN";
+  this._data.timestamp = options.timestamp || 0;
   this._data.type = "events";
-  this._data.counters=options.counters||{};
-  doCallback(callback, [false, self], self);
+  this._data.counters = options.counters || {};
+  doCallback(callback, [false, this], this);
   //this.save(callback);
 };
-var COUNTER_RESOLUTIONS=[
+var COUNTER_RESOLUTIONS = [
   'all', 'minute', 'five_minutes', 'half_hour',
   'hour', 'six_day', 'day', 'week', 'month'
 ];
@@ -36,9 +36,9 @@ Usergrid.Counter.prototype = new Usergrid.Entity();
  * @param {function} callback
  * @returns {callback} callback(err, event)
  */
-Usergrid.Counter.prototype.fetch=function(callback){
+Usergrid.Counter.prototype.fetch = function(callback) {
   this.getData({}, callback);
-}
+};
 /*
  * increments the counter for a specific event
  *
@@ -50,16 +50,16 @@ Usergrid.Counter.prototype.fetch=function(callback){
  * @param {function} callback
  * @returns {callback} callback(err, event)
  */
-Usergrid.Counter.prototype.increment=function(options, callback){
-  var self=this,
-    name=options.name,
-    value=options.value;
-  if(!name){
-    return doCallback(callback, [true, "'name' for increment, decrement must be a number"], self);
-  }else if(isNaN(value)){
-    return doCallback(callback, [true, "'value' for increment, decrement must be a number"], self);
-  }else{
-    self._data.counters[name]=(parseInt(value))||1;
+Usergrid.Counter.prototype.increment = function(options, callback) {
+  var self = this,
+    name = options.name,
+    value = options.value;
+  if (!name) {
+    return doCallback(callback, [new UsergridInvalidArgumentError("'name' for increment, decrement must be a number"), null, self], self);
+  } else if (isNaN(value)) {
+    return doCallback(callback, [new UsergridInvalidArgumentError("'value' for increment, decrement must be a number"), null, self], self);
+  } else {
+    self._data.counters[name] = (parseInt(value)) || 1;
     return self.save(callback);
   }
 };
@@ -75,11 +75,14 @@ Usergrid.Counter.prototype.increment=function(options, callback){
  * @returns {callback} callback(err, event)
  */
 
-Usergrid.Counter.prototype.decrement=function(options, callback){
-  var self=this,
-    name=options.name,
-    value=options.value;
-  self.increment({name:name, value:-((parseInt(value))||1)}, callback);
+Usergrid.Counter.prototype.decrement = function(options, callback) {
+  var self = this,
+    name = options.name,
+    value = options.value;
+  self.increment({
+    name: name,
+    value: -((parseInt(value)) || 1)
+  }, callback);
 };
 /*
  * resets the counter for a specific event
@@ -93,10 +96,13 @@ Usergrid.Counter.prototype.decrement=function(options, callback){
  * @returns {callback} callback(err, event)
  */
 
-Usergrid.Counter.prototype.reset=function(options, callback){
-  var self=this,
-    name=options.name;
-  self.increment({name:name, value:0}, callback);
+Usergrid.Counter.prototype.reset = function(options, callback) {
+  var self = this,
+    name = options.name;
+  self.increment({
+    name: name,
+    value: 0
+  }, callback);
 };
 
 /*
@@ -116,63 +122,55 @@ Usergrid.Counter.prototype.reset=function(options, callback){
  * @param {function} callback
  * @returns {callback} callback(err, event)
  */
-Usergrid.Counter.prototype.getData=function(options, callback){
-  var start_time, 
-      end_time,
-      start=options.start||0,
-      end=options.end||Date.now(),
-      resolution=(options.resolution||'all').toLowerCase(),
-      counters=options.counters||Object.keys(this._data.counters),
-      res=(resolution||'all').toLowerCase();
-  if(COUNTER_RESOLUTIONS.indexOf(res)===-1){
-    res='all';
-  }
-  if(start){
-    switch(typeof start){
-      case "undefined":
-        start_time=0;
-        break;
-      case "number":
-        start_time=start;
-        break;
-      case "string":
-        start_time=(isNaN(start))?Date.parse(start):parseInt(start);
-        break;
-      default:
-        start_time=Date.parse(start.toString());
-    }
-  }
-  if(end){
-    switch(typeof end){
-      case "undefined":
-        end_time=Date.now();
-        break;
-      case "number":
-        end_time=end;
-        break;
-      case "string":
-        end_time=(isNaN(end))?Date.parse(end):parseInt(end);
-        break;
-      default:
-        end_time=Date.parse(end.toString());
-    }
+Usergrid.Counter.prototype.getData = function(options, callback) {
+  var start_time,
+    end_time,
+    start = options.start || 0,
+    end = options.end || Date.now(),
+    resolution = (options.resolution || 'all').toLowerCase(),
+    counters = options.counters || Object.keys(this._data.counters),
+    res = (resolution || 'all').toLowerCase();
+  if (COUNTER_RESOLUTIONS.indexOf(res) === -1) {
+    res = 'all';
   }
-  var self=this;
+  start_time = getSafeTime(start);
+  end_time = getSafeTime(end);
+  var self = this;
   //https://api.usergrid.com/yourorgname/sandbox/counters?counter=test_counter
-  var params=Object.keys(counters).map(function(counter){
-      return ["counter", encodeURIComponent(counters[counter])].join('=');
-    });
-  params.push('resolution='+res)
-  params.push('start_time='+String(start_time))
-  params.push('end_time='+String(end_time))
-    
-  var endpoint="counters?"+params.join('&');
-  this._client.request({endpoint:endpoint}, function(err, data){
-    if(data.counters && data.counters.length){
-      data.counters.forEach(function(counter){
-        self._data.counters[counter.name]=counter.value||counter.values;
-      })
+  var params = Object.keys(counters).map(function(counter) {
+    return ["counter", encodeURIComponent(counters[counter])].join('=');
+  });
+  params.push('resolution=' + res);
+  params.push('start_time=' + String(start_time));
+  params.push('end_time=' + String(end_time));
+
+  var endpoint = "counters?" + params.join('&');
+  this._client.request({
+    endpoint: endpoint
+  }, function(err, data) {
+    if (data.counters && data.counters.length) {
+      data.counters.forEach(function(counter) {
+        self._data.counters[counter.name] = counter.value || counter.values;
+      });
     }
-    return doCallback(callback, [err, data], self);
-  })
+    return doCallback(callback, [err, data, self], self);
+  });
 };
+
+function getSafeTime(prop) {
+  var time;
+  switch (typeof prop) {
+    case "undefined":
+      time = Date.now();
+      break;
+    case "number":
+      time = prop;
+      break;
+    case "string":
+      time = (isNaN(prop)) ? Date.parse(prop) : parseInt(prop);
+      break;
+    default:
+      time = Date.parse(prop.toString());
+  }
+  return time;
+}